package com.laytonsmith.abstraction.bukkit; import com.laytonsmith.PureUtilities.Common.ReflectionUtils; import com.laytonsmith.abstraction.MCCommandMap; import com.laytonsmith.abstraction.MCCommandSender; import com.laytonsmith.abstraction.MCConsoleCommandSender; import com.laytonsmith.abstraction.MCHumanEntity; import com.laytonsmith.abstraction.MCInventory; import com.laytonsmith.abstraction.MCInventoryHolder; import com.laytonsmith.abstraction.MCItemFactory; import com.laytonsmith.abstraction.MCItemStack; import com.laytonsmith.abstraction.MCOfflinePlayer; import com.laytonsmith.abstraction.MCPlayer; import com.laytonsmith.abstraction.MCPluginManager; import com.laytonsmith.abstraction.MCRecipe; import com.laytonsmith.abstraction.MCScoreboard; import com.laytonsmith.abstraction.MCServer; import com.laytonsmith.abstraction.MCWorld; import com.laytonsmith.abstraction.bukkit.entities.BukkitMCHumanEntity; import com.laytonsmith.abstraction.bukkit.entities.BukkitMCPlayer; import com.laytonsmith.abstraction.bukkit.pluginmessages.BukkitMCMessenger; import com.laytonsmith.abstraction.enums.MCInventoryType; import com.laytonsmith.abstraction.enums.MCVersion; import com.laytonsmith.abstraction.pluginmessages.MCMessenger; import com.laytonsmith.core.Static; import com.laytonsmith.core.constructs.Target; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; import org.bukkit.Server; import org.bukkit.World; import org.bukkit.command.CommandSender; import org.bukkit.command.SimpleCommandMap; import org.bukkit.entity.Player; import org.bukkit.event.inventory.InventoryType; import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.Recipe; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.UUID; /** * * */ public class BukkitMCServer implements MCServer { Server s; MCVersion version; public BukkitMCServer(){ this.s = Bukkit.getServer(); } public BukkitMCServer(Server server) { this.s = server; } @Override public Object getHandle(){ return s; } public Server __Server(){ return s; } @Override public String getName() { return s.getName(); } @Override public Collection<MCPlayer> getOnlinePlayers() { Collection<Player> players = getOnlinePlayersOverwrite(s); if(players == null){ return null; } Set<MCPlayer> mcpa = new HashSet<>(); for(Player p : players){ mcpa.add(new BukkitMCPlayer(p)); } return mcpa; } /** * The bukkit method getOnlinePlayers changed from returning a Player[] * to a Collection<Player>. This method abstracts that out. * @return */ public static Collection<Player> getOnlinePlayersOverwrite(Server s){ Object retValue = ReflectionUtils.invokeMethod(s, "getOnlinePlayers"); if(retValue == null){ return null; } if(retValue instanceof Collection){ // New version return (Collection<Player>) retValue; } else { // Old version, it's an array Set<Player> mcpa = new HashSet<>(); Player[] pa = (Player[]) retValue; for(Player p : pa){ mcpa.add(p); } return mcpa; } } public static MCServer Get() { return new BukkitMCServer(); } @Override public boolean dispatchCommand(MCCommandSender sender, String command){ CommandSender cs; if(sender instanceof BukkitMCPlayer){ cs = (CommandSender)((MCPlayer)sender).getHandle(); } else { cs = (CommandSender)((MCCommandSender)sender).getHandle(); } return s.dispatchCommand(cs, command); } private class CommandSenderInterceptor implements InvocationHandler { private final StringBuilder buffer; private final CommandSender sender; public CommandSenderInterceptor(CommandSender sender){ this.buffer = new StringBuilder(); this.sender = sender; } @Override public Object invoke(Object o, Method method, Object[] args) throws Throwable { if ("sendMessage".equals(method.getName())) { buffer.append(args[0].toString()); return Void.TYPE; } else { return method.invoke(sender, args); } } public String getBuffer(){ return buffer.toString(); } } @Override public String dispatchAndCaptureCommand(MCCommandSender commandSender, String cmd) { // Grab the CommandSender object from the abstraction layer CommandSender sender = (CommandSender)commandSender.getHandle(); // Create the interceptor CommandSenderInterceptor interceptor = new CommandSenderInterceptor(sender); // Create a new proxy and abstraction layer wrapper around the proxy CommandSender newCommandSender = (CommandSender)Proxy.newProxyInstance(BukkitMCServer.class.getClassLoader(), new Class[]{CommandSender.class}, interceptor); BukkitMCCommandSender aCommandSender = new BukkitMCCommandSender(newCommandSender); MCCommandSender oldSender = Static.UninjectPlayer(commandSender); // Inject our new wrapped object Static.InjectPlayer(aCommandSender); // Dispatch the command now try { s.dispatchCommand(newCommandSender, cmd); } finally { // Clean up Static.UninjectPlayer(aCommandSender); if(oldSender != null){ Static.InjectPlayer(oldSender); } } // Return the buffered text (if any) return interceptor.getBuffer(); } @Override public MCPluginManager getPluginManager() { if(s.getPluginManager() == null){ return null; } return new BukkitMCPluginManager(s.getPluginManager()); } @Override public MCPlayer getPlayer(String name) { Player p = s.getPlayer(name); if (p == null) { return null; } return new BukkitMCPlayer(p); } @Override public MCPlayer getPlayer(UUID uuid) { Player p = s.getPlayer(uuid); if (p == null) { return null; } return new BukkitMCPlayer(p); } @Override public MCWorld getWorld(String name) { if(s.getWorld(name) == null){ return null; } return new BukkitMCWorld(s.getWorld(name)); } @Override public List<MCWorld> getWorlds(){ if(s.getWorlds() == null){ return null; } List<MCWorld> list = new ArrayList<MCWorld>(); for(World w : s.getWorlds()){ list.add(new BukkitMCWorld(w)); } return list; } @Override public void broadcastMessage(String message) { s.broadcastMessage(message); } @Override public void broadcastMessage(String message, String permission) { s.broadcast(message, permission); } @Override public MCConsoleCommandSender getConsole() { return new BukkitMCConsoleCommandSender(s.getConsoleSender()); } @Override public MCItemFactory getItemFactory() { return new BukkitMCItemFactory(s.getItemFactory()); } @Override public MCCommandMap getCommandMap() { return new BukkitMCCommandMap((SimpleCommandMap) ReflectionUtils.invokeMethod(s.getClass(), s, "getCommandMap")); } @Override public MCOfflinePlayer getOfflinePlayer(String player) { return new BukkitMCOfflinePlayer(s.getOfflinePlayer(player)); } @Override public MCOfflinePlayer getOfflinePlayer(UUID uuid) { return new BukkitMCOfflinePlayer(s.getOfflinePlayer(uuid)); } @Override public MCOfflinePlayer[] getOfflinePlayers() { if (s.getOfflinePlayers() == null) { return null; } OfflinePlayer[] offp = s.getOfflinePlayers(); MCOfflinePlayer[] mcoff = new MCOfflinePlayer[offp.length]; for (int i = 0; i < offp.length; i++) { mcoff[i] = new BukkitMCOfflinePlayer(offp[i]); } return mcoff; } /* Boring information get methods -.- */ @Override public String getAPIVersion() { return s.getBukkitVersion(); } @Override public String getServerVersion() { return s.getVersion(); } @Override public MCVersion getMinecraftVersion() { if (version == null) { int temp = s.getBukkitVersion().indexOf('-'); version = MCVersion.match(s.getBukkitVersion().substring(0, temp).split("\\.")); } return version; } @Override public int getPort() { return s.getPort(); } @Override public String getIp() { return s.getIp(); } @Override public boolean getAllowEnd() { return s.getAllowEnd(); } @Override public boolean getAllowFlight() { return s.getAllowFlight(); } @Override public boolean getAllowNether() { return s.getAllowNether(); } @Override public boolean getOnlineMode() { return s.getOnlineMode(); } @Override public int getViewDistance() { return s.getViewDistance(); } @Override public String getWorldContainer() { return s.getWorldContainer().getPath(); } @Override public String getServerName() { return s.getServerName(); } @Override public int getMaxPlayers() { return s.getMaxPlayers(); } @Override public List<MCOfflinePlayer> getBannedPlayers() { if(s.getBannedPlayers() == null){ return null; } List<MCOfflinePlayer> list = new ArrayList<MCOfflinePlayer>(); for(OfflinePlayer p : s.getBannedPlayers()){ list.add(getOfflinePlayer(p.getName())); } return list; } @Override public List<MCOfflinePlayer> getWhitelistedPlayers() { if(s.getBannedPlayers() == null){ return null; } List<MCOfflinePlayer> list = new ArrayList<MCOfflinePlayer>(); for(OfflinePlayer p : s.getWhitelistedPlayers()){ list.add(getOfflinePlayer(p.getName())); } return list; } @Override public List<MCOfflinePlayer> getOperators() { if(s.getOperators() == null){ return null; } List<MCOfflinePlayer> list = new ArrayList<MCOfflinePlayer>(); for(OfflinePlayer p : s.getOperators()){ list.add(getOfflinePlayer(p.getName())); } return list; } @Override public void runasConsole(String cmd) { CommandSender sender = (CommandSender)Static.GetCommandSender("~console", Target.UNKNOWN).getHandle(); s.dispatchCommand(sender, cmd); } @Override public String toString() { return s.toString(); } @Override public boolean equals(Object obj) { return (obj instanceof BukkitMCServer && s.equals(((BukkitMCServer) obj).s)); } @Override public int hashCode() { return s.hashCode(); } @Override public MCInventory createInventory(MCInventoryHolder holder, MCInventoryType type) { InventoryHolder ih = null; if (holder instanceof MCPlayer) { ih = ((BukkitMCPlayer)holder)._Player(); } else if (holder instanceof MCHumanEntity) { ih = ((BukkitMCHumanEntity)holder).asHumanEntity(); } else if (holder.getHandle() instanceof InventoryHolder) { ih = (InventoryHolder)holder.getHandle(); } return new BukkitMCInventory(Bukkit.createInventory(ih, InventoryType.valueOf(type.name()))); } @Override public MCInventory createInventory(MCInventoryHolder holder, int size) { InventoryHolder ih = null; if (holder instanceof MCPlayer) { ih = ((BukkitMCPlayer)holder)._Player(); } else if (holder instanceof MCHumanEntity) { ih = ((BukkitMCHumanEntity)holder).asHumanEntity(); } else if (holder.getHandle() instanceof InventoryHolder) { ih = (InventoryHolder)holder.getHandle(); } return new BukkitMCInventory(Bukkit.createInventory(ih, size)); } @Override public MCInventory createInventory(MCInventoryHolder holder, int size, String title) { InventoryHolder ih = null; if (holder instanceof MCPlayer) { ih = ((BukkitMCPlayer)holder)._Player(); } else if (holder instanceof MCHumanEntity) { ih = ((BukkitMCHumanEntity)holder).asHumanEntity(); } else if (holder.getHandle() instanceof InventoryHolder) { ih = (InventoryHolder)holder.getHandle(); } return new BukkitMCInventory(Bukkit.createInventory(ih, size, title)); } @Override public void banIP(String address) { s.banIP(address); } @Override public Set<String> getIPBans() { return s.getIPBans(); } @Override public void unbanIP(String address) { s.unbanIP(address); } @Override public MCMessenger getMessenger() { return new BukkitMCMessenger(s.getMessenger()); } @Override public MCScoreboard getMainScoreboard() { return new BukkitMCScoreboard(s.getScoreboardManager().getMainScoreboard()); } @Override public MCScoreboard getNewScoreboard() { return new BukkitMCScoreboard(s.getScoreboardManager().getNewScoreboard()); } @Override public boolean unloadWorld(MCWorld world, boolean save) { return s.unloadWorld(((BukkitMCWorld) world).__World(), save); } @Override public void savePlayers() { s.savePlayers(); } @Override public void shutdown() { s.shutdown(); } @Override public boolean addRecipe(MCRecipe recipe) { return s.addRecipe(((BukkitMCRecipe) recipe).r); } @Override public List<MCRecipe> getRecipesFor(MCItemStack result) { List<MCRecipe> ret = new ArrayList<MCRecipe>(); List<Recipe> recipes = s.getRecipesFor(((BukkitMCItemStack) result).__ItemStack()); for (Recipe recipe : recipes) { ret.add(BukkitConvertor.BukkitGetRecipe(recipe)); } return ret; } @Override public List<MCRecipe> allRecipes() { List<MCRecipe> ret = new ArrayList<MCRecipe>(); for (Iterator recipes = s.recipeIterator(); recipes.hasNext();) { Recipe recipe = (Recipe) recipes.next(); ret.add(BukkitConvertor.BukkitGetRecipe(recipe)); } return ret; } // public Iterator<MCRecipe> recipe iterator() { // Iterator<MCRecipe> ret = //create iterator; // } @Override public void clearRecipes() { s.clearRecipes(); } @Override public void resetRecipes() { s.resetRecipes(); } }