This commit is contained in:
Aleksey 2020-10-06 17:59:27 +03:00
commit 8066d9c990
20 changed files with 791 additions and 75 deletions

View file

@ -14,6 +14,7 @@ import ru.betterend.registry.FeatureRegistry;
import ru.betterend.registry.ItemRegistry; import ru.betterend.registry.ItemRegistry;
import ru.betterend.registry.ItemTagRegistry; import ru.betterend.registry.ItemTagRegistry;
import ru.betterend.registry.SoundRegistry; import ru.betterend.registry.SoundRegistry;
import ru.betterend.registry.StructureRegistry;
import ru.betterend.util.Logger; import ru.betterend.util.Logger;
import ru.betterend.world.generator.BetterEndBiomeSource; import ru.betterend.world.generator.BetterEndBiomeSource;
import ru.betterend.world.surface.DoubleBlockSurfaceBuilder; import ru.betterend.world.surface.DoubleBlockSurfaceBuilder;
@ -38,6 +39,7 @@ public class BetterEnd implements ModInitializer {
BlockTagRegistry.register(); BlockTagRegistry.register();
CraftingRecipes.register(); CraftingRecipes.register();
AlloyingRecipes.register(); AlloyingRecipes.register();
StructureRegistry.register();
} }
public static Identifier makeID(String path) { public static Identifier makeID(String path) {

View file

@ -0,0 +1,45 @@
package ru.betterend.mixin.common;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
import net.minecraft.server.command.LocateCommand;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.gen.feature.StructureFeature;
import ru.betterend.util.StructureHelper;
@Mixin(LocateCommand.class)
public class LocateCommandMixin {
@Shadow
@Final
private static SimpleCommandExceptionType FAILED_EXCEPTION;
@Shadow
public static int sendCoordinates(ServerCommandSource source, String structure, BlockPos sourcePos,
BlockPos structurePos, String successMessage) {
return 0;
}
@Inject(method = "execute", at = @At("HEAD"), cancellable = true)
private static void execute(ServerCommandSource source, StructureFeature<?> structureFeature, CallbackInfoReturnable<Integer> info) throws CommandSyntaxException {
if (source.getWorld().getRegistryKey() == World.END) {
BlockPos blockPos = new BlockPos(source.getPosition());
BlockPos blockPos2 = StructureHelper.getNearestStructure(structureFeature, source.getWorld(), blockPos, 100);
if (blockPos2 == null) {
throw FAILED_EXCEPTION.create();
} else {
info.setReturnValue(sendCoordinates(source, structureFeature.getName(), blockPos, blockPos2, "commands.locate.success"));
info.cancel();
}
}
}
}

View file

@ -0,0 +1,21 @@
package ru.betterend.registry;
import net.minecraft.structure.StructurePieceType;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.gen.GenerationStep.Feature;
import ru.betterend.BetterEnd;
import ru.betterend.world.structures.EndStructureFeature;
import ru.betterend.world.structures.features.StructureGiantMossyGlowshroom;
import ru.betterend.world.structures.piece.VoxelPiece;
public class StructureRegistry {
public static final StructurePieceType VOXEL_PIECE = register("voxel", VoxelPiece::new);
public static final EndStructureFeature GIANT_MOSSY_GLOWSHROOM = new EndStructureFeature("giant_mossy_glowshroom", new StructureGiantMossyGlowshroom(), Feature.SURFACE_STRUCTURES, 16, 8);
public static void register() {}
private static StructurePieceType register(String id, StructurePieceType pieceType) {
return Registry.register(Registry.STRUCTURE_PIECE, BetterEnd.makeID(id), pieceType);
}
}

View file

@ -0,0 +1,62 @@
package ru.betterend.util;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.gen.ChunkRandom;
import net.minecraft.world.gen.chunk.StructureConfig;
import net.minecraft.world.gen.feature.StructureFeature;
public class StructureHelper {
private static final Set<ChunkPos> POSITIONS = new HashSet<ChunkPos>(64);
private static void collectNearby(ServerWorld world, StructureFeature<?> feature, int chunkX, int chunkZ, int radius, StructureConfig config, long worldSeed, ChunkRandom chunkRandom) {
int x1 = chunkX - radius;
int x2 = chunkX + radius;
int z1 = chunkZ - radius;
int z2 = chunkZ + radius;
POSITIONS.clear();
for (int x = x1; x <= x2; x += 8) {
for (int z = z1; z <= z2; z += 8) {
ChunkPos chunk = feature.getStartChunk(config, worldSeed, chunkRandom, x, z);
if (world.getBiome(chunk.getStartPos()).getGenerationSettings().hasStructureFeature(feature))
POSITIONS.add(chunk);
}
}
}
private static long sqr(int x) {
return (long) x * (long) x;
}
public static BlockPos getNearestStructure(StructureFeature<?> feature, ServerWorld world, BlockPos pos, int radius) {
int cx = pos.getX() >> 4;
int cz = pos.getZ() >> 4;
StructureConfig config = world.getChunkManager().getChunkGenerator().getStructuresConfig().getForType(feature);
if (config == null)
return null;
collectNearby(world, feature, cx, cz, radius, config, world.getSeed(), new ChunkRandom());
Iterator<ChunkPos> iterator = POSITIONS.iterator();
if (iterator.hasNext()) {
ChunkPos nearest = POSITIONS.iterator().next();
long d = sqr(nearest.x - cx) + sqr(nearest.z - cz);
while (iterator.hasNext()) {
ChunkPos n = iterator.next();
long d2 = sqr(n.x - cx) + sqr(n.z - cz);
if (d2 < d) {
d = d2;
nearest = n;
}
}
return nearest.getStartPos();
}
return null;
}
}

View file

@ -7,18 +7,20 @@ import net.minecraft.block.Blocks;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction; import net.minecraft.util.math.Direction;
public class PosInfo { public class PosInfo implements Comparable<PosInfo> {
private static final BlockState AIR = Blocks.AIR.getDefaultState(); private static final BlockState AIR = Blocks.AIR.getDefaultState();
private final Map<BlockPos, PosInfo> blocks; private final Map<BlockPos, PosInfo> blocks;
private final Map<BlockPos, PosInfo> add;
private final BlockPos pos; private final BlockPos pos;
private BlockState state; private BlockState state;
public static PosInfo create(Map<BlockPos, PosInfo> blocks, BlockPos pos) { public static PosInfo create(Map<BlockPos, PosInfo> blocks, Map<BlockPos, PosInfo> add, BlockPos pos) {
return new PosInfo(blocks, pos); return new PosInfo(blocks, add, pos);
} }
private PosInfo(Map<BlockPos, PosInfo> blocks, BlockPos pos) { private PosInfo(Map<BlockPos, PosInfo> blocks, Map<BlockPos, PosInfo> add, BlockPos pos) {
this.blocks = blocks; this.blocks = blocks;
this.add = add;
this.pos = pos; this.pos = pos;
blocks.put(pos, this); blocks.put(pos, this);
} }
@ -33,6 +35,15 @@ public class PosInfo {
public BlockState getState(Direction dir) { public BlockState getState(Direction dir) {
PosInfo info = blocks.get(pos.offset(dir)); PosInfo info = blocks.get(pos.offset(dir));
if (info == null) {
info = add.get(pos.offset(dir));
return info == null ? AIR : info.getState();
}
return info.getState();
}
public BlockState getState(Direction dir, int distance) {
PosInfo info = blocks.get(pos.offset(dir, distance));
if (info == null) { if (info == null) {
return AIR; return AIR;
} }
@ -47,14 +58,31 @@ public class PosInfo {
return getState(Direction.DOWN); return getState(Direction.DOWN);
} }
@Override
public int hashCode() { public int hashCode() {
return pos.hashCode(); return pos.hashCode();
} }
@Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (!(obj instanceof PosInfo)) { if (!(obj instanceof PosInfo)) {
return false; return false;
} }
return pos.equals(((PosInfo) obj).pos); return pos.equals(((PosInfo) obj).pos);
} }
@Override
public int compareTo(PosInfo info) {
return this.pos.getY() - info.pos.getY();
}
public BlockPos getPos() {
return pos;
}
public void setBlockPos(BlockPos pos, BlockState state) {
PosInfo info = new PosInfo(blocks, add, pos);
info.state = state;
add.put(pos, info);
}
} }

View file

@ -1,5 +1,8 @@
package ru.betterend.util.sdf; package ru.betterend.util.sdf;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.function.Function; import java.util.function.Function;
@ -12,6 +15,7 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction; import net.minecraft.util.math.Direction;
import net.minecraft.world.ServerWorldAccess; import net.minecraft.world.ServerWorldAccess;
import ru.betterend.util.BlocksHelper; import ru.betterend.util.BlocksHelper;
import ru.betterend.world.structures.StructureWorld;
public abstract class SDF { public abstract class SDF {
private Function<PosInfo, BlockState> postProcess = (info) -> { private Function<PosInfo, BlockState> postProcess = (info) -> {
@ -35,8 +39,9 @@ public abstract class SDF {
return this; return this;
} }
public Set<BlockPos> fillRecursive(ServerWorldAccess world, BlockPos start, int dx, int dy, int dz) { public void fillRecursive(ServerWorldAccess world, BlockPos start, int dx, int dy, int dz) {
Map<BlockPos, PosInfo> mapWorld = Maps.newHashMap(); Map<BlockPos, PosInfo> mapWorld = Maps.newHashMap();
Map<BlockPos, PosInfo> addInfo = Maps.newHashMap();
Set<BlockPos> blocks = Sets.newHashSet(); Set<BlockPos> blocks = Sets.newHashSet();
Set<BlockPos> ends = Sets.newHashSet(); Set<BlockPos> ends = Sets.newHashSet();
Set<BlockPos> add = Sets.newHashSet(); Set<BlockPos> add = Sets.newHashSet();
@ -56,7 +61,7 @@ public abstract class SDF {
if (!blocks.contains(pos) && canReplace.apply(world.getBlockState(wpos))) { if (!blocks.contains(pos) && canReplace.apply(world.getBlockState(wpos))) {
if (this.getDistance(pos.getX(), pos.getY(), pos.getZ()) < 0) { if (this.getDistance(pos.getX(), pos.getY(), pos.getZ()) < 0) {
BlockState state = getBlockState(wpos); BlockState state = getBlockState(wpos);
PosInfo.create(mapWorld, wpos).setState(state); PosInfo.create(mapWorld, addInfo, wpos).setState(state);
if (Math.abs(pos.getX()) < dx && Math.abs(pos.getY()) < dy && Math.abs(pos.getZ()) < dz) { if (Math.abs(pos.getX()) < dx && Math.abs(pos.getY()) < dy && Math.abs(pos.getZ()) < dz) {
add.add(pos); add.add(pos);
} }
@ -73,16 +78,29 @@ public abstract class SDF {
run &= !ends.isEmpty(); run &= !ends.isEmpty();
} }
mapWorld.forEach((pos, info) -> { List<PosInfo> infos = new ArrayList<PosInfo>(mapWorld.values());
BlockState state = postProcess.apply(info); if (infos.size() > 0) {
BlocksHelper.setWithoutUpdate(world, pos, state); Collections.sort(infos);
}); infos.forEach((info) -> {
BlockState state = postProcess.apply(info);
BlocksHelper.setWithoutUpdate(world, info.getPos(), state);
});
return mapWorld.keySet(); infos.clear();
infos.addAll(addInfo.values());
Collections.sort(infos);
infos.forEach((info) -> {
if (canReplace.apply(world.getBlockState(info.getPos()))) {
BlockState state = postProcess.apply(info);
BlocksHelper.setWithoutUpdate(world, info.getPos(), state);
}
});
}
} }
public Set<BlockPos> fillRecursive(ServerWorldAccess world, BlockPos start) { public void fillRecursive(ServerWorldAccess world, BlockPos start) {
Map<BlockPos, PosInfo> mapWorld = Maps.newHashMap(); Map<BlockPos, PosInfo> mapWorld = Maps.newHashMap();
Map<BlockPos, PosInfo> addInfo = Maps.newHashMap();
Set<BlockPos> blocks = Sets.newHashSet(); Set<BlockPos> blocks = Sets.newHashSet();
Set<BlockPos> ends = Sets.newHashSet(); Set<BlockPos> ends = Sets.newHashSet();
Set<BlockPos> add = Sets.newHashSet(); Set<BlockPos> add = Sets.newHashSet();
@ -98,7 +116,7 @@ public abstract class SDF {
if (!blocks.contains(pos) && canReplace.apply(world.getBlockState(wpos))) { if (!blocks.contains(pos) && canReplace.apply(world.getBlockState(wpos))) {
if (this.getDistance(pos.getX(), pos.getY(), pos.getZ()) < 0) { if (this.getDistance(pos.getX(), pos.getY(), pos.getZ()) < 0) {
BlockState state = getBlockState(wpos); BlockState state = getBlockState(wpos);
PosInfo.create(mapWorld, wpos).setState(state); PosInfo.create(mapWorld, addInfo, wpos).setState(state);
add.add(pos); add.add(pos);
} }
} }
@ -113,11 +131,72 @@ public abstract class SDF {
run &= !ends.isEmpty(); run &= !ends.isEmpty();
} }
mapWorld.forEach((pos, info) -> { List<PosInfo> infos = new ArrayList<PosInfo>(mapWorld.values());
if (infos.size() > 0) {
Collections.sort(infos);
infos.forEach((info) -> {
BlockState state = postProcess.apply(info);
BlocksHelper.setWithoutUpdate(world, info.getPos(), state);
});
infos.clear();
infos.addAll(addInfo.values());
Collections.sort(infos);
infos.forEach((info) -> {
if (canReplace.apply(world.getBlockState(info.getPos()))) {
BlockState state = postProcess.apply(info);
BlocksHelper.setWithoutUpdate(world, info.getPos(), state);
}
});
}
}
public void fillRecursive(StructureWorld world, BlockPos start) {
Map<BlockPos, PosInfo> mapWorld = Maps.newHashMap();
Map<BlockPos, PosInfo> addInfo = Maps.newHashMap();
Set<BlockPos> blocks = Sets.newHashSet();
Set<BlockPos> ends = Sets.newHashSet();
Set<BlockPos> add = Sets.newHashSet();
ends.add(new BlockPos(0, 0, 0));
boolean run = true;
while (run) {
for (BlockPos center: ends) {
for (Direction dir: Direction.values()) {
BlockPos pos = center.offset(dir);
BlockPos wpos = pos.add(start);
if (!blocks.contains(pos)) {
if (this.getDistance(pos.getX(), pos.getY(), pos.getZ()) < 0) {
BlockState state = getBlockState(wpos);
PosInfo.create(mapWorld, addInfo, wpos).setState(state);
add.add(pos);
}
}
}
}
blocks.addAll(ends);
ends.clear();
ends.addAll(add);
add.clear();
run &= !ends.isEmpty();
}
List<PosInfo> infos = new ArrayList<PosInfo>(mapWorld.values());
Collections.sort(infos);
infos.forEach((info) -> {
BlockState state = postProcess.apply(info); BlockState state = postProcess.apply(info);
BlocksHelper.setWithoutUpdate(world, pos, state); world.setBlock(info.getPos(), state);
}); });
return mapWorld.keySet(); infos.clear();
infos.addAll(addInfo.values());
Collections.sort(infos);
infos.forEach((info) -> {
BlockState state = postProcess.apply(info);
world.setBlock(info.getPos(), state);
});
} }
} }

View file

@ -0,0 +1,15 @@
package ru.betterend.util.sdf.operator;
public class SDFRound extends SDFUnary {
private float radius;
public SDFRound setRadius(float radius) {
this.radius = radius;
return this;
}
@Override
public float getDistance(float x, float y, float z) {
return this.source.getDistance(x, y, z) - radius;
}
}

View file

@ -32,4 +32,8 @@ public abstract class SDFPrimitive extends SDF {
public BlockState getBlockState(BlockPos pos) { public BlockState getBlockState(BlockPos pos) {
return placerFunction.apply(pos); return placerFunction.apply(pos);
} }
/*public abstract CompoundTag toNBT(CompoundTag root) {
}*/
} }

View file

@ -33,6 +33,7 @@ import net.minecraft.world.gen.surfacebuilder.TernarySurfaceConfig;
import ru.betterend.BetterEnd; import ru.betterend.BetterEnd;
import ru.betterend.util.MHelper; import ru.betterend.util.MHelper;
import ru.betterend.world.features.EndFeature; import ru.betterend.world.features.EndFeature;
import ru.betterend.world.structures.EndStructureFeature;
import ru.betterend.world.surface.DoubleBlockSurfaceBuilder; import ru.betterend.world.surface.DoubleBlockSurfaceBuilder;
public class BiomeDefinition { public class BiomeDefinition {
@ -112,6 +113,11 @@ public class BiomeDefinition {
return this; return this;
} }
public BiomeDefinition addStructureFeature(EndStructureFeature feature) {
structures.add(feature.getFeatureConfigured());
return this;
}
public BiomeDefinition addFeature(EndFeature feature) { public BiomeDefinition addFeature(EndFeature feature) {
FeatureInfo info = new FeatureInfo(); FeatureInfo info = new FeatureInfo();
info.featureStep = feature.getFeatureStep(); info.featureStep = feature.getFeatureStep();

View file

@ -6,6 +6,7 @@ import ru.betterend.registry.EntityRegistry;
import ru.betterend.registry.FeatureRegistry; import ru.betterend.registry.FeatureRegistry;
import ru.betterend.registry.ParticleRegistry; import ru.betterend.registry.ParticleRegistry;
import ru.betterend.registry.SoundRegistry; import ru.betterend.registry.SoundRegistry;
import ru.betterend.registry.StructureRegistry;
public class BiomeFoggyMushroomland extends EndBiome { public class BiomeFoggyMushroomland extends EndBiome {
public BiomeFoggyMushroomland() { public BiomeFoggyMushroomland() {
@ -18,6 +19,7 @@ public class BiomeFoggyMushroomland extends EndBiome {
.setParticles(ParticleRegistry.GLOWING_SPHERE, 0.001F) .setParticles(ParticleRegistry.GLOWING_SPHERE, 0.001F)
.setLoop(SoundRegistry.AMBIENT_FOGGY_MUSHROOMLAND) .setLoop(SoundRegistry.AMBIENT_FOGGY_MUSHROOMLAND)
.setMusic(SoundRegistry.MUSIC_FOGGY_MUSHROOMLAND) .setMusic(SoundRegistry.MUSIC_FOGGY_MUSHROOMLAND)
.addStructureFeature(StructureRegistry.GIANT_MOSSY_GLOWSHROOM)
.addFeature(FeatureRegistry.ENDER_ORE) .addFeature(FeatureRegistry.ENDER_ORE)
.addFeature(FeatureRegistry.END_LAKE) .addFeature(FeatureRegistry.END_LAKE)
.addFeature(FeatureRegistry.MOSSY_GLOWSHROOM) .addFeature(FeatureRegistry.MOSSY_GLOWSHROOM)

View file

@ -2,7 +2,6 @@ package ru.betterend.world.features;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
import java.util.Set;
import java.util.function.Function; import java.util.function.Function;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
@ -23,7 +22,6 @@ import ru.betterend.registry.BlockTagRegistry;
import ru.betterend.util.BlocksHelper; import ru.betterend.util.BlocksHelper;
import ru.betterend.util.MHelper; import ru.betterend.util.MHelper;
import ru.betterend.util.SplineHelper; import ru.betterend.util.SplineHelper;
import ru.betterend.util.sdf.PosInfo;
import ru.betterend.util.sdf.SDF; import ru.betterend.util.sdf.SDF;
import ru.betterend.util.sdf.operator.SDFBinary; import ru.betterend.util.sdf.operator.SDFBinary;
import ru.betterend.util.sdf.operator.SDFCoordModify; import ru.betterend.util.sdf.operator.SDFCoordModify;
@ -39,7 +37,6 @@ import ru.betterend.util.sdf.primitive.SDFPrimitive;
import ru.betterend.util.sdf.primitive.SDFSphere; import ru.betterend.util.sdf.primitive.SDFSphere;
public class MossyGlowshroomFeature extends DefaultFeature { public class MossyGlowshroomFeature extends DefaultFeature {
private static final Function<PosInfo, BlockState> POST_PROCESS;
private static final Function<BlockState, Boolean> REPLACE; private static final Function<BlockState, Boolean> REPLACE;
private static final Vector3f CENTER = new Vector3f(); private static final Vector3f CENTER = new Vector3f();
private static final SDFBinary FUNCTION; private static final SDFBinary FUNCTION;
@ -112,37 +109,43 @@ public class MossyGlowshroomFeature extends DefaultFeature {
ROOTS_ROT.setAngle(random.nextFloat() * MHelper.PI2); ROOTS_ROT.setAngle(random.nextFloat() * MHelper.PI2);
FUNCTION.setSourceA(sdf); FUNCTION.setSourceA(sdf);
Set<BlockPos> blocks = new SDFScale() new SDFScale().setScale(scale)
.setScale(scale)
.setSource(FUNCTION) .setSource(FUNCTION)
.setReplaceFunction(REPLACE) .setReplaceFunction(REPLACE)
.setPostProcess(POST_PROCESS) .setPostProcess((info) -> {
.fillRecursive(world, blockPos); if (BlockRegistry.MOSSY_GLOWSHROOM.isTreeLog(info.getState())) {
if (random.nextBoolean() && info.getStateUp().getBlock() == BlockRegistry.MOSSY_GLOWSHROOM_CAP) {
info.setState(BlockRegistry.MOSSY_GLOWSHROOM_CAP.getDefaultState().with(BlockMossyGlowshroomCap.TRANSITION, true));
return info.getState();
}
else if (!BlockRegistry.MOSSY_GLOWSHROOM.isTreeLog(info.getStateUp()) || !BlockRegistry.MOSSY_GLOWSHROOM.isTreeLog(info.getStateDown())) {
info.setState(BlockRegistry.MOSSY_GLOWSHROOM.bark.getDefaultState());
return info.getState();
}
}
else if (info.getState().getBlock() == BlockRegistry.MOSSY_GLOWSHROOM_CAP) {
if (BlockRegistry.MOSSY_GLOWSHROOM.isTreeLog(info.getStateDown().getBlock())) {
info.setState(BlockRegistry.MOSSY_GLOWSHROOM_CAP.getDefaultState().with(BlockMossyGlowshroomCap.TRANSITION, true));
return info.getState();
}
for (BlockPos bpos: blocks) { info.setState(BlockRegistry.MOSSY_GLOWSHROOM_CAP.getDefaultState());
BlockState state = world.getBlockState(bpos); return info.getState();
if (state.getBlock() == BlockRegistry.MOSSY_GLOWSHROOM_HYMENOPHORE) { }
if (world.isAir(bpos.north())) { else if (info.getState().getBlock() == BlockRegistry.MOSSY_GLOWSHROOM_HYMENOPHORE) {
BlocksHelper.setWithoutUpdate(world, bpos.north(), BlockRegistry.MOSSY_GLOWSHROOM_FUR.getDefaultState().with(BlockGlowingFur.FACING, Direction.NORTH)); for (Direction dir: BlocksHelper.HORIZONTAL) {
} if (info.getState(dir) == AIR) {
if (world.isAir(bpos.east())) { info.setBlockPos(info.getPos().offset(dir), BlockRegistry.MOSSY_GLOWSHROOM_FUR.getDefaultState().with(BlockGlowingFur.FACING, dir));
BlocksHelper.setWithoutUpdate(world, bpos.east(), BlockRegistry.MOSSY_GLOWSHROOM_FUR.getDefaultState().with(BlockGlowingFur.FACING, Direction.EAST)); }
} }
if (world.isAir(bpos.south())) {
BlocksHelper.setWithoutUpdate(world, bpos.south(), BlockRegistry.MOSSY_GLOWSHROOM_FUR.getDefaultState().with(BlockGlowingFur.FACING, Direction.SOUTH)); if (info.getStateDown().getBlock() != BlockRegistry.MOSSY_GLOWSHROOM_HYMENOPHORE) {
} info.setBlockPos(info.getPos().down(), BlockRegistry.MOSSY_GLOWSHROOM_FUR.getDefaultState().with(BlockGlowingFur.FACING, Direction.DOWN));
if (world.isAir(bpos.west())) { }
BlocksHelper.setWithoutUpdate(world, bpos.west(), BlockRegistry.MOSSY_GLOWSHROOM_FUR.getDefaultState().with(BlockGlowingFur.FACING, Direction.WEST)); }
} return info.getState();
if (world.getBlockState(bpos.down()).getMaterial().isReplaceable()) { })
BlocksHelper.setWithoutUpdate(world, bpos.down(), BlockRegistry.MOSSY_GLOWSHROOM_FUR.getDefaultState().with(BlockGlowingFur.FACING, Direction.DOWN)); .fillRecursive(world, blockPos);
}
}
else if (BlockRegistry.MOSSY_GLOWSHROOM.isTreeLog(state) && random.nextBoolean() && world.getBlockState(bpos.up()).getBlock() == BlockRegistry.MOSSY_GLOWSHROOM_CAP) {
BlocksHelper.setWithoutUpdate(world, bpos, BlockRegistry.MOSSY_GLOWSHROOM_CAP.getDefaultState().with(BlockMossyGlowshroomCap.TRANSITION, true));
BlocksHelper.setWithoutUpdate(world, bpos.up(), BlockRegistry.MOSSY_GLOWSHROOM_CAP);
}
}
return true; return true;
} }
@ -151,7 +154,7 @@ public class MossyGlowshroomFeature extends DefaultFeature {
SDFCapedCone cone1 = new SDFCapedCone().setHeight(2.5F).setRadius1(1.5F).setRadius2(2.5F); SDFCapedCone cone1 = new SDFCapedCone().setHeight(2.5F).setRadius1(1.5F).setRadius2(2.5F);
SDFCapedCone cone2 = new SDFCapedCone().setHeight(3F).setRadius1(2.5F).setRadius2(13F); SDFCapedCone cone2 = new SDFCapedCone().setHeight(3F).setRadius1(2.5F).setRadius2(13F);
SDF posedCone2 = new SDFTranslate().setTranslate(0, 5, 0).setSource(cone2); SDF posedCone2 = new SDFTranslate().setTranslate(0, 5, 0).setSource(cone2);
SDF posedCone3 = new SDFTranslate().setTranslate(0, 7F, 0).setSource(cone2); SDF posedCone3 = new SDFTranslate().setTranslate(0, 12F, 0).setSource(new SDFScale().setScale(2).setSource(cone2));
SDF upCone = new SDFSubtraction().setSourceA(posedCone2).setSourceB(posedCone3); SDF upCone = new SDFSubtraction().setSourceA(posedCone2).setSourceB(posedCone3);
SDF wave = new SDFFlatWave().setRaysCount(12).setIntensity(1.3F).setSource(upCone); SDF wave = new SDFFlatWave().setRaysCount(12).setIntensity(1.3F).setSource(upCone);
SDF cones = new SDFSmoothUnion().setRadius(3).setSourceA(cone1).setSourceB(wave); SDF cones = new SDFSmoothUnion().setRadius(3).setSourceA(cone1).setSourceB(wave);
@ -195,30 +198,5 @@ public class MossyGlowshroomFeature extends DefaultFeature {
} }
return state.getMaterial().isReplaceable(); return state.getMaterial().isReplaceable();
}; };
POST_PROCESS = (info) -> {
if (BlockRegistry.MOSSY_GLOWSHROOM.isTreeLog(info.getState())) {
if (!BlockRegistry.MOSSY_GLOWSHROOM.isTreeLog(info.getStateUp()) || !BlockRegistry.MOSSY_GLOWSHROOM.isTreeLog(info.getStateDown())) {
return BlockRegistry.MOSSY_GLOWSHROOM.bark.getDefaultState();
}
}
else if (info.getState().getBlock() == BlockRegistry.MOSSY_GLOWSHROOM_CAP) {
if (BlockRegistry.MOSSY_GLOWSHROOM.isTreeLog(info.getStateDown())) {
return info.getState().with(BlockMossyGlowshroomCap.TRANSITION, true);
}
int air = 0;
for (Direction dir: Direction.values()) {
if (info.getState(dir).isAir()) {
air ++;
}
}
if (air > 4) {
info.setState(AIR);
return AIR;
}
}
return info.getState();
};
} }
} }

View file

@ -21,7 +21,7 @@ public class VineFeature extends InvertedScatterFeature {
@Override @Override
public boolean canGenerate(StructureWorldAccess world, Random random, BlockPos center, BlockPos blockPos, float radius) { public boolean canGenerate(StructureWorldAccess world, Random random, BlockPos center, BlockPos blockPos, float radius) {
return vineBlock.canPlaceAt(AIR, world, blockPos); return world.isAir(blockPos) && vineBlock.canPlaceAt(AIR, world, blockPos);
} }
@Override @Override

View file

@ -0,0 +1,45 @@
package ru.betterend.world.structures;
import java.util.Random;
import net.fabricmc.fabric.api.structure.v1.FabricStructureBuilder;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.BuiltinRegistries;
import net.minecraft.world.gen.GenerationStep;
import net.minecraft.world.gen.feature.ConfiguredStructureFeature;
import net.minecraft.world.gen.feature.DefaultFeatureConfig;
import net.minecraft.world.gen.feature.StructureFeature;
import ru.betterend.BetterEnd;
public class EndStructureFeature {
private static final Random RANDOM = new Random(354);
private final StructureFeature<DefaultFeatureConfig> structure;
private final ConfiguredStructureFeature<?, ?> featureConfigured;
private final GenerationStep.Feature featureStep;
public EndStructureFeature(String name, StructureFeature<DefaultFeatureConfig> structure, GenerationStep.Feature step, int spacing, int separation) {
Identifier id = BetterEnd.makeID(name);
this.featureStep = step;
this.structure = FabricStructureBuilder.create(id, structure)
.step(step)
.defaultConfig(spacing, separation, RANDOM.nextInt(8192))
.register();
this.featureConfigured = this.structure.configure(DefaultFeatureConfig.DEFAULT);
BuiltinRegistries.add(BuiltinRegistries.CONFIGURED_STRUCTURE_FEATURE, id, this.featureConfigured);
}
public StructureFeature<DefaultFeatureConfig> getStructure() {
return structure;
}
public ConfiguredStructureFeature<?, ?> getFeatureConfigured() {
return featureConfigured;
}
public GenerationStep.Feature getFeatureStep() {
return featureStep;
}
}

View file

@ -0,0 +1,139 @@
package ru.betterend.world.structures;
import java.util.Map;
import com.google.common.collect.Maps;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.NbtHelper;
import net.minecraft.util.math.BlockBox;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.StructureWorldAccess;
import net.minecraft.world.chunk.Chunk;
public class StructureWorld {
private Map<ChunkPos, Part> parts = Maps.newHashMap();
private int minX = Integer.MAX_VALUE;
private int minY = Integer.MAX_VALUE;
private int minZ = Integer.MAX_VALUE;
private int maxX = Integer.MIN_VALUE;
private int maxY = Integer.MIN_VALUE;
private int maxZ = Integer.MIN_VALUE;
public StructureWorld() {}
public StructureWorld(CompoundTag tag) {
minX = tag.getInt("minX");
maxX = tag.getInt("maxX");
minY = tag.getInt("minY");
maxY = tag.getInt("maxY");
minZ = tag.getInt("minZ");
maxZ = tag.getInt("maxZ");
ListTag map = tag.getList("parts", 10);
map.forEach((element) -> {
CompoundTag compound = (CompoundTag) element;
Part part = new Part(compound);
int x = compound.getInt("x");
int z = compound.getInt("z");
parts.put(new ChunkPos(x, z), part);
});
}
public void setBlock(BlockPos pos, BlockState state) {
ChunkPos cPos = new ChunkPos(pos);
Part part = parts.get(cPos);
if (part == null) {
part = new Part();
parts.put(cPos, part);
if (cPos.x < minX) minX = cPos.x;
if (cPos.x > maxX) maxX = cPos.x;
if (cPos.z < minZ) minZ = cPos.z;
if (cPos.z > maxZ) maxZ = cPos.z;
}
if (pos.getY() < minY) minY = pos.getY();
if (pos.getY() > maxY) maxY = pos.getY();
part.addBlock(pos, state);
}
public boolean placeChunk(StructureWorldAccess world, ChunkPos chunkPos) {
Part part = parts.get(chunkPos);
if (part != null) {
Chunk chunk = world.getChunk(chunkPos.x, chunkPos.z);
part.placeChunk(chunk);
return true;
}
return false;
}
public CompoundTag toBNT() {
CompoundTag tag = new CompoundTag();
tag.putInt("minX", minX);
tag.putInt("maxX", maxX);
tag.putInt("minY", minY);
tag.putInt("maxY", maxY);
tag.putInt("minZ", minZ);
tag.putInt("maxZ", maxZ);
ListTag map = new ListTag();
tag.put("parts", map);
parts.forEach((pos, part) -> {
map.add(part.toNBT(pos.x, pos.z));
});
return tag;
}
public BlockBox getBounds() {
if (minX == Integer.MAX_VALUE || maxX == Integer.MIN_VALUE || minZ == Integer.MAX_VALUE || maxZ == Integer.MIN_VALUE) {
return BlockBox.empty();
}
return new BlockBox(minX << 4, minY, minZ << 4, (maxX << 4) | 15, maxY, (maxZ << 4) | 15);
}
private static final class Part {
Map<BlockPos, BlockState> blocks = Maps.newHashMap();
public Part() {}
public Part(CompoundTag tag) {
ListTag map = tag.getList("blocks", 10);
map.forEach((element) -> {
CompoundTag block = (CompoundTag) element;
BlockPos pos = NbtHelper.toBlockPos(block.getCompound("pos"));
BlockState state = Block.getStateFromRawId(block.getInt("state"));
blocks.put(pos, state);
});
}
void addBlock(BlockPos pos, BlockState state) {
BlockPos inner = new BlockPos(pos.getX() & 15, pos.getY(), pos.getZ() & 15);
blocks.put(inner, state);
}
void placeChunk(Chunk chunk) {
blocks.forEach((pos, state) -> {
//if (pos.getY() > 10)
chunk.setBlockState(pos, state, false);
});
}
CompoundTag toNBT(int x, int z) {
CompoundTag tag = new CompoundTag();
tag.putInt("x", x);
tag.putInt("z", z);
ListTag map = new ListTag();
tag.put("blocks", map);
blocks.forEach((pos, state) -> {
CompoundTag block = new CompoundTag();
block.put("pos", NbtHelper.fromBlockPos(pos));
block.putInt("state", Block.getRawIdFromState(state));
map.add(block);
});
return tag;
}
}
}

View file

@ -0,0 +1,46 @@
package ru.betterend.world.structures.features;
import java.util.Random;
import net.minecraft.structure.StructureManager;
import net.minecraft.structure.StructureStart;
import net.minecraft.util.math.BlockBox;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.registry.DynamicRegistryManager;
import net.minecraft.world.Heightmap.Type;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.gen.chunk.ChunkGenerator;
import net.minecraft.world.gen.feature.DefaultFeatureConfig;
import net.minecraft.world.gen.feature.StructureFeature;
import ru.betterend.util.MHelper;
import ru.betterend.util.sdf.SDF;
import ru.betterend.world.structures.piece.VoxelPiece;
public abstract class SDFStructureFeature extends StructureFeatureBase {
protected abstract SDF getSDF(BlockPos pos, Random random);
@Override
public StructureFeature.StructureStartFactory<DefaultFeatureConfig> getStructureStartFactory() {
return SDFStructureStart::new;
}
public static class SDFStructureStart extends StructureStart<DefaultFeatureConfig> {
public SDFStructureStart(StructureFeature<DefaultFeatureConfig> feature, int chunkX, int chunkZ, BlockBox box, int references, long seed) {
super(feature, chunkX, chunkZ, box, references, seed);
}
@Override
public void init(DynamicRegistryManager registryManager, ChunkGenerator chunkGenerator, StructureManager manager, int chunkX, int chunkZ, Biome biome, DefaultFeatureConfig config) {
int x = (chunkX << 4) | MHelper.randRange(4, 12, random);
int z = (chunkZ << 4) | MHelper.randRange(4, 12, random);
int y = chunkGenerator.getHeight(x, z, Type.WORLD_SURFACE_WG);
if (y > 5) {
BlockPos start = new BlockPos(x, y, z);
VoxelPiece piece = new VoxelPiece((world) -> { ((SDFStructureFeature) this.getFeature()).getSDF(start, this.random).fillRecursive(world, start); }, random.nextInt());
this.children.add(piece);
}
this.setBoundingBoxFromChildren();
}
}
}

View file

@ -0,0 +1,50 @@
package ru.betterend.world.structures.features;
import java.util.Random;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.util.BlockRotation;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.Heightmap;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.source.BiomeSource;
import net.minecraft.world.gen.ChunkRandom;
import net.minecraft.world.gen.chunk.ChunkGenerator;
import net.minecraft.world.gen.feature.DefaultFeatureConfig;
import net.minecraft.world.gen.feature.StructureFeature;
public abstract class StructureFeatureBase extends StructureFeature<DefaultFeatureConfig> {
protected static final BlockState AIR = Blocks.AIR.getDefaultState();
public StructureFeatureBase() {
super(DefaultFeatureConfig.CODEC);
}
protected boolean shouldStartAt(ChunkGenerator chunkGenerator, BiomeSource biomeSource, long worldSeed, ChunkRandom chunkRandom, int chunkX, int chunkZ, Biome biome, ChunkPos chunkPos, DefaultFeatureConfig featureConfig) {
return getGenerationHeight(chunkX, chunkZ, chunkGenerator) >= 50;
}
private static int getGenerationHeight(int chunkX, int chunkZ, ChunkGenerator chunkGenerator) {
Random random = new Random((long) (chunkX + chunkZ * 10387313));
BlockRotation blockRotation = BlockRotation.random(random);
int i = 5;
int j = 5;
if (blockRotation == BlockRotation.CLOCKWISE_90) {
i = -5;
} else if (blockRotation == BlockRotation.CLOCKWISE_180) {
i = -5;
j = -5;
} else if (blockRotation == BlockRotation.COUNTERCLOCKWISE_90) {
j = -5;
}
int k = (chunkX << 4) + 7;
int l = (chunkZ << 4) + 7;
int m = chunkGenerator.getHeightInGround(k, l, Heightmap.Type.WORLD_SURFACE_WG);
int n = chunkGenerator.getHeightInGround(k, l + j, Heightmap.Type.WORLD_SURFACE_WG);
int o = chunkGenerator.getHeightInGround(k + i, l, Heightmap.Type.WORLD_SURFACE_WG);
int p = chunkGenerator.getHeightInGround(k + i, l + j, Heightmap.Type.WORLD_SURFACE_WG);
return Math.min(Math.min(m, n), Math.min(o, p));
}
}

View file

@ -0,0 +1,127 @@
package ru.betterend.world.structures.features;
import java.util.List;
import java.util.Random;
import net.minecraft.client.util.math.Vector3f;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import ru.betterend.blocks.BlockMossyGlowshroomCap;
import ru.betterend.blocks.basis.BlockGlowingFur;
import ru.betterend.noise.OpenSimplexNoise;
import ru.betterend.registry.BlockRegistry;
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.SDFBinary;
import ru.betterend.util.sdf.operator.SDFCoordModify;
import ru.betterend.util.sdf.operator.SDFFlatWave;
import ru.betterend.util.sdf.operator.SDFRound;
import ru.betterend.util.sdf.operator.SDFScale;
import ru.betterend.util.sdf.operator.SDFScale3D;
import ru.betterend.util.sdf.operator.SDFSmoothUnion;
import ru.betterend.util.sdf.operator.SDFSubtraction;
import ru.betterend.util.sdf.operator.SDFTranslate;
import ru.betterend.util.sdf.operator.SDFUnion;
import ru.betterend.util.sdf.primitive.SDFCapedCone;
import ru.betterend.util.sdf.primitive.SDFPrimitive;
import ru.betterend.util.sdf.primitive.SDFSphere;
public class StructureGiantMossyGlowshroom extends SDFStructureFeature {
@Override
protected SDF getSDF(BlockPos center, Random random) {
System.out.println(center);
SDFCapedCone cone1 = new SDFCapedCone().setHeight(2.5F).setRadius1(1.5F).setRadius2(2.5F);
SDFCapedCone cone2 = new SDFCapedCone().setHeight(3F).setRadius1(2.5F).setRadius2(13F);
SDF posedCone2 = new SDFTranslate().setTranslate(0, 5, 0).setSource(cone2);
SDF posedCone3 = new SDFTranslate().setTranslate(0, 12F, 0).setSource(new SDFScale().setScale(2).setSource(cone2));
SDF upCone = new SDFSubtraction().setSourceA(posedCone2).setSourceB(posedCone3);
SDF wave = new SDFFlatWave().setRaysCount(12).setIntensity(1.3F).setSource(upCone);
SDF cones = new SDFSmoothUnion().setRadius(3).setSourceA(cone1).setSourceB(wave);
SDF innerCone = new SDFTranslate().setTranslate(0, 1.25F, 0).setSource(upCone);
innerCone = new SDFScale3D().setScale(1.2F, 1F, 1.2F).setSource(innerCone);
cones = new SDFUnion().setSourceA(cones).setSourceB(innerCone);
SDF glowCone = new SDFCapedCone().setHeight(3F).setRadius1(2F).setRadius2(12.5F);
SDFPrimitive priGlowCone = (SDFPrimitive) glowCone;
glowCone = new SDFTranslate().setTranslate(0, 4.25F, 0).setSource(glowCone);
glowCone = new SDFSubtraction().setSourceA(glowCone).setSourceB(posedCone3);
cones = new SDFUnion().setSourceA(cones).setSourceB(glowCone);
OpenSimplexNoise noise = new OpenSimplexNoise(1234);
cones = new SDFCoordModify().setFunction((pos) -> {
float dist = MHelper.length(pos.getX(), pos.getZ());
float y = pos.getY() + (float) noise.eval(pos.getX() * 0.1 + center.getX(), pos.getZ() * 0.1 + center.getZ()) * dist * 0.3F - dist * 0.15F;
pos.set(pos.getX(), y, pos.getZ());
}).setSource(cones);
SDFTranslate HEAD_POS = (SDFTranslate) new SDFTranslate().setSource(new SDFTranslate().setTranslate(0, 2.5F, 0).setSource(cones));
SDF roots = new SDFSphere().setRadius(4F);
SDFPrimitive primRoots = (SDFPrimitive) roots;
roots = new SDFScale3D().setScale(1, 0.7F, 1).setSource(roots);
SDFFlatWave rotRoots = (SDFFlatWave) new SDFFlatWave().setRaysCount(5).setIntensity(1.5F).setSource(roots);
SDFBinary function = new SDFSmoothUnion().setRadius(4).setSourceB(new SDFUnion().setSourceA(HEAD_POS).setSourceB(rotRoots));
cone1.setBlock(BlockRegistry.MOSSY_GLOWSHROOM_CAP);
cone2.setBlock(BlockRegistry.MOSSY_GLOWSHROOM_CAP);
priGlowCone.setBlock(BlockRegistry.MOSSY_GLOWSHROOM_HYMENOPHORE);
primRoots.setBlock(BlockRegistry.MOSSY_GLOWSHROOM.bark);
float height = MHelper.randRange(10F, 25F, random);
int count = MHelper.floor(height / 4);
List<Vector3f> spline = SplineHelper.makeSpline(0, 0, 0, 0, height, 0, count);
SplineHelper.offsetParts(spline, random, 1F, 0, 1F);
SDF sdf = SplineHelper.buildSDF(spline, 2.1F, 1.5F, (pos) -> {
return BlockRegistry.MOSSY_GLOWSHROOM.log.getDefaultState();
});
Vector3f pos = spline.get(spline.size() - 1);
float scale = MHelper.randRange(2F, 3.5F, random);
HEAD_POS.setTranslate(pos.getX(), pos.getY(), pos.getZ());
rotRoots.setAngle(random.nextFloat() * MHelper.PI2);
function.setSourceA(sdf);
return new SDFRound().setRadius(1.5F).setSource(new SDFScale()
.setScale(scale)
.setSource(function))
.setPostProcess((info) -> {
if (BlockRegistry.MOSSY_GLOWSHROOM.isTreeLog(info.getState())) {
if (random.nextBoolean() && info.getStateUp().getBlock() == BlockRegistry.MOSSY_GLOWSHROOM_CAP) {
info.setState(BlockRegistry.MOSSY_GLOWSHROOM_CAP.getDefaultState().with(BlockMossyGlowshroomCap.TRANSITION, true));
return info.getState();
}
else if (!BlockRegistry.MOSSY_GLOWSHROOM.isTreeLog(info.getStateUp()) || !BlockRegistry.MOSSY_GLOWSHROOM.isTreeLog(info.getStateDown())) {
info.setState(BlockRegistry.MOSSY_GLOWSHROOM.bark.getDefaultState());
return info.getState();
}
}
else if (info.getState().getBlock() == BlockRegistry.MOSSY_GLOWSHROOM_CAP) {
if (BlockRegistry.MOSSY_GLOWSHROOM.isTreeLog(info.getStateDown().getBlock())) {
info.setState(BlockRegistry.MOSSY_GLOWSHROOM_CAP.getDefaultState().with(BlockMossyGlowshroomCap.TRANSITION, true));
return info.getState();
}
info.setState(BlockRegistry.MOSSY_GLOWSHROOM_CAP.getDefaultState());
return info.getState();
}
else if (info.getState().getBlock() == BlockRegistry.MOSSY_GLOWSHROOM_HYMENOPHORE) {
for (Direction dir: BlocksHelper.HORIZONTAL) {
if (info.getState(dir) == AIR) {
info.setBlockPos(info.getPos().offset(dir), BlockRegistry.MOSSY_GLOWSHROOM_FUR.getDefaultState().with(BlockGlowingFur.FACING, dir));
}
}
if (info.getStateDown().getBlock() != BlockRegistry.MOSSY_GLOWSHROOM_HYMENOPHORE) {
info.setBlockPos(info.getPos().down(), BlockRegistry.MOSSY_GLOWSHROOM_FUR.getDefaultState().with(BlockGlowingFur.FACING, Direction.DOWN));
}
}
return info.getState();
});
}
}

View file

@ -0,0 +1,18 @@
package ru.betterend.world.structures.piece;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.structure.StructurePiece;
import net.minecraft.structure.StructurePieceType;
public abstract class BasePiece extends StructurePiece {
protected BasePiece(StructurePieceType type, int i) {
super(type, i);
}
protected BasePiece(StructurePieceType type, CompoundTag tag) {
super(type, tag);
fromNbt(tag);
}
protected abstract void fromNbt(CompoundTag tag);
}

View file

@ -0,0 +1,48 @@
package ru.betterend.world.structures.piece;
import java.util.Random;
import java.util.function.Consumer;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.structure.StructureManager;
import net.minecraft.util.math.BlockBox;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.StructureWorldAccess;
import net.minecraft.world.gen.StructureAccessor;
import net.minecraft.world.gen.chunk.ChunkGenerator;
import ru.betterend.registry.StructureRegistry;
import ru.betterend.world.structures.StructureWorld;
public class VoxelPiece extends BasePiece {
private StructureWorld world;
public VoxelPiece(Consumer<StructureWorld> function, int id) {
super(StructureRegistry.VOXEL_PIECE, id);
world = new StructureWorld();
function.accept(world);
this.boundingBox = world.getBounds();
System.out.println(this.boundingBox);
}
public VoxelPiece(StructureManager manager, CompoundTag tag) {
super(StructureRegistry.VOXEL_PIECE, tag);
this.boundingBox = world.getBounds();
System.out.println(this.boundingBox);
}
@Override
protected void toNbt(CompoundTag tag) {
tag.put("world", world.toBNT());
}
protected void fromNbt(CompoundTag tag) {
world = new StructureWorld(tag.getCompound("world"));
}
@Override
public boolean generate(StructureWorldAccess world, StructureAccessor arg, ChunkGenerator chunkGenerator, Random random, BlockBox blockBox, ChunkPos chunkPos, BlockPos blockPos) {
this.world.placeChunk(world, chunkPos);
return true;
}
}

View file

@ -14,7 +14,8 @@
"AbstractBlockMixin", "AbstractBlockMixin",
"LivingEntityMixin", "LivingEntityMixin",
"BiomeMixin", "BiomeMixin",
"SlimeEntityMixin" "SlimeEntityMixin",
"LocateCommandMixin"
], ],
"injectors": { "injectors": {
"defaultRequire": 1 "defaultRequire": 1