From 40f8342732896e5728a25ced9df549ae6579358d Mon Sep 17 00:00:00 2001 From: paulevsGitch Date: Mon, 2 Nov 2020 15:05:26 +0300 Subject: [PATCH] Portals as structure feature --- gradle.properties | 2 +- .../ru/betterend/registry/EndFeatures.java | 5 +- .../ru/betterend/registry/EndStructures.java | 17 +-- .../ru/betterend/util/StructureHelper.java | 123 +++++++++--------- .../features/StructureEternalPortal.java | 45 +++++++ .../world/structures/piece/LakePiece.java | 11 +- .../world/structures/piece/NBTPiece.java | 71 ++++++++++ 7 files changed, 190 insertions(+), 84 deletions(-) create mode 100644 src/main/java/ru/betterend/world/structures/features/StructureEternalPortal.java create mode 100644 src/main/java/ru/betterend/world/structures/piece/NBTPiece.java 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..9d22cbe9 100644 --- a/src/main/java/ru/betterend/util/StructureHelper.java +++ b/src/main/java/ru/betterend/util/StructureHelper.java @@ -1,74 +1,73 @@ 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.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.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.world.StructureWorldAccess; public class StructureHelper { - private static final Set POSITIONS = new HashSet(64); + 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)); + } } 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..e41202f5 --- /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)); + } + 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..be03d741 --- /dev/null +++ b/src/main/java/ru/betterend/world/structures/piece/NBTPiece.java @@ -0,0 +1,71 @@ +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.StructureHelper; + +public class NBTPiece extends BasePiece { + private Identifier structureID; + private BlockRotation rotation; + private BlockMirror mirror; + private Structure structure; + private BlockPos pos; + + public NBTPiece(Identifier structureID, Structure structure, BlockPos pos, 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); + 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.put("pos", NbtHelper.fromBlockPos(pos)); + } + + @Override + protected void fromNbt(CompoundTag tag) { + structureID = new Identifier(tag.getString("id")); + rotation = BlockRotation.values()[tag.getInt("rotation")]; + mirror = BlockMirror.values()[tag.getInt("mirror")]; + pos = NbtHelper.toBlockPos(tag.getCompound("pos")); + structure = StructureHelper.readStructure(structureID); + } + + @Override + public boolean generate(StructureWorldAccess world, StructureAccessor arg, ChunkGenerator chunkGenerator, Random random, BlockBox blockBox, ChunkPos chunkPos, BlockPos blockPos) { + StructurePlacementData placementData = new StructurePlacementData().setRotation(rotation).setMirror(mirror).setBoundingBox(blockBox); + structure.place(world, pos, placementData, random); + return true; + } + + private void makeBoundingBox() { + this.boundingBox = StructureHelper.getStructureBounds(pos, structure, rotation, mirror); + } +}