diff --git a/common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/security/antiIllegalBundlePicker/AntiIllegalBundlePicker.java b/common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/security/antiIllegalBundlePicker/AntiIllegalBundlePicker.java new file mode 100644 index 0000000..d75313b --- /dev/null +++ b/common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/security/antiIllegalBundlePicker/AntiIllegalBundlePicker.java @@ -0,0 +1,78 @@ +package eu.mhsl.craftattack.spawn.common.appliances.security.antiIllegalBundlePicker; + +import eu.mhsl.craftattack.spawn.common.appliances.tooling.acInform.AcInform; +import eu.mhsl.craftattack.spawn.core.Main; +import eu.mhsl.craftattack.spawn.core.appliance.Appliance; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.InventoryView; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.BundleMeta; +import org.jetbrains.annotations.NotNull; + +import java.util.*; +import java.util.stream.Collectors; + +public class AntiIllegalBundlePicker extends Appliance { + private static final int visibleSlotsInBundle = 9; + + public void trackBundle(InventoryClickEvent event) { + ItemStack bundle = Objects.requireNonNull(event.getCurrentItem()); + final int rawSlot = event.getRawSlot(); + final Player player = (Player) event.getWhoClicked(); + final InventoryView view = event.getView(); + final List before = this.getBundleContents(bundle); + + Bukkit.getScheduler().runTask(Main.instance(), () -> { + ItemStack afterStack = view.getItem(rawSlot); + if(afterStack == null || afterStack.getType() != Material.BUNDLE) return; + + List after = this.getBundleContents(afterStack); + int removedSlotIndex = this.findRemoved(before, after); + + if(removedSlotIndex >= visibleSlotsInBundle) { + Main.instance().getAppliance(AcInform.class).notifyAdmins( + "internal", + player.getName(), + "illegalBundlePick", + (float) removedSlotIndex + ); + } + }); + } + + private int findRemoved(@NotNull List before, @NotNull List after) { + for (int i = 0; i < Math.max(before.size(), after.size()); i++) { + ItemStack a = i < after.size() ? after.get(i) : null; + ItemStack b = i < before.size() ? before.get(i) : null; + + if (b == null && a == null) continue; + if (b == null) throw new IllegalStateException("Size of bundle was smaller before pickup Action"); + + if (a == null) return i; + if (!a.isSimilar(b)) return i; + if (a.getAmount() != b.getAmount()) return i; + } + throw new IllegalStateException("Failed to find picked Item in bundle"); + } + + private List getBundleContents(@NotNull ItemStack bundle) { + if (bundle.getType() != Material.BUNDLE) + throw new IllegalStateException("ItemStack is not a bundle"); + + BundleMeta meta = (BundleMeta) bundle.getItemMeta(); + return meta.getItems().stream() + .map(ItemStack::clone) + .collect(Collectors.toCollection(ArrayList::new)); + } + + @Override + protected @NotNull List listeners() { + return List.of( + new OnBundlePickListener() + ); + } +} diff --git a/common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/security/antiIllegalBundlePicker/OnBundlePickListener.java b/common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/security/antiIllegalBundlePicker/OnBundlePickListener.java new file mode 100644 index 0000000..b25ae78 --- /dev/null +++ b/common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/security/antiIllegalBundlePicker/OnBundlePickListener.java @@ -0,0 +1,18 @@ +package eu.mhsl.craftattack.spawn.common.appliances.security.antiIllegalBundlePicker; + +import eu.mhsl.craftattack.spawn.core.appliance.ApplianceListener; +import org.bukkit.Material; +import org.bukkit.event.EventHandler; +import org.bukkit.event.inventory.InventoryAction; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; + +class OnBundlePickListener extends ApplianceListener { + @EventHandler + public void onBundlePick(InventoryClickEvent event) { + if(!event.getAction().equals(InventoryAction.PICKUP_FROM_BUNDLE)) return; + final ItemStack bundle = event.getCurrentItem(); + if (bundle == null || bundle.getType() != Material.BUNDLE) return; + this.getAppliance().trackBundle(event); + } +}