diff --git a/gradle.properties b/gradle.properties index 3faec8da..c5d8d362 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,7 +8,7 @@ loader_version = 0.10.5+build.213 # Mod Properties - mod_version = 0.5.0-beta + mod_version = 0.5.1-beta maven_group = ru.betterend archives_base_name = better-end diff --git a/src/main/java/ru/betterend/registry/EndFeatures.java b/src/main/java/ru/betterend/registry/EndFeatures.java index 5068dfbb..030ab543 100644 --- a/src/main/java/ru/betterend/registry/EndFeatures.java +++ b/src/main/java/ru/betterend/registry/EndFeatures.java @@ -19,7 +19,6 @@ import ru.betterend.world.features.EndLakeFeature; import ru.betterend.world.features.EndLilyFeature; import ru.betterend.world.features.EndLotusFeature; import ru.betterend.world.features.EndLotusLeafFeature; -import ru.betterend.world.features.EternalPortalFeature; import ru.betterend.world.features.LacugroveFeature; import ru.betterend.world.features.MossyGlowshroomFeature; import ru.betterend.world.features.PythadendronBushFeature; @@ -70,7 +69,7 @@ public class EndFeatures { public static final EndFeature FLAVOLITE_LAYER = EndFeature.makeLayerFeature("flavolite_layer", EndBlocks.FLAVOLITE, 12, 4, 96, 6); // Other // - public static final EndFeature ETERNAL_PORTAL = EndFeature.makeChansedFeature("eternal_portal", new EternalPortalFeature(), 500); + //public static final EndFeature ETERNAL_PORTAL = EndFeature.makeChansedFeature("eternal_portal", new EternalPortalFeature(), 500); public static void registerBiomeFeatures(Identifier id, Biome biome, List>>> features) { if (id.getNamespace().equals("minecraft")) { @@ -91,7 +90,7 @@ public class EndFeatures { addFeature(ENDER_ORE, features); addFeature(ROUND_CAVE_RARE, features); addFeature(CAVE_GRASS, features); - addFeature(ETERNAL_PORTAL, features); + //addFeature(ETERNAL_PORTAL, features); } private static void addFeature(EndFeature feature, List>>> features) { diff --git a/src/main/java/ru/betterend/registry/EndStructures.java b/src/main/java/ru/betterend/registry/EndStructures.java index 3b936335..ca7cd908 100644 --- a/src/main/java/ru/betterend/registry/EndStructures.java +++ b/src/main/java/ru/betterend/registry/EndStructures.java @@ -11,6 +11,7 @@ import net.minecraft.world.gen.GenerationStep.Feature; import net.minecraft.world.gen.feature.ConfiguredStructureFeature; import ru.betterend.BetterEnd; import ru.betterend.world.structures.EndStructureFeature; +import ru.betterend.world.structures.features.StructureEternalPortal; import ru.betterend.world.structures.features.StructureGiantMossyGlowshroom; import ru.betterend.world.structures.features.StructureMegaLake; import ru.betterend.world.structures.features.StructureMountain; @@ -18,6 +19,7 @@ import ru.betterend.world.structures.features.StructurePaintedMountain; import ru.betterend.world.structures.piece.CavePiece; import ru.betterend.world.structures.piece.LakePiece; import ru.betterend.world.structures.piece.MountainPiece; +import ru.betterend.world.structures.piece.NBTPiece; import ru.betterend.world.structures.piece.PaintedMountainPiece; import ru.betterend.world.structures.piece.VoxelPiece; @@ -27,11 +29,13 @@ public class EndStructures { public static final StructurePieceType CAVE_PIECE = register("cave_piece", CavePiece::new); public static final StructurePieceType LAKE_PIECE = register("lake_piece", LakePiece::new); public static final StructurePieceType PAINTED_MOUNTAIN_PIECE = register("painted_mountain_piece", PaintedMountainPiece::new); + public static final StructurePieceType NBT_PIECE = register("nbt_piece", NBTPiece::new); public static final EndStructureFeature GIANT_MOSSY_GLOWSHROOM = new EndStructureFeature("giant_mossy_glowshroom", new StructureGiantMossyGlowshroom(), Feature.SURFACE_STRUCTURES, 16, 8); public static final EndStructureFeature MEGALAKE = new EndStructureFeature("megalake", new StructureMegaLake(), Feature.RAW_GENERATION, 4, 1); public static final EndStructureFeature MOUNTAIN = new EndStructureFeature("mountain", new StructureMountain(), Feature.RAW_GENERATION, 3, 2); public static final EndStructureFeature PAINTED_MOUNTAIN = new EndStructureFeature("painted_mountain", new StructurePaintedMountain(), Feature.RAW_GENERATION, 3, 2); + public static final EndStructureFeature ETERNAL_PORTAL = new EndStructureFeature("eternal_portal", new StructureEternalPortal(), Feature.SURFACE_STRUCTURES, 16, 6); public static void register() {} @@ -40,15 +44,12 @@ public class EndStructures { } public static void registerBiomeStructures(Identifier id, Biome biome, Collection>> structures) { - /*if (id.getNamespace().equals("minecraft")) { - if (id.getPath().equals("end_highlands")) { - structures.clear(); - addStructure(MOUNTAIN, structures); - } - }*/ + if (!id.getPath().contains("mountain")) { + addStructure(ETERNAL_PORTAL, structures); + } } - protected static void addStructure(EndStructureFeature feature, Collection>> collection) { - collection.add(() -> { return feature.getFeatureConfigured(); }); + private static void addStructure(EndStructureFeature feature, Collection>> structures) { + structures.add(() -> { return feature.getFeatureConfigured(); }); } } diff --git a/src/main/java/ru/betterend/util/StructureHelper.java b/src/main/java/ru/betterend/util/StructureHelper.java index eabf3e21..a7681e3f 100644 --- a/src/main/java/ru/betterend/util/StructureHelper.java +++ b/src/main/java/ru/betterend/util/StructureHelper.java @@ -1,74 +1,217 @@ package ru.betterend.util; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Set; +import java.io.IOException; +import java.io.InputStream; +import java.util.Random; -import net.minecraft.server.world.ServerWorld; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.block.Material; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtIo; +import net.minecraft.server.MinecraftServer; +import net.minecraft.structure.Structure; +import net.minecraft.structure.StructurePlacementData; +import net.minecraft.tag.BlockTags; +import net.minecraft.util.BlockMirror; +import net.minecraft.util.BlockRotation; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.BlockBox; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.ChunkPos; -import net.minecraft.world.Heightmap; -import net.minecraft.world.gen.ChunkRandom; -import net.minecraft.world.gen.chunk.ChunkGenerator; -import net.minecraft.world.gen.chunk.StructureConfig; -import net.minecraft.world.gen.feature.StructureFeature; +import net.minecraft.util.math.BlockPos.Mutable; +import net.minecraft.util.math.Direction; +import net.minecraft.world.StructureWorldAccess; +import ru.betterend.registry.EndBlocks; +import ru.betterend.registry.EndTags; public class StructureHelper { - private static final Set POSITIONS = new HashSet(64); + private static final Direction[] DIR = BlocksHelper.makeHorizontal(); + + public static Structure readStructure(Identifier resource) { + String ns = resource.getNamespace(); + String nm = resource.getPath(); - private static void collectNearby(ServerWorld world, StructureFeature feature, int chunkX, int chunkZ, int radius, StructureConfig config, long worldSeed, ChunkRandom chunkRandom) { - int x1 = chunkX - radius; - int x2 = chunkX + radius; - int z1 = chunkZ - radius; - int z2 = chunkZ + radius; - - POSITIONS.clear(); - ChunkGenerator generator = world.getChunkManager().getChunkGenerator(); - for (int x = x1; x <= x2; x += 8) { - for (int z = z1; z <= z2; z += 8) { - ChunkPos chunk = feature.getStartChunk(config, worldSeed, chunkRandom, x, z); - if (world.getBiome(chunk.getStartPos()).getGenerationSettings().hasStructureFeature(feature)) - { - if (feature.getName().equals("endcity")) { - if (generator.getHeight((x << 16) | 8, (z << 16) | 8, Heightmap.Type.WORLD_SURFACE_WG) > 60) { - POSITIONS.add(chunk); - } - } - else { - POSITIONS.add(chunk); - } - } - } + try { + InputStream inputstream = MinecraftServer.class.getResourceAsStream("/data/" + ns + "/structures/" + nm + ".nbt"); + return readStructureFromStream(inputstream); } - } - - private static long sqr(int x) { - return (long) x * (long) x; - } - - public static BlockPos getNearestStructure(StructureFeature feature, ServerWorld world, BlockPos pos, int radius) { - int cx = pos.getX() >> 4; - int cz = pos.getZ() >> 4; - - StructureConfig config = world.getChunkManager().getChunkGenerator().getStructuresConfig().getForType(feature); - if (config == null) - return null; - - collectNearby(world, feature, cx, cz, radius, config, world.getSeed(), new ChunkRandom()); - Iterator iterator = POSITIONS.iterator(); - if (iterator.hasNext()) { - ChunkPos nearest = POSITIONS.iterator().next(); - long d = sqr(nearest.x - cx) + sqr(nearest.z - cz); - while (iterator.hasNext()) { - ChunkPos n = iterator.next(); - long d2 = sqr(n.x - cx) + sqr(n.z - cz); - if (d2 < d) { - d = d2; - nearest = n; - } - } - return nearest.getStartPos(); + catch (IOException e) { + e.printStackTrace(); } + return null; } + + private static Structure readStructureFromStream(InputStream stream) throws IOException { + CompoundTag nbttagcompound = NbtIo.readCompressed(stream); + + Structure template = new Structure(); + template.fromTag(nbttagcompound); + + return template; + } + + public static BlockPos offsetPos(BlockPos pos, Structure structure, BlockRotation rotation, BlockMirror mirror) { + BlockPos offset = Structure.transformAround(structure.getSize(), mirror, rotation, BlockPos.ORIGIN); + return pos.add(-offset.getX() * 0.5, 0, -offset.getZ() * 0.5); + } + + public static void placeCenteredBottom(StructureWorldAccess world, BlockPos pos, Structure structure, BlockRotation rotation, BlockMirror mirror, Random random) { + placeCenteredBottom(world, pos, structure, rotation, mirror, makeBox(pos), random); + } + + public static void placeCenteredBottom(StructureWorldAccess world, BlockPos pos, Structure structure, BlockRotation rotation, BlockMirror mirror, BlockBox bounds, Random random) { + BlockPos offset = offsetPos(pos, structure, rotation, mirror); + StructurePlacementData placementData = new StructurePlacementData().setRotation(rotation).setMirror(mirror).setBoundingBox(bounds); + structure.place(world, offset, placementData, random); + } + + private static BlockBox makeBox(BlockPos pos) { + int sx = ((pos.getX() >> 4) << 4) - 16; + int sz = ((pos.getZ() >> 4) << 4) - 16; + int ex = sx + 47; + int ez = sz + 47; + return BlockBox.create(sx, 0, sz, ex, 255, ez); + } + + public static BlockBox getStructureBounds(BlockPos pos, Structure structure, BlockRotation rotation, BlockMirror mirror) { + BlockPos max = structure.getSize(); + BlockPos min = Structure.transformAround(structure.getSize(), mirror, rotation, BlockPos.ORIGIN); + max = max.subtract(min); + return new BlockBox(min.add(pos), max.add(pos)); + } + + public static void erode(StructureWorldAccess world, BlockBox bounds, int iterations, Random random) { + Mutable mut = new Mutable(); + boolean canDestruct = true; + for (int i = 0; i < iterations; i++) { + for (int x = bounds.minX; x <= bounds.maxX; x++) { + mut.setX(x); + for (int z = bounds.minZ; z <= bounds.maxZ; z++) { + mut.setZ(z); + for (int y = bounds.maxY; y >= bounds.minY; y--) { + mut.setY(y); + BlockState state = world.getBlockState(mut); + if (canDestruct && state.isOf(EndBlocks.FLAVOLITE_RUNED_ETERNAL) && random.nextInt(8) == 0 && world.isAir(mut.down(2))) { + int r = MHelper.randRange(1, 4, random); + int cx = mut.getX(); + int cy = mut.getY(); + int cz = mut.getZ(); + int x1 = cx - r; + int y1 = cy - r; + int z1 = cz - r; + int x2 = cx + r; + int y2 = cy + r; + int z2 = cz + r; + for (int px = x1; px <= x2; px++) { + int dx = px - cx; + dx *= dx; + mut.setX(px); + for (int py = y1; py <= y2; py++) { + int dy = py - cy; + dy *= dy; + mut.setY(py); + for (int pz = z1; pz <= z2; pz++) { + int dz = pz - cz; + dz *= dz; + mut.setZ(pz); + if (dx + dy + dz <= r && world.getBlockState(mut).isOf(EndBlocks.FLAVOLITE_RUNED_ETERNAL)) { + BlocksHelper.setWithoutUpdate(world, mut, Blocks.AIR); + } + } + } + } + mut.setX(cx); + mut.setY(cy); + mut.setZ(cz); + canDestruct = false; + continue; + } + else if (ignore(state)) { + continue; + } + if (!state.isAir() && random.nextBoolean()) { + shuffle(random); + for (Direction dir: DIR) { + if (world.isAir(mut.offset(dir)) && world.isAir(mut.down().offset(dir))) { + BlocksHelper.setWithoutUpdate(world, mut, Blocks.AIR); + mut.move(dir).move(Direction.DOWN); + for (int py = mut.getY(); y >= bounds.minY - 10; y--) { + mut.setY(py - 1); + if (!world.isAir(mut)) { + mut.setY(py); + BlocksHelper.setWithoutUpdate(world, mut, state); + break; + } + } + } + } + break; + } + else if (random.nextInt(8) == 0 && !world.getBlockState(mut.up()).isOf(EndBlocks.ETERNAL_PEDESTAL)) { + BlocksHelper.setWithoutUpdate(world, mut, Blocks.AIR); + } + } + } + } + } + for (int x = bounds.minX; x <= bounds.maxX; x++) { + mut.setX(x); + for (int z = bounds.minZ; z <= bounds.maxZ; z++) { + mut.setZ(z); + for (int y = bounds.maxY; y >= bounds.minY; y--) { + mut.setY(y); + BlockState state = world.getBlockState(mut); + if (!ignore(state) && world.isAir(mut.down())) { + BlocksHelper.setWithoutUpdate(world, mut, Blocks.AIR); + for (int py = mut.getY(); y >= bounds.minY - 10; y--) { + mut.setY(py - 1); + if (!world.isAir(mut)) { + mut.setY(py); + BlocksHelper.setWithoutUpdate(world, mut, state); + break; + } + } + } + } + } + } + } + + private static boolean ignore(BlockState state) { + return state.isAir() + || state.isIn(EndTags.END_GROUND) + || state.isOf(EndBlocks.ETERNAL_PEDESTAL) + || state.isOf(EndBlocks.FLAVOLITE_RUNED_ETERNAL) + || state.isIn(BlockTags.LOGS) + || state.isIn(BlockTags.LEAVES) + || state.getMaterial().equals(Material.PLANT); + } + + private static void shuffle(Random random) { + for (int i = 0; i < 4; i++) { + int j = random.nextInt(4); + Direction d = DIR[i]; + DIR[i] = DIR[j]; + DIR[j] = d; + } + } + + public static void cover(StructureWorldAccess world, BlockBox bounds, Random random) { + Mutable mut = new Mutable(); + for (int x = bounds.minX; x <= bounds.maxX; x++) { + mut.setX(x); + for (int z = bounds.minZ; z <= bounds.maxZ; z++) { + mut.setZ(z); + BlockState top = world.getBiome(mut).getGenerationSettings().getSurfaceConfig().getTopMaterial(); + for (int y = bounds.maxY; y >= bounds.minY; y--) { + mut.setY(y); + BlockState state = world.getBlockState(mut); + if (state.isIn(EndTags.END_GROUND) && !world.getBlockState(mut.up()).getMaterial().blocksLight()) { + BlocksHelper.setWithoutUpdate(world, mut, top); + } + } + } + } + } } diff --git a/src/main/java/ru/betterend/world/features/EternalPortalFeature.java b/src/main/java/ru/betterend/world/features/EternalPortalFeature.java deleted file mode 100644 index 792c2545..00000000 --- a/src/main/java/ru/betterend/world/features/EternalPortalFeature.java +++ /dev/null @@ -1,64 +0,0 @@ -package ru.betterend.world.features; - -import java.util.Random; - -import net.minecraft.structure.Structure; -import net.minecraft.structure.StructurePlacementData; -import net.minecraft.util.BlockMirror; -import net.minecraft.util.BlockRotation; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.StructureWorldAccess; -import ru.betterend.BetterEnd; -import ru.betterend.registry.EndTags; -import ru.betterend.util.MHelper; - -public class EternalPortalFeature extends NBTStructureFeature { - private static final Structure PORTAL = readStructure(BetterEnd.makeID("portal/eternal_portal")); - - @Override - protected Structure getStructure() { - return PORTAL; - } - - @Override - protected boolean canSpawn(StructureWorldAccess world, BlockPos pos) { - if (world.getBlockState(pos.down()).isIn(EndTags.END_GROUND)) { - return world.getBlockState(pos.north(2)).getMaterial().isReplaceable() - && world.getBlockState(pos.south(2)).getMaterial().isReplaceable() - && world.getBlockState(pos.east(2)).getMaterial().isReplaceable() - && world.getBlockState(pos.west(2)).getMaterial().isReplaceable(); - } - return false; - } - - @Override - protected BlockRotation getRotation(StructureWorldAccess world, BlockPos pos, Random random) { - return BlockRotation.random(random); - } - - @Override - protected BlockMirror getMirror(StructureWorldAccess world, BlockPos pos, Random random) { - return BlockMirror.values()[random.nextInt(3)]; - } - - @Override - protected int getYOffset(Structure structure, StructureWorldAccess world, BlockPos pos, Random random) { - return -3; - } - - @Override - protected void addProcessors(StructurePlacementData placementData, Random random) { - DESTRUCTION.setChance(MHelper.randRange(4, 16, random)); - placementData.addProcessor(DESTRUCTION); - } - - @Override - protected boolean hasErosion() { - return true; - } - - @Override - protected boolean hasTerrainOverlay() { - return true; - } -} diff --git a/src/main/java/ru/betterend/world/structures/features/StructureEternalPortal.java b/src/main/java/ru/betterend/world/structures/features/StructureEternalPortal.java new file mode 100644 index 00000000..a51ecf22 --- /dev/null +++ b/src/main/java/ru/betterend/world/structures/features/StructureEternalPortal.java @@ -0,0 +1,45 @@ +package ru.betterend.world.structures.features; + +import net.minecraft.structure.Structure; +import net.minecraft.structure.StructureManager; +import net.minecraft.structure.StructureStart; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.BlockBox; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.registry.DynamicRegistryManager; +import net.minecraft.world.Heightmap.Type; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.gen.chunk.ChunkGenerator; +import net.minecraft.world.gen.feature.DefaultFeatureConfig; +import net.minecraft.world.gen.feature.StructureFeature; +import ru.betterend.BetterEnd; +import ru.betterend.util.MHelper; +import ru.betterend.util.StructureHelper; +import ru.betterend.world.structures.piece.NBTPiece; + +public class StructureEternalPortal extends StructureFeatureBase { + private static final Identifier STRUCTURE_ID = BetterEnd.makeID("portal/eternal_portal"); + private static final Structure STRUCTURE = StructureHelper.readStructure(STRUCTURE_ID); + + @Override + public StructureFeature.StructureStartFactory getStructureStartFactory() { + return SDFStructureStart::new; + } + + public static class SDFStructureStart extends StructureStart { + public SDFStructureStart(StructureFeature feature, int chunkX, int chunkZ, BlockBox box, int references, long seed) { + super(feature, chunkX, chunkZ, box, references, seed); + } + + @Override + public void init(DynamicRegistryManager registryManager, ChunkGenerator chunkGenerator, StructureManager manager, int chunkX, int chunkZ, Biome biome, DefaultFeatureConfig config) { + int x = (chunkX << 4) | MHelper.randRange(4, 12, random); + int z = (chunkZ << 4) | MHelper.randRange(4, 12, random); + int y = chunkGenerator.getHeight(x, z, Type.WORLD_SURFACE_WG); + if (y > 50) { + this.children.add(new NBTPiece(STRUCTURE_ID, STRUCTURE, new BlockPos(x, y - 3, z), random.nextInt(5), true, random)); + } + this.setBoundingBoxFromChildren(); + } + } +} diff --git a/src/main/java/ru/betterend/world/structures/piece/LakePiece.java b/src/main/java/ru/betterend/world/structures/piece/LakePiece.java index 10807b82..34d6e91a 100644 --- a/src/main/java/ru/betterend/world/structures/piece/LakePiece.java +++ b/src/main/java/ru/betterend/world/structures/piece/LakePiece.java @@ -125,16 +125,7 @@ public class LakePiece extends BasePiece { BlockState state = chunk.getBlockState(pos); if (state.getMaterial().isReplaceable() || state.isIn(EndTags.GEN_TERRAIN)) { if (pos.getY() > 56) { - pos.setY(pos.getY() + 1); - state = chunk.getBlockState(pos); - pos.setY(pos.getY() - 1); - if (state.getMaterial().isReplaceable()) { - state = world.getBiome(pos.add(sx, 0, sz)).getGenerationSettings().getSurfaceConfig().getTopMaterial(); - } - else { - state = EndBlocks.ENDSTONE_DUST.getDefaultState(); - } - chunk.setBlockState(pos, state, false); + chunk.setBlockState(pos, AIR, false); } else if (pos.getY() == 56) { if (random.nextBoolean()) { diff --git a/src/main/java/ru/betterend/world/structures/piece/NBTPiece.java b/src/main/java/ru/betterend/world/structures/piece/NBTPiece.java new file mode 100644 index 00000000..5e768f60 --- /dev/null +++ b/src/main/java/ru/betterend/world/structures/piece/NBTPiece.java @@ -0,0 +1,93 @@ +package ru.betterend.world.structures.piece; + +import java.util.Random; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtHelper; +import net.minecraft.structure.Structure; +import net.minecraft.structure.StructureManager; +import net.minecraft.structure.StructurePlacementData; +import net.minecraft.util.BlockMirror; +import net.minecraft.util.BlockRotation; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.BlockBox; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.world.StructureWorldAccess; +import net.minecraft.world.gen.StructureAccessor; +import net.minecraft.world.gen.chunk.ChunkGenerator; +import ru.betterend.registry.EndStructures; +import ru.betterend.util.MHelper; +import ru.betterend.util.StructureHelper; + +public class NBTPiece extends BasePiece { + private Identifier structureID; + private BlockRotation rotation; + private BlockMirror mirror; + private Structure structure; + private BlockPos pos; + private int erosion; + private boolean cover; + + public NBTPiece(Identifier structureID, Structure structure, BlockPos pos, int erosion, boolean cover, Random random) { + super(EndStructures.NBT_PIECE, random.nextInt()); + this.structureID = structureID; + this.structure = structure; + this.rotation = BlockRotation.random(random); + this.mirror = BlockMirror.values()[random.nextInt(3)]; + this.pos = StructureHelper.offsetPos(pos, structure, rotation, mirror); + this.erosion = erosion; + this.cover = cover; + makeBoundingBox(); + } + + public NBTPiece(StructureManager manager, CompoundTag tag) { + super(EndStructures.NBT_PIECE, tag); + makeBoundingBox(); + } + + @Override + protected void toNbt(CompoundTag tag) { + tag.putString("id", structureID.toString()); + tag.putInt("rotation", rotation.ordinal()); + tag.putInt("mirror", mirror.ordinal()); + tag.putInt("erosion", erosion); + tag.put("pos", NbtHelper.fromBlockPos(pos)); + tag.putBoolean("cover", cover); + } + + @Override + protected void fromNbt(CompoundTag tag) { + structureID = new Identifier(tag.getString("id")); + rotation = BlockRotation.values()[tag.getInt("rotation")]; + mirror = BlockMirror.values()[tag.getInt("mirror")]; + erosion = tag.getInt("erosion"); + pos = NbtHelper.toBlockPos(tag.getCompound("pos")); + cover = tag.getBoolean("cover"); + structure = StructureHelper.readStructure(structureID); + } + + @Override + public boolean generate(StructureWorldAccess world, StructureAccessor arg, ChunkGenerator chunkGenerator, Random random, BlockBox blockBox, ChunkPos chunkPos, BlockPos blockPos) { + BlockBox bounds = new BlockBox(blockBox); + bounds.maxY = this.boundingBox.maxY; + bounds.minY = this.boundingBox.minY; + StructurePlacementData placementData = new StructurePlacementData().setRotation(rotation).setMirror(mirror).setBoundingBox(bounds); + structure.place(world, pos, placementData, random); + if (erosion > 0) { + bounds.maxX = MHelper.min(bounds.maxX, boundingBox.maxX); + bounds.minX = MHelper.max(bounds.minX, boundingBox.minX); + bounds.maxZ = MHelper.min(bounds.maxZ, boundingBox.maxZ); + bounds.minZ = MHelper.max(bounds.minZ, boundingBox.minZ); + StructureHelper.erode(world, bounds, erosion, random); + } + if (cover) { + StructureHelper.cover(world, bounds, random); + } + return true; + } + + private void makeBoundingBox() { + this.boundingBox = StructureHelper.getStructureBounds(pos, structure, rotation, mirror); + } +}