Ponder.registry(event => {
    event.create("tconstruct:smeltery_controller")
        .scene("smeltery", "The Tinkers' Smeltery", "kubejs:smeltery_intro", (scene, util) => {
            scene.showBasePlate();
            const /** @type{Internal.WorldInstructions} */world = scene.world;
            world.showSection([3, 1, 1], Facing.DOWN);
            world.showSection([2, 1, 2], Facing.DOWN);
            scene
                .text(
                    60,
                    "The Tinkers' Smeltery is a multiblock structure used to melt items into fluids.",
                    [3, 1.5, 1.5],
                )
                .placeNearTarget();
            scene.idle(70);
            scene
                .text(
                    80,
                    "To assemble it, start with a Smeltery Controller, and build the main structure out of Seared blocks. Corners are not required, though they can be added for aesthetics.",
                    [3.5, 1.5, 1],
                )
                .placeNearTarget()
                .attachKeyFrame();
            scene.idle(10);
            for (let x = 2; x < 5; x++) {
                for (let z = 2; z < 5; z++) {
                    world.setBlock([x, 0, z], "tconstruct:seared_bricks", true);
                    scene.idle(3);
                }
            }
            const dropSmelteryBlock = (y, coilIdx) => {
                const onReturnWall = coilIdx > 5;
                const wallIdx = coilIdx % 6;
                const x = wallIdx < 3
                    // if we're on an x-axis wall, our position is 3 +/- 1
                    ? (3 + (wallIdx - 1) * (onReturnWall ? -1 : 1))
                    // if we're on a z-axis wall, x is either 1 or 5
                    : (5 - (onReturnWall ? 4 : 0));
                const z = wallIdx < 3
                    // same idea but reversed
                    ? (1 + (onReturnWall ? 4 : 0))
                    : (3 + (wallIdx - 4) * (onReturnWall ? -1 : 1));
                world.showSection([x, y, z], Facing.DOWN);
            };
            for (let coilIdx = 1; coilIdx < 12; coilIdx++) {
                dropSmelteryBlock(1, (coilIdx + 1) % 12);
                scene.idle(3);
            }
            scene.idle(20);
            scene.text(
                60,
                "The Smeltery also requires at least one fluid storage block.",
                [2, 1.5, 1.5],
            ).placeNearTarget().attachKeyFrame();
            scene.idle(30);
            world.setBlock([2, 1, 1], "tconstruct:seared_fuel_tank", true);
            world.modifyBlock([3, 1, 1], state => state.with("in_structure", true), false);
            scene.idle(40);
            scene.text(
                60,
                "Add fuel to the tank to heat the Smeltery (Lava, or Blazing Blood).",
                [2, 1.5, 1.5],
            ).placeNearTarget().attachKeyFrame();
            scene.idle(25);
            scene.showControls(40, [2.5, 1.5, 1], "right")
                .rightClick()
                .withItem("minecraft:lava_bucket");
            scene.idle(5);
            world.modifyBlockEntityNBT([2, 1, 1], nbt => {
                nbt.tank = {
                    FluidName: "minecraft:lava",
                    Amount: 1000,
                };
            });
            scene.idle(40);
            scene.text(
                60,
                "The Smeltery can now be used to melt items. Place them into the Smeltery Controller with its GUI or with item transfer blocks, or throw them into the smeltery in-world.",
                [3, 1.5, 1.5],
            ).placeNearTarget().attachKeyFrame();
            scene.idle(20);
            let sand = world.createItemEntity(
                [1.5, 3, 3.5], [0.2, 0.2, 0], "minecraft:sand",
            );
            scene.idle(20);
            world.removeEntity(sand);
            world.setBlock([2, 1, 2], "minecraft:sand", false);
            world.modifyBlock([3, 1, 1], state => state.with("active", true), false);
            scene.idle(30);
            scene.text(
                60,
                "Items will melt over time, producing fluids that are stored within the smeltery.",
                [2.5, 2, 2.5],
            );
            scene.idle(70);
            scene.text(
                60,
                "Some recipes take longer than others, and some recipes require higher temperatures.",
                [2.5, 2, 2.5],
            );
            scene.idle(60);
            world.setBlock([2, 1, 2], "minecraft:air", false);
            world.modifyBlockEntityNBT([3, 1, 1], nbt => {
                nbt.rate = 10;
                nbt.last_fuel = {X: -1, Y: 0, Z: 0};
                nbt.multiblock = {
                    insideCheck: {X: 1, Y: 0, Z: 2},
                    min: {X: -2, Y: -1, Z: 0},
                    max: {X: 2, Y: 3, Z: 4},
                    tanks: [{X: -1, Y: 0, Z: 0}],
                };
                nbt.fuel = 0;
                nbt.temperature = 1000;
                nbt.tank = {
                    fluids: [{
                        FluidName: "tconstruct:molten_glass",
                        Amount: 1000,
                    }],
                    capacity: 38880,
                };
                nbt.inventory = {size: 36};
            });
            scene.idle(10);
            scene.text(
                60,
                "Once the items have melted, the resulting fluid will be displayed on the Smeltery Controller.",
                [3.5, 1.78125, 1],
            ).placeNearTarget().attachKeyFrame();
            scene.idle(70);
            scene.text(
                30,
                "While fluid containers like Buckets can be used to take fluid from the controller's GUI...",
                [3.5, 1.5, 1],
            ).placeNearTarget().attachKeyFrame();
            scene.idle(30);
            scene.rotateCameraY(90);
            scene.text(
                60,
                "...it's much more convenient to use a Seared Drain to extract fluid in-world.",
                [4.5, 1.5, 1],
            );
            scene.idle(20);
            world.setBlock([4, 1, 1], "tconstruct:seared_drain", true);
            world.modifyBlock([4, 1, 1], state => state.with("facing", "north").with("in_structure", true), false);
            world.modifyBlockEntityNBT([4, 1, 1], nbt => {
                nbt.masterOffset = {X: -1, Y: 0, Z: 0};
                nbt.masterBlock = "tconstruct:smeltery_controller";
            });
            scene.idle(3);
            world.setBlock([5, 0, 1], "tconstruct:seared_basin", true);
            scene.idle(3);
            world.setBlock([4, 0, 0], "tconstruct:seared_table", true);
            scene.idle(3);
            world.showSection([4, 1, 0], Facing.SOUTH);
            scene.idle(3);
            world.showSection([5, 1, 1], Facing.WEST);
            scene.showControls(28, [5.25, 1.5, 1.5], "down")
                .rightClick();
            scene.idle(8);
            world.modifyBlockEntityNBT([5, 1, 1], nbt => {
                nbt.render_fluid = {
                    FluidName: "tconstruct:molten_glass",
                    Amount: 90,
                };
                nbt.state = 1;
            });
            for (let mbTransferred = 10; mbTransferred <= 1000; mbTransferred += 10) {
                scene.idle(1);
                world.modifyBlockEntityNBT([5, 0, 1], nbt => {
                    nbt.timer = 0;
                    nbt.recipe = "tconstruct:smeltery/casting/glass/block";
                    nbt.tank = {
                        filter: "tconstruct:molten_glass",
                        fluid: {
                            FluidName: "tconstruct:molten_glass",
                            Amount: mbTransferred,
                        },
                        capacity: 1000,
                    };
                });
                world.modifyBlockEntityNBT([3, 1, 1], nbt => {
                    nbt.tank = {
                        fluids: mbTransferred !== 1000 ? [{
                            FluidName: "tconstruct:molten_glass",
                            Amount: 1000 - mbTransferred,
                        }] : [],
                        capacity: 38880,
                    };
                });
                if (mbTransferred == 500) {
                    scene.rotateCameraY(-90);
                }
            }
            world.modifyBlockEntityNBT([5, 1, 1], nbt => {
                nbt.render_fluid = undefined;
                nbt.state = 0;
            });
            scene.text(
                60,
                "Once the fluid has finished pouring, it will solidify over time.",
                [5.5, 1, 1.5],
            );
            scene.idle(40);
            world.modifyBlockEntityNBT([5, 0, 1], nbt => {
                nbt.Items = [{Slot: 1, id: "tconstruct:clear_glass", Count: 1}];
                nbt.tank = {capacity: 0};
                delete nbt.recipe;
            });
            scene.idle(30);
            scene.text(
                60,
                "The Smeltery can melt many different items, and can be expanded in size to hold more fluid and melt more items at once.",
                [3, 1.5, 1.5],
            ).placeNearTarget().attachKeyFrame();
            for (let y = 2; y < 5; y++) {
                for (let coilIdx = 0; coilIdx < 12; coilIdx++) {
                    dropSmelteryBlock(y, coilIdx);
                    scene.idle(2);
                }
            }
            scene.markAsFinished();
        });
    event.create("tconstruct:seared_faucet")
        .scene("faucet", "The Seared Faucet", "kubejs:faucets", (scene, util) => {
            scene.showBasePlate();
            const /** @type{Internal.WorldInstructions} */world = scene.world;
            world.showSection([3, 2, 1], Facing.DOWN);
        });
    const /** @type{Internal.PonderStoryBoard_} */ castingScene = (scene, util) => {
    };
    event.create("tconstruct:seared_basin").scene("casting", "Casting", "kubejs:casting", castingScene);
    event.create("tconstruct:seared_table").scene("casting", "Casting", "kubejs:casting", castingScene);
});