NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript==
// @name Blue Marble
// @namespace https://github.com/KeksTM/
// @version 0.78.13
// @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
// @supportURL https://discord.gg/tpeBPy46hf
// @homepageURL https://github.com/x/Wplace-BlueMarble-Auto-Fill
// @icon https://raw.githubusercontent.com/KeksTM/Wplace-BlueMarble-Auto-Fill/refs/heads/main/dist/assets/Favicon.png
// @updateURL https://raw.githubusercontent.com/KeksTM/Wplace-BlueMarble-Auto-Fill/main/dist/BlueMarble.user.js
// @downloadURL https://raw.githubusercontent.com/KeksTM/Wplace-BlueMarble-Auto-Fill/main/dist/BlueMarble.user.js
// @run-at document-start
// @match https://*.wplace.live/*
// @connect *
// @grant GM_getResourceText
// @grant GM_addStyle
// @grant GM.setValue
// @grant GM_getValue
// @resource CSS-BM-File https://raw.githubusercontent.com/KeksTM/Wplace-BlueMarble-Auto-Fill/refs/heads/main/dist/BlueMarble.user.css
// ==/UserScript==
// Wplace --> https://wplace.live
// License --> https://www.mozilla.org/en-US/MPL/2.0/
(()=>{var e,t,n=e=>{throw TypeError(e)},o=(e,t,o)=>t.has(e)?n("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(e):t.set(e,o),i=(e,t,o)=>(((e,t)=>{t.has(e)||n("Cannot access private method")})(e,t),o),s=class{constructor(t,n){o(this,e),this.name=t,this.version=n,this.o=null,this.i="bm-b",this.l=null,this.u=null,this.m=[]}p(e){this.o=e}h(){return this.m.length>0&&(this.u=this.m.pop()),this}$(e){e?.appendChild(this.l),this.l=null,this.u=null,this.m=[]}C(n={},o=()=>{}){return o(this,i(this,e,t).call(this,"div",{},n)),this}O(n={},o=()=>{}){return o(this,i(this,e,t).call(this,"p",{},n)),this}v(n={},o=()=>{}){return o(this,i(this,e,t).call(this,"small",{},n)),this}L(n={},o=()=>{}){return o(this,i(this,e,t).call(this,"img",{},n)),this}T(n,o={},s=()=>{}){return s(this,i(this,e,t).call(this,"h"+n,{},o)),this}k(n={},o=()=>{}){return o(this,i(this,e,t).call(this,"hr",{},n)),this}P(n={},o=()=>{}){return o(this,i(this,e,t).call(this,"br",{},n)),this}A(n={},o=()=>{}){const s=i(this,e,t).call(this,"label",{textContent:n.textContent??""});delete n.textContent;const a=i(this,e,t).call(this,"input",{type:"checkbox"},n);return s.insertBefore(a,s.firstChild),this.h(),o(this,s,a),this}I(n={},o=()=>{}){return o(this,i(this,e,t).call(this,"button",{},n)),this}N(n={},o=()=>{}){const s=n.title??n.textContent??"Help: No info";delete n.textContent,n.title=`Help: ${s}`;const a={textContent:"?",className:"bm-q",onclick:()=>{this.M(this.i,s)}};return o(this,i(this,e,t).call(this,"button",a,n)),this}S(n={},o=()=>{}){return o(this,i(this,e,t).call(this,"input",{},n)),this}F(n={},o=()=>{}){const s=n.textContent??"";delete n.textContent;const a=i(this,e,t).call(this,"div"),l=i(this,e,t).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.h();const c=i(this,e,t).call(this,"button",{textContent:s});return this.h(),this.h(),l.setAttribute("tabindex","-1"),l.setAttribute("aria-hidden","true"),c.addEventListener("click",()=>{l.click()}),l.addEventListener("change",()=>{c.style.maxWidth=`${c.offsetWidth}px`,l.files.length>0?c.textContent=l.files[0].name:c.textContent=s}),o(this,a,l,c),this}U(n={},o=()=>{}){return o(this,i(this,e,t).call(this,"textarea",{},n)),this}M(e,t,n=!1){const o=document.getElementById(e.replace(/^#/,""));o&&(o instanceof HTMLInputElement?o.value=t:n?o.textContent=t:o.innerHTML=t)}W(e,t){let n,o=!1,i=0,s=null,a=0,l=0,c=0,r=0;if(e=document.querySelector("#"==e?.[0]?e:"#"+e),t=document.querySelector("#"==t?.[0]?t:"#"+t),!e||!t)return void this.B(`Can not drag! ${e?"":"moveMe"} ${e||t?"":"and "}${t?"":"iMoveThings "}was not found!`);const u=()=>{if(o){const t=Math.abs(a-c),n=Math.abs(l-r);(t>.5||n>.5)&&(a=c,l=r,e.style.transform=`translate(${a}px, ${l}px)`,e.style.left="0px",e.style.top="0px",e.style.right=""),s=requestAnimationFrame(u)}};let d=null;const m=(m,p)=>{o=!0,d=e.getBoundingClientRect(),n=m-d.left,i=p-d.top;const h=window.getComputedStyle(e).transform;if(h&&"none"!==h){const e=new DOMMatrix(h);a=e.m41,l=e.m42}else a=d.left,l=d.top;c=a,r=l,document.body.style.userSelect="none",t.classList.add("dragging"),s&&cancelAnimationFrame(s),u()},p=()=>{o=!1,s&&(cancelAnimationFrame(s),s=null),document.body.style.userSelect="",t.classList.remove("dragging")};t.addEventListener("mousedown",function(e){e.preventDefault(),m(e.clientX,e.clientY)}),t.addEventListener("touchstart",function(e){const t=e?.touches?.[0];t&&(m(t.clientX,t.clientY),e.preventDefault())},{passive:!1}),document.addEventListener("mousemove",function(e){o&&d&&(c=e.clientX-n,r=e.clientY-i)},{passive:!0}),document.addEventListener("touchmove",function(e){if(o&&d){const t=e?.touches?.[0];if(!t)return;c=t.clientX-n,r=t.clientY-i,e.preventDefault()}},{passive:!1}),document.addEventListener("mouseup",p),document.addEventListener("touchend",p),document.addEventListener("touchcancel",p)}D(e){(0,console.info)(`${this.name}: ${e}`),this.M(this.i,"Status: "+e,!0)}B(e){(0,console.error)(`${this.name}: ${e}`),this.M(this.i,"Error: "+e,!0)}};function a(e,t){if(0===e)return t[0];let n="";const o=t.length;for(;e>0;)n=t[e%o]+n,e=Math.floor(e/o);return n}function l(e){let t="";for(let n=0;n<e.length;n++)t+=String.fromCharCode(e[n]);return btoa(t)}function c(e){const t=atob(e),n=new Uint8Array(t.length);for(let e=0;e<t.length;e++)n[e]=t.charCodeAt(e);return n}e=new WeakSet,t=function(e,t={},n={}){const o=document.createElement(e);this.l?(this.u?.appendChild(o),this.m.push(this.u),this.u=o):(this.l=o,this.u=o);for(const[e,n]of Object.entries(t))o[e]=n;for(const[e,t]of Object.entries(n))o[e]=t;return o};var r,u,d,m=class{constructor({displayName:e="My template",_:t=0,G:n="",url:o="",file:i=null,coords:s=null,R:a=null,Y:l=1e3}={}){this.displayName=e,this._=t,this.G=n,this.url=o,this.file=i,this.coords=s,this.R=a,this.Y=l,this.J=0}async j(){console.log("Template coordinates:",this.coords);const e=await createImageBitmap(this.file),t=e.width,n=e.height,o=t*n;console.log(`Template pixel analysis - Dimensions: ${t}Ć${n} = ${o.toLocaleString()} pixels`),this.J=o;const i={},s={},a=new OffscreenCanvas(this.Y,this.Y),c=a.getContext("2d",{X:!0});for(let o=this.coords[3];o<n+this.coords[3];){const r=Math.min(this.Y-o%this.Y,n-(o-this.coords[3]));console.log(`Math.min(${this.Y} - (${o} % ${this.Y}), ${n} - (${o-this.coords[3]}))`);for(let n=this.coords[2];n<t+this.coords[2];){console.log(`Pixel X: ${n}\nPixel Y: ${o}`);const u=Math.min(this.Y-n%this.Y,t-(n-this.coords[2]));console.log(`Math.min(${this.Y} - (${n} % ${this.Y}), ${t} - (${n-this.coords[2]}))`),console.log(`Draw Size X: ${u}\nDraw Size Y: ${r}`);const d=3*u,m=3*r;a.width=d,a.height=m,console.log(`Draw X: ${u}\nDraw Y: ${r}\nCanvas Width: ${d}\nCanvas Height: ${m}`),c.imageSmoothingEnabled=!1,console.log(`Getting X ${n}-${n+u}\nGetting Y ${o}-${o+r}`),c.clearRect(0,0,d,m),c.drawImage(e,n-this.coords[2],o-this.coords[3],u,r,0,0,3*u,3*r);const p=c.getImageData(0,0,d,m);for(let e=0;e<m;e++)for(let t=0;t<d;t++)if(t%3!=1||e%3!=1){const n=4*(e*d+t);p.data[n+3]=0}console.log(`Shreaded pixels for ${n}, ${o}`,p),c.putImageData(p,0,0);const h=`${(this.coords[0]+Math.floor(n/1e3)).toString().padStart(4,"0")},${(this.coords[1]+Math.floor(o/1e3)).toString().padStart(4,"0")},${(n%1e3).toString().padStart(3,"0")},${(o%1e3).toString().padStart(3,"0")}`;i[h]=await createImageBitmap(a);const f=await a.convertToBlob(),b=await f.arrayBuffer(),$=Array.from(new Uint8Array(b));s[h]=l($),console.log(i),n+=u}o+=r}return console.log("Template Tiles: ",i),console.log("Template Tiles Buffers: ",s),{q:i,H:s}}};r=new WeakSet,u=async function(){GM.setValue("bmTemplates",JSON.stringify(this.V))},d=async function(e){console.log("Parsing BlueMarble...");const t=e.templates;if(console.log(`BlueMarble length: ${Object.keys(t).length}`),Object.keys(t).length>0)for(const e in t){const n=e,o=t[e];if(console.log(n),t.hasOwnProperty(e)){const e=n.split(" "),t=Number(e?.[0]),i=e?.[1]||"0",s=o.name||`Template ${t||""}`,a=o.tiles,l={};for(const e in a)if(console.log(e),a.hasOwnProperty(e)){const t=c(a[e]),n=new Blob([t],{type:"image/png"}),o=await createImageBitmap(n);l[e]=o}const r=new m({displayName:s,_:t||this.K?.length||0,G:i||""});r.R=l,this.K.push(r),console.log(this.K),console.log("^^^ This ^^^")}}};var p=GM_info.script.name.toString(),h=GM_info.script.version.toString();!function(e){const t=document.createElement("script");t.setAttribute("bm-r",p),t.setAttribute("bm-o","color: cornflowerblue;"),t.textContent=`(${e})();`,document.documentElement?.appendChild(t),t.remove()}(()=>{const e=document.currentScript,t=e?.getAttribute("bm-r")||"Blue Marble",n=e?.getAttribute("bm-o")||"",o=new Map;window.addEventListener("message",e=>{const{source:i,endpoint:s,blobID:a,blobData:l,blink:c}=e.data,r=Date.now()-c;if(console.groupCollapsed(`%c${t}%c: ${o.size} Recieved IMAGE message about blob "${a}"`,n,""),console.log(`Blob fetch took %c${String(Math.floor(r/6e4)).padStart(2,"0")}:${String(Math.floor(r/1e3)%60).padStart(2,"0")}.${String(r%1e3).padStart(3,"0")}%c MM:SS.mmm`,n,""),console.log(o),console.groupEnd(),"blue-marble"==i&&a&&l&&!s){const e=o.get(a);"function"==typeof e?e(l):function(...e){(0,console.warn)(...e)}(`%c${t}%c: Attempted to retrieve a blob (%s) from queue, but the blobID was not a function! Skipping...`,n,"",a),o.delete(a)}});const i=window.fetch;window.fetch=async function(...e){const s=(e[0]instanceof Request?e[0]?.url:e[0])||"ignore",a=(e[1],await i.apply(this,e)),l=a.clone(),c=s,r=l.headers.get("content-type")||"";if(r.includes("application/json"))console.log(`%c${t}%c: Sending JSON message about endpoint "${c}"`,n,""),l.json().then(e=>{window.postMessage({source:"blue-marble",endpoint:c,jsonData:e},"*")}).catch(e=>{console.error(`%c${t}%c: Failed to parse JSON: `,n,"",e)});else if(r.includes("image/")&&!c.includes("openfreemap")&&!c.includes("maps")){const e=Date.now(),i=await l.blob();return console.log(`%c${t}%c: ${o.size} Sending IMAGE message about endpoint "${c}"`,n,""),new Promise(s=>{const a=crypto.randomUUID();o.set(a,e=>{s(new Response(e,{headers:l.headers,status:l.status,statusText:l.statusText})),console.log(`%c${t}%c: ${o.size} Processed blob "${a}"`,n,"")}),window.postMessage({source:"blue-marble",endpoint:c,blobID:a,blobData:i,blink:e})}).catch(i=>{const s=Date.now();console.error(`%c${t}%c: Failed to Promise blob!`,n,""),console.groupCollapsed(`%c${t}%c: Details of failed blob Promise:`,n,""),console.log(`Endpoint: ${c}\nThere are ${o.size} blobs processing...\nBlink: ${e.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:",i),console.groupEnd()})}return a}});var f=GM_getResourceText("CSS-BM-File");GM_addStyle(f);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.Z=null,this.ee=null,this.te="#bm-5"}ne(e){return this.ee=e,this.Z=new MutationObserver(e=>{for(const t of e)for(const e of t.addedNodes)e instanceof HTMLElement&&e.matches?.(this.te)}),this}oe(){return this.Z}observe(e,t=!1,n=!1){e.observe(this.ee,{childList:t,subtree:n})}};var $=new s(p,h),w=(new s(p,h),new class{constructor(e,t,n){o(this,r),this.name=e,this.version=t,this.l=n,this.ie="1.0.0",this.se=null,this.ae="!#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",this.Y=1e3,this.le=3,this.ce=null,this.re=null,this.ue="bm-p",this.de="div#map canvas.maplibregl-canvas",this.me=null,this.pe="",this.K=[],this.V=null,this.he=!0}fe(){if(document.body.contains(this.ce))return this.ce;document.getElementById(this.ue)?.remove();const e=document.querySelector(this.de),t=document.createElement("canvas");return t.id=this.ue,t.className="maplibregl-canvas",t.style.position="absolute",t.style.top="0",t.style.left="0",t.style.height=e?.clientHeight*(window.devicePixelRatio||1)+"px",t.style.width=e?.clientWidth*(window.devicePixelRatio||1)+"px",t.height=e?.clientHeight*(window.devicePixelRatio||1),t.width=e?.clientWidth*(window.devicePixelRatio||1),t.style.zIndex="8999",t.style.pointerEvents="none",e?.parentElement?.appendChild(t),this.ce=t,window.addEventListener("move",this.be),window.addEventListener("zoom",this.$e),window.addEventListener("resize",this.we),this.ce}async ge(){return{whoami:this.name.replace(" ",""),scriptVersion:this.version,schemaVersion:this.ie,templates:{}}}async xe(e,t,n){this.V||(this.V=await this.ge(),console.log("Creating JSON...")),this.l.D(`Creating template at ${n.join(", ")}...`);const o=new m({displayName:t,_:0,G:a(this.se||0,this.ae),file:e,coords:n}),{q:s,H:l}=await o.j(this.Y);o.R=s,this.V.templates[`${o._} ${o.G}`]={name:o.displayName,coords:n.join(", "),enabled:!0,tiles:l},this.K=[],this.K.push(o);const c=(new Intl.NumberFormat).format(o.J);this.l.D(`Template created at ${n.join(", ")}! Total pixels: ${c}`),console.log(Object.keys(this.V.templates).length),console.log(this.V),console.log(this.K),console.log(JSON.stringify(this.V)),await i(this,r,u).call(this)}ye(){}async Ce(){this.V||(this.V=await this.ge(),console.log("Creating JSON..."))}async Oe(e,t){if(!this.he)return e;const n=this.Y*this.le;t=t[0].toString().padStart(4,"0")+","+t[1].toString().padStart(4,"0"),console.log(`Searching for templates in tile: "${t}"`);const o=this.K;console.log(o),o.sort((e,t)=>e._-t._),console.log(o);const i=o.map(e=>{const n=Object.keys(e.R).filter(e=>e.startsWith(t));if(0===n.length)return null;const o=n.map(t=>{const n=t.split(",");return{ve:e.R[t],Le:[n[0],n[1]],Te:[n[2],n[3]]}});return o?.[0]}).filter(Boolean);console.log(i);const s=i?.length||0;if(console.log(`templateCount = ${s}`),s>0){const e=o.filter(e=>Object.keys(e.R).filter(e=>e.startsWith(t)).length>0).reduce((e,t)=>e+(t.J||0),0),n=(new Intl.NumberFormat).format(e);this.l.D(`Displaying ${s} template${1==s?"":"s"}.\nTotal pixels: ${n}`)}else this.l.D(`Displaying ${s} templates.`);const a=await createImageBitmap(e),l=new OffscreenCanvas(n,n),c=l.getContext("2d");c.imageSmoothingEnabled=!1,c.beginPath(),c.rect(0,0,n,n),c.clip(),c.clearRect(0,0,n,n),c.drawImage(a,0,0,n,n);for(const e of i)console.log("Template:"),console.log(e),c.drawImage(e.ve,Number(e.Te[0])*this.le,Number(e.Te[1])*this.le);return await l.convertToBlob({type:"image/png"})}ke(e){console.log("Importing JSON..."),console.log(e),"BlueMarble"==e?.whoami&&i(this,r,d).call(this,e)}Pe(e){this.he=e}}(p,h,$)),g=new class{constructor(e){this.Ae=e,this.Ie=!1,this.Ee=[],this.Ne=[],this.droplets=0,this.charges=null,this.extraColorsBitmap=null}async Me(){try{const e=await fetch("https://backend.wplace.live/me",{credentials:"include"});if(e.ok){const t=await e.json();return console.log("ApiManager: Fetched fresh user data:",t),console.log("DEBUG API: Checking userData.extraColorsBitmap:",t.extraColorsBitmap),console.log("DEBUG API: userData.extraColorsBitmap type:",typeof t.extraColorsBitmap),console.log("DEBUG API: Full user data keys:",Object.keys(t)),console.log("DEBUG API: Full user data:",JSON.stringify(t,null,2)),void 0!==t.extraColorsBitmap?(this.extraColorsBitmap=t.extraColorsBitmap,console.log("DEBUG API: Set extraColorsBitmap to:",this.extraColorsBitmap)):console.log("DEBUG API: extraColorsBitmap is undefined in user data"),void 0!==t.droplets&&(this.droplets=t.droplets),void 0!==t.charges&&(this.charges=t.charges),void 0!==t.id&&(this.Ae.se=t.id),t}return console.warn("ApiManager: Failed to fetch user data:",e.status),null}catch(e){return console.error("ApiManager: Error fetching user data:",e),null}}Se(e){window.addEventListener("message",async t=>{const n=t.data,o=n.jsonData;if(!n||"blue-marble"!==n.source)return;if(!n.endpoint)return;const i=n.endpoint?.split("?")[0].split("/").filter(e=>e&&isNaN(Number(e))).filter(e=>e&&!e.includes(".")).pop();switch(console.log('%cBlue Marble%c: Recieved message about "%s"',"color: cornflowerblue;","",i),i){case"me":if(o.status&&"2"!=o.status?.toString()[0])return void e.B("You are not logged in!\nCould not fetch userdata.");const t=Math.ceil(Math.pow(Math.floor(o.level)*Math.pow(30,.65),1/.65)-o.pixelsPainted);console.log(o.id),(o.id||0===o.id)&&console.log(a(o.id,"!#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~")),console.log("DEBUG SPONTANEOUS: dataJSON extraColorsBitmap:",o.extraColorsBitmap),console.log("DEBUG SPONTANEOUS: dataJSON extraColorsBitmap type:",typeof o.extraColorsBitmap),console.log("DEBUG SPONTANEOUS: Full dataJSON keys:",Object.keys(o)),this.Ae.se=o.id,this.droplets=o.droplets,this.charges=o.charges,this.extraColorsBitmap=o.extraColorsBitmap,console.log("DEBUG SPONTANEOUS: Set extraColorsBitmap to:",this.extraColorsBitmap),e.M("bm-h",`Username: <b>${function(e){const t=document.createElement("div");return t.textContent=e,t.innerHTML}(o.name)}</b>`),e.M("bm-c",`Droplets: <b>${(new Intl.NumberFormat).format(o.droplets)}</b>`),e.M("bm-6",`Next level in <b>${(new Intl.NumberFormat).format(t)}</b> pixel${1==t?"":"s"}`);break;case"pixel":const i=n.endpoint.split("?")[0].split("/").filter(e=>e&&!isNaN(Number(e))),c=new URLSearchParams(n.endpoint.split("?")[1]),r=[c.get("x"),c.get("y")];if(this.Ee.length&&(!i.length||!r.length))return void e.B("Coordinates are malformed!\nDid you try clicking the canvas first?");this.Ee=[...i,...r];const u=(s=i,l=r,[parseInt(s[0])%4*1e3+parseInt(l[0]),parseInt(s[1])%4*1e3+parseInt(l[1])]),d=document.querySelectorAll("span");for(const e of d)if(e.textContent.trim().includes(`${u[0]}, ${u[1]}`)){let t=document.querySelector("#bm-5");const n=`(Tl X: ${i[0]}, Tl Y: ${i[1]}, Px X: ${r[0]}, Px Y: ${r[1]})`;t?t.textContent=n:(t=document.createElement("span"),t.id="bm-5",t.textContent=n,t.style="margin-left: calc(var(--spacing)*3); font-size: small;",e.parentNode.parentNode.parentNode.insertAdjacentElement("afterend",t))}break;case"tiles":let m=n.endpoint.split("/");m=[parseInt(m[m.length-2]),parseInt(m[m.length-1].replace(".png",""))];const p=n.blobID,h=n.blobData,f=await this.Ae.Oe(h,m);window.postMessage({source:"blue-marble",blobID:p,blobData:f,blink:n.blink});break;case"robots":this.Ie="false"==o.userscript?.toString().toLowerCase();break}var s,l})}}(w);$.p(g);var x=JSON.parse(GM_getValue("bmTemplates","{}"));console.log(x),w.ke(x),function(){let e=!1;$.C({id:"bm-n",style:"top: 10px; right: 75px;"}).C({id:"bm-7"}).C({id:"bm-i"}).h().L({alt:"Blue Marble Icon - Click to minimize/maximize",src:"https://raw.githubusercontent.com/SwingTheVine/Wplace-BlueMarble/main/dist/assets/Favicon.png",style:"cursor: pointer;"},(t,n)=>{n.addEventListener("click",()=>{e=!e;const o=document.querySelector("#bm-n"),i=document.querySelector("#bm-7"),s=document.querySelector("#bm-i"),a=document.querySelector("#bm-8"),l=document.querySelector("#bm-d"),c=document.querySelector("#bm-e"),r=document.querySelector("#bm-f"),u=document.querySelector("#bm-9"),d=document.querySelectorAll("#bm-8 input");e||(o.style.width="auto",o.style.maxWidth="300px",o.style.minWidth="200px",o.style.padding="10px"),["#bm-n h1","#bm-4","#bm-n hr","#bm-3 > *:not(#bm-8)","#bm-2","#bm-1",`#${t.i}`,"#bm-B"].forEach(t=>{document.querySelectorAll(t).forEach(t=>{t.style.display=e?"none":""})}),e?(a&&(a.style.display="none"),l&&(l.style.display="none"),c&&(c.style.display="none"),r&&(r.style.display="none"),u&&(u.style.display="none"),d.forEach(e=>{e.style.display="none"}),o.style.width="60px",o.style.height="76px",o.style.maxWidth="60px",o.style.minWidth="60px",o.style.padding="8px",n.style.marginLeft="3px",i.style.textAlign="center",i.style.margin="0",i.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=""),l&&(l.style.display=""),c&&(c.style.display="",c.style.marginTop=""),r&&(r.style.display="",r.style.marginTop=""),u&&(u.style.display="",u.style.marginTop=""),d.forEach(e=>{e.style.display=""}),n.style.marginLeft="",o.style.padding="10px",i.style.textAlign="",i.style.margin="",i.style.marginBottom="",s&&(s.style.marginBottom="0.5em"),o.style.width="",o.style.height=""),n.alt=e?"Blue Marble Icon - Minimized (Click to maximize)":"Blue Marble Icon - Maximized (Click to minimize)"})}).h().T(1,{textContent:p}).h().h().k().h().C({id:"bm-4"}).O({id:"bm-h",textContent:"Username:"}).h().O({id:"bm-c",textContent:"Droplets:"}).h().O({id:"bm-6",textContent:"Next level in..."}).h().h().k().h().C({id:"bm-3"}).C({id:"bm-8"}).I({id:"bm-d",className:"bm-q",style:"margin-top: 0;",innerHTML:'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 4 6"><circle cx="2" cy="2" r="2"></circle><path d="M2 6 L3.7 3 L0.3 3 Z"></path><circle cx="2" cy="2" r="0.7" fill="white"></circle></svg></svg>'},(e,t)=>{t.onclick=()=>{const t=e.o?.Ee;t?.[0]?(e.M("bm-j",t?.[0]||""),e.M("bm-k",t?.[1]||""),e.M("bm-l",t?.[2]||""),e.M("bm-m",t?.[3]||"")):e.B("Coordinates are malformed! Did you try clicking on the canvas first?")}}).h().S({type:"number",id:"bm-j",placeholder:"Tl X",min:0,max:2047,step:1,required:!0}).h().S({type:"number",id:"bm-k",placeholder:"Tl Y",min:0,max:2047,step:1,required:!0}).h().S({type:"number",id:"bm-l",placeholder:"Px X",min:0,max:2047,step:1,required:!0}).h().S({type:"number",id:"bm-m",placeholder:"Px Y",min:0,max:2047,step:1,required:!0}).h().h().F({id:"bm-2",textContent:"Upload Template",accept:"image/png, image/jpeg, image/webp, image/bmp, image/gif"}).h().C({id:"bm-0"}).I({id:"bm-f",textContent:"Enable"},(e,t)=>{t.onclick=()=>{e.o?.Ae?.Pe(!0),e.D("Enabled templates!");const t=document.querySelector("#bm-C"),n=document.querySelector("#bm-z"),o=document.querySelector("#bm-P"),i=document.querySelector("#bm-I");e.o?.Ae?.K.length&&e.o?.Ae?.he&&(t&&(t.disabled=!1),n&&(n.disabled=!1),o&&(o.disabled=!1),i&&(i.disabled=!1))}}).h().I({id:"bm-e",textContent:"Create"},(e,t)=>{t.onclick=async()=>{const t=document.querySelector("#bm-2"),n=document.querySelector("#bm-j");if(!n.checkValidity())return n.reportValidity(),void e.B("Coordinates are malformed! Did you try clicking on the canvas first?");const o=document.querySelector("#bm-k");if(!o.checkValidity())return o.reportValidity(),void e.B("Coordinates are malformed! Did you try clicking on the canvas first?");const i=document.querySelector("#bm-l");if(!i.checkValidity())return i.reportValidity(),void e.B("Coordinates are malformed! Did you try clicking on the canvas first?");const s=document.querySelector("#bm-m");if(!s.checkValidity())return s.reportValidity(),void e.B("Coordinates are malformed! Did you try clicking on the canvas first?");t?.files[0]?(await w.xe(t.files[0],t.files[0]?.name.replace(/\.[^/.]+$/,""),[Number(n.value),Number(o.value),Number(i.value),Number(s.value)]),e.D("Drew to canvas!")):e.B("No file selected!")}}).h().I({id:"bm-9",textContent:"Disable"},(e,t)=>{t.onclick=()=>{e.o?.Ae?.Pe(!1),e.D("Disabled templates!");const t=document.querySelector("#bm-C"),n=document.querySelector("#bm-z"),o=document.querySelector("#bm-P"),i=document.querySelector("#bm-I");t&&(t.disabled=!0),n&&(n.disabled=!0),o&&(o.disabled=!0),i&&(i.disabled=!0)}}).h().I({id:"bm-C",textContent:"Auto Fill",disabled:!0},(e,t)=>{let n=!1;const o=new Set,i=e=>new Promise(t=>setTimeout(t,e)),s={0:[0,0,0,0],1:[0,0,0,255],2:[60,60,60,255],3:[120,120,120,255],4:[210,210,210,255],5:[255,255,255,255],6:[96,0,24,255],7:[237,28,36,255],8:[255,127,39,255],9:[246,170,9,255],10:[249,221,59,255],11:[255,250,188,255],12:[14,185,104,255],13:[19,230,123,255],14:[135,255,94,255],15:[12,129,110,255],16:[16,174,166,255],17:[19,225,190,255],18:[40,80,158,255],19:[64,147,228,255],20:[96,247,242,255],21:[107,80,246,255],22:[153,177,251,255],23:[120,12,153,255],24:[170,56,185,255],25:[224,159,249,255],26:[203,0,122,255],27:[236,31,128,255],28:[243,141,169,255],29:[104,70,52,255],30:[149,104,42,255],31:[248,178,119,255],32:[170,170,170,255],33:[165,14,30,255],34:[250,128,114,255],35:[228,92,26,255],36:[214,181,148,255],37:[156,132,49,255],38:[197,173,49,255],39:[232,212,95,255],40:[74,107,58,255],41:[90,148,74,255],42:[132,197,115,255],43:[15,121,159,255],44:[187,250,242,255],45:[125,199,255,255],46:[77,49,184,255],47:[74,66,132,255],48:[122,113,196,255],49:[181,174,241,255],50:[219,164,99,255],51:[209,128,81,255],52:[255,197,165,255],53:[155,82,73,255],54:[209,128,120,255],55:[250,182,164,255],56:[123,99,82,255],57:[156,132,107,255],58:[51,57,65,255],59:[109,117,141,255],60:[179,185,209,255],61:[109,100,63,255],62:[148,140,107,255],63:[205,197,158,255]},a=e=>{const t=Math.floor(e/3600),n=Math.floor(e%3600/60),o=Math.floor(e%60);return`${t.toString().padStart(2,"0")}:${n.toString().padStart(2,"0")}:${o.toString().padStart(2,"0")}`},l=e=>{const t=document.querySelector("#bm-B");if(t){const n=`[${(new Date).toLocaleTimeString()}] ${e}`;t.value=n+"\n";const o=t.value.split("\n");o.length>20&&(t.value=o.slice(0,20).join("\n")),t.scrollTop=0}},c=e=>{const t=document.querySelector("#bm-A"),n=30*e;if(t){let o=`Remaining Pixels: ${e.toLocaleString()}`;o+=null!==n&&n>0?`\nEstimated Time: ${a(n)}`:"\nEstimated Time: N/A",t.value=o}},r=async(e,t={})=>{const{Fe:n=100,Ue:o=!1,We:s=200,Be:a="AUTOFILL",description:c="element",De:r=""}=t;let u=document.querySelector(e),d=0;for(console.log(`${a}: Looking for ${c}${r}...`),l(`š Looking for ${c}${r}...`);(!u||o&&u.disabled)&&d<n;){d++;const t=`${a}: Waiting for ${c} to be ready${r}... (${d}s/${n}s)`;console.log(t),l(`ā³ Waiting for ${c} to be ready${r}... (${d}s/${n}s)`),await i(s),u=document.querySelector(e)}return u?o&&u.disabled?(l(`ā ${c} still disabled after waiting${r}`),console.error(`${a}: ${c} still disabled after waiting${r}`),{_e:!1,element:u,reason:"disabled"}):(l(`ā
${c} is ready${r}`),console.log(`${a}: ${c} is ready${r}`),{_e:!0,element:u,reason:"ready"}):(l(`ā ${c} not found after waiting${r}`),console.error(`${a}: ${c} not found after waiting${r}`),{_e:!1,element:null,reason:"not_found"})};function u(e){const t=[];console.log("DEBUG: getOwnedColorsFromBitmap called with:",e),console.log("DEBUG: extraColorsBitmap type:",typeof e),console.log("DEBUG: extraColorsBitmap binary:",e?.toString(2));for(let e=0;e<=31;e++)t.push(e);if(null!=e&&0!==e){console.log("DEBUG: Processing extra colors from bitmap");for(let n=32;n<64;n++){const o=n-32;e&1<<o&&(t.push(n),console.log(`DEBUG: Color ${n} is owned (bit position ${o})`))}}else console.log("DEBUG: No extra colors - extraColorsBitmap is 0, null, or undefined");return console.log("DEBUG: Final owned colors array:",t),t.sort((e,t)=>e-t)}const d=(e,t,n,o)=>{if(0===o)return 0;let i=1/0,a=1;for(const[o,[l,c,r]]of Object.entries(s)){if("0"===o)continue;const s=Math.sqrt((e-l)**2+(t-c)**2+(n-r)**2);s<i&&(i=s,a=parseInt(o))}return a},m=async(e,t)=>{try{const n=await fetch(`https://backend.wplace.live/files/s0/tiles/${e}/${t}.png`);if(!n.ok)return console.log(`Chunk ${e},${t} not found or empty`),null;const o=await n.blob();return await createImageBitmap(o)}catch(n){return console.warn(`Failed to fetch chunk ${e},${t}:`,n),null}},p=async(t,n=[])=>{const i={};if(!e.o?.Ae?.K?.length)return[];const s=e.o.Ae.K[0].R;if(!s)return e.B("Template has no pixel data (chunked property is missing)."),[];const a=new Set(n),l=Object.keys(s).sort(),c=new Map,r=new Set,u=[];for(const e of l){const t=s[e];if(!t)continue;const i=e.split(",").map(Number),[l,p,h,f]=i;console.log(`Processing tile - ChunkX: ${l}, ChunkY: ${p}, TileCoordX: ${h}, TileCoordY: ${f}`);const b=`${l},${p}`;if(!c.has(b)){const e=await m(l,p);c.set(b,e)}const $=c.get(b),w=new OffscreenCanvas(t.width,t.height).getContext("2d");w.drawImage(t,0,0);const g=w.getImageData(0,0,t.width,t.height);let x=null;if($){const e=new OffscreenCanvas($.width,$.height).getContext("2d");e.drawImage($,0,0),x=e.getImageData(0,0,$.width,$.height)}for(let e=1;e<t.height;e+=3)for(let i=1;i<t.width;i+=3){const s=4*(e*t.width+i),c=g.data[s+3];if(0===c)continue;const m=g.data[s],b=g.data[s+1],$=g.data[s+2],w=d(m,b,$,c),y=h+Math.floor((i-1)/3),C=f+Math.floor((e-1)/3),O=`${l},${p},${y},${C}`;if(r.add(O),n.length>0&&!a.has(w))continue;let v=!0;if(x&&y>=0&&y<x.width&&C>=0&&C<x.height){const e=4*(C*x.width+y),t=x.data[e],n=x.data[e+1],o=x.data[e+2],i=x.data[e+3];d(t,n,o,i)===w&&(v=!1)}v&&!o.has(O)&&u.push({Ge:l,Re:p,Ye:y,ze:C,Je:w,je:O})}}const p=document.querySelector("#bm-P"),h=p?p.textContent.replace("Mode: ",""):"Random",f=e=>{console.log("AUTOFILL: Ran Edge Pixel");const t=1e3*e.Ge+e.Ye,n=1e3*e.Re+e.ze,o=[[t-1,n-1],[t,n-1],[t+1,n-1],[t-1,n],[t+1,n],[t-1,n+1],[t,n+1],[t+1,n+1]];for(const[e,t]of o){const n=Math.floor(e/1e3),o=Math.floor(t/1e3),i=`${n},${o},${e-1e3*n},${t-1e3*o}`;if(!r.has(i))return!0}return!1},b=u.filter(e=>f(e)),$=u.filter(e=>!f(e));console.log(`DEBUG: Total pixels to place: ${u.length}, Edge pixels: ${b.length}, Non-edge pixels: ${$.length}`);let w=[];if("Scan"===h)w=[...b,...$],console.log(`š Scan mode: ${w.length} total pixels in top-left to bottom-right scan order`);else{const e=e=>{const t=[...e];for(let e=t.length-1;e>0;e--){const n=Math.floor(Math.random()*(e+1));[t[e],t[n]]=[t[n],t[e]]}return t};w=[...e(b),...e($)],console.log(`š² Random mode: ${b.length} edge pixels first (randomized), then ${$.length} inner pixels (randomized)`)}let g=0;for(const e of w){if(g>=t)break;const n=`${e.Ge},${e.Re}`;i[n]||(i[n]={Xe:[e.Ge,e.Re],qe:[]}),i[n].qe.push([e.Ye,e.ze,e.Je]),g++}return console.log(`\nš SUMMARY: Found ${u.length} total pixels that need placement (filtered by ${n.length} owned colors), returning ${g} pixels (${b.length} edge priority)`),{He:Object.values(i).map(e=>[e.Xe,e.qe]),Ve:u.length}},h=async(e,t,n=0)=>{if(!t||0===t.length)return;const[o,s]=e,a=(e,n,i)=>({Ke:{colors:t.map(([,,e])=>e),coords:t.flatMap(([e,t])=>[e,t]),t:n},Ze:`https://backend.wplace.live/s0/pixel/${o}/${s}`}),c=async()=>{const e=document.querySelector(".maplibregl-canvas");if(!e)throw new Error("Could not find the map canvas.");const t=window.innerWidth/2,n=window.innerHeight/2,o=["mousedown","click","mouseup"];for(const s of o){const o=new MouseEvent(s,{clientX:t,clientY:n,bubbles:!0});e.dispatchEvent(o),await i(50)}console.log("AUTOFILL: Starting...");const s=await r(".btn.btn-primary.btn-lg.sm\\:btn-xl.relative",{Fe:100,Ue:!0,We:200,Be:"AUTOFILL",description:"final pixel placement button",De:""});if(!s._e)throw new Error(`Could not find or enable final paint button: ${s.reason}`);console.log("AUTOFILL: Final button is ready - clicking now"),s.element.click()};try{const i=await(async(e,t,n="REQUEST")=>{const o=unsafeWindow.fetch;let i=!0;return new Promise(async(s,a)=>{unsafeWindow.fetch=async(...t)=>{const l=t[0],c=t[1]||{},r=(c.method||"GET").toUpperCase();if(!i)return o.apply(unsafeWindow,t);if("POST"!==r||"string"!=typeof l||!l.includes("/pixel/"))return o.apply(unsafeWindow,t);try{console.log(`${n}: Intercepting fetch request`);const t=JSON.parse(c.body),a=t.t;if(!a)throw new Error("Could not find security token 't'");const{Ke:r,Ze:u}=e(t,a,l),d={...c,body:JSON.stringify(r)};i=!1,unsafeWindow.fetch=o,console.log(`${n}: Sending modified request`);const m=await o.call(unsafeWindow,u||l,d);return s(m),m}catch(e){i=!1,unsafeWindow.fetch=o,console.error(`${n}: Error during interception:`,e),a(e)}};try{await t()}catch(e){unsafeWindow.fetch=o,a(e)}})})(a,c,"AUTOFILL");return 429===i.status?(console.log(`Rate limited (429) on chunk ${o},${s}. Waiting 30s before retry...`),l(`ā° Rate limited! Waiting 30s before retry (attempt ${n+1})...`),await new Promise(e=>setTimeout(e,3e4)),l(`š Retrying pixel placement for chunk ${o},${s}...`),await h(e,t,n+1)):i}catch(e){throw e}};t.onclick=async()=>{if(n){if(console.log("AUTOFILL: User requested stop"),n=!1,t.textContent="Auto Fill",l("ā¹ļø Auto-fill stopped by user"),console.log("AUTOFILL: Stopping protection mode if active"),window.bmProtectionInterval||"Stop Fill"===t.textContent){console.log("AUTOFILL: Protection mode stopped"),clearInterval(window.bmProtectionInterval),window.bmProtectionInterval=null,window.bmProtectMode=!1,n=!1;const e=document.querySelector("#bm-I");e&&(e.textContent="Protect: Off"),l("š”ļø Protection mode stopped by user")}}else{if(!e.o?.Ae?.K.length||!e.o?.Ae?.he)return console.log("AUTOFILL: No active template available"),void l("ā No active template available");try{await e.o.Me()?console.log("Fetched fresh user data for auto-fill"):console.warn("Failed to fetch fresh user data, continuing with cached data")}catch(e){console.error("Error fetching fresh user data:",e)}for(console.log("AUTOFILL: Starting auto fill process"),n=!0,t.textContent="Stop Fill",l("š Auto-fill started!");n;)try{console.log("AUTOFILL: Starting new cycle");const s=e.o?.charges;if(!s){console.log("AUTOFILL: No charge data available, waiting..."),l("ā³ Waiting for charge data..."),await i(5e3);continue}const d=await p(1,u(e.o?.extraColorsBitmap||0));if(console.log(`AUTOFILL: Progress result: ${JSON.stringify(d)}`),console.log(`AUTOFILL: Found ${d.Ve} chunk groups to process`),0===d.Ve){if(console.log("AUTOFILL: Template completed - no more pixels to place"),console.log("AUTOFILL: Closing Paint Menu"),l("šØ Closing Paint Menu..."),l("š Template completed! All owned color pixels placed."),c(0),window.bmProtectMode){console.log("AUTOFILL: Starting protection mode - monitoring"),l("š”ļø Protection mode active - monitoring template"),t.textContent="Stop Fill";const n=setInterval(async()=>{try{console.log("PROTECT: Checking template integrity..."),l("š Checking template integrity...");const o=u(e.o?.extraColorsBitmap||0);if(0===o.length)return void console.log("PROTECT: No owned colors found, skipping check");const i=await p(0,o);if(i.Ve>0){console.log(`PROTECT: Found ${i.Ve} pixels that need protection!`),l(`šØ Protection alert: ${i.Ve} pixels need fixing!`);const o=e.o?.charges;if(o&&Math.floor(o.count)>0){const e=Math.min(Math.floor(o.count),i.Ve);console.log(`PROTECT: Attempting to fix ${e} pixels with ${Math.floor(o.count)} charges`),l(`š§ Fixing ${e} pixels with available charges...`),clearInterval(n),l("š”ļø Protection mode: Restarting auto-fill to fix damaged pixels"),t.click()}else console.log("PROTECT: No charges available for immediate fixing"),l("ā ļø Damage detected but no charges available for fixing")}else console.log("PROTECT: Template is intact"),l("ā
Template protection check: All pixels intact")}catch(e){console.error("PROTECT: Error during protection check:",e),l(`ā Protection error: ${e.message}`)}},1e4);window.bmProtectionInterval=n}else t.textContent="Auto Fill",n=!1;break}if(c(d.Ve),console.log(`AUTOFILL: Current charges: ${s.count}/${s.max}`),s.count<s.max&&d.Ve>Math.floor(s.count)){console.log(`AUTOFILL: Charges not full (${s.count}/${s.max}) and remaining pixels (${d.Ve}) > available charges (${Math.floor(s.count)}), refreshing user data`),l("š Refreshing user data for latest charges..."),await e.o.Me();const t=e.o?.charges;if(t&&t.count>=t.max){console.log("AUTOFILL: Charges are now full after refresh, proceeding"),l("ā
Charges are now full after refresh!");continue}console.log("AUTOFILL: Still need to wait for charges, calculating wait time");const o=s.max-Math.floor(s.count),c=s.count-Math.floor(s.count),r=s.Qe||3e4,u=Math.ceil((1-c)*r)+(o-1)*r;console.log(`AUTOFILL: Waiting ${(u/1e3).toFixed(1)}s for ${o} charges`),l(`ā±ļø Precise timing: ${s.count.toFixed(3)}/${s.max} charges, waiting ${a(u/1e3)}`);const m=Date.now()+u;let p=0;for(;Date.now()<m&&n;){const t=Math.max(0,m-Date.now());if(p++,p%10==0){console.log(`AUTOFILL: 10 seconds elapsed (iteration ${p}), refreshing user data`),l(`š ${p}s elapsed - checking charges via data refresh`),await e.o.Me();const t=e.o?.charges;if(t&&t.count>=t.max){console.log("AUTOFILL: Charges are now full after refresh, breaking wait loop"),l("ā
Charges full after refresh - proceeding immediately!");break}console.log(`AUTOFILL: After refresh - charges: ${t?.count.toFixed(3)}/${t?.max}, continuing wait`),l(`š Refresh result: ${t?.count.toFixed(3)}/${t?.max} charges, continuing wait`)}const n=a(t/1e3);l(`ā³ Charging ${n} remaining`),await i(Math.min(1e3,t))}if(!n){console.log("AUTOFILL: Stopped during charge wait");break}console.log("AUTOFILL: Charge wait completed, continuing");continue}s.count<s.max&&(console.log(`AUTOFILL: Charges not full (${s.count}/${s.max}) but sufficient for remaining pixels (${d.Ve}), proceeding with pixel placement`),l(`ā” Sufficient charges (${Math.floor(s.count)}) for remaining pixels (${d.Ve}), proceeding!`)),console.log("AUTOFILL: Proceeding with pixel placement"),console.log("AUTOFILL: Getting owned colors from extraColorsBitmap..."),l("š Getting owned colors from bitmap...");const m=e.o?.extraColorsBitmap||0,f=u(m);if(console.log(`AUTOFILL: Found ${f.length} owned colors from bitmap ${m}`),0===f.length){console.log("AUTOFILL: No owned colors found from bitmap, retrying in 10s"),l("ā No owned colors found from bitmap! Retrying in 10s..."),await i(1e4);continue}console.log(`AUTOFILL: Looking for up to ${s.count} pixels to place`),l(`ā” Charges available (${s.count}/${s.max}). Finding up to ${s.count} pixels from ${f.length} owned colors...`);const b=(await p(s.count,f)).He;if(console.log(`AUTOFILL: Found ${b.length} chunk groups to process`),0===d.Ve){console.log("AUTOFILL: Template completed - no more pixels to place"),console.log("AUTOFILL: Closing Paint Menu"),l("šØ Closing Paint Menu...");const e=document.querySelector(".relative.px-3"),o=e.querySelector('.btn.btn-circle.btn-sm svg path[d="m256-200-56-56 224-224-224-224 56-56 224 224 224-224 56 56-224 224 224 224-56 56-224-224-224 224Z"]')?.closest("button");o&&o.click(),n=!1,window.bmProtectMode?t.textContent="Stop Fill":t.textContent="Auto Fill",l("š Template completed! All owned color pixels placed."),c(0);break}const $=await r(".btn.btn-primary.btn-lg.sm\\:btn-xl.relative.z-30",{Fe:100,Ue:!0,We:200,Be:"AUTOFILL",description:"paint mode button",De:""});if(!$._e){await i(5e3);continue}$.element.click(),l("ā
Clicked paint mode button"),console.log("Clicked paint mode button"),await i(500);const w=b.reduce((e,t)=>e+t[1].length,0);console.log(`AUTOFILL: Will place ${w} pixels across ${b.length} chunks`),l(`šÆ Found ${w} pixels to place in ${b.length} chunks`);for(let e=0;e<b.length;e++){if(!n){console.log("AUTOFILL: Stopped during chunk processing");break}const t=b[e],[s,a]=t,[c,u]=s;if(console.log(`AUTOFILL: ChunkIndex: ${e}`),e>0){console.log(`AUTOFILL: Reopening paint menu for chunk ${e+1}/${b.length}`),l(`šØ Reopening paint menu for chunk ${e+1}...`);const t=await r(".btn.btn-primary.btn-lg.sm\\:btn-xl.relative.z-30",{Fe:100,Ue:!1,We:200,Be:"AUTOFILL",description:"paint button",De:` for chunk ${e+1}`});if(!t._e){console.error(`AUTOFILL: Could not find paint button for chunk ${e+1}, skipping chunk`),l(`ā Could not find paint button for chunk ${e+1}, skipping`);continue}t.element.click(),l(`ā
Paint menu reopened for chunk ${e+1}`),await i(200)}console.log(`AUTOFILL: Processing chunk ${c},${u} with ${a.length} pixels`),l(`š Placing ${a.length} pixels in chunk ${c},${u}...`),await h(s,a),console.log("AUTOFILL: Finished Intercept"),a.forEach(([e,t])=>o.add(`${c},${u},${e},${t}`)),l(`ā
Placed ${a.length} pixels in chunk (${c},${u})`)}console.log(`AUTOFILL: Completed placing ${w} pixels, starting UI cleanup`),n&&(console.log(`AUTOFILL: Batch completed successfully - ${w} pixels placed`),l(`šÆ Batch complete: ${w} pixels placed`)),console.log("AUTOFILL: Waiting before next cycle"),await i(1e4)}catch(e){console.error("AUTOFILL: Error during auto fill cycle:",e),l(`ā Error: ${e.message}. Retrying in 10s...`),await i(1e4)}}}}).h().I({id:"bm-z",textContent:"Place Now",disabled:!0},(e,t)=>{let n=!1;const o=new Set,i=e=>new Promise(t=>setTimeout(t,e)),s={0:[0,0,0,0],1:[0,0,0,255],2:[60,60,60,255],3:[120,120,120,255],4:[210,210,210,255],5:[255,255,255,255],6:[96,0,24,255],7:[237,28,36,255],8:[255,127,39,255],9:[246,170,9,255],10:[249,221,59,255],11:[255,250,188,255],12:[14,185,104,255],13:[19,230,123,255],14:[135,255,94,255],15:[12,129,110,255],16:[16,174,166,255],17:[19,225,190,255],18:[40,80,158,255],19:[64,147,228,255],20:[96,247,242,255],21:[107,80,246,255],22:[153,177,251,255],23:[120,12,153,255],24:[170,56,185,255],25:[224,159,249,255],26:[203,0,122,255],27:[236,31,128,255],28:[243,141,169,255],29:[104,70,52,255],30:[149,104,42,255],31:[248,178,119,255],32:[170,170,170,255],33:[165,14,30,255],34:[250,128,114,255],35:[228,92,26,255],36:[214,181,148,255],37:[156,132,49,255],38:[197,173,49,255],39:[232,212,95,255],40:[74,107,58,255],41:[90,148,74,255],42:[132,197,115,255],43:[15,121,159,255],44:[187,250,242,255],45:[125,199,255,255],46:[77,49,184,255],47:[74,66,132,255],48:[122,113,196,255],49:[181,174,241,255],50:[219,164,99,255],51:[209,128,81,255],52:[255,197,165,255],53:[155,82,73,255],54:[209,128,120,255],55:[250,182,164,255],56:[123,99,82,255],57:[156,132,107,255],58:[51,57,65,255],59:[109,117,141,255],60:[179,185,209,255],61:[109,100,63,255],62:[148,140,107,255],63:[205,197,158,255]},a=e=>{const t=document.querySelector("#bm-B");if(t){const n=`[${(new Date).toLocaleTimeString()}] ${e}`;t.value=n+"\n";const o=t.value.split("\n");o.length>20&&(t.value=o.slice(0,20).join("\n")),t.scrollTop=0}},l=async(e,t={})=>{const{Fe:n=100,Ue:o=!1,We:s=200,Be:l="PLACE_NOW",description:c="element",De:r=""}=t;let u=document.querySelector(e),d=0;for(console.log(`${l}: Looking for ${c}${r}...`),a(`š Looking for ${c}${r}...`);(!u||o&&u.disabled)&&d<n;){d++;const t=`${l}: Waiting for ${c} to be ready${r}... (${d}s/${n}s)`;console.log(t),a(`ā³ Waiting for ${c} to be ready${r}... (${d}s/${n}s)`),await i(s),u=document.querySelector(e)}return u?o&&u.disabled?(a(`ā ${c} still disabled after waiting${r}`),console.error(`${l}: ${c} still disabled after waiting${r}`),{_e:!1,element:u,reason:"disabled"}):(a(`ā
${c} is ready${r}`),console.log(`${l}: ${c} is ready${r}`),{_e:!0,element:u,reason:"ready"}):(a(`ā ${c} not found after waiting${r}`),console.error(`${l}: ${c} not found after waiting${r}`),{_e:!1,element:null,reason:"not_found"})},c=(e,t,n,o)=>{if(0===o)return 0;let i=1/0,a=1;for(const[o,[l,c,r]]of Object.entries(s)){if("0"===o)continue;const s=Math.sqrt((e-l)**2+(t-c)**2+(n-r)**2);s<i&&(i=s,a=parseInt(o))}return a},r=async(e,t)=>{try{const n=await fetch(`https://backend.wplace.live/files/s0/tiles/${e}/${t}.png`);if(!n.ok)return console.log(`Chunk ${e},${t} not found or empty`),null;const o=await n.blob();return await createImageBitmap(o)}catch(n){return console.warn(`Failed to fetch chunk ${e},${t}:`,n),null}},u=async(e,t,n=0)=>{if(!t||0===t.length)return;const[o,s]=e,c=(e,n,i)=>({Ke:{colors:t.map(([,,e])=>e),coords:t.flatMap(([e,t])=>[e,t]),t:n},Ze:`https://backend.wplace.live/s0/pixel/${o}/${s}`}),r=async()=>{const e=document.querySelector(".maplibregl-canvas");if(!e)throw new Error("Could not find the map canvas.");const t=window.innerWidth/2,n=window.innerHeight/2,o=["mousedown","click","mouseup"];for(const s of o){const o=new MouseEvent(s,{clientX:t,clientY:n,bubbles:!0});e.dispatchEvent(o),await i(50)}console.log("PLACE_NOW: Starting...");const s=await l(".btn.btn-primary.btn-lg.sm\\:btn-xl.relative",{Fe:100,Ue:!0,We:200,Be:"PLACE_NOW",description:"final pixel placement button",De:""});if(!s._e)throw new Error(`Could not find or enable final paint button: ${s.reason}`);console.log("PLACE_NOW: Final button is ready - clicking now"),s.element.click()};try{const i=await(async(e,t,n="PLACE_NOW")=>{const o=unsafeWindow.fetch;let i=!0;return new Promise(async(s,a)=>{unsafeWindow.fetch=async(...t)=>{const l=t[0],c=t[1]||{},r=(c.method||"GET").toUpperCase();if(!i)return o.apply(unsafeWindow,t);if("POST"!==r||"string"!=typeof l||!l.includes("/pixel/"))return o.apply(unsafeWindow,t);try{console.log(`${n}: Intercepting fetch request`);const t=JSON.parse(c.body),a=t.t;if(!a)throw new Error("Could not find security token 't'");const{Ke:r,Ze:u}=e(t,a,l),d={...c,body:JSON.stringify(r)};i=!1,unsafeWindow.fetch=o,console.log(`${n}: Sending modified request`);const m=await o.call(unsafeWindow,u||l,d);return s(m),m}catch(e){i=!1,unsafeWindow.fetch=o,console.error(`${n}: Error during interception:`,e),a(e)}};try{await t()}catch(e){unsafeWindow.fetch=o,a(e)}})})(c,r,"PLACE_NOW");return 429===i.status?(console.log(`Rate limited (429) on chunk ${o},${s}. Waiting 30s before retry...`),a(`ā° Rate limited! Waiting 30s before retry (attempt ${n+1})...`),await new Promise(e=>setTimeout(e,3e4)),a(`š Retrying pixel placement for chunk ${o},${s}...`),await u(e,t,n+1)):i}catch(e){throw e}};t.onclick=async()=>{if(n)return console.log("PLACE_NOW: User requested stop"),n=!1,t.textContent="Place Now",void a("ā¹ļø Place Now stopped by user");if(!e.o?.Ae?.K.length||!e.o?.Ae?.he)return console.log("PLACE_NOW: No active template available"),void a("ā No active template available");try{await e.o.Me()?console.log("PLACE_NOW: Fetched fresh user data"):console.warn("PLACE_NOW: Failed to fetch fresh user data, continuing with cached data")}catch(e){console.error("PLACE_NOW: Error fetching fresh user data:",e)}console.log("PLACE_NOW: Starting immediate pixel placement process"),n=!0,t.textContent="Stop Place",a("ā” Place Now started! Placing available pixels immediately...");try{const s=e.o?.charges;if(!s)return console.log("PLACE_NOW: No charge data available"),a("ā No charge data available"),n=!1,void(t.textContent="Place Now");const d=Math.floor(s.count);if(d<=0)return console.log("PLACE_NOW: No charges available"),a("ā No charges available to place pixels"),n=!1,void(t.textContent="Place Now");console.log("PLACE_NOW: Getting owned colors from extraColorsBitmap..."),a("š Getting owned colors from bitmap...");const m=e.o?.extraColorsBitmap||0,p=function(e){const t=[];console.log("DEBUG PLACE_NOW: getOwnedColorsFromBitmap called with:",e),console.log("DEBUG PLACE_NOW: extraColorsBitmap type:",typeof e),console.log("DEBUG PLACE_NOW: extraColorsBitmap binary:",e?.toString(2));for(let e=0;e<=31;e++)t.push(e);if(null!=e&&0!==e){console.log("DEBUG PLACE_NOW: Processing extra colors from bitmap");for(let n=32;n<64;n++){const o=n-32;e&1<<o&&(t.push(n),console.log(`DEBUG PLACE_NOW: Color ${n} is owned (bit position ${o})`))}}else console.log("DEBUG PLACE_NOW: No extra colors - extraColorsBitmap is 0, null, or undefined");return console.log("DEBUG PLACE_NOW: Final owned colors array:",t),t.sort((e,t)=>e-t)}(m);if(console.log(`PLACE_NOW: Found ${p.length} owned colors from bitmap ${m}`),0===p.length)return console.log("PLACE_NOW: No owned colors found from bitmap"),a("ā No owned colors found from bitmap!"),n=!1,void(t.textContent="Place Now");console.log(`PLACE_NOW: Looking for up to ${d} pixels to place immediately`),a(`ā” Available charges: ${d}. Finding pixels to place...`);const h=await(async(t,n=[])=>{const i={};if(!e.o?.Ae?.K?.length)return[];const s=e.o.Ae.K[0].R;if(!s)return e.B("Template has no pixel data (chunked property is missing)."),[];const a=new Set(n),l=Object.keys(s).sort(),u=new Map,d=new Set,m=[];for(const e of l){const t=s[e];if(!t)continue;const i=e.split(",").map(Number),[l,p,h,f]=i;console.log(`Processing tile - ChunkX: ${l}, ChunkY: ${p}, TileCoordX: ${h}, TileCoordY: ${f}`);const b=`${l},${p}`;if(!u.has(b)){const e=await r(l,p);u.set(b,e)}const $=u.get(b),w=new OffscreenCanvas(t.width,t.height).getContext("2d");w.drawImage(t,0,0);const g=w.getImageData(0,0,t.width,t.height);let x=null;if($){const e=new OffscreenCanvas($.width,$.height).getContext("2d");e.drawImage($,0,0),x=e.getImageData(0,0,$.width,$.height)}for(let e=1;e<t.height;e+=3)for(let i=1;i<t.width;i+=3){const s=4*(e*t.width+i),r=g.data[s+3];if(0===r)continue;const u=g.data[s],b=g.data[s+1],$=g.data[s+2],w=c(u,b,$,r),y=h+Math.floor((i-1)/3),C=f+Math.floor((e-1)/3),O=`${l},${p},${y},${C}`;if(d.add(O),n.length>0&&!a.has(w))continue;let v=!0;if(x&&y>=0&&y<x.width&&C>=0&&C<x.height){const e=4*(C*x.width+y),t=x.data[e],n=x.data[e+1],o=x.data[e+2],i=x.data[e+3];c(t,n,o,i)===w&&(v=!1)}v&&!o.has(O)&&m.push({Ge:l,Re:p,Ye:y,ze:C,Je:w,je:O})}}const p=document.querySelector("#bm-P"),h=p?p.textContent.replace("Mode: ",""):"Random",f=e=>{console.log("PLACE_NOW: Ran Edge Pixel");const t=1e3*e.Ge+e.Ye,n=1e3*e.Re+e.ze,o=[[t-1,n-1],[t,n-1],[t+1,n-1],[t-1,n],[t+1,n],[t-1,n+1],[t,n+1],[t+1,n+1]];for(const[e,t]of o){const n=Math.floor(e/1e3),o=Math.floor(t/1e3),i=`${n},${o},${e-1e3*n},${t-1e3*o}`;if(!d.has(i))return!0}return!1},b=m.filter(e=>f(e)),$=m.filter(e=>!f(e));console.log(`DEBUG: Total pixels to place: ${m.length}, Edge pixels: ${b.length}, Non-edge pixels: ${$.length}`);let w=[];if("Scan"===h)w=[...b,...$],console.log(`š Scan mode: ${w.length} total pixels in top-left to bottom-right scan order`);else{const e=e=>{const t=[...e];for(let e=t.length-1;e>0;e--){const n=Math.floor(Math.random()*(e+1));[t[e],t[n]]=[t[n],t[e]]}return t};w=[...e(b),...e($)],console.log(`š² Random mode: ${b.length} edge pixels first (randomized), then ${$.length} inner pixels (randomized)`)}let g=0;for(const e of w){if(g>=t)break;const n=`${e.Ge},${e.Re}`;i[n]||(i[n]={Xe:[e.Ge,e.Re],qe:[]}),i[n].qe.push([e.Ye,e.ze,e.Je]),g++}return console.log(`\nš SUMMARY: Found ${m.length} total pixels that need placement (filtered by ${n.length} owned colors), returning ${g} pixels (${b.length} edge priority)`),{He:Object.values(i).map(e=>[e.Xe,e.qe]),Ve:m.length}})(d,p),f=h.He;if(0===f.length)return console.log("PLACE_NOW: No pixels need to be placed"),a("ā
No pixels need to be placed - template is complete for owned colors!"),n=!1,void(t.textContent="Place Now");const b=await l(".btn.btn-primary.btn-lg.sm\\:btn-xl.relative.z-30",{Fe:100,Ue:!0,We:200,Be:"PLACE_NOW",description:"paint mode button",De:""});if(!b._e)return a("ā Could not find paint mode button"),n=!1,void(t.textContent="Place Now");b.element.click(),a("ā
Clicked paint mode button"),console.log("PLACE_NOW: Clicked paint mode button"),await i(500);const $=f.reduce((e,t)=>e+t[1].length,0);console.log(`PLACE_NOW: Will place ${$} pixels across ${f.length} chunks`),a(`šÆ Placing ${$} pixels immediately in ${f.length} chunks`);for(let e=0;e<f.length;e++){if(!n){console.log("PLACE_NOW: Stopped during chunk processing");break}const t=f[e],[s,c]=t,[r,d]=s;if(console.log(`PLACE_NOW: ChunkIndex: ${e}`),e>0){console.log(`PLACE_NOW: Reopening paint menu for chunk ${e+1}/${f.length}`),a(`šØ Reopening paint menu for chunk ${e+1}...`);const t=await l(".btn.btn-primary.btn-lg.sm\\:btn-xl.relative.z-30",{Fe:100,Ue:!1,We:200,Be:"PLACE_NOW",description:"paint button",De:` for chunk ${e+1}`});if(!t._e){console.error(`PLACE_NOW: Could not find paint button for chunk ${e+1}, skipping chunk`),a(`ā Could not find paint button for chunk ${e+1}, skipping`);continue}t.element.click(),a(`ā
Paint menu reopened for chunk ${e+1}`),await i(200)}console.log(`PLACE_NOW: Processing chunk ${r},${d} with ${c.length} pixels`),a(`š Placing ${c.length} pixels in chunk ${r},${d}...`),await u(s,c),console.log("PLACE_NOW: Finished Intercept"),c.forEach(([e,t])=>o.add(`${r},${d},${e},${t}`)),a(`ā
Placed ${c.length} pixels in chunk (${r},${d})`)}console.log(`PLACE_NOW: Completed placing ${$} pixels immediately`),a(`šÆ Complete! Placed ${$} pixels with available charges.`)}catch(e){console.error("PLACE_NOW: Error during immediate pixel placement:",e),a(`ā Error: ${e.message}`)}finally{n=!1,t.textContent="Place Now"}}}).h().I({id:"bm-P",textContent:"Mode: Scan",disabled:!0},(e,t)=>{const n=["Scan","Random"];let o=0;t.onclick=()=>{o=(o+1)%n.length,t.textContent=`Mode: ${n[o]}`}}).h().I({id:"bm-I",textContent:"Protect: Off",disabled:!0},(e,t)=>{let n=!1;t.onclick=()=>{if(n=!n,t.textContent="Protect: "+(n?"On":"Off"),e.D("š”ļø Protection mode "+(n?"enabled":"disabled")),window.bmProtectMode=n,!n&&window.bmProtectionInterval&&(clearInterval(window.bmProtectionInterval),window.bmProtectionInterval=null,e.D("š”ļø Protection monitoring stopped")),!n){const t=document.querySelector("#bm-C");t&&"Stop Fill"===t.textContent&&(t.click(),e.D("š Auto-fill button reset"))}}}).h().h().U({id:$.i,placeholder:`Status: Sleeping...\nVersion: ${h}`,readOnly:!0}).h().U({id:"bm-B",placeholder:"Auto-Fill Output:\nWaiting for auto-fill to start...",readOnly:!0}).h().U({id:"bm-A",placeholder:"Progress:\nWaiting for template analysis...",readOnly:!0}).h().C({id:"bm-1"}).C().I({id:"bm-a",className:"bm-q",innerHTML:"šØ",title:"Template Color Converter"},(e,t)=>{t.addEventListener("click",()=>{window.open("https://pepoafonso.github.io/color_converter_wplace/","_blank","noopener noreferrer")})}).h().h().v({textContent:"Made by SwingTheVine",style:"margin-top: auto;"}).h().h().h().$(document.body),setTimeout(()=>{const e=document.querySelector("#bm-C"),t=document.querySelector("#bm-z"),n=document.querySelector("#bm-P"),o=document.querySelector("#bm-I"),i=()=>{e&&($.o?.Ae?.K.length&&$.o?.Ae?.he?(e.disabled=!1,t&&(t.disabled=!1),n.disabled=!1,o&&(o.disabled=!1)):(e.disabled=!0,t&&(t.disabled=!0),n.disabled=!0,o&&(o.disabled=!0)))};i();const s=setInterval(()=>{i(),($.o?.Ae?.K.length>0||Date.now()-a>1e4)&&clearInterval(s)},500),a=Date.now()},100)}(),$.W("#bm-n","#bm-i"),g.Se($),new MutationObserver((e,t)=>{const n=document.querySelector("#color-1");if(!n)return;let o=document.querySelector("#bm-g");if(!o){o=document.createElement("button"),o.id="bm-g",o.textContent="Move ā",o.className="btn btn-soft",o.onclick=function(){const e=this.parentNode.parentNode.parentNode.parentNode,t="Move ā"==this.textContent;e.parentNode.className=e.parentNode.className.replace(t?"bottom":"top",t?"top":"bottom"),e.style.borderTopLeftRadius=t?"0px":"var(--radius-box)",e.style.borderTopRightRadius=t?"0px":"var(--radius-box)",e.style.borderBottomLeftRadius=t?"var(--radius-box)":"0px",e.style.borderBottomRightRadius=t?"var(--radius-box)":"0px",this.textContent=t?"Move ā":"Move ā"};const e=n.parentNode.parentNode.parentNode.parentNode.querySelector("h2");e.parentNode?.appendChild(o)}}).observe(document.body,{childList:!0,subtree:!0}),function(...e){(0,console.log)(...e)}(`%c${p}%c (${h}) userscript has loaded!`,"color: cornflowerblue;","")})();