001/* 002 * PlotSquared, a land and world management plugin for Minecraft. 003 * Copyright (C) IntellectualSites <https://intellectualsites.com> 004 * Copyright (C) IntellectualSites team and contributors 005 * 006 * This program is free software: you can redistribute it and/or modify 007 * it under the terms of the GNU General Public License as published by 008 * the Free Software Foundation, either version 3 of the License, or 009 * (at your option) any later version. 010 * 011 * This program is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU General Public License for more details. 015 * 016 * You should have received a copy of the GNU General Public License 017 * along with this program. If not, see <https://www.gnu.org/licenses/>. 018 */ 019package com.plotsquared.bukkit.listener; 020 021import com.destroystokyo.paper.MaterialTags; 022import com.google.common.base.Charsets; 023import com.google.inject.Inject; 024import com.plotsquared.bukkit.player.BukkitPlayer; 025import com.plotsquared.bukkit.util.BukkitEntityUtil; 026import com.plotsquared.bukkit.util.BukkitUtil; 027import com.plotsquared.bukkit.util.UpdateUtility; 028import com.plotsquared.core.PlotSquared; 029import com.plotsquared.core.configuration.Settings; 030import com.plotsquared.core.configuration.caption.Caption; 031import com.plotsquared.core.configuration.caption.TranslatableCaption; 032import com.plotsquared.core.listener.PlayerBlockEventType; 033import com.plotsquared.core.listener.PlotListener; 034import com.plotsquared.core.location.Location; 035import com.plotsquared.core.permissions.Permission; 036import com.plotsquared.core.player.ConsolePlayer; 037import com.plotsquared.core.player.MetaDataAccess; 038import com.plotsquared.core.player.PlayerMetaDataKeys; 039import com.plotsquared.core.player.PlotPlayer; 040import com.plotsquared.core.plot.Plot; 041import com.plotsquared.core.plot.PlotArea; 042import com.plotsquared.core.plot.PlotId; 043import com.plotsquared.core.plot.PlotInventory; 044import com.plotsquared.core.plot.flag.FlagContainer; 045import com.plotsquared.core.plot.flag.implementations.AnimalInteractFlag; 046import com.plotsquared.core.plot.flag.implementations.BlockedCmdsFlag; 047import com.plotsquared.core.plot.flag.implementations.ChatFlag; 048import com.plotsquared.core.plot.flag.implementations.DenyPortalTravelFlag; 049import com.plotsquared.core.plot.flag.implementations.DenyPortalsFlag; 050import com.plotsquared.core.plot.flag.implementations.DenyTeleportFlag; 051import com.plotsquared.core.plot.flag.implementations.DoneFlag; 052import com.plotsquared.core.plot.flag.implementations.DropProtectionFlag; 053import com.plotsquared.core.plot.flag.implementations.EditSignFlag; 054import com.plotsquared.core.plot.flag.implementations.HangingBreakFlag; 055import com.plotsquared.core.plot.flag.implementations.HangingPlaceFlag; 056import com.plotsquared.core.plot.flag.implementations.HostileInteractFlag; 057import com.plotsquared.core.plot.flag.implementations.InteractionInteractFlag; 058import com.plotsquared.core.plot.flag.implementations.ItemDropFlag; 059import com.plotsquared.core.plot.flag.implementations.KeepInventoryFlag; 060import com.plotsquared.core.plot.flag.implementations.LecternReadBookFlag; 061import com.plotsquared.core.plot.flag.implementations.MiscInteractFlag; 062import com.plotsquared.core.plot.flag.implementations.PlayerInteractFlag; 063import com.plotsquared.core.plot.flag.implementations.PreventCreativeCopyFlag; 064import com.plotsquared.core.plot.flag.implementations.TamedInteractFlag; 065import com.plotsquared.core.plot.flag.implementations.TileDropFlag; 066import com.plotsquared.core.plot.flag.implementations.UntrustedVisitFlag; 067import com.plotsquared.core.plot.flag.implementations.VehicleBreakFlag; 068import com.plotsquared.core.plot.flag.implementations.VehicleUseFlag; 069import com.plotsquared.core.plot.flag.implementations.VillagerInteractFlag; 070import com.plotsquared.core.plot.world.PlotAreaManager; 071import com.plotsquared.core.util.EventDispatcher; 072import com.plotsquared.core.util.MathMan; 073import com.plotsquared.core.util.PlotFlagUtil; 074import com.plotsquared.core.util.PremiumVerification; 075import com.plotsquared.core.util.entity.EntityCategories; 076import com.plotsquared.core.util.task.TaskManager; 077import com.plotsquared.core.util.task.TaskTime; 078import com.sk89q.worldedit.WorldEdit; 079import com.sk89q.worldedit.bukkit.BukkitAdapter; 080import com.sk89q.worldedit.world.block.BlockType; 081import io.papermc.lib.PaperLib; 082import net.kyori.adventure.text.Component; 083import net.kyori.adventure.text.minimessage.MiniMessage; 084import net.kyori.adventure.text.minimessage.tag.Tag; 085import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; 086import net.kyori.adventure.text.minimessage.tag.standard.StandardTags; 087import org.bukkit.Bukkit; 088import org.bukkit.FluidCollisionMode; 089import org.bukkit.Material; 090import org.bukkit.block.Block; 091import org.bukkit.block.BlockFace; 092import org.bukkit.block.BlockState; 093import org.bukkit.block.Sign; 094import org.bukkit.block.data.Waterlogged; 095import org.bukkit.command.PluginCommand; 096import org.bukkit.entity.ArmorStand; 097import org.bukkit.entity.Boat; 098import org.bukkit.entity.Entity; 099import org.bukkit.entity.EntityType; 100import org.bukkit.entity.HumanEntity; 101import org.bukkit.entity.ItemFrame; 102import org.bukkit.entity.LivingEntity; 103import org.bukkit.entity.Player; 104import org.bukkit.entity.Projectile; 105import org.bukkit.entity.Tameable; 106import org.bukkit.entity.Vehicle; 107import org.bukkit.event.Event; 108import org.bukkit.event.EventHandler; 109import org.bukkit.event.EventPriority; 110import org.bukkit.event.Listener; 111import org.bukkit.event.block.Action; 112import org.bukkit.event.block.BlockBreakEvent; 113import org.bukkit.event.entity.EntityPickupItemEvent; 114import org.bukkit.event.entity.EntityPlaceEvent; 115import org.bukkit.event.entity.EntityPotionEffectEvent; 116import org.bukkit.event.entity.PlayerDeathEvent; 117import org.bukkit.event.hanging.HangingBreakByEntityEvent; 118import org.bukkit.event.hanging.HangingPlaceEvent; 119import org.bukkit.event.inventory.ClickType; 120import org.bukkit.event.inventory.InventoryClickEvent; 121import org.bukkit.event.inventory.InventoryCloseEvent; 122import org.bukkit.event.player.AsyncPlayerChatEvent; 123import org.bukkit.event.player.AsyncPlayerPreLoginEvent; 124import org.bukkit.event.player.PlayerBucketEmptyEvent; 125import org.bukkit.event.player.PlayerBucketFillEvent; 126import org.bukkit.event.player.PlayerChangedWorldEvent; 127import org.bukkit.event.player.PlayerCommandPreprocessEvent; 128import org.bukkit.event.player.PlayerDropItemEvent; 129import org.bukkit.event.player.PlayerEvent; 130import org.bukkit.event.player.PlayerInteractAtEntityEvent; 131import org.bukkit.event.player.PlayerInteractEntityEvent; 132import org.bukkit.event.player.PlayerInteractEvent; 133import org.bukkit.event.player.PlayerJoinEvent; 134import org.bukkit.event.player.PlayerLocaleChangeEvent; 135import org.bukkit.event.player.PlayerMoveEvent; 136import org.bukkit.event.player.PlayerPortalEvent; 137import org.bukkit.event.player.PlayerQuitEvent; 138import org.bukkit.event.player.PlayerRespawnEvent; 139import org.bukkit.event.player.PlayerTakeLecternBookEvent; 140import org.bukkit.event.player.PlayerTeleportEvent; 141import org.bukkit.event.vehicle.VehicleDestroyEvent; 142import org.bukkit.event.vehicle.VehicleEntityCollisionEvent; 143import org.bukkit.event.vehicle.VehicleMoveEvent; 144import org.bukkit.event.world.PortalCreateEvent; 145import org.bukkit.help.HelpTopic; 146import org.bukkit.inventory.ItemStack; 147import org.bukkit.inventory.PlayerInventory; 148import org.bukkit.inventory.meta.ItemMeta; 149import org.bukkit.metadata.FixedMetadataValue; 150import org.bukkit.metadata.MetadataValue; 151import org.bukkit.plugin.Plugin; 152import org.bukkit.potion.PotionEffect; 153import org.bukkit.util.Vector; 154import org.checkerframework.checker.nullness.qual.NonNull; 155 156import java.lang.reflect.Field; 157import java.util.HashSet; 158import java.util.List; 159import java.util.Locale; 160import java.util.Set; 161import java.util.UUID; 162 163/** 164 * Player Events involving plots. 165 */ 166@SuppressWarnings("unused") 167public class PlayerEventListener implements Listener { 168 169 private static final Set<Material> MINECARTS = Set.of( 170 Material.MINECART, 171 Material.TNT_MINECART, 172 Material.CHEST_MINECART, 173 Material.COMMAND_BLOCK_MINECART, 174 Material.FURNACE_MINECART, 175 Material.HOPPER_MINECART 176 ); 177 private static final Set<Material> BOOKS = Set.of( 178 Material.BOOK, 179 Material.KNOWLEDGE_BOOK, 180 Material.WRITABLE_BOOK, 181 Material.WRITTEN_BOOK 182 ); 183 private static final Set<String> DYES; 184 static { 185 Set<String> mutableDyes = new HashSet<>(Set.of( 186 "WHITE_DYE", 187 "LIGHT_GRAY_DYE", 188 "GRAY_DYE", 189 "BLACK_DYE", 190 "BROWN_DYE", 191 "RED_DYE", 192 "ORANGE_DYE", 193 "YELLOW_DYE", 194 "LIME_DYE", 195 "GREEN_DYE", 196 "CYAN_DYE", 197 "LIGHT_BLUE_DYE", 198 "BLUE_DYE", 199 "PURPLE_DYE", 200 "MAGENTA_DYE", 201 "PINK_DYE", 202 "GLOW_INK_SAC" 203 )); 204 int[] version = PlotSquared.platform().serverVersion(); 205 if (version[1] >= 20) { 206 mutableDyes.add("HONEYCOMB"); 207 } 208 DYES = Set.copyOf(mutableDyes); 209 } 210 211 private static final Set<String> INTERACTABLE_MATERIALS; 212 213 static { 214 // @formatter:off 215 // "temporary" fix for https://hub.spigotmc.org/jira/browse/SPIGOT-7813 216 // can (and should) be removed when 1.21 support is dropped 217 // List of all interactable 1.21 materials 218 INTERACTABLE_MATERIALS = Material.CHEST.isInteractable() ? null : Set.of( 219 "REDSTONE_ORE", "DEEPSLATE_REDSTONE_ORE", "CHISELED_BOOKSHELF", "DECORATED_POT", "CHEST", "CRAFTING_TABLE", 220 "FURNACE", "JUKEBOX", "OAK_FENCE", "SPRUCE_FENCE", "BIRCH_FENCE", "JUNGLE_FENCE", "ACACIA_FENCE", "CHERRY_FENCE", 221 "DARK_OAK_FENCE", "MANGROVE_FENCE", "BAMBOO_FENCE", "CRIMSON_FENCE", "WARPED_FENCE", "PUMPKIN", 222 "NETHER_BRICK_FENCE", "ENCHANTING_TABLE", "DRAGON_EGG", "ENDER_CHEST", "COMMAND_BLOCK", "BEACON", "ANVIL", 223 "CHIPPED_ANVIL", "DAMAGED_ANVIL", "LIGHT", "REPEATING_COMMAND_BLOCK", "CHAIN_COMMAND_BLOCK", "SHULKER_BOX", 224 "WHITE_SHULKER_BOX", "ORANGE_SHULKER_BOX", "MAGENTA_SHULKER_BOX", "LIGHT_BLUE_SHULKER_BOX", "YELLOW_SHULKER_BOX", 225 "LIME_SHULKER_BOX", "PINK_SHULKER_BOX", "GRAY_SHULKER_BOX", "LIGHT_GRAY_SHULKER_BOX", "CYAN_SHULKER_BOX", 226 "PURPLE_SHULKER_BOX", "BLUE_SHULKER_BOX", "BROWN_SHULKER_BOX", "GREEN_SHULKER_BOX", "RED_SHULKER_BOX", 227 "BLACK_SHULKER_BOX", "REPEATER", "COMPARATOR", "HOPPER", "DISPENSER", "DROPPER", "LECTERN", "LEVER", 228 "DAYLIGHT_DETECTOR", "TRAPPED_CHEST", "TNT", "NOTE_BLOCK", "STONE_BUTTON", "POLISHED_BLACKSTONE_BUTTON", 229 "OAK_BUTTON", "SPRUCE_BUTTON", "BIRCH_BUTTON", "JUNGLE_BUTTON", "ACACIA_BUTTON", "CHERRY_BUTTON", 230 "DARK_OAK_BUTTON", "MANGROVE_BUTTON", "BAMBOO_BUTTON", "CRIMSON_BUTTON", "WARPED_BUTTON", "IRON_DOOR", "OAK_DOOR", 231 "SPRUCE_DOOR", "BIRCH_DOOR", "JUNGLE_DOOR", "ACACIA_DOOR", "CHERRY_DOOR", "DARK_OAK_DOOR", "MANGROVE_DOOR", 232 "BAMBOO_DOOR", "CRIMSON_DOOR", "WARPED_DOOR", "COPPER_DOOR", "EXPOSED_COPPER_DOOR", "WEATHERED_COPPER_DOOR", 233 "OXIDIZED_COPPER_DOOR", "WAXED_COPPER_DOOR", "WAXED_EXPOSED_COPPER_DOOR", "WAXED_WEATHERED_COPPER_DOOR", 234 "WAXED_OXIDIZED_COPPER_DOOR", "IRON_TRAPDOOR", "OAK_TRAPDOOR", "SPRUCE_TRAPDOOR", "BIRCH_TRAPDOOR", 235 "JUNGLE_TRAPDOOR", "ACACIA_TRAPDOOR", "CHERRY_TRAPDOOR", "DARK_OAK_TRAPDOOR", "MANGROVE_TRAPDOOR", 236 "BAMBOO_TRAPDOOR", "CRIMSON_TRAPDOOR", "WARPED_TRAPDOOR", "COPPER_TRAPDOOR", "EXPOSED_COPPER_TRAPDOOR", 237 "WEATHERED_COPPER_TRAPDOOR", "OXIDIZED_COPPER_TRAPDOOR", "WAXED_COPPER_TRAPDOOR", "WAXED_EXPOSED_COPPER_TRAPDOOR", 238 "WAXED_WEATHERED_COPPER_TRAPDOOR", "WAXED_OXIDIZED_COPPER_TRAPDOOR", "OAK_FENCE_GATE", "SPRUCE_FENCE_GATE", 239 "BIRCH_FENCE_GATE", "JUNGLE_FENCE_GATE", "ACACIA_FENCE_GATE", "CHERRY_FENCE_GATE", "DARK_OAK_FENCE_GATE", 240 "MANGROVE_FENCE_GATE", "BAMBOO_FENCE_GATE", "CRIMSON_FENCE_GATE", "WARPED_FENCE_GATE", "STRUCTURE_BLOCK", 241 "JIGSAW", "OAK_SIGN", "SPRUCE_SIGN", "BIRCH_SIGN", "JUNGLE_SIGN", "ACACIA_SIGN", "CHERRY_SIGN", "DARK_OAK_SIGN", 242 "MANGROVE_SIGN", "BAMBOO_SIGN", "CRIMSON_SIGN", "WARPED_SIGN", "OAK_HANGING_SIGN", "SPRUCE_HANGING_SIGN", 243 "BIRCH_HANGING_SIGN", "JUNGLE_HANGING_SIGN", "ACACIA_HANGING_SIGN", "CHERRY_HANGING_SIGN", 244 "DARK_OAK_HANGING_SIGN", "MANGROVE_HANGING_SIGN", "BAMBOO_HANGING_SIGN", "CRIMSON_HANGING_SIGN", 245 "WARPED_HANGING_SIGN", "CAKE", "WHITE_BED", "ORANGE_BED", "MAGENTA_BED", "LIGHT_BLUE_BED", "YELLOW_BED", 246 "LIME_BED", "PINK_BED", "GRAY_BED", "LIGHT_GRAY_BED", "CYAN_BED", "PURPLE_BED", "BLUE_BED", "BROWN_BED", 247 "GREEN_BED", "RED_BED", "BLACK_BED", "CRAFTER", "BREWING_STAND", "CAULDRON", "FLOWER_POT", "LOOM", "COMPOSTER", 248 "BARREL", "SMOKER", "BLAST_FURNACE", "CARTOGRAPHY_TABLE", "FLETCHING_TABLE", "GRINDSTONE", "SMITHING_TABLE", 249 "STONECUTTER", "BELL", "CAMPFIRE", "SOUL_CAMPFIRE", "BEE_NEST", "BEEHIVE", "RESPAWN_ANCHOR", "CANDLE", 250 "WHITE_CANDLE", "ORANGE_CANDLE", "MAGENTA_CANDLE", "LIGHT_BLUE_CANDLE", "YELLOW_CANDLE", "LIME_CANDLE", 251 "PINK_CANDLE", "GRAY_CANDLE", "LIGHT_GRAY_CANDLE", "CYAN_CANDLE", "PURPLE_CANDLE", "BLUE_CANDLE", "BROWN_CANDLE", 252 "GREEN_CANDLE", "RED_CANDLE", "BLACK_CANDLE", "VAULT", "MOVING_PISTON", "REDSTONE_WIRE", "OAK_WALL_SIGN", 253 "SPRUCE_WALL_SIGN", "BIRCH_WALL_SIGN", "ACACIA_WALL_SIGN", "CHERRY_WALL_SIGN", "JUNGLE_WALL_SIGN", 254 "DARK_OAK_WALL_SIGN", "MANGROVE_WALL_SIGN", "BAMBOO_WALL_SIGN", "OAK_WALL_HANGING_SIGN", 255 "SPRUCE_WALL_HANGING_SIGN", "BIRCH_WALL_HANGING_SIGN", "ACACIA_WALL_HANGING_SIGN", 256 "CHERRY_WALL_HANGING_SIGN", "JUNGLE_WALL_HANGING_SIGN", "DARK_OAK_WALL_HANGING_SIGN", 257 "MANGROVE_WALL_HANGING_SIGN", "CRIMSON_WALL_HANGING_SIGN", "WARPED_WALL_HANGING_SIGN", "BAMBOO_WALL_HANGING_SIGN", 258 "WATER_CAULDRON", "LAVA_CAULDRON", "POWDER_SNOW_CAULDRON", "POTTED_TORCHFLOWER", "POTTED_OAK_SAPLING", 259 "POTTED_SPRUCE_SAPLING", "POTTED_BIRCH_SAPLING", "POTTED_JUNGLE_SAPLING", "POTTED_ACACIA_SAPLING", 260 "POTTED_CHERRY_SAPLING", "POTTED_DARK_OAK_SAPLING", "POTTED_MANGROVE_PROPAGULE", "POTTED_FERN", 261 "POTTED_DANDELION", "POTTED_POPPY", "POTTED_BLUE_ORCHID", "POTTED_ALLIUM", "POTTED_AZURE_BLUET", 262 "POTTED_RED_TULIP", "POTTED_ORANGE_TULIP", "POTTED_WHITE_TULIP", "POTTED_PINK_TULIP", "POTTED_OXEYE_DAISY", 263 "POTTED_CORNFLOWER", "POTTED_LILY_OF_THE_VALLEY", "POTTED_WITHER_ROSE", "POTTED_RED_MUSHROOM", 264 "POTTED_BROWN_MUSHROOM", "POTTED_DEAD_BUSH", "POTTED_CACTUS", "POTTED_BAMBOO", "SWEET_BERRY_BUSH", 265 "CRIMSON_WALL_SIGN", "WARPED_WALL_SIGN", "POTTED_CRIMSON_FUNGUS", "POTTED_WARPED_FUNGUS", "POTTED_CRIMSON_ROOTS", 266 "POTTED_WARPED_ROOTS", "CANDLE_CAKE", "WHITE_CANDLE_CAKE", "ORANGE_CANDLE_CAKE", "MAGENTA_CANDLE_CAKE", 267 "LIGHT_BLUE_CANDLE_CAKE", "YELLOW_CANDLE_CAKE", "LIME_CANDLE_CAKE", "PINK_CANDLE_CAKE", "GRAY_CANDLE_CAKE", 268 "LIGHT_GRAY_CANDLE_CAKE", "CYAN_CANDLE_CAKE", "PURPLE_CANDLE_CAKE", "BLUE_CANDLE_CAKE", "BROWN_CANDLE_CAKE", 269 "GREEN_CANDLE_CAKE", "RED_CANDLE_CAKE", "BLACK_CANDLE_CAKE", "CAVE_VINES", "CAVE_VINES_PLANT", 270 "POTTED_AZALEA_BUSH", "POTTED_FLOWERING_AZALEA_BUSH" 271 ); 272 // @formatter:on 273 } 274 275 private final EventDispatcher eventDispatcher; 276 private final WorldEdit worldEdit; 277 private final PlotAreaManager plotAreaManager; 278 private final PlotListener plotListener; 279 // To prevent recursion 280 private boolean tmpTeleport = true; 281 private Field fieldPlayer; 282 private PlayerMoveEvent moveTmp; 283 private String internalVersion; 284 285 { 286 try { 287 fieldPlayer = PlayerEvent.class.getDeclaredField("player"); 288 fieldPlayer.setAccessible(true); 289 } catch (NoSuchFieldException e) { 290 e.printStackTrace(); 291 } 292 } 293 294 @Inject 295 public PlayerEventListener( 296 final @NonNull PlotAreaManager plotAreaManager, 297 final @NonNull EventDispatcher eventDispatcher, 298 final @NonNull WorldEdit worldEdit, 299 final @NonNull PlotListener plotListener 300 ) { 301 this.eventDispatcher = eventDispatcher; 302 this.worldEdit = worldEdit; 303 this.plotAreaManager = plotAreaManager; 304 this.plotListener = plotListener; 305 } 306 307 @EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST) 308 public void onBlockBreak(final BlockBreakEvent event) { 309 Location location = BukkitUtil.adapt(event.getBlock().getLocation()); 310 PlotArea area = location.getPlotArea(); 311 if (area == null) { 312 return; 313 } 314 Plot plot = area.getPlot(location); 315 if (plot != null) { 316 event.setDropItems(plot.getFlag(TileDropFlag.class)); 317 } 318 } 319 320 @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) 321 public void onPlayerDyeSign(PlayerInteractEvent event) { 322 ItemStack itemStack = event.getItem(); 323 if (itemStack == null) { 324 return; 325 } 326 Block block = event.getClickedBlock(); 327 if (block != null && block.getState() instanceof Sign) { 328 if (DYES.contains(itemStack.getType().toString())) { 329 Location location = BukkitUtil.adapt(block.getLocation()); 330 PlotArea area = location.getPlotArea(); 331 if (area == null) { 332 return; 333 } 334 Plot plot = location.getOwnedPlot(); 335 if (plot == null) { 336 if (PlotFlagUtil.isAreaRoadFlagsAndFlagEquals(area, EditSignFlag.class, false) 337 && !event.getPlayer().hasPermission(Permission.PERMISSION_ADMIN_INTERACT_ROAD.toString())) { 338 event.setCancelled(true); 339 } 340 return; 341 } 342 if (plot.isAdded(event.getPlayer().getUniqueId())) { 343 return; // allow for added players 344 } 345 if (!plot.getFlag(EditSignFlag.class) 346 && !event.getPlayer().hasPermission(Permission.PERMISSION_ADMIN_INTERACT_OTHER.toString())) { 347 plot.debug(event.getPlayer().getName() + " could not color the sign because of edit-sign = false"); 348 event.setCancelled(true); 349 } 350 } 351 } 352 } 353 354 @EventHandler(ignoreCancelled = true) 355 public void onEffect(@NonNull EntityPotionEffectEvent event) { 356 if (Settings.Enabled_Components.DISABLE_BEACON_EFFECT_OVERFLOW || 357 event.getCause() != EntityPotionEffectEvent.Cause.BEACON || 358 !(event.getEntity() instanceof Player player)) { 359 return; 360 } 361 362 UUID uuid = player.getUniqueId(); 363 PotionEffect effect = event.getNewEffect(); 364 if (effect == null) { 365 PotionEffect oldEffect = event.getOldEffect(); 366 if (oldEffect != null) { 367 String name = oldEffect.getType().getName(); 368 plotListener.addEffect(uuid, name, -1); 369 } 370 } else { 371 long expiresAt = System.currentTimeMillis() + effect.getDuration() * 50L; //Convert ticks to milliseconds 372 String name = effect.getType().getName(); 373 plotListener.addEffect(uuid, name, expiresAt); 374 } 375 } 376 377 @EventHandler 378 public void onVehicleEntityCollision(VehicleEntityCollisionEvent e) { 379 if (e.getVehicle() instanceof Boat) { 380 Location location = BukkitUtil.adapt(e.getEntity().getLocation()); 381 if (location.isPlotArea()) { 382 if (e.getEntity() instanceof Player) { 383 PlotPlayer<Player> player = BukkitUtil.adapt((Player) e.getEntity()); 384 Plot plot = player.getCurrentPlot(); 385 if (plot != null) { 386 if (!plot.isAdded(player.getUUID())) { 387 //Here the event is only canceled if the player is not the owner 388 //of the property on which he is located. 389 e.setCancelled(true); 390 } 391 } else { 392 e.setCancelled(true); 393 } 394 } else { 395 //Here the event is cancelled too, otherwise you can move the 396 //boat with EchoPets or other mobs running around on the plot. 397 e.setCancelled(true); 398 } 399 } 400 } 401 } 402 403 @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) 404 public void playerCommand(PlayerCommandPreprocessEvent event) { 405 String msg = event.getMessage().replace("/", "").toLowerCase(Locale.ROOT).trim(); 406 if (msg.isEmpty()) { 407 return; 408 } 409 Player player = event.getPlayer(); 410 PlotPlayer<Player> plotPlayer = BukkitUtil.adapt(player); 411 Location location = plotPlayer.getLocation(); 412 PlotArea area = location.getPlotArea(); 413 if (area == null) { 414 return; 415 } 416 String[] parts = msg.split(" "); 417 Plot plot = plotPlayer.getCurrentPlot(); 418 // Check WorldEdit 419 switch (parts[0]) { 420 case "up", "worldedit:up" -> { 421 if (plot == null || (!plot.isAdded(plotPlayer.getUUID()) && !plotPlayer.hasPermission( 422 Permission.PERMISSION_ADMIN_BUILD_OTHER, 423 true 424 ))) { 425 event.setCancelled(true); 426 return; 427 } 428 } 429 } 430 if (plot == null && !area.isRoadFlags()) { 431 return; 432 } 433 434 List<String> blockedCommands = plot != null ? 435 plot.getFlag(BlockedCmdsFlag.class) : 436 area.getFlag(BlockedCmdsFlag.class); 437 if (blockedCommands.isEmpty()) { 438 return; 439 } 440 if (plotPlayer.hasPermission(Permission.PERMISSION_ADMIN_INTERACT_BLOCKED_CMDS)) { 441 return; 442 } 443 // When using namespaced commands, we're not interested in the namespace 444 String part = parts[0]; 445 if (part.contains(":")) { 446 String[] namespaced = part.split(":"); 447 part = namespaced[1]; 448 msg = msg.substring(namespaced[0].length() + 1); 449 } 450 msg = replaceAliases(msg, part); 451 for (String blocked : blockedCommands) { 452 if (blocked.equalsIgnoreCase(msg)) { 453 String perm; 454 if (plot != null && plot.isAdded(plotPlayer.getUUID())) { 455 perm = "plots.admin.command.blocked-cmds.shared"; 456 } else { 457 perm = "plots.admin.command.blocked-cmds.road"; 458 } 459 if (!plotPlayer.hasPermission(perm)) { 460 plotPlayer.sendMessage(TranslatableCaption.of("blockedcmds.command_blocked")); 461 event.setCancelled(true); 462 } 463 return; 464 } 465 } 466 } 467 468 private String replaceAliases(String msg, String part) { 469 String s1 = part; 470 Set<String> aliases = new HashSet<>(); 471 for (HelpTopic cmdLabel : Bukkit.getServer().getHelpMap().getHelpTopics()) { 472 if (part.equals(cmdLabel.getName())) { 473 break; 474 } 475 String label = cmdLabel.getName().replaceFirst("/", ""); 476 if (aliases.contains(label)) { 477 continue; 478 } 479 PluginCommand p = Bukkit.getPluginCommand(label); 480 if (p != null) { 481 for (String a : p.getAliases()) { 482 if (aliases.contains(a)) { 483 continue; 484 } 485 aliases.add(a); 486 a = a.replaceFirst("/", ""); 487 if (!a.equals(label) && a.equals(part)) { 488 part = label; 489 break; 490 } 491 } 492 } 493 } 494 if (!s1.equals(part)) { 495 msg = msg.replace(s1, part); 496 } 497 return msg; 498 } 499 500 @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) 501 public void onPreLogin(final AsyncPlayerPreLoginEvent event) { 502 final UUID uuid; 503 if (Settings.UUID.OFFLINE) { 504 if (Settings.UUID.FORCE_LOWERCASE) { 505 uuid = UUID.nameUUIDFromBytes(("OfflinePlayer:" + event.getName().toLowerCase()).getBytes(Charsets.UTF_8)); 506 } else { 507 uuid = UUID.nameUUIDFromBytes(("OfflinePlayer:" + event.getName()).getBytes(Charsets.UTF_8)); 508 } 509 } else { 510 uuid = event.getUniqueId(); 511 } 512 PlotSquared.get().getImpromptuUUIDPipeline().storeImmediately(event.getName(), uuid); 513 } 514 515 @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) 516 @SuppressWarnings("deprecation") // Paper deprecation 517 public void onConnect(PlayerJoinEvent event) { 518 final Player player = event.getPlayer(); 519 PlotSquared.platform().playerManager().removePlayer(player.getUniqueId()); 520 final PlotPlayer<Player> pp = BukkitUtil.adapt(player); 521 522 // we're stripping the country code as we don't want to differ between countries 523 pp.setLocale(Locale.forLanguageTag(player.getLocale().substring(0, 2))); 524 525 Location location = pp.getLocation(); 526 PlotArea area = location.getPlotArea(); 527 if (area != null) { 528 Plot plot = area.getPlot(location); 529 if (plot != null) { 530 plotListener.plotEntry(pp, plot); 531 } 532 } 533 // Delayed 534 535 // Async 536 TaskManager.runTaskLaterAsync(() -> { 537 if (!player.hasPlayedBefore() && player.isOnline()) { 538 player.saveData(); 539 } 540 this.eventDispatcher.doJoinTask(pp); 541 }, TaskTime.seconds(1L)); 542 543 if (pp.hasPermission(Permission.PERMISSION_ADMIN_UPDATE_NOTIFICATION.toString()) && Settings.Enabled_Components.UPDATE_NOTIFICATIONS 544 && PremiumVerification.isPremium() && UpdateUtility.hasUpdate) { 545 Caption boundary = TranslatableCaption.of("update.update_boundary"); 546 Caption updateNotification = TranslatableCaption.of("update.update_notification"); 547 pp.sendMessage(boundary); 548 pp.sendMessage( 549 updateNotification, 550 TagResolver.builder() 551 .tag("p2version", Tag.inserting(Component.text(UpdateUtility.internalVersion.versionString()))) 552 .tag("spigotversion", Tag.inserting(Component.text(UpdateUtility.spigotVersion))) 553 .tag("downloadurl", Tag.preProcessParsed("https://www.spigotmc.org/resources/77506/updates")) 554 .build() 555 ); 556 pp.sendMessage(boundary); 557 } 558 } 559 560 @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) 561 public void playerRespawn(PlayerRespawnEvent event) { 562 Player player = event.getPlayer(); 563 PlotPlayer<Player> pp = BukkitUtil.adapt(player); 564 this.eventDispatcher.doRespawnTask(pp); 565 } 566 567 @SuppressWarnings("deprecation") // We explicitly want #getHomeSynchronous here 568 @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) 569 public void onTeleport(PlayerTeleportEvent event) { 570 Player player = event.getPlayer(); 571 //We need to account for bad plugins like NoCheatPlus that teleports player on/before login -_- 572 if (!player.isOnline()) { 573 return; 574 } 575 BukkitPlayer pp = BukkitUtil.adapt(player); 576 try (final MetaDataAccess<Plot> lastPlotAccess = 577 pp.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LAST_PLOT)) { 578 Plot lastPlot = lastPlotAccess.get().orElse(null); 579 org.bukkit.Location to = event.getTo(); 580 //noinspection ConstantConditions 581 if (to != null) { 582 Location location = BukkitUtil.adapt(to); 583 PlotArea area = location.getPlotArea(); 584 if (area == null) { 585 if (lastPlot != null) { 586 plotListener.plotExit(pp, lastPlot); 587 lastPlotAccess.remove(); 588 } 589 try (final MetaDataAccess<Location> lastLocationAccess = 590 pp.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LOCATION)) { 591 lastLocationAccess.remove(); 592 } 593 return; 594 } 595 Plot plot = area.getPlot(location); 596 if (plot != null && !plot.equals(lastPlot)) { 597 final boolean result = DenyTeleportFlag.allowsTeleport(pp, plot); 598 // there is one possibility to still allow teleportation: 599 // to is identical to the plot's home location, and untrusted-visit is true 600 // i.e. untrusted-visit can override deny-teleport 601 // this is acceptable, because otherwise it wouldn't make sense to have both flags set 602 if (result || (plot.getFlag(UntrustedVisitFlag.class) && plot.getHomeSynchronous().equals(BukkitUtil.adaptComplete(to)))) { 603 plotListener.plotEntry(pp, plot); 604 } else { 605 pp.sendMessage( 606 TranslatableCaption.of("deny.no_enter"), 607 TagResolver.resolver("plot", Tag.inserting(Component.text(plot.toString()))) 608 ); 609 event.setCancelled(true); 610 } 611 } 612 } 613 } 614 playerMove(event); 615 } 616 617 @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) 618 public void onWorldChanged(PlayerChangedWorldEvent event) { 619 Player player = event.getPlayer(); 620 BukkitPlayer pp = BukkitUtil.adapt(player); 621 if (this.worldEdit != null) { 622 if (!pp.hasPermission(Permission.PERMISSION_WORLDEDIT_BYPASS)) { 623 if (pp.getAttribute("worldedit")) { 624 pp.removeAttribute("worldedit"); 625 } 626 } 627 } 628 } 629 630 @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) 631 public void vehicleMove(VehicleMoveEvent event) 632 throws IllegalAccessException { 633 final org.bukkit.Location from = event.getFrom(); 634 final org.bukkit.Location to = event.getTo(); 635 636 int toX, toZ; 637 if ((toX = MathMan.roundInt(to.getX())) != MathMan.roundInt(from.getX()) | (toZ = MathMan.roundInt(to.getZ())) != MathMan 638 .roundInt(from.getZ())) { 639 Vehicle vehicle = event.getVehicle(); 640 641 // Check allowed 642 if (!vehicle.getPassengers().isEmpty()) { 643 Entity passenger = vehicle.getPassengers().get(0); 644 645 if (passenger instanceof final Player player) { 646 // reset 647 if (moveTmp == null) { 648 moveTmp = new PlayerMoveEvent(null, from, to); 649 } 650 moveTmp.setFrom(from); 651 moveTmp.setTo(to); 652 moveTmp.setCancelled(false); 653 fieldPlayer.set(moveTmp, player); 654 655 List<Entity> passengers = vehicle.getPassengers(); 656 657 this.playerMove(moveTmp); 658 org.bukkit.Location dest; 659 if (moveTmp.isCancelled()) { 660 dest = from; 661 } else if (MathMan.roundInt(moveTmp.getTo().getX()) != toX || MathMan.roundInt(moveTmp 662 .getTo() 663 .getZ()) != toZ) { 664 dest = to; 665 } else { 666 dest = null; 667 } 668 if (dest != null) { 669 vehicle.eject(); 670 vehicle.setVelocity(new Vector(0d, 0d, 0d)); 671 PaperLib.teleportAsync(vehicle, dest); 672 passengers.forEach(vehicle::addPassenger); 673 return; 674 } 675 } 676 if (Settings.Enabled_Components.KILL_ROAD_VEHICLES) { 677 final com.sk89q.worldedit.world.entity.EntityType entityType = BukkitAdapter.adapt(vehicle.getType()); 678 // Horses etc are vehicles, but they're also animals 679 // so this filters out all living entities 680 if (EntityCategories.VEHICLE.contains(entityType) && !EntityCategories.ANIMAL.contains(entityType)) { 681 List<MetadataValue> meta = vehicle.getMetadata("plot"); 682 Plot toPlot = BukkitUtil.adapt(to).getPlot(); 683 if (!meta.isEmpty()) { 684 Plot origin = (Plot) meta.get(0).value(); 685 if (origin != null && !origin.getBasePlot(false).equals(toPlot)) { 686 vehicle.remove(); 687 } 688 } else if (toPlot != null) { 689 vehicle.setMetadata("plot", new FixedMetadataValue((Plugin) PlotSquared.platform(), toPlot)); 690 } 691 } 692 } 693 } 694 695 } 696 } 697 698 @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) 699 public void playerMove(PlayerMoveEvent event) { 700 org.bukkit.Location from = event.getFrom(); 701 org.bukkit.Location to = event.getTo(); 702 int x2; 703 if (MathMan.roundInt(from.getX()) != (x2 = MathMan.roundInt(to.getX()))) { 704 Player player = event.getPlayer(); 705 BukkitPlayer pp = BukkitUtil.adapt(player); 706 // Cancel teleport 707 if (TaskManager.removeFromTeleportQueue(pp.getName())) { 708 pp.sendMessage(TranslatableCaption.of("teleport.teleport_failed")); 709 } 710 // Set last location 711 Location location = BukkitUtil.adapt(to); 712 try (final MetaDataAccess<Location> lastLocationAccess = 713 pp.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LOCATION)) { 714 lastLocationAccess.remove(); 715 } 716 PlotArea area = location.getPlotArea(); 717 if (area == null) { 718 try (final MetaDataAccess<Plot> lastPlotAccess = 719 pp.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LAST_PLOT)) { 720 lastPlotAccess.remove(); 721 } 722 return; 723 } 724 Plot now = area.getPlot(location); 725 Plot lastPlot; 726 try (final MetaDataAccess<Plot> lastPlotAccess = 727 pp.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LAST_PLOT)) { 728 lastPlot = lastPlotAccess.get().orElse(null); 729 } 730 if (now == null) { 731 try (final MetaDataAccess<Boolean> kickAccess = 732 pp.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_KICK)) { 733 if (lastPlot != null && !plotListener.plotExit(pp, lastPlot) && this.tmpTeleport && !kickAccess.get().orElse( 734 false)) { 735 pp.sendMessage( 736 TranslatableCaption.of("permission.no_permission_event"), 737 TagResolver.resolver( 738 "node", 739 Tag.inserting(Permission.PERMISSION_ADMIN_EXIT_DENIED) 740 ) 741 ); 742 this.tmpTeleport = false; 743 if (lastPlot.equals(BukkitUtil.adapt(from).getPlot())) { 744 player.teleport(from); 745 } else { 746 player.teleport(player.getWorld().getSpawnLocation()); 747 } 748 this.tmpTeleport = true; 749 event.setCancelled(true); 750 return; 751 } 752 } 753 } else if (now.equals(lastPlot)) { 754 ForceFieldListener.handleForcefield(player, pp, now); 755 } else if (!plotListener.plotEntry(pp, now) && this.tmpTeleport) { 756 pp.sendMessage( 757 TranslatableCaption.of("deny.no_enter"), 758 TagResolver.resolver("plot", Tag.inserting(Component.text(now.toString()))) 759 ); 760 this.tmpTeleport = false; 761 to.setX(from.getBlockX()); 762 to.setY(from.getBlockY()); 763 to.setZ(from.getBlockZ()); 764 player.teleport(event.getTo()); 765 this.tmpTeleport = true; 766 return; 767 } 768 int border = area.getBorder(true); 769 int x1; 770 if (x2 > border && this.tmpTeleport) { 771 if (!pp.hasPermission(Permission.PERMISSION_ADMIN_BYPASS_BORDER)) { 772 to.setX(border - 1); 773 this.tmpTeleport = false; 774 player.teleport(event.getTo()); 775 this.tmpTeleport = true; 776 pp.sendMessage(TranslatableCaption.of("border.denied")); 777 } else if (MathMan.roundInt(from.getX()) <= border) { // Only send if they just moved out of the border 778 pp.sendMessage(TranslatableCaption.of("border.bypass.exited")); 779 } 780 } else if (x2 < -border && this.tmpTeleport) { 781 if (!pp.hasPermission(Permission.PERMISSION_ADMIN_BYPASS_BORDER)) { 782 to.setX(-border + 1); 783 this.tmpTeleport = false; 784 player.teleport(event.getTo()); 785 this.tmpTeleport = true; 786 pp.sendMessage(TranslatableCaption.of("border.denied")); 787 } else if (MathMan.roundInt(from.getX()) >= -border) { // Only send if they just moved out of the border 788 pp.sendMessage(TranslatableCaption.of("border.bypass.exited")); 789 } 790 } else if (((x1 = MathMan.roundInt(from.getX())) >= border && x2 <= border) || (x1 <= -border && x2 >= -border)) { 791 if (pp.hasPermission(Permission.PERMISSION_ADMIN_BYPASS_BORDER)) { 792 pp.sendMessage(TranslatableCaption.of("border.bypass.entered")); 793 } 794 } 795 } 796 int z2; 797 if (MathMan.roundInt(from.getZ()) != (z2 = MathMan.roundInt(to.getZ()))) { 798 Player player = event.getPlayer(); 799 BukkitPlayer pp = BukkitUtil.adapt(player); 800 // Cancel teleport 801 if (TaskManager.removeFromTeleportQueue(pp.getName())) { 802 pp.sendMessage(TranslatableCaption.of("teleport.teleport_failed")); 803 } 804 // Set last location 805 Location location = BukkitUtil.adapt(to); 806 try (final MetaDataAccess<Location> lastLocationAccess = 807 pp.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LOCATION)) { 808 lastLocationAccess.set(location); 809 } 810 PlotArea area = location.getPlotArea(); 811 if (area == null) { 812 try (final MetaDataAccess<Plot> lastPlotAccess = 813 pp.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LAST_PLOT)) { 814 lastPlotAccess.remove(); 815 } 816 return; 817 } 818 Plot plot = area.getPlot(location); 819 Plot lastPlot; 820 try (final MetaDataAccess<Plot> lastPlotAccess = 821 pp.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LAST_PLOT)) { 822 lastPlot = lastPlotAccess.get().orElse(null); 823 } 824 if (plot == null) { 825 try (final MetaDataAccess<Boolean> kickAccess = 826 pp.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_KICK)) { 827 if (lastPlot != null && !plotListener.plotExit(pp, lastPlot) && this.tmpTeleport && !kickAccess.get().orElse( 828 false)) { 829 pp.sendMessage( 830 TranslatableCaption.of("permission.no_permission_event"), 831 TagResolver.resolver( 832 "node", 833 Tag.inserting(Permission.PERMISSION_ADMIN_EXIT_DENIED) 834 ) 835 ); 836 this.tmpTeleport = false; 837 if (lastPlot.equals(BukkitUtil.adapt(from).getPlot())) { 838 player.teleport(from); 839 } else { 840 player.teleport(player.getWorld().getSpawnLocation()); 841 } 842 this.tmpTeleport = true; 843 event.setCancelled(true); 844 return; 845 } 846 } 847 } else if (plot.equals(lastPlot)) { 848 ForceFieldListener.handleForcefield(player, pp, plot); 849 } else if (!plotListener.plotEntry(pp, plot) && this.tmpTeleport) { 850 pp.sendMessage( 851 TranslatableCaption.of("deny.no_enter"), 852 TagResolver.resolver("plot", Tag.inserting(Component.text(plot.toString()))) 853 ); 854 this.tmpTeleport = false; 855 player.teleport(from); 856 to.setX(from.getBlockX()); 857 to.setY(from.getBlockY()); 858 to.setZ(from.getBlockZ()); 859 player.teleport(event.getTo()); 860 this.tmpTeleport = true; 861 return; 862 } 863 int border = area.getBorder(true); 864 int z1; 865 if (z2 > border && this.tmpTeleport) { 866 if (!pp.hasPermission(Permission.PERMISSION_ADMIN_BYPASS_BORDER)) { 867 to.setZ(border - 1); 868 this.tmpTeleport = false; 869 player.teleport(event.getTo()); 870 this.tmpTeleport = true; 871 pp.sendMessage(TranslatableCaption.of("border.denied")); 872 } else if (MathMan.roundInt(from.getZ()) <= border) { // Only send if they just moved out of the border 873 pp.sendMessage(TranslatableCaption.of("border.bypass.exited")); 874 } 875 } else if (z2 < -border && this.tmpTeleport) { 876 if (!pp.hasPermission(Permission.PERMISSION_ADMIN_BYPASS_BORDER)) { 877 to.setZ(-border + 1); 878 this.tmpTeleport = false; 879 player.teleport(event.getTo()); 880 this.tmpTeleport = true; 881 pp.sendMessage(TranslatableCaption.of("border.denied")); 882 } else if (MathMan.roundInt(from.getZ()) >= -border) { // Only send if they just moved out of the border 883 pp.sendMessage(TranslatableCaption.of("border.bypass.exited")); 884 } 885 } else if (((z1 = MathMan.roundInt(from.getZ())) >= border && z2 <= border) || (z1 <= -border && z2 >= -border)) { 886 if (pp.hasPermission(Permission.PERMISSION_ADMIN_BYPASS_BORDER)) { 887 pp.sendMessage(TranslatableCaption.of("border.bypass.entered")); 888 } 889 } 890 } 891 } 892 893 @EventHandler(priority = EventPriority.LOW) 894 @SuppressWarnings("deprecation") // Paper deprecation 895 public void onChat(AsyncPlayerChatEvent event) { 896 if (event.isCancelled()) { 897 return; 898 } 899 900 BukkitPlayer plotPlayer = BukkitUtil.adapt(event.getPlayer()); 901 Location location = plotPlayer.getLocation(); 902 PlotArea area = location.getPlotArea(); 903 if (area == null) { 904 return; 905 } 906 Plot plot = area.getPlot(location); 907 if (plot == null) { 908 return; 909 } 910 if (!((plot.getFlag(ChatFlag.class) && area.isPlotChat() && plotPlayer.getAttribute("chat")) 911 || area.isForcingPlotChat())) { 912 return; 913 } 914 if (plot.isDenied(plotPlayer.getUUID()) && !plotPlayer.hasPermission(Permission.PERMISSION_ADMIN_CHAT_BYPASS)) { 915 return; 916 } 917 event.setCancelled(true); 918 Set<Player> recipients = event.getRecipients(); 919 recipients.clear(); 920 Set<PlotPlayer<?>> spies = new HashSet<>(); 921 Set<PlotPlayer<?>> plotRecipients = new HashSet<>(); 922 for (final PlotPlayer<?> pp : PlotSquared.platform().playerManager().getPlayers()) { 923 if (pp.getAttribute("chatspy")) { 924 spies.add(pp); 925 } else { 926 Plot current = pp.getCurrentPlot(); 927 if (current != null && current.getBasePlot(false).equals(plot)) { 928 plotRecipients.add(pp); 929 } 930 } 931 } 932 String message = event.getMessage(); 933 String sender = event.getPlayer().getDisplayName(); 934 PlotId id = plot.getId(); 935 String worldName = plot.getWorldName(); 936 Caption msg = TranslatableCaption.of("chat.plot_chat_format"); 937 TagResolver.Builder builder = TagResolver.builder(); 938 builder.tag("world", Tag.inserting(Component.text(worldName))); 939 builder.tag("plot_id", Tag.inserting(Component.text(id.toString()))); 940 builder.tag("sender", Tag.inserting(Component.text(sender))); 941 if (plotPlayer.hasPermission("plots.chat.color")) { 942 builder.tag("msg", Tag.inserting(MiniMessage.miniMessage().deserialize( 943 message, 944 TagResolver.resolver(StandardTags.color(), StandardTags.gradient(), 945 StandardTags.rainbow(), StandardTags.decorations() 946 ) 947 ))); 948 } else { 949 builder.tag("msg", Tag.inserting(Component.text(message))); 950 } 951 for (PlotPlayer<?> receiver : plotRecipients) { 952 receiver.sendMessage(msg, builder.build()); 953 } 954 if (!spies.isEmpty()) { 955 Caption spymsg = TranslatableCaption.of("chat.plot_chat_spy_format"); 956 for (PlotPlayer<?> player : spies) { 957 player.sendMessage(spymsg, builder.tag("message", Tag.inserting(Component.text(message))).build()); 958 } 959 } 960 if (Settings.Chat.LOG_PLOTCHAT_TO_CONSOLE) { 961 Caption spymsg = TranslatableCaption.of("chat.plot_chat_spy_format"); 962 ConsolePlayer.getConsole().sendMessage( 963 spymsg, 964 builder.tag("message", Tag.inserting(Component.text(message))).build() 965 ); 966 } 967 } 968 969 @SuppressWarnings("deprecation") 970 @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) 971 public void onInventoryClick(InventoryClickEvent event) { 972 /*if (!event.isLeftClick() || (event.getAction() != InventoryAction.PLACE_ALL) || event 973 .isShiftClick()) { 974 return; 975 }*/ 976 HumanEntity entity = event.getWhoClicked(); 977 if (!(entity instanceof Player) || !this.plotAreaManager 978 .hasPlotArea(entity.getWorld().getName())) { 979 return; 980 } 981 982 HumanEntity clicker = event.getWhoClicked(); 983 if (!(clicker instanceof Player player)) { 984 return; 985 } 986 BukkitPlayer pp = BukkitUtil.adapt(player); 987 final PlotInventory inventory = PlotInventory.getOpenPlotInventory(pp); 988 if (inventory != null && event.getRawSlot() == event.getSlot()) { 989 if (!inventory.onClick(event.getSlot())) { 990 event.setResult(Event.Result.DENY); 991 event.setCancelled(true); 992 inventory.close(); 993 } 994 } 995 PlayerInventory inv = player.getInventory(); 996 int slot = inv.getHeldItemSlot(); 997 if ((slot > 8) || !event.getEventName().equals("InventoryCreativeEvent")) { 998 return; 999 } 1000 ItemStack oldItem = inv.getItemInHand(); 1001 ItemMeta oldMeta = oldItem.getItemMeta(); 1002 ItemStack newItem = event.getCursor(); 1003 ItemMeta newMeta = newItem.getItemMeta(); 1004 1005 if (event.getClick() == ClickType.CREATIVE) { 1006 final Plot plot = pp.getCurrentPlot(); 1007 if (plot != null) { 1008 if (plot.getFlag(PreventCreativeCopyFlag.class) && !plot 1009 .isAdded(player.getUniqueId()) && !pp.hasPermission(Permission.PERMISSION_ADMIN_INTERACT_OTHER)) { 1010 final ItemStack newStack = 1011 new ItemStack(newItem.getType(), newItem.getAmount()); 1012 event.setCursor(newStack); 1013 plot.debug(player.getName() 1014 + " could not creative-copy an item because prevent-creative-copy = true"); 1015 } 1016 } else { 1017 PlotArea area = pp.getPlotAreaAbs(); 1018 if (area != null && PlotFlagUtil.isAreaRoadFlagsAndFlagEquals(area, PreventCreativeCopyFlag.class, true)) { 1019 final ItemStack newStack = 1020 new ItemStack(newItem.getType(), newItem.getAmount()); 1021 event.setCursor(newStack); 1022 } 1023 } 1024 return; 1025 } 1026 1027 String newLore = ""; 1028 if (newMeta != null) { 1029 List<String> lore = newMeta.getLore(); 1030 if (lore != null) { 1031 newLore = lore.toString(); 1032 } 1033 } 1034 String oldLore = ""; 1035 if (oldMeta != null) { 1036 List<String> lore = oldMeta.getLore(); 1037 if (lore != null) { 1038 oldLore = lore.toString(); 1039 } 1040 } 1041 Material itemType = newItem.getType(); 1042 if (!"[(+NBT)]".equals(newLore) || (oldItem.equals(newItem) && newLore.equals(oldLore))) { 1043 if (newMeta == null || (itemType != Material.LEGACY_BANNER && itemType != Material.PLAYER_HEAD)) { 1044 return; 1045 } 1046 } 1047 Block block = player.getTargetBlock(null, 7); 1048 org.bukkit.block.BlockState state = block.getState(); 1049 Material stateType = state.getType(); 1050 if (stateType != itemType) { 1051 if (stateType == Material.LEGACY_WALL_BANNER || stateType == Material.LEGACY_STANDING_BANNER) { 1052 if (itemType != Material.LEGACY_BANNER) { 1053 return; 1054 } 1055 } else if (stateType == Material.LEGACY_SKULL) { 1056 if (itemType != Material.LEGACY_SKULL_ITEM) { 1057 return; 1058 } 1059 } else { 1060 return; 1061 } 1062 } 1063 Location location = BukkitUtil.adapt(state.getLocation()); 1064 PlotArea area = location.getPlotArea(); 1065 if (area == null) { 1066 return; 1067 } 1068 Plot plot = area.getPlotAbs(location); 1069 boolean cancelled = false; 1070 if (plot == null) { 1071 if (!pp.hasPermission(Permission.PERMISSION_ADMIN_INTERACT_ROAD)) { 1072 pp.sendMessage( 1073 TranslatableCaption.of("permission.no_permission_event"), 1074 TagResolver.resolver( 1075 "node", 1076 Tag.inserting(Permission.PERMISSION_ADMIN_INTERACT_ROAD) 1077 ) 1078 ); 1079 cancelled = true; 1080 } 1081 } else if (!plot.hasOwner()) { 1082 if (!pp.hasPermission(Permission.PERMISSION_ADMIN_INTERACT_UNOWNED)) { 1083 pp.sendMessage( 1084 TranslatableCaption.of("permission.no_permission_event"), 1085 TagResolver.resolver( 1086 "node", 1087 Tag.inserting(Permission.PERMISSION_ADMIN_INTERACT_UNOWNED) 1088 ) 1089 ); 1090 cancelled = true; 1091 } 1092 } else { 1093 UUID uuid = pp.getUUID(); 1094 if (!plot.isAdded(uuid)) { 1095 if (!pp.hasPermission(Permission.PERMISSION_ADMIN_INTERACT_OTHER)) { 1096 pp.sendMessage( 1097 TranslatableCaption.of("permission.no_permission_event"), 1098 TagResolver.resolver( 1099 "node", 1100 Tag.inserting(Permission.PERMISSION_ADMIN_INTERACT_OTHER) 1101 ) 1102 ); 1103 cancelled = true; 1104 } 1105 } 1106 } 1107 if (cancelled) { 1108 if ((oldItem.getType() == newItem.getType()) && (oldItem.getDurability() == newItem 1109 .getDurability())) { 1110 event.setCursor( 1111 new ItemStack(newItem.getType(), newItem.getAmount(), newItem.getDurability())); 1112 event.setCancelled(true); 1113 return; 1114 } 1115 event.setCursor( 1116 new ItemStack(newItem.getType(), newItem.getAmount(), newItem.getDurability())); 1117 } 1118 } 1119 1120 @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) 1121 public void onInteract(PlayerInteractAtEntityEvent e) { 1122 Entity entity = e.getRightClicked(); 1123 if (!(entity instanceof ArmorStand) && !(entity instanceof ItemFrame)) { 1124 return; 1125 } 1126 Location location = BukkitUtil.adapt(e.getRightClicked().getLocation()); 1127 PlotArea area = location.getPlotArea(); 1128 if (area == null) { 1129 return; 1130 } 1131 EntitySpawnListener.testNether(entity); 1132 Plot plot = location.getPlotAbs(); 1133 BukkitPlayer pp = BukkitUtil.adapt(e.getPlayer()); 1134 if (plot == null) { 1135 if (!PlotFlagUtil.isAreaRoadFlagsAndFlagEquals(area, MiscInteractFlag.class, true) && !pp.hasPermission( 1136 Permission.PERMISSION_ADMIN_INTERACT_ROAD 1137 )) { 1138 pp.sendMessage( 1139 TranslatableCaption.of("permission.no_permission_event"), 1140 TagResolver.resolver( 1141 "node", 1142 Tag.inserting(Permission.PERMISSION_ADMIN_INTERACT_ROAD) 1143 ) 1144 ); 1145 e.setCancelled(true); 1146 } 1147 } else { 1148 if (Settings.Done.RESTRICT_BUILDING && DoneFlag.isDone(plot)) { 1149 if (!pp.hasPermission(Permission.PERMISSION_ADMIN_BUILD_OTHER)) { 1150 pp.sendMessage(TranslatableCaption.of("done.building_restricted")); 1151 e.setCancelled(true); 1152 return; 1153 } 1154 } 1155 if (!plot.hasOwner()) { 1156 if (!pp.hasPermission("plots.admin.interact.unowned")) { 1157 pp.sendMessage( 1158 TranslatableCaption.of("permission.no_permission_event"), 1159 TagResolver.resolver( 1160 "node", 1161 Tag.inserting(Permission.PERMISSION_ADMIN_INTERACT_UNOWNED) 1162 ) 1163 ); 1164 e.setCancelled(true); 1165 } 1166 } else { 1167 UUID uuid = pp.getUUID(); 1168 if (plot.isAdded(uuid)) { 1169 return; 1170 } 1171 if (plot.getFlag(MiscInteractFlag.class)) { 1172 return; 1173 } 1174 if (!pp.hasPermission(Permission.PERMISSION_ADMIN_INTERACT_OTHER)) { 1175 pp.sendMessage( 1176 TranslatableCaption.of("permission.no_permission_event"), 1177 TagResolver.resolver( 1178 "node", 1179 Tag.inserting(Permission.PERMISSION_ADMIN_INTERACT_OTHER) 1180 ) 1181 ); 1182 e.setCancelled(true); 1183 plot.debug(pp.getName() + " could not interact with " + entity.getType() 1184 + " because misc-interact = false"); 1185 } 1186 } 1187 } 1188 } 1189 1190 @EventHandler(priority = EventPriority.LOW) 1191 @SuppressWarnings("deprecation") // Paper deprecation 1192 public void onCancelledInteract(PlayerInteractEvent event) { 1193 if (event.isCancelled() && event.getAction() == Action.RIGHT_CLICK_AIR) { 1194 Player player = event.getPlayer(); 1195 BukkitPlayer pp = BukkitUtil.adapt(player); 1196 PlotArea area = pp.getPlotAreaAbs(); 1197 if (area == null) { 1198 return; 1199 } 1200 if (event.getAction() == Action.RIGHT_CLICK_AIR) { 1201 Material item = event.getMaterial(); 1202 if (item.toString().toLowerCase().endsWith("_egg")) { 1203 event.setCancelled(true); 1204 event.setUseItemInHand(Event.Result.DENY); 1205 } 1206 } 1207 ItemStack hand = player.getInventory().getItemInMainHand(); 1208 ItemStack offHand = player.getInventory().getItemInOffHand(); 1209 Material type = hand.getType(); 1210 Material offType = offHand.getType(); 1211 if (type == Material.AIR) { 1212 type = offType; 1213 } 1214 if (type.toString().toLowerCase().endsWith("_egg")) { 1215 Block block = player.getTargetBlockExact(5, FluidCollisionMode.SOURCE_ONLY); 1216 if (block != null && block.getType() != Material.AIR) { 1217 Location location = BukkitUtil.adapt(block.getLocation()); 1218 if (!this.eventDispatcher.checkPlayerBlockEvent(pp, PlayerBlockEventType.SPAWN_MOB, location, null, true)) { 1219 event.setCancelled(true); 1220 event.setUseItemInHand(Event.Result.DENY); 1221 } 1222 } 1223 } 1224 } 1225 } 1226 1227 @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) 1228 public void onInteract(PlayerInteractEvent event) { 1229 Player player = event.getPlayer(); 1230 BukkitPlayer pp = BukkitUtil.adapt(player); 1231 PlotArea area = pp.getPlotAreaAbs(); 1232 if (area == null) { 1233 return; 1234 } 1235 PlayerBlockEventType eventType; 1236 BlockType blocktype1; 1237 Block block = event.getClickedBlock(); 1238 if (block == null) { 1239 // We do not care in this case, the player is likely interacting with air ("nothing"). 1240 return; 1241 } 1242 Location location = BukkitUtil.adapt(block.getLocation()); 1243 Action action = event.getAction(); 1244 switch (action) { 1245 case PHYSICAL -> { 1246 eventType = PlayerBlockEventType.TRIGGER_PHYSICAL; 1247 blocktype1 = BukkitAdapter.asBlockType(block.getType()); 1248 } 1249 1250 //todo rearrange the right click code. it is all over the place. 1251 case RIGHT_CLICK_BLOCK -> { 1252 Material blockType = block.getType(); 1253 eventType = PlayerBlockEventType.INTERACT_BLOCK; 1254 blocktype1 = BukkitAdapter.asBlockType(block.getType()); 1255 1256 if (INTERACTABLE_MATERIALS != null ? INTERACTABLE_MATERIALS.contains(blockType.name()) : blockType.isInteractable()) { 1257 if (!player.isSneaking()) { 1258 break; 1259 } 1260 ItemStack hand = player.getInventory().getItemInMainHand(); 1261 ItemStack offHand = player.getInventory().getItemInOffHand(); 1262 1263 // sneaking players interact with blocks if both hands are empty 1264 if (hand.getType() == Material.AIR && offHand.getType() == Material.AIR) { 1265 break; 1266 } 1267 } 1268 1269 Material type = event.getMaterial(); 1270 1271 // in the following, lb needs to have the material of the item in hand i.e. type 1272 switch (type.toString()) { 1273 case "REDSTONE", "STRING", "PUMPKIN_SEEDS", "MELON_SEEDS", "COCOA_BEANS", "WHEAT_SEEDS", "BEETROOT_SEEDS", 1274 "SWEET_BERRIES", "GLOW_BERRIES" -> { 1275 return; 1276 } 1277 default -> { 1278 //eventType = PlayerBlockEventType.PLACE_BLOCK; 1279 if (type.isBlock()) { 1280 return; 1281 } 1282 } 1283 } 1284 if (PaperLib.isPaper()) { 1285 if (MaterialTags.SPAWN_EGGS.isTagged(type) || Material.EGG.equals(type)) { 1286 eventType = PlayerBlockEventType.SPAWN_MOB; 1287 break; 1288 } 1289 } else { 1290 if (type.toString().toLowerCase().endsWith("egg")) { 1291 eventType = PlayerBlockEventType.SPAWN_MOB; 1292 break; 1293 } 1294 } 1295 if (type.isEdible()) { 1296 //Allow all players to eat while also allowing the block place event to be fired 1297 return; 1298 } 1299 if (type == Material.ARMOR_STAND) { 1300 location = BukkitUtil.adapt(block.getRelative(event.getBlockFace()).getLocation()); 1301 eventType = PlayerBlockEventType.PLACE_MISC; 1302 } 1303 if (org.bukkit.Tag.ITEMS_BOATS.isTagged(type) || MINECARTS.contains(type)) { 1304 eventType = PlayerBlockEventType.PLACE_VEHICLE; 1305 break; 1306 } 1307 if (type == Material.FIREWORK_ROCKET || type == Material.FIREWORK_STAR) { 1308 eventType = PlayerBlockEventType.SPAWN_MOB; 1309 break; 1310 } 1311 if (BOOKS.contains(type)) { 1312 eventType = PlayerBlockEventType.READ; 1313 break; 1314 } 1315 } 1316 case LEFT_CLICK_BLOCK -> { 1317 Material blockType = block.getType(); 1318 1319 // todo: when the code above is rearranged, it would be great to beautify this as well. 1320 // will code this as a temporary, specific bug fix (for dragon eggs) 1321 if (blockType != Material.DRAGON_EGG) { 1322 return; 1323 } 1324 1325 eventType = PlayerBlockEventType.INTERACT_BLOCK; 1326 blocktype1 = BukkitAdapter.asBlockType(block.getType()); 1327 } 1328 default -> { 1329 return; 1330 } 1331 } 1332 if (this.worldEdit != null && pp.getAttribute("worldedit")) { 1333 if (event.getMaterial() == Material.getMaterial(this.worldEdit.getConfiguration().wandItem)) { 1334 return; 1335 } 1336 } 1337 if (!this.eventDispatcher.checkPlayerBlockEvent(pp, eventType, location, blocktype1, true)) { 1338 event.setCancelled(true); 1339 event.setUseInteractedBlock(Event.Result.DENY); 1340 } 1341 } 1342 1343 // Boats can sometimes be placed on interactable blocks such as levers, 1344 // see PS-175. Armor stands, minecarts and end crystals (the other entities 1345 // supported by this event) don't have this issue. 1346 @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) 1347 public void onBoatPlace(EntityPlaceEvent event) { 1348 Player player = event.getPlayer(); 1349 if (player == null) { 1350 return; 1351 } 1352 Entity placed = event.getEntity(); 1353 if (!(placed instanceof Boat)) { 1354 return; 1355 } 1356 BukkitPlayer pp = BukkitUtil.adapt(event.getPlayer()); 1357 PlotArea area = pp.getPlotAreaAbs(); 1358 if (area == null) { 1359 return; 1360 } 1361 PlayerBlockEventType eventType = PlayerBlockEventType.PLACE_VEHICLE; 1362 Block block = event.getBlock(); 1363 BlockType blockType = BukkitAdapter.asBlockType(block.getType()); 1364 Location location = BukkitUtil.adapt(block.getLocation()); 1365 if (!PlotSquared.get().getEventDispatcher() 1366 .checkPlayerBlockEvent(pp, eventType, location, blockType, true)) { 1367 event.setCancelled(true); 1368 } 1369 } 1370 1371 @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) 1372 public void onBucketEmpty(PlayerBucketEmptyEvent event) { 1373 BlockFace bf = event.getBlockFace(); 1374 // Note: a month after Bukkit 1.14.4 released, they added the API method 1375 // PlayerBucketEmptyEvent#getBlock(), which returns the block the 1376 // bucket contents is going to be placed at. Currently we determine this 1377 // block ourselves to retain compatibility with 1.13. 1378 final Block block; 1379 // if the block can be waterlogged, the event might waterlog the block 1380 // sometimes 1381 if (event.getBlockClicked().getBlockData() instanceof Waterlogged waterlogged 1382 && !waterlogged.isWaterlogged() && event.getBucket() != Material.LAVA_BUCKET) { 1383 block = event.getBlockClicked(); 1384 } else { 1385 block = event.getBlockClicked().getLocation() 1386 .add(bf.getModX(), bf.getModY(), bf.getModZ()) 1387 .getBlock(); 1388 } 1389 Location location = BukkitUtil.adapt(block.getLocation()); 1390 PlotArea area = location.getPlotArea(); 1391 if (area == null) { 1392 return; 1393 } 1394 BukkitPlayer pp = BukkitUtil.adapt(event.getPlayer()); 1395 Plot plot = area.getPlot(location); 1396 if (plot == null) { 1397 if (pp.hasPermission(Permission.PERMISSION_ADMIN_BUILD_ROAD)) { 1398 return; 1399 } 1400 pp.sendMessage( 1401 TranslatableCaption.of("permission.no_permission_event"), 1402 TagResolver.resolver("node", Tag.inserting(Permission.PERMISSION_ADMIN_BUILD_ROAD)) 1403 ); 1404 event.setCancelled(true); 1405 } else if (!plot.hasOwner()) { 1406 if (pp.hasPermission(Permission.PERMISSION_ADMIN_BUILD_UNOWNED)) { 1407 return; 1408 } 1409 pp.sendMessage( 1410 TranslatableCaption.of("permission.no_permission_event"), 1411 TagResolver.resolver( 1412 "node", 1413 Tag.inserting(Permission.PERMISSION_ADMIN_BUILD_UNOWNED) 1414 ) 1415 ); 1416 event.setCancelled(true); 1417 } else if (!plot.isAdded(pp.getUUID())) { 1418 if (pp.hasPermission(Permission.PERMISSION_ADMIN_BUILD_OTHER)) { 1419 return; 1420 } 1421 pp.sendMessage( 1422 TranslatableCaption.of("permission.no_permission_event"), 1423 TagResolver.resolver( 1424 "node", 1425 Tag.inserting(Permission.PERMISSION_ADMIN_BUILD_OTHER) 1426 ) 1427 ); 1428 event.setCancelled(true); 1429 } else if (Settings.Done.RESTRICT_BUILDING && DoneFlag.isDone(plot)) { 1430 if (!pp.hasPermission(Permission.PERMISSION_ADMIN_BUILD_OTHER)) { 1431 pp.sendMessage( 1432 TranslatableCaption.of("done.building_restricted") 1433 ); 1434 event.setCancelled(true); 1435 } 1436 } 1437 } 1438 1439 @EventHandler(priority = EventPriority.HIGHEST) 1440 public void onInventoryClose(InventoryCloseEvent event) { 1441 HumanEntity closer = event.getPlayer(); 1442 if (!(closer instanceof Player player)) { 1443 return; 1444 } 1445 PlotInventory.removePlotInventoryOpen(BukkitUtil.adapt(player)); 1446 } 1447 1448 @EventHandler(priority = EventPriority.MONITOR) 1449 public void onLeave(PlayerQuitEvent event) { 1450 TaskManager.removeFromTeleportQueue(event.getPlayer().getName()); 1451 BukkitPlayer pp = BukkitUtil.adapt(event.getPlayer()); 1452 pp.unregister(); 1453 plotListener.logout(pp.getUUID()); 1454 } 1455 1456 @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) 1457 public void onBucketFill(PlayerBucketFillEvent event) { 1458 Block blockClicked = event.getBlockClicked(); 1459 Location location = BukkitUtil.adapt(blockClicked.getLocation()); 1460 PlotArea area = location.getPlotArea(); 1461 if (area == null) { 1462 return; 1463 } 1464 Player player = event.getPlayer(); 1465 BukkitPlayer plotPlayer = BukkitUtil.adapt(player); 1466 Plot plot = area.getPlot(location); 1467 if (plot == null) { 1468 if (plotPlayer.hasPermission(Permission.PERMISSION_ADMIN_BUILD_ROAD)) { 1469 return; 1470 } 1471 plotPlayer.sendMessage( 1472 TranslatableCaption.of("permission.no_permission_event"), 1473 TagResolver.resolver("node", Tag.inserting(Permission.PERMISSION_ADMIN_BUILD_ROAD)) 1474 ); 1475 event.setCancelled(true); 1476 } else if (!plot.hasOwner()) { 1477 if (plotPlayer.hasPermission(Permission.PERMISSION_ADMIN_BUILD_UNOWNED)) { 1478 return; 1479 } 1480 plotPlayer.sendMessage( 1481 TranslatableCaption.of("permission.no_permission_event"), 1482 TagResolver.resolver( 1483 "node", 1484 Tag.inserting(Permission.PERMISSION_ADMIN_BUILD_UNOWNED) 1485 ) 1486 ); 1487 event.setCancelled(true); 1488 } else if (!plot.isAdded(plotPlayer.getUUID())) { 1489 if (plotPlayer.hasPermission(Permission.PERMISSION_ADMIN_BUILD_OTHER)) { 1490 return; 1491 } 1492 plotPlayer.sendMessage( 1493 TranslatableCaption.of("permission.no_permission_event"), 1494 TagResolver.resolver( 1495 "node", 1496 Tag.inserting(Permission.PERMISSION_ADMIN_BUILD_OTHER) 1497 ) 1498 ); 1499 event.setCancelled(true); 1500 } else if (Settings.Done.RESTRICT_BUILDING && DoneFlag.isDone(plot)) { 1501 if (!plotPlayer.hasPermission(Permission.PERMISSION_ADMIN_BUILD_OTHER)) { 1502 plotPlayer.sendMessage( 1503 TranslatableCaption.of("done.building_restricted") 1504 ); 1505 event.setCancelled(true); 1506 } 1507 } 1508 } 1509 1510 @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) 1511 public void onHangingPlace(HangingPlaceEvent event) { 1512 Block block = event.getBlock().getRelative(event.getBlockFace()); 1513 Location location = BukkitUtil.adapt(block.getLocation()); 1514 PlotArea area = location.getPlotArea(); 1515 if (area == null) { 1516 return; 1517 } 1518 Player p = event.getPlayer(); 1519 if (p == null) { 1520 event.setCancelled(true); 1521 return; 1522 } 1523 BukkitPlayer pp = BukkitUtil.adapt(p); 1524 Plot plot = area.getPlot(location); 1525 if (plot == null) { 1526 if (!pp.hasPermission(Permission.PERMISSION_ADMIN_BUILD_ROAD)) { 1527 pp.sendMessage( 1528 TranslatableCaption.of("permission.no_permission_event"), 1529 TagResolver.resolver( 1530 "node", 1531 Tag.inserting(Permission.PERMISSION_ADMIN_BUILD_ROAD) 1532 ) 1533 ); 1534 event.setCancelled(true); 1535 } 1536 } else { 1537 if (!plot.hasOwner()) { 1538 if (!pp.hasPermission(Permission.PERMISSION_ADMIN_BUILD_UNOWNED)) { 1539 pp.sendMessage( 1540 TranslatableCaption.of("permission.no_permission_event"), 1541 TagResolver.resolver( 1542 "node", 1543 Tag.inserting(Permission.PERMISSION_ADMIN_BUILD_UNOWNED) 1544 ) 1545 ); 1546 event.setCancelled(true); 1547 } 1548 return; 1549 } 1550 if (!plot.isAdded(pp.getUUID())) { 1551 if (!plot.getFlag(HangingPlaceFlag.class)) { 1552 if (!pp.hasPermission(Permission.PERMISSION_ADMIN_BUILD_OTHER)) { 1553 pp.sendMessage( 1554 TranslatableCaption.of("permission.no_permission_event"), 1555 TagResolver.resolver( 1556 "node", 1557 Tag.inserting(Permission.PERMISSION_ADMIN_BUILD_OTHER) 1558 ) 1559 ); 1560 event.setCancelled(true); 1561 } 1562 return; 1563 } 1564 } 1565 if (BukkitEntityUtil.checkEntity(event.getEntity(), plot)) { 1566 event.setCancelled(true); 1567 } 1568 1569 } 1570 } 1571 1572 @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) 1573 public void onHangingBreakByEntity(HangingBreakByEntityEvent event) { 1574 Entity remover = event.getRemover(); 1575 if (remover instanceof Player p) { 1576 Location location = BukkitUtil.adapt(event.getEntity().getLocation()); 1577 PlotArea area = location.getPlotArea(); 1578 if (area == null) { 1579 return; 1580 } 1581 BukkitPlayer pp = BukkitUtil.adapt(p); 1582 Plot plot = area.getPlot(location); 1583 if (plot == null) { 1584 if (!pp.hasPermission(Permission.PERMISSION_ADMIN_DESTROY_ROAD)) { 1585 pp.sendMessage( 1586 TranslatableCaption.of("permission.no_permission_event"), 1587 TagResolver.resolver( 1588 "node", 1589 Tag.inserting(Permission.PERMISSION_ADMIN_DESTROY_ROAD) 1590 ) 1591 ); 1592 event.setCancelled(true); 1593 } 1594 } else if (!plot.hasOwner()) { 1595 if (!pp.hasPermission(Permission.PERMISSION_ADMIN_DESTROY_UNOWNED)) { 1596 pp.sendMessage( 1597 TranslatableCaption.of("permission.no_permission_event"), 1598 TagResolver.resolver( 1599 "node", 1600 Tag.inserting(Permission.PERMISSION_ADMIN_DESTROY_UNOWNED) 1601 ) 1602 ); 1603 event.setCancelled(true); 1604 } 1605 } else if (!plot.isAdded(pp.getUUID())) { 1606 if (plot.getFlag(HangingBreakFlag.class)) { 1607 return; 1608 } 1609 if (!pp.hasPermission(Permission.PERMISSION_ADMIN_DESTROY_OTHER)) { 1610 pp.sendMessage( 1611 TranslatableCaption.of("permission.no_permission_event"), 1612 TagResolver.resolver( 1613 "node", 1614 Tag.inserting(Permission.PERMISSION_ADMIN_DESTROY_OTHER) 1615 ) 1616 ); 1617 event.setCancelled(true); 1618 plot.debug(p.getName() 1619 + " could not break hanging entity because hanging-break = false"); 1620 } 1621 } 1622 } else if (remover instanceof Projectile p) { 1623 if (p.getShooter() instanceof Player shooter) { 1624 Location location = BukkitUtil.adapt(event.getEntity().getLocation()); 1625 PlotArea area = location.getPlotArea(); 1626 if (area == null) { 1627 return; 1628 } 1629 BukkitPlayer player = BukkitUtil.adapt(shooter); 1630 Plot plot = area.getPlot(BukkitUtil.adapt(event.getEntity().getLocation())); 1631 if (plot != null) { 1632 if (!plot.hasOwner()) { 1633 if (!player.hasPermission(Permission.PERMISSION_ADMIN_DESTROY_UNOWNED)) { 1634 player.sendMessage( 1635 TranslatableCaption.of("permission.no_permission_event"), 1636 TagResolver.resolver( 1637 "node", 1638 Tag.inserting(Permission.PERMISSION_ADMIN_DESTROY_UNOWNED) 1639 ) 1640 ); 1641 event.setCancelled(true); 1642 } 1643 } else if (!plot.isAdded(player.getUUID())) { 1644 if (!plot.getFlag(HangingBreakFlag.class)) { 1645 if (!player.hasPermission(Permission.PERMISSION_ADMIN_DESTROY_OTHER)) { 1646 player.sendMessage( 1647 TranslatableCaption.of("permission.no_permission_event"), 1648 TagResolver.resolver( 1649 "node", 1650 Tag.inserting(Permission.PERMISSION_ADMIN_DESTROY_OTHER) 1651 ) 1652 ); 1653 event.setCancelled(true); 1654 plot.debug(player.getName() 1655 + " could not break hanging entity because hanging-break = false"); 1656 } 1657 } 1658 } 1659 } 1660 } 1661 } else { 1662 event.setCancelled(true); 1663 } 1664 } 1665 1666 @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) 1667 public void onPlayerInteractEntity(PlayerInteractEntityEvent event) { 1668 if (event.getRightClicked().getType() == EntityType.UNKNOWN) { 1669 return; 1670 } 1671 Location location = BukkitUtil.adapt(event.getRightClicked().getLocation()); 1672 PlotArea area = location.getPlotArea(); 1673 if (area == null) { 1674 return; 1675 } 1676 Player p = event.getPlayer(); 1677 BukkitPlayer pp = BukkitUtil.adapt(p); 1678 Plot plot = area.getPlot(location); 1679 if (plot == null && !area.isRoadFlags()) { 1680 if (!pp.hasPermission(Permission.PERMISSION_ADMIN_INTERACT_ROAD)) { 1681 pp.sendMessage( 1682 TranslatableCaption.of("permission.no_permission_event"), 1683 TagResolver.resolver( 1684 "node", 1685 Tag.inserting(Permission.PERMISSION_ADMIN_INTERACT_ROAD) 1686 ) 1687 ); 1688 event.setCancelled(true); 1689 } 1690 } else if (plot != null && !plot.hasOwner()) { 1691 if (!pp.hasPermission(Permission.PERMISSION_ADMIN_INTERACT_UNOWNED)) { 1692 pp.sendMessage( 1693 TranslatableCaption.of("permission.no_permission_event"), 1694 TagResolver.resolver( 1695 "node", 1696 Tag.inserting(Permission.PERMISSION_ADMIN_INTERACT_UNOWNED) 1697 ) 1698 ); 1699 event.setCancelled(true); 1700 } 1701 } else if ((plot != null && !plot.isAdded(pp.getUUID())) || (plot == null && area 1702 .isRoadFlags())) { 1703 final Entity entity = event.getRightClicked(); 1704 final com.sk89q.worldedit.world.entity.EntityType entityType = 1705 BukkitAdapter.adapt(entity.getType()); 1706 1707 FlagContainer flagContainer; 1708 if (plot == null) { 1709 flagContainer = area.getRoadFlagContainer(); 1710 } else { 1711 flagContainer = plot.getFlagContainer(); 1712 } 1713 1714 if (EntityCategories.HOSTILE.contains(entityType) && flagContainer 1715 .getFlag(HostileInteractFlag.class).getValue()) { 1716 return; 1717 } 1718 1719 if (EntityCategories.ANIMAL.contains(entityType) && flagContainer 1720 .getFlag(AnimalInteractFlag.class).getValue()) { 1721 return; 1722 } 1723 1724 // This actually makes use of the interface, so we don't use the 1725 // category 1726 if (entity instanceof Tameable && ((Tameable) entity).isTamed() && flagContainer 1727 .getFlag(TamedInteractFlag.class).getValue()) { 1728 return; 1729 } 1730 1731 if (EntityCategories.VEHICLE.contains(entityType) && flagContainer 1732 .getFlag(VehicleUseFlag.class).getValue()) { 1733 return; 1734 } 1735 1736 if (EntityCategories.PLAYER.contains(entityType) && flagContainer 1737 .getFlag(PlayerInteractFlag.class).getValue()) { 1738 return; 1739 } 1740 1741 if (EntityCategories.INTERACTION.contains(entityType) && flagContainer 1742 .getFlag(InteractionInteractFlag.class).getValue()) { 1743 return; 1744 } 1745 1746 if (EntityCategories.VILLAGER.contains(entityType) && flagContainer 1747 .getFlag(VillagerInteractFlag.class).getValue()) { 1748 return; 1749 } 1750 1751 if ((EntityCategories.HANGING.contains(entityType) || EntityCategories.OTHER 1752 .contains(entityType)) && flagContainer.getFlag(MiscInteractFlag.class) 1753 .getValue()) { 1754 return; 1755 } 1756 1757 if (!pp.hasPermission(Permission.PERMISSION_ADMIN_INTERACT_OTHER)) { 1758 pp.sendMessage( 1759 TranslatableCaption.of("permission.no_permission_event"), 1760 TagResolver.resolver( 1761 "node", 1762 Tag.inserting(Permission.PERMISSION_ADMIN_INTERACT_OTHER) 1763 ) 1764 ); 1765 event.setCancelled(true); 1766 } 1767 } 1768 } 1769 1770 @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) 1771 public void onVehicleDestroy(VehicleDestroyEvent event) { 1772 Location location = BukkitUtil.adapt(event.getVehicle().getLocation()); 1773 PlotArea area = location.getPlotArea(); 1774 if (area == null) { 1775 return; 1776 } 1777 Entity attacker = event.getAttacker(); 1778 if (attacker instanceof Player p) { 1779 BukkitPlayer pp = BukkitUtil.adapt(p); 1780 Plot plot = area.getPlot(location); 1781 if (plot == null) { 1782 if (!PlotFlagUtil.isAreaRoadFlagsAndFlagEquals(area, VehicleBreakFlag.class, true) && !pp.hasPermission( 1783 Permission.PERMISSION_ADMIN_DESTROY_VEHICLE_ROAD 1784 )) { 1785 pp.sendMessage( 1786 TranslatableCaption.of("permission.no_permission_event"), 1787 TagResolver.resolver( 1788 "node", 1789 Tag.inserting(Permission.PERMISSION_ADMIN_DESTROY_VEHICLE_ROAD) 1790 ) 1791 ); 1792 event.setCancelled(true); 1793 } 1794 } else { 1795 if (!plot.hasOwner()) { 1796 if (!pp.hasPermission(Permission.PERMISSION_ADMIN_DESTROY_VEHICLE_UNOWNED)) { 1797 pp.sendMessage( 1798 TranslatableCaption.of("permission.no_permission_event"), 1799 TagResolver.resolver( 1800 "node", 1801 Tag.inserting(Permission.PERMISSION_ADMIN_DESTROY_VEHICLE_UNOWNED) 1802 ) 1803 ); 1804 event.setCancelled(true); 1805 return; 1806 } 1807 return; 1808 } 1809 if (!plot.isAdded(pp.getUUID())) { 1810 if (plot.getFlag(VehicleBreakFlag.class)) { 1811 return; 1812 } 1813 if (!pp.hasPermission(Permission.PERMISSION_ADMIN_DESTROY_VEHICLE_OTHER)) { 1814 pp.sendMessage( 1815 TranslatableCaption.of("permission.no_permission_event"), 1816 TagResolver.resolver( 1817 "node", 1818 Tag.inserting(Permission.PERMISSION_ADMIN_DESTROY_VEHICLE_OTHER) 1819 ) 1820 ); 1821 event.setCancelled(true); 1822 plot.debug(pp.getName() 1823 + " could not break vehicle because vehicle-break = false"); 1824 } 1825 } 1826 } 1827 } 1828 } 1829 1830 @EventHandler 1831 public void onItemDrop(PlayerDropItemEvent event) { 1832 Player player = event.getPlayer(); 1833 BukkitPlayer pp = BukkitUtil.adapt(player); 1834 Location location = pp.getLocation(); 1835 PlotArea area = location.getPlotArea(); 1836 if (area == null) { 1837 return; 1838 } 1839 Plot plot = location.getOwnedPlot(); 1840 if (plot == null) { 1841 if (PlotFlagUtil.isAreaRoadFlagsAndFlagEquals(area, ItemDropFlag.class, false)) { 1842 event.setCancelled(true); 1843 } 1844 return; 1845 } 1846 UUID uuid = pp.getUUID(); 1847 if (!plot.isAdded(uuid)) { 1848 if (!plot.getFlag(ItemDropFlag.class)) { 1849 plot.debug(player.getName() + " could not drop item because of item-drop = false"); 1850 event.setCancelled(true); 1851 } 1852 } 1853 } 1854 1855 @EventHandler 1856 public void onItemPickup(EntityPickupItemEvent event) { 1857 LivingEntity ent = event.getEntity(); 1858 if (ent instanceof Player player) { 1859 BukkitPlayer pp = BukkitUtil.adapt(player); 1860 Location location = pp.getLocation(); 1861 PlotArea area = location.getPlotArea(); 1862 if (area == null) { 1863 return; 1864 } 1865 Plot plot = location.getOwnedPlot(); 1866 if (plot == null) { 1867 if (PlotFlagUtil.isAreaRoadFlagsAndFlagEquals(area, DropProtectionFlag.class, true)) { 1868 event.setCancelled(true); 1869 } 1870 return; 1871 } 1872 UUID uuid = pp.getUUID(); 1873 if (!plot.isAdded(uuid) && plot.getFlag(DropProtectionFlag.class)) { 1874 plot.debug(player.getName() + " could not pick up item because of drop-protection = true"); 1875 event.setCancelled(true); 1876 } 1877 } 1878 } 1879 1880 @EventHandler 1881 public void onDeath(final PlayerDeathEvent event) { 1882 Location location = BukkitUtil.adapt(event.getEntity().getLocation()); 1883 PlotArea area = location.getPlotArea(); 1884 if (area == null) { 1885 return; 1886 } 1887 Plot plot = location.getOwnedPlot(); 1888 if (plot == null) { 1889 if (PlotFlagUtil.isAreaRoadFlagsAndFlagEquals(area, KeepInventoryFlag.class, true)) { 1890 event.setCancelled(true); 1891 } 1892 return; 1893 } 1894 if (plot.getFlag(KeepInventoryFlag.class)) { 1895 plot.debug(event.getEntity().getName() + " kept their inventory because of keep-inventory = true"); 1896 event.getDrops().clear(); 1897 event.setKeepInventory(true); 1898 } 1899 } 1900 1901 @SuppressWarnings("deprecation") // #getLocate is needed for Spigot compatibility 1902 @EventHandler 1903 public void onLocaleChange(final PlayerLocaleChangeEvent event) { 1904 // The event is fired before the player is deemed online upon login 1905 if (!event.getPlayer().isOnline()) { 1906 return; 1907 } 1908 BukkitPlayer player = BukkitUtil.adapt(event.getPlayer()); 1909 // we're stripping the country code as we don't want to differ between countries 1910 player.setLocale(Locale.forLanguageTag(event.getLocale().substring(0, 2))); 1911 } 1912 1913 @EventHandler 1914 public void onPortalEnter(PlayerPortalEvent event) { 1915 Location location = BukkitUtil.adapt(event.getPlayer().getLocation()); 1916 PlotArea area = location.getPlotArea(); 1917 if (area == null) { 1918 return; 1919 } 1920 Plot plot = location.getOwnedPlot(); 1921 if (plot == null) { 1922 if (PlotFlagUtil.isAreaRoadFlagsAndFlagEquals(area, DenyPortalTravelFlag.class, true)) { 1923 event.setCancelled(true); 1924 } 1925 return; 1926 } 1927 if (plot.getFlag(DenyPortalTravelFlag.class)) { 1928 plot.debug(event.getPlayer().getName() + " did not travel thru a portal because of deny-portal-travel = true"); 1929 event.setCancelled(true); 1930 } 1931 } 1932 1933 @EventHandler 1934 public void onPortalCreation(PortalCreateEvent event) { 1935 String world = event.getWorld().getName(); 1936 if (PlotSquared.get().getPlotAreaManager().getPlotAreasSet(world).size() == 0) { 1937 return; 1938 } 1939 BukkitPlayer pp = (event.getEntity() instanceof Player player) ? BukkitUtil.adapt(player) : null; 1940 int minX = Integer.MAX_VALUE; 1941 int maxX = Integer.MIN_VALUE; 1942 int minZ = Integer.MAX_VALUE; 1943 int maxZ = Integer.MIN_VALUE; 1944 for (BlockState state : event.getBlocks()) { 1945 minX = Math.min(state.getX(), minX); 1946 maxX = Math.max(state.getX(), maxX); 1947 minZ = Math.min(state.getZ(), minZ); 1948 maxZ = Math.max(state.getZ(), maxZ); 1949 } 1950 int y = event.getBlocks().get(0).getY(); // Don't need to worry about this too much 1951 for (Location location : List.of( // We don't care about duplicate locations 1952 Location.at(world, minX, y, minZ), 1953 Location.at(world, minX, y, maxZ), 1954 Location.at(world, maxX, y, minZ), 1955 Location.at(world, maxX, y, maxZ) 1956 )) { 1957 PlotArea area = location.getPlotArea(); 1958 if (area == null) { 1959 continue; 1960 } 1961 if (area.notifyIfOutsideBuildArea(pp, location.getY())) { 1962 event.setCancelled(true); 1963 return; 1964 } 1965 Plot plot = location.getOwnedPlot(); 1966 if (plot == null) { 1967 if (PlotFlagUtil.isAreaRoadFlagsAndFlagEquals(area, DenyPortalsFlag.class, true)) { 1968 event.setCancelled(true); 1969 return; 1970 } 1971 continue; 1972 } 1973 if (plot.getFlag(DenyPortalsFlag.class)) { 1974 StringBuilder builder = new StringBuilder(); 1975 if (event.getEntity() != null) { 1976 builder.append(event.getEntity().getName()).append(" did not create a portal"); 1977 } else { 1978 builder.append("Portal creation cancelled"); 1979 } 1980 plot.debug(builder.append(" because of deny-portals = true").toString()); 1981 event.setCancelled(true); 1982 return; 1983 } 1984 } 1985 } 1986 1987 @EventHandler 1988 public void onPlayerTakeLecternBook(PlayerTakeLecternBookEvent event) { 1989 Player player = event.getPlayer(); 1990 BukkitPlayer pp = BukkitUtil.adapt(player); 1991 Location location = pp.getLocation(); 1992 PlotArea area = location.getPlotArea(); 1993 if (area == null) { 1994 return; 1995 } 1996 Plot plot = location.getOwnedPlot(); 1997 if (plot == null) { 1998 if (PlotFlagUtil.isAreaRoadFlagsAndFlagEquals(area, LecternReadBookFlag.class, true)) { 1999 event.setCancelled(true); 2000 } 2001 return; 2002 } 2003 if (!plot.isAdded(pp.getUUID())) { 2004 if (plot.getFlag(LecternReadBookFlag.class)) { 2005 plot.debug(event.getPlayer().getName() + " could not take the book because of lectern-read-book = true"); 2006 event.setCancelled(true); 2007 } 2008 } 2009 } 2010 2011}