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