Remove/consolidate some NMS usage

This commit is contained in:
fullwall 2012-12-07 23:04:31 +08:00
parent b23bd701cb
commit 159037ad69
10 changed files with 127 additions and 116 deletions

View File

@ -31,28 +31,22 @@ import net.citizensnpcs.command.command.ScriptCommands;
import net.citizensnpcs.command.command.TemplateCommands; import net.citizensnpcs.command.command.TemplateCommands;
import net.citizensnpcs.command.command.TraitCommands; import net.citizensnpcs.command.command.TraitCommands;
import net.citizensnpcs.command.command.WaypointCommands; import net.citizensnpcs.command.command.WaypointCommands;
import net.citizensnpcs.command.exception.CommandException;
import net.citizensnpcs.command.exception.CommandUsageException;
import net.citizensnpcs.command.exception.ServerCommandException;
import net.citizensnpcs.command.exception.UnhandledCommandException;
import net.citizensnpcs.command.exception.WrappedCommandException;
import net.citizensnpcs.editor.Editor; import net.citizensnpcs.editor.Editor;
import net.citizensnpcs.npc.CitizensNPCRegistry; import net.citizensnpcs.npc.CitizensNPCRegistry;
import net.citizensnpcs.npc.CitizensTraitFactory; import net.citizensnpcs.npc.CitizensTraitFactory;
import net.citizensnpcs.npc.NPCSelector; import net.citizensnpcs.npc.NPCSelector;
import net.citizensnpcs.util.Messages; import net.citizensnpcs.util.Messages;
import net.citizensnpcs.util.Messaging; import net.citizensnpcs.util.Messaging;
import net.citizensnpcs.util.NMS;
import net.citizensnpcs.util.StringHelper; import net.citizensnpcs.util.StringHelper;
import net.citizensnpcs.util.Util;
import net.milkbowl.vault.economy.Economy; import net.milkbowl.vault.economy.Economy;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.craftbukkit.v1_4_5.CraftServer;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginLoadOrder;
import org.bukkit.plugin.RegisteredServiceProvider; import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
@ -108,7 +102,7 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
ex.printStackTrace(); ex.printStackTrace();
} }
} }
((CraftServer) Bukkit.getServer()).enablePlugins(PluginLoadOrder.POSTWORLD); NMS.loadPlugins();
} }
public CommandInfo getCommandInfo(String rootCommand, String modifier) { public CommandInfo getCommandInfo(String rootCommand, String modifier) {
@ -140,40 +134,17 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
@Override @Override
public boolean onCommand(CommandSender sender, Command command, String cmdName, String[] args) { public boolean onCommand(CommandSender sender, Command command, String cmdName, String[] args) {
try { String modifier = args.length > 0 ? args[0] : "";
String modifier = args.length > 0 ? args[0] : ""; if (!commands.hasCommand(command, modifier) && !modifier.isEmpty()) {
if (!commands.hasCommand(command, modifier) && !modifier.isEmpty()) { return suggestClosestModifier(sender, command.getName(), modifier);
return suggestClosestModifier(sender, command.getName().toLowerCase(), modifier);
}
NPC npc = selector.getSelected(sender);
// TODO: change the args supplied to a context style system for
// flexibility (ie. adding more context in the future without
// changing everything)
try {
commands.execute(command, args, sender, sender, npc);
} catch (ServerCommandException ex) {
Messaging.sendTr(sender, Messages.COMMAND_MUST_BE_INGAME);
} catch (CommandUsageException ex) {
Messaging.sendError(sender, ex.getMessage());
Messaging.sendError(sender, ex.getUsage());
} catch (WrappedCommandException ex) {
throw ex.getCause();
} catch (UnhandledCommandException ex) {
return false;
} catch (CommandException ex) {
Messaging.sendError(sender, ex.getMessage());
}
} catch (NumberFormatException ex) {
Messaging.sendErrorTr(sender, Messages.COMMAND_INVALID_NUMBER);
} catch (Throwable ex) {
ex.printStackTrace();
if (sender instanceof Player) {
Messaging.sendErrorTr(sender, Messages.COMMAND_REPORT_ERROR);
Messaging.sendError(sender, ex.getClass().getName() + ": " + ex.getMessage());
}
} }
return true;
NPC npc = selector.getSelected(sender);
// TODO: change the args supplied to a context style system for
// flexibility (ie. adding more context in the future without
// changing everything)
return commands.executeSafe(command, args, sender, sender, npc);
} }
@Override @Override
@ -196,7 +167,7 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
public void onEnable() { public void onEnable() {
CitizensAPI.setImplementation(this); CitizensAPI.setImplementation(this);
// Disable if the server is not using the compatible Minecraft version // Disable if the server is not using the compatible Minecraft version
String mcVersion = ((CraftServer) getServer()).getServer().getVersion(); String mcVersion = Util.getMinecraftVersion();
compatible = mcVersion.startsWith(COMPATIBLE_MC_VERSION); compatible = mcVersion.startsWith(COMPATIBLE_MC_VERSION);
if (!compatible) { if (!compatible) {
Messaging.severeTr(Messages.CITIZENS_INCOMPATIBLE, getDescription().getVersion(), mcVersion); Messaging.severeTr(Messages.CITIZENS_INCOMPATIBLE, getDescription().getVersion(), mcVersion);

View File

@ -21,6 +21,7 @@ import net.citizensnpcs.command.exception.ServerCommandException;
import net.citizensnpcs.command.exception.UnhandledCommandException; import net.citizensnpcs.command.exception.UnhandledCommandException;
import net.citizensnpcs.command.exception.WrappedCommandException; import net.citizensnpcs.command.exception.WrappedCommandException;
import net.citizensnpcs.util.Messages; import net.citizensnpcs.util.Messages;
import net.citizensnpcs.util.Messaging;
import net.citizensnpcs.util.StringHelper; import net.citizensnpcs.util.StringHelper;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
@ -86,11 +87,11 @@ public class CommandManager {
Object[] newMethodArgs = new Object[methodArgs.length + 1]; Object[] newMethodArgs = new Object[methodArgs.length + 1];
System.arraycopy(methodArgs, 0, newMethodArgs, 1, methodArgs.length); System.arraycopy(methodArgs, 0, newMethodArgs, 1, methodArgs.length);
executeMethod(null, newArgs, sender, newMethodArgs); executeMethod(newArgs, sender, newMethodArgs);
} }
// Attempt to execute a command. // Attempt to execute a command.
private void executeMethod(Method parent, String[] args, CommandSender sender, Object[] methodArgs) private void executeMethod(String[] args, CommandSender sender, Object[] methodArgs)
throws CommandException { throws CommandException {
String cmdName = args[0]; String cmdName = args[0];
String modifier = args.length > 1 ? args[1] : ""; String modifier = args.length > 1 ? args[1] : "";
@ -99,7 +100,7 @@ public class CommandManager {
if (method == null) if (method == null)
method = commands.get(cmdName.toLowerCase() + " *"); method = commands.get(cmdName.toLowerCase() + " *");
if (method == null && parent == null) if (method == null)
throw new UnhandledCommandException(); throw new UnhandledCommandException();
if (!serverCommands.contains(method) && sender instanceof ConsoleCommandSender) if (!serverCommands.contains(method) && sender instanceof ConsoleCommandSender)
@ -140,11 +141,47 @@ public class CommandManager {
} catch (InvocationTargetException e) { } catch (InvocationTargetException e) {
if (e.getCause() instanceof CommandException) if (e.getCause() instanceof CommandException)
throw (CommandException) e.getCause(); throw (CommandException) e.getCause();
throw new WrappedCommandException(e.getCause()); throw new WrappedCommandException(e.getCause());
} }
} }
/**
* A safe version of <code>execute</code> which catches and logs all errors
* that occur. Returns whether the command handler should print usage or
* not.
*
* @see #execute(Command, String[], CommandSender, Object...)
* @return Whether further usage should be printed
*/
public boolean executeSafe(org.bukkit.command.Command command, String[] args, CommandSender sender,
Object... methodArgs) {
try {
try {
execute(command, args, sender, methodArgs);
} catch (ServerCommandException ex) {
Messaging.sendTr(sender, Messages.COMMAND_MUST_BE_INGAME);
} catch (CommandUsageException ex) {
Messaging.sendError(sender, ex.getMessage());
Messaging.sendError(sender, ex.getUsage());
} catch (UnhandledCommandException ex) {
return false;
} catch (WrappedCommandException ex) {
throw ex.getCause();
} catch (CommandException ex) {
Messaging.sendError(sender, ex.getMessage());
} catch (NumberFormatException ex) {
Messaging.sendErrorTr(sender, Messages.COMMAND_INVALID_NUMBER);
}
} catch (Throwable ex) {
ex.printStackTrace();
if (sender instanceof Player) {
Messaging.sendErrorTr(sender, Messages.COMMAND_REPORT_ERROR);
Messaging.sendError(sender, ex.getClass().getName() + ": " + ex.getMessage());
}
}
return true;
}
/** /**
* Searches for the closest modifier using Levenshtein distance to the given * Searches for the closest modifier using Levenshtein distance to the given
* top level command and modifier. * top level command and modifier.

View File

@ -1,11 +1,11 @@
package net.citizensnpcs.npc; package net.citizensnpcs.npc;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.util.Arrays;
import java.util.Map; import java.util.Map;
import net.citizensnpcs.api.npc.NPC; import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.util.NMS; import net.citizensnpcs.util.NMS;
import net.minecraft.server.v1_4_5.Block;
import net.minecraft.server.v1_4_5.EntityLiving; import net.minecraft.server.v1_4_5.EntityLiving;
import net.minecraft.server.v1_4_5.World; import net.minecraft.server.v1_4_5.World;
@ -16,18 +16,19 @@ import org.bukkit.craftbukkit.v1_4_5.CraftWorld;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
public abstract class CitizensMobNPC extends CitizensNPC { public abstract class CitizensMobNPC extends CitizensNPC {
private final Constructor<? extends EntityLiving> constructor; private final Constructor<?> constructor;
protected CitizensMobNPC(int id, String name, Class<? extends EntityLiving> clazz) { protected CitizensMobNPC(int id, String name, Class<?> clazz) {
super(id, name); super(id, name);
this.constructor = getConstructor(clazz); this.constructor = getConstructor(clazz);
NMS.registerEntityClass(clazz); NMS.registerEntityClass(clazz);
} }
private EntityLiving createEntityFromClass(World world) { private EntityLiving createEntityFromClass(Object... args) {
try { try {
return constructor.newInstance(world, this); Object[] newArgs = Arrays.copyOf(args, args.length + 1);
newArgs[args.length] = this;
return (EntityLiving) constructor.newInstance(newArgs);
} catch (Exception ex) { } catch (Exception ex) {
ex.printStackTrace(); ex.printStackTrace();
return null; return null;
@ -42,20 +43,15 @@ public abstract class CitizensMobNPC extends CitizensNPC {
// entity.onGround isn't updated right away - we approximate here so // entity.onGround isn't updated right away - we approximate here so
// that things like pathfinding still work *immediately* after spawn. // that things like pathfinding still work *immediately* after spawn.
org.bukkit.Material beneath = loc.getBlock().getRelative(BlockFace.DOWN).getType(); org.bukkit.Material beneath = loc.getBlock().getRelative(BlockFace.DOWN).getType();
if (beneath.isBlock()) { if (beneath.isBlock())
Block block = Block.byId[beneath.getId()]; entity.onGround = true;
if (block != null && block.material != null) {
entity.onGround = block.material.isSolid();
}
}
return entity; return entity;
} }
private static final Map<Class<? extends EntityLiving>, Constructor<? extends EntityLiving>> CONSTRUCTOR_CACHE = Maps private static final Map<Class<?>, Constructor<?>> CONSTRUCTOR_CACHE = Maps.newHashMap();
.newHashMap();
private static Constructor<? extends EntityLiving> getConstructor(Class<? extends EntityLiving> clazz) { private static Constructor<?> getConstructor(Class<?> clazz) {
Constructor<? extends EntityLiving> constructor = CONSTRUCTOR_CACHE.get(clazz); Constructor<?> constructor = CONSTRUCTOR_CACHE.get(clazz);
if (constructor != null) if (constructor != null)
return constructor; return constructor;
try { try {

View File

@ -75,9 +75,9 @@ public abstract class CitizensNPC extends AbstractNPC {
@Override @Override
public LivingEntity getBukkitEntity() { public LivingEntity getBukkitEntity() {
if (getHandle() == null) if (mcEntity == null)
return null; return null;
return (LivingEntity) getHandle().getBukkitEntity(); return (LivingEntity) mcEntity.getBukkitEntity();
} }
public EntityLiving getHandle() { public EntityLiving getHandle() {
@ -221,7 +221,7 @@ public abstract class CitizensNPC extends AbstractNPC {
try { try {
super.update(); super.update();
if (isSpawned()) { if (isSpawned()) {
NMS.trySwim(getHandle()); NMS.trySwim(getBukkitEntity());
navigator.run(); navigator.run();
} }
} catch (Exception ex) { } catch (Exception ex) {

View File

@ -51,13 +51,13 @@ public class AStarNavigationStrategy extends AbstractPathStrategy {
return true; return true;
if (plan == null || plan.isComplete()) if (plan == null || plan.isComplete())
return true; return true;
if (NMS.distanceSquared(npc.getHandle(), vector) <= params.distanceMargin()) { if (npc.getBukkitEntity().getVelocity().distanceSquared(vector) <= params.distanceMargin()) {
plan.update(npc); plan.update(npc);
if (plan.isComplete()) if (plan.isComplete())
return true; return true;
vector = plan.getCurrentVector(); vector = plan.getCurrentVector();
} }
npc.getHandle().getControllerMove().a(vector.getX(), vector.getY(), vector.getZ(), params.speed()); NMS.setDestination(npc.getBukkitEntity(), vector.getX(), vector.getY(), vector.getZ(), params.speed());
return false; return false;
} }

View File

@ -17,7 +17,6 @@ import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.util.DataKey; import net.citizensnpcs.api.util.DataKey;
import net.citizensnpcs.npc.CitizensNPC; import net.citizensnpcs.npc.CitizensNPC;
import net.citizensnpcs.util.NMS; import net.citizensnpcs.util.NMS;
import net.minecraft.server.v1_4_5.EntityLiving;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
@ -34,7 +33,6 @@ public class CitizensNavigator implements Navigator, Runnable {
private NavigatorParameters localParams = defaultParams; private NavigatorParameters localParams = defaultParams;
private final CitizensNPC npc; private final CitizensNPC npc;
private int stationaryTicks; private int stationaryTicks;
private boolean updatedAvoidWater = false;
public CitizensNavigator(CitizensNPC npc) { public CitizensNavigator(CitizensNPC npc) {
this.npc = npc; this.npc = npc;
@ -100,11 +98,6 @@ public class CitizensNavigator implements Navigator, Runnable {
if (defaultParams.baseSpeed() == UNINITIALISED_SPEED) if (defaultParams.baseSpeed() == UNINITIALISED_SPEED)
defaultParams.baseSpeed(NMS.getSpeedFor(npc)); defaultParams.baseSpeed(NMS.getSpeedFor(npc));
updatePathfindingRange(); updatePathfindingRange();
if (!updatedAvoidWater) {
boolean defaultAvoidWater = npc.getHandle().getNavigation().a();
defaultParams.avoidWater(defaultAvoidWater);
updatedAvoidWater = true;
}
} }
@Override @Override

View File

@ -3,28 +3,31 @@ package net.citizensnpcs.npc.ai;
import net.citizensnpcs.api.ai.NavigatorParameters; import net.citizensnpcs.api.ai.NavigatorParameters;
import net.citizensnpcs.api.ai.TargetType; import net.citizensnpcs.api.ai.TargetType;
import net.citizensnpcs.api.ai.event.CancelReason; import net.citizensnpcs.api.ai.event.CancelReason;
import net.citizensnpcs.npc.CitizensNPC; import net.citizensnpcs.api.npc.NPC;
import net.minecraft.server.v1_4_5.EntityPlayer; import net.minecraft.server.v1_4_5.EntityHuman;
import net.minecraft.server.v1_4_5.EntityLiving;
import net.minecraft.server.v1_4_5.Navigation; import net.minecraft.server.v1_4_5.Navigation;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.craftbukkit.v1_4_5.entity.CraftLivingEntity;
public class MCNavigationStrategy extends AbstractPathStrategy { public class MCNavigationStrategy extends AbstractPathStrategy {
private final Navigation navigation; private final Navigation navigation;
private final NavigatorParameters parameters; private final NavigatorParameters parameters;
private final Location target; private final Location target;
MCNavigationStrategy(final CitizensNPC npc, Location dest, NavigatorParameters params) { MCNavigationStrategy(final NPC npc, Location dest, NavigatorParameters params) {
super(TargetType.LOCATION); super(TargetType.LOCATION);
this.target = dest; this.target = dest;
this.parameters = params; this.parameters = params;
if (npc.getHandle() instanceof EntityPlayer) { EntityLiving handle = ((CraftLivingEntity) npc.getBukkitEntity()).getHandle();
npc.getHandle().onGround = true; if (handle instanceof EntityHuman) {
handle.onGround = true;
// not sure of a better way around this - if onGround is false, then // not sure of a better way around this - if onGround is false, then
// navigation won't execute, and calling entity.move doesn't // navigation won't execute, and calling entity.move doesn't
// entirely fix the problem. // entirely fix the problem.
} }
navigation = npc.getHandle().getNavigation(); navigation = handle.getNavigation();
navigation.a(parameters.avoidWater()); navigation.a(parameters.avoidWater());
navigation.a(dest.getX(), dest.getY(), dest.getZ(), parameters.speed()); navigation.a(dest.getX(), dest.getY(), dest.getZ(), parameters.speed());
if (navigation.f()) if (navigation.f())

View File

@ -5,7 +5,7 @@ import net.citizensnpcs.api.ai.EntityTarget;
import net.citizensnpcs.api.ai.NavigatorParameters; import net.citizensnpcs.api.ai.NavigatorParameters;
import net.citizensnpcs.api.ai.TargetType; import net.citizensnpcs.api.ai.TargetType;
import net.citizensnpcs.api.ai.event.CancelReason; import net.citizensnpcs.api.ai.event.CancelReason;
import net.citizensnpcs.npc.CitizensNPC; import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.util.NMS; import net.citizensnpcs.util.NMS;
import net.citizensnpcs.util.PlayerAnimation; import net.citizensnpcs.util.PlayerAnimation;
import net.minecraft.server.v1_4_5.EntityLiving; import net.minecraft.server.v1_4_5.EntityLiving;
@ -24,8 +24,8 @@ public class MCTargetStrategy implements PathStrategy, EntityTarget {
private final Navigation navigation; private final Navigation navigation;
private final NavigatorParameters parameters; private final NavigatorParameters parameters;
public MCTargetStrategy(CitizensNPC handle, LivingEntity target, boolean aggro, NavigatorParameters params) { public MCTargetStrategy(NPC handle, LivingEntity target, boolean aggro, NavigatorParameters params) {
this.handle = handle.getHandle(); this.handle = ((CraftLivingEntity) handle.getBukkitEntity()).getHandle();
this.target = ((CraftLivingEntity) target).getHandle(); this.target = ((CraftLivingEntity) target).getHandle();
this.navigation = this.handle.getNavigation(); this.navigation = this.handle.getNavigation();
this.aggro = aggro; this.aggro = aggro;

View File

@ -9,7 +9,6 @@ import java.util.Set;
import java.util.WeakHashMap; import java.util.WeakHashMap;
import net.citizensnpcs.api.npc.NPC; import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.CitizensNPC;
import net.minecraft.server.v1_4_5.ControllerLook; import net.minecraft.server.v1_4_5.ControllerLook;
import net.minecraft.server.v1_4_5.DamageSource; import net.minecraft.server.v1_4_5.DamageSource;
import net.minecraft.server.v1_4_5.EnchantmentManager; import net.minecraft.server.v1_4_5.EnchantmentManager;
@ -25,10 +24,12 @@ import net.minecraft.server.v1_4_5.Packet;
import net.minecraft.server.v1_4_5.PathfinderGoalSelector; import net.minecraft.server.v1_4_5.PathfinderGoalSelector;
import net.minecraft.server.v1_4_5.World; import net.minecraft.server.v1_4_5.World;
import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.craftbukkit.v1_4_5.entity.CraftEntity; import org.bukkit.craftbukkit.v1_4_5.CraftServer;
import org.bukkit.craftbukkit.v1_4_5.CraftWorld; import org.bukkit.craftbukkit.v1_4_5.CraftWorld;
import org.bukkit.craftbukkit.v1_4_5.entity.CraftEntity;
import org.bukkit.craftbukkit.v1_4_5.entity.CraftLivingEntity; import org.bukkit.craftbukkit.v1_4_5.entity.CraftLivingEntity;
import org.bukkit.craftbukkit.v1_4_5.entity.CraftPlayer; import org.bukkit.craftbukkit.v1_4_5.entity.CraftPlayer;
import org.bukkit.entity.EntityType; import org.bukkit.entity.EntityType;
@ -36,7 +37,7 @@ import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.material.Stairs; import org.bukkit.material.Stairs;
import org.bukkit.material.Step; import org.bukkit.material.Step;
import org.bukkit.util.Vector; import org.bukkit.plugin.PluginLoadOrder;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
@ -48,9 +49,9 @@ public class NMS {
} }
private static final float DEFAULT_SPEED = 0.4F; private static final float DEFAULT_SPEED = 0.4F;
private static Map<Class<? extends Entity>, Integer> ENTITY_CLASS_TO_INT; private static Map<Class<?>, Integer> ENTITY_CLASS_TO_INT;
private static final Map<Class<? extends Entity>, Constructor<? extends Entity>> ENTITY_CONSTRUCTOR_CACHE = new WeakHashMap<Class<? extends Entity>, Constructor<? extends Entity>>(); private static final Map<Class<?>, Constructor<?>> ENTITY_CONSTRUCTOR_CACHE = new WeakHashMap<Class<?>, Constructor<?>>();
private static Map<Integer, Class<? extends Entity>> ENTITY_INT_TO_CLASS; private static Map<Integer, Class<?>> ENTITY_INT_TO_CLASS;
private static Field GOAL_FIELD; private static Field GOAL_FIELD;
private static Field LAND_SPEED_MODIFIER_FIELD; private static Field LAND_SPEED_MODIFIER_FIELD;
private static final Map<EntityType, Float> MOVEMENT_SPEEDS = Maps.newEnumMap(EntityType.class); private static final Map<EntityType, Float> MOVEMENT_SPEEDS = Maps.newEnumMap(EntityType.class);
@ -125,18 +126,9 @@ public class NMS {
} }
} }
public static double distance(EntityLiving handle, Vector vector) { private static Constructor<?> getCustomEntityConstructor(Class<?> clazz, EntityType type)
return Math.sqrt(distanceSquared(handle, vector)); throws SecurityException, NoSuchMethodException {
} Constructor<?> constructor = ENTITY_CONSTRUCTOR_CACHE.get(clazz);
public static double distanceSquared(EntityLiving handle, Vector vector) {
return Math.pow(handle.locX - vector.getX(), 2) + Math.pow(handle.locY - vector.getY(), 2)
+ Math.pow(handle.locZ - vector.getZ(), 2);
}
private static Constructor<? extends Entity> getCustomEntityConstructor(Class<? extends Entity> clazz,
EntityType type) throws SecurityException, NoSuchMethodException {
Constructor<? extends Entity> constructor = ENTITY_CONSTRUCTOR_CACHE.get(clazz);
if (constructor == null) { if (constructor == null) {
constructor = clazz.getConstructor(World.class); constructor = clazz.getConstructor(World.class);
constructor.setAccessible(true); constructor.setAccessible(true);
@ -167,7 +159,7 @@ public class NMS {
return DEFAULT_SPEED; return DEFAULT_SPEED;
} }
try { try {
float speed = SPEED_FIELD.getFloat(((CraftEntity)npc.getBukkitEntity()).getHandle()); float speed = SPEED_FIELD.getFloat(((CraftEntity) npc.getBukkitEntity()).getHandle());
MOVEMENT_SPEEDS.put(entityType, speed); MOVEMENT_SPEEDS.put(entityType, speed);
return speed; return speed;
} catch (IllegalAccessException ex) { } catch (IllegalAccessException ex) {
@ -176,10 +168,14 @@ public class NMS {
} }
} }
public static boolean inWater(EntityLiving mcEntity) { public static boolean inWater(Entity mcEntity) {
return mcEntity.I() || mcEntity.J(); return mcEntity.I() || mcEntity.J();
} }
public static void loadPlugins() {
((CraftServer) Bukkit.getServer()).enablePlugins(PluginLoadOrder.POSTWORLD);
}
public static void look(ControllerLook controllerLook, EntityLiving handle, EntityLiving target) { public static void look(ControllerLook controllerLook, EntityLiving handle, EntityLiving target) {
controllerLook.a(target, 10.0F, handle.bp()); controllerLook.a(target, 10.0F, handle.bp());
} }
@ -189,7 +185,7 @@ public class NMS {
handle.pitch = pitch; handle.pitch = pitch;
} }
public static void registerEntityClass(Class<? extends Entity> clazz) { public static void registerEntityClass(Class<?> clazz) {
if (ENTITY_CLASS_TO_INT.containsKey(clazz)) if (ENTITY_CLASS_TO_INT.containsKey(clazz))
return; return;
Class<?> search = clazz; Class<?> search = clazz;
@ -208,6 +204,10 @@ public class NMS {
((CraftPlayer) player).getHandle().netServerHandler.sendPacket(packet); ((CraftPlayer) player).getHandle().netServerHandler.sendPacket(packet);
} }
public static void setDestination(LivingEntity bukkitEntity, double x, double y, double z, float speed) {
((CraftLivingEntity) bukkitEntity).getHandle().getControllerMove().a(x, y, z, speed);
}
public static void setHeadYaw(EntityLiving handle, float yaw) { public static void setHeadYaw(EntityLiving handle, float yaw) {
handle.ay = yaw; handle.ay = yaw;
} }
@ -227,8 +227,8 @@ public class NMS {
World handle = ((CraftWorld) world).getHandle(); World handle = ((CraftWorld) world).getHandle();
Entity entity = null; Entity entity = null;
try { try {
Constructor<? extends Entity> constructor = getCustomEntityConstructor(clazz, type); Constructor<?> constructor = getCustomEntityConstructor(clazz, type);
entity = constructor.newInstance(handle); entity = (Entity) constructor.newInstance(handle);
} catch (Exception e) { } catch (Exception e) {
Messaging.logTr(Messages.ERROR_SPAWNING_CUSTOM_ENTITY, e.getMessage()); Messaging.logTr(Messages.ERROR_SPAWNING_CUSTOM_ENTITY, e.getMessage());
return null; return null;
@ -248,16 +248,16 @@ public class NMS {
} }
} }
public static void trySwim(EntityLiving handle) { public static void trySwim(Entity handle, float power) {
trySwim(handle, 0.04F);
}
public static void trySwim(EntityLiving handle, float power) {
if (RANDOM.nextFloat() < 0.8F && inWater(handle)) { if (RANDOM.nextFloat() < 0.8F && inWater(handle)) {
handle.motY += power; handle.motY += power;
} }
} }
public static void trySwim(org.bukkit.entity.Entity handle) {
trySwim(((CraftEntity) handle).getHandle(), 0.04F);
}
public static void updateAI(EntityLiving entity) { public static void updateAI(EntityLiving entity) {
updateSenses(entity); updateSenses(entity);
entity.getNavigation().e(); entity.getNavigation().e();
@ -278,10 +278,10 @@ public class NMS {
} }
} }
public static void updatePathfindingRange(CitizensNPC npc, float pathfindingRange) { public static void updatePathfindingRange(NPC npc, float pathfindingRange) {
if (PATHFINDING_RANGE == null) if (PATHFINDING_RANGE == null)
return; return;
Navigation navigation = npc.getHandle().getNavigation(); Navigation navigation = ((CraftLivingEntity) npc.getBukkitEntity()).getHandle().getNavigation();
try { try {
PATHFINDING_RANGE.set(navigation, pathfindingRange); PATHFINDING_RANGE.set(navigation, pathfindingRange);
} catch (Exception e) { } catch (Exception e) {
@ -318,9 +318,9 @@ public class NMS {
try { try {
Field field = getField(EntityTypes.class, "d"); Field field = getField(EntityTypes.class, "d");
ENTITY_INT_TO_CLASS = (Map<Integer, Class<? extends Entity>>) field.get(null); ENTITY_INT_TO_CLASS = (Map<Integer, Class<?>>) field.get(null);
field = getField(EntityTypes.class, "e"); field = getField(EntityTypes.class, "e");
ENTITY_CLASS_TO_INT = (Map<Class<? extends Entity>, Integer>) field.get(null); ENTITY_CLASS_TO_INT = (Map<Class<?>, Integer>) field.get(null);
} catch (Exception e) { } catch (Exception e) {
Messaging.logTr(Messages.ERROR_GETTING_ID_MAPPING, e.getMessage()); Messaging.logTr(Messages.ERROR_GETTING_ID_MAPPING, e.getMessage());
} }

View File

@ -75,6 +75,16 @@ public class Util {
} }
} }
public static String getMinecraftVersion() {
String raw = Bukkit.getVersion();
int start = raw.indexOf("MC:");
if (start == -1)
return raw;
start += 4;
int end = raw.indexOf(')', start);
return raw.substring(start, end);
}
public static boolean isLoaded(Location location) { public static boolean isLoaded(Location location) {
if (location.getWorld() == null) if (location.getWorld() == null)
return false; return false;
@ -145,6 +155,7 @@ public class Util {
} }
} }
} }
static { static {
try { try {
RNG_CLASS = Class.forName("org.uncommons.maths.random.XORShiftRNG"); RNG_CLASS = Class.forName("org.uncommons.maths.random.XORShiftRNG");