Minepacks/Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Listener/ItemShortcut.java

358 lines
12 KiB
Java

/*
* Copyright (C) 2021 GeorgH93
*
* This program 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.
*
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
*/
package at.pcgamingfreaks.Minepacks.Bukkit.Listener;
import at.pcgamingfreaks.Bukkit.MCVersion;
import at.pcgamingfreaks.Bukkit.Message.Message;
import at.pcgamingfreaks.Bukkit.Util.HeadUtils;
import at.pcgamingfreaks.Minepacks.Bukkit.API.Backpack;
import at.pcgamingfreaks.Minepacks.Bukkit.API.Events.InventoryClearedEvent;
import at.pcgamingfreaks.Minepacks.Bukkit.API.WorldBlacklistMode;
import at.pcgamingfreaks.Minepacks.Bukkit.Minepacks;
import at.pcgamingfreaks.Minepacks.Bukkit.Permissions;
import org.bukkit.Bukkit;
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.block.Action;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.inventory.*;
import org.bukkit.event.player.*;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.UUID;
public class ItemShortcut extends MinepacksListener
{
private static final UUID MINEPACKS_UUID = UUID.nameUUIDFromBytes("Minepacks".getBytes());
private final String itemName, itemNameNoReset, value, openCommand;
private final Message messageDoNotRemoveItem;
private final boolean improveDeathChestCompatibility, blockAsHat, allowRightClickOnContainers, blockItemFromMoving;
private final int preferredSlotId;
private final Set<Material> containerMaterials = new HashSet<>();
public ItemShortcut(final @NotNull Minepacks plugin)
{
super(plugin);
itemName = ChatColor.translateAlternateColorCodes('&', plugin.getConfiguration().getItemShortcutItemName());
itemNameNoReset = itemName.replace(ChatColor.RESET.toString(), "");
value = plugin.getConfiguration().getItemShortcutHeadValue();
improveDeathChestCompatibility = plugin.getConfiguration().isItemShortcutImproveDeathChestCompatibilityEnabled();
blockAsHat = plugin.getConfiguration().isItemShortcutBlockAsHatEnabled();
allowRightClickOnContainers = plugin.getConfiguration().isItemShortcutRightClickOnContainerAllowed();
preferredSlotId = plugin.getConfiguration().getItemShortcutPreferredSlotId();
blockItemFromMoving = plugin.getConfiguration().getItemShortcutBlockItemFromMoving();
openCommand = plugin.getLanguage().getCommandAliases("Backpack", "backpack")[0] + ' ' + plugin.getLanguage().getCommandAliases("Open", "open")[0];
messageDoNotRemoveItem = plugin.getLanguage().getMessage("Ingame.DontRemoveShortcut");
if(allowRightClickOnContainers)
{
containerMaterials.add(Material.CHEST);
containerMaterials.add(Material.TRAPPED_CHEST);
containerMaterials.add(Material.ENDER_CHEST);
containerMaterials.add(Material.CRAFTING_TABLE);
containerMaterials.add(Material.FURNACE);
containerMaterials.add(Material.BLAST_FURNACE);
containerMaterials.add(Material.DISPENSER);
containerMaterials.add(Material.DROPPER);
containerMaterials.add(Material.HOPPER);
if(MCVersion.isNewerOrEqualThan(MCVersion.MC_1_11)) containerMaterials.addAll(DisableShulkerboxes.SHULKER_BOX_MATERIALS);
}
}
public boolean isItemShortcut(final @Nullable ItemStack stack)
{
if(stack == null || stack.getType() != HeadUtils.HEAD_MATERIAL || !stack.hasItemMeta()) return false;
String itemDisplayName = stack.getItemMeta().getDisplayName();
return itemDisplayName != null && itemNameNoReset.equals(itemDisplayName.replace(ChatColor.RESET.toString(), ""));
}
private void addItem(Player player)
{
if(player.hasPermission(Permissions.USE))
{
boolean empty = false, item = false;
for(ItemStack itemStack : player.getInventory())
{
if(itemStack == null || itemStack.getType() == Material.AIR) empty = true;
else if(isItemShortcut(itemStack))
{
item = true;
if(itemStack.getAmount() > 1) itemStack.setAmount(1);
break;
}
}
if(!item && empty)
{
if(preferredSlotId >= 0 && preferredSlotId < 36)
{
ItemStack stack = player.getInventory().getItem(preferredSlotId);
if(stack == null || stack.getType() == Material.AIR)
{
player.getInventory().setItem(preferredSlotId, HeadUtils.fromBase64(value, itemName, MINEPACKS_UUID));
return;
}
}
player.getInventory().addItem(HeadUtils.fromBase64(value, itemName, MINEPACKS_UUID));
}
}
}
private void removeItem(Player player)
{
for(ItemStack itemStack : player.getInventory())
{
if(isItemShortcut(itemStack))
{
itemStack.setAmount(0);
return;
}
}
}
//region Add backpack item
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onJoin(PlayerJoinEvent event)
{
if(plugin.isDisabled(event.getPlayer()) != WorldBlacklistMode.None) return;
Bukkit.getScheduler().runTaskLater(plugin, () -> addItem(event.getPlayer()), 2L);
}
@EventHandler(priority = EventPriority.MONITOR)
public void onSpawn(PlayerRespawnEvent event)
{
if(plugin.isDisabled(event.getPlayer()) != WorldBlacklistMode.None) return;
Bukkit.getScheduler().runTaskLater(plugin, () -> addItem(event.getPlayer()), 2L);
}
@EventHandler(priority = EventPriority.MONITOR)
public void onWorldChange(final PlayerChangedWorldEvent event)
{
Bukkit.getScheduler().runTaskLater(plugin, () -> {
Player player = event.getPlayer();
if(!player.isOnline()) return;
if(player.hasPermission(Permissions.USE) && plugin.isDisabled(player) == WorldBlacklistMode.None)
addItem(player);
else
removeItem(player);
}, 2L);
}
@EventHandler(priority = EventPriority.MONITOR)
public void onInventoryClear(InventoryClearedEvent event)
{
if(plugin.isDisabled(event.getPlayer()) != WorldBlacklistMode.None) return;
addItem(event.getPlayer());
}
//endregion
//region Prevent placing of backpack item
@EventHandler(priority = EventPriority.LOWEST)
public void onItemInteract(PlayerInteractEvent event)
{
if ((event.getAction() != Action.RIGHT_CLICK_AIR && event.getAction() != Action.RIGHT_CLICK_BLOCK)) return;
if(isItemShortcut(event.getItem()))
{
if(allowRightClickOnContainers && event.getAction() == Action.RIGHT_CLICK_BLOCK)
{
//noinspection ConstantConditions
if(containerMaterials.contains(event.getClickedBlock().getType())) return;
}
event.getPlayer().performCommand(openCommand);
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void onArmorStandManipulation(PlayerArmorStandManipulateEvent event)
{
if(isItemShortcut(event.getPlayerItem()))
{
event.getPlayer().performCommand(openCommand);
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void onItemFrameInteract(PlayerInteractEntityEvent event)
{
Player player = event.getPlayer();
ItemStack item;
if(MCVersion.isDualWieldingMC())
{
item = (event.getHand() == EquipmentSlot.HAND) ? player.getInventory().getItemInMainHand() : player.getInventory().getItemInOffHand();
}
else
{
item = player.getItemInHand();
}
if(isItemShortcut(item))
{
event.getPlayer().performCommand(openCommand);
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void onBlockPlace(BlockPlaceEvent event)
{
if(isItemShortcut(event.getItemInHand()))
{
event.getPlayer().performCommand(openCommand);
event.setCancelled(true);
}
}
//endregion
//region Handle inventory actions
@EventHandler(priority = EventPriority.LOWEST)
public void onItemClick(InventoryClickEvent event)
{
if(event.getWhoClicked() instanceof Player)
{
final Player player = (Player) event.getWhoClicked();
if(isItemShortcut(event.getCurrentItem()))
{
if(event.getAction() == InventoryAction.SWAP_WITH_CURSOR)
{
if(plugin.isDisabled(player) != WorldBlacklistMode.None || !player.hasPermission(Permissions.USE) || !plugin.isPlayerGameModeAllowed(player)) return;
Backpack backpack = plugin.getBackpackCachedOnly(player);
if(backpack != null)
{
//TODO right click should place only one
final ItemStack stack = event.getCursor();
if(plugin.getItemFilter() == null || !plugin.getItemFilter().isItemBlocked(stack))
{
ItemStack full = backpack.addItem(stack);
stack.setAmount((full == null) ? 0 : full.getAmount());
event.setCursor(full);
event.setCancelled(true);
}
else
{
plugin.getItemFilter().messageNotAllowedInBackpack.send(player, plugin.getItemFilter().itemNameResolver.getName(stack));
}
}
}
else if(event.getClick() == ClickType.RIGHT || event.getClick() == ClickType.SHIFT_RIGHT)
{
plugin.getServer().getScheduler().runTask(plugin, () -> { player.performCommand(openCommand); });
event.setCancelled(true);
}
else if(event.getAction() == InventoryAction.MOVE_TO_OTHER_INVENTORY)
{
event.setCancelled(true);
messageDoNotRemoveItem.send(player);
}
if(blockItemFromMoving) event.setCancelled(true);
}
else if((event.getAction() == InventoryAction.HOTBAR_MOVE_AND_READD || event.getAction() == InventoryAction.HOTBAR_SWAP) && event.getHotbarButton() != -1)
{
ItemStack item = player.getInventory().getItem(event.getHotbarButton());
if(isItemShortcut(item))
{
event.setCancelled(true);
messageDoNotRemoveItem.send(player);
}
}
else if((event.getAction() == InventoryAction.HOTBAR_MOVE_AND_READD || event.getAction() == InventoryAction.HOTBAR_SWAP) && event.getClick().name().equals("SWAP_OFFHAND"))
{
if(isItemShortcut(player.getInventory().getItemInOffHand()))
{
event.setCancelled(true);
messageDoNotRemoveItem.send(player);
}
}
else if(isItemShortcut(event.getCursor()))
{
if(!player.getInventory().equals(event.getClickedInventory()))
{
event.setCancelled(true);
messageDoNotRemoveItem.send(player);
}
else if(event.getSlotType() == InventoryType.SlotType.ARMOR && blockAsHat)
{
event.setCancelled(true);
}
}
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onItemDrag(InventoryDragEvent event)
{
if(!event.getInventory().equals(event.getWhoClicked().getInventory()) && event.getRawSlots().containsAll(event.getInventorySlots()))
{
if(isItemShortcut(event.getCursor()) || isItemShortcut(event.getOldCursor()))
{
event.setCancelled(true);
messageDoNotRemoveItem.send(event.getWhoClicked());
}
}
}
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void onDropItem(PlayerDropItemEvent event)
{
if(isItemShortcut(event.getItemDrop().getItemStack()))
{
event.setCancelled(true);
messageDoNotRemoveItem.send(event.getPlayer());
}
}
//endregion
/**
* Removes the backpack item form the drops on death
*/
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void onDeath(PlayerDeathEvent event)
{
//region prevent drop
Iterator<ItemStack> itemStackIterator = event.getDrops().iterator();
while(itemStackIterator.hasNext())
{
if(isItemShortcut(itemStackIterator.next()))
{
itemStackIterator.remove();
break;
}
}
//endregion
if(improveDeathChestCompatibility)
{ // improveDeathChestCompatibility
for(ItemStack itemStack : event.getEntity().getInventory())
{
if(isItemShortcut(itemStack))
{
itemStack.setAmount(0);
itemStack.setType(Material.AIR);
}
}
}
}
}