From b0d79adc661cc4d69c853c1fce1ee9a9d6429f75 Mon Sep 17 00:00:00 2001 From: SD Date: Thu, 10 Sep 2020 11:24:05 +0530 Subject: [PATCH] Added schematic parser Basically just v2 without biomes Changes to be committed: new file: src/main/java/org/dimdev/dimcore/schematic/v2/Schematic.java new file: src/main/java/org/dimdev/dimcore/schematic/v2/SchematicBlockPallete.java new file: src/main/java/org/dimdev/dimcore/schematic/v2/SchematicMetadata.java --- .../dimcore/schematic/v2/Schematic.java | 110 ++++++++++++++++++ .../schematic/v2/SchematicBlockPallete.java | 75 ++++++++++++ .../schematic/v2/SchematicMetadata.java | 47 ++++++++ 3 files changed, 232 insertions(+) create mode 100644 src/main/java/org/dimdev/dimcore/schematic/v2/Schematic.java create mode 100644 src/main/java/org/dimdev/dimcore/schematic/v2/SchematicBlockPallete.java create mode 100644 src/main/java/org/dimdev/dimcore/schematic/v2/SchematicMetadata.java diff --git a/src/main/java/org/dimdev/dimcore/schematic/v2/Schematic.java b/src/main/java/org/dimdev/dimcore/schematic/v2/Schematic.java new file mode 100644 index 00000000..a5e00037 --- /dev/null +++ b/src/main/java/org/dimdev/dimcore/schematic/v2/Schematic.java @@ -0,0 +1,110 @@ +package org.dimdev.dimcore.schematic.v2; + +import java.util.List; +import java.util.Map; +import java.util.stream.IntStream; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; + +import net.minecraft.block.BlockState; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.util.math.Vec3i; + +@SuppressWarnings("CodeBlock2Expr") +public class Schematic { + public static final Codec CODEC = RecordCodecBuilder.create((instance) -> { + return instance.group( + Codec.INT.fieldOf("Version").forGetter(Schematic::getVersion), + Codec.INT.fieldOf("Data Version").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.field_25123.optionalFieldOf("Offset", Vec3i.ZERO).forGetter(Schematic::getOffset), + Codec.INT.fieldOf("PalleteMax").forGetter(Schematic::getPalleteMax), + SchematicBlockPallete.CODEC.optionalFieldOf("Palette", ImmutableMap.of()).forGetter(Schematic::getBlockPallete), + Codec.INT_STREAM.fieldOf("BlockData").forGetter(Schematic::getBlockData), + Codec.list(CompoundTag.field_25128).optionalFieldOf("BlockEntities", ImmutableList.of()).forGetter(Schematic::getBlockEntities), + Codec.list(CompoundTag.field_25128).optionalFieldOf("Entities", ImmutableList.of()).forGetter(Schematic::getEntities) + ).apply(instance, Schematic::new); + }); + + private final int version; + private final int dataVersion; + private final SchematicMetadata metadata; + private final short width; + private final short height; + private final short length; + private final Vec3i offset; + private final int palleteMax; + private final Map blockPallete; + private final IntStream blockData; + private final List blockEntities; + private final List entities; + + public Schematic(int version, int dataVersion, SchematicMetadata metadata, short width, short height, short length, Vec3i offset, int palleteMax, Map blockPallete, IntStream blockData, List blockEntities, List entities) { + this.version = version; + this.dataVersion = dataVersion; + this.metadata = metadata; + this.width = width; + this.height = height; + this.length = length; + this.offset = offset; + this.palleteMax = palleteMax; + this.blockPallete = blockPallete; + this.blockData = blockData; + this.blockEntities = blockEntities; + this.entities = entities; + } + + public int getVersion() { + return this.version; + } + + public int getDataVersion() { + return this.dataVersion; + } + + public SchematicMetadata getMetadata() { + return this.metadata; + } + + public short getWidth() { + return this.width; + } + + public short getHeight() { + return this.height; + } + + public short getLength() { + return this.length; + } + + public Vec3i getOffset() { + return this.offset; + } + + public int getPalleteMax() { + return this.palleteMax; + } + + public Map getBlockPallete() { + return this.blockPallete; + } + + public IntStream getBlockData() { + return this.blockData; + } + + public List getBlockEntities() { + return this.blockEntities; + } + + public List getEntities() { + return this.entities; + } +} diff --git a/src/main/java/org/dimdev/dimcore/schematic/v2/SchematicBlockPallete.java b/src/main/java/org/dimdev/dimcore/schematic/v2/SchematicBlockPallete.java new file mode 100644 index 00000000..0b400e4e --- /dev/null +++ b/src/main/java/org/dimdev/dimcore/schematic/v2/SchematicBlockPallete.java @@ -0,0 +1,75 @@ +package org.dimdev.dimcore.schematic.v2; + +import java.util.Iterator; +import java.util.Objects; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.DataResult; +import com.mojang.serialization.codecs.UnboundedMapCodec; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.state.property.Property; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.Registry; + +public class SchematicBlockPallete { + public static final UnboundedMapCodec CODEC = Codec.unboundedMap(Entry.CODEC, Codec.INT); + + private static > void process(Property property, String value, BlockState state) { + state.with(property, property.parse(value).orElseThrow(NullPointerException::new)); + } + + public interface Entry { + Codec CODEC = Codec.STRING.comapFlatMap(Entry::to, Entry::from); + + static > DataResult to(String string) { + if (!string.contains("[") && !string.contains("]")) { + BlockState state = Registry.BLOCK.get(new Identifier(string)).getDefaultState(); + return DataResult.success(state); + } else { + Block block = Objects.requireNonNull(Registry.BLOCK.get(new Identifier(string.substring(0, string.indexOf("["))))); + BlockState state = block.getDefaultState(); + String[] stateArray = string.substring(string.indexOf("[") + 1, string.length() - 1).split(","); + for (String stateString : stateArray) { + Property property = Objects.requireNonNull(block.getStateManager().getProperty(stateString.split("=")[0])); + process(property,stateString.split("=")[1], state); + } + return DataResult.success(state); + } + } + + static String from(BlockState state) { + StringBuilder builder = new StringBuilder(); + builder.append(Objects.requireNonNull(Registry.BLOCK.getId(state.getBlock()))); + // Ensures that [ and ] are only added when properties are present + boolean flag = true; + Iterator> iterator = state.getProperties().iterator(); + while(iterator.hasNext()) { + if (flag) { + builder.append("["); + flag = false; + } + + Property property = iterator.next(); + builder.append(property.getName()); + builder.append("="); + + if (state.get(property) instanceof Enum) { + // Enum might have override toString + builder.append(((Enum) state.get(property)).name()); + } else { + builder.append(state.get(property).toString()); + } + + if (iterator.hasNext()) { + builder.append(","); + } + } + if (!flag) { + builder.append("]"); + } + return builder.toString(); + } + } +} diff --git a/src/main/java/org/dimdev/dimcore/schematic/v2/SchematicMetadata.java b/src/main/java/org/dimdev/dimcore/schematic/v2/SchematicMetadata.java new file mode 100644 index 00000000..ff044222 --- /dev/null +++ b/src/main/java/org/dimdev/dimcore/schematic/v2/SchematicMetadata.java @@ -0,0 +1,47 @@ +package org.dimdev.dimcore.schematic.v2; + +import java.util.List; + +import com.google.common.collect.ImmutableList; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; + +@SuppressWarnings("CodeBlock2Expr") +public class SchematicMetadata { + public static final SchematicMetadata EMPTY = new SchematicMetadata("", "", 0L, ImmutableList.of()); + public static final Codec CODEC = RecordCodecBuilder.create((instance) -> { + return instance.group( + Codec.STRING.fieldOf("Name").forGetter(SchematicMetadata::getName), + Codec.STRING.fieldOf("Author").forGetter(SchematicMetadata::getAuthor), + Codec.LONG.fieldOf("Date").forGetter(SchematicMetadata::getDate), + Codec.list(Codec.STRING).fieldOf("RequiredMods").forGetter(SchematicMetadata::getRequiredMods) + ).apply(instance, SchematicMetadata::new); + }); + private final String name; + private final String author; + private final long date; + private final List requiredMods; + + private SchematicMetadata(String name, String author, long date, List requiredMods) { + this.name = name; + this.author = author; + this.date = date; + this.requiredMods = requiredMods; + } + + public String getName() { + return this.name; + } + + public String getAuthor() { + return this.author; + } + + public long getDate() { + return this.date; + } + + public List getRequiredMods() { + return this.requiredMods; + } +}