diff --git a/src/main/java/ru/betterend/registry/EndBiomes.java b/src/main/java/ru/betterend/registry/EndBiomes.java index 72ad1329..5434af5a 100644 --- a/src/main/java/ru/betterend/registry/EndBiomes.java +++ b/src/main/java/ru/betterend/registry/EndBiomes.java @@ -85,14 +85,6 @@ public class EndBiomes { CLIENT.clear(); } - private static EndBiome registerBiome(RegistryKey key, BiomeType type, float genChance) { - return registerBiome(BuiltinRegistries.BIOME.get(key), type, genChance); - } - - private static EndBiome registerSubBiome(RegistryKey key, EndBiome parent, float genChance) { - return registerSubBiome(BuiltinRegistries.BIOME.get(key), parent, genChance); - } - /** * Registers new {@link EndBiome} and adds it to picker, can be used to add existing mod biomes into the End. * @param biome - {@link Biome} instance @@ -173,6 +165,14 @@ public class EndBiomes { return biome; } + private static EndBiome registerBiome(RegistryKey key, BiomeType type, float genChance) { + return registerBiome(BuiltinRegistries.BIOME.get(key), type, genChance); + } + + private static EndBiome registerSubBiome(RegistryKey key, EndBiome parent, float genChance) { + return registerSubBiome(BuiltinRegistries.BIOME.get(key), parent, genChance); + } + private static void addToPicker(EndBiome biome, BiomeType type) { if (type == BiomeType.LAND) LAND_BIOMES.addBiome(biome); diff --git a/src/main/java/ru/betterend/registry/EndFeatures.java b/src/main/java/ru/betterend/registry/EndFeatures.java index f2385ac3..db56bd86 100644 --- a/src/main/java/ru/betterend/registry/EndFeatures.java +++ b/src/main/java/ru/betterend/registry/EndFeatures.java @@ -20,6 +20,7 @@ import ru.betterend.world.features.EndLilyFeature; import ru.betterend.world.features.EndLotusFeature; import ru.betterend.world.features.EndLotusLeafFeature; import ru.betterend.world.features.EndPortalFeature; +import ru.betterend.world.features.EteranlPortalFeature; import ru.betterend.world.features.LacugroveFeature; import ru.betterend.world.features.MossyGlowshroomFeature; import ru.betterend.world.features.PythadendronBushFeature; @@ -70,6 +71,8 @@ public class EndFeatures { public static final EndPortalFeature END_PORTAL = new EndPortalFeature(new DefaultEndPortalFeature(), (RunedFlavolite) EndBlocks.FLAVOLITE_RUNED); public static final EndPortalFeature END_PORTAL_ETERNAL = new EndPortalFeature(new DefaultEndPortalFeature(), (RunedFlavolite) EndBlocks.FLAVOLITE_RUNED_ETERNAL); + public static final EndFeature ETERNAL_PORTAL = EndFeature.makeChancedFeature("eternal_portal", new EteranlPortalFeature(), 500); + public static void registerBiomeFeatures(Identifier id, Biome biome, List>>> features) { if (id.getNamespace().equals("minecraft")) { String path = id.getPath(); @@ -89,6 +92,7 @@ public class EndFeatures { addFeature(ENDER_ORE, features); addFeature(ROUND_CAVE_RARE, features); addFeature(CAVE_GRASS, features); + addFeature(ETERNAL_PORTAL, features); } private static void addFeature(EndFeature feature, List>>> features) { diff --git a/src/main/java/ru/betterend/world/features/DefaultFeature.java b/src/main/java/ru/betterend/world/features/DefaultFeature.java index 239e6c4f..adf0ff64 100644 --- a/src/main/java/ru/betterend/world/features/DefaultFeature.java +++ b/src/main/java/ru/betterend/world/features/DefaultFeature.java @@ -17,6 +17,14 @@ public abstract class DefaultFeature extends Feature { super(DefaultFeatureConfig.CODEC); } + public static int getYOnSurface(StructureWorldAccess world, int x, int z) { + return world.getTopY(Type.WORLD_SURFACE, x, z); + } + + public static int getYOnSurfaceWG(StructureWorldAccess world, int x, int z) { + return world.getTopY(Type.WORLD_SURFACE_WG, x, z); + } + public static BlockPos getPosOnSurface(StructureWorldAccess world, BlockPos pos) { return world.getTopPosition(Type.WORLD_SURFACE, pos); } diff --git a/src/main/java/ru/betterend/world/features/EndFeature.java b/src/main/java/ru/betterend/world/features/EndFeature.java index 672814d7..e170e8c7 100644 --- a/src/main/java/ru/betterend/world/features/EndFeature.java +++ b/src/main/java/ru/betterend/world/features/EndFeature.java @@ -97,6 +97,11 @@ public class EndFeature { return new EndFeature(name, feature, GenerationStep.Feature.LOCAL_MODIFICATIONS, configured); } + public static EndFeature makeChancedFeature(String name, Feature feature, int chance) { + ConfiguredFeature configured = feature.configure(FeatureConfig.DEFAULT).decorate(Decorator.CHANCE.configure(new ChanceDecoratorConfig(chance))); + return new EndFeature(name, feature, GenerationStep.Feature.SURFACE_STRUCTURES, configured); + } + public Feature getFeature() { return feature; } diff --git a/src/main/java/ru/betterend/world/features/EteranlPortalFeature.java b/src/main/java/ru/betterend/world/features/EteranlPortalFeature.java new file mode 100644 index 00000000..c9127144 --- /dev/null +++ b/src/main/java/ru/betterend/world/features/EteranlPortalFeature.java @@ -0,0 +1,46 @@ +package ru.betterend.world.features; + +import java.util.Random; + +import net.minecraft.structure.Structure; +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; + +public class EteranlPortalFeature 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; + } +} diff --git a/src/main/java/ru/betterend/world/features/NBTStructureFeature.java b/src/main/java/ru/betterend/world/features/NBTStructureFeature.java new file mode 100644 index 00000000..c39b452d --- /dev/null +++ b/src/main/java/ru/betterend/world/features/NBTStructureFeature.java @@ -0,0 +1,98 @@ +package ru.betterend.world.features; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Random; + +import net.minecraft.block.Blocks; +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.world.StructureWorldAccess; +import net.minecraft.world.gen.chunk.ChunkGenerator; +import net.minecraft.world.gen.feature.DefaultFeatureConfig; +import ru.betterend.util.BlocksHelper; + +public abstract class NBTStructureFeature extends DefaultFeature { + protected abstract Structure getStructure(); + + protected abstract boolean canSpawn(StructureWorldAccess world, BlockPos pos); + + protected abstract BlockRotation getRotation(StructureWorldAccess world, BlockPos pos, Random random); + + protected abstract BlockMirror getMirror(StructureWorldAccess world, BlockPos pos, Random random); + + protected abstract int getYOffset(Structure structure, StructureWorldAccess world, BlockPos pos, Random random); + + protected BlockPos getGround(StructureWorldAccess world, BlockPos center) { + return getPosOnSurfaceWG(world, center); + } + + @Override + public boolean generate(StructureWorldAccess world, ChunkGenerator chunkGenerator, Random random, BlockPos center, DefaultFeatureConfig featureConfig) { + BlockPos a = center; + center = new BlockPos(((center.getX() >> 4) << 4) | 8, 128, ((center.getZ() >> 4) << 4) | 8); + center = getGround(world, center); + + if (!canSpawn(world, center)) { + return false; + } + + Structure structure = getStructure(); + BlockRotation rotation = getRotation(world, center, random); + BlockMirror mirror = getMirror(world, center, random); + BlockPos size = structure.getSize().rotate(rotation); + double px = size.getX(); + double pz = size.getZ(); + if (mirror == BlockMirror.FRONT_BACK) + px = -px; + if (mirror == BlockMirror.LEFT_RIGHT) + pz = -pz; + + center = center.add(-px * 0.5, 0, -pz * 0.5); + //center.subtract(structure.getRotatedSize(rotation)); + int offset = getYOffset(structure, world, center, random); + center = center.add(0, offset, 0); + StructurePlacementData placementData = new StructurePlacementData() + .setRotation(rotation) + .setMirror(mirror) + .setPosition(center) + .setBoundingBox(BlockBox.create(center.getX() - 8 - 15, 0, center.getZ() - 8 - 15, center.getX() + 8 + 15, 128, center.getZ() + 8 + 15)); + structure.place(world, center, placementData, random); + BlocksHelper.setWithoutUpdate(world, new BlockPos(a.getX(), center.getY() + 10, a.getZ()), Blocks.DIAMOND_BLOCK); + BlocksHelper.setWithoutUpdate(world, center, Blocks.GOLD_BLOCK); + + return true; + } + + protected static Structure readStructure(Identifier resource) { + String ns = resource.getNamespace(); + String nm = resource.getPath(); + + try { + InputStream inputstream = MinecraftServer.class.getResourceAsStream("/data/" + ns + "/structures/" + nm + ".nbt"); + return readStructureFromStream(inputstream); + } + 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; + } +} diff --git a/src/main/resources/data/betterend/structures/portal/eternal_portal.nbt b/src/main/resources/data/betterend/structures/portal/eternal_portal.nbt new file mode 100644 index 00000000..2e3acc9a Binary files /dev/null and b/src/main/resources/data/betterend/structures/portal/eternal_portal.nbt differ