From 46308e328fc20fb41cce616c13cef7b7f63192d3 Mon Sep 17 00:00:00 2001 From: theone1000 Date: Sun, 13 Oct 2019 19:10:58 -0600 Subject: [PATCH] update --- .../commands/admin/UpgradeCommand.java | 2 +- .../songoda/skyblock/config/FileManager.java | 114 +++--- .../skyblock/island/IslandManager.java | 10 +- .../com/songoda/skyblock/listeners/Block.java | 4 +- .../com/songoda/skyblock/listeners/Grow.java | 8 +- .../java/com/songoda/skyblock/menus/Coop.java | 11 +- .../com/songoda/skyblock/menus/Upgrade.java | 1 + .../utils/structure/StructureUtil.java | 334 ++++++++++-------- .../resources/structures/default.structure | Bin 2656 -> 153500 bytes 9 files changed, 263 insertions(+), 221 deletions(-) diff --git a/src/main/java/com/songoda/skyblock/command/commands/admin/UpgradeCommand.java b/src/main/java/com/songoda/skyblock/command/commands/admin/UpgradeCommand.java index d920abd5..72b657f0 100644 --- a/src/main/java/com/songoda/skyblock/command/commands/admin/UpgradeCommand.java +++ b/src/main/java/com/songoda/skyblock/command/commands/admin/UpgradeCommand.java @@ -25,7 +25,7 @@ public class UpgradeCommand extends SubCommand { Config config = fileManager.getConfig(new File(skyblock.getDataFolder(), "language.yml")); FileConfiguration configLoad = config.getFileConfiguration(); - + if (skyblock.getUpgradeManager() == null) { messageManager.sendMessage(player, configLoad.getString("Command.Island.Admin.Upgrade.Disabled.Message")); soundManager.playSound(player, Sounds.ANVIL_LAND.bukkitSound(), 1.0F, 1.0F); diff --git a/src/main/java/com/songoda/skyblock/config/FileManager.java b/src/main/java/com/songoda/skyblock/config/FileManager.java index 5729aac4..0ddf9abe 100644 --- a/src/main/java/com/songoda/skyblock/config/FileManager.java +++ b/src/main/java/com/songoda/skyblock/config/FileManager.java @@ -5,15 +5,16 @@ import com.songoda.skyblock.SkyBlock; import com.songoda.skyblock.island.IslandWorld; import org.bukkit.Bukkit; import org.bukkit.Location; +import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; import java.io.*; -import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; +import java.util.Map.Entry; import java.util.logging.Level; public class FileManager { @@ -31,13 +32,18 @@ public class FileManager { if (!skyblock.getDataFolder().exists()) { skyblock.getDataFolder().mkdir(); } + + File structureDirectory = new File(skyblock.getDataFolder().toString() + "/structures"); - if (!new File(skyblock.getDataFolder().toString() + "/structures").exists()) { - new File(skyblock.getDataFolder().toString() + "/structures").mkdir(); + if (!structureDirectory.exists()) { + structureDirectory.mkdir(); } + + // Will remain null unless WorldEdit is present. + File schematicsDirectory = null; - if (Bukkit.getPluginManager().isPluginEnabled("WorldEdit") && !new File(skyblock.getDataFolder().toString() + "/schematics").exists()) { - new File(skyblock.getDataFolder().toString() + "/schematics").mkdir(); + if (Bukkit.getPluginManager().isPluginEnabled("WorldEdit") && !(schematicsDirectory = new File(skyblock.getDataFolder().toString() + "/schematics")).exists()) { + schematicsDirectory.mkdir(); } Map configFiles = new LinkedHashMap<>(); @@ -53,19 +59,40 @@ public class FileManager { configFiles.put("structures.yml", new File(skyblock.getDataFolder(), "structures.yml")); configFiles.put("structures/default.structure", new File(skyblock.getDataFolder().toString() + "/structures", "default.structure")); + + File oldStructureFile = new File(skyblock.getDataFolder().toString() + "/structures", "default.structure"); + oldStructureFile.delete(); - for (String configFileList : configFiles.keySet()) { - File configFile = configFiles.get(configFileList); + for (Entry configEntry : configFiles.entrySet()) { + + String fileName = configEntry.getKey(); + File configFile = configEntry.getValue(); + + if (fileName.equals("structures/default.structure")) { + configFile.delete(); + try { + configFile.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + try (InputStream is = skyblock.getResource(fileName); + OutputStream os = new FileOutputStream(configFile)) { + ByteStreams.copy(is, os); + } catch (IOException e) { + e.printStackTrace(); + } + continue; + } if (configFile.exists()) { - if (configFileList.equals("config.yml") || configFileList.equals("language.yml") - || configFileList.equals("settings.yml")) { + if (fileName.equals("config.yml") || fileName.equals("language.yml") + || fileName.equals("settings.yml")) { FileChecker fileChecker; - if (configFileList.equals("config.yml")) { - fileChecker = new FileChecker(skyblock, this, configFileList, true); + if (fileName.equals("config.yml")) { + fileChecker = new FileChecker(skyblock, this, fileName, true); } else { - fileChecker = new FileChecker(skyblock, this, configFileList, false); + fileChecker = new FileChecker(skyblock, this, fileName, false); } fileChecker.loadSections(); @@ -75,13 +102,13 @@ public class FileManager { } else { try { configFile.createNewFile(); - try (InputStream is = skyblock.getResource(configFileList); + try (InputStream is = skyblock.getResource(fileName); OutputStream os = new FileOutputStream(configFile)) { ByteStreams.copy(is, os); } - if (configFileList.equals("worlds.yml")) { - File mainConfigFile = new File(skyblock.getDataFolder(), "config.yml"); + if (fileName.equals("worlds.yml")) { + File mainConfigFile = configFiles.get("config.yml"); if (isFileExist(mainConfigFile)) { Config config = new Config(this, configFile); @@ -116,54 +143,46 @@ public class FileManager { } public void setLocation(Config config, String path, Location location, boolean direction) { - File configFile = config.getFile(); - FileConfiguration configLoad = config.getFileConfiguration(); - configLoad.set(path + ".world", location.getWorld().getName()); - configLoad.set(path + ".x", Double.valueOf(location.getX())); - configLoad.set(path + ".y", Double.valueOf(location.getY())); - configLoad.set(path + ".z", Double.valueOf(location.getZ())); + final ConfigurationSection section = config.getFileConfiguration().createSection(path); + + section.set("world", location.getWorld().getName()); + section.set("x", Double.valueOf(location.getX())); + section.set("y", Double.valueOf(location.getY())); + section.set("z", Double.valueOf(location.getZ())); if (direction) { - configLoad.set(path + ".yaw", Float.valueOf(location.getYaw())); - configLoad.set(path + ".pitch", Float.valueOf(location.getPitch())); + section.set("yaw", Float.valueOf(location.getYaw())); + section.set("pitch", Float.valueOf(location.getPitch())); } try { - configLoad.save(configFile); + config.getFileConfiguration().save(config.getFile()); } catch (IOException ex) { ex.printStackTrace(); } } public Location getLocation(Config config, String path, boolean direction) { - Location location = null; - FileConfiguration configLoad = config.getFileConfiguration(); + ConfigurationSection section = config.getFileConfiguration().getConfigurationSection(path); - if (configLoad.contains(path)) { - String world = configLoad.getString(path + ".world"); + if (section == null) return null; - double x = configLoad.getDouble(path + ".x"); - double y = configLoad.getDouble(path + ".y"); - double z = configLoad.getDouble(path + ".z"); - double yaw = 0.0D; - double pitch = 0.0D; + String world = section.getString("world"); + double x = section.getDouble("x"); + double y = section.getDouble("y"); + double z = section.getDouble("z"); - if (configLoad.contains(path + ".yaw")) { - yaw = configLoad.getDouble(path + ".yaw"); - pitch = configLoad.getDouble(path + ".pitch"); - } + double yaw = 0.0D; + double pitch = 0.0D; - location = new org.bukkit.Location(Bukkit.getWorld(world), x, y, z); - - if (direction) { - location.setYaw((float) yaw); - location.setPitch((float) pitch); - } + if (direction) { + yaw = section.getDouble("yaw"); + pitch = section.getDouble("pitch"); } - return location; + return new org.bukkit.Location(Bukkit.getWorld(world), x, y, z, (short) yaw, (short) pitch); } public boolean isFileExist(File configPath) { @@ -181,9 +200,10 @@ public class FileManager { } public Config getConfig(File configPath) { - if (loadedConfigs.containsKey(configPath.getPath())) { - return loadedConfigs.get(configPath.getPath()); - } + + Config cached = loadedConfigs.get(configPath.getPath()); + + if (cached != null) return cached; Config config = new Config(this, configPath); loadedConfigs.put(configPath.getPath(), config); diff --git a/src/main/java/com/songoda/skyblock/island/IslandManager.java b/src/main/java/com/songoda/skyblock/island/IslandManager.java index 36d6c187..89765bc8 100644 --- a/src/main/java/com/songoda/skyblock/island/IslandManager.java +++ b/src/main/java/com/songoda/skyblock/island/IslandManager.java @@ -1276,7 +1276,7 @@ public class IslandManager { FileConfiguration configLoad = config.getFileConfiguration(); boolean coopPlayers = island.getSetting(IslandRole.Operator, "CoopPlayers").getStatus(); - + for (Player all : Bukkit.getOnlinePlayers()) { if (uuid != null && all.getUniqueId().equals(uuid)) { continue; @@ -1367,9 +1367,7 @@ public class IslandManager { public List getCoopIslands(Player player) { List islands = new ArrayList<>(); - for (UUID islandList : getIslands().keySet()) { - Island island = getIslands().get(islandList); - + for (Island island : getIslands().values()) { if (island.getCoopPlayers().containsKey(player.getUniqueId())) { islands.add(island); } @@ -1379,9 +1377,7 @@ public class IslandManager { } public Island getIslandAtLocation(org.bukkit.Location location) { - for (UUID islandList : getIslands().keySet()) { - Island island = getIslands().get(islandList); - + for (Island island : getIslands().values()) { if (isLocationAtIsland(island, location)) { return island; } diff --git a/src/main/java/com/songoda/skyblock/listeners/Block.java b/src/main/java/com/songoda/skyblock/listeners/Block.java index 9919e0ed..0b19c20f 100644 --- a/src/main/java/com/songoda/skyblock/listeners/Block.java +++ b/src/main/java/com/songoda/skyblock/listeners/Block.java @@ -99,7 +99,7 @@ public class Block implements Listener { int droppedAmount = 0; if (event.getPlayer().isSneaking()) { - Location dropLoc = event.getBlock().getLocation().clone().add(0.5, 0.5, 0.5); + Location dropLoc = event.getBlock().getLocation().add(0.5, 0.5, 0.5); int count = stackable.getSize(); droppedAmount = count; while (count > 64) { @@ -110,7 +110,7 @@ public class Block implements Listener { block.setType(Material.AIR); stackable.setSize(0); } else { - block.getWorld().dropItemNaturally(block.getLocation().clone().add(.5, 1, .5), new ItemStack(material, 1, data)); + block.getWorld().dropItemNaturally(block.getLocation().add(.5, 1, .5), new ItemStack(material, 1, data)); stackable.takeOne(); droppedAmount = 1; } diff --git a/src/main/java/com/songoda/skyblock/listeners/Grow.java b/src/main/java/com/songoda/skyblock/listeners/Grow.java index c531e39f..22bbc4c9 100644 --- a/src/main/java/com/songoda/skyblock/listeners/Grow.java +++ b/src/main/java/com/songoda/skyblock/listeners/Grow.java @@ -2,6 +2,7 @@ package com.songoda.skyblock.listeners; import java.io.File; import java.lang.reflect.InvocationTargetException; +import java.util.Iterator; import java.util.List; import org.bukkit.Material; @@ -46,19 +47,20 @@ public class Grow implements Listener { IslandManager islandManager = skyblock.getIslandManager(); Island origin = islandManager.getIslandAtLocation(event.getLocation()); - for (BlockState state : event.getBlocks()) { + for (Iterator it = event.getBlocks().iterator(); it.hasNext();) { + BlockState state = it.next(); Island growingTo = islandManager.getIslandAtLocation(state.getLocation()); // This block is ok to continue as it's not related to Skyblock islands. if (origin == null && growingTo == null) continue; // A block from the structure is outside/inside that it's not suppose to. if (origin == null || growingTo == null) { - event.getBlocks().remove(state); + it.remove(); continue; } // The structure is growing from one island to another. if (!origin.getIslandUUID().equals(growingTo.getIslandUUID())) { - event.getBlocks().remove(state); + it.remove(); continue; } } diff --git a/src/main/java/com/songoda/skyblock/menus/Coop.java b/src/main/java/com/songoda/skyblock/menus/Coop.java index 1f0cf999..60da1401 100644 --- a/src/main/java/com/songoda/skyblock/menus/Coop.java +++ b/src/main/java/com/songoda/skyblock/menus/Coop.java @@ -162,7 +162,13 @@ public class Coop { if ((island.hasRole(IslandRole.Operator, player.getUniqueId()) && island.getSetting(IslandRole.Operator, "CoopPlayers").getStatus()) || island.hasRole(IslandRole.Owner, player.getUniqueId())) { + String playerName = ChatColor.stripColor(is.getItemMeta().getDisplayName()); + + int space = playerName.indexOf(" "); + + if(space != -1) playerName = playerName.substring(0, space); + Bukkit.getServer().dispatchCommand(player, "island coop " + playerName); Bukkit.getServer().getScheduler().runTaskLater(skyblock, @@ -184,10 +190,7 @@ public class Coop { Island island = islandManager.getIsland(player); Map coopPlayers = island.getCoopPlayers(); - for (UUID uuid : coopPlayers.keySet()) - if (!Bukkit.getOfflinePlayer(uuid).hasPlayedBefore()) - coopPlayers.remove(uuid); - + int playerMenuPage = playerData.getPage(), nextEndIndex = coopPlayers.size() - playerMenuPage * 36; nInv.addItem(nInv.createItem(Materials.OAK_FENCE_GATE.parseItem(), diff --git a/src/main/java/com/songoda/skyblock/menus/Upgrade.java b/src/main/java/com/songoda/skyblock/menus/Upgrade.java index a12c01f9..8fda10de 100644 --- a/src/main/java/com/songoda/skyblock/menus/Upgrade.java +++ b/src/main/java/com/songoda/skyblock/menus/Upgrade.java @@ -379,6 +379,7 @@ public class Upgrade { economyManager.withdraw(player, upgrade.getCost()); island.setSize(upgrade.getValue()); + islandManager.updateBorder(island); Bukkit.getServer().getPluginManager().callEvent(new IslandUpgradeEvent( island.getAPIWrapper(), player, APIUtil.fromImplementation( diff --git a/src/main/java/com/songoda/skyblock/utils/structure/StructureUtil.java b/src/main/java/com/songoda/skyblock/utils/structure/StructureUtil.java index d1daaf8a..eac82b58 100644 --- a/src/main/java/com/songoda/skyblock/utils/structure/StructureUtil.java +++ b/src/main/java/com/songoda/skyblock/utils/structure/StructureUtil.java @@ -1,6 +1,8 @@ package com.songoda.skyblock.utils.structure; +import com.google.common.io.Files; import com.google.gson.Gson; +import com.google.gson.JsonSyntaxException; import com.google.gson.reflect.TypeToken; import com.songoda.skyblock.SkyBlock; import com.songoda.skyblock.config.FileManager; @@ -32,203 +34,221 @@ import java.util.ArrayList; import java.util.Base64; import java.util.LinkedHashMap; import java.util.List; +import java.util.logging.Level; public final class StructureUtil { - public static void saveStructure(File configFile, org.bukkit.Location originLocation, - org.bukkit.Location[] positions) throws Exception { - if (!configFile.exists()) { - configFile.createNewFile(); - } + public static void saveStructure(File configFile, org.bukkit.Location originLocation, + org.bukkit.Location[] positions) throws Exception { + if (!configFile.exists()) { + configFile.createNewFile(); + } - LinkedHashMap blocks = SelectionLocation.getBlocks(originLocation, positions[0], positions[1]); - LinkedHashMap entities = SelectionLocation.getEntities(originLocation, positions[0], - positions[1]); + LinkedHashMap blocks = SelectionLocation.getBlocks(originLocation, positions[0], positions[1]); + LinkedHashMap entities = SelectionLocation.getEntities(originLocation, positions[0], + positions[1]); - List blockData = new ArrayList<>(); - List entityData = new ArrayList<>(); + List blockData = new ArrayList<>(); + List entityData = new ArrayList<>(); - String originBlockLocation = ""; + String originBlockLocation = ""; - for (Block blockList : blocks.keySet()) { - Location location = blocks.get(blockList); + for (Block blockList : blocks.keySet()) { + Location location = blocks.get(blockList); - if (location.isOriginLocation()) { - originBlockLocation = location.getX() + ":" + location.getY() + ":" + location.getZ() + ":" - + positions[0].getWorld().getName(); + if (location.isOriginLocation()) { + originBlockLocation = location.getX() + ":" + location.getY() + ":" + location.getZ() + ":" + + positions[0].getWorld().getName(); - if (blockList.getType() == Material.AIR) { - blockData.add(BlockUtil.convertBlockToBlockData(blockList, location.getX(), location.getY(), - location.getZ())); - } - } + if (blockList.getType() == Material.AIR) { + blockData.add(BlockUtil.convertBlockToBlockData(blockList, location.getX(), location.getY(), + location.getZ())); + } + } - if (blockList.getType() == Material.AIR) { - continue; - } + if (blockList.getType() == Material.AIR) { + continue; + } - blockData.add( - BlockUtil.convertBlockToBlockData(blockList, location.getX(), location.getY(), location.getZ())); - } + blockData.add( + BlockUtil.convertBlockToBlockData(blockList, location.getX(), location.getY(), location.getZ())); + } - for (Entity entityList : entities.keySet()) { - if (entityList.getType() == EntityType.PLAYER) { - continue; - } + for (Entity entityList : entities.keySet()) { + if (entityList.getType() == EntityType.PLAYER) { + continue; + } - Location location = entities.get(entityList); - entityData.add(EntityUtil.convertEntityToEntityData(entityList, location.getX(), location.getY(), - location.getZ())); - } + Location location = entities.get(entityList); + entityData.add(EntityUtil.convertEntityToEntityData(entityList, location.getX(), location.getY(), + location.getZ())); + } - if (!originBlockLocation.isEmpty()) { - originBlockLocation = originBlockLocation + ":" + originLocation.getYaw() + ":" + originLocation.getPitch(); - } + if (!originBlockLocation.isEmpty()) { + originBlockLocation = originBlockLocation + ":" + originLocation.getYaw() + ":" + originLocation.getPitch(); + } - String JSONString = new Gson().toJson(new Storage(new Gson().toJson(blockData), new Gson().toJson(entityData), - originBlockLocation, System.currentTimeMillis(), NMSUtil.getVersionNumber()), Storage.class); + String JSONString = new Gson().toJson(new Storage(new Gson().toJson(blockData), new Gson().toJson(entityData), + originBlockLocation, System.currentTimeMillis(), NMSUtil.getVersionNumber()), Storage.class); - FileOutputStream fileOutputStream = new FileOutputStream(configFile, false); - fileOutputStream.write(Base64.getEncoder().encode(JSONString.getBytes(StandardCharsets.UTF_8))); - fileOutputStream.flush(); - fileOutputStream.close(); - } + FileOutputStream fileOutputStream = new FileOutputStream(configFile, false); + fileOutputStream.write(Base64.getEncoder().encode(JSONString.getBytes(StandardCharsets.UTF_8))); + fileOutputStream.flush(); + fileOutputStream.close(); + } - public static Structure loadStructure(File configFile) throws IOException { - if (!configFile.exists()) - return null; + private static String getBase64String(File file) { + if (!file.exists()) return null; - byte[] content = new byte[(int) configFile.length()]; + String firstLine = null; - FileInputStream fileInputStream = new FileInputStream(configFile); - fileInputStream.read(content); - fileInputStream.close(); + try { + firstLine = Files.asCharSource(file, StandardCharsets.UTF_8).readFirstLine(); + } catch (IOException e) { + e.printStackTrace(); + } - String json; - try { - json = Compression.decompress(content); - } catch (Exception e) { - Bukkit.getConsoleSender().sendMessage("Could not load structure '" + configFile.getName() + "' Try using the '/is admin structure tool' command to make a new schematic of it."); - File defaultStructure = new File(SkyBlock.getInstance().getDataFolder() + "/" + "structures", "default.structure"); - content = new byte[(int) defaultStructure.length()]; - fileInputStream = new FileInputStream(defaultStructure); - fileInputStream.read(content); - fileInputStream.close(); - json = Compression.decompress(content); - } + return firstLine; + } - Storage storage = new Gson().fromJson(json, Storage.class); - return new Structure(storage, configFile.getName()); - } + public static Structure loadStructure(File configFile) throws IOException { + String base64 = getBase64String(configFile); - @SuppressWarnings("unchecked") - public static Float[] pasteStructure(Structure structure, org.bukkit.Location location, BlockDegreesType type) { - Storage storage = structure.getStructureStorage(); + if (base64 == null) { + base64 = getBase64String( + new File(SkyBlock.getInstance().getDataFolder() + "/" + "structures", "default.structure")); + SkyBlock.getInstance().getLogger().log(Level.SEVERE, + "Unable to load structure '" + configFile.getAbsolutePath() + "' using default instead."); + } - String[] originLocationPositions = null; + if (base64 == null) { + throw new IllegalArgumentException("Couldn't load the default structure file."); + } - if (!storage.getOriginLocation().isEmpty()) { - originLocationPositions = storage.getOriginLocation().split(":"); - } + Storage storage; - float yaw = 0.0F, pitch = 0.0F; + try { + storage = new Gson().fromJson( + new String(Base64.getDecoder().decode(base64.getBytes(StandardCharsets.UTF_8))), Storage.class); + } catch (JsonSyntaxException e) { + e.printStackTrace(); + return null; + } - if (originLocationPositions.length == 6) { - yaw = Float.valueOf(originLocationPositions[4]); - pitch = Float.valueOf(originLocationPositions[5]); - } + return new Structure(storage, configFile.getName()); + } - List blockData = new Gson().fromJson(storage.getBlocks(), - new TypeToken>() { - }.getType()); + @SuppressWarnings("unchecked") + public static Float[] pasteStructure(Structure structure, org.bukkit.Location location, BlockDegreesType type) { + Storage storage = structure.getStructureStorage(); - for (BlockData blockDataList : blockData) { - Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(SkyBlock.getInstance(), () -> { - try { - org.bukkit.Location blockRotationLocation = LocationUtil - .rotateLocation(new org.bukkit.Location(location.getWorld(), blockDataList.getX(), - blockDataList.getY(), blockDataList.getZ()), type); - org.bukkit.Location blockLocation = new org.bukkit.Location(location.getWorld(), - location.getX() - Math.abs(Integer.valueOf(storage.getOriginLocation().split(":")[0])), - location.getY() - Integer.valueOf(storage.getOriginLocation().split(":")[1]), - location.getZ() + Math.abs(Integer.valueOf(storage.getOriginLocation().split(":")[2]))); - blockLocation.add(blockRotationLocation); - BlockUtil.convertBlockDataToBlock(blockLocation.getBlock(), blockDataList); - } catch (Exception e) { - SkyBlock.getInstance().getLogger().warning("Unable to convert BlockData to Block for type {" + blockDataList.getMaterial() + - ":" + blockDataList.getData() + "} in structure {" + structure.getStructureFile() + "}"); - } - }); - } + String[] originLocationPositions = null; - Bukkit.getScheduler().scheduleSyncDelayedTask(SkyBlock.getInstance(), () -> { - for (EntityData entityDataList : (List) new Gson().fromJson(storage.getEntities(), - new TypeToken>() { - }.getType())) { - Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(SkyBlock.getInstance(), () -> { - try { - org.bukkit.Location blockRotationLocation = LocationUtil - .rotateLocation(new org.bukkit.Location(location.getWorld(), entityDataList.getX(), - entityDataList.getY(), entityDataList.getZ()), type); - org.bukkit.Location blockLocation = new org.bukkit.Location(location.getWorld(), - location.getX() - Math.abs(Integer.valueOf(storage.getOriginLocation().split(":")[0])), - location.getY() - Integer.valueOf(storage.getOriginLocation().split(":")[1]), - location.getZ() + Math.abs(Integer.valueOf(storage.getOriginLocation().split(":")[2]))); - blockLocation.add(blockRotationLocation); - EntityUtil.convertEntityDataToEntity(entityDataList, blockLocation, type); - } catch (Exception e) { - SkyBlock.getInstance().getLogger().warning("Unable to convert EntityData to Entity for type {" + entityDataList.getEntityType() + - "} in structure {" + structure.getStructureFile() + "}"); - } - }); - } - }, 60L); + if (!storage.getOriginLocation().isEmpty()) { + originLocationPositions = storage.getOriginLocation().split(":"); + } - return new Float[]{yaw, pitch}; - } + float yaw = 0.0F, pitch = 0.0F; - public static ItemStack getTool() throws Exception { - SkyBlock skyblock = SkyBlock.getInstance(); + if (originLocationPositions.length == 6) { + yaw = Float.valueOf(originLocationPositions[4]); + pitch = Float.valueOf(originLocationPositions[5]); + } - FileManager fileManager = skyblock.getFileManager(); + List blockData = new Gson().fromJson(storage.getBlocks(), new TypeToken>() { + }.getType()); - FileManager.Config config = fileManager.getConfig(new File(skyblock.getDataFolder(), "language.yml")); - FileConfiguration configLoad = config.getFileConfiguration(); + for (BlockData blockDataList : blockData) { + Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(SkyBlock.getInstance(), () -> { + try { + org.bukkit.Location blockRotationLocation = LocationUtil + .rotateLocation(new org.bukkit.Location(location.getWorld(), blockDataList.getX(), + blockDataList.getY(), blockDataList.getZ()), type); + org.bukkit.Location blockLocation = new org.bukkit.Location(location.getWorld(), + location.getX() - Math.abs(Integer.valueOf(storage.getOriginLocation().split(":")[0])), + location.getY() - Integer.valueOf(storage.getOriginLocation().split(":")[1]), + location.getZ() + Math.abs(Integer.valueOf(storage.getOriginLocation().split(":")[2]))); + blockLocation.add(blockRotationLocation); + BlockUtil.convertBlockDataToBlock(blockLocation.getBlock(), blockDataList); + } catch (Exception e) { + SkyBlock.getInstance().getLogger() + .warning("Unable to convert BlockData to Block for type {" + blockDataList.getMaterial() + + ":" + blockDataList.getData() + "} in structure {" + structure.getStructureFile() + + "}"); + } + }); + } - ItemStack is = new ItemStack( - Material.valueOf(fileManager.getConfig(new File(skyblock.getDataFolder(), "config.yml")) - .getFileConfiguration().getString("Island.Admin.Structure.Selector"))); - ItemMeta im = is.getItemMeta(); - im.setDisplayName(ChatColor.translateAlternateColorCodes('&', - configLoad.getString("Island.Structure.Tool.Item.Displayname"))); + Bukkit.getScheduler().scheduleSyncDelayedTask(SkyBlock.getInstance(), () -> { + for (EntityData entityDataList : (List) new Gson().fromJson(storage.getEntities(), + new TypeToken>() { + }.getType())) { + Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(SkyBlock.getInstance(), () -> { + try { + org.bukkit.Location blockRotationLocation = LocationUtil + .rotateLocation(new org.bukkit.Location(location.getWorld(), entityDataList.getX(), + entityDataList.getY(), entityDataList.getZ()), type); + org.bukkit.Location blockLocation = new org.bukkit.Location(location.getWorld(), + location.getX() - Math.abs(Integer.valueOf(storage.getOriginLocation().split(":")[0])), + location.getY() - Integer.valueOf(storage.getOriginLocation().split(":")[1]), + location.getZ() + Math.abs(Integer.valueOf(storage.getOriginLocation().split(":")[2]))); + blockLocation.add(blockRotationLocation); + EntityUtil.convertEntityDataToEntity(entityDataList, blockLocation, type); + } catch (Exception e) { + SkyBlock.getInstance().getLogger() + .warning("Unable to convert EntityData to Entity for type {" + + entityDataList.getEntityType() + "} in structure {" + + structure.getStructureFile() + "}"); + } + }); + } + }, 60L); - List itemLore = new ArrayList<>(); + return new Float[] { yaw, pitch }; + } - for (String itemLoreList : configLoad.getStringList("Island.Structure.Tool.Item.Lore")) { - itemLore.add(ChatColor.translateAlternateColorCodes('&', itemLoreList)); - } + public static ItemStack getTool() throws Exception { + SkyBlock skyblock = SkyBlock.getInstance(); - im.setLore(itemLore); - is.setItemMeta(im); + FileManager fileManager = skyblock.getFileManager(); - return is; - } + FileManager.Config config = fileManager.getConfig(new File(skyblock.getDataFolder(), "language.yml")); + FileConfiguration configLoad = config.getFileConfiguration(); - public static org.bukkit.Location[] getFixedLocations(org.bukkit.Location location1, - org.bukkit.Location location2) { - org.bukkit.Location location1Fixed = location1.clone(); - org.bukkit.Location location2Fixed = location2.clone(); + ItemStack is = new ItemStack( + Material.valueOf(fileManager.getConfig(new File(skyblock.getDataFolder(), "config.yml")) + .getFileConfiguration().getString("Island.Admin.Structure.Selector"))); + ItemMeta im = is.getItemMeta(); + im.setDisplayName(ChatColor.translateAlternateColorCodes('&', + configLoad.getString("Island.Structure.Tool.Item.Displayname"))); - if (location1.getX() > location2.getX()) { - location1Fixed.setX(location2.getX()); - location2Fixed.setX(location1.getX()); - } + List itemLore = new ArrayList<>(); - if (location1.getZ() < location2.getZ()) { - location1Fixed.setZ(location2.getZ()); - location2Fixed.setZ(location1.getZ()); - } + for (String itemLoreList : configLoad.getStringList("Island.Structure.Tool.Item.Lore")) { + itemLore.add(ChatColor.translateAlternateColorCodes('&', itemLoreList)); + } - return new org.bukkit.Location[]{location1Fixed, location2Fixed}; - } + im.setLore(itemLore); + is.setItemMeta(im); + + return is; + } + + public static org.bukkit.Location[] getFixedLocations(org.bukkit.Location location1, + org.bukkit.Location location2) { + org.bukkit.Location location1Fixed = location1.clone(); + org.bukkit.Location location2Fixed = location2.clone(); + + if (location1.getX() > location2.getX()) { + location1Fixed.setX(location2.getX()); + location2Fixed.setX(location1.getX()); + } + + if (location1.getZ() < location2.getZ()) { + location1Fixed.setZ(location2.getZ()); + location2Fixed.setZ(location1.getZ()); + } + + return new org.bukkit.Location[] { location1Fixed, location2Fixed }; + } } diff --git a/src/main/resources/structures/default.structure b/src/main/resources/structures/default.structure index fc2652e3780ef49ab6a1655bed75ba65f1e60298..c4836d5467b29b23889b49c7a22306b4056e0361 100644 GIT binary patch literal 153500 zcmeHQU3a3&w*5gZO*hZT5 zWRG+uV29N-$oQdvnLtO&q_)@oRj)eB=97;9J>D>usZsA@9?A#lf(Tm9NBC9WU9Po z|2Y|D&(WIYVb0P-ukPO+^^}Fz+uL54<2jV-n%na3bKh}?Ot*D;eva`ybs6P&K0Ysa z_B)IbXuTcgY#$D*xp8uRS3i?{mMkjlO)}2v`~1Q%&-~obUv83N`5b7vxCc2`a;`%> zTav}N4xeXt&4#{Whqm*0kmDYrk=|W+-9nycF=iPvwKtqIYv3!^WX_D4JodEklD#v+ zTKQOmbQAe=tY=|hPO#o?xC}HV@2~p>>peN2*J0ae*y}_&JId=!qmG>}aR2-nVr{2J zqtd!+P-NONR>o>>fYU^p>xGmtV{J z%Ykam8*Q~}Ady0=+onxqR z-hDL=)>zxU{H*9Nld+xQ*b_h3Qx$%H+5Jez92q+611c_rP_Y`r~4zR1d_M!rbyZ-f8roqdtRvoBKUh<}VP zl5j*gx~5P6D~_5z{r3A82}gvZ-vCFg_Zbq72uB}}qxSm&2}gvZ-vCFg_w5mm2uHsG zj#}@pqnszoGvqmZzhj$+-ispAHHmOElDYtM(@Hcs=){ z_&h9F77fb`HP^^ztm~h7?XoWFtgCwHx(2yACn(r4%3h9xTKDJ0tFdF$k0&D>TQus* zb9NK(TKW;&hJOE9Z~~+oCB}U`%*(%!x4Gl>|8brzMZGrO&yJ$s`AVtJSg5!W9kG z_z=GReSjM7(5?6h%x%ZP%{PPr<#g!(6Q8^<*vnIdAy0;C)cK%W9u|N+H8cqRdWqY9o2B>=ko*?!Iwnqo_Q0T zyr%@(vU-NXdP=-<%No2Be62l~&E<1!q5>QOg^fKc_!|DgentEO`wM#r>%lQqRym9q z6MqZd0?uoY4h7ck@odwTBKQmlkN?2qk?<(;)(MZ?F1sEcPb42nK9YR=ZRF#T@OTlA z3du*3k5|%HE8Ug!Rk9z+er)#%l;gak5%0>*^lpUKQ{45`s!sos-&-y zzIr8nRbY_(t8d0TNIsH$yjHxUiAT~`Nj_5ivEuRiDEqOA$JXnshzrk|jO%_c4K7@RnOzc*33mLO5_QO9Edl*Ho2f6WyBGF1Y^X`RD!u z7>i#|#;MQo{aKYGF%2XiK4SLrSvco@rU?FfexFLum*;}JK2sd@eL!A?jA=LG{}?aP z&RqX<#7rJ+J=3RYzZ$pbZv#K$9Q;+Rf2}fC$&Vrpo{RT?V8fSjdZ&}1UqRj9p^IJx)}wre(}MRU&>J}ye63lg zyLeW94O~;>xeVau7r6}g9l_hLVLbFg=Gogq~e1BGXo^A~OrqdD`Yx@**+DRyW(j|VyKf%66Py(!n*V$3qY-8!5z3-w>tWX_D4 zJQg)p$=(@(@6~Vc0{@nM;Kcfi8nJ1k4_y0ub@cjkwP)I{?%7P@Apc(6uD4vMy=~~} zsFSlI)Kzls<9(p9GjB5H&`f(m>%b@!0zQaqoo3IpLA;czryQzWNP)mE{0-}Ol8Vk7Pey%YJO;1CT%GqI@L#vC8Wq`%&c4yeBX7OZiCtoXdEm z_#?^3Ysp8ETS@sjZ{^F8d?fjJrM?BFh&k5&Rr2Rtl#i6ZN_hMTJd!`>vOkC9BjNEw z@JRlgi}De9_7v}+c*k|(9S!?YWG_pZiJ(X$CK*usUH7d+4*|J|g?*W9%alGph69Ngk0r zB6;*f^5_MQNFEW62uDAUBl6b~jtECTjU)2ck-v`obwB2>YwC6F=PM>Z1Nj*~-p|nf zIwryq;poG0bl^EiL1AQxhB_V9-b5bz+UKxfSu`v&IgB3qM=eF0Y`U_!O)jbCv zt9T%Q1 z;t{aH`tx(0wDC6AORjIYy(Hc-WS>b}ljk#Jim2n`cBIntCH~OII8&TaFU2}>8?owD zEaxwTEu3iQI^4PK+7Gs#>C?0?ZKpopBfKB8>~X9zSIGvxf|#dbJRp!_rh=P&lf)Yd(6l55Af$>J#<$+^B{c(N7iHLTZ*TJ%Rs~o%Q$gv52j|rw`eGf z&!r-`4D?bp2e+qiZ1H`t4d-R2irtmZp_XK!em*ZpFYHsuRJkXOf5pS}^4`gJ^2cHm za>C^D0GL~xu-^tl{M;(BH&O6gi{R7_a+XG;<=z_gR#wi6WDstm&IJ2#b}&bJ5yQ_F zjcz*ALBHT*aamx>SYg2TF#mjTdkhC`gWqb9+iT0a(E_grnPaMpG`s$cZm6kgGSJJ=TkfOOevZ?>4;Ib|yyO@n4jKUx7DtyBOUlkv4%2k|@@xuV76w(<^ri-`F58VZHFwWjwI{^UpQDy{XsO z;_qqvn0&smzWjPqZ?~J`_d>I`3r#)6qsb|BvLZtMf$8g6IM#Qe*IO+-ywgU?kZy(j7OU%>y$lOCmZ+QUC00STHnTo zg7^IeY&@QV6MKx(CD!Tjt+g*}EMHoaFu%Aa>D0gFSX==QZ(wa$R{LsF^7S9-X?!ofeph_mN2XKb*yUpa-x%KsH!=Tx z(s$sxJ@PdT$G4hU^#8Ls#ofrM#tjGh26*1b=@RcK>;u2g-(zn*hs5?Je7HFO0zUE{ zo=eXbqpcSB7Vu%M`E$h`<0*9X9o_+od2-)e7fbH13-3d1aru3i;(b_P%}evdFsI=z z!n@4UEJfgIY`lq0)8Y9>{9UuK6??!_70!7Jom@{7o#$V%1J||qK2OGm8v4ri9`B#X)45Hxfj(8u>AKgSt3A_E zpodr2|Bi0gTQ1Zdj!B}xUv6Sdztruzbu1|$+eywP*-oL?Rj?05F5rDf>`@K-?*x5l z&-bS3%=o^&5r2P;5jSn8*2lISMZfcv@{0}pRlWt0Q}E3=air-_K4Q0_x?94=KAm$h z##w@S;`0TaqgVN1ptHEcvOjmbj{NR~z6DCi>~1`g@6C1hi@R3)j?`x>f6TYP4|4q! zx_IZnzrxoA*Q;X5=_ZQvWMz(*BN;!g?+5Ri7jfe1-IDd6;X8Pa)+~o!%HK=;o+5L8 z_}f+cI(!24`SAZ#`4;ke5GftZy%52yYusTg4gd$qQS2r^-qWAC~7bB5!pC9 z)cJ~htv#2`<#TMJ0`^J)8=w$eQ-2``7P2YK;sQ3c@X0)uRc#5zOdkc7gfAzJ`98wh zPCnf^f-k+zKE5wAclY27dt*5-t7^XpTfbW4T;=PN#<`v+gUxf`?H+JU;b}Vdi52@} zuCH0^`ycc%@H|q-)lGT*HO~QQuG_2cSJ1t(Dknqk!F7c<_&JZEHaXl6tNaW*lRl5) zHI^!S#eJ2xQC)Le-hJ*n?vP<$*FKXomgJtV@PoW-=%o5S99F(jCx=ZVb$a#OJ_Mqd52PW`E_}RU9Njce|+on z4oRmZos#Qr(BXa~opSvL>XfX{)~vRz{!6`*E#Y@Qc^Z0I!3KzO=>K)BYcSlx2I75- zV5h-9@QY$xuk=gOKl5;lI)<}d<*wNfvE|Tq9%XF7IPe-pp3@+4WHDwLukzeG6OL<#Eo2t)1DE^LZV_V}>77!#NfA$YV;6 zyY_Pmyp#U9BK?!cz2tr+{gdOh@>5AW8MPTK(_PFF*B|k|K%DW1e43^3<=1h8)^oSL z6CTMP6me+6`_*xN!N_~2_~Vu0k4-%CzjK4~b6)vZ$$lg} zCLf@$Qhv^5`AB#qJYEftf+MP`X%xIRBp?47e8sb0j}1JM{YdhW>__V<@ye~! zNx&6Qb9;5c6L2N_v5Cjl+mF=$ocf<%lRHCjkyd@nn|>IMsaETmgd@Vy2jQq8kJ@jq z5snB)ACIH<+gXGo!qIPlBeIVKUxPE$4JVVFzJ;am9$as5R};73|17uQSNllla(_%- zCCMX_M;{}PUf`(p`H+Mo!qLa$i0q?^hl}(&(Gw@0tgSCh_Fh8&=uI-@{g-sXT_!op zWIv1lRnF+kdR_bLNl6}&Jo*jfQS0kKllhEUj;|Q#6KUPax{UAjLO?HN{S>Rc>Ns_G zit=9Po}K$e{!~wI>UU7}PXq@e$*#{;e@VgDRr@4b@7p8HC9>{>dffePJw_V(VuOFA z{d{?ZIl>(03-}%T`g{X(t@jxc<_L4`!d(0Pi-bACT+1*=_FTFkAByO~cIG9Zp5>X0 zU(68e32j#Ug0emOkM5IE?(P#9UFq1UWxZz7NPm3$F}kR5`4txbAo~$ zqwM84cz-@GUX2~2k1hHUAETnt-!^AA0s1`SiCSg5-)<{IQY-ntv&*rj}5?a)Uv3p&O!EM}h~O@H#WG7HdaC{}mt zg^wIWubYPFSi!8k8~3xguy{Y^EW&-%T+3muZ)1%m7?<}WLVwQQE(CuK=c{ptWq)y@0PFe|>-9`W9s<-F5`^8#N>$dE&9HGh*n^44GfcOvtXl=XpRjPi=#h(ACD8lBjGV!NIfRjc4{;#o4t2`nSJ;YkHT(T5gzSjlv|mvm#R6qJ%xiI z;gRt80eCb?K590%5nthvR!@Xn%lw9FlyzC?98}uabPc z5*`Hx$)7|1)$;Ch-*Jabw{=z4Fd(+#snFf)I0^Yzxu5ZU{W(oMl0V10C?CmwBz^T- z`f3x8b4Wgt ze7u%?Y~qppIhW-l*^h+BkH91Ob1vhN#M^#Gu*m17gQ*uh69#YOMyck5%dtccbnU#kkdD< zj#%aSI)ZZ}B^*&b{@0p|kZ{C#8^9qUIQjnqe*}0I!S?`82k;~C`rNYWg|g&-H*h3; zn14!qf#gxe(}5ambq9`*HGiMuJ@GpK^K&JuyUU9Igm5I~>LvnaejZ1yj|&iv2uEKM zt((QrIXTylllPQBgX|D}yRE0hE4OT%9hzJ~p3COH7Dr?s5zi9YM?Wu*TJMJ^c|`K) zH;_lI_n(j5weGlT@3S+659q(-4-CO078tH9DZ+ zA(K9dpzSr~ggN5nY=J+$iMiJE021a1b1lPM>wSiVIl^4aFxPtjB4Lg&*D}nt-WN%j zBh0l7bL6)~e-!dtiXLxg4lwdtzN6pLY<=I@UVpCkOxx8xo1te>)gN$+eAFkq?(u-U zfQaXqde$-ULS>rwmJ7AF4Lw~8eJct_8Se?S4>Wd;6`;500ePz@-h+te?43E?N8vIW zBhM6TB6@!0$axjLnRsqe-<-MGwC;Dr`KOVW+T`Eod8yXSMb4YJPmzQC#`lP4Xsqfj zB=Z|)T5lV5ko(#(iXiRZ$UZ}(`hL)VLP5^*-uBRG2tAu*Ue)YX{~>Wr?=;*_bZch2 zY*?Rv?x~0TRUXrqc@pP5ty$H>X&QKHoog$fh4-1u6p{0a^JYrVm*-~p_}oFxHF{^r z9KS{$7sg98R`*ew+phg!>zO`H`!a{4&-->D=NI|LoXcUYGFQn4zG54$Vm-{1rQv4v zvDPNkx+d=_)$Gp^^PCX$r?PV$y`*HG$htRY!6SoJK>S!Bgw}PkdJ1i-;sQLrLRJ7Abpke)$8c1qGpHmRk9z+ zer(nme3<>%z$59am;E^;AIYC{HGfVMkEE|&^smDIMfxh~tJl$2IR?qU`ewX?K2{5t}~8v}evxH=Io7 z6BL$+A2)df9K??uS2tyRSj1f4_c=uI&zq;m@dgxVk$5otu*z15Jtj;NzBKP4PdmxCqKN0g6 zv3sd!wqLF#^BJ=oUolKavF_wPUwwx=uKnO)lr-4CtOu#STOi*v99oayO0H^H(%b5|yqAaT8haIKJtbBy z+*6S)6FmF0zQ>}!k+G#u_1Kr*zhRyoLuPMK11V}y?i^7M3crW-6f5Nh=Lnu?(=j#E z3A%jFBJ>Y{{Bux~lA&HkS%`PIsDr`tz&ElkGn|JySk&KeTcxnJyr#z0vQI)zR`awB zg>M7%hVuj8*opd~ysGsQpTVycvTCmQSYfVjV@>c6X{Zs~fOAgNLp44>;l5Bagn4L; zgU^l&S?|<1cA04UlenM8v8d(Zy%VzV)fhns>o)4`Dp?-+PPjMsZD_#SAC5fnJz zgTFo9C~?6uF|VHRd42sq*Q>q>^1KJ8tnNM=&vBj=@MC@LGqIX{nxy6@i`Pu08_WUr zL2f_5-+1Kn?spQLQ?92g1z2zomNPlv*zzuoJ7#L)f0vJoy`^S?bKZ$db8uUl=|r14 Qw;gsNGcRpt000m?~9OO36~hzKkvQWN7Kwm6l6#C5?L+nMWJr|Oxdl!1 z9eKe!QoAC0k8PU&Tw7fjWW3NA5k)YT{h->$X4JjKKbzdnu3%dV?;%0C``u?t(POHW2#1#w&Y6kCc-EORidtLEpH--)R4Sk?Op6POWl-u8xRp&1UTLa z?!xoO<$N}H^#U-knqI+uVhE z4dD%jAV89;sT5k(4SXhTu6}vZ&1!$F4Km0ie9|wiH6LYL#oUCpX()OmW?5fsXiAH5 zdg1=pv-ZKw?cRm&^^ao{l6DTC99S*?u}^kOD7>_Kw79!l;{)&Nc^v(hILNYUcyqi` z9203b79b5;D0pgrKbNLvgHa%-*{6UULO}V*EB-;CnYe+ZTd4|uD1x(MG(&%8L%=M0 zP>=VzKaheDSRbft^(LKJ9|&lW@nHmE2;Trso%}4CqT|u6*6T0J{qi;BU86gjVNbTU zkih68E=<6GQ#!V=P*6NJk#B#g7x!-Q1{tkN6{)ByTKPagxNTIkH(rf}^W(){NHASp zaAhsbWJncsu+nw~=CdnBSh`ciO{GITp$@4LXMfBsybMip=1YLK!1vSn4eRu1A@9Wn z#u^)XhqT4MqYnWzDLQ;qSl|k=G1j&vPtdGy9SWN($oaMlsWgKl3A72#sI&;Qee}zW z7wRP1p|UnQiTwYHWFkLEn9>6lh_qv>Q9NXLsv5+2s-AFFRTLv>Y96Xenf6$ac!<`6 zgG+V5q_2i^LZ}V~OFe2Cbq8z?hZ!DCvnxI)0QIWBiOdq#<*V-SE%XxmF{zLMiN5BX z^+j05^T=7lYNSWO_e~5SYz5BnUB)0(d;@X{y%N%Y?ok~TOxDS|relqk`f zG59~R-O?--YkI4rjjk1SMV@?dqkw%{j5il57p(IRJ9F7*#apkDD~vM)xTTExi8nfL z)yEbFd!NW7UV3l(VH;VlF00S9X|Gu(IhIoKQ3g>*4V7yWI?KW0(b5(}K2h_Qwn>p@y@7%~o< zrM|lRxNc6WF@Zwx!rMP`^tPwfwJX=1>vt&J*|=M)9hj`t`=6Quv}zV1>PmR{&HP)kJc0wI&0}tl4ax1Znq@PSm z!wk2?s}kG;StMNBo8!HXnqM8uO;xddQGbk*rUD{@-69%;?_FQ`y8F=%uxRvKKcmJ# zcS1~y0sWKBwxCh{4f9p0H{@-m=LbCA)Q58SU@PoxX2z;!#94nm)ccavAfqYpbhu$@ zk5Rgj=*TTniAc-T)cp8L(SG^sdx**cWfrcxt0;A>+3-xtGV4u6?Hbc9GkCpXP|3g5 zG10$e%4ZYUP>hKSv-L)yLQ2Va6`g=_2UjW>f%I$`zw8SQW%sa>Pz$3X~K&oA} zQTaRRfEfHJjlB3|Gq%8do^e%j9-!^mpfDFPP2YQ9uEp55OzeZX(0_f9wC&P?MFYia z*{4dhE!vdwe|I{1J6EVm!QFIXU&)qGPf-=mHfNrX%De_g+(pbT7qijq6~m8(s;v(2 zBX#ItqI51Rtcw#vcoZR#$MaX(v!^%GRJ)ydr{Cmub8PExZob2klL6JpTg0#?#vhJ6 zr&X4KReZmmx(wg1gst4=InPTakmtOVboX=7w4uGZtuJZsf6^z06bA4NneWZ78CM;< zRh+5A2lt{4X$RVzfTvjMO{!k(G@|uemTd~xII)X2>R6{xEB_#7^Jr$lv%-7&;=f$> z#dp#37Zwer4%a2o>1p=kpuy$tNMX$Rp98pv&SvQId=x7OT9Di~_85;1cJg~@=keXH z38e2z%OdluK&UJ|<#8y9;-+TQlP1H*#m>BI=@wgCy3m{{FO z7K~Yn_TdQ|)Z+;YyTC(iD|c}`ye|(5Zqdwy`nX-f`ZR< zNp#Aqnv}^;I>f7&-s*UzRhq31=)I2P0t=VtsbUDQRuzk5Ey?wIVgXMA@-~k+Q9uH% z`G=M$W#FBM_N(;mWq$RcOV8gs3QlTVr)$7+RE5_KvThieiAkJyc7MK^CnzuAR zd>z)nE?j0VG|WJv?!rr(a$+_@DWuQwK@$+MszdA`Ox4`EPi3=(DELw6jfRD-qg zrSPIXQha{ja{PyPIh;hb9e`k&;%*Vxf?$MBeapZnkTjM{?rvlR4!AzM