11package world .bentobox .border .listeners ;
22
33import java .util .HashSet ;
4+ import java .util .HashMap ;
5+ import java .util .Map ;
46import java .util .Objects ;
57import java .util .Optional ;
68import java .util .Set ;
1113import org .bukkit .Location ;
1214import org .bukkit .Material ;
1315import org .bukkit .block .BlockFace ;
16+ import org .bukkit .entity .Entity ;
1417import org .bukkit .entity .Player ;
1518import org .bukkit .event .EventHandler ;
1619import org .bukkit .event .EventPriority ;
2225import org .bukkit .event .player .PlayerTeleportEvent ;
2326import org .bukkit .event .player .PlayerTeleportEvent .TeleportCause ;
2427import org .bukkit .event .vehicle .VehicleMoveEvent ;
28+ import org .bukkit .scheduler .BukkitTask ;
29+ import org .bukkit .util .NumberConversions ;
2530import org .bukkit .util .RayTraceResult ;
2631import org .bukkit .util .Vector ;
2732
33+ import org .spigotmc .event .entity .EntityDismountEvent ;
34+ import org .spigotmc .event .entity .EntityMountEvent ;
2835import world .bentobox .bentobox .api .events .island .IslandProtectionRangeChangeEvent ;
2936import world .bentobox .bentobox .api .flags .Flag ;
3037import world .bentobox .bentobox .api .metadata .MetaDataValue ;
@@ -44,6 +51,7 @@ public class PlayerListener implements Listener {
4451 private final Border addon ;
4552 private Set <UUID > inTeleport ;
4653 private final BorderShower show ;
54+ private Map <Player , BukkitTask > mountedPlayers = new HashMap <>();
4755
4856 public PlayerListener (Border addon ) {
4957 this .addon = addon ;
@@ -64,17 +72,19 @@ protected void processEvent(PlayerJoinEvent e) {
6472 // Just for sure, disable world Border
6573 user .getPlayer ().setWorldBorder (null );
6674
67- // Check player perms and return to defaults if players don't have them
68- if (!e .getPlayer ().hasPermission (addon .getPermissionPrefix () + IslandBorderCommand .BORDER_COMMAND_PERM )) {
69- // Restore barrier on/off to default
70- user .putMetaData (BorderShower .BORDER_STATE_META_DATA , new MetaDataValue (addon .getSettings ().isShowByDefault ()));
71-
72- if (!e .getPlayer ().hasPermission (addon .getPermissionPrefix () + BorderTypeCommand .BORDER_TYPE_COMMAND_PERM )) {
75+ // Get the game mode that this player is in
76+ addon .getPlugin ().getIWM ().getAddon (e .getPlayer ().getWorld ()).map (gma -> gma .getPermissionPrefix ()).filter (
77+ permPrefix -> !e .getPlayer ().hasPermission (permPrefix + IslandBorderCommand .BORDER_COMMAND_PERM ))
78+ .ifPresent (permPrefix -> {
79+ // Restore barrier on/off to default
80+ user .putMetaData (BorderShower .BORDER_STATE_META_DATA ,
81+ new MetaDataValue (addon .getSettings ().isShowByDefault ()));
82+ if (!e .getPlayer ().hasPermission (permPrefix + BorderTypeCommand .BORDER_TYPE_COMMAND_PERM )) {
7383 // Restore default barrier type to player
7484 MetaDataValue metaDataValue = new MetaDataValue (addon .getSettings ().getType ().getId ());
7585 user .putMetaData (PerPlayerBorderProxy .BORDER_BORDERTYPE_META_DATA , metaDataValue );
7686 }
77- }
87+ });
7888
7989 // Show the border if required one tick after
8090 Bukkit .getScheduler ().runTask (addon .getPlugin (), () -> addon .getIslands ().getIslandAt (e .getPlayer ().getLocation ()).ifPresent (i ->
@@ -151,10 +161,15 @@ public void onPlayerLeaveIsland(PlayerMoveEvent e) {
151161 addon .getIslands ().getIslandAt (p .getLocation ()).ifPresent (i -> {
152162 Vector unitVector = i .getProtectionCenter ().toVector ().subtract (p .getLocation ().toVector ()).normalize ()
153163 .multiply (new Vector (1 ,0 ,1 ));
164+ if (unitVector .lengthSquared () <= 0D ) {
165+ // Direction is zero, so nothing to do; cannot move.
166+ return ;
167+ }
154168 RayTraceResult r = i .getProtectionBoundingBox ().rayTrace (p .getLocation ().toVector (), unitVector , i .getRange ());
155- if (r != null ) {
169+ if (r != null && checkFinite ( r . getHitPosition ()) ) {
156170 inTeleport .add (p .getUniqueId ());
157171 Location targetPos = r .getHitPosition ().toLocation (p .getWorld (), p .getLocation ().getYaw (), p .getLocation ().getPitch ());
172+
158173 if (!e .getPlayer ().isFlying () && addon .getSettings ().isReturnTeleportBlock ()
159174 && !addon .getIslands ().isSafeLocation (targetPos )) {
160175 switch (targetPos .getWorld ().getEnvironment ()) {
@@ -174,6 +189,11 @@ public void onPlayerLeaveIsland(PlayerMoveEvent e) {
174189 });
175190 }
176191
192+ public boolean checkFinite (Vector toCheck ) {
193+ return NumberConversions .isFinite (toCheck .getX ()) && NumberConversions .isFinite (toCheck .getY ())
194+ && NumberConversions .isFinite (toCheck .getZ ());
195+ }
196+
177197 /**
178198 * Check if the player is outside the island protection zone that they are supposed to be in.
179199 * @param player - player moving
@@ -195,6 +215,56 @@ private boolean outsideCheck(Player player, Location from, Location to) {
195215 return addon .getIslands ().getIslandAt (to ).filter (i -> !i .onIsland (to )).isPresent ();
196216 }
197217
218+ /**
219+ * Runs a task while the player is mounting an entity and eject
220+ * if the entity went outside the protection range
221+ * @param event - event
222+ */
223+ @ EventHandler
224+ public void onEntityMount (EntityMountEvent event ) {
225+ Entity entity = event .getEntity ();
226+ if (!(entity instanceof Player player )) {
227+ return ;
228+ }
229+
230+ mountedPlayers .put (player , Bukkit .getScheduler ().runTaskTimer (addon .getPlugin (), () -> {
231+ Location loc = player .getLocation ();
232+
233+ if (!addon .inGameWorld (loc .getWorld ())) {
234+ return ;
235+ }
236+ // Eject from mount if outside the protection range
237+ if (addon .getIslands ().getProtectedIslandAt (loc ).isEmpty ()) {
238+ // Force the dismount event for custom entities
239+ if (!event .getMount ().eject ()) {
240+ var dismountEvent = new EntityDismountEvent (player , event .getMount ());
241+ Bukkit .getPluginManager ().callEvent (dismountEvent );
242+ }
243+ }
244+ }, 1 , 20 ));
245+ }
246+
247+ /**
248+ * Cancel the running task if the player was mounting an entity
249+ * @param event - event
250+ */
251+ @ EventHandler (priority = EventPriority .NORMAL , ignoreCancelled = true )
252+ public void onEntityDismount (EntityDismountEvent event ) {
253+ Entity entity = event .getEntity ();
254+ if (!(entity instanceof Player player )) {
255+ return ;
256+ }
257+
258+ BukkitTask task = mountedPlayers .get (player );
259+ if (task == null ) {
260+ return ;
261+ }
262+
263+ task .cancel ();
264+ mountedPlayers .remove (player );
265+ }
266+
267+
198268 /**
199269 * Refreshes the barrier view when the player moves (more than just moving their head)
200270 * @param e event
0 commit comments