Volver al índice
src/main/java/ar/com/companeros/CompanionTests.java
package ar.com.companeros;
import net.minecraft.core.BlockPos;
import net.minecraft.gametest.framework.GameTest;
import net.minecraft.gametest.framework.GameTestHelper;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.block.Blocks;
import net.minecraftforge.gametest.GameTestHolder;
import net.minecraftforge.gametest.PrefixGameTestTemplate;
/** Pruebas de inventario y modificaciones reales del mundo en un servidor Forge. */
@GameTestHolder(Companeros.ID)
@PrefixGameTestTemplate(false)
public final class CompanionTests {
@net.minecraft.gametest.framework.BeforeBatch(batch = "legacy")
public static void resetProtection(net.minecraft.server.level.ServerLevel level) {
// Cada ejecución del banco de pruebas debe comenzar con sus zonas vacías.
level.getDataStorage().set("companeros_zonas", new WorkArea());
}
private Companion bot(GameTestHelper helper) {
Companion bot = Companeros.COMPANION.get().create(helper.getLevel());
bot.home = helper.absolutePos(new BlockPos(4, 2, 4));
bot.moveTo(bot.home.getX() + .5, bot.home.getY(), bot.home.getZ() + .5, 0, 0);
bot.radius = 16; bot.mode = "quieto";
helper.getLevel().addFreshEntity(bot);
return bot;
}
@GameTest(template = "empty", batch = "legacy")
public void craftingConsumesIngredients(GameTestHelper helper) {
Companion bot = bot(helper);
helper.assertTrue(!Crafting.make(bot.serverLevel(), bot.bag, Items.OAK_PLANKS, false), "No puede fabricar sin madera");
bot.bag.addItem(new ItemStack(Items.OAK_LOG));
helper.assertTrue(Crafting.make(bot.serverLevel(), bot.bag, Items.OAK_PLANKS, false), "La receta debe funcionar");
helper.assertTrue(bot.count(Items.OAK_LOG) == 0 && bot.count(Items.OAK_PLANKS) == 4, "Consume un tronco y produce cuatro tablas");
helper.assertTrue(!Crafting.make(bot.serverLevel(), bot.bag, Items.WOODEN_PICKAXE, false), "No fabrica herramientas sin mesa");
helper.succeed();
}
@GameTest(template = "empty", batch = "legacy")
public void hungerAndSavePersist(GameTestHelper helper) {
Companion bot = bot(helper);
bot.hunger = 10; bot.bag.addItem(new ItemStack(Items.BREAD, 2));
helper.assertTrue(bot.eat(), "Puede comer");
helper.assertTrue(bot.hunger == 15 && bot.count(Items.BREAD) == 1, "Comer consume alimento");
bot.building = true; bot.shelterStep = 8;
bot.owner = java.util.UUID.randomUUID();
CompoundTag tag = new CompoundTag(); bot.addAdditionalSaveData(tag);
Companion loaded = Companeros.COMPANION.get().create(helper.getLevel());
loaded.readAdditionalSaveData(tag);
helper.assertTrue(loaded.count(Items.BREAD) == 1 && loaded.hunger == 15 && loaded.shelterStep == 8
&& loaded.home.equals(bot.home) && loaded.owner.equals(bot.owner), "Mantiene el progreso al cargar");
helper.succeed();
}
@GameTest(template = "empty", batch = "legacy")
public void protectedBlocksAndAreas(GameTestHelper helper) {
Companion bot = bot(helper);
BlockPos tree = bot.home.offset(7, 0, 0);
helper.getLevel().setBlock(tree, Blocks.OAK_LOG.defaultBlockState(), 3);
helper.getLevel().setBlock(tree.above(2), Blocks.OAK_LEAVES.defaultBlockState(), 3);
helper.assertTrue(WorldActions.isResource(bot, tree, "wood"), "Detecta árbol con hojas");
WorkArea.get(helper.getLevel()).protect(tree);
helper.assertTrue(!WorldActions.isResource(bot, tree, "wood"), "No corta un bloque protegido");
helper.assertTrue(!WorldActions.allowed(bot, bot.home.offset(40, 0, 0)), "No sale de su zona");
helper.succeed();
}
@GameTest(template = "empty", batch = "legacy")
public void placementConsumesMaterial(GameTestHelper helper) {
Companion bot = bot(helper);
BlockPos wall = bot.home.offset(2, 0, 0);
helper.getLevel().setBlock(wall.below(), Blocks.DIRT.defaultBlockState(), 3);
bot.bag.addItem(new ItemStack(Items.OAK_PLANKS, 2));
ItemStack stack = bot.bag.getItem(0);
helper.assertTrue(WorldActions.place(bot, wall, stack), "Coloca pared sobre suelo");
helper.assertTrue(helper.getLevel().getBlockState(wall).is(Blocks.OAK_PLANKS) && stack.getCount() == 1,
"La pared cuesta una tabla");
helper.assertTrue(!WorldActions.place(bot, wall, stack) && stack.getCount() == 1, "No reemplaza ni cobra dos veces");
helper.succeed();
}
@GameTest(template = "empty", batch = "legacy")
public void shelterBuiltFromInventory(GameTestHelper helper) {
Companion bot = bot(helper);
for (int x = -2; x <= 2; x++) for (int z = -2; z <= 2; z++)
helper.getLevel().setBlock(bot.home.offset(x, -1, z), Blocks.DIRT.defaultBlockState(), 3);
helper.assertTrue(Shelter.clearSite(bot, bot.home), "Campamento despejado");
bot.bag.addItem(new ItemStack(Items.OAK_PLANKS, 64));
bot.bag.addItem(new ItemStack(Items.OAK_PLANKS, 7));
bot.bag.addItem(new ItemStack(Items.OAK_DOOR));
bot.building = true;
for (int i = 0; i < 80 && bot.building && !Shelter.complete(bot); i++) Shelter.step(bot);
helper.assertTrue(Shelter.complete(bot), "Termina paredes, techo y puerta");
helper.assertTrue(bot.count(Items.OAK_PLANKS) == 0 && bot.count(Items.OAK_DOOR) == 0, "Utiliza todos los materiales exactos");
helper.assertTrue(helper.getLevel().getBlockState(bot.home.above(3)).is(Blocks.OAK_PLANKS), "Techo construido");
helper.assertTrue(helper.getLevel().getBlockState(bot.home.offset(0, 0, -2)).is(Blocks.OAK_DOOR), "Entrada con puerta");
helper.succeed();
}
@GameTest(template = "empty", batch = "legacy")
public void harvestingUsesRealLoot(GameTestHelper helper) {
Companion bot = bot(helper);
BlockPos tree = bot.home.offset(7, 0, 0);
helper.getLevel().setBlock(tree, Blocks.OAK_LOG.defaultBlockState(), 3);
helper.getLevel().setBlock(tree.above(2), Blocks.OAK_LEAVES.defaultBlockState(), 3);
bot.moveTo(tree.getX() - 1, tree.getY(), tree.getZ() + .5, 0, 0);
helper.getLevel().setBlock(bot.blockPosition().below(), Blocks.DIRT.defaultBlockState(), 3);
bot.setOnGround(true);
for (int i = 0; i < 100; i++) if (WorldActions.mine(bot, tree, "wood")) break;
helper.assertTrue(helper.getLevel().getBlockState(tree).isAir(), "Corta árbol");
helper.assertTrue(bot.count(Items.OAK_LOG) == 1, "Recibe el botín real una sola vez");
WorldActions.mine(bot, tree, "wood");
helper.assertTrue(bot.count(Items.OAK_LOG) == 1, "No duplica botín");
helper.succeed();
}
@GameTest(template = "empty", batch = "legacy", timeoutTicks = 500)
public void autonomousForagingMovesAndEats(GameTestHelper helper) {
helper.getLevel().setDayTime(1000);
Companion bot = new Companion(Companeros.COMPANION.get(), helper.getLevel()) {
@Override public boolean humanPresent() { return true; }
};
bot.home = helper.absolutePos(new BlockPos(4, 2, 4));
bot.moveTo(bot.home.getX() + .5, bot.home.getY(), bot.home.getZ() + .5, 0, 0);
bot.radius = 8; bot.hunger = 10; bot.mode = "autonomo";
for (int x = 0; x <= 13; x++) for (int z = 0; z <= 13; z++)
helper.setBlock(new BlockPos(x, 1, z), Blocks.DIRT);
BlockPos berries = bot.home.offset(6, 0, 0);
helper.getLevel().setChunkForced(bot.home.getX() >> 4, bot.home.getZ() >> 4, true);
helper.getLevel().setChunkForced(berries.getX() >> 4, berries.getZ() >> 4, true);
helper.getLevel().setBlock(berries, Blocks.SWEET_BERRY_BUSH.defaultBlockState()
.setValue(net.minecraft.world.level.block.SweetBerryBushBlock.AGE, 3), 3);
helper.getLevel().addFreshEntity(bot);
helper.succeedWhen(() -> {
helper.assertTrue(bot.hunger > 10, "El cerebro debe buscar, caminar, recolectar y comer: "
+ bot.activity + ", ticks=" + bot.workTicks + ", recurso=" + bot.resource + ", posición=" + bot.blockPosition());
helper.assertTrue(bot.getX() > bot.home.getX() + 1, "Se desplazó hacia la comida");
});
}
@GameTest(template = "empty", batch = "legacy")
public void fullInventoryDoesNotLoseIngredients(GameTestHelper helper) {
Companion bot = bot(helper);
bot.bag.setItem(0, new ItemStack(Items.OAK_LOG, 2));
for (int i = 1; i < 36; i++) bot.bag.setItem(i, new ItemStack(Items.COBBLESTONE, 64));
helper.assertTrue(!Crafting.make(bot.serverLevel(), bot.bag, Items.OAK_PLANKS, false), "No cabe la fabricación");
helper.assertTrue(bot.count(Items.OAK_LOG) == 2 && bot.count(Items.OAK_PLANKS) == 0,
"Conserva ingredientes cuando no hay espacio");
helper.succeed();
}
public static final class PlacementVeto {
private final BlockPos pos;
public PlacementVeto(BlockPos pos) { this.pos = pos; }
@net.minecraftforge.eventbus.api.SubscribeEvent
public void cancel(net.minecraftforge.event.level.BlockEvent.EntityPlaceEvent event) {
if (event.getPos().equals(pos)) event.setCanceled(true);
}
}
@GameTest(template = "empty", batch = "legacy")
public void placementRespectsProtectionEvents(GameTestHelper helper) {
Companion bot = bot(helper);
BlockPos wall = bot.home.offset(2, 0, 0);
helper.getLevel().setBlock(wall.below(), Blocks.DIRT.defaultBlockState(), 3);
bot.bag.addItem(new ItemStack(Items.OAK_PLANKS, 2));
var veto = new PlacementVeto(wall);
net.minecraftforge.common.MinecraftForge.EVENT_BUS.register(veto);
try {
helper.assertTrue(!WorldActions.place(bot, wall, bot.bag.getItem(0)), "Una protección puede cancelar la acción");
helper.assertTrue(helper.getLevel().getBlockState(wall).isAir() && bot.count(Items.OAK_PLANKS) == 2,
"La cancelación restaura el bloque y los materiales");
} finally { net.minecraftforge.common.MinecraftForge.EVENT_BUS.unregister(veto); }
helper.succeed();
}
}