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