From 54258d38e33cde7783e94f31d579522e1ecd0c54 Mon Sep 17 00:00:00 2001 From: paulevsGitch Date: Thu, 23 Dec 2021 10:16:02 +0300 Subject: [PATCH] Erosion with fixes --- .../blocks/MossyGlowshroomCapBlock.java | 23 +- .../ru/betterend/util/StructureErode.java | 273 ++++++++++++++++++ .../world/features/CrashedShipFeature.java | 3 +- .../terrain/SulphuricCaveFeature.java | 4 +- .../world/structures/piece/NBTPiece.java | 9 +- 5 files changed, 297 insertions(+), 15 deletions(-) create mode 100644 src/main/java/ru/betterend/util/StructureErode.java diff --git a/src/main/java/ru/betterend/blocks/MossyGlowshroomCapBlock.java b/src/main/java/ru/betterend/blocks/MossyGlowshroomCapBlock.java index 3320e2ef..3fbf69b2 100644 --- a/src/main/java/ru/betterend/blocks/MossyGlowshroomCapBlock.java +++ b/src/main/java/ru/betterend/blocks/MossyGlowshroomCapBlock.java @@ -2,6 +2,8 @@ package ru.betterend.blocks; import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags; +import net.minecraft.tags.Tag.Named; +import net.minecraft.world.item.Item; import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.SoundType; @@ -9,26 +11,35 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.level.block.state.properties.BooleanProperty; import net.minecraft.world.level.material.Material; +import ru.bclib.api.TagAPI; import ru.bclib.blocks.BaseBlock; +import ru.bclib.interfaces.TagProvider; import ru.betterend.registry.EndBlocks; -public class MossyGlowshroomCapBlock extends BaseBlock { +import java.util.List; + +public class MossyGlowshroomCapBlock extends BaseBlock implements TagProvider { public static final BooleanProperty TRANSITION = EndBlockProperties.TRANSITION; public MossyGlowshroomCapBlock() { - super(FabricBlockSettings.of(Material.WOOD).breakByTool(FabricToolTags.AXES).sound(SoundType.WOOD)); + super(FabricBlockSettings.of(Material.WOOD).sound(SoundType.WOOD)); this.registerDefaultState(this.stateDefinition.any().setValue(TRANSITION, false)); } public BlockState getStateForPlacement(BlockPlaceContext ctx) { return this.defaultBlockState() - .setValue( - TRANSITION, - EndBlocks.MOSSY_GLOWSHROOM.isTreeLog(ctx.getLevel().getBlockState(ctx.getClickedPos().below())) - ); + .setValue( + TRANSITION, + EndBlocks.MOSSY_GLOWSHROOM.isTreeLog(ctx.getLevel().getBlockState(ctx.getClickedPos().below())) + ); } protected void createBlockStateDefinition(StateDefinition.Builder builder) { builder.add(TRANSITION); } + + @Override + public void addTags(List> blockTags, List> itemTags) { + blockTags.add(TagAPI.MINEABLE_AXE); + } } diff --git a/src/main/java/ru/betterend/util/StructureErode.java b/src/main/java/ru/betterend/util/StructureErode.java new file mode 100644 index 00000000..3da5858d --- /dev/null +++ b/src/main/java/ru/betterend/util/StructureErode.java @@ -0,0 +1,273 @@ +package ru.betterend.util; + +import com.google.common.collect.Sets; +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.core.Direction; +import net.minecraft.tags.BlockTags; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.structure.BoundingBox; +import net.minecraft.world.level.material.Material; +import ru.bclib.api.TagAPI; +import ru.bclib.api.biomes.BiomeAPI; +import ru.bclib.util.BlocksHelper; +import ru.bclib.util.MHelper; + +import java.util.Random; +import java.util.Set; + +public class StructureErode { + private static final Direction[] DIR = BlocksHelper.makeHorizontal(); + + public static void erode(WorldGenLevel world, BoundingBox bounds, int iterations, Random random) { + MutableBlockPos mut = new MutableBlockPos(); + boolean canDestruct = true; + for (int i = 0; i < iterations; i++) { + for (int x = bounds.minX(); x <= bounds.maxX(); x++) { + mut.setX(x); + for (int z = bounds.minZ(); z <= bounds.maxZ(); z++) { + mut.setZ(z); + for (int y = bounds.maxY(); y >= bounds.minY(); y--) { + mut.setY(y); + BlockState state = world.getBlockState(mut); + boolean ignore = ignore(state, world, mut); + if (canDestruct && BlocksHelper.isInvulnerable( + state, + world, + mut + ) && random.nextInt(8) == 0 && world.isEmptyBlock(mut.below(2))) { + int r = MHelper.randRange(1, 4, random); + int cx = mut.getX(); + int cy = mut.getY(); + int cz = mut.getZ(); + int x1 = cx - r; + int y1 = cy - r; + int z1 = cz - r; + int x2 = cx + r; + int y2 = cy + r; + int z2 = cz + r; + for (int px = x1; px <= x2; px++) { + int dx = px - cx; + dx *= dx; + mut.setX(px); + for (int py = y1; py <= y2; py++) { + int dy = py - cy; + dy *= dy; + mut.setY(py); + for (int pz = z1; pz <= z2; pz++) { + int dz = pz - cz; + dz *= dz; + mut.setZ(pz); + if (dx + dy + dz <= r && BlocksHelper.isInvulnerable( + world.getBlockState(mut), + world, + mut + )) { + BlocksHelper.setWithoutUpdate(world, mut, Blocks.AIR); + } + } + } + } + mut.setX(cx); + mut.setY(cy); + mut.setZ(cz); + canDestruct = false; + continue; + } + else if (ignore) { + continue; + } + if (!state.isAir() && random.nextBoolean()) { + MHelper.shuffle(DIR, random); + for (Direction dir : DIR) { + if (world.isEmptyBlock(mut.relative(dir)) && world.isEmptyBlock(mut.below() + .relative(dir))) { + BlocksHelper.setWithoutUpdate(world, mut, Blocks.AIR); + mut.move(dir).move(Direction.DOWN); + for (int py = mut.getY(); y >= bounds.minY() - 10; y--) { + mut.setY(py - 1); + if (!world.isEmptyBlock(mut)) { + mut.setY(py); + BlocksHelper.setWithoutUpdate(world, mut, state); + break; + } + } + } + } + break; + } + else if (random.nextInt(8) == 0 && !BlocksHelper.isInvulnerable( + world.getBlockState(mut.above()), + world, + mut + )) { + BlocksHelper.setWithoutUpdate(world, mut, Blocks.AIR); + } + } + } + } + } + for (int x = bounds.minX(); x <= bounds.maxX(); x++) { + mut.setX(x); + for (int z = bounds.minZ(); z <= bounds.maxZ(); z++) { + mut.setZ(z); + for (int y = bounds.maxY(); y >= bounds.minY(); y--) { + mut.setY(y); + BlockState state = world.getBlockState(mut); + if (!ignore(state, world, mut) && world.isEmptyBlock(mut.below())) { + BlocksHelper.setWithoutUpdate(world, mut, Blocks.AIR); + for (int py = mut.getY(); py >= bounds.minY() - 10; py--) { + mut.setY(py - 1); + if (!world.isEmptyBlock(mut)) { + mut.setY(py); + BlocksHelper.setWithoutUpdate(world, mut, state); + break; + } + } + } + } + } + } + } + + public static void erodeIntense(WorldGenLevel world, BoundingBox bounds, Random random) { + MutableBlockPos mut = new MutableBlockPos(); + MutableBlockPos mut2 = new MutableBlockPos(); + int minY = bounds.minY() - 10; + for (int x = bounds.minX(); x <= bounds.maxX(); x++) { + mut.setX(x); + for (int z = bounds.minZ(); z <= bounds.maxZ(); z++) { + mut.setZ(z); + for (int y = bounds.maxY(); y >= bounds.minY(); y--) { + mut.setY(y); + BlockState state = world.getBlockState(mut); + if (!ignore(state, world, mut)) { + if (random.nextInt(6) == 0) { + BlocksHelper.setWithoutUpdate(world, mut, Blocks.AIR); + if (random.nextBoolean()) { + int px = MHelper.floor(random.nextGaussian() * 2 + x + 0.5); + int pz = MHelper.floor(random.nextGaussian() * 2 + z + 0.5); + mut2.set(px, y, pz); + while (world.getBlockState(mut2).getMaterial().isReplaceable() && mut2.getY() > minY) { + mut2.setY(mut2.getY() - 1); + } + if (!world.getBlockState(mut2).isAir() && state.canSurvive(world, mut2)) { + mut2.setY(mut2.getY() + 1); + BlocksHelper.setWithoutUpdate(world, mut2, state); + } + } + } + else if (random.nextInt(8) == 0) { + BlocksHelper.setWithoutUpdate(world, mut, Blocks.AIR); + } + } + } + } + } + + drop(world, bounds); + } + + private static void drop(WorldGenLevel world, BoundingBox bounds) { + MutableBlockPos mut = new MutableBlockPos(); + + Set blocks = Sets.newHashSet(); + Set edge = Sets.newHashSet(); + Set add = Sets.newHashSet(); + + for (int x = bounds.minX(); x <= bounds.maxX(); x++) { + mut.setX(x); + for (int z = bounds.minZ(); z <= bounds.maxZ(); z++) { + mut.setZ(z); + for (int y = bounds.minY(); y <= bounds.maxY(); y++) { + mut.setY(y); + BlockState state = world.getBlockState(mut); + if (!ignore(state, world, mut) && isTerrainNear(world, mut)) { + edge.add(mut.immutable()); + } + } + } + } + + if (edge.isEmpty()) { + return; + } + + while (!edge.isEmpty()) { + for (BlockPos center : edge) { + for (Direction dir : BlocksHelper.DIRECTIONS) { + BlockState state = world.getBlockState(center); + if (state.isCollisionShapeFullBlock(world, center)) { + mut.set(center).move(dir); + if (bounds.isInside(mut)) { + state = world.getBlockState(mut); + if (!ignore(state, world, mut) && !blocks.contains(mut)) { + add.add(mut.immutable()); + } + } + } + } + } + + blocks.addAll(edge); + edge.clear(); + edge.addAll(add); + add.clear(); + } + + int minY = bounds.minY() - 10; + for (int x = bounds.minX(); x <= bounds.maxX(); x++) { + mut.setX(x); + for (int z = bounds.minZ(); z <= bounds.maxZ(); z++) { + mut.setZ(z); + for (int y = bounds.minY(); y <= bounds.maxY(); y++) { + mut.setY(y); + BlockState state = world.getBlockState(mut); + if (!ignore(state, world, mut) && !blocks.contains(mut)) { + BlocksHelper.setWithoutUpdate(world, mut, Blocks.AIR); + while (world.getBlockState(mut).getMaterial().isReplaceable() && mut.getY() > minY) { + mut.setY(mut.getY() - 1); + } + if (mut.getY() > minY) { + mut.setY(mut.getY() + 1); + BlocksHelper.setWithoutUpdate(world, mut, state); + } + } + } + } + } + } + + private static boolean ignore(BlockState state, WorldGenLevel world, BlockPos pos) { + return !state.getMaterial().equals(Material.STONE) || BlocksHelper.isInvulnerable(state, world, pos); + } + + private static boolean isTerrainNear(WorldGenLevel world, BlockPos pos) { + for (Direction dir : BlocksHelper.DIRECTIONS) { + if (world.getBlockState(pos.relative(dir)).is(TagAPI.BLOCK_GEN_TERRAIN)) { + return true; + } + } + return false; + } + + public static void cover(WorldGenLevel world, BoundingBox bounds, Random random, BlockState defaultBlock) { + MutableBlockPos mut = new MutableBlockPos(); + for (int x = bounds.minX(); x <= bounds.maxX(); x++) { + mut.setX(x); + for (int z = bounds.minZ(); z <= bounds.maxZ(); z++) { + mut.setZ(z); + BlockState top = BiomeAPI.findTopMaterial(world.getBiome(mut)).orElse(defaultBlock); + for (int y = bounds.maxY(); y >= bounds.minY(); y--) { + mut.setY(y); + BlockState state = world.getBlockState(mut); + if (state.is(TagAPI.BLOCK_END_GROUND) && !world.getBlockState(mut.above()).getMaterial().isSolidBlocking()) { + BlocksHelper.setWithoutUpdate(world, mut, top); + } + } + } + } + } +} diff --git a/src/main/java/ru/betterend/world/features/CrashedShipFeature.java b/src/main/java/ru/betterend/world/features/CrashedShipFeature.java index b6301235..124e07ea 100644 --- a/src/main/java/ru/betterend/world/features/CrashedShipFeature.java +++ b/src/main/java/ru/betterend/world/features/CrashedShipFeature.java @@ -23,6 +23,7 @@ import ru.bclib.util.MHelper; import ru.bclib.util.StructureHelper; import ru.bclib.world.features.NBTStructureFeature; import ru.betterend.util.BlockFixer; +import ru.betterend.util.StructureErode; import ru.betterend.world.biome.EndBiome; import java.util.Random; @@ -111,7 +112,7 @@ public class CrashedShipFeature extends NBTStructureFeature { addStructureData(placementData); structure.placeInWorld(world, center, center, placementData.setBoundingBox(bounds), random, 2); - StructureHelper.erodeIntense(world, bounds, random); + StructureErode.erodeIntense(world, bounds, random); BlockFixer.fixBlocks( world, new BlockPos(bounds.minX(), bounds.minY(), bounds.minZ()), diff --git a/src/main/java/ru/betterend/world/features/terrain/SulphuricCaveFeature.java b/src/main/java/ru/betterend/world/features/terrain/SulphuricCaveFeature.java index 39c261a1..00398093 100644 --- a/src/main/java/ru/betterend/world/features/terrain/SulphuricCaveFeature.java +++ b/src/main/java/ru/betterend/world/features/terrain/SulphuricCaveFeature.java @@ -167,9 +167,7 @@ public class SulphuricCaveFeature extends DefaultFeature { state = world.getBlockState(mut); while (state.is(Blocks.WATER)) { BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.VENT_BUBBLE_COLUMN.defaultBlockState()); - //TODO: 1.18 test ticks - world/*.getBlockTicks()*/ - .scheduleTick(mut, EndBlocks.VENT_BUBBLE_COLUMN, MHelper.randRange(8, 32, random)); + world.scheduleTick(mut.immutable(), EndBlocks.VENT_BUBBLE_COLUMN, MHelper.randRange(8, 32, random)); mut.setY(mut.getY() + 1); state = world.getBlockState(mut); } diff --git a/src/main/java/ru/betterend/world/structures/piece/NBTPiece.java b/src/main/java/ru/betterend/world/structures/piece/NBTPiece.java index b4112065..9242bb5d 100644 --- a/src/main/java/ru/betterend/world/structures/piece/NBTPiece.java +++ b/src/main/java/ru/betterend/world/structures/piece/NBTPiece.java @@ -18,6 +18,7 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemp import ru.bclib.util.MHelper; import ru.bclib.util.StructureHelper; import ru.betterend.registry.EndStructures; +import ru.betterend.util.StructureErode; import ru.betterend.world.biome.EndBiome; import java.util.Random; @@ -77,9 +78,7 @@ public class NBTPiece extends BasePiece { this.boundingBox.minY(), blockBox.minZ() ), new Vec3i(blockBox.maxX(), this.boundingBox.maxX(), blockBox.maxZ())); - StructurePlaceSettings placementData = new StructurePlaceSettings().setRotation(rotation) - .setMirror(mirror) - .setBoundingBox(bounds); + StructurePlaceSettings placementData = new StructurePlaceSettings().setRotation(rotation).setMirror(mirror).setBoundingBox(bounds); structure.placeInWorld(world, pos, pos, placementData, random, 2); if (erosion > 0) { int x1 = MHelper.min(bounds.maxX(), boundingBox.maxX()); @@ -87,10 +86,10 @@ public class NBTPiece extends BasePiece { int z1 = MHelper.min(bounds.maxZ(), boundingBox.maxZ()); int z0 = MHelper.max(bounds.minZ(), boundingBox.minZ()); bounds = BoundingBox.fromCorners(new Vec3i(x0, bounds.minY(), z0), new Vec3i(x1, bounds.maxY(), z1)); - StructureHelper.erode(world, bounds, erosion, random); + StructureErode.erode(world, bounds, erosion, random); } if (cover) { - StructureHelper.cover(world, bounds, random, EndBiome.Config.DEFAULT_MATERIAL.getTopMaterial()); + StructureErode.cover(world, bounds, random, EndBiome.Config.DEFAULT_MATERIAL.getTopMaterial()); } }