您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Script for OWOP
当前为
// ==UserScript== // @name Neko's Scripts // @namespace http://tampermonkey.net/ // @version 0.12.2 // @description Script for OWOP // @author Neko // @match https://ourworldofpixels.com/* // @exclude https://ourworldofpixels.com/api* // @run-at document-start // @icon https://www.google.com/s2/favicons?sz=64&domain=ourworldofpixels.com // @grant none // @unwrap // ==/UserScript== 'use strict'; /*global OWOP*/ const NS = {}; if (window) window.NS = NS; { // Thanks Lapis NS.modules = []; let originalFunction = Object.defineProperty; Object.defineProperty = function (object, property, info) { let x = originalFunction(object, property, info); if (!object["__esModule"]) return x; NS.modules.push(object); if (NS.modules.length === 43) Object.defineProperty = originalFunction; return x; } 0, 13, 14, 15, 16, 20, 22, 21, 23, 24, 25; // Thanks again Lapis } { let k = EventTarget.prototype.addEventListener; EventTarget._eventlists = []; EventTarget.prototype.addEventListener = function (r, i, e) { if (EventTarget._eventlists) EventTarget._eventlists.push(i); return k.bind(this)(...arguments) }; let l = EventTarget.prototype.removeEventListener; EventTarget.prototype.removeEventListener = function () { return l.bind(this)(...arguments); }; } function install() { "use strict"; class Point { constructor(x, y) { this.x = x; this.y = y; } static distance(p1, p2) { if (p1 instanceof Point && p2 instanceof Point) return Math.sqrt((p1.x - p2.x) ** 2 + (p1.y - p2.y) ** 2); } } class BPoint extends Point { constructor(x, y) { super(x, y); this.bottom = false; this.right = false; } static check(bp1, bp2, direction) { let p1 = NS.PM.queue[`${bp1.x},${bp1.y}`]; let p2 = NS.PM.queue[`${bp2.x},${bp2.y}`]; let d = false; if ((!!p1 && !p2) || (!p1 && !!p2)) d = true; return bp1[direction] = d; } } class Color { static compare(c1, c2) { return (c1[0] == c2[0] && c1[1] == c2[1] && c1[2] == c2[2]); } } class Pixel extends Point { constructor(x, y, c, o = false) { super(x, y); this.c = c; this.o = o; this.placed = false; } static compare(p1, p2) { return (p1.x == p2.x && p1.y == p2.y) && Color.compare(p1.c, p2.c); } } class Action { constructor(p1, p2) { this.x = p1.x; this.y = p1.y; this.before_color = p1.c; this.after_color = p2.c; } undo() { return this.before_color; } redo() { return this.after_color; } } class PixelManager { constructor() { this.undoStack = []; this.redoStack = []; this.actionStack = {}; this.record = false; this.queue = {}; this.chunkQueueTemp = {}; this.border = {}; this.borderCheck = true; this.renderBorder = false; this.autoMove = false; this.whitelist = {}; this.enabled = true; this.extra = {}; this.extra.placeData = []; let p1 = new Point(0, 0); for (let y = -47; y < 47; y++) { for (let x = -47; x < 47; x++) { let p2 = new Point(x, y); let d = Point.distance(p1, p2); // d = Math.random(); this.extra.placeData.push([d, p2]); } } this.extra.placeData.sort((a, b) => { return a[0] - b[0]; }); NS.M14.eventSys.addListener(NS.M13.EVENTS.tick, () => NS.PM.enabled ? NS.PM.placePixel() : void 0); NS.M14.eventSys.addListener(NS.M13.EVENTS.net.world.tilesUpdated, function (message) { for (let i = 0; i < message.length; i++) { let p = message[i]; let placedColor = [(p.rgb & (255 << 0)) >> 0, (p.rgb & (255 << 8)) >> 8, (p.rgb & (255 << 16)) >> 16]; if (Object.keys(NS.PM.whitelist).includes(`${p.id}`)) NS.PM.setPixel(p.x, p.y, placedColor); let pixel = NS.PM.queue[`${p.x},${p.y}`]; if (pixel) (NS.PM.borderCheck = true, pixel.placed = false, NS.PM.updateBorder(p.x, p.y)); } }); NS.M14.eventSys.addListener(NS.M13.EVENTS.net.world.leave, function () { OWOP.sounds.play(OWOP.sounds.launch); NS.PM.disable(); this.border = {}; console.log(arguments, "leave"); }); NS.M14.eventSys.addListener(NS.M13.EVENTS.net.world.join, function () { NS.PM.enable(); console.log(arguments, "join"); }); } moveToNext() { if (!this.autoMove) return; if (!this.borderCheck) return; for (let e in this.chunkQueueTemp) { if (this.chunkQueueTemp[e]) { let [x, y] = e.split(","); for (let i = 0; i < 16; i++) { for (let j = 0; j < 16; j++) { if (this.queue[`${x * 16 + i},${y * 16 + j}`]?.placed === false) return NS.M20.centerCameraTo(x * 16 + i, y * 16 + j); } } this.chunkQueueTemp[e] = false; } } this.borderCheck = false; } updateBorder(x, y) { let p = this.border[`${x},${y}`]; if (!p) p = this.border[`${x},${y}`] = new BPoint(x, y); let t = this.border[`${x},${y - 1}`]; let l = this.border[`${x - 1},${y}`]; let b = this.border[`${x},${y + 1}`]; let r = this.border[`${x + 1},${y}`]; if (!t) t = new BPoint(x, y - 1); if (!l) l = new BPoint(x - 1, y); if (!b) b = new BPoint(x, y + 1); if (!r) r = new BPoint(x + 1, y); if (BPoint.check(t, p, "bottom") && (t.bottom || t.right)) this.border[`${x},${y - 1}`] = t; if (BPoint.check(l, p, "right") && (l.bottom || l.right)) this.border[`${x - 1},${y}`] = l; if (BPoint.check(p, b, "bottom") && (b.bottom || b.right)) this.border[`${x},${y + 1}`] = b; if (BPoint.check(p, r, "right") && (r.bottom || r.right)) this.border[`${x + 1},${y}`] = r; } undo() { if (!this.enabled) return; if (!this.undoStack.length) return; let action = this.undoStack.pop(); for (let e in action) { let e2 = action[e]; if (!this.queue[`${e2.x},${e2.y}`] && (delete action[e], true)) continue; this.setPixel(e2.x, e2.y, e2.undo()); // console.log(e2.x, e2.y, e2.undo()); } if (!Object.keys(action).length) { this.undo(); return; } this.redoStack.push(action); } redo() { if (!this.enabled) return; if (!this.redoStack.length) return; let action = this.redoStack.pop(); for (let e in action) { let e2 = action[e]; if (!this.queue[`${e2.x},${e2.y}`] && (delete action[e], true)) continue; this.setPixel(e2.x, e2.y, e2.redo()); // console.log(e2.x, e2.y, e2.redo()); } if (!Object.keys(action).length) { this.redo(); return; } this.undoStack.push(action); } startHistory() { this.record = true; } endHistory() { if (!this.record) return; this.record = false; if (Object.keys(this.actionStack).length) this.undoStack.push(this.actionStack); this.actionStack = {}; this.redoStack = []; } enable() { this.enabled = true; } disable() { this.enabled = false; } clearQueue() { this.queue = {}; this.chunkQueueTemp = {}; this.border = {}; } unsetPixel(x, y) { let p = new Point(x, y); this.deletePixels(p); return true; } deletePixels() { for (let i = 0; i < arguments.length; i++) { if (Array.isArray(arguments[i])) this.deletePixels(arguments[i]); else if (arguments[i] instanceof Point) { delete this.queue[`${arguments[i].x},${arguments[i].y}`]; let x = Math.floor(arguments[i].x / 16); let y = Math.floor(arguments[i].y / 16); let found = false; for (let i = 0; i < 16; i++) { for (let j = 0; j < 16; j++) { if (this.queue[`${x * 16 + i},${y * 16 + j}`]) { found = true; break; } } if (found) break; } if (!found) delete this.chunkQueueTemp[`${x},${y}`]; this.updateBorder(arguments[i].x, arguments[i].y); } } } setPixel(x, y, c, placeOnce = false) { // make checks for all variables coming in to make sure nothing is incorrectly set and c 4th element is either undefined or 255 otherwise drop the set if (!this.enabled) { OWOP.world.setPixel(x, y, c); return; } if (!Number.isInteger(x) || !Number.isInteger(y)) return false; if (!Array.isArray(c) || c.length < 3 || c.length > 4) return false; if (c.length == 4) c.pop(); if (c.find(e => !Number.isInteger(e) || e < 0 || e > 255) !== undefined) return false; let p = new Pixel(x, y, c); if (placeOnce) p.o = true; let xchunk = Math.floor(p.x / 16); let ychunk = Math.floor(p.y / 16); if (NS.M0.misc.world.protectedChunks[`${xchunk},${ychunk}`]) return false; if (this.record) { let stackE = this.actionStack[`${x},${y}`]; if (!(stackE instanceof Action)) { let bp = new Pixel(x, y, this.getPixel(x, y, 1)); if (bp.c !== p.c) this.actionStack[`${x},${y}`] = new Action(bp, p); } else if (stackE.after_color !== c) { stackE.after_color = c; } } this.addPixels(p); return true; } getPixel(x, y, a = 1) { if (!Number.isInteger(x) || !Number.isInteger(y)) return console.error("There is no inputs in \"getPixel\" on PixelManager instance."); // if (!Object.keys(OWOP.world).includes("_getPixel")) return undefined; if (a && this.queue[`${x},${y}`]) return this.queue[`${x},${y}`].c; try { OWOP.world.getPixel; } catch (e) { return undefined; } return OWOP.world.getPixel(x, y); } addPixels() { for (let i = 0; i < arguments.length; i++) { if (Array.isArray(arguments[i])) this.addPixels(arguments[i]); else if (arguments[i] instanceof Pixel) { this.queue[`${arguments[i].x},${arguments[i].y}`] = arguments[i]; let x = Math.floor(arguments[i].x / 16); let y = Math.floor(arguments[i].y / 16); this.chunkQueueTemp[`${x},${y}`] = true; this.updateBorder(arguments[i].x, arguments[i].y); this.borderCheck = true; } } } placePixel() { let totalPlaced = 0; for (let i = 0; i < this.extra.placeData.length; i++) { let e = this.extra.placeData[i][1]; let tX = OWOP.mouse.tileX; let tY = OWOP.mouse.tileY; let pixel = this.queue[`${tX + e.x},${tY + e.y}`]; if (!pixel) continue; let xchunk = Math.floor(pixel.x / 16); let ychunk = Math.floor(pixel.y / 16); if (NS.M0.misc.world.protectedChunks[`${xchunk},${ychunk}`]) continue; let xcc = Math.floor(tX / 16) * 16; let ycc = Math.floor(tY / 16) * 16; if (pixel.x < (xcc - 31) || pixel.y < (ycc - 31) || pixel.x > (xcc + 46) || pixel.y > (ycc + 46)) continue; let c = this.getPixel(pixel.x, pixel.y, 0); if (!c) continue; if (!Color.compare(pixel.c, c)) { if (!OWOP.world.setPixel(pixel.x, pixel.y, pixel.c) || (++totalPlaced === 5, pixel.placed = true, false)) return; } else if ((pixel.o && this.deletePixels(pixel), pixel.placed = true, true)) continue; } this.moveToNext(); } } const modulo = (i, m) => { return i - m * Math.floor(i / m); } const line = (x1, y1, x2, y2, m, e, plot) => { if (x1 === undefined || y1 === undefined || x2 === undefined || y2 === undefined) return console.error(); var dx = Math.abs(x2 - x1), sx = x1 < x2 ? 1 : -1; var dy = -Math.abs(y2 - y1), sy = y1 < y2 ? 1 : -1; var err = dx + dy, e2; if (e?.type == "mousemove") { if (x1 == x2 && y1 == y2) return; e2 = 2 * err; if (e2 >= dy) { err += dy; x1 += sx; } if (e2 <= dx) { err += dx; y1 += sy; } } var i = 0; while (true) { plot(x1, y1, i); i++; if (x1 == x2 && y1 == y2) break; e2 = 2 * err; if (e2 >= dy) { err += dy; x1 += sx; } if (e2 <= dx) { err += dx; y1 += sy; } } return [i]; } NS.modulo = modulo; NS.line = line; NS.Point = Point; NS.Color = Color; NS.Pixel = Pixel; NS.PixelManager = PixelManager; const PM = new PixelManager(); NS.PM = PM; NS.localStorage = localStorage.NS; if (!NS.localStorage) { localStorage.NS = JSON.stringify({}); NS.localStorage = localStorage.NS; } NS.localStorage = JSON.parse(NS.localStorage); OWOP.OPM = false; if (OWOP.misc) OWOP.OPM = true; if (!OWOP.OPM) { OWOP.misc = NS.M0.misc; OWOP.tool = OWOP.tools; } if (localStorage.options) { let o = JSON.parse(localStorage.options); if (o?.enableSounds) OWOP.options.enableSounds = o.enableSounds; } const windows = {}; NS.windows = windows; if (!NS.localStorage.cursors) { let l = NS.localStorage.cursors = { cursor: { hotspot: [7, 2] }, move: { hotspot: [18, 18] }, pipette: { hotspot: [3, 31] }, zoom: { hotspot: [22, 13] }, export: { hotspot: [0, 3] }, // needs better hotspot fill: { hotspot: [6, 32] }, line: { hotspot: [6, 6] }, paste: { hotspot: [5, 2] }, // this too copy: { hotspot: [5, 5] }, // and this write: { hotspot: [17, 8] } // fix hotspot }; l.cursor.icon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAAA00lEQVRYw+3YMQ6DMAwFUPPFhTpCRxaW3qYzQ9f2Nl1YGIGRI8ENShz7W6mEZxwe34kUIXKVoR63+x79TpSGQmlJobTxJYHe8xiGSk4oCgXNwxEoaBvYKOQ0MVHIbew/AwWVDeqaloKCdQFvlAnUNa07Cl5Re6HguSE9UPA+tlaUO8iKMoGmdXFHURKyoJCTxLQuP9OxoGrLeMbnS31H/25zRRmZFpN686ytmLMvpp8yJkYNYmNUoAiMiEil3YBMjHpkbIwKFIFJBkVhivz7cdXf1QFBsW2mhPMCDAAAAABJRU5ErkJggg==" l.move.icon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAABgklEQVRYw+2YvU7EMAzH/055CYZj6IJ0243Q8ZYs9zbcWgErfZtbTkgdGNqOtyM2Ft7imHKK0g/nw4Ui4S1K7Pzi2q4TQEB2m+K82xRnCVskAWOPD6eGfg3IwLw0RwDAvtDJUCQFYyQViiRhJKBIGiYVilICmPNQTKCrEKCYTxCqo+bcIOYACguTvwMk9SsIta2mFDiofaFRd+1lXHdtL8NCbVOKZ3zTPiTwVUzRAwBdlVFz7mFcB1BMBfYB9l3rVvTMhtFViXy1mjSQrXN2TcjabJ3j4/UNt9c3j+9fn09kwwDA9u7+R9PcJMXx4RkAcDW2YG4wOzt7MeR6iRNf2LFNXTHeOZwaUnZAmQkf5ZCNfGF6dcj2FGdMV+Wop+qu9dJ3YRZZGIn71wy1EPa87SnXM5zu0Lyaoub6GZMEdddeAphLDM62kmyuJBq3/wZNHCgkC2OaPDUXTKxO9EWRy6ahojf7VXoMKhZG5LHBhUqBEXuOMVCpMIt8sBK7Z0nd474B40/4pg5xCDEAAAAASUVORK5CYII=" l.pipette.icon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAABAUlEQVRYw+3XvQ6CMBQF4FPiCzHQRDu6uPA2zg6u+jYuLI5ogoOPhFOTpnL7Y3ovDj0jIeRLzyEEoKaGTt+auW/NHLpHSUH8a7f3qFYBuZhOawDAa5pIlJLAWIgbCrXhrmYJI7KhHEyosqYUyH14p3X2ybBtKLSb2OkUB/m1+agYhmVDh+sJADAcz8mvevENWcxlHLDf7uDCLCQ1TUkMANyfD3I37KAQxlYWq6jYhnIxfWvmFJz6l5P5GcSJyQZxY7JAEphkkBQmCSSJiYKkMUHQGhgS5H8o3XBisj8d3JhFkF+VJOarMhdjN2MhEhiysrUw5Aml/GGKgHyUNKampkQ+wWnd9v+Wv9QAAAAASUVORK5CYII=" l.zoom.icon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAABMUlEQVRYw+3Wuw6CMBQG4L+NL+SIjgyy+CSuujo4u/ISri4wdFQTHFx9CScS1zrVNFCgdzThJCRcGvrlHHooMMWfBfH5svV8yVX3z48LiQrqgtjAiE9M14Q6Y7yVSEyWs5I/33XryFnJVeODYVQQGSFHzkoeBCW/VAdigqIuMBnAblds0hWJ3idU2dHJjG6WqCvQd2acQb7LRPFjQV3LZRNpsggDsimX6QIwXmmm8XzX4fpQiOxQm+zI57olyFnJ02SB3TLr/ckSG0x23AMAiu0B8rXqmxIQAIMYI1AT8zoVAIB7VX3HiGfN1SQgOtsP4oJpgqJs0HQwYqLgW1gTTPBN/hiYTtBYGCVoTMxgY4yNaWVIzs4YGACY9WVG7jExMJ2gZrOLhen9qGNDppjCV3wAmp0jyCb9nC4AAAAASUVORK5CYII=" l.export.icon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAABCklEQVRYw+2YMQ6CQBBFP4QL2Ql02mDhadQWg+3iaSzcRrsVO4+k1RCNhB3RHdZkfzUJBW//Z4YBIOjPFAHAcpLfpW54uJmoF0gShgOVULHYbwEAs2kKADhfm5/Xm7ywR0YOKaNxvjZOnTmuKqtDsVRM5JJNLZBrd7iKPz3BUHEPHCILkXkdGc0dryIjKG8iU0bjuKr86jJlNOs9Jtplymi/ugwAirqEbf8SHYzzNLNCiUXGdSruGmAE9209BMr5ClvUJeZpBgA4NZe363q9e1nanC/55ESfnqEiVyB0yC4gAhi97W0wh5uJkjFgvFjyOTBiQFyYtstcPtTcT2hRh7gwzjXGf4MgcT0AtrSSgUtEfWEAAAAASUVORK5CYII=" l.fill.icon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAABjUlEQVRYw+2YsW7DIBCGAfWFMhgpZezCkreJVw9Z7bfpwpLRiYSHPlI6XYSviLszWG2lnJQhGJNP//3HQZR6xT8LzZ14OrgHHvv8mvWvAOVg9oLTXBg/DavxcL7sAqU5MOMcVO/86lln7er7EmMTKC2FwSAYqBbKtICBgLRyPMcG2grTCspwJlEwS4wr09dAaUodjmfgnev9lq1EiaeMRJklxufHT8NTCT8N6nq/qY/je3X63jiTQI3cXpSOAVSqlJ8GFc4XdTq4B0cpQ4FgNVKYcQ4/3qlVylAVg0EwDP7xWqgsUO+8GueQbQ+QpjQtLaGMpCRznmkNpUtdHW+OufRhGFz68Jy7JZhSt4bUlWC2KiVOGRg69VPOU62hWB7qnVedtaqzdncokamXGKuhqJZipDCcKEHlTF+lEO7sUiiq4YqAqGqjoDjdnw0Ei5T8U4KC/YxqsCKFtkJxYUignMRSKOkhTewhCVTzE+NWqHRXl16JNHV1phYsHSW23M+KF0Xughhqjz8hXvFn4xvHckf64m/UhgAAAABJRU5ErkJggg==" l.line.icon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAABEUlEQVRYw+2XvRGEIBCFkbEDKzGQxAZITK3E2OBiKzG9hAYuweAqsQYvWofjVOB4GPESHRdmP/cHV8aysrLSqrgydnW70f3z/Sp8bUmATIc+QkFx1wI5jUxO48/zRgjWCAFPWem78AhqnRUciLtSoIbHoX2dFVu0vg/IpaqXXykLrTk4EEHJadzBEFBlzGY7bYhO4662p7e3C1gNDziMd8ooEgRlwlH33VZDi9Z7JOxrIwRbZwWFcrb91dlDYEiooLzb3y+7zqpe7ufWvzUVvKmr2810hoaCdAYSCjY2oKBgQCgoKBACCg4UC5UEKAYqGdARlHmYnkHxlEDkNGSQSxqhs+EN+ZcSBYWaCLKysmL0AfZSsN1jloZVAAAAAElFTkSuQmCC" l.paste.icon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAABQ0lEQVRYw+2Yvw6CMBDGr4QXYpBA2Jx04GmMs3E2Po2DTmwEggOPhFOTUtvSa6/FGC4xacuf/vjuu1IE2CJg1Fk11Vk1Ud6T+cCI/cfYslWARJDj/QIAAM/TlQyM+cBwELHtC8VsU2JSxTSOhUwwMCoAuY19QDlS08Fdns/672HQQmGucwZSTaRLiQ4GGyn2At8JnTy0ZqAUwnghWspu7Qt1/rk6/F7KeDXalH40D9lCpTFg5KWizqpJt3J7ATV9BwAA+6L86vP2rX3Nxpc85QXEQVR9XZu8ykQlVOrICpkegAxIdWOTWkHXIZ1XVIAqJYMrZJrIRaXEVSH+k/0T/dVB6Zf/e9uryl5n4KbvZuPRTL2URmw6yRRa3UP7oiQFsVLItEOkLPVFoMfYMtO+JYQy6E9p6n85dPsh52/7EDBb2MQHK+ObZIdb/JMAAAAASUVORK5CYII=" l.copy.icon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAABS0lEQVRYw+2XMQ6CMBSGfwxH8CIOEg2bkx2cOYhxJs6Ggzg74ORGNGXwIt5BpxrAAn3PVzWGPzEpaMLH199CgSFD/iwB5cerSXznXORwLQJxIC4MFYoMpLKUBJKvtySo0JeRaqZRhFJrrCbxvQ8qkIZpGszXW0yjCABQat1rqhNoVxxJMJt4+QJVnTKXToXSf1uVpTUrKktx2+cAgHGiWgFNRj7WEpWlKLXGOFFPEDNml5qbqoGqKQMmBnS6nAEAi9n85diMd8Wxdn4TL53NkIEMiO24bQyg1h8RIHPHNjtNQzZgcUPNO+6z9W5CSndsJmzfvQNIMtR1ISlLIxdD5tPsj0tu+/xZbC8dopqgltrLSv2RUncV+HQ5185/rNR90yhRbJahr05Z2wrNediKAXFAuC/8rA753AaFLq+kP7FRlNp1UOwMGfKXeQBOJJ69p18KUgAAAABJRU5ErkJggg==" l.write.icon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAABTUlEQVRYw+2XPW6DQBCFHyNu4JOktF26oUnrk7hO4TY5CW2abbY0SEvhk3AGp8miMcGEmVmMLPEa/0iGx3xvZsfAqlU2ZdYLvL/tb/zz9/WSLWaobyaFqcxq5vPiAAC+rgAA7nQ2maIU3KOZFKKUZtrSLWOoj8udzh2q4utjNF+zVsjXVWcEAJoQlkcWA2xtd7UhjmsoM23pTNjIgmsIkRWb2tBYR1m6jbS4YiV4duL7JgQ1NrLOntQiC66hzorfabGRBdeYtNhyCy7tNJ59MD59QeO4fF3hsN3dVeyw3d299iVZSXINrv5NfV2hLR38b5g3x6IL9eZYiCokzhA/TP8ohp2FvhAaIgkuTStLz7ZcgmtoOv/3ME0IoiqRZomf44+BqO05Lsnew6d2xJZkDj1aNaZK8luaGkyrpl6DJE+oWVP5SvKSR8eqVVb9AMXs1T0X1uPeAAAAAElFTkSuQmCC" localStorage.NS = JSON.stringify(NS.localStorage); } { function holeify(img) { let canvas = document.createElement("canvas"); var shadowcolor = 0xFF3B314D; var backgroundcolor = 0xFF5C637E; canvas.width = img.width; canvas.height = img.height; var ctx = canvas.getContext('2d'); ctx.drawImage(img, 0, 0); var idat = ctx.getImageData(0, 0, canvas.width, canvas.height); var u32dat = new Uint32Array(idat.data.buffer); var clr = (x, y) => { return (x < 0 || y < 0 || x >= idat.width || y >= idat.height) ? 0 : u32dat[y * idat.width + x]; }; for (var i = u32dat.length; i--;) { if (u32dat[i] !== 0) { u32dat[i] = backgroundcolor; } } for (var y = idat.height; y--;) { for (var x = idat.width; x--;) { if (clr(x, y) === backgroundcolor && (!clr(x, y - 1) || !clr(x - 1, y)) && !clr(x - 1, y - 1)) { u32dat[y * idat.width + x] = shadowcolor; } } } for (var y = idat.height; y--;) { for (var x = idat.width; x--;) { if (clr(x, y - 1) === shadowcolor && clr(x - 1, y) === shadowcolor) { u32dat[y * idat.width + x] = shadowcolor; } } } ctx.putImageData(idat, 0, 0); return canvas.toDataURL(); } let iconStyler = document.createElement("style"); document.getElementById("toole-container").parentElement.appendChild(iconStyler); for (let cursor in NS.localStorage.cursors) { let cursorURL = NS.localStorage.cursors[cursor].icon; // cursorURL = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAACeElEQVRYw+2XsWsaYRiHH6VRSyGBEwepi5nsIFToWKUKDoVkyl/QIQhZRMdCJqGj0kUoGRw6FqcIGY4qnI6BBBwiFCqBKzcUDxoieMlgB/NdYtN6Z7yzGfyBy3eIj8/3vu/3HayyQGKvPoyX/ZvexwblfWymLIEMrb1UKFuGQk+PMLT2UqC8Vnb0UReAyOblUqBmAumjLlIgDkClpZhQ0edvx/9ty/zhJACdoWFC+cNJ10zNBJICcbR+FYDXz/wU0il2GrKrNeW1siO2rDM0AKhvZam0FPD1XIHy2ml5YUikkE6RPz0DX8/xkWBpSHSZMFRpKaapL9++YwwOHDU1E0jrV80tE+kMDXYa8j1TTkFZFrUwJKIcqrd1BHx8+YJESXYMynIOhaN7f31WSKdMqJP97FRNLTKnbLe9SGo7MgWVKMmmKSlTxhgcLDSnLA3d3SqAz8WjyfmWqxHK1UhtR0wovVk0obR+9UFQnlkPhfrI5iU7DZn6VpZQrsZ5q4veLP7ze4mSzMl+Fq5i6KMuvwaqx3GgUK7Gz0/vqLQUCumUaenPnLdurerNIlzF8IeT9I7fexYG2ghGxlIgDr4e+dMz6ltZAFRVRcqUZ1qammfBXbR+1ZYp222vHKqo6uSTKMnmv9cvrtEvruEqNrER3DXXxZqhtQlH92zVlOVpLwaj2AopU+Zr/s0E5OZ6IsD1Ude8Q4lxIaa9obVtFbplDemjLtL6GlKmPFUXIv0fRx4czBN7F7TePZh5u8eRLtsIRsYA0vraZOGmjaVA3HEzc9fQ3ZpxC8a+oTsnvpswtl+DROu7DTPXli0DxrYhN7rpQRE1tMoqM/Ibi49haAcCegQAAAAASUVORK5CYII="; iconStyler.innerHTML += `#tool-${cursor}:not(.selected) div { background-image: url("${cursorURL}") !important } ` let img = new Image(); img.onload = function () { iconStyler.innerHTML += `#tool-${cursor}.selected div { background-image: url("${holeify(img)}") !important } ` } img.src = cursorURL; } } (function () { var camera = OWOP.camera; // NS.M20.camera var renderer = OWOP.renderer; // NS.M20.renderer var GUIWindow = OWOP.windowSys.class.window; const mkHTML = OWOP.util.mkHTML; // NS. const isSame = (a, b) => a && b && a[0] === b[0] && a[1] === b[1] && a[2] === b[2]; var drawText = (t, e, n, r, o) => { t.strokeStyle = "#000000"; t.fillStyle = "#FFFFFF"; t.lineWidth = 2.5; t.globalAlpha = 0.5; o && (n -= t.measureText(e).width >> 1); t.strokeText(e, n, r); t.globalAlpha = 1; t.fillText(e, n, r); }; var setColor = (cursor, color) => { if (!color) return; if (cursor === 1) { OWOP.player.selectedColor = color; } else if (cursor === 2) { OWOP.player.rightSelectedColor = color; localStorage.setItem("rSC", JSON.stringify(OWOP.player.rightSelectedColor)); } }; NS.renderPlayer = function (fx, ctx, time) { (function (fx, ctx, time) { if (!NS.PM.renderPlayerRings) return; let t = 1; let e = 5; let i = fx.extra.player.x; let a = fx.extra.player.y; let defaultLine = ctx.lineWidth; let s = ((i / (16 * t) + 0.5) * t - OWOP.camera.x) * OWOP.camera.zoom; let u = ((a / (16 * t) + 0.5) * t - OWOP.camera.y) * OWOP.camera.zoom; new NS.Point(OWOP.mouse.worldX, OWOP.mouse.worldY); ctx.globalAlpha = 1; ctx.lineWidth = 16; ctx.beginPath(); ctx.strokeStyle = "#000000"; ctx.arc(s, u, OWOP.camera.zoom * t * e, 0, Math.PI * 2, false); ctx.stroke(); ctx.closePath(); ctx.lineWidth = 15; ctx.beginPath(); ctx.strokeStyle = "#FFFFFF"; ctx.arc(s, u, OWOP.camera.zoom * t * e, Math.PI, Math.PI * 3, false); ctx.stroke(); ctx.setLineDash([0]); ctx.closePath(); ctx.lineWidth = 11; ctx.beginPath(); ctx.setLineDash([]); ctx.strokeStyle = fx.extra.player.htmlRgb; ctx.arc(s, u, OWOP.camera.zoom * t * e, 0, Math.PI * 2, false); ctx.stroke(); ctx.closePath(); ctx.lineWidth = defaultLine; ctx.globalAlpha = .8; // let canvas = document.getElementById('canvas4'); // let ctx = canvas.getContext('2d'); // ctx.strokeStyle = '#b668ff'; // ctx.lineWidth = 4; })(fx, ctx, time); return 1; } NS.renderBorder = function (fx, ctx, time) { (function (fx, ctx, time) { if (!NS.PM.renderBorder) return; let t = "#00FF00"; let e = 1; let l = NS.M20; ctx.globalAlpha = 1; ctx.strokeStyle = t || fx.extra.player.htmlRgb; // ctx.strokeRect(i, j, l.camera.zoom * e, l.camera.zoom * e); let oldWidth = ctx.lineWidth; ctx.lineWidth = 5; for (let k in NS.PM.border) { if (NS.PM.border[k].right || NS.PM.border[k].bottom) { let x = NS.PM.border[k].x; let y = NS.PM.border[k].y; if (Point.distance(new Point(OWOP.mouse.tileX, OWOP.mouse.tileY), new Point(x, y)) > (16 * 25)) continue; let i = (Math.floor(x / (e)) * e - l.camera.x) * l.camera.zoom; let j = (Math.floor(y / (e)) * e - l.camera.y) * l.camera.zoom; ctx.beginPath(); if (NS.PM.border[k].bottom) { ctx.moveTo(i, j + l.camera.zoom); ctx.lineTo(i + l.camera.zoom, j + l.camera.zoom); ctx.stroke(); } if (NS.PM.border[k].right) { ctx.moveTo(i + l.camera.zoom, j); ctx.lineTo(i + l.camera.zoom, j + l.camera.zoom); ctx.stroke(); } } else delete NS.PM.border[k]; } ctx.lineWidth = oldWidth; return 1; })(fx, ctx, time); return 0; } // var C = OWOP.require('util/color').colorUtils; // var C = NS.colorUtils; if (!localStorage["rSC"]) localStorage.setItem("rSC", JSON.stringify([255, 255, 255])); OWOP.player.rightSelectedColor = JSON.parse(localStorage.getItem("rSC")); let someRenderer = ((fx, ctx, time, defaultFx) => { if (!fx.extra.isLocalPlayer) { if (fx.visible) return NS.renderPlayer(fx, ctx, time); return defaultFx(fx, ctx, time); } return NS.renderBorder(fx, ctx, time); }); let mouseStyler = document.createElement("style"); document.getElementById("viewport").appendChild(mouseStyler); { let i = NS.localStorage.cursors[OWOP.player.tool.id]; // i = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAACeElEQVRYw+2XsWsaYRiHH6VRSyGBEwepi5nsIFToWKUKDoVkyl/QIQhZRMdCJqGj0kUoGRw6FqcIGY4qnI6BBBwiFCqBKzcUDxoieMlgB/NdYtN6Z7yzGfyBy3eIj8/3vu/3HayyQGKvPoyX/ZvexwblfWymLIEMrb1UKFuGQk+PMLT2UqC8Vnb0UReAyOblUqBmAumjLlIgDkClpZhQ0edvx/9ty/zhJACdoWFC+cNJ10zNBJICcbR+FYDXz/wU0il2GrKrNeW1siO2rDM0AKhvZam0FPD1XIHy2ml5YUikkE6RPz0DX8/xkWBpSHSZMFRpKaapL9++YwwOHDU1E0jrV80tE+kMDXYa8j1TTkFZFrUwJKIcqrd1BHx8+YJESXYMynIOhaN7f31WSKdMqJP97FRNLTKnbLe9SGo7MgWVKMmmKSlTxhgcLDSnLA3d3SqAz8WjyfmWqxHK1UhtR0wovVk0obR+9UFQnlkPhfrI5iU7DZn6VpZQrsZ5q4veLP7ze4mSzMl+Fq5i6KMuvwaqx3GgUK7Gz0/vqLQUCumUaenPnLdurerNIlzF8IeT9I7fexYG2ghGxlIgDr4e+dMz6ltZAFRVRcqUZ1qammfBXbR+1ZYp222vHKqo6uSTKMnmv9cvrtEvruEqNrER3DXXxZqhtQlH92zVlOVpLwaj2AopU+Zr/s0E5OZ6IsD1Ude8Q4lxIaa9obVtFbplDemjLtL6GlKmPFUXIv0fRx4czBN7F7TePZh5u8eRLtsIRsYA0vraZOGmjaVA3HEzc9fQ3ZpxC8a+oTsnvpswtl+DROu7DTPXli0DxrYhN7rpQRE1tMoqM/Ibi49haAcCegQAAAAASUVORK5CYII="; mouseStyler.innerHTML = `#viewport { cursor: url("${i.icon}") ${i.hotspot[0]} ${i.hotspot[1]}, pointer !important; } } `; } let oldFunction = Object.getOwnPropertyDescriptor(OWOP.player, "tool").set; Object.defineProperty(OWOP.player, 'tool', { set: function (x) { let i = NS.localStorage.cursors[x]; // i = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAACeElEQVRYw+2XsWsaYRiHH6VRSyGBEwepi5nsIFToWKUKDoVkyl/QIQhZRMdCJqGj0kUoGRw6FqcIGY4qnI6BBBwiFCqBKzcUDxoieMlgB/NdYtN6Z7yzGfyBy3eIj8/3vu/3HayyQGKvPoyX/ZvexwblfWymLIEMrb1UKFuGQk+PMLT2UqC8Vnb0UReAyOblUqBmAumjLlIgDkClpZhQ0edvx/9ty/zhJACdoWFC+cNJ10zNBJICcbR+FYDXz/wU0il2GrKrNeW1siO2rDM0AKhvZam0FPD1XIHy2ml5YUikkE6RPz0DX8/xkWBpSHSZMFRpKaapL9++YwwOHDU1E0jrV80tE+kMDXYa8j1TTkFZFrUwJKIcqrd1BHx8+YJESXYMynIOhaN7f31WSKdMqJP97FRNLTKnbLe9SGo7MgWVKMmmKSlTxhgcLDSnLA3d3SqAz8WjyfmWqxHK1UhtR0wovVk0obR+9UFQnlkPhfrI5iU7DZn6VpZQrsZ5q4veLP7ze4mSzMl+Fq5i6KMuvwaqx3GgUK7Gz0/vqLQUCumUaenPnLdurerNIlzF8IeT9I7fexYG2ghGxlIgDr4e+dMz6ltZAFRVRcqUZ1qammfBXbR+1ZYp222vHKqo6uSTKMnmv9cvrtEvruEqNrER3DXXxZqhtQlH92zVlOVpLwaj2AopU+Zr/s0E5OZ6IsD1Ude8Q4lxIaa9obVtFbplDemjLtL6GlKmPFUXIv0fRx4czBN7F7TePZh5u8eRLtsIRsYA0vraZOGmjaVA3HEzc9fQ3ZpxC8a+oTsnvpswtl+DROu7DTPXli0DxrYhN7rpQRE1tMoqM/Ibi49haAcCegQAAAAASUVORK5CYII="; if (i) mouseStyler.innerHTML = `#viewport { cursor: url("${i.icon}") ${i.hotspot[0]} ${i.hotspot[1]}, pointer !important; } } `; oldFunction.bind(this)(...arguments); } }); setTimeout(() => { OWOP.tool.addToolObject(new OWOP.tool.class('Cursor', OWOP.cursors.cursor, null, 1, tool => { // render protected chunks tool.setFxRenderer((fx, ctx, time) => { let defaultFx = OWOP.fx.player.RECT_SELECT_ALIGNED(1); if (someRenderer(fx, ctx, time, defaultFx)) return; if (tool.extra.state.chunkize) defaultFx = OWOP.fx.player.RECT_SELECT_ALIGNED(16); defaultFx(fx, ctx, time); return; if (!fx.extra.isLocalPlayer) return 1; var x = fx.extra.player.x; var y = fx.extra.player.y; var fxx = (Math.floor(x / 16) - camera.x) * camera.zoom; var fxy = (Math.floor(y / 16) - camera.y) * camera.zoom; var oldlinew = ctx.lineWidth; ctx.lineWidth = 1; if (tool.extra.end) { var s = tool.extra.start; var e = tool.extra.end; var x = (s[0] - camera.x) * camera.zoom + 0.5; var y = (s[1] - camera.y) * camera.zoom + 0.5; var w = e[0] - s[0]; var h = e[1] - s[1]; ctx.beginPath(); ctx.rect(x, y, w * camera.zoom, h * camera.zoom); ctx.globalAlpha = 1; ctx.strokeStyle = "#FFFFFF"; ctx.stroke(); ctx.setLineDash([3, 4]); ctx.strokeStyle = "#000000"; ctx.stroke(); ctx.globalAlpha = 0.25 + Math.sin(time / 500) / 4; ctx.fillStyle = renderer.patterns.unloaded; ctx.fill(); ctx.setLineDash([]); var oldfont = ctx.font; ctx.font = "16px sans-serif"; var txt = `${!tool.extra.clicking ? "Right click to screenshot " : ""}(${Math.abs(w)}x${Math.abs(h)})`; var txtx = window.innerWidth >> 1; var txty = window.innerHeight >> 1; txtx = Math.max(x, Math.min(txtx, x + w * camera.zoom)); txty = Math.max(y, Math.min(txty, y + h * camera.zoom)); drawText(ctx, txt, txtx, txty, true); ctx.font = oldfont; ctx.lineWidth = oldlinew; return 0; } else { ctx.beginPath(); ctx.moveTo(0, fxy + 0.5); ctx.lineTo(window.innerWidth, fxy + 0.5); ctx.moveTo(fxx + 0.5, 0); ctx.lineTo(fxx + 0.5, window.innerHeight); //ctx.lineWidth = 1; ctx.globalAlpha = 1; ctx.strokeStyle = "#FFFFFF"; ctx.stroke(); ctx.setLineDash([3]); ctx.strokeStyle = "#000000"; ctx.stroke(); ctx.setLineDash([]); ctx.lineWidth = oldlinew; return 1; } }); // cursor functionality tool.extra.state = { scalar: "1", rainbow: false, chunkize: false, perfect: false }; tool.extra.lastX; tool.extra.lastY; tool.extra.last1PX; tool.extra.last1PY; tool.extra.last2PX; tool.extra.last2PY; tool.extra.start; tool.extra.c = 0; tool.setEvent('mousedown mousemove', (mouse, event) => { if (mouse.buttons !== 2 && mouse.buttons !== 1) return 3; if (tool.extra.lastX == mouse.tileX && tool.extra.lastY == mouse.tileY) return 3; if (event?.ctrlKey) return setColor(mouse.buttons, PM.getPixel(mouse.tileX, mouse.tileY)); let c = mouse.buttons === 1 ? OWOP.player.selectedColor : OWOP.player.rightSelectedColor; if (isNaN(tool.extra.lastX) || isNaN(tool.extra.lastY)) { tool.extra.lastX = mouse.tileX; tool.extra.lastY = mouse.tileY; tool.extra.last1PX = mouse.tileX; tool.extra.last1PY = mouse.tileY; tool.extra.last2PX = mouse.tileX; tool.extra.last2PY = mouse.tileY; tool.extra.start = true; } PM.startHistory(); line(tool.extra.lastX, tool.extra.lastY, mouse.tileX, mouse.tileY, undefined, event, (x, y) => { let tempx = x; let tempy = y; if (tool.extra.state.perfect) { let place = false; // check to place if (tool.extra.start) { tool.extra.start = false; place = true; } else { if (tool.extra.last1PX == x && tool.extra.last1PY == y) { tool.extra.last2PX = tool.extra.last1PX; tool.extra.last2PY = tool.extra.last1PY; tool.extra.last1PX = x; tool.extra.last1PY = y; return; } } if (!place) { for (let x1 = -1; x1 < 2; x1++) { for (let y1 = -1; y1 < 2; y1++) { if (x1 == 0 && y1 == 0) continue; if (tool.extra.last2PX === (x + x1) && tool.extra.last2PY === (y + y1)) { tool.extra.last1PX = x; tool.extra.last1PY = y; return; } } } } tempx = tool.extra.last1PX; tempy = tool.extra.last1PY; } let size = Number(tool.extra.state.scalar); if (tool.extra.state.chunkize) size = 16; let offset = Math.floor(size / 2); if (tool.extra.state.chunkize) { tempx = Math.floor(tempx / 16) * 16; tempy = Math.floor(tempy / 16) * 16; offset = 0; } for (let x1 = 0; x1 < size; x1++) { for (let y1 = 0; y1 < size; y1++) { if (tool.extra.state.rainbow) { let pixel; if ((pixel = PM.getPixel(tempx + x1 - offset, tempy + y1 - offset), !pixel)) continue; c = mouse.buttons === 1 ? hue((tempx + x1 - offset) - (tempy + y1 - offset), 8) : hue(tool.extra.c++, 8); if (Color.compare(pixel, c)) continue; } PM.setPixel(tempx + x1 - offset, tempy + y1 - offset, c); //[Math.round(OWOP.mouse.worldX/16)-0.5, Math.round(OWOP.mouse.worldY/16)-0.5] } } if (tool.extra.state.perfect) { tool.extra.last2PX = tool.extra.last1PX; tool.extra.last2PY = tool.extra.last1PY; tool.extra.last1PX = x; tool.extra.last1PY = y; } }); tool.extra.lastX = mouse.tileX; tool.extra.lastY = mouse.tileY; return 3; }); tool.setEvent('mouseup deselect', () => { PM.endHistory(); tool.extra.lastX = undefined; tool.extra.lastY = undefined; tool.extra.last1PX = undefined; tool.extra.last1PY = undefined; tool.extra.last2PX = undefined; tool.extra.last2PY = undefined; }); // change color positions tool.setEvent('keydown', keys => { if ((keys["87"] && keys["83"]) || !keys["16"]) return; if (keys["87"]) { // w let i1 = OWOP.player.paletteIndex; let i2 = modulo(i1 - 1, OWOP.player.palette.length); if (i2 == OWOP.player.palette.length - 1) { OWOP.player.palette.push(OWOP.player.palette.shift()); } else { [OWOP.player.palette[i1], OWOP.player.palette[i2]] = [OWOP.player.palette[i2], OWOP.player.palette[i1]]; } OWOP.player.paletteIndex = i2; } if (keys["83"]) { // s let i1 = OWOP.player.paletteIndex; let i2 = modulo(i1 + 1, OWOP.player.palette.length); if (i2 === 0) { OWOP.player.palette.unshift(OWOP.player.palette.pop()); } else { [OWOP.player.palette[i1], OWOP.player.palette[i2]] = [OWOP.player.palette[i2], OWOP.player.palette[i1]]; } OWOP.player.paletteIndex = i2; } }); })); OWOP.tool.addToolObject(new OWOP.tool.class('Pipette', OWOP.cursors.pipette, null, 0, tool => { tool.extra.state = {}; tool.setEvent('mousedown mousemove', mouse => { var c = PM.getPixel(mouse.tileX, mouse.tileY); if (!c) return mouse.buttons; switch (mouse.buttons) { case 1: OWOP.player.selectedColor = c; break; case 2: OWOP.player.rightSelectedColor = c; localStorage.setItem("rSC", JSON.stringify(OWOP.player.rightSelectedColor)); break; } return mouse.buttons; }); })); OWOP.tool.addToolObject(new OWOP.tool.class('Export', OWOP.cursors.select, null, 0, tool => { tool.extra.state = { type: "export", rainbow: false, chunkize: false }; tool.setFxRenderer((fx, ctx, time) => { if (someRenderer(fx, ctx, time, () => 1)) return; var x = fx.extra.player.x; var y = fx.extra.player.y; var fxx = (Math.floor(x / 16) - camera.x) * camera.zoom; var fxy = (Math.floor(y / 16) - camera.y) * camera.zoom; var oldlinew = ctx.lineWidth; ctx.lineWidth = 1; if (tool.extra.end) { var s = tool.extra.start; var e = tool.extra.end; var x = s[0]; var y = s[1]; var w = e[0]; var h = e[1]; if (s[0] > e[0]) [w, x] = [x, w]; if (s[1] > e[1]) [h, y] = [y, h]; if (tool.extra.state.chunkize) { x = Math.floor(x / 16) * 16; y = Math.floor(y / 16) * 16; w = Math.floor(w / 16) * 16 + 16; h = Math.floor(h / 16) * 16 + 16; } w = w - x; h = h - y; x = (x - camera.x) * camera.zoom + 0.5; y = (y - camera.y) * camera.zoom + 0.5; ctx.beginPath(); ctx.rect(x, y, w * camera.zoom, h * camera.zoom); ctx.globalAlpha = 1; ctx.strokeStyle = "#FFFFFF"; ctx.stroke(); ctx.setLineDash([3, 4]); ctx.strokeStyle = "#000000"; ctx.stroke(); ctx.globalAlpha = 0.25 + Math.sin(time / 500) / 4; ctx.fillStyle = renderer.patterns.unloaded; ctx.fill(); ctx.setLineDash([]); var oldfont = ctx.font; ctx.font = "16px sans-serif"; var txt = `${!tool.extra.clicking ? "Right click " : ""}(${Math.abs(w)}x${Math.abs(h)})`; var txtx = window.innerWidth >> 1; var txty = window.innerHeight >> 1; txtx = Math.max(x, Math.min(txtx, x + w * camera.zoom)); txty = Math.max(y, Math.min(txty, y + h * camera.zoom)); drawText(ctx, txt, txtx, txty, true); ctx.font = oldfont; ctx.lineWidth = oldlinew; return 0; } else { var x = fx.extra.player.x; var y = fx.extra.player.y; var fxx = Math.floor(x / 16); var fxy = Math.floor(y / 16); if (tool.extra.state.chunkize) { fxx = Math.floor(fxx / 16) * 16; fxy = Math.floor(fxy / 16) * 16; } fxx -= camera.x; fxy -= camera.y; fxx *= camera.zoom; fxy *= camera.zoom; ctx.beginPath(); ctx.moveTo(0, fxy + 0.5); ctx.lineTo(window.innerWidth, fxy + 0.5); ctx.moveTo(fxx + 0.5, 0); ctx.lineTo(fxx + 0.5, window.innerHeight); //ctx.lineWidth = 1; ctx.globalAlpha = 1; ctx.strokeStyle = "#FFFFFF"; ctx.stroke(); ctx.setLineDash([3]); ctx.strokeStyle = "#000000"; ctx.stroke(); ctx.setLineDash([]); ctx.lineWidth = oldlinew; return 1; } }); tool.extra.start = undefined; tool.extra.end = undefined; tool.extra.clicking = false; tool.setEvent('mousedown', (mouse, event) => { var s = tool.extra.start; var e = tool.extra.end; const isInside = () => { var x = s[0]; var y = s[1]; var w = e[0]; var h = e[1]; if (tool.extra.state.chunkize) { x = Math.floor(x / 16) * 16; y = Math.floor(y / 16) * 16; w = Math.floor(w / 16) * 16 + 16; h = Math.floor(h / 16) * 16 + 16; } return mouse.tileX >= x && mouse.tileX < w && mouse.tileY >= y && mouse.tileY < h; } if (mouse.buttons === 1 && !tool.extra.end) { tool.extra.start = [mouse.tileX, mouse.tileY]; tool.extra.clicking = true; tool.setEvent('mousemove', (mouse, event) => { if (tool.extra.start && mouse.buttons === 1) { tool.extra.end = [mouse.tileX, mouse.tileY]; return 1; } }); const finish = () => { tool.setEvent('mousemove mouseup deselect', null); tool.extra.clicking = false; var s = tool.extra.start; var e = tool.extra.end; var tmp = undefined; if (e) { if (s[0] === e[0] || s[1] === e[1]) { tool.extra.start = undefined; tool.extra.end = undefined; } if (s[0] > e[0]) { tmp = e[0]; e[0] = s[0]; s[0] = tmp; } if (s[1] > e[1]) { tmp = e[1]; e[1] = s[1]; s[1] = tmp; } } renderer.render(renderer.rendertype.FX); } tool.setEvent('deselect', finish); tool.setEvent('mouseup', (mouse, event) => { if (!(mouse.buttons & 1)) { finish(); } }); } else if (mouse.buttons === 1 && tool.extra.end) { if (isInside()) { var offx = mouse.tileX; var offy = mouse.tileY; tool.setEvent('mousemove', (mouse, event) => { var dx = mouse.tileX - offx; var dy = mouse.tileY - offy; tool.extra.start = [s[0] + dx, s[1] + dy]; tool.extra.end = [e[0] + dx, e[1] + dy]; }); const end = () => { tool.setEvent('mouseup deselect mousemove', null); } tool.setEvent('deselect', end); tool.setEvent('mouseup', (mouse, event) => { if (!(mouse.buttons & 1)) { end(); } }); } else { tool.extra.start = undefined; tool.extra.end = undefined; } } else if (mouse.buttons === 2 && tool.extra.end && isInside()) { tool.extra.start = undefined; tool.extra.end = undefined; var x = s[0]; var y = s[1]; var w = e[0]; var h = e[1]; if (tool.extra.state.chunkize) { x = Math.floor(x / 16) * 16; y = Math.floor(y / 16) * 16; w = Math.floor(w / 16) * 16 + 16; h = Math.floor(h / 16) * 16 + 16; } w -= x; h -= y; let warn = false; switch (tool.extra.state.type) { case "export": { ((x, y, w, h, onblob) => { var c = document.createElement('canvas'); c.width = w; c.height = h; var ctx = c.getContext('2d'); var d = ctx.createImageData(w, h); for (var i = y; i < y + h; i++) { for (var j = x; j < x + w; j++) { let pix; let tempPix = PM.queue[`${j},${i}`]; if (!tempPix) { if ((pix = PM.getPixel(j, i), !pix)) { warn = true; pix = [255, 255, 255]; } } else { pix = tempPix.c; } d.data[4 * ((i - y) * w + (j - x))] = pix[0]; d.data[4 * ((i - y) * w + (j - x)) + 1] = pix[1]; d.data[4 * ((i - y) * w + (j - x)) + 2] = pix[2]; d.data[4 * ((i - y) * w + (j - x)) + 3] = 255; } } ctx.putImageData(d, 0, 0); c.toBlob(onblob); })(x, y, w, h, b => { var url = URL.createObjectURL(b); var img = new Image(); img.onload = () => { if (OWOP.windowSys.windows['Resulting image']) OWOP.windowSys.delWindow(OWOP.windowSys.windows['Resulting image']); OWOP.windowSys.addWindow(new GUIWindow("Resulting image", { centerOnce: true, closeable: true }, win => { var props = ['width', 'height']; if (img.width > img.height) { props.reverse(); } var r = img[props[0]] / img[props[1]]; var shownSize = img[props[1]] >= 128 ? 256 : 128; img[props[0]] = r * shownSize; img[props[1]] = shownSize; //win.container.classList.add('centeredChilds'); //setTooltip(img, "Right click to copy/save!"); var p1 = document.createElement("p"); img.style = "display:block; margin-left: auto; margin-right: auto; padding-bottom:15px;"; p1.appendChild(img); //p1.appendChild(document.createElement("br")); var closeButton = mkHTML("button", { innerHTML: "CLOSE", style: "width: 100%; height: 30px; margin: auto; padding-left: 10%;", onclick: () => { img.remove(); URL.revokeObjectURL(url); win.getWindow().close(); } }); var saveButton = mkHTML("button", { innerHTML: "SAVE", style: "width: 100%; height: 30px; margin: auto; padding-left: 10%;" }); saveButton.onclick = () => { var a = document.createElement('a'); a.download = `${Base64.fromNumber(Date.now())} OWOP_${OWOP.world.name} at ${s[0]} ${s[1]}.png`; a.href = img.src; a.click(); } var scalar = document.createElement("input"); scalar.id = "scalar"; scalar.type = "range"; scalar.style = "width: 100%; margin: auto;"; scalar.value = "1"; scalar.min = "1"; scalar.max = "10"; //<p id="scalar-num" style="margin: auto;top: -8px; right: 12px; user-select: none; color: white;">1</p> scalar.oninput = () => { // scalarNum.textContent = scalar.value; } p1.appendChild(saveButton); p1.appendChild(closeButton); p1.appendChild(scalar); var image = win.addObj(p1); })); } img.src = url; }); } break; case "color": { let test = false; let totalAdded = 0; let limit = 50; for (var i = x; i < x + w; i++) { for (var j = y; j < y + h; j++) { if (totalAdded >= limit) continue; var pix = PM.getPixel(i, j); if (!pix) continue; for (let k = 0; k < OWOP.player.palette.length; k++) { var c = OWOP.player.palette[k]; if (isSame(c, pix)) { test = true; break; } } if (test) { test = false; continue; } OWOP.player.palette.push(pix); totalAdded++; } } OWOP.player.paletteIndex = OWOP.player.palette.length - 1; if (totalAdded >= limit) OWOP.chat.local(`total colors added limit has been reached (${limit} added)`); } break; case "adder": { for (var i = x; i < x + w; i++) { for (var j = y; j < y + h; j++) { var pix = PM.getPixel(i, j); if (pix && !PM.queue[`${i},${j}`]) PM.setPixel(i, j, pix); } } } break; case "filler": { var pix = OWOP.player.selectedColor; PM.startHistory(); for (var i = x; i < x + w; i++) { for (var j = y; j < y + h; j++) { PM.setPixel(i, j, pix); } } PM.endHistory(); } break; case "clearer": { for (var i = x; i < x + w; i++) { for (var j = y; j < y + h; j++) { PM.unsetPixel(i, j); } } } break; } if (warn) console.warn("Well something happened, you probably tried getting an area outside of loaded chunks."); } }); })); OWOP.tool.addToolObject(new OWOP.tool.class('Fill', OWOP.cursors.fill, null, 1, tool => { tool.extra.state = { rainbow: false, checkered: false, dither: false, dither2: false, dither3: false, dither4: false, dither5: false, dither6: false } tool.extra.usedQueue = {}; tool.extra.queue = {}; tool.extra.fillingColor = undefined; tool.extra.button = 0; tool.extra.checkered = 0; const isFillColor = (x, y) => isSame(PM.getPixel(x, y), tool.extra.fillingColor) && (!tool.extra.usedQueue[`${x},${y}`]) && (tool.extra.queue[`${x},${y}`] = { x: x, y: y }, true); function tick() { var selClr = tool.extra.button === 1 ? OWOP.player.selectedColor : OWOP.player.rightSelectedColor; for (let current in tool.extra.queue) { current = tool.extra.queue[current]; var x = current.x; var y = current.y; if (tool.extra.state.rainbow) selClr = hue(x - y, 8); var thisClr = PM.getPixel(x, y); if (isSame(thisClr, tool.extra.fillingColor) && !isSame(thisClr, selClr)) { if (tool.extra.state.checkered) { let pattern = [ [1, 0], [0, 1] ]; if (pattern[modulo(x, 2)][modulo(y, 2)]) PM.setPixel(x, y, selClr); } else if (tool.extra.state.dither) { let pattern = [ [1, 0, 1, 0], [0, 1, 0, 0], [1, 0, 1, 0], [0, 0, 0, 1] ]; if (pattern[modulo(x, 4)][modulo(y, 4)]) PM.setPixel(x, y, selClr); } else if (tool.extra.state.dither2) { let pattern = [ [0, 0], [0, 1], [0, 0], [1, 0] ]; if (pattern[modulo(x, 4)][modulo(y, 2)]) PM.setPixel(x, y, selClr); } else if (tool.extra.state.dither3) { let pattern = [ [1, 0, 0, 0, 1, 0, 1, 0], [0, 1, 0, 1, 0, 1, 0, 0], [1, 0, 1, 0, 0, 0, 1, 0], [0, 0, 0, 1, 0, 1, 0, 1], [1, 0, 1, 0, 1, 0, 0, 0], [0, 1, 0, 0, 0, 1, 0, 1], [0, 0, 1, 0, 1, 0, 1, 0], [0, 1, 0, 1, 0, 0, 0, 1] ]; if (pattern[modulo(x, 8)][modulo(y, 8)]) PM.setPixel(x, y, selClr); } else if (tool.extra.state.dither4) { let pattern = [ [0, 1, 0, 0], [1, 1, 0, 0], [0, 0, 1, 1], [0, 0, 1, 0] ]; if (pattern[modulo(x, 4)][modulo(y, 4)]) PM.setPixel(x, y, selClr); } else if (tool.extra.state.dither5) { let pattern = [ [0, 1, 0, 0, 0, 0, 1, 0], [1, 1, 0, 0, 0, 0, 1, 1], [0, 0, 1, 1, 1, 1, 0, 0], [0, 0, 1, 0, 0, 1, 0, 0], [0, 0, 1, 0, 0, 1, 0, 0], [0, 0, 1, 1, 1, 1, 0, 0], [1, 1, 0, 0, 0, 0, 1, 1], [0, 1, 0, 0, 0, 0, 1, 0] ]; if (pattern[modulo(x, 8)][modulo(y, 8)]) PM.setPixel(x, y, selClr); } else if (tool.extra.state.dither6) { let pattern = [ [0, 1, 1, 0, 0], [1, 1, 1, 1, 0], [1, 0, 1, 0, 0], [1, 0, 1, 1, 0], [0, 0, 0, 0, 0] ]; if (pattern[modulo(x, 5)][modulo(y, 5)]) PM.setPixel(x, y, selClr); } else if (tool.extra.state.dither7) { let pattern = [ [1, 1, 1, 0, 1, 1, 1, 0, 1, 0], [0, 0, 0, 0, 1, 0, 1, 0, 0, 0], [1, 0, 1, 0, 1, 1, 1, 0, 1, 1], [1, 0, 0, 0, 0, 0, 0, 0, 1, 0], [1, 0, 1, 1, 1, 0, 1, 0, 1, 1], [0, 0, 1, 0, 1, 0, 0, 0, 0, 0], [1, 0, 1, 1, 1, 0, 1, 1, 1, 0], [0, 0, 0, 0, 0, 0, 1, 0, 1, 0], [1, 1, 1, 0, 1, 0, 1, 1, 1, 0], [1, 0, 1, 0, 0, 0, 0, 0, 0, 0] ]; if (pattern[modulo(x, 10)][modulo(y, 10)]) PM.setPixel(x, y, selClr); } else if (tool.extra.state.dither8) { let pattern = [ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0], [0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0], [0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0] ]; if (pattern[modulo(x, 10)][modulo(y, 10)]) PM.setPixel(x, y, selClr); } else { PM.setPixel(x, y, selClr); } var t = isFillColor(x, y - 1); var b = isFillColor(x, y + 1); var l = isFillColor(x - 1, y); var r = isFillColor(x + 1, y); t && l && isFillColor(x - 1, y - 1); t && r && isFillColor(x + 1, y - 1); b && l && isFillColor(x - 1, y + 1); b && r && isFillColor(x + 1, y + 1); } delete tool.extra.queue[`${x},${y}`]; tool.extra.usedQueue[`${x},${y}`] = true; } } tool.setFxRenderer((fx, ctx, time) => { let defaultFx = OWOP.fx.player.RECT_SELECT_ALIGNED(1); if (someRenderer(fx, ctx, time, defaultFx)) return; ctx.globalAlpha = 0.8; ctx.strokeStyle = rgb(...(tool.extra.button === 1 ? OWOP.player.selectedColor : OWOP.player.rightSelectedColor)); var z = OWOP.camera.zoom; if (!tool.extra.fillingColor) return defaultFx(fx, ctx, time); ctx.beginPath(); for (let current in tool.extra.queue) { current = tool.extra.queue[current]; if (tool.extra.state.rainbow) ctx.strokeStyle = rgb(...hue(current.x - current.y, 8)); let x = current.x let y = current.y; // if (tool.extra.state.checkered) { // if ((x + y) - 2 * Math.floor((x + y) / 2) == tool.extra.checkered) ctx.rect((x - OWOP.camera.x) * z, (y - OWOP.camera.y) * z, z, z); // } else { ctx.rect((x - OWOP.camera.x) * z, (y - OWOP.camera.y) * z, z, z); // } } ctx.stroke(); }); tool.setEvent("mousedown", (mouse, event) => { if (event.which !== 1 && event.which !== 3) return; tool.extra.button = event.which; tool.extra.fillingColor = PM.getPixel(mouse.tileX, mouse.tileY); tool.extra.queue[`${mouse.tileX},${mouse.tileY}`] = { x: mouse.tileX, y: mouse.tileY }; tool.extra.checkered = (mouse.tileX + mouse.tileY) - 2 * Math.floor((mouse.tileX + mouse.tileY) / 2); PM.startHistory(); tool.setEvent("tick", tick); }); tool.setEvent("mouseup deselect", mouse => { PM.endHistory(); tool.extra.usedQueue = {}; tool.extra.queue = {}; tool.extra.fillingColor = undefined; tool.extra.button = 0; tool.extra.checkered = 0; tool.setEvent("tick", null); return mouse && 1 & mouse.buttons; }); })); OWOP.tool.addToolObject(new OWOP.tool.class('Line', OWOP.cursors.wand, null, 1, tool => { tool.extra.state = { rainbow: false, gradient: false }; tool.extra.start = undefined; tool.extra.end = undefined; tool.extra.lineLength = 0; tool.extra.c = 0; tool.setFxRenderer((fx, ctx, time) => { let defaultFx = OWOP.fx.player.RECT_SELECT_ALIGNED(1); if (someRenderer(fx, ctx, time, defaultFx)) return; ctx.globalAlpha = 0.8; ctx.strokeStyle = rgb(...(tool.extra.button === 1 ? OWOP.player.selectedColor : OWOP.player.rightSelectedColor)); if (tool.extra.state.rainbow) ctx.strokeStyle = rgb(...hue(~~(time / 100), 8)); if ((!tool.extra.start || !tool.extra.end) && (defaultFx(fx, ctx, time), true)) return; tool.extra.lineLength = line(tool.extra.start[0], tool.extra.start[1], tool.extra.end[0], tool.extra.end[1], undefined, undefined, (x, y, i) => { ctx.beginPath(); if (tool.extra.state.rainbow) ctx.strokeStyle = rgb(...hue(~~(time / 100) + i, 8)); ctx.rect((x - camera.x) * camera.zoom, (y - camera.y) * camera.zoom, camera.zoom, camera.zoom); ctx.stroke(); })[0]; }); tool.setEvent('mousedown mouseup', (mouse, event) => { if (event.which !== 1 && event.which !== 3) return; tool.extra.button = event.which; if (event.type === "mousedown" && !tool.extra.start) return tool.extra.start = [mouse.tileX, mouse.tileY]; if (!tool.extra.start) return; tool.extra.end = [mouse.tileX, mouse.tileY]; if (event.type === "mouseup" && tool.extra.start[0] === tool.extra.end[0] && tool.extra.start[1] === tool.extra.end[1]) return; PM.startHistory(); let sc = PM.getPixel(tool.extra.start[0], tool.extra.start[1]); line(tool.extra.start[0], tool.extra.start[1], tool.extra.end[0], tool.extra.end[1], undefined, undefined, (x, y, i) => { let c = event.which === 1 ? OWOP.player.selectedColor : OWOP.player.rightSelectedColor; if (tool.extra.state.gradient) { let divisor = (tool.extra.lineLength - 1); let r = sc[0] - ((sc[0] - c[0]) / divisor) * i; let g = sc[1] - ((sc[1] - c[1]) / divisor) * i; let b = sc[2] - ((sc[2] - c[2]) / divisor) * i; c = [~~r, ~~g, ~~b]; if (i == 0) c = sc; } else if (tool.extra.state.rainbow) c = event.which === 1 ? hue(x - y, 8) : hue(tool.extra.c++, 8); PM.setPixel(x, y, c); }); PM.endHistory(); tool.extra.start = undefined; tool.extra.end = undefined; }); tool.setEvent('mousemove', mouse => { if (tool.extra.start) tool.extra.end = [mouse.tileX, mouse.tileY]; }); tool.setEvent('deselect', () => { PM.endHistory(); tool.extra.start = undefined; tool.extra.end = undefined; tool.extra.c = 0; }); })); OWOP.tool.addToolObject(new OWOP.tool.class('Paste', OWOP.cursors.paste, null, 1, tool => { tool.extra.state = { chunkize: false, rc: () => tool.extra.renderData(0b00), rcc: () => tool.extra.renderData(0b01), fh: () => tool.extra.renderData(0b10), fv: () => tool.extra.renderData(0b11) }; tool.extra.img = undefined; tool.extra.data = undefined; tool.extra.renderData = function (type) { let transpose3 = function (m) { let result = new Array(m[0].length); for (let i = 0; i < m[0].length; i++) { result[i] = new Array(m.length - 1); for (let j = m.length - 1; j > -1; j--) { result[i][j] = m[j][i]; } } return result; }; let reverseRows = function (m) { return m.reverse(); }; let reverseCols = function (m) { for (let i = 0; i < m.length; i++) { m[i].reverse(); } return m; }; let rotateCc = m => transpose3(m).reverse(); let rotateCw = m => transpose3(m.reverse()); switch (type) { case 0: { tool.extra.data = rotateCw(tool.extra.data); } break; case 1: { tool.extra.data = rotateCc(tool.extra.data); } break; case 2: { reverseCols(tool.extra.data); } break; case 3: { reverseRows(tool.extra.data); } break; } ((arr, onblob) => { let c = document.createElement('canvas'); let w = arr[0].length; let h = arr.length; c.width = w; c.height = h; let ctx = c.getContext('2d'); let d = ctx.createImageData(w, h); for (let j = 0; j < h; j++) { for (let i = 0; i < w; i++) { let pix = arr[j][i]; d.data[4 * (j * w + i)] = pix[0]; d.data[4 * (j * w + i) + 1] = pix[1]; d.data[4 * (j * w + i) + 2] = pix[2]; d.data[4 * (j * w + i) + 3] = 255; } } ctx.putImageData(d, 0, 0); c.toBlob(onblob); })(tool.extra.data, b => { let url = URL.createObjectURL(b); let img = new Image(); img.onload = () => tool.extra.img = img; img.src = url; }); } tool.setFxRenderer((fx, ctx, time) => { let defaultFx = OWOP.fx.player.RECT_SELECT_ALIGNED(1); if (someRenderer(fx, ctx, time, defaultFx)) return; let p9 = OWOP.camera.zoom; let pp = OWOP.mouse.tileX; let pD = OWOP.mouse.tileY; if (tool.extra.state.chunkize) { pp = Math.floor(pp / 16) * 16; pD = Math.floor(pD / 16) * 16; } pp -= OWOP.camera.x; pD -= OWOP.camera.y; // if (p2.length) { // ctx.globalAlpha = 0.8; //for (let pS = 0; pS < p2.length; pS++) { // ctx.strokeStyle = C.toHTML(p2[pS][2]); // ctx.strokeRect((p2[pS][0] - OWOP.camera.x) * p9, (p2[pS][1] - OWOP.camera.y) * p9, p9, p9); //} // return 0; // } if (tool.extra.img) { ctx.globalAlpha = 0.5 + Math.sin(time / 500) / 4; ctx.strokeStyle = '#000000'; ctx.scale(p9, p9); ctx.drawImage(tool.extra.img, pp, pD); ctx.scale(1 / p9, 1 / p9); ctx.globalAlpha = 0.8; ctx.strokeRect(pp * p9, pD * p9, tool.extra.img.width * p9, tool.extra.img.height * p9); return 0; } }); tool.setEvent('select', () => { if (tool.extra.k) { if (tool.extra.k instanceof Image) tool.extra.k = NS.getImageData(tool.extra.k); tool.extra.data = tool.extra.k; tool.extra.renderData(); delete tool.extra.k; return; } let p6 = document.createElement('input'); p6.type = 'file'; p6.accept = 'image/*'; p6.addEventListener('change', () => { if (!p6.files || !p6.files[0]) return; let p7 = new FileReader(); p7.addEventListener('load', () => { let p8 = new Image(); p8.addEventListener('load', () => { tool.extra.data = NS.getImageData(p8); tool.extra.renderData(); }); p8.src = p7.result; }); p7.readAsDataURL(p6.files[0]); }); p6.click(); }); tool.setEvent('mousedown', (mouse, event) => { if (!(mouse.buttons & 1)) return; if (!tool.extra.data) return; let x = mouse.tileX; let y = mouse.tileY; let data = tool.extra.data; let fix = (p6, p7, p8) => Math.floor(p6 * (1 - p8) + p7 * p8); if (tool.extra.state.chunkize) { x = Math.floor(x / 16) * 16; y = Math.floor(y / 16) * 16; } PM.startHistory(); for (let j = 0; j < data.length; j++) { for (let i = 0; i < data[0].length; i++) { let d = data[j][i]; let color = PM.getPixel(i + x, j + y); if (!color) continue; let pH = !isNaN(d[3]) ? d[3] / 255 : 1; // let pH = 1; // color = [fix(color[0], data[pD + 0], pH), fix(color[1], data[pD + 1], pH), fix(color[2], data[pD + 2], pH)]; color = [fix(color[0], d[0], pH), fix(color[1], d[1], pH), fix(color[2], d[2], pH)]; // use this when color is checked against being alpha color cause this is stupid // var pix = PM.getPixel(i, j); // if (!PM.queue[`${i},${j}`]) PM.setPixel(i, j, pix); PM.setPixel(i + x, j + y, color); } } PM.endHistory(); }); tool.setEvent('mousemove', (mouse, event) => { if (!OWOP.OPM) return; if (mouse.buttons !== 0) { ((x, y, startX, startY) => { OWOP.require("canvas_renderer").moveCameraBy((startX - x) / 16, (startY - y) / 16); })(mouse.worldX, mouse.worldY, mouse.mouseDownWorldX, mouse.mouseDownWorldY); return mouse.buttons; } }); })); OWOP.tool.addToolObject(new OWOP.tool.class('Copy', OWOP.cursors.copy, null, 1, tool => { tool.extra.state = { margin: false }; function shrinkMargin(s, e) { // for () { // } return [s2, e2]; } tool.setFxRenderer((fx, ctx, time) => { if (someRenderer(fx, ctx, time, () => 1)) return; var x = fx.extra.player.x; var y = fx.extra.player.y; var fxx = (Math.floor(x / 16) - camera.x) * camera.zoom; var fxy = (Math.floor(y / 16) - camera.y) * camera.zoom; var oldlinew = ctx.lineWidth; ctx.lineWidth = 1; if (tool.extra.end) { var s = tool.extra.start; var e = tool.extra.end; var x = s[0]; var y = s[1]; var w = e[0]; var h = e[1]; if (s[0] > e[0]) [w, x] = [x, w]; if (s[1] > e[1]) [h, y] = [y, h]; if (NS.chunkize) { x = Math.floor(x / 16) * 16; y = Math.floor(y / 16) * 16; w = Math.floor(w / 16) * 16 + 16; h = Math.floor(h / 16) * 16 + 16; } w = w - x; h = h - y; x = (x - camera.x) * camera.zoom + 0.5; y = (y - camera.y) * camera.zoom + 0.5; ctx.beginPath(); ctx.rect(x, y, w * camera.zoom, h * camera.zoom); ctx.globalAlpha = 1; ctx.strokeStyle = "#FFFFFF"; ctx.stroke(); ctx.setLineDash([3, 4]); ctx.strokeStyle = "#000000"; ctx.stroke(); ctx.globalAlpha = 0.25 + Math.sin(time / 500) / 4; ctx.fillStyle = renderer.patterns.unloaded; ctx.fill(); ctx.setLineDash([]); var oldfont = ctx.font; ctx.font = "16px sans-serif"; var txt = `${!tool.extra.clicking ? "Right click to copy area " : ""}(${Math.abs(w)}x${Math.abs(h)})`; var txtx = window.innerWidth >> 1; var txty = window.innerHeight >> 1; txtx = Math.max(x, Math.min(txtx, x + w * camera.zoom)); txty = Math.max(y, Math.min(txty, y + h * camera.zoom)); drawText(ctx, txt, txtx, txty, true); ctx.font = oldfont; ctx.lineWidth = oldlinew; return 0; } else { ctx.beginPath(); ctx.moveTo(0, fxy + 0.5); ctx.lineTo(window.innerWidth, fxy + 0.5); ctx.moveTo(fxx + 0.5, 0); ctx.lineTo(fxx + 0.5, window.innerHeight); //ctx.lineWidth = 1; ctx.globalAlpha = 1; ctx.strokeStyle = "#FFFFFF"; ctx.stroke(); ctx.setLineDash([3]); ctx.strokeStyle = "#000000"; ctx.stroke(); ctx.setLineDash([]); ctx.lineWidth = oldlinew; return 1; } }); tool.extra.start = undefined; tool.extra.end = undefined; tool.extra.clicking = false; tool.extra.tempCallback = undefined; tool.setEvent('mousedown', (mouse, event) => { var s = tool.extra.start; var e = tool.extra.end; const isInside = () => { var x = s[0]; var y = s[1]; var w = e[0]; var h = e[1]; if (NS.chunkize) { x = Math.floor(x / 16) * 16; y = Math.floor(y / 16) * 16; w = Math.floor(w / 16) * 16 + 16; h = Math.floor(h / 16) * 16 + 16; } return mouse.tileX >= x && mouse.tileX < w && mouse.tileY >= y && mouse.tileY < h; } if (mouse.buttons === 1 && !tool.extra.end) { tool.extra.start = [mouse.tileX, mouse.tileY]; tool.extra.clicking = true; tool.setEvent('mousemove', (mouse, event) => { if (tool.extra.start && mouse.buttons === 1) { tool.extra.end = [mouse.tileX, mouse.tileY]; return 1; } }); tool.setEvent('mouseup', (mouse, event) => { if (!(mouse.buttons & 1)) { tool.setEvent('mousemove mouseup', null); tool.extra.clicking = false; var s = tool.extra.start; var e = tool.extra.end; if (e) { if (s[0] === e[0] || s[1] === e[1]) { tool.extra.start = undefined; tool.extra.end = undefined; } if (s[0] > e[0]) { var tmp = e[0]; e[0] = s[0]; s[0] = tmp; } if (s[1] > e[1]) { var tmp = e[1]; e[1] = s[1]; s[1] = tmp; } } renderer.render(renderer.rendertype.FX); } }); } else if (mouse.buttons === 1 && tool.extra.end) { if (isInside()) { var offx = mouse.tileX; var offy = mouse.tileY; tool.setEvent('mousemove', (mouse, event) => { var dx = mouse.tileX - offx; var dy = mouse.tileY - offy; tool.extra.start = [s[0] + dx, s[1] + dy]; tool.extra.end = [e[0] + dx, e[1] + dy]; }); tool.setEvent('mouseup', (mouse, event) => { if (!(mouse.buttons & 1)) tool.setEvent('mousemove mouseup', null) }); } else { tool.extra.start = undefined; tool.extra.end = undefined; } } else if (mouse.buttons === 2 && tool.extra.end && isInside()) { tool.extra.start = undefined; tool.extra.end = undefined; let x = s[0]; let y = s[1]; let w = e[0]; let h = e[1]; if (tool.extra.state.chunkize) { x = Math.floor(x / 16) * 16; y = Math.floor(y / 16) * 16; w = Math.floor(w / 16) * 16 + 16; h = Math.floor(h / 16) * 16 + 16; } w -= x; h -= y; let data = []; for (let j = 0; j < h; j++) { data.push([]); for (let i = 0; i < w; i++) { let pix = PM.getPixel(x + i, y + j); if (pix) data[j].push(pix); } } if (tool.extra.tempCallback) { if (tool.extra.tempCallback(data)) { tool.extra.tempCallback = undefined; OWOP.player.tool = "move"; } } else { OWOP.tool.allTools.paste.extra.k = data; OWOP.player.tool = "paste"; } } }); tool.setEvent('deselect', () => { tool.setEvent('mousemove mouseup', null); if (!tool.extra.end) { tool.extra.clicking = false; var s = tool.extra.start; var e = tool.extra.end; if (e) { if (s[0] === e[0] || s[1] === e[1]) { tool.extra.start = undefined; tool.extra.end = undefined; } if (s[0] > e[0]) { var tmp = e[0]; e[0] = s[0]; s[0] = tmp; } if (s[1] > e[1]) { var tmp = e[1]; e[1] = s[1]; s[1] = tmp; } } } tool.extra.tempCallback = undefined; }); })); OWOP.tool.addToolObject(new OWOP.tool.class('Write', OWOP.cursors.write, null, 1, tool => { tool.extra.state = { rainbow: false }; tool.extra.text = ""; tool.extra.newText = { data: { gap: 1, space: 1, height: 8, bottom: 6 }, " ": { width: 1, height: 8, skip: 0, text: "00000000" }, a: { width: 3, height: 3, skip: 3, text: "011101011" }, b: { width: 3, height: 6, skip: 0, text: `100100100110101110` }, c: { width: 3, height: 3, skip: 3, text: `011100011` }, d: { width: 3, height: 5, skip: 1, text: `001001011101011` }, e: { width: 3, height: 3, skip: 3, text: `010110011` }, f: { width: 2, height: 5, skip: 1, text: `0110111010` }, g: { width: 3, height: 5, skip: 3, text: `011101011001110` }, h: { width: 3, height: 5, skip: 1, text: `100100110101101` }, i: { width: 1, height: 5, skip: 1, text: `10111` }, j: { width: 2, height: 7, skip: 1, text: `01000101010110` }, k: { width: 3, height: 5, skip: 1, text: `100100101110101` }, l: { width: 2, height: 5, skip: 1, text: `1010101001` }, m: { width: 5, height: 3, skip: 3, text: `111101010110101` }, n: { width: 3, height: 3, skip: 3, text: `110101101` }, o: { width: 3, height: 3, skip: 3, text: `010101010` }, p: { width: 3, height: 5, skip: 3, text: `110101110100100` }, q: { width: 3, height: 5, skip: 3, text: `011101011001001` }, r: { width: 2, height: 3, skip: 3, text: `111010` }, s: { width: 3, height: 3, skip: 3, text: `011010110` }, t: { width: 2, height: 5, skip: 1, text: `1010111001` }, u: { width: 3, height: 3, skip: 3, text: `101101011` }, v: { width: 3, height: 3, skip: 3, text: `101101010` }, w: { width: 5, height: 3, skip: 3, text: `101011010101010` }, x: { width: 3, height: 3, skip: 3, text: `101010101` }, y: { width: 3, height: 5, skip: 3, text: `101101011001010` }, z: { width: 3, height: 3, skip: 3, text: `110010011` } } tool.extra.position = 0; tool.extra.start = undefined; tool.extra.end = undefined; function setText(t, pos, func) { let localPos = [...pos]; let furthestPos = [...pos]; function setLetter(letter, pos, func) { if (letter === "\n") return 1; if (!tool.extra.newText[letter]) return 0; let data = tool.extra.newText.data; let letterData = tool.extra.newText[letter]; for (let x = 0; x < letterData.width; x++) { for (let y = 0; y < letterData.height; y++) { if (letterData.text[x + y * letterData.width] !== "0") func(pos[0] + x, pos[1] + y + letterData.skip); } } return letterData; } for (let p5 = 0; p5 < t.length; p5++) { let l = setLetter(t[p5].toLowerCase(), localPos, func); if (l === 0) continue; if (l === 1) { localPos[0] = pos[0]; localPos[1] = localPos[1] + tool.extra.newText.data.height + 1; } else { localPos[0] += l.width + tool.extra.newText.data.gap; } if (localPos[0] > furthestPos[0]) furthestPos[0] = localPos[0]; if (localPos[1] > furthestPos[1]) furthestPos[1] = localPos[1]; } return furthestPos; } tool.setFxRenderer((fx, ctx, time) => { if (someRenderer(fx, ctx, time, () => 1)) return; let camera = OWOP.camera; // let x = fx.extra.player.x; // let y = fx.extra.player.y; // let fxx = (Math.floor(x / 16) - camera.x) * camera.zoom; // let fxy = (Math.floor(y / 16) - camera.y) * camera.zoom; let oldlinew = ctx.lineWidth; ctx.lineWidth = 2; let s, e; if (!tool.extra.start) { s = [OWOP.mouse.tileX, OWOP.mouse.tileY]; ctx.strokeStyle = "#00FF00"; } else { s = tool.extra.start; ctx.strokeStyle = "#FF0000"; } let oldFillstyle = ctx.fillStyle; ctx.fillStyle = OWOP.player.htmlRgb; let tempEnd = setText(tool.extra.text, [...s], (x, y) => { let x1 = (x - camera.x) * camera.zoom + 0.5; let y1 = (y - camera.y) * camera.zoom + 0.5; ctx.fillStyle = tool.extra.state.rainbow ? rgb(...hue(x - y, 8)) : OWOP.player.htmlRgb; ctx.fillRect(x1, y1, camera.zoom, camera.zoom); }); e = [tempEnd[0] + 1, tempEnd[1] + 8] if (tool.extra.end) tool.extra.end = e; let x = (s[0] - camera.x) * camera.zoom + 0.5; let y = (s[1] - camera.y) * camera.zoom + 0.5; let w = e[0] - s[0]; let h = e[1] - s[1]; ctx.beginPath(); ctx.rect(x, y, w * camera.zoom, h * camera.zoom); ctx.stroke(); ctx.lineWidth = oldlinew; ctx.fillStyle = oldFillstyle; return 0; }); tool.setEvent('mousedown', (mouse, event) => { var s = tool.extra.start; var e = tool.extra.end; const isInside = () => mouse.tileX >= s[0] && mouse.tileX < e[0] && mouse.tileY >= s[1] && mouse.tileY < e[1]; if (mouse.buttons === 1 && !tool.extra.end) { tool.extra.start = [mouse.tileX, mouse.tileY]; tool.extra.end = [mouse.tileX + 1, mouse.tileY + 7]; tool.setEvent('keydown', (keysDown, event) => { if (event.key.length > 1) { switch (event.key) { case "Enter": { tool.extra.text += "\n"; } break; case "Backspace": { let t = tool.extra.text.split(""); t.pop(); tool.extra.text = t.join(""); } break; } return; } tool.extra.text += event.key; return 1; }); } else if (mouse.buttons === 1 && tool.extra.end) { if (isInside()) { var offx = mouse.tileX; var offy = mouse.tileY; tool.setEvent('mousemove', (mouse, event) => { var dx = mouse.tileX - offx; var dy = mouse.tileY - offy; tool.extra.start = [s[0] + dx, s[1] + dy]; tool.extra.end = [e[0] + dx, e[1] + dy]; }); tool.setEvent('mouseup', () => tool.setEvent('mouseup mousemove', null)); } else { tool.extra.start = undefined; tool.extra.end = undefined; } } else if (mouse.buttons === 2 && tool.extra.end && isInside()) { PM.startHistory(); setText(tool.extra.text, [...tool.extra.start], (x, y) => PM.setPixel(x, y, tool.extra.state.rainbow ? hue(x - y, 8) : OWOP.player.selectedColor)); PM.endHistory(); /* for (let p9 = 0; p9 < 7; p9++) { for (let pp = 0; pp < 7; pp++) { let pD = (p9 * 189 + pp + offsetx * 7); // console.log(tool.extra.text[pD]); // let color = [p8[pD + 0], p8[pD + 1], p8[pD + 2], p8[pD + 3]]; let c = [OWOP.player.selectedColor, undefined, undefined]; let pos = [...tool.extra.start]; pos[0] = pos[0] + pp + p6 * 7; pos[1] = pos[1] + p9 + row * 7; let color = c[tool.extra.text[pD]]; if (color) PM.setPixel(...pos, color); } } } */ return true; } }); tool.setEvent('deselect', () => { tool.extra.position = 0; tool.extra.start = undefined; tool.extra.end = undefined; // tool.extra.text = ""; tool.setEvent('keydown mouseup mousemove', null); }); tool.setEvent('keyup', () => 1); })); if (OWOP?.tool?.allTools?.pipette) OWOP.tool.allTools.pipette.fxRenderer = someRenderer; if (OWOP?.tool?.allTools?.move) OWOP.tool.allTools.move.fxRenderer = someRenderer; // make fucking sure the move tool fucking exists gahhhhh if (OWOP?.tool?.allTools?.zoom) OWOP.tool.allTools.zoom.fxRenderer = someRenderer; OWOP.tool.updateToolbar(); if (document.domain && !NS.OPM) { let r = 0; for (let e in OWOP.tool.allTools) { e = OWOP.tool.allTools[e]; if (e.rankRequired < 2) r++; } document.getElementById("toole-container").style.maxWidth = 40 * Math.ceil(r / 8) + "px"; } makeOptionsWindow(); }, 1.5e3); })(); if (document.domain && !NS.OPM) { let originalFunction = OWOP.chat.sendModifier; NS.privateMessageID = void 0; OWOP.chat.sendModifier = function () { let command = arguments[0].slice(1).split(' '); if (arguments[0].startsWith('/')) { switch (command[0]) { case "commands": case "help": { OWOP.chat.local(`Commands: /tp, /whitelist, /msg`); } break; case "tp": { if (!NS.teleport) NS.teleport = {}; if (command.length === 3) { if (isNaN(Number(command[1])) || isNaN(Number(command[2]))) break; if (Math.abs(Number(command[1])) < 500000 && Math.abs(Number(command[2])) < 500000) { NS.M20.centerCameraTo(Number(command[1]), Number(command[2])); NS.teleport.camera = { x: undefined, y: undefined } } else { if (NS.teleport.camera?.x === undefined) { NS.teleport.camera = { x: Number(command[1]), y: Number(command[2]) } !function teleport() { let dx = NS.teleport.camera.x - NS.M20.camera.x; let dy = NS.teleport.camera.y - NS.M20.camera.y; let distanceX = Math.abs(dx) < 10000 ? -window.innerWidth / OWOP.camera.zoom / 2 + dx : Math.sign(dx) * 10000; let distanceY = Math.abs(dy) < 10000 ? -window.innerHeight / OWOP.camera.zoom / 2 + dy : Math.sign(dy) * 10000; let teleported = false; if (Math.abs(dx) > 1000) { NS.M20.camera.zoom = 32; NS.M20.moveCameraBy(distanceX, 0); teleported = true; } else if (Math.abs(dy) > 1000) { NS.M20.camera.zoom = 32; NS.M20.moveCameraBy(0, distanceY); teleported = true; } if (teleported) setTimeout(teleport, 150); else NS.teleport.camera = { x: undefined, y: undefined }; }(); } else { NS.teleport.camera = { x: Number(command[1]), y: Number(command[2]) } } } } if (command.length === 2) { if (isNaN(Number(command[1]))) break; let p = NS.M0.misc.world.players[command[1]]; if (!p) { OWOP.chat.local(`Player ${command[1]} doesn't exist.`); break; } if (Math.abs(p.x) > 2 ** 24 || Math.abs(p.y) > 2 ** 24) break; if (Math.abs(Number(p.tileX)) < 500000 && Math.abs(Number(p.tileY)) < 500000) { NS.M20.centerCameraTo(Number(p.tileX), Number(p.tileY)); // NS.M20.centerCameraTo(Number(command[1]), Number(command[2])); NS.teleport.camera = { x: undefined, y: undefined } } else { if (NS.teleport.camera?.x === undefined) { NS.teleport.camera = { x: Number(p.tileX), y: Number(p.tileY) } !function teleport() { let dx = NS.teleport.camera.x - NS.M20.camera.x; let dy = NS.teleport.camera.y - NS.M20.camera.y; let distanceX = Math.abs(dx) < 10000 ? window.innerWidth / OWOP.camera.zoom / 2 + dx : Math.sign(dx) * 10000; let distanceY = Math.abs(dy) < 10000 ? window.innerHeight / OWOP.camera.zoom / 2 + dy : Math.sign(dy) * 10000; if (Math.abs(dx) > 1000) { NS.M20.camera.zoom = 32; NS.M20.moveCameraBy(distanceX, 0); setTimeout(teleport, 150); } else if (Math.abs(dy) > 1000) { NS.M20.camera.zoom = 32; NS.M20.moveCameraBy(0, distanceY); setTimeout(teleport, 150); } else { NS.teleport.camera = { x: undefined, y: undefined } } }(); } else { NS.teleport.camera = { x: Number(p.tileX), y: Number(p.tileY) } } } } } break; case "chat": { // if (isNaN(Number(command[1]))) break; if (command[1] === "all") { NS.privateMessageID = void 0; OWOP.chat.local(`Chat set to Mode: All.`); } else if (isNaN(Number(command[1]))) { } else { OWOP.chat.local(`Chat set to Mode: Private Messaging\nID: ${command[1]}`); } NS.privateMessageID = Number(command[1]); command[0] = "tell"; arguments[0] = "/" + command.join(" "); } break; case "pm": case "message": case "msg": { command[0] = "tell"; arguments[0] = "/" + command.join(" "); } break; case "wl": case "whitelist": { if (!command[1]) { OWOP.chat.local(`Whitelist: ${Object.keys(PM.whitelist).join(", ")}`); console.log(1); break; } // if (!isNaN(Number(command[1]))) [command[1], command[2], command[3]] = ["add", command[1], command[2]]; // else { // OWOP.chat.local(`Syntax: /whitelist [add/remove] [id] -[super: true/false]-`); // console.log(2); // break; // } switch (command[1]) { case "add": { if (isNaN(Number(command[2]))) { OWOP.chat.local(`Syntax: /whitelist [add/remove] [id] -[super: true/false]-`); console.log(3); break; } if (PM.whitelist[command[2]]) { OWOP.chat.local(`Player ${command[2]} is already whitelisted.`); console.log(4); break; } if (!Object.keys(NS.M0.playerList).includes(command[2])) { OWOP.chat.local(`Player ${command[2]} doesn't exist.`); console.log(5); break; } let _super = false; if (command[3] === "true") _super = true; PM.whitelist[command[2]] = { super: _super }; OWOP.chat.local(`Player ${command[2]} added to whitelist.`); console.log(6); } break; case "remove": { if (isNaN(Number(command[2]))) { OWOP.chat.local(`Syntax: /whitelist [add/remove] [id] -[super: true/false]-`); console.log(7); break; } if (!PM.whitelist[command[2]]) { OWOP.chat.local(`Player ${command[2]} is not on the whitelist.`); console.log(8); break; } delete PM.whitelist[command[2]]; OWOP.chat.local(`Player ${command[2]} removed from whitelist.`); console.log(9); } break; default: { } } } break; } } else if (NS.privateMessageID) { command[0] = "tell"; arguments[0] = "/" + command.join(" "); } return originalFunction.bind(this)(...arguments); } console.log("non opm completed"); } if (document.domain && NS.OPM) { let element1 = document.createElement("span"); element1.className = "top-bar"; element1.style.float = "right"; element1.style.width = "34px"; element1.style.height = "17px"; element1.style.background = "#FFFFFF"; if (localStorage.rSC) { let arr = JSON.parse(localStorage.rSC); element1.style.background = `#${arr[0].toString(16).padStart(2, "0")}${arr[1].toString(16).padStart(2, "0")}${arr[2].toString(16).padStart(2, "0")}`; } let element2 = document.createElement("span"); element2.className = "top-bar"; element2.style.float = "right"; element2.textContent = "Right Color:"; let element3 = document.createElement("span"); element3.className = "top-bar"; element3.style.float = "right"; element3.textContent = "Your ID: null"; OWOP.elements.topBar.appendChild(element1); OWOP.elements.topBar.appendChild(element2); OWOP.elements.topBar.appendChild(element3); document.getElementById("playercount-display").style.marginRight = "45px"; setInterval(() => { let arr = OWOP.player.rightSelectedColor; element1.style.background = rgb(...arr); element3.textContent = `Your ID:${OWOP.player.id}`; }, 10); // teleport detector OWOP.playerList = {}; function tick() { let players = OWOP.require("main").playerList; let playersFixed = {}; playersFixed[OWOP.player.id] = { id: OWOP.player.id, x: OWOP.mouse.tileX, y: OWOP.mouse.tileY }; for (let player in players) { let n = players[player].childNodes; playersFixed[n[0].innerHTML] = { id: ~~n[0].innerHTML, x: ~~n[1].innerHTML, y: ~~n[2].innerHTML } } players = playersFixed; // check if the local copy has a disconnected player for (let p1 in OWOP.playerList) { let test = false; for (let p2 in players) { if (p1 === p2) { test = true; break; } } if (!test) { delete OWOP.playerList[p1]; //OWOP.chat.local(`${p1} has left.`); } } // check if the main copy has new players for (let p1 in players) { let test = false; for (let p2 in OWOP.playerList) { if (p1 === p2) { test = true; break; } } if (!test) { let p = players[p1]; OWOP.playerList[p.id] = { id: p.id, x: p.x, y: p.y } //OWOP.chat.local(`${p1} has joined.`); } } // check for a teleport var banlist = []; for (let player in players) { let p1 = OWOP.playerList[player]; let p2 = players[player]; if (Math.sqrt((p1.x - p2.x) ** 2 + (p1.y - p2.y) ** 2) > 2000) { //console.log("someone teleported", p2.id, p2.x, p2.y); p1.tp = !isNaN(p1.tp) ? p1.tp + 1 : 1; //if (!p1.ban && p1.tp < 10) OWOP.chat.local(`${player} Teleported from ${p1.x} ${p1.y} to ${p2.x} ${p2.y}`); } p1.x = p2.x; p1.y = p2.y; } return players; } setInterval(tick, 10); setInterval(() => { for (let player in OWOP.playerList) { let p1 = OWOP.playerList[player]; if (p1.tp >= 10) p1.ban = true; p1.tp = 0; } }, 10 * 1000); // it gets in the way of reading chat, im not trying to be mean to arc. { let e = document.querySelector("div[id='arc-widget-container']"); e ? e.parentElement.removeChild(e) : void 0; } console.log("opm completed"); } { setInterval(() => { let k = document.getElementById("chat-messages").children; for (let i = 0; i < k.length; i++) { let t = k[i].innerHTML; let id = OWOP.player.id; var hasClass = t.classList !== undefined ? Array.from(t.classList).indexOf('nK') > -1 : false; if (!t.match(`(\\[${id}\\]: )|(${id}: )`) && t.match(`${id}`) && !hasClass) k[i].style = "background: #FF404059;"; } }, 100);// change this to mutation observer OWOP.windowSys.class.window.prototype.move = (function (t, e) { document.getElementById('windows').appendChild(this.frame); document.getElementById('windows').appendChild(OWOP.windowSys.windows.Tools.frame); return this.opt.immobile || (this.frame.style.transform = "translate(" + t + "px," + e + "px)", this.x = t, this.y = e), this }); Object.keys(OWOP.windowSys.windows).forEach(e => OWOP.windowSys.windows[e].move = (function (t, e) { document.getElementById('windows').appendChild(this.frame); document.getElementById('windows').appendChild(OWOP.windowSys.windows.Tools.frame); return this.opt.immobile || (this.frame.style.transform = "translate(" + t + "px," + e + "px)", this.x = t, this.y = e), this })); if (NS.et) { clearInterval(OWOP.misc.tickInterval); OWOP.misc.tickIntervalNS = setInterval(O, 1e3 / OWOP.options.tickSpeed); function O() { NS.M14.eventSys.emit(OWOP.events.tick, t); if (null !== OWOP.player.tool && null !== OWOP.misc.world) OWOP.player.tool.call("tick"); if (OWOP.player.tool == OWOP.tool.allTools.write) return; var t = ++OWOP.misc.tick; var e = Math.max(Math.min(OWOP.options.movementSpeed, 64), 0); var n = 0; var r = 0; (NS.keysdown[38] || (NS.keysdown[87] && !NS.keysdown[16])) && (r -= e); (NS.keysdown[37] || (NS.keysdown[65] && !NS.keysdown[16])) && (n -= e); (NS.keysdown[40] || (NS.keysdown[83] && !NS.keysdown[16])) && (r += e); (NS.keysdown[39] || (NS.keysdown[68] && !NS.keysdown[16])) && (n += e); if (0 !== n || 0 !== r) { // OWOP.require("canvas_renderer").moveCameraBy(n, r); NS.M20.moveCameraBy(n, r); A(null, "mousemove", OWOP.mouse.x, OWOP.mouse.y); } } function A(t, e, n, r) { OWOP.mouse.x = n; OWOP.mouse.y = r; let o = 0; if (null !== OWOP.misc.world) OWOP.mouse.validTile = OWOP.misc.world.validMousePos(OWOP.mouse.tileX, OWOP.mouse.tileY); if (null !== OWOP.player.tool) o = OWOP.player.tool.call(e, [OWOP.mouse, t]); if (F(OWOP.mouse.tileX, OWOP.mouse.tileY)) NS.M21.updateClientFx(); return o; } function F(t, e) { return (OWOP.misc.lastXYDisplay[0] !== t || OWOP.misc.lastXYDisplay[1] !== e) && (OWOP.misc.lastXYDisplay = [t, e], OWOP.options.hexCoords && (t = (t < 0 ? "-" : "") + "0x" + Math.abs(t).toString(16), e = (e < 0 ? "-" : "") + "0x" + Math.abs(e).toString(16)), OWOP.elements.xyDisplay.innerHTML = "X: " + t + ", Y: " + e, !0) } } console.log("all completed"); } // window setup // palette saver !(function () { let windowName = "Palette Saver"; let options = { closeable: false } let paletteJson = {} function windowFunc(thisWindow) { var divwindow = document.createElement("div"); divwindow.style = "width: 300px; overflow-y: scroll; overflow-x: scroll; max-height: 165px;" divwindow.innerHTML = `<input id="pName" type="text" style="max-width: 100px; border: 0px;" placeholder="Name"></input> <button id="addPalette" >Save Current Palette</button> <table id="paletteTable" style="overflow-x: hidden; overflow-y: scroll;"></table>`; thisWindow.addObj(divwindow); } var windowClass = OWOP.windowSys.addWindow(new OWOP.windowSys.class.window(windowName, options, windowFunc)) .move(window.innerWidth / 3, window.innerHeight / 3); windows[windowName] = windowClass; NS.windows[windowName].frame.style.visibility = "hidden"; var pName = document.getElementById("pName"); pName.oninput = () => { if (pName.value.length > 25) pName.style.backgroundColor = "rgb(255 148 129)"; else pName.style.backgroundColor = "rgb(255, 255, 255)"; } document.getElementById("addPalette").onclick = () => { if (pName.value.length > 25) return alert("Your max name length is 25 characters."); if (pName.value.length == 0) return alert("Invalid Name"); if (!localStorage.getItem("paletteJson")) { paletteJson[pName.value] = OWOP.player.palette; localStorage.setItem("paletteJson", JSON.stringify(paletteJson)); } else { paletteJson = JSON.parse(localStorage.getItem("paletteJson")); if (paletteJson[pName.value]) { pName.value = ""; return alert("You already have a palette with this name."); } paletteJson[pName.value] = OWOP.player.palette; localStorage.setItem("paletteJson", JSON.stringify(paletteJson)); } var divPalette = document.createElement("tr"); let pN = pName.value; divPalette.id = `im-busy${pN}`; divPalette.innerHTML = `<td id="palette-${pN}" style="cursor: pointer; padding: 5px; border: 1px solid white; border-radius: 5px; color: white;">${pN}</td> <td id="useT1-${pN}"><button id="useB1-${pN}">Use</button></td> <td id="useT2-${pN}"><button id="useB2-${pN}">Replace</button></td> <td id="useT3-${pN}"><button id="useB3-${pN}">Delete</button></td>`; document.getElementById("paletteTable").appendChild(divPalette); document.getElementById(`useB1-${pN}`).onclick = () => { let paletteJson = JSON.parse(localStorage.getItem("paletteJson")); OWOP.player.palette.splice(0); OWOP.player.palette.push(...paletteJson[pN]); OWOP.player.paletteIndex = OWOP.player.paletteIndex; } document.getElementById(`useB2-${pN}`).onclick = () => { if (!confirm(`Are you sure you want to REPLACE the palette ${pN}?`)) return; let paletteJson = JSON.parse(localStorage.getItem("paletteJson")); paletteJson[`${pN}`] = OWOP.player.palette; localStorage.setItem('paletteJson', JSON.stringify(paletteJson)); } document.getElementById(`useB3-${pN}`).onclick = () => { if (!confirm(`Are you sure you want to DELETE the palette ${pN}?`)) return; let paletteJson = JSON.parse(localStorage.getItem("paletteJson")); document.getElementById(`palette-${pN}`).outerHTML = ''; document.getElementById(`im-busy${pN}`).outerHTML = ''; delete paletteJson[pN]; localStorage.setItem('paletteJson', JSON.stringify(paletteJson)); } pName.style.backgroundColor = "rgb(255 255 255)"; pName.value = ""; } if (localStorage.getItem("paletteJson")) { var gettedJson = JSON.parse(localStorage.getItem("paletteJson")); var obj = Object.keys(gettedJson); for (var i = 0; i < obj.length; i++) { let pN = obj[i]; var divPalette = document.createElement("tr"); divPalette.id = `im-busy${pN}`; divPalette.innerHTML = `<td id="palette-${pN}" style="cursor: pointer; padding: 5px; border: 1px solid white; border-radius: 5px; color: white;">${pN}</td> <td id="useT1-${pN}"><button id="useB1-${pN}">Use</button></td> <td id="useT2-${pN}"><button id="useB2-${pN}">Replace</button></td> <td id="useT3-${pN}"><button id="useB3-${pN}">Delete</button></td>`; document.getElementById("paletteTable").appendChild(divPalette); document.getElementById(`useB1-${pN}`).onclick = () => { let paletteJson = JSON.parse(localStorage.getItem("paletteJson")); OWOP.player.palette.splice(0); OWOP.player.palette.push(...paletteJson[`${pN}`]); OWOP.player.paletteIndex = OWOP.player.paletteIndex; } document.getElementById(`useB2-${pN}`).onclick = () => { if (!confirm(`Are you sure you want to REPLACE the palette ${pN}?`)) return; let paletteJson = JSON.parse(localStorage.getItem("paletteJson")); paletteJson[`${pN}`] = OWOP.player.palette; localStorage.setItem('paletteJson', JSON.stringify(paletteJson)); } document.getElementById(`useB3-${pN}`).onclick = () => { if (!confirm(`Are you sure you want to DELETE the palette ${pN}?`)) return; let paletteJson = JSON.parse(localStorage.getItem("paletteJson")); document.getElementById(`palette-${pN}`).outerHTML = ''; document.getElementById(`im-busy${pN}`).outerHTML = ''; delete paletteJson[pN]; localStorage.setItem('paletteJson', JSON.stringify(paletteJson)); } } } })(); // icons !(function () { let windowName = "Icons"; let options = { closeable: false } function windowFunc(thisWindow) { let content = ` <style> .NSspan1 { display: flex; flex-direction: column; max-height: 200px; width: 300px; } .NSspan2 { display: flex; justify-content: space-between; padding: 4px 0px; } .NSspan3 { display: flex; background: #0003; border-radius: 10px; padding: 5px; } .NSspan4 { display: flex; flex-direction: column; align-items: center; width: 75px; } .NSspan5 { display: flex; flex-direction: column; justify-content: space-evenly; } .NSspan6 { padding: 5px 0px; } .NSdiv1 { background-image: url("https://ourworldofpixels.com/img/toolset.png"); width: 36px; height: 36px; } .NSdiv2 { background: #aba389; color: #7e635c; border-radius: 6px; border: initial; padding: 4px; text-shadow: 1px 1px #4d313b; } </style> <span class="NSspan1"> <span class="NSspan2"> <span class="NSspan3"> <span class="NSspan4"> <span class="NSspan6"> <div class="NSdiv1" style="background-position: 0px 0px;"></div> </span> <div class="NSdiv2">Cursor</div> </span> <span class="NSspan5"> <button class="optionButton" style="max-height: 25px;" onclick="NS.iconSelect('cursor')">Select</button> <button class="optionButton" style="max-height: 25px;" onclick="NS.iconPaste('cursor')">Paste</button> </span> </span> <span class="NSspan3"> <span class="NSspan4"> <span class="NSspan6"> <div class="NSdiv1" style="background-position: -36px 0px;"></div> </span> <div class="NSdiv2">Move</div> </span> <span class="NSspan5"> <button class="optionButton" style="max-height: 25px;" onclick="NS.iconSelect('move')">Select</button> <button class="optionButton" style="max-height: 25px;" onclick="NS.iconPaste('move')">Paste</button> </span> </span> </span> <span class="NSspan2"> <span class="NSspan3"> <span class="NSspan4"> <span class="NSspan6"> <div class="NSdiv1" style="background-position: 0px -36px;"></div> </span> <div class="NSdiv2">Pipette</div> </span> <span class="NSspan5"> <button class="optionButton" style="max-height: 25px;" onclick="NS.iconSelect('pipette')">Select</button> <button class="optionButton" style="max-height: 25px;" onclick="NS.iconPaste('pipette')">Paste</button> </span> </span> <span class="NSspan3"> <span class="NSspan4"> <span class="NSspan6"> <div class="NSdiv1" style="background-position: -36px -72px;"></div> </span> <div class="NSdiv2">Zoom</div> </span> <span class="NSspan5"> <button class="optionButton" style="max-height: 25px;" onclick="NS.iconSelect('zoom')">Select</button> <button class="optionButton" style="max-height: 25px;" onclick="NS.iconPaste('zoom')">Paste</button> </span> </span> </span> <span class="NSspan2"> <span class="NSspan3"> <span class="NSspan4"> <span class="NSspan6"> <div class="NSdiv1" style="background-position: -72px 0px;"></div> </span> <div class="NSdiv2">Select</div> </span> <span class="NSspan5"> <button class="optionButton" style="max-height: 25px;" onclick="NS.iconSelect('export')">Select</button> <button class="optionButton" style="max-height: 25px;" onclick="NS.iconPaste('export')">Paste</button> </span> </span> <span class="NSspan3"> <span class="NSspan4"> <span class="NSspan6"> <div class="NSdiv1" style="background-position: -36px -36px;"></div> </span> <div class="NSdiv2">Bucket</div> </span> <span class="NSspan5"> <button class="optionButton" style="max-height: 25px;" onclick="NS.iconSelect('fill')">Select</button> <button class="optionButton" style="max-height: 25px;" onclick="NS.iconPaste('fill')">Paste</button> </span> </span> </span> <span class="NSspan2"> <span class="NSspan3"> <span class="NSspan4"> <span class="NSspan6"> <div class="NSdiv1" style="background-position: -108px -108px;"></div> </span> <div class="NSdiv2">Wand</div> </span> <span class="NSspan5"> <button class="optionButton" style="max-height: 25px;" onclick="NS.iconSelect('line')">Select</button> <button class="optionButton" style="max-height: 25px;" onclick="NS.iconPaste('line')">Paste</button> </span> </span> <span class="NSspan3"> <span class="NSspan4"> <span class="NSspan6"> <div class="NSdiv1" style="background-position: -108px -36px;"></div> </span> <div class="NSdiv2">Paste</div> </span> <span class="NSspan5"> <button class="optionButton" style="max-height: 25px;" onclick="NS.iconSelect('paste')">Select</button> <button class="optionButton" style="max-height: 25px;" onclick="NS.iconPaste('paste')">Paste</button> </span> </span> </span> <span class="NSspan2"> <span class="NSspan3"> <span class="NSspan4"> <span class="NSspan6"> <div class="NSdiv1" style="background-position: -108px 0px;"></div> </span> <div class="NSdiv2">Copy</div> </span> <span class="NSspan5"> <button class="optionButton" style="max-height: 25px;" onclick="NS.iconSelect('copy')">Select</button> <button class="optionButton" style="max-height: 25px;" onclick="NS.iconPaste('copy')">Paste</button> </span> </span> <span class="NSspan3"> <span class="NSspan4"> <span class="NSspan6"> <div class="NSdiv1" style="background-position: -36px -108px;"></div> </span> <div class="NSdiv2">Text</div> </span> <span class="NSspan5"> <button class="optionButton" style="max-height: 25px;" onclick="NS.iconSelect('write')">Select</button> <button class="optionButton" style="max-height: 25px;" onclick="NS.iconPaste('write')">Paste</button> </span> </span> </span> </span> `; thisWindow.container.innerHTML = content; NS.iconSelect = function (iconsName) { OWOP.tool.allTools.copy.extra.tempCallback = function (data) { if (data.length !== 36 || data[0].length !== 36) { OWOP.chat.local("The size needs to be (36 by 36)."); return false; } NS.localStorage.cursors[iconsName].icon = NS.setImageData(data).toDataURL(); localStorage.NS = JSON.stringify(NS.localStorage); return true; } OWOP.player.tool = "copy"; } NS.iconPaste = function (iconsName) { let offset = [0, 0]; let icon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAAA00lEQVRYw+3YMQ6DMAwFUPPFhTpCRxaW3qYzQ9f2Nl1YGIGRI8ENShz7W6mEZxwe34kUIXKVoR63+x79TpSGQmlJobTxJYHe8xiGSk4oCgXNwxEoaBvYKOQ0MVHIbew/AwWVDeqaloKCdQFvlAnUNa07Cl5Re6HguSE9UPA+tlaUO8iKMoGmdXFHURKyoJCTxLQuP9OxoGrLeMbnS31H/25zRRmZFpN686ytmLMvpp8yJkYNYmNUoAiMiEil3YBMjHpkbIwKFIFJBkVhivz7cdXf1QFBsW2mhPMCDAAAAABJRU5ErkJggg=="; switch (iconsName) { case "cursor": { icon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAAA00lEQVRYw+3YMQ6DMAwFUPPFhTpCRxaW3qYzQ9f2Nl1YGIGRI8ENShz7W6mEZxwe34kUIXKVoR63+x79TpSGQmlJobTxJYHe8xiGSk4oCgXNwxEoaBvYKOQ0MVHIbew/AwWVDeqaloKCdQFvlAnUNa07Cl5Re6HguSE9UPA+tlaUO8iKMoGmdXFHURKyoJCTxLQuP9OxoGrLeMbnS31H/25zRRmZFpN686ytmLMvpp8yJkYNYmNUoAiMiEil3YBMjHpkbIwKFIFJBkVhivz7cdXf1QFBsW2mhPMCDAAAAABJRU5ErkJggg=="; } break; case "move": { icon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAABgklEQVRYw+2YvU7EMAzH/055CYZj6IJ0243Q8ZYs9zbcWgErfZtbTkgdGNqOtyM2Ft7imHKK0g/nw4Ui4S1K7Pzi2q4TQEB2m+K82xRnCVskAWOPD6eGfg3IwLw0RwDAvtDJUCQFYyQViiRhJKBIGiYVilICmPNQTKCrEKCYTxCqo+bcIOYACguTvwMk9SsIta2mFDiofaFRd+1lXHdtL8NCbVOKZ3zTPiTwVUzRAwBdlVFz7mFcB1BMBfYB9l3rVvTMhtFViXy1mjSQrXN2TcjabJ3j4/UNt9c3j+9fn09kwwDA9u7+R9PcJMXx4RkAcDW2YG4wOzt7MeR6iRNf2LFNXTHeOZwaUnZAmQkf5ZCNfGF6dcj2FGdMV+Wop+qu9dJ3YRZZGIn71wy1EPa87SnXM5zu0Lyaoub6GZMEdddeAphLDM62kmyuJBq3/wZNHCgkC2OaPDUXTKxO9EWRy6ahojf7VXoMKhZG5LHBhUqBEXuOMVCpMIt8sBK7Z0nd474B40/4pg5xCDEAAAAASUVORK5CYII="; } break; case "pipette": { icon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAABAUlEQVRYw+3XvQ6CMBQF4FPiCzHQRDu6uPA2zg6u+jYuLI5ogoOPhFOTpnL7Y3ovDj0jIeRLzyEEoKaGTt+auW/NHLpHSUH8a7f3qFYBuZhOawDAa5pIlJLAWIgbCrXhrmYJI7KhHEyosqYUyH14p3X2ybBtKLSb2OkUB/m1+agYhmVDh+sJADAcz8mvevENWcxlHLDf7uDCLCQ1TUkMANyfD3I37KAQxlYWq6jYhnIxfWvmFJz6l5P5GcSJyQZxY7JAEphkkBQmCSSJiYKkMUHQGhgS5H8o3XBisj8d3JhFkF+VJOarMhdjN2MhEhiysrUw5Aml/GGKgHyUNKampkQ+wWnd9v+Wv9QAAAAASUVORK5CYII="; } break; case "zoom": { icon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAABMUlEQVRYw+3Wuw6CMBQG4L+NL+SIjgyy+CSuujo4u/ISri4wdFQTHFx9CScS1zrVNFCgdzThJCRcGvrlHHooMMWfBfH5svV8yVX3z48LiQrqgtjAiE9M14Q6Y7yVSEyWs5I/33XryFnJVeODYVQQGSFHzkoeBCW/VAdigqIuMBnAblds0hWJ3idU2dHJjG6WqCvQd2acQb7LRPFjQV3LZRNpsggDsimX6QIwXmmm8XzX4fpQiOxQm+zI57olyFnJ02SB3TLr/ckSG0x23AMAiu0B8rXqmxIQAIMYI1AT8zoVAIB7VX3HiGfN1SQgOtsP4oJpgqJs0HQwYqLgW1gTTPBN/hiYTtBYGCVoTMxgY4yNaWVIzs4YGACY9WVG7jExMJ2gZrOLhen9qGNDppjCV3wAmp0jyCb9nC4AAAAASUVORK5CYII="; } break; case "export": { icon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAABCklEQVRYw+2YMQ6CQBBFP4QL2Ql02mDhadQWg+3iaSzcRrsVO4+k1RCNhB3RHdZkfzUJBW//Z4YBIOjPFAHAcpLfpW54uJmoF0gShgOVULHYbwEAs2kKADhfm5/Xm7ywR0YOKaNxvjZOnTmuKqtDsVRM5JJNLZBrd7iKPz3BUHEPHCILkXkdGc0dryIjKG8iU0bjuKr86jJlNOs9Jtplymi/ugwAirqEbf8SHYzzNLNCiUXGdSruGmAE9209BMr5ClvUJeZpBgA4NZe363q9e1nanC/55ESfnqEiVyB0yC4gAhi97W0wh5uJkjFgvFjyOTBiQFyYtstcPtTcT2hRh7gwzjXGf4MgcT0AtrSSgUtEfWEAAAAASUVORK5CYII="; } break; case "fill": { icon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAABjUlEQVRYw+2YsW7DIBCGAfWFMhgpZezCkreJVw9Z7bfpwpLRiYSHPlI6XYSviLszWG2lnJQhGJNP//3HQZR6xT8LzZ14OrgHHvv8mvWvAOVg9oLTXBg/DavxcL7sAqU5MOMcVO/86lln7er7EmMTKC2FwSAYqBbKtICBgLRyPMcG2grTCspwJlEwS4wr09dAaUodjmfgnev9lq1EiaeMRJklxufHT8NTCT8N6nq/qY/je3X63jiTQI3cXpSOAVSqlJ8GFc4XdTq4B0cpQ4FgNVKYcQ4/3qlVylAVg0EwDP7xWqgsUO+8GueQbQ+QpjQtLaGMpCRznmkNpUtdHW+OufRhGFz68Jy7JZhSt4bUlWC2KiVOGRg69VPOU62hWB7qnVedtaqzdncokamXGKuhqJZipDCcKEHlTF+lEO7sUiiq4YqAqGqjoDjdnw0Ei5T8U4KC/YxqsCKFtkJxYUignMRSKOkhTewhCVTzE+NWqHRXl16JNHV1phYsHSW23M+KF0Xughhqjz8hXvFn4xvHckf64m/UhgAAAABJRU5ErkJggg=="; } break; case "line": { icon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAABEUlEQVRYw+2XvRGEIBCFkbEDKzGQxAZITK3E2OBiKzG9hAYuweAqsQYvWofjVOB4GPESHRdmP/cHV8aysrLSqrgydnW70f3z/Sp8bUmATIc+QkFx1wI5jUxO48/zRgjWCAFPWem78AhqnRUciLtSoIbHoX2dFVu0vg/IpaqXXykLrTk4EEHJadzBEFBlzGY7bYhO4662p7e3C1gNDziMd8ooEgRlwlH33VZDi9Z7JOxrIwRbZwWFcrb91dlDYEiooLzb3y+7zqpe7ufWvzUVvKmr2810hoaCdAYSCjY2oKBgQCgoKBACCg4UC5UEKAYqGdARlHmYnkHxlEDkNGSQSxqhs+EN+ZcSBYWaCLKysmL0AfZSsN1jloZVAAAAAElFTkSuQmCC"; } break; case "paste": { icon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAABQ0lEQVRYw+2Yvw6CMBDGr4QXYpBA2Jx04GmMs3E2Po2DTmwEggOPhFOTUtvSa6/FGC4xacuf/vjuu1IE2CJg1Fk11Vk1Ud6T+cCI/cfYslWARJDj/QIAAM/TlQyM+cBwELHtC8VsU2JSxTSOhUwwMCoAuY19QDlS08Fdns/672HQQmGucwZSTaRLiQ4GGyn2At8JnTy0ZqAUwnghWspu7Qt1/rk6/F7KeDXalH40D9lCpTFg5KWizqpJt3J7ATV9BwAA+6L86vP2rX3Nxpc85QXEQVR9XZu8ykQlVOrICpkegAxIdWOTWkHXIZ1XVIAqJYMrZJrIRaXEVSH+k/0T/dVB6Zf/e9uryl5n4KbvZuPRTL2URmw6yRRa3UP7oiQFsVLItEOkLPVFoMfYMtO+JYQy6E9p6n85dPsh52/7EDBb2MQHK+ObZIdb/JMAAAAASUVORK5CYII="; } break; case "copy": { icon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAABS0lEQVRYw+2XMQ6CMBSGfwxH8CIOEg2bkx2cOYhxJs6Ggzg74ORGNGXwIt5BpxrAAn3PVzWGPzEpaMLH199CgSFD/iwB5cerSXznXORwLQJxIC4MFYoMpLKUBJKvtySo0JeRaqZRhFJrrCbxvQ8qkIZpGszXW0yjCABQat1rqhNoVxxJMJt4+QJVnTKXToXSf1uVpTUrKktx2+cAgHGiWgFNRj7WEpWlKLXGOFFPEDNml5qbqoGqKQMmBnS6nAEAi9n85diMd8Wxdn4TL53NkIEMiO24bQyg1h8RIHPHNjtNQzZgcUPNO+6z9W5CSndsJmzfvQNIMtR1ISlLIxdD5tPsj0tu+/xZbC8dopqgltrLSv2RUncV+HQ5185/rNR90yhRbJahr05Z2wrNediKAXFAuC/8rA753AaFLq+kP7FRlNp1UOwMGfKXeQBOJJ69p18KUgAAAABJRU5ErkJggg=="; } break; case "write": { icon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAABTUlEQVRYw+2XPW6DQBCFHyNu4JOktF26oUnrk7hO4TY5CW2abbY0SEvhk3AGp8miMcGEmVmMLPEa/0iGx3xvZsfAqlU2ZdYLvL/tb/zz9/WSLWaobyaFqcxq5vPiAAC+rgAA7nQ2maIU3KOZFKKUZtrSLWOoj8udzh2q4utjNF+zVsjXVWcEAJoQlkcWA2xtd7UhjmsoM23pTNjIgmsIkRWb2tBYR1m6jbS4YiV4duL7JgQ1NrLOntQiC66hzorfabGRBdeYtNhyCy7tNJ59MD59QeO4fF3hsN3dVeyw3d299iVZSXINrv5NfV2hLR38b5g3x6IL9eZYiCokzhA/TP8ohp2FvhAaIgkuTStLz7ZcgmtoOv/3ME0IoiqRZomf44+BqO05Lsnew6d2xJZkDj1aNaZK8luaGkyrpl6DJE+oWVP5SvKSR8eqVVb9AMXs1T0X1uPeAAAAAElFTkSuQmCC"; } break; } let img = document.createElement("img"); img.src = icon; img.onload = function () { ((onblob) => { let c1 = document.createElement('canvas'); let ctx1 = c1.getContext('2d'); ctx1.drawImage(img, 0, 0); let iconImageData = ctx1.getImageData(0, 0, 36, 36); let c2 = document.createElement('canvas'); c2.width = 38; c2.height = 38; let ctx2 = c2.getContext('2d'); ctx2.fillStyle = "#000000"; ctx2.fillRect(0, 0, c2.width, c2.height); for (let y = 0; y < 36; y++) { for (let x = 0; x < 36; x++) { let pix = iconImageData.data[4 * (y * 36 + x) + 3]; if (pix < 255) { iconImageData.data[4 * (y * 36 + x)] = 255; iconImageData.data[4 * (y * 36 + x) + 1] = 255; iconImageData.data[4 * (y * 36 + x) + 2] = 255; iconImageData.data[4 * (y * 36 + x) + 3] = 255; } } } ctx2.putImageData(iconImageData, 1, 1); c2.toBlob(onblob); })(b => { let url = URL.createObjectURL(b); let image = new Image(); image.onload = () => { OWOP.tool.allTools.paste.extra.k = image; OWOP.player.tool = "move"; OWOP.player.tool = "paste"; } image.src = url; }); } } } var windowClass = OWOP.windowSys.addWindow(new OWOP.windowSys.class.window(windowName, options, windowFunc) .move(OWOP.windowSys.windows['Tools'].realw + 15, 32)); windows[windowName] = windowClass; windowClass.frame.style.visibility = "hidden"; })() // assets !(function () { let windowName = "Assets"; let options = { closeable: false } var mkHTML = OWOP.util.mkHTML; let G = r => document.getElementById(r); function windowFunc(thisWindow) { thisWindow.frame.style.width = "500px"; let innerFrame = document.createElement("div"); let realAssetsCont = mkHTML("div", { id: "real-assets-cont" }); let p = mkHTML("p"); p.style["margin-block"] = "auto"; p.style["display"] = "flex"; p.style["justify-content"] = "space-evenly"; let button1 = mkHTML("button", { id: "NSoptions", innerHTML: "Add" }); let button2 = mkHTML("button", { id: "NSoptions", innerHTML: "Paste" }); let button3 = mkHTML("button", { id: "NSoptions", innerHTML: "Delete" }); let button4 = mkHTML("button", { id: "NSoptions", innerHTML: "Reload" }); button1.onclick = async () => { OWOP.sounds.play(OWOP.sounds.click); let pE = localStorage.MB_Assets; if (!pE) pE = []; else pE = JSON.parse(pE); var _imgTotal = 0; { var _lsTotal = 0, _xLen, _x; for (_x in localStorage) { if (!localStorage.hasOwnProperty(_x)) { continue; } _xLen = ((localStorage[_x].length + _x.length) * 2); _lsTotal += _xLen; }; //console.log("Total = " + (_lsTotal / 1024).toFixed(2) + " KB"); if ((_lsTotal / 1024) > 3000) return OWOP.chat.local(`Storage limit reached (3MB), remove images to add more.`); _imgTotal = _lsTotal; } { var _imageData = await X('image/*'); var _lsTotal = 0, _x; _x = JSON.stringify(_imageData); _lsTotal = _x.length * 2; //console.log("Total = " + (_lsTotal / 1024).toFixed(2) + " KB"); if ((_lsTotal / 1024) > 500) { if (((_lsTotal + _imgTotal) / 1024) > 3000) return OWOP.chat.local(`Image being added is more than Storage limit (3KB)`); if (!confirm(`Are you sure you want to add a image with ${(_lsTotal / 1024).toFixed(2)} KB`)) return; } } pE.push(_imageData); localStorage.MB_Assets = JSON.stringify(pE); J(); }; button2.onclick = () => { OWOP.sounds.play(OWOP.sounds.click); var img = new Image(); img.onload = () => { OWOP.tool.allTools.paste.extra.k = img; OWOP.player.tool = "move"; OWOP.player.tool = "paste"; } img.src = NS.selectedAsset; }; button3.onclick = () => { OWOP.sounds.play(OWOP.sounds.click); if (!NS.selectedAssetIndex) return; if (confirm("Do you want to delete the selected asset?")) NS.assets.splice(NS.selectedAssetIndex, 1); else return; localStorage.MB_Assets = JSON.stringify(NS.assets); J(); }; button4.onclick = () => { OWOP.sounds.play(OWOP.sounds.click); J(); }; let J = () => { NS.assets = localStorage.MB_Assets; if (!NS.assets) NS.assets = []; else NS.assets = JSON.parse(NS.assets); let y = G("real-assets-cont"); y.innerHTML = ''; for (let p0 in NS.assets) { let p1 = new Image(); p1.onload = () => { p1.style.width = '48px'; p1.style.height = '48px'; p1.style.border = 'solid 1px'; p1.onclick = () => { for (let p4 in G('real-assets-cont').children) { if (typeof G('real-assets-cont').children[p4] !== 'object') break; G('real-assets-cont').children[p4].style.border = 'solid 1px'; } if (NS.selectedImg) { NS.selectedImg.style.width = '48px'; NS.selectedImg.style.height = '48px'; } NS.selectedAsset = NS.assets[p0]; NS.selectedAssetIndex = p0; NS.selectedImg = p1; p1.style.width = '40px'; p1.style.height = '40px'; p1.style.border = 'solid 5px black'; }; p1.oncontextmenu = p3 => { p3.preventDefault(); NS.assets.splice(p0, 1); localStorage.MB_Assets = JSON.stringify(NS.assets); J(); }; y.append(p1); }; p1.src = NS.assets[p0]; } }; let X = (r = '*') => new Promise(Q => { let c = document.createElement('input'); c.type = 'file'; c.accept = r; c.onchange = () => { let N = new FileReader(); N.onloadend = () => { Q(N.result); }; N.readAsDataURL(c.files[0]); }; c.onclick = () => void 0; c.click(); }); button2.addEventListener("click", function () { OWOP.sounds.play(OWOP.sounds.click) }); p.appendChild(button1); p.appendChild(button2); p.appendChild(button3); p.appendChild(button4); innerFrame.appendChild(p); innerFrame.appendChild(realAssetsCont); thisWindow.addObj(innerFrame); } var windowClass = OWOP.windowSys.addWindow(new OWOP.windowSys.class.window(windowName, options, windowFunc) .move(window.innerWidth / 3, window.innerHeight / 3)); windows[windowName] = windowClass; windowClass.frame.style.visibility = "hidden"; })(); // patterns !(function () { return 1; let windowName = "Patterns"; let options = { closeable: false } function windowFunc(thisWindow) { let content = ` <span style="display: flex;"> <style> #div1, #div2, #div3 { float: left; width: 75px; height: 75px; margin: 10px; border: 1px solid black; } </style> <div style="display: flex;margin: 0px;border-radius: 5px;background-color: #7e635c;box-shadow: inset 3px 2px 0px 0px #4d313b;align-content: space-around;"> <span style="border: 10px #0000 solid;display: flex;flex-direction: column;"> <span style="display: flex;"> <div id="div1" ondrop="NS.drop(event)" ondragover="NS.allowDrop(event)"> <img src="https://opm.dimden.dev/client/img/gui.png" draggable="true" ondragstart="NS.drag(event)" id="drag1" width="75" height="75"> </div> <div style="display: flex;flex-direction: column;justify-content: center;"> <button class="tablinks1"> Filter Type:\nOR </button> <button class="tablinks1"> Flip </button> </div> </span> <span style="display: flex;"> <div id="div2" ondrop="NS.drop(event)" ondragover="NS.allowDrop(event)"> <img src="https://opm.dimden.dev/client/img/gui.png" draggable="true" ondragstart="NS.drag(event)" id="drag2" width="75" height="75"> </div> <div style="display: flex;flex-direction: column;justify-content: center;"> <button class="tablinks1"> Filter Type:\nOR </button> <button class="tablinks1"> Flip </button> </div> </span> <span style="display: flex;"> <div id="div3" ondrop="NS.drop(event)" ondragover="NS.allowDrop(event)"></div> <div style="display: flex;flex-direction: column;justify-content: center;"> <button class="tablinks1"> Filter Type:\nOR </button> <button class="tablinks1"> Flip </button> </div> </span> </span> </div> <div style="width: 5px;"></div> <div style="display: flex;margin: 0px;border-radius: 5px;background-color: #7e635c;box-shadow: inset 3px 2px 0px 0px #4d313b;align-content: space-around;"> <span style="border: 10px #0000 solid;"> <div>something 2 </div> </span> </div> </span> `; let container = thisWindow.container; container.style = "margin: 0px -5px -5px -5px;"; container.className = "optionsDiv"; container.innerHTML = content; function allowDrop(ev) { ev.preventDefault(); } function drag(ev) { ev.dataTransfer.setData("text", ev.target.id); } function drop(ev) { ev.preventDefault(); var data = ev.dataTransfer.getData("text"); ev.target.appendChild(document.getElementById(data)); } NS.allowDrop = allowDrop; NS.drag = drag; NS.drop = drop; return; const root = [...container.childNodes].find(e => e.nodeType !== Node.TEXT_NODE); let mkHTML = OWOP.util.mkHTML; let display = root.querySelector("#display"); for (let w in OWOP.windowSys.windows) { w = OWOP.windowSys.windows[w]; if (w.title === "Options" || w.title === "Resulting image") continue; if (w.title !== "Tools") { w.move(window.innerWidth / 3, window.innerHeight / 3); w.frame.style.visibility = "hidden"; let b = w.frame.querySelectorAll(".windowCloseButton"); if (b.length) w.frame.removeChild(b[0]); } let v = w.frame.style; let current = mkHTML("p"); current.className = "tabp"; current.appendChild(mkHTML("p", { innerHTML: w.title })); let button = mkHTML("button"); current.appendChild(button); let isVisible = v.visibility === "visible" || v.visibility === "" ? true : false; button.id = button.innerHTML = isVisible ? "on" : "off"; button.onclick = function () { isVisible = !isVisible; button.id = button.innerHTML = isVisible ? "on" : "off"; v.visibility = isVisible ? "visible" : "hidden"; } display.appendChild(current); } let options = root.querySelector("#options"); if (window) window.openCity = function (evt, cityName, s, button) { var i, tabcontent, tablinks; tabcontent = document.getElementsByClassName("tabcontent" + s); for (i = 0; i < tabcontent.length; i++) { tabcontent[i].style.display = "none"; } tablinks = document.getElementsByClassName(button.className); for (i = 0; i < tablinks.length; i++) { tablinks[i].id = ""; } button.id = "on"; document.getElementById(cityName).style.display = "block"; } NS.optionbutton = function (button) { let parent1 = button.parentElement; let parent2 = parent1.parentElement; let s = button.id === "on" ? false : true; button.innerHTML = button.id = s ? "on" : "off"; if (parent2.className === "tabcontentright") OWOP.tool.allTools[`${parent2.id}`].extra.state[`${parent1.id}`] = s; } } var windowClass = OWOP.windowSys.addWindow(new OWOP.windowSys.class.window(windowName, options, windowFunc) .move(window.innerWidth / 3, window.innerHeight / 3)); windows[windowName] = windowClass; windowClass.frame.style.visibility = "hidden"; })(); function makeOptionsWindow() { if (OWOP.windowSys.windows['Options']) OWOP.windowSys.delWindow(OWOP.windowSys.windows['Options']); let windowName = "Options"; let options = { closeable: false } function windowFunc(thisWindow) { let content = ` <span> <span id="optionsMinimize" style="display: flex;"> <style> p { margin-block: auto; color: white; font-family: Arial; } .tabcontentleft, .tabcontentright { display: none; margin-block: auto; text-align: center; } .tabp { display: flex; justify-content: space-between; margin: 1px 0px; } .tabButton, .optionButton { border-style: none !important; border-image: none !important; border: initial; border-radius: 6px; padding: 5px 8px; } .optionButton { padding: 5px 12px; } .tabButton { margin: 0px 1px; } button.on { background: #9a937b; } </style> <div style="display: flex;margin: 0px;border-radius: 5px;background-color: #7e635c;box-shadow: inset 3px 2px 0px 0px #4d313b;align-content: space-around;"> <span style="border: 10px #0000 solid;"> <div class="tab"> <div style="align-content: center;margin: 0px 0px 5px 0px;display: flex;justify-content: space-between;"> <button class="tabButton olt on" onclick="NS.switchTabs(event, 'display', 'olt', this)"> Window Display </button> <button class="tabButton olt" onclick="NS.switchTabs(event, 'options', 'olt', this)"> Options </button> </div> <div id="display" class="tabcontentolt" style="display: block;"></div> <div id="options" class="tabcontentolt" style="display: none;"></div> </div> </span> </div> <div style="width: 5px;"></div> <div style="display: flex;margin: 0px;border-radius: 5px;background-color: #7e635c;box-shadow: inset 3px 2px 0px 0px #4d313b;align-content: space-around;"> <span style="border: 10px #0000 solid;"> <div class="tab"> <span> <div style="align-content: center;margin: 0px 0px 5px 0px;display: flex;justify-content: space-between;"> <button class="tabButton ort on" onclick="NS.switchTabs(event, 'cursor', 'ort', this)"> Cursor </button> <button class="tabButton ort" onclick="NS.switchTabs(event, 'line', 'ort', this)"> Line </button> <button class="tabButton ort" onclick="NS.switchTabs(event, 'fill', 'ort', this)"> Bucket </button> <button class="tabButton ort" onclick="NS.switchTabs(event, 'export', 'ort', this)"> Select </button> </div> <div style="align-content: center;margin: 0px 0px 5px 0px;display: flex;justify-content: space-between;"> <button class="tabButton ort" onclick="NS.switchTabs(event, 'copy', 'ort', this)"> Copy </button> <button class="tabButton ort" onclick="NS.switchTabs(event, 'paste', 'ort', this)"> Paste </button> <button class="tabButton ort" onclick="NS.switchTabs(event, 'write', 'ort', this)"> Write </button> <button class="tabButton ort" onclick="NS.switchTabs(event, 'all', 'ort', this)"> All </button> </div> </span> <div id="cursor" class="tabcontentort" style="display: block;"> <div class="tabp"> <p>Scale</p> <input type="range" style="margin: 0px 15px;" value="1" min="1" max="16" oninput="OWOP.tool.allTools.cursor.extra.state.scalar = this.value;document.getElementById('cursorspan').innerHTML = this.value;"></input> <span style="padding: 4px 0px 5px 0px;" id="cursorspan">1</span> </div> <div class="tabp"> <p>Chunkize</p> <button class="optionButton switch" onclick="NS.optionbutton(this, 'chunkize')">off</button> </div> <div class="tabp"> <p>Rainbow</p> <button class="optionButton switch" onclick="NS.optionbutton(this, 'rainbow')">off</button> </div> <div class="tabp"> <p>Pixel Perfect</p> <button class="optionButton switch" onclick="NS.optionbutton(this, 'perfect')">off</button> </div> </div> <div id="line" class="tabcontentort" style="display: none;"> <div class="tabp"> <p>Rainbow</p> <button class="optionButton switch" onclick="NS.optionbutton(this, 'rainbow')">off</button> </div> <div class="tabp"> <p>Gradient</p> <button class="optionButton switch" onclick="NS.optionbutton(this, 'gradient')">off</button> </div> </div> <div id="fill" class="tabcontentort" style="display: none;"> <div class="tabp"> <p>Rainbow</p> <button class="optionButton switch" onclick="NS.optionbutton(this, 'rainbow')">off</button> </div> <div class="tabp"> <p>Checkered</p> <button class="optionButton switch" onclick="NS.optionbutton(this, 'checkered')">off</button> </div> <div class="tabp"> <p>Pattern 1</p> <button class="optionButton switch" onclick="NS.optionbutton(this, 'dither')">off</button> </div> <div class="tabp"> <p>Pattern 2</p> <button class="optionButton switch" onclick="NS.optionbutton(this, 'dither2')">off</button> </div> <div class="tabp"> <p>Pattern 3</p> <button class="optionButton switch" onclick="NS.optionbutton(this, 'dither3')">off</button> </div> <div class="tabp"> <p>Pattern 4</p> <button class="optionButton switch" onclick="NS.optionbutton(this, 'dither4')">off</button> </div> <div class="tabp"> <p>Pattern 5</p> <button class="optionButton switch" onclick="NS.optionbutton(this, 'dither5')">off</button> </div> <div class="tabp"> <p>Pattern 6</p> <button class="optionButton switch" onclick="NS.optionbutton(this, 'dither6')">off</button> </div> <div class="tabp"> <p>Pattern 7</p> <button class="optionButton switch" onclick="NS.optionbutton(this, 'dither7')">off</button> </div> <div class="tabp"> <p>Pattern 8</p> <button class="optionButton switch" onclick="NS.optionbutton(this, 'dither8')">off</button> </div> </div> <div id="export" class="tabcontentort" style="display: none;"> <div class="tabp"> <p>Type</p> <select style="padding: 3px 0px;background: #aba389;" class="exportselect" oninput="OWOP.tool.allTools.export.extra.state.type=this.value"> <option value="export">Export</option> <option value="color">Palette Color Adder</option> <option value="adder">Queue Adder</option> <option value="filler">Queue Filler</option> <option value="clearer">Queue Clearer</option> </select> </div> <div class="tabp"> <p>Chunkize</p> <button class="optionButton switch" onclick="NS.optionbutton(this, 'chunkize')">off</button> </div> <div class="tabp"> <p>Rainbow</p> <button class="optionButton switch" onclick="NS.optionbutton(this, 'rainbow')">off</button> </div> </div> <div id="copy" class="tabcontentort" style="display: none;"> <!-- <div class="tabp"> <p>Shrink Margins</p> <button class="optionButton switch" onclick="NS.optionbutton(this, 'margin')">off</button> </div> --> </div> <div id="paste" class="tabcontentort" style="display: none;"> <div class="tabp"> <p>Chunkize</p> <button class="optionButton switch" onclick="NS.optionbutton(this, 'chunkize')">off</button> </div> <div class="tabp"> <p>Rotate Clockwise</p> <button class="optionButton click" onclick="NS.optionbutton(this, 'rc')"> </button> </div> <div class="tabp"> <p>Rotate the other way</p> <button class="optionButton click" onclick="NS.optionbutton(this, 'rcc')"> </button> </div> <div class="tabp"> <p>Flip Horizontally</p> <button class="optionButton click" onclick="NS.optionbutton(this, 'fh')"> </button> </div> <div class="tabp"> <p>Flip Vertically</p> <button class="optionButton click" onclick="NS.optionbutton(this, 'fv')"> </button> </div> </div> <div id="write" class="tabcontentort" style="display: none;"> <div class="tabp"> <p>Rainbow</p> <button class="optionButton switch" onclick="NS.optionbutton(this, 'rainbow')">off</button> </div> <!-- <div class="tabp"> <p>Font Size</p> <button class="optionButton switch" onclick="NS.optionbutton(this, 'gradient')">off</button> </div> <div class="tabp"> <p>Font Type</p> <button class="optionButton switch" onclick="NS.optionbutton(this, 'gradient')">off</button> </div> --> </div> <!-- <div id="all" class="tabcontentort" style="display: none;"> <div class="tabp"> <p>Rainbow</p> <button class="optionButton switch" onclick="NS.optionbutton(this, 'rainbow')">off</button> </div> <div class="tabp"> <p>Some color stuff</p> <button class="optionButton switch" onclick="NS.optionbutton(this, 'gradient')">off</button> </div> </div> --> </div> </span> </div> </span> <span id="optionsMaximize" style="display: none;"> <div style="display: flex;margin: 0px;border-radius: 5px;background-color: #7e635c;box-shadow: inset 3px 2px 0px 0px #4d313b;align-content: space-around;"> <span style="border: 10px #0000 solid;"> <button class="optionButton" onclick="NS.minimizeOptions(false)">Maximize</button> </span> </div> </span> </span> `; let container = thisWindow.container; container.style = "margin: 0px -5px -5px -5px;"; container.className = "optionsDiv"; container.innerHTML = content; const root = [...container.childNodes].find(e => e.nodeType !== Node.TEXT_NODE); let mkHTML = OWOP.util.mkHTML; let display = root.querySelector("#display"); for (let w in OWOP.windowSys.windows) { w = OWOP.windowSys.windows[w]; if (w.title === "Options" || w.title === "Resulting image") continue; if (w.title !== "Tools") { w.move(window.innerWidth / 3, window.innerHeight / 3); w.frame.style.visibility = "hidden"; let b = w.frame.querySelectorAll(".windowCloseButton"); if (b.length) w.frame.removeChild(b[0]); } let v = w.frame.style; let current = mkHTML("p"); current.className = "tabp"; current.appendChild(mkHTML("p", { innerHTML: w.title })); let button = mkHTML("button"); button.classList.add("optionButton"); current.appendChild(button); v.visibility === "visible" || v.visibility === "" ? button.classList.toggle("on") : void 0; button.innerHTML = button.classList.contains("on") ? "on" : "off"; button.onclick = function () { button.classList.toggle("on"); let s = button.classList.contains("on"); button.innerHTML = s ? "on" : "off"; v.visibility = s ? "visible" : "hidden"; } display.appendChild(current); } let options = root.querySelector("#options"); function optionmaker(name, inputType, checked, onclick) { let current = mkHTML("div"); current.className = "tabp"; current.appendChild(mkHTML("p", { innerHTML: name })); let button = mkHTML("button"); button.classList.add("optionButton"); current.appendChild(button); if (inputType === "button") button.innerHTML = checked ? "on" : "off"; else if (inputType === "select") button.innerHTML = " "; button.onclick = function () { if (inputType === "button") { button.classList.toggle("on"); button.innerHTML = button.classList.contains("on") ? "on" : "off"; } onclick(); } if (checked) button.classList.toggle("on"); return current; } options.appendChild(optionmaker("Disable PM", "button", !NS.PM.enabled, () => NS.PM.enabled = !NS.PM.enabled)); options.appendChild(optionmaker("Clear PM", "select", void 0, () => NS.PM.clearQueue())); options.appendChild(optionmaker("Render PM", "button", NS.PM.renderBorder, () => NS.PM.renderBorder = !NS.PM.renderBorder)); options.appendChild(optionmaker("Render Rings", "button", NS.PM.renderPlayerRings, () => NS.PM.renderPlayerRings = !NS.PM.renderPlayerRings)); options.appendChild(optionmaker("AutoFix", "button", NS.PM.autoMove, () => NS.PM.autoMove = !NS.PM.autoMove)); options.appendChild(optionmaker("Mute", "button", !OWOP.options.enableSounds, () => { OWOP.options.enableSounds = !OWOP.options.enableSounds; localStorage.setItem("options", JSON.stringify({ enableSounds: OWOP.options.enableSounds })) })); options.appendChild(optionmaker("Undo", "select", void 0, () => PM.undo())); options.appendChild(optionmaker("Redo", "select", void 0, () => PM.redo())); options.appendChild(optionmaker("Minimize Options", "select", void 0, () => NS.minimizeOptions(true))); NS.switchTabs = function (evt, cityName, s, button) { var i, tabcontent, tablinks; tabcontent = document.getElementsByClassName("tabcontent" + s); for (i = 0; i < tabcontent.length; i++) { tabcontent[i].style.display = "none"; } tablinks = document.getElementsByClassName(s); for (i = 0; i < tablinks.length; i++) { tablinks[i].classList.remove("on"); } button.classList.add("on"); document.getElementById(cityName).style.display = "block"; } NS.optionbutton = function (button, state) { let type = "unknown"; let s = true; if (button.classList.contains("switch")) type = "switch"; if (button.classList.contains("click")) type = "click"; if (type === "unknown") return; let parent1 = button.parentElement; let parent2 = parent1.parentElement; if (type === "switch") { button.classList.toggle("on"); s = button.classList.contains("on"); button.innerHTML = s ? "on" : "off"; } let extraState = OWOP.tool.allTools[parent2.id].extra.state; if (typeof extraState[state] === "function") { if (parent2.className === "tabcontentort" && parent2.id !== "all") extraState[state](s); } else { if (parent2.className === "tabcontentort" && parent2.id !== "all") extraState[state] = s; } } NS.minimizeOptions = function (minimize) { let max = document.getElementById("optionsMaximize"); let min = document.getElementById("optionsMinimize"); if (minimize) { max.style = "display: flex;"; min.style = "display: none;"; } else { max.style = "display: none;"; min.style = "display: flex;"; } } } var windowClass = OWOP.windowSys.addWindow(new OWOP.windowSys.class.window(windowName, options, windowFunc) .move(OWOP.windowSys.windows['Tools'].realw + 15, 32)); windows[windowName] = windowClass; windowClass.frame.style.visibility = "visible"; } { // please make a better checking statement function x() { if (OWOP.OPM && OWOP?.windowSys?.windows?.['Coordinates Saver']) makeOptionsWindow(); else if (OWOP.OPM) setTimeout(x, 1000); } // x(); } console.log("windows completed"); function hue(d, b = 1) { let a = 256 / b; // 1 2 4 8 16 32 64 128 256 //let b = mul; // 256 128 64 32 16 8 4 2 1 d = Math.floor(d); // d = d % (b * 6); m_{F}\left(a,b\right)=a-b\operatorname{floor}\left(\frac{a}{b}\right) d = (Math.abs(Math.floor(d / (b * 6)) * ((b * 6))) + (d % (b * 6))) % (b * 6); // d = d - (b * 6) * ~~(d/(b * 6)); let nD = Math.floor(Math.abs(d / b)); let output; if (nD < 1) { output = [255, 0, (d % b) * a]; } else if (nD < 2) { output = [255 - ((d % b) * a), 0, 255]; } else if (nD < 3) { output = [0, (d % b) * a, 255]; } else if (nD < 4) { output = [0, 255, 255 - ((d % b) * a)]; } else if (nD < 5) { output = [(d % b) * a, 255, 0]; } else if (nD < 6) { output = [255, 255 - ((d % b) * a), 0]; } // console.log(d); // console.log(nD); // console.log(output); return output; } var rangeMap = (a, b) => s => { const [a1, a2] = a; const [b1, b2] = b; // Scaling up an order, and then down, to bypass a potential, // precision issue with negative numbers. return (((((b2 - b1) * (s - a1)) / (a2 - a1)) * 10) + (10 * b1)) / 10; }; var clamp = v => Math.round(Math.max(Math.min(v, 255), 0)); var degToRad = d => d * (Math.PI / 180); var radToDeg = r => r / (Math.PI / 180); class RGBRotate { constructor(degrees) { this.matrix = [[1, 0, 0], [0, 1, 0], [0, 0, 1]]; this.set_hue_rotation(degrees); } set_hue_rotation(degrees) { let cosA = Math.cos(degToRad(degrees)); let sinA = Math.sin(degToRad(degrees)); this.matrix[0][0] = cosA + (1 - cosA) / 3; this.matrix[0][1] = 1 / 3 * (1 - cosA) - Math.sqrt(1 / 3) * sinA; this.matrix[0][2] = 1 / 3 * (1 - cosA) + Math.sqrt(1 / 3) * sinA; this.matrix[1][0] = 1 / 3 * (1 - cosA) + Math.sqrt(1 / 3) * sinA; this.matrix[1][1] = cosA + 1 / 3 * (1 - cosA); this.matrix[1][2] = 1 / 3 * (1 - cosA) - Math.sqrt(1 / 3) * sinA; this.matrix[2][0] = 1 / 3 * (1 - cosA) - Math.sqrt(1 / 3) * sinA; this.matrix[2][1] = 1 / 3 * (1 - cosA) + Math.sqrt(1 / 3) * sinA; this.matrix[2][2] = cosA + 1 / 3 * (1 - cosA); } apply(r, g, b) { let rx = r * this.matrix[0][0] + g * this.matrix[0][1] + b * this.matrix[0][2]; let gx = r * this.matrix[1][0] + g * this.matrix[1][1] + b * this.matrix[1][2]; let bx = r * this.matrix[2][0] + g * this.matrix[2][1] + b * this.matrix[2][2]; return [clamp(rx), clamp(gx), clamp(bx)]; } } function rgb(r, g, b) { return "#" + [r, g, b].map(v => { return ('0' + Math.min(Math.max(parseInt(v), 0), 255) .toString(16) ).slice(-2); }).join(''); } const Base64 = { // sourced from https://stackoverflow.com/questions/6213227/fastest-way-to-convert-a-number-to-radix-64-in-javascript // coded by https://stackoverflow.com/users/520997/reb-cabin _Rixits: // 0 8 16 24 32 40 48 56 63 // v v v v v v v v v "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/", // You have the freedom, here, to choose the glyphs you want for // representing your base-64 numbers. The ASCII encoding guys usually // choose a set of glyphs beginning with ABCD..., but, looking at // your update #2, I deduce that you want glyphs beginning with // 0123..., which is a fine choice and aligns the first ten numbers // in base 64 with the first ten numbers in decimal. // This cannot handle negative numbers and only works on the // integer part, discarding the fractional part. // Doing better means deciding on whether you're just representing // the subset of javascript numbers of twos-complement 32-bit integers // or going with base-64 representations for the bit pattern of the // underlying IEEE floating-point number, or representing the mantissae // and exponents separately, or some other possibility. For now, bail fromBigInt: function (bigint) { if (typeof bigint !== "bigint") throw "The input is not valid"; var rixit; // like 'digit', only in some non-decimal radix var residual = bigint; var result = ''; while (true) { rixit = residual % 64n; result = this._Rixits.charAt(Number(rixit)) + result; residual = residual / 64n; if (residual == 0n) break; } return result; }, fromNumber: function (number) { if (isNaN(Number(number)) || number === null || number === Number.POSITIVE_INFINITY) throw "The input is not valid"; if (number < 0) throw "Can't represent negative numbers now"; var rixit; // like 'digit', only in some non-decimal radix var residual = Math.floor(number); var result = ''; while (true) { rixit = residual % 64; result = this._Rixits.charAt(rixit) + result; residual = Math.floor(residual / 64); if (residual == 0) break; } return result; }, toNumber: function (rixits) { let result = 0; rixits = rixits.split(''); for (let e of rixits) { result = (result * 64) + this._Rixits.indexOf(e); } return result; }, toBigInt: function (rixits) { let result = 0n; rixits = rixits.split(''); for (let e of rixits) { result = (result * 64n) + BigInt(this._Rixits.indexOf(e)); } return result; } } const Base256 = { // sourced from https://stackoverflow.com/questions/6213227/fastest-way-to-convert-a-number-to-radix-64-in-javascript // coded by https://stackoverflow.com/users/520997/reb-cabin // modified by NekoNoka _Rixits: // 0 8 16 24 32 40 48 56 63 // v v v v v v v v v "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖÙÚÛÜÝÞßàáâãäåçèéêëìíîïðñòóôõöùúûüýþÿĀāĂ㥹ĆćĈĉĊċČčĎďĐđĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħĨĩĪīĬĭĮįİIJijĴĵĶķĸĹĺĻļĽľĿŀŁłŃńŅņŇňʼnŊŋŌōŎŏŐőŔŕŖŗŘřŚśŜŝŞşŠšŢţŤťŦŧŨũŪūŬŭŮůŰűŲųŴŵŶŷŸŹźŻżŽžǞǟǠǡǦǧǨǩǪǫǬǭ", // You have the freedom, here, to choose the glyphs you want for // representing your base-64 numbers. The ASCII encoding guys usually // choose a set of glyphs beginning with ABCD..., but, looking at // your update #2, I deduce that you want glyphs beginning with // 0123..., which is a fine choice and aligns the first ten numbers // in base 64 with the first ten numbers in decimal. // This cannot handle negative numbers and only works on the // integer part, discarding the fractional part. // Doing better means deciding on whether you're just representing // the subset of javascript numbers of twos-complement 32-bit integers // or going with base-64 representations for the bit pattern of the // underlying IEEE floating-point number, or representing the mantissae // and exponents separately, or some other possibility. For now, bail fromBigInt: function (bigint) { if (typeof bigint !== "bigint") throw "The input is not valid"; if (bigint < 0) throw "Can't represent negative numbers now"; var rixit; // like 'digit', only in some non-decimal radix var residual = bigint; var result = ''; var l = BigInt(this._Rixits.length); while (true) { rixit = residual % l; result = this._Rixits.charAt(Number(rixit)) + result; residual = residual / l; if (residual == 0n) break; } return result; }, fromNumber: function (number) { if (isNaN(Number(number)) || number === null || number === Number.POSITIVE_INFINITY) throw "The input is not valid"; if (number < 0) throw "Can't represent negative numbers now"; var rixit; // like 'digit', only in some non-decimal radix var residual = Math.floor(number); var result = ''; while (true) { rixit = residual % 256; // console.log("rixit : " + rixit); // console.log("result before : " + result); result = this._Rixits.charAt(rixit) + result; // console.log("result after : " + result); // console.log("residual before : " + residual); residual = Math.floor(residual / 256); // console.log("residual after : " + residual); if (residual == 0) break; } return result; }, toNumber: function (rixits) { var result = 0; // console.log("rixits : " + rixits); // console.log("rixits.split('') : " + rixits.split('')); rixits = rixits.split(''); for (var e = 0; e < rixits.length; e++) { // console.log("_Rixits.indexOf(" + rixits[e] + ") : " + // this._Rixits.indexOf(rixits[e])); // console.log("result before : " + result); result = (result * 256) + this._Rixits.indexOf(rixits[e]); // console.log("result after : " + result); } return result; }, toBigInt: function (rixits) { var result = 0n; rixits = rixits.split(''); for (var e = 0; e < rixits.length; e++) { result = (result * 256n) + BigInt(this._Rixits.indexOf(rixits[e])); } return result; } } NS.getImageData = function (image) { let c = document.createElement('canvas'); let ctx = c.getContext('2d'); if (image instanceof HTMLCanvasElement) { c = image; } else if (image instanceof Image) { c.width = image.width; c.height = image.height; ctx.drawImage(image, 0, 0); } else return false; let w = c.width let h = c.height; let d = ctx.getImageData(0, 0, w, h); let data = []; for (let j = 0; j < h; j++) { data.push([]); for (let i = 0; i < w; i++) { let c = []; c.push(d.data[4 * (j * w + i)]); c.push(d.data[4 * (j * w + i) + 1]); c.push(d.data[4 * (j * w + i) + 2]); c.push(d.data[4 * (j * w + i) + 3]); data[j].push(c); } } return data; } NS.setImageData = function (data) { let c = document.createElement('canvas'); let w = data[0].length; let h = data.length; c.width = w; c.height = h; let ctx = c.getContext('2d'); let d = ctx.createImageData(w, h); for (let j = 0; j < h; j++) { for (let i = 0; i < w; i++) { let r = data[j][i][0]; let g = data[j][i][1]; let b = data[j][i][2]; let a = r === 255 && g === 255 && b === 255 ? 0 : 255; d.data[4 * (j * w + i)] = r; d.data[4 * (j * w + i) + 1] = g; d.data[4 * (j * w + i) + 2] = b; d.data[4 * (j * w + i) + 3] = a; } } ctx.putImageData(d, 0, 0); return c; } NS.rangeMap = rangeMap; NS.hue = hue; NS.rgb = rgb; NS.Base64 = Base64; NS.Base256 = Base256; NS.clamp = clamp; NS.degToRad = degToRad; NS.radToDeg = radToDeg; NS.RGBRotate = RGBRotate; NS.chunkize = false; console.log("Neko's Scripts Loaded."); console.timeEnd("Neko"); } function init() { let x = document.getElementById("load-scr"); if (x?.style?.transform) { console.time("Neko"); console.log("Loading Neko's Scripts."); if (document.getElementById("dev-chat")) document.getElementById("dev-chat").parentNode.removeChild(document.getElementById("dev-chat")); // im so pissed at devchat for screaming at me every time i press a single letter while typing out something in the console its so annoying. thats why its the first thing i delete when initializing. NS.OPM = !!OWOP.misc; if (!NS.OPM) { NS.modules.forEach(e => { 0, 13, 14, 15, 16, 20, 22, 21, 23, 24, 25; // module numbers if (e.misc) NS.M0 = e; if (e.EVENTS) NS.M13 = e; if (e.eventSys) NS.M14 = e; if (e.camera) NS.M20 = e; if (e.updateClientFx) NS.M21 = e; }); if (!NS.M0 || !NS.M13 || !NS.M14 || !NS.M20 || !NS.M21) { // im gonna make a localstorage check to make sure the reload doesnt happen indefinitely, and if the check happens at least 3 times then it will resume code execution without anymore reloads and provide a warning that the script wasnt loaded correctly, for now there wont be anything (this is a pre-release version currently). // localStorage.NS; // if (temp1) let l = JSON.parse(localStorage.NS); if (!l.reloadCheck) l.reloadCheck = 1; if (l.reloadCheck === 3) { delete l.reloadCheck; localStorage.NS = JSON.stringify(l); OWOP.chat.local("Neko's Script was not loaded correctly, please reload the tab."); } else { l.reloadCheck++; localStorage.NS = JSON.stringify(l); location.reload(); } return; } else { let l = JSON.parse(localStorage.NS); if (l.reloadCheck) delete l.reloadCheck; localStorage.NS = JSON.stringify(l); } NS.keysdown = []; NS.extra = {}; NS.extra.log = false; function keydown(event) { var e = event.which || event.keyCode; if ("TEXTAREA" !== document.activeElement.tagName && "INPUT" !== document.activeElement.tagName) { NS.keysdown[e] = !0; var n = OWOP.player.tool; if (undefined !== OWOP?.world && n?.isEventDefined("keydown") && n?.call("keydown", [NS.keysdown, event])) return !1; switch (e) { case 80: OWOP.player.tool = "pipette"; break; case 77: case 81: OWOP.player.tool = "move"; break; case 79: OWOP.player.tool = "cursor"; break; case 70: break; case 69: //OWOP.player.tool = "neko eraser"; break; case 66: //OWOP.player.tool = "fill"; break; case 72: // make options window open/close // options window will include options to switch the behavior of the tools, the game, and open/close all windows break; case 71: OWOP.renderer.showGrid(!OWOP.renderer.gridShown); break; case 90: if (!event.ctrlKey) break; NS.PM.undo(event.shiftKey); event.preventDefault(); break; case 89: if (!event.ctrlKey) break; NS.PM.redo(event.shiftKey); event.preventDefault(); break; case 112: // f1 event.preventDefault(); break; case 107: case 187: ++OWOP.camera.zoom; break; case 109: case 189: --OWOP.camera.zoom; break; case 76: NS.extra.log = !NS.extra.log; break; } (NS.extra.log && console.log(event)); } } function keyup(event) { var e = event.which || event.keyCode; if (delete NS.keysdown[e], "INPUT" !== document.activeElement.tagName) { var n = OWOP.player.tool; if (undefined !== OWOP?.world && n?.isEventDefined("keyup") && n?.call("keyup", [NS.keysdown, event])) return !1; switch (event.key) { case "Enter": case "`": document.getElementById("chat-input").focus(); break; } } } let t = EventTarget._eventlists; let down = [/Custom color\\nType three values separated by a comma: r,g,b\\n\(\.\.\.or the hex string: #RRGGBB\)\\nYou can add multiple colors at a time separating them with a space\./]; let up = [/function\(.\)\{var .=.\.which\|\|.\.keyCode;if\(delete .\[.\],"INPUT"!==document\.activeElement\.tagName\){var .=.\.player\.tool;if\(null!==.&&null!==.\.world&&.\.isEventDefined\("keyup"\)&&.\.call\("keyup",\[.,.\]\)\)return!1;13==.\?.\.chatInput\.focus\(\):16==.&&\(.\.player\.tool="cursor"\)}}/]; NS.etdown = false; NS.etup = false; NS.et = false; if (NS.OPM) { up.push('function(t) {\n var e = t.which || t.keyCode;\n if (delete b[e], "INPUT" !== document.activeElement.tagName) {\n var n = f.player.tool;\n if (null !== n && null !== E.world && n.isEventDefined("keyup") && n.call("keyup", [b, t])) return !1;\n 13 == e ? k.chatInput.focus() : 16 == e && (f.player.tool = "cursor")\n }\n }'); up.push('function(t){var e=t.which||t.keyCode;if(delete b[e],"INPUT"!==document.activeElement.tagName){var n=f.player.tool;if(null!==n&&null!==E.world&&n.isEventDefined("keyup")&&n.call("keyup",[b,t]))return!1;13==e?k.chatInput.focus():16==e&&(f.player.tool="cursor")}}'); } else { up.push('function(e){var t=e.which||e.keyCode;if(delete w[t],"INPUT"!==document.activeElement.tagName){var n=d.player.tool;if(null!==n&&null!==x.world&&n.isEventDefined("keyup")&&n.call("keyup",[w,e]))return!1;13==t?k.chatInput.focus():16==t&&(d.player.tool="cursor")}}'); } for (let e of t) { if (NS.etdown !== true) for (let d of down) { if ((d instanceof RegExp && d.test(String(e))) || String(e) === d) { NS.etdown = true; NS.tempdown = e; console.log("found down"); } if (NS.etdown === true) break; } if (NS.etup !== true) for (let u of up) { if (String(e) === u) { NS.etup = true NS.tempup = e; console.log("found up"); } if (NS.etup === true) break; } if (NS.etdown === true && NS.etup === true) break; } if (NS.etdown !== true) console.warn("down was not found"); if (NS.etup !== true) console.warn("up was not found"); if (NS.etdown === true && NS.etup === true) { NS.et = true; window.removeEventListener("keydown", NS.tempdown); window.removeEventListener("keyup", NS.tempup); window.addEventListener("keydown", keydown); window.addEventListener("keyup", keyup); } delete EventTarget._eventlists; new MutationObserver(function (mutationList, observer) { for (const mutation of mutationList) { if (mutation.type === 'attributes') { if (mutation.attributeName === "style") { if (mutation.target.style.transform) { console.log(observer, mutation); setTimeout(() => NS.M0.showPlayerList(true), 5e3); } } } } }).observe(document.getElementById("load-scr"), { attributes: true }); NS.M0.showPlayerList(true); install(); } else { let modal = document.createElement("div"); modal.id = "notiModal"; modal.className = "modal"; let s = document.createElement("style"); s.innerHTML = ` .modal { position: fixed; z-index: 1; padding-top: 100px; left: 0; top: 0; width: 100%; height: 100%; overflow: auto; background-color: rgb(0, 0, 0); background-color: rgba(0, 0, 0, 0.4); } .modal-content { background-color: #aba389; margin: auto; padding: 20px; width: 80%; border-radius: 6px; border: 3px solid #7e635c; } `; modal.appendChild(s); let mc = document.createElement("div"); mc.className = "modal-content"; mc.innerHTML = ` <p style="font-size: 20px;color: #7e635c;text-shadow: 1px 1px #4d313b;"> This is a notification telling you that Neko's Scripts can no longer run with OPM 2 enabled <br> it's unfortunate but as my script keeps updating more features that is present in OPM 2 will appear in my script. <br> If you want to keep using this script you must disable OPM 2 from tampermonkey. <br> <a href="https://github.com/NekoNoka/Neko-OWOP-Scripts">Neko's Scripts</a> </p> `; modal.appendChild(mc); document.body.appendChild(modal); window.onclick = function (event) { let notiModal = document.getElementById('notiModal'); if (event.target == notiModal) notiModal.style.display = "none"; } } } else { setTimeout(init, 100); } } init();