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.acidisland.schematics; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Random; import java.util.Set; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.TreeType; import org.bukkit.World; import org.bukkit.block.Biome; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.block.Chest; import org.bukkit.block.Sign; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.bukkit.material.DirectionalContainer; import org.bukkit.util.BlockVector; import org.bukkit.util.Vector; import org.jnbt.ByteArrayTag; import org.jnbt.CompoundTag; import org.jnbt.IntTag; import org.jnbt.ListTag; import org.jnbt.NBTInputStream; import org.jnbt.ShortTag; 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; import com.wasteofplastic.acidisland.ASkyBlock; import com.wasteofplastic.acidisland.Settings; import com.wasteofplastic.acidisland.Settings.GameType; public class Schematic { private short[] blocks; private byte[] data; private short width; private short length; private short height; private Map<BlockVector, Map<String, Tag>> tileEntitiesMap = new HashMap<BlockVector, Map<String, Tag>>(); private File file; private String heading; private String name; private String perm; private String description; private int rating; private boolean useDefaultChest; private Material icon; private Biome biome; private boolean usePhysics; public Schematic() { // Initialize name = ""; heading = ""; description = "Default Island"; perm = ""; icon = Material.MAP; rating = 50; useDefaultChest = true; biome = Settings.defaultBiome; usePhysics = Settings.usePhysics; file = null; } public Schematic(File file) { // Initialize name = file.getName(); heading = ""; description = ""; perm = ""; icon = Material.MAP; rating = 50; useDefaultChest = true; biome = Settings.defaultBiome; usePhysics = Settings.usePhysics; this.file = file; // Try to load the file try { FileInputStream stream = new FileInputStream(file); // InputStream is = new DataInputStream(new // GZIPInputStream(stream)); NBTInputStream nbtStream = new NBTInputStream(stream); CompoundTag schematicTag = (CompoundTag) nbtStream.readTag(); nbtStream.close(); if (!schematicTag.getName().equals("Schematic")) { throw new IllegalArgumentException("Tag \"Schematic\" does not exist or is not first"); } Map<String, Tag> schematic = schematicTag.getValue(); if (!schematic.containsKey("Blocks")) { throw new IllegalArgumentException("Schematic file is missing a \"Blocks\" tag"); } width = getChildTag(schematic, "Width", ShortTag.class).getValue(); length = getChildTag(schematic, "Length", ShortTag.class).getValue(); height = getChildTag(schematic, "Height", ShortTag.class).getValue(); String materials = getChildTag(schematic, "Materials", StringTag.class).getValue(); if (!materials.equals("Alpha")) { throw new IllegalArgumentException("Schematic file is not an Alpha schematic"); } byte[] blockId = getChildTag(schematic, "Blocks", ByteArrayTag.class).getValue(); data = getChildTag(schematic, "Data", ByteArrayTag.class).getValue(); byte[] addId = new byte[0]; blocks = new short[blockId.length]; // Have to later combine IDs // We support 4096 block IDs using the same method as vanilla // Minecraft, where // the highest 4 bits are stored in a separate byte array. if (schematic.containsKey("AddBlocks")) { addId = getChildTag(schematic, "AddBlocks", ByteArrayTag.class).getValue(); } // Combine the AddBlocks data with the first 8-bit block ID for (int index = 0; index < blockId.length; index++) { if ((index >> 1) >= addId.length) { // No corresponding // AddBlocks index blocks[index] = (short) (blockId[index] & 0xFF); } else { if ((index & 1) == 0) { blocks[index] = (short) (((addId[index >> 1] & 0x0F) << 8) + (blockId[index] & 0xFF)); } else { blocks[index] = (short) (((addId[index >> 1] & 0xF0) << 4) + (blockId[index] & 0xFF)); } } } // Need to pull out tile entities List<Tag> tileEntities = getChildTag(schematic, "TileEntities", ListTag.class).getValue(); // Map<BlockVector, Map<String, Tag>> tileEntitiesMap = new // HashMap<BlockVector, Map<String, Tag>>(); for (Tag tag : tileEntities) { if (!(tag instanceof CompoundTag)) continue; CompoundTag t = (CompoundTag) tag; int x = 0; int y = 0; int z = 0; Map<String, Tag> values = new HashMap<String, Tag>(); for (Map.Entry<String, Tag> entry : t.getValue().entrySet()) { if (entry.getKey().equals("x")) { if (entry.getValue() instanceof IntTag) { x = ((IntTag) entry.getValue()).getValue(); } } else if (entry.getKey().equals("y")) { if (entry.getValue() instanceof IntTag) { y = ((IntTag) entry.getValue()).getValue(); } } else if (entry.getKey().equals("z")) { if (entry.getValue() instanceof IntTag) { z = ((IntTag) entry.getValue()).getValue(); } } values.put(entry.getKey(), entry.getValue()); } BlockVector vec = new BlockVector(x, y, z); tileEntitiesMap.put(vec, values); } } catch (IOException e) { Bukkit.getLogger().severe("Could not load island schematic! Error in file."); e.printStackTrace(); } } /** * @return the biome */ public Biome getBiome() { return biome; } /** * @return the blocks */ public short[] getBlocks() { return blocks; } /** * @return the data */ public byte[] getData() { return data; } /** * @return the description */ public String getDescription() { return description; } /** * @return the file */ public File getFile() { return file; } /** * @return the heading */ public String getHeading() { return heading; } /** * @return the height */ public short getHeight() { return height; } /** * @return the icon */ public Material getIcon() { return icon; } /** * @return the length */ public short getLength() { return length; } /** * @return the name */ public String getName() { return name; } /** * @return the perm */ public String getPerm() { return perm; } /** * @return the rating */ public int getRating() { return rating; } /** * @return the tileEntitiesMap */ public Map<BlockVector, Map<String, Tag>> getTileEntitiesMap() { return tileEntitiesMap; } /** * @return the width */ public short getWidth() { return width; } /** * @return the useDefaultChest */ public boolean isUseDefaultChest() { return useDefaultChest; } /** * @return the usePhysics */ public boolean isUsePhysics() { return usePhysics; } /** * This method pastes a schematic and returns a location where a cow (or other entity) * could be placed. Actually, the location should be that of a grass block. * @param world * @param loc * @param player * @return Location of highest grass block */ @SuppressWarnings("deprecation") public void pasteSchematic(final Location loc, final Player player) { // If this is not a file schematic, paste the default island if (this.file == null) { if (Settings.GAMETYPE == GameType.ACIDISLAND) { generateIslandBlocks(loc, player); } else { loc.getBlock().setType(Material.BEDROCK); ASkyBlock.getPlugin().getLogger().severe("Missing schematic - using bedrock block only"); } return; } World world = loc.getWorld(); Map<BlockVector, Map<String, Tag>> tileEntitiesMap = this.getTileEntitiesMap(); // Bukkit.getLogger().info("World is " + world.getName() + // "and schematic size is " + schematic.getBlocks().length); // Bukkit.getLogger().info("DEBUG Location to place island is:" + // loc.toString()); // Find top most bedrock - this is the key stone // Find top most chest // Find top most grass Location bedrock = null; Location chest = null; Location welcomeSign = null; Set<Vector> grassBlocks = new HashSet<Vector>(); for (int x = 0; x < width; ++x) { for (int y = 0; y < height; ++y) { for (int z = 0; z < length; ++z) { int index = y * width * length + z * width + x; // Bukkit.getLogger().info("DEBUG " + index + // " changing to ID:"+blocks[index] + " data = " + // blockData[index]); if (blocks[index] == 7) { // Last bedrock if (bedrock == null || bedrock.getY() < y) { bedrock = new Location(world, x, y, z); //Bukkit.getLogger().info("DEBUG higher bedrock found:" + bedrock.toString()); } } else if (blocks[index] == 54) { // Last chest if (chest == null || chest.getY() < y) { chest = new Location(world, x, y, z); // Bukkit.getLogger().info("Island loc:" + // loc.toString()); // Bukkit.getLogger().info("Chest relative location is " // + chest.toString()); } } else if (blocks[index] == 63) { // Sign if (welcomeSign == null || welcomeSign.getY() < y) { welcomeSign = new Location(world, x, y, z); // Bukkit.getLogger().info("DEBUG higher sign found:" // + welcomeSign.toString()); } } else if (blocks[index] == 2) { // Grass grassBlocks.add(new Vector(x, y, z)); } } } } if (bedrock == null) { Bukkit.getLogger().severe("Schematic must have at least one bedrock in it!"); return; } if (chest == null) { Bukkit.getLogger().severe("Schematic must have at least one chest in it!"); return; } /* * These are now optional * if (welcomeSign == null) { * Bukkit.getLogger().severe( * "ASkyBlock: Schematic must have at least one sign post in it!"); * return null; * } */ if (grassBlocks.isEmpty()) { Bukkit.getLogger().severe("Schematic must have at least one grass block in it!"); return; } // Center on the last bedrock location //Bukkit.getLogger().info("DEBUG bedrock is:" + bedrock.toString()); // Bukkit.getLogger().info("DEBUG loc is before subtract:" + // loc.toString()); Location blockLoc = new Location(world, loc.getX(), loc.getY(), loc.getZ()); blockLoc.subtract(bedrock); // Bukkit.getLogger().info("DEBUG loc is after subtract:" + // loc.toString()); //Bukkit.getLogger().info("DEBUG blockloc is:" + blockLoc.toString()); // Bukkit.getLogger().info("DEBUG there are " + tileEntitiesMap.size() + // " tile entities in the schematic"); // Bukkit.getLogger().info("Placing blocks..."); for (int x = 0; x < width; ++x) { for (int y = 0; y < height; ++y) { for (int z = 0; z < length; ++z) { int index = y * width * length + z * width + x; Block block = new Location(world, x, y, z).add(blockLoc).getBlock(); try { // Do not post torches because they fall off every so often // May have to include banners too if (blocks[index] != Material.TORCH.getId()) { block.setTypeIdAndData(blocks[index], data[index], this.usePhysics); } } catch (Exception e) { // Do some 1.7.9 helping for the built-in schematic if (blocks[index] == 179) { // Red sandstone - use red sand instead block.setTypeIdAndData(12, (byte) 1, this.usePhysics); } else { Bukkit.getLogger().info("Could not set (" + x + "," + y + "," + z + ") block ID:" + blocks[index] + " block data = " + data[index]); } } } } } // Second pass for (int x = 0; x < width; ++x) { for (int y = 0; y < height; ++y) { for (int z = 0; z < length; ++z) { int index = y * width * length + z * width + x; Block block = new Location(world, x, y, z).add(blockLoc).getBlock(); try { block.setTypeIdAndData(blocks[index], data[index], this.usePhysics); } catch (Exception e) { // Do some 1.7.9 helping for the built-in schematic if (blocks[index] == 179) { // Red sandstone - use red sand instead block.setTypeIdAndData(12, (byte) 1, this.usePhysics); } else { Bukkit.getLogger().info("Could not set (" + x + "," + y + "," + z + ") block ID:" + blocks[index] + " block data = " + data[index]); } } if (tileEntitiesMap.containsKey(new BlockVector(x, y, z))) { String ver = Bukkit.getServer().getBukkitVersion(); int major = Integer.valueOf(ver.substring(0, 1)); int minor = Integer.valueOf(ver.substring(ver.indexOf(".") + 1, ver.indexOf(".") + 2)); if (major >= 1 && minor >= 8) { if (block.getType() == Material.STANDING_BANNER || block.getType() == Material.WALL_BANNER) { BannerBlock.set(block, tileEntitiesMap.get(new BlockVector(x, y, z))); } } if ((block.getType() == Material.SIGN_POST) || (block.getType() == Material.WALL_SIGN)) { Sign sign = (Sign) block.getState(); Map<String, Tag> tileData = tileEntitiesMap.get(new BlockVector(x, y, z)); // for (String key : tileData.keySet()) { // Bukkit.getLogger().info("DEBUG: key = " + key + // " : " + tileData.get(key)); // //StringTag st = (StringTag) tileData.get(key); // Bukkit.getLogger().info("DEBUG: key = " + key + // " : " + st.getName() + " " + st.getValue()); // } List<String> text = new ArrayList<String>(); text.add(((StringTag) tileData.get("Text1")).getValue()); text.add(((StringTag) tileData.get("Text2")).getValue()); text.add(((StringTag) tileData.get("Text3")).getValue()); text.add(((StringTag) tileData.get("Text4")).getValue()); // TODO Parse sign text formatting, colors and ULR's using JSON - this does not work right now JSONParser parser = new JSONParser(); ContainerFactory containerFactory = new ContainerFactory() { public List creatArrayContainer() { return new LinkedList(); } public Map createObjectContainer() { return new LinkedHashMap(); } }; /* for (int line = 0; line < 4; line++) { if (!text.get(line).equals("\"\"")) { try{ Bukkit.getLogger().info("Text: '" + text.get(line) + "'"); Map json = (Map)parser.parse(text.get(line), containerFactory); Iterator iter = json.entrySet().iterator(); System.out.println("==iterate result=="); while(iter.hasNext()){ Map.Entry entry = (Map.Entry)iter.next(); if (entry.getValue().toString().equals("extra")) { List content = (List)parser.parse(entry) } System.out.println(entry.getKey() + "=>" + entry.getValue()); } System.out.println("==toJSONString()=="); System.out.println(JSONValue.toJSONString(json)); } catch(ParseException pe){ System.out.println(pe); } } */ // This just removes all the JSON formatting and provides the raw text for (int line = 0; line < 4; line++) { 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) + "'"); String lineText = ""; 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)); 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 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('"')); } } } } 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) { lineText = text.get(line).substring(text.get(line).indexOf('"') + 1, text.get(line).lastIndexOf('"')); } else { // ust in case it isn't - show the raw line lineText = text.get(line); } } //Bukkit.getLogger().info("Line " + line + " is " + lineText); // Set the line sign.setLine(line, lineText); } } sign.update(); } if (block.getType().equals(Material.CHEST)) { Chest chestBlock = (Chest) block.getState(); // Bukkit.getLogger().info("Chest tile entity found"); Map<String, Tag> tileData = tileEntitiesMap.get(new BlockVector(x, y, z)); try { ListTag chestItems = (ListTag) tileData.get("Items"); if (chestItems != null) { 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); chestBlock.getInventory().setItem(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 // REEDS, that is sugar // cane if (material.equalsIgnoreCase("REEDS")) { material = "SUGAR_CANE"; } if (material.equalsIgnoreCase("MYCELIUM")) { material = "MYCEL"; } if (material.equalsIgnoreCase("COOKED_PORKCHOP")) { material = "GRILLED_PORK"; } Material 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); chestBlock.getInventory().setItem(itemSlot, chestItem); // Bukkit.getLogger().info("Adding " // + // chestItem.toString() // + " to chest"); } } 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()); } } } } catch (Exception e) { Bukkit.getLogger().severe("Could not parse schematic file item, skipping!"); // e.printStackTrace(); } } } } } } // Go through all the grass blocks and try to find a safe one // Sort by height List<Vector> sorted = new ArrayList<Vector>(); for (Vector v : grassBlocks) { v.subtract(bedrock.toVector()); v.add(loc.toVector()); v.add(new Vector(0.5D, 1.1D, 0.5D)); // Center of block //if (GridManager.isSafeLocation(v.toLocation(world))) { // Add to sorted list boolean inserted = false; for (int i = 0; i < sorted.size(); i++) { if (v.getBlockY() > sorted.get(i).getBlockY()) { sorted.add(i, v); inserted = true; break; } } if (!inserted) { // just add to the end of the list sorted.add(v); } //} } final Location grass = sorted.get(0).toLocation(world); //Bukkit.getLogger().info("DEBUG cow location " + grass.toString()); Block blockToChange = null; // world.spawnEntity(grass, EntityType.COW); // Place a helpful sign in front of player if (welcomeSign != null) { // Bukkit.getLogger().info("DEBUG welcome sign schematic relative is:" // + welcomeSign.toString()); welcomeSign.subtract(bedrock); // Bukkit.getLogger().info("DEBUG welcome sign relative to bedrock is:" // + welcomeSign.toString()); welcomeSign.add(loc); // Bukkit.getLogger().info("DEBUG welcome sign actual position is:" // + welcomeSign.toString()); blockToChange = welcomeSign.getBlock(); blockToChange.setType(Material.SIGN_POST); Sign sign = (Sign) blockToChange.getState(); sign.setLine(0, ASkyBlock.getPlugin().myLocale(player.getUniqueId()).signLine1.replace("[player]", player.getName())); sign.setLine(1, ASkyBlock.getPlugin().myLocale(player.getUniqueId()).signLine2.replace("[player]", player.getName())); sign.setLine(2, ASkyBlock.getPlugin().myLocale(player.getUniqueId()).signLine3.replace("[player]", player.getName())); sign.setLine(3, ASkyBlock.getPlugin().myLocale(player.getUniqueId()).signLine4.replace("[player]", player.getName())); // BlockFace direction = ((org.bukkit.material.Sign) // sign.getData()).getFacing(); ((org.bukkit.material.Sign) sign.getData()).setFacingDirection(BlockFace.NORTH); sign.update(); } chest.subtract(bedrock); chest.add(loc); // Place the chest - no need to use the safe spawn function because we // know what this island looks like blockToChange = chest.getBlock(); // Bukkit.getLogger().info("Chest block = " + blockToChange); // blockToChange.setType(Material.CHEST); // Bukkit.getLogger().info("Chest item settings = " + // Settings.chestItems[0]); // Bukkit.getLogger().info("Chest item settings length = " + // Settings.chestItems.length); if (useDefaultChest && Settings.chestItems[0] != null) { // Fill the chest if (blockToChange.getType() == Material.CHEST) { final Chest islandChest = (Chest) blockToChange.getState(); final Inventory inventory = islandChest.getInventory(); inventory.clear(); inventory.setContents(Settings.chestItems); } } if (Settings.islandCompanion != null) { Bukkit.getServer().getScheduler().runTaskLater(ASkyBlock.getPlugin(), new Runnable() { @Override public void run() { spawnCompanion(player, grass); } }, 40L); } } /** * @param biome the biome to set */ public void setBiome(Biome biome) { this.biome = biome; } /** * @param description the description to set */ public void setDescription(String description) { this.description = description; } /** * @param heading the heading to set */ public void setHeading(String heading) { this.heading = heading; } /** * @param icon the icon to set */ public void setIcon(Material icon) { this.icon = icon; } /** * @param name the name to set */ public void setName(String name) { this.name = name; } /** * @param perm the perm to set */ public void setPerm(String perm) { this.perm = perm; } /** * @param rating the rating to set */ public void setRating(int rating) { this.rating = rating; } /** * @param useDefaultChest the useDefaultChest to set */ public void setUseDefaultChest(boolean useDefaultChest) { this.useDefaultChest = useDefaultChest; } /** * @param usePhysics the usePhysics to set */ public void setUsePhysics(boolean usePhysics) { this.usePhysics = usePhysics; } /** * Creates an island block by block * * @param x * @param z * @param player * @param world */ @SuppressWarnings("deprecation") public static void generateIslandBlocks(final Location islandLoc, final Player player) { // AcidIsland // Build island layer by layer // Start from the base // half sandstone; half sand int x = islandLoc.getBlockX(); int z = islandLoc.getBlockZ(); World world = islandLoc.getWorld(); int y = 0; for (int x_space = x - 4; x_space <= x + 4; x_space++) { for (int z_space = z - 4; z_space <= z + 4; z_space++) { final Block b = world.getBlockAt(x_space, y, z_space); b.setType(Material.BEDROCK); } } for (y = 1; y < Settings.island_level + 5; y++) { for (int x_space = x - 4; x_space <= x + 4; x_space++) { for (int z_space = z - 4; z_space <= z + 4; z_space++) { final Block b = world.getBlockAt(x_space, y, z_space); if (y < (Settings.island_level / 2)) { b.setType(Material.SANDSTONE); } else { b.setType(Material.SAND); b.setData((byte) 0); } } } } // Then cut off the corners to make it round-ish for (y = 0; y < Settings.island_level + 5; y++) { for (int x_space = x - 4; x_space <= x + 4; x_space += 8) { for (int z_space = z - 4; z_space <= z + 4; z_space += 8) { final Block b = world.getBlockAt(x_space, y, z_space); b.setType(Material.STATIONARY_WATER); } } } // Add some grass for (y = Settings.island_level + 4; y < Settings.island_level + 5; y++) { for (int x_space = x - 2; x_space <= x + 2; x_space++) { for (int z_space = z - 2; z_space <= z + 2; z_space++) { final Block blockToChange = world.getBlockAt(x_space, y, z_space); blockToChange.setType(Material.GRASS); } } } // Place bedrock - MUST be there (ensures island are not // overwritten Block b = world.getBlockAt(x, Settings.island_level, z); b.setType(Material.BEDROCK); // Then add some more dirt in the classic shape y = Settings.island_level + 3; for (int x_space = x - 2; x_space <= x + 2; x_space++) { for (int z_space = z - 2; z_space <= z + 2; z_space++) { b = world.getBlockAt(x_space, y, z_space); b.setType(Material.DIRT); } } b = world.getBlockAt(x - 3, y, z); b.setType(Material.DIRT); b = world.getBlockAt(x + 3, y, z); b.setType(Material.DIRT); b = world.getBlockAt(x, y, z - 3); b.setType(Material.DIRT); b = world.getBlockAt(x, y, z + 3); b.setType(Material.DIRT); y = Settings.island_level + 2; for (int x_space = x - 1; x_space <= x + 1; x_space++) { for (int z_space = z - 1; z_space <= z + 1; z_space++) { b = world.getBlockAt(x_space, y, z_space); b.setType(Material.DIRT); } } b = world.getBlockAt(x - 2, y, z); b.setType(Material.DIRT); b = world.getBlockAt(x + 2, y, z); b.setType(Material.DIRT); b = world.getBlockAt(x, y, z - 2); b.setType(Material.DIRT); b = world.getBlockAt(x, y, z + 2); b.setType(Material.DIRT); y = Settings.island_level + 1; b = world.getBlockAt(x - 1, y, z); b.setType(Material.DIRT); b = world.getBlockAt(x + 1, y, z); b.setType(Material.DIRT); b = world.getBlockAt(x, y, z - 1); b.setType(Material.DIRT); b = world.getBlockAt(x, y, z + 1); b.setType(Material.DIRT); // Add island items y = Settings.island_level; // Add tree (natural) final Location treeLoc = new Location(world, x, y + 5D, z); world.generateTree(treeLoc, TreeType.ACACIA); // Place the cow final Location cowSpot = new Location(world, x, (Settings.island_level + 5), z - 2); // Place a helpful sign in front of player Block blockToChange = world.getBlockAt(x, Settings.island_level + 5, z + 3); blockToChange.setType(Material.SIGN_POST); Sign sign = (Sign) blockToChange.getState(); sign.setLine(0, ASkyBlock.getPlugin().myLocale(player.getUniqueId()).signLine1.replace("[player]", player.getName())); sign.setLine(1, ASkyBlock.getPlugin().myLocale(player.getUniqueId()).signLine2.replace("[player]", player.getName())); sign.setLine(2, ASkyBlock.getPlugin().myLocale(player.getUniqueId()).signLine3.replace("[player]", player.getName())); sign.setLine(3, ASkyBlock.getPlugin().myLocale(player.getUniqueId()).signLine4.replace("[player]", player.getName())); ((org.bukkit.material.Sign) sign.getData()).setFacingDirection(BlockFace.NORTH); sign.update(); // Place the chest - no need to use the safe spawn function // because we // know what this island looks like blockToChange = world.getBlockAt(x, Settings.island_level + 5, z + 1); blockToChange.setType(Material.CHEST); // Only set if the config has items in it if (Settings.chestItems.length > 0) { final Chest chest = (Chest) blockToChange.getState(); final Inventory inventory = chest.getInventory(); inventory.clear(); inventory.setContents(Settings.chestItems); chest.update(); } // Fill the chest and orient it correctly (1.8 faces it north! DirectionalContainer dc = (DirectionalContainer) blockToChange.getState().getData(); dc.setFacingDirection(BlockFace.SOUTH); blockToChange.setData(dc.getData(), true); if (Settings.islandCompanion != null) { Bukkit.getServer().getScheduler().runTaskLater(ASkyBlock.getPlugin(), new Runnable() { @Override public void run() { spawnCompanion(player, cowSpot); } }, 40L); } } /** * Get child tag of a NBT structure. * * @param items * The parent tag map * @param key * The name of the tag to get * @param expected * The expected type of the tag * @return child tag casted to the expected type * @throws DataException * if the tag does not exist or the tag is not of the * expected type */ private static <T extends Tag> T getChildTag(Map<String, Tag> items, String key, Class<T> expected) throws IllegalArgumentException { if (!items.containsKey(key)) { throw new IllegalArgumentException("Schematic file is missing a \"" + key + "\" tag"); } Tag tag = items.get(key); if (!expected.isInstance(tag)) { throw new IllegalArgumentException(key + " tag is not of tag type " + expected.getName()); } return expected.cast(tag); } /** * Spawns a companion for the player at the location given * @param player * @param cowSpot */ protected static void spawnCompanion(Player player, Location cowSpot) { // Older versions of the server require custom names to only apply to Living Entities LivingEntity companion = (LivingEntity) player.getWorld().spawnEntity(cowSpot, Settings.islandCompanion); if (!Settings.companionNames.isEmpty()) { Random rand = new Random(); int randomNum = rand.nextInt(Settings.companionNames.size()); String name = Settings.companionNames.get(randomNum).replace("[player]", player.getDisplayName()); //plugin.getLogger().info("DEBUG: name is " + name); companion.setCustomName(name); companion.setCustomNameVisible(true); } } }