Crashed ships, better erosion
This commit is contained in:
parent
10d315e1a2
commit
f9c49ba4aa
6 changed files with 223 additions and 2 deletions
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue