diff --git a/src/main/java/net/Chipperfluff/chipi/command/ChpCommand.java b/src/main/java/net/Chipperfluff/chipi/command/ChpCommand.java index d3b7ce5..cfd2ff6 100644 --- a/src/main/java/net/Chipperfluff/chipi/command/ChpCommand.java +++ b/src/main/java/net/Chipperfluff/chipi/command/ChpCommand.java @@ -1,9 +1,14 @@ package net.Chipperfluff.chipi.command; import com.mojang.brigadier.CommandDispatcher; -import net.Chipperfluff.chipi.world.gen.struct.ChipiStructures; -import net.minecraft.command.argument.BlockPosArgumentType; +import com.mojang.brigadier.arguments.BoolArgumentType; import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.context.CommandContext; + +import net.Chipperfluff.chipi.world.gen.struct.ChipiStructures; + +import net.minecraft.command.CommandSource; +import net.minecraft.command.argument.BlockPosArgumentType; import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.world.ServerWorld; @@ -15,35 +20,57 @@ public class ChpCommand { public static void register(CommandDispatcher dispatcher) { dispatcher.register( - CommandManager.literal("chp") - .then(CommandManager.argument("name", StringArgumentType.word()) - .then(CommandManager.argument("pos", BlockPosArgumentType.blockPos()) - .executes(ctx -> { - - String name = - StringArgumentType.getString(ctx, "name"); - - BlockPos center = - BlockPosArgumentType.getBlockPos(ctx, "pos"); - - ServerWorld world = - ctx.getSource().getWorld(); - - var structure = - ChipiStructures.get(name); - - if (structure == null) { - ctx.getSource().sendError( - Text.literal("Unknown structure: " + name) - ); - return 0; - } - - structure.place(world, center); - return 1; - }) - ) + CommandManager.literal("chp") + .then(CommandManager.argument("name", StringArgumentType.word()) + // autocomplete structure names + .suggests((ctx, builder) -> + CommandSource.suggestMatching( + ChipiStructures.getNames(), + builder ) + ) + .then(CommandManager.argument("pos", BlockPosArgumentType.blockPos()) + // default: no marker + .executes(ctx -> execute(ctx, false)) + // optional marker flag + .then(CommandManager.argument("marker", BoolArgumentType.bool()) + .executes(ctx -> + execute(ctx, BoolArgumentType.getBool(ctx, "marker")) + ) + ) + ) + ) ); } + + private static int execute( + CommandContext ctx, + boolean marker + ) { + ServerCommandSource source = ctx.getSource(); + ServerWorld world = source.getWorld(); + + String name = StringArgumentType.getString(ctx, "name"); + BlockPos pos = BlockPosArgumentType.getBlockPos(ctx, "pos"); + + var structure = ChipiStructures.get(name); + + if (structure == null) { + source.sendError(Text.literal("Unknown structure: " + name)); + return 0; + } + + // SINGLE call – structure decides everything + structure.placeCommand(world, pos, marker); + + source.sendFeedback( + () -> Text.literal( + "Placed structure '" + name + + (marker ? "' with structure block" : "'") + ), + false + ); + + return 1; + } } diff --git a/src/main/java/net/Chipperfluff/chipi/world/gen/ChipiDungeonGenerator.java b/src/main/java/net/Chipperfluff/chipi/world/gen/ChipiDungeonGenerator.java index ae26665..d1a03c6 100644 --- a/src/main/java/net/Chipperfluff/chipi/world/gen/ChipiDungeonGenerator.java +++ b/src/main/java/net/Chipperfluff/chipi/world/gen/ChipiDungeonGenerator.java @@ -2,7 +2,12 @@ package net.Chipperfluff.chipi.world.gen; import net.Chipperfluff.chipi.world.gen.struct.CorridorNSStructure; import net.Chipperfluff.chipi.world.gen.struct.RoomBaseStructure; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.block.enums.BlockHalf; import net.minecraft.server.world.ServerWorld; +import net.minecraft.state.property.Properties; +import net.minecraft.util.math.Direction; import net.minecraft.util.math.BlockPos; public class ChipiDungeonGenerator { @@ -12,17 +17,18 @@ public class ChipiDungeonGenerator { private static final int ROOM_EXTENT_NORTH = 8; // Fixed Y-levels - private static final int ROOM_Y = 88; + private static final int ROOM_Y = 89; private static final int CORRIDOR_Y = 89; - // Corridors are 10 long; place them with a 1-block gap from room walls (-1 overlap into each room) - private static final int GAP_TO_CORRIDOR = 1; + // Corridors are 10 long; they should overwrite 1 block into each room (-1 on both ends). private static final int CORRIDOR_LENGTH = 10; - // Center-to-center step so corridors start 1 block after the room wall and end 1 block before the next - private static final int STEP_Z = ROOM_EXTENT_SOUTH + GAP_TO_CORRIDOR + CORRIDOR_LENGTH + ROOM_EXTENT_NORTH; // 27 + // Center-to-center step so corridors start 1 block inside the north room and end 1 block inside the south room. + private static final int STEP_Z = ROOM_EXTENT_SOUTH + CORRIDOR_LENGTH + ROOM_EXTENT_NORTH - 1; // 25 + private static final int STEP_X = STEP_Z; // symmetric spacing on X - private static final int ROWS_SOUTH = 40; // total rooms including the first fixed one + private static final int ROWS_SOUTH = 40; // rows of rooms south of spawn (spawn room itself is already placed) + private static final int COLS_EW = 40; // columns across X (split roughly evenly around center) private static RoomBaseStructure getRoom() { return new RoomBaseStructure(); @@ -36,38 +42,108 @@ public class ChipiDungeonGenerator { public static void generateInitialLayout(ServerWorld world, BlockPos portalSpawnPos) { - // Fixed anchors (not relative to portal): first corridor then the first room. + // Spawn is already placed. Fixed anchors (not relative to portal): + // first corridor origin, then the first generated room center is south of spawn. BlockPos firstCorridorAnchor = new BlockPos(5, CORRIDOR_Y, 11); - BlockPos firstRoomCenter = new BlockPos(5, ROOM_Y, 11); + BlockPos firstGeneratedRoomCenter = new BlockPos(5, ROOM_Y, 24); // explicit first floor anchor + + // First room/corridor use direct instances as requested. + RoomBaseStructure firstRoom = new RoomBaseStructure(); + CorridorNSStructure firstCorridor = new CorridorNSStructure(); RoomBaseStructure room = getRoom(); CorridorNSStructure corridorNS = getTunnelNS(); - // Place the fixed corridor and first room. - corridorNS.place(world, firstCorridorAnchor); - room.place(world, firstRoomCenter); + // Place the first room (absolute coordinates). + firstRoom.placeAt(world, firstGeneratedRoomCenter); - // Place remaining rooms strictly southward (Z never decreases). - for (int row = 1; row < ROWS_SOUTH; row++) { - BlockPos center = firstRoomCenter.add( - 0, - 0, - row * STEP_Z - ); - room.place(world, center); + // Place the fixed corridor leaving spawn intact. + firstCorridor.placeAt(world, firstCorridorAnchor); + + // Column range centered on x=5 for a 40-wide grid (approx. 20 each side). + int minCol = -(COLS_EW / 2) + 1; // -19 for 40 cols -> -19..20 inclusive + int maxCol = (COLS_EW / 2); // 20 + + // Place rooms strictly southward (Z never decreases), across X in both directions. + for (int row = 0; row < ROWS_SOUTH; row++) { + for (int col = minCol; col <= maxCol; col++) { + BlockPos center = new BlockPos( + firstGeneratedRoomCenter.getX() + (col * STEP_X), + ROOM_Y, + firstGeneratedRoomCenter.getZ() + (row * STEP_Z) + ); + room.placeAt(world, center); + } } - // Connect each room to the next one south with a corridor at fixed Y. + // Connect each room to the next one south with a corridor at fixed Y (no northward connections). for (int row = 0; row < ROWS_SOUTH - 1; row++) { - BlockPos currentCenter = firstRoomCenter.add(0, 0, row * STEP_Z); + for (int col = minCol; col <= maxCol; col++) { + BlockPos currentCenter = new BlockPos( + firstGeneratedRoomCenter.getX() + (col * STEP_X), + ROOM_Y, + firstGeneratedRoomCenter.getZ() + (row * STEP_Z) + ); - BlockPos anchorSouth = new BlockPos( - currentCenter.getX(), - CORRIDOR_Y, - currentCenter.getZ() + ROOM_EXTENT_SOUTH + GAP_TO_CORRIDOR - ); + BlockPos anchorSouth = new BlockPos( + currentCenter.getX(), + CORRIDOR_Y, + currentCenter.getZ() + ROOM_EXTENT_SOUTH + ); - corridorNS.place(world, anchorSouth); + corridorNS.placeAt(world, anchorSouth); + } + } + + cleanUpEntrance(world); + } + + /** Runs the post-placement cleanup/decoration around spawn and first room. */ + private static void cleanUpEntrance(ServerWorld world) { + + runInChipi(world, "fill 7 87 15 3 91 16 minecraft:air"); + + runInChipi(world, "setblock 4 88 15 minecraft:deepslate_tile_stairs[facing=west,waterlogged=true]"); + runInChipi(world, "setblock 4 88 16 minecraft:deepslate_tile_stairs[facing=west,waterlogged=true]"); + runInChipi(world, "setblock 6 88 15 minecraft:deepslate_tile_stairs[facing=east,waterlogged=true]"); + runInChipi(world, "setblock 6 88 16 minecraft:deepslate_tile_stairs[facing=east,waterlogged=true]"); + + runInChipi(world, "fill 7 88 15 7 91 16 minecraft:deepslate_tiles"); + runInChipi(world, "fill 3 88 16 3 91 15 minecraft:deepslate_tiles"); + + runInChipi(world, "setblock 4 90 15 minecraft:deepslate_tile_stairs[facing=west,half=top]"); + runInChipi(world, "setblock 4 90 16 minecraft:deepslate_tile_stairs[facing=west,half=top]"); + runInChipi(world, "setblock 6 90 15 minecraft:deepslate_tile_stairs[facing=east,half=top]"); + runInChipi(world, "setblock 6 90 16 minecraft:deepslate_tile_stairs[facing=east,half=top]"); + + runInChipi(world, "fill 5 88 15 5 87 16 minecraft:deepslate_tile_slab[waterlogged=true]"); + runInChipi(world, "fill 5 91 16 5 91 15 minecraft:deepslate_tiles"); + } + + private static void fillBox(ServerWorld world, int x1, int y1, int z1, + int x2, int y2, int z2, BlockState state) { + int minX = Math.min(x1, x2); + int maxX = Math.max(x1, x2); + int minY = Math.min(y1, y2); + int maxY = Math.max(y1, y2); + int minZ = Math.min(z1, z2); + int maxZ = Math.max(z1, z2); + + for (int x = minX; x <= maxX; x++) { + for (int y = minY; y <= maxY; y++) { + for (int z = minZ; z <= maxZ; z++) { + world.setBlockState(new BlockPos(x, y, z), state, 3); + } + } } } + + private static void runInChipi(ServerWorld world, String command) { + world.getServer() + .getCommandManager() + .executeWithPrefix( + world.getServer().getCommandSource(), + "execute in chipi:chipi_dimension run " + command + ); + } } diff --git a/src/main/java/net/Chipperfluff/chipi/world/gen/ChipiStructure.java b/src/main/java/net/Chipperfluff/chipi/world/gen/ChipiStructure.java index fa8d0d9..6ee30d7 100644 --- a/src/main/java/net/Chipperfluff/chipi/world/gen/ChipiStructure.java +++ b/src/main/java/net/Chipperfluff/chipi/world/gen/ChipiStructure.java @@ -1,24 +1,48 @@ package net.Chipperfluff.chipi.world.gen; +import net.minecraft.block.Blocks; +import net.minecraft.block.entity.StructureBlockBlockEntity; +import net.minecraft.block.enums.StructureBlockMode; import net.minecraft.server.world.ServerWorld; import net.minecraft.structure.StructurePlacementData; import net.minecraft.structure.StructureTemplate; import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3i; + +import java.util.Optional; public abstract class ChipiStructure { protected final Identifier id; - protected ChipiStructure(Identifier id) { + /** Offset from STRUCTURE BLOCK → actual structure origin */ + protected final int deltaX; + protected final int deltaY; + protected final int deltaZ; + + protected ChipiStructure(Identifier id, int deltaX, int deltaY, int deltaZ) { this.id = id; + this.deltaX = deltaX; + this.deltaY = deltaY; + this.deltaZ = deltaZ; } - /** Override this per structure */ - protected abstract BlockPos centerToOrigin(BlockPos center, StructureTemplate template); + /** REAL size from NBT */ + public BlockPos getSize(ServerWorld world) { + Optional opt = + world.getStructureTemplateManager().getTemplate(id); - public void place(ServerWorld world, BlockPos center) { - var opt = world.getStructureTemplateManager().getTemplate(id); + if (opt.isEmpty()) return BlockPos.ORIGIN; + + Vec3i size = opt.get().getSize(); + return new BlockPos(size.getX(), size.getY(), size.getZ()); + } + + /** Pure structure placement */ + public void placeAt(ServerWorld world, BlockPos origin) { + Optional opt = + world.getStructureTemplateManager().getTemplate(id); if (opt.isEmpty()) { System.out.println("[CHIPI] Missing structure: " + id); @@ -26,7 +50,6 @@ public abstract class ChipiStructure { } StructureTemplate template = opt.get(); - BlockPos origin = centerToOrigin(center, template); template.place( world, @@ -36,8 +59,30 @@ public abstract class ChipiStructure { world.getRandom(), 2 ); + } - System.out.println("[CHIPI] Placed " + id + " at center " + center + - " (origin " + origin + ")"); + /** Command placement (structure + optional marker) */ + public void placeCommand(ServerWorld world, BlockPos placePos, boolean marker) { + + + BlockPos origin = placePos.add( + new BlockPos(deltaX, deltaY, deltaZ) + ); + + placeAt(world, origin); + + if (!marker) return; + + world.setBlockState(origin, Blocks.STRUCTURE_BLOCK.getDefaultState(), 3); + + if (world.getBlockEntity(origin) instanceof StructureBlockBlockEntity be) { + be.setMode(StructureBlockMode.SAVE); + be.setTemplateName(id); + be.setSize(getSize(world)); + be.setIgnoreEntities(false); + be.setShowAir(true); + be.setShowBoundingBox(true); + be.markDirty(); + } } } diff --git a/src/main/java/net/Chipperfluff/chipi/world/gen/struct/ChipiStructures.java b/src/main/java/net/Chipperfluff/chipi/world/gen/struct/ChipiStructures.java index c34ccc0..dea2d48 100644 --- a/src/main/java/net/Chipperfluff/chipi/world/gen/struct/ChipiStructures.java +++ b/src/main/java/net/Chipperfluff/chipi/world/gen/struct/ChipiStructures.java @@ -3,6 +3,7 @@ package net.Chipperfluff.chipi.world.gen.struct; import net.Chipperfluff.chipi.world.gen.ChipiStructure; // <-- THIS WAS MISSING import java.util.HashMap; import java.util.Map; +import java.util.Set; public class ChipiStructures { @@ -15,6 +16,11 @@ public class ChipiStructures { REGISTRY.put("corridor_ew", new CorridorEWStructure()); } + public static Set getNames() { + return REGISTRY.keySet(); + } + + public static ChipiStructure get(String name) { return REGISTRY.get(name); } diff --git a/src/main/java/net/Chipperfluff/chipi/world/gen/struct/CorridorEWStructure.java b/src/main/java/net/Chipperfluff/chipi/world/gen/struct/CorridorEWStructure.java index f33d517..65769e0 100644 --- a/src/main/java/net/Chipperfluff/chipi/world/gen/struct/CorridorEWStructure.java +++ b/src/main/java/net/Chipperfluff/chipi/world/gen/struct/CorridorEWStructure.java @@ -9,17 +9,6 @@ import net.minecraft.util.math.Vec3i; public class CorridorEWStructure extends ChipiStructure { public CorridorEWStructure() { - super(new Identifier("chipi", "coridor_straight_ew")); - } - - @Override - protected BlockPos centerToOrigin(BlockPos center, StructureTemplate template) { - Vec3i size = template.getSize(); - // west side centered at (0,0,0) - return center.add( - 0, - -2, - -2 - ); + super(new Identifier("chipi", "coridor_straight_ew"), 0, -2, -2); } } diff --git a/src/main/java/net/Chipperfluff/chipi/world/gen/struct/CorridorNSStructure.java b/src/main/java/net/Chipperfluff/chipi/world/gen/struct/CorridorNSStructure.java index 28cb1a9..c9c933b 100644 --- a/src/main/java/net/Chipperfluff/chipi/world/gen/struct/CorridorNSStructure.java +++ b/src/main/java/net/Chipperfluff/chipi/world/gen/struct/CorridorNSStructure.java @@ -9,17 +9,6 @@ import net.minecraft.util.math.Vec3i; public class CorridorNSStructure extends ChipiStructure { public CorridorNSStructure() { - super(new Identifier("chipi", "coridor_straight_ns")); - } - - @Override - protected BlockPos centerToOrigin(BlockPos center, StructureTemplate template) { - Vec3i size = template.getSize(); - //north side centered at (0,0,0) - return center.add( - -2, - -2, - 0 - ); + super(new Identifier("chipi", "coridor_straight_ns"), -2, -2, 0); } } diff --git a/src/main/java/net/Chipperfluff/chipi/world/gen/struct/RoomBaseStructure.java b/src/main/java/net/Chipperfluff/chipi/world/gen/struct/RoomBaseStructure.java index e7aeca4..9a72277 100644 --- a/src/main/java/net/Chipperfluff/chipi/world/gen/struct/RoomBaseStructure.java +++ b/src/main/java/net/Chipperfluff/chipi/world/gen/struct/RoomBaseStructure.java @@ -9,17 +9,6 @@ import net.minecraft.util.math.Vec3i; public class RoomBaseStructure extends ChipiStructure { public RoomBaseStructure() { - super(new Identifier("chipi", "room_base")); - } - - @Override - protected BlockPos centerToOrigin(BlockPos center, StructureTemplate template) { - Vec3i size = template.getSize(); - - return center.add( - -9, - -1, - -8 - ); + super(new Identifier("chipi", "room_base"), -9, -1, -8); } } diff --git a/src/main/java/net/Chipperfluff/chipi/world/gen/struct/SpawnStructure.java b/src/main/java/net/Chipperfluff/chipi/world/gen/struct/SpawnStructure.java index 3b1ec5d..0650149 100644 --- a/src/main/java/net/Chipperfluff/chipi/world/gen/struct/SpawnStructure.java +++ b/src/main/java/net/Chipperfluff/chipi/world/gen/struct/SpawnStructure.java @@ -9,17 +9,6 @@ import net.minecraft.util.math.Vec3i; public class SpawnStructure extends ChipiStructure { public SpawnStructure() { - super(new Identifier("chipi", "spawn")); - } - - @Override - protected BlockPos centerToOrigin(BlockPos center, StructureTemplate template) { - Vec3i size = template.getSize(); - - return center.add( - -5, - -9, - -6 - ); + super(new Identifier("chipi", "spawn"), -5, -9, -6); } }