diff --git a/dist/BlueMarble-For-GreasyFork.user.js b/dist/BlueMarble-For-GreasyFork.user.js
index 461a066..43b08cd 100644
--- a/dist/BlueMarble-For-GreasyFork.user.js
+++ b/dist/BlueMarble-For-GreasyFork.user.js
@@ -2,7 +2,7 @@
// @name Blue Marble
// @name:en Blue Marble
// @namespace https://github.com/SwingTheVine/
-// @version 0.88.133
+// @version 0.88.144
// @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.
// @description:en 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
@@ -37,7 +37,7 @@
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
// src/Overlay.js
- var _Overlay_instances, createElement_fn;
+ var _Overlay_instances, createElement_fn, applyAttribute_fn;
var Overlay = class {
/** Constructor for the Overlay class.
* @param {string} name - The name of the userscript
@@ -449,6 +449,8 @@
}) {
const properties = {
"type": "file",
+ "tabindex": "-1",
+ "aria-hidden": "true",
"style": "display: none !important; visibility: hidden !important; position: absolute !important; left: -9999px !important; width: 0 !important; height: 0 !important; opacity: 0 !important;"
};
const text = additionalProperties["textContent"] ?? "";
@@ -459,8 +461,6 @@
const button = __privateMethod(this, _Overlay_instances, createElement_fn).call(this, "button", { "textContent": text });
this.buildElement();
this.buildElement();
- input.setAttribute("tabindex", "-1");
- input.setAttribute("aria-hidden", "true");
button.addEventListener("click", () => {
input.click();
});
@@ -521,6 +521,52 @@
element.innerHTML = html;
}
}
+ /** Handles the minimization logic for windows spawned by Blue Marble
+ * @param {HTMLButtonElement} button - The UI button that triggered this minimization event
+ * @since 0.88.142
+ */
+ handleMinimization(button) {
+ button.disabled = true;
+ button.style.textDecoration = "none";
+ const window2 = button.closest(".bm-window");
+ const dragbar = button.closest(".bm-dragbar");
+ const header = window2.querySelector("h1");
+ const windowContent = window2.querySelector(".bm-window-content");
+ if (button.dataset["buttonStatus"] == "expanded") {
+ const dragbarHeader1 = header.cloneNode(true);
+ const dragbarHeader1Text = dragbarHeader1.textContent;
+ button.parentNode.appendChild(dragbarHeader1);
+ windowContent.style.height = windowContent.scrollHeight + "px";
+ window2.style.width = window2.scrollWidth + "px";
+ windowContent.style.height = "0";
+ windowContent.addEventListener("transitionend", function handler() {
+ windowContent.style.display = "none";
+ button.disabled = false;
+ button.style.textDecoration = "";
+ windowContent.removeEventListener("transitionend", handler);
+ });
+ button.textContent = "\u25B6";
+ button.dataset["buttonStatus"] = "collapsed";
+ button.ariaLabel = `Unminimize window "${dragbarHeader1Text}"`;
+ } else {
+ const dragbarHeader1 = dragbar.querySelector("h1");
+ const dragbarHeader1Text = dragbarHeader1.textContent;
+ dragbarHeader1.remove();
+ windowContent.style.display = "";
+ windowContent.style.height = "0";
+ window2.style.width = "";
+ windowContent.style.height = windowContent.scrollHeight + "px";
+ windowContent.addEventListener("transitionend", function handler() {
+ windowContent.style.height = "";
+ button.disabled = false;
+ button.style.textDecoration = "";
+ windowContent.removeEventListener("transitionend", handler);
+ });
+ button.textContent = "\u25BC";
+ button.dataset["buttonStatus"] = "expanded";
+ button.ariaLabel = `Minimize window "${dragbarHeader1Text}"`;
+ }
+ }
/** Handles dragging of the overlay.
* Uses requestAnimationFrame for smooth animations and GPU-accelerated transforms.
* Use the appropriate CSS selectors.
@@ -671,13 +717,43 @@
this.currentParent = element;
}
for (const [property, value] of Object.entries(properties)) {
- element[property != "class" ? property : "className"] = value;
+ __privateMethod(this, _Overlay_instances, applyAttribute_fn).call(this, element, property, value);
}
for (const [property, value] of Object.entries(additionalProperties)) {
- element[property != "class" ? property : "className"] = value;
+ __privateMethod(this, _Overlay_instances, applyAttribute_fn).call(this, element, property, value);
}
return element;
};
+ /** Applies an attribute to an element
+ * @param {HTMLElement} element - The element to apply the attribute to
+ * @param {String} property - The name of the attribute to apply
+ * @param {String} value - The value of the attribute
+ * @since 0.88.136
+ */
+ applyAttribute_fn = function(element, property, value) {
+ if (property == "class") {
+ element.classList.add(...value.split(/\s+/));
+ } else if (property == "for") {
+ element.htmlFor = value;
+ } else if (property == "tabindex") {
+ element.tabIndex = Number(value);
+ } else if (property == "readonly") {
+ element.readOnly = value == "true" || value == "1";
+ } else if (property == "maxlength") {
+ element.maxLength = Number(value);
+ } else if (property.startsWith("data")) {
+ element.dataset[property.slice(5).split("-").map(
+ (part, i) => i == 0 ? part : part[0].toUpperCase() + part.slice(1)
+ ).join("")] = value;
+ } else if (property.startsWith("aria")) {
+ const camelCase = property.slice(5).split("-").map(
+ (part, i) => i == 0 ? part : part[0].toUpperCase() + part.slice(1)
+ ).join("");
+ element["aria" + camelCase[0].toUpperCase() + camelCase.slice(1)] = value;
+ } else {
+ element[property] = value;
+ }
+ };
// src/observers.js
var Observers = class {
@@ -1698,36 +1774,8 @@ Time Since Blink: ${String(Math.floor(elapsed / 6e4)).padStart(2, "0")}:${String
observer.observe(document.body, { childList: true, subtree: true });
}
function buildOverlayMain() {
- overlayMain.addDiv({ "id": "bm-window-main", "class": "bm-window", "style": "top: 10px; right: 75px;" }).addDiv({ "class": "bm-dragbar" }).addDiv().addButton({ "class": "bm-button-circle", "textContent": "\u25BC" }, (instance, button) => {
- button.onclick = () => {
- const window2 = button.closest(".bm-window");
- const dragbar = button.closest(".bm-dragbar");
- const header = window2.querySelector("h1");
- const windowContent = window2.querySelector(".bm-window-content");
- if (button.textContent == "\u25BC") {
- const dragbarHeader1 = header.cloneNode(true);
- button.parentNode.appendChild(dragbarHeader1);
- windowContent.style.height = windowContent.scrollHeight + "px";
- window2.style.width = window2.scrollWidth + "px";
- windowContent.style.height = "0";
- windowContent.addEventListener("transitionend", function handler() {
- windowContent.style.display = "none";
- windowContent.removeEventListener("transitionend", handler);
- });
- } else {
- const dragbarHeader1 = dragbar.querySelector("h1");
- dragbarHeader1.remove();
- windowContent.style.display = "";
- windowContent.style.height = "0";
- window2.style.width = "";
- windowContent.style.height = windowContent.scrollHeight + "px";
- windowContent.addEventListener("transitionend", function handler() {
- windowContent.style.height = "";
- windowContent.removeEventListener("transitionend", handler);
- });
- }
- button.textContent = button.textContent == "\u25BC" ? "\u25B6" : "\u25BC";
- };
+ overlayMain.addDiv({ "id": "bm-window-main", "class": "bm-window", "style": "top: 10px; right: 75px;" }).addDiv({ "class": "bm-dragbar" }).addDiv().addButton({ "class": "bm-button-circle", "textContent": "\u25BC", "aria-label": 'Minimize window "Blue Marble"', "data-button-status": "expanded" }, (instance, button) => {
+ button.onclick = () => instance.handleMinimization(button);
}).buildElement().buildElement().buildElement().addDiv({ "class": "bm-window-content" }).addDiv({ "class": "bm-container" }).addImg({ "class": "bm-favicon", "src": "https://raw.githubusercontent.com/SwingTheVine/Wplace-BlueMarble/main/dist/assets/Favicon.png" }).buildElement().addHeader(1, { "textContent": name }).buildElement().buildElement().addHr().buildElement().addDiv({ "class": "bm-container" }).addP({ "id": "bm-user-droplets", "textContent": "Droplets:" }).buildElement().addP({ "id": "bm-user-nextlevel", "textContent": "Next level in..." }).buildElement().buildElement().addHr().buildElement().addDiv({ "class": "bm-container" }).addDiv({ "class": "bm-container" }).addButton(
{ "class": "bm-button-circle bm-button-pin", "style": "margin-top: 0;", "innerHTML": '' },
(instance, button) => {
@@ -1755,25 +1803,21 @@ Time Since Blink: ${String(Math.floor(elapsed / 6e4)).padStart(2, "0")}:${String
}
event.preventDefault();
});
- const handler = () => persistCoords();
- input.addEventListener("input", handler);
- input.addEventListener("change", handler);
- }).buildElement().addInput({ "type": "number", "id": "bm-input-ty", "class": "bm-input-coords", "placeholder": "Tl Y", "min": 0, "max": 2047, "step": 1, "required": true }, (instance, input) => {
- const handler = () => persistCoords();
- input.addEventListener("input", handler);
- input.addEventListener("change", handler);
- }).buildElement().addInput({ "type": "number", "id": "bm-input-px", "class": "bm-input-coords", "placeholder": "Px X", "min": 0, "max": 2047, "step": 1, "required": true }, (instance, input) => {
- const handler = () => persistCoords();
- input.addEventListener("input", handler);
- input.addEventListener("change", handler);
- }).buildElement().addInput({ "type": "number", "id": "bm-input-py", "class": "bm-input-coords", "placeholder": "Px Y", "min": 0, "max": 2047, "step": 1, "required": true }, (instance, input) => {
- const handler = () => persistCoords();
- input.addEventListener("input", handler);
- input.addEventListener("change", handler);
- }).buildElement().buildElement().addDiv({ "class": "bm-container" }).addInputFile({ "class": "bm-input-file", "textContent": "Upload Template", "accept": "image/png, image/jpeg, image/webp, image/bmp, image/gif" }).buildElement().buildElement().addDiv({ "class": "bm-container bm-flex-between" }).addButton({ "textContent": "Enable" }, (instance, button) => {
+ }).buildElement().addInput({ "type": "number", "id": "bm-input-ty", "class": "bm-input-coords", "placeholder": "Tl Y", "min": 0, "max": 2047, "step": 1, "required": true }).buildElement().addInput({ "type": "number", "id": "bm-input-px", "class": "bm-input-coords", "placeholder": "Px X", "min": 0, "max": 2047, "step": 1, "required": true }).buildElement().addInput({ "type": "number", "id": "bm-input-py", "class": "bm-input-coords", "placeholder": "Px Y", "min": 0, "max": 2047, "step": 1, "required": true }).buildElement().buildElement().addDiv({ "class": "bm-container" }).addInputFile({ "class": "bm-input-file", "textContent": "Upload Template", "accept": "image/png, image/jpeg, image/webp, image/bmp, image/gif" }).buildElement().buildElement().addDiv({ "class": "bm-container bm-flex-between" }).addButton({ "textContent": "Disable", "data-button-status": "shown" }, (instance, button) => {
button.onclick = () => {
- instance.apiManager?.templateManager?.setTemplatesShouldBeDrawn(true);
- instance.handleDisplayStatus(`Enabled templates!`);
+ button.disabled = true;
+ if (button.dataset["buttonStatus"] == "shown") {
+ instance.apiManager?.templateManager?.setTemplatesShouldBeDrawn(false);
+ button.dataset["buttonStatus"] = "hidden";
+ button.textContent = "Enable";
+ instance.handleDisplayStatus(`Disabled templates!`);
+ } else {
+ instance.apiManager?.templateManager?.setTemplatesShouldBeDrawn(true);
+ button.dataset["buttonStatus"] = "shown";
+ button.textContent = "Disable";
+ instance.handleDisplayStatus(`Enabled templates!`);
+ }
+ button.disabled = false;
};
}).buildElement().addButton({ "textContent": "Create" }, (instance, button) => {
button.onclick = () => {
@@ -1809,27 +1853,19 @@ Time Since Blink: ${String(Math.floor(elapsed / 6e4)).padStart(2, "0")}:${String
templateManager.createTemplate(input.files[0], input.files[0]?.name.replace(/\.[^/.]+$/, ""), [Number(coordTlX.value), Number(coordTlY.value), Number(coordPxX.value), Number(coordPxY.value)]);
instance.handleDisplayStatus(`Drew to canvas!`);
};
- }).buildElement().addButton({ "textContent": "Disable" }, (instance, button) => {
+ }).buildElement().addButton({ "textContent": "Filter" }, (instance, button) => {
button.onclick = () => {
- instance.apiManager?.templateManager?.setTemplatesShouldBeDrawn(false);
- instance.handleDisplayStatus(`Disabled templates!`);
};
}).buildElement().buildElement().addDiv({ "class": "bm-container" }).addTextarea({ "id": overlayMain.outputStatusId, "placeholder": `Status: Sleeping...
-Version: ${version}`, "readOnly": true }).buildElement().buildElement().addDiv({ "class": "bm-container bm-flex-between", "style": "margin-bottom: 0;" }).addDiv({ "class": "bm-flex-between" }).addButton(
- { "class": "bm-button-circle", "innerHTML": "\u{1F3A8}", "title": "Template Color Converter" },
- (instance, button) => {
- button.addEventListener("click", () => {
- window.open("https://pepoafonso.github.io/color_converter_wplace/", "_blank", "noopener noreferrer");
- });
- }
- ).buildElement().addButton(
- { "class": "bm-button-circle", "innerHTML": "\u{1F310}", "title": "Official Blue Marble Website" },
- (instance, button) => {
- button.addEventListener("click", () => {
- window.open("https://bluemarble.lol/", "_blank", "noopener noreferrer");
- });
- }
- ).buildElement().buildElement().addSmall({ "textContent": "Made by SwingTheVine", "style": "margin-top: auto;" }).buildElement().buildElement().buildElement().buildElement().buildElement().buildOverlay(document.body);
+Version: ${version}`, "readOnly": true }).buildElement().buildElement().addDiv({ "class": "bm-container bm-flex-between", "style": "margin-bottom: 0;" }).addDiv({ "class": "bm-flex-between" }).addButton({ "class": "bm-button-circle", "innerHTML": "\u{1F3A8}", "title": "Template Color Converter" }, (instance, button) => {
+ button.onclick = () => {
+ window.open("https://pepoafonso.github.io/color_converter_wplace/", "_blank", "noopener noreferrer");
+ };
+ }).buildElement().addButton({ "class": "bm-button-circle", "innerHTML": "\u{1F310}", "title": "Official Blue Marble Website" }, (instance, button) => {
+ button.onclick = () => {
+ window.open("https://bluemarble.lol/", "_blank", "noopener noreferrer");
+ };
+ }).buildElement().buildElement().addSmall({ "textContent": "Made by SwingTheVine", "style": "margin-top: auto;" }).buildElement().buildElement().buildElement().buildElement().buildElement().buildOverlay(document.body);
}
function buildTelemetryOverlay(overlay) {
overlay.addDiv({ "id": "bm-overlay-telemetry", style: "top: 0px; left: 0px; width: 100vw; max-width: 100vw; height: 100vh; max-height: 100vh; z-index: 9999;" }).addDiv({ "id": "bm-contain-all-telemetry", style: "display: flex; flex-direction: column; align-items: center;" }).addDiv({ "id": "bm-contain-header-telemetry", style: "margin-top: 10%;" }).addHeader(1, { "textContent": `${name} Telemetry` }).buildElement().buildElement().addDiv({ "id": "bm-contain-telemetry", style: "max-width: 50%; overflow-y: auto; max-height: 80vh;" }).addHr().buildElement().addBr().buildElement().addDiv({ "style": "width: fit-content; margin: auto; text-align: center;" }).addButton({ "id": "bm-button-telemetry-more", "textContent": "More Information" }, (instance, button) => {
diff --git a/dist/BlueMarble-Standalone.user.js b/dist/BlueMarble-Standalone.user.js
index 8e73c09..5b56f65 100644
--- a/dist/BlueMarble-Standalone.user.js
+++ b/dist/BlueMarble-Standalone.user.js
@@ -2,7 +2,7 @@
// @name Blue Marble
// @name:en Blue Marble
// @namespace https://github.com/SwingTheVine/
-// @version 0.88.133
+// @version 0.88.144
// @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.
// @description:en 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
@@ -27,4 +27,4 @@
// License --> https://www.mozilla.org/en-US/MPL/2.0/
// Donate --> https://ko-fi.com/swingthevine
-(()=>{var e,t,n=e=>{throw TypeError(e)},i=(e,t,i)=>t.has(e)?n("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(e):t.set(e,i),o=(e,t,i)=>(((e,t)=>{t.has(e)||n("Cannot access private method")})(e,t),i),s=class{constructor(t,n){i(this,e),this.name=t,this.version=n,this.t=null,this.i="bm-o",this.o=null,this.l=null,this.m=[]}u(e){this.t=e}h(){return this.m.length>0&&(this.l=this.m.pop()),this}p(e){e?.appendChild(this.o),this.o=null,this.l=null,this.m=[]}v(n={},i=()=>{}){return i(this,o(this,e,t).call(this,"div",{},n)),this}S(n={},i=()=>{}){return i(this,o(this,e,t).call(this,"p",{},n)),this}$(n={},i=()=>{}){return i(this,o(this,e,t).call(this,"small",{},n)),this}M(n={},i=()=>{}){return i(this,o(this,e,t).call(this,"details",{},n)),this}T(n={},i=()=>{}){return i(this,o(this,e,t).call(this,"summary",{},n)),this}D(n={},i=()=>{}){return i(this,o(this,e,t).call(this,"img",{},n)),this}O(n,i={},s=()=>{}){return s(this,o(this,e,t).call(this,"h"+n,{},i)),this}k(n={},i=()=>{}){return i(this,o(this,e,t).call(this,"hr",{},n)),this}C(n={},i=()=>{}){return i(this,o(this,e,t).call(this,"br",{},n)),this}N(n={},i=()=>{}){const s=o(this,e,t).call(this,"label",{textContent:n.textContent??""});delete n.textContent;const r=o(this,e,t).call(this,"input",{type:"checkbox"},n);return s.insertBefore(r,s.firstChild),this.h(),i(this,s,r),this}B(n={},i=()=>{}){return i(this,o(this,e,t).call(this,"button",{},n)),this}I(n={},i=()=>{}){const s=n.title??n.textContent??"Help: No info";delete n.textContent,n.title=`Help: ${s}`;const r={textContent:"?",className:"bm-D",onclick:()=>{this.L(this.i,s)}};return i(this,o(this,e,t).call(this,"button",r,n)),this}P(n={},i=()=>{}){return i(this,o(this,e,t).call(this,"input",{},n)),this}G(n={},i=()=>{}){const s=n.textContent??"";delete n.textContent;const r=o(this,e,t).call(this,"div"),a=o(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 l=o(this,e,t).call(this,"button",{textContent:s});return this.h(),this.h(),a.setAttribute("tabindex","-1"),a.setAttribute("aria-hidden","true"),l.addEventListener("click",()=>{a.click()}),a.addEventListener("change",()=>{l.style.maxWidth=`${l.offsetWidth}px`,a.files.length>0?l.textContent=a.files[0].name:l.textContent=s}),i(this,r,a,l),this}W(n={},i=()=>{}){return i(this,o(this,e,t).call(this,"textarea",{},n)),this}L(e,t,n=!1){const i=document.getElementById(e.replace(/^#/,""));i&&(i instanceof HTMLInputElement?i.value=t:n?i.textContent=t:i.innerHTML=t)}_(e,t){let n,i=!1,o=0,s=null,r=0,a=0,l=0,c=0,m=null;if(e=document.querySelector(e),t=document.querySelector(t),!e||!t)return void this.U(`Can not drag! ${e?"":"moveMe"} ${e||t?"":"and "}${t?"":"iMoveThings "}was not found!`);const u=()=>{if(i){const t=Math.abs(r-l),n=Math.abs(a-c);(t>.5||n>.5)&&(r=l,a=c,e.style.transform=`translate(${r}px, ${a}px)`,e.style.left="0px",e.style.top="0px",e.style.right=""),s=requestAnimationFrame(u)}},h=(h,g)=>{i=!0,m=e.getBoundingClientRect(),n=h-m.left,o=g-m.top;const f=window.getComputedStyle(e).transform;if(f&&"none"!==f){const e=new DOMMatrix(f);r=e.m41,a=e.m42}else r=m.left,a=m.top;l=r,c=a,document.body.style.userSelect="none",t.classList.add("bm-_"),document.addEventListener("mousemove",p),document.addEventListener("touchmove",b,{passive:!1}),document.addEventListener("mouseup",d),document.addEventListener("touchend",d),document.addEventListener("touchcancel",d),s&&cancelAnimationFrame(s),u()},d=()=>{i=!1,s&&(cancelAnimationFrame(s),s=null),document.body.style.userSelect="",t.classList.remove("bm-_"),document.removeEventListener("mousemove",p),document.removeEventListener("touchmove",b),document.removeEventListener("mouseup",d),document.removeEventListener("touchend",d),document.removeEventListener("touchcancel",d)},p=e=>{i&&m&&(l=e.clientX-n,c=e.clientY-o)},b=e=>{if(i&&m){const t=e.touches[0];if(!t)return;l=t.clientX-n,c=t.clientY-o,e.preventDefault()}};t.addEventListener("mousedown",function(e){e.preventDefault(),h(e.clientX,e.clientY)}),t.addEventListener("touchstart",function(e){const t=e?.touches?.[0];t&&(h(t.clientX,t.clientY),e.preventDefault())},{passive:!1})}A(e){(0,console.info)(`${this.name}: ${e}`),this.L(this.i,"Status: "+e,!0)}U(e){(0,console.error)(`${this.name}: ${e}`),this.L(this.i,"Error: "+e,!0)}};function r(...e){(0,console.error)(...e)}function a(e,t){if(0===e)return t[0];let n="";const i=t.length;for(;e>0;)n=t[e%i]+n,e=Math.floor(e/i);return n}function l(e){let t="";for(let n=0;n>>24==0?0:o.get(t)??-2;const r=s.get(i);s.set(i,r?r+1:1)}return console.log(s),s},h=new WeakSet,d=async function(){GM.setValue("bmTemplates",JSON.stringify(this.ee))},p=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,i=t[e];if(console.log(`Template Key: ${n}`),t.hasOwnProperty(e)){const e=n.split(" "),t=Number(e?.[0]),o=e?.[1]||"0",s=i.name||`Template ${t||""}`,r={total:i.pixels.total,colors:new Map(Object.entries(i.pixels.colors).map(([e,t])=>[Number(e),t]))},a=i.tiles,l={},m={},u=this.Y*this.te;for(const e in a)if(console.log(e),a.hasOwnProperty(e)){const t=c(a[e]),n=new Blob([t],{type:"image/png"}),i=await createImageBitmap(n);l[e]=i;const o=new OffscreenCanvas(u,u).getContext("2d");o.drawImage(i,0,0);const s=o.getImageData(0,0,i.width,i.height);m[e]=new Uint32Array(s.data.buffer)}const h=new v({displayName:s,X:t||this.ne?.length||0,J:o||""});h.V=r,h.j=l,h.R=m,this.ne.push(h),console.log(this.ne),console.log("^^^ This ^^^")}}},b=function(e,t,n){const i=this.te,o=this.Y*i,s=n[0],r=n[1],a=n[2],l=n[3],c=this.ie,{palette:m,Z:u}=this.oe,h=new Map;for(let n=1;n>>24&255)<=c||(i>>>24&255)<=c)continue;const d=u.get(i)??-2,p=u.get(m)??-2;if(d!=p)continue;const b=h.get(p);h.set(p,b?b+1:1)}return console.log("List of template pixels that match the tile:"),console.log(h),h},g=new WeakSet,f=async function(e=navigator.userAgent){return(e=e||"").includes("OPR/")||e.includes("Opera")?"Opera":e.includes("Edg/")?"Edge":e.includes("Vivaldi")?"Vivaldi":e.includes("YaBrowser")?"Yandex":e.includes("Kiwi")?"Kiwi":e.includes("Brave")?"Brave":e.includes("Firefox/")?"Firefox":e.includes("Chrome/")?"Chrome":e.includes("Safari/")?"Safari":navigator.brave&&"function"==typeof navigator.brave.isBrave&&await navigator.brave.isBrave()?"Brave":"Unknown"},w=function(e=navigator.userAgent){return/Windows NT 11/i.test(e=e||"")?"Windows 11":/Windows NT 10/i.test(e)?"Windows 10":/Windows NT 6\.3/i.test(e)?"Windows 8.1":/Windows NT 6\.2/i.test(e)?"Windows 8":/Windows NT 6\.1/i.test(e)?"Windows 7":/Windows NT 6\.0/i.test(e)?"Windows Vista":/Windows NT 5\.1|Windows XP/i.test(e)?"Windows XP":/Mac OS X 10[_\.]15/i.test(e)?"macOS Catalina":/Mac OS X 10[_\.]14/i.test(e)?"macOS Mojave":/Mac OS X 10[_\.]13/i.test(e)?"macOS High Sierra":/Mac OS X 10[_\.]12/i.test(e)?"macOS Sierra":/Mac OS X 10[_\.]11/i.test(e)?"OS X El Capitan":/Mac OS X 10[_\.]10/i.test(e)?"OS X Yosemite":/Mac OS X 10[_\.]/i.test(e)?"macOS":/Android/i.test(e)?"Android":/iPhone|iPad|iPod/i.test(e)?"iOS":/Linux/i.test(e)?"Linux":"Unknown"};var x=GM_info.script.name.toString(),S=GM_info.script.version.toString();!function(e){const t=document.createElement("script");t.setAttribute("bm-E",x),t.setAttribute("bm-B","color: cornflowerblue;"),t.textContent=`(${e})();`,document.documentElement?.appendChild(t),t.remove()}(()=>{const e=document.currentScript,t=e?.getAttribute("bm-E")||"Blue Marble",n=e?.getAttribute("bm-B")||"",i=new Map;window.addEventListener("message",e=>{const{source:o,endpoint:s,blobID:r,blobData:a,blink:l}=e.data,c=Date.now()-l;if(console.groupCollapsed(`%c${t}%c: ${i.size} Recieved IMAGE message about blob "${r}"`,n,""),console.log(`Blob fetch took %c${String(Math.floor(c/6e4)).padStart(2,"0")}:${String(Math.floor(c/1e3)%60).padStart(2,"0")}.${String(c%1e3).padStart(3,"0")}%c MM:SS.mmm`,n,""),console.log(i),console.groupEnd(),"blue-marble"==o&&r&&a&&!s){const e=i.get(r);"function"==typeof e?e(a):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,"",r),i.delete(r)}});const o=window.fetch;window.fetch=async function(...e){const s=await o.apply(this,e),r=s.clone(),a=(e[0]instanceof Request?e[0]?.url:e[0])||"ignore",l=r.headers.get("content-type")||"";if(l.includes("application/json"))console.log(`%c${t}%c: Sending JSON message about endpoint "${a}"`,n,""),r.json().then(e=>{window.postMessage({source:"blue-marble",endpoint:a,jsonData:e},"*")}).catch(e=>{console.error(`%c${t}%c: Failed to parse JSON: `,n,"",e)});else if(l.includes("image/")&&!a.includes("openfreemap")&&!a.includes("maps")){const e=Date.now(),o=await r.blob();return console.log(`%c${t}%c: ${i.size} Sending IMAGE message about endpoint "${a}"`,n,""),new Promise(s=>{const l=crypto.randomUUID();i.set(l,e=>{s(new Response(e,{headers:r.headers,status:r.status,statusText:r.statusText})),console.log(`%c${t}%c: ${i.size} Processed blob "${l}"`,n,"")}),window.postMessage({source:"blue-marble",endpoint:a,blobID:l,blobData:o,blink:e})}).catch(o=>{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: ${a}\nThere are ${i.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:",o),console.groupEnd()})}return s}});var $=`.bm-17{position:fixed;background-color:#153063e6;color:#fff;padding:10px;border-radius:8px;z-index:9000;transition:all .3s ease,transform 0s;max-width:300px;width:auto;font-family:Roboto Mono,Courier New,Monaco,DejaVu Sans Mono,monospace,Arial;letter-spacing:.05em}.bm-14{display:flex;align-items:center;flex-wrap:nowrap;justify-content:space-between;gap:.5ch;background:url('data:image/svg+xml;utf8,') repeat;cursor:grab;width:100%;height:fit-content}.bm-14.bm-_{cursor:grabbing}.bm-17:has(.bm-14.bm-_){pointer-events:none;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}.bm-14.bm-_{pointer-events:auto}.bm-15{display:inline-block;height:2.5em;margin-right:1ch;vertical-align:middle}.bm-17 h1{display:inline-block;font-size:x-large;font-weight:700;vertical-align:middle}.bm-14 h1{font-size:1.2em;margin-left:.5ch;user-select:none;text-shadow:3px 0px rgba(21,48,99,.5),-3px 0px rgba(21,48,99,.5),0px 3px rgba(21,48,99,.5),0px -3px rgba(21,48,99,.5),3px 3px rgba(21,48,99,.5),-3px 3px rgba(21,48,99,.5),3px -3px rgba(21,48,99,.5),-3px -3px rgba(21,48,99,.5)}.bm--{margin:.5em 0}.bm-17 button{background-color:#144eb9;border-radius:1em;padding:0 .75ch}.bm-17 button:hover,.bm-17 button:focus-visible{background-color:#1061e5}.bm-17 button:active .bm-17 button:disabled{background-color:#2e97ff}.bm-17 button:disabled{text-decoration:line-through}.bm-T{border:white 1px solid;height:1.5em;width:1.5em;margin-top:2px;text-align:center;line-height:1em;padding:0!important}.bm-Y{vertical-align:middle}.bm-Y svg{width:50%;margin:0 auto;fill:#111}input[type=number].bm-U{appearance:auto;-moz-appearance:textfield;width:5.5ch;margin-left:1ch;background-color:#0003;padding:0 .5ch;font-size:small}input[type=number].bm-U::-webkit-outer-spin-button,input[type=number].bm-U::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}div:has(>.bm-Z)>button{width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.bm-Z,input[type=file]{display:none!important;visibility:hidden!important;position:absolute!important;left:-9999px!important;top:-9999px!important;width:0!important;height:0!important;opacity:0!important;z-index:-9999!important;pointer-events:none!important}.bm-Q{overflow:hidden;transition:height .3s cubic-bezier(.4,0,.2,1)}.bm-17 textarea{font-size:small;background-color:#0003;padding:0 .5ch;height:5.25em;width:100%}.bm-17 small{font-size:x-small;color:#d3d3d3}.bm-V{display:flex;align-content:center;justify-content:space-between;align-items:center;gap:.5ch}.bm-flex-center{display:flex;align-content:center;justify-content:center;align-items:center;gap:.5ch}#bm-A,#bm-d{position:fixed;background-color:#153063e6;color:#fff;padding:10px;border-radius:8px;z-index:9000;transition:all .3s ease,transform 0s;max-width:300px;width:auto;will-change:transform;backface-visibility:hidden;-webkit-backface-visibility:hidden;transform-style:preserve-3d;-webkit-transform-style:preserve-3d}#bm-f,#bm-A hr,#bm-d hr,#bm-c,#bm-6{transition:opacity .2s ease,height .2s ease}div#bm-A,div#bm-d{font-family:Roboto Mono,Courier New,Monaco,DejaVu Sans Mono,monospace,Arial;letter-spacing:.05em}#bm-z,#bm-z-telemetry{margin-bottom:.5em;background:url('data:image/svg+xml;utf8,') repeat;cursor:grab;width:100%;height:1em}#bm-z.dragging,#bm-z-telemetry.dragging{cursor:grabbing}#bm-A:has(#bm-z.dragging),#bm-d:has(#bm-z-telemetry.dragging){pointer-events:none;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}#bm-z.dragging,#bm-z-telemetry.dragging{pointer-events:auto}#bm-j,#bm-1{margin-bottom:.5em}#bm-j[style*="text-align: center"],#bm-1[style*="text-align: center"]{display:flex;flex-direction:column;align-items:center;justify-content:center}#bm-A[style*="padding: 5px"],#bm-d[style*="padding: 5px"]{width:auto!important;max-width:300px;min-width:200px}#bm-A img{display:inline-block;height:2.5em;margin-right:1ch;vertical-align:middle;transition:opacity .2s ease}#bm-j[style*="text-align: center"] img{display:block;margin:0 auto}#bm-z,#bm-z-telemetry{transition:margin-bottom .2s ease}#bm-A h1,#bm-d h1{display:inline-block;font-size:x-large;font-weight:700;vertical-align:middle}#bm-c input[type=checkbox]{vertical-align:middle;margin-right:.5ch}#bm-c label{margin-right:.5ch}.bm-D{border:white 1px solid;height:1.5em;width:1.5em;margin-top:2px;text-align:center;line-height:1em;padding:0!important}#bm-q{vertical-align:middle}#bm-q svg{width:50%;margin:0 auto;fill:#111}#bm-f{margin-bottom:.5em}div:has(>#bm-button-teleport){display:flex;gap:.5ch}#bm-button-favorite svg,#bm-button-template svg{height:1em;margin:2px auto 0;text-align:center;line-height:1em;vertical-align:bottom}#bm-k input[type=number]{appearance:auto;-moz-appearance:textfield;width:5.5ch;margin-left:1ch;background-color:#0003;padding:0 .5ch;font-size:small}#bm-k input[type=number]::-webkit-outer-spin-button,#bm-k input[type=number]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}#bm-4{display:flex;flex-direction:row;flex-wrap:wrap;align-content:center;justify-content:center;align-items:center;gap:1ch}div:has(>#bm-a)>button{width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}#bm-a,input[type=file][id*=template]{display:none!important;visibility:hidden!important;position:absolute!important;left:-9999px!important;top:-9999px!important;width:0!important;height:0!important;opacity:0!important;z-index:-9999!important;pointer-events:none!important}#bm-o{font-size:small;background-color:#0003;padding:0 .5ch;height:3.75em;width:100%}#bm-6{display:flex;justify-content:space-between}div#bm-6 button#bm-D{margin-right:2px}#bm-A small{font-size:x-small;color:#d3d3d3}#bm-f,#bm-c,#bm-k,#bm-4,div:has(>#bm-a),#bm-o{margin-top:.5em}#bm-A button,#bm-d button{background-color:#144eb9;border-radius:1em;padding:0 .75ch}#bm-A button:hover,#bm-A button:focus-visible,#bm-d button:hover,#bm-d button:focus-visible{background-color:#1061e5}#bm-A button:active,#bm-d button:active #bm-A button:disabled,#bm-d button:disabled{background-color:#2e97ff}#bm-A button:disabled,#bm-d button:disabled{text-decoration:line-through}`;GM_addStyle($);var M,T="@font-face{font-family:'Roboto Mono';font-style:normal;font-weight:400;src:url(data:font/woff2;base64,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)format('woff2');}";T.indexOf("@font-face")+1?(console.log("Loading Roboto Mono as a file..."),GM_addStyle(T)):((M=document.createElement("link")).href="https://fonts.googleapis.com/css2?family=Roboto+Mono:ital,wght@0,100..700;1,100..700&display=swap",M.rel="preload",M.as="style",M.onload=function(){this.onload=null,this.rel="stylesheet"},document.head?.appendChild(M)),new class{constructor(){this.se=null,this.re=null,this.ae="#bm-h"}le(e){return this.re=e,this.se=new MutationObserver(e=>{for(const t of e)for(const e of t.addedNodes)e instanceof HTMLElement&&e.matches?.(this.ae)}),this}ce(){return this.se}observe(e,t=!1,n=!1){e.observe(this.re,{childList:t,subtree:n})}};var D=new s(x,S),O=(new s(x,S),new class{constructor(e,t,n){i(this,h),this.name=e,this.version=t,this.o=n,this.me="1.0.0",this.ue=null,this.he="!#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",this.Y=1e3,this.te=3,this.ie=3,this.oe=function(e){const t=y;t.unshift({id:-1,premium:!1,name:"Erased",rgb:[222,250,206]}),t.unshift({id:-2,premium:!1,name:"Other",rgb:[0,0,0]});const n=new Map;for(const i of t){if(0==i.id||-2==i.id)continue;const t=i.rgb[0],o=i.rgb[1],s=i.rgb[2];for(let r=-e;r<=e;r++)for(let a=-e;a<=e;a++)for(let l=-e;l<=e;l++){const e=t+r,c=o+a,m=s+l;if(e<0||e>255||c<0||c>255||m<0||m>255)continue;const u=(255<<24|m<<16|c<<8|e)>>>0;n.has(u)||n.set(u,i.id)}}return{palette:t,Z:n}}(this.ie),this.de=null,this.pe="",this.ne=[],this.ee=null,this.be=!0,this.ge=null}async fe(){return{whoami:this.name.replace(" ",""),scriptVersion:this.version,schemaVersion:this.me,templates:{}}}async we(e,t,n){this.ee||(this.ee=await this.fe(),console.log("Creating JSON...")),this.o.A(`Creating template at ${n.join(", ")}...`);const i=new v({displayName:t,X:0,J:a(this.ue||0,this.he),file:e,coords:n}),{q:s,K:r}=await i.F(this.Y,this.oe);i.j=s;const l={total:i.V.total,colors:Object.fromEntries(i.V.colors)};this.ee.templates[`${i.X} ${i.J}`]={name:i.displayName,coords:n.join(", "),enabled:!0,pixels:l,tiles:r},this.ne=[],this.ne.push(i),this.o.A(`Template created at ${n.join(", ")}!`),console.log(Object.keys(this.ee.templates).length),console.log(this.ee),console.log(this.ne),console.log(JSON.stringify(this.ee)),await o(this,h,d).call(this)}ye(){}async ve(){this.ee||(this.ee=await this.fe(),console.log("Creating JSON..."))}async xe(e,t){if(!this.be)return e;const n=this.Y*this.te;t=t[0].toString().padStart(4,"0")+","+t[1].toString().padStart(4,"0"),console.log(`Searching for templates in tile: "${t}"`);const i=this.ne;console.log(i),i.sort((e,t)=>e.X-t.X),console.log(i);const s=i.map(e=>{const n=Object.keys(e.j).filter(e=>e.startsWith(t));if(0===n.length)return null;const i=n.map(t=>{const n=t.split(",");return{Se:e,$e:e.j[t],R:e.R?.[t],Me:[n[0],n[1]],Te:[n[2],n[3]]}});return i?.[0]}).filter(Boolean);console.log(s);const r=s?.length||0;if(console.log(`templateCount = ${r}`),!(r>0))return this.o.A(`Sleeping\nVersion: ${this.version}`),e;{const e=i.filter(e=>Object.keys(e.j).filter(e=>e.startsWith(t)).length>0).reduce((e,t)=>e+(t.V.total||0),0),n=(new Intl.NumberFormat).format(e);this.o.A(`Displaying ${r} template${1==r?"":"s"}.\nTotal pixels: ${n}`)}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);const m=c.getImageData(0,0,n,n),u=new Uint32Array(m.data.buffer);for(const e of s){console.log("Template:"),console.log(e);let n=e.R;const i=Number(e.Te[0])*this.te,s=Number(e.Te[1])*this.te;if(c.drawImage(e.$e,i,s),!n){const t=c.getImageData(i,s,e.$e.width,e.$e.height);n=new Uint32Array(t.data.buffer)}const r=Date.now(),a=o(this,h,b).call(this,u,n,[i,s,e.$e.width,e.$e.height]);let l=0;const m=0;for(const[e,t]of a)e!=m&&(l+=t);console.log(`Finished calculating correct pixels for the tile ${t} in ${(Date.now()-r)/1e3} seconds!\nThere are ${l} correct pixels.`),e.Se.V.correct=a}return await l.convertToBlob({type:"image/png"})}De(e){console.log("Importing JSON..."),console.log(e),"BlueMarble"==e?.whoami&&o(this,h,p).call(this,e)}Oe(e){this.be=e}}(x,S,D)),k=new class{constructor(e){i(this,g),this.ke=e,this.Ce=!1,this.Ne=[],this.Be=[]}Ie(e){window.addEventListener("message",async t=>{const n=t.data,i=n.jsonData;if(!n||"blue-marble"!==n.source)return;if(!n.endpoint)return;const o=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;","",o),o){case"me":if(i.status&&"2"!=i.status?.toString()[0])return void e.U("You are not logged in!\nCould not fetch userdata.");const t=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(a(i.id,"!#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~")),this.ke.ue=i.id,e.L("bm-p",`Droplets: ${(new Intl.NumberFormat).format(i.droplets)}`),e.L("bm-i",`Next level in ${(new Intl.NumberFormat).format(t)} pixel${1==t?"":"s"}`);break;case"pixel":const o=n.endpoint.split("?")[0].split("/").filter(e=>e&&!isNaN(Number(e))),l=new URLSearchParams(n.endpoint.split("?")[1]),c=[l.get("x"),l.get("y")];if(this.Ne.length&&(!o.length||!c.length))return void e.U("Coordinates are malformed!\nDid you try clicking the canvas first?");this.Ne=[...o,...c];const m=(s=o,r=c,[parseInt(s[0])%4*1e3+parseInt(r[0]),parseInt(s[1])%4*1e3+parseInt(r[1])]),u=document.querySelectorAll("span");for(const e of u)if(e.textContent.trim().includes(`${m[0]}, ${m[1]}`)){let t=document.querySelector("#bm-h");const n=`(Tl X: ${o[0]}, Tl Y: ${o[1]}, Px X: ${c[0]}, Px Y: ${c[1]})`;t?t.textContent=n:(t=document.createElement("span"),t.id="bm-h",t.textContent=n,t.style="margin-left: calc(var(--spacing)*3); font-size: small;",e.parentNode.parentNode.insertAdjacentElement("afterend",t))}break;case"tiles":let h=n.endpoint.split("/");h=[parseInt(h[h.length-2]),parseInt(h[h.length-1].replace(".png",""))];const d=n.blobID,p=n.blobData,b=Date.now(),g=await this.ke.xe(p,h);console.log(`Finished loading the tile in ${(Date.now()-b)/1e3} seconds!`),window.postMessage({source:"blue-marble",blobID:d,blobData:g,blink:n.blink});break;case"robots":this.Ce="false"==i.userscript?.toString().toLowerCase();break}var s,r})}async Le(e){console.log("Sending heartbeat to telemetry server...");let t=GM_getValue("bmUserSettings","{}");if(t=JSON.parse(t),!t||!t.telemetry||!t.uuid)return void console.log("Telemetry is disabled, not sending heartbeat.");const n=navigator.userAgent;let i=await o(this,g,f).call(this,n),s=o(this,g,w).call(this,n);GM_xmlhttpRequest({method:"POST",url:"https://telemetry.thebluecorner.net/heartbeat",headers:{"Content-Type":"application/json"},data:JSON.stringify({uuid:t.uuid,version:e,browser:i,os:s}),onload:e=>{200!==e.status&&r("Failed to send heartbeat:",e.statusText)},onerror:e=>{r("Error sending heartbeat:",e)}})}}(O);D.u(k);var C=JSON.parse(GM_getValue("bmTemplates","{}"));console.log(C),O.De(C);var N=JSON.parse(GM_getValue("bmUserSettings","{}"));if(console.log(N),console.log(Object.keys(N).length),0==Object.keys(N).length){const e=crypto.randomUUID();console.log(e),GM.setValue("bmUserSettings",JSON.stringify({uuid:e}))}if(setInterval(()=>k.Le(S),18e5),console.log(`Telemetry is ${!(null==N?.telemetry)}`),null==N?.telemetry||N?.telemetry>1){const e=new s(x,S);e.u(k),e.v({id:"bm-d",style:"top: 0px; left: 0px; width: 100vw; max-width: 100vw; height: 100vh; max-height: 100vh; z-index: 9999;"}).v({id:"bm-7",style:"display: flex; flex-direction: column; align-items: center;"}).v({id:"bm-1",style:"margin-top: 10%;"}).O(1,{textContent:`${x} Telemetry`}).h().h().v({id:"bm-e",style:"max-width: 50%; overflow-y: auto; max-height: 80vh;"}).k().h().C().h().v({style:"width: fit-content; margin: auto; text-align: center;"}).B({id:"bm-8",textContent:"More Information"},(e,t)=>{t.onclick=()=>{window.open("https://github.com/SwingTheVine/Wplace-TelemetryServer#telemetry-data","_blank","noopener noreferrer")}}).h().h().C().h().v({style:"width: fit-content; margin: auto; text-align: center;"}).B({id:"bm-5",textContent:"Enable Telemetry",style:"margin-right: 2ch;"},(e,t)=>{t.onclick=()=>{const e=JSON.parse(GM_getValue("bmUserSettings","{}"));e.telemetry=1,GM.setValue("bmUserSettings",JSON.stringify(e));const t=document.getElementById("bm-d");t&&(t.style.display="none")}}).h().B({id:"bm-2",textContent:"Disable Telemetry"},(e,t)=>{t.onclick=()=>{const e=JSON.parse(GM_getValue("bmUserSettings","{}"));e.telemetry=0,GM.setValue("bmUserSettings",JSON.stringify(e));const t=document.getElementById("bm-d");t&&(t.style.display="none")}}).h().h().C().h().S({textContent:"We collect anonymous telemetry data such as your browser, OS, and script version to make the experience better for everyone. The data is never shared personally. The data is never sold. You can turn this off by pressing the 'Disable' button, but keeping it on helps us improve features and reliability faster. Thank you for supporting the Blue Marble!"}).h().S({textContent:'You can disable telemetry by pressing the "Disable" button below.'}).h().h().h().p(document.body)}D.v({id:"bm-W",class:"bm-17",style:"top: 10px; right: 75px;"}).v({class:"bm-14"}).v().B({class:"bm-T",textContent:"▼"},(e,t)=>{t.onclick=()=>{const e=t.closest(".bm-17"),n=t.closest(".bm-14"),i=e.querySelector("h1"),o=e.querySelector(".bm-Q");if("▼"==t.textContent){const n=i.cloneNode(!0);t.parentNode.appendChild(n),o.style.height=o.scrollHeight+"px",e.style.width=e.scrollWidth+"px",o.style.height="0",o.addEventListener("transitionend",function e(){o.style.display="none",o.removeEventListener("transitionend",e)})}else n.querySelector("h1").remove(),o.style.display="",o.style.height="0",e.style.width="",o.style.height=o.scrollHeight+"px",o.addEventListener("transitionend",function e(){o.style.height="",o.removeEventListener("transitionend",e)});t.textContent="▼"==t.textContent?"▶":"▼"}}).h().h().h().v({class:"bm-Q"}).v({class:"bm--"}).D({class:"bm-15",src:"data:image/png;base64,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"}).h().O(1,{textContent:x}).h().h().k().h().v({class:"bm--"}).S({id:"bm-p",textContent:"Droplets:"}).h().S({id:"bm-i",textContent:"Next level in..."}).h().h().k().h().v({class:"bm--"}).v({class:"bm--"}).B({class:"bm-T bm-Y",style:"margin-top: 0;",innerHTML:''},(e,t)=>{t.onclick=()=>{const t=e.t?.Ne;t?.[0]?(e.L("bm-v",t?.[0]||""),e.L("bm-w",t?.[1]||""),e.L("bm-x",t?.[2]||""),e.L("bm-y",t?.[3]||"")):e.U("Coordinates are malformed! Did you try clicking on the canvas first?")}}).h().P({type:"number",id:"bm-v",class:"bm-U",placeholder:"Tl X",min:0,max:2047,step:1,required:!0},(e,t)=>{t.addEventListener("paste",e=>{let t=(e.clipboardData||window.clipboardData).getData("text").split(" ").filter(e=>e).map(Number).filter(e=>!isNaN(e));if(4!==t.length)return;let n=selectAllCoordinateInputs(document);for(let e=0;epersistCoords();t.addEventListener("input",n),t.addEventListener("change",n)}).h().P({type:"number",id:"bm-w",class:"bm-U",placeholder:"Tl Y",min:0,max:2047,step:1,required:!0},(e,t)=>{const n=()=>persistCoords();t.addEventListener("input",n),t.addEventListener("change",n)}).h().P({type:"number",id:"bm-x",class:"bm-U",placeholder:"Px X",min:0,max:2047,step:1,required:!0},(e,t)=>{const n=()=>persistCoords();t.addEventListener("input",n),t.addEventListener("change",n)}).h().P({type:"number",id:"bm-y",class:"bm-U",placeholder:"Px Y",min:0,max:2047,step:1,required:!0},(e,t)=>{const n=()=>persistCoords();t.addEventListener("input",n),t.addEventListener("change",n)}).h().h().v({class:"bm--"}).G({class:"bm-Z",textContent:"Upload Template",accept:"image/png, image/jpeg, image/webp, image/bmp, image/gif"}).h().h().v({class:"bm-- bm-V"}).B({textContent:"Enable"},(e,t)=>{t.onclick=()=>{e.t?.ke?.Oe(!0),e.A("Enabled templates!")}}).h().B({textContent:"Create"},(e,t)=>{t.onclick=()=>{const t=document.querySelector("#bm-W button.bm-Z"),n=document.querySelector("#bm-v");if(!n.checkValidity())return n.reportValidity(),void e.U("Coordinates are malformed! Did you try clicking on the canvas first?");const i=document.querySelector("#bm-w");if(!i.checkValidity())return i.reportValidity(),void e.U("Coordinates are malformed! Did you try clicking on the canvas first?");const o=document.querySelector("#bm-x");if(!o.checkValidity())return o.reportValidity(),void e.U("Coordinates are malformed! Did you try clicking on the canvas first?");const s=document.querySelector("#bm-y");if(!s.checkValidity())return s.reportValidity(),void e.U("Coordinates are malformed! Did you try clicking on the canvas first?");t?.files[0]?(O.we(t.files[0],t.files[0]?.name.replace(/\.[^/.]+$/,""),[Number(n.value),Number(i.value),Number(o.value),Number(s.value)]),e.A("Drew to canvas!")):e.U("No file selected!")}}).h().B({textContent:"Disable"},(e,t)=>{t.onclick=()=>{e.t?.ke?.Oe(!1),e.A("Disabled templates!")}}).h().h().v({class:"bm--"}).W({id:D.i,placeholder:`Status: Sleeping...\nVersion: ${S}`,readOnly:!0}).h().h().v({class:"bm-- bm-V",style:"margin-bottom: 0;"}).v({class:"bm-V"}).B({class:"bm-T",innerHTML:"🎨",title:"Template Color Converter"},(e,t)=>{t.addEventListener("click",()=>{window.open("https://pepoafonso.github.io/color_converter_wplace/","_blank","noopener noreferrer")})}).h().B({class:"bm-T",innerHTML:"🌐",title:"Official Blue Marble Website"},(e,t)=>{t.addEventListener("click",()=>{window.open("https://bluemarble.lol/","_blank","noopener noreferrer")})}).h().h().$({textContent:"Made by SwingTheVine",style:"margin-top: auto;"}).h().h().h().h().h().p(document.body),D._("#bm-W.bm-17","#bm-W .bm-14"),k.Ie(D),new MutationObserver((e,t)=>{const n=document.querySelector("#color-1");if(!n)return;let i=document.querySelector("#bm-t");if(!i){i=document.createElement("button"),i.id="bm-t",i.textContent="Move ↑",i.className="btn btn-soft",i.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(i)}}).observe(document.body,{childList:!0,subtree:!0}),function(...e){(0,console.log)(...e)}(`%c${x}%c (${S}) userscript has loaded!`,"color: cornflowerblue;","")})();
\ No newline at end of file
+(()=>{var e,t,n,i=e=>{throw TypeError(e)},o=(e,t,n)=>t.has(e)?i("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(e):t.set(e,n),s=(e,t,n)=>(((e,t)=>{t.has(e)||i("Cannot access private method")})(e,t),n),a=class{constructor(t,n){o(this,e),this.name=t,this.version=n,this.t=null,this.i="bm-o",this.o=null,this.l=null,this.m=[]}u(e){this.t=e}h(){return this.m.length>0&&(this.l=this.m.pop()),this}p(e){e?.appendChild(this.o),this.o=null,this.l=null,this.m=[]}v(n={},i=()=>{}){return i(this,s(this,e,t).call(this,"div",{},n)),this}S(n={},i=()=>{}){return i(this,s(this,e,t).call(this,"p",{},n)),this}$(n={},i=()=>{}){return i(this,s(this,e,t).call(this,"small",{},n)),this}M(n={},i=()=>{}){return i(this,s(this,e,t).call(this,"details",{},n)),this}T(n={},i=()=>{}){return i(this,s(this,e,t).call(this,"summary",{},n)),this}D(n={},i=()=>{}){return i(this,s(this,e,t).call(this,"img",{},n)),this}O(n,i={},o=()=>{}){return o(this,s(this,e,t).call(this,"h"+n,{},i)),this}k(n={},i=()=>{}){return i(this,s(this,e,t).call(this,"hr",{},n)),this}C(n={},i=()=>{}){return i(this,s(this,e,t).call(this,"br",{},n)),this}N(n={},i=()=>{}){const o=s(this,e,t).call(this,"label",{textContent:n.textContent??""});delete n.textContent;const a=s(this,e,t).call(this,"input",{type:"checkbox"},n);return o.insertBefore(a,o.firstChild),this.h(),i(this,o,a),this}B(n={},i=()=>{}){return i(this,s(this,e,t).call(this,"button",{},n)),this}I(n={},i=()=>{}){const o=n.title??n.textContent??"Help: No info";delete n.textContent,n.title=`Help: ${o}`;const a={textContent:"?",className:"bm-D",onclick:()=>{this.L(this.i,o)}};return i(this,s(this,e,t).call(this,"button",a,n)),this}P(n={},i=()=>{}){return i(this,s(this,e,t).call(this,"input",{},n)),this}G(n={},i=()=>{}){const o=n.textContent??"";delete n.textContent;const a=s(this,e,t).call(this,"div"),r=s(this,e,t).call(this,"input",{type:"file",tabindex:"-1","aria-hidden":"true",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 l=s(this,e,t).call(this,"button",{textContent:o});return this.h(),this.h(),l.addEventListener("click",()=>{r.click()}),r.addEventListener("change",()=>{l.style.maxWidth=`${l.offsetWidth}px`,r.files.length>0?l.textContent=r.files[0].name:l.textContent=o}),i(this,a,r,l),this}W(n={},i=()=>{}){return i(this,s(this,e,t).call(this,"textarea",{},n)),this}L(e,t,n=!1){const i=document.getElementById(e.replace(/^#/,""));i&&(i instanceof HTMLInputElement?i.value=t:n?i.textContent=t:i.innerHTML=t)}U(e){e.disabled=!0,e.style.textDecoration="none";const t=e.closest(".bm-16"),n=e.closest(".bm-14"),i=t.querySelector("h1"),o=t.querySelector(".bm-O");if("expanded"==e.dataset.buttonStatus){const n=i.cloneNode(!0),s=n.textContent;e.parentNode.appendChild(n),o.style.height=o.scrollHeight+"px",t.style.width=t.scrollWidth+"px",o.style.height="0",o.addEventListener("transitionend",function t(){o.style.display="none",e.disabled=!1,e.style.textDecoration="",o.removeEventListener("transitionend",t)}),e.textContent="▶",e.dataset.buttonStatus="collapsed",e.ariaLabel=`Unminimize window "${s}"`}else{const i=n.querySelector("h1"),s=i.textContent;i.remove(),o.style.display="",o.style.height="0",t.style.width="",o.style.height=o.scrollHeight+"px",o.addEventListener("transitionend",function t(){o.style.height="",e.disabled=!1,e.style.textDecoration="",o.removeEventListener("transitionend",t)}),e.textContent="▼",e.dataset.buttonStatus="expanded",e.ariaLabel=`Minimize window "${s}"`}}_(e,t){let n,i=!1,o=0,s=null,a=0,r=0,l=0,m=0,c=null;if(e=document.querySelector(e),t=document.querySelector(t),!e||!t)return void this.A(`Can not drag! ${e?"":"moveMe"} ${e||t?"":"and "}${t?"":"iMoveThings "}was not found!`);const d=()=>{if(i){const t=Math.abs(a-l),n=Math.abs(r-m);(t>.5||n>.5)&&(a=l,r=m,e.style.transform=`translate(${a}px, ${r}px)`,e.style.left="0px",e.style.top="0px",e.style.right=""),s=requestAnimationFrame(d)}},u=(u,g)=>{i=!0,c=e.getBoundingClientRect(),n=u-c.left,o=g-c.top;const f=window.getComputedStyle(e).transform;if(f&&"none"!==f){const e=new DOMMatrix(f);a=e.m41,r=e.m42}else a=c.left,r=c.top;l=a,m=r,document.body.style.userSelect="none",t.classList.add("bm-_"),document.addEventListener("mousemove",b),document.addEventListener("touchmove",p,{passive:!1}),document.addEventListener("mouseup",h),document.addEventListener("touchend",h),document.addEventListener("touchcancel",h),s&&cancelAnimationFrame(s),d()},h=()=>{i=!1,s&&(cancelAnimationFrame(s),s=null),document.body.style.userSelect="",t.classList.remove("bm-_"),document.removeEventListener("mousemove",b),document.removeEventListener("touchmove",p),document.removeEventListener("mouseup",h),document.removeEventListener("touchend",h),document.removeEventListener("touchcancel",h)},b=e=>{i&&c&&(l=e.clientX-n,m=e.clientY-o)},p=e=>{if(i&&c){const t=e.touches[0];if(!t)return;l=t.clientX-n,m=t.clientY-o,e.preventDefault()}};t.addEventListener("mousedown",function(e){e.preventDefault(),u(e.clientX,e.clientY)}),t.addEventListener("touchstart",function(e){const t=e?.touches?.[0];t&&(u(t.clientX,t.clientY),e.preventDefault())},{passive:!1})}X(e){(0,console.info)(`${this.name}: ${e}`),this.L(this.i,"Status: "+e,!0)}A(e){(0,console.error)(`${this.name}: ${e}`),this.L(this.i,"Error: "+e,!0)}};function r(...e){(0,console.error)(...e)}function l(e,t){if(0===e)return t[0];let n="";const i=t.length;for(;e>0;)n=t[e%i]+n,e=Math.floor(e/i);return n}function m(e){let t="";for(let n=0;n0==t?e:e[0].toUpperCase()+e.slice(1)).join("")]=n;else if(t.startsWith("aria")){const i=t.slice(5).split("-").map((e,t)=>0==t?e:e[0].toUpperCase()+e.slice(1)).join("");e["aria"+i[0].toUpperCase()+i.slice(1)]=n}else e[t]=n};var d,u,h,b,p,g,f,w,y,v=[{id:0,premium:!1,name:"Transparent",rgb:[0,0,0]},{id:1,premium:!1,name:"Black",rgb:[0,0,0]},{id:2,premium:!1,name:"Dark Gray",rgb:[60,60,60]},{id:3,premium:!1,name:"Gray",rgb:[120,120,120]},{id:4,premium:!1,name:"Light Gray",rgb:[210,210,210]},{id:5,premium:!1,name:"White",rgb:[255,255,255]},{id:6,premium:!1,name:"Deep Red",rgb:[96,0,24]},{id:7,premium:!1,name:"Red",rgb:[237,28,36]},{id:8,premium:!1,name:"Orange",rgb:[255,127,39]},{id:9,premium:!1,name:"Gold",rgb:[246,170,9]},{id:10,premium:!1,name:"Yellow",rgb:[249,221,59]},{id:11,premium:!1,name:"Light Yellow",rgb:[255,250,188]},{id:12,premium:!1,name:"Dark Green",rgb:[14,185,104]},{id:13,premium:!1,name:"Green",rgb:[19,230,123]},{id:14,premium:!1,name:"Light Green",rgb:[135,255,94]},{id:15,premium:!1,name:"Dark Teal",rgb:[12,129,110]},{id:16,premium:!1,name:"Teal",rgb:[16,174,166]},{id:17,premium:!1,name:"Light Teal",rgb:[19,225,190]},{id:18,premium:!1,name:"Dark Blue",rgb:[40,80,158]},{id:19,premium:!1,name:"Blue",rgb:[64,147,228]},{id:20,premium:!1,name:"Cyan",rgb:[96,247,242]},{id:21,premium:!1,name:"Indigo",rgb:[107,80,246]},{id:22,premium:!1,name:"Light Indigo",rgb:[153,177,251]},{id:23,premium:!1,name:"Dark Purple",rgb:[120,12,153]},{id:24,premium:!1,name:"Purple",rgb:[170,56,185]},{id:25,premium:!1,name:"Light Purple",rgb:[224,159,249]},{id:26,premium:!1,name:"Dark Pink",rgb:[203,0,122]},{id:27,premium:!1,name:"Pink",rgb:[236,31,128]},{id:28,premium:!1,name:"Light Pink",rgb:[243,141,169]},{id:29,premium:!1,name:"Dark Brown",rgb:[104,70,52]},{id:30,premium:!1,name:"Brown",rgb:[149,104,42]},{id:31,premium:!1,name:"Beige",rgb:[248,178,119]},{id:32,premium:!0,name:"Medium Gray",rgb:[170,170,170]},{id:33,premium:!0,name:"Dark Red",rgb:[165,14,30]},{id:34,premium:!0,name:"Light Red",rgb:[250,128,114]},{id:35,premium:!0,name:"Dark Orange",rgb:[228,92,26]},{id:36,premium:!0,name:"Light Tan",rgb:[214,181,148]},{id:37,premium:!0,name:"Dark Goldenrod",rgb:[156,132,49]},{id:38,premium:!0,name:"Goldenrod",rgb:[197,173,49]},{id:39,premium:!0,name:"Light Goldenrod",rgb:[232,212,95]},{id:40,premium:!0,name:"Dark Olive",rgb:[74,107,58]},{id:41,premium:!0,name:"Olive",rgb:[90,148,74]},{id:42,premium:!0,name:"Light Olive",rgb:[132,197,115]},{id:43,premium:!0,name:"Dark Cyan",rgb:[15,121,159]},{id:44,premium:!0,name:"Light Cyan",rgb:[187,250,242]},{id:45,premium:!0,name:"Light Blue",rgb:[125,199,255]},{id:46,premium:!0,name:"Dark Indigo",rgb:[77,49,184]},{id:47,premium:!0,name:"Dark Slate Blue",rgb:[74,66,132]},{id:48,premium:!0,name:"Slate Blue",rgb:[122,113,196]},{id:49,premium:!0,name:"Light Slate Blue",rgb:[181,174,241]},{id:50,premium:!0,name:"Light Brown",rgb:[219,164,99]},{id:51,premium:!0,name:"Dark Beige",rgb:[209,128,81]},{id:52,premium:!0,name:"Light Beige",rgb:[255,197,165]},{id:53,premium:!0,name:"Dark Peach",rgb:[155,82,73]},{id:54,premium:!0,name:"Peach",rgb:[209,128,120]},{id:55,premium:!0,name:"Light Peach",rgb:[250,182,164]},{id:56,premium:!0,name:"Dark Tan",rgb:[123,99,82]},{id:57,premium:!0,name:"Tan",rgb:[156,132,107]},{id:58,premium:!0,name:"Dark Slate",rgb:[51,57,65]},{id:59,premium:!0,name:"Slate",rgb:[109,117,141]},{id:60,premium:!0,name:"Light Slate",rgb:[179,185,209]},{id:61,premium:!0,name:"Dark Stone",rgb:[109,100,63]},{id:62,premium:!0,name:"Stone",rgb:[148,140,107]},{id:63,premium:!0,name:"Light Stone",rgb:[205,197,158]}],x=class{constructor({displayName:e="My template",J:t=0,j:n="",url:i="",file:s=null,coords:a=null,R:r=null,Y:l={},F:m=1e3}={}){o(this,d),this.displayName=e,this.J=t,this.j=n,this.url=i,this.file=s,this.coords=a,this.R=r,this.Y=l,this.F=m,this.V={total:0,colors:new Map}}async H(e,t){console.log("Template coordinates:",this.coords);const n=await createImageBitmap(this.file),i=n.width,o=n.height;this.F=e;const a={},r={},l=new OffscreenCanvas(this.F,this.F),c=l.getContext("2d",{q:!0});l.width=i,l.height=o,c.imageSmoothingEnabled=!1,c.drawImage(n,0,0);let h=Date.now();const b=s(this,d,u).call(this,c.getImageData(0,0,i,o),t);console.log(`Calculating total pixels took ${(Date.now()-h)/1e3} seconds`);let p=0;for(const[e,t]of b)0!=e&&(p+=t);this.V={total:p,colors:b},h=Date.now();const g=new OffscreenCanvas(3,3),f=g.getContext("2d");f.clearRect(0,0,3,3),f.fillStyle="white",f.fillRect(1,1,1,1);for(let e=this.coords[3];e>>24==0?0:o.get(t)??-2;const a=s.get(i);s.set(i,a?a+1:1)}return console.log(s),s},h=new WeakSet,b=async function(){GM.setValue("bmTemplates",JSON.stringify(this.te))},p=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,i=t[e];if(console.log(`Template Key: ${n}`),t.hasOwnProperty(e)){const e=n.split(" "),t=Number(e?.[0]),o=e?.[1]||"0",s=i.name||`Template ${t||""}`,a={total:i.pixels.total,colors:new Map(Object.entries(i.pixels.colors).map(([e,t])=>[Number(e),t]))},r=i.tiles,l={},m={},d=this.F*this.ne;for(const e in r)if(console.log(e),r.hasOwnProperty(e)){const t=c(r[e]),n=new Blob([t],{type:"image/png"}),i=await createImageBitmap(n);l[e]=i;const o=new OffscreenCanvas(d,d).getContext("2d");o.drawImage(i,0,0);const s=o.getImageData(0,0,i.width,i.height);m[e]=new Uint32Array(s.data.buffer)}const u=new x({displayName:s,J:t||this.ie?.length||0,j:o||""});u.V=a,u.R=l,u.Y=m,this.ie.push(u),console.log(this.ie),console.log("^^^ This ^^^")}}},g=function(e,t,n){const i=this.ne,o=this.F*i,s=n[0],a=n[1],r=n[2],l=n[3],m=this.oe,{palette:c,ee:d}=this.se,u=new Map;for(let n=1;n>>24&255)<=m||(i>>>24&255)<=m)continue;const h=d.get(i)??-2,b=d.get(c)??-2;if(h!=b)continue;const p=u.get(b);u.set(b,p?p+1:1)}return console.log("List of template pixels that match the tile:"),console.log(u),u},f=new WeakSet,w=async function(e=navigator.userAgent){return(e=e||"").includes("OPR/")||e.includes("Opera")?"Opera":e.includes("Edg/")?"Edge":e.includes("Vivaldi")?"Vivaldi":e.includes("YaBrowser")?"Yandex":e.includes("Kiwi")?"Kiwi":e.includes("Brave")?"Brave":e.includes("Firefox/")?"Firefox":e.includes("Chrome/")?"Chrome":e.includes("Safari/")?"Safari":navigator.brave&&"function"==typeof navigator.brave.isBrave&&await navigator.brave.isBrave()?"Brave":"Unknown"},y=function(e=navigator.userAgent){return/Windows NT 11/i.test(e=e||"")?"Windows 11":/Windows NT 10/i.test(e)?"Windows 10":/Windows NT 6\.3/i.test(e)?"Windows 8.1":/Windows NT 6\.2/i.test(e)?"Windows 8":/Windows NT 6\.1/i.test(e)?"Windows 7":/Windows NT 6\.0/i.test(e)?"Windows Vista":/Windows NT 5\.1|Windows XP/i.test(e)?"Windows XP":/Mac OS X 10[_\.]15/i.test(e)?"macOS Catalina":/Mac OS X 10[_\.]14/i.test(e)?"macOS Mojave":/Mac OS X 10[_\.]13/i.test(e)?"macOS High Sierra":/Mac OS X 10[_\.]12/i.test(e)?"macOS Sierra":/Mac OS X 10[_\.]11/i.test(e)?"OS X El Capitan":/Mac OS X 10[_\.]10/i.test(e)?"OS X Yosemite":/Mac OS X 10[_\.]/i.test(e)?"macOS":/Android/i.test(e)?"Android":/iPhone|iPad|iPod/i.test(e)?"iOS":/Linux/i.test(e)?"Linux":"Unknown"};var S=GM_info.script.name.toString(),$=GM_info.script.version.toString();!function(e){const t=document.createElement("script");t.setAttribute("bm-E",S),t.setAttribute("bm-B","color: cornflowerblue;"),t.textContent=`(${e})();`,document.documentElement?.appendChild(t),t.remove()}(()=>{const e=document.currentScript,t=e?.getAttribute("bm-E")||"Blue Marble",n=e?.getAttribute("bm-B")||"",i=new Map;window.addEventListener("message",e=>{const{source:o,endpoint:s,blobID:a,blobData:r,blink:l}=e.data,m=Date.now()-l;if(console.groupCollapsed(`%c${t}%c: ${i.size} Recieved IMAGE message about blob "${a}"`,n,""),console.log(`Blob fetch took %c${String(Math.floor(m/6e4)).padStart(2,"0")}:${String(Math.floor(m/1e3)%60).padStart(2,"0")}.${String(m%1e3).padStart(3,"0")}%c MM:SS.mmm`,n,""),console.log(i),console.groupEnd(),"blue-marble"==o&&a&&r&&!s){const e=i.get(a);"function"==typeof e?e(r):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),i.delete(a)}});const o=window.fetch;window.fetch=async function(...e){const s=await o.apply(this,e),a=s.clone(),r=(e[0]instanceof Request?e[0]?.url:e[0])||"ignore",l=a.headers.get("content-type")||"";if(l.includes("application/json"))console.log(`%c${t}%c: Sending JSON message about endpoint "${r}"`,n,""),a.json().then(e=>{window.postMessage({source:"blue-marble",endpoint:r,jsonData:e},"*")}).catch(e=>{console.error(`%c${t}%c: Failed to parse JSON: `,n,"",e)});else if(l.includes("image/")&&!r.includes("openfreemap")&&!r.includes("maps")){const e=Date.now(),o=await a.blob();return console.log(`%c${t}%c: ${i.size} Sending IMAGE message about endpoint "${r}"`,n,""),new Promise(s=>{const l=crypto.randomUUID();i.set(l,e=>{s(new Response(e,{headers:a.headers,status:a.status,statusText:a.statusText})),console.log(`%c${t}%c: ${i.size} Processed blob "${l}"`,n,"")}),window.postMessage({source:"blue-marble",endpoint:r,blobID:l,blobData:o,blink:e})}).catch(o=>{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: ${r}\nThere are ${i.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:",o),console.groupEnd()})}return s}});var M=`.bm-16{position:fixed;background-color:#153063e6;color:#fff;padding:10px;border-radius:8px;z-index:9000;transition:all .3s ease,transform 0s;max-width:300px;width:auto;font-family:Roboto Mono,Courier New,Monaco,DejaVu Sans Mono,monospace,Arial;letter-spacing:.05em}.bm-14{display:flex;align-items:center;flex-wrap:nowrap;justify-content:space-between;gap:.5ch;background:url('data:image/svg+xml;utf8,') repeat;cursor:grab;width:100%;height:fit-content}.bm-14.bm-_{cursor:grabbing}.bm-16:has(.bm-14.bm-_){pointer-events:none;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}.bm-14.bm-_{pointer-events:auto}.bm-15{display:inline-block;height:2.5em;margin-right:1ch;vertical-align:middle}.bm-16 h1{display:inline-block;font-size:x-large;font-weight:700;vertical-align:middle}.bm-14 h1{font-size:1.2em;margin-left:.5ch;user-select:none;text-shadow:3px 0px rgba(21,48,99,.5),-3px 0px rgba(21,48,99,.5),0px 3px rgba(21,48,99,.5),0px -3px rgba(21,48,99,.5),3px 3px rgba(21,48,99,.5),-3px 3px rgba(21,48,99,.5),3px -3px rgba(21,48,99,.5),-3px -3px rgba(21,48,99,.5)}.bm--{margin:.5em 0}.bm-16 button{background-color:#144eb9;border-radius:1em;padding:0 .75ch}.bm-16 button:hover,.bm-16 button:focus-visible{background-color:#1061e5}.bm-16 button:active .bm-16 button:disabled{background-color:#2e97ff}.bm-16 button:disabled{text-decoration:line-through}.bm-T{border:white 1px solid;height:1.5em;width:1.5em;margin-top:2px;text-align:center;line-height:1em;padding:0!important}.bm-Y{vertical-align:middle}.bm-Y svg{width:50%;margin:0 auto;fill:#111}input[type=number].bm-U{appearance:auto;-moz-appearance:textfield;width:5.5ch;margin-left:1ch;background-color:#0003;padding:0 .5ch;font-size:small}input[type=number].bm-U::-webkit-outer-spin-button,input[type=number].bm-U::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}div:has(>.bm-Z)>button{width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.bm-Z,input[type=file]{display:none!important;visibility:hidden!important;position:absolute!important;left:-9999px!important;top:-9999px!important;width:0!important;height:0!important;opacity:0!important;z-index:-9999!important;pointer-events:none!important}.bm-O{overflow:hidden;transition:height .3s cubic-bezier(.4,0,.2,1)}.bm-16 textarea{font-size:small;background-color:#0003;padding:0 .5ch;height:5.25em;width:100%}.bm-16 small{font-size:x-small;color:#d3d3d3}.bm-V{display:flex;align-content:center;justify-content:space-between;align-items:center;gap:.5ch}.bm-flex-center{display:flex;align-content:center;justify-content:center;align-items:center;gap:.5ch}#bm-A,#bm-d{position:fixed;background-color:#153063e6;color:#fff;padding:10px;border-radius:8px;z-index:9000;transition:all .3s ease,transform 0s;max-width:300px;width:auto;will-change:transform;backface-visibility:hidden;-webkit-backface-visibility:hidden;transform-style:preserve-3d;-webkit-transform-style:preserve-3d}#bm-f,#bm-A hr,#bm-d hr,#bm-c,#bm-6{transition:opacity .2s ease,height .2s ease}div#bm-A,div#bm-d{font-family:Roboto Mono,Courier New,Monaco,DejaVu Sans Mono,monospace,Arial;letter-spacing:.05em}#bm-z,#bm-z-telemetry{margin-bottom:.5em;background:url('data:image/svg+xml;utf8,') repeat;cursor:grab;width:100%;height:1em}#bm-z.dragging,#bm-z-telemetry.dragging{cursor:grabbing}#bm-A:has(#bm-z.dragging),#bm-d:has(#bm-z-telemetry.dragging){pointer-events:none;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}#bm-z.dragging,#bm-z-telemetry.dragging{pointer-events:auto}#bm-j,#bm-1{margin-bottom:.5em}#bm-j[style*="text-align: center"],#bm-1[style*="text-align: center"]{display:flex;flex-direction:column;align-items:center;justify-content:center}#bm-A[style*="padding: 5px"],#bm-d[style*="padding: 5px"]{width:auto!important;max-width:300px;min-width:200px}#bm-A img{display:inline-block;height:2.5em;margin-right:1ch;vertical-align:middle;transition:opacity .2s ease}#bm-j[style*="text-align: center"] img{display:block;margin:0 auto}#bm-z,#bm-z-telemetry{transition:margin-bottom .2s ease}#bm-A h1,#bm-d h1{display:inline-block;font-size:x-large;font-weight:700;vertical-align:middle}#bm-c input[type=checkbox]{vertical-align:middle;margin-right:.5ch}#bm-c label{margin-right:.5ch}.bm-D{border:white 1px solid;height:1.5em;width:1.5em;margin-top:2px;text-align:center;line-height:1em;padding:0!important}#bm-q{vertical-align:middle}#bm-q svg{width:50%;margin:0 auto;fill:#111}#bm-f{margin-bottom:.5em}div:has(>#bm-button-teleport){display:flex;gap:.5ch}#bm-button-favorite svg,#bm-button-template svg{height:1em;margin:2px auto 0;text-align:center;line-height:1em;vertical-align:bottom}#bm-k input[type=number]{appearance:auto;-moz-appearance:textfield;width:5.5ch;margin-left:1ch;background-color:#0003;padding:0 .5ch;font-size:small}#bm-k input[type=number]::-webkit-outer-spin-button,#bm-k input[type=number]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}#bm-4{display:flex;flex-direction:row;flex-wrap:wrap;align-content:center;justify-content:center;align-items:center;gap:1ch}div:has(>#bm-a)>button{width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}#bm-a,input[type=file][id*=template]{display:none!important;visibility:hidden!important;position:absolute!important;left:-9999px!important;top:-9999px!important;width:0!important;height:0!important;opacity:0!important;z-index:-9999!important;pointer-events:none!important}#bm-o{font-size:small;background-color:#0003;padding:0 .5ch;height:3.75em;width:100%}#bm-6{display:flex;justify-content:space-between}div#bm-6 button#bm-D{margin-right:2px}#bm-A small{font-size:x-small;color:#d3d3d3}#bm-f,#bm-c,#bm-k,#bm-4,div:has(>#bm-a),#bm-o{margin-top:.5em}#bm-A button,#bm-d button{background-color:#144eb9;border-radius:1em;padding:0 .75ch}#bm-A button:hover,#bm-A button:focus-visible,#bm-d button:hover,#bm-d button:focus-visible{background-color:#1061e5}#bm-A button:active,#bm-d button:active #bm-A button:disabled,#bm-d button:disabled{background-color:#2e97ff}#bm-A button:disabled,#bm-d button:disabled{text-decoration:line-through}`;GM_addStyle(M);var T,D="@font-face{font-family:'Roboto Mono';font-style:normal;font-weight:400;src:url(data:font/woff2;base64,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)format('woff2');}";D.indexOf("@font-face")+1?(console.log("Loading Roboto Mono as a file..."),GM_addStyle(D)):((T=document.createElement("link")).href="https://fonts.googleapis.com/css2?family=Roboto+Mono:ital,wght@0,100..700;1,100..700&display=swap",T.rel="preload",T.as="style",T.onload=function(){this.onload=null,this.rel="stylesheet"},document.head?.appendChild(T)),new class{constructor(){this.ae=null,this.re=null,this.le="#bm-h"}me(e){return this.re=e,this.ae=new MutationObserver(e=>{for(const t of e)for(const e of t.addedNodes)e instanceof HTMLElement&&e.matches?.(this.le)}),this}ce(){return this.ae}observe(e,t=!1,n=!1){e.observe(this.re,{childList:t,subtree:n})}};var O=new a(S,$),k=(new a(S,$),new class{constructor(e,t,n){o(this,h),this.name=e,this.version=t,this.o=n,this.de="1.0.0",this.ue=null,this.he="!#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",this.F=1e3,this.ne=3,this.oe=3,this.se=function(e){const t=v;t.unshift({id:-1,premium:!1,name:"Erased",rgb:[222,250,206]}),t.unshift({id:-2,premium:!1,name:"Other",rgb:[0,0,0]});const n=new Map;for(const i of t){if(0==i.id||-2==i.id)continue;const t=i.rgb[0],o=i.rgb[1],s=i.rgb[2];for(let a=-e;a<=e;a++)for(let r=-e;r<=e;r++)for(let l=-e;l<=e;l++){const e=t+a,m=o+r,c=s+l;if(e<0||e>255||m<0||m>255||c<0||c>255)continue;const d=(255<<24|c<<16|m<<8|e)>>>0;n.has(d)||n.set(d,i.id)}}return{palette:t,ee:n}}(this.oe),this.be=null,this.pe="",this.ie=[],this.te=null,this.ge=!0,this.fe=null}async we(){return{whoami:this.name.replace(" ",""),scriptVersion:this.version,schemaVersion:this.de,templates:{}}}async ye(e,t,n){this.te||(this.te=await this.we(),console.log("Creating JSON...")),this.o.X(`Creating template at ${n.join(", ")}...`);const i=new x({displayName:t,J:0,j:l(this.ue||0,this.he),file:e,coords:n}),{K:o,Z:a}=await i.H(this.F,this.se);i.R=o;const r={total:i.V.total,colors:Object.fromEntries(i.V.colors)};this.te.templates[`${i.J} ${i.j}`]={name:i.displayName,coords:n.join(", "),enabled:!0,pixels:r,tiles:a},this.ie=[],this.ie.push(i),this.o.X(`Template created at ${n.join(", ")}!`),console.log(Object.keys(this.te.templates).length),console.log(this.te),console.log(this.ie),console.log(JSON.stringify(this.te)),await s(this,h,b).call(this)}ve(){}async xe(){this.te||(this.te=await this.we(),console.log("Creating JSON..."))}async Se(e,t){if(!this.ge)return e;const n=this.F*this.ne;t=t[0].toString().padStart(4,"0")+","+t[1].toString().padStart(4,"0"),console.log(`Searching for templates in tile: "${t}"`);const i=this.ie;console.log(i),i.sort((e,t)=>e.J-t.J),console.log(i);const o=i.map(e=>{const n=Object.keys(e.R).filter(e=>e.startsWith(t));if(0===n.length)return null;const i=n.map(t=>{const n=t.split(",");return{$e:e,Me:e.R[t],Y:e.Y?.[t],Te:[n[0],n[1]],De:[n[2],n[3]]}});return i?.[0]}).filter(Boolean);console.log(o);const a=o?.length||0;if(console.log(`templateCount = ${a}`),!(a>0))return this.o.X(`Sleeping\nVersion: ${this.version}`),e;{const e=i.filter(e=>Object.keys(e.R).filter(e=>e.startsWith(t)).length>0).reduce((e,t)=>e+(t.V.total||0),0),n=(new Intl.NumberFormat).format(e);this.o.X(`Displaying ${a} template${1==a?"":"s"}.\nTotal pixels: ${n}`)}const r=await createImageBitmap(e),l=new OffscreenCanvas(n,n),m=l.getContext("2d");m.imageSmoothingEnabled=!1,m.beginPath(),m.rect(0,0,n,n),m.clip(),m.clearRect(0,0,n,n),m.drawImage(r,0,0,n,n);const c=m.getImageData(0,0,n,n),d=new Uint32Array(c.data.buffer);for(const e of o){console.log("Template:"),console.log(e);let n=e.Y;const i=Number(e.De[0])*this.ne,o=Number(e.De[1])*this.ne;if(m.drawImage(e.Me,i,o),!n){const t=m.getImageData(i,o,e.Me.width,e.Me.height);n=new Uint32Array(t.data.buffer)}const a=Date.now(),r=s(this,h,g).call(this,d,n,[i,o,e.Me.width,e.Me.height]);let l=0;const c=0;for(const[e,t]of r)e!=c&&(l+=t);console.log(`Finished calculating correct pixels for the tile ${t} in ${(Date.now()-a)/1e3} seconds!\nThere are ${l} correct pixels.`),e.$e.V.correct=r}return await l.convertToBlob({type:"image/png"})}Oe(e){console.log("Importing JSON..."),console.log(e),"BlueMarble"==e?.whoami&&s(this,h,p).call(this,e)}ke(e){this.ge=e}}(S,$,O)),C=new class{constructor(e){o(this,f),this.Ce=e,this.Ne=!1,this.Be=[],this.Ie=[]}Le(e){window.addEventListener("message",async t=>{const n=t.data,i=n.jsonData;if(!n||"blue-marble"!==n.source)return;if(!n.endpoint)return;const o=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;","",o),o){case"me":if(i.status&&"2"!=i.status?.toString()[0])return void e.A("You are not logged in!\nCould not fetch userdata.");const t=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(l(i.id,"!#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~")),this.Ce.ue=i.id,e.L("bm-p",`Droplets: ${(new Intl.NumberFormat).format(i.droplets)}`),e.L("bm-i",`Next level in ${(new Intl.NumberFormat).format(t)} pixel${1==t?"":"s"}`);break;case"pixel":const o=n.endpoint.split("?")[0].split("/").filter(e=>e&&!isNaN(Number(e))),r=new URLSearchParams(n.endpoint.split("?")[1]),m=[r.get("x"),r.get("y")];if(this.Be.length&&(!o.length||!m.length))return void e.A("Coordinates are malformed!\nDid you try clicking the canvas first?");this.Be=[...o,...m];const c=(s=o,a=m,[parseInt(s[0])%4*1e3+parseInt(a[0]),parseInt(s[1])%4*1e3+parseInt(a[1])]),d=document.querySelectorAll("span");for(const e of d)if(e.textContent.trim().includes(`${c[0]}, ${c[1]}`)){let t=document.querySelector("#bm-h");const n=`(Tl X: ${o[0]}, Tl Y: ${o[1]}, Px X: ${m[0]}, Px Y: ${m[1]})`;t?t.textContent=n:(t=document.createElement("span"),t.id="bm-h",t.textContent=n,t.style="margin-left: calc(var(--spacing)*3); font-size: small;",e.parentNode.parentNode.insertAdjacentElement("afterend",t))}break;case"tiles":let u=n.endpoint.split("/");u=[parseInt(u[u.length-2]),parseInt(u[u.length-1].replace(".png",""))];const h=n.blobID,b=n.blobData,p=Date.now(),g=await this.Ce.Se(b,u);console.log(`Finished loading the tile in ${(Date.now()-p)/1e3} seconds!`),window.postMessage({source:"blue-marble",blobID:h,blobData:g,blink:n.blink});break;case"robots":this.Ne="false"==i.userscript?.toString().toLowerCase();break}var s,a})}async Pe(e){console.log("Sending heartbeat to telemetry server...");let t=GM_getValue("bmUserSettings","{}");if(t=JSON.parse(t),!t||!t.telemetry||!t.uuid)return void console.log("Telemetry is disabled, not sending heartbeat.");const n=navigator.userAgent;let i=await s(this,f,w).call(this,n),o=s(this,f,y).call(this,n);GM_xmlhttpRequest({method:"POST",url:"https://telemetry.thebluecorner.net/heartbeat",headers:{"Content-Type":"application/json"},data:JSON.stringify({uuid:t.uuid,version:e,browser:i,os:o}),onload:e=>{200!==e.status&&r("Failed to send heartbeat:",e.statusText)},onerror:e=>{r("Error sending heartbeat:",e)}})}}(k);O.u(C);var N=JSON.parse(GM_getValue("bmTemplates","{}"));console.log(N),k.Oe(N);var B=JSON.parse(GM_getValue("bmUserSettings","{}"));if(console.log(B),console.log(Object.keys(B).length),0==Object.keys(B).length){const e=crypto.randomUUID();console.log(e),GM.setValue("bmUserSettings",JSON.stringify({uuid:e}))}if(setInterval(()=>C.Pe($),18e5),console.log(`Telemetry is ${!(null==B?.telemetry)}`),null==B?.telemetry||B?.telemetry>1){const e=new a(S,$);e.u(C),e.v({id:"bm-d",style:"top: 0px; left: 0px; width: 100vw; max-width: 100vw; height: 100vh; max-height: 100vh; z-index: 9999;"}).v({id:"bm-7",style:"display: flex; flex-direction: column; align-items: center;"}).v({id:"bm-1",style:"margin-top: 10%;"}).O(1,{textContent:`${S} Telemetry`}).h().h().v({id:"bm-e",style:"max-width: 50%; overflow-y: auto; max-height: 80vh;"}).k().h().C().h().v({style:"width: fit-content; margin: auto; text-align: center;"}).B({id:"bm-8",textContent:"More Information"},(e,t)=>{t.onclick=()=>{window.open("https://github.com/SwingTheVine/Wplace-TelemetryServer#telemetry-data","_blank","noopener noreferrer")}}).h().h().C().h().v({style:"width: fit-content; margin: auto; text-align: center;"}).B({id:"bm-5",textContent:"Enable Telemetry",style:"margin-right: 2ch;"},(e,t)=>{t.onclick=()=>{const e=JSON.parse(GM_getValue("bmUserSettings","{}"));e.telemetry=1,GM.setValue("bmUserSettings",JSON.stringify(e));const t=document.getElementById("bm-d");t&&(t.style.display="none")}}).h().B({id:"bm-2",textContent:"Disable Telemetry"},(e,t)=>{t.onclick=()=>{const e=JSON.parse(GM_getValue("bmUserSettings","{}"));e.telemetry=0,GM.setValue("bmUserSettings",JSON.stringify(e));const t=document.getElementById("bm-d");t&&(t.style.display="none")}}).h().h().C().h().S({textContent:"We collect anonymous telemetry data such as your browser, OS, and script version to make the experience better for everyone. The data is never shared personally. The data is never sold. You can turn this off by pressing the 'Disable' button, but keeping it on helps us improve features and reliability faster. Thank you for supporting the Blue Marble!"}).h().S({textContent:'You can disable telemetry by pressing the "Disable" button below.'}).h().h().h().p(document.body)}O.v({id:"bm-W",class:"bm-16",style:"top: 10px; right: 75px;"}).v({class:"bm-14"}).v().B({class:"bm-T",textContent:"▼","aria-label":'Minimize window "Blue Marble"',"data-button-status":"expanded"},(e,t)=>{t.onclick=()=>e.U(t)}).h().h().h().v({class:"bm-O"}).v({class:"bm--"}).D({class:"bm-15",src:"data:image/png;base64,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"}).h().O(1,{textContent:S}).h().h().k().h().v({class:"bm--"}).S({id:"bm-p",textContent:"Droplets:"}).h().S({id:"bm-i",textContent:"Next level in..."}).h().h().k().h().v({class:"bm--"}).v({class:"bm--"}).B({class:"bm-T bm-Y",style:"margin-top: 0;",innerHTML:''},(e,t)=>{t.onclick=()=>{const t=e.t?.Be;t?.[0]?(e.L("bm-v",t?.[0]||""),e.L("bm-w",t?.[1]||""),e.L("bm-x",t?.[2]||""),e.L("bm-y",t?.[3]||"")):e.A("Coordinates are malformed! Did you try clicking on the canvas first?")}}).h().P({type:"number",id:"bm-v",class:"bm-U",placeholder:"Tl X",min:0,max:2047,step:1,required:!0},(e,t)=>{t.addEventListener("paste",e=>{let t=(e.clipboardData||window.clipboardData).getData("text").split(" ").filter(e=>e).map(Number).filter(e=>!isNaN(e));if(4!==t.length)return;let n=selectAllCoordinateInputs(document);for(let e=0;e{t.onclick=()=>{t.disabled=!0,"shown"==t.dataset.buttonStatus?(e.t?.Ce?.ke(!1),t.dataset.buttonStatus="hidden",t.textContent="Enable",e.X("Disabled templates!")):(e.t?.Ce?.ke(!0),t.dataset.buttonStatus="shown",t.textContent="Disable",e.X("Enabled templates!")),t.disabled=!1}}).h().B({textContent:"Create"},(e,t)=>{t.onclick=()=>{const t=document.querySelector("#bm-W button.bm-Z"),n=document.querySelector("#bm-v");if(!n.checkValidity())return n.reportValidity(),void e.A("Coordinates are malformed! Did you try clicking on the canvas first?");const i=document.querySelector("#bm-w");if(!i.checkValidity())return i.reportValidity(),void e.A("Coordinates are malformed! Did you try clicking on the canvas first?");const o=document.querySelector("#bm-x");if(!o.checkValidity())return o.reportValidity(),void e.A("Coordinates are malformed! Did you try clicking on the canvas first?");const s=document.querySelector("#bm-y");if(!s.checkValidity())return s.reportValidity(),void e.A("Coordinates are malformed! Did you try clicking on the canvas first?");t?.files[0]?(k.ye(t.files[0],t.files[0]?.name.replace(/\.[^/.]+$/,""),[Number(n.value),Number(i.value),Number(o.value),Number(s.value)]),e.X("Drew to canvas!")):e.A("No file selected!")}}).h().B({textContent:"Filter"},(e,t)=>{t.onclick=()=>{}}).h().h().v({class:"bm--"}).W({id:O.i,placeholder:`Status: Sleeping...\nVersion: ${$}`,readOnly:!0}).h().h().v({class:"bm-- bm-V",style:"margin-bottom: 0;"}).v({class:"bm-V"}).B({class:"bm-T",innerHTML:"🎨",title:"Template Color Converter"},(e,t)=>{t.onclick=()=>{window.open("https://pepoafonso.github.io/color_converter_wplace/","_blank","noopener noreferrer")}}).h().B({class:"bm-T",innerHTML:"🌐",title:"Official Blue Marble Website"},(e,t)=>{t.onclick=()=>{window.open("https://bluemarble.lol/","_blank","noopener noreferrer")}}).h().h().$({textContent:"Made by SwingTheVine",style:"margin-top: auto;"}).h().h().h().h().h().p(document.body),O._("#bm-W.bm-16","#bm-W .bm-14"),C.Le(O),new MutationObserver((e,t)=>{const n=document.querySelector("#color-1");if(!n)return;let i=document.querySelector("#bm-t");if(!i){i=document.createElement("button"),i.id="bm-t",i.textContent="Move ↑",i.className="btn btn-soft",i.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(i)}}).observe(document.body,{childList:!0,subtree:!0}),function(...e){(0,console.log)(...e)}(`%c${S}%c (${$}) userscript has loaded!`,"color: cornflowerblue;","")})();
\ No newline at end of file
diff --git a/dist/BlueMarble.user.css b/dist/BlueMarble.user.css
index 114fa4d..271836c 100644
--- a/dist/BlueMarble.user.css
+++ b/dist/BlueMarble.user.css
@@ -1 +1 @@
-.bm-17{position:fixed;background-color:#153063e6;color:#fff;padding:10px;border-radius:8px;z-index:9000;transition:all .3s ease,transform 0s;max-width:300px;width:auto;font-family:Roboto Mono,Courier New,Monaco,DejaVu Sans Mono,monospace,Arial;letter-spacing:.05em}.bm-14{display:flex;align-items:center;flex-wrap:nowrap;justify-content:space-between;gap:.5ch;background:url('data:image/svg+xml;utf8,') repeat;cursor:grab;width:100%;height:fit-content}.bm-14.bm-_{cursor:grabbing}.bm-17:has(.bm-14.bm-_){pointer-events:none;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}.bm-14.bm-_{pointer-events:auto}.bm-15{display:inline-block;height:2.5em;margin-right:1ch;vertical-align:middle}.bm-17 h1{display:inline-block;font-size:x-large;font-weight:700;vertical-align:middle}.bm-14 h1{font-size:1.2em;margin-left:.5ch;user-select:none;text-shadow:3px 0px rgba(21,48,99,.5),-3px 0px rgba(21,48,99,.5),0px 3px rgba(21,48,99,.5),0px -3px rgba(21,48,99,.5),3px 3px rgba(21,48,99,.5),-3px 3px rgba(21,48,99,.5),3px -3px rgba(21,48,99,.5),-3px -3px rgba(21,48,99,.5)}.bm--{margin:.5em 0}.bm-17 button{background-color:#144eb9;border-radius:1em;padding:0 .75ch}.bm-17 button:hover,.bm-17 button:focus-visible{background-color:#1061e5}.bm-17 button:active .bm-17 button:disabled{background-color:#2e97ff}.bm-17 button:disabled{text-decoration:line-through}.bm-T{border:white 1px solid;height:1.5em;width:1.5em;margin-top:2px;text-align:center;line-height:1em;padding:0!important}.bm-Y{vertical-align:middle}.bm-Y svg{width:50%;margin:0 auto;fill:#111}input[type=number].bm-U{appearance:auto;-moz-appearance:textfield;width:5.5ch;margin-left:1ch;background-color:#0003;padding:0 .5ch;font-size:small}input[type=number].bm-U::-webkit-outer-spin-button,input[type=number].bm-U::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}div:has(>.bm-Z)>button{width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.bm-Z,input[type=file]{display:none!important;visibility:hidden!important;position:absolute!important;left:-9999px!important;top:-9999px!important;width:0!important;height:0!important;opacity:0!important;z-index:-9999!important;pointer-events:none!important}.bm-Q{overflow:hidden;transition:height .3s cubic-bezier(.4,0,.2,1)}.bm-17 textarea{font-size:small;background-color:#0003;padding:0 .5ch;height:5.25em;width:100%}.bm-17 small{font-size:x-small;color:#d3d3d3}.bm-V{display:flex;align-content:center;justify-content:space-between;align-items:center;gap:.5ch}.bm-flex-center{display:flex;align-content:center;justify-content:center;align-items:center;gap:.5ch}#bm-A,#bm-d{position:fixed;background-color:#153063e6;color:#fff;padding:10px;border-radius:8px;z-index:9000;transition:all .3s ease,transform 0s;max-width:300px;width:auto;will-change:transform;backface-visibility:hidden;-webkit-backface-visibility:hidden;transform-style:preserve-3d;-webkit-transform-style:preserve-3d}#bm-f,#bm-A hr,#bm-d hr,#bm-c,#bm-6{transition:opacity .2s ease,height .2s ease}div#bm-A,div#bm-d{font-family:Roboto Mono,Courier New,Monaco,DejaVu Sans Mono,monospace,Arial;letter-spacing:.05em}#bm-z,#bm-z-telemetry{margin-bottom:.5em;background:url('data:image/svg+xml;utf8,') repeat;cursor:grab;width:100%;height:1em}#bm-z.dragging,#bm-z-telemetry.dragging{cursor:grabbing}#bm-A:has(#bm-z.dragging),#bm-d:has(#bm-z-telemetry.dragging){pointer-events:none;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}#bm-z.dragging,#bm-z-telemetry.dragging{pointer-events:auto}#bm-j,#bm-1{margin-bottom:.5em}#bm-j[style*="text-align: center"],#bm-1[style*="text-align: center"]{display:flex;flex-direction:column;align-items:center;justify-content:center}#bm-A[style*="padding: 5px"],#bm-d[style*="padding: 5px"]{width:auto!important;max-width:300px;min-width:200px}#bm-A img{display:inline-block;height:2.5em;margin-right:1ch;vertical-align:middle;transition:opacity .2s ease}#bm-j[style*="text-align: center"] img{display:block;margin:0 auto}#bm-z,#bm-z-telemetry{transition:margin-bottom .2s ease}#bm-A h1,#bm-d h1{display:inline-block;font-size:x-large;font-weight:700;vertical-align:middle}#bm-c input[type=checkbox]{vertical-align:middle;margin-right:.5ch}#bm-c label{margin-right:.5ch}.bm-D{border:white 1px solid;height:1.5em;width:1.5em;margin-top:2px;text-align:center;line-height:1em;padding:0!important}#bm-q{vertical-align:middle}#bm-q svg{width:50%;margin:0 auto;fill:#111}#bm-f{margin-bottom:.5em}div:has(>#bm-button-teleport){display:flex;gap:.5ch}#bm-button-favorite svg,#bm-button-template svg{height:1em;margin:2px auto 0;text-align:center;line-height:1em;vertical-align:bottom}#bm-k input[type=number]{appearance:auto;-moz-appearance:textfield;width:5.5ch;margin-left:1ch;background-color:#0003;padding:0 .5ch;font-size:small}#bm-k input[type=number]::-webkit-outer-spin-button,#bm-k input[type=number]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}#bm-4{display:flex;flex-direction:row;flex-wrap:wrap;align-content:center;justify-content:center;align-items:center;gap:1ch}div:has(>#bm-a)>button{width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}#bm-a,input[type=file][id*=template]{display:none!important;visibility:hidden!important;position:absolute!important;left:-9999px!important;top:-9999px!important;width:0!important;height:0!important;opacity:0!important;z-index:-9999!important;pointer-events:none!important}#bm-o{font-size:small;background-color:#0003;padding:0 .5ch;height:3.75em;width:100%}#bm-6{display:flex;justify-content:space-between}div#bm-6 button#bm-D{margin-right:2px}#bm-A small{font-size:x-small;color:#d3d3d3}#bm-f,#bm-c,#bm-k,#bm-4,div:has(>#bm-a),#bm-o{margin-top:.5em}#bm-A button,#bm-d button{background-color:#144eb9;border-radius:1em;padding:0 .75ch}#bm-A button:hover,#bm-A button:focus-visible,#bm-d button:hover,#bm-d button:focus-visible{background-color:#1061e5}#bm-A button:active,#bm-d button:active #bm-A button:disabled,#bm-d button:disabled{background-color:#2e97ff}#bm-A button:disabled,#bm-d button:disabled{text-decoration:line-through}
+.bm-16{position:fixed;background-color:#153063e6;color:#fff;padding:10px;border-radius:8px;z-index:9000;transition:all .3s ease,transform 0s;max-width:300px;width:auto;font-family:Roboto Mono,Courier New,Monaco,DejaVu Sans Mono,monospace,Arial;letter-spacing:.05em}.bm-14{display:flex;align-items:center;flex-wrap:nowrap;justify-content:space-between;gap:.5ch;background:url('data:image/svg+xml;utf8,') repeat;cursor:grab;width:100%;height:fit-content}.bm-14.bm-_{cursor:grabbing}.bm-16:has(.bm-14.bm-_){pointer-events:none;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}.bm-14.bm-_{pointer-events:auto}.bm-15{display:inline-block;height:2.5em;margin-right:1ch;vertical-align:middle}.bm-16 h1{display:inline-block;font-size:x-large;font-weight:700;vertical-align:middle}.bm-14 h1{font-size:1.2em;margin-left:.5ch;user-select:none;text-shadow:3px 0px rgba(21,48,99,.5),-3px 0px rgba(21,48,99,.5),0px 3px rgba(21,48,99,.5),0px -3px rgba(21,48,99,.5),3px 3px rgba(21,48,99,.5),-3px 3px rgba(21,48,99,.5),3px -3px rgba(21,48,99,.5),-3px -3px rgba(21,48,99,.5)}.bm--{margin:.5em 0}.bm-16 button{background-color:#144eb9;border-radius:1em;padding:0 .75ch}.bm-16 button:hover,.bm-16 button:focus-visible{background-color:#1061e5}.bm-16 button:active .bm-16 button:disabled{background-color:#2e97ff}.bm-16 button:disabled{text-decoration:line-through}.bm-T{border:white 1px solid;height:1.5em;width:1.5em;margin-top:2px;text-align:center;line-height:1em;padding:0!important}.bm-Y{vertical-align:middle}.bm-Y svg{width:50%;margin:0 auto;fill:#111}input[type=number].bm-U{appearance:auto;-moz-appearance:textfield;width:5.5ch;margin-left:1ch;background-color:#0003;padding:0 .5ch;font-size:small}input[type=number].bm-U::-webkit-outer-spin-button,input[type=number].bm-U::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}div:has(>.bm-Z)>button{width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.bm-Z,input[type=file]{display:none!important;visibility:hidden!important;position:absolute!important;left:-9999px!important;top:-9999px!important;width:0!important;height:0!important;opacity:0!important;z-index:-9999!important;pointer-events:none!important}.bm-O{overflow:hidden;transition:height .3s cubic-bezier(.4,0,.2,1)}.bm-16 textarea{font-size:small;background-color:#0003;padding:0 .5ch;height:5.25em;width:100%}.bm-16 small{font-size:x-small;color:#d3d3d3}.bm-V{display:flex;align-content:center;justify-content:space-between;align-items:center;gap:.5ch}.bm-flex-center{display:flex;align-content:center;justify-content:center;align-items:center;gap:.5ch}#bm-A,#bm-d{position:fixed;background-color:#153063e6;color:#fff;padding:10px;border-radius:8px;z-index:9000;transition:all .3s ease,transform 0s;max-width:300px;width:auto;will-change:transform;backface-visibility:hidden;-webkit-backface-visibility:hidden;transform-style:preserve-3d;-webkit-transform-style:preserve-3d}#bm-f,#bm-A hr,#bm-d hr,#bm-c,#bm-6{transition:opacity .2s ease,height .2s ease}div#bm-A,div#bm-d{font-family:Roboto Mono,Courier New,Monaco,DejaVu Sans Mono,monospace,Arial;letter-spacing:.05em}#bm-z,#bm-z-telemetry{margin-bottom:.5em;background:url('data:image/svg+xml;utf8,') repeat;cursor:grab;width:100%;height:1em}#bm-z.dragging,#bm-z-telemetry.dragging{cursor:grabbing}#bm-A:has(#bm-z.dragging),#bm-d:has(#bm-z-telemetry.dragging){pointer-events:none;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}#bm-z.dragging,#bm-z-telemetry.dragging{pointer-events:auto}#bm-j,#bm-1{margin-bottom:.5em}#bm-j[style*="text-align: center"],#bm-1[style*="text-align: center"]{display:flex;flex-direction:column;align-items:center;justify-content:center}#bm-A[style*="padding: 5px"],#bm-d[style*="padding: 5px"]{width:auto!important;max-width:300px;min-width:200px}#bm-A img{display:inline-block;height:2.5em;margin-right:1ch;vertical-align:middle;transition:opacity .2s ease}#bm-j[style*="text-align: center"] img{display:block;margin:0 auto}#bm-z,#bm-z-telemetry{transition:margin-bottom .2s ease}#bm-A h1,#bm-d h1{display:inline-block;font-size:x-large;font-weight:700;vertical-align:middle}#bm-c input[type=checkbox]{vertical-align:middle;margin-right:.5ch}#bm-c label{margin-right:.5ch}.bm-D{border:white 1px solid;height:1.5em;width:1.5em;margin-top:2px;text-align:center;line-height:1em;padding:0!important}#bm-q{vertical-align:middle}#bm-q svg{width:50%;margin:0 auto;fill:#111}#bm-f{margin-bottom:.5em}div:has(>#bm-button-teleport){display:flex;gap:.5ch}#bm-button-favorite svg,#bm-button-template svg{height:1em;margin:2px auto 0;text-align:center;line-height:1em;vertical-align:bottom}#bm-k input[type=number]{appearance:auto;-moz-appearance:textfield;width:5.5ch;margin-left:1ch;background-color:#0003;padding:0 .5ch;font-size:small}#bm-k input[type=number]::-webkit-outer-spin-button,#bm-k input[type=number]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}#bm-4{display:flex;flex-direction:row;flex-wrap:wrap;align-content:center;justify-content:center;align-items:center;gap:1ch}div:has(>#bm-a)>button{width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}#bm-a,input[type=file][id*=template]{display:none!important;visibility:hidden!important;position:absolute!important;left:-9999px!important;top:-9999px!important;width:0!important;height:0!important;opacity:0!important;z-index:-9999!important;pointer-events:none!important}#bm-o{font-size:small;background-color:#0003;padding:0 .5ch;height:3.75em;width:100%}#bm-6{display:flex;justify-content:space-between}div#bm-6 button#bm-D{margin-right:2px}#bm-A small{font-size:x-small;color:#d3d3d3}#bm-f,#bm-c,#bm-k,#bm-4,div:has(>#bm-a),#bm-o{margin-top:.5em}#bm-A button,#bm-d button{background-color:#144eb9;border-radius:1em;padding:0 .75ch}#bm-A button:hover,#bm-A button:focus-visible,#bm-d button:hover,#bm-d button:focus-visible{background-color:#1061e5}#bm-A button:active,#bm-d button:active #bm-A button:disabled,#bm-d button:disabled{background-color:#2e97ff}#bm-A button:disabled,#bm-d button:disabled{text-decoration:line-through}
diff --git a/dist/BlueMarble.user.js b/dist/BlueMarble.user.js
index 20bcdcc..b2e9857 100644
--- a/dist/BlueMarble.user.js
+++ b/dist/BlueMarble.user.js
@@ -2,7 +2,7 @@
// @name Blue Marble
// @name:en Blue Marble
// @namespace https://github.com/SwingTheVine/
-// @version 0.88.133
+// @version 0.88.144
// @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.
// @description:en 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
@@ -28,4 +28,4 @@
// License --> https://www.mozilla.org/en-US/MPL/2.0/
// Donate --> https://ko-fi.com/swingthevine
-(()=>{var e,t,n=e=>{throw TypeError(e)},i=(e,t,i)=>t.has(e)?n("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(e):t.set(e,i),o=(e,t,i)=>(((e,t)=>{t.has(e)||n("Cannot access private method")})(e,t),i),s=class{constructor(t,n){i(this,e),this.name=t,this.version=n,this.t=null,this.i="bm-o",this.o=null,this.l=null,this.m=[]}u(e){this.t=e}h(){return this.m.length>0&&(this.l=this.m.pop()),this}p(e){e?.appendChild(this.o),this.o=null,this.l=null,this.m=[]}v(n={},i=()=>{}){return i(this,o(this,e,t).call(this,"div",{},n)),this}S(n={},i=()=>{}){return i(this,o(this,e,t).call(this,"p",{},n)),this}$(n={},i=()=>{}){return i(this,o(this,e,t).call(this,"small",{},n)),this}M(n={},i=()=>{}){return i(this,o(this,e,t).call(this,"details",{},n)),this}T(n={},i=()=>{}){return i(this,o(this,e,t).call(this,"summary",{},n)),this}D(n={},i=()=>{}){return i(this,o(this,e,t).call(this,"img",{},n)),this}O(n,i={},s=()=>{}){return s(this,o(this,e,t).call(this,"h"+n,{},i)),this}k(n={},i=()=>{}){return i(this,o(this,e,t).call(this,"hr",{},n)),this}C(n={},i=()=>{}){return i(this,o(this,e,t).call(this,"br",{},n)),this}N(n={},i=()=>{}){const s=o(this,e,t).call(this,"label",{textContent:n.textContent??""});delete n.textContent;const r=o(this,e,t).call(this,"input",{type:"checkbox"},n);return s.insertBefore(r,s.firstChild),this.h(),i(this,s,r),this}B(n={},i=()=>{}){return i(this,o(this,e,t).call(this,"button",{},n)),this}I(n={},i=()=>{}){const s=n.title??n.textContent??"Help: No info";delete n.textContent,n.title=`Help: ${s}`;const r={textContent:"?",className:"bm-D",onclick:()=>{this.L(this.i,s)}};return i(this,o(this,e,t).call(this,"button",r,n)),this}P(n={},i=()=>{}){return i(this,o(this,e,t).call(this,"input",{},n)),this}G(n={},i=()=>{}){const s=n.textContent??"";delete n.textContent;const r=o(this,e,t).call(this,"div"),a=o(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 l=o(this,e,t).call(this,"button",{textContent:s});return this.h(),this.h(),a.setAttribute("tabindex","-1"),a.setAttribute("aria-hidden","true"),l.addEventListener("click",()=>{a.click()}),a.addEventListener("change",()=>{l.style.maxWidth=`${l.offsetWidth}px`,a.files.length>0?l.textContent=a.files[0].name:l.textContent=s}),i(this,r,a,l),this}W(n={},i=()=>{}){return i(this,o(this,e,t).call(this,"textarea",{},n)),this}L(e,t,n=!1){const i=document.getElementById(e.replace(/^#/,""));i&&(i instanceof HTMLInputElement?i.value=t:n?i.textContent=t:i.innerHTML=t)}_(e,t){let n,i=!1,o=0,s=null,r=0,a=0,l=0,c=0,m=null;if(e=document.querySelector(e),t=document.querySelector(t),!e||!t)return void this.U(`Can not drag! ${e?"":"moveMe"} ${e||t?"":"and "}${t?"":"iMoveThings "}was not found!`);const u=()=>{if(i){const t=Math.abs(r-l),n=Math.abs(a-c);(t>.5||n>.5)&&(r=l,a=c,e.style.transform=`translate(${r}px, ${a}px)`,e.style.left="0px",e.style.top="0px",e.style.right=""),s=requestAnimationFrame(u)}},h=(h,g)=>{i=!0,m=e.getBoundingClientRect(),n=h-m.left,o=g-m.top;const f=window.getComputedStyle(e).transform;if(f&&"none"!==f){const e=new DOMMatrix(f);r=e.m41,a=e.m42}else r=m.left,a=m.top;l=r,c=a,document.body.style.userSelect="none",t.classList.add("bm-_"),document.addEventListener("mousemove",p),document.addEventListener("touchmove",b,{passive:!1}),document.addEventListener("mouseup",d),document.addEventListener("touchend",d),document.addEventListener("touchcancel",d),s&&cancelAnimationFrame(s),u()},d=()=>{i=!1,s&&(cancelAnimationFrame(s),s=null),document.body.style.userSelect="",t.classList.remove("bm-_"),document.removeEventListener("mousemove",p),document.removeEventListener("touchmove",b),document.removeEventListener("mouseup",d),document.removeEventListener("touchend",d),document.removeEventListener("touchcancel",d)},p=e=>{i&&m&&(l=e.clientX-n,c=e.clientY-o)},b=e=>{if(i&&m){const t=e.touches[0];if(!t)return;l=t.clientX-n,c=t.clientY-o,e.preventDefault()}};t.addEventListener("mousedown",function(e){e.preventDefault(),h(e.clientX,e.clientY)}),t.addEventListener("touchstart",function(e){const t=e?.touches?.[0];t&&(h(t.clientX,t.clientY),e.preventDefault())},{passive:!1})}A(e){(0,console.info)(`${this.name}: ${e}`),this.L(this.i,"Status: "+e,!0)}U(e){(0,console.error)(`${this.name}: ${e}`),this.L(this.i,"Error: "+e,!0)}};function r(...e){(0,console.error)(...e)}function a(e,t){if(0===e)return t[0];let n="";const i=t.length;for(;e>0;)n=t[e%i]+n,e=Math.floor(e/i);return n}function l(e){let t="";for(let n=0;n>>24==0?0:o.get(t)??-2;const r=s.get(i);s.set(i,r?r+1:1)}return console.log(s),s},h=new WeakSet,d=async function(){GM.setValue("bmTemplates",JSON.stringify(this.ee))},p=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,i=t[e];if(console.log(`Template Key: ${n}`),t.hasOwnProperty(e)){const e=n.split(" "),t=Number(e?.[0]),o=e?.[1]||"0",s=i.name||`Template ${t||""}`,r={total:i.pixels.total,colors:new Map(Object.entries(i.pixels.colors).map(([e,t])=>[Number(e),t]))},a=i.tiles,l={},m={},u=this.Y*this.te;for(const e in a)if(console.log(e),a.hasOwnProperty(e)){const t=c(a[e]),n=new Blob([t],{type:"image/png"}),i=await createImageBitmap(n);l[e]=i;const o=new OffscreenCanvas(u,u).getContext("2d");o.drawImage(i,0,0);const s=o.getImageData(0,0,i.width,i.height);m[e]=new Uint32Array(s.data.buffer)}const h=new v({displayName:s,X:t||this.ne?.length||0,J:o||""});h.V=r,h.j=l,h.R=m,this.ne.push(h),console.log(this.ne),console.log("^^^ This ^^^")}}},b=function(e,t,n){const i=this.te,o=this.Y*i,s=n[0],r=n[1],a=n[2],l=n[3],c=this.ie,{palette:m,Z:u}=this.oe,h=new Map;for(let n=1;n>>24&255)<=c||(i>>>24&255)<=c)continue;const d=u.get(i)??-2,p=u.get(m)??-2;if(d!=p)continue;const b=h.get(p);h.set(p,b?b+1:1)}return console.log("List of template pixels that match the tile:"),console.log(h),h},g=new WeakSet,f=async function(e=navigator.userAgent){return(e=e||"").includes("OPR/")||e.includes("Opera")?"Opera":e.includes("Edg/")?"Edge":e.includes("Vivaldi")?"Vivaldi":e.includes("YaBrowser")?"Yandex":e.includes("Kiwi")?"Kiwi":e.includes("Brave")?"Brave":e.includes("Firefox/")?"Firefox":e.includes("Chrome/")?"Chrome":e.includes("Safari/")?"Safari":navigator.brave&&"function"==typeof navigator.brave.isBrave&&await navigator.brave.isBrave()?"Brave":"Unknown"},w=function(e=navigator.userAgent){return/Windows NT 11/i.test(e=e||"")?"Windows 11":/Windows NT 10/i.test(e)?"Windows 10":/Windows NT 6\.3/i.test(e)?"Windows 8.1":/Windows NT 6\.2/i.test(e)?"Windows 8":/Windows NT 6\.1/i.test(e)?"Windows 7":/Windows NT 6\.0/i.test(e)?"Windows Vista":/Windows NT 5\.1|Windows XP/i.test(e)?"Windows XP":/Mac OS X 10[_\.]15/i.test(e)?"macOS Catalina":/Mac OS X 10[_\.]14/i.test(e)?"macOS Mojave":/Mac OS X 10[_\.]13/i.test(e)?"macOS High Sierra":/Mac OS X 10[_\.]12/i.test(e)?"macOS Sierra":/Mac OS X 10[_\.]11/i.test(e)?"OS X El Capitan":/Mac OS X 10[_\.]10/i.test(e)?"OS X Yosemite":/Mac OS X 10[_\.]/i.test(e)?"macOS":/Android/i.test(e)?"Android":/iPhone|iPad|iPod/i.test(e)?"iOS":/Linux/i.test(e)?"Linux":"Unknown"};var x=GM_info.script.name.toString(),S=GM_info.script.version.toString();!function(e){const t=document.createElement("script");t.setAttribute("bm-E",x),t.setAttribute("bm-B","color: cornflowerblue;"),t.textContent=`(${e})();`,document.documentElement?.appendChild(t),t.remove()}(()=>{const e=document.currentScript,t=e?.getAttribute("bm-E")||"Blue Marble",n=e?.getAttribute("bm-B")||"",i=new Map;window.addEventListener("message",e=>{const{source:o,endpoint:s,blobID:r,blobData:a,blink:l}=e.data,c=Date.now()-l;if(console.groupCollapsed(`%c${t}%c: ${i.size} Recieved IMAGE message about blob "${r}"`,n,""),console.log(`Blob fetch took %c${String(Math.floor(c/6e4)).padStart(2,"0")}:${String(Math.floor(c/1e3)%60).padStart(2,"0")}.${String(c%1e3).padStart(3,"0")}%c MM:SS.mmm`,n,""),console.log(i),console.groupEnd(),"blue-marble"==o&&r&&a&&!s){const e=i.get(r);"function"==typeof e?e(a):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,"",r),i.delete(r)}});const o=window.fetch;window.fetch=async function(...e){const s=await o.apply(this,e),r=s.clone(),a=(e[0]instanceof Request?e[0]?.url:e[0])||"ignore",l=r.headers.get("content-type")||"";if(l.includes("application/json"))console.log(`%c${t}%c: Sending JSON message about endpoint "${a}"`,n,""),r.json().then(e=>{window.postMessage({source:"blue-marble",endpoint:a,jsonData:e},"*")}).catch(e=>{console.error(`%c${t}%c: Failed to parse JSON: `,n,"",e)});else if(l.includes("image/")&&!a.includes("openfreemap")&&!a.includes("maps")){const e=Date.now(),o=await r.blob();return console.log(`%c${t}%c: ${i.size} Sending IMAGE message about endpoint "${a}"`,n,""),new Promise(s=>{const l=crypto.randomUUID();i.set(l,e=>{s(new Response(e,{headers:r.headers,status:r.status,statusText:r.statusText})),console.log(`%c${t}%c: ${i.size} Processed blob "${l}"`,n,"")}),window.postMessage({source:"blue-marble",endpoint:a,blobID:l,blobData:o,blink:e})}).catch(o=>{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: ${a}\nThere are ${i.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:",o),console.groupEnd()})}return s}});var $=GM_getResourceText("CSS-BM-File");GM_addStyle($);var M,T="robotoMonoInjectionPoint";T.indexOf("@font-face")+1?(console.log("Loading Roboto Mono as a file..."),GM_addStyle(T)):((M=document.createElement("link")).href="https://fonts.googleapis.com/css2?family=Roboto+Mono:ital,wght@0,100..700;1,100..700&display=swap",M.rel="preload",M.as="style",M.onload=function(){this.onload=null,this.rel="stylesheet"},document.head?.appendChild(M)),new class{constructor(){this.se=null,this.re=null,this.ae="#bm-h"}le(e){return this.re=e,this.se=new MutationObserver(e=>{for(const t of e)for(const e of t.addedNodes)e instanceof HTMLElement&&e.matches?.(this.ae)}),this}ce(){return this.se}observe(e,t=!1,n=!1){e.observe(this.re,{childList:t,subtree:n})}};var D=new s(x,S),O=(new s(x,S),new class{constructor(e,t,n){i(this,h),this.name=e,this.version=t,this.o=n,this.me="1.0.0",this.ue=null,this.he="!#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",this.Y=1e3,this.te=3,this.ie=3,this.oe=function(e){const t=y;t.unshift({id:-1,premium:!1,name:"Erased",rgb:[222,250,206]}),t.unshift({id:-2,premium:!1,name:"Other",rgb:[0,0,0]});const n=new Map;for(const i of t){if(0==i.id||-2==i.id)continue;const t=i.rgb[0],o=i.rgb[1],s=i.rgb[2];for(let r=-e;r<=e;r++)for(let a=-e;a<=e;a++)for(let l=-e;l<=e;l++){const e=t+r,c=o+a,m=s+l;if(e<0||e>255||c<0||c>255||m<0||m>255)continue;const u=(255<<24|m<<16|c<<8|e)>>>0;n.has(u)||n.set(u,i.id)}}return{palette:t,Z:n}}(this.ie),this.de=null,this.pe="",this.ne=[],this.ee=null,this.be=!0,this.ge=null}async fe(){return{whoami:this.name.replace(" ",""),scriptVersion:this.version,schemaVersion:this.me,templates:{}}}async we(e,t,n){this.ee||(this.ee=await this.fe(),console.log("Creating JSON...")),this.o.A(`Creating template at ${n.join(", ")}...`);const i=new v({displayName:t,X:0,J:a(this.ue||0,this.he),file:e,coords:n}),{q:s,K:r}=await i.F(this.Y,this.oe);i.j=s;const l={total:i.V.total,colors:Object.fromEntries(i.V.colors)};this.ee.templates[`${i.X} ${i.J}`]={name:i.displayName,coords:n.join(", "),enabled:!0,pixels:l,tiles:r},this.ne=[],this.ne.push(i),this.o.A(`Template created at ${n.join(", ")}!`),console.log(Object.keys(this.ee.templates).length),console.log(this.ee),console.log(this.ne),console.log(JSON.stringify(this.ee)),await o(this,h,d).call(this)}ye(){}async ve(){this.ee||(this.ee=await this.fe(),console.log("Creating JSON..."))}async xe(e,t){if(!this.be)return e;const n=this.Y*this.te;t=t[0].toString().padStart(4,"0")+","+t[1].toString().padStart(4,"0"),console.log(`Searching for templates in tile: "${t}"`);const i=this.ne;console.log(i),i.sort((e,t)=>e.X-t.X),console.log(i);const s=i.map(e=>{const n=Object.keys(e.j).filter(e=>e.startsWith(t));if(0===n.length)return null;const i=n.map(t=>{const n=t.split(",");return{Se:e,$e:e.j[t],R:e.R?.[t],Me:[n[0],n[1]],Te:[n[2],n[3]]}});return i?.[0]}).filter(Boolean);console.log(s);const r=s?.length||0;if(console.log(`templateCount = ${r}`),!(r>0))return this.o.A(`Sleeping\nVersion: ${this.version}`),e;{const e=i.filter(e=>Object.keys(e.j).filter(e=>e.startsWith(t)).length>0).reduce((e,t)=>e+(t.V.total||0),0),n=(new Intl.NumberFormat).format(e);this.o.A(`Displaying ${r} template${1==r?"":"s"}.\nTotal pixels: ${n}`)}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);const m=c.getImageData(0,0,n,n),u=new Uint32Array(m.data.buffer);for(const e of s){console.log("Template:"),console.log(e);let n=e.R;const i=Number(e.Te[0])*this.te,s=Number(e.Te[1])*this.te;if(c.drawImage(e.$e,i,s),!n){const t=c.getImageData(i,s,e.$e.width,e.$e.height);n=new Uint32Array(t.data.buffer)}const r=Date.now(),a=o(this,h,b).call(this,u,n,[i,s,e.$e.width,e.$e.height]);let l=0;const m=0;for(const[e,t]of a)e!=m&&(l+=t);console.log(`Finished calculating correct pixels for the tile ${t} in ${(Date.now()-r)/1e3} seconds!\nThere are ${l} correct pixels.`),e.Se.V.correct=a}return await l.convertToBlob({type:"image/png"})}De(e){console.log("Importing JSON..."),console.log(e),"BlueMarble"==e?.whoami&&o(this,h,p).call(this,e)}Oe(e){this.be=e}}(x,S,D)),k=new class{constructor(e){i(this,g),this.ke=e,this.Ce=!1,this.Ne=[],this.Be=[]}Ie(e){window.addEventListener("message",async t=>{const n=t.data,i=n.jsonData;if(!n||"blue-marble"!==n.source)return;if(!n.endpoint)return;const o=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;","",o),o){case"me":if(i.status&&"2"!=i.status?.toString()[0])return void e.U("You are not logged in!\nCould not fetch userdata.");const t=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(a(i.id,"!#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~")),this.ke.ue=i.id,e.L("bm-p",`Droplets: ${(new Intl.NumberFormat).format(i.droplets)}`),e.L("bm-i",`Next level in ${(new Intl.NumberFormat).format(t)} pixel${1==t?"":"s"}`);break;case"pixel":const o=n.endpoint.split("?")[0].split("/").filter(e=>e&&!isNaN(Number(e))),l=new URLSearchParams(n.endpoint.split("?")[1]),c=[l.get("x"),l.get("y")];if(this.Ne.length&&(!o.length||!c.length))return void e.U("Coordinates are malformed!\nDid you try clicking the canvas first?");this.Ne=[...o,...c];const m=(s=o,r=c,[parseInt(s[0])%4*1e3+parseInt(r[0]),parseInt(s[1])%4*1e3+parseInt(r[1])]),u=document.querySelectorAll("span");for(const e of u)if(e.textContent.trim().includes(`${m[0]}, ${m[1]}`)){let t=document.querySelector("#bm-h");const n=`(Tl X: ${o[0]}, Tl Y: ${o[1]}, Px X: ${c[0]}, Px Y: ${c[1]})`;t?t.textContent=n:(t=document.createElement("span"),t.id="bm-h",t.textContent=n,t.style="margin-left: calc(var(--spacing)*3); font-size: small;",e.parentNode.parentNode.insertAdjacentElement("afterend",t))}break;case"tiles":let h=n.endpoint.split("/");h=[parseInt(h[h.length-2]),parseInt(h[h.length-1].replace(".png",""))];const d=n.blobID,p=n.blobData,b=Date.now(),g=await this.ke.xe(p,h);console.log(`Finished loading the tile in ${(Date.now()-b)/1e3} seconds!`),window.postMessage({source:"blue-marble",blobID:d,blobData:g,blink:n.blink});break;case"robots":this.Ce="false"==i.userscript?.toString().toLowerCase();break}var s,r})}async Le(e){console.log("Sending heartbeat to telemetry server...");let t=GM_getValue("bmUserSettings","{}");if(t=JSON.parse(t),!t||!t.telemetry||!t.uuid)return void console.log("Telemetry is disabled, not sending heartbeat.");const n=navigator.userAgent;let i=await o(this,g,f).call(this,n),s=o(this,g,w).call(this,n);GM_xmlhttpRequest({method:"POST",url:"https://telemetry.thebluecorner.net/heartbeat",headers:{"Content-Type":"application/json"},data:JSON.stringify({uuid:t.uuid,version:e,browser:i,os:s}),onload:e=>{200!==e.status&&r("Failed to send heartbeat:",e.statusText)},onerror:e=>{r("Error sending heartbeat:",e)}})}}(O);D.u(k);var C=JSON.parse(GM_getValue("bmTemplates","{}"));console.log(C),O.De(C);var N=JSON.parse(GM_getValue("bmUserSettings","{}"));if(console.log(N),console.log(Object.keys(N).length),0==Object.keys(N).length){const e=crypto.randomUUID();console.log(e),GM.setValue("bmUserSettings",JSON.stringify({uuid:e}))}if(setInterval(()=>k.Le(S),18e5),console.log(`Telemetry is ${!(null==N?.telemetry)}`),null==N?.telemetry||N?.telemetry>1){const e=new s(x,S);e.u(k),e.v({id:"bm-d",style:"top: 0px; left: 0px; width: 100vw; max-width: 100vw; height: 100vh; max-height: 100vh; z-index: 9999;"}).v({id:"bm-7",style:"display: flex; flex-direction: column; align-items: center;"}).v({id:"bm-1",style:"margin-top: 10%;"}).O(1,{textContent:`${x} Telemetry`}).h().h().v({id:"bm-e",style:"max-width: 50%; overflow-y: auto; max-height: 80vh;"}).k().h().C().h().v({style:"width: fit-content; margin: auto; text-align: center;"}).B({id:"bm-8",textContent:"More Information"},(e,t)=>{t.onclick=()=>{window.open("https://github.com/SwingTheVine/Wplace-TelemetryServer#telemetry-data","_blank","noopener noreferrer")}}).h().h().C().h().v({style:"width: fit-content; margin: auto; text-align: center;"}).B({id:"bm-5",textContent:"Enable Telemetry",style:"margin-right: 2ch;"},(e,t)=>{t.onclick=()=>{const e=JSON.parse(GM_getValue("bmUserSettings","{}"));e.telemetry=1,GM.setValue("bmUserSettings",JSON.stringify(e));const t=document.getElementById("bm-d");t&&(t.style.display="none")}}).h().B({id:"bm-2",textContent:"Disable Telemetry"},(e,t)=>{t.onclick=()=>{const e=JSON.parse(GM_getValue("bmUserSettings","{}"));e.telemetry=0,GM.setValue("bmUserSettings",JSON.stringify(e));const t=document.getElementById("bm-d");t&&(t.style.display="none")}}).h().h().C().h().S({textContent:"We collect anonymous telemetry data such as your browser, OS, and script version to make the experience better for everyone. The data is never shared personally. The data is never sold. You can turn this off by pressing the 'Disable' button, but keeping it on helps us improve features and reliability faster. Thank you for supporting the Blue Marble!"}).h().S({textContent:'You can disable telemetry by pressing the "Disable" button below.'}).h().h().h().p(document.body)}D.v({id:"bm-W",class:"bm-17",style:"top: 10px; right: 75px;"}).v({class:"bm-14"}).v().B({class:"bm-T",textContent:"▼"},(e,t)=>{t.onclick=()=>{const e=t.closest(".bm-17"),n=t.closest(".bm-14"),i=e.querySelector("h1"),o=e.querySelector(".bm-Q");if("▼"==t.textContent){const n=i.cloneNode(!0);t.parentNode.appendChild(n),o.style.height=o.scrollHeight+"px",e.style.width=e.scrollWidth+"px",o.style.height="0",o.addEventListener("transitionend",function e(){o.style.display="none",o.removeEventListener("transitionend",e)})}else n.querySelector("h1").remove(),o.style.display="",o.style.height="0",e.style.width="",o.style.height=o.scrollHeight+"px",o.addEventListener("transitionend",function e(){o.style.height="",o.removeEventListener("transitionend",e)});t.textContent="▼"==t.textContent?"▶":"▼"}}).h().h().h().v({class:"bm-Q"}).v({class:"bm--"}).D({class:"bm-15",src:"https://raw.githubusercontent.com/SwingTheVine/Wplace-BlueMarble/main/dist/assets/Favicon.png"}).h().O(1,{textContent:x}).h().h().k().h().v({class:"bm--"}).S({id:"bm-p",textContent:"Droplets:"}).h().S({id:"bm-i",textContent:"Next level in..."}).h().h().k().h().v({class:"bm--"}).v({class:"bm--"}).B({class:"bm-T bm-Y",style:"margin-top: 0;",innerHTML:''},(e,t)=>{t.onclick=()=>{const t=e.t?.Ne;t?.[0]?(e.L("bm-v",t?.[0]||""),e.L("bm-w",t?.[1]||""),e.L("bm-x",t?.[2]||""),e.L("bm-y",t?.[3]||"")):e.U("Coordinates are malformed! Did you try clicking on the canvas first?")}}).h().P({type:"number",id:"bm-v",class:"bm-U",placeholder:"Tl X",min:0,max:2047,step:1,required:!0},(e,t)=>{t.addEventListener("paste",e=>{let t=(e.clipboardData||window.clipboardData).getData("text").split(" ").filter(e=>e).map(Number).filter(e=>!isNaN(e));if(4!==t.length)return;let n=selectAllCoordinateInputs(document);for(let e=0;epersistCoords();t.addEventListener("input",n),t.addEventListener("change",n)}).h().P({type:"number",id:"bm-w",class:"bm-U",placeholder:"Tl Y",min:0,max:2047,step:1,required:!0},(e,t)=>{const n=()=>persistCoords();t.addEventListener("input",n),t.addEventListener("change",n)}).h().P({type:"number",id:"bm-x",class:"bm-U",placeholder:"Px X",min:0,max:2047,step:1,required:!0},(e,t)=>{const n=()=>persistCoords();t.addEventListener("input",n),t.addEventListener("change",n)}).h().P({type:"number",id:"bm-y",class:"bm-U",placeholder:"Px Y",min:0,max:2047,step:1,required:!0},(e,t)=>{const n=()=>persistCoords();t.addEventListener("input",n),t.addEventListener("change",n)}).h().h().v({class:"bm--"}).G({class:"bm-Z",textContent:"Upload Template",accept:"image/png, image/jpeg, image/webp, image/bmp, image/gif"}).h().h().v({class:"bm-- bm-V"}).B({textContent:"Enable"},(e,t)=>{t.onclick=()=>{e.t?.ke?.Oe(!0),e.A("Enabled templates!")}}).h().B({textContent:"Create"},(e,t)=>{t.onclick=()=>{const t=document.querySelector("#bm-W button.bm-Z"),n=document.querySelector("#bm-v");if(!n.checkValidity())return n.reportValidity(),void e.U("Coordinates are malformed! Did you try clicking on the canvas first?");const i=document.querySelector("#bm-w");if(!i.checkValidity())return i.reportValidity(),void e.U("Coordinates are malformed! Did you try clicking on the canvas first?");const o=document.querySelector("#bm-x");if(!o.checkValidity())return o.reportValidity(),void e.U("Coordinates are malformed! Did you try clicking on the canvas first?");const s=document.querySelector("#bm-y");if(!s.checkValidity())return s.reportValidity(),void e.U("Coordinates are malformed! Did you try clicking on the canvas first?");t?.files[0]?(O.we(t.files[0],t.files[0]?.name.replace(/\.[^/.]+$/,""),[Number(n.value),Number(i.value),Number(o.value),Number(s.value)]),e.A("Drew to canvas!")):e.U("No file selected!")}}).h().B({textContent:"Disable"},(e,t)=>{t.onclick=()=>{e.t?.ke?.Oe(!1),e.A("Disabled templates!")}}).h().h().v({class:"bm--"}).W({id:D.i,placeholder:`Status: Sleeping...\nVersion: ${S}`,readOnly:!0}).h().h().v({class:"bm-- bm-V",style:"margin-bottom: 0;"}).v({class:"bm-V"}).B({class:"bm-T",innerHTML:"🎨",title:"Template Color Converter"},(e,t)=>{t.addEventListener("click",()=>{window.open("https://pepoafonso.github.io/color_converter_wplace/","_blank","noopener noreferrer")})}).h().B({class:"bm-T",innerHTML:"🌐",title:"Official Blue Marble Website"},(e,t)=>{t.addEventListener("click",()=>{window.open("https://bluemarble.lol/","_blank","noopener noreferrer")})}).h().h().$({textContent:"Made by SwingTheVine",style:"margin-top: auto;"}).h().h().h().h().h().p(document.body),D._("#bm-W.bm-17","#bm-W .bm-14"),k.Ie(D),new MutationObserver((e,t)=>{const n=document.querySelector("#color-1");if(!n)return;let i=document.querySelector("#bm-t");if(!i){i=document.createElement("button"),i.id="bm-t",i.textContent="Move ↑",i.className="btn btn-soft",i.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(i)}}).observe(document.body,{childList:!0,subtree:!0}),function(...e){(0,console.log)(...e)}(`%c${x}%c (${S}) userscript has loaded!`,"color: cornflowerblue;","")})();
\ No newline at end of file
+(()=>{var e,t,n,i=e=>{throw TypeError(e)},o=(e,t,n)=>t.has(e)?i("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(e):t.set(e,n),s=(e,t,n)=>(((e,t)=>{t.has(e)||i("Cannot access private method")})(e,t),n),a=class{constructor(t,n){o(this,e),this.name=t,this.version=n,this.t=null,this.i="bm-o",this.o=null,this.l=null,this.m=[]}u(e){this.t=e}h(){return this.m.length>0&&(this.l=this.m.pop()),this}p(e){e?.appendChild(this.o),this.o=null,this.l=null,this.m=[]}v(n={},i=()=>{}){return i(this,s(this,e,t).call(this,"div",{},n)),this}S(n={},i=()=>{}){return i(this,s(this,e,t).call(this,"p",{},n)),this}$(n={},i=()=>{}){return i(this,s(this,e,t).call(this,"small",{},n)),this}M(n={},i=()=>{}){return i(this,s(this,e,t).call(this,"details",{},n)),this}T(n={},i=()=>{}){return i(this,s(this,e,t).call(this,"summary",{},n)),this}D(n={},i=()=>{}){return i(this,s(this,e,t).call(this,"img",{},n)),this}O(n,i={},o=()=>{}){return o(this,s(this,e,t).call(this,"h"+n,{},i)),this}k(n={},i=()=>{}){return i(this,s(this,e,t).call(this,"hr",{},n)),this}C(n={},i=()=>{}){return i(this,s(this,e,t).call(this,"br",{},n)),this}N(n={},i=()=>{}){const o=s(this,e,t).call(this,"label",{textContent:n.textContent??""});delete n.textContent;const a=s(this,e,t).call(this,"input",{type:"checkbox"},n);return o.insertBefore(a,o.firstChild),this.h(),i(this,o,a),this}B(n={},i=()=>{}){return i(this,s(this,e,t).call(this,"button",{},n)),this}I(n={},i=()=>{}){const o=n.title??n.textContent??"Help: No info";delete n.textContent,n.title=`Help: ${o}`;const a={textContent:"?",className:"bm-D",onclick:()=>{this.L(this.i,o)}};return i(this,s(this,e,t).call(this,"button",a,n)),this}P(n={},i=()=>{}){return i(this,s(this,e,t).call(this,"input",{},n)),this}G(n={},i=()=>{}){const o=n.textContent??"";delete n.textContent;const a=s(this,e,t).call(this,"div"),r=s(this,e,t).call(this,"input",{type:"file",tabindex:"-1","aria-hidden":"true",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 l=s(this,e,t).call(this,"button",{textContent:o});return this.h(),this.h(),l.addEventListener("click",()=>{r.click()}),r.addEventListener("change",()=>{l.style.maxWidth=`${l.offsetWidth}px`,r.files.length>0?l.textContent=r.files[0].name:l.textContent=o}),i(this,a,r,l),this}W(n={},i=()=>{}){return i(this,s(this,e,t).call(this,"textarea",{},n)),this}L(e,t,n=!1){const i=document.getElementById(e.replace(/^#/,""));i&&(i instanceof HTMLInputElement?i.value=t:n?i.textContent=t:i.innerHTML=t)}U(e){e.disabled=!0,e.style.textDecoration="none";const t=e.closest(".bm-16"),n=e.closest(".bm-14"),i=t.querySelector("h1"),o=t.querySelector(".bm-O");if("expanded"==e.dataset.buttonStatus){const n=i.cloneNode(!0),s=n.textContent;e.parentNode.appendChild(n),o.style.height=o.scrollHeight+"px",t.style.width=t.scrollWidth+"px",o.style.height="0",o.addEventListener("transitionend",function t(){o.style.display="none",e.disabled=!1,e.style.textDecoration="",o.removeEventListener("transitionend",t)}),e.textContent="▶",e.dataset.buttonStatus="collapsed",e.ariaLabel=`Unminimize window "${s}"`}else{const i=n.querySelector("h1"),s=i.textContent;i.remove(),o.style.display="",o.style.height="0",t.style.width="",o.style.height=o.scrollHeight+"px",o.addEventListener("transitionend",function t(){o.style.height="",e.disabled=!1,e.style.textDecoration="",o.removeEventListener("transitionend",t)}),e.textContent="▼",e.dataset.buttonStatus="expanded",e.ariaLabel=`Minimize window "${s}"`}}_(e,t){let n,i=!1,o=0,s=null,a=0,r=0,l=0,m=0,c=null;if(e=document.querySelector(e),t=document.querySelector(t),!e||!t)return void this.A(`Can not drag! ${e?"":"moveMe"} ${e||t?"":"and "}${t?"":"iMoveThings "}was not found!`);const d=()=>{if(i){const t=Math.abs(a-l),n=Math.abs(r-m);(t>.5||n>.5)&&(a=l,r=m,e.style.transform=`translate(${a}px, ${r}px)`,e.style.left="0px",e.style.top="0px",e.style.right=""),s=requestAnimationFrame(d)}},u=(u,g)=>{i=!0,c=e.getBoundingClientRect(),n=u-c.left,o=g-c.top;const f=window.getComputedStyle(e).transform;if(f&&"none"!==f){const e=new DOMMatrix(f);a=e.m41,r=e.m42}else a=c.left,r=c.top;l=a,m=r,document.body.style.userSelect="none",t.classList.add("bm-_"),document.addEventListener("mousemove",b),document.addEventListener("touchmove",p,{passive:!1}),document.addEventListener("mouseup",h),document.addEventListener("touchend",h),document.addEventListener("touchcancel",h),s&&cancelAnimationFrame(s),d()},h=()=>{i=!1,s&&(cancelAnimationFrame(s),s=null),document.body.style.userSelect="",t.classList.remove("bm-_"),document.removeEventListener("mousemove",b),document.removeEventListener("touchmove",p),document.removeEventListener("mouseup",h),document.removeEventListener("touchend",h),document.removeEventListener("touchcancel",h)},b=e=>{i&&c&&(l=e.clientX-n,m=e.clientY-o)},p=e=>{if(i&&c){const t=e.touches[0];if(!t)return;l=t.clientX-n,m=t.clientY-o,e.preventDefault()}};t.addEventListener("mousedown",function(e){e.preventDefault(),u(e.clientX,e.clientY)}),t.addEventListener("touchstart",function(e){const t=e?.touches?.[0];t&&(u(t.clientX,t.clientY),e.preventDefault())},{passive:!1})}X(e){(0,console.info)(`${this.name}: ${e}`),this.L(this.i,"Status: "+e,!0)}A(e){(0,console.error)(`${this.name}: ${e}`),this.L(this.i,"Error: "+e,!0)}};function r(...e){(0,console.error)(...e)}function l(e,t){if(0===e)return t[0];let n="";const i=t.length;for(;e>0;)n=t[e%i]+n,e=Math.floor(e/i);return n}function m(e){let t="";for(let n=0;n0==t?e:e[0].toUpperCase()+e.slice(1)).join("")]=n;else if(t.startsWith("aria")){const i=t.slice(5).split("-").map((e,t)=>0==t?e:e[0].toUpperCase()+e.slice(1)).join("");e["aria"+i[0].toUpperCase()+i.slice(1)]=n}else e[t]=n};var d,u,h,b,p,g,f,w,y,v=[{id:0,premium:!1,name:"Transparent",rgb:[0,0,0]},{id:1,premium:!1,name:"Black",rgb:[0,0,0]},{id:2,premium:!1,name:"Dark Gray",rgb:[60,60,60]},{id:3,premium:!1,name:"Gray",rgb:[120,120,120]},{id:4,premium:!1,name:"Light Gray",rgb:[210,210,210]},{id:5,premium:!1,name:"White",rgb:[255,255,255]},{id:6,premium:!1,name:"Deep Red",rgb:[96,0,24]},{id:7,premium:!1,name:"Red",rgb:[237,28,36]},{id:8,premium:!1,name:"Orange",rgb:[255,127,39]},{id:9,premium:!1,name:"Gold",rgb:[246,170,9]},{id:10,premium:!1,name:"Yellow",rgb:[249,221,59]},{id:11,premium:!1,name:"Light Yellow",rgb:[255,250,188]},{id:12,premium:!1,name:"Dark Green",rgb:[14,185,104]},{id:13,premium:!1,name:"Green",rgb:[19,230,123]},{id:14,premium:!1,name:"Light Green",rgb:[135,255,94]},{id:15,premium:!1,name:"Dark Teal",rgb:[12,129,110]},{id:16,premium:!1,name:"Teal",rgb:[16,174,166]},{id:17,premium:!1,name:"Light Teal",rgb:[19,225,190]},{id:18,premium:!1,name:"Dark Blue",rgb:[40,80,158]},{id:19,premium:!1,name:"Blue",rgb:[64,147,228]},{id:20,premium:!1,name:"Cyan",rgb:[96,247,242]},{id:21,premium:!1,name:"Indigo",rgb:[107,80,246]},{id:22,premium:!1,name:"Light Indigo",rgb:[153,177,251]},{id:23,premium:!1,name:"Dark Purple",rgb:[120,12,153]},{id:24,premium:!1,name:"Purple",rgb:[170,56,185]},{id:25,premium:!1,name:"Light Purple",rgb:[224,159,249]},{id:26,premium:!1,name:"Dark Pink",rgb:[203,0,122]},{id:27,premium:!1,name:"Pink",rgb:[236,31,128]},{id:28,premium:!1,name:"Light Pink",rgb:[243,141,169]},{id:29,premium:!1,name:"Dark Brown",rgb:[104,70,52]},{id:30,premium:!1,name:"Brown",rgb:[149,104,42]},{id:31,premium:!1,name:"Beige",rgb:[248,178,119]},{id:32,premium:!0,name:"Medium Gray",rgb:[170,170,170]},{id:33,premium:!0,name:"Dark Red",rgb:[165,14,30]},{id:34,premium:!0,name:"Light Red",rgb:[250,128,114]},{id:35,premium:!0,name:"Dark Orange",rgb:[228,92,26]},{id:36,premium:!0,name:"Light Tan",rgb:[214,181,148]},{id:37,premium:!0,name:"Dark Goldenrod",rgb:[156,132,49]},{id:38,premium:!0,name:"Goldenrod",rgb:[197,173,49]},{id:39,premium:!0,name:"Light Goldenrod",rgb:[232,212,95]},{id:40,premium:!0,name:"Dark Olive",rgb:[74,107,58]},{id:41,premium:!0,name:"Olive",rgb:[90,148,74]},{id:42,premium:!0,name:"Light Olive",rgb:[132,197,115]},{id:43,premium:!0,name:"Dark Cyan",rgb:[15,121,159]},{id:44,premium:!0,name:"Light Cyan",rgb:[187,250,242]},{id:45,premium:!0,name:"Light Blue",rgb:[125,199,255]},{id:46,premium:!0,name:"Dark Indigo",rgb:[77,49,184]},{id:47,premium:!0,name:"Dark Slate Blue",rgb:[74,66,132]},{id:48,premium:!0,name:"Slate Blue",rgb:[122,113,196]},{id:49,premium:!0,name:"Light Slate Blue",rgb:[181,174,241]},{id:50,premium:!0,name:"Light Brown",rgb:[219,164,99]},{id:51,premium:!0,name:"Dark Beige",rgb:[209,128,81]},{id:52,premium:!0,name:"Light Beige",rgb:[255,197,165]},{id:53,premium:!0,name:"Dark Peach",rgb:[155,82,73]},{id:54,premium:!0,name:"Peach",rgb:[209,128,120]},{id:55,premium:!0,name:"Light Peach",rgb:[250,182,164]},{id:56,premium:!0,name:"Dark Tan",rgb:[123,99,82]},{id:57,premium:!0,name:"Tan",rgb:[156,132,107]},{id:58,premium:!0,name:"Dark Slate",rgb:[51,57,65]},{id:59,premium:!0,name:"Slate",rgb:[109,117,141]},{id:60,premium:!0,name:"Light Slate",rgb:[179,185,209]},{id:61,premium:!0,name:"Dark Stone",rgb:[109,100,63]},{id:62,premium:!0,name:"Stone",rgb:[148,140,107]},{id:63,premium:!0,name:"Light Stone",rgb:[205,197,158]}],x=class{constructor({displayName:e="My template",J:t=0,j:n="",url:i="",file:s=null,coords:a=null,R:r=null,Y:l={},F:m=1e3}={}){o(this,d),this.displayName=e,this.J=t,this.j=n,this.url=i,this.file=s,this.coords=a,this.R=r,this.Y=l,this.F=m,this.V={total:0,colors:new Map}}async H(e,t){console.log("Template coordinates:",this.coords);const n=await createImageBitmap(this.file),i=n.width,o=n.height;this.F=e;const a={},r={},l=new OffscreenCanvas(this.F,this.F),c=l.getContext("2d",{q:!0});l.width=i,l.height=o,c.imageSmoothingEnabled=!1,c.drawImage(n,0,0);let h=Date.now();const b=s(this,d,u).call(this,c.getImageData(0,0,i,o),t);console.log(`Calculating total pixels took ${(Date.now()-h)/1e3} seconds`);let p=0;for(const[e,t]of b)0!=e&&(p+=t);this.V={total:p,colors:b},h=Date.now();const g=new OffscreenCanvas(3,3),f=g.getContext("2d");f.clearRect(0,0,3,3),f.fillStyle="white",f.fillRect(1,1,1,1);for(let e=this.coords[3];e>>24==0?0:o.get(t)??-2;const a=s.get(i);s.set(i,a?a+1:1)}return console.log(s),s},h=new WeakSet,b=async function(){GM.setValue("bmTemplates",JSON.stringify(this.te))},p=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,i=t[e];if(console.log(`Template Key: ${n}`),t.hasOwnProperty(e)){const e=n.split(" "),t=Number(e?.[0]),o=e?.[1]||"0",s=i.name||`Template ${t||""}`,a={total:i.pixels.total,colors:new Map(Object.entries(i.pixels.colors).map(([e,t])=>[Number(e),t]))},r=i.tiles,l={},m={},d=this.F*this.ne;for(const e in r)if(console.log(e),r.hasOwnProperty(e)){const t=c(r[e]),n=new Blob([t],{type:"image/png"}),i=await createImageBitmap(n);l[e]=i;const o=new OffscreenCanvas(d,d).getContext("2d");o.drawImage(i,0,0);const s=o.getImageData(0,0,i.width,i.height);m[e]=new Uint32Array(s.data.buffer)}const u=new x({displayName:s,J:t||this.ie?.length||0,j:o||""});u.V=a,u.R=l,u.Y=m,this.ie.push(u),console.log(this.ie),console.log("^^^ This ^^^")}}},g=function(e,t,n){const i=this.ne,o=this.F*i,s=n[0],a=n[1],r=n[2],l=n[3],m=this.oe,{palette:c,ee:d}=this.se,u=new Map;for(let n=1;n>>24&255)<=m||(i>>>24&255)<=m)continue;const h=d.get(i)??-2,b=d.get(c)??-2;if(h!=b)continue;const p=u.get(b);u.set(b,p?p+1:1)}return console.log("List of template pixels that match the tile:"),console.log(u),u},f=new WeakSet,w=async function(e=navigator.userAgent){return(e=e||"").includes("OPR/")||e.includes("Opera")?"Opera":e.includes("Edg/")?"Edge":e.includes("Vivaldi")?"Vivaldi":e.includes("YaBrowser")?"Yandex":e.includes("Kiwi")?"Kiwi":e.includes("Brave")?"Brave":e.includes("Firefox/")?"Firefox":e.includes("Chrome/")?"Chrome":e.includes("Safari/")?"Safari":navigator.brave&&"function"==typeof navigator.brave.isBrave&&await navigator.brave.isBrave()?"Brave":"Unknown"},y=function(e=navigator.userAgent){return/Windows NT 11/i.test(e=e||"")?"Windows 11":/Windows NT 10/i.test(e)?"Windows 10":/Windows NT 6\.3/i.test(e)?"Windows 8.1":/Windows NT 6\.2/i.test(e)?"Windows 8":/Windows NT 6\.1/i.test(e)?"Windows 7":/Windows NT 6\.0/i.test(e)?"Windows Vista":/Windows NT 5\.1|Windows XP/i.test(e)?"Windows XP":/Mac OS X 10[_\.]15/i.test(e)?"macOS Catalina":/Mac OS X 10[_\.]14/i.test(e)?"macOS Mojave":/Mac OS X 10[_\.]13/i.test(e)?"macOS High Sierra":/Mac OS X 10[_\.]12/i.test(e)?"macOS Sierra":/Mac OS X 10[_\.]11/i.test(e)?"OS X El Capitan":/Mac OS X 10[_\.]10/i.test(e)?"OS X Yosemite":/Mac OS X 10[_\.]/i.test(e)?"macOS":/Android/i.test(e)?"Android":/iPhone|iPad|iPod/i.test(e)?"iOS":/Linux/i.test(e)?"Linux":"Unknown"};var S=GM_info.script.name.toString(),$=GM_info.script.version.toString();!function(e){const t=document.createElement("script");t.setAttribute("bm-E",S),t.setAttribute("bm-B","color: cornflowerblue;"),t.textContent=`(${e})();`,document.documentElement?.appendChild(t),t.remove()}(()=>{const e=document.currentScript,t=e?.getAttribute("bm-E")||"Blue Marble",n=e?.getAttribute("bm-B")||"",i=new Map;window.addEventListener("message",e=>{const{source:o,endpoint:s,blobID:a,blobData:r,blink:l}=e.data,m=Date.now()-l;if(console.groupCollapsed(`%c${t}%c: ${i.size} Recieved IMAGE message about blob "${a}"`,n,""),console.log(`Blob fetch took %c${String(Math.floor(m/6e4)).padStart(2,"0")}:${String(Math.floor(m/1e3)%60).padStart(2,"0")}.${String(m%1e3).padStart(3,"0")}%c MM:SS.mmm`,n,""),console.log(i),console.groupEnd(),"blue-marble"==o&&a&&r&&!s){const e=i.get(a);"function"==typeof e?e(r):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),i.delete(a)}});const o=window.fetch;window.fetch=async function(...e){const s=await o.apply(this,e),a=s.clone(),r=(e[0]instanceof Request?e[0]?.url:e[0])||"ignore",l=a.headers.get("content-type")||"";if(l.includes("application/json"))console.log(`%c${t}%c: Sending JSON message about endpoint "${r}"`,n,""),a.json().then(e=>{window.postMessage({source:"blue-marble",endpoint:r,jsonData:e},"*")}).catch(e=>{console.error(`%c${t}%c: Failed to parse JSON: `,n,"",e)});else if(l.includes("image/")&&!r.includes("openfreemap")&&!r.includes("maps")){const e=Date.now(),o=await a.blob();return console.log(`%c${t}%c: ${i.size} Sending IMAGE message about endpoint "${r}"`,n,""),new Promise(s=>{const l=crypto.randomUUID();i.set(l,e=>{s(new Response(e,{headers:a.headers,status:a.status,statusText:a.statusText})),console.log(`%c${t}%c: ${i.size} Processed blob "${l}"`,n,"")}),window.postMessage({source:"blue-marble",endpoint:r,blobID:l,blobData:o,blink:e})}).catch(o=>{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: ${r}\nThere are ${i.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:",o),console.groupEnd()})}return s}});var M=GM_getResourceText("CSS-BM-File");GM_addStyle(M);var T,D="robotoMonoInjectionPoint";D.indexOf("@font-face")+1?(console.log("Loading Roboto Mono as a file..."),GM_addStyle(D)):((T=document.createElement("link")).href="https://fonts.googleapis.com/css2?family=Roboto+Mono:ital,wght@0,100..700;1,100..700&display=swap",T.rel="preload",T.as="style",T.onload=function(){this.onload=null,this.rel="stylesheet"},document.head?.appendChild(T)),new class{constructor(){this.ae=null,this.re=null,this.le="#bm-h"}me(e){return this.re=e,this.ae=new MutationObserver(e=>{for(const t of e)for(const e of t.addedNodes)e instanceof HTMLElement&&e.matches?.(this.le)}),this}ce(){return this.ae}observe(e,t=!1,n=!1){e.observe(this.re,{childList:t,subtree:n})}};var O=new a(S,$),k=(new a(S,$),new class{constructor(e,t,n){o(this,h),this.name=e,this.version=t,this.o=n,this.de="1.0.0",this.ue=null,this.he="!#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",this.F=1e3,this.ne=3,this.oe=3,this.se=function(e){const t=v;t.unshift({id:-1,premium:!1,name:"Erased",rgb:[222,250,206]}),t.unshift({id:-2,premium:!1,name:"Other",rgb:[0,0,0]});const n=new Map;for(const i of t){if(0==i.id||-2==i.id)continue;const t=i.rgb[0],o=i.rgb[1],s=i.rgb[2];for(let a=-e;a<=e;a++)for(let r=-e;r<=e;r++)for(let l=-e;l<=e;l++){const e=t+a,m=o+r,c=s+l;if(e<0||e>255||m<0||m>255||c<0||c>255)continue;const d=(255<<24|c<<16|m<<8|e)>>>0;n.has(d)||n.set(d,i.id)}}return{palette:t,ee:n}}(this.oe),this.be=null,this.pe="",this.ie=[],this.te=null,this.ge=!0,this.fe=null}async we(){return{whoami:this.name.replace(" ",""),scriptVersion:this.version,schemaVersion:this.de,templates:{}}}async ye(e,t,n){this.te||(this.te=await this.we(),console.log("Creating JSON...")),this.o.X(`Creating template at ${n.join(", ")}...`);const i=new x({displayName:t,J:0,j:l(this.ue||0,this.he),file:e,coords:n}),{K:o,Z:a}=await i.H(this.F,this.se);i.R=o;const r={total:i.V.total,colors:Object.fromEntries(i.V.colors)};this.te.templates[`${i.J} ${i.j}`]={name:i.displayName,coords:n.join(", "),enabled:!0,pixels:r,tiles:a},this.ie=[],this.ie.push(i),this.o.X(`Template created at ${n.join(", ")}!`),console.log(Object.keys(this.te.templates).length),console.log(this.te),console.log(this.ie),console.log(JSON.stringify(this.te)),await s(this,h,b).call(this)}ve(){}async xe(){this.te||(this.te=await this.we(),console.log("Creating JSON..."))}async Se(e,t){if(!this.ge)return e;const n=this.F*this.ne;t=t[0].toString().padStart(4,"0")+","+t[1].toString().padStart(4,"0"),console.log(`Searching for templates in tile: "${t}"`);const i=this.ie;console.log(i),i.sort((e,t)=>e.J-t.J),console.log(i);const o=i.map(e=>{const n=Object.keys(e.R).filter(e=>e.startsWith(t));if(0===n.length)return null;const i=n.map(t=>{const n=t.split(",");return{$e:e,Me:e.R[t],Y:e.Y?.[t],Te:[n[0],n[1]],De:[n[2],n[3]]}});return i?.[0]}).filter(Boolean);console.log(o);const a=o?.length||0;if(console.log(`templateCount = ${a}`),!(a>0))return this.o.X(`Sleeping\nVersion: ${this.version}`),e;{const e=i.filter(e=>Object.keys(e.R).filter(e=>e.startsWith(t)).length>0).reduce((e,t)=>e+(t.V.total||0),0),n=(new Intl.NumberFormat).format(e);this.o.X(`Displaying ${a} template${1==a?"":"s"}.\nTotal pixels: ${n}`)}const r=await createImageBitmap(e),l=new OffscreenCanvas(n,n),m=l.getContext("2d");m.imageSmoothingEnabled=!1,m.beginPath(),m.rect(0,0,n,n),m.clip(),m.clearRect(0,0,n,n),m.drawImage(r,0,0,n,n);const c=m.getImageData(0,0,n,n),d=new Uint32Array(c.data.buffer);for(const e of o){console.log("Template:"),console.log(e);let n=e.Y;const i=Number(e.De[0])*this.ne,o=Number(e.De[1])*this.ne;if(m.drawImage(e.Me,i,o),!n){const t=m.getImageData(i,o,e.Me.width,e.Me.height);n=new Uint32Array(t.data.buffer)}const a=Date.now(),r=s(this,h,g).call(this,d,n,[i,o,e.Me.width,e.Me.height]);let l=0;const c=0;for(const[e,t]of r)e!=c&&(l+=t);console.log(`Finished calculating correct pixels for the tile ${t} in ${(Date.now()-a)/1e3} seconds!\nThere are ${l} correct pixels.`),e.$e.V.correct=r}return await l.convertToBlob({type:"image/png"})}Oe(e){console.log("Importing JSON..."),console.log(e),"BlueMarble"==e?.whoami&&s(this,h,p).call(this,e)}ke(e){this.ge=e}}(S,$,O)),C=new class{constructor(e){o(this,f),this.Ce=e,this.Ne=!1,this.Be=[],this.Ie=[]}Le(e){window.addEventListener("message",async t=>{const n=t.data,i=n.jsonData;if(!n||"blue-marble"!==n.source)return;if(!n.endpoint)return;const o=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;","",o),o){case"me":if(i.status&&"2"!=i.status?.toString()[0])return void e.A("You are not logged in!\nCould not fetch userdata.");const t=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(l(i.id,"!#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~")),this.Ce.ue=i.id,e.L("bm-p",`Droplets: ${(new Intl.NumberFormat).format(i.droplets)}`),e.L("bm-i",`Next level in ${(new Intl.NumberFormat).format(t)} pixel${1==t?"":"s"}`);break;case"pixel":const o=n.endpoint.split("?")[0].split("/").filter(e=>e&&!isNaN(Number(e))),r=new URLSearchParams(n.endpoint.split("?")[1]),m=[r.get("x"),r.get("y")];if(this.Be.length&&(!o.length||!m.length))return void e.A("Coordinates are malformed!\nDid you try clicking the canvas first?");this.Be=[...o,...m];const c=(s=o,a=m,[parseInt(s[0])%4*1e3+parseInt(a[0]),parseInt(s[1])%4*1e3+parseInt(a[1])]),d=document.querySelectorAll("span");for(const e of d)if(e.textContent.trim().includes(`${c[0]}, ${c[1]}`)){let t=document.querySelector("#bm-h");const n=`(Tl X: ${o[0]}, Tl Y: ${o[1]}, Px X: ${m[0]}, Px Y: ${m[1]})`;t?t.textContent=n:(t=document.createElement("span"),t.id="bm-h",t.textContent=n,t.style="margin-left: calc(var(--spacing)*3); font-size: small;",e.parentNode.parentNode.insertAdjacentElement("afterend",t))}break;case"tiles":let u=n.endpoint.split("/");u=[parseInt(u[u.length-2]),parseInt(u[u.length-1].replace(".png",""))];const h=n.blobID,b=n.blobData,p=Date.now(),g=await this.Ce.Se(b,u);console.log(`Finished loading the tile in ${(Date.now()-p)/1e3} seconds!`),window.postMessage({source:"blue-marble",blobID:h,blobData:g,blink:n.blink});break;case"robots":this.Ne="false"==i.userscript?.toString().toLowerCase();break}var s,a})}async Pe(e){console.log("Sending heartbeat to telemetry server...");let t=GM_getValue("bmUserSettings","{}");if(t=JSON.parse(t),!t||!t.telemetry||!t.uuid)return void console.log("Telemetry is disabled, not sending heartbeat.");const n=navigator.userAgent;let i=await s(this,f,w).call(this,n),o=s(this,f,y).call(this,n);GM_xmlhttpRequest({method:"POST",url:"https://telemetry.thebluecorner.net/heartbeat",headers:{"Content-Type":"application/json"},data:JSON.stringify({uuid:t.uuid,version:e,browser:i,os:o}),onload:e=>{200!==e.status&&r("Failed to send heartbeat:",e.statusText)},onerror:e=>{r("Error sending heartbeat:",e)}})}}(k);O.u(C);var N=JSON.parse(GM_getValue("bmTemplates","{}"));console.log(N),k.Oe(N);var B=JSON.parse(GM_getValue("bmUserSettings","{}"));if(console.log(B),console.log(Object.keys(B).length),0==Object.keys(B).length){const e=crypto.randomUUID();console.log(e),GM.setValue("bmUserSettings",JSON.stringify({uuid:e}))}if(setInterval(()=>C.Pe($),18e5),console.log(`Telemetry is ${!(null==B?.telemetry)}`),null==B?.telemetry||B?.telemetry>1){const e=new a(S,$);e.u(C),e.v({id:"bm-d",style:"top: 0px; left: 0px; width: 100vw; max-width: 100vw; height: 100vh; max-height: 100vh; z-index: 9999;"}).v({id:"bm-7",style:"display: flex; flex-direction: column; align-items: center;"}).v({id:"bm-1",style:"margin-top: 10%;"}).O(1,{textContent:`${S} Telemetry`}).h().h().v({id:"bm-e",style:"max-width: 50%; overflow-y: auto; max-height: 80vh;"}).k().h().C().h().v({style:"width: fit-content; margin: auto; text-align: center;"}).B({id:"bm-8",textContent:"More Information"},(e,t)=>{t.onclick=()=>{window.open("https://github.com/SwingTheVine/Wplace-TelemetryServer#telemetry-data","_blank","noopener noreferrer")}}).h().h().C().h().v({style:"width: fit-content; margin: auto; text-align: center;"}).B({id:"bm-5",textContent:"Enable Telemetry",style:"margin-right: 2ch;"},(e,t)=>{t.onclick=()=>{const e=JSON.parse(GM_getValue("bmUserSettings","{}"));e.telemetry=1,GM.setValue("bmUserSettings",JSON.stringify(e));const t=document.getElementById("bm-d");t&&(t.style.display="none")}}).h().B({id:"bm-2",textContent:"Disable Telemetry"},(e,t)=>{t.onclick=()=>{const e=JSON.parse(GM_getValue("bmUserSettings","{}"));e.telemetry=0,GM.setValue("bmUserSettings",JSON.stringify(e));const t=document.getElementById("bm-d");t&&(t.style.display="none")}}).h().h().C().h().S({textContent:"We collect anonymous telemetry data such as your browser, OS, and script version to make the experience better for everyone. The data is never shared personally. The data is never sold. You can turn this off by pressing the 'Disable' button, but keeping it on helps us improve features and reliability faster. Thank you for supporting the Blue Marble!"}).h().S({textContent:'You can disable telemetry by pressing the "Disable" button below.'}).h().h().h().p(document.body)}O.v({id:"bm-W",class:"bm-16",style:"top: 10px; right: 75px;"}).v({class:"bm-14"}).v().B({class:"bm-T",textContent:"▼","aria-label":'Minimize window "Blue Marble"',"data-button-status":"expanded"},(e,t)=>{t.onclick=()=>e.U(t)}).h().h().h().v({class:"bm-O"}).v({class:"bm--"}).D({class:"bm-15",src:"https://raw.githubusercontent.com/SwingTheVine/Wplace-BlueMarble/main/dist/assets/Favicon.png"}).h().O(1,{textContent:S}).h().h().k().h().v({class:"bm--"}).S({id:"bm-p",textContent:"Droplets:"}).h().S({id:"bm-i",textContent:"Next level in..."}).h().h().k().h().v({class:"bm--"}).v({class:"bm--"}).B({class:"bm-T bm-Y",style:"margin-top: 0;",innerHTML:''},(e,t)=>{t.onclick=()=>{const t=e.t?.Be;t?.[0]?(e.L("bm-v",t?.[0]||""),e.L("bm-w",t?.[1]||""),e.L("bm-x",t?.[2]||""),e.L("bm-y",t?.[3]||"")):e.A("Coordinates are malformed! Did you try clicking on the canvas first?")}}).h().P({type:"number",id:"bm-v",class:"bm-U",placeholder:"Tl X",min:0,max:2047,step:1,required:!0},(e,t)=>{t.addEventListener("paste",e=>{let t=(e.clipboardData||window.clipboardData).getData("text").split(" ").filter(e=>e).map(Number).filter(e=>!isNaN(e));if(4!==t.length)return;let n=selectAllCoordinateInputs(document);for(let e=0;e{t.onclick=()=>{t.disabled=!0,"shown"==t.dataset.buttonStatus?(e.t?.Ce?.ke(!1),t.dataset.buttonStatus="hidden",t.textContent="Enable",e.X("Disabled templates!")):(e.t?.Ce?.ke(!0),t.dataset.buttonStatus="shown",t.textContent="Disable",e.X("Enabled templates!")),t.disabled=!1}}).h().B({textContent:"Create"},(e,t)=>{t.onclick=()=>{const t=document.querySelector("#bm-W button.bm-Z"),n=document.querySelector("#bm-v");if(!n.checkValidity())return n.reportValidity(),void e.A("Coordinates are malformed! Did you try clicking on the canvas first?");const i=document.querySelector("#bm-w");if(!i.checkValidity())return i.reportValidity(),void e.A("Coordinates are malformed! Did you try clicking on the canvas first?");const o=document.querySelector("#bm-x");if(!o.checkValidity())return o.reportValidity(),void e.A("Coordinates are malformed! Did you try clicking on the canvas first?");const s=document.querySelector("#bm-y");if(!s.checkValidity())return s.reportValidity(),void e.A("Coordinates are malformed! Did you try clicking on the canvas first?");t?.files[0]?(k.ye(t.files[0],t.files[0]?.name.replace(/\.[^/.]+$/,""),[Number(n.value),Number(i.value),Number(o.value),Number(s.value)]),e.X("Drew to canvas!")):e.A("No file selected!")}}).h().B({textContent:"Filter"},(e,t)=>{t.onclick=()=>{}}).h().h().v({class:"bm--"}).W({id:O.i,placeholder:`Status: Sleeping...\nVersion: ${$}`,readOnly:!0}).h().h().v({class:"bm-- bm-V",style:"margin-bottom: 0;"}).v({class:"bm-V"}).B({class:"bm-T",innerHTML:"🎨",title:"Template Color Converter"},(e,t)=>{t.onclick=()=>{window.open("https://pepoafonso.github.io/color_converter_wplace/","_blank","noopener noreferrer")}}).h().B({class:"bm-T",innerHTML:"🌐",title:"Official Blue Marble Website"},(e,t)=>{t.onclick=()=>{window.open("https://bluemarble.lol/","_blank","noopener noreferrer")}}).h().h().$({textContent:"Made by SwingTheVine",style:"margin-top: auto;"}).h().h().h().h().h().p(document.body),O._("#bm-W.bm-16","#bm-W .bm-14"),C.Le(O),new MutationObserver((e,t)=>{const n=document.querySelector("#color-1");if(!n)return;let i=document.querySelector("#bm-t");if(!i){i=document.createElement("button"),i.id="bm-t",i.textContent="Move ↑",i.className="btn btn-soft",i.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(i)}}).observe(document.body,{childList:!0,subtree:!0}),function(...e){(0,console.log)(...e)}(`%c${S}%c (${$}) userscript has loaded!`,"color: cornflowerblue;","")})();
\ No newline at end of file
diff --git a/docs/README.md b/docs/README.md
index c273dc8..6e5b23c 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -51,7 +51,7 @@
-
+
diff --git a/package-lock.json b/package-lock.json
index 4a1f3ba..fa30531 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "wplace-bluemarble",
- "version": "0.88.133",
+ "version": "0.88.144",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "wplace-bluemarble",
- "version": "0.88.133",
+ "version": "0.88.144",
"devDependencies": {
"esbuild": "^0.25.0",
"jsdoc": "^4.0.5",
diff --git a/package.json b/package.json
index eec9427..0165065 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "wplace-bluemarble",
- "version": "0.88.133",
+ "version": "0.88.144",
"type": "module",
"homepage": "https://bluemarble.lol/",
"repository": {
diff --git a/src/BlueMarble.meta.js b/src/BlueMarble.meta.js
index 98473b8..61b0d08 100644
--- a/src/BlueMarble.meta.js
+++ b/src/BlueMarble.meta.js
@@ -2,7 +2,7 @@
// @name Blue Marble
// @name:en Blue Marble
// @namespace https://github.com/SwingTheVine/
-// @version 0.88.133
+// @version 0.88.144
// @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.
// @description:en 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
diff --git a/src/Overlay.js b/src/Overlay.js
index 145aab1..73043a6 100644
--- a/src/Overlay.js
+++ b/src/Overlay.js
@@ -73,17 +73,50 @@ export default class Overlay {
// For every passed in property (shared by all like-elements), apply the it to the element
for (const [property, value] of Object.entries(properties)) {
- element[(property != 'class') ? property : 'className'] = value; // if the property is 'class', pass in 'className' instead
+ this.#applyAttribute(element, property, value);
}
// For every passed in additional property, apply the it to the element
for (const [property, value] of Object.entries(additionalProperties)) {
- element[(property != 'class') ? property : 'className'] = value; // if the property is 'class', pass in 'className' instead
+ this.#applyAttribute(element, property, value);
}
return element;
}
+ /** Applies an attribute to an element
+ * @param {HTMLElement} element - The element to apply the attribute to
+ * @param {String} property - The name of the attribute to apply
+ * @param {String} value - The value of the attribute
+ * @since 0.88.136
+ */
+ #applyAttribute(element, property, value) {
+ if (property == 'class') {
+ element.classList.add(...value.split(/\s+/)); // converts `'foo bar'` to `'foo', 'bar'` which is accepted
+ } else if (property == 'for') {
+ element.htmlFor = value;
+ } else if (property == 'tabindex') {
+ element.tabIndex = Number(value);
+ } else if (property == 'readonly') {
+ element.readOnly = ((value == 'true') || (value == '1'));
+ } else if (property == 'maxlength') {
+ element.maxLength = Number(value);
+ } else if (property.startsWith('data')) {
+ element.dataset[
+ property.slice(5).split('-').map(
+ (part, i) => (i == 0) ? part : part[0].toUpperCase() + part.slice(1)
+ ).join('')
+ ] = value;
+ } else if (property.startsWith('aria')) {
+ const camelCase = property.slice(5).split('-').map(
+ (part, i) => (i == 0) ? part : part[0].toUpperCase() + part.slice(1)
+ ).join('');
+ element['aria' + camelCase[0].toUpperCase() + camelCase.slice(1)] = value;
+ } else {
+ element[property] = value;
+ }
+ }
+
/** Finishes building an element.
* Call this after you are finished adding children.
* If the element will have no children, call it anyways.
@@ -505,6 +538,8 @@ export default class Overlay {
const properties = {
'type': 'file',
+ 'tabindex': '-1',
+ 'aria-hidden': 'true',
'style': 'display: none !important; visibility: hidden !important; position: absolute !important; left: -9999px !important; width: 0 !important; height: 0 !important; opacity: 0 !important;'
}; // Complete file input hiding to prevent native browser text interference
const text = additionalProperties['textContent'] ?? ''; // Retrieves the text content
@@ -519,8 +554,8 @@ export default class Overlay {
this.buildElement(); // Signifies that we are done adding children to the container
// Prevent file input from being accessible or visible by screen-readers and tabbing
- input.setAttribute('tabindex', '-1');
- input.setAttribute('aria-hidden', 'true');
+ //input.setAttribute('tabindex', '-1');
+ //input.setAttribute('aria-hidden', 'true');
button.addEventListener('click', () => {
input.click(); // Clicks the file input
@@ -592,6 +627,69 @@ export default class Overlay {
}
}
+ /** Handles the minimization logic for windows spawned by Blue Marble
+ * @param {HTMLButtonElement} button - The UI button that triggered this minimization event
+ * @since 0.88.142
+ */
+ handleMinimization(button) {
+
+ button.disabled = true; // Disables the button until the transition ends
+ button.style.textDecoration = 'none'; // Disables the disabled button text decoration strikethrough line
+
+ const window = button.closest('.bm-window'); // Get the window
+ const dragbar = button.closest('.bm-dragbar'); // Get the dragbar
+ const header = window.querySelector('h1'); // Get the header
+ const windowContent = window.querySelector('.bm-window-content'); // Get the window content container
+
+ // If window content is open...
+ if (button.dataset['buttonStatus'] == 'expanded') {
+ // ...we want to close it
+
+ // Makes a clone of the h1 element inside the window, and adds it to the dragbar
+ const dragbarHeader1 = header.cloneNode(true);
+ const dragbarHeader1Text = dragbarHeader1.textContent;
+ button.parentNode.appendChild(dragbarHeader1);
+
+ // Logic for the transition animation to collapse the window
+ windowContent.style.height = windowContent.scrollHeight + 'px';
+ window.style.width = window.scrollWidth + 'px'; // So the width of the window does not change due to the lack of content
+ windowContent.style.height = '0'; // Set the height to 0px
+ windowContent.addEventListener('transitionend', function handler() { // Add an event listener to cleanup once the minimize transition is complete
+ windowContent.style.display = 'none'; // Changes "display" to "none" for screen readers
+ button.disabled = false; // Enables the button
+ button.style.textDecoration = ''; // Resets the text decoration to default
+ windowContent.removeEventListener('transitionend', handler); // Removes the event listener
+ });
+
+ button.textContent = '▶'; // Swap button icon
+ button.dataset['buttonStatus'] = 'collapsed'; // Swap button status tracker
+ button.ariaLabel = `Unminimize window "${dragbarHeader1Text}"`; // Screen reader label
+ } else {
+ // Else, the window is closed, and we want to open it
+
+ // Deletes the h1 element inside the dragbar
+ const dragbarHeader1 = dragbar.querySelector('h1');
+ const dragbarHeader1Text = dragbarHeader1.textContent;
+ dragbarHeader1.remove();
+
+ // Logic for the transition animation to expand the window
+ windowContent.style.display = ''; // Resets display to default
+ windowContent.style.height = '0'; // Sets the height to 0
+ window.style.width = ''; // Resets the window width to default
+ windowContent.style.height = windowContent.scrollHeight + 'px'; // Change the height back to normal
+ windowContent.addEventListener('transitionend', function handler() { // Add an event listener to cleanup once the minimize transition is complete
+ windowContent.style.height = ''; // Changes the height back to default
+ button.disabled = false; // Enables the button
+ button.style.textDecoration = ''; // Resets the text decoration to default
+ windowContent.removeEventListener('transitionend', handler); // Removes the event listener
+ });
+
+ button.textContent = '▼'; // Swap button icon
+ button.dataset['buttonStatus'] = 'expanded'; // Swap button status tracker
+ button.ariaLabel = `Minimize window "${dragbarHeader1Text}"`; // Screen reader label
+ }
+ }
+
/** Handles dragging of the overlay.
* Uses requestAnimationFrame for smooth animations and GPU-accelerated transforms.
* Use the appropriate CSS selectors.
diff --git a/src/main.js b/src/main.js
index 4541897..9e5265c 100644
--- a/src/main.js
+++ b/src/main.js
@@ -276,36 +276,8 @@ function buildOverlayMain() {
overlayMain.addDiv({'id': 'bm-window-main', 'class': 'bm-window', 'style': 'top: 10px; right: 75px;'})
.addDiv({'class': 'bm-dragbar'})
.addDiv()
- .addButton({'class': 'bm-button-circle', 'textContent': '▼'}, (instance, button) => {
- button.onclick = () => {
- const window = button.closest('.bm-window'); // Get the window
- const dragbar = button.closest('.bm-dragbar'); // Get the dragbar
- const header = window.querySelector('h1'); // Get the header
- const windowContent = window.querySelector('.bm-window-content'); // Get the window content container
- if (button.textContent == '▼') { // If window content is open...
- const dragbarHeader1 = header.cloneNode(true); // Makes a copy of the header 1
- button.parentNode.appendChild(dragbarHeader1); // Adds the header to the dragbar
- windowContent.style.height = windowContent.scrollHeight + 'px';
- window.style.width = window.scrollWidth + 'px'; // So the width of the window does not change due to the lack of content
- windowContent.style.height = '0'; // Set the height to 0px
- windowContent.addEventListener('transitionend', function handler() { // Add an event listener to cleanup once the minimize transition is complete
- windowContent.style.display = 'none'; // Changes "display" to "none" for screen readers
- windowContent.removeEventListener('transitionend', handler); // Removes the event listener
- });
- } else { // Else, the window is closed
- const dragbarHeader1 = dragbar.querySelector('h1'); // Get the header 1
- dragbarHeader1.remove(); // Removes the dragbar header 1
- windowContent.style.display = ''; // Resets display to default
- windowContent.style.height = '0'; // Sets the height to 0
- window.style.width = ''; // Resets the window width to default
- windowContent.style.height = windowContent.scrollHeight + 'px'; // Change the height back to normal
- windowContent.addEventListener('transitionend', function handler() { // Add an event listener to cleanup once the minimize transition is complete
- windowContent.style.height = ''; // Changes the height back to default
- windowContent.removeEventListener('transitionend', handler); // Removes the event listener
- });
- }
- button.textContent = (button.textContent == '▼') ? '▶' : '▼'; // Swap button icon
- }
+ .addButton({'class': 'bm-button-circle', 'textContent': '▼', 'aria-label': 'Minimize window "Blue Marble"', 'data-button-status': 'expanded'}, (instance, button) => {
+ button.onclick = () => instance.handleMinimization(button);
}).buildElement()
.buildElement()
.buildElement()
@@ -350,40 +322,37 @@ function buildOverlayMain() {
}
event.preventDefault(); //prevent the pasting of the original paste that would overide the split value
})
- const handler = () => persistCoords();
- input.addEventListener('input', handler);
- input.addEventListener('change', handler);
- }).buildElement()
- .addInput({'type': 'number', 'id': 'bm-input-ty', 'class': 'bm-input-coords', 'placeholder': 'Tl Y', 'min': 0, 'max': 2047, 'step': 1, 'required': true}, (instance, input) => {
- const handler = () => persistCoords();
- input.addEventListener('input', handler);
- input.addEventListener('change', handler);
- }).buildElement()
- .addInput({'type': 'number', 'id': 'bm-input-px', 'class': 'bm-input-coords', 'placeholder': 'Px X', 'min': 0, 'max': 2047, 'step': 1, 'required': true}, (instance, input) => {
- const handler = () => persistCoords();
- input.addEventListener('input', handler);
- input.addEventListener('change', handler);
- }).buildElement()
- .addInput({'type': 'number', 'id': 'bm-input-py', 'class': 'bm-input-coords', 'placeholder': 'Px Y', 'min': 0, 'max': 2047, 'step': 1, 'required': true}, (instance, input) => {
- const handler = () => persistCoords();
- input.addEventListener('input', handler);
- input.addEventListener('change', handler);
}).buildElement()
+ .addInput({'type': 'number', 'id': 'bm-input-ty', 'class': 'bm-input-coords', 'placeholder': 'Tl Y', 'min': 0, 'max': 2047, 'step': 1, 'required': true}).buildElement()
+ .addInput({'type': 'number', 'id': 'bm-input-px', 'class': 'bm-input-coords', 'placeholder': 'Px X', 'min': 0, 'max': 2047, 'step': 1, 'required': true}).buildElement()
+ .addInput({'type': 'number', 'id': 'bm-input-py', 'class': 'bm-input-coords', 'placeholder': 'Px Y', 'min': 0, 'max': 2047, 'step': 1, 'required': true}).buildElement()
.buildElement()
.addDiv({'class': 'bm-container'})
.addInputFile({'class': 'bm-input-file', 'textContent': 'Upload Template', 'accept': 'image/png, image/jpeg, image/webp, image/bmp, image/gif'}).buildElement()
.buildElement()
.addDiv({'class': 'bm-container bm-flex-between'})
- .addButton({'textContent': 'Enable'}, (instance, button) => {
+ .addButton({'textContent': 'Disable', 'data-button-status': 'shown'}, (instance, button) => {
button.onclick = () => {
- instance.apiManager?.templateManager?.setTemplatesShouldBeDrawn(true);
- instance.handleDisplayStatus(`Enabled templates!`);
+ button.disabled = true; // Disables the button until the transition ends
+ if (button.dataset['buttonStatus'] == 'shown') { // If templates are currently being 'shown' then hide them
+ instance.apiManager?.templateManager?.setTemplatesShouldBeDrawn(false); // Disables templates from being drawn
+ button.dataset['buttonStatus'] = 'hidden'; // Swap internal button status tracker
+ button.textContent = 'Enable'; // Swap button text
+ instance.handleDisplayStatus(`Disabled templates!`); // Inform the user
+ } else { // In all other cases, we should show templates instead of hiding them
+ instance.apiManager?.templateManager?.setTemplatesShouldBeDrawn(true); // Allows templates to be drawn
+ button.dataset['buttonStatus'] = 'shown'; // Swap internal button status tracker
+ button.textContent = 'Disable'; // Swap button text
+ instance.handleDisplayStatus(`Enabled templates!`); // Inform the user
+ }
+ button.disabled = false; // Enables the button
}
}).buildElement()
.addButton({'textContent': 'Create'}, (instance, button) => {
button.onclick = () => {
const input = document.querySelector('#bm-window-main button.bm-input-file');
+ // Checks to see if the coordinates are valid. Throws an error if they are not
const coordTlX = document.querySelector('#bm-input-tx');
if (!coordTlX.checkValidity()) {coordTlX.reportValidity(); instance.handleDisplayError('Coordinates are malformed! Did you try clicking on the canvas first?'); return;}
const coordTlY = document.querySelector('#bm-input-ty');
@@ -400,10 +369,9 @@ function buildOverlayMain() {
instance.handleDisplayStatus(`Drew to canvas!`);
}
}).buildElement()
- .addButton({'textContent': 'Disable'}, (instance, button) => {
+ .addButton({'textContent': 'Filter'}, (instance, button) => {
button.onclick = () => {
- instance.apiManager?.templateManager?.setTemplatesShouldBeDrawn(false);
- instance.handleDisplayStatus(`Disabled templates!`);
+
}
}).buildElement()
.buildElement()
@@ -413,17 +381,15 @@ function buildOverlayMain() {
.addDiv({'class': 'bm-container bm-flex-between', 'style': 'margin-bottom: 0;'})
.addDiv({'class': 'bm-flex-between'})
// .addButton({'class': 'bm-button-circle', 'innerHTML': '🖌'}).buildElement()
- .addButton({'class': 'bm-button-circle', 'innerHTML': '🎨', 'title': 'Template Color Converter'},
- (instance, button) => {
- button.addEventListener('click', () => {
+ .addButton({'class': 'bm-button-circle', 'innerHTML': '🎨', 'title': 'Template Color Converter'}, (instance, button) => {
+ button.onclick = () => {
window.open('https://pepoafonso.github.io/color_converter_wplace/', '_blank', 'noopener noreferrer');
- });
+ }
}).buildElement()
- .addButton({'class': 'bm-button-circle', 'innerHTML': '🌐', 'title': 'Official Blue Marble Website'},
- (instance, button) => {
- button.addEventListener('click', () => {
+ .addButton({'class': 'bm-button-circle', 'innerHTML': '🌐', 'title': 'Official Blue Marble Website'}, (instance, button) => {
+ button.onclick = () => {
window.open('https://bluemarble.lol/', '_blank', 'noopener noreferrer');
- });
+ }
}).buildElement()
.buildElement()
.addSmall({'textContent': 'Made by SwingTheVine', 'style': 'margin-top: auto;'}).buildElement()
@@ -431,345 +397,6 @@ function buildOverlayMain() {
.buildElement()
.buildElement()
.buildElement().buildOverlay(document.body);
-
-
- // let isMinimized = false; // Overlay state tracker (false = maximized, true = minimized)
-
- // overlayMain.addDiv({'id': 'bm-overlay', 'style': 'top: 10px; right: 75px;'})
- // .addDiv({'id': 'bm-contain-header'})
- // .addDiv({'id': 'bm-bar-drag'}).buildElement()
- // .addImg({'alt': 'Blue Marble Icon - Click to minimize/maximize', 'src': 'https://raw.githubusercontent.com/SwingTheVine/Wplace-BlueMarble/main/dist/assets/Favicon.png', 'style': 'cursor: pointer;'},
- // (instance, img) => {
- // /** Click event handler for overlay minimize/maximize functionality.
- // *
- // * Toggles between two distinct UI states:
- // * 1. MINIMIZED STATE (60×76px):
- // * - Shows only the Blue Marble icon and drag bar
- // * - Hides all input fields, buttons, and status information
- // * - Applies fixed dimensions for consistent appearance
- // * - Repositions icon with 3px right offset for visual centering
- // *
- // * 2. MAXIMIZED STATE (responsive):
- // * - Restores full functionality with all UI elements
- // * - Removes fixed dimensions to allow responsive behavior
- // * - Resets icon positioning to default alignment
- // * - Shows success message when returning to maximized state
- // *
- // * @param {Event} event - The click event object (implicit)
- // */
- // img.addEventListener('click', () => {
- // isMinimized = !isMinimized; // Toggle the current state
-
- // const overlay = document.querySelector('#bm-overlay');
- // const header = document.querySelector('#bm-contain-header');
- // const dragBar = document.querySelector('#bm-bar-drag');
- // const coordsContainer = document.querySelector('#bm-contain-coords');
- // const coordsButton = document.querySelector('#bm-button-coords');
- // const createButton = document.querySelector('#bm-button-create');
- // const enableButton = document.querySelector('#bm-button-enable');
- // const disableButton = document.querySelector('#bm-button-disable');
- // const coordInputs = document.querySelectorAll('#bm-contain-coords input');
-
- // // Pre-restore original dimensions when switching to maximized state
- // // This ensures smooth transition and prevents layout issues
- // if (!isMinimized) {
- // overlay.style.width = "auto";
- // overlay.style.maxWidth = "300px";
- // overlay.style.minWidth = "200px";
- // overlay.style.padding = "10px";
- // }
-
- // // Define elements that should be hidden/shown during state transitions
- // // Each element is documented with its purpose for maintainability
- // const elementsToToggle = [
- // '#bm-overlay h1', // Main title "Blue Marble"
- // '#bm-contain-userinfo', // User information section (username, droplets, level)
- // '#bm-overlay hr', // Visual separator lines
- // '#bm-contain-automation > *:not(#bm-contain-coords)', // Automation section excluding coordinates
- // '#bm-input-file-template', // Template file upload interface
- // '#bm-contain-buttons-action', // Action buttons container
- // `#${instance.outputStatusId}`, // Status log textarea for user feedback
- // ];
-
- // // Apply visibility changes to all toggleable elements
- // elementsToToggle.forEach(selector => {
- // const elements = document.querySelectorAll(selector);
- // elements.forEach(element => {
- // element.style.display = isMinimized ? 'none' : '';
- // });
- // });
- // // Handle coordinate container and button visibility based on state
- // if (isMinimized) {
- // // ==================== MINIMIZED STATE CONFIGURATION ====================
- // // In minimized state, we hide ALL interactive elements except the icon and drag bar
- // // This creates a clean, unobtrusive interface that maintains only essential functionality
-
- // // Hide coordinate input container completely
- // if (coordsContainer) {
- // coordsContainer.style.display = 'none';
- // }
-
- // // Hide coordinate button (pin icon)
- // if (coordsButton) {
- // coordsButton.style.display = 'none';
- // }
-
- // // Hide create template button
- // if (createButton) {
- // createButton.style.display = 'none';
- // }
-
- // // Hide enable templates button
- // if (enableButton) {
- // enableButton.style.display = 'none';
- // }
-
- // // Hide disable templates button
- // if (disableButton) {
- // disableButton.style.display = 'none';
- // }
-
- // // Hide all coordinate input fields individually (failsafe)
- // coordInputs.forEach(input => {
- // input.style.display = 'none';
- // });
-
- // // Apply fixed dimensions for consistent minimized appearance
- // // These dimensions were chosen to accommodate the icon while remaining compact
- // overlay.style.width = '60px'; // Fixed width for consistency
- // overlay.style.height = '76px'; // Fixed height (60px + 16px for better proportions)
- // overlay.style.maxWidth = '60px'; // Prevent expansion
- // overlay.style.minWidth = '60px'; // Prevent shrinking
- // overlay.style.padding = '8px'; // Comfortable padding around icon
-
- // // Apply icon positioning for better visual centering in minimized state
- // // The 3px offset compensates for visual weight distribution
- // img.style.marginLeft = '3px';
-
- // // Configure header layout for minimized state
- // header.style.textAlign = 'center';
- // header.style.margin = '0';
- // header.style.marginBottom = '0';
-
- // // Ensure drag bar remains visible and properly spaced
- // if (dragBar) {
- // dragBar.style.display = '';
- // dragBar.style.marginBottom = '0.25em';
- // }
- // } else {
- // // ==================== MAXIMIZED STATE RESTORATION ====================
- // // In maximized state, we restore all elements to their default functionality
- // // This involves clearing all style overrides applied during minimization
-
- // // Restore coordinate container to default state
- // if (coordsContainer) {
- // coordsContainer.style.display = ''; // Show container
- // coordsContainer.style.flexDirection = ''; // Reset flex layout
- // coordsContainer.style.justifyContent = ''; // Reset alignment
- // coordsContainer.style.alignItems = ''; // Reset alignment
- // coordsContainer.style.gap = ''; // Reset spacing
- // coordsContainer.style.textAlign = ''; // Reset text alignment
- // coordsContainer.style.margin = ''; // Reset margins
- // }
-
- // // Restore coordinate button visibility
- // if (coordsButton) {
- // coordsButton.style.display = '';
- // }
-
- // // Restore create button visibility and reset positioning
- // if (createButton) {
- // createButton.style.display = '';
- // createButton.style.marginTop = '';
- // }
-
- // // Restore enable button visibility and reset positioning
- // if (enableButton) {
- // enableButton.style.display = '';
- // enableButton.style.marginTop = '';
- // }
-
- // // Restore disable button visibility and reset positioning
- // if (disableButton) {
- // disableButton.style.display = '';
- // disableButton.style.marginTop = '';
- // }
-
- // // Restore all coordinate input fields
- // coordInputs.forEach(input => {
- // input.style.display = '';
- // });
-
- // // Reset icon positioning to default (remove minimized state offset)
- // img.style.marginLeft = '';
-
- // // Restore overlay to responsive dimensions
- // overlay.style.padding = '10px';
-
- // // Reset header styling to defaults
- // header.style.textAlign = '';
- // header.style.margin = '';
- // header.style.marginBottom = '';
-
- // // Reset drag bar spacing
- // if (dragBar) {
- // dragBar.style.marginBottom = '0.5em';
- // }
-
- // // Remove all fixed dimensions to allow responsive behavior
- // // This ensures the overlay can adapt to content changes
- // overlay.style.width = '';
- // overlay.style.height = '';
- // }
-
- // // ==================== ACCESSIBILITY AND USER FEEDBACK ====================
- // // Update accessibility information for screen readers and tooltips
-
- // // Update alt text to reflect current state for screen readers and tooltips
- // img.alt = isMinimized ?
- // 'Blue Marble Icon - Minimized (Click to maximize)' :
- // 'Blue Marble Icon - Maximized (Click to minimize)';
-
- // // No status message needed - state change is visually obvious to users
- // });
- // }
- // ).buildElement()
- // .addHeader(1, {'textContent': name}).buildElement()
- // .buildElement()
-
- // .addHr().buildElement()
-
- // .addDiv({'id': 'bm-contain-userinfo'})
- // .addP({'id': 'bm-user-droplets', 'textContent': 'Droplets:'}).buildElement()
- // .addP({'id': 'bm-user-nextlevel', 'textContent': 'Next level in...'}).buildElement()
- // .buildElement()
-
- // .addHr().buildElement()
-
- // .addDiv({'id': 'bm-contain-automation'})
- // // .addCheckbox({'id': 'bm-input-stealth', 'textContent': 'Stealth', 'checked': true}).buildElement()
- // // .addButtonHelp({'title': 'Waits for the website to make requests, instead of sending requests.'}).buildElement()
- // // .addBr().buildElement()
- // // .addCheckbox({'id': 'bm-input-possessed', 'textContent': 'Possessed', 'checked': true}).buildElement()
- // // .addButtonHelp({'title': 'Controls the website as if it were possessed.'}).buildElement()
- // // .addBr().buildElement()
- // .addDiv({'id': 'bm-contain-coords'})
- // .addButton({'id': 'bm-button-coords', 'className': 'bm-help', 'style': 'margin-top: 0;', 'innerHTML': ''},
- // (instance, button) => {
- // button.onclick = () => {
- // const coords = instance.apiManager?.coordsTilePixel; // Retrieves the coords from the API manager
- // if (!coords?.[0]) {
- // instance.handleDisplayError('Coordinates are malformed! Did you try clicking on the canvas first?');
- // return;
- // }
- // instance.updateInnerHTML('bm-input-tx', coords?.[0] || '');
- // instance.updateInnerHTML('bm-input-ty', coords?.[1] || '');
- // instance.updateInnerHTML('bm-input-px', coords?.[2] || '');
- // instance.updateInnerHTML('bm-input-py', coords?.[3] || '');
- // }
- // }
- // ).buildElement()
- // .addInput({'type': 'number', 'id': 'bm-input-tx', 'placeholder': 'Tl X', 'min': 0, 'max': 2047, 'step': 1, 'required': true}, (instance, input) => {
- // //if a paste happens on tx, split and format it into other coordinates if possible
- // input.addEventListener("paste", (event) => {
- // let splitText = (event.clipboardData || window.clipboardData).getData("text").split(" ").filter(n => n).map(Number).filter(n => !isNaN(n)); //split and filter all Non Numbers
-
- // if (splitText.length !== 4 ) { // If we don't have 4 clean coordinates, end the function.
- // return;
- // }
-
- // let coords = selectAllCoordinateInputs(document);
-
- // for (let i = 0; i < coords.length; i++) {
- // coords[i].value = splitText[i]; //add the split vales
- // }
-
- // event.preventDefault(); //prevent the pasting of the original paste that would overide the split value
- // })
- // const handler = () => persistCoords();
- // input.addEventListener('input', handler);
- // input.addEventListener('change', handler);
- // }).buildElement()
- // .addInput({'type': 'number', 'id': 'bm-input-ty', 'placeholder': 'Tl Y', 'min': 0, 'max': 2047, 'step': 1, 'required': true}, (instance, input) => {
- // const handler = () => persistCoords();
- // input.addEventListener('input', handler);
- // input.addEventListener('change', handler);
- // }).buildElement()
- // .addInput({'type': 'number', 'id': 'bm-input-px', 'placeholder': 'Px X', 'min': 0, 'max': 2047, 'step': 1, 'required': true}, (instance, input) => {
- // const handler = () => persistCoords();
- // input.addEventListener('input', handler);
- // input.addEventListener('change', handler);
- // }).buildElement()
- // .addInput({'type': 'number', 'id': 'bm-input-py', 'placeholder': 'Px Y', 'min': 0, 'max': 2047, 'step': 1, 'required': true}, (instance, input) => {
- // const handler = () => persistCoords();
- // input.addEventListener('input', handler);
- // input.addEventListener('change', handler);
- // }).buildElement()
- // .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');
-
- // const coordTlX = document.querySelector('#bm-input-tx');
- // if (!coordTlX.checkValidity()) {coordTlX.reportValidity(); instance.handleDisplayError('Coordinates are malformed! Did you try clicking on the canvas first?'); return;}
- // const coordTlY = document.querySelector('#bm-input-ty');
- // if (!coordTlY.checkValidity()) {coordTlY.reportValidity(); instance.handleDisplayError('Coordinates are malformed! Did you try clicking on the canvas first?'); return;}
- // const coordPxX = document.querySelector('#bm-input-px');
- // if (!coordPxX.checkValidity()) {coordPxX.reportValidity(); instance.handleDisplayError('Coordinates are malformed! Did you try clicking on the canvas first?'); return;}
- // const coordPxY = document.querySelector('#bm-input-py');
- // if (!coordPxY.checkValidity()) {coordPxY.reportValidity(); instance.handleDisplayError('Coordinates are malformed! Did you try clicking on the canvas first?'); return;}
-
- // // Kills itself if there is no file
- // if (!input?.files[0]) {instance.handleDisplayError(`No file selected!`); return;}
-
- // templateManager.createTemplate(input.files[0], input.files[0]?.name.replace(/\.[^/.]+$/, ''), [Number(coordTlX.value), Number(coordTlY.value), Number(coordPxX.value), Number(coordPxY.value)]);
-
- // // console.log(`TCoords: ${apiManager.templateCoordsTilePixel}\nCoords: ${apiManager.coordsTilePixel}`);
- // // apiManager.templateCoordsTilePixel = apiManager.coordsTilePixel; // Update template coords
- // // console.log(`TCoords: ${apiManager.templateCoordsTilePixel}\nCoords: ${apiManager.coordsTilePixel}`);
- // // templateManager.setTemplateImage(input.files[0]);
-
- // instance.handleDisplayStatus(`Drew to canvas!`);
- // }
- // }).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': overlayMain.outputStatusId, 'placeholder': `Status: Sleeping...\nVersion: ${version}`, 'readOnly': true}).buildElement()
- // .addDiv({'id': 'bm-contain-buttons-action'})
- // .addDiv()
- // // .addButton({'id': 'bm-button-teleport', 'className': 'bm-help', 'textContent': '✈'}).buildElement()
- // // .addButton({'id': 'bm-button-favorite', 'className': 'bm-help', 'innerHTML': ''}).buildElement()
- // // .addButton({'id': 'bm-button-templates', 'className': 'bm-help', 'innerHTML': '🖌'}).buildElement()
- // .addButton({'id': 'bm-button-convert', 'className': 'bm-help', 'innerHTML': '🎨', 'title': 'Template Color Converter'},
- // (instance, button) => {
- // button.addEventListener('click', () => {
- // window.open('https://pepoafonso.github.io/color_converter_wplace/', '_blank', 'noopener noreferrer');
- // });
- // }).buildElement()
- // .addButton({'id': 'bm-button-website', 'className': 'bm-help', 'innerHTML': '🌐', 'title': 'Official Blue Marble Website'},
- // (instance, button) => {
- // button.addEventListener('click', () => {
- // window.open('https://bluemarble.lol/', '_blank', 'noopener noreferrer');
- // });
- // }).buildElement()
- // .buildElement()
- // .addSmall({'textContent': 'Made by SwingTheVine', 'style': 'margin-top: auto;'}).buildElement()
- // .buildElement()
- // .buildElement()
- // .buildOverlay(document.body);
}
function buildTelemetryOverlay(overlay) {