Greasy Fork

diepAPI

https://github.com/Cazka/diepAPI

当前为 2022-02-26 提交的版本,查看 最新版本

此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.greasyfork.icu/scripts/433681/1022511/diepAPI.js

var diepAPI;
/******/ (() => { // webpackBootstrap
/******/ 	"use strict";
/******/ 	// The require scope
/******/ 	var __webpack_require__ = {};
/******/ 	
/************************************************************************/
/******/ 	/* webpack/runtime/define property getters */
/******/ 	(() => {
/******/ 		// define getter functions for harmony exports
/******/ 		__webpack_require__.d = (exports, definition) => {
/******/ 			for(var key in definition) {
/******/ 				if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ 					Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ 				}
/******/ 			}
/******/ 		};
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/hasOwnProperty shorthand */
/******/ 	(() => {
/******/ 		__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/make namespace object */
/******/ 	(() => {
/******/ 		// define __esModule on exports
/******/ 		__webpack_require__.r = (exports) => {
/******/ 			if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ 				Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ 			}
/******/ 			Object.defineProperty(exports, '__esModule', { value: true });
/******/ 		};
/******/ 	})();
/******/ 	
/************************************************************************/
var __webpack_exports__ = {};
// ESM COMPAT FLAG
__webpack_require__.r(__webpack_exports__);

// EXPORTS
__webpack_require__.d(__webpack_exports__, {
  "CanvasKit": () => (/* reexport */ CanvasKit),
  "Vector": () => (/* reexport */ Vector),
  "arena": () => (/* reexport */ arena),
  "arenaScaling": () => (/* reexport */ arenaScaling),
  "entityManager": () => (/* reexport */ entityManager),
  "game": () => (/* reexport */ game),
  "gamepad": () => (/* reexport */ gamepad),
  "minimap": () => (/* reexport */ minimap),
  "player": () => (/* reexport */ player)
});

;// CONCATENATED MODULE: ./src/vector.ts
class Vector {
    x;
    y;
    constructor(x, y) {
        this.x = x;
        this.y = y;
    }
    /**
     * ( u1 ) + ( v1 ) = ( u1 + v1 )
     * ( u2 )   ( v2 )   ( u2 + v2 )
     */
    static add(u, v) {
        return new Vector(u.x + v.x, u.y + v.y);
    }
    /**
     * ( u1 ) - ( v1 ) = ( u1 - v1 )
     * ( u2 )   ( v2 )   ( u2 - v2 )
     */
    static subtract(u, v) {
        return new Vector(u.x - v.x, u.y - v.y);
    }
    /**
     * ( u1 ) * ( v1 ) = ( u1 * v1 )
     * ( u2 )   ( v2 )   ( u2 * v2 )
     */
    static multiply(u, v) {
        return new Vector(u.x * v.x, u.y * v.y);
    }
    /**
     * ( u1 ) / ( v1 ) = ( u1 / v1 )
     * ( u2 )   ( v2 )   ( u2 / v2 )
     */
    static divide(u, v) {
        return new Vector(u.x / v.x, u.y / v.y);
    }
    /**
     * r * ( v1 ) = ( r * v1 )
     *     ( v2 )   ( r * v2 )
     */
    static scale(r, v) {
        return new Vector(r * v.x, r * v.y);
    }
    static round(v) {
        return new Vector(Math.round(v.x), Math.round(v.y));
    }
    static len(v) {
        return Math.sqrt(v.x ** 2 + v.y ** 2);
    }
    static distance(u, v) {
        return Vector.len(Vector.subtract(u, v));
    }
    /**
     * Calculates the [centroid](https://en.wikipedia.org/wiki/Centroid)
     */
    static centroid(...vertices) {
        const sum = vertices.reduce((acc, vec) => Vector.add(acc, vec), new Vector(0, 0));
        const centroid = Vector.scale(1 / vertices.length, sum);
        return centroid;
    }
    /**
     * Calcutes the radius from a set of vertices that are placed on a circle
     */
    static radius(...vertices) {
        const centroid = Vector.centroid(...vertices);
        const distance = vertices.reduce((acc, vec) => acc + Vector.distance(centroid, vec), 0);
        const radius = distance / vertices.length;
        return radius;
    }
}

;// CONCATENATED MODULE: ./src/canvas_kit.ts
class CanvasKit {
    /**
     * The consumer will be called before
     */
    static hook(method, consumer) {
        const target = window.CanvasRenderingContext2D.prototype;
        target[method] = new Proxy(target[method], {
            apply(target, thisArg, args) {
                if (thisArg.canvas.className !== 'CanvasKit-bypass')
                    consumer(target, thisArg, args);
                return Reflect.apply(target, thisArg, args);
            },
        });
    }
    /**
     * replaces the function. Use `return Reflect.apply(target, thisArg, args);` in
     * your function to call the original function.
     */
    static replace(method, func) {
        const target = window.CanvasRenderingContext2D.prototype;
        target[method] = new Proxy(target[method], {
            apply(target, thisArg, args) {
                if (thisArg.canvas.className !== 'CanvasKit-bypass')
                    return func(target, thisArg, args);
                return Reflect.apply(target, thisArg, args);
            },
        });
    }
    /**
     * The consumer will be called before.
     */
    static hookRAF(consumer) {
        window.requestAnimationFrame = new Proxy(window.requestAnimationFrame, {
            apply(target, thisArg, args) {
                consumer();
                return Reflect.apply(target, thisArg, args);
            },
        });
    }
    /**
     * If you want to a canvas then create it with this method.
     */
    static createCanvas() {
        const canvas = document.createElement('canvas');
        canvas.className = 'CanvasKit-bypass';
        canvas.style.pointerEvents = 'none';
        canvas.style.position = 'fixed';
        canvas.style['z-index'] = 1;
        canvas.style.top = '0px';
        canvas.style.left = '0px';
        canvas.style.right = '0px';
        canvas.style.bottom = '0px';
        canvas.style.width = '100%';
        canvas.style.height = '100%';
        return canvas;
    }
}

;// CONCATENATED MODULE: ./src/diep_gamepad.ts
class DiepGamepad {
    #axes;
    #buttons;
    connected;
    /**
     * Emulates a Gampad
     * when `gamepad.connected` is set to `true` the game will
     * ignore following keyboard inputs:
     * 		W, A, S, D, upArrow, leftArrow, downArrow, rightArray
     *      leftMouse, rightMouse, Spacebar, Shift,
     *      MouseMovement to change tank angle
     * these are also the only keys we emulate with this gamepad
     *
     */
    constructor() {
        this.#axes = [0, 0, 0, 0];
        this.#buttons = [...Array(17)].map((x) => {
            return { pressed: false };
        });
        this.connected = false;
        //window.navigator.getGamepads = () => [this.connected ? this.#toGamepad() : undefined];
        window.navigator.getGamepads = new Proxy(window.navigator.getGamepads, {
            apply: (target, thisArg, args) => {
                if (this.connected)
                    return [this.#toGamepad()];
                return Reflect.apply(target, thisArg, args);
            },
        });
    }
    set x(value) {
        this.#axes[0] = value;
    }
    set y(value) {
        this.#axes[1] = value;
    }
    set mx(value) {
        this.#axes[2] = value;
    }
    set my(value) {
        this.#axes[3] = value;
    }
    set leftMouse(value) {
        this.#buttons[7].pressed = value;
    }
    set rightMouse(value) {
        this.#buttons[6].pressed = value;
    }
    get x() {
        return this.#axes[0];
    }
    get y() {
        return this.#axes[1];
    }
    get mx() {
        return this.#axes[2];
    }
    get my() {
        return this.#axes[3];
    }
    get leftMouse() {
        return this.#buttons[7].pressed;
    }
    get rightMouse() {
        return this.#buttons[6].pressed;
    }
    #toGamepad() {
        return {
            axes: this.#axes,
            buttons: this.#buttons,
            mapping: 'standard',
        };
    }
}
const gamepad = new DiepGamepad();

;// CONCATENATED MODULE: ./src/event_emitter.ts
class EventEmitter extends EventTarget {
    /**
     *
     * @param {string} eventName The name of the event
     * @param  {...any} args The arguments that will be passed to the listener
     */
    emit(eventName, ...args) {
        this.dispatchEvent(new CustomEvent(eventName, { detail: args }));
    }
    /**
     *
     * @param {string} eventName The name of the event
     * @param {EventCallback} listener The callback function
     */
    on(eventName, listener) {
        this.addEventListener(eventName, (e) => Reflect.apply(listener, this, e.detail));
    }
    /**
     *
     * @param {string} eventName The name of the event
     * @param {EventCallback} listener The callback function
     */
    once(eventName, listener) {
        this.addEventListener(eventName, (e) => Reflect.apply(listener, this, e.detail), { once: true });
    }
    /**
     *
     * @param {string} eventName The name of the event
     * @param {EventCallback} listener The callback function
     */
    off(eventName, listener) {
        this.removeEventListener(eventName, listener);
    }
}

;// CONCATENATED MODULE: ./src/game.ts


class Game extends EventEmitter {
    #ready = false;
    constructor() {
        super();
        CanvasKit.hookRAF(() => this.#onframe());
    }
    #onframe() {
        if (!this.#ready && window.input !== undefined) {
            this.#ready = true;
            this.#onready();
        }
        super.emit('frame');
    }
    #onready() {
        setTimeout(() => super.emit('ready'), 100);
    }
}
const game = new Game();

;// CONCATENATED MODULE: ./src/minimap.ts



class Minimap {
    #minimapDim = new Vector(1, 1);
    #minimapPos = new Vector(0, 0);
    #viewportDim = new Vector(1, 1);
    #viewportPos = new Vector(0, 0);
    /**
     * @description The position of the arrow normalized to the range [0,1]
     */
    #arrowPos = new Vector(0.5, 0.5);
    #drawViewport = false;
    constructor() {
        game.once('ready', () => {
            window.input.set_convar('ren_minimap_viewport', 'true');
            window.input.set_convar = new Proxy(window.input.set_convar, {
                apply: (target, thisArg, args) => {
                    if (args[0] === 'ren_minimap_viewport')
                        this.#drawViewport = args[1];
                    else
                        Reflect.apply(target, thisArg, args);
                },
            });
        });
        this._minimapHook();
        this._viewportHook();
        this._arrowHook();
    }
    get minimapDim() {
        return this.#minimapDim;
    }
    get minimapPos() {
        return this.#minimapPos;
    }
    get viewportDim() {
        return this.#viewportDim;
    }
    get viewportPos() {
        return this.#viewportPos;
    }
    get arrowPos() {
        return this.#arrowPos;
    }
    drawViewport(value) {
        this.#drawViewport = value;
    }
    _minimapHook() {
        CanvasKit.hook('strokeRect', (target, thisArg, args) => {
            const transform = thisArg.getTransform();
            this.#minimapDim = new Vector(transform.a, transform.d);
            this.#minimapPos = new Vector(transform.e, transform.f);
        });
    }
    _viewportHook() {
        CanvasKit.replace('fillRect', (target, thisArg, args) => {
            const transform = thisArg.getTransform();
            if (Math.round((transform.a / transform.d) * 10_000) !==
                Math.round((window.innerWidth / window.innerHeight) * 10_000)) {
                return Reflect.apply(target, thisArg, args);
            }
            if (transform.a >= window.innerWidth && transform.d >= window.innerHeight) {
                return Reflect.apply(target, thisArg, args);
            }
            this.#viewportDim = new Vector(transform.a, transform.d);
            this.#viewportPos = new Vector(transform.e, transform.f);
            if (this.#drawViewport)
                return Reflect.apply(target, thisArg, args);
        });
    }
    _arrowHook() {
        let index = 0;
        let pointA;
        let pointB;
        let pointC;
        const calculatePos = () => {
            const side1 = Math.round(Vector.distance(pointA, pointB));
            const side2 = Math.round(Vector.distance(pointA, pointC));
            const side3 = Math.round(Vector.distance(pointB, pointC));
            if (side1 === side2 && side2 === side3)
                return;
            const centroid = Vector.centroid(pointA, pointB, pointC);
            const arrowPos = Vector.subtract(centroid, this.#minimapPos);
            const position = Vector.divide(arrowPos, this.#minimapDim);
            this.#arrowPos = position;
        };
        CanvasKit.hook('beginPath', (target, thisArg, args) => {
            index = 1;
        });
        CanvasKit.hook('moveTo', (target, thisArg, args) => {
            if (index === 1) {
                index++;
                pointA = new Vector(args[0], args[1]);
                return;
            }
            index = 0;
        });
        CanvasKit.hook('lineTo', (target, thisArg, args) => {
            if (index === 2) {
                index++;
                pointB = new Vector(args[0], args[1]);
                return;
            }
            if (index === 3) {
                index++;
                pointC = new Vector(args[0], args[1]);
                return;
            }
            index = 0;
        });
        CanvasKit.hook('fill', (target, thisArg, args) => {
            if (index === 4) {
                index++;
                calculatePos();
                return;
            }
            index = 0;
        });
    }
}
const minimap = new Minimap();

;// CONCATENATED MODULE: ./src/camera.ts



class Camera {
    get position() {
        const center = Vector.add(minimap.viewportPos, Vector.scale(0.5, minimap.viewportDim));
        const cameraPos = Vector.subtract(center, minimap.minimapPos);
        const normalized = Vector.divide(cameraPos, minimap.minimapDim);
        return arena.scale(normalized);
    }
}
const camera = new Camera();

;// CONCATENATED MODULE: ./src/arena_scaling.ts



class ArenaScaling {
    #scalingFactor = 1;
    constructor() {
        CanvasKit.hook('stroke', (target, thisArg, args) => {
            if (thisArg.fillStyle === '#cdcdcd' && thisArg.globalAlpha !== 0) {
                this.#scalingFactor = thisArg.globalAlpha * 10;
            }
        });
    }
    get scalingFactor() {
        return this.#scalingFactor;
    }
    get windowRatio() {
        return Math.max(window.innerWidth / 1920, window.innerHeight / 1080);
    }
    get fov() {
        return this.#scalingFactor / this.windowRatio;
    }
    /**
     *
     * @param {Vector} v The vector in canvas units
     * @returns {Vector} The vector in arena units
     */
    toArenaUnits(v) {
        return Vector.scale(1 / this.#scalingFactor, v);
    }
    /**
     *
     * @param {Vector} v The vector in arena units
     * @returns {Vector} The vector in canvas units
     */
    toCanvasUnits(v) {
        return Vector.scale(this.#scalingFactor, v);
    }
    /**
     * Will translate coordinates from canvas to arena
     * @param {Vector} canvasPos The canvas coordinates
     * @returns {Vector} The `canvasPos` translated to arena coordinates
     */
    toArenaPos(canvasPos) {
        const direction = Vector.subtract(canvasPos, this.screenToCanvas(new Vector(window.innerWidth / 2, window.innerHeight / 2)));
        const scaled = this.toArenaUnits(direction);
        const arenaPos = Vector.add(scaled, camera.position);
        return arenaPos;
    }
    /**
     * Will translate coordinates from arena to canvas
     * @param {Vector} arenaPos The arena coordinates
     * @returns {Vector} The `arenaPos` translated to canvas coordinates
     */
    toCanvasPos(arenaPos) {
        const direction = Vector.subtract(arenaPos, camera.position);
        const scaled = this.toCanvasUnits(direction);
        const canvasPos = Vector.add(scaled, this.screenToCanvas(new Vector(window.innerWidth / 2, window.innerHeight / 2)));
        return canvasPos;
    }
    screenToCanvasUnits(n) {
        return n * window.devicePixelRatio;
    }
    canvasToScreenUnits(n) {
        return n / window.devicePixelRatio;
    }
    /**
     * Will translate coordinates from screen to canvas
     * @param v The screen coordinates
     * @returns The canvas coordinates
     */
    screenToCanvas(v) {
        return Vector.scale(window.devicePixelRatio, v);
    }
    /**
     * Will translate coordinates from canvas to screen
     * @param v The canvas coordinates
     * @returns the screen coordinates
     */
    canvasToScreen(v) {
        return Vector.scale(1 / window.devicePixelRatio, v);
    }
}
const arenaScaling = new ArenaScaling();

;// CONCATENATED MODULE: ./src/arena.ts




class Arena {
    #size = 1;
    constructor() {
        game.on('frame', () => {
            const ratio = Vector.divide(minimap.minimapDim, minimap.viewportDim);
            const arenaDim = Vector.multiply(ratio, arenaScaling.screenToCanvas(new Vector(window.innerWidth, window.innerHeight)));
            const arenaSize = Vector.round(arenaScaling.toArenaUnits(arenaDim));
            this.#size = arenaSize.x;
        });
    }
    /**
     * @returns {number} The Arena size in arena units
     */
    get size() {
        return this.#size;
    }
    //These methods are not much used. can be moved to playerMovement.mjs where its currently only used.
    /**
     *
     * @param {Vector} vector The vector in [0, 1] coordinates
     * @returns {Vector} The scaled vector in [-Arena.size/2, Arena.size/2] coordinates
     */
    scale(vector) {
        const scale = (value) => Math.round(this.#size * (value - 0.5));
        return new Vector(scale(vector.x), scale(vector.y));
    }
    /**
     *
     * @param {Vector} vector - The scaled vector in [-Arena.size/2, Arena.size/2] coordinates
     * @returns {Vector} The unscaled vector in [0, 1] coordinates
     */
    unscale(vector) {
        const unscale = (value) => value / this.#size + 0.5;
        return new Vector(unscale(vector.x), unscale(vector.y));
    }
}
const arena = new Arena();

;// CONCATENATED MODULE: ./src/movement.ts

class Movement {
    #position = new Vector(0, 0);
    #velocity = new Vector(0, 0);
    /*
     * used for average velocity calculation
     */
    #velocitySamplesSize = 10;
    #velocitySamples = [];
    #velocitySamplesIndex = 0;
    #velocityLastNow = performance.now();
    get position() {
        return this.#position;
    }
    /**
     * Velocity in [diep_]units / second
     */
    get velocity() {
        return this.#velocity;
    }
    /**
     * Predict where this object will be after `time`
     * @param time The time in ms.
     */
    predictPos(time) {
        const duration = (time + performance.now() - this.#velocityLastNow) / 1000;
        return Vector.add(this.#position, Vector.scale(duration, this.#velocity));
    }
    updatePos(newPos) {
        this.#updateVelocity(newPos);
        this.#position = newPos;
    }
    #updateVelocity(newPos) {
        const now = performance.now();
        const time = (now - this.#velocityLastNow) / 1000;
        if (time === 0)
            return;
        this.#velocityLastNow = now;
        const velocity = Vector.scale(1 / time, Vector.subtract(newPos, this.#position));
        // add current velocity to our samples array
        this.#velocitySamples[this.#velocitySamplesIndex++] = velocity;
        this.#velocitySamplesIndex %= this.#velocitySamplesSize;
        // calculate the average velocity
        this.#velocity = Vector.scale(1 / this.#velocitySamples.length, this.#velocitySamples.reduce((acc, x) => Vector.add(acc, x)));
    }
}

;// CONCATENATED MODULE: ./src/player_movement.ts




class PlayerMovement extends Movement {
    /**
     * Using the minimap arrow to get the player position and velocity
     */
    constructor() {
        super();
        game.on('frame', () => super.updatePos(arena.scale(minimap.arrowPos)));
    }
}
const playerMovement = new PlayerMovement();

;// CONCATENATED MODULE: ./src/player.ts







const sleep = (ms) => new Promise((resolve, reject) => setTimeout(resolve, ms));
class Player extends EventEmitter {
    #isDead = true;
    #mouseLock = false;
    #mouseCanvasPos = new Vector(0, 0);
    #mousePos = new Vector(0, 0);
    #gamemode = window.localStorage.gamemode;
    #level = 1;
    #tank = 'Tank';
    constructor() {
        super();
        game.once('ready', () => {
            //Check dead or alive
            game.on('frame', () => {
                const isDead = !window.input.should_prevent_unload();
                if (this.#isDead == isDead)
                    return;
                this.#isDead = isDead;
                if (this.#isDead)
                    this.#ondead();
                else
                    this.#onspawn();
            });
            //update mouse position
            game.on('frame', () => {
                this.#mousePos = arenaScaling.toArenaPos(this.#mouseCanvasPos);
            });
            //Mouse events
            const canvas = document.getElementById('canvas');
            canvas.onmousemove = new Proxy(canvas.onmousemove, {
                apply: (target, thisArg, args) => {
                    if (this.#mouseLock)
                        return;
                    this.#onmousemove(args[0]);
                    return Reflect.apply(target, thisArg, args);
                },
            });
            canvas.onmousedown = new Proxy(canvas.onmousedown, {
                apply: (target, thisArg, args) => {
                    if (this.#mouseLock)
                        return;
                    this.#onmousedown(args[0]);
                    return Reflect.apply(target, thisArg, args);
                },
            });
            canvas.onmouseup = new Proxy(canvas.onmouseup, {
                apply: (target, thisArg, args) => {
                    if (this.#mouseLock)
                        return;
                    this.#onmouseup(args[0]);
                    return Reflect.apply(target, thisArg, args);
                },
            });
            //Key events
            window.onkeydown = new Proxy(window.onkeydown, {
                apply: (target, thisArg, args) => {
                    this.#onkeydown(args[0]);
                    return Reflect.apply(target, thisArg, args);
                },
            });
            window.onkeyup = new Proxy(window.onkeyup, {
                apply: (target, thisArg, args) => {
                    this.#onkeyup(args[0]);
                    return Reflect.apply(target, thisArg, args);
                },
            });
            // tank and level event listener
            CanvasKit.hook('fillText', (target, thisArg, args) => {
                const text = args[0];
                const match = text.match(/^Lvl (\d+) (\w*)$/);
                if (match == null) {
                    return;
                }
                const newLevel = Number(match[1]);
                const newTank = match[2];
                // make sure to trigger events for all levels in between.
                while (newLevel > this.#level + 1) {
                    super.emit('level', ++this.#level);
                }
                if (newLevel !== this.#level)
                    super.emit('level', newLevel);
                if (newTank !== this.#tank)
                    super.emit('tank', newTank);
                this.#level = newLevel;
                this.#tank = match[2];
            });
        });
    }
    get position() {
        return playerMovement.position;
    }
    get velocity() {
        return playerMovement.velocity;
    }
    get mouse() {
        return this.#mousePos;
    }
    get isDead() {
        return this.#isDead;
    }
    get gamemode() {
        return this.#gamemode;
    }
    get level() {
        return this.#level;
    }
    get tank() {
        return this.#tank;
    }
    /**
     * Predict where this object will be after `time`
     * @param time The time in ms
     */
    predictPos(time) {
        return playerMovement.predictPos(time);
    }
    /**
     * Fun function to upgrade to octo
     * @async
     */
    async octoBuild() {
        this.keyDown('k');
        await this.upgrade_stat(4, 7);
        await this.upgrade_stat(5, 7);
        await this.upgrade_stat(6, 7);
        await this.upgrade_stat(7, 7);
        await this.upgrade_stat(8, 5);
        await this.upgrade_tank(1);
        await this.upgrade_tank(2);
        await this.upgrade_tank(1);
        this.keyUp('k');
    }
    async #ondead() {
        await sleep(50);
        super.emit('dead');
    }
    async #onspawn() {
        this.#gamemode = window.localStorage.gamemode;
        await sleep(50);
        super.emit('spawn');
    }
    useGamepad(value) {
        gamepad.connected = value;
    }
    keyDown(key) {
        if (typeof key == 'string') {
            if (key.length != 1)
                throw new Error(`diepAPI: Unsupported key: ${key}`);
            key = key.toUpperCase().charCodeAt(0);
        }
        window.input.keyDown(key);
        this.#onkeydown({ keyCode: key });
    }
    keyUp(key) {
        if (typeof key == 'string') {
            if (key.length != 1)
                throw new Error(`diepAPI: Unsupported key: ${key}`);
            key = key.toUpperCase().charCodeAt(0);
        }
        window.input.keyUp(key);
        this.#onkeyup({ keyCode: key });
    }
    async keyPress(key) {
        this.keyDown(key);
        await sleep(200);
        this.keyUp(key);
        await sleep(10);
    }
    async spawn(name, attempts = 0) {
        if (!this.#isDead)
            return;
        if (name !== undefined)
            document.getElementById('textInput').value = name;
        await this.keyPress(13);
        await sleep(250);
        await this.spawn(name, attempts + 1);
    }
    async upgrade_stat(id, level) {
        if (id < 1 || id > 8)
            throw `diepAPI: ${id} is not a supported stat`;
        this.keyDown(85);
        for (let i = 0; i < level; i++) {
            await this.keyPress(48 + id);
        }
        this.keyUp(85);
        await sleep(250);
    }
    async upgrade_tank(index) {
        index -= 1;
        const x_index = index % 2;
        const y_index = Math.floor(index / 2);
        const x = arenaScaling.screenToCanvasUnits(arenaScaling.windowRatio * (x_index * 115 + 97.5));
        const y = arenaScaling.screenToCanvasUnits(arenaScaling.windowRatio * (y_index * 110 + 120));
        this.#mouseLock = true;
        window.input.mouse(x, y);
        await this.keyPress(1);
        // wait 200 ms before disabling mouselock
        await sleep(200);
        this.#mouseLock = false;
        // wait 1500 ms for the animation to finish
        await sleep(1500);
    }
    moveTo(arenaPos) {
        if (gamepad.connected) {
            const direction = Vector.subtract(arenaPos, this.position);
            const distance = Vector.len(direction);
            if (distance === 0) {
                gamepad.x = 0;
                gamepad.y = 0;
                return;
            }
            //max speed
            const velocity = Vector.scale(1 / distance, direction);
            gamepad.x = velocity.x;
            gamepad.y = velocity.y;
        }
        else {
            const direction = Vector.subtract(arenaPos, this.position);
            if (direction.x > 0) {
                this.keyUp('a');
                this.keyDown('d');
            }
            else if (direction.x < 0) {
                this.keyUp('d');
                this.keyDown('a');
            }
            else {
                this.keyUp('a');
                this.keyUp('d');
            }
            if (direction.y > 0) {
                this.keyUp('w');
                this.keyDown('s');
            }
            else if (direction.y < 0) {
                this.keyUp('s');
                this.keyDown('w');
            }
            else {
                this.keyUp('w');
                this.keyUp('s');
            }
        }
    }
    lookAt(arenaPos) {
        const position = arenaScaling.toCanvasPos(arenaPos);
        window.input.mouse(position.x, position.y);
        this.#onmousemove({ clientX: position.x, clientY: position.y });
    }
    #onmousemove(e) {
        this.#mouseCanvasPos = arenaScaling.screenToCanvas(new Vector(e.clientX, e.clientY));
        if (gamepad.connected) {
            const arenaPos = arenaScaling.toArenaPos(this.#mouseCanvasPos);
            const direction = Vector.subtract(arenaPos, this.position);
            let axes = Vector.scale(arenaScaling.fov / 1200 / 1.1, direction);
            const length = Vector.len(axes);
            if (length !== 0 && length < 0.15) {
                axes = Vector.scale(0.15 / length, axes);
            }
            gamepad.mx = axes.x;
            gamepad.my = axes.y;
        }
    }
    #onmousedown(e) {
        if (gamepad.connected)
            this.#onkeydown({ keyCode: e.which });
    }
    #onmouseup(e) {
        if (gamepad.connected)
            this.#onkeyup({ keyCode: e.which });
    }
    #onkeydown(e) {
        super.emit('keydown', e.keyCode);
        if (gamepad.connected) {
            switch (e.keyCode) {
                case 37:
                case 65:
                    gamepad.x = -1;
                    break;
                case 40:
                case 83:
                    gamepad.y = 1;
                    break;
                case 38:
                case 87:
                    gamepad.y = -1;
                    break;
                case 39:
                case 68:
                    gamepad.x = 1;
                    break;
                case 1:
                case 32:
                    gamepad.leftMouse = true;
                    break;
                case 3:
                case 16:
                    gamepad.rightMouse = true;
                    break;
            }
        }
    }
    #onkeyup(e) {
        super.emit('keyup', e.keyCode);
        if (gamepad.connected) {
            switch (e.keyCode) {
                case 37:
                case 65:
                    gamepad.x = 0;
                    break;
                case 40:
                case 83:
                    gamepad.y = 0;
                    break;
                case 38:
                case 87:
                    gamepad.y = 0;
                    break;
                case 39:
                case 68:
                    gamepad.x = 0;
                    break;
                case 1:
                case 32:
                    gamepad.leftMouse = false;
                    break;
                case 3:
                case 16:
                    gamepad.rightMouse = false;
                    break;
            }
        }
    }
}
const player = new Player();

;// CONCATENATED MODULE: ./src/entity.ts

var EntityType;
(function (EntityType) {
    EntityType[EntityType["Player"] = 0] = "Player";
    EntityType[EntityType["Bullet"] = 1] = "Bullet";
    EntityType[EntityType["Drone"] = 2] = "Drone";
    EntityType[EntityType["Trap"] = 3] = "Trap";
    EntityType[EntityType["Square"] = 4] = "Square";
    EntityType[EntityType["Triangle"] = 5] = "Triangle";
    EntityType[EntityType["Pentagon"] = 6] = "Pentagon";
    EntityType[EntityType["AlphaPentagon"] = 7] = "AlphaPentagon";
    EntityType[EntityType["Crasher"] = 8] = "Crasher";
    EntityType[EntityType["UNKNOWN"] = 9] = "UNKNOWN";
})(EntityType || (EntityType = {}));
var EntityColor;
(function (EntityColor) {
    EntityColor["TeamBlue"] = "#00b2e1";
    EntityColor["TeamRed"] = "#f14e54";
    EntityColor["TeamPurple"] = "#bf7ff5";
    EntityColor["TeamGreen"] = "#00e16e";
    EntityColor["Square"] = "#ffe869";
    EntityColor["Triangle"] = "#fc7677";
    EntityColor["Pentagon"] = "#768dfc";
    EntityColor["AlphaPentagon"] = "#768dfc";
    EntityColor["Crasher"] = "#f177dd";
    EntityColor["NecromancerDrone"] = "#fcc376";
})(EntityColor || (EntityColor = {}));
const TeamColors = [EntityColor.TeamBlue, EntityColor.TeamRed, EntityColor.TeamPurple, EntityColor.TeamGreen];
/**
 * Represents an ingame Entity.
 *
 * Holds minimal information currently.
 */
class Entity extends Movement {
    type;
    extras;
    constructor(type, extras = {}) {
        super();
        this.type = type;
        this.extras = extras;
    }
    updatePos(newPos) {
        super.updatePos(newPos);
    }
}

;// CONCATENATED MODULE: ./src/entity_manager.ts





/**
 * Entity Manager is used to access the information about the entities, that are currently drawn on the screen.
 * To access the entities the EntityManager exposes the EntityManager.entities field.
 */
class EntityManager {
    #entities = [];
    #entitiesUpdated = [];
    constructor() {
        this.#triangleHook();
        this.#squareHook();
        this.#pentagonHook();
        //when is a bullet being drawn?
        //when is a player being drawn?
        this.#playerHook();
        game.on('frame', () => {
            this.#entities = this.#entitiesUpdated;
            this.#entitiesUpdated = [];
        });
    }
    get entities() {
        return this.#entities;
    }
    /**
     * Adds the entity to `#entitiesUpdated`.
     *
     * Will either find the entity in `#entities` or create a new `Entity`.
     */
    #add(type, position, extras = {}) {
        const entityIndex = this.#findEntity(type, position);
        let entity;
        if (entityIndex === -1) {
            entity = new Entity(type, {
                id: Math.random().toString(36).slice(2, 5),
                timestamp: performance.now(),
                ...extras,
            });
        }
        else {
            entity = this.#entities[entityIndex];
        }
        entity.updatePos(position);
        this.#entitiesUpdated.push(entity);
    }
    /**
     * Searches `#entities` for the entity that is closest to `position` and
     * returns the __index__ of that entity or __-1__ if there is no match.
     */
    #findEntity(type, position) {
        let result = -1;
        let shortestDistance = Number.MAX_SAFE_INTEGER;
        this.#entities.forEach((x, i) => {
            const distance = Vector.distance(x.predictPos(0), position);
            if (distance < shortestDistance) {
                shortestDistance = distance;
                result = i;
            }
        });
        //if distance is too high
        if (shortestDistance > 28 /* accuracy */) {
            return -1;
        }
        //sanity check
        if (EntityType.UNKNOWN !== type && this.#entities[result].type !== type) {
            return -1;
        }
        return result;
    }
    /**
     * Will call the cb method, when a polygon with `numVertices` vertices is drawn.
     */
    #createPolygonHook(numVertices, cb) {
        let index = 0;
        let vertices = [];
        const onFillPolygon = (ctx) => {
            cb(vertices, ctx);
        };
        CanvasKit.hook('beginPath', (target, thisArg, args) => {
            index = 1;
            vertices = [];
        });
        CanvasKit.hook('moveTo', (target, thisArg, args) => {
            if (index === 1) {
                index++;
                vertices.push(new Vector(args[0], args[1]));
                return;
            }
            index = 0;
        });
        CanvasKit.hook('lineTo', (target, thisArg, args) => {
            if (index >= 2 && index <= numVertices) {
                index++;
                vertices.push(new Vector(args[0], args[1]));
                return;
            }
            index = 0;
        });
        CanvasKit.hook('fill', (target, thisArg, args) => {
            if (index === numVertices + 1) {
                index++;
                onFillPolygon(thisArg);
                return;
            }
            index = 0;
        });
    }
    #triangleHook() {
        this.#createPolygonHook(3, (vertices, ctx) => {
            const side1 = Math.round(Vector.distance(vertices[0], vertices[1]));
            const side2 = Math.round(Vector.distance(vertices[0], vertices[2]));
            const side3 = Math.round(Vector.distance(vertices[1], vertices[2]));
            //ignore Minimap Arrow
            if (side1 !== side2 || side2 !== side3)
                return;
            //ignore Leader Arrow
            if ('#000000' === ctx.fillStyle)
                return;
            vertices = vertices.map((x) => arenaScaling.toArenaPos(x));
            const position = Vector.centroid(...vertices);
            const radius = Math.round(Vector.radius(...vertices));
            const color = ctx.fillStyle;
            let type;
            switch (radius) {
                case 23:
                    //battleship drone
                    if (TeamColors.includes(color))
                        type = EntityType.Drone;
                    break;
                case 30:
                    //base drone
                    if (TeamColors.includes(color))
                        type = EntityType.Drone;
                    break;
                case 35:
                    //small crasher
                    if (EntityColor.Crasher === color)
                        type = EntityType.Crasher;
                    break;
                case 40:
                case 41:
                case 42:
                case 43:
                case 44:
                case 45:
                case 46:
                    //overseer/overlord drone
                    if (TeamColors.includes(color))
                        type = EntityType.Drone;
                    break;
                case 55:
                    //big crasher
                    if (EntityColor.Crasher === color)
                        type = EntityType.Crasher;
                    //triangle
                    if (EntityColor.Triangle === color)
                        type = EntityType.Triangle;
                    break;
            }
            if (type === undefined)
                type = EntityType.UNKNOWN;
            this.#add(type, position, { color, radius });
        });
    }
    #squareHook() {
        this.#createPolygonHook(4, (vertices, ctx) => {
            vertices = vertices.map((x) => arenaScaling.toArenaPos(x));
            const position = Vector.centroid(...vertices);
            const radius = Math.round(Vector.radius(...vertices));
            const color = ctx.fillStyle;
            let type;
            switch (radius) {
                case 55:
                    //square
                    if (EntityColor.Square === color)
                        type = EntityType.Square;
                    //necromancer drone
                    if (TeamColors.includes(color) || EntityColor.NecromancerDrone === color)
                        type = EntityType.Drone;
                    break;
            }
            if (type === undefined)
                type = EntityType.UNKNOWN;
            this.#add(type, position, { color, radius });
        });
    }
    #pentagonHook() {
        this.#createPolygonHook(5, (vertices, ctx) => {
            vertices = vertices.map((x) => arenaScaling.toArenaPos(x));
            const position = Vector.centroid(...vertices);
            const radius = Math.round(Vector.radius(...vertices));
            const color = ctx.fillStyle;
            let type;
            switch (radius) {
                case 75:
                    if (EntityColor.Pentagon === color)
                        type = EntityType.Pentagon;
                    break;
                case 200:
                    if (EntityColor.AlphaPentagon === color)
                        type = EntityType.AlphaPentagon;
                    break;
            }
            if (type === undefined)
                type = EntityType.UNKNOWN;
            this.#add(type, position, { color, radius });
        });
    }
    #playerHook() {
        let index = 0;
        let position;
        let color;
        let radius;
        const onCircle = () => {
            position = arenaScaling.toArenaPos(position);
            radius = arenaScaling.toArenaUnits(new Vector(radius, radius)).x;
            let type = EntityType.UNKNOWN;
            if (radius > 53) {
                type = EntityType.Player;
            }
            else {
                type = EntityType.Bullet;
            }
            this.#add(type, position, {
                color,
                radius,
            });
        };
        //Sequence: beginPath -> arc -> fill -> beginPath -> arc -> fill -> arc
        CanvasKit.hook('beginPath', (target, thisArg, args) => {
            //start
            if (index !== 3) {
                index = 1;
                return;
            }
            if (index === 3) {
                index++;
                return;
            }
            index = 0;
        });
        //check when a circle is drawn.
        CanvasKit.hook('arc', (target, thisArg, args) => {
            //outline
            if (index === 1) {
                index++;
                const transform = thisArg.getTransform();
                position = new Vector(transform.e, transform.f);
                radius = transform.a;
                return;
            }
            if (index === 4) {
                index++;
                color = thisArg.fillStyle;
                return;
            }
            //last arc call
            if (index === 6) {
                index++;
                onCircle();
                return;
            }
            index = 0;
        });
        CanvasKit.hook('fill', (target, thisArg, args) => {
            if (index === 2) {
                index++;
                return;
            }
            if (index === 5) {
                index++;
                return;
            }
            index = 0;
        });
    }
}
const entityManager = new EntityManager();

;// CONCATENATED MODULE: ./src/index.ts










diepAPI = __webpack_exports__;
/******/ })()
;