Jstris Keyboard Display Script

shows keyboard inputs on screen

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Jstris Keyboard Display Script
// @namespace    http://tampermonkey.net/
// @version      0.0.0
// @description  shows keyboard inputs on screen
// @author       mat1jaczyyy (based on Oki and meppydc's works)
// @match        https://*.jstris.jezevec10.com/*
// @grant        none
// @license      MIT
// ==/UserScript==

/* eslint-disable no-undef */

(function() {
    window.addEventListener('load', function() {
        const isGame = typeof Game != "undefined";
        const isReplayer = typeof Replayer != "undefined";

        if (!isGame && !isReplayer) return;

        const pos = {x: -300, y: 100};

        const keyConfig = [
            [
                'new',
                null,
                {k: 'reset', l: 'F4'},
            ],
            [
                null
            ],
            [
                '180',
                'ccw',
                'cw',
                null,
                null,
                'hd',
            ],
            [
                null,
                null,
                {k: 'hold', l: 'HLD'},
                null,
                {k: 'left', l: 'L'},
                'sd',
                {k: 'right', l: 'R'}
            ]
        ];

        var kbhold = document.createElement("div");
        kbhold.id = "keyboardHolder";
        kbhold.style.position = "absolute"
        kbhold.style.left = (myCanvas.getBoundingClientRect().left + pos.x) + "px";
        kbhold.style.top = (myCanvas.getBoundingClientRect().top + pos.y) + "px";
        document.body.appendChild(kbhold);

        let keyTable = `
            <style>
                #kbo {text-align:center;position: absolute;font-size:15px;}
                #kbo .tg {border-collapse:collapse;border-spacing:0;color:red;}
                #kbo .tg td{padding:10px 5px;border-style:solid;border-width:2px;}
                #kbo .tg th{padding:10px 5px;border-style:solid;border-width:2px;}
                #kbo .tg .kbnone{border-color:#000000;border:inherit;}
                #kbo .tg .kbkey{border-color:#34ff34;background-color:black;}
            </style>

            <div id="kbo">
                <div id="kps"></div>
                <table class="tg">
        `;

        for (const row of keyConfig) {
            keyTable += `<tr>`;

            for (const key of row) {
                let isKey = key != null;
                let label = "";
                let cssClass = "kbnone";

                if (isKey) {
                    label = typeof key == 'string'? key.toUpperCase() : key.l;
                    cssClass = "kbkey kbd-" + (typeof key == 'string'? key.toLowerCase() : key.k);
                }

                keyTable += `<td class="${cssClass}">${label}</td>`;
            }

            keyTable += `</tr>`;
        }

        keyTable += `
                </table>
            </div>
        `;

        keyboardHolder.innerHTML = keyTable;

        let inject = function(o, f, c) {
            let text = o.prototype[f].toString();

            let params = text.slice(text.indexOf("(") + 1, text.indexOf(")"))
                .trim().split(",")
                .map(i => i.trim())
                .filter(i => i);

            let body = text.slice(text.indexOf("{") + 1, -1);

            o.prototype[f] = new Function(...params, c(params, body));
        };

        let setKey = function(key, type) {
            for (const td of document.getElementsByClassName(`kbd-${key}`)) {
                td.style.backgroundColor = ["", "lightgoldenrodyellow"][type];
            }
        }

        if (isGame) {
            inject(Game, 'readyGo', (p, i) => "Game['set2ings'] = this.Settings.controls;" + i);
            inject(Game, 'updateTextBar', (p, i) => i + "; kps.innerHTML = 'KPS: ' + (this.getKPP() * this.placedBlocks / this.clock).toFixed(2);");

            let press = function (e) {
                if (typeof Game.set2ings == 'undefined') return;

                let i = Game.set2ings.indexOf(e.keyCode);
                if (i == -1) return;

                let key = ['left', 'right', 'sd', 'hd', 'ccw', 'cw', 'hold', '180', 'reset', 'new'][i];
                setKey(key, +(e.type == "keydown"))
            }

            document.addEventListener('keydown', press);
            document.addEventListener('keyup', press);

        } else if (isReplayer) {
            var url = window.location.href.split("/")

            if (!url[2].endsWith("jstris.jezevec10.com")) return;
            if (url[3] != "replay") return;

            fetch(`https://${url[2]}/replay/data?id=${url.length == 6? (url[5] + "&live=1") : url[4]}&type=0`)
                .then(res => res.json())
                .then(json => {
                    let das = json.c.das;

                    Replayer.setKey = setKey;

                    inject(Replayer, 'playUntilTime', (p, i) => {
                        let before = `;
                            kps.innerHTML = 'KPS: ' + (this.getKPP() * this.placedBlocks / this.clock * 1000).toFixed(2);

                            if (this.ptr == 0) Replayer.lastPtr = -1;

                            this.kbdActions = [];

                            for (let i = 0; i < this.actions.length; i++) {
                                let o = {a: this.actions[i].a, t: this.actions[i].t};

                                if (o.a == 2 || o.a == 3) {
			                        o.a -= 2;
                                    for (let j = i - 1; j >= 0; j--) {
                                        if (this.kbdActions[j].a < 2) {
                                            this.kbdActions[j].a += 2;
                                            break;
                                        }
                                    }
			                    }

                                this.kbdActions.push(o);
                            }

                            let pressKey = function(key, type) {
                                Replayer.setKey(key, Math.min(type, 1));

                                if (type == 2) {
                                    setTimeout(x => Replayer.setKey(key, 0), ${das} * 3 / 5)
                                }
                            };
                        `;

                        let after = `;
                            if (this.ptr != Replayer.lastPtr && this.ptr - 1 < this.kbdActions.length) {
                                var highlight = [
                                    ["left", 2],
                                    ["right", 2],
                                    ["left", 1],
                                    ["right", 1],
                                    ["ccw", 2],
                                    ["cw", 2],
                                    ["180", 2],
                                    ["hd", 2],
                                    ["sd", 2],
                                    null,
                                    ["hold", 2]
                                ][this.kbdActions[this.ptr - 1].a];

			                    if (highlight) {
			                        pressKey(...highlight)
			                    }
                            }

                            Replayer.lastPtr = this.ptr;
                        `;

                        return before + i + after;
                    });
                });
        }
    });
})();