Volver al índice

src/main/java/ar/com/companeros/Shelter.java

package ar.com.companeros;

import java.util.ArrayList;
import java.util.List;
import net.minecraft.core.BlockPos;
import net.minecraft.tags.ItemTags;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.Blocks;

/** Refugio 5×5: paredes de tres bloques, techo, entrada y mesa de trabajo. */
public final class Shelter {
    private Shelter() { }

    public static List<BlockPos> blueprint(BlockPos home) {
        List<BlockPos> positions = new ArrayList<>();
        for (int y = 0; y < 3; y++) for (int z = -2; z <= 2; z++) for (int x = -2; x <= 2; x++) {
            if (Math.abs(x) != 2 && Math.abs(z) != 2) continue;
            if (x == 0 && z == -2 && y < 2) continue;
            positions.add(home.offset(x, y, z));
        }
        for (int z = -2; z <= 2; z++) for (int x = -2; x <= 2; x++) positions.add(home.offset(x, 3, z));
        positions.add(home.offset(0, 0, -2));
        return positions;
    }

    public static boolean clearSite(Companion bot, BlockPos home) {
        for (BlockPos pos : BlockPos.betweenClosed(home.offset(-2, 0, -2), home.offset(2, 3, 2))) {
            if (!bot.serverLevel().hasChunkAt(pos) || !bot.level().getBlockState(pos).isAir()
                    || WorkArea.get(bot.serverLevel()).contains(pos)) return false;
        }
        for (int x = -2; x <= 2; x++) for (int z = -2; z <= 2; z++) {
            BlockPos floor = home.offset(x, -1, z);
            if (!bot.level().getBlockState(floor).isCollisionShapeFullBlock(bot.level(), floor)) return false;
        }
        return true;
    }

    public static boolean complete(Companion bot) {
        return bot.shelterStep >= blueprint(bot.home).size();
    }

    public static void step(Companion bot) {
        var plan = blueprint(bot.home);
        if (bot.shelterStep >= plan.size()) { bot.activity = "Campamento listo"; return; }
        BlockPos pos = plan.get(bot.shelterStep);
        boolean door = bot.shelterStep == plan.size() - 1;
        var state = bot.level().getBlockState(pos);
        if (!state.isAir()) {
            // Sólo acepta su pared previamente construida. Una intervención humana pausa la obra.
            if ((state.is(net.minecraft.tags.BlockTags.PLANKS) || door && state.is(net.minecraft.tags.BlockTags.WOODEN_DOORS))
                    && !WorkArea.get(bot.serverLevel()).contains(pos))
                bot.shelterStep++;
            else { bot.building = false; bot.activity = "Campamento ocupado"; }
            return;
        }
        if (bot.position().distanceToSqr(net.minecraft.world.phys.Vec3.atCenterOf(bot.home)) > 2.6) {
            bot.getNavigation().moveTo(bot.home.getX() + .5, bot.home.getY(), bot.home.getZ() + .5, 1);
            return;
        }
        for (int i = 0; i < bot.bag.getContainerSize(); i++) {
            ItemStack stack = bot.bag.getItem(i);
            if (stack.is(door ? ItemTags.WOODEN_DOORS : ItemTags.PLANKS)) {
                if (WorldActions.place(bot, pos, stack)) bot.shelterStep++;
                else { bot.building = false; bot.activity = "Construcción detenida"; }
                return;
            }
        }
    }
}