// ==UserScript==
// @name PPT
// @description Pixel Place Tools
// @version 1.5.1
// @author 0vC4
// @namespace https://gf.qytechs.cn/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 PPT = (() => {
if (window.PPT) return window.PPT;
const log = console.log;
const worker = function(func) {
const worker = new Worker(URL.createObjectURL(new Blob(["onmessage=async({data})=>self.postMessage(await(" + func.toString() + ")(data))"], { type: "text/javascript" })));
const root = {};
const post = data => (worker.postMessage(data), root);
const then = callback => (worker.onmessage=({data})=>callback(data), root);
return Object.assign(root, {post, then});
};
const PPT = {
config({colors, exclude, zero, timer}) {
this.colors = colors;
this.exclude = exclude;
this.zero = zero;
this.timer = timer;
this.palette = [...colors].filter(color => !this.exclude.includes(color));
this.rgb = [...this.palette].map(rgb => [
((clr>>16)&0xFF),
((clr>>8)&0xFF),
(clr&0xFF),
]);
},
_wheelID: 0,
get wheel() {
let pixel = this._wheelID+1;
while (this.exclude.includes(this.palette[pixel]))
if (this.palette[++pixel] == null)
pixel = 0;
this._wheelID = pixel;
return this._wheelID;
},
RGB2P(r, g, b) {
const closest = this.rgb.map(([r2, g2, b2]) =>
((r2-r)**2 + (g2-g)**2 + (b2-b)**2)*0x1000000 + clr
)
.sort((a,b) => a-b)[0];
return this.colors.indexOf(closest&0xFFFFFF);
},
CLR2P(color) {
return this.RGB2P((color>>16)&0xFF, (color>>8)&0xFF, color&0xFF);
},
client: null,
get order() {
if (!this.client) throw new Error('assign client variable first');
const client = this.client;
const queue = client._pixelQueue;
const [cxn, cyn] = queue.reduce(([x,y], [x2,y2]) => [x+x2,y+y2], [0, 0]);
const [cx, cy] = [cxn/queue.length>>0, cyn/queue.length>>0];
const workQueue = (func, ...args) => {
let fin = queue => 0;
const then = finish => finish && (fin = finish);
worker(func)
.then(queue => fin(client._pixelQueue = queue))
.post([queue, ...args]);
return {then}
};
return {
start(finish){
workQueue(([queue]) => {
return [...queue].sort(([x,y,p,i], [x2,y2,p2,i2]) => i-i2);
}).then(finish);
},
end(finish){
workQueue(([queue]) => {
return [...queue].sort(([x,y,p,i], [x2,y2,p2,i2]) => i2-i);
}).then(finish);
},
rand(finish){
workQueue(([queue]) => {
return [...queue].sort(() => Math.random()-.5);
}).then(finish);
},
top(finish){
workQueue(([queue]) => {
return [...queue].sort(([x,y], [x2,y2]) => y-y2);
}).then(finish);
},
left(finish){
workQueue(([queue]) => {
return [...queue].sort(([x,y], [x2,y2]) => x-x2);
}).then(finish);
},
right(finish){
workQueue(([queue]) => {
return [...queue].sort(([x,y], [x2,y2]) => x2-x);
}).then(finish);
},
bottom(finish){
workQueue(([queue]) => {
return [...queue].sort(([x,y], [x2,y2]) => y2-y);
}).then(finish);
},
fromCenter(finish){
workQueue(([queue, cx, cy]) => {
return [...queue].sort(([x,y], [x2,y2]) =>
((x-cx)**2+(y-cy)**2) -
((x2-cx)**2+(y2-cy)**2)
);
}, cx, cy).then(finish);
},
toCenter(finish){
workQueue(([queue, cx, cy]) => {
return [...queue].sort(([x,y], [x2,y2]) =>
((x2-cx)**2+(y2-cy)**2) -
((x-cx)**2+(y-cy)**2)
);
}, cx, cy).then(finish);
},
fromVertical(finish){
workQueue(([queue, cx, cy]) => {
return [...queue].sort(([x,y], [x2,y2]) => Math.abs(x-cx) - Math.abs(x2-cx));
}, cx, cy).then(finish);
},
fromHorizontal(finish){
workQueue(([queue, cx, cy]) => {
return [...queue].sort(([x,y], [x2,y2]) => Math.abs(y-cy) - Math.abs(y2-cy));
}, cx, cy).then(finish);
},
toVertical(finish){
workQueue(([queue, cx, cy]) => {
return [...queue].sort(([x,y], [x2,y2]) => Math.abs(x2-cx) - Math.abs(x-cx));
}, cx, cy).then(finish);
},
toHorizontal(finish){
workQueue(([queue, cx, cy]) => {
return [...queue].sort(([x,y], [x2,y2]) => Math.abs(y2-cy) - Math.abs(y-cy));
}, cx, cy).then(finish);
},
fromMapCenter(finish){
workQueue(([queue, cx, cy]) => {
return [...queue].sort(([x,y], [x2,y2]) =>
((x-cx)**2+(y-cy)**2) -
((x2-cx)**2+(y2-cy)**2)
);
}, client.map.width/2, client.map.height/2).then(finish);
},
toMapCenter(finish){
workQueue(([queue, cx, cy]) => {
return [...queue].sort(([x,y], [x2,y2]) =>
((x2-cx)**2+(y2-cy)**2) -
((x-cx)**2+(y-cy)**2)
);
}, client.map.width/2, client.map.height/2).then(finish);
},
fromMapVertical(finish){
workQueue(([queue, cx, cy]) => {
return [...queue].sort(([x,y], [x2,y2]) => Math.abs(x-cx) - Math.abs(x2-cx));
}, client.map.width/2, client.map.height/2).then(finish);
},
fromMapHorizontal(finish){
workQueue(([queue, cx, cy]) => {
return [...queue].sort(([x,y], [x2,y2]) => Math.abs(y-cx) - Math.abs(y2-cx));
}, client.map.width/2, client.map.height/2).then(finish);
},
toMapVertical(finish){
workQueue(([queue, cx, cy]) => {
return [...queue].sort(([x,y], [x2,y2]) => Math.abs(x2-cx) - Math.abs(x-cx));
}, client.map.width/2, client.map.height/2).then(finish);
},
toMapHorizontal(finish){
workQueue(([queue, cx, cy]) => {
return [...queue].sort(([x,y], [x2,y2]) => Math.abs(y2-cx) - Math.abs(y-cx));
}, client.map.width/2, client.map.height/2).then(finish);
},
};
},
timer: window,
pixel: 0,
size: 1,
innerSize: 0,
speed: 100,
map: {pixels:[],width:0,height:0,get(x,y){return 255}},
square(x,y, callback, finish) {
const {pixel, timer, speed, size, innerSize} = this;
const half = size>>1;
const innerHalf = innerSize>>1;
let xi = -half;
let yi = -half;
let t = timer.setInterval(() => {
let i = 0;
for (; yi < half+1;) {
for (; xi < half+1;) {
if (pixel === 255 || xi > -innerHalf && xi < innerHalf && yi > -innerHalf && yi < innerHalf) {
xi++;
continue;
}
callback(x+xi, y+yi, pixel, t);
xi++;
i++;
if (i > speed) return;
continue;
}
yi++;
xi = -half;
}
timer.clearInterval(t);
finish&&finish();
});
return t;
},
ring(x,y, callback, finish) {
const {pixel, timer, speed, size, innerSize} = this;
const half = size>>1;
const innerHalf = innerSize>>1;
let xi = -half;
let yi = -half;
let t = timer.setInterval(() => {
let i = 0;
for (; yi < half+1;) {
for (; xi < half+1;) {
if (pixel === 255 || xi**2 + yi**2 > half**2 || xi**2 + yi**2 < innerHalf**2) {
xi++;
continue;
}
callback(x+xi, y+yi, pixel, t);
xi++;
i++;
if (i > speed) return;
continue;
}
yi++;
xi = -half;
}
timer.clearInterval(t);
finish&&finish();
});
return t;
},
shader(callback, finish) {
const {timer, speed, map} = this;
let pos = 0;
let t = timer.setInterval(() => {
let i = 0;
for (; pos < map.pixels.length; ) {
if (map.pixels[pos] === 255) {
pos++;
continue;
}
callback(pos%map.width, pos/map.width>>0, map.pixels[pos], t);
pos++;
i++;
if (i > speed) return;
continue;
}
timer.clearInterval(t);
finish&&finish();
});
return t;
},
image(pixels, x,y,w,h, callback, finish) {
const {timer, speed} = this;
let xi = 0;
let yi = 0;
let t = timer.setInterval(() => {
let i = 0;
for (; yi < h;) {
for (; xi < w;) {
const pixel = pixels[xi+yi*w];
if (pixel === 255) {
xi++;
continue;
}
callback(x+xi, y+yi, pixel, t);
xi++;
i++;
if (i > speed) return;
continue;
}
yi++;
xi = 0;
}
timer.clearInterval(t);
finish&&finish();
});
return t;
}
};
window.PPT = PPT;
return PPT;
})();
// 0vC4#7152