PPT

Pixel Place Tools

此脚本不应直接安装,它是一个供其他脚本使用的外部库。如果您需要使用该库,请在脚本元属性加入:// @require https://update.cn-greasyfork.org/scripts/443807/1050374/PPT.js

  1. // ==UserScript==
  2. // @name PPT
  3. // @description Pixel Place Tools
  4. // @version 1.6.2
  5. // @author 0vC4
  6. // @namespace https://greasyfork.org/users/670183
  7. // @match https://pixelplace.io/*
  8. // @icon https://www.google.com/s2/favicons?sz=64&domain=pixelplace.io
  9. // @license MIT
  10. // @grant none
  11. // @run-at document-start
  12. // ==/UserScript==
  13. (() => {
  14. const PPClient = window.PPClient || {modules:{}};
  15. window.PPClient = PPClient;
  16. if ('Tools' in PPClient.modules) return;
  17.  
  18. const progressManager = func => {
  19. const callbacks = {};
  20. const root = new Proxy({}, {
  21. get(target, key) {
  22. if (!target[key]) target[key] = callback => (callbacks[key] = callback, root);
  23. return target[key];
  24. }
  25. });
  26. root.start = (...args) => func(callbacks)(...args);
  27. return root;
  28. };
  29.  
  30. const worker = progressManager(({progress=()=>0, finish=()=>0}) =>
  31. (data, func) => {
  32. const worker = new Worker(URL.createObjectURL(new Blob([`
  33. const progress = value => self.postMessage({progress:true,value});
  34. const finish = value => self.postMessage({finish:true,value});
  35. onmessage = async ({data}) => {
  36. await (${func.toString()})(data);
  37. close();
  38. };
  39. `], { type: "text/javascript" })));
  40. worker.addEventListener('message', ({data}) => data.progress && progress(data.value));
  41. worker.addEventListener('message', ({data}) => data.finish && finish(data.value));
  42. worker.postMessage(data);
  43. });
  44.  
  45. const module = {
  46. args: {},
  47.  
  48. _wheelID: 0,
  49. get wheel() {
  50. const {exclude, colors} = module.args;
  51. let pixel = module._wheelID+1;
  52. while (exclude.includes(colors[pixel]))
  53. if (colors[++pixel] == null)
  54. pixel = 0;
  55. module._wheelID = pixel;
  56. return pixel;
  57. },
  58.  
  59. pixel: 0,
  60. size: 9,
  61. innerSize: 0,
  62. interval: 0,
  63.  
  64. RGB2P(r, g, b) {
  65. const closest = module.args.rgb.map(([r2, g2, b2]) =>
  66. ((r2-r)**2 + (g2-g)**2 + (b2-b)**2)*0x1000000 + (r2<<16)+ (g2<<8) + b
  67. )
  68. .sort((a,b) => a-b)[0];
  69.  
  70. return module.args.colors.indexOf(closest&0xFFFFFF);
  71. },
  72. CLR2P(color) {
  73. return module.RGB2P((color>>16)&0xFF, (color>>8)&0xFF, color&0xFF);
  74. },
  75. };
  76.  
  77. module.config = ({colors,exclude,zero, timer,tickSpeed}) => {
  78. const palette = [...colors].map(color => exclude.includes(color) ? zero : color);
  79. const rgb = palette.filter(clr => clr != zero).map(clr => [((clr>>16)&0xFF), ((clr>>8)&0xFF), (clr&0xFF)]);
  80. Object.assign(module.args, {colors,exclude,zero, timer,tickSpeed, palette,rgb});
  81. };
  82.  
  83.  
  84.  
  85. module.shader = progressManager(({
  86. progress=()=>0, finish=()=>0, tick=()=>0,
  87. silent=true,
  88. interval=module.interval
  89. }) => (map) => {
  90. const {timer} = module.args;
  91. let pos = 0;
  92. let t = timer.setInterval(() => {
  93. const {tickSpeed} = module.args;
  94. let i = 0;
  95. for (; pos < map.pixels.length; ) {
  96. silent || progress(pos/map.pixels.length, t);
  97. if (map.pixels[pos] === 255) {
  98. pos++;
  99. continue;
  100. }
  101. tick(pos%map.width, pos/map.width>>0, map.pixels[pos]);
  102. pos++;
  103. i++;
  104. if (i > tickSpeed) return;
  105. continue;
  106. }
  107. timer.clearInterval(t);
  108. finish(t);
  109. }, interval);
  110. return t;
  111. });
  112.  
  113.  
  114.  
  115. module.square = progressManager(({
  116. progress=()=>0, finish=()=>0, tick=()=>0,
  117. silent=true,
  118. interval=module.interval,
  119. size=module.size,
  120. innerSize=module.innerSize,
  121. }) => (x,y,pixel=module.pixel) => {
  122. const {timer} = module.args;
  123. const half = size>>1;
  124. const innerHalf = innerSize>>1;
  125. let xi = -half;
  126. let yi = -half;
  127. let t = timer.setInterval(() => {
  128. const {tickSpeed} = module.args;
  129. let i = 0;
  130. for (; yi < half+1;) {
  131. for (; xi < half+1;) {
  132. const pos = (xi+half+(yi+half)*size);
  133. silent || progress(pos/size**2, t);
  134.  
  135. if (pixel === 255 || xi > -innerHalf && xi < innerHalf && yi > -innerHalf && yi < innerHalf) {
  136. xi++;
  137. continue;
  138. }
  139. tick(x+xi, y+yi, pixel);
  140. xi++;
  141. i++;
  142. if (i > tickSpeed) return;
  143. continue;
  144. }
  145. yi++;
  146. xi = -half;
  147. }
  148. timer.clearInterval(t);
  149. finish(t);
  150. }, interval);
  151. return t;
  152. });
  153.  
  154.  
  155.  
  156. module.circle = progressManager(({
  157. progress=()=>0, finish=()=>0, tick=()=>0,
  158. silent=true,
  159. interval=module.interval,
  160. radius=module.size>>1,
  161. innerRadius=module.innerSize>>1,
  162. }) => (x,y,pixel=module.pixel) => {
  163. const {timer} = module.args;
  164. const half = radius;
  165. const innerHalf = innerRadius;
  166. let xi = -half;
  167. let yi = -half;
  168. let t = timer.setInterval(() => {
  169. const {tickSpeed} = module.args;
  170. let i = 0;
  171. for (; yi < half+1;) {
  172. for (; xi < half+1;) {
  173. const pos = (xi+half+(yi+half)*size);
  174. silent || progress(pos/size**2, t);
  175.  
  176. if (pixel === 255 || xi**2 + yi**2 > half**2 || xi**2 + yi**2 < innerHalf**2) {
  177. xi++;
  178. continue;
  179. }
  180. tick(x+xi, y+yi, pixel);
  181. xi++;
  182. i++;
  183. if (i > tickSpeed) return;
  184. continue;
  185. }
  186. yi++;
  187. xi = -half;
  188. }
  189. timer.clearInterval(t);
  190. finish(t);
  191. }, interval);
  192. return t;
  193. });
  194.  
  195.  
  196.  
  197. module.image = progressManager(({
  198. progress=()=>0, finish=()=>0, tick=()=>0,
  199. interval=module.interval,
  200. }) => (pixels, x,y,w,h) => {
  201. const {timer} = module.args;
  202. let xi = 0;
  203. let yi = 0;
  204. let t = timer.setInterval(() => {
  205. const {tickSpeed} = module.args;
  206. let i = 0;
  207. for (; yi < h;) {
  208. for (; xi < w;) {
  209. const pos = xi+yi*w;
  210. progress(pos/pixels.length, t);
  211.  
  212. const pixel = pixels[pos];
  213. if (pixel === 255) {
  214. xi++;
  215. continue;
  216. }
  217. tick(x+xi, y+yi, pixel);
  218. xi++;
  219. i++;
  220. if (i > tickSpeed) return;
  221. continue;
  222. }
  223. yi++;
  224. xi = 0;
  225. }
  226. timer.clearInterval(t);
  227. finish(t);
  228. }, interval);
  229. return t;
  230. });
  231.  
  232.  
  233.  
  234. module.order = new Proxy({}, {
  235. get(_, type) {
  236. return progressManager(({
  237. progress=()=>0, finish=()=>0,
  238. silent=true,
  239. center=[0,0]
  240. }) => (queue) => {
  241. if (type == 'fromCenterQueue' || type == 'toCenterQueue') {
  242. type = type.replace('Queue', '');
  243. const [cxn, cyn] = queue.reduce(([x,y], [x2,y2]) => [x+x2,y+y2], [0, 0]);
  244. center = [cxn/queue.length>>0, cyn/queue.length>>0];
  245. }
  246. worker.progress(progress).finish(finish)
  247. .start(
  248. {queue, type, center, silent},
  249. async ({queue, type, center, silent}) => {
  250. const q = [...queue];
  251. const size = queue.length*Math.log(queue.length)|0;
  252. const [cx, cy] = center;
  253. let i = 0;
  254.  
  255. const method = ({
  256. start([x,y,p,i], [x2,y2,p2,i2]) {
  257. silent || progress(i++/size);
  258. return i-i2;
  259. },
  260. end([x,y,p,i], [x2,y2,p2,i2]) {
  261. silent || progress(i++/size);
  262. return i2-i;
  263. },
  264. rand() {
  265. silent || progress(i++/size);
  266. return Math.random()-.5;
  267. },
  268.  
  269. top([x,y], [x2,y2]){
  270. silent || progress(i++/size);
  271. return y-y2;
  272. },
  273. left([x,y], [x2,y2]){
  274. silent || progress(i++/size);
  275. return x-x2;
  276. },
  277. right([x,y], [x2,y2]){
  278. silent || progress(i++/size);
  279. return x2-x;
  280. },
  281. bottom([x,y], [x2,y2]){
  282. silent || progress(i++/size);
  283. return y2-y;
  284. },
  285.  
  286. fromCenter([x,y], [x2,y2]) {
  287. silent || progress(i++/size);
  288. return ((x-cx)**2+(y-cy)**2) - ((x2-cx)**2+(y2-cy)**2);
  289. },
  290. toCenter([x,y], [x2,y2]) {
  291. silent || progress(i++/size);
  292. return ((x2-cx)**2+(y2-cy)**2) - ((x-cx)**2+(y-cy)**2);
  293. },
  294.  
  295. fromVertical([x,y], [x2,y2]) {
  296. silent || progress(i++/size);
  297. return Math.abs(x-cx) - Math.abs(x2-cx);
  298. },
  299. toVertical([x,y], [x2,y2]) {
  300. silent || progress(i++/size);
  301. return Math.abs(x2-cx) - Math.abs(x-cx);
  302. },
  303.  
  304. fromHorizontal([x,y], [x2,y2]) {
  305. silent || progress(i++/size);
  306. return Math.abs(y-cy) - Math.abs(y2-cy);
  307. },
  308. toHorizontal([x,y], [x2,y2]) {
  309. silent || progress(i++/size);
  310. return Math.abs(y2-cy) - Math.abs(y-cy);
  311. },
  312. });
  313. q.sort(method[type] || method['start']);
  314. silent || progress(1);
  315. finish(q);
  316. }
  317. );
  318. });
  319. }
  320. });
  321.  
  322.  
  323.  
  324. PPClient.modules.Tools = module;
  325. })();
  326. // 0vC4#7152