/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.royaldev.royalcommands; import org.bukkit.Bukkit; import org.bukkit.Difficulty; import org.bukkit.GameMode; import org.bukkit.World; import org.bukkit.WorldCreator; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerChangedWorldEvent; import org.bukkit.event.weather.ThunderChangeEvent; import org.bukkit.event.weather.WeatherChangeEvent; import org.bukkit.event.world.WorldLoadEvent; import org.bukkit.event.world.WorldUnloadEvent; import org.royaldev.royalcommands.configuration.Configuration; import org.royaldev.royalcommands.listeners.InventoryListener; import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.logging.Logger; public class WorldManager { public static InventoryListener il; private final List<String> loadedWorlds = new ArrayList<>(); private final List<String> configuredWorlds = new ArrayList<>(); private final Configuration config = Configuration.getConfiguration("worlds.yml"); private final Logger log = RoyalCommands.getInstance().getLogger(); public WorldManager() { il = new InventoryListener(RoyalCommands.getInstance()); if (!Config.useWorldManager) return; if (!config.exists()) config.createFile(); if (config.getConfigurationSection("worlds") != null) { synchronized (configuredWorlds) { for (String key : config.getConfigurationSection("worlds").getKeys(false)) { configuredWorlds.add(key); } } } for (World w : Bukkit.getWorlds()) { if (loadedWorlds.contains(w.getName())) continue; loadedWorlds.add(w.getName()); } this.addNewToConfig(); this.setupWorlds(); for (String s : loadedWorlds) { if (!configuredWorlds.contains(s)) continue; World w = Bukkit.getWorld(s); if (w == null) continue; boolean isStorming = config.getBoolean("worlds." + w.getName() + ".is_storming_if_weather_false", false); w.setStorm(isStorming); } Bukkit.getPluginManager().registerEvents(il, RoyalCommands.getInstance()); Bukkit.getPluginManager().registerEvents(new WorldWatcher(), RoyalCommands.getInstance()); } public void addNewToConfig() { for (String ws : loadedWorlds) { if (configuredWorlds.contains(ws)) continue; World w = Bukkit.getWorld(ws); if (w == null) continue; String path = "worlds." + ws + "."; config.set(path + "displayname", ws); config.set(path + "spawnmonsters", w.getAllowMonsters()); config.set(path + "spawnanimals", w.getAllowAnimals()); config.set(path + "keepspawnloaded", w.getKeepSpawnInMemory()); config.set(path + "generatestructures", w.canGenerateStructures()); config.set(path + "pvp", w.getPVP()); config.set(path + "weather", true); config.set(path + "maxheight", w.getMaxHeight()); config.set(path + "monsterspawnlimit", w.getMonsterSpawnLimit()); config.set(path + "animalspawnlimit", w.getAnimalSpawnLimit()); config.set(path + "wateranimalspawnlimit", w.getWaterAnimalSpawnLimit()); config.set(path + "animalspawnticks", w.getTicksPerAnimalSpawns()); config.set(path + "monsterspawnticks", w.getTicksPerMonsterSpawns()); config.set(path + "difficulty", w.getDifficulty().name()); config.set(path + "worldtype", w.getWorldType().name()); config.set(path + "environment", w.getEnvironment().name()); config.set(path + "gamemode", Bukkit.getServer().getDefaultGameMode().name()); if (w.getGenerator() == null) config.set(path + "generator", "DefaultGen"); config.set(path + "seed", w.getSeed()); config.set(path + "freezetime", false); config.set(path + "loadatstartup", true); } } public void addToLoadedWorlds(String name) { synchronized (loadedWorlds) { if (!loadedWorlds.contains(name)) loadedWorlds.add(name); } } public void addToLoadedWorlds(World w) { synchronized (loadedWorlds) { if (!loadedWorlds.contains(w.getName())) loadedWorlds.add(w.getName()); } } /** * Gets a world based on its alias (case-sensitive). * * @param name Alias of world * @return World or null if no matching alias */ public World getCaseSensitiveWorld(String name) { World w; for (String s : loadedWorlds) { String path = "worlds." + s + "."; if (config.getString(path + "displayname", "").equals(name)) { w = Bukkit.getWorld(s); return w; } } return null; } public Configuration getConfig() { return config; } /** * Gets a world based on its alias (case-insensitive). * * @param name Alias of world * @return World or null if no matching alias */ public World getWorld(String name) { World w; for (String s : loadedWorlds) { String path = "worlds." + s + "."; if (config.getString(path + "displayname", "").equalsIgnoreCase(name)) { w = Bukkit.getWorld(s); return w; } } return null; } /** * Attempts to load a world. * * @param name Name of world to load (i.e. folder name) * @return Loaded world * @throws IllegalArgumentException If there is no such world * @throws NullPointerException If could not read the world container's files */ public World loadWorld(String name) throws IllegalArgumentException, NullPointerException { if (Bukkit.getServer().getWorldContainer() == null) throw new NullPointerException("Could not read world files!"); File world = new File(Bukkit.getServer().getWorldContainer(), name); if (!world.exists()) throw new IllegalArgumentException("No such world!"); if (!world.isDirectory()) throw new IllegalArgumentException("World is not a directory!"); WorldCreator wc = new WorldCreator(name); String generator = config.getString("worlds." + name + ".generator", "DefaultGen"); if (generator.equals("DefaultGen")) generator = null; World w; try { wc.generator(generator); w = wc.createWorld(); } catch (Exception e) { // catch silly generators using old code (may not actually catch) throw new IllegalArgumentException("Generator (" + generator + ") is using old code: " + e.getMessage()); } synchronized (loadedWorlds) { loadedWorlds.add(w.getName()); } return w; } public void reloadConfig() { config.reload(); this.setupWorlds(); } public void removeFromLoadedWorlds(String name) { synchronized (loadedWorlds) { if (loadedWorlds.contains(name)) loadedWorlds.remove(name); } } public void removeFromLoadedWorlds(World w) { synchronized (loadedWorlds) { if (loadedWorlds.contains(w.getName())) loadedWorlds.remove(w.getName()); } } public void setupWorlds() { for (String ws : configuredWorlds) { String path = "worlds." + ws + "."; World w = null; if (config.getBoolean(path + "loadatstartup") && Bukkit.getWorld(ws) == null) { try { w = loadWorld(ws); } catch (IllegalArgumentException e) { log.warning("Could not load world " + ws + " as specified in worlds.yml: " + e.getMessage()); continue; } catch (NullPointerException e) { log.warning("Could not load world " + ws + " as specified in worlds.yml: " + e.getMessage()); continue; } } if (!loadedWorlds.contains(ws)) continue; if (w == null) w = Bukkit.getWorld(ws); if (w == null) { log.warning("Could not manage world " + ws + ": No such world"); continue; } w.setSpawnFlags(config.getBoolean(path + "spawnmonsters", true), config.getBoolean(path + "spawnanimals", true)); w.setKeepSpawnInMemory(config.getBoolean("keepspawnloaded", true)); w.setPVP(config.getBoolean(path + "pvp", true)); w.setMonsterSpawnLimit(config.getInt(path + "monsterspawnlimit", 70)); w.setAnimalSpawnLimit(config.getInt(path + "animalspawnlimit", 15)); w.setWaterAnimalSpawnLimit(config.getInt(path + "wateranimalspawnlimit", 5)); w.setTicksPerAnimalSpawns(config.getInt(path + "animalspawnticks", 400)); w.setTicksPerMonsterSpawns(config.getInt(path + "monsterspawnticks", 1)); Difficulty d; try { d = Difficulty.valueOf(config.getString(path + "difficulty", "normal").toUpperCase()); } catch (Exception e) { d = Difficulty.NORMAL; } w.setDifficulty(d); } } /** * Attempts to unload a world * * @param w World to unload * @return If world was unloaded */ public boolean unloadWorld(World w) { boolean worked = Bukkit.unloadWorld(w, true); synchronized (loadedWorlds) { if (loadedWorlds.contains(w.getName()) && worked) loadedWorlds.remove(w.getName()); } return worked; } /** * Attempts to unload a world * * @param name Name of world to unload * @return If world was unloaded */ public boolean unloadWorld(String name) { boolean worked = Bukkit.unloadWorld(name, true); synchronized (loadedWorlds) { if (loadedWorlds.contains(name) && worked) loadedWorlds.remove(name); } return worked; } private class WorldWatcher implements Listener { @EventHandler public void onThunder(ThunderChangeEvent e) { if (e.isCancelled()) return; World w = e.getWorld(); if (!configuredWorlds.contains(w.getName())) return; if (!loadedWorlds.contains(w.getName())) return; boolean allowWeather = config.getBoolean("worlds." + w.getName() + ".weather", true); if (!allowWeather) e.setCancelled(true); } @EventHandler public void onWeather(WeatherChangeEvent e) { if (e.isCancelled()) return; World w = e.getWorld(); if (!configuredWorlds.contains(w.getName())) return; if (!loadedWorlds.contains(w.getName())) return; boolean allowWeather = config.getBoolean("worlds." + w.getName() + ".weather", true); if (!allowWeather) e.setCancelled(true); } @EventHandler public void onWorldTele(PlayerChangedWorldEvent e) { World to = e.getPlayer().getWorld(); if (!configuredWorlds.contains(to.getName())) return; if (!loadedWorlds.contains(to.getName())) return; GameMode gm; String mode = config.getString("worlds." + to.getName() + ".gamemode", "SURVIVAL").trim(); try { gm = GameMode.valueOf(mode); } catch (IllegalArgumentException ex) { gm = GameMode.SURVIVAL; } e.getPlayer().setGameMode(gm); } @EventHandler public void worldLoad(WorldLoadEvent e) { synchronized (loadedWorlds) { if (!loadedWorlds.contains(e.getWorld().getName())) loadedWorlds.add(e.getWorld().getName()); WorldManager.this.addNewToConfig(); } } @EventHandler public void worldUnload(WorldUnloadEvent e) { if (e.isCancelled()) return; synchronized (loadedWorlds) { if (loadedWorlds.contains(e.getWorld().getName())) loadedWorlds.remove(e.getWorld().getName()); } } } }