diff --git a/src/main/java/ru/betterend/registry/StructureRegistry.java b/src/main/java/ru/betterend/registry/StructureRegistry.java new file mode 100644 index 00000000..c555fb85 --- /dev/null +++ b/src/main/java/ru/betterend/registry/StructureRegistry.java @@ -0,0 +1,14 @@ +package ru.betterend.registry; + +import net.minecraft.structure.StructurePieceType; +import net.minecraft.util.registry.Registry; +import ru.betterend.BetterEnd; +import ru.betterend.world.structures.piece.VoxelPiece; + +public class StructureRegistry { + public static final StructurePieceType VOXEL_PIECE = register("sdf", VoxelPiece::new); + + private static StructurePieceType register(String id, StructurePieceType pieceType) { + return Registry.register(Registry.STRUCTURE_PIECE, BetterEnd.makeID(id), pieceType); + } +} diff --git a/src/main/java/ru/betterend/util/sdf/primitive/SDFPrimitive.java b/src/main/java/ru/betterend/util/sdf/primitive/SDFPrimitive.java index 707c8d0b..5f8cf461 100644 --- a/src/main/java/ru/betterend/util/sdf/primitive/SDFPrimitive.java +++ b/src/main/java/ru/betterend/util/sdf/primitive/SDFPrimitive.java @@ -32,4 +32,8 @@ public abstract class SDFPrimitive extends SDF { public BlockState getBlockState(BlockPos pos) { return placerFunction.apply(pos); } + + /*public abstract CompoundTag toNBT(CompoundTag root) { + + }*/ } diff --git a/src/main/java/ru/betterend/world/features/MossyGlowshroomFeature.java b/src/main/java/ru/betterend/world/features/MossyGlowshroomFeature.java index 85364689..3f64ce72 100644 --- a/src/main/java/ru/betterend/world/features/MossyGlowshroomFeature.java +++ b/src/main/java/ru/betterend/world/features/MossyGlowshroomFeature.java @@ -78,6 +78,10 @@ public class MossyGlowshroomFeature extends DefaultFeature { Vector3f pos = spline.get(spline.size() - 1); float scale = MHelper.randRange(0.75F, 1.1F, random); + if (featureConfig != null && random.nextInt(32) == 0) { + scale *= MHelper.randRange(2F, 3F, random); + } + Vector3f vec = spline.get(0); float x1 = blockPos.getX() + vec.getX() * scale; float y1 = blockPos.getY() + vec.getY() * scale; diff --git a/src/main/java/ru/betterend/world/structures/piece/BasePiece.java b/src/main/java/ru/betterend/world/structures/piece/BasePiece.java new file mode 100644 index 00000000..aa8fe1a4 --- /dev/null +++ b/src/main/java/ru/betterend/world/structures/piece/BasePiece.java @@ -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); +} \ No newline at end of file diff --git a/src/main/java/ru/betterend/world/structures/piece/StructureWorld.java b/src/main/java/ru/betterend/world/structures/piece/StructureWorld.java new file mode 100644 index 00000000..ab9f9942 --- /dev/null +++ b/src/main/java/ru/betterend/world/structures/piece/StructureWorld.java @@ -0,0 +1,126 @@ +package ru.betterend.world.structures.piece; + +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 parts = Maps.newHashMap(); + private int minX = Integer.MAX_VALUE; + private int minZ = Integer.MAX_VALUE; + private int maxX = Integer.MIN_VALUE; + private int maxZ = Integer.MIN_VALUE; + + public StructureWorld() {} + + public StructureWorld(CompoundTag tag) { + minX = tag.getInt("minX"); + maxX = tag.getInt("maxX"); + 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; + } + 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("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() { + return new BlockBox(minX << 4, minZ << 4, (maxX << 4) | 15, (maxZ << 4) | 15); + } + + private static final class Part { + Map 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) -> { + 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; + } + } +} diff --git a/src/main/java/ru/betterend/world/structures/piece/VoxelPiece.java b/src/main/java/ru/betterend/world/structures/piece/VoxelPiece.java new file mode 100644 index 00000000..4216c710 --- /dev/null +++ b/src/main/java/ru/betterend/world/structures/piece/VoxelPiece.java @@ -0,0 +1,43 @@ +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; + +public class VoxelPiece extends BasePiece { + private StructureWorld world; + + public VoxelPiece(Consumer function, int id) { + super(StructureRegistry.VOXEL_PIECE, id); + world = new StructureWorld(); + function.accept(world); + this.boundingBox = world.getBounds(); + } + + public VoxelPiece(StructureManager manager, CompoundTag tag) { + super(StructureRegistry.VOXEL_PIECE, tag); + } + + @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) { + return true; + } +}