/******************************************************************************* * Copyright (C) 2014 Travis Ralston (turt2live) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. ******************************************************************************/ package com.turt2live.antishare.utils; import com.turt2live.antishare.engine.DevEngine; import com.turt2live.lib.items.AbstractedItem; import com.turt2live.lib.items.serialization.ItemDeserializer; import org.jnbt.*; import java.util.*; /** * Represents an abstract item as an NBT item. Changes made to the item between * creation of this object and the call to {@link #getTag(java.lang.String)} are represented in * the returned Tag. * * @author turt2live */ public class NBTItem { private AbstractedItem item; /** * Creates a new NBT item * * @param item the item to represent, cannot be null. */ public NBTItem(AbstractedItem item) { if (item == null) throw new IllegalArgumentException(); this.item = item; } /** * Gets the NBT tag that represents this item * * @param name an optional name for the tag. If null, a random one will be chosen * * @return the NBT tag */ public Tag getTag(String name) { Map<String, Object> serialized = item.serialize(); return createCompoundTag(serialized, name); } private CompoundTag createCompoundTag(Map<String, Object> serialized, String name) { Map<String, Tag> tags = new HashMap<>(); for (Map.Entry<String, Object> entry : serialized.entrySet()) { Object value = entry.getValue(); Tag created = createTag(value, entry.getKey()); if (created != null) { tags.put(entry.getKey(), created); } else { DevEngine.log("Unknown type, cannot convert to an NBT tag: " + entry.getKey() + " = " + value.getClass().getName() + " (" + value + ")"); } } return new CompoundTag(name == null ? UUID.randomUUID().toString() : name, tags); } private Tag createTag(Object value, String name) { Tag created = null; if (value instanceof Map) { // Assume Map<String,Object> created = createCompoundTag((Map<String, Object>) value, name); } else if (value instanceof Integer) { created = new IntTag(name, (Integer) value); } else if (value instanceof String) { created = new StringTag(name, (String) value); } else if (value instanceof Short) { created = new ShortTag(name, (Short) value); } else if (value instanceof Boolean) { created = new StringTag(name, "BOOLEAN|" + value); } else if (value instanceof Double) { created = new DoubleTag(name, (Double) value); } else if (value instanceof List) { List<Tag> list = new ArrayList<>(); List<?> objs = (List<?>) value; Class<? extends Tag> tagClass = CompoundTag.class; for (Object s : objs) { Tag tag = createTag(s, ""); tagClass = tag.getClass(); list.add(tag); } created = new ListTag(name, tagClass, list); } else if (value instanceof Enum) { Enum e = (Enum) value; Map<String, Tag> constants = new HashMap<>(); constants.put("enum_class", new StringTag("ENUM_CLASS", e.getClass().getName())); constants.put("enum_value", new StringTag("ENUM_VALUE", e.name())); created = new CompoundTag(name, constants); } return created; } /** * Reconstructs this item from the specified tag * * @param tag the tag, cannot be null * * @return the reconstructed item, or null if one could not be made */ public static AbstractedItem reconstructItem(Tag tag) { if (tag == null) throw new IllegalArgumentException(); if (tag instanceof CompoundTag) { Map<String, Object> reconstructed = createMap((CompoundTag) tag); return ItemDeserializer.deserialize(reconstructed); } return null; } private static Map<String, Object> createMap(CompoundTag tag) { Map<String, Object> map = new HashMap<>(); for (Tag t : tag.getValue().values()) { map.put(t.getName(), createObject(t)); } return map; } private static List<Object> createList(ListTag tag) { List<Object> objs = new ArrayList<>(); for (Tag t : tag.getValue()) { objs.add(createObject(t)); } return objs; } private static Object createObject(Tag tag) { if (tag instanceof CompoundTag) { CompoundTag comp = (CompoundTag) tag; if (comp.getValue().containsKey("ENUM_CLASS")) { // Enum :D String enumClass = (String) comp.getValue().get("ENUM_CLASS").getValue(); String enumValue = (String) comp.getValue().get("ENUM_VALUE").getValue(); try { Class<? extends Enum> enumClazz = (Class<? extends Enum>) Class.forName(enumClass); return Enum.valueOf(enumClazz, enumValue); } catch (ClassNotFoundException e) { e.printStackTrace(); return null; } } return createMap(comp); } else if (tag instanceof StringTag) { StringTag str = (StringTag) tag; if (str.getValue().startsWith("BOOLEAN|")) { return Boolean.parseBoolean(str.getValue().substring("BOOLEAN|".length())); } return str.getValue(); } else if (tag instanceof ListTag) return createList((ListTag) tag); else return tag.getValue(); } }