Java tutorial
/* * Copyright (C) 2016 larryTheHarry * * 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.larryTheCoder.schematic; import cn.nukkit.block.Block; import cn.nukkit.item.Item; import cn.nukkit.level.Location; import cn.nukkit.math.Vector3; import cn.nukkit.utils.TextFormat; import com.intellectiualcrafters.TaskManager; 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 com.larryTheCoder.ASkyBlock; import com.larryTheCoder.task.ChestPopulateTask; import com.larryTheCoder.task.SignPopulateTask; import com.larryTheCoder.utils.Utils; import static com.larryTheCoder.utils.Utils.loadChunkAt; import org.jnbt.CompoundTag; import org.jnbt.ListTag; import org.jnbt.StringTag; import org.jnbt.Tag; import org.json.simple.JSONValue; import org.json.simple.parser.ContainerFactory; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; /** * The package will rules every object in Schematic without this, the schematic * is useless * * @author larryTheCoder */ public class IslandBlock { private short typeId; private int data; private final int x; private final int y; private final int z; private List<String> signText; private PotBlock pot; // Chest contents private final HashMap<Integer, Item> chestContents; public static final HashMap<String, Integer> WETOME = new HashMap<>(); static { // Establish the World Edit to Material look up WETOME.put("ARMORSTAND", 0); WETOME.put("ACACIA_DOOR", Item.ACACIA_DOOR); WETOME.put("BIRCH_DOOR", Item.BIRCH_DOOR); WETOME.put("BIRCH_STAIRS", Item.BIRCH_WOOD_STAIRS); WETOME.put("DARK_OAK_DOOR", Item.DARK_OAK_DOOR); WETOME.put("JUNGLE_DOOR", Item.JUNGLE_DOOR); WETOME.put("SLIME", Item.SLIME_BLOCK); WETOME.put("SPRUCE_DOOR", Item.SPRUCE_DOOR); WETOME.put("BREWING_STAND", Item.BREWING_STAND); WETOME.put("CARROT_ON_A_STICK", Item.AIR); WETOME.put("CARROT", Item.CARROT); WETOME.put("CAULDRON", Item.CAULDRON); WETOME.put("CLOCK", Item.CLOCK); WETOME.put("COBBLESTONE_WALL", Item.COBBLE_WALL); WETOME.put("COMPARATOR", Item.COMPARATOR); WETOME.put("COOKED_PORKCHOP", Item.COOKED_PORKCHOP); WETOME.put("DIAMOND_HORSE_ARMOR", Item.DIAMOND_HORSE_ARMOR); WETOME.put("DIAMOND_SHOVEL", Item.DIAMOND_SHOVEL); WETOME.put("DYE", Item.DYE); WETOME.put("END_PORTAL_FRAME", Item.END_PORTAL_FRAME); WETOME.put("END_STONE", Item.END_STONE); WETOME.put("EXPERIENCE_BOTTLE", Item.EXPERIENCE_BOTTLE); WETOME.put("FILLED_MAP", Item.MAP); WETOME.put("FIRE_CHARGE", Item.AIR); WETOME.put("FIREWORKS", Item.AIR); WETOME.put("FLOWER_POT", Item.FLOWER_POT); WETOME.put("GLASS_PANE", Item.GLASS_PANE); WETOME.put("GOLDEN_CHESTPLATE", Item.GOLD_CHESTPLATE); WETOME.put("GOLDEN_HORSE_ARMOR", Item.GOLD_HORSE_ARMOR); WETOME.put("GOLDEN_LEGGINGS", Item.GOLD_LEGGINGS); WETOME.put("GOLDEN_PICKAXE", Item.GOLD_PICKAXE); WETOME.put("GOLDEN_RAIL", Item.POWERED_RAIL); WETOME.put("GOLDEN_SHOVEL", Item.GOLD_SHOVEL); WETOME.put("GOLDEN_SWORD", Item.GOLD_SWORD); WETOME.put("GOLDEN_HELMET", Item.GOLD_HELMET); WETOME.put("GOLDEN_HOE", Item.GOLD_HOE); WETOME.put("GOLDEN_AXE", Item.GOLD_AXE); WETOME.put("GOLDEN_BOOTS", Item.GOLD_BOOTS); WETOME.put("HARDENED_CLAY", Item.HARDENED_CLAY); WETOME.put("HEAVY_WEIGHTED_PRESSURE_PLATE", Item.HEAVY_WEIGHTED_PRESSURE_PLATE); WETOME.put("IRON_BARS", Item.IRON_BARS); WETOME.put("IRON_HORSE_ARMOR", Item.IRON_HORSE_ARMOR); WETOME.put("IRON_SHOVEL", Item.IRON_SHOVEL); WETOME.put("LEAD", Item.AIR); WETOME.put("LEAVES2", Item.LEAVES2); WETOME.put("LIGHT_WEIGHTED_PRESSURE_PLATE", Item.LIGHT_WEIGHTED_PRESSURE_PLATE); WETOME.put("LOG2", Item.LOG2); WETOME.put("MAP", Item.EMPTY_MAP); WETOME.put("MYCELIUM", Item.MYCELIUM); WETOME.put("NETHER_BRICK_FENCE", Item.NETHER_BRICK_FENCE); WETOME.put("NETHER_WART", Item.NETHER_WART); WETOME.put("NETHERBRICK", Item.NETHER_BRICK); WETOME.put("OAK_STAIRS", Item.WOOD_STAIRS); WETOME.put("POTATO", Item.POTATO); WETOME.put("RAIL", Item.RAIL); WETOME.put("RECORD_11", Item.AIR); WETOME.put("RECORD_13", Item.AIR); WETOME.put("RECORD_BLOCKS", Item.AIR); WETOME.put("RECORD_CAT", Item.AIR); WETOME.put("RECORD_CHIRP", Item.AIR); WETOME.put("RECORD_FAR", Item.AIR); WETOME.put("RECORD_MALL", Item.AIR); WETOME.put("RECORD_MELLOHI", Item.AIR); WETOME.put("RECORD_STAL", Item.AIR); WETOME.put("RECORD_STRAD", Item.AIR); WETOME.put("RECORD_WAIT", Item.AIR); WETOME.put("RECORD_WARD", Item.AIR); WETOME.put("RED_FLOWER", Item.AIR); WETOME.put("REEDS", Item.SUGAR_CANE); WETOME.put("REPEATER", Item.REPEATER); WETOME.put("SKULL", Item.SKULL); WETOME.put("SPAWN_EGG", Item.SPAWN_EGG); WETOME.put("STONE_BRICK_STAIRS", Item.BRICK_STAIRS); WETOME.put("STONE_BRICK_STAIRS", Item.STONE_BRICK_STAIRS); WETOME.put("STONE_SHOVEL", Item.STONE_SHOVEL); WETOME.put("STONE_SLAB", Item.SLAB); WETOME.put("STONE_STAIRS", Item.COBBLESTONE_STAIRS); WETOME.put("TNT_MINECART", Item.MINECART_WITH_TNT); WETOME.put("WATERLILY", Item.WATER_LILY); WETOME.put("WHEAT_SEEDS", Item.SEEDS); WETOME.put("WOODEN_AXE", Item.WOODEN_AXE); WETOME.put("WOODEN_BUTTON", Item.WOODEN_BUTTON); WETOME.put("WOODEN_DOOR", Item.WOODEN_DOOR); WETOME.put("WOODEN_HOE", Item.WOODEN_HOE); WETOME.put("WOODEN_PICKAXE", Item.WOODEN_PICKAXE); WETOME.put("WOODEN_PRESSURE_PLATE", Item.WOODEN_PRESSURE_PLATE); WETOME.put("WOODEN_SHOVEL", Item.WOODEN_SHOVEL); WETOME.put("WOODEN_SLAB", Item.WOODEN_SLAB); WETOME.put("WOODEN_SWORD", Item.WOODEN_SWORD); } /** * @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; pot = null; chestContents = new HashMap<>(); } /** * @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 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 this block's sign data * * @param tileData */ public void setSign(Map<String, Tag> tileData) { signText = new ArrayList<>(); List<String> text = new ArrayList<>(); 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() { @Override public List creatArrayContainer() { return new LinkedList<>(); } @Override 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 += TextFormat.valueOf(value.toUpperCase()); } catch (Exception noColor) { Utils.ConsoleMsg("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 += TextFormat.OBFUSCATED; } else if (key.equalsIgnoreCase("underlined") && value.equalsIgnoreCase("true")) { lineText += TextFormat.UNDERLINE; } else { // The rest of the formats try { lineText += TextFormat.valueOf(key.toUpperCase()); } catch (Exception noFormat) { // Ignore //System.out.println("DEBUG3:" + key + "=>" + value); Utils.ConsoleMsg("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 += TextFormat.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 "); Utils.ConsoleMsg(tileData.toString()); } @SuppressWarnings("deprecation") public void setChest(Map<String, Tag> tileData) { try { ListTag chestItems = (ListTag) tileData.get("Items"); if (chestItems != null) { //int number = 0; chestItems.getValue().stream().filter((item) -> (item instanceof CompoundTag)).forEach((item) -> { 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(); chestContents.put((int) itemSlot, Item.get(itemType, (int) itemDamage, itemAmount)); } 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 int itemMaterial; //Bukkit.getLogger().info("DEBUG: " + material); if (WETOME.containsKey(material)) { itemMaterial = WETOME.get(material); } else { itemMaterial = Item.fromString(material).getId(); } byte itemAmount = (byte) ((CompoundTag) item).getValue().get("Count").getValue(); short itemDamage = (short) ((CompoundTag) item).getValue().get("Damage").getValue(); byte itemSlot = (byte) ((CompoundTag) item).getValue().get("Slot").getValue(); chestContents.put((int) itemSlot, Item.get(itemMaterial, (int) itemDamage, itemAmount)); } } catch (Exception exx) { Utils.ConsoleMsg("Could not parse item [" + itemType.substring(10).toUpperCase() + "] in schematic"); exx.printStackTrace(); } } }); // 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 } } catch (Exception e) { Utils.ConsoleMsg("Could not parse schematic file item, skipping!"); if (ASkyBlock.get().isDebug()) { e.printStackTrace(); } } } /** * Paste this block at blockLoc * * @param usePhysics * @param blockLoc */ public void paste(Location blockLoc, boolean usePhysics) { Location loc = new Location(x, y, z, 0, 0, blockLoc.getLevel()).add(blockLoc); loadChunkAt(loc); // Only paste air if it is below the sea level and in the overworld Block block = loc.getLevelBlock(); // found the problem why blocks didnt shows up blockLoc.getLevel().setBlock(block, Block.get(typeId, data), usePhysics, true); if (Block.get(typeId, data).getId() == Block.SIGN_POST || Block.get(typeId, data).getId() == Block.WALL_SIGN) { TaskManager.runTaskLater(new SignPopulateTask(loc, signText), 10); } else if (pot != null) { pot.set(blockLoc, block); } else if (Block.get(typeId, data).getId() == Block.CHEST) { TaskManager.runTaskLater(new ChestPopulateTask(loc, chestContents), 10); } } /** * @return Vector for where this block is in the schematic */ public Vector3 getVector() { return new Vector3(x, y, z); } }