/* * This file is part of RPG Items. * * RPG Items 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. * * RPG Items 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 RPG Items. If not, see <http://www.gnu.org/licenses/>. */ package think.rpgitems; import gnu.trove.map.hash.TIntByteHashMap; import gnu.trove.map.hash.TIntIntHashMap; import gnu.trove.map.hash.TObjectIntHashMap; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Random; import java.util.Set; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.entity.Entity; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.entity.Projectile; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.block.Action; import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.entity.EntityDeathEvent; import org.bukkit.event.entity.ProjectileHitEvent; import org.bukkit.event.entity.ProjectileLaunchEvent; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryCloseEvent; import org.bukkit.event.inventory.InventoryOpenEvent; import org.bukkit.event.inventory.InventoryType; import org.bukkit.event.inventory.PrepareItemCraftEvent; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerItemConsumeEvent; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerPickupItemEvent; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.PlayerInventory; import org.bukkit.projectiles.ProjectileSource; import org.bukkit.scheduler.BukkitRunnable; import think.rpgitems.data.Locale; import think.rpgitems.data.RPGMetadata; import think.rpgitems.item.ItemManager; import think.rpgitems.item.LocaleInventory; import think.rpgitems.item.RPGItem; import think.rpgitems.support.WorldGuard; public class Events implements Listener { public static TIntByteHashMap removeArrows = new TIntByteHashMap(); public static TIntIntHashMap rpgProjectiles = new TIntIntHashMap(); public static TObjectIntHashMap<String> recipeWindows = new TObjectIntHashMap<String>(); public static HashMap<String, Set<Integer>> drops = new HashMap<String, Set<Integer>>(); public static boolean useLocaleInv = false; @SuppressWarnings("deprecation") @EventHandler(ignoreCancelled = true) public void onBlockBreak(BlockBreakEvent e) { Player player = e.getPlayer(); ItemStack item = player.getItemInHand(); RPGItem rItem; if ((rItem = ItemManager.toRPGItem(item)) != null) { RPGMetadata meta = RPGItem.getMetadata(item); if(rItem.getMaxDurability() != -1) { int durability = meta.containsKey(RPGMetadata.DURABILITY) ? ((Number) meta.get(RPGMetadata.DURABILITY)).intValue() : rItem.getMaxDurability(); durability--; if (durability <= 0) { player.setItemInHand(null); } meta.put(RPGMetadata.DURABILITY, Integer.valueOf(durability)); } RPGItem.updateItem(item, Locale.getPlayerLocale(player), meta); player.updateInventory(); } } @EventHandler public void onEntityDeath(EntityDeathEvent e) { String type = e.getEntity().getType().toString(); Random random = new Random(); if (drops.containsKey(type)) { Set<Integer> items = drops.get(type); Iterator<Integer> it = items.iterator(); while (it.hasNext()) { int id = it.next(); RPGItem item = ItemManager.getItemById(id); if (item == null) { it.remove(); continue; } double chance = item.dropChances.get(type); if (random.nextDouble() < chance / 100d) { e.getDrops().add(item.toItemStack("en_GB")); } } } } @EventHandler public void onProjectileHit(ProjectileHitEvent e) { final Entity entity = e.getEntity(); if (removeArrows.contains(entity.getEntityId())) { entity.remove(); removeArrows.remove(entity.getEntityId()); } else if (rpgProjectiles.contains(entity.getEntityId())) { RPGItem item = ItemManager.getItemById(rpgProjectiles.get(entity.getEntityId())); new BukkitRunnable() { public void run() { rpgProjectiles.remove(entity.getEntityId()); } }.runTask(Plugin.plugin); if (item == null) return; item.projectileHit((Player) ((Projectile) entity).getShooter(), (Projectile) entity); } } @SuppressWarnings("deprecation") @EventHandler public void onProjectileFire(ProjectileLaunchEvent e) { ProjectileSource shooter = e.getEntity().getShooter(); if (shooter instanceof Player) { Player player = (Player) shooter; ItemStack item = player.getItemInHand(); RPGItem rItem = ItemManager.toRPGItem(item); if (rItem == null) return; if (!WorldGuard.canPvP(player.getLocation()) && !rItem.ignoreWorldGuard) return; if (rItem.getHasPermission() == true && player.hasPermission(rItem.getPermission()) == false){ e.setCancelled(true); player.sendMessage(ChatColor.RED + String.format(Locale.get("message.error.permission", Locale.getPlayerLocale(player))));} RPGMetadata meta = RPGItem.getMetadata(item); if (rItem.getMaxDurability() != -1) { int durability = meta.containsKey(RPGMetadata.DURABILITY) ? ((Number) meta.get(RPGMetadata.DURABILITY)).intValue() : rItem.getMaxDurability(); durability--; if (durability <= 0) { player.setItemInHand(null); } meta.put(RPGMetadata.DURABILITY, Integer.valueOf(durability)); } RPGItem.updateItem(item, Locale.getPlayerLocale(player), meta); player.updateInventory(); rpgProjectiles.put(e.getEntity().getEntityId(), rItem.getID()); } } @EventHandler public void onPlayerAction(PlayerInteractEvent e) { Player player = e.getPlayer(); if ((e.getAction() == Action.RIGHT_CLICK_AIR || (e.getAction() == Action.RIGHT_CLICK_BLOCK) && !e.isCancelled())) { ItemStack item = player.getItemInHand(); if (item.getType() == Material.BOW || item.getType() == Material.SNOW_BALL || item.getType() == Material.EGG || item.getType() == Material.POTION) return; RPGItem rItem = ItemManager.toRPGItem(item); if (rItem == null) return; if (!WorldGuard.canPvP(player.getLocation()) && !rItem.ignoreWorldGuard) return; if (rItem.getHasPermission() == true && player.hasPermission(rItem.getPermission()) == false){ e.setCancelled(true); player.sendMessage(ChatColor.RED + String.format(Locale.get("message.error.permission", Locale.getPlayerLocale(player))));} rItem.rightClick(player); if (player.getItemInHand().getTypeId() != 0){ RPGItem.updateItem(item, Locale.getPlayerLocale(player)); }else player.setItemInHand(null); player.updateInventory(); } else if (e.getAction() == Action.LEFT_CLICK_AIR || e.getAction() == Action.LEFT_CLICK_BLOCK) { ItemStack item = player.getItemInHand(); if (item.getType() == Material.BOW || item.getType() == Material.SNOW_BALL || item.getType() == Material.EGG || item.getType() == Material.POTION) return; RPGItem rItem = ItemManager.toRPGItem(item); if (rItem == null) return; if (!WorldGuard.canPvP(player.getLocation()) && !rItem.ignoreWorldGuard) return; if (rItem.getHasPermission() == true && player.hasPermission(rItem.getPermission()) == false){ e.setCancelled(true); player.sendMessage(ChatColor.RED + String.format(Locale.get("message.error.permission", Locale.getPlayerLocale(player))));} rItem.leftClick(player); RPGItem.updateItem(item, Locale.getPlayerLocale(player)); } } @EventHandler public void onBlockPlace(BlockPlaceEvent e) { ItemStack item = e.getPlayer().getItemInHand(); if (item == null) return; RPGItem rItem = ItemManager.toRPGItem(item); if (rItem == null) return; e.setCancelled(true); } @EventHandler public void onPlayerJoin(PlayerJoinEvent e) { Player player = e.getPlayer(); PlayerInventory in = player.getInventory(); String locale = Locale.getPlayerLocale(player); for (int i = 0; i < in.getSize(); i++) { ItemStack item = in.getItem(i); if (ItemManager.toRPGItem(item) != null) RPGItem.updateItem(item, locale); } for (ItemStack item : player.getInventory().getArmorContents()) { if (ItemManager.toRPGItem(item) != null) RPGItem.updateItem(item, locale); } } @EventHandler public void onPlayerPickup(PlayerPickupItemEvent e) { ItemStack item = e.getItem().getItemStack(); String locale = Locale.getPlayerLocale(e.getPlayer()); if (ItemManager.toRPGItem(item) != null) { RPGItem.updateItem(item, locale); e.getItem().setItemStack(item); } } private HashSet<LocaleInventory> localeInventories = new HashSet<LocaleInventory>(); @EventHandler public void onInventoryClose(InventoryCloseEvent e) { if (recipeWindows.containsKey(e.getPlayer().getName())) { int id = recipeWindows.remove(e.getPlayer().getName()); RPGItem item = ItemManager.getItemById(id); if (item.recipe == null) { item.recipe = new ArrayList<ItemStack>(); } item.recipe.clear(); for (int y = 0; y < 3; y++) { for (int x = 0; x < 3; x++) { int i = x + y * 9; ItemStack it = e.getInventory().getItem(i); item.recipe.add(it); } } item.hasRecipe = true; item.resetRecipe(true); ItemManager.save(Plugin.plugin); ((Player) e.getPlayer()).sendMessage(ChatColor.AQUA + "Recipe set for " + item.getName()); } else if (useLocaleInv && e.getView() instanceof LocaleInventory) { localeInventories.remove(e.getView()); ((LocaleInventory) e.getView()).getView().close(); } } @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) public void onInventoryClick(InventoryClickEvent e) { if (useLocaleInv && e.getView() instanceof LocaleInventory) { LocaleInventory inv = (LocaleInventory) e.getView(); InventoryClickEvent clickEvent = new InventoryClickEvent(inv.getView(), e.getSlotType(), e.getRawSlot(), e.isRightClick(), e.isShiftClick()); Bukkit.getServer().getPluginManager().callEvent(clickEvent); if (clickEvent.isCancelled()) { e.setCancelled(true); } else { switch (clickEvent.getResult()) { case DEFAULT: // Can't really do this with current events case ALLOW: System.out.println("ok..."); System.out.println(inv.getView().getItem(e.getRawSlot())); inv.getView().setItem(e.getRawSlot(), clickEvent.getCursor()); System.out.println(inv.getView().getItem(e.getRawSlot())); break; case DENY: break; } } for (LocaleInventory localeInv : localeInventories) { if (localeInv != inv) localeInv.reload(); } } } @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) public void onInventoryOpen(final InventoryOpenEvent e) { if (e.getView() instanceof LocaleInventory) return; if (e.getInventory().getType() != InventoryType.CHEST || !useLocaleInv) { Inventory in = e.getInventory(); Iterator<ItemStack> it = in.iterator(); String locale = Locale.getPlayerLocale((Player) e.getPlayer()); try { while (it.hasNext()) { ItemStack item = it.next(); if (ItemManager.toRPGItem(item) != null) RPGItem.updateItem(item, locale); } } catch (ArrayIndexOutOfBoundsException ex) { // Fix for the bug with anvils in craftbukkit } } else if (useLocaleInv) { LocaleInventory localeInv = new LocaleInventory((Player) e.getPlayer(), e.getView()); e.setCancelled(true); e.getPlayer().openInventory(localeInv); localeInventories.add(localeInv); } } private Random random = new Random(); @SuppressWarnings("deprecation") private double playerDamager(EntityDamageByEntityEvent e, double damage) { Player player = (Player) e.getDamager(); ItemStack item = player.getItemInHand(); if (item.getType() == Material.BOW || item.getType() == Material.SNOW_BALL || item.getType() == Material.EGG || item.getType() == Material.POTION) return damage; RPGItem rItem = ItemManager.toRPGItem(item); if (rItem == null) return damage; if (!WorldGuard.canPvP(player.getLocation()) && !rItem.ignoreWorldGuard) return damage; if (rItem.getHasPermission() == true && player.hasPermission(rItem.getPermission()) == false){ damage = 0; e.setCancelled(true); player.sendMessage(ChatColor.RED + String.format(Locale.get("message.error.permission", Locale.getPlayerLocale(player))));} damage = rItem.getDamageMin() != rItem.getDamageMax() ? (rItem.getDamageMin() + random.nextInt(rItem.getDamageMax() - rItem.getDamageMin())) : rItem.getDamageMin(); if (e.getEntity() instanceof LivingEntity) { LivingEntity le = (LivingEntity) e.getEntity(); rItem.hit(player, le, e.getDamage()); } RPGMetadata meta = RPGItem.getMetadata(item); if (rItem.getMaxDurability() != -1) { int durability = meta.containsKey(RPGMetadata.DURABILITY) ? ((Number) meta.get(RPGMetadata.DURABILITY)).intValue() : rItem.getMaxDurability(); durability--; if (durability <= 0) { player.setItemInHand(null); } meta.put(RPGMetadata.DURABILITY, Integer.valueOf(durability)); } RPGItem.updateItem(item, Locale.getPlayerLocale(player), meta); player.updateInventory(); return damage; } private double projectileDamager(EntityDamageByEntityEvent e, double damage) { Projectile entity = (Projectile) e.getDamager(); if (rpgProjectiles.contains(entity.getEntityId())) { RPGItem rItem = ItemManager.getItemById(rpgProjectiles.get(entity.getEntityId())); if (rItem == null) return damage; damage = rItem.getDamageMin() != rItem.getDamageMax() ? (rItem.getDamageMin() + random.nextInt(rItem.getDamageMax() - rItem.getDamageMin())) : rItem.getDamageMin(); if (e.getEntity() instanceof LivingEntity) { LivingEntity le = (LivingEntity) e.getEntity(); rItem.hit((Player) entity.getShooter(), le, e.getDamage()); } } return damage; } private double playerHit(EntityDamageByEntityEvent e, double damage) { Player p = (Player) e.getEntity(); if (e.isCancelled() || !WorldGuard.canPvP(p.getLocation())) return damage; String locale = Locale.getPlayerLocale(p); ItemStack[] armour = p.getInventory().getArmorContents(); for (int i = 0; i < armour.length; i++) { ItemStack pArmour = armour[i]; RPGItem pRItem = ItemManager.toRPGItem(pArmour); if (pRItem == null) continue; if (!WorldGuard.canPvP(p.getLocation()) && !pRItem.ignoreWorldGuard) return damage; if (pRItem.getHasPermission() == true && p.hasPermission(pRItem.getPermission()) == false){ damage = 0; e.setCancelled(true); p.sendMessage(ChatColor.RED + String.format(Locale.get("message.error.permission", Locale.getPlayerLocale(p))));} if (pRItem.getArmour() > 0) { damage -= Math.round(((double) damage) * (((double) pRItem.getArmour()) / 100d)); } RPGMetadata meta = RPGItem.getMetadata(pArmour); if (pRItem.getMaxDurability() != -1) { int durability = meta.containsKey(RPGMetadata.DURABILITY) ? ((Number) meta.get(RPGMetadata.DURABILITY)).intValue() : pRItem.getMaxDurability(); durability--; if (durability <= 0) { armour[i] = null; } meta.put(RPGMetadata.DURABILITY, Integer.valueOf(durability)); } RPGItem.updateItem(pArmour, locale, meta); } p.getInventory().setArmorContents(armour); p.updateInventory(); return damage; } @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) public void onDamage(EntityDamageByEntityEvent e) { double damage = e.getDamage(); if (e.getDamager() instanceof Player) { damage = playerDamager(e, damage); } else if (e.getDamager() instanceof Projectile) { damage = projectileDamager(e, damage); } if (e.getEntity() instanceof Player) { damage = playerHit(e, damage); } e.setDamage(damage); } @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) public void onItemCraft(PrepareItemCraftEvent e) { if (ItemManager.toRPGItem(e.getInventory().getResult()) != null){ Random random = new Random(); if (random.nextInt(ItemManager.toRPGItem(e.getInventory().getResult()).recipechance) != 0){ ItemStack baseitem = new ItemStack(e.getInventory().getResult().getType()); e.getInventory().setResult(baseitem); } } } public void onItemDamage(PlayerItemConsumeEvent e){ if (ItemManager.toRPGItem(e.getItem()) != null){ RPGItem rpgitem = ItemManager.toRPGItem(e.getItem()); if (rpgitem.getMaxDurability() > 0){ e.getItem().setDurability((short)-1); } } } }