From 3aaf92b7881ecd62b9c73a5e4aaa61a67138039b Mon Sep 17 00:00:00 2001 From: NotEvil Date: Thu, 16 Apr 2026 01:39:40 +0200 Subject: [PATCH] =?UTF-8?q?feat(UC-02):=20data-driven=20room=20themes=20?= =?UTF-8?q?=E2=80=94=206=20JSON=20+=20consumer=20migration=20+=20cleanup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 3: Extract 6 themes into JSON (oubliette, inferno, crypt, ice, sculk, sandstone) Phase 4: Migrate HangingCagePiece to use RoomThemeRegistry.pickRandomOrFallback() - Move 7 shared static methods from RoomTheme into HangingCagePiece - Replace per-enum placeDecorations() with generic DecorationConfig-based placement Phase 5: Delete RoomTheme.java (-1368L) --- .../remake/worldgen/HangingCagePiece.java | 385 ++++- .../com/tiedup/remake/worldgen/RoomTheme.java | 1368 ----------------- .../data/tiedup/tiedup_room_themes/crypt.json | 61 + .../data/tiedup/tiedup_room_themes/ice.json | 58 + .../tiedup/tiedup_room_themes/inferno.json | 58 + .../tiedup/tiedup_room_themes/oubliette.json | 62 + .../tiedup/tiedup_room_themes/sandstone.json | 52 + .../data/tiedup/tiedup_room_themes/sculk.json | 58 + 8 files changed, 679 insertions(+), 1423 deletions(-) delete mode 100644 src/main/java/com/tiedup/remake/worldgen/RoomTheme.java create mode 100644 src/main/resources/data/tiedup/tiedup_room_themes/crypt.json create mode 100644 src/main/resources/data/tiedup/tiedup_room_themes/ice.json create mode 100644 src/main/resources/data/tiedup/tiedup_room_themes/inferno.json create mode 100644 src/main/resources/data/tiedup/tiedup_room_themes/oubliette.json create mode 100644 src/main/resources/data/tiedup/tiedup_room_themes/sandstone.json create mode 100644 src/main/resources/data/tiedup/tiedup_room_themes/sculk.json diff --git a/src/main/java/com/tiedup/remake/worldgen/HangingCagePiece.java b/src/main/java/com/tiedup/remake/worldgen/HangingCagePiece.java index 06c8256..e545b10 100644 --- a/src/main/java/com/tiedup/remake/worldgen/HangingCagePiece.java +++ b/src/main/java/com/tiedup/remake/worldgen/HangingCagePiece.java @@ -26,6 +26,7 @@ import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.WorldGenLevel; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.ChestBlock; +import net.minecraft.world.level.block.LanternBlock; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.RandomizableContainerBlockEntity; import net.minecraft.world.level.block.state.BlockState; @@ -279,7 +280,7 @@ public class HangingCagePiece extends StructurePiece { /** * Fallback: carve a 13x13x12 dungeon room and place the cage inside. - * Randomly selects a theme (Oubliette/Inferno) and layout (Square/Octagonal). + * Randomly selects a data-driven theme and layout (Square/Octagonal). */ private void carveAndPlaceRoom( WorldGenLevel level, @@ -288,9 +289,7 @@ public class HangingCagePiece extends StructurePiece { int centerZ, BoundingBox chunkBB ) { - RoomTheme theme = RoomTheme.values()[random.nextInt( - RoomTheme.values().length - )]; + RoomThemeDefinition theme = RoomThemeRegistry.pickRandomOrFallback(random); RoomLayout layout = RoomLayout.values()[random.nextInt( RoomLayout.values().length )]; @@ -358,62 +357,24 @@ public class HangingCagePiece extends StructurePiece { } } - theme.placeDecorations( - level, - random, - baseX, - baseZ, - floorY, - layout, - chunkBB + placeThemeDecorations( + level, random, baseX, baseZ, floorY, layout, chunkBB, theme ); - RoomTheme.placeSharedPillars( - level, - random, - baseX, - baseZ, - floorY, - layout, - theme, - chunkBB + placeSharedPillars( + level, random, baseX, baseZ, floorY, layout, theme, chunkBB ); - RoomTheme.placeSharedFloorScatter( - level, - random, - baseX, - baseZ, - floorY, - layout, - theme, - chunkBB + placeSharedFloorScatter( + level, random, baseX, baseZ, floorY, layout, theme, chunkBB ); - RoomTheme.placeSharedCeilingDecor( - level, - random, - baseX, - baseZ, - floorY, - layout, - chunkBB + placeSharedCeilingDecor( + level, random, baseX, baseZ, floorY, layout, chunkBB ); - RoomTheme.placeSharedWallLighting( - level, - random, - baseX, - baseZ, - floorY, - layout, - chunkBB + placeSharedWallLighting( + level, random, baseX, baseZ, floorY, layout, chunkBB ); - RoomTheme.placeSharedWallBands( - level, - baseX, - baseZ, - floorY, - layout, - theme, - chunkBB + placeSharedWallBands( + level, baseX, baseZ, floorY, layout, theme, chunkBB ); placeVanillaChest(level, random, baseX, baseZ, floorY, layout, chunkBB); @@ -451,7 +412,7 @@ public class HangingCagePiece extends StructurePiece { TiedUpMod.LOGGER.info( "[HangingCage] Placed cage in carved room (theme={}, layout={}) at {}", - theme.name(), + theme.id(), layout.name(), masterPos.toShortString() ); @@ -655,4 +616,318 @@ public class HangingCagePiece extends StructurePiece { ); } } + + // ── Data-driven theme decorations ─────────────────────────────── + + /** + * Place decorations from the data-driven {@link DecorationConfig}. + * Replaces the old per-enum {@code RoomTheme.placeDecorations()} method. + */ + private static void placeThemeDecorations( + WorldGenLevel level, + RandomSource random, + int baseX, + int baseZ, + int floorY, + RoomLayout layout, + BoundingBox chunkBB, + RoomThemeDefinition theme + ) { + DecorationConfig deco = theme.decorations(); + int[][] corners = layout.innerCorners(); + + // Corner decorations (e.g. cobwebs low+high, soul fire, snow layers) + for (DecorationConfig.PositionedBlock pb : deco.cornerDecorations()) { + for (int[] c : corners) { + if (layout.isInShape(c[0], c[1]) && !layout.isWall(c[0], c[1])) { + safeSetBlock(level, + new BlockPos(baseX + c[0], floorY + pb.yOffset(), baseZ + c[1]), + pb.state(), chunkBB); + } + } + } + + // Wall midpoint decorations (e.g. soul lanterns, crying obsidian, sculk veins) + int[][] wallMidpoints = {{6, 1}, {6, 11}, {1, 6}, {11, 6}}; + for (DecorationConfig.PositionedBlock pb : deco.wallMidpointBlocks()) { + for (int[] wp : wallMidpoints) { + if (layout.isWall(wp[0], wp[1])) { + safeSetBlock(level, + new BlockPos(baseX + wp[0], floorY + pb.yOffset(), baseZ + wp[1]), + pb.state(), chunkBB); + } + } + } + + // First corner special (e.g. water cauldron, skull, TNT, sculk catalyst) + if (deco.firstCornerSpecial() != null && corners.length > 0) { + int[] sc = corners[0]; + if (layout.isInShape(sc[0], sc[1]) && !layout.isWall(sc[0], sc[1])) { + safeSetBlock(level, + new BlockPos(baseX + sc[0], floorY + deco.firstCornerSpecial().yOffset(), baseZ + sc[1]), + deco.firstCornerSpecial().state(), chunkBB); + } + } + + // Furniture cluster at corners[1] (e.g. barrel+brewing_stand, soul_campfire+cauldron) + if (corners.length > 1) { + int[] fc = corners[1]; + int fcx = fc[0] + (fc[0] < 6 ? 1 : -1); + int fcz = fc[1] + (fc[1] < 6 ? 1 : -1); + if (layout.isInShape(fcx, fcz) && !layout.isWall(fcx, fcz)) { + for (DecorationConfig.PositionedBlock pb : deco.furnitureCluster()) { + safeSetBlock(level, + new BlockPos(baseX + fcx, floorY + pb.yOffset(), baseZ + fcz), + pb.state(), chunkBB); + } + } + + // Ceiling chain above furniture + if (deco.hasCeilingChain()) { + for (int cy = 8; cy <= 10; cy++) { + safeSetBlock(level, + new BlockPos(baseX + fcx, floorY + cy, baseZ + fcz), + Blocks.CHAIN.defaultBlockState(), chunkBB); + } + } + } + + // Torch lighting (wall torches at outer wall midpoints) -- used by Crypt, Sandstone + if (deco.useTorchLighting()) { + for (int[] wallPos : new int[][] {{6, 0}, {6, 12}, {0, 6}, {12, 6}}) { + if (layout.isWall(wallPos[0], wallPos[1])) { + Direction torchDir = getTorchDirection(wallPos[0], wallPos[1]); + if (torchDir != null) { + safeSetBlock(level, + new BlockPos(baseX + wallPos[0], floorY + 3, baseZ + wallPos[1]), + Blocks.WALL_TORCH.defaultBlockState().setValue( + net.minecraft.world.level.block.WallTorchBlock.FACING, torchDir), + chunkBB); + } + } + } + } + + // Side chains + hanging lanterns (shared by all themes) + placeSharedChains(level, baseX, baseZ, floorY, chunkBB); + placeSharedHangingLanterns(level, baseX, baseZ, floorY, chunkBB); + } + + // ── Shared structural features (moved from RoomTheme) ────────── + + /** Pillar positions -- verified to be inside all 4 layouts. */ + private static final int[][] PILLAR_POSITIONS = { + {4, 4}, {4, 8}, {8, 4}, {8, 8}, + }; + + /** Place 4 full-height pillars at verified positions. */ + private static void placeSharedPillars( + WorldGenLevel level, + RandomSource random, + int baseX, + int baseZ, + int floorY, + RoomLayout layout, + RoomThemeDefinition theme, + BoundingBox chunkBB + ) { + for (int[] p : PILLAR_POSITIONS) { + if (!layout.isInShape(p[0], p[1]) || layout.isWall(p[0], p[1])) continue; + for (int ry = 1; ry <= 10; ry++) { + safeSetBlock(level, + new BlockPos(baseX + p[0], floorY + ry, baseZ + p[1]), + theme.pillarBlock(random, ry), chunkBB); + } + } + } + + /** Place random floor scatter (~12% of interior positions). */ + private static void placeSharedFloorScatter( + WorldGenLevel level, + RandomSource random, + int baseX, + int baseZ, + int floorY, + RoomLayout layout, + RoomThemeDefinition theme, + BoundingBox chunkBB + ) { + for (int rx = 1; rx <= 11; rx++) { + for (int rz = 1; rz <= 11; rz++) { + if (!layout.isInShape(rx, rz) || layout.isWall(rx, rz)) continue; + // Skip pillar positions + if ((rx == 4 || rx == 8) && (rz == 4 || rz == 8)) continue; + // Skip cage center area (5-7, 5-7) + if (rx >= 5 && rx <= 7 && rz >= 5 && rz <= 7) continue; + // Skip corner positions (used by decorations/chests) + if ((rx <= 2 || rx >= 10) && (rz <= 2 || rz >= 10)) continue; + if (random.nextFloat() < 0.12f) { + BlockState scatter = theme.scatterBlock(random); + if (scatter != null) { + safeSetBlock(level, + new BlockPos(baseX + rx, floorY + 1, baseZ + rz), + scatter, chunkBB); + } + } + } + } + } + + /** Place ceiling cobwebs and extra hanging chains. */ + private static void placeSharedCeilingDecor( + WorldGenLevel level, + RandomSource random, + int baseX, + int baseZ, + int floorY, + RoomLayout layout, + BoundingBox chunkBB + ) { + // Cobwebs along walls at ceiling level + int[][] cobwebCandidates = { + {2, 1}, {4, 1}, {8, 1}, {10, 1}, + {2, 11}, {4, 11}, {8, 11}, {10, 11}, + {1, 4}, {1, 8}, {11, 4}, {11, 8}, + }; + for (int[] pos : cobwebCandidates) { + if (layout.isInShape(pos[0], pos[1]) + && !layout.isWall(pos[0], pos[1]) + && random.nextFloat() < 0.45f) { + safeSetBlock(level, + new BlockPos(baseX + pos[0], floorY + 10, baseZ + pos[1]), + Blocks.COBWEB.defaultBlockState(), chunkBB); + } + } + // Extra hanging chains at random interior positions + int[][] chainCandidates = {{5, 3}, {7, 9}, {3, 7}}; + for (int[] pos : chainCandidates) { + if (layout.isInShape(pos[0], pos[1]) + && !layout.isWall(pos[0], pos[1]) + && random.nextFloat() < 0.6f) { + safeSetBlock(level, + new BlockPos(baseX + pos[0], floorY + 10, baseZ + pos[1]), + Blocks.CHAIN.defaultBlockState(), chunkBB); + safeSetBlock(level, + new BlockPos(baseX + pos[0], floorY + 9, baseZ + pos[1]), + Blocks.CHAIN.defaultBlockState(), chunkBB); + } + } + } + + /** Place additional wall-mounted lighting. */ + private static void placeSharedWallLighting( + WorldGenLevel level, + RandomSource random, + int baseX, + int baseZ, + int floorY, + RoomLayout layout, + BoundingBox chunkBB + ) { + // Lanterns on pillar sides (facing center) at ry=1 (on the floor) + int[][] pillarLanternPositions = { + {5, 4}, {4, 7}, {8, 5}, {7, 8}, + }; + for (int[] pos : pillarLanternPositions) { + if (layout.isInShape(pos[0], pos[1]) + && !layout.isWall(pos[0], pos[1])) { + safeSetBlock(level, + new BlockPos(baseX + pos[0], floorY + 1, baseZ + pos[1]), + Blocks.LANTERN.defaultBlockState(), chunkBB); + } + } + // Extra wall sconces at quarter-points + int[][] wallSconces = { + {4, 0}, {8, 0}, {4, 12}, {8, 12}, + {0, 4}, {0, 8}, {12, 4}, {12, 8}, + }; + for (int[] pos : wallSconces) { + if (layout.isWall(pos[0], pos[1]) && random.nextFloat() < 0.5f) { + Direction torchDir = getTorchDirection(pos[0], pos[1]); + if (torchDir != null) { + safeSetBlock(level, + new BlockPos(baseX + pos[0], floorY + 3, baseZ + pos[1]), + Blocks.WALL_TORCH.defaultBlockState().setValue( + net.minecraft.world.level.block.WallTorchBlock.FACING, torchDir), + chunkBB); + } + } + } + } + + /** Place wall accent bands at ry=5 and ry=8. */ + private static void placeSharedWallBands( + WorldGenLevel level, + int baseX, + int baseZ, + int floorY, + RoomLayout layout, + RoomThemeDefinition theme, + BoundingBox chunkBB + ) { + int[][] bandPositions = { + {6, 1}, {6, 11}, {1, 6}, {11, 6}, + {4, 1}, {8, 1}, {4, 11}, {8, 11}, + {1, 4}, {1, 8}, {11, 4}, {11, 8}, + }; + for (int[] pos : bandPositions) { + if (layout.isWall(pos[0], pos[1])) { + // Band at ry=5 + safeSetBlock(level, + new BlockPos(baseX + pos[0], floorY + 5, baseZ + pos[1]), + theme.wallAccentBlock(), chunkBB); + // Optional band at ry=8 + safeSetBlock(level, + new BlockPos(baseX + pos[0], floorY + 8, baseZ + pos[1]), + theme.wallAccentBlock(), chunkBB); + } + } + } + + /** Chains on cage flanks and ceiling corners -- shared by all themes. */ + private static void placeSharedChains( + WorldGenLevel level, + int baseX, + int baseZ, + int floorY, + BoundingBox chunkBB + ) { + for (int[] chainPos : new int[][] {{3, 6}, {9, 6}}) { + for (int ry = 5; ry <= 10; ry++) { + safeSetBlock(level, + new BlockPos(baseX + chainPos[0], floorY + ry, baseZ + chainPos[1]), + Blocks.CHAIN.defaultBlockState(), chunkBB); + } + } + for (int[] chainPos : new int[][] {{3, 3}, {3, 9}, {9, 3}, {9, 9}}) { + safeSetBlock(level, + new BlockPos(baseX + chainPos[0], floorY + 10, baseZ + chainPos[1]), + Blocks.CHAIN.defaultBlockState(), chunkBB); + } + } + + /** Determine torch facing direction for a wall position (torch faces inward). */ + private static Direction getTorchDirection(int rx, int rz) { + if (rz == 0) return Direction.SOUTH; + if (rz == 12) return Direction.NORTH; + if (rx == 0) return Direction.EAST; + if (rx == 12) return Direction.WEST; + return null; + } + + /** Hanging lanterns -- shared by all themes. */ + private static void placeSharedHangingLanterns( + WorldGenLevel level, + int baseX, + int baseZ, + int floorY, + BoundingBox chunkBB + ) { + for (int[] pos : new int[][] {{3, 3}, {9, 9}}) { + safeSetBlock(level, + new BlockPos(baseX + pos[0], floorY + 9, baseZ + pos[1]), + Blocks.LANTERN.defaultBlockState().setValue(LanternBlock.HANGING, true), + chunkBB); + } + } } diff --git a/src/main/java/com/tiedup/remake/worldgen/RoomTheme.java b/src/main/java/com/tiedup/remake/worldgen/RoomTheme.java deleted file mode 100644 index 7c06ada..0000000 --- a/src/main/java/com/tiedup/remake/worldgen/RoomTheme.java +++ /dev/null @@ -1,1368 +0,0 @@ -package com.tiedup.remake.worldgen; - -import javax.annotation.Nullable; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.util.RandomSource; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.LanternBlock; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraft.world.level.levelgen.structure.BoundingBox; - -enum RoomTheme { - OUBLIETTE { - @Override - public BlockState wallBlock(RandomSource r, int ry) { - if ( - ry == 1 && r.nextFloat() < 0.30f - ) return Blocks.MOSSY_COBBLESTONE.defaultBlockState(); - return r.nextFloat() < 0.20f - ? Blocks.CRACKED_DEEPSLATE_BRICKS.defaultBlockState() - : Blocks.DEEPSLATE_BRICKS.defaultBlockState(); - } - - @Override - public BlockState floorBlock( - RandomSource r, - int rx, - int rz, - boolean isEdge - ) { - boolean isCorner = (rx == 1 || rx == 11) && (rz == 1 || rz == 11); - if (isCorner) return Blocks.MOSSY_COBBLESTONE.defaultBlockState(); - return r.nextFloat() < 0.15f - ? Blocks.COBBLESTONE.defaultBlockState() - : Blocks.DEEPSLATE_TILES.defaultBlockState(); - } - - @Override - public BlockState ceilingBlock(RandomSource r) { - return r.nextFloat() < 0.20f - ? Blocks.CRACKED_DEEPSLATE_BRICKS.defaultBlockState() - : Blocks.DEEPSLATE_BRICKS.defaultBlockState(); - } - - @Override - public BlockState wallShellBlock() { - return Blocks.DEEPSLATE_BRICKS.defaultBlockState(); - } - - @Override - public void placeDecorations( - WorldGenLevel level, - RandomSource random, - int baseX, - int baseZ, - int floorY, - RoomLayout layout, - BoundingBox chunkBB - ) { - int[][] corners = layout.innerCorners(); - // Cobwebs at corners (low + high) - for (int[] c : corners) { - if ( - layout.isInShape(c[0], c[1]) && !layout.isWall(c[0], c[1]) - ) { - HangingCagePiece.safeSetBlock( - level, - new BlockPos(baseX + c[0], floorY + 1, baseZ + c[1]), - Blocks.COBWEB.defaultBlockState(), - chunkBB - ); - HangingCagePiece.safeSetBlock( - level, - new BlockPos(baseX + c[0], floorY + 9, baseZ + c[1]), - Blocks.COBWEB.defaultBlockState(), - chunkBB - ); - } - } - // Water cauldron near first corner - int cx = corners[0][0] + 1, - cz = corners[0][1] + 1; - if (layout.isInShape(cx, cz) && !layout.isWall(cx, cz)) { - HangingCagePiece.safeSetBlock( - level, - new BlockPos(baseX + cx, floorY + 1, baseZ + cz), - Blocks.WATER_CAULDRON.defaultBlockState().setValue( - BlockStateProperties.LEVEL_CAULDRON, - 3 - ), - chunkBB - ); - } - // Soul lanterns on wall midpoints - for (int[] wallPos : new int[][] { - { 6, 1 }, - { 6, 11 }, - { 1, 6 }, - { 11, 6 }, - }) { - if (layout.isWall(wallPos[0], wallPos[1])) { - HangingCagePiece.safeSetBlock( - level, - new BlockPos( - baseX + wallPos[0], - floorY + 3, - baseZ + wallPos[1] - ), - Blocks.SOUL_LANTERN.defaultBlockState(), - chunkBB - ); - } - } - // Corner furniture: barrel + brewing_stand + chain - int[] fc = corners[1]; - int fcx = fc[0] + (fc[0] < 6 ? 1 : -1); - int fcz = fc[1] + (fc[1] < 6 ? 1 : -1); - if (layout.isInShape(fcx, fcz) && !layout.isWall(fcx, fcz)) { - HangingCagePiece.safeSetBlock( - level, - new BlockPos(baseX + fcx, floorY + 1, baseZ + fcz), - Blocks.BARREL.defaultBlockState(), - chunkBB - ); - int fcx2 = fcx + (fcx < 6 ? 1 : -1); - if (layout.isInShape(fcx2, fcz) && !layout.isWall(fcx2, fcz)) { - HangingCagePiece.safeSetBlock( - level, - new BlockPos(baseX + fcx2, floorY + 1, baseZ + fcz), - Blocks.BREWING_STAND.defaultBlockState(), - chunkBB - ); - } - // Chain above barrel - for (int cy = 8; cy <= 10; cy++) { - HangingCagePiece.safeSetBlock( - level, - new BlockPos(baseX + fcx, floorY + cy, baseZ + fcz), - Blocks.CHAIN.defaultBlockState(), - chunkBB - ); - } - } - // Side chains - placeSharedChains(level, baseX, baseZ, floorY, chunkBB); - // Hanging lanterns - placeSharedHangingLanterns(level, baseX, baseZ, floorY, chunkBB); - } - - @Override - public BlockState pillarBlock(RandomSource r, int ry) { - if ( - ry == 1 || ry == 10 - ) return Blocks.POLISHED_DEEPSLATE.defaultBlockState(); - return Blocks.DEEPSLATE_BRICK_WALL.defaultBlockState(); - } - - @Override - @Nullable - public BlockState scatterBlock(RandomSource r) { - float f = r.nextFloat(); - if (f < 0.40f) return Blocks.COBWEB.defaultBlockState(); - if (f < 0.70f) return Blocks.CANDLE.defaultBlockState() - .setValue(BlockStateProperties.CANDLES, 1 + r.nextInt(3)) - .setValue(BlockStateProperties.LIT, true); - return Blocks.MOSS_CARPET.defaultBlockState(); - } - - @Override - public BlockState wallAccentBlock() { - return Blocks.POLISHED_DEEPSLATE.defaultBlockState(); - } - }, - INFERNO { - @Override - public BlockState wallBlock(RandomSource r, int ry) { - return r.nextFloat() < 0.20f - ? Blocks.CRACKED_NETHER_BRICKS.defaultBlockState() - : Blocks.NETHER_BRICKS.defaultBlockState(); - } - - @Override - public BlockState floorBlock( - RandomSource r, - int rx, - int rz, - boolean isEdge - ) { - if (isEdge) return Blocks.MAGMA_BLOCK.defaultBlockState(); - return r.nextFloat() < 0.08f - ? Blocks.GILDED_BLACKSTONE.defaultBlockState() - : Blocks.BLACKSTONE.defaultBlockState(); - } - - @Override - public BlockState ceilingBlock(RandomSource r) { - return r.nextFloat() < 0.20f - ? Blocks.CRACKED_NETHER_BRICKS.defaultBlockState() - : Blocks.NETHER_BRICKS.defaultBlockState(); - } - - @Override - public BlockState wallShellBlock() { - return Blocks.NETHER_BRICKS.defaultBlockState(); - } - - @Override - public void placeDecorations( - WorldGenLevel level, - RandomSource random, - int baseX, - int baseZ, - int floorY, - RoomLayout layout, - BoundingBox chunkBB - ) { - int[][] corners = layout.innerCorners(); - // Soul fire at corners: soul_sand at ry=0, soul_fire at ry=1 - for (int[] c : corners) { - if ( - layout.isInShape(c[0], c[1]) && !layout.isWall(c[0], c[1]) - ) { - HangingCagePiece.safeSetBlock( - level, - new BlockPos(baseX + c[0], floorY, baseZ + c[1]), - Blocks.SOUL_SAND.defaultBlockState(), - chunkBB - ); - HangingCagePiece.safeSetBlock( - level, - new BlockPos(baseX + c[0], floorY + 1, baseZ + c[1]), - Blocks.SOUL_FIRE.defaultBlockState(), - chunkBB - ); - } - } - // Crying obsidian accents at wall midpoints - for (int[] wallPos : new int[][] { - { 6, 1 }, - { 6, 11 }, - { 1, 6 }, - { 11, 6 }, - }) { - if (layout.isWall(wallPos[0], wallPos[1])) { - HangingCagePiece.safeSetBlock( - level, - new BlockPos( - baseX + wallPos[0], - floorY + 2, - baseZ + wallPos[1] - ), - Blocks.CRYING_OBSIDIAN.defaultBlockState(), - chunkBB - ); - } - } - // Soul lanterns on wall midpoints - for (int[] wallPos : new int[][] { - { 6, 1 }, - { 6, 11 }, - { 1, 6 }, - { 11, 6 }, - }) { - if (layout.isWall(wallPos[0], wallPos[1])) { - HangingCagePiece.safeSetBlock( - level, - new BlockPos( - baseX + wallPos[0], - floorY + 3, - baseZ + wallPos[1] - ), - Blocks.SOUL_LANTERN.defaultBlockState(), - chunkBB - ); - } - } - // Corner furniture: soul_campfire + cauldron(lava) + gilded_blackstone - int[][] icorners = layout.innerCorners(); - int[] ifc = icorners[1]; - int ifcx = ifc[0] + (ifc[0] < 6 ? 1 : -1); - int ifcz = ifc[1] + (ifc[1] < 6 ? 1 : -1); - if (layout.isInShape(ifcx, ifcz) && !layout.isWall(ifcx, ifcz)) { - HangingCagePiece.safeSetBlock( - level, - new BlockPos(baseX + ifcx, floorY + 1, baseZ + ifcz), - Blocks.SOUL_CAMPFIRE.defaultBlockState(), - chunkBB - ); - int ifcx2 = ifcx + (ifcx < 6 ? 1 : -1); - if ( - layout.isInShape(ifcx2, ifcz) && !layout.isWall(ifcx2, ifcz) - ) { - HangingCagePiece.safeSetBlock( - level, - new BlockPos(baseX + ifcx2, floorY + 1, baseZ + ifcz), - Blocks.LAVA_CAULDRON.defaultBlockState(), - chunkBB - ); - } - if ( - layout.isInShape(ifcx, ifcz + (ifcz < 6 ? 1 : -1)) && - !layout.isWall(ifcx, ifcz + (ifcz < 6 ? 1 : -1)) - ) { - HangingCagePiece.safeSetBlock( - level, - new BlockPos( - baseX + ifcx, - floorY + 1, - baseZ + ifcz + (ifcz < 6 ? 1 : -1) - ), - Blocks.GILDED_BLACKSTONE.defaultBlockState(), - chunkBB - ); - } - } - // Side chains - placeSharedChains(level, baseX, baseZ, floorY, chunkBB); - // Hanging lanterns - placeSharedHangingLanterns(level, baseX, baseZ, floorY, chunkBB); - } - - @Override - public BlockState pillarBlock(RandomSource r, int ry) { - if ( - ry == 1 || ry == 10 - ) return Blocks.QUARTZ_PILLAR.defaultBlockState(); - return Blocks.NETHER_BRICK_WALL.defaultBlockState(); - } - - @Override - @Nullable - public BlockState scatterBlock(RandomSource r) { - float f = r.nextFloat(); - if (f < 0.40f) return Blocks.SOUL_SAND.defaultBlockState(); - if (f < 0.70f) return Blocks.NETHER_WART_BLOCK.defaultBlockState(); - return Blocks.BONE_BLOCK.defaultBlockState(); - } - - @Override - public BlockState wallAccentBlock() { - return Blocks.RED_NETHER_BRICKS.defaultBlockState(); - } - }, - CRYPT { - @Override - public BlockState wallBlock(RandomSource r, int ry) { - float f = r.nextFloat(); - if ( - ry == 1 && f < 0.20f - ) return Blocks.MOSSY_COBBLESTONE.defaultBlockState(); - if (f < 0.15f) return Blocks.MOSSY_STONE_BRICKS.defaultBlockState(); - if ( - f < 0.30f - ) return Blocks.CRACKED_STONE_BRICKS.defaultBlockState(); - return Blocks.STONE_BRICKS.defaultBlockState(); - } - - @Override - public BlockState floorBlock( - RandomSource r, - int rx, - int rz, - boolean isEdge - ) { - boolean isCorner = (rx == 1 || rx == 11) && (rz == 1 || rz == 11); - if (isCorner) return Blocks.MOSSY_COBBLESTONE.defaultBlockState(); - return r.nextFloat() < 0.20f - ? Blocks.COBBLESTONE.defaultBlockState() - : Blocks.STONE_BRICKS.defaultBlockState(); - } - - @Override - public BlockState ceilingBlock(RandomSource r) { - return r.nextFloat() < 0.20f - ? Blocks.CRACKED_STONE_BRICKS.defaultBlockState() - : Blocks.STONE_BRICKS.defaultBlockState(); - } - - @Override - public BlockState wallShellBlock() { - return Blocks.STONE_BRICKS.defaultBlockState(); - } - - @Override - public void placeDecorations( - WorldGenLevel level, - RandomSource random, - int baseX, - int baseZ, - int floorY, - RoomLayout layout, - BoundingBox chunkBB - ) { - int[][] corners = layout.innerCorners(); - // Cobwebs at corners (low + high) - for (int[] c : corners) { - if ( - layout.isInShape(c[0], c[1]) && !layout.isWall(c[0], c[1]) - ) { - HangingCagePiece.safeSetBlock( - level, - new BlockPos(baseX + c[0], floorY + 1, baseZ + c[1]), - Blocks.COBWEB.defaultBlockState(), - chunkBB - ); - HangingCagePiece.safeSetBlock( - level, - new BlockPos(baseX + c[0], floorY + 9, baseZ + c[1]), - Blocks.COBWEB.defaultBlockState(), - chunkBB - ); - } - } - // Wall torches at midpoints - for (int[] wallPos : new int[][] { - { 6, 0 }, - { 6, 12 }, - { 0, 6 }, - { 12, 6 }, - }) { - if (layout.isWall(wallPos[0], wallPos[1])) { - Direction torchDir = getTorchDirection( - wallPos[0], - wallPos[1] - ); - if (torchDir != null) { - HangingCagePiece.safeSetBlock( - level, - new BlockPos( - baseX + wallPos[0], - floorY + 3, - baseZ + wallPos[1] - ), - Blocks.WALL_TORCH.defaultBlockState().setValue( - net.minecraft.world.level.block.WallTorchBlock.FACING, - torchDir - ), - chunkBB - ); - } - } - } - // Skull in first corner - int[] sc = corners[0]; - if ( - layout.isInShape(sc[0], sc[1]) && !layout.isWall(sc[0], sc[1]) - ) { - HangingCagePiece.safeSetBlock( - level, - new BlockPos(baseX + sc[0], floorY + 1, baseZ + sc[1]), - Blocks.SKELETON_SKULL.defaultBlockState(), - chunkBB - ); - } - // Corner furniture: lectern + candles on floor - int[] cfc = corners[1]; - int cfcx = cfc[0] + (cfc[0] < 6 ? 1 : -1); - int cfcz = cfc[1] + (cfc[1] < 6 ? 1 : -1); - if (layout.isInShape(cfcx, cfcz) && !layout.isWall(cfcx, cfcz)) { - HangingCagePiece.safeSetBlock( - level, - new BlockPos(baseX + cfcx, floorY + 1, baseZ + cfcz), - Blocks.LECTERN.defaultBlockState(), - chunkBB - ); - int cfcx2 = cfcx + (cfcx < 6 ? 1 : -1); - if ( - layout.isInShape(cfcx2, cfcz) && !layout.isWall(cfcx2, cfcz) - ) { - HangingCagePiece.safeSetBlock( - level, - new BlockPos(baseX + cfcx2, floorY + 1, baseZ + cfcz), - Blocks.CANDLE.defaultBlockState() - .setValue(BlockStateProperties.CANDLES, 4) - .setValue(BlockStateProperties.LIT, true), - chunkBB - ); - } - } - placeSharedChains(level, baseX, baseZ, floorY, chunkBB); - placeSharedHangingLanterns(level, baseX, baseZ, floorY, chunkBB); - } - - @Override - public BlockState pillarBlock(RandomSource r, int ry) { - if ( - ry == 1 || ry == 10 - ) return Blocks.CHISELED_STONE_BRICKS.defaultBlockState(); - return Blocks.STONE_BRICK_WALL.defaultBlockState(); - } - - @Override - @Nullable - public BlockState scatterBlock(RandomSource r) { - float f = r.nextFloat(); - if (f < 0.40f) return Blocks.COBWEB.defaultBlockState(); - if (f < 0.70f) return Blocks.CANDLE.defaultBlockState() - .setValue(BlockStateProperties.CANDLES, 1 + r.nextInt(3)) - .setValue(BlockStateProperties.LIT, true); - return Blocks.BONE_BLOCK.defaultBlockState(); - } - - @Override - public BlockState wallAccentBlock() { - return Blocks.MOSSY_STONE_BRICKS.defaultBlockState(); - } - }, - ICE { - @Override - public BlockState wallBlock(RandomSource r, int ry) { - float f = r.nextFloat(); - if (f < 0.10f) return Blocks.ICE.defaultBlockState(); - if (f < 0.30f) return Blocks.BLUE_ICE.defaultBlockState(); - return Blocks.PACKED_ICE.defaultBlockState(); - } - - @Override - public BlockState floorBlock( - RandomSource r, - int rx, - int rz, - boolean isEdge - ) { - if (isEdge) return Blocks.BLUE_ICE.defaultBlockState(); - return r.nextFloat() < 0.20f - ? Blocks.SNOW_BLOCK.defaultBlockState() - : Blocks.PACKED_ICE.defaultBlockState(); - } - - @Override - public BlockState ceilingBlock(RandomSource r) { - return r.nextFloat() < 0.20f - ? Blocks.BLUE_ICE.defaultBlockState() - : Blocks.PACKED_ICE.defaultBlockState(); - } - - @Override - public BlockState wallShellBlock() { - return Blocks.PACKED_ICE.defaultBlockState(); - } - - @Override - public void placeDecorations( - WorldGenLevel level, - RandomSource random, - int baseX, - int baseZ, - int floorY, - RoomLayout layout, - BoundingBox chunkBB - ) { - int[][] corners = layout.innerCorners(); - // Snow layers in corners - for (int[] c : corners) { - if ( - layout.isInShape(c[0], c[1]) && !layout.isWall(c[0], c[1]) - ) { - HangingCagePiece.safeSetBlock( - level, - new BlockPos(baseX + c[0], floorY + 1, baseZ + c[1]), - Blocks.SNOW.defaultBlockState().setValue( - net.minecraft.world.level.block.SnowLayerBlock.LAYERS, - 2 + random.nextInt(3) - ), - chunkBB - ); - } - } - // Lanterns on wall midpoints - for (int[] wallPos : new int[][] { - { 6, 1 }, - { 6, 11 }, - { 1, 6 }, - { 11, 6 }, - }) { - if (layout.isWall(wallPos[0], wallPos[1])) { - HangingCagePiece.safeSetBlock( - level, - new BlockPos( - baseX + wallPos[0], - floorY + 3, - baseZ + wallPos[1] - ), - Blocks.LANTERN.defaultBlockState(), - chunkBB - ); - } - } - // Ice stalactites near ceiling corners - for (int[] c : corners) { - int cx = c[0], - cz = c[1]; - if (layout.isInShape(cx, cz) && !layout.isWall(cx, cz)) { - HangingCagePiece.safeSetBlock( - level, - new BlockPos(baseX + cx, floorY + 10, baseZ + cz), - Blocks.ICE.defaultBlockState(), - chunkBB - ); - } - } - // Corner furniture: cauldron(powder_snow) + blue_ice seat + lantern - int[] ifc2 = corners[1]; - int ifc2x = ifc2[0] + (ifc2[0] < 6 ? 1 : -1); - int ifc2z = ifc2[1] + (ifc2[1] < 6 ? 1 : -1); - if ( - layout.isInShape(ifc2x, ifc2z) && !layout.isWall(ifc2x, ifc2z) - ) { - HangingCagePiece.safeSetBlock( - level, - new BlockPos(baseX + ifc2x, floorY + 1, baseZ + ifc2z), - Blocks.POWDER_SNOW_CAULDRON.defaultBlockState().setValue( - BlockStateProperties.LEVEL_CAULDRON, - 3 - ), - chunkBB - ); - int ifc2x2 = ifc2x + (ifc2x < 6 ? 1 : -1); - if ( - layout.isInShape(ifc2x2, ifc2z) && - !layout.isWall(ifc2x2, ifc2z) - ) { - HangingCagePiece.safeSetBlock( - level, - new BlockPos(baseX + ifc2x2, floorY + 1, baseZ + ifc2z), - Blocks.BLUE_ICE.defaultBlockState(), - chunkBB - ); - } - if ( - layout.isInShape(ifc2x, ifc2z + (ifc2z < 6 ? 1 : -1)) && - !layout.isWall(ifc2x, ifc2z + (ifc2z < 6 ? 1 : -1)) - ) { - HangingCagePiece.safeSetBlock( - level, - new BlockPos( - baseX + ifc2x, - floorY + 2, - baseZ + ifc2z + (ifc2z < 6 ? 1 : -1) - ), - Blocks.LANTERN.defaultBlockState(), - chunkBB - ); - } - } - placeSharedChains(level, baseX, baseZ, floorY, chunkBB); - placeSharedHangingLanterns(level, baseX, baseZ, floorY, chunkBB); - } - - @Override - public BlockState pillarBlock(RandomSource r, int ry) { - if (ry == 1 || ry == 10) return Blocks.BLUE_ICE.defaultBlockState(); - return r.nextFloat() < 0.5f - ? Blocks.PACKED_ICE.defaultBlockState() - : Blocks.BLUE_ICE.defaultBlockState(); - } - - @Override - @Nullable - public BlockState scatterBlock(RandomSource r) { - float f = r.nextFloat(); - if (f < 0.50f) return Blocks.SNOW.defaultBlockState().setValue( - net.minecraft.world.level.block.SnowLayerBlock.LAYERS, - 1 + r.nextInt(2) - ); - if (f < 0.70f) return Blocks.POWDER_SNOW.defaultBlockState(); - return Blocks.ICE.defaultBlockState(); - } - - @Override - public BlockState wallAccentBlock() { - return Blocks.BLUE_ICE.defaultBlockState(); - } - }, - SCULK { - @Override - public BlockState wallBlock(RandomSource r, int ry) { - float f = r.nextFloat(); - if ( - f < 0.10f - ) return Blocks.CRACKED_DEEPSLATE_BRICKS.defaultBlockState(); - if (f < 0.40f) return Blocks.SCULK.defaultBlockState(); - return Blocks.DEEPSLATE_BRICKS.defaultBlockState(); - } - - @Override - public BlockState floorBlock( - RandomSource r, - int rx, - int rz, - boolean isEdge - ) { - if (isEdge) return Blocks.SCULK.defaultBlockState(); - return r.nextFloat() < 0.30f - ? Blocks.SCULK.defaultBlockState() - : Blocks.DEEPSLATE_TILES.defaultBlockState(); - } - - @Override - public BlockState ceilingBlock(RandomSource r) { - float f = r.nextFloat(); - if ( - f < 0.10f - ) return Blocks.CRACKED_DEEPSLATE_BRICKS.defaultBlockState(); - if (f < 0.30f) return Blocks.SCULK.defaultBlockState(); - return Blocks.DEEPSLATE_BRICKS.defaultBlockState(); - } - - @Override - public BlockState wallShellBlock() { - return Blocks.DEEPSLATE_BRICKS.defaultBlockState(); - } - - @Override - public void placeDecorations( - WorldGenLevel level, - RandomSource random, - int baseX, - int baseZ, - int floorY, - RoomLayout layout, - BoundingBox chunkBB - ) { - // Sculk veins on wall midpoints at ry=2 - for (int[] wallPos : new int[][] { - { 6, 1 }, - { 6, 11 }, - { 1, 6 }, - { 11, 6 }, - }) { - if (layout.isWall(wallPos[0], wallPos[1])) { - HangingCagePiece.safeSetBlock( - level, - new BlockPos( - baseX + wallPos[0], - floorY + 2, - baseZ + wallPos[1] - ), - Blocks.SCULK_VEIN.defaultBlockState(), - chunkBB - ); - } - } - // Soul lanterns on wall midpoints at ry=3 - for (int[] wallPos : new int[][] { - { 6, 1 }, - { 6, 11 }, - { 1, 6 }, - { 11, 6 }, - }) { - if (layout.isWall(wallPos[0], wallPos[1])) { - HangingCagePiece.safeSetBlock( - level, - new BlockPos( - baseX + wallPos[0], - floorY + 3, - baseZ + wallPos[1] - ), - Blocks.SOUL_LANTERN.defaultBlockState(), - chunkBB - ); - } - } - // Sculk catalyst in first corner - int[][] corners = layout.innerCorners(); - int[] sc = corners[0]; - if ( - layout.isInShape(sc[0], sc[1]) && !layout.isWall(sc[0], sc[1]) - ) { - HangingCagePiece.safeSetBlock( - level, - new BlockPos(baseX + sc[0], floorY + 1, baseZ + sc[1]), - Blocks.SCULK_CATALYST.defaultBlockState(), - chunkBB - ); - } - // Corner furniture: sculk_shrieker + sculk_sensor + candle - int[][] scorners = layout.innerCorners(); - int[] sfc = scorners[1]; - int sfcx = sfc[0] + (sfc[0] < 6 ? 1 : -1); - int sfcz = sfc[1] + (sfc[1] < 6 ? 1 : -1); - if (layout.isInShape(sfcx, sfcz) && !layout.isWall(sfcx, sfcz)) { - HangingCagePiece.safeSetBlock( - level, - new BlockPos(baseX + sfcx, floorY + 1, baseZ + sfcz), - Blocks.SCULK_SHRIEKER.defaultBlockState(), - chunkBB - ); - int sfcx2 = sfcx + (sfcx < 6 ? 1 : -1); - if ( - layout.isInShape(sfcx2, sfcz) && !layout.isWall(sfcx2, sfcz) - ) { - HangingCagePiece.safeSetBlock( - level, - new BlockPos(baseX + sfcx2, floorY + 1, baseZ + sfcz), - Blocks.SCULK_SENSOR.defaultBlockState(), - chunkBB - ); - } - if ( - layout.isInShape(sfcx, sfcz + (sfcz < 6 ? 1 : -1)) && - !layout.isWall(sfcx, sfcz + (sfcz < 6 ? 1 : -1)) - ) { - HangingCagePiece.safeSetBlock( - level, - new BlockPos( - baseX + sfcx, - floorY + 1, - baseZ + sfcz + (sfcz < 6 ? 1 : -1) - ), - Blocks.CANDLE.defaultBlockState() - .setValue(BlockStateProperties.CANDLES, 3) - .setValue(BlockStateProperties.LIT, true), - chunkBB - ); - } - } - placeSharedChains(level, baseX, baseZ, floorY, chunkBB); - placeSharedHangingLanterns(level, baseX, baseZ, floorY, chunkBB); - } - - @Override - public BlockState pillarBlock(RandomSource r, int ry) { - if (ry == 1 || ry == 10) return Blocks.SCULK.defaultBlockState(); - return r.nextFloat() < 0.3f - ? Blocks.SCULK.defaultBlockState() - : Blocks.DEEPSLATE_TILE_WALL.defaultBlockState(); - } - - @Override - @Nullable - public BlockState scatterBlock(RandomSource r) { - float f = r.nextFloat(); - if (f < 0.50f) return Blocks.SCULK.defaultBlockState(); - if (f < 0.80f) return Blocks.SCULK_VEIN.defaultBlockState(); - return Blocks.MOSS_CARPET.defaultBlockState(); - } - - @Override - public BlockState wallAccentBlock() { - return Blocks.SCULK_CATALYST.defaultBlockState(); - } - }, - SANDSTONE { - @Override - public BlockState wallBlock(RandomSource r, int ry) { - float f = r.nextFloat(); - if (f < 0.10f) return Blocks.CHISELED_SANDSTONE.defaultBlockState(); - if (f < 0.30f) return Blocks.SANDSTONE.defaultBlockState(); - return Blocks.CUT_SANDSTONE.defaultBlockState(); - } - - @Override - public BlockState floorBlock( - RandomSource r, - int rx, - int rz, - boolean isEdge - ) { - return r.nextFloat() < 0.15f - ? Blocks.SAND.defaultBlockState() - : Blocks.SMOOTH_SANDSTONE.defaultBlockState(); - } - - @Override - public BlockState ceilingBlock(RandomSource r) { - return r.nextFloat() < 0.20f - ? Blocks.SANDSTONE.defaultBlockState() - : Blocks.CUT_SANDSTONE.defaultBlockState(); - } - - @Override - public BlockState wallShellBlock() { - return Blocks.CUT_SANDSTONE.defaultBlockState(); - } - - @Override - public void placeDecorations( - WorldGenLevel level, - RandomSource random, - int baseX, - int baseZ, - int floorY, - RoomLayout layout, - BoundingBox chunkBB - ) { - // Wall torches at midpoints - for (int[] wallPos : new int[][] { - { 6, 0 }, - { 6, 12 }, - { 0, 6 }, - { 12, 6 }, - }) { - if (layout.isWall(wallPos[0], wallPos[1])) { - Direction torchDir = getTorchDirection( - wallPos[0], - wallPos[1] - ); - if (torchDir != null) { - HangingCagePiece.safeSetBlock( - level, - new BlockPos( - baseX + wallPos[0], - floorY + 3, - baseZ + wallPos[1] - ), - Blocks.WALL_TORCH.defaultBlockState().setValue( - net.minecraft.world.level.block.WallTorchBlock.FACING, - torchDir - ), - chunkBB - ); - } - } - } - // Orange terracotta accents at wall midpoints ry=2 - for (int[] wallPos : new int[][] { - { 6, 1 }, - { 6, 11 }, - { 1, 6 }, - { 11, 6 }, - }) { - if (layout.isWall(wallPos[0], wallPos[1])) { - HangingCagePiece.safeSetBlock( - level, - new BlockPos( - baseX + wallPos[0], - floorY + 2, - baseZ + wallPos[1] - ), - Blocks.ORANGE_TERRACOTTA.defaultBlockState(), - chunkBB - ); - } - } - // TNT hidden in first corner - int[][] corners = layout.innerCorners(); - int[] tc = corners[0]; - if ( - layout.isInShape(tc[0], tc[1]) && !layout.isWall(tc[0], tc[1]) - ) { - HangingCagePiece.safeSetBlock( - level, - new BlockPos(baseX + tc[0], floorY + 1, baseZ + tc[1]), - Blocks.TNT.defaultBlockState(), - chunkBB - ); - } - // Corner furniture: barrel + flower_pot + orange_terracotta bench - int[] ssfc = corners[1]; - int ssfcx = ssfc[0] + (ssfc[0] < 6 ? 1 : -1); - int ssfcz = ssfc[1] + (ssfc[1] < 6 ? 1 : -1); - if ( - layout.isInShape(ssfcx, ssfcz) && !layout.isWall(ssfcx, ssfcz) - ) { - HangingCagePiece.safeSetBlock( - level, - new BlockPos(baseX + ssfcx, floorY + 1, baseZ + ssfcz), - Blocks.BARREL.defaultBlockState(), - chunkBB - ); - int ssfcx2 = ssfcx + (ssfcx < 6 ? 1 : -1); - if ( - layout.isInShape(ssfcx2, ssfcz) && - !layout.isWall(ssfcx2, ssfcz) - ) { - HangingCagePiece.safeSetBlock( - level, - new BlockPos(baseX + ssfcx2, floorY + 1, baseZ + ssfcz), - Blocks.FLOWER_POT.defaultBlockState(), - chunkBB - ); - } - if ( - layout.isInShape(ssfcx, ssfcz + (ssfcz < 6 ? 1 : -1)) && - !layout.isWall(ssfcx, ssfcz + (ssfcz < 6 ? 1 : -1)) - ) { - HangingCagePiece.safeSetBlock( - level, - new BlockPos( - baseX + ssfcx, - floorY + 1, - baseZ + ssfcz + (ssfcz < 6 ? 1 : -1) - ), - Blocks.ORANGE_TERRACOTTA.defaultBlockState(), - chunkBB - ); - } - } - placeSharedChains(level, baseX, baseZ, floorY, chunkBB); - placeSharedHangingLanterns(level, baseX, baseZ, floorY, chunkBB); - } - - @Override - public BlockState pillarBlock(RandomSource r, int ry) { - if ( - ry == 1 || ry == 10 - ) return Blocks.CHISELED_SANDSTONE.defaultBlockState(); - return Blocks.SANDSTONE_WALL.defaultBlockState(); - } - - @Override - @Nullable - public BlockState scatterBlock(RandomSource r) { - float f = r.nextFloat(); - if (f < 0.40f) return Blocks.SAND.defaultBlockState(); - if (f < 0.70f) return Blocks.DEAD_BUSH.defaultBlockState(); - return Blocks.CANDLE.defaultBlockState() - .setValue(BlockStateProperties.CANDLES, 1 + r.nextInt(3)) - .setValue(BlockStateProperties.LIT, true); - } - - @Override - public BlockState wallAccentBlock() { - return Blocks.CHISELED_SANDSTONE.defaultBlockState(); - } - }; - - public abstract BlockState wallBlock(RandomSource r, int ry); - - public abstract BlockState floorBlock( - RandomSource r, - int rx, - int rz, - boolean isEdge - ); - - public abstract BlockState ceilingBlock(RandomSource r); - - /** Solid block used for wall positions on the floor layer. */ - public abstract BlockState wallShellBlock(); - - public abstract void placeDecorations( - WorldGenLevel level, - RandomSource random, - int baseX, - int baseZ, - int floorY, - RoomLayout layout, - BoundingBox chunkBB - ); - - /** Block used for pillars (may vary by height). */ - public abstract BlockState pillarBlock(RandomSource r, int ry); - - /** Random scatter block for floor decoration, or null to skip. */ - @Nullable - public abstract BlockState scatterBlock(RandomSource r); - - /** Accent block for decorative wall bands. */ - public abstract BlockState wallAccentBlock(); - - // ── Shared structural features ────────────────────────────────── - - /** Pillar positions -- verified to be inside all 4 layouts. */ - private static final int[][] PILLAR_POSITIONS = { - { 4, 4 }, - { 4, 8 }, - { 8, 4 }, - { 8, 8 }, - }; - - /** Place 4 full-height pillars at verified positions. */ - static void placeSharedPillars( - WorldGenLevel level, - RandomSource random, - int baseX, - int baseZ, - int floorY, - RoomLayout layout, - RoomTheme theme, - BoundingBox chunkBB - ) { - for (int[] p : PILLAR_POSITIONS) { - if ( - !layout.isInShape(p[0], p[1]) || layout.isWall(p[0], p[1]) - ) continue; - for (int ry = 1; ry <= 10; ry++) { - HangingCagePiece.safeSetBlock( - level, - new BlockPos(baseX + p[0], floorY + ry, baseZ + p[1]), - theme.pillarBlock(random, ry), - chunkBB - ); - } - } - } - - /** Place random floor scatter (~12% of interior positions). */ - static void placeSharedFloorScatter( - WorldGenLevel level, - RandomSource random, - int baseX, - int baseZ, - int floorY, - RoomLayout layout, - RoomTheme theme, - BoundingBox chunkBB - ) { - for (int rx = 1; rx <= 11; rx++) { - for (int rz = 1; rz <= 11; rz++) { - if ( - !layout.isInShape(rx, rz) || layout.isWall(rx, rz) - ) continue; - // Skip pillar positions - if ((rx == 4 || rx == 8) && (rz == 4 || rz == 8)) continue; - // Skip cage center area (5-7, 5-7) - if (rx >= 5 && rx <= 7 && rz >= 5 && rz <= 7) continue; - // Skip corner positions (used by decorations/chests) - if ((rx <= 2 || rx >= 10) && (rz <= 2 || rz >= 10)) continue; - if (random.nextFloat() < 0.12f) { - BlockState scatter = theme.scatterBlock(random); - if (scatter != null) { - HangingCagePiece.safeSetBlock( - level, - new BlockPos(baseX + rx, floorY + 1, baseZ + rz), - scatter, - chunkBB - ); - } - } - } - } - } - - /** Place ceiling cobwebs and extra hanging chains. */ - static void placeSharedCeilingDecor( - WorldGenLevel level, - RandomSource random, - int baseX, - int baseZ, - int floorY, - RoomLayout layout, - BoundingBox chunkBB - ) { - // Cobwebs along walls at ceiling level - int[][] cobwebCandidates = { - { 2, 1 }, - { 4, 1 }, - { 8, 1 }, - { 10, 1 }, - { 2, 11 }, - { 4, 11 }, - { 8, 11 }, - { 10, 11 }, - { 1, 4 }, - { 1, 8 }, - { 11, 4 }, - { 11, 8 }, - }; - for (int[] pos : cobwebCandidates) { - if ( - layout.isInShape(pos[0], pos[1]) && - !layout.isWall(pos[0], pos[1]) && - random.nextFloat() < 0.45f - ) { - HangingCagePiece.safeSetBlock( - level, - new BlockPos(baseX + pos[0], floorY + 10, baseZ + pos[1]), - Blocks.COBWEB.defaultBlockState(), - chunkBB - ); - } - } - // Extra hanging chains at random interior positions - int[][] chainCandidates = { { 5, 3 }, { 7, 9 }, { 3, 7 } }; - for (int[] pos : chainCandidates) { - if ( - layout.isInShape(pos[0], pos[1]) && - !layout.isWall(pos[0], pos[1]) && - random.nextFloat() < 0.6f - ) { - HangingCagePiece.safeSetBlock( - level, - new BlockPos(baseX + pos[0], floorY + 10, baseZ + pos[1]), - Blocks.CHAIN.defaultBlockState(), - chunkBB - ); - HangingCagePiece.safeSetBlock( - level, - new BlockPos(baseX + pos[0], floorY + 9, baseZ + pos[1]), - Blocks.CHAIN.defaultBlockState(), - chunkBB - ); - } - } - } - - /** Place additional wall-mounted lighting. */ - static void placeSharedWallLighting( - WorldGenLevel level, - RandomSource random, - int baseX, - int baseZ, - int floorY, - RoomLayout layout, - BoundingBox chunkBB - ) { - // Lanterns on pillar sides (facing center) at ry=1 (on the floor) - int[][] pillarLanternPositions = { - { 5, 4 }, - { 4, 7 }, - { 8, 5 }, - { 7, 8 }, - }; - for (int[] pos : pillarLanternPositions) { - if ( - layout.isInShape(pos[0], pos[1]) && - !layout.isWall(pos[0], pos[1]) - ) { - HangingCagePiece.safeSetBlock( - level, - new BlockPos(baseX + pos[0], floorY + 1, baseZ + pos[1]), - Blocks.LANTERN.defaultBlockState(), - chunkBB - ); - } - } - // Extra wall sconces at quarter-points - int[][] wallSconces = { - { 4, 0 }, - { 8, 0 }, - { 4, 12 }, - { 8, 12 }, - { 0, 4 }, - { 0, 8 }, - { 12, 4 }, - { 12, 8 }, - }; - for (int[] pos : wallSconces) { - if (layout.isWall(pos[0], pos[1]) && random.nextFloat() < 0.5f) { - Direction torchDir = getTorchDirection(pos[0], pos[1]); - if (torchDir != null) { - HangingCagePiece.safeSetBlock( - level, - new BlockPos( - baseX + pos[0], - floorY + 3, - baseZ + pos[1] - ), - Blocks.WALL_TORCH.defaultBlockState().setValue( - net.minecraft.world.level.block.WallTorchBlock.FACING, - torchDir - ), - chunkBB - ); - } - } - } - } - - /** Place wall accent bands at ry=5 and ry=8. */ - static void placeSharedWallBands( - WorldGenLevel level, - int baseX, - int baseZ, - int floorY, - RoomLayout layout, - RoomTheme theme, - BoundingBox chunkBB - ) { - int[][] bandPositions = { - { 6, 1 }, - { 6, 11 }, - { 1, 6 }, - { 11, 6 }, - { 4, 1 }, - { 8, 1 }, - { 4, 11 }, - { 8, 11 }, - { 1, 4 }, - { 1, 8 }, - { 11, 4 }, - { 11, 8 }, - }; - for (int[] pos : bandPositions) { - if (layout.isWall(pos[0], pos[1])) { - // Band at ry=5 - HangingCagePiece.safeSetBlock( - level, - new BlockPos(baseX + pos[0], floorY + 5, baseZ + pos[1]), - theme.wallAccentBlock(), - chunkBB - ); - // Optional band at ry=8 - HangingCagePiece.safeSetBlock( - level, - new BlockPos(baseX + pos[0], floorY + 8, baseZ + pos[1]), - theme.wallAccentBlock(), - chunkBB - ); - } - } - } - - /** Chains on cage flanks and ceiling corners -- shared by all themes. */ - static void placeSharedChains( - WorldGenLevel level, - int baseX, - int baseZ, - int floorY, - BoundingBox chunkBB - ) { - for (int[] chainPos : new int[][] { { 3, 6 }, { 9, 6 } }) { - for (int ry = 5; ry <= 10; ry++) { - HangingCagePiece.safeSetBlock( - level, - new BlockPos( - baseX + chainPos[0], - floorY + ry, - baseZ + chainPos[1] - ), - Blocks.CHAIN.defaultBlockState(), - chunkBB - ); - } - } - for (int[] chainPos : new int[][] { - { 3, 3 }, - { 3, 9 }, - { 9, 3 }, - { 9, 9 }, - }) { - HangingCagePiece.safeSetBlock( - level, - new BlockPos( - baseX + chainPos[0], - floorY + 10, - baseZ + chainPos[1] - ), - Blocks.CHAIN.defaultBlockState(), - chunkBB - ); - } - } - - /** Determine torch facing direction for a wall position (torch faces inward). */ - static Direction getTorchDirection(int rx, int rz) { - if (rz == 0) return Direction.SOUTH; - if (rz == 12) return Direction.NORTH; - if (rx == 0) return Direction.EAST; - if (rx == 12) return Direction.WEST; - return null; - } - - /** Hanging lanterns -- shared by all themes. */ - static void placeSharedHangingLanterns( - WorldGenLevel level, - int baseX, - int baseZ, - int floorY, - BoundingBox chunkBB - ) { - for (int[] pos : new int[][] { { 3, 3 }, { 9, 9 } }) { - HangingCagePiece.safeSetBlock( - level, - new BlockPos(baseX + pos[0], floorY + 9, baseZ + pos[1]), - Blocks.LANTERN.defaultBlockState().setValue( - LanternBlock.HANGING, - true - ), - chunkBB - ); - } - } -} diff --git a/src/main/resources/data/tiedup/tiedup_room_themes/crypt.json b/src/main/resources/data/tiedup/tiedup_room_themes/crypt.json new file mode 100644 index 0000000..84557e5 --- /dev/null +++ b/src/main/resources/data/tiedup/tiedup_room_themes/crypt.json @@ -0,0 +1,61 @@ +{ + "weight": 10, + "wall_palette": { + "default": [ + { "block": "minecraft:mossy_stone_bricks", "weight": 0.15 }, + { "block": "minecraft:cracked_stone_bricks", "weight": 0.15 }, + { "block": "minecraft:stone_bricks", "weight": 0.70 } + ], + "bottom_row": [ + { "block": "minecraft:mossy_cobblestone", "weight": 0.20 }, + { "block": "minecraft:mossy_stone_bricks", "weight": 0.12 }, + { "block": "minecraft:cracked_stone_bricks", "weight": 0.12 }, + { "block": "minecraft:stone_bricks", "weight": 0.56 } + ] + }, + "floor_palette": { + "default": [ + { "block": "minecraft:cobblestone", "weight": 0.20 }, + { "block": "minecraft:stone_bricks", "weight": 0.80 } + ], + "corner": [ + { "block": "minecraft:mossy_cobblestone", "weight": 1.0 } + ] + }, + "ceiling_palette": { + "default": [ + { "block": "minecraft:cracked_stone_bricks", "weight": 0.20 }, + { "block": "minecraft:stone_bricks", "weight": 0.80 } + ] + }, + "wall_shell": "minecraft:stone_bricks", + "wall_accent": "minecraft:mossy_stone_bricks", + "pillar_palette": { + "default": [ + { "block": "minecraft:stone_brick_wall", "weight": 1.0 } + ], + "cap": [ + { "block": "minecraft:chiseled_stone_bricks", "weight": 1.0 } + ] + }, + "scatter_palette": { + "default": [ + { "block": "minecraft:cobweb", "weight": 0.40 }, + { "block": "minecraft:candle[lit=true]", "weight": 0.30, "random_property": { "name": "candles", "min": 1, "max": 3 } }, + { "block": "minecraft:bone_block", "weight": 0.30 } + ] + }, + "decorations": { + "corner_decorations": [ + { "block": "minecraft:cobweb", "y_offset": 1 }, + { "block": "minecraft:cobweb", "y_offset": 9 } + ], + "first_corner_special": { "block": "minecraft:skeleton_skull", "y_offset": 1 }, + "furniture_cluster": [ + { "block": "minecraft:lectern", "y_offset": 1 }, + { "block": "minecraft:candle[lit=true,candles=4]", "y_offset": 1 } + ], + "use_torch_lighting": true, + "has_ceiling_chain": true + } +} diff --git a/src/main/resources/data/tiedup/tiedup_room_themes/ice.json b/src/main/resources/data/tiedup/tiedup_room_themes/ice.json new file mode 100644 index 0000000..ec8b3cc --- /dev/null +++ b/src/main/resources/data/tiedup/tiedup_room_themes/ice.json @@ -0,0 +1,58 @@ +{ + "weight": 10, + "wall_palette": { + "default": [ + { "block": "minecraft:ice", "weight": 0.10 }, + { "block": "minecraft:blue_ice", "weight": 0.20 }, + { "block": "minecraft:packed_ice", "weight": 0.70 } + ] + }, + "floor_palette": { + "default": [ + { "block": "minecraft:snow_block", "weight": 0.20 }, + { "block": "minecraft:packed_ice", "weight": 0.80 } + ], + "edge": [ + { "block": "minecraft:blue_ice", "weight": 1.0 } + ] + }, + "ceiling_palette": { + "default": [ + { "block": "minecraft:blue_ice", "weight": 0.20 }, + { "block": "minecraft:packed_ice", "weight": 0.80 } + ] + }, + "wall_shell": "minecraft:packed_ice", + "wall_accent": "minecraft:blue_ice", + "pillar_palette": { + "default": [ + { "block": "minecraft:packed_ice", "weight": 0.50 }, + { "block": "minecraft:blue_ice", "weight": 0.50 } + ], + "cap": [ + { "block": "minecraft:blue_ice", "weight": 1.0 } + ] + }, + "scatter_palette": { + "default": [ + { "block": "minecraft:snow[layers=1]", "weight": 0.50, "random_property": { "name": "layers", "min": 1, "max": 2 } }, + { "block": "minecraft:powder_snow", "weight": 0.20 }, + { "block": "minecraft:ice", "weight": 0.30 } + ] + }, + "decorations": { + "corner_decorations": [ + { "block": "minecraft:snow[layers=2]", "y_offset": 1 } + ], + "wall_midpoint_blocks": [ + { "block": "minecraft:lantern", "y_offset": 3 } + ], + "furniture_cluster": [ + { "block": "minecraft:powder_snow_cauldron[level=3]", "y_offset": 1 }, + { "block": "minecraft:blue_ice", "y_offset": 1 }, + { "block": "minecraft:lantern", "y_offset": 2 } + ], + "use_torch_lighting": false, + "has_ceiling_chain": true + } +} diff --git a/src/main/resources/data/tiedup/tiedup_room_themes/inferno.json b/src/main/resources/data/tiedup/tiedup_room_themes/inferno.json new file mode 100644 index 0000000..434af69 --- /dev/null +++ b/src/main/resources/data/tiedup/tiedup_room_themes/inferno.json @@ -0,0 +1,58 @@ +{ + "weight": 10, + "wall_palette": { + "default": [ + { "block": "minecraft:cracked_nether_bricks", "weight": 0.20 }, + { "block": "minecraft:nether_bricks", "weight": 0.80 } + ] + }, + "floor_palette": { + "default": [ + { "block": "minecraft:gilded_blackstone", "weight": 0.08 }, + { "block": "minecraft:blackstone", "weight": 0.92 } + ], + "edge": [ + { "block": "minecraft:magma_block", "weight": 1.0 } + ] + }, + "ceiling_palette": { + "default": [ + { "block": "minecraft:cracked_nether_bricks", "weight": 0.20 }, + { "block": "minecraft:nether_bricks", "weight": 0.80 } + ] + }, + "wall_shell": "minecraft:nether_bricks", + "wall_accent": "minecraft:red_nether_bricks", + "pillar_palette": { + "default": [ + { "block": "minecraft:nether_brick_wall", "weight": 1.0 } + ], + "cap": [ + { "block": "minecraft:quartz_pillar", "weight": 1.0 } + ] + }, + "scatter_palette": { + "default": [ + { "block": "minecraft:soul_sand", "weight": 0.40 }, + { "block": "minecraft:nether_wart_block", "weight": 0.30 }, + { "block": "minecraft:bone_block", "weight": 0.30 } + ] + }, + "decorations": { + "corner_decorations": [ + { "block": "minecraft:soul_sand", "y_offset": 0 }, + { "block": "minecraft:soul_fire", "y_offset": 1 } + ], + "wall_midpoint_blocks": [ + { "block": "minecraft:crying_obsidian", "y_offset": 2 }, + { "block": "minecraft:soul_lantern", "y_offset": 3 } + ], + "furniture_cluster": [ + { "block": "minecraft:soul_campfire", "y_offset": 1 }, + { "block": "minecraft:lava_cauldron", "y_offset": 1 }, + { "block": "minecraft:gilded_blackstone", "y_offset": 1 } + ], + "use_torch_lighting": false, + "has_ceiling_chain": true + } +} diff --git a/src/main/resources/data/tiedup/tiedup_room_themes/oubliette.json b/src/main/resources/data/tiedup/tiedup_room_themes/oubliette.json new file mode 100644 index 0000000..8d2b881 --- /dev/null +++ b/src/main/resources/data/tiedup/tiedup_room_themes/oubliette.json @@ -0,0 +1,62 @@ +{ + "weight": 10, + "wall_palette": { + "default": [ + { "block": "minecraft:cracked_deepslate_bricks", "weight": 0.20 }, + { "block": "minecraft:deepslate_bricks", "weight": 0.80 } + ], + "bottom_row": [ + { "block": "minecraft:mossy_cobblestone", "weight": 0.30 }, + { "block": "minecraft:cracked_deepslate_bricks", "weight": 0.14 }, + { "block": "minecraft:deepslate_bricks", "weight": 0.56 } + ] + }, + "floor_palette": { + "default": [ + { "block": "minecraft:cobblestone", "weight": 0.15 }, + { "block": "minecraft:deepslate_tiles", "weight": 0.85 } + ], + "corner": [ + { "block": "minecraft:mossy_cobblestone", "weight": 1.0 } + ] + }, + "ceiling_palette": { + "default": [ + { "block": "minecraft:cracked_deepslate_bricks", "weight": 0.20 }, + { "block": "minecraft:deepslate_bricks", "weight": 0.80 } + ] + }, + "wall_shell": "minecraft:deepslate_bricks", + "wall_accent": "minecraft:polished_deepslate", + "pillar_palette": { + "default": [ + { "block": "minecraft:deepslate_brick_wall", "weight": 1.0 } + ], + "cap": [ + { "block": "minecraft:polished_deepslate", "weight": 1.0 } + ] + }, + "scatter_palette": { + "default": [ + { "block": "minecraft:cobweb", "weight": 0.40 }, + { "block": "minecraft:candle[lit=true]", "weight": 0.30, "random_property": { "name": "candles", "min": 1, "max": 3 } }, + { "block": "minecraft:moss_carpet", "weight": 0.30 } + ] + }, + "decorations": { + "corner_decorations": [ + { "block": "minecraft:cobweb", "y_offset": 1 }, + { "block": "minecraft:cobweb", "y_offset": 9 } + ], + "wall_midpoint_blocks": [ + { "block": "minecraft:soul_lantern", "y_offset": 3 } + ], + "first_corner_special": { "block": "minecraft:water_cauldron[level=3]", "y_offset": 1 }, + "furniture_cluster": [ + { "block": "minecraft:barrel", "y_offset": 1 }, + { "block": "minecraft:brewing_stand", "y_offset": 1 } + ], + "use_torch_lighting": false, + "has_ceiling_chain": true + } +} diff --git a/src/main/resources/data/tiedup/tiedup_room_themes/sandstone.json b/src/main/resources/data/tiedup/tiedup_room_themes/sandstone.json new file mode 100644 index 0000000..fdf457c --- /dev/null +++ b/src/main/resources/data/tiedup/tiedup_room_themes/sandstone.json @@ -0,0 +1,52 @@ +{ + "weight": 10, + "wall_palette": { + "default": [ + { "block": "minecraft:chiseled_sandstone", "weight": 0.10 }, + { "block": "minecraft:sandstone", "weight": 0.20 }, + { "block": "minecraft:cut_sandstone", "weight": 0.70 } + ] + }, + "floor_palette": { + "default": [ + { "block": "minecraft:sand", "weight": 0.15 }, + { "block": "minecraft:smooth_sandstone", "weight": 0.85 } + ] + }, + "ceiling_palette": { + "default": [ + { "block": "minecraft:sandstone", "weight": 0.20 }, + { "block": "minecraft:cut_sandstone", "weight": 0.80 } + ] + }, + "wall_shell": "minecraft:cut_sandstone", + "wall_accent": "minecraft:chiseled_sandstone", + "pillar_palette": { + "default": [ + { "block": "minecraft:sandstone_wall", "weight": 1.0 } + ], + "cap": [ + { "block": "minecraft:chiseled_sandstone", "weight": 1.0 } + ] + }, + "scatter_palette": { + "default": [ + { "block": "minecraft:sand", "weight": 0.40 }, + { "block": "minecraft:dead_bush", "weight": 0.30 }, + { "block": "minecraft:candle[lit=true]", "weight": 0.30, "random_property": { "name": "candles", "min": 1, "max": 3 } } + ] + }, + "decorations": { + "wall_midpoint_blocks": [ + { "block": "minecraft:orange_terracotta", "y_offset": 2 } + ], + "first_corner_special": { "block": "minecraft:tnt", "y_offset": 1 }, + "furniture_cluster": [ + { "block": "minecraft:barrel", "y_offset": 1 }, + { "block": "minecraft:flower_pot", "y_offset": 1 }, + { "block": "minecraft:orange_terracotta", "y_offset": 1 } + ], + "use_torch_lighting": true, + "has_ceiling_chain": true + } +} diff --git a/src/main/resources/data/tiedup/tiedup_room_themes/sculk.json b/src/main/resources/data/tiedup/tiedup_room_themes/sculk.json new file mode 100644 index 0000000..474b66a --- /dev/null +++ b/src/main/resources/data/tiedup/tiedup_room_themes/sculk.json @@ -0,0 +1,58 @@ +{ + "weight": 10, + "wall_palette": { + "default": [ + { "block": "minecraft:cracked_deepslate_bricks", "weight": 0.10 }, + { "block": "minecraft:sculk", "weight": 0.30 }, + { "block": "minecraft:deepslate_bricks", "weight": 0.60 } + ] + }, + "floor_palette": { + "default": [ + { "block": "minecraft:sculk", "weight": 0.30 }, + { "block": "minecraft:deepslate_tiles", "weight": 0.70 } + ], + "edge": [ + { "block": "minecraft:sculk", "weight": 1.0 } + ] + }, + "ceiling_palette": { + "default": [ + { "block": "minecraft:cracked_deepslate_bricks", "weight": 0.10 }, + { "block": "minecraft:sculk", "weight": 0.20 }, + { "block": "minecraft:deepslate_bricks", "weight": 0.70 } + ] + }, + "wall_shell": "minecraft:deepslate_bricks", + "wall_accent": "minecraft:sculk_catalyst", + "pillar_palette": { + "default": [ + { "block": "minecraft:sculk", "weight": 0.30 }, + { "block": "minecraft:deepslate_tile_wall", "weight": 0.70 } + ], + "cap": [ + { "block": "minecraft:sculk", "weight": 1.0 } + ] + }, + "scatter_palette": { + "default": [ + { "block": "minecraft:sculk", "weight": 0.50 }, + { "block": "minecraft:sculk_vein", "weight": 0.30 }, + { "block": "minecraft:moss_carpet", "weight": 0.20 } + ] + }, + "decorations": { + "wall_midpoint_blocks": [ + { "block": "minecraft:sculk_vein", "y_offset": 2 }, + { "block": "minecraft:soul_lantern", "y_offset": 3 } + ], + "first_corner_special": { "block": "minecraft:sculk_catalyst", "y_offset": 1 }, + "furniture_cluster": [ + { "block": "minecraft:sculk_shrieker", "y_offset": 1 }, + { "block": "minecraft:sculk_sensor", "y_offset": 1 }, + { "block": "minecraft:candle[lit=true,candles=3]", "y_offset": 1 } + ], + "use_torch_lighting": false, + "has_ceiling_chain": true + } +}