Erosion with fixes
This commit is contained in:
parent
affd63646a
commit
54258d38e3
5 changed files with 297 additions and 15 deletions
|
@ -2,6 +2,8 @@ package ru.betterend.blocks;
|
||||||
|
|
||||||
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
|
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
|
||||||
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
|
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.item.context.BlockPlaceContext;
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
import net.minecraft.world.level.block.SoundType;
|
import net.minecraft.world.level.block.SoundType;
|
||||||
|
@ -9,14 +11,18 @@ import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraft.world.level.block.state.StateDefinition;
|
import net.minecraft.world.level.block.state.StateDefinition;
|
||||||
import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
||||||
import net.minecraft.world.level.material.Material;
|
import net.minecraft.world.level.material.Material;
|
||||||
|
import ru.bclib.api.TagAPI;
|
||||||
import ru.bclib.blocks.BaseBlock;
|
import ru.bclib.blocks.BaseBlock;
|
||||||
|
import ru.bclib.interfaces.TagProvider;
|
||||||
import ru.betterend.registry.EndBlocks;
|
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 static final BooleanProperty TRANSITION = EndBlockProperties.TRANSITION;
|
||||||
|
|
||||||
public MossyGlowshroomCapBlock() {
|
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));
|
this.registerDefaultState(this.stateDefinition.any().setValue(TRANSITION, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,4 +37,9 @@ public class MossyGlowshroomCapBlock extends BaseBlock {
|
||||||
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
|
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
|
||||||
builder.add(TRANSITION);
|
builder.add(TRANSITION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addTags(List<Named<Block>> blockTags, List<Named<Item>> itemTags) {
|
||||||
|
blockTags.add(TagAPI.MINEABLE_AXE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
273
src/main/java/ru/betterend/util/StructureErode.java
Normal file
273
src/main/java/ru/betterend/util/StructureErode.java
Normal file
|
@ -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<BlockPos> blocks = Sets.newHashSet();
|
||||||
|
Set<BlockPos> edge = Sets.newHashSet();
|
||||||
|
Set<BlockPos> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,6 +23,7 @@ import ru.bclib.util.MHelper;
|
||||||
import ru.bclib.util.StructureHelper;
|
import ru.bclib.util.StructureHelper;
|
||||||
import ru.bclib.world.features.NBTStructureFeature;
|
import ru.bclib.world.features.NBTStructureFeature;
|
||||||
import ru.betterend.util.BlockFixer;
|
import ru.betterend.util.BlockFixer;
|
||||||
|
import ru.betterend.util.StructureErode;
|
||||||
import ru.betterend.world.biome.EndBiome;
|
import ru.betterend.world.biome.EndBiome;
|
||||||
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
@ -111,7 +112,7 @@ public class CrashedShipFeature extends NBTStructureFeature {
|
||||||
addStructureData(placementData);
|
addStructureData(placementData);
|
||||||
structure.placeInWorld(world, center, center, placementData.setBoundingBox(bounds), random, 2);
|
structure.placeInWorld(world, center, center, placementData.setBoundingBox(bounds), random, 2);
|
||||||
|
|
||||||
StructureHelper.erodeIntense(world, bounds, random);
|
StructureErode.erodeIntense(world, bounds, random);
|
||||||
BlockFixer.fixBlocks(
|
BlockFixer.fixBlocks(
|
||||||
world,
|
world,
|
||||||
new BlockPos(bounds.minX(), bounds.minY(), bounds.minZ()),
|
new BlockPos(bounds.minX(), bounds.minY(), bounds.minZ()),
|
||||||
|
|
|
@ -167,9 +167,7 @@ public class SulphuricCaveFeature extends DefaultFeature {
|
||||||
state = world.getBlockState(mut);
|
state = world.getBlockState(mut);
|
||||||
while (state.is(Blocks.WATER)) {
|
while (state.is(Blocks.WATER)) {
|
||||||
BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.VENT_BUBBLE_COLUMN.defaultBlockState());
|
BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.VENT_BUBBLE_COLUMN.defaultBlockState());
|
||||||
//TODO: 1.18 test ticks
|
world.scheduleTick(mut.immutable(), EndBlocks.VENT_BUBBLE_COLUMN, MHelper.randRange(8, 32, random));
|
||||||
world/*.getBlockTicks()*/
|
|
||||||
.scheduleTick(mut, EndBlocks.VENT_BUBBLE_COLUMN, MHelper.randRange(8, 32, random));
|
|
||||||
mut.setY(mut.getY() + 1);
|
mut.setY(mut.getY() + 1);
|
||||||
state = world.getBlockState(mut);
|
state = world.getBlockState(mut);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemp
|
||||||
import ru.bclib.util.MHelper;
|
import ru.bclib.util.MHelper;
|
||||||
import ru.bclib.util.StructureHelper;
|
import ru.bclib.util.StructureHelper;
|
||||||
import ru.betterend.registry.EndStructures;
|
import ru.betterend.registry.EndStructures;
|
||||||
|
import ru.betterend.util.StructureErode;
|
||||||
import ru.betterend.world.biome.EndBiome;
|
import ru.betterend.world.biome.EndBiome;
|
||||||
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
@ -77,9 +78,7 @@ public class NBTPiece extends BasePiece {
|
||||||
this.boundingBox.minY(),
|
this.boundingBox.minY(),
|
||||||
blockBox.minZ()
|
blockBox.minZ()
|
||||||
), new Vec3i(blockBox.maxX(), this.boundingBox.maxX(), blockBox.maxZ()));
|
), new Vec3i(blockBox.maxX(), this.boundingBox.maxX(), blockBox.maxZ()));
|
||||||
StructurePlaceSettings placementData = new StructurePlaceSettings().setRotation(rotation)
|
StructurePlaceSettings placementData = new StructurePlaceSettings().setRotation(rotation).setMirror(mirror).setBoundingBox(bounds);
|
||||||
.setMirror(mirror)
|
|
||||||
.setBoundingBox(bounds);
|
|
||||||
structure.placeInWorld(world, pos, pos, placementData, random, 2);
|
structure.placeInWorld(world, pos, pos, placementData, random, 2);
|
||||||
if (erosion > 0) {
|
if (erosion > 0) {
|
||||||
int x1 = MHelper.min(bounds.maxX(), boundingBox.maxX());
|
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 z1 = MHelper.min(bounds.maxZ(), boundingBox.maxZ());
|
||||||
int z0 = MHelper.max(bounds.minZ(), boundingBox.minZ());
|
int z0 = MHelper.max(bounds.minZ(), boundingBox.minZ());
|
||||||
bounds = BoundingBox.fromCorners(new Vec3i(x0, bounds.minY(), z0), new Vec3i(x1, bounds.maxY(), z1));
|
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) {
|
if (cover) {
|
||||||
StructureHelper.cover(world, bounds, random, EndBiome.Config.DEFAULT_MATERIAL.getTopMaterial());
|
StructureErode.cover(world, bounds, random, EndBiome.Config.DEFAULT_MATERIAL.getTopMaterial());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue