Crashed ships, better erosion

This commit is contained in:
paulevsGitch 2020-11-29 16:31:27 +03:00
parent 10d315e1a2
commit f9c49ba4aa
6 changed files with 223 additions and 2 deletions

View file

@ -12,6 +12,7 @@ import net.minecraft.world.gen.feature.ConfiguredFeature;
import ru.betterend.world.biome.EndBiome;
import ru.betterend.world.features.BlueVineFeature;
import ru.betterend.world.features.CavePlantFeature;
import ru.betterend.world.features.CrashedShipFeature;
import ru.betterend.world.features.DoublePlantFeature;
import ru.betterend.world.features.EndFeature;
import ru.betterend.world.features.EndLilyFeature;
@ -98,6 +99,9 @@ public class EndFeatures {
public static final EndFeature VIOLECITE_LAYER = EndFeature.makeLayerFeature("violecite_layer", EndBlocks.VIOLECITE, 15, 4, 96, 8);
public static final EndFeature FLAVOLITE_LAYER = EndFeature.makeLayerFeature("flavolite_layer", EndBlocks.FLAVOLITE, 12, 4, 96, 6);
// Buildings
public static final EndFeature CRASHED_SHIP = EndFeature.makeChansedFeature("crashed_ship", new CrashedShipFeature(), 500);
public static void registerBiomeFeatures(Identifier id, Biome biome, List<List<Supplier<ConfiguredFeature<?, ?>>>> features) {
if (id.getNamespace().equals("minecraft")) {
String path = id.getPath();
@ -115,6 +119,7 @@ public class EndFeatures {
addFeature(FLAVOLITE_LAYER, features);
addFeature(ENDER_ORE, features);
addFeature(CRASHED_SHIP, features);
if (!id.getPath().equals("blossoming_spires")) {
addFeature(ROUND_CAVE_RARE, features);

View file

@ -39,6 +39,7 @@ public class BlocksHelper {
public static final int SET_SILENT = FLAG_UPDATE_BLOCK | FLAG_IGNORE_OBSERVERS | FLAG_SEND_CLIENT_CHANGES;
public static final Direction[] HORIZONTAL = makeHorizontal();
public static final Direction[] DIRECTIONS = Direction.values();
private static final Mutable POS = new Mutable();
protected static final BlockState AIR = Blocks.AIR.getDefaultState();

View file

@ -3,6 +3,9 @@ package ru.betterend.util;
import java.io.IOException;
import java.io.InputStream;
import java.util.Random;
import java.util.Set;
import com.google.common.collect.Sets;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
@ -165,7 +168,7 @@ public class StructureHelper {
BlockState state = world.getBlockState(mut);
if (!ignore(state) && world.isAir(mut.down())) {
BlocksHelper.setWithoutUpdate(world, mut, Blocks.AIR);
for (int py = mut.getY(); y >= bounds.minY - 10; y--) {
for (int py = mut.getY(); py >= bounds.minY - 10; py--) {
mut.setY(py - 1);
if (!world.isAir(mut)) {
mut.setY(py);
@ -178,7 +181,124 @@ public class StructureHelper {
}
}
}
public static void erodeIntense(StructureWorldAccess world, BlockBox bounds, Random random) {
Mutable mut = new Mutable();
Mutable mut2 = new Mutable();
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)) {
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 (y > 50 && state.canPlaceAt(world, mut2)) {
mut2.setY(mut2.getY() + 1);
BlocksHelper.setWithoutUpdate(world, mut2, state);
}
}
}
else if (random.nextInt(8) == 0 && !world.getBlockState(mut.up()).isOf(EndBlocks.ETERNAL_PEDESTAL)) {
BlocksHelper.setWithoutUpdate(world, mut, Blocks.AIR);
}
}
}
}
}
drop(world, bounds);
}
private static boolean isTerrainNear(StructureWorldAccess world, BlockPos pos) {
for (Direction dir: BlocksHelper.DIRECTIONS) {
if (world.getBlockState(pos.offset(dir)).isIn(EndTags.GEN_TERRAIN)) {
return true;
}
}
return false;
}
private static void drop(StructureWorldAccess world, BlockBox bounds) {
Mutable mut = new Mutable();
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) && isTerrainNear(world, mut)) {
edge.add(mut.toImmutable());
}
}
}
}
if (edge.isEmpty()) {
return;
}
while (!edge.isEmpty()) {
for (BlockPos center: edge) {
for (Direction dir: BlocksHelper.DIRECTIONS) {
BlockState state = world.getBlockState(center);
if (state.isFullCube(world, center)) {
mut.set(center).move(dir);
if (bounds.contains(mut)) {
state = world.getBlockState(mut);
if (!ignore(state) && !blocks.contains(mut)) {
add.add(mut.toImmutable());
}
}
}
}
}
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) && !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) {
return state.getMaterial().isReplaceable()
|| !state.getFluidState().isEmpty()

View file

@ -0,0 +1,88 @@
package ru.betterend.world.features;
import java.util.Random;
import net.minecraft.structure.Structure;
import net.minecraft.structure.StructurePlacementData;
import net.minecraft.structure.processor.BlockIgnoreStructureProcessor;
import net.minecraft.util.BlockMirror;
import net.minecraft.util.BlockRotation;
import net.minecraft.util.math.BlockBox;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.StructureWorldAccess;
import net.minecraft.world.gen.chunk.ChunkGenerator;
import net.minecraft.world.gen.feature.DefaultFeatureConfig;
import ru.betterend.registry.EndTags;
import ru.betterend.util.BlocksHelper;
import ru.betterend.util.MHelper;
import ru.betterend.util.StructureHelper;
public class CrashedShipFeature extends NBTStructureFeature {
private static final String STRUCTURE_PATH = "/data/minecraft/structures/end_city/ship.nbt";
@Override
protected Structure getStructure(StructureWorldAccess world, BlockPos pos, Random random) {
return StructureHelper.readStructure(STRUCTURE_PATH);
}
@Override
protected boolean canSpawn(StructureWorldAccess world, BlockPos pos, Random random) {
int cx = pos.getX() >> 4;
int cz = pos.getZ() >> 4;
return ((cx + cz) & 1) == 0 && pos.getY() > 58 && world.getBlockState(pos.down()).isIn(EndTags.GEN_TERRAIN);
}
@Override
protected BlockRotation getRotation(StructureWorldAccess world, BlockPos pos, Random random) {
return BlockRotation.random(random);
}
@Override
protected BlockMirror getMirror(StructureWorldAccess world, BlockPos pos, Random random) {
return BlockMirror.values()[random.nextInt(3)];
}
@Override
protected int getYOffset(Structure structure, StructureWorldAccess world, BlockPos pos, Random random) {
int min = structure.getSize().getY() >> 3;
int max = structure.getSize().getY() >> 2;
return -MHelper.randRange(min, max, random);
}
@Override
protected TerrainMerge getTerrainMerge(StructureWorldAccess world, BlockPos pos, Random random) {
return TerrainMerge.NONE;
}
@Override
public boolean generate(StructureWorldAccess world, ChunkGenerator chunkGenerator, Random random, BlockPos center, DefaultFeatureConfig featureConfig) {
center = new BlockPos(((center.getX() >> 4) << 4) | 8, 128, ((center.getZ() >> 4) << 4) | 8);
center = getGround(world, center);
if (!canSpawn(world, center, random)) {
return false;
}
Structure structure = getStructure(world, center, random);
BlockRotation rotation = getRotation(world, center, random);
BlockMirror mirror = getMirror(world, center, random);
BlockPos offset = Structure.transformAround(structure.getSize(), mirror, rotation, BlockPos.ORIGIN);
center = center.add(0, getYOffset(structure, world, center, random) + 0.5, 0);
BlockBox bounds = makeBox(center);
StructurePlacementData placementData = new StructurePlacementData().setRotation(rotation).setMirror(mirror).setBoundingBox(bounds);
addStructureData(placementData);
center = center.add(-offset.getX() * 0.5, 0, -offset.getZ() * 0.5);
structure.place(world, center, placementData, random);
StructureHelper.erodeIntense(world, bounds, random);
BlocksHelper.fixBlocks(world, new BlockPos(bounds.minX, bounds.minY, bounds.minZ), new BlockPos(bounds.maxX, bounds.maxY, bounds.maxZ));
return true;
}
@Override
protected void addStructureData(StructurePlacementData data) {
data.addProcessor(BlockIgnoreStructureProcessor.IGNORE_AIR_AND_STRUCTURE_BLOCKS).setIgnoreEntities(true);
}
}

View file

@ -4,6 +4,7 @@ import java.util.List;
import java.util.Random;
import net.minecraft.structure.Structure;
import net.minecraft.structure.StructurePlacementData;
import net.minecraft.util.BlockMirror;
import net.minecraft.util.BlockRotation;
import net.minecraft.util.math.BlockPos;
@ -51,6 +52,9 @@ public class ListFeature extends NBTStructureFeature {
return selected.terrainMerge;
}
@Override
protected void addStructureData(StructurePlacementData data) {}
public static final class StructureInfo {
public final TerrainMerge terrainMerge;
public final Structure structure;

View file

@ -42,6 +42,8 @@ public abstract class NBTStructureFeature extends DefaultFeature {
protected abstract TerrainMerge getTerrainMerge(StructureWorldAccess world, BlockPos pos, Random random);
protected abstract void addStructureData(StructurePlacementData data);
protected BlockPos getGround(StructureWorldAccess world, BlockPos center) {
Biome biome = world.getBiome(center);
Identifier id = EndBiomes.getBiomeID(biome);
@ -91,6 +93,7 @@ public abstract class NBTStructureFeature extends DefaultFeature {
BlockBox bounds = makeBox(center);
StructurePlacementData placementData = new StructurePlacementData().setRotation(rotation).setMirror(mirror).setBoundingBox(bounds);
addStructureData(placementData);
center = center.add(-offset.getX() * 0.5, 0, -offset.getZ() * 0.5);
structure.place(world, center, placementData, random);
@ -158,7 +161,7 @@ public abstract class NBTStructureFeature extends DefaultFeature {
return true;
}
private BlockBox makeBox(BlockPos pos) {
protected BlockBox makeBox(BlockPos pos) {
int sx = ((pos.getX() >> 4) << 4) - 16;
int sz = ((pos.getZ() >> 4) << 4) - 16;
int ex = sx + 47;