diff --git a/pom.xml b/pom.xml index 8ad0cbe..e888e33 100755 --- a/pom.xml +++ b/pom.xml @@ -216,7 +216,7 @@ io.papermc.paper paper-api - 1.21.1-R0.1-SNAPSHOT + 1.21.10-R0.1-SNAPSHOT provided diff --git a/src/main/java/net/coreprotect/listener/ListenerHandler.java b/src/main/java/net/coreprotect/listener/ListenerHandler.java index 338b532..64beee4 100644 --- a/src/main/java/net/coreprotect/listener/ListenerHandler.java +++ b/src/main/java/net/coreprotect/listener/ListenerHandler.java @@ -55,6 +55,7 @@ import net.coreprotect.listener.world.LeavesDecayListener; import net.coreprotect.listener.world.PortalCreateListener; import net.coreprotect.listener.world.StructureGrowListener; import net.coreprotect.paper.listener.BlockPreDispenseListener; +import net.coreprotect.paper.listener.CopperGolemChestListener; import net.coreprotect.paper.listener.PaperChatListener; public final class ListenerHandler { @@ -72,6 +73,14 @@ public final class ListenerHandler { BlockPreDispenseListener.useBlockPreDispenseEvent = false; } + try { + Class.forName("io.papermc.paper.event.entity.ItemTransportingEntityValidateTargetEvent"); // Paper 1.21.10+ + pluginManager.registerEvents(new CopperGolemChestListener(plugin), plugin); + } + catch (Exception e) { + // Ignore registration failures to remain compatible with older servers. + } + // Block Listeners pluginManager.registerEvents(new BlockBreakListener(), plugin); pluginManager.registerEvents(new BlockBurnListener(), plugin); diff --git a/src/main/java/net/coreprotect/paper/listener/CopperGolemChestListener.java b/src/main/java/net/coreprotect/paper/listener/CopperGolemChestListener.java new file mode 100644 index 0000000..b6874ee --- /dev/null +++ b/src/main/java/net/coreprotect/paper/listener/CopperGolemChestListener.java @@ -0,0 +1,108 @@ +package net.coreprotect.paper.listener; + +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +import org.bukkit.Location; +import org.bukkit.block.Block; +import org.bukkit.block.BlockState; +import org.bukkit.entity.Entity; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.inventory.InventoryHolder; +import org.bukkit.scheduler.BukkitTask; + +import io.papermc.paper.event.entity.ItemTransportingEntityValidateTargetEvent; +import net.coreprotect.CoreProtect; +import net.coreprotect.config.Config; +import net.coreprotect.listener.player.InventoryChangeListener; + +public final class CopperGolemChestListener implements Listener { + + private static final String COPPER_GOLEM_NAME = "COPPER_GOLEM"; + private static final String USERNAME = "#copper_golem"; + private static final long DELAY_TICKS = 50L; + + private final CoreProtect plugin; + private final Map pendingTransactions = new ConcurrentHashMap<>(); + + public CopperGolemChestListener(CoreProtect plugin) { + this.plugin = plugin; + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onValidate(ItemTransportingEntityValidateTargetEvent event) { + if (!event.isAllowed()) { + return; + } + + Entity entity = event.getEntity(); + if (entity == null || entity.getType() == null || !COPPER_GOLEM_NAME.equals(entity.getType().name())) { + return; + } + + Block block = event.getBlock(); + if (block == null) { + return; + } + + BlockState blockState = block.getState(); + if (!(blockState instanceof InventoryHolder)) { + return; + } + + Location location = blockState.getLocation(); + if (location == null || location.getWorld() == null) { + return; + } + + if (!Config.getConfig(location.getWorld()).ITEM_TRANSACTIONS) { + return; + } + + scheduleTransaction(entity, location); + } + + private void scheduleTransaction(Entity entity, Location location) { + UUID entityId = entity.getUniqueId(); + PendingTransaction pendingTransaction = pendingTransactions.remove(entityId); + if (pendingTransaction != null) { + pendingTransaction.cancel(); + } + + Location targetLocation = location.clone(); + PendingTransaction scheduled = new PendingTransaction(); + BukkitTask task = plugin.getServer().getScheduler().runTaskLater(plugin, () -> { + if (!pendingTransactions.remove(entityId, scheduled)) { + return; + } + + Entity trackedEntity = plugin.getServer().getEntity(entityId); + if (trackedEntity == null || !trackedEntity.isValid()) { + return; + } + + InventoryChangeListener.inventoryTransaction(USERNAME, targetLocation, null); + }, DELAY_TICKS); + + scheduled.setTask(task); + pendingTransactions.put(entityId, scheduled); + } + + private static final class PendingTransaction { + + private BukkitTask task; + + private void cancel() { + if (task != null) { + task.cancel(); + } + } + + private void setTask(BukkitTask task) { + this.task = task; + } + } +} diff --git a/src/main/java/net/coreprotect/worldedit/WorldEditBlockState.java b/src/main/java/net/coreprotect/worldedit/WorldEditBlockState.java index 89007f1..23a9a81 100644 --- a/src/main/java/net/coreprotect/worldedit/WorldEditBlockState.java +++ b/src/main/java/net/coreprotect/worldedit/WorldEditBlockState.java @@ -196,4 +196,9 @@ public final class WorldEditBlockState implements BlockState { return null; } + @Override + public boolean isSuffocating() { + return false; + } + }