/* * This file is part of Libelula Minecraft Edition Project. * * Libelula Minecraft Edition 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. * * Libelula Minecraft Edition 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 Libelula Minecraft Edition. * If not, see <http://www.gnu.org/licenses/>. * */ package me.libelula.libelulalogger; import java.util.ArrayList; import java.util.Comparator; import java.util.TreeMap; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.block.BlockDamageEvent; import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.player.PlayerBedEnterEvent; import org.bukkit.event.player.PlayerDropItemEvent; import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; /** * Class ToolBox of the plugin. * * @author Diego Lucio D'Onofrio <ddonofrio@member.fsf.org> * @version 1.0 */ public class ToolBox implements Listener { private final LibelulaLogger plugin; private TreeMap<Player, Tool> assignedTools; private final Lock _discoveryTools_mutex; private enum ToolType { DISCOVERY, RESTORE } private class Tool { public ToolType type; public ItemStack item; } @SuppressWarnings("unchecked") public ToolBox(final LibelulaLogger plugin) { this.plugin = plugin; _discoveryTools_mutex = new ReentrantLock(true); assignedTools = new TreeMap<>(new Comparator() { @Override public int compare(Object o1, Object o2) { Player player1; Player player2; player1 = (Player) o1; player2 = (Player) o2; return player1.getUniqueId().compareTo(player2.getUniqueId()); } }); } private void startListeningForEvents() { plugin.getServer().getPluginManager().registerEvents(this, plugin); } private void stopListeningForEvents() { BlockBreakEvent.getHandlerList().unregister(this); BlockPlaceEvent.getHandlerList().unregister(this); PlayerDropItemEvent.getHandlerList().unregister(this); PlayerQuitEvent.getHandlerList().unregister(this); } public void giveDiscoveryTool(Player player) { giveTool(player, ToolType.DISCOVERY); } public void giveRestoreTool(Player player) { giveTool(player, ToolType.RESTORE); } private void giveTool(Player player, ToolType toolType) { ItemStack itemTool; if (assignedTools.containsKey(player) && assignedTools.get(player).type == toolType) { itemTool = assignedTools.get(player).item; if (player.getItemInHand().equals(itemTool)) { player.sendMessage(ChatColor.YELLOW + "Just hit the blocks to know who placed them..."); player.sendMessage(ChatColor.YELLOW + "...or put put this block to know who broken one."); } else { player.getInventory().remove(itemTool); addToolToPlayerInventory(itemTool, player); } } else { if (assignedTools.containsKey(player)) { itemTool = assignedTools.get(player).item; player.getInventory().remove(itemTool); removeAssignedToolfromList(player); } itemTool = forgeTool(toolType); if (addToolToPlayerInventory(itemTool, player)) { Tool tool = new Tool(); tool.item = itemTool; tool.type = toolType; addAssignedToolToList(player, tool); player.sendMessage(ChatColor.GREEN + "Here you go."); } else { player.sendMessage(ChatColor.RED + "You don't have enough space in inventory."); } } } private boolean addToolToPlayerInventory(ItemStack tool, Player player) { if (player.getInventory().firstEmpty() != -1) { if (player.getItemInHand().getTypeId() == 0) { player.setItemInHand(tool); } else { player.getInventory().setItem(player.getInventory().firstEmpty(), player.getItemInHand()); player.setItemInHand(tool); } return true; } return false; } private ItemStack forgeTool(ToolType type) { ItemStack tool; ArrayList<String> lore = new ArrayList<>(); String toolName; switch (type) { case DISCOVERY: toolName = "LibelulaLogger Discovery tool"; Material discovery = Material.matchMaterial(plugin.getConfig().getString("discovery-item")); if (discovery == null) { plugin.getLogger().warning("Invalid configured material at configuration key discovery-item=" .concat(plugin.getConfig().getString("discovery-item"))); discovery = Material.BURNING_FURNACE; } tool = new ItemStack(discovery); lore.add("Who made this?"); break; case RESTORE: toolName = "LibelulaLogger fixing tool"; Material restore = Material.matchMaterial(plugin.getConfig().getString("restore-item")); if (restore == null || restore == Material.AIR || restore == Material.REDSTONE_LAMP_ON) { plugin.getLogger().warning("Invalid configured material at configuration key restore-item=" .concat(plugin.getConfig().getString("restore-item"))); restore = Material.REDSTONE_LAMP_OFF; plugin.getLogger().warning("Auto configured default item =" + restore.name()); } tool = new ItemStack(restore); lore.add("I can fix it!"); break; default: return null; } ItemMeta dtMeta = tool.getItemMeta(); dtMeta.setDisplayName(ChatColor.AQUA + toolName); dtMeta.setLore(lore); tool.setItemMeta(dtMeta); return tool; } private void addAssignedToolToList(Player player, Tool tool) { _discoveryTools_mutex.lock(); try { if (assignedTools.isEmpty()) { startListeningForEvents(); } assignedTools.put(player, tool); } finally { _discoveryTools_mutex.unlock(); } } public void removeAllTools() { while (!assignedTools.isEmpty()) { Player player = assignedTools.firstEntry().getKey(); Tool tool = assignedTools.firstEntry().getValue(); player.getInventory().removeItem(tool.item); removeAssignedToolfromList(player); } } private void removeAssignedToolfromList(Player player) { _discoveryTools_mutex.lock(); try { assignedTools.remove(player); if (assignedTools.isEmpty()) { stopListeningForEvents(); } } finally { _discoveryTools_mutex.unlock(); } } // Events ----------------------------------------------- @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) private void onPlayerDropItem(PlayerDropItemEvent e) { Player player = e.getPlayer(); if (assignedTools.containsKey(player)) { Tool tool = assignedTools.get(player); if (tool.item.equals(e.getItemDrop().getItemStack())) { e.getItemDrop().remove(); removeAssignedToolfromList(player); } } } @EventHandler(priority = EventPriority.HIGHEST) private void onPlayerQuit(PlayerQuitEvent e) { Player player = e.getPlayer(); if (assignedTools.containsKey(player)) { player.getInventory().remove(assignedTools.get(player).item); removeAssignedToolfromList(player); } } @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) private void onBlockBreak(BlockBreakEvent e) { Player player = e.getPlayer(); if (assignedTools.containsKey(player)) { Tool tool = assignedTools.get(player); if (tool.item.equals(player.getItemInHand())) { e.setCancelled(true); if (tool.type == ToolType.DISCOVERY) { plugin.meode.asyncTellBlockInfo(e.getBlock(), player, true); } } } } @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) private void onBlockDamage(BlockDamageEvent e) { Player player = e.getPlayer(); if (assignedTools.containsKey(player)) { Tool tool = assignedTools.get(player); if (tool.item.equals(player.getItemInHand())) { e.setCancelled(true); if (tool.type == ToolType.DISCOVERY) { plugin.meode.asyncTellBlockInfo(e.getBlock(), player, true); } } } } @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) private void onBlockPlace(BlockPlaceEvent e) { Player player = e.getPlayer(); if (assignedTools.containsKey(player)) { Tool tool = assignedTools.get(player); if (tool.item.equals(player.getItemInHand())) { e.setCancelled(true); if (tool.type == ToolType.DISCOVERY) { plugin.meode.asyncTellBlockInfo(e.getBlock(), player, false); } else { plugin.meode.asyncRestoreBlock(e.getBlock(), player); } } } } // Prevents to get in bed while trying to restore a home. @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) private void playerBedEnter(PlayerBedEnterEvent e) { Player player = e.getPlayer(); if (assignedTools.containsKey(player)) { Tool tool = assignedTools.get(player); if (tool.item.equals(player.getItemInHand())) { e.setCancelled(true); } } } }