diff --git a/src/main/java/ru/betterend/registry/EndFeatures.java b/src/main/java/ru/betterend/registry/EndFeatures.java index df3f1345..a6d406b1 100644 --- a/src/main/java/ru/betterend/registry/EndFeatures.java +++ b/src/main/java/ru/betterend/registry/EndFeatures.java @@ -39,7 +39,7 @@ public class EndFeatures { public static final EndFeature PYTHADENDRON_TREE = new EndFeature("pythadendron_tree", new PythadendronTreeFeature(), 2); public static final EndFeature LACUGROVE = new EndFeature("lacugrove", new LacugroveFeature(), 4); public static final EndFeature DRAGON_TREE = new EndFeature("dragon_tree", new DragonTreeFeature(), 3); - public static final EndFeature TENANEA = new EndFeature("tenanea", new TenaneaFeature(), 7); + public static final EndFeature TENANEA = new EndFeature("tenanea", new TenaneaFeature(), 3); // 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/features/trees/TenaneaFeature.java b/src/main/java/ru/betterend/world/features/trees/TenaneaFeature.java index 5fcea8ff..a9670faf 100644 --- a/src/main/java/ru/betterend/world/features/trees/TenaneaFeature.java +++ b/src/main/java/ru/betterend/world/features/trees/TenaneaFeature.java @@ -1,139 +1,164 @@ package ru.betterend.world.features.trees; +import java.util.List; import java.util.Random; -import java.util.Set; +import java.util.function.Function; -import com.google.common.collect.Sets; +import com.google.common.collect.Lists; import net.minecraft.block.BlockState; -import net.minecraft.block.Blocks; +import net.minecraft.block.LeavesBlock; +import net.minecraft.block.Material; +import net.minecraft.client.util.math.Vector3f; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos.Mutable; import net.minecraft.util.math.Direction; -import net.minecraft.util.math.Vec3i; import net.minecraft.world.StructureWorldAccess; import net.minecraft.world.gen.chunk.ChunkGenerator; import net.minecraft.world.gen.feature.DefaultFeatureConfig; +import ru.betterend.blocks.BlockProperties; +import ru.betterend.blocks.BlockProperties.TripleShape; +import ru.betterend.noise.OpenSimplexNoise; +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.SDF; +import ru.betterend.util.sdf.operator.SDFDisplacement; +import ru.betterend.util.sdf.operator.SDFScale; +import ru.betterend.util.sdf.operator.SDFScale3D; +import ru.betterend.util.sdf.operator.SDFSubtraction; +import ru.betterend.util.sdf.operator.SDFTranslate; +import ru.betterend.util.sdf.primitive.SDFSphere; import ru.betterend.world.features.DefaultFeature; public class TenaneaFeature extends DefaultFeature { - private static final Vec3i[] DIRECTIONS; - private static final Vec3i UP; + private static final Function REPLACE; + private static final Function IGNORE; + private static final List SPLINE; @Override public boolean generate(StructureWorldAccess world, ChunkGenerator chunkGenerator, Random random, BlockPos pos, DefaultFeatureConfig config) { - Set set = branch(Sets.newHashSet(), world, pos, UP, 100, random); - set.forEach((bpos) -> { - BlocksHelper.setWithoutUpdate(world, bpos, Blocks.DIAMOND_BLOCK); - }); + if (!world.getBlockState(pos.down()).getBlock().isIn(EndTags.END_GROUND)) return false; + + float size = MHelper.randRange(7, 10, random); + int count = (int) (size * 0.45F); + float var = MHelper.PI2 / (float) (count * 3); + float start = MHelper.randRange(0, MHelper.PI2, random); + for (int i = 0; i < count; i++) { + float angle = (float) i / (float) count * MHelper.PI2 + MHelper.randRange(0, var, random) + start; + List spline = SplineHelper.copySpline(SPLINE); + SplineHelper.rotateSpline(spline, angle); + SplineHelper.scale(spline, size + MHelper.randRange(0, size * 0.5F, random)); + SplineHelper.offsetParts(spline, random, 1F, 0, 1F); + SplineHelper.fillSpline(spline, world, EndBlocks.TENANEA.bark.getDefaultState(), pos, REPLACE); + Vector3f last = spline.get(spline.size() - 1); + float leavesRadius = (size * 0.3F + MHelper.randRange(0.8F, 1.5F, random)); + OpenSimplexNoise noise = new OpenSimplexNoise(random.nextLong()); + leavesBall(world, pos.add(last.getX(), last.getY(), last.getZ()), leavesRadius, random, noise); + } + return true; } - private Set branch(Set set, StructureWorldAccess world, BlockPos pos, Vec3i dir, int length, Random random) { - Mutable mut = new Mutable().set(pos); - int upCount = 0; - for (int i = 0; i < length; i++) { - MHelper.shuffle(DIRECTIONS, random); - boolean up = false; - - set.add(mut.toImmutable()); - - for (Direction hor: BlocksHelper.HORIZONTAL) { - if (!isReplaceable(world.getBlockState(mut.offset(hor))) || !isReplaceable(world.getBlockState(mut.offset(hor).down()))) { - upCount = -1; - up = true; - break; - } + private void leavesBall(StructureWorldAccess world, BlockPos pos, float radius, Random random, OpenSimplexNoise noise) { + SDF sphere = new SDFSphere().setRadius(radius).setBlock(EndBlocks.TENANEA_LEAVES.getDefaultState().with(LeavesBlock.DISTANCE, 6)); + SDF sub = new SDFScale().setScale(5).setSource(sphere); + sub = new SDFTranslate().setTranslate(0, -radius * 5, 0).setSource(sub); + sphere = new SDFSubtraction().setSourceA(sphere).setSourceB(sub); + sphere = new SDFScale3D().setScale(1, 0.5F, 1).setSource(sphere); + sphere = new SDFDisplacement().setFunction((vec) -> { return (float) noise.eval(vec.getX() * 0.2, vec.getY() * 0.2, vec.getZ() * 0.2) * 1F; }).setSource(sphere); + sphere = new SDFDisplacement().setFunction((vec) -> { return random.nextFloat() * 3F - 1.5F; }).setSource(sphere); + Mutable mut = new Mutable(); + List support = Lists.newArrayList(); + sphere.setPostProcess((info) -> { + if (random.nextBoolean() && info.getStateDown().isAir()) { + support.add(info.getPos().toImmutable()); } - if (up) { - upCount ++; - mut.move(Direction.UP); - if (upCount > 8) { - break; - } - - if (random.nextInt(4) == 0) { - Direction d = BlocksHelper.randomHorizontal(random); - mut.move(d); - } - - /*if (random.nextInt(16) == 0) { - int l = length - i; - if (l > 5) { - l = MHelper.randRange(l / 2, l, random); - Vec3i d = DIRECTIONS[random.nextInt(DIRECTIONS.length)]; - if (d != dir) { - branch(set, world, mut.add(d), d, l, random); - } + if (random.nextInt(5) == 0) { + for (Direction dir: Direction.values()) { + BlockState state = info.getState(dir, 2); + if (state.isAir()) { + return info.getState(); } - }*/ - - continue; - } - else { - up = true; - for (Vec3i d: DIRECTIONS) { - BlockPos offseted = mut.add(d.getX(), d.getY(), d.getZ()); - boolean canOffset = Math.abs(offseted.getX() - pos.getX()) < 16 && Math.abs(offseted.getZ() - pos.getZ()) < 16; - if (canOffset && isReplaceable(world.getBlockState(offseted))) { - int dist = BlocksHelper.raycastSqr(world, offseted, d.getX(), d.getY(), d.getZ(), 10); - if (dist < 64) { - mut.move(d.getX(), d.getY(), d.getZ()); - upCount = 0; - up = false; - dir = d; - break; + } + info.setState(EndBlocks.TENANEA.bark.getDefaultState()); + for (int x = -6; x < 7; x++) { + int ax = Math.abs(x); + mut.setX(x + info.getPos().getX()); + for (int z = -6; z < 7; z++) { + int az = Math.abs(z); + mut.setZ(z + info.getPos().getZ()); + for (int y = -6; y < 7; y++) { + int ay = Math.abs(y); + int d = ax + ay + az; + if (d < 7) { + mut.setY(y + info.getPos().getY()); + BlockState state = info.getState(mut); + if (state.getBlock() instanceof LeavesBlock) { + int distance = state.get(LeavesBlock.DISTANCE); + if (d < distance) { + info.setState(mut, state.with(LeavesBlock.DISTANCE, d)); + } + } + } } } } - if (up) { - upCount ++; - mut.move(Direction.UP); - if (upCount > 8) { - break; - } - } } - - if (!world.getBlockState(mut).getMaterial().isReplaceable()) { - boolean br = true; - for (Direction hor: BlocksHelper.HORIZONTAL) { - if (isReplaceable(world.getBlockState(mut.offset(hor)))) { - mut.move(hor); - br = false; - } - } - if (br) { - break; - } - } - } + return info.getState(); + }); + sphere.fillRecursiveIgnore(world, pos, IGNORE); - return set; - } - - private boolean isReplaceable(BlockState state) { - return state.getMaterial().isReplaceable(); + BlocksHelper.setWithoutUpdate(world, pos, EndBlocks.TENANEA.bark); + + BlockState top = EndBlocks.TENANEA_FLOWERS.getDefaultState().with(BlockProperties.TRIPLE_SHAPE, TripleShape.TOP); + BlockState middle = EndBlocks.TENANEA_FLOWERS.getDefaultState().with(BlockProperties.TRIPLE_SHAPE, TripleShape.MIDDLE); + BlockState bottom = EndBlocks.TENANEA_FLOWERS.getDefaultState().with(BlockProperties.TRIPLE_SHAPE, TripleShape.BOTTOM); + + support.forEach((bpos) -> { + int count = MHelper.randRange(5, 9, random); + mut.set(bpos).move(Direction.DOWN); + BlocksHelper.setWithoutUpdate(world, mut, top); + for (int i = 1; i < count; i++) { + mut.setY(mut.getY() - 1); + if (world.isAir(mut.down())) { + BlocksHelper.setWithoutUpdate(world, mut, middle); + } + else { + break; + } + } + BlocksHelper.setWithoutUpdate(world, mut, bottom); + }); } static { - DIRECTIONS = new Vec3i[] { - new Vec3i(0, 0, 1), - new Vec3i(0, 0, -1), - new Vec3i(1, 0, 0), - new Vec3i(-1, 0, 0), - new Vec3i(1, 0, 1), - new Vec3i(1, 0, -1), - new Vec3i(-1, 0, 1), - new Vec3i(-1, 0, -1), - new Vec3i(1, 1, 1), - new Vec3i(1, 1, -1), - new Vec3i(-1, 1, 1), - new Vec3i(-1, 1, -1) + REPLACE = (state) -> { + if (state.isIn(EndTags.END_GROUND)) { + return true; + } + if (state.getBlock() == EndBlocks.TENANEA_LEAVES) { + return true; + } + if (state.getMaterial().equals(Material.PLANT)) { + return true; + } + return state.getMaterial().isReplaceable(); }; - UP = new Vec3i(0, 1, 0); + IGNORE = (state) -> { + return EndBlocks.TENANEA.isTreeLog(state); + }; + + SPLINE = Lists.newArrayList( + new Vector3f(0.00F, 0.00F, 0.00F), + new Vector3f(0.10F, 0.35F, 0.00F), + new Vector3f(0.20F, 0.50F, 0.00F), + new Vector3f(0.30F, 0.55F, 0.00F), + new Vector3f(0.42F, 0.70F, 0.00F), + new Vector3f(0.50F, 1.00F, 0.00F) + ); } } diff --git a/src/main/resources/assets/betterend/textures/block/tenanea_flowers.png b/src/main/resources/assets/betterend/textures/block/tenanea_flowers.png index 5ce1df84..bd8ea393 100644 Binary files a/src/main/resources/assets/betterend/textures/block/tenanea_flowers.png and b/src/main/resources/assets/betterend/textures/block/tenanea_flowers.png differ diff --git a/src/main/resources/assets/betterend/textures/block/tenanea_flowers_bottom.png b/src/main/resources/assets/betterend/textures/block/tenanea_flowers_bottom.png index 16334402..a7e013b6 100644 Binary files a/src/main/resources/assets/betterend/textures/block/tenanea_flowers_bottom.png and b/src/main/resources/assets/betterend/textures/block/tenanea_flowers_bottom.png differ diff --git a/src/main/resources/assets/betterend/textures/block/tenanea_flowers_top.png b/src/main/resources/assets/betterend/textures/block/tenanea_flowers_top.png index 50b0a533..7bdf495a 100644 Binary files a/src/main/resources/assets/betterend/textures/block/tenanea_flowers_top.png and b/src/main/resources/assets/betterend/textures/block/tenanea_flowers_top.png differ diff --git a/src/main/resources/assets/betterend/textures/block/tenanea_leaves.png b/src/main/resources/assets/betterend/textures/block/tenanea_leaves.png index 845e07a7..bcc87a62 100644 Binary files a/src/main/resources/assets/betterend/textures/block/tenanea_leaves.png and b/src/main/resources/assets/betterend/textures/block/tenanea_leaves.png differ