diff --git a/src/main/java/net/tylermurphy/hideAndSeek/Main.java b/src/main/java/net/tylermurphy/hideAndSeek/Main.java index 30d0233..1e78bc9 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/Main.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/Main.java @@ -1,5 +1,7 @@ package net.tylermurphy.hideAndSeek; +import static net.tylermurphy.hideAndSeek.configuration.Config.spawnWorld; + import java.io.File; import java.util.HashMap; import java.util.List; @@ -24,6 +26,7 @@ import net.tylermurphy.hideAndSeek.events.Glow; import net.tylermurphy.hideAndSeek.events.Taunt; import net.tylermurphy.hideAndSeek.events.Worldborder; import net.tylermurphy.hideAndSeek.util.Board; +import net.tylermurphy.hideAndSeek.world.WorldLoader; public class Main extends JavaPlugin implements Listener { @@ -36,6 +39,8 @@ public class Main extends JavaPlugin implements Listener { public Board board; + public WorldLoader worldLoader; + public Map playerList = new HashMap(); public String status = "Standby"; @@ -61,6 +66,9 @@ public class Main extends JavaPlugin implements Listener { Config.loadConfig(); Localization.init(); + // Create World Loader + worldLoader = new WorldLoader(spawnWorld); + // Register Commands CommandHandler.registerCommands(); diff --git a/src/main/java/net/tylermurphy/hideAndSeek/bukkit/CommandHandler.java b/src/main/java/net/tylermurphy/hideAndSeek/bukkit/CommandHandler.java index 2001df6..1efb505 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/bukkit/CommandHandler.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/bukkit/CommandHandler.java @@ -35,6 +35,7 @@ public class CommandHandler { registerCommand(new SetBorder()); registerCommand(new Reload()); registerCommand(new SaveMap()); + registerCommand(new SetBounds()); registerCommand(new Join()); registerCommand(new Leave()); } diff --git a/src/main/java/net/tylermurphy/hideAndSeek/bukkit/EventListener.java b/src/main/java/net/tylermurphy/hideAndSeek/bukkit/EventListener.java index c0ee5eb..4a4bac1 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/bukkit/EventListener.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/bukkit/EventListener.java @@ -46,11 +46,21 @@ public class EventListener implements Listener { @EventHandler public void onQuit(PlayerQuitEvent event) { Main.plugin.board.remove(event.getPlayer()); + if(Main.plugin.status.equals("Standby")) { + Main.plugin.board.reloadLobbyBoards(); + } else { + Main.plugin.board.reloadGameBoards(); + } } @EventHandler public void onKick(PlayerKickEvent event) { Main.plugin.board.remove(event.getPlayer()); + if(Main.plugin.status.equals("Standby")) { + Main.plugin.board.reloadLobbyBoards(); + } else { + Main.plugin.board.reloadGameBoards(); + } } @EventHandler(priority = EventPriority.HIGHEST) diff --git a/src/main/java/net/tylermurphy/hideAndSeek/command/SaveMap.java b/src/main/java/net/tylermurphy/hideAndSeek/command/SaveMap.java index a2554d1..2befd73 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/command/SaveMap.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/command/SaveMap.java @@ -2,15 +2,6 @@ package net.tylermurphy.hideAndSeek.command; import static net.tylermurphy.hideAndSeek.configuration.Config.*; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.Arrays; - import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.bukkit.scheduler.BukkitRunnable; @@ -36,66 +27,15 @@ public class SaveMap implements ICommand { Bukkit.getServer().getWorld(spawnWorld).save(); BukkitRunnable runnable = new BukkitRunnable() { public void run() { - File current = new File(Main.root+File.separator+spawnWorld); - if(current.exists()) { - File temp_destenation = new File(Main.root+File.separator+"temp_hideandseek_"+spawnWorld); - File destenation = new File(Main.root+File.separator+"hideandseek_"+spawnWorld); - copyFileStructure(current, temp_destenation); - if(destenation.exists()) { - deleteDirectory(destenation); - destenation.mkdir(); - } - temp_destenation.renameTo(destenation); - sender.sendMessage(messagePrefix + message("MAPSAVE_END")); - runningBackup = false; - } else { - sender.sendMessage(errorPrefix + message("MAPSAVE_ERROR")); - } + sender.sendMessage( + Main.plugin.worldLoader.save() + ); + runningBackup = false; } }; runnable.runTaskAsynchronously(Main.plugin); runningBackup = true; } - - private static void copyFileStructure(File source, File target){ - try { - ArrayList ignore = new ArrayList<>(Arrays.asList("uid.dat", "session.lock")); - if(!ignore.contains(source.getName())) { - if(source.isDirectory()) { - if(!target.exists()) - if (!target.mkdirs()) - throw new IOException("Couldn't create world directory!"); - String files[] = source.list(); - for (String file : files) { - File srcFile = new File(source, file); - File destFile = new File(target, file); - copyFileStructure(srcFile, destFile); - } - } else { - InputStream in = new FileInputStream(source); - OutputStream out = new FileOutputStream(target); - byte[] buffer = new byte[1024]; - int length; - while ((length = in.read(buffer)) > 0) - out.write(buffer, 0, length); - in.close(); - out.close(); - } - } - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - private boolean deleteDirectory(File directoryToBeDeleted) { - File[] allContents = directoryToBeDeleted.listFiles(); - if (allContents != null) { - for (File file : allContents) { - deleteDirectory(file); - } - } - return directoryToBeDeleted.delete(); - } public String getLabel() { return "saveMap"; diff --git a/src/main/java/net/tylermurphy/hideAndSeek/command/SetBounds.java b/src/main/java/net/tylermurphy/hideAndSeek/command/SetBounds.java new file mode 100644 index 0000000..210f7fe --- /dev/null +++ b/src/main/java/net/tylermurphy/hideAndSeek/command/SetBounds.java @@ -0,0 +1,67 @@ +package net.tylermurphy.hideAndSeek.command; + +import static net.tylermurphy.hideAndSeek.configuration.Config.*; + +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import net.tylermurphy.hideAndSeek.Main; +import static net.tylermurphy.hideAndSeek.configuration.Localization.*; + +public class SetBounds implements ICommand { + + public void execute(CommandSender sender, String[] args) { + if(!Main.plugin.status.equals("Standby")) { + sender.sendMessage(errorPrefix + message("GAME_INPROGRESS")); + return; + } + if(spawnPosition == null) { + sender.sendMessage(errorPrefix + message("ERROR_GAME_SPAWN")); + return; + } + Player player = (Player) sender; + if(!player.getWorld().getName().equals(spawnWorld)){ + sender.sendMessage(errorPrefix + message("BOUNDS_WRONG_WORLD")); + return; + } + if(saveMaxX == 0) { + addToConfig("bounds.max.x", player.getLocation().getBlockX()); + saveMaxX = player.getLocation().getBlockX(); + } else if(saveMaxX < player.getLocation().getBlockX()) { + addToConfig("bounds.max.x", player.getLocation().getBlockX()); + addToConfig("bounds.min.x", saveMaxX); + saveMinX = saveMaxX; + saveMaxX = player.getLocation().getBlockX(); + } else { + addToConfig("bounds.min.x", player.getLocation().getBlockX()); + saveMinX = player.getLocation().getBlockX(); + } + if(saveMaxZ == 0) { + addToConfig("bounds.max.z", player.getLocation().getBlockZ()); + saveMaxZ = player.getLocation().getBlockZ(); + } else if(saveMaxZ < player.getLocation().getBlockZ()) { + addToConfig("bounds.max.z", player.getLocation().getBlockZ()); + addToConfig("bounds.min.z", saveMaxZ); + saveMinZ = saveMaxZ; + saveMaxZ = player.getLocation().getBlockZ(); + } else { + addToConfig("bounds.min.z", player.getLocation().getBlockZ()); + saveMinZ = player.getLocation().getBlockZ(); + } + sender.sendMessage(messagePrefix + message("BOUNDS")); + saveConfig(); + } + + public String getLabel() { + return "setBounds"; + } + + public String getUsage() { + return ""; + } + + public String getDescription() { + return "Sets the map bounds for the game."; + } + +} diff --git a/src/main/java/net/tylermurphy/hideAndSeek/command/Setup.java b/src/main/java/net/tylermurphy/hideAndSeek/command/Setup.java index 8be0141..f47503a 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/command/Setup.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/command/Setup.java @@ -28,9 +28,13 @@ public class Setup implements ICommand { msg = msg + "\n" + message("SETUP_EXIT").toString(); count++; } + if(saveMinX == 0 || saveMinZ == 0 || saveMaxX == 0 || saveMaxZ == 0) { + msg = msg + "\n" + message("SETUP_BOUNDS").toString(); + count++; + } File destenation = new File(Main.root+File.separator+"hideandseek_"+spawnWorld); if(!destenation.exists()) { - msg = msg + "\n" + message("SETUP_MAPSAVE").toString(); + msg = msg + "\n" + message("SETUP_SAVEMAP").toString(); count++; } if(count < 1) { diff --git a/src/main/java/net/tylermurphy/hideAndSeek/command/Start.java b/src/main/java/net/tylermurphy/hideAndSeek/command/Start.java index 89cbc09..4bedd2f 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/command/Start.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/command/Start.java @@ -49,9 +49,9 @@ public class Start implements ICommand { return; } if(Bukkit.getServer().getWorld("hideandseek_"+spawnWorld) != null) { - Util.rollback("hideandseek_"+spawnWorld); + Main.plugin.worldLoader.rollback(); } else { - Util.loadMap("hideandseek_"+spawnWorld); + Main.plugin.worldLoader.loadMap(); } String seekerName; if(args.length < 1) { @@ -124,9 +124,6 @@ public class Start implements ICommand { if(gameLength > 0) { Main.plugin.timeLeft = gameLength; - for(Player player : Main.plugin.board.getPlayers()) { - player.setLevel(gameLength); - } } } }, 20 * 30); diff --git a/src/main/java/net/tylermurphy/hideAndSeek/command/Stop.java b/src/main/java/net/tylermurphy/hideAndSeek/command/Stop.java index 810c071..52bf310 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/command/Stop.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/command/Stop.java @@ -58,7 +58,7 @@ public class Stop implements ICommand { Packet.setGlow(player, temp, false); } } - Util.unloadMap("hideandseek_"+spawnWorld); + Main.plugin.worldLoader.unloadMap(); Main.plugin.board.reloadLobbyBoards(); } diff --git a/src/main/java/net/tylermurphy/hideAndSeek/configuration/Config.java b/src/main/java/net/tylermurphy/hideAndSeek/configuration/Config.java index 83b6ceb..efae5d2 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/configuration/Config.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/configuration/Config.java @@ -40,7 +40,11 @@ public class Config { worldborderSize, worldborderDelay, currentWorldborderSize, - gameLength; + gameLength, + saveMinX, + saveMinZ, + saveMaxX, + saveMaxZ; public static FileConfiguration getConfig() { return Main.plugin.getConfig(); @@ -101,6 +105,12 @@ public class Config { gameoverPrefix = getConfig().getString("prefix.gameover").replace("&", SYMBOLE_STRING); warningPrefix = getConfig().getString("prefix.warning").replace("&", SYMBOLE_STRING); + //Map Bounds + saveMinX = getConfig().getInt("bounds.min.x"); + saveMinZ = getConfig().getInt("bounds.min.z"); + saveMaxX = getConfig().getInt("bounds.max.x"); + saveMaxZ = getConfig().getInt("bounds.max.z"); + //Other nametagsVisible = getConfig().getBoolean("nametagsVisible"); permissionsRequired = getConfig().getBoolean("permissionsRequired"); @@ -123,4 +133,8 @@ public class Config { saveConfig(); } + public static void addToConfig(String path, Object value) { + getConfig().set(path, value); + } + } \ No newline at end of file diff --git a/src/main/java/net/tylermurphy/hideAndSeek/configuration/Localization.java b/src/main/java/net/tylermurphy/hideAndSeek/configuration/Localization.java index 177b5bf..ee34d4a 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/configuration/Localization.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/configuration/Localization.java @@ -1,6 +1,9 @@ package net.tylermurphy.hideAndSeek.configuration; import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; import java.util.HashMap; import java.util.Map; @@ -13,12 +16,20 @@ public class Localization { public static final Map LOCAL = new HashMap(); - static YamlConfiguration config; + static YamlConfiguration config, defaultConfig; + static File location; public static boolean init() { + Main.plugin.saveResource("localization.yml", false); String path = Main.data.getAbsolutePath()+File.separator + "localization.yml"; - config = YamlConfiguration.loadConfiguration(new File(path)); + location = new File(path); + config = YamlConfiguration.loadConfiguration(location); + + InputStream is = Main.plugin.getResource("localization.yml"); + InputStreamReader isr = new InputStreamReader(is); + defaultConfig = YamlConfiguration.loadConfiguration(isr); + for(String key : config.getConfigurationSection("Localization").getKeys(false)) { LOCAL.put( key, @@ -30,8 +41,19 @@ public class Localization { public static LocalizationString message(String key) { LocalizationString temp = LOCAL.get(key); - if(temp == null) - return new LocalizationString(key+" missing from localization.yml"); + if(temp == null) { + config.set("Localization."+key, defaultConfig.getString("Localization."+key)); + try { + config.save(location); + } catch (IOException e) { + Main.plugin.getLogger().severe(e.getMessage()); + } + LOCAL.put(key, + new LocalizationString( ChatColor.translateAlternateColorCodes('&', defaultConfig.getString("Localization."+key) ) ) + ); + return new LocalizationString(LOCAL.get(key).toString()); + } return new LocalizationString(temp.toString()); + } } diff --git a/src/main/java/net/tylermurphy/hideAndSeek/util/Util.java b/src/main/java/net/tylermurphy/hideAndSeek/util/Util.java index 028b217..57839f1 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/util/Util.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/util/Util.java @@ -5,7 +5,6 @@ import static net.tylermurphy.hideAndSeek.configuration.Config.*; import java.io.File; import org.bukkit.Bukkit; -import org.bukkit.WorldCreator; import org.bukkit.entity.Player; import net.tylermurphy.hideAndSeek.Main; @@ -27,24 +26,6 @@ public class Util { return true; } - public static void unloadMap(String mapname){ - if(Bukkit.getServer().unloadWorld(Bukkit.getServer().getWorld(mapname), false)){ - Main.plugin.getLogger().info("Successfully unloaded " + mapname); - }else{ - Main.plugin.getLogger().severe("COULD NOT UNLOAD " + mapname); - } - } - - public static void loadMap(String mapname){ - Bukkit.getServer().createWorld(new WorldCreator(mapname)); - Bukkit.getServer().getWorld("hideandseek_"+spawnWorld).setAutoSave(false); - } - - public static void rollback(String mapname){ - unloadMap(mapname); - loadMap(mapname); - } - public static void sendDelayedMessage(String message, int gameId, int delay) { Bukkit.getScheduler().runTaskLaterAsynchronously(Main.plugin, new Runnable() { public void run() { diff --git a/src/main/java/net/tylermurphy/hideAndSeek/world/VoidGenerator.java b/src/main/java/net/tylermurphy/hideAndSeek/world/VoidGenerator.java new file mode 100644 index 0000000..d03fd17 --- /dev/null +++ b/src/main/java/net/tylermurphy/hideAndSeek/world/VoidGenerator.java @@ -0,0 +1,57 @@ +package net.tylermurphy.hideAndSeek.world; + +import java.util.Collections; +import java.util.List; + +import org.bukkit.World; +import org.bukkit.generator.BlockPopulator; +import org.bukkit.generator.ChunkGenerator; + +public class VoidGenerator extends ChunkGenerator{ + + @Override + public List getDefaultPopulators(World world) { + return Collections.emptyList(); + } + + @Override + public boolean shouldGenerateNoise() { + return false; + } + + @Override + public boolean shouldGenerateSurface() { + return false; + } + + @Override + public boolean shouldGenerateBedrock() { + return false; + } + + @Override + public boolean shouldGenerateCaves() { + return false; + } + + @Override + public boolean shouldGenerateDecorations() { + return false; + } + + @Override + public boolean shouldGenerateMobs() { + return false; + } + + @Override + public boolean shouldGenerateStructures() { + return false; + } + + @Override + public boolean canSpawn(World world, int x, int z) { + return true; + } + +} diff --git a/src/main/java/net/tylermurphy/hideAndSeek/world/WorldLoader.java b/src/main/java/net/tylermurphy/hideAndSeek/world/WorldLoader.java new file mode 100644 index 0000000..cfb85bf --- /dev/null +++ b/src/main/java/net/tylermurphy/hideAndSeek/world/WorldLoader.java @@ -0,0 +1,129 @@ +package net.tylermurphy.hideAndSeek.world; + +import static net.tylermurphy.hideAndSeek.configuration.Config.*; +import static net.tylermurphy.hideAndSeek.configuration.Localization.message; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import org.bukkit.Bukkit; +import org.bukkit.WorldCreator; + +import net.tylermurphy.hideAndSeek.Main; + +public class WorldLoader { + + String mapname; + String savename; + + public WorldLoader(String mapname) { + this.mapname = mapname; + this.savename = "hideandseek_"+mapname; + } + + public void unloadMap(){ + if(Bukkit.getServer().unloadWorld(Bukkit.getServer().getWorld(savename), false)){ + Main.plugin.getLogger().info("Successfully unloaded " + savename); + }else{ + Main.plugin.getLogger().severe("COULD NOT UNLOAD " + savename); + } + } + + public void loadMap(){ + Bukkit.getServer().createWorld(new WorldCreator(savename).generator(new VoidGenerator())); + Bukkit.getServer().getWorld(savename).setAutoSave(false); + } + + public void rollback(){ + unloadMap(); + loadMap(); + } + + public String save() { + File current = new File(Main.root+File.separator+mapname); + if(current.exists()) { + try { + File destenation = new File(Main.root+File.separator+savename); + File temp_destenation = new File(Main.root+File.separator+"temp_"+savename); + copyFileFolder("region",true); + copyFileFolder("entities",true); + copyFileFolder("datapacks",false); + File srcFile = new File(current, "level.dat"); + File destFile = new File(temp_destenation, "level.dat"); + copyFile(srcFile,destFile); + if(destenation.exists()) { + deleteDirectory(destenation); + destenation.mkdir(); + } + temp_destenation.renameTo(destenation); + } catch(IOException e) { + e.printStackTrace(); + return errorPrefix + message("COMMAND_ERROR"); + } + return messagePrefix + message("MAPSAVE_END"); + } else { + return errorPrefix + message("MAPSAVE_ERROR"); + } + } + + private void copyFileFolder(String name, Boolean isMca) throws IOException { + File region = new File(Main.root+File.separator+mapname+File.separator+name); + File temp = new File(Main.root+File.separator+"temp_"+savename+File.separator+name); + if(region.exists() && region.isDirectory()) { + if(!temp.exists()) + if(!temp.mkdirs()) + throw new IOException("Couldn't create region directory!"); + String files[] = region.list(); + for (String file : files) { + + if(isMca) { + int minX = (int)Math.floor(saveMinX / 32.0); + int minZ = (int)Math.floor(saveMinZ / 32.0); + int maxX = (int)Math.floor(saveMaxX / 32.0); + int maxZ = (int)Math.floor(saveMaxZ / 32.0); + + String[] parts = file.split("."); + if(parts.length > 1) { + Main.plugin.getLogger().info(file); + if( Integer.parseInt(parts[1]) < minX || Integer.parseInt(parts[1]) > maxX ||Integer.parseInt(parts[2]) < minZ || Integer.parseInt(parts[2]) > maxZ ) + continue; + } + } + + File srcFile = new File(region, file); + if(srcFile.isDirectory()) { + copyFileFolder(name+File.separator+file, false); + } else { + File destFile = new File(temp, file); + copyFile(srcFile, destFile); + } + } + } + } + + private void copyFile(File source, File target) throws IOException { + InputStream in = new FileInputStream(source); + OutputStream out = new FileOutputStream(target); + byte[] buffer = new byte[1024]; + int length; + while ((length = in.read(buffer)) > 0) + out.write(buffer, 0, length); + in.close(); + out.close(); + } + + private boolean deleteDirectory(File directoryToBeDeleted) { + File[] allContents = directoryToBeDeleted.listFiles(); + if (allContents != null) { + for (File file : allContents) { + deleteDirectory(file); + } + } + return directoryToBeDeleted.delete(); + } + +} diff --git a/src/main/resources/localization.yml b/src/main/resources/localization.yml index cf2fd30..e714046 100644 --- a/src/main/resources/localization.yml +++ b/src/main/resources/localization.yml @@ -19,7 +19,7 @@ Localization: CONFIG_RELOAD: "Reloaded the config." MAPSAVE_INPROGRESS: "Map save is currently in progress. Try again later." MAPSAVE_START: "Starting map save." - MAPSAVE_WARNING: "All commands will be disabled whenthe save is in progress. Do not turn off the server." + MAPSAVE_WARNING: "All commands will be disabled when the save is in progress. Do not turn off the server." MAPSAVE_END: "Map save complete." MAPSAVE_ERROR: "Coudnt find current map." WORLDBORDER_DISABLE: "Disabled worldborder." @@ -37,6 +37,7 @@ Localization: SETUP_LOBBY: "&c&l- &fLobby spawn isnt set, /hs setlobby" SETUP_EXIT: "&c&l- &fQuit/exit teleport location isnt set, /hs setexit" SETUP_SAVEMAP: "&c&l- &fHide and seek map isnt saved, /hs savemap (after /hs setspawn)" + SETUP_BOUNDS: "&c&l- &fPlease set game bounds in 2 opposite corners of the game map, /hs setbounds" SETUP_COMPLETE: "Everything is setup and ready to go!" GAME_SPAWN: "Set game spawn position to current location" LOBBY_SPAWN: "Set lobby position to current location" @@ -45,6 +46,8 @@ Localization: START_INVALID_NAME: "Invalid player: {PLAYER}." START_COUNTDOWN: "Hiders have {AMOUNT} seconds to hide!" START: "Attetion SEEKERS, its time to fin the hiders!" - STOP: "Game has been force stopped" + STOP: "Game has been force stopped." HIDERS_SUBTITLE: "Hide away from the seekers" SEEKERS_SUBTITLE: "Eliminate all hiders" + BOUNDS_WRONG_WORLD: "Please run this command in the game world." + BOUNDS: "Sucessfully set bounds at this position."