diff --git a/dist/BlueMarble.user.js b/dist/BlueMarble.user.js index 6416868..77e4c35 100644 --- a/dist/BlueMarble.user.js +++ b/dist/BlueMarble.user.js @@ -1,7 +1,7 @@ // ==UserScript== // @name Blue Marble // @namespace https://github.com/SwingTheVine/ -// @version 0.69.0 +// @version 0.69.1 // @description A userscript to automate and/or enhance the user experience on Wplace.live. Make sure to comply with the site's Terms of Service, and rules! This script is not affiliated with Wplace.live in any way, use at your own risk. This script is not affiliated with TamperMonkey. The author of this userscript is not responsible for any damages, issues, loss of data, or punishment that may occur as a result of using this script. This script is provided "as is" under the MPL-2.0 license. The "Blue Marble" icon is licensed under CC0 1.0 Universal (CC0 1.0) Public Domain Dedication. The image is owned by NASA. // @author SwingTheVine // @license MPL-2.0 @@ -20,4 +20,4 @@ // Wplace --> https://wplace.live // License --> https://www.mozilla.org/en-US/MPL/2.0/ -(()=>{var t,e,n=t=>{throw TypeError(t)},i=(t,e,i)=>e.has(t)?n("Cannot add the same private member more than once"):e instanceof WeakSet?e.add(t):e.set(t,i),s=(t,e,i)=>(((t,e)=>{e.has(t)||n("Cannot access private method")})(t,e),i);t=new WeakSet,e=function(t,e={},n={}){const i=document.createElement(t);this.t?(this.i.appendChild(i),this.o.push(this.i),this.i=i):(this.t=i,this.i=i);for(const[t,n]of Object.entries(e))i[t]=n;for(const[t,e]of Object.entries(n))i[t]=e;return i};var o,a=class{constructor({displayName:t="My template",h:e=0,l:n="",url:i="",file:s=null,coords:o=null,u:a=null,m:r=1e3}={}){this.displayName=t,this.h=e,this.l=n,this.url=i,this.file=s,this.coords=o,this.u=a,this.m=r}async p(){const t=await createImageBitmap(this.file),e=t.width,n=t.height,i={},s=new OffscreenCanvas(this.m,this.m),o=s.getContext("2d",{v:!0});for(let a=this.coords[3];a0;)n=e[t%i]+n,t=Math.floor(t/i);return n}o=new WeakSet;var c=GM_info.script.name.toString(),h=GM_info.script.version.toString();!function(t){const e=document.createElement("script");e.setAttribute("bm-o",c),e.setAttribute("bm-m","color: cornflowerblue;"),e.textContent=`(${t})();`,document.documentElement.appendChild(e),e.remove()}(()=>{const t=document.currentScript,e=t?.getAttribute("bm-o")||"Blue Marble",n=t?.getAttribute("bm-m")||"",i=new Map;window.addEventListener("message",t=>{const{source:s,endpoint:o,blobID:a,blobData:r,blink:c}=t.data;if(Date.now(),"blue-marble"==s&&a&&r&&!o){const t=i.get(a);"function"==typeof t?t(r):function(...t){(0,console.warn)(...t)}(`%c${e}%c: Attempted to retrieve a blob (%s) from queue, but the blobID was not a function! Skipping...`,n,"",a),i.delete(a)}});const s=window.fetch;window.fetch=async function(...t){const e=await s.apply(this,t),n=e.clone(),o=(t[0]instanceof Request?t[0]?.url:t[0])||"ignore",a=n.headers.get("content-type")||"";if(a.includes("application/json"))n.json().then(t=>{window.postMessage({source:"blue-marble",endpoint:o,jsonData:t},"*")}).catch(t=>{});else if(a.includes("image/")&&!o.includes("openfreemap")){const t=Date.now(),e=await n.blob();return new Promise(s=>{const a=crypto.randomUUID();i.set(a,t=>{s(new Response(t,{headers:n.headers,status:n.status,statusText:n.statusText}))}),window.postMessage({source:"blue-marble",endpoint:o,blobID:a,blobData:e,blink:t})}).catch(t=>{Date.now()})}return e}});var l=GM_getResourceText("CSS-BM-File");GM_addStyle(l);var u=document.createElement("link");u.href="https://fonts.googleapis.com/css2?family=Roboto+Mono:ital,wght@0,100..700;1,100..700&display=swap",u.rel="preload",u.as="style",u.onload=function(){this.onload=null,this.rel="stylesheet"},document.head.appendChild(u),new class{constructor(){this.M=null,this.$=null,this.D="#bm-5"}C(t){return this.$=t,this.M=new MutationObserver(t=>{for(const e of t)for(const t of e.addedNodes)t instanceof HTMLElement&&t.matches?.(this.D)}),this}T(){return this.M}observe(t,e=!1,n=!1){t.observe(this.$,{childList:e,subtree:n})}};var d=new class{constructor(e,n){i(this,t),this.name=e,this.version=n,this.I=null,this.k="bm-a",this.t=null,this.i=null,this.o=[]}N(t){this.I=t}S(){return this.o.length>0&&(this.i=this.o.pop()),this}B(t){t.appendChild(this.t),this.t=null,this.i=null,this.o=[]}O(n={},i=()=>{}){return i(this,s(this,t,e).call(this,"div",{},n)),this}L(n={},i=()=>{}){return i(this,s(this,t,e).call(this,"p",{},n)),this}H(n={},i=()=>{}){return i(this,s(this,t,e).call(this,"small",{},n)),this}q(n={},i=()=>{}){return i(this,s(this,t,e).call(this,"img",{},n)),this}P(n,i={},o=()=>{}){return o(this,s(this,t,e).call(this,"h"+n,{},i)),this}R(n={},i=()=>{}){return i(this,s(this,t,e).call(this,"hr",{},n)),this}_(n={},i=()=>{}){return i(this,s(this,t,e).call(this,"br",{},n)),this}j(n={},i=()=>{}){const o=s(this,t,e).call(this,"label",{textContent:n.textContent??""});delete n.textContent;const a=s(this,t,e).call(this,"input",{type:"checkbox"},n);return o.insertBefore(a,o.firstChild),this.S(),i(this,o,a),this}V(n={},i=()=>{}){return i(this,s(this,t,e).call(this,"button",{},n)),this}Y(n={},i=()=>{}){const o=n.title??n.textContent??"Help: No info";delete n.textContent,n.title=`Help: ${o}`;const a={textContent:"?",className:"bm-p",onclick:()=>{this.F(this.k,o)}};return i(this,s(this,t,e).call(this,"button",a,n)),this}G(n={},i=()=>{}){return i(this,s(this,t,e).call(this,"input",{},n)),this}U(n={},i=()=>{}){const o=n.textContent??"";delete n.textContent;const a=s(this,t,e).call(this,"div"),r=s(this,t,e).call(this,"input",{type:"file",style:"display: none;"},n);this.S();const c=s(this,t,e).call(this,"button",{textContent:o});return this.S(),this.S(),c.addEventListener("click",()=>{r.click()}),r.addEventListener("change",()=>{c.style.maxWidth=`${c.offsetWidth}px`,r.files.length>0?c.textContent=r.files[0].name:c.textContent=o}),i(this,a,r,c),this}W(n={},i=()=>{}){return i(this,s(this,t,e).call(this,"textarea",{},n)),this}F(t,e,n=!1){const i=document.getElementById(t.replace(/^#/,""));i&&(i instanceof HTMLInputElement?i.value=e:n?i.textContent=e:i.innerHTML=e)}X(t,e){let n,i=!1,s=0;t=document.querySelector("#"==t?.[0]?t:"#"+t),e=document.querySelector("#"==e?.[0]?e:"#"+e),t&&e?(e.addEventListener("mousedown",function(o){i=!0,n=o.clientX-t.getBoundingClientRect().left,s=o.clientY-t.getBoundingClientRect().top,document.body.style.userSelect="none",e.classList.add("dragging")}),e.addEventListener("touchstart",function(o){i=!0;const a=o?.touches?.[0];a&&(n=a.clientX-t.getBoundingClientRect().left,s=a.clientY-t.getBoundingClientRect().top,document.body.style.userSelect="none",e.classList.add("dragging"))},{passive:!1}),document.addEventListener("mousemove",function(e){i&&(t.style.left=e.clientX-n+"px",t.style.top=e.clientY-s+"px",t.style.right="")}),document.addEventListener("touchmove",function(e){if(i){const i=e?.touches?.[0];if(!i)return;t.style.left=i.clientX-n+"px",t.style.top=i.clientY-s+"px",e.preventDefault()}},{passive:!1}),document.addEventListener("mouseup",function(){i=!1,document.body.style.userSelect="",e.classList.remove("dragging")}),document.addEventListener("touchend",function(){i=!1,document.body.style.userSelect="",e.classList.remove("dragging")}),document.addEventListener("touchcancel",function(){i=!1,document.body.style.userSelect="",e.classList.remove("dragging")})):this.A(`Can not drag! ${t?"":"moveMe"} ${t||e?"":"and "}${e?"":"iMoveThings "}was not found!`)}J(t){(0,console.info)(`${this.name}: ${t}`),this.F(this.k,"Status: "+t,!0)}A(t){(0,console.error)(`${this.name}: ${t}`),this.F(this.k,"Error: "+t,!0)}}(c,h),m=new class{constructor(t,e,n){i(this,o),this.name=t,this.version=e,this.t=n,this.Z="1.0.0",this.K=null,this.tt="!#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",this.m=1e3,this.et=3,this.nt=null,this.it=null,this.st="bm-n",this.ot="div#map canvas.maplibregl-canvas",this.rt=null,this.ct="",this.ht=[],this.lt=null}ut(){if(document.body.contains(this.nt))return this.nt;document.getElementById(this.st)?.remove();const t=document.querySelector(this.ot),e=document.createElement("canvas");return e.id=this.st,e.className="maplibregl-canvas",e.style.position="absolute",e.style.top="0",e.style.left="0",e.style.height=t?.clientHeight*(window.devicePixelRatio||1)+"px",e.style.width=t?.clientWidth*(window.devicePixelRatio||1)+"px",e.height=t?.clientHeight*(window.devicePixelRatio||1),e.width=t?.clientWidth*(window.devicePixelRatio||1),e.style.zIndex="8999",e.style.pointerEvents="none",t?.parentElement?.appendChild(e),this.nt=e,window.addEventListener("move",this.dt),window.addEventListener("zoom",this.bt),window.addEventListener("resize",this.ft),this.nt}async wt(){return{whoami:this.name.replace(" ",""),scriptVersion:this.version,schemaVersion:this.Z,templates:{}}}async gt(t,e,n){this.lt||(this.lt=await this.wt()),this.t.J(`Creating template at ${n.join(", ")}...`);const i=new a({displayName:e,h:0,l:r(this.K||0,this.tt),file:t,coords:n});i.u=await i.p(this.m),this.lt.templates[`${i.h} ${i.l}`]={name:i.displayName,enabled:!0,tiles:i.u},this.ht=[],this.ht.push(i),this.t.J(`Template created at ${n.join(", ")}!`)}vt(){}async yt(){this.lt||(this.lt=await this.wt())}async xt(t,e){const n=this.m*this.et;e=e[0].toString().padStart(4,"0")+","+e[1].toString().padStart(4,"0");const i=this.ht;i.sort((t,e)=>t.h-e.h);const s=i.map(t=>{const n=Object.keys(t.u).filter(t=>t.startsWith(e));if(0===n.length)return null;const i=n.map(e=>t.u[e]);return i?.[0]}).filter(Boolean);s.length>0&&this.t.J(`Displaying ${s.length} template${1==s.length?"":"s"}.`);const o=await createImageBitmap(t),a=new OffscreenCanvas(n,n),r=a.getContext("2d");r.imageSmoothingEnabled=!1,r.beginPath(),r.rect(0,0,n,n),r.clip(),r.clearRect(0,0,n,n),r.drawImage(o,0,0,n,n);for(const t of s)r.drawImage(t,0,0);return await a.convertToBlob({type:"image/png"})}Mt(){}}(c,h,d),p=new class{constructor(t){this.$t=t,this.Dt=!1,this.Ct=[],this.Tt=[]}It(t){window.addEventListener("message",async e=>{const n=e.data,i=n.jsonData;if(!n||"blue-marble"!==n.source)return;if(!n.endpoint)return;const s=n.endpoint?.split("?")[0].split("/").filter(t=>t&&isNaN(Number(t))).filter(t=>t&&!t.includes(".")).pop();switch(s){case"me":if(i.status&&"2"!=i.status?.toString()[0])return void t.A("You are not logged in!\nCould not fetch userdata.");const e=Math.ceil(Math.pow(Math.floor(i.level)*Math.pow(30,.65),1/.65)-i.pixelsPainted);i.id||i.id,this.$t.K=i.id,t.F("bm-f",`Username: ${function(t){const e=document.createElement("div");return e.textContent=t,e.innerHTML}(i.name)}`),t.F("bm-b",`Droplets: ${(new Intl.NumberFormat).format(i.droplets)}`),t.F("bm-6",`Next level in ${(new Intl.NumberFormat).format(e)} pixel${1==e?"":"s"}`);break;case"pixel":const s=n.endpoint.split("?")[0].split("/").filter(t=>t&&!isNaN(Number(t))),r=new URLSearchParams(n.endpoint.split("?")[1]),c=[r.get("x"),r.get("y")];if(this.Ct.length&&(!s.length||!c.length))return void t.A("Coordinates are malformed!\nDid you try clicking the canvas first?");this.Ct=[...s,...c];const h=(o=s,a=c,[parseInt(o[0])%4*1e3+parseInt(a[0]),parseInt(o[1])%4*1e3+parseInt(a[1])]),l=document.querySelectorAll("span");for(const t of l)if(t.textContent.trim().includes(`${h[0]}, ${h[1]}`)){let e=document.querySelector("#bm-5");const n=`(Tl X: ${s[0]}, Tl Y: ${s[1]}, Px X: ${c[0]}, Px Y: ${c[1]})`;e?e.textContent=n:(e=document.createElement("span"),e.id="bm-5",e.textContent=n,e.style="margin-left: calc(var(--spacing)*3); font-size: small;",t.parentNode.parentNode.parentNode.insertAdjacentElement("afterend",e))}break;case"tiles":let u=n.endpoint.split("/");u=[parseInt(u[u.length-2]),parseInt(u[u.length-1].replace(".png",""))];const d=n.blobID,m=n.blobData,p=await this.$t.xt(m,u);window.postMessage({source:"blue-marble",blobID:d,blobData:p,blink:n.blink});break;case"robots":this.Dt="false"==i.userscript?.toString().toLowerCase()}var o,a})}}(m);d.N(p),d.O({id:"bm-l",style:"top: 10px; right: 75px;"}).O({id:"bm-7"}).O({id:"bm-g"}).S().q({alt:"Blue Marble Icon",src:"https://raw.githubusercontent.com/SwingTheVine/Wplace-BlueMarble/main/dist/assets/Favicon.png"}).S().P(1,{textContent:c}).S().S().R().S().O({id:"bm-4"}).L({id:"bm-f",textContent:"Username:"}).S().L({id:"bm-b",textContent:"Droplets:"}).S().L({id:"bm-6",textContent:"Next level in..."}).S().S().R().S().O({id:"bm-3"}).O({id:"bm-8"}).V({id:"bm-c",className:"bm-p",style:"margin-top: 0;",innerHTML:''},(t,e)=>{e.onclick=()=>{const e=t.I?.Ct;e?.[0]?(t.F("bm-h",e?.[0]||""),t.F("bm-i",e?.[1]||""),t.F("bm-j",e?.[2]||""),t.F("bm-k",e?.[3]||"")):t.A("Coordinates are malformed! Did you try clicking on the canvas first?")}}).S().G({type:"number",id:"bm-h",placeholder:"Tl X",min:0,max:2047,step:1,required:!0}).S().G({type:"number",id:"bm-i",placeholder:"Tl Y",min:0,max:2047,step:1,required:!0}).S().G({type:"number",id:"bm-j",placeholder:"Px X",min:0,max:2047,step:1,required:!0}).S().G({type:"number",id:"bm-k",placeholder:"Px Y",min:0,max:2047,step:1,required:!0}).S().S().U({id:"bm-2",textContent:"Upload Template",accept:"image/png, image/jpeg, image/webp, image/bmp, image/gif"}).S().O({id:"bm-0"}).V({id:"bm-d",textContent:"Enable"},(t,e)=>{e.onclick=()=>{const e=document.querySelector("#bm-2"),n=document.querySelector("#bm-h");if(!n.checkValidity())return n.reportValidity(),void t.A("Coordinates are malformed! Did you try clicking on the canvas first?");const i=document.querySelector("#bm-i");if(!i.checkValidity())return i.reportValidity(),void t.A("Coordinates are malformed! Did you try clicking on the canvas first?");const s=document.querySelector("#bm-j");if(!s.checkValidity())return s.reportValidity(),void t.A("Coordinates are malformed! Did you try clicking on the canvas first?");const o=document.querySelector("#bm-k");if(!o.checkValidity())return o.reportValidity(),void t.A("Coordinates are malformed! Did you try clicking on the canvas first?");e?.files[0]?(m.gt(e.files[0],e.files[0]?.name.replace(/\.[^/.]+$/,""),[Number(n.value),Number(i.value),Number(s.value),Number(o.value)]),t.J("Drew to canvas!")):t.A("No file selected!")}}).S().S().W({id:d.k,placeholder:`Status: Sleeping...\nVersion: ${h}`,readOnly:!0}).S().O({id:"bm-1"}).O().V({id:"bm-9",className:"bm-p",innerHTML:"🎨",title:"Template Color Converter"},(t,e)=>{e.addEventListener("click",()=>{window.open("https://pepoafonso.github.io/color_converter_wplace/","_blank","noopener noreferrer")})}).S().S().H({textContent:"Made by SwingTheVine",style:"margin-top: auto;"}).S().S().S().B(document.body),d.X("#bm-l","#bm-g"),p.It(d),new MutationObserver((t,e)=>{const n=document.querySelector("#color-1");if(!n)return;let i=document.querySelector("#bm-e");i||(i=document.createElement("button"),i.id="bm-e",i.textContent="Move ↑",i.className="btn btn-soft",i.onclick=function(){const t=this.parentNode.parentNode.parentNode.parentNode,e="Move ↑"==this.textContent;t.parentNode.className=t.parentNode.className.replace(e?"bottom":"top",e?"top":"bottom"),t.style.borderTopLeftRadius=e?"0px":"var(--radius-box)",t.style.borderTopRightRadius=e?"0px":"var(--radius-box)",t.style.borderBottomLeftRadius=e?"var(--radius-box)":"0px",t.style.borderBottomRightRadius=e?"var(--radius-box)":"0px",this.textContent=e?"Move ↓":"Move ↑"},n.parentNode.parentNode.parentNode.parentNode.querySelector("h2").parentNode.appendChild(i))}).observe(document.body,{childList:!0,subtree:!0}),function(...t){(0,console.log)(...t)}(`%c${c}%c (${h}) userscript has loaded!`,"color: cornflowerblue;","")})(); \ No newline at end of file +(()=>{var t,e,n=t=>{throw TypeError(t)},s=(t,e,s)=>e.has(t)?n("Cannot add the same private member more than once"):e instanceof WeakSet?e.add(t):e.set(t,s),i=(t,e,s)=>(((t,e)=>{e.has(t)||n("Cannot access private method")})(t,e),s);t=new WeakSet,e=function(t,e={},n={}){const s=document.createElement(t);this.t?(this.i.appendChild(s),this.o.push(this.i),this.i=s):(this.t=s,this.i=s);for(const[t,n]of Object.entries(e))s[t]=n;for(const[t,e]of Object.entries(n))s[t]=e;return s};var o,a=class{constructor({displayName:t="My template",l:e=0,h:n="",url:s="",file:i=null,coords:o=null,u:a=null,m:r=1e3}={}){this.displayName=t,this.l=e,this.h=n,this.url=s,this.file=i,this.coords=o,this.u=a,this.m=r}async p(){console.log(this.coords);const t=await createImageBitmap(this.file),e=t.width,n=t.height,s={},i=new OffscreenCanvas(this.m,this.m),o=i.getContext("2d",{$:!0});for(let a=this.coords[3];a0;)n=e[t%s]+n,t=Math.floor(t/s);return n}o=new WeakSet;var c=GM_info.script.name.toString(),l=GM_info.script.version.toString();!function(t){const e=document.createElement("script");e.setAttribute("bm-o",c),e.setAttribute("bm-m","color: cornflowerblue;"),e.textContent=`(${t})();`,document.documentElement.appendChild(e),e.remove()}(()=>{const t=document.currentScript,e=t?.getAttribute("bm-o")||"Blue Marble",n=t?.getAttribute("bm-m")||"",s=new Map;window.addEventListener("message",t=>{const{source:i,endpoint:o,blobID:a,blobData:r,blink:c}=t.data,l=Date.now()-c;if(console.groupCollapsed(`%c${e}%c: ${s.size} Recieved IMAGE message about blob "${a}"`,n,""),console.log(`Blob fetch took %c${String(Math.floor(l/6e4)).padStart(2,"0")}:${String(Math.floor(l/1e3)%60).padStart(2,"0")}.${String(l%1e3).padStart(3,"0")}%c MM:SS.mmm`,n,""),console.log(s),console.groupEnd(),"blue-marble"==i&&a&&r&&!o){const t=s.get(a);"function"==typeof t?t(r):function(...t){(0,console.warn)(...t)}(`%c${e}%c: Attempted to retrieve a blob (%s) from queue, but the blobID was not a function! Skipping...`,n,"",a),s.delete(a)}});const i=window.fetch;window.fetch=async function(...t){const o=await i.apply(this,t),a=o.clone(),r=(t[0]instanceof Request?t[0]?.url:t[0])||"ignore",c=a.headers.get("content-type")||"";if(c.includes("application/json"))console.log(`%c${e}%c: Sending JSON message about endpoint "${r}"`,n,""),a.json().then(t=>{window.postMessage({source:"blue-marble",endpoint:r,jsonData:t},"*")}).catch(t=>{console.error(`%c${e}%c: Failed to parse JSON: `,n,"",t)});else if(c.includes("image/")&&!r.includes("openfreemap")){const t=Date.now(),i=await a.blob();return console.log(`%c${e}%c: ${s.size} Sending IMAGE message about endpoint "${r}"`,n,""),new Promise(o=>{const c=crypto.randomUUID();s.set(c,t=>{o(new Response(t,{headers:a.headers,status:a.status,statusText:a.statusText})),console.log(`%c${e}%c: ${s.size} Processed blob "${c}"`,n,"")}),window.postMessage({source:"blue-marble",endpoint:r,blobID:c,blobData:i,blink:t})}).catch(i=>{const o=Date.now();console.error(`%c${e}%c: Failed to Promise blob!`,n,""),console.groupCollapsed(`%c${e}%c: Details of failed blob Promise:`,n,""),console.log(`Endpoint: ${r}\nThere are ${s.size} blobs processing...\nBlink: ${t.toLocaleString()}\nTime Since Blink: ${String(Math.floor(o/6e4)).padStart(2,"0")}:${String(Math.floor(o/1e3)%60).padStart(2,"0")}.${String(o%1e3).padStart(3,"0")} MM:SS.mmm`),console.error("Exception stack:",i),console.groupEnd()})}return o}});var h=GM_getResourceText("CSS-BM-File");GM_addStyle(h);var u=document.createElement("link");u.href="https://fonts.googleapis.com/css2?family=Roboto+Mono:ital,wght@0,100..700;1,100..700&display=swap",u.rel="preload",u.as="style",u.onload=function(){this.onload=null,this.rel="stylesheet"},document.head.appendChild(u),new class{constructor(){this.v=null,this.M=null,this.S="#bm-5"}D(t){return this.M=t,this.v=new MutationObserver(t=>{for(const e of t)for(const t of e.addedNodes)t instanceof HTMLElement&&t.matches?.(this.S)}),this}C(){return this.v}observe(t,e=!1,n=!1){t.observe(this.M,{childList:e,subtree:n})}};var d=new class{constructor(e,n){s(this,t),this.name=e,this.version=n,this.T=null,this.k="bm-a",this.t=null,this.i=null,this.o=[]}I(t){this.T=t}N(){return this.o.length>0&&(this.i=this.o.pop()),this}B(t){t.appendChild(this.t),this.t=null,this.i=null,this.o=[]}O(n={},s=()=>{}){return s(this,i(this,t,e).call(this,"div",{},n)),this}L(n={},s=()=>{}){return s(this,i(this,t,e).call(this,"p",{},n)),this}P(n={},s=()=>{}){return s(this,i(this,t,e).call(this,"small",{},n)),this}H(n={},s=()=>{}){return s(this,i(this,t,e).call(this,"img",{},n)),this}R(n,s={},o=()=>{}){return o(this,i(this,t,e).call(this,"h"+n,{},s)),this}Y(n={},s=()=>{}){return s(this,i(this,t,e).call(this,"hr",{},n)),this}G(n={},s=()=>{}){return s(this,i(this,t,e).call(this,"br",{},n)),this}X(n={},s=()=>{}){const o=i(this,t,e).call(this,"label",{textContent:n.textContent??""});delete n.textContent;const a=i(this,t,e).call(this,"input",{type:"checkbox"},n);return o.insertBefore(a,o.firstChild),this.N(),s(this,o,a),this}j(n={},s=()=>{}){return s(this,i(this,t,e).call(this,"button",{},n)),this}q(n={},s=()=>{}){const o=n.title??n.textContent??"Help: No info";delete n.textContent,n.title=`Help: ${o}`;const a={textContent:"?",className:"bm-p",onclick:()=>{this._(this.k,o)}};return s(this,i(this,t,e).call(this,"button",a,n)),this}F(n={},s=()=>{}){return s(this,i(this,t,e).call(this,"input",{},n)),this}J(n={},s=()=>{}){const o=n.textContent??"";delete n.textContent;const a=i(this,t,e).call(this,"div"),r=i(this,t,e).call(this,"input",{type:"file",style:"display: none;"},n);this.N();const c=i(this,t,e).call(this,"button",{textContent:o});return this.N(),this.N(),c.addEventListener("click",()=>{r.click()}),r.addEventListener("change",()=>{c.style.maxWidth=`${c.offsetWidth}px`,r.files.length>0?c.textContent=r.files[0].name:c.textContent=o}),s(this,a,r,c),this}V(n={},s=()=>{}){return s(this,i(this,t,e).call(this,"textarea",{},n)),this}_(t,e,n=!1){const s=document.getElementById(t.replace(/^#/,""));s&&(s instanceof HTMLInputElement?s.value=e:n?s.textContent=e:s.innerHTML=e)}W(t,e){let n,s=!1,i=0;t=document.querySelector("#"==t?.[0]?t:"#"+t),e=document.querySelector("#"==e?.[0]?e:"#"+e),t&&e?(e.addEventListener("mousedown",function(o){s=!0,n=o.clientX-t.getBoundingClientRect().left,i=o.clientY-t.getBoundingClientRect().top,document.body.style.userSelect="none",e.classList.add("dragging")}),e.addEventListener("touchstart",function(o){s=!0;const a=o?.touches?.[0];a&&(n=a.clientX-t.getBoundingClientRect().left,i=a.clientY-t.getBoundingClientRect().top,document.body.style.userSelect="none",e.classList.add("dragging"))},{passive:!1}),document.addEventListener("mousemove",function(e){s&&(t.style.left=e.clientX-n+"px",t.style.top=e.clientY-i+"px",t.style.right="")}),document.addEventListener("touchmove",function(e){if(s){const s=e?.touches?.[0];if(!s)return;t.style.left=s.clientX-n+"px",t.style.top=s.clientY-i+"px",t.style.right="",e.preventDefault()}},{passive:!1}),document.addEventListener("mouseup",function(){s=!1,document.body.style.userSelect="",e.classList.remove("dragging")}),document.addEventListener("touchend",function(){s=!1,document.body.style.userSelect="",e.classList.remove("dragging")}),document.addEventListener("touchcancel",function(){s=!1,document.body.style.userSelect="",e.classList.remove("dragging")})):this.A(`Can not drag! ${t?"":"moveMe"} ${t||e?"":"and "}${e?"":"iMoveThings "}was not found!`)}U(t){(0,console.info)(`${this.name}: ${t}`),this._(this.k,"Status: "+t,!0)}A(t){(0,console.error)(`${this.name}: ${t}`),this._(this.k,"Error: "+t,!0)}}(c,l),m=new class{constructor(t,e,n){s(this,o),this.name=t,this.version=e,this.t=n,this.Z="1.0.0",this.K=null,this.tt="!#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",this.m=1e3,this.et=3,this.nt=null,this.st=null,this.it="bm-n",this.ot="div#map canvas.maplibregl-canvas",this.rt=null,this.ct="",this.lt=[],this.ht=null}ut(){if(document.body.contains(this.nt))return this.nt;document.getElementById(this.it)?.remove();const t=document.querySelector(this.ot),e=document.createElement("canvas");return e.id=this.it,e.className="maplibregl-canvas",e.style.position="absolute",e.style.top="0",e.style.left="0",e.style.height=t?.clientHeight*(window.devicePixelRatio||1)+"px",e.style.width=t?.clientWidth*(window.devicePixelRatio||1)+"px",e.height=t?.clientHeight*(window.devicePixelRatio||1),e.width=t?.clientWidth*(window.devicePixelRatio||1),e.style.zIndex="8999",e.style.pointerEvents="none",t?.parentElement?.appendChild(e),this.nt=e,window.addEventListener("move",this.dt),window.addEventListener("zoom",this.bt),window.addEventListener("resize",this.ft),this.nt}async gt(){return{whoami:this.name.replace(" ",""),scriptVersion:this.version,schemaVersion:this.Z,templates:{}}}async wt(t,e,n){this.ht||(this.ht=await this.gt(),console.log("Creating JSON...")),this.t.U(`Creating template at ${n.join(", ")}...`);const s=new a({displayName:e,l:0,h:r(this.K||0,this.tt),file:t,coords:n});s.u=await s.p(this.m),this.ht.templates[`${s.l} ${s.h}`]={name:s.displayName,enabled:!0,tiles:s.u},this.lt=[],this.lt.push(s),this.t.U(`Template created at ${n.join(", ")}!`),console.log(Object.keys(this.ht.templates).length),console.log(this.ht),console.log(this.lt)}$t(){}async vt(){this.ht||(this.ht=await this.gt(),console.log("Creating JSON..."))}async yt(t,e){const n=this.m*this.et;e=e[0].toString().padStart(4,"0")+","+e[1].toString().padStart(4,"0"),console.log(`Looking for "${e}"`);const s=this.lt;s.sort((t,e)=>t.l-e.l),console.log(s);const i=s.map(t=>{const n=Object.keys(t.u).filter(t=>t.startsWith(e));if(0===n.length)return null;const s=n.map(e=>t.u[e]);return s?.[0]}).filter(Boolean);console.log(i),i.length>0&&this.t.U(`Displaying ${i.length} template${1==i.length?"":"s"}.`);const o=await createImageBitmap(t),a=new OffscreenCanvas(n,n),r=a.getContext("2d");r.imageSmoothingEnabled=!1,r.beginPath(),r.rect(0,0,n,n),r.clip(),r.clearRect(0,0,n,n),r.drawImage(o,0,0,n,n);for(const t of i)console.log("Template Blob is "+typeof t),console.log(t),r.drawImage(t,0,0);return await a.convertToBlob({type:"image/png"})}xt(){}}(c,l,d),p=new class{constructor(t){this.Mt=t,this.St=!1,this.Dt=[],this.Ct=[]}Tt(t){window.addEventListener("message",async e=>{const n=e.data,s=n.jsonData;if(!n||"blue-marble"!==n.source)return;if(!n.endpoint)return;const i=n.endpoint?.split("?")[0].split("/").filter(t=>t&&isNaN(Number(t))).filter(t=>t&&!t.includes(".")).pop();switch(console.log('%cBlue Marble%c: Recieved message about "%s"',"color: cornflowerblue;","",i),i){case"me":if(s.status&&"2"!=s.status?.toString()[0])return void t.A("You are not logged in!\nCould not fetch userdata.");const e=Math.ceil(Math.pow(Math.floor(s.level)*Math.pow(30,.65),1/.65)-s.pixelsPainted);console.log(s.id),(s.id||0===s.id)&&console.log(r(s.id,"!#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~")),this.Mt.K=s.id,t._("bm-f",`Username: ${function(t){const e=document.createElement("div");return e.textContent=t,e.innerHTML}(s.name)}`),t._("bm-b",`Droplets: ${(new Intl.NumberFormat).format(s.droplets)}`),t._("bm-6",`Next level in ${(new Intl.NumberFormat).format(e)} pixel${1==e?"":"s"}`);break;case"pixel":const i=n.endpoint.split("?")[0].split("/").filter(t=>t&&!isNaN(Number(t))),c=new URLSearchParams(n.endpoint.split("?")[1]),l=[c.get("x"),c.get("y")];if(this.Dt.length&&(!i.length||!l.length))return void t.A("Coordinates are malformed!\nDid you try clicking the canvas first?");this.Dt=[...i,...l];const h=(o=i,a=l,[parseInt(o[0])%4*1e3+parseInt(a[0]),parseInt(o[1])%4*1e3+parseInt(a[1])]),u=document.querySelectorAll("span");for(const t of u)if(t.textContent.trim().includes(`${h[0]}, ${h[1]}`)){let e=document.querySelector("#bm-5");const n=`(Tl X: ${i[0]}, Tl Y: ${i[1]}, Px X: ${l[0]}, Px Y: ${l[1]})`;e?e.textContent=n:(e=document.createElement("span"),e.id="bm-5",e.textContent=n,e.style="margin-left: calc(var(--spacing)*3); font-size: small;",t.parentNode.parentNode.parentNode.insertAdjacentElement("afterend",e))}break;case"tiles":let d=n.endpoint.split("/");d=[parseInt(d[d.length-2]),parseInt(d[d.length-1].replace(".png",""))];const m=n.blobID,p=n.blobData,b=await this.Mt.yt(p,d);window.postMessage({source:"blue-marble",blobID:m,blobData:b,blink:n.blink});break;case"robots":this.St="false"==s.userscript?.toString().toLowerCase();break}var o,a})}}(m);d.I(p),d.O({id:"bm-l",style:"top: 10px; right: 75px;"}).O({id:"bm-7"}).O({id:"bm-g"}).N().H({alt:"Blue Marble Icon",src:"https://raw.githubusercontent.com/SwingTheVine/Wplace-BlueMarble/main/dist/assets/Favicon.png"}).N().R(1,{textContent:c}).N().N().Y().N().O({id:"bm-4"}).L({id:"bm-f",textContent:"Username:"}).N().L({id:"bm-b",textContent:"Droplets:"}).N().L({id:"bm-6",textContent:"Next level in..."}).N().N().Y().N().O({id:"bm-3"}).O({id:"bm-8"}).j({id:"bm-c",className:"bm-p",style:"margin-top: 0;",innerHTML:''},(t,e)=>{e.onclick=()=>{const e=t.T?.Dt;e?.[0]?(t._("bm-h",e?.[0]||""),t._("bm-i",e?.[1]||""),t._("bm-j",e?.[2]||""),t._("bm-k",e?.[3]||"")):t.A("Coordinates are malformed! Did you try clicking on the canvas first?")}}).N().F({type:"number",id:"bm-h",placeholder:"Tl X",min:0,max:2047,step:1,required:!0}).N().F({type:"number",id:"bm-i",placeholder:"Tl Y",min:0,max:2047,step:1,required:!0}).N().F({type:"number",id:"bm-j",placeholder:"Px X",min:0,max:2047,step:1,required:!0}).N().F({type:"number",id:"bm-k",placeholder:"Px Y",min:0,max:2047,step:1,required:!0}).N().N().J({id:"bm-2",textContent:"Upload Template",accept:"image/png, image/jpeg, image/webp, image/bmp, image/gif"}).N().O({id:"bm-0"}).j({id:"bm-d",textContent:"Enable"},(t,e)=>{e.onclick=()=>{const e=document.querySelector("#bm-2"),n=document.querySelector("#bm-h");if(!n.checkValidity())return n.reportValidity(),void t.A("Coordinates are malformed! Did you try clicking on the canvas first?");const s=document.querySelector("#bm-i");if(!s.checkValidity())return s.reportValidity(),void t.A("Coordinates are malformed! Did you try clicking on the canvas first?");const i=document.querySelector("#bm-j");if(!i.checkValidity())return i.reportValidity(),void t.A("Coordinates are malformed! Did you try clicking on the canvas first?");const o=document.querySelector("#bm-k");if(!o.checkValidity())return o.reportValidity(),void t.A("Coordinates are malformed! Did you try clicking on the canvas first?");e?.files[0]?(m.wt(e.files[0],e.files[0]?.name.replace(/\.[^/.]+$/,""),[Number(n.value),Number(s.value),Number(i.value),Number(o.value)]),t.U("Drew to canvas!")):t.A("No file selected!")}}).N().N().V({id:d.k,placeholder:`Status: Sleeping...\nVersion: ${l}`,readOnly:!0}).N().O({id:"bm-1"}).O().j({id:"bm-9",className:"bm-p",innerHTML:"🎨",title:"Template Color Converter"},(t,e)=>{e.addEventListener("click",()=>{window.open("https://pepoafonso.github.io/color_converter_wplace/","_blank","noopener noreferrer")})}).N().N().P({textContent:"Made by SwingTheVine",style:"margin-top: auto;"}).N().N().N().B(document.body),d.W("#bm-l","#bm-g"),p.Tt(d),new MutationObserver((t,e)=>{const n=document.querySelector("#color-1");if(!n)return;let s=document.querySelector("#bm-e");s||(s=document.createElement("button"),s.id="bm-e",s.textContent="Move ↑",s.className="btn btn-soft",s.onclick=function(){const t=this.parentNode.parentNode.parentNode.parentNode,e="Move ↑"==this.textContent;t.parentNode.className=t.parentNode.className.replace(e?"bottom":"top",e?"top":"bottom"),t.style.borderTopLeftRadius=e?"0px":"var(--radius-box)",t.style.borderTopRightRadius=e?"0px":"var(--radius-box)",t.style.borderBottomLeftRadius=e?"var(--radius-box)":"0px",t.style.borderBottomRightRadius=e?"var(--radius-box)":"0px",this.textContent=e?"Move ↓":"Move ↑"},n.parentNode.parentNode.parentNode.parentNode.querySelector("h2").parentNode.appendChild(s))}).observe(document.body,{childList:!0,subtree:!0}),function(...t){(0,console.log)(...t)}(`%c${c}%c (${l}) userscript has loaded!`,"color: cornflowerblue;","")})(); \ No newline at end of file diff --git a/docs/README.md b/docs/README.md index e40fc6c..64ec54c 100644 --- a/docs/README.md +++ b/docs/README.md @@ -35,7 +35,7 @@ Software License: MPL-2.0 Contact Me WakaTime -Total Patches +Total Patches Total Lines of Code Total Comments Compression @@ -48,14 +48,14 @@

Installation Instructions

Supported Browsers - Unupported Browsers + Unupported Browsers

- Blue Marble has been verified to work on mobile devices. Blue Marble was designed on Chrome, but Blue Marble might work on "unsupported" browsers not listed above. Some versions/forks of FireFox work. Some versions/forks of FireFox do not work. + Blue Marble has been verified to work on mobile devices. Blue Marble was designed on Chrome, but Blue Marble might work on "unsupported" browsers not listed above. Some versions/forks of Firefox work. Some versions/forks of Firefox do not work.
Installation instructions for Blue Marble are below. Click the arrows to expand the instructions you want to see. Blue text is a link.

- Computer - Chrome (Click to Expand) + Install Chrome (Computer) (Click to Expand)
  1. Install the TamperMonkey plugin for Chrome. @@ -67,42 +67,11 @@
  2. Left-click "Manage Extension."
  3. Enable "Developer Mode."
    - Enable 'Developer Mode' and 'Allow user scripts'
  4. + Enable 'Developer Mode' and 'Allow user scripts'
  5. Enable "Allow user scripts."
  6. Download the BlueMarble.user.js file in the "assets" of the latest release.
  7. Open the TamperMonkey Dashboard.
    - Enter the TamperMonkey 'Dashboard'
  8. -
  9. Drag the BlueMarble.user.js file inside the dashboard of TamperMonkey. -
    - Drag the userscript into the dashboard
  10. -
  11. Click the "Install" button to install Blue Marble. -
    - Click the 'Install' button
  12. -
  13. Enable Blue Marble inside the TamperMonkey dashboard. -
    - Enable Blue Marble
  14. -
  15. Refresh the wplace.live webpage.
  16. -
-
-
- - Computer - Edge (Click to Expand) - -
    -
  1. Install the TamperMonkey plugin for Microsoft Edge. -
    - Click the 'Get' button
  2. -
  3. Right-click the extention. -
    - Enter the 'Manage Extention' menu
  4. -
  5. Left-click "Manage Extension."
  6. -
  7. Enable "Developer Mode." -
    - Enable 'Developer Mode'
  8. -
  9. Download the BlueMarble.user.js file in the "assets" of the latest release.
  10. -
  11. Open the TamperMonkey Dashboard. -
    Enter the TamperMonkey 'Dashboard'
  12. Drag the BlueMarble.user.js file inside the dashboard of TamperMonkey.
    @@ -118,19 +87,50 @@
- Computer - FireFox (Click to Expand) + Install Edge (Computer) (Click to Expand)
    -
  1. Install the TamperMonkey plugin for FireFox. +
  2. Install the TamperMonkey plugin for Microsoft Edge.
    - Click the 'Add to FireFox' button
  3. + Click the 'Get' button +
  4. Right-click the extention. +
    + Enter the 'Manage Extention' menu
  5. +
  6. Left-click "Manage Extension."
  7. +
  8. Enable "Developer Mode." +
    + Enable 'Developer Mode'
  9. Download the BlueMarble.user.js file in the "assets" of the latest release.
  10. Open the TamperMonkey Dashboard.
    - Enter the TamperMonkey 'Dashboard'
  11. + Enter the TamperMonkey 'Dashboard'
  12. Drag the BlueMarble.user.js file inside the dashboard of TamperMonkey.
    - Drag the userscript into the dashboard
  13. + Drag the userscript into the dashboard +
  14. Click the "Install" button to install Blue Marble. +
    + Click the 'Install' button
  15. +
  16. Enable Blue Marble inside the TamperMonkey dashboard. +
    + Enable Blue Marble
  17. +
  18. Refresh the wplace.live webpage.
  19. +
+
+
+ + Install Firefox (Computer) (Click to Expand) + +
    +
  1. Install the TamperMonkey plugin for Firefox. +
    + Click the 'Add to Firefox' button
  2. +
  3. Download the BlueMarble.user.js file in the "assets" of the latest release.
  4. +
  5. Open the TamperMonkey Dashboard. +
    + Enter the TamperMonkey 'Dashboard'
  6. +
  7. Drag the BlueMarble.user.js file inside the dashboard of TamperMonkey. +
    + Drag the userscript into the dashboard
  8. Click the "Install" button to install Blue Marble.
    Click the 'Install' button
  9. diff --git a/docs/assets/ComputerFirefoxInstall1.png b/docs/assets/ComputerFirefoxInstall1.png new file mode 100644 index 0000000..f02fcef Binary files /dev/null and b/docs/assets/ComputerFirefoxInstall1.png differ diff --git a/docs/assets/ComputerFirefoxInstall2.png b/docs/assets/ComputerFirefoxInstall2.png new file mode 100644 index 0000000..633fe8b Binary files /dev/null and b/docs/assets/ComputerFirefoxInstall2.png differ diff --git a/docs/assets/ComputerFirefoxInstall3.png b/docs/assets/ComputerFirefoxInstall3.png new file mode 100644 index 0000000..a2ea838 Binary files /dev/null and b/docs/assets/ComputerFirefoxInstall3.png differ diff --git a/package-lock.json b/package-lock.json index aefe7b9..21c4f68 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "wplace-bluemarble", - "version": "0.67.0", + "version": "0.69.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "wplace-bluemarble", - "version": "0.67.0", + "version": "0.69.1", "devDependencies": { "esbuild": "^0.25.0", "terser": "^5.43.1" diff --git a/package.json b/package.json index bfd36f4..33ea11c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wplace-bluemarble", - "version": "0.69.0", + "version": "0.69.1", "type": "module", "scripts": { "build": "node build/build.js", diff --git a/src/BlueMarble.meta.js b/src/BlueMarble.meta.js index 2e6d416..3bbada1 100644 --- a/src/BlueMarble.meta.js +++ b/src/BlueMarble.meta.js @@ -1,7 +1,7 @@ // ==UserScript== // @name Blue Marble // @namespace https://github.com/SwingTheVine/ -// @version 0.69.0 +// @version 0.69.1 // @description A userscript to automate and/or enhance the user experience on Wplace.live. Make sure to comply with the site's Terms of Service, and rules! This script is not affiliated with Wplace.live in any way, use at your own risk. This script is not affiliated with TamperMonkey. The author of this userscript is not responsible for any damages, issues, loss of data, or punishment that may occur as a result of using this script. This script is provided "as is" under the MPL-2.0 license. The "Blue Marble" icon is licensed under CC0 1.0 Universal (CC0 1.0) Public Domain Dedication. The image is owned by NASA. // @author SwingTheVine // @license MPL-2.0 diff --git a/src/Overlay.js b/src/Overlay.js index 6036f3c..ea206fe 100644 --- a/src/Overlay.js +++ b/src/Overlay.js @@ -586,8 +586,9 @@ export default class Overlay { if (isDragging) { const touch = event?.touches?.[0]; if (!touch) {return;} - moveMe.style.left = (touch.clientX - offsetX) + 'px'; - moveMe.style.top = (touch.clientY - offsetY) + 'px'; + moveMe.style.left = (touch.clientX - offsetX) + 'px'; // Binds the overlay to the left side of the screen, and sets it's position to the cursor + moveMe.style.top = (touch.clientY - offsetY) + 'px'; // Binds the overlay to the top of the screen, and sets it's position to the cursor + moveMe.style.right = ''; // Destroys the right property to unbind the overlay from the right side of the screen event.preventDefault(); // prevent scrolling while dragging } }, { passive: false }); // Prevents scrolling from being captured