Java tutorial
/******************************************************************************* * This file is part of ASkyBlock. * * ASkyBlock 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. * * ASkyBlock 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 ASkyBlock. If not, see <http://www.gnu.org/licenses/>. *******************************************************************************/ package com.wasteofplastic.askyblock.schematics; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Biome; import org.bukkit.block.Block; import org.bukkit.block.Chest; import org.bukkit.block.CreatureSpawner; import org.bukkit.block.DoubleChest; import org.bukkit.block.Sign; import org.bukkit.entity.EntityType; import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.ItemStack; import org.bukkit.util.Vector; import org.json.simple.JSONValue; import org.json.simple.parser.ContainerFactory; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; import com.wasteofplastic.askyblock.nms.NMSAbstraction; import com.wasteofplastic.org.jnbt.CompoundTag; import com.wasteofplastic.org.jnbt.ListTag; import com.wasteofplastic.org.jnbt.StringTag; import com.wasteofplastic.org.jnbt.Tag; public class IslandBlock { private short typeId; private byte data; private int x; private int y; private int z; private List<String> signText; private BannerBlock banner; private SkullBlock skull; private PotBlock pot; private EntityType spawnerBlockType; // Chest contents private HashMap<Byte, ItemStack> chestContents = new HashMap<Byte, ItemStack>(); public static final HashMap<String, Material> WEtoM = new HashMap<String, Material>(); public static final HashMap<String, EntityType> WEtoME = new HashMap<String, EntityType>(); static { // Establish the World Edit to Material look up // V1.8 items if (!Bukkit.getServer().getVersion().contains("(MC: 1.7")) { WEtoM.put("ARMORSTAND", Material.ARMOR_STAND); WEtoM.put("ACACIA_DOOR", Material.ACACIA_DOOR_ITEM); WEtoM.put("BIRCH_DOOR", Material.BIRCH_DOOR_ITEM); WEtoM.put("BIRCH_STAIRS", Material.BIRCH_WOOD_STAIRS); WEtoM.put("DARK_OAK_DOOR", Material.DARK_OAK_DOOR_ITEM); WEtoM.put("JUNGLE_DOOR", Material.JUNGLE_DOOR_ITEM); WEtoM.put("SLIME", Material.SLIME_BLOCK); WEtoM.put("SPRUCE_DOOR", Material.SPRUCE_DOOR_ITEM); } WEtoM.put("BREWING_STAND", Material.BREWING_STAND_ITEM); WEtoM.put("CARROT_ON_A_STICK", Material.CARROT_STICK); WEtoM.put("CARROT", Material.CARROT_ITEM); WEtoM.put("CAULDRON", Material.CAULDRON_ITEM); WEtoM.put("CLOCK", Material.WATCH); WEtoM.put("COBBLESTONE_WALL", Material.COBBLE_WALL); WEtoM.put("COMPARATOR", Material.REDSTONE_COMPARATOR); WEtoM.put("COOKED_PORKCHOP", Material.GRILLED_PORK); WEtoM.put("CLOCK", Material.WATCH); WEtoM.put("DIAMOND_HORSE_ARMOR", Material.DIAMOND_BARDING); WEtoM.put("DIAMOND_SHOVEL", Material.DIAMOND_SPADE); WEtoM.put("DYE", Material.INK_SACK); WEtoM.put("END_PORTAL_FRAME", Material.ENDER_PORTAL_FRAME); WEtoM.put("END_STONE", Material.ENDER_STONE); WEtoM.put("EXPERIENCE_BOTTLE", Material.EXP_BOTTLE); WEtoM.put("FILLED_MAP", Material.MAP); WEtoM.put("FIRE_CHARGE", Material.FIREBALL); WEtoM.put("FIREWORKS", Material.FIREWORK); WEtoM.put("FLOWER_POT", Material.FLOWER_POT_ITEM); WEtoM.put("GLASS_PANE", Material.THIN_GLASS); WEtoM.put("GOLDEN_CHESTPLATE", Material.GOLD_CHESTPLATE); WEtoM.put("GOLDEN_HORSE_ARMOR", Material.GOLD_BARDING); WEtoM.put("GOLDEN_LEGGINGS", Material.GOLD_LEGGINGS); WEtoM.put("GOLDEN_PICKAXE", Material.GOLD_PICKAXE); WEtoM.put("GOLDEN_RAIL", Material.POWERED_RAIL); WEtoM.put("GOLDEN_SHOVEL", Material.GOLD_SPADE); WEtoM.put("GOLDEN_SWORD", Material.GOLD_SWORD); WEtoM.put("GOLDEN_HELMET", Material.GOLD_HELMET); WEtoM.put("GOLDEN_HOE", Material.GOLD_HOE); WEtoM.put("GOLDEN_AXE", Material.GOLD_AXE); WEtoM.put("GOLDEN_BOOTS", Material.GOLD_BOOTS); WEtoM.put("HARDENED_CLAY", Material.HARD_CLAY); WEtoM.put("HEAVY_WEIGHTED_PRESSURE_PLATE", Material.GOLD_PLATE); WEtoM.put("IRON_BARS", Material.IRON_FENCE); WEtoM.put("IRON_HORSE_ARMOR", Material.IRON_BARDING); WEtoM.put("IRON_SHOVEL", Material.IRON_SPADE); WEtoM.put("LEAD", Material.LEASH); WEtoM.put("LEAVES2", Material.LEAVES_2); WEtoM.put("LIGHT_WEIGHTED_PRESSURE_PLATE", Material.IRON_PLATE); WEtoM.put("LOG2", Material.LOG_2); WEtoM.put("MAP", Material.EMPTY_MAP); WEtoM.put("MYCELIUM", Material.MYCEL); WEtoM.put("NETHER_BRICK_FENCE", Material.NETHER_FENCE); WEtoM.put("NETHER_WART", Material.NETHER_STALK); WEtoM.put("NETHERBRICK", Material.NETHER_BRICK_ITEM); WEtoM.put("OAK_STAIRS", Material.WOOD_STAIRS); WEtoM.put("POTATO", Material.POTATO_ITEM); WEtoM.put("RAIL", Material.RAILS); WEtoM.put("RECORD_11", Material.RECORD_11); WEtoM.put("RECORD_13", Material.GOLD_RECORD); WEtoM.put("RECORD_BLOCKS", Material.RECORD_3); WEtoM.put("RECORD_CAT", Material.GREEN_RECORD); WEtoM.put("RECORD_CHIRP", Material.RECORD_4); WEtoM.put("RECORD_FAR", Material.RECORD_5); WEtoM.put("RECORD_MALL", Material.RECORD_6); WEtoM.put("RECORD_MELLOHI", Material.RECORD_7); WEtoM.put("RECORD_STAL", Material.RECORD_8); WEtoM.put("RECORD_STRAD", Material.RECORD_9); WEtoM.put("RECORD_WAIT", Material.RECORD_12); WEtoM.put("RECORD_WARD", Material.RECORD_10); WEtoM.put("RED_FLOWER", Material.RED_ROSE); WEtoM.put("REEDS", Material.SUGAR_CANE); WEtoM.put("REPEATER", Material.DIODE); WEtoM.put("SKULL", Material.SKULL_ITEM); WEtoM.put("SPAWN_EGG", Material.MONSTER_EGG); WEtoM.put("STONE_BRICK_STAIRS", Material.BRICK_STAIRS); WEtoM.put("STONE_BRICK_STAIRS", Material.SMOOTH_STAIRS); WEtoM.put("STONE_SHOVEL", Material.STONE_SPADE); WEtoM.put("STONE_SLAB", Material.STEP); WEtoM.put("STONE_STAIRS", Material.COBBLESTONE_STAIRS); WEtoM.put("TNT_MINECART", Material.EXPLOSIVE_MINECART); WEtoM.put("WATERLILY", Material.WATER_LILY); WEtoM.put("WHEAT_SEEDS", Material.SEEDS); WEtoM.put("WOODEN_AXE", Material.WOOD_AXE); WEtoM.put("WOODEN_BUTTON", Material.WOOD_BUTTON); WEtoM.put("WOODEN_DOOR", Material.WOOD_DOOR); WEtoM.put("WOODEN_HOE", Material.WOOD_HOE); WEtoM.put("WOODEN_PICKAXE", Material.WOOD_PICKAXE); WEtoM.put("WOODEN_PRESSURE_PLATE", Material.WOOD_PLATE); WEtoM.put("WOODEN_SHOVEL", Material.WOOD_SPADE); WEtoM.put("WOODEN_SLAB", Material.WOOD_STEP); WEtoM.put("WOODEN_SWORD", Material.WOOD_SWORD); // Entities WEtoME.put("LAVASLIME", EntityType.MAGMA_CUBE); WEtoME.put("ENTITYHORSE", EntityType.HORSE); WEtoME.put("OZELOT", EntityType.OCELOT); WEtoME.put("MUSHROOMCOW", EntityType.MUSHROOM_COW); WEtoME.put("PIGZOMBIE", EntityType.PIG_ZOMBIE); WEtoME.put("CAVESPIDER", EntityType.CAVE_SPIDER); WEtoME.put("XPORB", EntityType.EXPERIENCE_ORB); WEtoME.put("MINECARTRIDEABLE", EntityType.MINECART); WEtoME.put("MINECARTHOPPER", EntityType.MINECART_HOPPER); WEtoME.put("MINECARTFURNACE", EntityType.MINECART_FURNACE); WEtoME.put("MINECARTMOBSPAWNER", EntityType.MINECART_MOB_SPAWNER); WEtoME.put("MINECARTTNT", EntityType.MINECART_TNT); WEtoME.put("MINECARTCHEST", EntityType.MINECART_CHEST); WEtoME.put("VILLAGERGOLEM", EntityType.IRON_GOLEM); WEtoME.put("ENDERDRAGON", EntityType.ENDER_DRAGON); WEtoME.put("PAINTING", EntityType.PAINTING); WEtoME.put("ITEMFRAME", EntityType.ITEM_FRAME); if (!Bukkit.getServer().getVersion().contains("(MC: 1.7")) { WEtoME.put("ENDERCRYSTAL", EntityType.ENDER_CRYSTAL); WEtoME.put("ARMORSTAND", EntityType.ARMOR_STAND); } } /** * @param x * @param y * @param z */ public IslandBlock(int x, int y, int z) { this.x = x; this.y = y; this.z = z; signText = null; banner = null; skull = null; pot = null; spawnerBlockType = null; chestContents = new HashMap<Byte, ItemStack>(); } /** * @return the type */ public int getTypeId() { return typeId; } /** * @param type the type to set */ public void setTypeId(short type) { this.typeId = type; } /** * @return the data */ public int getData() { return data; } /** * @param data the data to set */ public void setData(byte data) { this.data = data; } /** * @return the signText */ public List<String> getSignText() { return signText; } /** * @param signText the signText to set */ public void setSignText(List<String> signText) { this.signText = signText; } /** * @param s * @param b */ public void setBlock(int s, byte b) { this.typeId = (short) s; this.data = b; } /** * Sets this block up with all the banner data required * @param map */ public void setBanner(Map<String, Tag> map) { banner = new BannerBlock(); banner.prep(map); } /** * Sets this block up with all the skull data required * @param map * @param dataValue */ public void setSkull(Map<String, Tag> map, int dataValue) { skull = new SkullBlock(); skull.prep(map, dataValue); } public void setFlowerPot(Map<String, Tag> map) { pot = new PotBlock(); pot.prep(map); } /** * Sets the spawner type if this block is a spawner * @param tileData */ public void setSpawnerType(Map<String, Tag> tileData) { String creatureType = ((StringTag) tileData.get("EntityId")).getValue().toUpperCase(); if (WEtoME.containsKey(creatureType)) { spawnerBlockType = WEtoME.get(creatureType); } else { try { spawnerBlockType = EntityType.valueOf(creatureType); } catch (Exception e) { Bukkit.getLogger() .severe("I don't know what a " + creatureType + " is... Skipping spawner setting."); } } } /** * Sets this block's sign data * @param tileData */ public void setSign(Map<String, Tag> tileData) { signText = new ArrayList<String>(); List<String> text = new ArrayList<String>(); for (int i = 1; i < 5; i++) { String line = ((StringTag) tileData.get("Text" + String.valueOf(i))).getValue(); // This value can actually be a string that says null sometimes. if (line.equalsIgnoreCase("null")) { line = ""; } //System.out.println("DEBUG: line " + i + " = '"+ line + "' of length " + line.length()); text.add(line); } JSONParser parser = new JSONParser(); ContainerFactory containerFactory = new ContainerFactory() { public List creatArrayContainer() { return new LinkedList(); } public Map createObjectContainer() { return new LinkedHashMap(); } }; // This just removes all the JSON formatting and provides the raw text for (int line = 0; line < 4; line++) { String lineText = ""; if (!text.get(line).equals("\"\"") && !text.get(line).isEmpty()) { //String lineText = text.get(line).replace("{\"extra\":[\"", "").replace("\"],\"text\":\"\"}", ""); //Bukkit.getLogger().info("DEBUG: sign text = '" + text.get(line) + "'"); if (text.get(line).startsWith("{")) { // JSON string try { Map json = (Map) parser.parse(text.get(line), containerFactory); List list = (List) json.get("extra"); //System.out.println("DEBUG1:" + JSONValue.toJSONString(list)); if (list != null) { Iterator iter = list.iterator(); while (iter.hasNext()) { Object next = iter.next(); String format = JSONValue.toJSONString(next); //System.out.println("DEBUG2:" + format); // This doesn't see right, but appears to be the easiest way to identify this string as JSON... if (format.startsWith("{")) { // JSON string Map jsonFormat = (Map) parser.parse(format, containerFactory); Iterator formatIter = jsonFormat.entrySet().iterator(); while (formatIter.hasNext()) { Map.Entry entry = (Map.Entry) formatIter.next(); //System.out.println("DEBUG3:" + entry.getKey() + "=>" + entry.getValue()); String key = entry.getKey().toString(); String value = entry.getValue().toString(); if (key.equalsIgnoreCase("color")) { try { lineText += ChatColor.valueOf(value.toUpperCase()); } catch (Exception noColor) { Bukkit.getLogger().warning("Unknown color " + value + " in sign when pasting schematic, skipping..."); } } else if (key.equalsIgnoreCase("text")) { lineText += value; } else { // Formatting - usually the value is always true, but check just in case if (key.equalsIgnoreCase("obfuscated") && value.equalsIgnoreCase("true")) { lineText += ChatColor.MAGIC; } else if (key.equalsIgnoreCase("underlined") && value.equalsIgnoreCase("true")) { lineText += ChatColor.UNDERLINE; } else { // The rest of the formats try { lineText += ChatColor.valueOf(key.toUpperCase()); } catch (Exception noFormat) { // Ignore //System.out.println("DEBUG3:" + key + "=>" + value); Bukkit.getLogger().warning("Unknown format " + value + " in sign when pasting schematic, skipping..."); } } } } } else { // This is unformatted text. It is included in "". A reset is required to clear // any previous formatting if (format.length() > 1) { lineText += ChatColor.RESET + format.substring(format.indexOf('"') + 1, format.lastIndexOf('"')); } } } } else { // No extra tag json = (Map) parser.parse(text.get(line), containerFactory); String value = (String) json.get("text"); //System.out.println("DEBUG text only?:" + value); lineText += value; } } catch (ParseException e) { // TODO Auto-generated catch block e.printStackTrace(); } } else { // This is unformatted text (not JSON). It is included in "". if (text.get(line).length() > 1) { try { lineText = text.get(line).substring(text.get(line).indexOf('"') + 1, text.get(line).lastIndexOf('"')); } catch (Exception e) { //There may not be those "'s, so just use the raw line lineText = text.get(line); } } else { // just in case it isn't - show the raw line lineText = text.get(line); } } //Bukkit.getLogger().info("Line " + line + " is " + lineText); } signText.add(lineText); } } public void setBook(Map<String, Tag> tileData) { //Bukkit.getLogger().info("DEBUG: Book data "); Bukkit.getLogger().info(tileData.toString()); } @SuppressWarnings("deprecation") public void setChest(NMSAbstraction nms, Map<String, Tag> tileData) { try { ListTag chestItems = (ListTag) tileData.get("Items"); if (chestItems != null) { //int number = 0; for (Tag item : chestItems.getValue()) { // Format for chest items is: // id = short value of item id // Damage = short value of item damage // Count = the number of items // Slot = the slot in the chest // inventory if (item instanceof CompoundTag) { try { // Id is a number short itemType = (Short) ((CompoundTag) item).getValue().get("id").getValue(); short itemDamage = (Short) ((CompoundTag) item).getValue().get("Damage").getValue(); byte itemAmount = (Byte) ((CompoundTag) item).getValue().get("Count").getValue(); byte itemSlot = (Byte) ((CompoundTag) item).getValue().get("Slot").getValue(); ItemStack chestItem = new ItemStack(itemType, itemAmount, itemDamage); chestContents.put(itemSlot, chestItem); } catch (ClassCastException ex) { // Id is a material String itemType = (String) ((CompoundTag) item).getValue().get("id").getValue(); try { // Get the material if (itemType.startsWith("minecraft:")) { String material = itemType.substring(10).toUpperCase(); // Special case for non-standard material names Material itemMaterial; //Bukkit.getLogger().info("DEBUG: " + material); if (WEtoM.containsKey(material)) { //Bukkit.getLogger().info("DEBUG: Found in hashmap"); itemMaterial = WEtoM.get(material); } else { //Bukkit.getLogger().info("DEBUG: Not in hashmap"); itemMaterial = Material.valueOf(material); } short itemDamage = (Short) ((CompoundTag) item).getValue().get("Damage") .getValue(); byte itemAmount = (Byte) ((CompoundTag) item).getValue().get("Count") .getValue(); byte itemSlot = (Byte) ((CompoundTag) item).getValue().get("Slot").getValue(); ItemStack chestItem = new ItemStack(itemMaterial, itemAmount, itemDamage); if (itemMaterial.equals(Material.WRITTEN_BOOK)) { chestItem = nms.setBook(item); } // Check for potions if (itemMaterial.toString().contains("POTION")) { chestItem = nms.setPotion(itemMaterial, item, chestItem); } chestContents.put(itemSlot, chestItem); } } catch (Exception exx) { // Bukkit.getLogger().info(item.toString()); // Bukkit.getLogger().info(((CompoundTag)item).getValue().get("id").getName()); Bukkit.getLogger().severe("Could not parse item [" + itemType.substring(10).toUpperCase() + "] in schematic - skipping!"); // Bukkit.getLogger().severe(item.toString()); exx.printStackTrace(); } } // Bukkit.getLogger().info("Set chest inventory slot " // + itemSlot + " to " + // chestItem.toString()); } } //Bukkit.getLogger().info("Added " + number + " items to chest"); } } catch (Exception e) { Bukkit.getLogger().severe("Could not parse schematic file item, skipping!"); // e.printStackTrace(); } } /** * Paste this block at blockLoc * @param nms * @param blockLoc */ public void paste(NMSAbstraction nms, Location blockLoc, boolean usePhysics, Biome biome) { // Only paste air if it is below the sea level and in the overworld Block block = new Location(blockLoc.getWorld(), x, y, z).add(blockLoc).getBlock(); block.setBiome(biome); nms.setBlockSuperFast(block, typeId, data, usePhysics); if (signText != null) { // Sign Sign sign = (Sign) block.getState(); int index = 0; for (String line : signText) { sign.setLine(index++, line); } sign.update(); } else if (banner != null) { banner.set(block); } else if (skull != null) { skull.set(block); } else if (pot != null) { pot.set(nms, block); } else if (spawnerBlockType != null) { CreatureSpawner cs = (CreatureSpawner) block.getState(); cs.setSpawnedType(spawnerBlockType); } else if (!chestContents.isEmpty()) { // Check if this is a double chest Chest chestBlock = (Chest) block.getState(); InventoryHolder iH = chestBlock.getInventory().getHolder(); if (iH instanceof DoubleChest) { //Bukkit.getLogger().info("DEBUG: double chest"); DoubleChest doubleChest = (DoubleChest) iH; for (ItemStack chestItem : chestContents.values()) { doubleChest.getInventory().addItem(chestItem); } } else { // Signle chest for (Entry<Byte, ItemStack> en : chestContents.entrySet()) { chestBlock.getInventory().setItem(en.getKey(), en.getValue()); } } } } /** * @return Vector for where this block is in the schematic */ public Vector getVector() { return new Vector(x, y, z); } }