From 5da0569493dac73320b8b2f37b734f27219833c6 Mon Sep 17 00:00:00 2001 From: GenOpenDiesel Date: Thu, 18 Jun 2026 20:38:31 +0200 Subject: [PATCH] Folia support: migrate Bukkit scheduler usage to SchedulerUtils ItemTag declared folia-supported but still scheduled tasks through the global BukkitScheduler / BukkitRunnable, which throws on Folia (and left a `//TODO folia fix` in Usable). - Replace all one-shot runTaskLater / BukkitRunnable delayed tasks with ItemEdit's Folia-aware SchedulerUtils, scoped to the relevant player so they run on that entity's region thread (Usable, EquipmentFlag, RenamableOld, WearPermission, EffectsResurrectListener, Effects, DelayedAction, activity DelayedActionType). - EquipmentChangeListener: SlotCheck no longer extends BukkitRunnable; it implements Runnable and exposes schedule() backed by SchedulerUtils. - Equipment poll timer: keep the BukkitRunnable timer off Folia; on Folia self-reschedule via SchedulerUtils and fan each player check out to its own region thread. Back equips/clickDrop with thread-safe collections on Folia (mirrors ActionHandler). Co-Authored-By: Claude Opus 4.8 --- .../itemtag/actions/DelayedAction.java | 9 +- .../activity/action/DelayedActionType.java | 9 +- .../itemtag/command/itemtag/Effects.java | 11 +-- .../itemtag/EffectsResurrectListener.java | 7 +- .../command/itemtag/WearPermission.java | 6 +- .../itemtag/customflags/EquipmentFlag.java | 6 +- .../itemtag/customflags/RenamableOld.java | 7 +- .../command/itemtag/customflags/Usable.java | 6 +- .../EquipmentChangeListener.java | 10 +-- .../EquipmentChangeListenerBase.java | 90 ++++++++++++++++--- .../EquipmentChangeListenerUpTo1_13.java | 11 +-- .../EquipmentChangeListenerUpTo1_8.java | 10 +-- 12 files changed, 113 insertions(+), 69 deletions(-) diff --git a/src/main/java/emanondev/itemtag/actions/DelayedAction.java b/src/main/java/emanondev/itemtag/actions/DelayedAction.java index 4bcd0b0..49dc7c6 100644 --- a/src/main/java/emanondev/itemtag/actions/DelayedAction.java +++ b/src/main/java/emanondev/itemtag/actions/DelayedAction.java @@ -1,10 +1,10 @@ package emanondev.itemtag.actions; import emanondev.itemedit.utility.CompleteUtility; +import emanondev.itemedit.utility.SchedulerUtils; import emanondev.itemtag.ItemTag; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -import org.bukkit.scheduler.BukkitRunnable; import java.util.ArrayList; import java.util.Arrays; @@ -48,11 +48,8 @@ public String fixActionInfo(String actionInfo) { @Override public void execute(Player player, String text) { String[] args = text.split(" "); - new BukkitRunnable() { - public void run() { - ActionHandler.handleAction(player, args[1], text.substring(args[0].length() + args[1].length() + 2)); - } - }.runTaskLater(ItemTag.get(), Long.parseLong(args[0])); + SchedulerUtils.runLater(ItemTag.get(), player, Long.parseLong(args[0]), () -> + ActionHandler.handleAction(player, args[1], text.substring(args[0].length() + args[1].length() + 2))); } @Override diff --git a/src/main/java/emanondev/itemtag/activity/action/DelayedActionType.java b/src/main/java/emanondev/itemtag/activity/action/DelayedActionType.java index 5844141..fbe5b49 100644 --- a/src/main/java/emanondev/itemtag/activity/action/DelayedActionType.java +++ b/src/main/java/emanondev/itemtag/activity/action/DelayedActionType.java @@ -1,12 +1,12 @@ package emanondev.itemtag.activity.action; +import emanondev.itemedit.utility.SchedulerUtils; import emanondev.itemtag.ItemTag; import emanondev.itemtag.activity.ActionManager; import emanondev.itemtag.activity.ActionType; import org.bukkit.entity.Player; import org.bukkit.event.Event; import org.bukkit.inventory.ItemStack; -import org.bukkit.scheduler.BukkitRunnable; import org.jetbrains.annotations.NotNull; public class DelayedActionType extends ActionType { @@ -37,12 +37,7 @@ public DelayedAction(@NotNull String info) { @Override public boolean execute(@NotNull Player player, @NotNull ItemStack item, Event event) { - new BukkitRunnable() { - @Override - public void run() { - action.execute(player, item, event); - } - }.runTaskLater(ItemTag.get(), delay); + SchedulerUtils.runLater(ItemTag.get(), player, delay, () -> action.execute(player, item, event)); return true; } } diff --git a/src/main/java/emanondev/itemtag/command/itemtag/Effects.java b/src/main/java/emanondev/itemtag/command/itemtag/Effects.java index 7717c75..662fb23 100644 --- a/src/main/java/emanondev/itemtag/command/itemtag/Effects.java +++ b/src/main/java/emanondev/itemtag/command/itemtag/Effects.java @@ -3,6 +3,7 @@ import emanondev.itemedit.aliases.Aliases; import emanondev.itemedit.utility.CompleteUtility; import emanondev.itemedit.utility.ItemUtils; +import emanondev.itemedit.utility.SchedulerUtils; import emanondev.itemedit.utility.VersionUtils; import emanondev.itemtag.EffectsInfo; import emanondev.itemtag.ItemTag; @@ -11,7 +12,6 @@ import emanondev.itemtag.command.ListenerSubCmd; import emanondev.itemtag.equipmentchange.EquipmentChangeEvent; import emanondev.itemtag.gui.EffectsGui; -import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -22,7 +22,6 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; -import org.bukkit.scheduler.BukkitRunnable; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -269,8 +268,7 @@ public void onEquipChange(EquipmentChangeEvent event) { @EventHandler private void onPlayerRespawn(PlayerRespawnEvent event) { - new BukkitRunnable() { - public void run() { + SchedulerUtils.runLater(ItemTag.get(), event.getPlayer(), 1L, () -> { for (EquipmentSlot slot : ItemTagUtility.getPlayerEquipmentSlots()) { ItemStack equip = getEquip(event.getPlayer(), slot); if (ItemUtils.isAirOrNull(equip)) @@ -301,8 +299,7 @@ else if (currentEffect.getAmplifier() <= effect.getAmplifier()) } } } - } - }.runTaskLater(ItemTag.get(), 1L); //effect are resetted just after playerrespawnevent + }); //effect are resetted just after playerrespawnevent } @@ -327,7 +324,7 @@ private void addEffect(@NotNull Player target, @NotNull PotionEffectType type, @ @EventHandler(ignoreCancelled = true) private void event(PlayerItemConsumeEvent event) { if (event.getItem().getType() == Material.MILK_BUCKET) - Bukkit.getScheduler().runTaskLater(this.getPlugin(), () -> restoreEffects(event.getPlayer()), 1L); + SchedulerUtils.runLater(this.getPlugin(), event.getPlayer(), 1L, () -> restoreEffects(event.getPlayer())); } public void restoreEffects(Player p) { diff --git a/src/main/java/emanondev/itemtag/command/itemtag/EffectsResurrectListener.java b/src/main/java/emanondev/itemtag/command/itemtag/EffectsResurrectListener.java index b76af4e..3872030 100644 --- a/src/main/java/emanondev/itemtag/command/itemtag/EffectsResurrectListener.java +++ b/src/main/java/emanondev/itemtag/command/itemtag/EffectsResurrectListener.java @@ -1,6 +1,6 @@ package emanondev.itemtag.command.itemtag; -import org.bukkit.Bukkit; +import emanondev.itemedit.utility.SchedulerUtils; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; @@ -21,7 +21,7 @@ public class EffectsResurrectListener implements Listener { @EventHandler(ignoreCancelled = true) private void event(EntityResurrectEvent event) { if (event.getEntity() instanceof Player) - Bukkit.getScheduler().runTaskLater(parent.getPlugin(), + SchedulerUtils.runLater(parent.getPlugin(), (Player) event.getEntity(), 1L, () -> { List l = new ArrayList<>(event.getEntity().getActivePotionEffects()); l.forEach((e) -> event.getEntity().removePotionEffect(e.getType())); @@ -31,8 +31,7 @@ private void event(EntityResurrectEvent event) { e.getAmplifier() > event.getEntity().getPotionEffect(e.getType()).getAmplifier()) event.getEntity().addPotionEffect(e); }); - } - , 1L); + }); } } diff --git a/src/main/java/emanondev/itemtag/command/itemtag/WearPermission.java b/src/main/java/emanondev/itemtag/command/itemtag/WearPermission.java index 4791925..3970a32 100644 --- a/src/main/java/emanondev/itemtag/command/itemtag/WearPermission.java +++ b/src/main/java/emanondev/itemtag/command/itemtag/WearPermission.java @@ -7,11 +7,11 @@ import emanondev.itemedit.utility.CompleteUtility; import emanondev.itemedit.utility.InventoryUtils; import emanondev.itemedit.utility.ItemUtils; +import emanondev.itemedit.utility.SchedulerUtils; import emanondev.itemtag.ItemTag; import emanondev.itemtag.TagItem; import emanondev.itemtag.command.ListenerSubCmd; import emanondev.itemtag.equipmentchange.EquipmentChangeEvent; -import org.bukkit.Bukkit; import org.bukkit.Sound; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -114,7 +114,7 @@ public void event(final EquipmentChangeEvent event) { return; } - Bukkit.getScheduler().runTaskLater(getPlugin(), () -> { + SchedulerUtils.runLater(getPlugin(), player, 1L, () -> { if (!player.isOnline()) return; ItemStack originalItem = InventoryUtils.getItem(player, event.getSlotType()); @@ -141,7 +141,7 @@ public void event(final EquipmentChangeEvent event) { api.setCooldown(player,cooldownKey,1, TimeUnit.SECONDS); Util.sendMessage(player, UtilsString.fix(tagItem.getString(WEARMSG_KEY), player, true, "%permission%", perm)); } - }, 1L); + }); } diff --git a/src/main/java/emanondev/itemtag/command/itemtag/customflags/EquipmentFlag.java b/src/main/java/emanondev/itemtag/command/itemtag/customflags/EquipmentFlag.java index 010326f..c60573d 100644 --- a/src/main/java/emanondev/itemtag/command/itemtag/customflags/EquipmentFlag.java +++ b/src/main/java/emanondev/itemtag/command/itemtag/customflags/EquipmentFlag.java @@ -2,10 +2,10 @@ import emanondev.itemedit.utility.InventoryUtils; import emanondev.itemedit.utility.ItemUtils; +import emanondev.itemedit.utility.SchedulerUtils; import emanondev.itemtag.ItemTag; import emanondev.itemtag.command.itemtag.Flag; import emanondev.itemtag.equipmentchange.EquipmentChangeEvent; -import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.Sound; import org.bukkit.event.EventHandler; @@ -48,7 +48,7 @@ public void event(EquipmentChangeEvent event) { if (this.getValue(ItemTag.getTagItem(event.getTo()))) { return; } - Bukkit.getScheduler().runTaskLater(getPlugin(), () -> { + SchedulerUtils.runLater(getPlugin(), event.getPlayer(), 1L, () -> { if (!event.getPlayer().isOnline()) { return; } @@ -94,6 +94,6 @@ public void event(EquipmentChangeEvent event) { InventoryUtils.giveAmount(event.getPlayer(), item, item.getAmount(), InventoryUtils.ExcessMode.DROP_EXCESS); ItemTag.get().getEquipChangeListener().onEquipChange(event.getPlayer(), EquipmentChangeEvent.EquipMethod.UNKNOWN , event.getSlotType(), item, null); - }, 1L); + }); } } diff --git a/src/main/java/emanondev/itemtag/command/itemtag/customflags/RenamableOld.java b/src/main/java/emanondev/itemtag/command/itemtag/customflags/RenamableOld.java index cdb238a..84944c8 100644 --- a/src/main/java/emanondev/itemtag/command/itemtag/customflags/RenamableOld.java +++ b/src/main/java/emanondev/itemtag/command/itemtag/customflags/RenamableOld.java @@ -1,9 +1,10 @@ package emanondev.itemtag.command.itemtag.customflags; +import emanondev.itemedit.utility.SchedulerUtils; import emanondev.itemtag.ItemTag; import emanondev.itemtag.command.itemtag.Flag; -import org.bukkit.Bukkit; import org.bukkit.Material; +import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.inventory.InventoryClickEvent; @@ -27,12 +28,12 @@ public void event(InventoryClickEvent event) { } if (ItemTag.getTagItem(event.getInventory().getItem(0)).hasBooleanTag(RENAMABLE_KEY) || ItemTag.getTagItem(event.getInventory().getItem(1)).hasBooleanTag(RENAMABLE_KEY)) { - Bukkit.getScheduler().runTaskLater(ItemTag.get(), () -> { + SchedulerUtils.runLater(ItemTag.get(), (Player) event.getWhoClicked(), 1L, () -> { if (ItemTag.getTagItem(event.getInventory().getItem(0)).hasBooleanTag(RENAMABLE_KEY) || ItemTag.getTagItem(event.getInventory().getItem(1)).hasBooleanTag(RENAMABLE_KEY)) { event.getInventory().setItem(2, null); } - }, 1L); + }); if (event.getSlot() == 2) { event.setCancelled(true); } diff --git a/src/main/java/emanondev/itemtag/command/itemtag/customflags/Usable.java b/src/main/java/emanondev/itemtag/command/itemtag/customflags/Usable.java index e99ef35..1131a6f 100644 --- a/src/main/java/emanondev/itemtag/command/itemtag/customflags/Usable.java +++ b/src/main/java/emanondev/itemtag/command/itemtag/customflags/Usable.java @@ -1,10 +1,10 @@ package emanondev.itemtag.command.itemtag.customflags; import emanondev.itemedit.utility.InventoryUtils; +import emanondev.itemedit.utility.SchedulerUtils; import emanondev.itemedit.utility.VersionUtils; import emanondev.itemtag.ItemTag; import emanondev.itemtag.command.itemtag.Flag; -import org.bukkit.Bukkit; import org.bukkit.FluidCollisionMode; import org.bukkit.Material; import org.bukkit.block.Block; @@ -37,14 +37,14 @@ private void event(PlayerInteractEvent event) { b = event.getPlayer().getTargetBlockExact(7, FluidCollisionMode.SOURCE_ONLY); } else b = null; - Bukkit.getScheduler().runTaskLater(ItemTag.get(), () -> { //TODO folia fix + SchedulerUtils.runLater(ItemTag.get(), event.getPlayer(), 1L, () -> { if (!VersionUtils.isVersionAfter(1, 20)) { InventoryUtils.updateView(event.getPlayer()); } if (b != null) {//reduce clientside visual glich on liquids only for 1.14+ event.getPlayer().sendBlockChange(b.getLocation(), b.getBlockData()); } - }, 1L); + }); } default: } diff --git a/src/main/java/emanondev/itemtag/equipmentchange/EquipmentChangeListener.java b/src/main/java/emanondev/itemtag/equipmentchange/EquipmentChangeListener.java index c8b96e2..bdd018e 100644 --- a/src/main/java/emanondev/itemtag/equipmentchange/EquipmentChangeListener.java +++ b/src/main/java/emanondev/itemtag/equipmentchange/EquipmentChangeListener.java @@ -2,7 +2,6 @@ import emanondev.itemedit.utility.InventoryUtils; import emanondev.itemedit.utility.ItemUtils; -import emanondev.itemtag.ItemTag; import emanondev.itemtag.ItemTagUtility; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -110,10 +109,9 @@ else if (event.getHotbarButton() == p.getInventory().getHeldItemSlot()) onEquipChange(p, EquipmentChangeEvent.EquipMethod.INVENTORY_MOVE_TO_OTHER_INVENTORY, slot, null, event.getCurrentItem()); if (clickedSlot == null || clickedSlot == EquipmentSlot.HAND) new SlotCheck(p, EquipmentChangeEvent.EquipMethod.INVENTORY_MOVE_TO_OTHER_INVENTORY, EquipmentSlot.HAND) - .runTaskLater(ItemTag.get(), 1L); + .schedule(); else - new SlotCheck(p, EquipmentChangeEvent.EquipMethod.INVENTORY_MOVE_TO_OTHER_INVENTORY, clickedSlot).runTaskLater(ItemTag.get(), - 1L); + new SlotCheck(p, EquipmentChangeEvent.EquipMethod.INVENTORY_MOVE_TO_OTHER_INVENTORY, clickedSlot).schedule(); return; } case COLLECT_TO_CURSOR: @@ -126,7 +124,7 @@ else if (event.getHotbarButton() == p.getInventory().getHeldItemSlot()) else if (event.getCursor().isSimilar(getEquip(p, EquipmentSlot.HAND))) slots.add(EquipmentSlot.HAND); if (!slots.isEmpty()) - new SlotCheck(p, EquipmentChangeEvent.EquipMethod.INVENTORY_COLLECT_TO_CURSOR, slots).runTaskLater(ItemTag.get(), 1L); + new SlotCheck(p, EquipmentChangeEvent.EquipMethod.INVENTORY_COLLECT_TO_CURSOR, slots).schedule(); return; case PICKUP_SOME: case UNKNOWN: @@ -255,6 +253,6 @@ private void event(EntityPickupItemEvent event) { for (int i = 0; i < p.getInventory().getHeldItemSlot(); i++) if (ItemUtils.isAirOrNull(p.getInventory().getItem(i))) return; - new SlotCheck(p, EquipmentChangeEvent.EquipMethod.PICKUP, EquipmentSlot.HAND).runTaskLater(ItemTag.get(), 1L); + new SlotCheck(p, EquipmentChangeEvent.EquipMethod.PICKUP, EquipmentSlot.HAND).schedule(); } } \ No newline at end of file diff --git a/src/main/java/emanondev/itemtag/equipmentchange/EquipmentChangeListenerBase.java b/src/main/java/emanondev/itemtag/equipmentchange/EquipmentChangeListenerBase.java index 46b3244..5f4f703 100644 --- a/src/main/java/emanondev/itemtag/equipmentchange/EquipmentChangeListenerBase.java +++ b/src/main/java/emanondev/itemtag/equipmentchange/EquipmentChangeListenerBase.java @@ -1,6 +1,7 @@ package emanondev.itemtag.equipmentchange; import emanondev.itemedit.utility.ItemUtils; +import emanondev.itemedit.utility.SchedulerUtils; import emanondev.itemedit.utility.VersionUtils; import emanondev.itemtag.ItemTag; import emanondev.itemtag.ItemTagUtility; @@ -25,19 +26,26 @@ import org.jetbrains.annotations.NotNull; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; public abstract class EquipmentChangeListenerBase implements Listener { - protected final HashMap> equips = new HashMap<>(); - protected final HashSet clickDrop = new HashSet<>(); + // On Folia equipment is read/written from each player's own region thread, so the + // backing collections must be thread-safe (mirrors ActionHandler's Folia handling). + protected final Map> equips = + VersionUtils.hasFoliaAPI() ? new ConcurrentHashMap<>() : new HashMap<>(); + protected final Set clickDrop = + VersionUtils.hasFoliaAPI() ? ConcurrentHashMap.newKeySet() : new HashSet<>(); private int maxCheckedPlayerPerTick = 5; + private long timerCheckFrequencyTicks = 10; private TimerCheckTask timerTask = null; + private boolean foliaPollRunning = false; public void reload() { if (timerTask != null) { timerTask.cancel(); } - long timerCheckFrequencyTicks = Math.max(5, ItemTag.get().getConfig().getInteger("equipment_change.frequency_ticks", 10)); + timerCheckFrequencyTicks = Math.max(5, ItemTag.get().getConfig().getInteger("equipment_change.frequency_ticks", 10)); maxCheckedPlayerPerTick = Math.max(1, ItemTag.get().getConfig().getInteger("equipment_change.max_checked_players_per_tick", 5)); for (Player p : new ArrayList<>(equips.keySet())) { untrackPlayer(p); @@ -48,9 +56,56 @@ public void reload() { trackPlayer(p); } - timerTask = new TimerCheckTask(); - timerTask.runTaskTimer(ItemTag.get(), timerCheckFrequencyTicks, timerCheckFrequencyTicks); + if (VersionUtils.hasFoliaAPI()) { + // Folia has no global repeating scheduler usable here; self-reschedule via + // SchedulerUtils and fan out each player check to its own region thread. + if (!foliaPollRunning) { + foliaPollRunning = true; + scheduleFoliaPoll(); + } + } else { + timerTask = new TimerCheckTask(); + timerTask.runTaskTimer(ItemTag.get(), timerCheckFrequencyTicks, timerCheckFrequencyTicks); + } + + } + + private void scheduleFoliaPoll() { + SchedulerUtils.runLater(ItemTag.get(), timerCheckFrequencyTicks, () -> { + if (!foliaPollRunning) { + return; + } + for (Player p : new ArrayList<>(equips.keySet())) { + if (!p.isOnline()) { + untrackPlayer(p); + continue; + } + if (p.hasMetadata("BOT")) { + continue; + } + SchedulerUtils.run(ItemTag.get(), p, () -> checkPlayerEquipment(p)); + } + scheduleFoliaPoll(); + }); + } + private void checkPlayerEquipment(Player p) { + if (!p.isOnline()) { + untrackPlayer(p); + return; + } + trackPlayer(p); + EnumMap map = equips.get(p); + if (map == null) { + return; + } + for (EquipmentSlot slot : ItemTagUtility.getPlayerEquipmentSlots()) { + ItemStack newItem = getEquip(p, slot); + ItemStack oldItem = map.get(slot); + if (!isSimilarIgnoreDamage(oldItem, newItem)) { + onEquipChange(p, EquipmentChangeEvent.EquipMethod.UNKNOWN, slot, oldItem, newItem); + } + } } public abstract boolean isSimilarIgnoreDamage(ItemStack item, ItemStack item2); @@ -111,7 +166,7 @@ protected void handle(PlayerTeleportEvent event) { if (!equips.containsKey(event.getPlayer())) return; // some plugins teleport players just after login, before join this listener new SlotCheck(event.getPlayer(), EquipmentChangeEvent.EquipMethod.PLUGIN_WORLD_CHANGE, ItemTagUtility.getPlayerEquipmentSlots()) - .runTaskLater(ItemTag.get(), 1L); + .schedule(); } protected void handle(PlayerRespawnEvent event) { @@ -155,7 +210,7 @@ protected void handle(PlayerItemBreakEvent e) { onEquipChange(e.getPlayer(), EquipmentChangeEvent.EquipMethod.BROKE, slots.get(0), e.getBrokenItem(), null); return; } - new SlotCheck(e.getPlayer(), EquipmentChangeEvent.EquipMethod.BROKE, slots).runTaskLater(ItemTag.get(), 1L); + new SlotCheck(e.getPlayer(), EquipmentChangeEvent.EquipMethod.BROKE, slots).schedule(); } protected void handle(PlayerArmorStandManipulateEvent event) { @@ -215,7 +270,7 @@ protected void handle(PlayerInteractEntityEvent event) { onEquipChange(event.getPlayer(), EquipmentChangeEvent.EquipMethod.SHEEP_COLOR, slot, handItem, null); return; } - new SlotCheck(event.getPlayer(), EquipmentChangeEvent.EquipMethod.USE_ON_ENTITY, slot).runTaskLater(ItemTag.get(), 1L); + new SlotCheck(event.getPlayer(), EquipmentChangeEvent.EquipMethod.USE_ON_ENTITY, slot).schedule(); } protected void handle(PlayerInteractEvent e) { @@ -238,15 +293,15 @@ protected void handle(PlayerInteractEvent e) { if (e.getPlayer().getGameMode() != GameMode.CREATIVE) onEquipChange(e.getPlayer(), EquipmentChangeEvent.EquipMethod.RIGHT_CLICK, slot, e.getItem(), null); } else if (e.getItem().getAmount() == 1) - new SlotCheck(e.getPlayer(), EquipmentChangeEvent.EquipMethod.USE, slot).runTaskLater(ItemTag.get(), 1L); + new SlotCheck(e.getPlayer(), EquipmentChangeEvent.EquipMethod.USE, slot).schedule(); return; case RIGHT_CLICK_BLOCK: if (e.useItemInHand() == Event.Result.DENY) return; if (type != null && ItemUtils.isAirOrNull(getEquip(e.getPlayer(), type))) { - new SlotCheck(e.getPlayer(), EquipmentChangeEvent.EquipMethod.RIGHT_CLICK, slot, type).runTaskLater(ItemTag.get(), 1L); + new SlotCheck(e.getPlayer(), EquipmentChangeEvent.EquipMethod.RIGHT_CLICK, slot, type).schedule(); } else if (e.getItem().getAmount() == 1) - new SlotCheck(e.getPlayer(), EquipmentChangeEvent.EquipMethod.USE, slot).runTaskLater(ItemTag.get(), 1L); + new SlotCheck(e.getPlayer(), EquipmentChangeEvent.EquipMethod.USE, slot).schedule(); return; default: return; @@ -269,11 +324,11 @@ protected void handle(PlayerItemConsumeEvent event) { onEquipChange(event.getPlayer(), EquipmentChangeEvent.EquipMethod.CONSUME, slots.get(0), event.getItem(), event.getItem().getType() == Material.MILK_BUCKET ? new ItemStack(Material.BUCKET) : null); else if (slots.size() > 1) - new SlotCheck(event.getPlayer(), EquipmentChangeEvent.EquipMethod.CONSUME, slots).runTaskLater(ItemTag.get(), 1L); + new SlotCheck(event.getPlayer(), EquipmentChangeEvent.EquipMethod.CONSUME, slots).schedule(); else // 3rd party plugin if (VersionUtils.isVersionAfter(1, 9))// safe new SlotCheck(event.getPlayer(), EquipmentChangeEvent.EquipMethod.CONSUME, - Arrays.asList(EquipmentSlot.HAND, EquipmentSlot.OFF_HAND)).runTaskLater(ItemTag.get(), 1L); + Arrays.asList(EquipmentSlot.HAND, EquipmentSlot.OFF_HAND)).schedule(); } protected void handle(PlayerItemHeldEvent event) { @@ -466,12 +521,19 @@ public void run() { } - protected class SlotCheck extends BukkitRunnable { + protected class SlotCheck implements Runnable { private final EnumSet slots = EnumSet.noneOf(EquipmentSlot.class); private final Player p; private final EquipmentChangeEvent.EquipMethod method; + /** + * Runs this check one tick later on the player's region thread (Folia-safe). + */ + public void schedule() { + SchedulerUtils.runLater(ItemTag.get(), p, 1L, this); + } + public SlotCheck(Player p, EquipmentChangeEvent.EquipMethod method, EquipmentSlot... slots) { if (slots == null || slots.length == 0 || p == null || method == null) throw new IllegalArgumentException(); diff --git a/src/main/java/emanondev/itemtag/equipmentchange/EquipmentChangeListenerUpTo1_13.java b/src/main/java/emanondev/itemtag/equipmentchange/EquipmentChangeListenerUpTo1_13.java index 15cce70..9808a87 100644 --- a/src/main/java/emanondev/itemtag/equipmentchange/EquipmentChangeListenerUpTo1_13.java +++ b/src/main/java/emanondev/itemtag/equipmentchange/EquipmentChangeListenerUpTo1_13.java @@ -3,8 +3,6 @@ import emanondev.itemedit.utility.InventoryUtils; import emanondev.itemedit.utility.ItemUtils; import emanondev.itemedit.utility.VersionUtils; -import emanondev.itemtag.ItemTag; -import emanondev.itemtag.ItemTagUtility; import org.bukkit.GameMode; import org.bukkit.Material; import org.bukkit.entity.EntityType; @@ -202,10 +200,9 @@ else if (event.getHotbarButton() == p.getInventory().getHeldItemSlot()) onEquipChange(p, EquipmentChangeEvent.EquipMethod.INVENTORY_MOVE_TO_OTHER_INVENTORY, slot, null, event.getCurrentItem()); if (clickedSlot == null || clickedSlot == EquipmentSlot.HAND) new SlotCheck(p, EquipmentChangeEvent.EquipMethod.INVENTORY_MOVE_TO_OTHER_INVENTORY, EquipmentSlot.HAND) - .runTaskLater(ItemTag.get(), 1L); + .schedule(); else - new SlotCheck(p, EquipmentChangeEvent.EquipMethod.INVENTORY_MOVE_TO_OTHER_INVENTORY, clickedSlot).runTaskLater(ItemTag.get(), - 1L); + new SlotCheck(p, EquipmentChangeEvent.EquipMethod.INVENTORY_MOVE_TO_OTHER_INVENTORY, clickedSlot).schedule(); return; } case COLLECT_TO_CURSOR: @@ -218,7 +215,7 @@ else if (event.getHotbarButton() == p.getInventory().getHeldItemSlot()) else if (event.getCursor().isSimilar(getEquip(p, EquipmentSlot.HAND))) slots.add(EquipmentSlot.HAND); if (!slots.isEmpty()) - new SlotCheck(p, EquipmentChangeEvent.EquipMethod.INVENTORY_COLLECT_TO_CURSOR, slots).runTaskLater(ItemTag.get(), 1L); + new SlotCheck(p, EquipmentChangeEvent.EquipMethod.INVENTORY_COLLECT_TO_CURSOR, slots).schedule(); return; case PICKUP_SOME: case UNKNOWN: @@ -248,7 +245,7 @@ private void event(@SuppressWarnings("deprecation") PlayerPickupItemEvent event) for (int i = 0; i < event.getPlayer().getInventory().getHeldItemSlot(); i++) if (ItemUtils.isAirOrNull(event.getPlayer().getInventory().getItem(i))) return; - new SlotCheck(event.getPlayer(), EquipmentChangeEvent.EquipMethod.PICKUP, EquipmentSlot.HAND).runTaskLater(ItemTag.get(), 1L); + new SlotCheck(event.getPlayer(), EquipmentChangeEvent.EquipMethod.PICKUP, EquipmentSlot.HAND).schedule(); } private boolean isUbreakable(ItemMeta meta) { diff --git a/src/main/java/emanondev/itemtag/equipmentchange/EquipmentChangeListenerUpTo1_8.java b/src/main/java/emanondev/itemtag/equipmentchange/EquipmentChangeListenerUpTo1_8.java index f886241..43908dd 100644 --- a/src/main/java/emanondev/itemtag/equipmentchange/EquipmentChangeListenerUpTo1_8.java +++ b/src/main/java/emanondev/itemtag/equipmentchange/EquipmentChangeListenerUpTo1_8.java @@ -2,7 +2,6 @@ import emanondev.itemedit.utility.InventoryUtils; import emanondev.itemedit.utility.ItemUtils; -import emanondev.itemtag.ItemTag; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; @@ -190,10 +189,9 @@ else if (event.getHotbarButton() == p.getInventory().getHeldItemSlot()) onEquipChange(p, EquipmentChangeEvent.EquipMethod.INVENTORY_MOVE_TO_OTHER_INVENTORY, slot, null, event.getCurrentItem()); if (clickedSlot == null || clickedSlot == EquipmentSlot.HAND) new SlotCheck(p, EquipmentChangeEvent.EquipMethod.INVENTORY_MOVE_TO_OTHER_INVENTORY, EquipmentSlot.HAND) - .runTaskLater(ItemTag.get(), 1L); + .schedule(); else - new SlotCheck(p, EquipmentChangeEvent.EquipMethod.INVENTORY_MOVE_TO_OTHER_INVENTORY, clickedSlot).runTaskLater(ItemTag.get(), - 1L); + new SlotCheck(p, EquipmentChangeEvent.EquipMethod.INVENTORY_MOVE_TO_OTHER_INVENTORY, clickedSlot).schedule(); return; } case COLLECT_TO_CURSOR: @@ -206,7 +204,7 @@ else if (event.getHotbarButton() == p.getInventory().getHeldItemSlot()) else if (event.getCursor().isSimilar(getEquip(p, EquipmentSlot.HAND))) slots.add(EquipmentSlot.HAND); if (!slots.isEmpty()) - new SlotCheck(p, EquipmentChangeEvent.EquipMethod.INVENTORY_COLLECT_TO_CURSOR, slots).runTaskLater(ItemTag.get(), 1L); + new SlotCheck(p, EquipmentChangeEvent.EquipMethod.INVENTORY_COLLECT_TO_CURSOR, slots).schedule(); return; case PICKUP_SOME: case UNKNOWN: @@ -224,7 +222,7 @@ private void event(@SuppressWarnings("deprecation") PlayerPickupItemEvent event) for (int i = 0; i < event.getPlayer().getInventory().getHeldItemSlot(); i++) if (ItemUtils.isAirOrNull(event.getPlayer().getInventory().getItem(i))) return; - new SlotCheck(event.getPlayer(), EquipmentChangeEvent.EquipMethod.PICKUP, EquipmentSlot.HAND).runTaskLater(ItemTag.get(), 1L); + new SlotCheck(event.getPlayer(), EquipmentChangeEvent.EquipMethod.PICKUP, EquipmentSlot.HAND).schedule(); } private boolean isUbreakable(ItemMeta meta) {