diff --git a/src/main/java/ru/betterend/registry/EndFeatures.java b/src/main/java/ru/betterend/registry/EndFeatures.java index 6e1e5b3b..c0f693f2 100644 --- a/src/main/java/ru/betterend/registry/EndFeatures.java +++ b/src/main/java/ru/betterend/registry/EndFeatures.java @@ -51,6 +51,7 @@ import ru.betterend.world.features.terrain.SulphuricCaveFeature; import ru.betterend.world.features.terrain.SulphuricLakeFeature; import ru.betterend.world.features.terrain.SurfaceVentFeature; import ru.betterend.world.features.trees.DragonTreeFeature; +import ru.betterend.world.features.trees.GiganticAmaranitaFeature; import ru.betterend.world.features.trees.HelixTreeFeature; import ru.betterend.world.features.trees.JellyshroomFeature; import ru.betterend.world.features.trees.LacugroveFeature; @@ -70,6 +71,7 @@ public class EndFeatures { public static final EndFeature HELIX_TREE = new EndFeature("helix_tree", new HelixTreeFeature(), 2); public static final EndFeature UMBRELLA_TREE = new EndFeature("umbrella_tree", new UmbrellaTreeFeature(), 4); public static final EndFeature JELLYSHROOM = new EndFeature("jellyshroom", new JellyshroomFeature(), 3); + public static final EndFeature GIGANTIC_AMARANITA = new EndFeature("gigantic_amaranita", new GiganticAmaranitaFeature(), 1); // Bushes // public static final EndFeature PYTHADENDRON_BUSH = new EndFeature("pythadendron_bush", new BushFeature(EndBlocks.PYTHADENDRON_LEAVES, EndBlocks.PYTHADENDRON.bark), 4); diff --git a/src/main/java/ru/betterend/world/biome/DragonGraveyardsBiome.java b/src/main/java/ru/betterend/world/biome/DragonGraveyardsBiome.java index 765ae2a3..07c0dc74 100644 --- a/src/main/java/ru/betterend/world/biome/DragonGraveyardsBiome.java +++ b/src/main/java/ru/betterend/world/biome/DragonGraveyardsBiome.java @@ -21,6 +21,7 @@ public class DragonGraveyardsBiome extends EndBiome { .addFeature(EndFeatures.OBSIDIAN_PILLAR_BASEMENT) .addFeature(EndFeatures.FALLEN_PILLAR) .addFeature(EndFeatures.OBSIDIAN_BOULDER) + .addFeature(EndFeatures.GIGANTIC_AMARANITA) .addFeature(EndFeatures.LARGE_AMARANITA) .addFeature(EndFeatures.SMALL_AMARANITA) .addFeature(EndFeatures.GLOBULAGUS) diff --git a/src/main/java/ru/betterend/world/features/trees/GiganticAmaranitaFeature.java b/src/main/java/ru/betterend/world/features/trees/GiganticAmaranitaFeature.java new file mode 100644 index 00000000..f91d2d0d --- /dev/null +++ b/src/main/java/ru/betterend/world/features/trees/GiganticAmaranitaFeature.java @@ -0,0 +1,339 @@ +package ru.betterend.world.features.trees; + +import java.util.List; +import java.util.Random; +import java.util.function.Function; + +import net.minecraft.block.BlockState; +import net.minecraft.block.Material; +import net.minecraft.client.util.math.Vector3f; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.Direction.Axis; +import net.minecraft.util.math.Direction.AxisDirection; +import net.minecraft.util.math.MathHelper; +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.blocks.basis.AttachedBlock; +import ru.betterend.registry.EndBlocks; +import ru.betterend.registry.EndTags; +import ru.betterend.util.BlocksHelper; +import ru.betterend.util.MHelper; +import ru.betterend.util.SplineHelper; +import ru.betterend.util.sdf.PosInfo; +import ru.betterend.util.sdf.SDF; +import ru.betterend.world.features.DefaultFeature; + +public class GiganticAmaranitaFeature extends DefaultFeature { + private static final Function REPLACE; + private static final Function IGNORE; + private static final Function POST; + + @Override + public boolean generate(StructureWorldAccess world, ChunkGenerator chunkGenerator, Random random, BlockPos pos, DefaultFeatureConfig config) { + if (!world.getBlockState(pos.down()).getBlock().isIn(EndTags.END_GROUND)) return false; + + float size = MHelper.randRange(5, 10, random); + List spline = SplineHelper.makeSpline(0, 0, 0, 0, size, 0, 5); + SplineHelper.offsetParts(spline, random, 0.7F, 0, 0.7F); + + if (!SplineHelper.canGenerate(spline, pos, world, REPLACE)) { + return false; + } + BlocksHelper.setWithoutUpdate(world, pos, AIR); + + float radius = size * 0.17F;//MHelper.randRange(0.8F, 1.2F, random); + SDF function = SplineHelper.buildSDF(spline, radius, 0.2F, (bpos) -> { + return EndBlocks.AMARANITA_STEM.getDefaultState(); + }); + + Vector3f capPos = spline.get(spline.size() - 1); + makeHead(world, pos.add(capPos.getX() + 0.5F, capPos.getY() + 1.5F ,capPos.getZ() + 0.5F), MathHelper.floor(size / 1.6F)); + + function.setReplaceFunction(REPLACE); + function.addPostProcess(POST); + function.fillRecursiveIgnore(world, pos, IGNORE); + + for (int i = 0; i < 3; i++) { + List copy = SplineHelper.copySpline(spline); + SplineHelper.offsetParts(copy, random, 0.2F, 0, 0.2F); + SplineHelper.fillSplineForce(copy, world, EndBlocks.AMARANITA_HYPHAE.getDefaultState(), pos, REPLACE); + } + + return true; + } + + private void makeHead(StructureWorldAccess world, BlockPos pos, int radius) { + Mutable mut = new Mutable(); + if (radius < 2) { + for (int i = -1; i < 2; i++) { + mut.set(pos).move(Direction.NORTH, 2).move(Direction.EAST, i); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); + } + mut.set(pos).move(Direction.SOUTH, 2).move(Direction.EAST, i); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); + } + mut.set(pos).move(Direction.EAST, 2).move(Direction.NORTH, i); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); + } + mut.set(pos).move(Direction.WEST, 2).move(Direction.NORTH, i); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); + } + } + for (int x = -1; x < 2; x++) { + for (int z = -1; z < 2; z++) { + mut.set(pos).move(x, 0, z); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_LANTERN); + mut.move(Direction.DOWN); + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_LANTERN); + mut.move(Direction.DOWN); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_FUR.getDefaultState().with(AttachedBlock.FACING, Direction.DOWN)); + } + } + } + } + + int h = radius + 1; + for (int y = 0; y < h; y++) { + mut.setY(pos.getY() + y + 1); + for (int x = -1; x < 2; x++) { + mut.setX(pos.getX() + x); + for (int z = -1; z < 2; z++) { + mut.setZ(pos.getZ() + z); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_CAP); + } + } + } + } + + mut.setY(pos.getY() + h + 1); + for (int x = -1; x < 2; x++) { + mut.setX(pos.getX() + x); + for (int z = -1; z < 2; z++) { + mut.setZ(pos.getZ() + z); + if ((x == 0 || z == 0) && world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_CAP); + } + } + } + } + else if (radius < 4) { + pos = pos.add(-1, 0, -1); + for (int i = -2; i < 2; i++) { + mut.set(pos).move(Direction.NORTH, 2).move(Direction.WEST, i); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); + } + mut.set(pos).move(Direction.SOUTH, 3).move(Direction.WEST, i); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); + } + mut.set(pos).move(Direction.EAST, 3).move(Direction.NORTH, i); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); + } + mut.set(pos).move(Direction.WEST, 2).move(Direction.NORTH, i); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); + } + } + for (int x = -1; x < 3; x++) { + for (int z = -1; z < 3; z++) { + mut.set(pos).move(x, 0, z); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_LANTERN); + mut.move(Direction.DOWN); + if ((x >> 1) == 0 || (z >> 1) == 0) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_LANTERN); + Axis axis = x < 0 || x > 1 ? Axis.X : Axis.Z; + int distance = axis == Axis.X ? x < 0 ? -1 : 1 : z < 0 ? -1 : 1; + BlockPos offseted = mut.offset(axis, distance); + if (world.getBlockState(offseted).getMaterial().isReplaceable()) { + Direction dir = Direction.from(axis, distance < 0 ? AxisDirection.NEGATIVE : AxisDirection.POSITIVE); + BlocksHelper.setWithoutUpdate(world, offseted, EndBlocks.AMARANITA_FUR.getDefaultState().with(AttachedBlock.FACING, dir)); + } + mut.move(Direction.DOWN); + } + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_FUR.getDefaultState().with(AttachedBlock.FACING, Direction.DOWN)); + } + } + } + } + + int h = radius - 1; + for (int y = 0; y < h; y++) { + mut.setY(pos.getY() + y + 1); + for (int x = -1; x < 3; x++) { + mut.setX(pos.getX() + x); + for (int z = -1; z < 3; z++) { + mut.setZ(pos.getZ() + z); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_CAP); + } + } + } + } + + mut.setY(pos.getY() + h + 1); + for (int x = -1; x < 3; x++) { + mut.setX(pos.getX() + x); + for (int z = -1; z < 3; z++) { + mut.setZ(pos.getZ() + z); + if (((x >> 1) == 0 || (z >> 1) == 0) && world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_CAP); + } + } + } + } + else { + for (int i = -2; i < 3; i++) { + mut.set(pos).move(Direction.NORTH, 3).move(Direction.EAST, i); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); + } + mut.move(Direction.UP); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); + } + mut.move(Direction.NORTH); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); + } + + mut.set(pos).move(Direction.SOUTH, 3).move(Direction.EAST, i); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); + } + mut.move(Direction.UP); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); + } + mut.move(Direction.SOUTH); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); + } + + mut.set(pos).move(Direction.EAST, 3).move(Direction.NORTH, i); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); + } + mut.move(Direction.UP); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); + } + mut.move(Direction.EAST); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); + } + + mut.set(pos).move(Direction.WEST, 3).move(Direction.NORTH, i); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); + } + mut.move(Direction.UP); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); + } + mut.move(Direction.WEST); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); + } + } + + for (int i = 0; i < 4; i++) { + mut.set(pos).move(Direction.UP).move(BlocksHelper.HORIZONTAL[i], 3).move(BlocksHelper.HORIZONTAL[(i + 1) & 3], 3); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); + } + } + + for (int x = -2; x < 3; x++) { + for (int z = -2; z < 3; z++) { + mut.set(pos).move(x, 0, z); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_LANTERN); + mut.move(Direction.DOWN); + if ((x / 2) == 0 || (z / 2) == 0) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_LANTERN); + Axis axis = x < 0 || x > 1 ? Axis.X : Axis.Z; + int distance = axis == Axis.X ? x < 0 ? -1 : 1 : z < 0 ? -1 : 1; + BlockPos offseted = mut.offset(axis, distance); + if (world.getBlockState(offseted).getMaterial().isReplaceable()) { + Direction dir = Direction.from(axis, distance < 0 ? AxisDirection.NEGATIVE : AxisDirection.POSITIVE); + BlocksHelper.setWithoutUpdate(world, offseted, EndBlocks.AMARANITA_FUR.getDefaultState().with(AttachedBlock.FACING, dir)); + } + mut.move(Direction.DOWN); + } + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_FUR.getDefaultState().with(AttachedBlock.FACING, Direction.DOWN)); + } + } + } + } + + for (int y = 0; y < 3; y++) { + mut.setY(pos.getY() + y + 1); + for (int x = -2; x < 3; x++) { + mut.setX(pos.getX() + x); + for (int z = -2; z < 3; z++) { + mut.setZ(pos.getZ() + z); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_CAP); + } + } + } + } + + int h = radius + 1; + for (int y = 4; y < h; y++) { + mut.setY(pos.getY() + y); + for (int x = -2; x < 3; x++) { + mut.setX(pos.getX() + x); + for (int z = -2; z < 3; z++) { + mut.setZ(pos.getZ() + z); + if (y < 6) { + if (((x / 2) == 0 || (z / 2) == 0) && world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_CAP); + } + } + else { + if ((x == 0 || z == 0) && (Math.abs(x) < 2 && Math.abs(z) < 2) && world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_CAP); + } + } + } + } + } + } + } + + static { + REPLACE = (state) -> { + if (state.isIn(EndTags.END_GROUND) || state.getMaterial().equals(Material.PLANT)) { + return true; + } + return state.getMaterial().isReplaceable(); + }; + + IGNORE = (state) -> { + return EndBlocks.DRAGON_TREE.isTreeLog(state); + }; + + POST = (info) -> { + if (!info.getStateUp().isOf(EndBlocks.AMARANITA_STEM) || !info.getStateDown().isOf(EndBlocks.AMARANITA_STEM)) { + return EndBlocks.AMARANITA_HYPHAE.getDefaultState(); + } + return info.getState(); + }; + } +}