이 스크립트는 직접 설치해서 쓰는 게 아닙니다. 다른 스크립트가 메타 명령 // @require https://update.greasyfork.org/scripts/443807/1050374/PPT.js
(으)로 포함하여 쓰는 라이브러리입니다.
// ==UserScript==
// @name PPT
// @description Pixel Place Tools
// @version 1.6.2
// @author 0vC4
// @namespace https://greasyfork.org/users/670183
// @match https://pixelplace.io/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=pixelplace.io
// @license MIT
// @grant none
// @run-at document-start
// ==/UserScript==
(() => {
const PPClient = window.PPClient || {modules:{}};
window.PPClient = PPClient;
if ('Tools' in PPClient.modules) return;
const progressManager = func => {
const callbacks = {};
const root = new Proxy({}, {
get(target, key) {
if (!target[key]) target[key] = callback => (callbacks[key] = callback, root);
return target[key];
}
});
root.start = (...args) => func(callbacks)(...args);
return root;
};
const worker = progressManager(({progress=()=>0, finish=()=>0}) =>
(data, func) => {
const worker = new Worker(URL.createObjectURL(new Blob([`
const progress = value => self.postMessage({progress:true,value});
const finish = value => self.postMessage({finish:true,value});
onmessage = async ({data}) => {
await (${func.toString()})(data);
close();
};
`], { type: "text/javascript" })));
worker.addEventListener('message', ({data}) => data.progress && progress(data.value));
worker.addEventListener('message', ({data}) => data.finish && finish(data.value));
worker.postMessage(data);
});
const module = {
args: {},
_wheelID: 0,
get wheel() {
const {exclude, colors} = module.args;
let pixel = module._wheelID+1;
while (exclude.includes(colors[pixel]))
if (colors[++pixel] == null)
pixel = 0;
module._wheelID = pixel;
return pixel;
},
pixel: 0,
size: 9,
innerSize: 0,
interval: 0,
RGB2P(r, g, b) {
const closest = module.args.rgb.map(([r2, g2, b2]) =>
((r2-r)**2 + (g2-g)**2 + (b2-b)**2)*0x1000000 + (r2<<16)+ (g2<<8) + b
)
.sort((a,b) => a-b)[0];
return module.args.colors.indexOf(closest&0xFFFFFF);
},
CLR2P(color) {
return module.RGB2P((color>>16)&0xFF, (color>>8)&0xFF, color&0xFF);
},
};
module.config = ({colors,exclude,zero, timer,tickSpeed}) => {
const palette = [...colors].map(color => exclude.includes(color) ? zero : color);
const rgb = palette.filter(clr => clr != zero).map(clr => [((clr>>16)&0xFF), ((clr>>8)&0xFF), (clr&0xFF)]);
Object.assign(module.args, {colors,exclude,zero, timer,tickSpeed, palette,rgb});
};
module.shader = progressManager(({
progress=()=>0, finish=()=>0, tick=()=>0,
silent=true,
interval=module.interval
}) => (map) => {
const {timer} = module.args;
let pos = 0;
let t = timer.setInterval(() => {
const {tickSpeed} = module.args;
let i = 0;
for (; pos < map.pixels.length; ) {
silent || progress(pos/map.pixels.length, t);
if (map.pixels[pos] === 255) {
pos++;
continue;
}
tick(pos%map.width, pos/map.width>>0, map.pixels[pos]);
pos++;
i++;
if (i > tickSpeed) return;
continue;
}
timer.clearInterval(t);
finish(t);
}, interval);
return t;
});
module.square = progressManager(({
progress=()=>0, finish=()=>0, tick=()=>0,
silent=true,
interval=module.interval,
size=module.size,
innerSize=module.innerSize,
}) => (x,y,pixel=module.pixel) => {
const {timer} = module.args;
const half = size>>1;
const innerHalf = innerSize>>1;
let xi = -half;
let yi = -half;
let t = timer.setInterval(() => {
const {tickSpeed} = module.args;
let i = 0;
for (; yi < half+1;) {
for (; xi < half+1;) {
const pos = (xi+half+(yi+half)*size);
silent || progress(pos/size**2, t);
if (pixel === 255 || xi > -innerHalf && xi < innerHalf && yi > -innerHalf && yi < innerHalf) {
xi++;
continue;
}
tick(x+xi, y+yi, pixel);
xi++;
i++;
if (i > tickSpeed) return;
continue;
}
yi++;
xi = -half;
}
timer.clearInterval(t);
finish(t);
}, interval);
return t;
});
module.circle = progressManager(({
progress=()=>0, finish=()=>0, tick=()=>0,
silent=true,
interval=module.interval,
radius=module.size>>1,
innerRadius=module.innerSize>>1,
}) => (x,y,pixel=module.pixel) => {
const {timer} = module.args;
const half = radius;
const innerHalf = innerRadius;
let xi = -half;
let yi = -half;
let t = timer.setInterval(() => {
const {tickSpeed} = module.args;
let i = 0;
for (; yi < half+1;) {
for (; xi < half+1;) {
const pos = (xi+half+(yi+half)*size);
silent || progress(pos/size**2, t);
if (pixel === 255 || xi**2 + yi**2 > half**2 || xi**2 + yi**2 < innerHalf**2) {
xi++;
continue;
}
tick(x+xi, y+yi, pixel);
xi++;
i++;
if (i > tickSpeed) return;
continue;
}
yi++;
xi = -half;
}
timer.clearInterval(t);
finish(t);
}, interval);
return t;
});
module.image = progressManager(({
progress=()=>0, finish=()=>0, tick=()=>0,
interval=module.interval,
}) => (pixels, x,y,w,h) => {
const {timer} = module.args;
let xi = 0;
let yi = 0;
let t = timer.setInterval(() => {
const {tickSpeed} = module.args;
let i = 0;
for (; yi < h;) {
for (; xi < w;) {
const pos = xi+yi*w;
progress(pos/pixels.length, t);
const pixel = pixels[pos];
if (pixel === 255) {
xi++;
continue;
}
tick(x+xi, y+yi, pixel);
xi++;
i++;
if (i > tickSpeed) return;
continue;
}
yi++;
xi = 0;
}
timer.clearInterval(t);
finish(t);
}, interval);
return t;
});
module.order = new Proxy({}, {
get(_, type) {
return progressManager(({
progress=()=>0, finish=()=>0,
silent=true,
center=[0,0]
}) => (queue) => {
if (type == 'fromCenterQueue' || type == 'toCenterQueue') {
type = type.replace('Queue', '');
const [cxn, cyn] = queue.reduce(([x,y], [x2,y2]) => [x+x2,y+y2], [0, 0]);
center = [cxn/queue.length>>0, cyn/queue.length>>0];
}
worker.progress(progress).finish(finish)
.start(
{queue, type, center, silent},
async ({queue, type, center, silent}) => {
const q = [...queue];
const size = queue.length*Math.log(queue.length)|0;
const [cx, cy] = center;
let i = 0;
const method = ({
start([x,y,p,i], [x2,y2,p2,i2]) {
silent || progress(i++/size);
return i-i2;
},
end([x,y,p,i], [x2,y2,p2,i2]) {
silent || progress(i++/size);
return i2-i;
},
rand() {
silent || progress(i++/size);
return Math.random()-.5;
},
top([x,y], [x2,y2]){
silent || progress(i++/size);
return y-y2;
},
left([x,y], [x2,y2]){
silent || progress(i++/size);
return x-x2;
},
right([x,y], [x2,y2]){
silent || progress(i++/size);
return x2-x;
},
bottom([x,y], [x2,y2]){
silent || progress(i++/size);
return y2-y;
},
fromCenter([x,y], [x2,y2]) {
silent || progress(i++/size);
return ((x-cx)**2+(y-cy)**2) - ((x2-cx)**2+(y2-cy)**2);
},
toCenter([x,y], [x2,y2]) {
silent || progress(i++/size);
return ((x2-cx)**2+(y2-cy)**2) - ((x-cx)**2+(y-cy)**2);
},
fromVertical([x,y], [x2,y2]) {
silent || progress(i++/size);
return Math.abs(x-cx) - Math.abs(x2-cx);
},
toVertical([x,y], [x2,y2]) {
silent || progress(i++/size);
return Math.abs(x2-cx) - Math.abs(x-cx);
},
fromHorizontal([x,y], [x2,y2]) {
silent || progress(i++/size);
return Math.abs(y-cy) - Math.abs(y2-cy);
},
toHorizontal([x,y], [x2,y2]) {
silent || progress(i++/size);
return Math.abs(y2-cy) - Math.abs(y-cy);
},
});
q.sort(method[type] || method['start']);
silent || progress(1);
finish(q);
}
);
});
}
});
PPClient.modules.Tools = module;
})();
// 0vC4#7152