package com.tommytony.war.mapper; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import org.bukkit.Material; import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.block.BlockState; import org.bukkit.block.Chest; import org.bukkit.block.Dispenser; import org.bukkit.block.Sign; import org.bukkit.inventory.ItemStack; import org.bukkit.material.MaterialData; import com.tommytony.war.War; import com.tommytony.war.job.DeferredBlockResetsJob; import com.tommytony.war.utility.DeferredBlockReset; import com.tommytony.war.volume.ZoneVolume; /** * The ZoneVolumeMapper take the blocks from disk and sets them in the worlds, since the ZoneVolume doesn't hold its blocks in memory like regular Volumes. * * @author tommytony * */ @SuppressWarnings("deprecation") public class PreDeGaulleZoneVolumeMapper { private static List<ItemStack> readInventoryString(String invString) { List<ItemStack> items = new ArrayList<ItemStack>(); String[] itemsStrSplit = invString.split(";;"); for (String itemStr : itemsStrSplit) { String[] itemStrSplit = itemStr.split(";"); if (itemStrSplit.length == 4) { ItemStack stack = new ItemStack(Integer.parseInt(itemStrSplit[0]), Integer.parseInt(itemStrSplit[1])); stack.setData(new MaterialData(stack.getTypeId(), Byte.parseByte(itemStrSplit[3]))); short durability = (short) Integer.parseInt(itemStrSplit[2]); stack.setDurability(durability); items.add(stack); } else if (itemStrSplit.length == 3) { ItemStack stack = new ItemStack(Integer.parseInt(itemStrSplit[0]), Integer.parseInt(itemStrSplit[1])); short durability = (short) Integer.parseInt(itemStrSplit[2]); stack.setDurability(durability); items.add(stack); } else { items.add(new ItemStack(Integer.parseInt(itemStrSplit[0]), Integer.parseInt(itemStrSplit[1]))); } } return items; } public static int load(ZoneVolume volume, String zoneName, World world, boolean onlyLoadCorners) { BufferedReader in = null; int noOfResetBlocks = 0; try { in = new BufferedReader(new FileReader(new File(War.war.getDataFolder().getPath() + "/dat/warzone-" + zoneName + "/volume-" + volume.getName() + ".dat"))); String firstLine = in.readLine(); if (firstLine != null && !firstLine.equals("")) { boolean height129Fix = false; int x1 = Integer.parseInt(in.readLine()); int y1 = Integer.parseInt(in.readLine()); if (y1 == 128) { height129Fix = true; y1 = 127; } int z1 = Integer.parseInt(in.readLine()); in.readLine(); int x2 = Integer.parseInt(in.readLine()); int y2 = Integer.parseInt(in.readLine()); if (y2 == 128) { height129Fix = true; y2 = 127; } int z2 = Integer.parseInt(in.readLine()); volume.setCornerOne(world.getBlockAt(x1, y1, z1)); volume.setCornerTwo(world.getBlockAt(x2, y2, z2)); if (!onlyLoadCorners) { DeferredBlockResetsJob deferred = new DeferredBlockResetsJob(world); int blockReads = 0, visitedBlocks = 0, x = 0, y = 0, z = 0, i = 0, j = 0, k = 0; int diskBlockType; byte diskBlockData; Block worldBlock; int worldBlockId; volume.clearBlocksThatDontFloat(); x = volume.getMinX(); String blockLine; String[] blockSplit; for (i = 0; i < volume.getSizeX(); i++) { y = volume.getMinY(); for (j = 0; j < volume.getSizeY(); j++) { z = volume.getMinZ(); for (k = 0; k < volume.getSizeZ(); k++) { try { blockLine = in.readLine(); if (blockLine != null && !blockLine.equals("")) { blockSplit = blockLine.split(","); if (blockLine != null && !blockLine.equals("") && blockSplit.length > 1) { diskBlockType = Integer.parseInt(blockSplit[0]); diskBlockData = Byte.parseByte(blockSplit[1]); worldBlock = volume.getWorld().getBlockAt(x, y, z); worldBlockId = worldBlock.getTypeId(); if (worldBlockId != diskBlockType || (worldBlockId == diskBlockType && worldBlock.getData() != diskBlockData) || (worldBlockId == diskBlockType && worldBlock.getData() == diskBlockData && (diskBlockType == Material.WALL_SIGN.getId() || diskBlockType == Material.SIGN_POST.getId() || diskBlockType == Material.CHEST.getId() || diskBlockType == Material.DISPENSER.getId()))) { if (diskBlockType == Material.WALL_SIGN.getId() || diskBlockType == Material.SIGN_POST.getId()) { // Signs read String linesStr = ""; if (blockSplit.length > 2) { for (int o = 2; o < blockSplit.length; o++) { linesStr += blockSplit[o]; } String[] lines = linesStr.split(";;"); // Signs set // A sign post hanging on a wall south of here will if (diskBlockType == Material.SIGN_POST.getId() && ((diskBlockData & 0x04) == 0x04) && i + 1 != volume.getSizeX()) { deferred.add(new DeferredBlockReset(x, y, z, diskBlockType, diskBlockData, lines)); } else { worldBlock.setType(Material.getMaterial(diskBlockType)); BlockState state = worldBlock.getState(); state.setData(new org.bukkit.material.Sign(diskBlockType, diskBlockData)); if (state instanceof Sign) { Sign sign = (Sign) state; if (lines != null && sign.getLines() != null) { if (lines.length > 0) { sign.setLine(0, lines[0]); } if (lines.length > 1) { sign.setLine(1, lines[1]); } if (lines.length > 2) { sign.setLine(2, lines[2]); } if (lines.length > 3) { sign.setLine(3, lines[3]); } sign.update(true); } } } } } else if (diskBlockType == Material.CHEST.getId()) { // Chests read List<ItemStack> items = null; if (blockSplit.length > 2) { String itemsStr = blockSplit[2]; items = PreDeGaulleZoneVolumeMapper.readInventoryString(itemsStr); } // Chests set worldBlock.setType(Material.getMaterial(diskBlockType)); worldBlock.setData(diskBlockData); BlockState state = worldBlock.getState(); if (state instanceof Chest) { Chest chest = (Chest) state; if (items != null) { int ii = 0; chest.getInventory().clear(); for (ItemStack item : items) { if (item != null) { chest.getInventory().setItem(ii, item); ii++; } } chest.update(true); } } } else if (diskBlockType == Material.DISPENSER.getId()) { // Dispensers read List<ItemStack> items = null; if (blockSplit.length > 2) { String itemsStr = blockSplit[2]; // String itemsStr = lineScanner.nextLine(); items = PreDeGaulleZoneVolumeMapper.readInventoryString(itemsStr); } // Dispensers set worldBlock.setType(Material.getMaterial(diskBlockType)); worldBlock.setData(diskBlockData); BlockState state = worldBlock.getState(); if (state instanceof Dispenser) { Dispenser dispenser = (Dispenser) state; if (items != null) { int ii = 0; dispenser.getInventory().clear(); for (ItemStack item : items) { if (item != null) { dispenser.getInventory().setItem(ii, item); ii++; } } dispenser.update(true); } } } else if (diskBlockType == Material.WOODEN_DOOR.getId() || diskBlockType == Material.IRON_DOOR_BLOCK.getId()) { // Door blocks if (j - 1 > 0) { Block blockBelow = world.getBlockAt(x, y - 1, z); boolean belowIsGlass = blockBelow.getTypeId() == Material.GLASS.getId(); // Set current block to glass if block below isn't glass. // Having a glass block below means the current block is a door top. if (belowIsGlass) { // Top door block. Set both it and the block below as door. blockBelow.setType(Material.getMaterial(diskBlockType)); blockBelow.setData(diskBlockData); worldBlock.setType(Material.getMaterial(diskBlockType)); worldBlock.setData(diskBlockData); } else { worldBlock.setType(Material.GLASS); } } } else if (((diskBlockType == Material.TORCH.getId() && ((diskBlockData & 0x02) == 0x02)) || (diskBlockType == Material.REDSTONE_TORCH_OFF.getId() && ((diskBlockData & 0x02) == 0x02)) || (diskBlockType == Material.REDSTONE_TORCH_ON.getId() && ((diskBlockData & 0x02) == 0x02)) || (diskBlockType == Material.LEVER.getId() && ((diskBlockData & 0x02) == 0x02)) || (diskBlockType == Material.STONE_BUTTON.getId() && ((diskBlockData & 0x02) == 0x02)) || (diskBlockType == Material.LADDER.getId() && ((diskBlockData & 0x04) == 0x04)) || (diskBlockType == Material.RAILS.getId() && ((diskBlockData & 0x02) == 0x02))) && i + 1 != volume.getSizeX()) { // Blocks that hang on a block south of themselves need to make sure that block is there before placing themselves... lol // Change the block itself later on: deferred.add(new DeferredBlockReset(x, y, z, diskBlockType, diskBlockData)); } else { // regular block worldBlock.setType(Material.getMaterial(diskBlockType)); worldBlock.setData(diskBlockData); } noOfResetBlocks++; } visitedBlocks++; } blockReads++; } } catch (Exception e) { War.war.getLogger().warning("Failed to reset block in zone volume " + volume.getName() + ". " + "Blocks read: " + blockReads + ". Visited blocks so far:" + visitedBlocks + ". Blocks reset: " + noOfResetBlocks + ". Error at x:" + x + " y:" + y + " z:" + z + ". Exception:" + e.getClass().toString() + " " + e.getMessage()); e.printStackTrace(); } finally { z++; } } if (height129Fix && j == volume.getSizeY() - 1) { for (int skip = 0; skip < volume.getSizeZ(); skip++) { in.readLine(); // throw away the extra vertical block I used to save pre 0.8 // scanner.nextLine(); } } y++; } x++; } if (!deferred.isEmpty()) { War.war.getServer().getScheduler().scheduleSyncDelayedTask(War.war, deferred, 1); } } } } catch (IOException e) { War.war.log("Failed to read volume file " + volume.getName() + " for warzone " + zoneName + ". " + e.getClass().getName() + " " + e.getMessage(), Level.WARNING); e.printStackTrace(); } catch (Exception e) { War.war.log("Unexpected error caused failure to read volume file " + zoneName + " for warzone " + volume.getName() + ". " + e.getClass().getName() + " " + e.getMessage(), Level.WARNING); e.printStackTrace(); } finally { if (in != null) { // if (scanner != null) try { in.close(); in = null; // scanner.close(); // scanner = null; } catch (IOException e) { War.war.log("Failed to close file reader for volume " + volume.getName() + " for warzone " + zoneName + ". " + e.getClass().getName() + " " + e.getMessage(), Level.WARNING); e.printStackTrace(); } } } return noOfResetBlocks; } }