package org.pepsoft.worldpainter.layers.bo2; import org.jnbt.*; import org.pepsoft.minecraft.Entity; import org.pepsoft.minecraft.MCInterface; import org.pepsoft.minecraft.Material; import org.pepsoft.minecraft.TileEntity; import org.pepsoft.worldpainter.objects.AbstractObject; import org.pepsoft.worldpainter.objects.WPObject; import javax.vecmath.Point3i; import java.io.*; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.zip.GZIPInputStream; /** * Created by Pepijn on 26-6-2016. */ public class Structure extends AbstractObject implements Bo2ObjectProvider { private Structure(CompoundTag root, String name, Map<Point3i, Material> blocks) { this.root = root; this.name = name; this.blocks = blocks; } @Override public WPObject getObject() { return this; } @Override public List<WPObject> getAllObjects() { return Collections.singletonList(this); } @Override public void setSeed(long seed) { // Do nothing } @Override public String getName() { return name; } @Override public void setName(String name) { this.name = name; } @Override public Point3i getDimensions() { List size = ((ListTag) root.getTag("size")).getValue(); return new Point3i(((IntTag) size.get(0)).getValue(), ((IntTag) size.get(2)).getValue(), ((IntTag) size.get(1)).getValue()); } @Override public Material getMaterial(int x, int y, int z) { return blocks.get(new Point3i(x, y, z)); } @Override public boolean getMask(int x, int y, int z) { return blocks.containsKey(new Point3i(x, y, z)); } @Override public List<Entity> getEntities() { // TODO return null; } @Override public List<TileEntity> getTileEntities() { // TODO return null; } @Override public Map<String, Serializable> getAttributes() { return attributes; } @Override public void setAttributes(Map<String, Serializable> attributes) { this.attributes = attributes; } @Override public <T extends Serializable> void setAttribute(AttributeKey<T> key, T value) { if (value != null) { if (attributes == null) { attributes = new HashMap<>(); } attributes.put(key.key, value); } else if (attributes != null) { attributes.remove(key.key); if (attributes.isEmpty()) { attributes = null; } } } public static Structure load(File file, MCInterface mcInterface) throws IOException { CompoundTag root; try (NBTInputStream in = new NBTInputStream(new GZIPInputStream(new BufferedInputStream(new FileInputStream(file))))) { root = (CompoundTag) in.readTag(); } String name = file.getName(); if (name.toLowerCase().endsWith(".nbt")) { name = name.substring(0, name.length() - 4).trim(); } // Load the palette ListTag paletteTag = (ListTag) root.getTag("palette"); Material[] palette = new Material[paletteTag.getValue().size()]; for (int i = 0; i < palette.length; i++) { palette[i] = mcInterface.decodeStructureMaterial((CompoundTag) paletteTag.getValue().get(i)); } // Load the blocks Map<Point3i, Material> blocks = new HashMap<>(); ListTag blocksTag = (ListTag) root.getTag("blocks"); for (Tag tag: blocksTag.getValue()) { CompoundTag blockTag = (CompoundTag) tag; List<Tag> posTags = ((ListTag) blockTag.getTag("pos")).getValue(); blocks.put(new Point3i(((IntTag) posTags.get(0)).getValue(), ((IntTag) posTags.get(2)).getValue(),((IntTag) posTags.get(1)).getValue()), palette[((IntTag) blockTag.getTag("state")).getValue()]); } // Remove palette and blocks from the tag so we don't waste space root.setTag("palette", null); root.setTag("blocks", null); return new Structure(root, name, blocks); } private final CompoundTag root; private final Map<Point3i, Material> blocks; private String name; private Map<String, Serializable> attributes; private static final long serialVersionUID = 1L; }