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