From 6630ce0cab0c12b44ddb54f6cc7c67864e67a84c Mon Sep 17 00:00:00 2001 From: Aleksey Date: Sun, 4 Apr 2021 14:56:18 +0300 Subject: [PATCH] Portal islands --- .../ru/betterend/registry/EndFeatures.java | 4 +- .../ru/betterend/rituals/EternalRitual.java | 33 +++++---- .../java/ru/betterend/util/BlocksHelper.java | 8 ++- .../world/features/BiomeIslandFeature.java | 69 +++++++++++++++++++ .../betterend/world/features/EndFeature.java | 2 +- .../features/OverworldIslandFeature.java | 47 ------------- 6 files changed, 98 insertions(+), 65 deletions(-) create mode 100644 src/main/java/ru/betterend/world/features/BiomeIslandFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/OverworldIslandFeature.java diff --git a/src/main/java/ru/betterend/registry/EndFeatures.java b/src/main/java/ru/betterend/registry/EndFeatures.java index ac5616d2..cc003815 100644 --- a/src/main/java/ru/betterend/registry/EndFeatures.java +++ b/src/main/java/ru/betterend/registry/EndFeatures.java @@ -29,7 +29,7 @@ import ru.betterend.world.features.HydraluxFeature; import ru.betterend.world.features.LanceleafFeature; import ru.betterend.world.features.MengerSpongeFeature; import ru.betterend.world.features.NeonCactusFeature; -import ru.betterend.world.features.OverworldIslandFeature; +import ru.betterend.world.features.BiomeIslandFeature; import ru.betterend.world.features.SilkMothNestFeature; import ru.betterend.world.features.SingleInvertedScatterFeature; import ru.betterend.world.features.SinglePlantFeature; @@ -179,7 +179,7 @@ public class EndFeatures { public static final EndFeature CHARNIA_GREEN = new EndFeature("charnia_green", new CharniaFeature(EndBlocks.CHARNIA_GREEN), 10); public static final EndFeature MENGER_SPONGE = new EndFeature("menger_sponge", new MengerSpongeFeature(5), 1); public static final EndFeature CHARNIA_RED_RARE = new EndFeature("charnia_red_rare", new CharniaFeature(EndBlocks.CHARNIA_RED), 2); - public static final EndFeature OVERWORLD_ISLAND = EndFeature.makeFetureConfigured("overworld_island", new OverworldIslandFeature()); + public static final EndFeature BIOME_ISLAND = EndFeature.makeFeatureConfigured("overworld_island", new BiomeIslandFeature()); public static final EndFeature FLAMAEA = new EndFeature("flamaea", new SinglePlantFeature(EndBlocks.FLAMAEA, 12, false, 5), 20); // Terrain // diff --git a/src/main/java/ru/betterend/rituals/EternalRitual.java b/src/main/java/ru/betterend/rituals/EternalRitual.java index 76afba18..ab031512 100644 --- a/src/main/java/ru/betterend/rituals/EternalRitual.java +++ b/src/main/java/ru/betterend/rituals/EternalRitual.java @@ -8,7 +8,6 @@ import java.util.Set; import java.util.function.Predicate; import com.google.common.collect.Lists; -import net.minecraft.util.BlockRotation; import net.minecraft.world.chunk.ChunkSection; import net.minecraft.world.chunk.WorldChunk; import org.jetbrains.annotations.Nullable; @@ -38,6 +37,7 @@ import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.dimension.DimensionType; import net.minecraft.world.gen.feature.ConfiguredFeatures; +import ru.betterend.BetterEnd; import ru.betterend.blocks.BlockProperties; import ru.betterend.blocks.EndPortalBlock; import ru.betterend.blocks.RunedFlavolite; @@ -158,22 +158,29 @@ public class EternalRitual { if (active) return; Identifier itemId = Registry.ITEM.getId(keyItem); int portalId = EndPortals.getPortalIdByItem(itemId); - activatePortal(world, center, portalId); - doEffects((ServerWorld) world, center); World targetWorld = getTargetWorld(portalId); Identifier worldId = targetWorld.getRegistryKey().getValue(); - if (exit == null) { - initPortal(worldId, portalId); - } else { - if (!worldId.equals(targetWorldId)) { + try { + if (exit == null) { initPortal(worldId, portalId); - } else if (!checkFrame(targetWorld, exit.down())) { - Direction.Axis portalAxis = (Direction.Axis.X == axis) ? Direction.Axis.Z : Direction.Axis.X; - generatePortal(targetWorld, exit, portalAxis, portalId); + } else { + if (!worldId.equals(targetWorldId)) { + initPortal(worldId, portalId); + } else if (!checkFrame(targetWorld, exit.down())) { + Direction.Axis portalAxis = (Direction.Axis.X == axis) ? Direction.Axis.Z : Direction.Axis.X; + generatePortal(targetWorld, exit, portalAxis, portalId); + } + activatePortal(targetWorld, exit, portalId); } - activatePortal(targetWorld, exit, portalId); + activatePortal(world, center, portalId); + doEffects((ServerWorld) world, center); + active = true; + } catch (Exception ex) { + BetterEnd.LOGGER.error("Create End portals error.", ex); + removePortal(targetWorld, exit); + removePortal(world, center); + active = false; } - this.active = true; } private void initPortal(Identifier worldId, int portalId) { @@ -328,8 +335,8 @@ public class EternalRitual { ConfiguredFeatures.END_ISLAND.generate(targetWorld, targetWorld.getChunkManager().getChunkGenerator(), new Random(basePos.asLong()), basePos.down()); } else if (targetWorld.getRegistryKey() == World.OVERWORLD) { basePos.setY(targetWorld.getChunk(basePos).sampleHeightmap(Heightmap.Type.WORLD_SURFACE, basePos.getX(), basePos.getZ()) + 1); - EndFeatures.OVERWORLD_ISLAND.getFeatureConfigured().generate(targetWorld, targetWorld.getChunkManager().getChunkGenerator(), new Random(basePos.asLong()), basePos.down()); } + EndFeatures.BIOME_ISLAND.getFeatureConfigured().generate(targetWorld, targetWorld.getChunkManager().getChunkGenerator(), new Random(basePos.asLong()), basePos.down()); generatePortal(targetWorld, basePos, portalAxis, portalId); return basePos.toImmutable(); } diff --git a/src/main/java/ru/betterend/util/BlocksHelper.java b/src/main/java/ru/betterend/util/BlocksHelper.java index 87371a24..fe2601ab 100644 --- a/src/main/java/ru/betterend/util/BlocksHelper.java +++ b/src/main/java/ru/betterend/util/BlocksHelper.java @@ -121,11 +121,11 @@ public class BlocksHelper { } public static BlockState rotateHorizontal(BlockState state, BlockRotation rotation, Property facing) { - return (BlockState) state.with(facing, rotation.rotate((Direction) state.get(facing))); + return state.with(facing, rotation.rotate(state.get(facing))); } public static BlockState mirrorHorizontal(BlockState state, BlockMirror mirror, Property facing) { - return state.rotate(mirror.getRotation((Direction) state.get(facing))); + return state.rotate(mirror.getRotation(state.get(facing))); } public static int getLengthDown(WorldAccess world, BlockPos pos, Block block) { @@ -364,4 +364,8 @@ public class BlocksHelper { public static Direction randomDirection(Random random) { return DIRECTIONS[random.nextInt(6)]; } + + public static boolean isFluid(BlockState blockState) { + return !blockState.getFluidState().isEmpty(); + } } diff --git a/src/main/java/ru/betterend/world/features/BiomeIslandFeature.java b/src/main/java/ru/betterend/world/features/BiomeIslandFeature.java new file mode 100644 index 00000000..e203909d --- /dev/null +++ b/src/main/java/ru/betterend/world/features/BiomeIslandFeature.java @@ -0,0 +1,69 @@ +package ru.betterend.world.features; + +import java.util.Random; + +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.BlockPos.Mutable; +import net.minecraft.world.StructureWorldAccess; +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.surfacebuilder.SurfaceConfig; +import net.minecraft.world.gen.surfacebuilder.TernarySurfaceConfig; +import ru.betterend.noise.OpenSimplexNoise; +import ru.betterend.util.BlocksHelper; +import ru.betterend.util.sdf.SDF; +import ru.betterend.util.sdf.operator.SDFDisplacement; +import ru.betterend.util.sdf.operator.SDFTranslate; +import ru.betterend.util.sdf.primitive.SDFCappedCone; + +public class BiomeIslandFeature extends DefaultFeature { + private static final Mutable CENTER = new Mutable(); + private static final SDF ISLAND; + + private static OpenSimplexNoise simplexNoise = new OpenSimplexNoise(412L); + private static BlockState topBlock = Blocks.GRASS_BLOCK.getDefaultState(); + private static BlockState underBlock = Blocks.DIRT.getDefaultState(); + + @Override + public boolean generate(StructureWorldAccess world, ChunkGenerator chunkGenerator, Random random, BlockPos pos, DefaultFeatureConfig config) { + Biome biome = world.getBiome(pos); + SurfaceConfig surfaceConfig = biome.getGenerationSettings().getSurfaceConfig(); + BlockState topMaterial = surfaceConfig.getTopMaterial(); + if (BlocksHelper.isFluid(topMaterial)) { + topBlock = ((TernarySurfaceConfig) surfaceConfig).getUnderwaterMaterial(); + } else { + topBlock = topMaterial; + } + underBlock = surfaceConfig.getUnderMaterial(); + simplexNoise = new OpenSimplexNoise(world.getSeed()); + CENTER.set(pos); + ISLAND.fillRecursive(world, pos.down()); + return true; + } + + private static SDF createSDFIsland() { + SDF sdfCone = new SDFCappedCone().setRadius1(0).setRadius2(6).setHeight(4).setBlock(pos -> { + if (pos.getY() > CENTER.getY()) return AIR; + if (pos.getY() == CENTER.getY()) return topBlock; + return underBlock; + }); + sdfCone = new SDFTranslate().setTranslate(0, -2, 0).setSource(sdfCone); + sdfCone = new SDFDisplacement().setFunction(pos -> { + float deltaX = Math.abs(pos.getX()); + float deltaY = Math.abs(pos.getY()); + float deltaZ = Math.abs(pos.getZ()); + if (deltaY < 2.0f && (deltaX < 3.0f || deltaZ < 3.0F)) return 0.0f; + return (float) simplexNoise.eval(CENTER.getX() + pos.getX(), + CENTER.getY() + pos.getY(), CENTER.getZ() + pos.getZ()); + }).setSource(sdfCone).setReplaceFunction(state -> BlocksHelper.isFluid(state) || + state.getMaterial().isReplaceable()); + return sdfCone; + } + + static { + ISLAND = createSDFIsland(); + } +} diff --git a/src/main/java/ru/betterend/world/features/EndFeature.java b/src/main/java/ru/betterend/world/features/EndFeature.java index 09a9484b..b1891370 100644 --- a/src/main/java/ru/betterend/world/features/EndFeature.java +++ b/src/main/java/ru/betterend/world/features/EndFeature.java @@ -114,7 +114,7 @@ public class EndFeature { return new EndFeature(name, feature, GenerationStep.Feature.RAW_GENERATION, configured); } - public static EndFeature makeFetureConfigured(String name, Feature feature) { + public static EndFeature makeFeatureConfigured(String name, Feature feature) { ConfiguredFeature configured = feature.configure(FeatureConfig.DEFAULT); return new EndFeature(name, feature, GenerationStep.Feature.RAW_GENERATION, configured); } diff --git a/src/main/java/ru/betterend/world/features/OverworldIslandFeature.java b/src/main/java/ru/betterend/world/features/OverworldIslandFeature.java deleted file mode 100644 index a9a2ac41..00000000 --- a/src/main/java/ru/betterend/world/features/OverworldIslandFeature.java +++ /dev/null @@ -1,47 +0,0 @@ -package ru.betterend.world.features; - -import java.util.Random; - -import net.minecraft.block.Blocks; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.BlockPos.Mutable; -import net.minecraft.world.StructureWorldAccess; -import net.minecraft.world.gen.chunk.ChunkGenerator; -import net.minecraft.world.gen.feature.DefaultFeatureConfig; -import ru.betterend.noise.OpenSimplexNoise; -import ru.betterend.util.sdf.SDF; -import ru.betterend.util.sdf.operator.SDFDisplacement; -import ru.betterend.util.sdf.operator.SDFTranslate; -import ru.betterend.util.sdf.primitive.SDFCappedCone; - -public class OverworldIslandFeature extends DefaultFeature { - private static final OpenSimplexNoise NOISE = new OpenSimplexNoise(412); - private static final Mutable CENTER = new Mutable(); - private static final SDF ISLAND; - - @Override - public boolean generate(StructureWorldAccess world, ChunkGenerator chunkGenerator, Random random, BlockPos pos, DefaultFeatureConfig config) { - CENTER.set(pos); - ISLAND.fillRecursive(world, pos.down()); - return true; - } - - static { - SDF cone = new SDFCappedCone().setRadius1(0).setRadius2(6).setHeight(4).setBlock((pos) -> { - if (pos.getY() == CENTER.getY()) return Blocks.GRASS_BLOCK.getDefaultState(); - if (pos.getY() == CENTER.getY() - 1) { - return Blocks.DIRT.getDefaultState(); - } else if (pos.getY() == CENTER.getY() - Math.round(2.0 * Math.random())) { - return Blocks.DIRT.getDefaultState(); - } - return Blocks.STONE.getDefaultState(); - }); - cone = new SDFTranslate().setTranslate(0, -3, 0).setSource(cone); - cone = new SDFDisplacement().setFunction((pos) -> { - return (float) NOISE.eval(CENTER.getX() + pos.getX(), CENTER.getY() + pos.getY(), CENTER.getZ() + pos.getZ()); - }).setSource(cone).setReplaceFunction(state -> { - return state.isOf(Blocks.WATER) || state.getMaterial().isReplaceable(); - }); - ISLAND = cone; - } -}