Paper.IO by DangNhutNguyen

Zoom hack, game speed change hack, instant movement hack, and pause/resume functionality.

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name Paper.IO by DangNhutNguyen
// @namespace -
// @version 1.1.5
// @description Zoom hack, game speed change hack, instant movement hack, and pause/resume functionality.
// @author Dang Nhut
// @match *://paper-io.com/*
// @match *://*.paper-io.com/*
// @run-at document-start
// @license GPL-3.0-or-later
// @grant none
// @icon data:image/png;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAe8MAYnvDAHp7wwB6e8MAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHvDAMp7wwD/e8MA/3vDAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB7wwDKe8MA/3vDAP97wwBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfcQAyn3EAP99xAD/fcQAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIHGAMqBxgD/gcYA/4HGAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACHyQDKh8kA/4fJAP+HyQBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjcwAyo3MAP+NzAD/jcwAsI7MAJSOzACUhrgAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJPPAMqTzwD/k88A/5PPAP+TzwD/k88A/4q5DfqKtxdaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACb0wDKm9MA/5vTAP+b0wD/m9MA/5vTAP+Rvif/kLss+pG8MVoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAodYDyqHWA/+h1gP/oNYBhp/VAFyf1QBcnc4X7J3OGP+ezhf6oNMOIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKnaKMqp2ij/qdoo/6naKEAAAAAAAAAAAKnaKOKp2ij/qdoo/6naKCoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACv3UHKr91B/6/dQf+v3UFAAAAAAAAAAACv3UHir91B/6/dQf+v3UEqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr9VclK/UX/+v1F//tN1WwrXgVK614FSur9Ve9q/UX/+v1F7gsdpUEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK/QbASx0XCisdFx/7nfY/+64mD/uuJg/7LTb/+x0XDgsNBtIgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtdN3ArbUeqK+4W//v+Rt/7/kbf+31nngtdN4IgAAAAAAAAAAAAAAALXTdwwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC614AEweR2QMLmdELC5nRCvNt8GgAAAAAAAAAAAAAAAAAAAAAAAAAA//8AAPH/AADx/wAA8f8AAPH/AADx/wAA8D8AAPAfAADwDwAA8McAAPHHAADxxwAA8AcAAPgPAAD8HwAA//8AAA==
// ==/UserScript==

(function() {
    const MIN_ZOOM = 0.5;
    const MAX_ZOOM = 100000;

    const MIN_GAME_SPEED = 0;
    const MAX_GAME_SPEED = 900000;

    const DEBUG_LEVEL = 0 /* 0 - disabled; 1 - info; 2 - errors */;
    const API_PROPS = ['paperio2api', 'paper2'];

    class Utils {
        static minmax(n, min, max) {
            return Math.min(Math.max(n, min), max);
        }

        static debug(level, ...args) {
            let _level;

            switch (level) {
                case 'log':
                    _level = 0;
                    break;
                case 'error':
                    _level = 1;
                    break;
            }

            if (DEBUG_LEVEL > _level) {
                console[level].apply(this, args);
            }
        }

        static waitForProperty(target, props) {
            let tries = 0;

            try {
                return new Promise((res, rej) => {
                    let intervalId = setInterval(() => {
                        tries++;

                        let validProp = props.find(prop => target[prop]);

                        if (validProp) {
                            clearInterval(intervalId);
                            return res(target[validProp]);
                        }

                        if (tries > 6) {
                            rej('Timeout error, cannot find properties: "' + props + '" in target object.');
                        }
                    }, 1e3);
                });
            } catch(e) {
                Utils.debug('error', 'waitForProperty', e);
            }
        }
    }

    class Hack {
        static init(paper_api) {
            const GAME = paper_api.game;
            const CONFIG = GAME.config;
            const SCENE = getScene();
            let isPaused = false;
            let previousSpeed = CONFIG.unitSpeed;

            Utils.debug('log', this.name + ' initialized!');

            class GameSpeedHack {
                static init(maxGameSpeed, minGameSpeed) {
                    window.addEventListener('keydown', e => {
                        if (e.code === 'ArrowUp') {
                            e.preventDefault();
                            CONFIG.unitSpeed += 100;
                            CONFIG.unitSpeed = Utils.minmax(CONFIG.unitSpeed, minGameSpeed, maxGameSpeed);
                        } else if (e.code === 'ArrowDown') {
                            e.preventDefault();
                            CONFIG.unitSpeed -= 100;
                            CONFIG.unitSpeed = Utils.minmax(CONFIG.unitSpeed, minGameSpeed, maxGameSpeed);
                        }
                    });

                    window.addEventListener('keydown', e => {
                        if (e.code === 'Space') {
                            e.preventDefault();
                            if (isPaused) {
                                CONFIG.unitSpeed = previousSpeed;
                                isPaused = false;
                            } else {
                                previousSpeed = CONFIG.unitSpeed;
                                CONFIG.unitSpeed = 0;
                                isPaused = true;
                            }
                        }
                    });
                }
            }

            class ZoomHack {
                static init(maxZoom, minZoom) {
                    window.addEventListener('wheel', e => {
                        e.preventDefault();

                        const isPositive = e.deltaY > 0;
                        const zoomChange = isPositive ? -0.1 : 0.1; // Adjust zoom sensitivity

                        SCENE.maxScale += zoomChange;
                        SCENE.maxScale = Utils.minmax(SCENE.maxScale, minZoom, maxZoom);
                    });
                }
            }

            class InstantMovement {
                static init(listenersData) {
                    listenersData.forEach(data => {
                        try {
                            window.addEventListener('keydown', e => {
                                try {
                                    if (e.code === data.code) {
                                        const PLAYER = GAME.player;

                                        PLAYER.position[data.direction] += 200 * (data.isNegative ? -1 : 1);
                                    }
                                } catch (err) {
                                    Utils.debug('error', data, err);
                                }
                            });
                        } catch (e) {
                            Utils.debug('error', this.name, data, e);
                        }
                    });
                }
            }

            GameSpeedHack.init(
                MAX_GAME_SPEED,
                MIN_GAME_SPEED
            );

            ZoomHack.init(
                MAX_ZOOM,
                MIN_ZOOM
            );

            InstantMovement.init([{
                code: 'KeyW',
                direction: 'y',
                isNegative: true,
            }, {
                code: 'KeyS',
                direction: 'y',
                isNegative: false,
            }, {
                code: 'KeyA',
                direction: 'x',
                isNegative: true,
            }, {
                code: 'KeyD',
                direction: 'x',
                isNegative: false,
            }]);

            function getScene() {
                if (paper_api.currentConfig) {
                    return paper_api.currentConfig;
                }

                if (paper_api.configs) {
                    return paper_api.configs.paper2_classic;
                }

                return paper_api.config;
            }
        }
    }

    class Main {
        static init() {
            Utils.waitForProperty(window, API_PROPS).then(paperapi => {
                Utils.waitForProperty(paperapi, ['game']).then(() => {
                    Main.showInstructions();
                    Hack.init(paperapi);
                });
            });
        }

        static showInstructions() {
            alert(
                "PAPER.IO Script - Made by Dang Nhut INSTRUCTION:\n" +
                "- Follow me on Github: https://github.com/DangNhutNguyen:\n" +
                "- This script only for education purpose only, please use this script as tools to developed your programming language.\n" +
                "- Zoom: Use the mouse wheel to zoom in and out.\n" +
                "- Change game speed: Use the up/down arrow keys to adjust speed.\n" +
                "- Instant Movement: Use 'W', 'A', 'S', 'D' for quick moves in the respective directions.\n" +
                "- Pause/Resume: Press 'Spacebar' to pause or resume the game."
            );
        }
    }

    Main.init();
})();