Improve portal search radius.

* Fix portal search radius not respected after travel agent removed.
* Set portal search radius for entity entering portals.
This commit is contained in:
Ben Woo 2021-04-26 22:52:24 +08:00
parent 29617059b3
commit 3bb8de6d33
3 changed files with 97 additions and 31 deletions

View File

@ -11,6 +11,7 @@ import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.api.MultiverseWorld;
import com.onarandombox.MultiverseCore.utils.CompatibilityLayer;
import org.bukkit.World;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
@ -18,6 +19,7 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
import org.bukkit.event.entity.EntityPortalEvent;
import org.bukkit.event.entity.EntityRegainHealthEvent;
import org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason;
import org.bukkit.event.entity.FoodLevelChangeEvent;
@ -107,4 +109,17 @@ public class MVEntityListener implements Listener {
event.setCancelled(this.plugin.getMVWorldManager().getTheWorldPurger().shouldWeKillThisCreature(mvworld, event.getEntity()));
}
/**
* Handles portal search radius adjustment.
* @param event The Event that was fired.
*/
@EventHandler
public void entityPortal(EntityPortalEvent event) {
if (event.isCancelled() || event.getTo() == null) {
return;
}
if (!this.plugin.getMVConfig().isUsingDefaultPortalSearch()) {
CompatibilityLayer.setPortalSearchRadius(event, this.plugin.getMVConfig().getPortalSearchRadius());
}
}
}

View File

@ -7,10 +7,6 @@
package com.onarandombox.MultiverseCore.listeners;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
@ -35,6 +31,9 @@ import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.player.PlayerRespawnEvent;
import org.bukkit.event.player.PlayerTeleportEvent;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* Multiverse's {@link Listener} for players.
*/
@ -313,16 +312,8 @@ public class MVPlayerListener implements Listener {
+ "' was allowed to go to '" + event.getTo().getWorld().getName()
+ "' because enforceaccess is off.");
}
if (!plugin.getMVConfig().isUsingDefaultPortalSearch()) {
try {
Class.forName("org.bukkit.TravelAgent");
if (event.getPortalTravelAgent() != null) {
event.getPortalTravelAgent().setSearchRadius(plugin.getMVConfig().getPortalSearchRadius());
}
} catch (ClassNotFoundException ignore) {
Logging.fine("TravelAgent not available for PlayerPortalEvent for " + event.getPlayer().getName());
}
if (!this.plugin.getMVConfig().isUsingDefaultPortalSearch()) {
CompatibilityLayer.setPortalSearchRadius(event, this.plugin.getMVConfig().getPortalSearchRadius());
}
}

View File

@ -1,32 +1,35 @@
package com.onarandombox.MultiverseCore.utils;
import com.dumptruckman.minecraft.util.Logging;
import org.bukkit.Bukkit;
import org.bukkit.event.entity.EntityPortalEvent;
import org.bukkit.event.player.PlayerPortalEvent;
import org.bukkit.event.player.PlayerRespawnEvent;
import java.lang.reflect.Method;
/**
* A utility class to enable version specific minecraft features.
* Utility class to enable version specific minecraft features.
*/
public class CompatibilityLayer {
private static Method checkAnchorSpawn;
private static boolean useTravelAgent;
private static Method playerPortalSearchRadius;
private static Method entityPortalSearchRadius;
/**
* Initialise the reflection methods.
* Initialise the reflection class, methods and fields.
*/
public static void init() {
try {
checkAnchorSpawn = PlayerRespawnEvent.class.getDeclaredMethod("isAnchorSpawn");
} catch (NoSuchMethodException e) {
Logging.fine("%s does not support respawn anchors.", Bukkit.getVersion());
}
checkAnchorSpawn = ReflectHelper.getMethod(PlayerRespawnEvent.class, "isAnchorSpawn");
useTravelAgent = ReflectHelper.hasClass("org.bukkit.TravelAgent");
playerPortalSearchRadius = ReflectHelper.getMethod(PlayerPortalEvent.class, "setSearchRadius", int.class);
entityPortalSearchRadius = ReflectHelper.getMethod(EntityPortalEvent.class, "setSearchRadius", int.class);
}
/**
* Check if the respawn point is of respawn anchor type.
* Introduced in minecraft 1.16
* <p>Check if the respawn point is of respawn anchor type.</p>
* <p>Introduced in minecraft 1.16</p>
*
* @param event A player respawn event.
* @return If the respawn location is an anchor point.
@ -35,12 +38,69 @@ public class CompatibilityLayer {
if (checkAnchorSpawn == null) {
return false;
}
try {
return (boolean) checkAnchorSpawn.invoke(event);
} catch (Exception e) {
Logging.warning("Error checking for: %s", checkAnchorSpawn);
e.printStackTrace();
Boolean result = ReflectHelper.invokeMethod(event, checkAnchorSpawn);
if (result == null) {
Logging.warning("Unable to check if spawning at respawn anchor!");
return false;
}
return false;
return result;
}
}
/**
* <p>Gets if Travel Agent is supported on the server's minecraft version.</p>
* <p>Removed in minecraft 1.14</p>
*
* @return True if Travel Agent is supported, else false.
*/
public static boolean isUseTravelAgent() {
return useTravelAgent;
}
/**
* <p>Sets search radius for a PlayerPortalEvent.</p>
*
* <p>Use travel agent if available, else using new PlayerPortalEvent.setSearchRadius(int) method
* introduced in minecraft 1.15</p>
*
* @param event A Player Portal Event.
* @param searchRadius Target search radius to set to.
*/
public static void setPortalSearchRadius(PlayerPortalEvent event, int searchRadius) {
if (useTravelAgent) {
event.getPortalTravelAgent().setSearchRadius(searchRadius);
event.useTravelAgent(true);
Logging.finer("Used travel agent to set player portal search radius.");
return;
}
if (playerPortalSearchRadius == null) {
Logging.warning("Unable to set player portal search radius!");
return;
}
ReflectHelper.invokeMethod(event, playerPortalSearchRadius, searchRadius);
Logging.finer("Used new method to set player portal search radius.");
}
/**
* <p>Sets search radius for a EntityPortalEvent.</p>
*
* <p>Use travel agent if available, else using new EntityPortalEvent.setSearchRadius(int) method
* introduced in minecraft 1.15</p>
*
* @param event A Entity Portal Event.
* @param searchRadius Target search radius to set to.
*/
public static void setPortalSearchRadius(EntityPortalEvent event, int searchRadius) {
if (useTravelAgent) {
event.getPortalTravelAgent().setSearchRadius(searchRadius);
event.useTravelAgent(true);
Logging.finer("Used travel agent to set entity portal search radius.");
return;
}
if (entityPortalSearchRadius == null) {
Logging.warning("Unable to set entity portal search radius!");
return;
}
ReflectHelper.invokeMethod(event, entityPortalSearchRadius, searchRadius);
Logging.finer("Used new method to set entity portal search radius.");
}
}