package com.laytonsmith.abstraction.bukkit; import com.laytonsmith.PureUtilities.Common.ReflectionUtils; import com.laytonsmith.PureUtilities.DaemonManager; import com.laytonsmith.abstraction.AbstractConvertor; import com.laytonsmith.abstraction.ConvertorHelper; import com.laytonsmith.abstraction.Implementation; import com.laytonsmith.abstraction.MCColor; import com.laytonsmith.abstraction.MCCommand; import com.laytonsmith.abstraction.MCCommandSender; import com.laytonsmith.abstraction.MCEnchantment; import com.laytonsmith.abstraction.MCEntity; import com.laytonsmith.abstraction.MCFireworkBuilder; import com.laytonsmith.abstraction.MCInventory; import com.laytonsmith.abstraction.MCItemMeta; import com.laytonsmith.abstraction.MCItemStack; import com.laytonsmith.abstraction.MCLocation; import com.laytonsmith.abstraction.MCMetadataValue; import com.laytonsmith.abstraction.MCNote; import com.laytonsmith.abstraction.MCPattern; import com.laytonsmith.abstraction.MCPlugin; import com.laytonsmith.abstraction.MCPluginMeta; import com.laytonsmith.abstraction.MCPotionData; import com.laytonsmith.abstraction.MCRecipe; import com.laytonsmith.abstraction.MCServer; import com.laytonsmith.abstraction.MCWorld; import com.laytonsmith.abstraction.MCWorldCreator; import com.laytonsmith.abstraction.blocks.MCBlockState; import com.laytonsmith.abstraction.blocks.MCMaterial; import com.laytonsmith.abstraction.bukkit.blocks.BukkitMCBanner; import com.laytonsmith.abstraction.bukkit.blocks.BukkitMCBlockState; import com.laytonsmith.abstraction.bukkit.blocks.BukkitMCMaterial; import com.laytonsmith.abstraction.bukkit.blocks.BukkitMCShulkerBox; import com.laytonsmith.abstraction.bukkit.entities.BukkitMCAgeable; import com.laytonsmith.abstraction.bukkit.entities.BukkitMCComplexEntityPart; import com.laytonsmith.abstraction.bukkit.entities.BukkitMCComplexLivingEntity; import com.laytonsmith.abstraction.bukkit.entities.BukkitMCEntity; import com.laytonsmith.abstraction.bukkit.entities.BukkitMCHanging; import com.laytonsmith.abstraction.bukkit.entities.BukkitMCHumanEntity; import com.laytonsmith.abstraction.bukkit.entities.BukkitMCLivingEntity; import com.laytonsmith.abstraction.bukkit.entities.BukkitMCMinecart; import com.laytonsmith.abstraction.bukkit.entities.BukkitMCPlayer; import com.laytonsmith.abstraction.bukkit.entities.BukkitMCProjectile; import com.laytonsmith.abstraction.bukkit.entities.BukkitMCTameable; import com.laytonsmith.abstraction.bukkit.entities.BukkitMCVehicle; import com.laytonsmith.abstraction.bukkit.events.BukkitAbstractEventMixin; import com.laytonsmith.abstraction.bukkit.events.drivers.BukkitBlockListener; import com.laytonsmith.abstraction.bukkit.events.drivers.BukkitEntityListener; import com.laytonsmith.abstraction.bukkit.events.drivers.BukkitInventoryListener; import com.laytonsmith.abstraction.bukkit.events.drivers.BukkitPlayerListener; import com.laytonsmith.abstraction.bukkit.events.drivers.BukkitServerListener; import com.laytonsmith.abstraction.bukkit.events.drivers.BukkitVehicleListener; import com.laytonsmith.abstraction.bukkit.events.drivers.BukkitWeatherListener; import com.laytonsmith.abstraction.bukkit.events.drivers.BukkitWorldListener; import com.laytonsmith.abstraction.enums.MCDyeColor; import com.laytonsmith.abstraction.enums.MCEntityType; import com.laytonsmith.abstraction.enums.MCPatternShape; import com.laytonsmith.abstraction.enums.MCPotionType; import com.laytonsmith.abstraction.enums.MCRecipeType; import com.laytonsmith.abstraction.enums.MCTone; import com.laytonsmith.abstraction.enums.MCVersion; import com.laytonsmith.abstraction.enums.bukkit.BukkitMCDyeColor; import com.laytonsmith.abstraction.enums.bukkit.BukkitMCEntityType; import com.laytonsmith.abstraction.enums.bukkit.BukkitMCPatternShape; import com.laytonsmith.abstraction.enums.bukkit.BukkitMCPotionType; import com.laytonsmith.annotations.convert; import com.laytonsmith.commandhelper.CommandHelperPlugin; import com.laytonsmith.core.CHLog; import com.laytonsmith.core.LogLevel; import com.laytonsmith.core.Static; import com.laytonsmith.core.constructs.Target; import com.laytonsmith.core.environments.CommandHelperEnvironment; import com.laytonsmith.core.environments.Environment; import com.laytonsmith.core.exceptions.CRE.CREFormatException; import com.laytonsmith.core.exceptions.CancelCommandException; import org.bukkit.Bukkit; import org.bukkit.Color; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.World; import org.bukkit.block.Banner; import org.bukkit.block.Block; import org.bukkit.block.BlockState; import org.bukkit.block.CreatureSpawner; import org.bukkit.block.DoubleChest; import org.bukkit.block.ShulkerBox; import org.bukkit.block.banner.Pattern; import org.bukkit.command.BlockCommandSender; import org.bukkit.command.CommandSender; import org.bukkit.command.ConsoleCommandSender; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Ageable; import org.bukkit.entity.ComplexEntityPart; import org.bukkit.entity.ComplexLivingEntity; import org.bukkit.entity.Entity; import org.bukkit.entity.Hanging; import org.bukkit.entity.HumanEntity; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Minecart; import org.bukkit.entity.Player; import org.bukkit.entity.Projectile; import org.bukkit.entity.Tameable; import org.bukkit.entity.Vehicle; import org.bukkit.inventory.FurnaceRecipe; import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.Recipe; import org.bukkit.inventory.ShapedRecipe; import org.bukkit.inventory.ShapelessRecipe; import org.bukkit.inventory.meta.*; import org.bukkit.material.MaterialData; import org.bukkit.metadata.FixedMetadataValue; import org.bukkit.potion.PotionData; import org.yaml.snakeyaml.Yaml; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; import java.util.logging.Level; /** * * */ @convert(type = Implementation.Type.BUKKIT) public class BukkitConvertor extends AbstractConvertor { private static BukkitMCPluginMeta pluginMeta = null; @Override public MCLocation GetLocation(MCWorld w, double x, double y, double z, float yaw, float pitch) { World w2 = null; if (w != null) { w2 = ((BukkitMCWorld) w).__World(); } return new BukkitMCLocation(new Location(w2, x, y, z, yaw, pitch)); } @Override public Class GetServerEventMixin() { return BukkitAbstractEventMixin.class; } @Override public MCEnchantment[] GetEnchantmentValues() { MCEnchantment[] ea = new MCEnchantment[Enchantment.values().length]; Enchantment[] oea = Enchantment.values(); for (int i = 0; i < ea.length; i++) { ea[i] = new BukkitMCEnchantment(oea[i]); } return ea; } @Override public MCEnchantment GetEnchantmentByName(String name) { try { //If they are looking it up by number, we can support that int i = Integer.valueOf(name); return new BukkitMCEnchantment(Enchantment.getById(i)); } catch (NumberFormatException e) { try { return new BukkitMCEnchantment(Enchantment.getByName(name)); } catch (NullPointerException ee) { return null; } } catch(NullPointerException e) { return null; } } @Override public MCServer GetServer() { return BukkitMCServer.Get(); } @Override public MCMaterial getMaterial(int id) { Material mat = Material.getMaterial(id); return mat == null ? null : new BukkitMCMaterial(mat); } @Override public MCItemStack GetItemStack(int type, int qty) { return new BukkitMCItemStack(new ItemStack(type, qty)); } @Override public MCItemStack GetItemStack(int type, int data, int qty) { return new BukkitMCItemStack(new ItemStack(type, qty, (short) data)); } @Override public MCItemStack GetItemStack(MCMaterial type, int qty) { return new BukkitMCItemStack(new ItemStack(((BukkitMCMaterial) type).getHandle(), qty)); } @Override public MCItemStack GetItemStack(MCMaterial type, int data, int qty) { return new BukkitMCItemStack(new ItemStack(((BukkitMCMaterial) type).getHandle(), qty, (short) data)); } public MCItemStack GetItemStack(String type, int qty) { Material mat = Material.matchMaterial(type); if (mat == null) { return null; } return new BukkitMCItemStack(new ItemStack(mat, qty)); } public MCItemStack GetItemStack(String type, int data, int qty) { Material mat = Material.matchMaterial(type); if (mat == null) { return null; } return new BukkitMCItemStack(new ItemStack(mat, qty, (short) data)); } public MCPotionData GetPotionData(MCPotionType type, boolean extended, boolean upgraded){ return new BukkitMCPotionData(new PotionData( BukkitMCPotionType.getConvertor().getConcreteEnum(type), extended, upgraded)); } @Override public MCMetadataValue GetMetadataValue(Object value, MCPlugin plugin) { return new BukkitMCMetadataValue(new FixedMetadataValue(((BukkitMCPlugin) plugin).getHandle(), value)); } public static final BukkitBlockListener BlockListener = new BukkitBlockListener(); public static final BukkitEntityListener EntityListener = new BukkitEntityListener(); public static final BukkitInventoryListener InventoryListener = new BukkitInventoryListener(); public static final BukkitPlayerListener PlayerListener = new BukkitPlayerListener(); public static final BukkitServerListener ServerListener = new BukkitServerListener(); public static final BukkitVehicleListener VehicleListener = new BukkitVehicleListener(); public static final BukkitWeatherListener WeatherListener = new BukkitWeatherListener(); public static final BukkitWorldListener WorldListener = new BukkitWorldListener(); @Override public void Startup(CommandHelperPlugin chp) { chp.registerEvents(BlockListener); chp.registerEventsDynamic(EntityListener); chp.registerEventsDynamic(InventoryListener); chp.registerEvents(PlayerListener); chp.registerEvents(ServerListener); chp.registerEvents(VehicleListener); chp.registerEvents(WeatherListener); chp.registerEvents(WorldListener); } @Override public int LookupItemId(String materialName) { if (Material.matchMaterial(materialName) != null) { return new MaterialData(Material.matchMaterial(materialName)).getItemTypeId(); } else { return -1; } } @Override public String LookupMaterialName(int id) { return Material.getMaterial(id).toString(); } @Override protected void triggerRunnable(final Runnable r) { try { runOnMainThreadAndWait(new Callable<Object>() { @Override public Object call() throws Exception { r.run(); return null; } }); } catch(CancellationException ex) { // Ignore the Exception when the plugin is disabled (server shutting down). if(CommandHelperPlugin.self.isEnabled()) { java.util.logging.Logger.getLogger(BukkitConvertor.class.getName()).log(Level.SEVERE, null, ex); } } catch (InterruptedException | ExecutionException ex) { java.util.logging.Logger.getLogger(BukkitConvertor.class.getName()).log(Level.SEVERE, null, ex); } } // /** // * We don't want to allow scripts to clear other plugin's tasks // * on accident, so only ids registered through our interface // * can also be cancelled. // */ // private static final Set<Integer> validIDs = new TreeSet<Integer>(); // // @Override // public synchronized int SetFutureRunnable(DaemonManager dm, long ms, Runnable r) { // int id = Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(CommandHelperPlugin.self, r, Static.msToTicks(ms)); // validIDs.add(id); // return id; // } // // @Override // public synchronized int SetFutureRepeater(DaemonManager dm, long ms, long initialDelay, Runnable r){ // int id = Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(CommandHelperPlugin.self, r, Static.msToTicks(initialDelay), Static.msToTicks(ms)); // validIDs.add(id); // return id; // } // // @Override // public synchronized void ClearAllRunnables() { // //Doing cancelTasks apparently does not work, so let's just manually cancel each task, which does appear to work. // //Anyways, it's better that way anyhow, because we actually remove IDs from validIDs that way. // //((BukkitMCServer)Static.getServer()).__Server().getScheduler().cancelTasks(CommandHelperPlugin.self); // Set<Integer> ids = new TreeSet<Integer>(validIDs); // for(int id : ids){ // try{ // //If this doesn't work, it shouldn't kill everything. // ClearFutureRunnable(id); // } catch(Exception e){ // Logger.getLogger(BukkitConvertor.class.getName()).log(null, Level.SEVERE, e); // } // } // } // // @Override // public void ClearFutureRunnable(int id) { // if(validIDs.contains(id)){ // Bukkit.getServer().getScheduler().cancelTask(id); // validIDs.remove(id); // } // } public static MCEntity BukkitGetCorrectEntity(Entity be) { if (be == null) { return null; } BukkitMCEntityType type = BukkitMCEntityType.valueOfConcrete(be.getType()); if (type.getWrapperClass() != null) { return ReflectionUtils.newInstance(type.getWrapperClass(), new Class[]{Entity.class}, new Object[]{be}); } if (be instanceof Hanging) { type.setWrapperClass(BukkitMCHanging.class); return new BukkitMCHanging(be); } if (be instanceof Minecart) { // Must come before Vehicle type.setWrapperClass(BukkitMCMinecart.class); return new BukkitMCMinecart(be); } if (be instanceof Projectile) { type.setWrapperClass(BukkitMCProjectile.class); return new BukkitMCProjectile(be); } if (be instanceof Tameable) { // Must come before Ageable type.setWrapperClass(BukkitMCTameable.class); return new BukkitMCTameable(be); } if (be instanceof Ageable) { // Must come before LivingEntity type.setWrapperClass(BukkitMCAgeable.class); return new BukkitMCAgeable(be); } if (be instanceof HumanEntity) { // Must come before LivingEntity type.setWrapperClass(BukkitMCHumanEntity.class); return new BukkitMCHumanEntity(be); } if (be instanceof ComplexEntityPart) { type.setWrapperClass(BukkitMCComplexEntityPart.class); return new BukkitMCComplexEntityPart(be); } if (be instanceof ComplexLivingEntity) { // Must come before LivingEntity type.setWrapperClass(BukkitMCComplexLivingEntity.class); return new BukkitMCComplexLivingEntity(be); } if (be instanceof LivingEntity) { type.setWrapperClass(BukkitMCLivingEntity.class); return new BukkitMCLivingEntity(be); } if (be instanceof Vehicle) { type.setWrapperClass(BukkitMCVehicle.class); return new BukkitMCVehicle(be); } // Handle generically if we can't find a more specific type type.setWrapperClass(BukkitMCEntity.class); return new BukkitMCEntity(be); } @Override public MCEntity GetCorrectEntity(MCEntity e) { Entity be = ((BukkitMCEntity) e).getHandle(); try { return BukkitConvertor.BukkitGetCorrectEntity(be); } catch (IllegalArgumentException iae) { CHLog.GetLogger().Log(CHLog.Tags.RUNTIME, LogLevel.INFO, iae.getMessage(), Target.UNKNOWN); return e; } } @Override public MCItemMeta GetCorrectMeta(MCItemMeta im) { ItemMeta bim = ((BukkitMCItemMeta) im).asItemMeta(); return BukkitConvertor.BukkitGetCorrectMeta(bim); } @Override public List<MCEntity> GetEntitiesAt(MCLocation location, double radius) { if (location == null) { return Collections.EMPTY_LIST; } if (radius <= 0) { radius = 1; } Entity tempEntity = ((BukkitMCEntity) location.getWorld().spawn(location, MCEntityType.MCVanillaEntityType.ARROW)).getHandle(); List<Entity> near = tempEntity.getNearbyEntities(radius, radius, radius); tempEntity.remove(); List<MCEntity> entities = new ArrayList<MCEntity>(); for (Entity e : near) { entities.add(BukkitGetCorrectEntity(e)); } return entities; } public static MCBlockState BukkitGetCorrectBlockState(BlockState bs) { MCVersion version = Static.getServer().getMinecraftVersion(); if(version.gte(MCVersion.MC1_11) && bs instanceof ShulkerBox){ return new BukkitMCShulkerBox((ShulkerBox) bs); } if(version.gte(MCVersion.MC1_9) && bs instanceof Banner){ return new BukkitMCBanner((Banner) bs); } if(bs instanceof CreatureSpawner){ return new BukkitMCCreatureSpawner((CreatureSpawner) bs); } return new BukkitMCBlockState(bs); } public static MCItemMeta BukkitGetCorrectMeta(ItemMeta im) { MCVersion version = Static.getServer().getMinecraftVersion(); if (version.gte(MCVersion.MC1_11_X) && im instanceof SpawnEggMeta) { return new BukkitMCSpawnEggMeta((SpawnEggMeta) im); } if (version.gte(MCVersion.MC1_8_6) && im instanceof BlockStateMeta) { return new BukkitMCBlockStateMeta((BlockStateMeta) im); } if (version.gte(MCVersion.MC1_8) && im instanceof BannerMeta) { return new BukkitMCBannerMeta((BannerMeta) im); } if (im instanceof BookMeta) { return new BukkitMCBookMeta((BookMeta) im); } if (im instanceof EnchantmentStorageMeta) { return new BukkitMCEnchantmentStorageMeta((EnchantmentStorageMeta) im); } if (im instanceof FireworkEffectMeta) { return new BukkitMCFireworkEffectMeta((FireworkEffectMeta) im); } if (im instanceof FireworkMeta) { return new BukkitMCFireworkMeta((FireworkMeta) im); } if (im instanceof LeatherArmorMeta) { return new BukkitMCLeatherArmorMeta((LeatherArmorMeta) im); } if (im instanceof PotionMeta) { return new BukkitMCPotionMeta((PotionMeta) im); } if (im instanceof SkullMeta) { return new BukkitMCSkullMeta((SkullMeta) im); } return new BukkitMCItemMeta(im); } @Override public MCInventory GetEntityInventory(MCEntity e) { Entity entity = ((BukkitMCEntity) e).getHandle(); if (entity instanceof InventoryHolder) { if (entity instanceof Player) { return new BukkitMCPlayerInventory(((Player) entity).getInventory()); } else { return new BukkitMCInventory(((InventoryHolder) entity).getInventory()); } } else { return null; } } @Override public MCInventory GetLocationInventory(MCLocation location) { Block b = ((Location) (location.getHandle())).getBlock(); if (b.getState() instanceof InventoryHolder) { if (b.getState() instanceof DoubleChest) { DoubleChest dc = (DoubleChest) (b.getState()); return new BukkitMCDoubleChest(dc.getLeftSide().getInventory(), dc.getRightSide().getInventory()); } else { return new BukkitMCInventory(((InventoryHolder) b.getState()).getInventory()); } } else { return null; } } @Override public void runOnMainThreadLater(DaemonManager dm, final Runnable r) { if(!CommandHelperPlugin.self.isEnabled()) { throw new CancelCommandException(Implementation.GetServerType().getBranding() + " tried to schedule a task while the plugin was disabled (is the server shutting down?).", Target.UNKNOWN); } Bukkit.getServer().getScheduler().callSyncMethod(CommandHelperPlugin.self, new Callable<Object>() { @Override public Object call() throws Exception { r.run(); return null; } }); } @Override public <T> T runOnMainThreadAndWait(Callable<T> callable) throws InterruptedException, ExecutionException { if(!CommandHelperPlugin.self.isEnabled()) { throw new CancelCommandException(Implementation.GetServerType().getBranding() + " tried to schedule a task while the plugin was disabled (is the server shutting down?).", Target.UNKNOWN); } return Bukkit.getServer().getScheduler().callSyncMethod(CommandHelperPlugin.self, callable).get(); } @Override public MCWorldCreator getWorldCreator(String worldName) { return new BukkitMCWorldCreator(worldName); } @Override public MCNote GetNote(int octave, MCTone tone, boolean sharp) { return new BukkitMCNote(octave, tone, sharp); } @Override public MCColor GetColor(int red, int green, int blue) { return BukkitMCColor.GetMCColor(Color.fromRGB(red, green, blue)); } @Override public MCPattern GetPattern(MCDyeColor color, MCPatternShape shape) { return new BukkitMCPattern(new Pattern(BukkitMCDyeColor.getConvertor().getConcreteEnum(color), BukkitMCPatternShape.getConvertor().getConcreteEnum(shape))); } @Override public MCFireworkBuilder GetFireworkBuilder() { return new BukkitMCFireworkBuilder(); } @Override public MCPluginMeta GetPluginMeta() { if (pluginMeta == null) { pluginMeta = new BukkitMCPluginMeta(CommandHelperPlugin.self); addShutdownHook(new Runnable() { @Override public void run() { pluginMeta = null; } }); } return pluginMeta; } @Override public MCRecipe GetNewRecipe(MCRecipeType type, MCItemStack result) { switch (type) { case FURNACE: return new BukkitMCFurnaceRecipe(result); case SHAPED: return new BukkitMCShapedRecipe(result); case SHAPELESS: return new BukkitMCShapelessRecipe(result); } return null; } @Override public MCRecipe GetRecipe(MCRecipe unspecific) { Recipe r = ((BukkitMCRecipe) unspecific).r; return BukkitGetRecipe(r); } public static MCRecipe BukkitGetRecipe(Recipe r) { if (r instanceof ShapelessRecipe) { return new BukkitMCShapelessRecipe((ShapelessRecipe) r); } else if (r instanceof ShapedRecipe) { return new BukkitMCShapedRecipe((ShapedRecipe) r); } else if (r instanceof FurnaceRecipe) { return new BukkitMCFurnaceRecipe((FurnaceRecipe) r); } else { return null; } } @Override public MCCommand getNewCommand(String name) { return BukkitMCCommand.newCommand(name); } @Override public MCCommandSender GetCorrectSender(MCCommandSender unspecific) { if (unspecific == null) { return null; } return BukkitGetCorrectSender(((BukkitMCCommandSender) unspecific)._CommandSender()); } public static MCCommandSender BukkitGetCorrectSender(CommandSender sender) { if (sender instanceof Player) { return new BukkitMCPlayer((Player) sender); } else if (sender instanceof ConsoleCommandSender) { return new BukkitMCConsoleCommandSender((ConsoleCommandSender) sender); } else if (sender instanceof BlockCommandSender) { return new BukkitMCBlockCommandSender((BlockCommandSender) sender); } else { return null; } } @Override public MCMaterial GetMaterial(String name) { Material match = Material.matchMaterial(name); if (match == null) { return null; } return new BukkitMCMaterial(match); } @Override public String GetPluginName() { return (String) new Yaml().loadAs(getClass().getResourceAsStream("/plugin.yml"), Map.class).get("name"); } @Override public MCPlugin GetPlugin() { return new BukkitMCPlugin(CommandHelperPlugin.self); } @Override public MCColor GetColor(String colorName, Target t) throws CREFormatException { return ConvertorHelper.GetColor(colorName, t); } @Override public String GetUser(Environment env) { MCCommandSender cs = env.getEnv(CommandHelperEnvironment.class).GetCommandSender(); if(cs == null){ return null; } else { String name = cs.getName(); if("CONSOLE".equals(name)){ name = "~console"; } return name; } } }