File size: 6,916 Bytes
8524bea
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
(function TreeChopperMod() {
    ModAPI.meta.title("Vein Miner");
    ModAPI.meta.description("Vein-mines trees & ores while crouching. Press the 'config' button for settings.");
    ModAPI.meta.credits("By ZXMushroom63");
    ModAPI.meta.version("v1.0");
    globalThis.VEINMINERCONF = {
        doLogs: true,
        doOres: true,
        doGravel: false,
        doClay: false,
    };
    try {
        Object.assign(conf, JSON.parse(localStorage.getItem("trc_mod::conf") || "{}"));
    } catch (error) {
        //swallow
    }
    ModAPI.meta.config(() => {
        var conf = document.createElement("div");
        conf.innerHTML = `
        <h1>Vein Miner Settings&nbsp;<a href="javascript:void(0)" onclick="this.parentElement.parentElement.remove()" style="color:red">[X]</a></h1>
        <sub>Refresh page to apply settings</sub><br>
        <label>Veinmine Logs: </label><input type=checkbox ${VEINMINERCONF.doLogs ? "checked" : ""} oninput="VEINMINERCONF.doLogs = this.checked; this.parentElement.__save();"></input><br>
        <label>Veinmine Ores: </label><input type=checkbox ${VEINMINERCONF.doOres ? "checked" : ""} oninput="VEINMINERCONF.doOres = this.checked; this.parentElement.__save();"></input><br>
        <label>Veinmine Gravel: </label><input type=checkbox ${VEINMINERCONF.doGravel ? "checked" : ""} oninput="VEINMINERCONF.doGravel = this.checked; this.parentElement.__save();"></input><br>
        <label>Veinmine Clay: </label><input type=checkbox ${VEINMINERCONF.doClay ? "checked" : ""} oninput="VEINMINERCONF.doClay = this.checked; this.parentElement.__save();"></input><br>
        `;
        conf.style = "position: fixed; background-color: white; color: black; width: 100vw; height: 100vh; z-index: 256;top:0;left:0;";
        conf.__save = () => localStorage.setItem("trc_mod::conf", JSON.stringify(VEINMINERCONF));
        document.body.appendChild(conf);
    });

    ModAPI.dedicatedServer.appendCode(`globalThis.VEINMINERCONF = ${JSON.stringify(VEINMINERCONF)};`);

    ModAPI.dedicatedServer.appendCode(function () {
        ModAPI.addEventListener("bootstrap", () => {
            const axes = [ModAPI.items.iron_axe, ModAPI.items.stone_axe, ModAPI.items.golden_axe, ModAPI.items.wooden_axe, ModAPI.items.diamond_axe].map(x => x.getRef());
            const logs = ["log", "log2"].map(x => ModAPI.blocks[x].getRef());
            const targettedBlockIds = [];
            if (VEINMINERCONF.doLogs) {
                targettedBlockIds.push("log", "log2");
            }
            if (VEINMINERCONF.doOres) {
                targettedBlockIds.push("coal_ore", "gold_ore", "iron_ore", "lapis_ore", "quartz_ore", "diamond_ore", "emerald_ore", "redstone_ore", "lit_redstone_ore");
            }
            if (VEINMINERCONF.doGravel) {
                targettedBlockIds.push("gravel");
            }
            if (VEINMINERCONF.doClay) {
                targettedBlockIds.push("clay");
            }
            console.log(targettedBlockIds);
            const valid_log_blocks = targettedBlockIds.map(x => ModAPI.blocks[x].getRef());

            function stringifyBlockPos(blockPos) {
                return blockPos.x + "," + blockPos.y + "," + blockPos.z;
            }
            function getNeighbors(blockPos) {
                return [
                    //direct neighbors
                    blockPos.down(1),
                    blockPos.up(1),
                    blockPos.north(1),
                    blockPos.south(1),
                    blockPos.east(1),
                    blockPos.west(1),

                    //edges
                    blockPos.down(1).north(1),
                    blockPos.down(1).south(1),
                    blockPos.down(1).east(1),
                    blockPos.down(1).west(1),
                    blockPos.up(1).north(1),
                    blockPos.up(1).south(1),
                    blockPos.up(1).east(1),
                    blockPos.up(1).west(1),
                    blockPos.north(1).east(1),
                    blockPos.north(1).west(1),
                    blockPos.south(1).east(1),
                    blockPos.south(1).west(1),

                    //corners
                    blockPos.down(1).north(1).east(1),
                    blockPos.down(1).north(1).west(1),
                    blockPos.down(1).south(1).east(1),
                    blockPos.down(1).south(1).west(1),
                    blockPos.up(1).north(1).east(1),
                    blockPos.up(1).north(1).west(1),
                    blockPos.up(1).south(1).east(1),
                    blockPos.up(1).south(1).west(1),
                ];
            }
            async function getBlockGraph(blockPos, getBlockState, targetType) {
                const closed = [stringifyBlockPos(blockPos)];
                const logs = [];
                const open = [...getNeighbors(blockPos)];
                const maxIters = 120;
                var i = 0;
                while (open.length > 0 && i < maxIters) {
                    const target = open.pop();

                    closed.push(stringifyBlockPos(target));

                    i++;
                    const iBlockState = await getBlockState(target.getRef());
                    if (iBlockState.block.getRef() === targetType) {
                        logs.push(target);
                        open.push(...getNeighbors(target).filter(x => !closed.includes(stringifyBlockPos(x))));
                    }
                }
                return logs;
            }

            valid_log_blocks.forEach(b => {
                const originalHarvest = b.$harvestBlock;
                b.$harvestBlock = function ($theWorld, $player, $blockpos, $blockstate, $tileentity, ...args) {
                    const blockState = ModAPI.util.wrap($blockstate);
                    const player = ModAPI.util.wrap($player);
                    if (player.isSneaking() && !ModAPI.util.isCritical() && !(logs.includes(blockState.block.getRef()) && !axes.includes(player.inventory.mainInventory[player.inventory.currentItem]?.getCorrective()?.item?.getRef()))) {
                        ModAPI.promisify(async () => {
                            var world = ModAPI.util.wrap($theWorld);
                            var harvestCall = ModAPI.promisify(ModAPI.is_1_12 ? player.interactionManager.tryHarvestBlock : player.theItemInWorldManager.tryHarvestBlock);
                            const blocks = await getBlockGraph(ModAPI.util.wrap($blockpos), ModAPI.promisify(world.getBlockState), b);
                            for (let i = 0; i < blocks.length; i++) {
                                await harvestCall(blocks[i].getRef());
                            }
                        })();
                    }
                    originalHarvest.apply(this, [$theWorld, $player, $blockpos, $blockstate, $tileentity, ...args]);
                }
            });
        });
    });
})();