From ca34eeeea82b8a8d80b12e2b0f61ae486421fcbb Mon Sep 17 00:00:00 2001 From: SwingTheVine Date: Thu, 7 Aug 2025 17:25:14 -0400 Subject: [PATCH] Added Enable/Disable buttons and functionality --- dist/BlueMarble.user.js | 4 ++-- docs/CONTRIBUTING.md | 3 +++ docs/README.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- src/BlueMarble.meta.js | 2 +- src/main.js | 15 +++++++++++++-- src/templateManager.js | 12 ++++++++++++ 8 files changed, 35 insertions(+), 9 deletions(-) diff --git a/dist/BlueMarble.user.js b/dist/BlueMarble.user.js index 7d37a09..722df84 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.73.3 +// @version 0.73.7 // @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 @@ -22,4 +22,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),o=(t,e,i)=>(((t,e)=>{e.has(t)||n("Cannot access private method")})(t,e),i);function s(t,e){if(0===t)return e[0];let n="";const i=e.length;for(;t>0;)n=e[t%i]+n,t=Math.floor(t/i);return n}function a(t){let e="";for(let n=0;n0)for(const t in e){const n=t,i=e[t];if(console.log(n),e.hasOwnProperty(t)){const t=n.split(" "),e=Number(t?.[0]),o=t?.[1]||"0",s=i.name||`Template ${e||""}`,a=i.tiles,c={};for(const t in a)if(console.log(t),a.hasOwnProperty(t)){const e=r(a[t]),n=new Blob([e],{type:"image/png"}),i=await createImageBitmap(n);c[t]=i}const l=new m({displayName:s,l:e||this.C?.length||0,h:o||""});l.m=c,this.C.push(l),console.log(this.C),console.log("^^^ This ^^^")}}};var u=GM_info.script.name.toString(),d=GM_info.script.version.toString();!function(t){const e=document.createElement("script");e.setAttribute("bm-o",u),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:o,endpoint:s,blobID:a,blobData:r,blink:c}=t.data,l=Date.now()-c;if(console.groupCollapsed(`%c${e}%c: ${i.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(i),console.groupEnd(),"blue-marble"==o&&a&&r&&!s){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 o=window.fetch;window.fetch=async function(...t){const s=await o.apply(this,t),a=s.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(),o=await a.blob();return console.log(`%c${e}%c: ${i.size} Sending IMAGE message about endpoint "${r}"`,n,""),new Promise(s=>{const c=crypto.randomUUID();i.set(c,t=>{s(new Response(t,{headers:a.headers,status:a.status,statusText:a.statusText})),console.log(`%c${e}%c: ${i.size} Processed blob "${c}"`,n,"")}),window.postMessage({source:"blue-marble",endpoint:r,blobID:c,blobData:o,blink:t})}).catch(o=>{const s=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 ${i.size} blobs processing...\nBlink: ${t.toLocaleString()}\nTime Since Blink: ${String(Math.floor(s/6e4)).padStart(2,"0")}:${String(Math.floor(s/1e3)%60).padStart(2,"0")}.${String(s%1e3).padStart(3,"0")} MM:SS.mmm`),console.error("Exception stack:",o),console.groupEnd()})}return s}});var p=GM_getResourceText("CSS-BM-File");GM_addStyle(p);var b=document.createElement("link");b.href="https://fonts.googleapis.com/css2?family=Roboto+Mono:ital,wght@0,100..700;1,100..700&display=swap",b.rel="preload",b.as="style",b.onload=function(){this.onload=null,this.rel="stylesheet"},document.head.appendChild(b),new class{constructor(){this.D=null,this.I=null,this.k="#bm-5"}N(t){return this.I=t,this.D=new MutationObserver(t=>{for(const e of t)for(const t of e.addedNodes)t instanceof HTMLElement&&t.matches?.(this.k)}),this}B(){return this.D}observe(t,e=!1,n=!1){t.observe(this.I,{childList:e,subtree:n})}};var f=new class{constructor(e,n){i(this,t),this.name=e,this.version=n,this.O=null,this.P="bm-a",this.t=null,this.i=null,this.o=[]}H(t){this.O=t}L(){return this.o.length>0&&(this.i=this.o.pop()),this}j(t){t.appendChild(this.t),this.t=null,this.i=null,this.o=[]}A(n={},i=()=>{}){return i(this,o(this,t,e).call(this,"div",{},n)),this}G(n={},i=()=>{}){return i(this,o(this,t,e).call(this,"p",{},n)),this}J(n={},i=()=>{}){return i(this,o(this,t,e).call(this,"small",{},n)),this}F(n={},i=()=>{}){return i(this,o(this,t,e).call(this,"img",{},n)),this}R(n,i={},s=()=>{}){return s(this,o(this,t,e).call(this,"h"+n,{},i)),this}Y(n={},i=()=>{}){return i(this,o(this,t,e).call(this,"hr",{},n)),this}q(n={},i=()=>{}){return i(this,o(this,t,e).call(this,"br",{},n)),this}X(n={},i=()=>{}){const s=o(this,t,e).call(this,"label",{textContent:n.textContent??""});delete n.textContent;const a=o(this,t,e).call(this,"input",{type:"checkbox"},n);return s.insertBefore(a,s.firstChild),this.L(),i(this,s,a),this}_(n={},i=()=>{}){return i(this,o(this,t,e).call(this,"button",{},n)),this}U(n={},i=()=>{}){const s=n.title??n.textContent??"Help: No info";delete n.textContent,n.title=`Help: ${s}`;const a={textContent:"?",className:"bm-p",onclick:()=>{this.V(this.P,s)}};return i(this,o(this,t,e).call(this,"button",a,n)),this}W(n={},i=()=>{}){return i(this,o(this,t,e).call(this,"input",{},n)),this}Z(n={},i=()=>{}){const s=n.textContent??"";delete n.textContent;const a=o(this,t,e).call(this,"div"),r=o(this,t,e).call(this,"input",{type:"file",style:"display: none !important; visibility: hidden !important; position: absolute !important; left: -9999px !important; width: 0 !important; height: 0 !important; opacity: 0 !important;"},n);this.L();const c=o(this,t,e).call(this,"button",{textContent:s});return this.L(),this.L(),r.setAttribute("tabindex","-1"),r.setAttribute("aria-hidden","true"),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=s}),i(this,a,r,c),this}K(n={},i=()=>{}){return i(this,o(this,t,e).call(this,"textarea",{},n)),this}V(t,e,n=!1){const i=document.getElementById(t.replace(/^#/,""));i&&(i instanceof HTMLInputElement?i.value=e:n?i.textContent=e:i.innerHTML=e)}tt(t,e){let n,i=!1,o=0,s=null,a=0,r=0,c=0,l=0;if(t=document.querySelector("#"==t?.[0]?t:"#"+t),e=document.querySelector("#"==e?.[0]?e:"#"+e),!t||!e)return void this.et(`Can not drag! ${t?"":"moveMe"} ${t||e?"":"and "}${e?"":"iMoveThings "}was not found!`);const h=()=>{if(i){const e=Math.abs(a-c),n=Math.abs(r-l);(e>.5||n>.5)&&(a=c,r=l,t.style.transform=`translate(${a}px, ${r}px)`,t.style.left="0px",t.style.top="0px",t.style.right=""),s=requestAnimationFrame(h)}};let m=null;const u=(u,d)=>{i=!0,m=t.getBoundingClientRect(),n=u-m.left,o=d-m.top;const p=window.getComputedStyle(t).transform;if(p&&"none"!==p){const t=new DOMMatrix(p);a=t.m41,r=t.m42}else a=m.left,r=m.top;c=a,l=r,document.body.style.userSelect="none",e.classList.add("dragging"),s&&cancelAnimationFrame(s),h()},d=()=>{i=!1,s&&(cancelAnimationFrame(s),s=null),document.body.style.userSelect="",e.classList.remove("dragging")};e.addEventListener("mousedown",function(t){t.preventDefault(),u(t.clientX,t.clientY)}),e.addEventListener("touchstart",function(t){const e=t?.touches?.[0];e&&(u(e.clientX,e.clientY),t.preventDefault())},{passive:!1}),document.addEventListener("mousemove",function(t){i&&m&&(c=t.clientX-n,l=t.clientY-o)},{passive:!0}),document.addEventListener("touchmove",function(t){if(i&&m){const e=t?.touches?.[0];if(!e)return;c=e.clientX-n,l=e.clientY-o,t.preventDefault()}},{passive:!1}),document.addEventListener("mouseup",d),document.addEventListener("touchend",d),document.addEventListener("touchcancel",d)}nt(t){(0,console.info)(`${this.name}: ${t}`),this.V(this.P,"Status: "+t,!0)}et(t){(0,console.error)(`${this.name}: ${t}`),this.V(this.P,"Error: "+t,!0)}}(u,d),w=new class{constructor(t,e,n){i(this,c),this.name=t,this.version=e,this.t=n,this.it="1.0.0",this.ot=null,this.st="!#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",this.u=1e3,this.rt=3,this.ct=null,this.lt=null,this.ht="bm-n",this.ut="div#map canvas.maplibregl-canvas",this.dt=null,this.bt="",this.C=[],this.T=null}ft(){if(document.body.contains(this.ct))return this.ct;document.getElementById(this.ht)?.remove();const t=document.querySelector(this.ut),e=document.createElement("canvas");return e.id=this.ht,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.ct=e,window.addEventListener("move",this.wt),window.addEventListener("zoom",this.gt),window.addEventListener("resize",this.$t),this.ct}async vt(){return{whoami:this.name.replace(" ",""),scriptVersion:this.version,schemaVersion:this.it,templates:{}}}async xt(t,e,n){this.T||(this.T=await this.vt(),console.log("Creating JSON...")),this.t.nt(`Creating template at ${n.join(", ")}...`);const i=new m({displayName:e,l:0,h:s(this.ot||0,this.st),file:t,coords:n}),{M:a,S:r}=await i.$(this.u);i.m=a,this.T.templates[`${i.l} ${i.h}`]={name:i.displayName,coords:n.join(", "),enabled:!0,tiles:r},this.C=[],this.C.push(i);const h=(new Intl.NumberFormat).format(i.p);this.t.nt(`Template created at ${n.join(", ")}! Total pixels: ${h}`),console.log(Object.keys(this.T.templates).length),console.log(this.T),console.log(this.C),console.log(JSON.stringify(this.T)),await o(this,c,l).call(this)}yt(){}async Mt(){this.T||(this.T=await this.vt(),console.log("Creating JSON..."))}async St(t,e){const n=this.u*this.rt;e=e[0].toString().padStart(4,"0")+","+e[1].toString().padStart(4,"0"),console.log(`Searching for templates in tile: "${e}"`);const i=this.C;console.log(i),i.sort((t,e)=>t.l-e.l),console.log(i);const o=i.map(t=>{const n=Object.keys(t.m).filter(t=>t.startsWith(e));if(0===n.length)return null;const i=n.map(e=>{const n=e.split(",");return{Tt:t.m[e],Ct:[n[0],n[1]],Dt:[n[2],n[3]]}});return i?.[0]}).filter(Boolean);if(console.log(o),o?.Tt?.length>0){const t=i.filter(t=>Object.keys(t.m).filter(t=>t.startsWith(e)).length>0).reduce((t,e)=>t+(e.p||0),0),n=(new Intl.NumberFormat).format(t);this.t.nt(`Displaying ${o.Tt.length} template${1==o.Tt.length?"":"s"}. Total pixels: ${n}`)}const s=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(s,0,0,n,n);for(const t of o)console.log("Template:"),console.log(t),r.drawImage(t.Tt,Number(t.Dt[0])*this.rt,Number(t.Dt[1])*this.rt);return await a.convertToBlob({type:"image/png"})}It(t){console.log("Importing JSON..."),console.log(t),"BlueMarble"==t?.whoami&&o(this,c,h).call(this,t)}}(u,d,f),g=new class{constructor(t){this.kt=t,this.Nt=!1,this.Bt=[],this.Ot=[]}Pt(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 o=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;","",o),o){case"me":if(i.status&&"2"!=i.status?.toString()[0])return void t.et("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);console.log(i.id),(i.id||0===i.id)&&console.log(s(i.id,"!#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~")),this.kt.ot=i.id,t.V("bm-f",`Username: ${function(t){const e=document.createElement("div");return e.textContent=t,e.innerHTML}(i.name)}`),t.V("bm-b",`Droplets: ${(new Intl.NumberFormat).format(i.droplets)}`),t.V("bm-6",`Next level in ${(new Intl.NumberFormat).format(e)} pixel${1==e?"":"s"}`);break;case"pixel":const o=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.Bt.length&&(!o.length||!l.length))return void t.et("Coordinates are malformed!\nDid you try clicking the canvas first?");this.Bt=[...o,...l];const h=(a=o,r=l,[parseInt(a[0])%4*1e3+parseInt(r[0]),parseInt(a[1])%4*1e3+parseInt(r[1])]),m=document.querySelectorAll("span");for(const t of m)if(t.textContent.trim().includes(`${h[0]}, ${h[1]}`)){let e=document.querySelector("#bm-5");const n=`(Tl X: ${o[0]}, Tl Y: ${o[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 u=n.endpoint.split("/");u=[parseInt(u[u.length-2]),parseInt(u[u.length-1].replace(".png",""))];const d=n.blobID,p=n.blobData,b=await this.kt.St(p,u);window.postMessage({source:"blue-marble",blobID:d,blobData:b,blink:n.blink});break;case"robots":this.Nt="false"==i.userscript?.toString().toLowerCase();break}var a,r})}}(w);f.H(g);var $=JSON.parse(GM_getValue("bmTemplates","{}"));console.log($),w.It($),function(){let t=!1;f.A({id:"bm-l",style:"top: 10px; right: 75px;"}).A({id:"bm-7"}).A({id:"bm-g"}).L().F({alt:"Blue Marble Icon - Click to minimize/maximize",src:"https://raw.githubusercontent.com/SwingTheVine/Wplace-BlueMarble/main/dist/assets/Favicon.png",style:"cursor: pointer;"},(e,n)=>{n.addEventListener("click",()=>{t=!t;const i=document.querySelector("#bm-l"),o=document.querySelector("#bm-7"),s=document.querySelector("#bm-g"),a=document.querySelector("#bm-8"),r=document.querySelector("#bm-c"),c=document.querySelector("#bm-F"),l=document.querySelectorAll("#bm-8 input");t||(i.style.width="auto",i.style.maxWidth="300px",i.style.minWidth="200px",i.style.padding="10px"),["#bm-l h1","#bm-4","#bm-l hr","#bm-3 > *:not(#bm-8)","#bm-2","#bm-1",`#${e.P}`].forEach(e=>{document.querySelectorAll(e).forEach(e=>{e.style.display=t?"none":""})}),t?(a&&(a.style.display="none"),r&&(r.style.display="none"),c&&(c.style.display="none"),l.forEach(t=>{t.style.display="none"}),i.style.width="60px",i.style.height="76px",i.style.maxWidth="60px",i.style.minWidth="60px",i.style.padding="8px",n.style.marginLeft="3px",o.style.textAlign="center",o.style.margin="0",o.style.marginBottom="0",s&&(s.style.display="",s.style.marginBottom="0.25em")):(a&&(a.style.display="",a.style.flexDirection="",a.style.justifyContent="",a.style.alignItems="",a.style.gap="",a.style.textAlign="",a.style.margin=""),r&&(r.style.display=""),c&&(c.style.display="",c.style.marginTop=""),l.forEach(t=>{t.style.display=""}),n.style.marginLeft="",i.style.padding="10px",o.style.textAlign="",o.style.margin="",o.style.marginBottom="",s&&(s.style.marginBottom="0.5em"),i.style.width="",i.style.height=""),n.alt=t?"Blue Marble Icon - Minimized (Click to maximize)":"Blue Marble Icon - Maximized (Click to minimize)"})}).L().R(1,{textContent:u}).L().L().Y().L().A({id:"bm-4"}).G({id:"bm-f",textContent:"Username:"}).L().G({id:"bm-b",textContent:"Droplets:"}).L().G({id:"bm-6",textContent:"Next level in..."}).L().L().Y().L().A({id:"bm-3"}).A({id:"bm-8"})._({id:"bm-c",className:"bm-p",style:"margin-top: 0;",innerHTML:''},(t,e)=>{e.onclick=()=>{const e=t.O?.Bt;e?.[0]?(t.V("bm-h",e?.[0]||""),t.V("bm-i",e?.[1]||""),t.V("bm-j",e?.[2]||""),t.V("bm-k",e?.[3]||"")):t.et("Coordinates are malformed! Did you try clicking on the canvas first?")}}).L().W({type:"number",id:"bm-h",placeholder:"Tl X",min:0,max:2047,step:1,required:!0}).L().W({type:"number",id:"bm-i",placeholder:"Tl Y",min:0,max:2047,step:1,required:!0}).L().W({type:"number",id:"bm-j",placeholder:"Px X",min:0,max:2047,step:1,required:!0}).L().W({type:"number",id:"bm-k",placeholder:"Px Y",min:0,max:2047,step:1,required:!0}).L().L().Z({id:"bm-2",textContent:"Upload Template",accept:"image/png, image/jpeg, image/webp, image/bmp, image/gif"}).L().A({id:"bm-0"})._({id:"bm-F",textContent:"Create"},(t,e)=>{e.onclick=()=>{const e=document.querySelector("#bm-2"),n=document.querySelector("#bm-h");if(!n.checkValidity())return n.reportValidity(),void t.et("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.et("Coordinates are malformed! Did you try clicking on the canvas first?");const o=document.querySelector("#bm-j");if(!o.checkValidity())return o.reportValidity(),void t.et("Coordinates are malformed! Did you try clicking on the canvas first?");const s=document.querySelector("#bm-k");if(!s.checkValidity())return s.reportValidity(),void t.et("Coordinates are malformed! Did you try clicking on the canvas first?");e?.files[0]?(w.xt(e.files[0],e.files[0]?.name.replace(/\.[^/.]+$/,""),[Number(n.value),Number(i.value),Number(o.value),Number(s.value)]),t.nt("Drew to canvas!")):t.et("No file selected!")}}).L().L().K({id:f.P,placeholder:`Status: Sleeping...\nVersion: ${d}`,readOnly:!0}).L().A({id:"bm-1"}).A()._({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")})}).L().L().J({textContent:"Made by SwingTheVine",style:"margin-top: auto;"}).L().L().L().j(document.body)}(),f.tt("#bm-l","#bm-g"),g.Pt(f),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${u}%c (${d}) userscript has loaded!`,"color: cornflowerblue;","")})(); \ No newline at end of file +(()=>{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),o=(t,e,i)=>(((t,e)=>{e.has(t)||n("Cannot access private method")})(t,e),i);function s(t,e){if(0===t)return e[0];let n="";const i=e.length;for(;t>0;)n=e[t%i]+n,t=Math.floor(t/i);return n}function a(t){let e="";for(let n=0;n0)for(const t in e){const n=t,i=e[t];if(console.log(n),e.hasOwnProperty(t)){const t=n.split(" "),e=Number(t?.[0]),o=t?.[1]||"0",s=i.name||`Template ${e||""}`,a=i.tiles,c={};for(const t in a)if(console.log(t),a.hasOwnProperty(t)){const e=r(a[t]),n=new Blob([e],{type:"image/png"}),i=await createImageBitmap(n);c[t]=i}const l=new m({displayName:s,l:e||this.D?.length||0,h:o||""});l.m=c,this.D.push(l),console.log(this.D),console.log("^^^ This ^^^")}}};var u=GM_info.script.name.toString(),d=GM_info.script.version.toString();!function(t){const e=document.createElement("script");e.setAttribute("bm-o",u),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:o,endpoint:s,blobID:a,blobData:r,blink:c}=t.data,l=Date.now()-c;if(console.groupCollapsed(`%c${e}%c: ${i.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(i),console.groupEnd(),"blue-marble"==o&&a&&r&&!s){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 o=window.fetch;window.fetch=async function(...t){const s=await o.apply(this,t),a=s.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(),o=await a.blob();return console.log(`%c${e}%c: ${i.size} Sending IMAGE message about endpoint "${r}"`,n,""),new Promise(s=>{const c=crypto.randomUUID();i.set(c,t=>{s(new Response(t,{headers:a.headers,status:a.status,statusText:a.statusText})),console.log(`%c${e}%c: ${i.size} Processed blob "${c}"`,n,"")}),window.postMessage({source:"blue-marble",endpoint:r,blobID:c,blobData:o,blink:t})}).catch(o=>{const s=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 ${i.size} blobs processing...\nBlink: ${t.toLocaleString()}\nTime Since Blink: ${String(Math.floor(s/6e4)).padStart(2,"0")}:${String(Math.floor(s/1e3)%60).padStart(2,"0")}.${String(s%1e3).padStart(3,"0")} MM:SS.mmm`),console.error("Exception stack:",o),console.groupEnd()})}return s}});var p=GM_getResourceText("CSS-BM-File");GM_addStyle(p);var b=document.createElement("link");b.href="https://fonts.googleapis.com/css2?family=Roboto+Mono:ital,wght@0,100..700;1,100..700&display=swap",b.rel="preload",b.as="style",b.onload=function(){this.onload=null,this.rel="stylesheet"},document.head.appendChild(b),new class{constructor(){this.C=null,this.I=null,this.k="#bm-5"}N(t){return this.I=t,this.C=new MutationObserver(t=>{for(const e of t)for(const t of e.addedNodes)t instanceof HTMLElement&&t.matches?.(this.k)}),this}B(){return this.C}observe(t,e=!1,n=!1){t.observe(this.I,{childList:e,subtree:n})}};var f=new class{constructor(e,n){i(this,t),this.name=e,this.version=n,this.O=null,this.P="bm-a",this.t=null,this.i=null,this.o=[]}H(t){this.O=t}L(){return this.o.length>0&&(this.i=this.o.pop()),this}j(t){t.appendChild(this.t),this.t=null,this.i=null,this.o=[]}A(n={},i=()=>{}){return i(this,o(this,t,e).call(this,"div",{},n)),this}G(n={},i=()=>{}){return i(this,o(this,t,e).call(this,"p",{},n)),this}J(n={},i=()=>{}){return i(this,o(this,t,e).call(this,"small",{},n)),this}F(n={},i=()=>{}){return i(this,o(this,t,e).call(this,"img",{},n)),this}R(n,i={},s=()=>{}){return s(this,o(this,t,e).call(this,"h"+n,{},i)),this}Y(n={},i=()=>{}){return i(this,o(this,t,e).call(this,"hr",{},n)),this}q(n={},i=()=>{}){return i(this,o(this,t,e).call(this,"br",{},n)),this}X(n={},i=()=>{}){const s=o(this,t,e).call(this,"label",{textContent:n.textContent??""});delete n.textContent;const a=o(this,t,e).call(this,"input",{type:"checkbox"},n);return s.insertBefore(a,s.firstChild),this.L(),i(this,s,a),this}_(n={},i=()=>{}){return i(this,o(this,t,e).call(this,"button",{},n)),this}U(n={},i=()=>{}){const s=n.title??n.textContent??"Help: No info";delete n.textContent,n.title=`Help: ${s}`;const a={textContent:"?",className:"bm-p",onclick:()=>{this.V(this.P,s)}};return i(this,o(this,t,e).call(this,"button",a,n)),this}W(n={},i=()=>{}){return i(this,o(this,t,e).call(this,"input",{},n)),this}Z(n={},i=()=>{}){const s=n.textContent??"";delete n.textContent;const a=o(this,t,e).call(this,"div"),r=o(this,t,e).call(this,"input",{type:"file",style:"display: none !important; visibility: hidden !important; position: absolute !important; left: -9999px !important; width: 0 !important; height: 0 !important; opacity: 0 !important;"},n);this.L();const c=o(this,t,e).call(this,"button",{textContent:s});return this.L(),this.L(),r.setAttribute("tabindex","-1"),r.setAttribute("aria-hidden","true"),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=s}),i(this,a,r,c),this}K(n={},i=()=>{}){return i(this,o(this,t,e).call(this,"textarea",{},n)),this}V(t,e,n=!1){const i=document.getElementById(t.replace(/^#/,""));i&&(i instanceof HTMLInputElement?i.value=e:n?i.textContent=e:i.innerHTML=e)}tt(t,e){let n,i=!1,o=0,s=null,a=0,r=0,c=0,l=0;if(t=document.querySelector("#"==t?.[0]?t:"#"+t),e=document.querySelector("#"==e?.[0]?e:"#"+e),!t||!e)return void this.et(`Can not drag! ${t?"":"moveMe"} ${t||e?"":"and "}${e?"":"iMoveThings "}was not found!`);const h=()=>{if(i){const e=Math.abs(a-c),n=Math.abs(r-l);(e>.5||n>.5)&&(a=c,r=l,t.style.transform=`translate(${a}px, ${r}px)`,t.style.left="0px",t.style.top="0px",t.style.right=""),s=requestAnimationFrame(h)}};let m=null;const u=(u,d)=>{i=!0,m=t.getBoundingClientRect(),n=u-m.left,o=d-m.top;const p=window.getComputedStyle(t).transform;if(p&&"none"!==p){const t=new DOMMatrix(p);a=t.m41,r=t.m42}else a=m.left,r=m.top;c=a,l=r,document.body.style.userSelect="none",e.classList.add("dragging"),s&&cancelAnimationFrame(s),h()},d=()=>{i=!1,s&&(cancelAnimationFrame(s),s=null),document.body.style.userSelect="",e.classList.remove("dragging")};e.addEventListener("mousedown",function(t){t.preventDefault(),u(t.clientX,t.clientY)}),e.addEventListener("touchstart",function(t){const e=t?.touches?.[0];e&&(u(e.clientX,e.clientY),t.preventDefault())},{passive:!1}),document.addEventListener("mousemove",function(t){i&&m&&(c=t.clientX-n,l=t.clientY-o)},{passive:!0}),document.addEventListener("touchmove",function(t){if(i&&m){const e=t?.touches?.[0];if(!e)return;c=e.clientX-n,l=e.clientY-o,t.preventDefault()}},{passive:!1}),document.addEventListener("mouseup",d),document.addEventListener("touchend",d),document.addEventListener("touchcancel",d)}nt(t){(0,console.info)(`${this.name}: ${t}`),this.V(this.P,"Status: "+t,!0)}et(t){(0,console.error)(`${this.name}: ${t}`),this.V(this.P,"Error: "+t,!0)}}(u,d),w=new class{constructor(t,e,n){i(this,c),this.name=t,this.version=e,this.t=n,this.it="1.0.0",this.ot=null,this.st="!#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",this.u=1e3,this.rt=3,this.ct=null,this.lt=null,this.ht="bm-n",this.ut="div#map canvas.maplibregl-canvas",this.dt=null,this.bt="",this.D=[],this.T=null,this.ft=!0}wt(){if(document.body.contains(this.ct))return this.ct;document.getElementById(this.ht)?.remove();const t=document.querySelector(this.ut),e=document.createElement("canvas");return e.id=this.ht,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.ct=e,window.addEventListener("move",this.gt),window.addEventListener("zoom",this.$t),window.addEventListener("resize",this.vt),this.ct}async xt(){return{whoami:this.name.replace(" ",""),scriptVersion:this.version,schemaVersion:this.it,templates:{}}}async yt(t,e,n){this.T||(this.T=await this.xt(),console.log("Creating JSON...")),this.t.nt(`Creating template at ${n.join(", ")}...`);const i=new m({displayName:e,l:0,h:s(this.ot||0,this.st),file:t,coords:n}),{M:a,S:r}=await i.$(this.u);i.m=a,this.T.templates[`${i.l} ${i.h}`]={name:i.displayName,coords:n.join(", "),enabled:!0,tiles:r},this.D=[],this.D.push(i);const h=(new Intl.NumberFormat).format(i.p);this.t.nt(`Template created at ${n.join(", ")}! Total pixels: ${h}`),console.log(Object.keys(this.T.templates).length),console.log(this.T),console.log(this.D),console.log(JSON.stringify(this.T)),await o(this,c,l).call(this)}Mt(){}async St(){this.T||(this.T=await this.xt(),console.log("Creating JSON..."))}async Tt(t,e){if(!this.ft)return t;const n=this.u*this.rt;e=e[0].toString().padStart(4,"0")+","+e[1].toString().padStart(4,"0"),console.log(`Searching for templates in tile: "${e}"`);const i=this.D;console.log(i),i.sort((t,e)=>t.l-e.l),console.log(i);const o=i.map(t=>{const n=Object.keys(t.m).filter(t=>t.startsWith(e));if(0===n.length)return null;const i=n.map(e=>{const n=e.split(",");return{Dt:t.m[e],Ct:[n[0],n[1]],It:[n[2],n[3]]}});return i?.[0]}).filter(Boolean);if(console.log(o),o?.Dt?.length>0){const t=i.filter(t=>Object.keys(t.m).filter(t=>t.startsWith(e)).length>0).reduce((t,e)=>t+(e.p||0),0),n=(new Intl.NumberFormat).format(t);this.t.nt(`Displaying ${o.Dt.length} template${1==o.Dt.length?"":"s"}. Total pixels: ${n}`)}const s=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(s,0,0,n,n);for(const t of o)console.log("Template:"),console.log(t),r.drawImage(t.Dt,Number(t.It[0])*this.rt,Number(t.It[1])*this.rt);return await a.convertToBlob({type:"image/png"})}kt(t){console.log("Importing JSON..."),console.log(t),"BlueMarble"==t?.whoami&&o(this,c,h).call(this,t)}Nt(t){this.ft=t}}(u,d,f),g=new class{constructor(t){this.Bt=t,this.Ot=!1,this.Pt=[],this.zt=[]}Et(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 o=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;","",o),o){case"me":if(i.status&&"2"!=i.status?.toString()[0])return void t.et("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);console.log(i.id),(i.id||0===i.id)&&console.log(s(i.id,"!#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~")),this.Bt.ot=i.id,t.V("bm-f",`Username: ${function(t){const e=document.createElement("div");return e.textContent=t,e.innerHTML}(i.name)}`),t.V("bm-b",`Droplets: ${(new Intl.NumberFormat).format(i.droplets)}`),t.V("bm-6",`Next level in ${(new Intl.NumberFormat).format(e)} pixel${1==e?"":"s"}`);break;case"pixel":const o=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.Pt.length&&(!o.length||!l.length))return void t.et("Coordinates are malformed!\nDid you try clicking the canvas first?");this.Pt=[...o,...l];const h=(a=o,r=l,[parseInt(a[0])%4*1e3+parseInt(r[0]),parseInt(a[1])%4*1e3+parseInt(r[1])]),m=document.querySelectorAll("span");for(const t of m)if(t.textContent.trim().includes(`${h[0]}, ${h[1]}`)){let e=document.querySelector("#bm-5");const n=`(Tl X: ${o[0]}, Tl Y: ${o[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 u=n.endpoint.split("/");u=[parseInt(u[u.length-2]),parseInt(u[u.length-1].replace(".png",""))];const d=n.blobID,p=n.blobData,b=await this.Bt.Tt(p,u);window.postMessage({source:"blue-marble",blobID:d,blobData:b,blink:n.blink});break;case"robots":this.Ot="false"==i.userscript?.toString().toLowerCase();break}var a,r})}}(w);f.H(g);var $=JSON.parse(GM_getValue("bmTemplates","{}"));console.log($),w.kt($),function(){let t=!1;f.A({id:"bm-l",style:"top: 10px; right: 75px;"}).A({id:"bm-7"}).A({id:"bm-g"}).L().F({alt:"Blue Marble Icon - Click to minimize/maximize",src:"https://raw.githubusercontent.com/SwingTheVine/Wplace-BlueMarble/main/dist/assets/Favicon.png",style:"cursor: pointer;"},(e,n)=>{n.addEventListener("click",()=>{t=!t;const i=document.querySelector("#bm-l"),o=document.querySelector("#bm-7"),s=document.querySelector("#bm-g"),a=document.querySelector("#bm-8"),r=document.querySelector("#bm-c"),c=document.querySelector("#bm-G"),l=document.querySelectorAll("#bm-8 input");t||(i.style.width="auto",i.style.maxWidth="300px",i.style.minWidth="200px",i.style.padding="10px"),["#bm-l h1","#bm-4","#bm-l hr","#bm-3 > *:not(#bm-8)","#bm-2","#bm-1",`#${e.P}`].forEach(e=>{document.querySelectorAll(e).forEach(e=>{e.style.display=t?"none":""})}),t?(a&&(a.style.display="none"),r&&(r.style.display="none"),c&&(c.style.display="none"),l.forEach(t=>{t.style.display="none"}),i.style.width="60px",i.style.height="76px",i.style.maxWidth="60px",i.style.minWidth="60px",i.style.padding="8px",n.style.marginLeft="3px",o.style.textAlign="center",o.style.margin="0",o.style.marginBottom="0",s&&(s.style.display="",s.style.marginBottom="0.25em")):(a&&(a.style.display="",a.style.flexDirection="",a.style.justifyContent="",a.style.alignItems="",a.style.gap="",a.style.textAlign="",a.style.margin=""),r&&(r.style.display=""),c&&(c.style.display="",c.style.marginTop=""),l.forEach(t=>{t.style.display=""}),n.style.marginLeft="",i.style.padding="10px",o.style.textAlign="",o.style.margin="",o.style.marginBottom="",s&&(s.style.marginBottom="0.5em"),i.style.width="",i.style.height=""),n.alt=t?"Blue Marble Icon - Minimized (Click to maximize)":"Blue Marble Icon - Maximized (Click to minimize)"})}).L().R(1,{textContent:u}).L().L().Y().L().A({id:"bm-4"}).G({id:"bm-f",textContent:"Username:"}).L().G({id:"bm-b",textContent:"Droplets:"}).L().G({id:"bm-6",textContent:"Next level in..."}).L().L().Y().L().A({id:"bm-3"}).A({id:"bm-8"})._({id:"bm-c",className:"bm-p",style:"margin-top: 0;",innerHTML:''},(t,e)=>{e.onclick=()=>{const e=t.O?.Pt;e?.[0]?(t.V("bm-h",e?.[0]||""),t.V("bm-i",e?.[1]||""),t.V("bm-j",e?.[2]||""),t.V("bm-k",e?.[3]||"")):t.et("Coordinates are malformed! Did you try clicking on the canvas first?")}}).L().W({type:"number",id:"bm-h",placeholder:"Tl X",min:0,max:2047,step:1,required:!0}).L().W({type:"number",id:"bm-i",placeholder:"Tl Y",min:0,max:2047,step:1,required:!0}).L().W({type:"number",id:"bm-j",placeholder:"Px X",min:0,max:2047,step:1,required:!0}).L().W({type:"number",id:"bm-k",placeholder:"Px Y",min:0,max:2047,step:1,required:!0}).L().L().Z({id:"bm-2",textContent:"Upload Template",accept:"image/png, image/jpeg, image/webp, image/bmp, image/gif"}).L().A({id:"bm-0"})._({id:"bm-d",textContent:"Enable"},(t,e)=>{e.onclick=()=>{t.O?.Bt?.Nt(!0),t.nt("Enabled templates!")}}).L()._({id:"bm-G",textContent:"Create"},(t,e)=>{e.onclick=()=>{const e=document.querySelector("#bm-2"),n=document.querySelector("#bm-h");if(!n.checkValidity())return n.reportValidity(),void t.et("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.et("Coordinates are malformed! Did you try clicking on the canvas first?");const o=document.querySelector("#bm-j");if(!o.checkValidity())return o.reportValidity(),void t.et("Coordinates are malformed! Did you try clicking on the canvas first?");const s=document.querySelector("#bm-k");if(!s.checkValidity())return s.reportValidity(),void t.et("Coordinates are malformed! Did you try clicking on the canvas first?");e?.files[0]?(w.yt(e.files[0],e.files[0]?.name.replace(/\.[^/.]+$/,""),[Number(n.value),Number(i.value),Number(o.value),Number(s.value)]),t.nt("Drew to canvas!")):t.et("No file selected!")}}).L()._({id:"bm-B",textContent:"Disable"},(t,e)=>{e.onclick=()=>{t.O?.Bt?.Nt(!1),t.nt("Disabled templates!")}}).L().L().K({id:f.P,placeholder:`Status: Sleeping...\nVersion: ${d}`,readOnly:!0}).L().A({id:"bm-1"}).A()._({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")})}).L().L().J({textContent:"Made by SwingTheVine",style:"margin-top: auto;"}).L().L().L().j(document.body)}(),f.tt("#bm-l","#bm-g"),g.Et(f),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${u}%c (${d}) userscript has loaded!`,"color: cornflowerblue;","")})(); \ No newline at end of file diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index 6588222..d16ee6a 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -186,6 +186,7 @@ classDiagram } class templateManager { userID : number + templatesShouldBeDrawn : boolean +createJSON() +createTemplate() -storeTemplates() @@ -193,6 +194,7 @@ classDiagram +drawTemplateOnTile() +importJSON() +parseBlueMarble() + +setTemplatesShouldBeDrawn() } class Template { +createTemplateTiles() @@ -216,6 +218,7 @@ classDiagram apiManager ..> templateManager : calls drawTemplateOnTiles(), sets userID apiManager ..> utils : calls escapeHTML(), numberToEncoded(), serverTPtoDisplayTP() Overlay ..> apiManager : uses coordsTilePixel + Overlay ..> templateManager : calls setTemplatesShouldBeDrawn() templateManager *-- Template : manages templateManager ..> utils : calls base64ToUint8(), numberToEncoded() Template ..> utils : calls uint8ToBase64() diff --git a/docs/README.md b/docs/README.md index 8ddd51d..ec7977b 100644 --- a/docs/README.md +++ b/docs/README.md @@ -44,7 +44,7 @@ Software License: MPL-2.0 Contact Me WakaTime -Total Patches +Total Patches Total Lines of Code Total Comments Compression diff --git a/package-lock.json b/package-lock.json index 9fbb799..caa30b8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "wplace-bluemarble", - "version": "0.73.3", + "version": "0.73.7", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "wplace-bluemarble", - "version": "0.73.3", + "version": "0.73.7", "devDependencies": { "esbuild": "^0.25.0", "terser": "^5.43.1" diff --git a/package.json b/package.json index a17e595..b6f91e3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wplace-bluemarble", - "version": "0.73.3", + "version": "0.73.7", "type": "module", "scripts": { "build": "node build/build.js", diff --git a/src/BlueMarble.meta.js b/src/BlueMarble.meta.js index 8e5a0dd..06ec136 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.73.3 +// @version 0.73.7 // @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/main.js b/src/main.js index f3c38ef..9138d8e 100644 --- a/src/main.js +++ b/src/main.js @@ -460,6 +460,12 @@ function buildOverlayMain() { .buildElement() .addInputFile({'id': 'bm-input-file-template', 'textContent': 'Upload Template', 'accept': 'image/png, image/jpeg, image/webp, image/bmp, image/gif'}).buildElement() .addDiv({'id': 'bm-contain-buttons-template'}) + .addButton({'id': 'bm-button-enable', 'textContent': 'Enable'}, (instance, button) => { + button.onclick = () => { + instance.apiManager?.templateManager?.setTemplatesShouldBeDrawn(true); + instance.handleDisplayStatus(`Enabled templates!`); + } + }).buildElement() .addButton({'id': 'bm-button-create', 'textContent': 'Create'}, (instance, button) => { button.onclick = () => { const input = document.querySelector('#bm-input-file-template'); @@ -486,7 +492,12 @@ function buildOverlayMain() { instance.handleDisplayStatus(`Drew to canvas!`); } }).buildElement() - // .addButton({'id': 'bm-button-disable', 'textContent': 'Disable'}).buildElement() + .addButton({'id': 'bm-button-disable', 'textContent': 'Disable'}, (instance, button) => { + button.onclick = () => { + instance.apiManager?.templateManager?.setTemplatesShouldBeDrawn(false); + instance.handleDisplayStatus(`Disabled templates!`); + } + }).buildElement() .buildElement() .addTextarea({'id': overlay.outputStatusId, 'placeholder': `Status: Sleeping...\nVersion: ${version}`, 'readOnly': true}).buildElement() .addDiv({'id': 'bm-contain-buttons-action'}) @@ -505,4 +516,4 @@ function buildOverlayMain() { .buildElement() .buildElement() .buildOverlay(document.body); -} \ No newline at end of file +} diff --git a/src/templateManager.js b/src/templateManager.js index 5951ee3..90e3f87 100644 --- a/src/templateManager.js +++ b/src/templateManager.js @@ -59,6 +59,7 @@ export default class TemplateManager { this.templateState = ''; // The state of the template ('blob', 'proccessing', 'template', etc.) this.templatesArray = []; // All Template instnaces currently loaded (Template) this.templatesJSON = null; // All templates currently loaded (JSON) + this.templatesShouldBeDrawn = true; // Should ALL templates be drawn to the canvas? } /** Retrieves the pixel art canvas. @@ -203,6 +204,9 @@ export default class TemplateManager { */ async drawTemplateOnTile(tileBlob, tileCoords) { + // Returns early if no templates should be drawn + if (!this.templatesShouldBeDrawn) {return tileBlob;} + const drawSize = this.tileSize * this.drawMult; // Calculate draw multiplier for scaling // Format tile coordinates with proper padding for consistent lookup @@ -374,4 +378,12 @@ export default class TemplateManager { #parseOSU() { } + + /** Sets the `templatesShouldBeDrawn` boolean to a value. + * @param {boolean} value - The value to set the boolean to + * @since 0.73.7 + */ + setTemplatesShouldBeDrawn(value) { + this.templatesShouldBeDrawn = value; + } }