Biomes
This commit is contained in:
parent
f610f9039a
commit
bf97807f02
5 changed files with 166 additions and 57 deletions
|
@ -2,17 +2,14 @@ package org.dimdev.dimdoors.util.schematic.v2;
|
|||
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.google.common.collect.BiMap;
|
||||
import com.google.common.collect.HashBiMap;
|
||||
import com.google.common.collect.ImmutableBiMap;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Maps;
|
||||
import io.github.boogiemonster1o1.libcbe.api.ConditionalBlockEntityProvider;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockEntityProvider;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
|
@ -21,7 +18,6 @@ import net.minecraft.entity.Entity;
|
|||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.fluid.FluidState;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.IntArrayTag;
|
||||
import net.minecraft.nbt.ListTag;
|
||||
import net.minecraft.nbt.NbtOps;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
@ -29,23 +25,29 @@ import net.minecraft.util.math.Vec3d;
|
|||
import net.minecraft.world.BlockView;
|
||||
import net.minecraft.world.ModifiableWorld;
|
||||
import net.minecraft.world.StructureWorldAccess;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
|
||||
import net.fabricmc.fabric.api.util.NbtType;
|
||||
|
||||
public class RelativeBlockSample implements BlockView, ModifiableWorld {
|
||||
public final Schematic schematic;
|
||||
private final int[][][] blockData;
|
||||
private final int[][] biomeData;
|
||||
private final BiMap<BlockState, Integer> blockPalette;
|
||||
private final BiMap<Biome, Integer> biomePalette;
|
||||
private final Map<BlockPos, BlockState> blockContainer;
|
||||
private final Map<BlockPos, Biome> biomeContainer;
|
||||
private final Map<BlockPos, CompoundTag> blockEntityContainer;
|
||||
private final BiMap<CompoundTag, Vec3d> entityContainer;
|
||||
private StructureWorldAccess world;
|
||||
|
||||
public RelativeBlockSample(Schematic schematic) {
|
||||
this.schematic = schematic;
|
||||
this.blockData = SchematicPlacer.getBlockData(schematic);
|
||||
this.biomeData = SchematicPlacer.getBiomeData(schematic);
|
||||
this.blockPalette = ImmutableBiMap.copyOf(schematic.getBlockPalette());
|
||||
this.biomePalette = ImmutableBiMap.copyOf(schematic.getBiomePalette());
|
||||
this.blockContainer = Maps.newHashMap();
|
||||
this.biomeContainer = Maps.newHashMap();
|
||||
this.blockEntityContainer = Maps.newHashMap();
|
||||
int width = schematic.getWidth();
|
||||
int height = schematic.getHeight();
|
||||
|
@ -54,10 +56,14 @@ public class RelativeBlockSample implements BlockView, ModifiableWorld {
|
|||
for (int y = 0; y < height; y++) {
|
||||
for (int z = 0; z < length; z++) {
|
||||
this.setBlockState(new BlockPos(x, y, z), this.blockPalette.inverse().get(this.blockData[x][y][z]), 2);
|
||||
this.blockContainer.put(new BlockPos(x, y, z), this.blockPalette.inverse().get(this.blockData[x][y][z]));
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int x = 0; x < width; x++) {
|
||||
for (int z = 0; z < length; z++) {
|
||||
this.biomeContainer.put(new BlockPos(x, 0, z), this.biomePalette.inverse().get(this.biomeData[x][z]));
|
||||
}
|
||||
}
|
||||
for (CompoundTag blockEntityTag : schematic.getBlockEntities()) {
|
||||
int[] arr = blockEntityTag.getIntArray("Pos");
|
||||
BlockPos position = new BlockPos(arr[0], arr[1], arr[2]);
|
||||
|
@ -73,15 +79,12 @@ public class RelativeBlockSample implements BlockView, ModifiableWorld {
|
|||
|
||||
@Override
|
||||
public @Nullable BlockEntity getBlockEntity(BlockPos pos) {
|
||||
Block block = this.getBlockState(pos).getBlock();
|
||||
if (block.hasBlockEntity()) {
|
||||
if (block instanceof ConditionalBlockEntityProvider && ((ConditionalBlockEntityProvider) block).hasBlockEntity(this.getBlockState(pos)) && ((ConditionalBlockEntityProvider) block).hasBlockEntity(pos, this)) {
|
||||
return ((ConditionalBlockEntityProvider) block).createBlockEntity(this.world);
|
||||
} else {
|
||||
return ((BlockEntityProvider) block).createBlockEntity(this.world);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return Optional.of(this.getBlockState(pos))
|
||||
.map(BlockState::getBlock)
|
||||
.filter(BlockEntityProvider.class::isInstance)
|
||||
.map(BlockEntityProvider.class::cast)
|
||||
.map(bep -> bep.createBlockEntity(this))
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -94,18 +97,15 @@ public class RelativeBlockSample implements BlockView, ModifiableWorld {
|
|||
return this.blockContainer.get(pos).getFluidState();
|
||||
}
|
||||
|
||||
public void place(BlockPos origin) {
|
||||
if (this.world == null) {
|
||||
throw new UnsupportedOperationException("Can not place in a null world!");
|
||||
}
|
||||
this.blockContainer.forEach((pos, state) -> this.world.setBlockState(origin.add(pos), state, 0b0000011));
|
||||
public void place(BlockPos origin, StructureWorldAccess world, boolean biomes) {
|
||||
this.blockContainer.forEach((pos, state) -> world.setBlockState(origin.add(pos), state, 0b0000011));
|
||||
for (Map.Entry<BlockPos, CompoundTag> entry : this.blockEntityContainer.entrySet()) {
|
||||
BlockPos pos = entry.getKey();
|
||||
BlockPos actualPos = origin.add(entry.getKey());
|
||||
|
||||
BlockEntity blockEntity = BlockEntity.createFromTag(this.getBlockState(pos), entry.getValue());
|
||||
if (blockEntity != null) {
|
||||
this.world.toServerWorld().setBlockEntity(actualPos, blockEntity);
|
||||
world.toServerWorld().setBlockEntity(actualPos, blockEntity);
|
||||
}
|
||||
}
|
||||
for (Map.Entry<CompoundTag, Vec3d> entry : this.entityContainer.entrySet()) {
|
||||
|
@ -116,8 +116,8 @@ public class RelativeBlockSample implements BlockView, ModifiableWorld {
|
|||
doubles.set(1, NbtOps.INSTANCE.createDouble(vec.y));
|
||||
doubles.set(2, NbtOps.INSTANCE.createDouble(vec.z));
|
||||
tag.put("Pos", doubles);
|
||||
Entity entity = EntityType.getEntityFromTag(tag, this.world.toServerWorld()).orElseThrow(NoSuchElementException::new);
|
||||
this.world.spawnEntity(entity);
|
||||
Entity entity = EntityType.getEntityFromTag(tag, world.toServerWorld()).orElseThrow(NoSuchElementException::new);
|
||||
world.spawnEntity(entity);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -137,15 +137,6 @@ public class RelativeBlockSample implements BlockView, ModifiableWorld {
|
|||
return this.blockEntityContainer;
|
||||
}
|
||||
|
||||
public StructureWorldAccess getWorld() {
|
||||
return this.world;
|
||||
}
|
||||
|
||||
public RelativeBlockSample setWorld(StructureWorldAccess world) {
|
||||
this.world = world;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBlockState(BlockPos pos, BlockState state, int flags, int maxUpdateDepth) {
|
||||
this.blockContainer.put(pos, state);
|
||||
|
|
|
@ -2,6 +2,7 @@ package org.dimdev.dimdoors.util.schematic.v2;
|
|||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
@ -12,6 +13,8 @@ import com.google.common.collect.HashBiMap;
|
|||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.Dynamic;
|
||||
import com.mojang.serialization.DynamicOps;
|
||||
import com.mojang.serialization.JsonOps;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
|
||||
|
@ -22,25 +25,26 @@ import net.minecraft.nbt.CompoundTag;
|
|||
import net.minecraft.nbt.NbtOps;
|
||||
import net.minecraft.util.math.Vec3i;
|
||||
import net.minecraft.world.StructureWorldAccess;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
|
||||
public class Schematic {
|
||||
private static final Consumer<String> PRINT_TO_STDERR = System.err::println;
|
||||
public static final Codec<Schematic> CODEC = RecordCodecBuilder.create((instance) -> {
|
||||
return instance.group(
|
||||
Codec.INT.fieldOf("Version").forGetter(Schematic::getVersion),
|
||||
Codec.INT.optionalFieldOf("Data Version", SharedConstants.getGameVersion().getWorldVersion()).forGetter(Schematic::getDataVersion),
|
||||
SchematicMetadata.CODEC.optionalFieldOf("Metadata", SchematicMetadata.EMPTY).forGetter(Schematic::getMetadata),
|
||||
Codec.SHORT.fieldOf("Width").forGetter(Schematic::getWidth),
|
||||
Codec.SHORT.fieldOf("Height").forGetter(Schematic::getHeight),
|
||||
Codec.SHORT.fieldOf("Length").forGetter(Schematic::getLength),
|
||||
Vec3i.CODEC.fieldOf("Offset").forGetter(Schematic::getOffset),
|
||||
Codec.INT.fieldOf("PaletteMax").forGetter(Schematic::getPaletteMax),
|
||||
SchematicBlockPalette.CODEC.fieldOf("Palette").forGetter(Schematic::getBlockPalette),
|
||||
Codec.BYTE_BUFFER.fieldOf("BlockData").forGetter(Schematic::getBlockData),
|
||||
Codec.list(CompoundTag.CODEC).optionalFieldOf("BlockEntities", ImmutableList.of()).forGetter(Schematic::getBlockEntities),
|
||||
Codec.list(CompoundTag.CODEC).optionalFieldOf("Entities", ImmutableList.of()).forGetter(Schematic::getEntities)
|
||||
).apply(instance, Schematic::new);
|
||||
});
|
||||
public static final Codec<Schematic> CODEC = RecordCodecBuilder.create((instance) -> instance.group(
|
||||
Codec.INT.fieldOf("Version").forGetter(Schematic::getVersion),
|
||||
Codec.INT.optionalFieldOf("Data Version", SharedConstants.getGameVersion().getWorldVersion()).forGetter(Schematic::getDataVersion),
|
||||
SchematicMetadata.CODEC.optionalFieldOf("Metadata", SchematicMetadata.EMPTY).forGetter(Schematic::getMetadata),
|
||||
Codec.SHORT.fieldOf("Width").forGetter(Schematic::getWidth),
|
||||
Codec.SHORT.fieldOf("Height").forGetter(Schematic::getHeight),
|
||||
Codec.SHORT.fieldOf("Length").forGetter(Schematic::getLength),
|
||||
Vec3i.CODEC.fieldOf("Offset").forGetter(Schematic::getOffset),
|
||||
Codec.INT.fieldOf("PaletteMax").forGetter(Schematic::getPaletteMax),
|
||||
SchematicBlockPalette.CODEC.fieldOf("Palette").forGetter(Schematic::getBlockPalette),
|
||||
Codec.BYTE_BUFFER.fieldOf("BlockData").forGetter(Schematic::getBlockData),
|
||||
Codec.list(CompoundTag.CODEC).optionalFieldOf("BlockEntities", ImmutableList.of()).forGetter(Schematic::getBlockEntities),
|
||||
Codec.list(CompoundTag.CODEC).optionalFieldOf("Entities", ImmutableList.of()).forGetter(Schematic::getEntities),
|
||||
SchematicBiomePalette.CODEC.optionalFieldOf("BiomePalette", Collections.emptyMap()).forGetter(Schematic::getBiomePalette),
|
||||
Codec.BYTE_BUFFER.optionalFieldOf("BiomeData", ByteBuffer.wrap(new byte[0])).forGetter(Schematic::getBlockData)
|
||||
).apply(instance, Schematic::new));
|
||||
|
||||
private final int version;
|
||||
private final int dataVersion;
|
||||
|
@ -54,8 +58,11 @@ public class Schematic {
|
|||
private final ByteBuffer blockData;
|
||||
private List<CompoundTag> blockEntities;
|
||||
private List<CompoundTag> entities;
|
||||
private final BiMap<Biome, Integer> biomePalette;
|
||||
private final ByteBuffer biomeData;
|
||||
private RelativeBlockSample cachedBlockSample = null;
|
||||
|
||||
public Schematic(int version, int dataVersion, SchematicMetadata metadata, short width, short height, short length, Vec3i offset, int paletteMax, Map<BlockState, Integer> blockPalette, ByteBuffer blockData, List<CompoundTag> blockEntities, List<CompoundTag> entities) {
|
||||
public Schematic(int version, int dataVersion, SchematicMetadata metadata, short width, short height, short length, Vec3i offset, int paletteMax, Map<BlockState, Integer> blockPalette, ByteBuffer blockData, List<CompoundTag> blockEntities, List<CompoundTag> entities, Map<Biome, Integer> biomePalette, ByteBuffer biomeData) {
|
||||
this.version = version;
|
||||
this.dataVersion = dataVersion;
|
||||
this.metadata = metadata;
|
||||
|
@ -68,6 +75,8 @@ public class Schematic {
|
|||
this.blockData = blockData;
|
||||
this.blockEntities = blockEntities;
|
||||
this.entities = entities;
|
||||
this.biomePalette = HashBiMap.create(biomePalette);
|
||||
this.biomeData = biomeData;
|
||||
}
|
||||
|
||||
public int getVersion() {
|
||||
|
@ -114,6 +123,14 @@ public class Schematic {
|
|||
return this.blockEntities;
|
||||
}
|
||||
|
||||
public BiMap<Biome, Integer> getBiomePalette() {
|
||||
return this.biomePalette;
|
||||
}
|
||||
|
||||
public ByteBuffer getBiomeData() {
|
||||
return this.biomeData;
|
||||
}
|
||||
|
||||
public void setBlockEntities(List<CompoundTag> blockEntities) {
|
||||
this.blockEntities = blockEntities.stream().map(SchematicPlacer::fixEntityId).collect(Collectors.toList());
|
||||
}
|
||||
|
@ -135,11 +152,10 @@ public class Schematic {
|
|||
}
|
||||
|
||||
public static RelativeBlockSample getBlockSample(Schematic schem) {
|
||||
return new RelativeBlockSample(schem);
|
||||
}
|
||||
|
||||
public static RelativeBlockSample getBlockSample(Schematic schem, StructureWorldAccess world) {
|
||||
return getBlockSample(schem).setWorld(world);
|
||||
if (schem.cachedBlockSample == null) {
|
||||
return (schem.cachedBlockSample = new RelativeBlockSample(schem));
|
||||
}
|
||||
return schem.cachedBlockSample;
|
||||
}
|
||||
|
||||
public static Schematic fromTag(CompoundTag tag) {
|
||||
|
@ -157,4 +173,12 @@ public class Schematic {
|
|||
public static JsonObject toJson(Schematic schem) {
|
||||
return (JsonObject) CODEC.encodeStart(JsonOps.INSTANCE, schem).getOrThrow(false, PRINT_TO_STDERR);
|
||||
}
|
||||
|
||||
public static <T> Schematic fromDynamic(Dynamic<T> dynamic) {
|
||||
return CODEC.parse(dynamic).getOrThrow(false, PRINT_TO_STDERR);
|
||||
}
|
||||
|
||||
public static <T> T toDynamic(Schematic schem, DynamicOps<T> ops) {
|
||||
return CODEC.encodeStart(ops, schem).getOrThrow(false, PRINT_TO_STDERR);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
package org.dimdev.dimdoors.util.schematic.v2;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.UnboundedMapCodec;
|
||||
|
||||
import net.minecraft.util.registry.BuiltinRegistries;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
|
||||
public class SchematicBiomePalette {
|
||||
public static final UnboundedMapCodec<Biome, Integer> CODEC = Codec.unboundedMap(BuiltinRegistries.BIOME, Codec.INT);
|
||||
}
|
|
@ -31,8 +31,8 @@ public final class SchematicPlacer {
|
|||
LOGGER.warn("Schematic \"" + schematic.getMetadata().getName() + "\" depends on mod \"" + id + "\", which is missing!");
|
||||
}
|
||||
}
|
||||
RelativeBlockSample blockSample = Schematic.getBlockSample(schematic, world);
|
||||
blockSample.place(origin);
|
||||
RelativeBlockSample blockSample = Schematic.getBlockSample(schematic);
|
||||
blockSample.place(origin, world, false);
|
||||
}
|
||||
|
||||
public static int[][][] getBlockData(Schematic schematic) {
|
||||
|
@ -51,6 +51,19 @@ public final class SchematicPlacer {
|
|||
return blockData;
|
||||
}
|
||||
|
||||
public static int[][] getBiomeData(Schematic schematic) {
|
||||
int width = schematic.getWidth();
|
||||
int length = schematic.getLength();
|
||||
byte[] biomeDataArray = schematic.getBiomeData().array();
|
||||
int[][] biomeData = new int[width][length];
|
||||
for (int x = 0; x < width; x++) {
|
||||
for (int z = 0; z < length; z++) {
|
||||
biomeData[x][z] = biomeDataArray[x + z * width];
|
||||
}
|
||||
}
|
||||
return biomeData;
|
||||
}
|
||||
|
||||
private static void placeEntities(int originX, int originY, int originZ, Schematic schematic, StructureWorldAccess world) {
|
||||
List<CompoundTag> entityTags = schematic.getEntities();
|
||||
for (CompoundTag tag : entityTags) {
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
package org.dimdev.dimdoors.util.schematic.v2;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.fluid.FluidState;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.minecraft.world.Heightmap;
|
||||
import net.minecraft.world.ModifiableTestableWorld;
|
||||
import net.minecraft.world.StructureWorldAccess;
|
||||
|
||||
public class WorldlyBlockSample implements BlockView, ModifiableTestableWorld {
|
||||
private final RelativeBlockSample relativeBlockSample;
|
||||
private final StructureWorldAccess world;
|
||||
|
||||
public WorldlyBlockSample(RelativeBlockSample relativeBlockSample, StructureWorldAccess world) {
|
||||
this.relativeBlockSample = relativeBlockSample;
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
public void place(BlockPos origin, boolean biomes) {
|
||||
this.relativeBlockSample.place(origin, this.world, biomes);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BlockEntity getBlockEntity(BlockPos pos) {
|
||||
return this.relativeBlockSample.getBlockEntity(pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getBlockState(BlockPos pos) {
|
||||
return this.relativeBlockSample.getBlockState(pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FluidState getFluidState(BlockPos pos) {
|
||||
return this.relativeBlockSample.getFluidState(pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBlockState(BlockPos pos, BlockState state, int flags, int maxUpdateDepth) {
|
||||
return this.relativeBlockSample.setBlockState(pos, state, flags, maxUpdateDepth);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeBlock(BlockPos pos, boolean move) {
|
||||
return this.relativeBlockSample.removeBlock(pos, move);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean breakBlock(BlockPos pos, boolean drop, @Nullable Entity breakingEntity, int maxUpdateDepth) {
|
||||
return this.relativeBlockSample.breakBlock(pos, drop, breakingEntity, maxUpdateDepth);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean testBlockState(BlockPos pos, Predicate<BlockState> state) {
|
||||
return state.test(this.getBlockState(pos));
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos getTopPosition(Heightmap.Type type, BlockPos pos) {
|
||||
return this.world.getTopPosition(type, pos);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue