var _a;
import * as mc from "@minecraft/server";
import * as utils from "../../utils/index";
export class OreGeneration {
    static enable() {
        utils.mclog("Enabling ore generation...", "ores");
        this.active = true;
        this.loop();
    }
    static disable() {
        utils.mclog("Disabling ore generation...", "ores");
        this.active = false;
    }
    static async loop() {
        while (this.active) {
            const promises = [];
            for (const player of utils.getAllPlayersSafe().filter(p => p.dimension === utils.overworld)) {
                const chunkCenter = player.location.divide(16).floor().multiply(16).add(8);
                chunkCenter.y = utils.overworld.heightRange.min;
                const block = utils.overworld.getBlock(chunkCenter);
                if ((block === null || block === void 0 ? void 0 : block.typeId) !== "minecraft:bedrock") {
                    utils.mclog(`Chunk ${chunkCenter.x}, ${chunkCenter.z} already generated`, "ores", "verbose");
                    continue;
                }
                ;
                block.setType("ldz:fake_bedrock");
                chunkCenter.y = utils.overworld.heightRange.max;
                promises.push(this.generateOres(chunkCenter, 8));
            }
            try {
                if (promises.length)
                    await Promise.all(promises);
            }
            catch (error) {
                utils.mcerror(error, "ores");
            }
            await utils.waitForTicks(200);
        }
    }
    static generateOres(chunkCenter, variance) {
        utils.mclog(`Generating ores for chunk ${chunkCenter.x}, ${chunkCenter.z}...`, "ores");
        const maxDistance = utils.overworld.heightRange.max - utils.overworld.heightRange.min;
        const includeTypes = ["minecraft:stone", "minecraft:deepslate"];
        // Random offset from chunk center
        const originalLocation = new utils.Vector3(chunkCenter);
        chunkCenter.x += utils.getRandomInteger(-variance, variance);
        chunkCenter.z += utils.getRandomInteger(-variance, variance);
        return new Promise((resolve, reject) => {
            function* iterate() {
                var _b, _c;
                const validBlocks = [];
                let block = utils.overworld.getBlock(chunkCenter);
                while (block && block.location.y > utils.overworld.heightRange.min) {
                    yield;
                    block = (_b = utils.overworld.getBlockFromRay(new utils.Vector3(block.location).down(), utils.Vector3.DOWN, { maxDistance, includeTypes })) === null || _b === void 0 ? void 0 : _b.block;
                    if (((_c = block === null || block === void 0 ? void 0 : block.above()) === null || _c === void 0 ? void 0 : _c.isAir) && !blocksMatch(block, utils.overworld.getTopmostBlock(block.location))) {
                        validBlocks.push(block);
                    }
                }
                if (validBlocks.length === 0) {
                    utils.mclog(`No valid blocks found for chunk ${originalLocation.x}, ${originalLocation.z}`, "ores");
                    return;
                }
                else {
                    utils.mclog(`Found ${validBlocks.length} valid blocks for chunk ${originalLocation.x}, ${originalLocation.z}`, "ores");
                    for (const block of validBlocks) {
                        const location = new utils.Vector3(block.location);
                        switch (block.typeId) {
                            case "minecraft:stone":
                                utils.mclog(`Placing heart_ore_stone structure in chunk ${originalLocation.x}, ${originalLocation.z} at ${location}`, "ores");
                                mc.world.structureManager.place("heart_ore_stone", utils.overworld, location, {
                                    integrity: utils.getRandomInteger(1, 75) / 100,
                                });
                                break;
                            case "minecraft:deepslate":
                                utils.mclog(`Placing heart_ore_deepslate structure in chunk ${originalLocation.x}, ${originalLocation.z} at ${location}`, "ores");
                                mc.world.structureManager.place("heart_ore_deepslate", utils.overworld, location, {
                                    integrity: utils.getRandomInteger(1, 75) / 100,
                                });
                            default:
                                break;
                        }
                    }
                }
                resolve();
            }
            const jobId = mc.system.runJob(iterate());
            mc.system.runTimeout(() => {
                reject(new Error(`Timeout after 100 ticks in chunk ${originalLocation.x}, ${originalLocation.z}`));
                mc.system.clearRun(jobId);
            }, 100);
        });
    }
}
_a = OreGeneration;
OreGeneration.active = false;
(() => {
    utils.afterEvents.scriptEventRecieve.subscribe("ldz:ore", event => {
        if (event.sourceEntity) {
            const location = event.sourceEntity.location;
            location.y = utils.overworld.heightRange.max;
            _a.generateOres(location, 0);
        }
    });
    utils.afterEvents.scriptEventRecieve.subscribe("ldz:ore_check", event => {
        var _b;
        const player = (_b = event.sourceEntity) === null || _b === void 0 ? void 0 : _b.getPlayer();
        if (player) {
            const chunkCenter = player.location.divide(16).floor().multiply(16).add(8);
            chunkCenter.y = utils.overworld.heightRange.min;
            const block = utils.overworld.getBlock(chunkCenter);
            if ((block === null || block === void 0 ? void 0 : block.typeId) === "minecraft:bedrock") {
                player.sendMessage(`Ores at ${utils.TextFormat.aqua(`${chunkCenter.x} ${chunkCenter.z}`)} ${utils.TextFormat.red("have not")} been generated`);
            }
            else {
                player.sendMessage(`Ores at ${utils.TextFormat.aqua(`${chunkCenter.x} ${chunkCenter.z}`)} ${utils.TextFormat.green("have")} been generated`);
            }
        }
    });
})();
function blocksMatch(block1, block2) {
    if (!block1 || !block2)
        return false;
    const diff = new utils.Vector3(block1.location).approximatelyEqual(block2.location);
    return diff;
}
