/* * This file is part of SpoutcraftPlugin. * * Copyright (c) 2011 SpoutcraftDev <http://spoutcraft.org//> * SpoutcraftPlugin is licensed under the GNU Lesser General Public License. * * SpoutcraftPlugin is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * SpoutcraftPlugin 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.getspout.spout; import java.io.File; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import net.minecraft.server.v1_6_R3.Packet18ArmAnimation; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; import org.bukkit.permissions.Permission; import org.bukkit.permissions.PermissionDefault; import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.java.JavaPlugin; import org.getspout.spout.block.SpoutCraftChunk; import org.getspout.spout.block.mcblock.CustomMCBlock; import org.getspout.spout.command.SpoutCommand; import org.getspout.spout.config.ConfigReader; import org.getspout.spout.inventory.SimpleMaterialManager; import org.getspout.spout.inventory.SpoutInventoryBuilder; import org.getspout.spout.item.mcitem.CustomItemFlint; import org.getspout.spout.item.mcitem.CustomItemPickaxe; import org.getspout.spout.item.mcitem.CustomItemSpade; import org.getspout.spout.keyboard.SimpleKeyBindingManager; import org.getspout.spout.listeners.SpoutBlockListener; import org.getspout.spout.listeners.SpoutPlayerListener; import org.getspout.spout.listeners.PluginListener; import org.getspout.spout.listeners.SpoutWorldListener; import org.getspout.spout.listeners.SpoutEntityListener; import org.getspout.spout.listeners.InventoryListener; import org.getspout.spout.packet.CustomPacket; import org.getspout.spout.packet.SimplePacketManager; import org.getspout.spout.player.SimpleBiomeManager; import org.getspout.spout.player.SimpleFileManager; import org.getspout.spout.player.SimplePlayerChunkMap; import org.getspout.spout.player.SimpleSkyManager; import org.getspout.spout.player.SpoutCraftPlayer; import org.getspout.spout.sound.SimpleSoundManager; import org.getspout.spout.util.DeadlockMonitor; import org.getspout.spoutapi.SpoutManager; import org.getspout.spoutapi.chunkstore.SimpleChunkDataManager; import org.getspout.spoutapi.inventory.ItemMap; import org.getspout.spoutapi.io.CRCStore; import org.getspout.spoutapi.io.store.FlatFileStore; import org.getspout.spoutapi.packet.PacketRenderDistance; import org.getspout.spoutapi.player.SpoutPlayer; public class Spout extends JavaPlugin { public SpoutPlayerListener playerListener; protected SpoutWorldListener chunkListener; protected SpoutWorldMonitorListener chunkMonitorListener; protected SpoutBlockListener blockListener; protected SpoutEntityListener entityListener; protected PluginListener pluginListener; protected SpoutCustomBlockMonitor blockMonitor; protected static Spout instance; protected FlatFileStore<String> CRCConfig; protected FlatFileStore<Integer> itemMapConfig; protected ItemMap serverItemMap; protected final List<SpoutPlayer> playersOnline = new ArrayList<SpoutPlayer>(); protected Thread shutdownThread = null; protected InventoryListener invListener; private boolean hardDisable = false; public Spout() { super(); Spout.instance = this; SpoutManager.getInstance().setSoundManager(new SimpleSoundManager()); SpoutManager.getInstance().setSkyManager(new SimpleSkyManager()); SpoutManager.getInstance().setInventoryBuilder(new SpoutInventoryBuilder()); SpoutManager.getInstance().setPacketManager(new SimplePacketManager()); SpoutManager.getInstance().setPlayerChunkMap(new SimplePlayerChunkMap()); SpoutManager.getInstance().setChunkDataManager(new SimpleChunkDataManager()); SpoutManager.getInstance().setBiomeManager(new SimpleBiomeManager()); SpoutManager.getInstance().setFileManager(new SimpleFileManager()); SpoutManager.getInstance().setKeyBindingManager(new SimpleKeyBindingManager()); SpoutManager.getInstance().setMaterialManager(new SimpleMaterialManager()); SpoutManager.getInstance().setWorldManager(new SimpleWorldManager()); shutdownThread = new ShutdownThread(); Runtime.getRuntime().addShutdownHook(shutdownThread); } @Override public void onDisable() { if (hardDisable) { Runtime.getRuntime().removeShutdownHook(shutdownThread); return; } // Order matters CustomMCBlock.resetBlocks(); ((SimpleMaterialManager) SpoutManager.getMaterialManager()).reset(); ((SimpleSkyManager) SpoutManager.getSkyManager()).reset(); ((SimplePlayerChunkMap) SpoutManager.getPlayerChunkMap()).onPluginDisable(); Player[] online = getServer().getOnlinePlayers(); for (Player player : online) { try { SpoutCraftPlayer scp = (SpoutCraftPlayer) SpoutCraftPlayer.getPlayer(player); scp.resetMovement(); if (scp.isSpoutCraftEnabled()) { scp.sendPacket(new PacketRenderDistance(true, true)); } } catch (Exception e) { e.printStackTrace(); } } SpoutCraftChunk.resetAllBukkitChunks(); getServer().getScheduler().cancelTasks(this); SimpleChunkDataManager dm = (SimpleChunkDataManager) SpoutManager.getChunkDataManager(); dm.unloadAllChunks(); dm.closeAllFiles(); CRCConfig.save(); if (itemMapConfig != null) { synchronized (itemMapConfig) { itemMapConfig.save(); } } SimpleFileManager.clearTempDirectory(); // End the thread PacketCompressionThread.endThread(); Runtime.getRuntime().removeShutdownHook(shutdownThread); super.onDisable(); } @Override public void onEnable() { (new ConfigReader()).read(); // The infamous SpoutPlugin build check if (ConfigReader.isBuildCheck()) { InputStream is = getResource("plugin.yml"); final YamlConfiguration config = YamlConfiguration.loadConfiguration(is); final String currentVersion = Bukkit.getBukkitVersion(); final List<String> supportedVersions = config.getStringList("supportedVersions"); if (!supportedVersions.contains(currentVersion.substring(0, 10))) { hardDisable = true; Bukkit.getPluginManager().disablePlugin(this); Bukkit.getLogger().warning( "\n-----------------------------------------------------------------------------\n" + " SpoutcraftPlugin has been disabled due to version mismatch.\n" + " * You are currently running CraftBukkit " + currentVersion + "\n" + " * You must run one of the following CraftBukkit versions...\n" + supportedVersions.toString().replace("[", " * ").replace(", ", "\n * ").replace("]", "\n") + " * To bypass this restriction, disable 'ServerVersionCheck' in \n" + " SpoutcraftPlugin's config.yml. Do so at your own risk.\n" + "-----------------------------------------------------------------------------"); } } if (!hardDisable) { playerListener = new SpoutPlayerListener(this); chunkListener = new SpoutWorldListener(this); chunkMonitorListener = new SpoutWorldMonitorListener(this); pluginListener = new PluginListener(this); entityListener = new SpoutEntityListener(this); blockMonitor = new SpoutCustomBlockMonitor(this); blockListener = new SpoutBlockListener(this); invListener = new InventoryListener(this); for (SpoutPlayer player : org.getspout.spoutapi.Spout.getServer().getOnlinePlayers()) { SpoutCraftPlayer.resetPlayerConnection(player); SpoutCraftPlayer.updatePlayerConnection(player); SpoutCraftPlayer.updateBukkitEntity(player); authenticate(player); playerListener.manager.onPlayerJoin(player); ((SimplePlayerChunkMap) SpoutManager.getPlayerChunkMap()).onPlayerJoin(player); player.setPreCachingComplete(true); // Already done if we are already online! synchronized (playersOnline) { playersOnline.add(player); } } SpoutCraftChunk.replaceAllBukkitChunks(); ((SimplePlayerChunkMap) SpoutManager.getPlayerChunkMap()).onPluginEnable(); CustomItemSpade.replaceSpades(); CustomItemPickaxe.replacePickaxes(); CustomItemFlint.replaceFlint(); CustomMCBlock.replaceBlocks(); PacketCompressionThread.startThread(); // Start counting ticks Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(this, new ServerTickTask(), 0, 1); // Remove mappings from previous loads // Can not remove them on disable because the packets will still be in the send queue CustomPacket.removeClassMapping(); CustomPacket.addClassMapping(); SimpleChunkDataManager dm = (SimpleChunkDataManager) SpoutManager.getChunkDataManager(); dm.loadAllChunks(); SimpleMaterialManager.disableFlintStackMix(); try { Class.forName("org.getspout.spoutapi.inventory.SpoutEnchantment"); } catch (ClassNotFoundException e) { e.printStackTrace(); } } // These are safe even if the build check fails getCommand("spout").setExecutor(new SpoutCommand(this)); CRCConfig = new FlatFileStore<String>(new File(this.getDataFolder(), "CRCCache.txt"), String.class); CRCConfig.load(); CRCStore.setConfigFile(CRCConfig); itemMapConfig = new FlatFileStore<Integer>(new File(this.getDataFolder(), "itemMap.txt"), Integer.class); if (!itemMapConfig.load()) { System.out.println("[SpoutPlugin] Unable to load global item map"); } else { serverItemMap = new ItemMap(null, itemMapConfig, null); } ItemMap.setRootMap(serverItemMap); if (ConfigReader.runDeadlockMonitor()) { new DeadlockMonitor().start(); } super.onEnable(); } public List<SpoutPlayer> getOnlinePlayers() { return playersOnline; } /** * Gets the singleton instance of the Spout plugin * @return Spout plugin */ public static Spout getInstance() { return instance; } public void authenticate(Player player) { Packet18ArmAnimation packet = new Packet18ArmAnimation(); packet.a = -42; ((SpoutCraftPlayer) SpoutCraftPlayer.getPlayer(player)).getPlayerConnection().sendImmediatePacket(packet); } } class ShutdownThread extends Thread { public void run() { SimpleChunkDataManager dm = (SimpleChunkDataManager) SpoutManager.getChunkDataManager(); dm.unloadAllChunks(); dm.closeAllFiles(); } }