Java tutorial
/* * Copyright (C) 2013-2016 Dabo Ross <http://www.daboross.net/> * * This program 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. * * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */ package net.daboross.bukkitdev.skywars; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.net.URLConnection; import java.nio.file.Path; import java.util.Locale; import java.util.UUID; import java.util.logging.Level; import net.daboross.bukkitdev.bukkitstorageprotobuf.ProtobufStatic; import net.daboross.bukkitdev.skywars.api.SkyStatic; import net.daboross.bukkitdev.skywars.api.SkyWars; import net.daboross.bukkitdev.skywars.api.config.SkyConfiguration; import net.daboross.bukkitdev.skywars.api.config.SkyConfigurationException; import net.daboross.bukkitdev.skywars.api.game.SkyGameHandler; import net.daboross.bukkitdev.skywars.api.kits.SkyKitGui; import net.daboross.bukkitdev.skywars.api.kits.SkyKits; import net.daboross.bukkitdev.skywars.api.location.SkyLocationStore; import net.daboross.bukkitdev.skywars.api.translations.SkyTrans; import net.daboross.bukkitdev.skywars.api.translations.SkyTranslations; import net.daboross.bukkitdev.skywars.api.translations.TransKey; import net.daboross.bukkitdev.skywars.commands.MainCommand; import net.daboross.bukkitdev.skywars.commands.SetupCommand; import net.daboross.bukkitdev.skywars.config.RandomChestConfiguration; import net.daboross.bukkitdev.skywars.config.SkyWarsConfiguration; import net.daboross.bukkitdev.skywars.config.TranslationsConfiguration; import net.daboross.bukkitdev.skywars.economy.EconomyFailedException; import net.daboross.bukkitdev.skywars.economy.SkyEconomyGameRewards; import net.daboross.bukkitdev.skywars.economy.SkyEconomyHook; import net.daboross.bukkitdev.skywars.events.GameEventDistributor; import net.daboross.bukkitdev.skywars.events.listeners.BackupInventoryClearListener; import net.daboross.bukkitdev.skywars.events.listeners.GameBroadcaster; import net.daboross.bukkitdev.skywars.events.listeners.InventorySaveListener; import net.daboross.bukkitdev.skywars.events.listeners.KitApplyListener; import net.daboross.bukkitdev.skywars.events.listeners.KitQueueNotifier; import net.daboross.bukkitdev.skywars.events.listeners.ResetHealthListener; import net.daboross.bukkitdev.skywars.events.listeners.SignListener; import net.daboross.bukkitdev.skywars.game.CurrentGames; import net.daboross.bukkitdev.skywars.game.GameHandler; import net.daboross.bukkitdev.skywars.game.GameIDHandler; import net.daboross.bukkitdev.skywars.game.GameQueue; import net.daboross.bukkitdev.skywars.game.GameQueueTimer; import net.daboross.bukkitdev.skywars.kits.KitGuiManager; import net.daboross.bukkitdev.skywars.kits.SkyKitConfiguration; import net.daboross.bukkitdev.skywars.libraries.pluginstatistics.PluginStatistics; import net.daboross.bukkitdev.skywars.listeners.AttackerStorageListener; import net.daboross.bukkitdev.skywars.listeners.BuildingLimiter; import net.daboross.bukkitdev.skywars.listeners.CommandWhitelistListener; import net.daboross.bukkitdev.skywars.listeners.KitGuiListener; import net.daboross.bukkitdev.skywars.listeners.MobSpawnDisable; import net.daboross.bukkitdev.skywars.listeners.PlayerJoinInArenaWorldListener; import net.daboross.bukkitdev.skywars.listeners.PlayerStateListener; import net.daboross.bukkitdev.skywars.listeners.PortalListener; import net.daboross.bukkitdev.skywars.listeners.ScoreReplaceChatListener; import net.daboross.bukkitdev.skywars.player.OnlineSkyPlayers; import net.daboross.bukkitdev.skywars.score.ScoreStorage; import net.daboross.bukkitdev.skywars.scoreboards.TeamScoreboardListener; import net.daboross.bukkitdev.skywars.storage.LocationStore; import net.daboross.bukkitdev.skywars.util.CrossVersion; import net.daboross.bukkitdev.skywars.world.SkyWorldHandler; import org.apache.commons.lang.Validate; import org.bukkit.Bukkit; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.configuration.InvalidConfigurationException; import org.bukkit.entity.Player; import org.bukkit.event.Listener; import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.scheduler.BukkitRunnable; import org.mcstats.MetricsLite; public class SkyWarsPlugin extends JavaPlugin implements SkyWars { private SkyTranslations translations; private SkyConfiguration configuration; private RandomChestConfiguration chestConfiguration; private SkyLocationStore locationStore; private SkyGameHandler gameHandler; private SkyWorldHandler worldHandler; private SkyEconomyHook economyHook; private SkyEconomyGameRewards ecoRewards; private SkyKits kits; private SkyKitGui kitGui; private GameQueue gameQueue; private GameQueueTimer gameQueueTimer; private CurrentGames currentGameTracker; private GameIDHandler idHandler; private GameBroadcaster broadcaster; private GameEventDistributor distributor; private ScoreStorage score; private KitQueueNotifier kitQueueNotifier; private SignListener signListener; private BackupInventoryClearListener backupInventoryClearListener; private OnlineSkyPlayers inGame; private TeamScoreboardListener teamListener; private AttackerStorageListener attackerStorage; // Info listeners private ResetHealthListener resetHealth; private KitApplyListener kitApplyListener; private InventorySaveListener inventorySaveListener; // Bukkit listeners private ScoreReplaceChatListener chatListener; private boolean enabledCorrectly = false; // Workaround variables private boolean multiinvWorkaroundEnabled = false; @Override public void onLoad() { SkyStatic.setPluginName(this.getDescription().getName()); SkyStatic.setVersion(this.getDescription().getVersion()); SkyStatic.setLogger(this.getLogger()); ProtobufStatic.setLogger(this.getLogger()); } @Override public void onEnable() { try { startPlugin(); metrics(); pluginStatistics(); } catch (Throwable ex) { getLogger().log(Level.SEVERE, "Startup failed", ex); enabledCorrectly = false; getServer().getPluginManager().disablePlugin(this); } } private void startPlugin() throws StartupFailedException { try { configuration = new SkyWarsConfiguration(this); } catch (IOException | InvalidConfigurationException | SkyConfigurationException ex) { throw new StartupFailedException("Failed to load configuration", ex); } if (!configuration.isSkipUuidCheck() && !supportsUuids()) { getLogger().log(Level.SEVERE, "Warning! You are running a CraftBukkit version that is not supported by SkyWars v" + SkyStatic.getVersion()); getLogger().log(Level.SEVERE, "Please update to at least CraftBukkit version 1.7.8, or the equivilant for your server software."); getLogger().log(Level.SEVERE, "If you wish to ignore this, and run SkyWars anyways, set 'skip-uuid-version-check' to true in plugins/SkyWars/main-config.yml"); getLogger().log(Level.SEVERE, "Download SkyWars v1.4.4 if you want to run on an older version of Minecraft."); throw new StartupFailedException("See above"); } multiinvWorkaroundEnabled = testForMultiinvWorkaround(configuration.isMultiinvWorkaroundPossible(), configuration.isMultiinvWorkaroundForced()); try { translations = new TranslationsConfiguration(this); } catch (SkyConfigurationException ex) { throw new StartupFailedException("Failed to load translations", ex); } SkyTrans.setInstance(translations); currentGameTracker = new CurrentGames(); idHandler = new GameIDHandler(); broadcaster = new GameBroadcaster(this); worldHandler = new SkyWorldHandler(this); inventorySaveListener = new InventorySaveListener(this); resetHealth = new ResetHealthListener(this); try { locationStore = new LocationStore(this); } catch (SkyConfigurationException ex) { throw new StartupFailedException("Failed to load locations", ex); } gameQueue = new GameQueue(this); gameQueueTimer = new GameQueueTimer(this); gameHandler = new GameHandler(this); attackerStorage = new AttackerStorageListener(this); distributor = new GameEventDistributor(this); teamListener = new TeamScoreboardListener(); inGame = new OnlineSkyPlayers(this); signListener = new SignListener(this); backupInventoryClearListener = new BackupInventoryClearListener(this); if (configuration.isEnableScore()) { score = new ScoreStorage(this); chatListener = new ScoreReplaceChatListener(this); } // For supporting /reload or plugin manager reloading. for (Player online : CrossVersion.getOnlinePlayers(getServer())) { inGame.loadPlayer(online); } if (configuration.isEconomyEnabled()) { SkyStatic.debug("[SkyWars] Enabling economy support"); try { economyHook = new SkyEconomyHook(this); ecoRewards = new SkyEconomyGameRewards(this); } catch (EconomyFailedException ex) { getLogger().log(Level.WARNING, "{0}. Could not enable economy hook.", ex.getMessage()); } } try { chestConfiguration = new RandomChestConfiguration(this); } catch (IOException | InvalidConfigurationException | SkyConfigurationException ex) { throw new StartupFailedException("Failed to load chest configuration", ex); } try { kits = new SkyKitConfiguration(this); } catch (IOException | InvalidConfigurationException ex) { throw new StartupFailedException("Failed to load kit configuration", ex); } kitGui = new KitGuiManager(this); kitQueueNotifier = new KitQueueNotifier(this); kitApplyListener = new KitApplyListener(this); new BukkitRunnable() { @Override public void run() { worldHandler.create(); worldHandler.loadArenas(); } }.runTask(this); new PermissionHandler().setupPermissions(); setupCommand(); PluginManager pm = getServer().getPluginManager(); registerListeners(pm, attackerStorage, new PlayerStateListener(this), new PortalListener(this), new PlayerJoinInArenaWorldListener(this), new CommandWhitelistListener(this), new BuildingLimiter(this), new MobSpawnDisable(), new KitGuiListener(this), chatListener, signListener); enabledCorrectly = true; } private boolean testForMultiinvWorkaround(boolean possiblyEnable, boolean alwaysEnable) { // since it's a workaround and not a hook, we don't actually need the plugin instance. We just need to know if it is loaded or not. if (alwaysEnable) { SkyStatic.debug("[SkyWars] Enabling MultiInv workaround: workaround enabled without check in config."); return true; } if (!possiblyEnable) { SkyStatic.debug("[SkyWars] Not enabling MultiInv workaround: check disabled in config."); return false; } if (getServer().getPluginManager().isPluginEnabled("MultiInv")) { SkyStatic.debug("[SkyWars] Enabling MultiInv workaround: check enabled in config, plugin found."); return true; } return false; } private boolean supportsUuids() { String packageName = Bukkit.getServer().getClass().getPackage().getName(); // Get full package string of CraftServer. // org.bukkit.craftbukkit.versionstring (or for pre-refactor, just org.bukkit.craftbukkit String version = packageName.substring(packageName.lastIndexOf('.') + 1); if (version.equals("craftbukkit")) { return false; } String[] split = version.split("_"); if (split.length != 3) { return backupUuidCheck(); } int first, second, third; try { first = Integer.parseInt(split[0].substring(1)); // substring for v1 -> 1 second = Integer.parseInt(split[1]); third = Integer.parseInt(split[2].substring(1)); // substring for R1 -> 1 } catch (NumberFormatException ignored) { return backupUuidCheck(); } // if we're on minecraft v2.X, the other version parts don't matter return first > 1 || second > 7 || (second == 7 && third >= 3); } private boolean backupUuidCheck() { try { Bukkit.class.getMethod("getPlayer", UUID.class); return true; } catch (NoSuchMethodException ignored) { return false; } } private void registerListeners(PluginManager pm, Listener... listeners) { for (Listener l : listeners) { if (l != null) { pm.registerEvents(l, this); } } } @Override public void onDisable() { if (enabledCorrectly) { locationStore.save(); idHandler.saveAndUnload(this); // For better transparency when using /reload. for (UUID uuid : gameQueue.getSecondaryCopy()) { Player player = getServer().getPlayer(uuid); gameQueue.removePlayer(player); player.sendMessage(SkyTrans.get(TransKey.CMD_LEAVE_REMOVED_FROM_SECONDARY_QUEUE)); } for (UUID uuid : gameQueue.getCopy()) { Player player = getServer().getPlayer(uuid); gameQueue.removePlayer(player); player.sendMessage(SkyTrans.get(TransKey.CMD_LEAVE_REMOVED_FROM_QUEUE)); } if (score != null) { try { score.save(); } catch (IOException ex) { getLogger().log(Level.WARNING, "Failed to save score", ex); } } getLogger().log(Level.INFO, "Unloading arena world - without saving"); worldHandler.destroyArenaWorld(); SkyStatic.setLogger(null); ProtobufStatic.setLogger(null); getLogger().log(Level.INFO, "SkyWars disabled successfully"); } } @Override public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) { if (!enabledCorrectly) { sender.sendMessage(SkyTrans.get(TransKey.NOT_FULLY_ENABLED)); } else { sender.sendMessage(SkyTrans.get(TransKey.NO_CLUE_COMMAND, cmd.getName())); } return true; } private void setupCommand() { MainCommand main = new MainCommand(this); SetupCommand setup = new SetupCommand(this); for (String commandName : getDescription().getCommands().keySet()) { if (commandName.toLowerCase(Locale.ENGLISH).endsWith("setup")) { setup.latchOnto(getCommand(commandName)); } else { main.latchOnto(getCommand(commandName)); } } } private void metrics() { try { MetricsLite metrics; try { metrics = new MetricsLite(this); } catch (IOException ex) { return; } metrics.start(); } catch (Throwable ex) { if (configuration.isDebug()) { getLogger().log(Level.WARNING, "Failed to start plugin metrics!", ex); } } } private void pluginStatistics() { try { if (!configuration.isReportPluginStatistics()) { return; } PluginStatistics statistics = new PluginStatistics(this, configuration.isDebug()); statistics.start(); } catch (Throwable ex) { if (configuration.isDebug()) { getLogger().log(Level.WARNING, "Failed to start plugin-statistics!", ex); } } } @Override public boolean reloadTranslations() { SkyTranslations tempTrans; try { tempTrans = new TranslationsConfiguration(this); } catch (SkyConfigurationException | RuntimeException ex) { getLogger().log(Level.WARNING, "Failed to reload translations. Just using older version for now.", ex); return false; } translations = tempTrans; SkyTrans.setInstance(tempTrans); return true; } @Override public InputStream getResourceAsStream(final String filename) throws IOException { // copied from JavaPlugin.java, and modified to actually give useful errors. Validate.notNull(filename, "Filename cannot be null"); URL url = getClassLoader().getResource(filename); if (url == null) { throw new FileNotFoundException("No resource '" + filename + "' found."); } URLConnection connection = url.openConnection(); connection.setUseCaches(false); return connection.getInputStream(); } @Override public SkyTranslations getTranslations() { return translations; } @Override public SkyConfiguration getConfiguration() { return configuration; } @Override public RandomChestConfiguration getChestRandomizer() { return chestConfiguration; } @Override public SkyLocationStore getLocationStore() { return locationStore; } @Override public GameQueue getGameQueue() { return gameQueue; } @Override public CurrentGames getCurrentGameTracker() { return currentGameTracker; } @Override public SkyGameHandler getGameHandler() { return gameHandler; } @Override public GameIDHandler getIDHandler() { return idHandler; } @Override public AttackerStorageListener getAttackerStorage() { return attackerStorage; } @Override public ScoreStorage getScore() { return score; } @Override public SkyEconomyHook getEconomyHook() { return economyHook; } @Override public SkyKits getKits() { return kits; } @Override public SkyKitGui getKitGui() { return kitGui; } @Override public Path getArenaPath() { return getDataPath().resolve("arenas"); } @Override public Path getDataPath() { return getDataFolder().toPath(); } @Override public OnlineSkyPlayers getPlayers() { return inGame; } public SkyWorldHandler getWorldHandler() { return worldHandler; } public GameBroadcaster getBroadcaster() { return broadcaster; } public ResetHealthListener getResetHealth() { return resetHealth; } public GameEventDistributor getDistributor() { return distributor; } public InventorySaveListener getInventorySaveListener() { return inventorySaveListener; } public SkyEconomyGameRewards getEcoRewards() { return ecoRewards; } public TeamScoreboardListener getTeamScoreBoardListener() { return teamListener; } public KitQueueNotifier getKitQueueNotifier() { return kitQueueNotifier; } public KitApplyListener getKitApplyListener() { return kitApplyListener; } public SignListener getSignListener() { return signListener; } public BackupInventoryClearListener getBackupInvClearListener() { return backupInventoryClearListener; } public GameQueueTimer getGameQueueTimer() { return gameQueueTimer; } @Override public boolean isMultiinvWorkaroundEnabled() { return multiinvWorkaroundEnabled; } }