From f56e1fcf9c68cb0113507e787c805527349f5e71 Mon Sep 17 00:00:00 2001 From: tastybento Date: Wed, 1 Jan 2025 09:30:53 -0800 Subject: [PATCH] Release 4.4.1 (#137) * Version 4.2.2 * Added protection against console error spam if island size is zero. If the protection range is 0 then the caluclations to teleport players back into the border will result in infinite values and other strangeness so this prevents that. This is an edge case and only really happens when the island size has been set wrongly. * Update README.md * Fix perm issue #120 (#121) * feat: detect mounted players on entity (#88) * Version 4.3.0 * Changes to work with 1.20.6. Has backwards compatibility. (#125) * Fix imports * Update zh-CN.yml (#127) * Latvian translationa (#128) * Translate lv.yml via GitLocalize * Translate lv.yml via GitLocalize --------- Co-authored-by: mt-gitlocalize Co-authored-by: tastybento * Add explicit bordertype command (#130) * Add explicit bordertype command * Add perm to addon.yml and make it default to off * Remove unused method. * 131 null to location (#132) * Version 4.3.1 * Add defensive code for null to's #131 * If border is off, then don't move player back. * Update to MC 1.21.3 and codemc updates (#134) * Version 4.4.1 * Improved operation when border is off (#136) * Fix merge issue * Remove duplicate BlockListener class --------- Co-authored-by: evlad Co-authored-by: Minecraft_15 <147026380+huguyt@users.noreply.github.com> Co-authored-by: gitlocalize-app[bot] <55277160+gitlocalize-app[bot]@users.noreply.github.com> Co-authored-by: mt-gitlocalize --- pom.xml | 2 +- .../border/listeners/BlockListener.java | 325 ------------------ .../border/listeners/PlayerListener.java | 63 ++-- 3 files changed, 42 insertions(+), 348 deletions(-) delete mode 100644 src/main/java/world/bentobox/border/listeners/BlockListener.java diff --git a/pom.xml b/pom.xml index 92442e1..8ffc1f1 100644 --- a/pom.xml +++ b/pom.xml @@ -50,7 +50,7 @@ ${build.version}-SNAPSHOT - 4.4.0 + 4.4.1 -LOCAL BentoBoxWorld_Border diff --git a/src/main/java/world/bentobox/border/listeners/BlockListener.java b/src/main/java/world/bentobox/border/listeners/BlockListener.java deleted file mode 100644 index a7d187d..0000000 --- a/src/main/java/world/bentobox/border/listeners/BlockListener.java +++ /dev/null @@ -1,325 +0,0 @@ -package world.bentobox.border.listeners; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.UUID; - -import org.bukkit.Bukkit; -import org.bukkit.GameMode; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.BlockFace; -import org.bukkit.entity.Entity; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; -import org.bukkit.event.entity.EntityDismountEvent; -import org.bukkit.event.entity.EntityMountEvent; -import org.bukkit.event.player.PlayerJoinEvent; -import org.bukkit.event.player.PlayerMoveEvent; -import org.bukkit.event.player.PlayerQuitEvent; -import org.bukkit.event.player.PlayerRespawnEvent; -import org.bukkit.event.player.PlayerTeleportEvent; -import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; -import org.bukkit.event.vehicle.VehicleMoveEvent; -import org.bukkit.scheduler.BukkitTask; -import org.bukkit.util.NumberConversions; -import org.bukkit.util.RayTraceResult; -import org.bukkit.util.Vector; - -import world.bentobox.bentobox.api.events.island.IslandProtectionRangeChangeEvent; -import world.bentobox.bentobox.api.flags.Flag; -import world.bentobox.bentobox.api.metadata.MetaDataValue; -import world.bentobox.bentobox.api.user.User; -import world.bentobox.bentobox.util.Util; -import world.bentobox.border.Border; -import world.bentobox.border.PerPlayerBorderProxy; -import world.bentobox.border.commands.IslandBorderCommand; - -/** - * @author tastybento - */ -public class BlockListener implements Listener { - - private static final Vector XZ = new Vector(1,0,1); - private final Border addon; - private Set inTeleport; - private final BorderShower show; - private Map mountedPlayers = new HashMap<>(); - - public BlockListener(Border addon) { - this.addon = addon; - inTeleport = new HashSet<>(); - this.show = addon.getBorderShower(); - } - - @EventHandler(priority = EventPriority.NORMAL) - public void onPlayerJoin(PlayerJoinEvent e) { - // Run one-tick after joining because meta data cannot be set otherwise - Bukkit.getScheduler().runTask(addon.getPlugin(), () -> processEvent(e)); - } - - protected void processEvent(PlayerJoinEvent e) { - User user = User.getInstance(e.getPlayer()); - - show.hideBorder(user); - // Just for sure, disable world Border - user.getPlayer().setWorldBorder(null); - - // Get the game mode that this player is in - addon.getPlugin().getIWM().getAddon(e.getPlayer().getWorld()).map(gma -> gma.getPermissionPrefix()).filter( - permPrefix -> !e.getPlayer().hasPermission(permPrefix + IslandBorderCommand.BORDER_COMMAND_PERM)) - .ifPresent(permPrefix -> { - // Restore barrier on/off to default - user.putMetaData(BorderShower.BORDER_STATE_META_DATA, - new MetaDataValue(addon.getSettings().isShowByDefault())); - if (!e.getPlayer().hasPermission(permPrefix + "border.type") && !e.getPlayer().hasPermission(permPrefix + "border.bordertype")) { - // Restore default barrier type to player - MetaDataValue metaDataValue = new MetaDataValue(addon.getSettings().getType().getId()); - user.putMetaData(PerPlayerBorderProxy.BORDER_BORDERTYPE_META_DATA, metaDataValue); - } - }); - - // Show the border if required one tick after - Bukkit.getScheduler().runTask(addon.getPlugin(), () -> addon.getIslands().getIslandAt(e.getPlayer().getLocation()).ifPresent(i -> - show.showBorder(e.getPlayer(), i))); - } - - @EventHandler(priority = EventPriority.NORMAL) - public void onPlayerQuit(PlayerQuitEvent e) { - show.clearUser(User.getInstance(e.getPlayer())); - } - - @EventHandler(priority = EventPriority.NORMAL) - public void onPlayerRespawn(PlayerRespawnEvent e) { - show.clearUser(User.getInstance(e.getPlayer())); - Bukkit.getScheduler().runTask(addon.getPlugin(), () -> addon.getIslands().getIslandAt(e.getPlayer().getLocation()).ifPresent(i -> - show.showBorder(e.getPlayer(), i))); - } - - private boolean isOn(Player player) { - // Check if border is off - User user = User.getInstance(player); - return user.getMetaData(BorderShower.BORDER_STATE_META_DATA).map(MetaDataValue::asBoolean) - .orElse(addon.getSettings().isShowByDefault()); - - } - - @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onPlayerTeleport(PlayerTeleportEvent e) { - Player player = e.getPlayer(); - if (!isOn(player)) { - return; - } - Location to = e.getTo(); - - show.clearUser(User.getInstance(player)); - - if (to == null || !addon.inGameWorld(to.getWorld())) { - return; - } - - TeleportCause cause = e.getCause(); - boolean isBlacklistedCause = cause == TeleportCause.ENDER_PEARL || cause == TeleportCause.CHORUS_FRUIT; - - Bukkit.getScheduler().runTask(addon.getPlugin(), () -> - addon.getIslands().getIslandAt(to).ifPresentOrElse(i -> { - Optional boxedEnderPearlFlag = i.getPlugin().getFlagsManager().getFlag("ALLOW_MOVE_BOX"); - - if (isBlacklistedCause - && (!i.getProtectionBoundingBox().contains(to.toVector()) - || !i.onIsland(player.getLocation()))) { - e.setCancelled(true); - } - - if (boxedEnderPearlFlag.isPresent() - && boxedEnderPearlFlag.get().isSetForWorld(to.getWorld()) - && cause == TeleportCause.ENDER_PEARL) { - e.setCancelled(false); - } - - show.showBorder(player, i); - }, () -> { - if (isBlacklistedCause) { - e.setCancelled(true); - return; - } - }) - ); - } - - @EventHandler(priority = EventPriority.NORMAL) - public void onPlayerLeaveIsland(PlayerMoveEvent e) { - Player p = e.getPlayer(); - if (!isOn(p)) { - return; - } - Location from = e.getFrom(); - if (!addon.getSettings().isReturnTeleport() || !outsideCheck(e.getPlayer(), from, e.getTo())) { - return; - } - // Move the player back inside the border - if (addon.getIslands().getProtectedIslandAt(from).isPresent()) { - e.setCancelled(true); - inTeleport.add(p.getUniqueId()); - Util.teleportAsync(p, from).thenRun(() -> inTeleport.remove(p.getUniqueId())); - return; - } - // Backtrack - addon.getIslands().getIslandAt(p.getLocation()).ifPresent(i -> { - Vector unitVector = i.getProtectionCenter().toVector().subtract(p.getLocation().toVector()).normalize() - .multiply(new Vector(1,0,1)); - if (unitVector.lengthSquared() <= 0D) { - // Direction is zero, so nothing to do; cannot move. - return; - } - RayTraceResult r = i.getProtectionBoundingBox().rayTrace(p.getLocation().toVector(), unitVector, i.getRange()); - if (r != null && checkFinite(r.getHitPosition())) { - inTeleport.add(p.getUniqueId()); - Location targetPos = r.getHitPosition().toLocation(p.getWorld(), p.getLocation().getYaw(), p.getLocation().getPitch()); - - if (!e.getPlayer().isFlying() && addon.getSettings().isReturnTeleportBlock() - && !addon.getIslands().isSafeLocation(targetPos)) { - switch (targetPos.getWorld().getEnvironment()) { - case NETHER: - targetPos.getBlock().getRelative(BlockFace.DOWN).setType(Material.NETHERRACK); - break; - case THE_END: - targetPos.getBlock().getRelative(BlockFace.DOWN).setType(Material.END_STONE); - break; - default: - targetPos.getBlock().getRelative(BlockFace.DOWN).setType(Material.STONE); - break; - } - } - Util.teleportAsync(p, targetPos).thenRun(() -> inTeleport.remove(p.getUniqueId())); - } - }); - } - - public boolean checkFinite(Vector toCheck) { - return NumberConversions.isFinite(toCheck.getX()) && NumberConversions.isFinite(toCheck.getY()) - && NumberConversions.isFinite(toCheck.getZ()); - } - - /** - * Check if the player is outside the island protection zone that they are supposed to be in. - * @param player - player moving - * @param from - from location - * @param to - to location - * @return true if outside the island protection zone - */ - private boolean outsideCheck(Player player, Location from, Location to) { - User user = Objects.requireNonNull(User.getInstance(player)); - - if ((from.getWorld() != null && from.getWorld().equals(to.getWorld()) - && from.toVector().multiply(XZ).equals(to.toVector().multiply(XZ))) - || !addon.inGameWorld(player.getWorld()) - || user.getPlayer().getGameMode() == GameMode.SPECTATOR - // || !addon.getIslands().getIslandAt(to).filter(i -> addon.getIslands().locationIsOnIsland(player, i.getProtectionCenter())).isPresent() - || !user.getMetaData(BorderShower.BORDER_STATE_META_DATA).map(MetaDataValue::asBoolean).orElse(addon.getSettings().isShowByDefault())) { - return false; - } - return addon.getIslands().getIslandAt(to).filter(i -> !i.onIsland(to)).isPresent(); - } - - /** - * Runs a task while the player is mounting an entity and eject - * if the entity went outside the protection range - * @param event - event - */ - @EventHandler - public void onEntityMount(EntityMountEvent event) { - Entity entity = event.getEntity(); - if (!(entity instanceof Player player)) { - return; - } - - mountedPlayers.put(player, Bukkit.getScheduler().runTaskTimer(addon.getPlugin(), () -> { - Location loc = player.getLocation(); - - if (!addon.inGameWorld(loc.getWorld())) { - return; - } - // Eject from mount if outside the protection range - if (addon.getIslands().getProtectedIslandAt(loc).isEmpty()) { - // Force the dismount event for custom entities - if (!event.getMount().eject()) { - var dismountEvent = new EntityDismountEvent(player, event.getMount()); - Bukkit.getPluginManager().callEvent(dismountEvent); - } - } - }, 1, 20)); - } - - /** - * Cancel the running task if the player was mounting an entity - * @param event - event - */ - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onEntityDismount(EntityDismountEvent event) { - Entity entity = event.getEntity(); - if (!(entity instanceof Player player)) { - return; - } - - BukkitTask task = mountedPlayers.get(player); - if (task == null) { - return; - } - - task.cancel(); - mountedPlayers.remove(player); - } - - - /** - * Refreshes the barrier view when the player moves (more than just moving their head) - * @param e event - */ - @EventHandler(priority = EventPriority.NORMAL) - public void onPlayerMove(PlayerMoveEvent e) { - // Remove head movement - if (!e.getFrom().toVector().equals(e.getTo().toVector())) { - addon.getIslands() - .getIslandAt(e.getPlayer().getLocation()) - .ifPresent(i -> show.refreshView(User.getInstance(e.getPlayer()), i)); - } - } - - /** - * Refresh the view when riding in a vehicle - * @param e event - */ - @EventHandler(priority = EventPriority.NORMAL) - public void onVehicleMove(VehicleMoveEvent e) { - // Remove head movement - if (!e.getFrom().toVector().equals(e.getTo().toVector())) { - e.getVehicle().getPassengers().stream() - .filter(Player.class::isInstance) - .map(Player.class::cast) - .forEach(p -> addon - .getIslands() - .getIslandAt(p.getLocation()) - .ifPresent(i -> show.refreshView(User.getInstance(p), i))); - } - } - - /** - * Hide and then show the border to react to the change in protection area - * @param e - */ - @EventHandler(priority = EventPriority.NORMAL) - public void onProtectionRangeChange(IslandProtectionRangeChangeEvent e) { - // Hide and show again - e.getIsland().getPlayersOnIsland().forEach(player -> { - show.hideBorder(User.getInstance(player)); - show.showBorder(player, e.getIsland()); - }); - } -} diff --git a/src/main/java/world/bentobox/border/listeners/PlayerListener.java b/src/main/java/world/bentobox/border/listeners/PlayerListener.java index b62d066..1258bfb 100644 --- a/src/main/java/world/bentobox/border/listeners/PlayerListener.java +++ b/src/main/java/world/bentobox/border/listeners/PlayerListener.java @@ -60,11 +60,19 @@ public PlayerListener(Border addon) { @EventHandler(priority = EventPriority.NORMAL) public void onPlayerJoin(PlayerJoinEvent e) { - // Run one-tick after joining because meta data cannot be set otherwise - Bukkit.getScheduler().runTask(addon.getPlugin(), () -> processEvent(e)); + Player player = e.getPlayer(); + if (isOn(player)) { + // Run one-tick after joining because meta data cannot be set otherwise + Bukkit.getScheduler().runTask(addon.getPlugin(), () -> processEvent(e)); + } } protected void processEvent(PlayerJoinEvent e) { + Player player = e.getPlayer(); + if (!isOn(player)) { + return; + } + User user = User.getInstance(e.getPlayer()); show.hideBorder(user); @@ -97,11 +105,19 @@ public void onPlayerQuit(PlayerQuitEvent e) { @EventHandler(priority = EventPriority.NORMAL) public void onPlayerRespawn(PlayerRespawnEvent e) { - show.clearUser(User.getInstance(e.getPlayer())); - Bukkit.getScheduler().runTask(addon.getPlugin(), () -> addon.getIslands().getIslandAt(e.getPlayer().getLocation()).ifPresent(i -> - show.showBorder(e.getPlayer(), i))); + Player player = e.getPlayer(); + if (isOn(player)) { + show.clearUser(User.getInstance(e.getPlayer())); + Bukkit.getScheduler().runTask(addon.getPlugin(), () -> addon.getIslands() + .getIslandAt(e.getPlayer().getLocation()).ifPresent(i -> show.showBorder(e.getPlayer(), i))); + } } + /** + * Check if the border is on or off + * @param player player + * @return true if the border is on, false if not + */ private boolean isOn(Player player) { // Check if border is off User user = User.getInstance(player); @@ -236,7 +252,7 @@ private boolean outsideCheck(Player player, Location from, Location to) { @EventHandler public void onEntityMount(EntityMountEvent event) { Entity entity = event.getEntity(); - if (!(entity instanceof Player player)) { + if (!(entity instanceof Player player) || !isOn(player)) { return; } @@ -268,13 +284,15 @@ public void onEntityDismount(EntityDismountEvent event) { return; } - BukkitTask task = mountedPlayers.get(player); - if (task == null) { - return; - } + if (isOn(player)) { + BukkitTask task = mountedPlayers.get(player); + if (task == null) { + return; + } - task.cancel(); - mountedPlayers.remove(player); + task.cancel(); + mountedPlayers.remove(player); + } } @@ -284,8 +302,9 @@ public void onEntityDismount(EntityDismountEvent event) { */ @EventHandler(priority = EventPriority.NORMAL) public void onPlayerMove(PlayerMoveEvent e) { + Player player = e.getPlayer(); // Remove head movement - if (!e.getFrom().toVector().equals(e.getTo().toVector())) { + if (isOn(player) && !e.getFrom().toVector().equals(e.getTo().toVector())) { addon.getIslands() .getIslandAt(e.getPlayer().getLocation()) .ifPresent(i -> show.refreshView(User.getInstance(e.getPlayer()), i)); @@ -300,13 +319,9 @@ public void onPlayerMove(PlayerMoveEvent e) { public void onVehicleMove(VehicleMoveEvent e) { // Remove head movement if (!e.getFrom().toVector().equals(e.getTo().toVector())) { - e.getVehicle().getPassengers().stream() - .filter(Player.class::isInstance) - .map(Player.class::cast) - .forEach(p -> addon - .getIslands() - .getIslandAt(p.getLocation()) - .ifPresent(i -> show.refreshView(User.getInstance(p), i))); + e.getVehicle().getPassengers().stream().filter(Player.class::isInstance).map(Player.class::cast) + .filter(this::isOn).forEach(p -> addon.getIslands().getIslandAt(p.getLocation()) + .ifPresent(i -> show.refreshView(User.getInstance(p), i))); } } @@ -316,10 +331,14 @@ public void onVehicleMove(VehicleMoveEvent e) { */ @EventHandler(priority = EventPriority.NORMAL) public void onProtectionRangeChange(IslandProtectionRangeChangeEvent e) { + // Get default game mode + GameMode gm = this.addon.getPlugin().getIWM().getDefaultGameMode(e.getIsland().getWorld()); // Hide and show again e.getIsland().getPlayersOnIsland().forEach(player -> { - show.hideBorder(User.getInstance(player)); - show.showBorder(player, e.getIsland()); + if (isOn(player)) { + show.hideBorder(User.getInstance(player)); + show.showBorder(player, e.getIsland()); + } }); } }