From a18a9a0deac89f573af1eeb58cfceea2be453670 Mon Sep 17 00:00:00 2001 From: Mykhailo Alipa <6442572+strobil@users.noreply.github.com> Date: Mon, 19 Oct 2026 20:37:24 +0200 Subject: [PATCH 1/5] Protect cushion placement in claimed regions --- .../bukkit/listener/EventAbstractionListener.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/EventAbstractionListener.java b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/EventAbstractionListener.java index 129e4e6fc..b66ebae4c 100644 --- a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/EventAbstractionListener.java +++ b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/EventAbstractionListener.java @@ -128,6 +128,7 @@ import org.bukkit.event.entity.EntityInteractEvent; import org.bukkit.event.entity.EntityKnockbackByEntityEvent; import org.bukkit.event.entity.EntityPickupItemEvent; +import org.bukkit.event.entity.EntityPlaceEvent; import org.bukkit.event.entity.EntityTameEvent; import org.bukkit.event.entity.EntityUnleashEvent; import org.bukkit.event.entity.ExpBottleEvent; @@ -782,6 +783,19 @@ public void onCreatureSpawn(CreatureSpawnEvent event) { } } + @EventHandler(ignoreCancelled = true) + public void onEntityPlace(EntityPlaceEvent event) { + if (event.getEntityType() != EntityType.CUSHION) { + return; + } + + Events.fireToCancel(event, new SpawnEntityEvent(event, create(event.getPlayer()), event.getEntity())); + + if (event.isCancelled() && event.getPlayer() != null) { + playDenyEffect(event.getPlayer(), event.getEntity().getLocation()); + } + } + @EventHandler(ignoreCancelled = true) public void onHangingPlace(HangingPlaceEvent event) { Events.fireToCancel(event, new SpawnEntityEvent(event, create(event.getPlayer()), event.getEntity())); From d4c7a1fe5e216518d4d171c645bf79303dac2ed4 Mon Sep 17 00:00:00 2001 From: Mykhailo Alipa <6442572+strobil@users.noreply.github.com> Date: Mon, 19 Oct 2026 20:43:10 +0200 Subject: [PATCH 2/5] Use entity placement events for all player-placed entities --- .../listener/EventAbstractionListener.java | 58 +++++++++---------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/EventAbstractionListener.java b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/EventAbstractionListener.java index b66ebae4c..55a8085a3 100644 --- a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/EventAbstractionListener.java +++ b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/EventAbstractionListener.java @@ -785,10 +785,6 @@ public void onCreatureSpawn(CreatureSpawnEvent event) { @EventHandler(ignoreCancelled = true) public void onEntityPlace(EntityPlaceEvent event) { - if (event.getEntityType() != EntityType.CUSHION) { - return; - } - Events.fireToCancel(event, new SpawnEntityEvent(event, create(event.getPlayer()), event.getEntity())); if (event.isCancelled() && event.getPlayer() != null) { @@ -1268,36 +1264,40 @@ private static void handleBlockRightClick(T even return; } - // Handle created Minecarts - if (item != null && Materials.isMinecart(item.getType())) { - EntityType entityType = Materials.getRelatedEntity(item.getType()); - if (entityType == null) { - entityType = EntityType.MINECART; + // Player placements are checked at the entity's final position by onEntityPlace. + // Retain the item-based checks for dispensers. + if (event instanceof BlockDispenseEvent) { + // Handle created Minecarts + if (item != null && Materials.isMinecart(item.getType())) { + EntityType entityType = Materials.getRelatedEntity(item.getType()); + if (entityType == null) { + entityType = EntityType.MINECART; + } + Events.fireToCancel(event, new SpawnEntityEvent(event, cause, clicked.getLocation().add(0.5, 0, 0.5), entityType)); + return; } - Events.fireToCancel(event, new SpawnEntityEvent(event, cause, clicked.getLocation().add(0.5, 0, 0.5), entityType)); - return; - } - // Handle created boats - if (item != null && Materials.isBoat(item.getType())) { - EntityType entityType = Materials.getRelatedEntity(item.getType()); - if (entityType == null) { - entityType = EntityType.OAK_BOAT; + // Handle created boats + if (item != null && Materials.isBoat(item.getType())) { + EntityType entityType = Materials.getRelatedEntity(item.getType()); + if (entityType == null) { + entityType = EntityType.OAK_BOAT; + } + Events.fireToCancel(event, new SpawnEntityEvent(event, cause, placed.getLocation().add(0.5, 0, 0.5), entityType)); + return; } - Events.fireToCancel(event, new SpawnEntityEvent(event, cause, placed.getLocation().add(0.5, 0, 0.5), entityType)); - return; - } - // Handle created armor stands - if (item != null && item.getType() == Material.ARMOR_STAND) { - Events.fireToCancel(event, new SpawnEntityEvent(event, cause, placed.getLocation().add(0.5, 0, 0.5), EntityType.ARMOR_STAND)); - return; - } + // Handle created armor stands + if (item != null && item.getType() == Material.ARMOR_STAND) { + Events.fireToCancel(event, new SpawnEntityEvent(event, cause, placed.getLocation().add(0.5, 0, 0.5), EntityType.ARMOR_STAND)); + return; + } - if (item != null && item.getType() == Material.END_CRYSTAL) { /*&& placed.getType() == Material.BEDROCK) {*/ // in vanilla you can only place them on bedrock but who knows what plugins will add - // may be overprotective as a result, but better than being underprotective - Events.fireToCancel(event, new SpawnEntityEvent(event, cause, placed.getLocation().add(0.5, 0, 0.5), EntityType.END_CRYSTAL)); - return; + if (item != null && item.getType() == Material.END_CRYSTAL) { /*&& placed.getType() == Material.BEDROCK) {*/ // in vanilla you can only place them on bedrock but who knows what plugins will add + // may be overprotective as a result, but better than being underprotective + Events.fireToCancel(event, new SpawnEntityEvent(event, cause, placed.getLocation().add(0.5, 0, 0.5), EntityType.END_CRYSTAL)); + return; + } } // Handle created spawn eggs From 81d87bfec296ce54c805e035f4999136e6622d66 Mon Sep 17 00:00:00 2001 From: Mykhailo Alipa <6442572+strobil@users.noreply.github.com> Date: Mon, 19 Oct 2026 20:45:44 +0200 Subject: [PATCH 3/5] Minimize the entity placement diff --- .../listener/EventAbstractionListener.java | 55 +++++++++---------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/EventAbstractionListener.java b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/EventAbstractionListener.java index 55a8085a3..444f5a994 100644 --- a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/EventAbstractionListener.java +++ b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/EventAbstractionListener.java @@ -1265,39 +1265,38 @@ private static void handleBlockRightClick(T even } // Player placements are checked at the entity's final position by onEntityPlace. - // Retain the item-based checks for dispensers. - if (event instanceof BlockDispenseEvent) { - // Handle created Minecarts - if (item != null && Materials.isMinecart(item.getType())) { - EntityType entityType = Materials.getRelatedEntity(item.getType()); - if (entityType == null) { - entityType = EntityType.MINECART; - } - Events.fireToCancel(event, new SpawnEntityEvent(event, cause, clicked.getLocation().add(0.5, 0, 0.5), entityType)); - return; - } + boolean fromDispenser = event instanceof BlockDispenseEvent; - // Handle created boats - if (item != null && Materials.isBoat(item.getType())) { - EntityType entityType = Materials.getRelatedEntity(item.getType()); - if (entityType == null) { - entityType = EntityType.OAK_BOAT; - } - Events.fireToCancel(event, new SpawnEntityEvent(event, cause, placed.getLocation().add(0.5, 0, 0.5), entityType)); - return; + // Handle created Minecarts + if (fromDispenser && item != null && Materials.isMinecart(item.getType())) { + EntityType entityType = Materials.getRelatedEntity(item.getType()); + if (entityType == null) { + entityType = EntityType.MINECART; } + Events.fireToCancel(event, new SpawnEntityEvent(event, cause, clicked.getLocation().add(0.5, 0, 0.5), entityType)); + return; + } - // Handle created armor stands - if (item != null && item.getType() == Material.ARMOR_STAND) { - Events.fireToCancel(event, new SpawnEntityEvent(event, cause, placed.getLocation().add(0.5, 0, 0.5), EntityType.ARMOR_STAND)); - return; + // Handle created boats + if (fromDispenser && item != null && Materials.isBoat(item.getType())) { + EntityType entityType = Materials.getRelatedEntity(item.getType()); + if (entityType == null) { + entityType = EntityType.OAK_BOAT; } + Events.fireToCancel(event, new SpawnEntityEvent(event, cause, placed.getLocation().add(0.5, 0, 0.5), entityType)); + return; + } - if (item != null && item.getType() == Material.END_CRYSTAL) { /*&& placed.getType() == Material.BEDROCK) {*/ // in vanilla you can only place them on bedrock but who knows what plugins will add - // may be overprotective as a result, but better than being underprotective - Events.fireToCancel(event, new SpawnEntityEvent(event, cause, placed.getLocation().add(0.5, 0, 0.5), EntityType.END_CRYSTAL)); - return; - } + // Handle created armor stands + if (fromDispenser && item != null && item.getType() == Material.ARMOR_STAND) { + Events.fireToCancel(event, new SpawnEntityEvent(event, cause, placed.getLocation().add(0.5, 0, 0.5), EntityType.ARMOR_STAND)); + return; + } + + if (fromDispenser && item != null && item.getType() == Material.END_CRYSTAL) { /*&& placed.getType() == Material.BEDROCK) {*/ // in vanilla you can only place them on bedrock but who knows what plugins will add + // may be overprotective as a result, but better than being underprotective + Events.fireToCancel(event, new SpawnEntityEvent(event, cause, placed.getLocation().add(0.5, 0, 0.5), EntityType.END_CRYSTAL)); + return; } // Handle created spawn eggs From 2dd62c0c3d253bf318ca04ea70adc9baf96a5080 Mon Sep 17 00:00:00 2001 From: Mykhailo Alipa <6442572+strobil@users.noreply.github.com> Date: Mon, 19 Oct 2026 20:51:30 +0200 Subject: [PATCH 4/5] Handle cushions through the existing item placement path --- .../listener/EventAbstractionListener.java | 27 +++++++------------ 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/EventAbstractionListener.java b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/EventAbstractionListener.java index 444f5a994..8003e6f2c 100644 --- a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/EventAbstractionListener.java +++ b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/EventAbstractionListener.java @@ -128,7 +128,6 @@ import org.bukkit.event.entity.EntityInteractEvent; import org.bukkit.event.entity.EntityKnockbackByEntityEvent; import org.bukkit.event.entity.EntityPickupItemEvent; -import org.bukkit.event.entity.EntityPlaceEvent; import org.bukkit.event.entity.EntityTameEvent; import org.bukkit.event.entity.EntityUnleashEvent; import org.bukkit.event.entity.ExpBottleEvent; @@ -783,15 +782,6 @@ public void onCreatureSpawn(CreatureSpawnEvent event) { } } - @EventHandler(ignoreCancelled = true) - public void onEntityPlace(EntityPlaceEvent event) { - Events.fireToCancel(event, new SpawnEntityEvent(event, create(event.getPlayer()), event.getEntity())); - - if (event.isCancelled() && event.getPlayer() != null) { - playDenyEffect(event.getPlayer(), event.getEntity().getLocation()); - } - } - @EventHandler(ignoreCancelled = true) public void onHangingPlace(HangingPlaceEvent event) { Events.fireToCancel(event, new SpawnEntityEvent(event, create(event.getPlayer()), event.getEntity())); @@ -1264,11 +1254,8 @@ private static void handleBlockRightClick(T even return; } - // Player placements are checked at the entity's final position by onEntityPlace. - boolean fromDispenser = event instanceof BlockDispenseEvent; - // Handle created Minecarts - if (fromDispenser && item != null && Materials.isMinecart(item.getType())) { + if (item != null && Materials.isMinecart(item.getType())) { EntityType entityType = Materials.getRelatedEntity(item.getType()); if (entityType == null) { entityType = EntityType.MINECART; @@ -1278,7 +1265,7 @@ private static void handleBlockRightClick(T even } // Handle created boats - if (fromDispenser && item != null && Materials.isBoat(item.getType())) { + if (item != null && Materials.isBoat(item.getType())) { EntityType entityType = Materials.getRelatedEntity(item.getType()); if (entityType == null) { entityType = EntityType.OAK_BOAT; @@ -1287,13 +1274,19 @@ private static void handleBlockRightClick(T even return; } + // Handle created cushions + if (item != null && Tag.ITEMS_CUSHIONS.isTagged(item.getType())) { + Events.fireToCancel(event, new SpawnEntityEvent(event, cause, placed.getLocation().add(0.5, 0, 0.5), EntityType.CUSHION)); + return; + } + // Handle created armor stands - if (fromDispenser && item != null && item.getType() == Material.ARMOR_STAND) { + if (item != null && item.getType() == Material.ARMOR_STAND) { Events.fireToCancel(event, new SpawnEntityEvent(event, cause, placed.getLocation().add(0.5, 0, 0.5), EntityType.ARMOR_STAND)); return; } - if (fromDispenser && item != null && item.getType() == Material.END_CRYSTAL) { /*&& placed.getType() == Material.BEDROCK) {*/ // in vanilla you can only place them on bedrock but who knows what plugins will add + if (item != null && item.getType() == Material.END_CRYSTAL) { /*&& placed.getType() == Material.BEDROCK) {*/ // in vanilla you can only place them on bedrock but who knows what plugins will add // may be overprotective as a result, but better than being underprotective Events.fireToCancel(event, new SpawnEntityEvent(event, cause, placed.getLocation().add(0.5, 0, 0.5), EntityType.END_CRYSTAL)); return; From e0b2347ce7c3fff67ae513c3f63fa9ec8ca4f646 Mon Sep 17 00:00:00 2001 From: Mykhailo Alipa <6442572+strobil@users.noreply.github.com> Date: Mon, 19 Oct 2026 20:54:33 +0200 Subject: [PATCH 5/5] Add a cushion material helper matching the boat check --- .../bukkit/listener/EventAbstractionListener.java | 2 +- .../com/sk89q/worldguard/bukkit/util/Materials.java | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/EventAbstractionListener.java b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/EventAbstractionListener.java index 8003e6f2c..0b274f505 100644 --- a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/EventAbstractionListener.java +++ b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/EventAbstractionListener.java @@ -1275,7 +1275,7 @@ private static void handleBlockRightClick(T even } // Handle created cushions - if (item != null && Tag.ITEMS_CUSHIONS.isTagged(item.getType())) { + if (item != null && Materials.isCushion(item.getType())) { Events.fireToCancel(event, new SpawnEntityEvent(event, cause, placed.getLocation().add(0.5, 0, 0.5), EntityType.CUSHION)); return; } diff --git a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/util/Materials.java b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/util/Materials.java index 73cb73591..db1a3d101 100644 --- a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/util/Materials.java +++ b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/util/Materials.java @@ -1181,6 +1181,16 @@ public static boolean isBoat(Material material) { return Tag.ITEMS_BOATS.isTagged(material); } + /** + * Test whether the given material is a Cushion. + * + * @param material the material + * @return true if a Cushion item + */ + public static boolean isCushion(Material material) { + return Tag.ITEMS_CUSHIONS.isTagged(material); + } + /** * Test whether the given material is a Shulker Box. *