Move reflection into its own file

This commit is contained in:
fullwall 2012-08-03 21:18:10 +08:00
parent 8c7cfa88e9
commit ec9962b36f
32 changed files with 219 additions and 282 deletions

View File

@ -1,33 +1,27 @@
package net.citizensnpcs.npc;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.Map;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.util.NMSReflection;
import net.minecraft.server.Block;
import net.minecraft.server.Entity;
import net.minecraft.server.EntityLiving;
import net.minecraft.server.EntityTypes;
import net.minecraft.server.World;
import org.bukkit.Location;
import org.bukkit.block.BlockFace;
import org.bukkit.craftbukkit.CraftWorld;
@SuppressWarnings("unchecked")
import com.google.common.collect.Maps;
public abstract class CitizensMobNPC extends CitizensNPC {
private final Constructor<? extends EntityLiving> constructor;
protected CitizensMobNPC(int id, String name, Class<? extends EntityLiving> clazz) {
super(id, name);
try {
this.constructor = clazz.getConstructor(World.class, NPC.class);
} catch (Exception ex) {
throw new IllegalStateException("unable to find an entity constructor");
}
if (!classToInt.containsKey(clazz))
registerEntityClass(clazz);
this.constructor = getConstructor(clazz);
NMSReflection.registerEntityClass(clazz);
}
private EntityLiving createEntityFromClass(World world) {
@ -56,32 +50,17 @@ public abstract class CitizensMobNPC extends CitizensNPC {
return entity;
}
private static Map<Class<? extends Entity>, Integer> classToInt;
private static Map<Integer, Class<? extends Entity>> intToClass;
private static final Map<Class<? extends EntityLiving>, Constructor<? extends EntityLiving>> CONSTRUCTOR_CACHE = Maps
.newHashMap();
private static void registerEntityClass(Class<? extends Entity> clazz) {
Class<?> search = clazz;
while ((search = search.getSuperclass()) != null && Entity.class.isAssignableFrom(search)) {
if (!classToInt.containsKey(search))
continue;
int code = classToInt.get(search);
intToClass.put(code, clazz);
classToInt.put(clazz, code);
return;
}
throw new IllegalArgumentException("unable to find valid entity superclass");
}
static {
private static Constructor<? extends EntityLiving> getConstructor(Class<? extends EntityLiving> clazz) {
Constructor<? extends EntityLiving> constructor = CONSTRUCTOR_CACHE.get(clazz);
if (constructor != null)
return constructor;
try {
Field field = EntityTypes.class.getDeclaredField("d");
field.setAccessible(true);
intToClass = (Map<Integer, Class<? extends Entity>>) field.get(null);
field = EntityTypes.class.getDeclaredField("e");
field.setAccessible(true);
classToInt = (Map<Class<? extends Entity>, Integer>) field.get(null);
return clazz.getConstructor(World.class, NPC.class);
} catch (Exception ex) {
ex.printStackTrace();
throw new IllegalStateException("unable to find an entity constructor");
}
}
}

View File

@ -1,8 +1,5 @@
package net.citizensnpcs.npc.ai;
import java.lang.reflect.Field;
import java.util.Map;
import net.citizensnpcs.Settings.Setting;
import net.citizensnpcs.api.ai.EntityTarget;
import net.citizensnpcs.api.ai.Navigator;
@ -11,17 +8,12 @@ import net.citizensnpcs.api.ai.event.NavigationBeginEvent;
import net.citizensnpcs.api.ai.event.NavigationCancelEvent;
import net.citizensnpcs.api.ai.event.NavigationReplaceEvent;
import net.citizensnpcs.npc.CitizensNPC;
import net.citizensnpcs.util.Messaging;
import net.minecraft.server.EntityLiving;
import net.minecraft.server.Navigation;
import net.citizensnpcs.util.NMSReflection;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.LivingEntity;
import com.google.common.collect.Maps;
public class CitizensNavigator implements Navigator {
private PathStrategy executing;
private final CitizensNPC npc;
@ -55,25 +47,6 @@ public class CitizensNavigator implements Navigator {
return speed;
}
private float getSpeedFor(EntityLiving from) {
EntityType entityType = from.getBukkitEntity().getType();
Float cached = MOVEMENT_SPEEDS.get(entityType);
if (cached != null)
return cached;
if (SPEED_FIELD == null) {
MOVEMENT_SPEEDS.put(entityType, DEFAULT_SPEED);
return DEFAULT_SPEED;
}
try {
float speed = SPEED_FIELD.getFloat(from);
MOVEMENT_SPEEDS.put(entityType, speed);
return speed;
} catch (IllegalAccessException ex) {
ex.printStackTrace();
return DEFAULT_SPEED;
}
}
@Override
public Location getTargetAsLocation() {
return executing.getTargetAsLocation();
@ -91,7 +64,7 @@ public class CitizensNavigator implements Navigator {
public void onSpawn() {
if (speed == -1)
this.speed = getSpeedFor(npc.getHandle());
this.speed = NMSReflection.getSpeedFor(npc.getHandle());
updatePathfindingRange();
}
@ -139,43 +112,6 @@ public class CitizensNavigator implements Navigator {
}
private void updatePathfindingRange() {
if (PATHFINDING_RANGE == null)
return;
Navigation navigation = npc.getHandle().getNavigation();
try {
PATHFINDING_RANGE.set(navigation, pathfindingRange);
} catch (Exception ex) {
Messaging.logF("Could not update pathfinding range: %s.", ex.getMessage());
}
}
private static final float DEFAULT_SPEED = 0.4F;
private static final Map<EntityType, Float> MOVEMENT_SPEEDS = Maps.newEnumMap(EntityType.class);
private static Field PATHFINDING_RANGE;
private static Field SPEED_FIELD;
static {
// constants taken from source code
MOVEMENT_SPEEDS.put(EntityType.CHICKEN, 0.25F);
MOVEMENT_SPEEDS.put(EntityType.COW, 0.2F);
MOVEMENT_SPEEDS.put(EntityType.CREEPER, 0.3F);
MOVEMENT_SPEEDS.put(EntityType.IRON_GOLEM, 0.15F);
MOVEMENT_SPEEDS.put(EntityType.MUSHROOM_COW, 0.2F);
MOVEMENT_SPEEDS.put(EntityType.OCELOT, 0.23F);
MOVEMENT_SPEEDS.put(EntityType.SHEEP, 0.25F);
MOVEMENT_SPEEDS.put(EntityType.SNOWMAN, 0.25F);
MOVEMENT_SPEEDS.put(EntityType.PIG, 0.27F);
MOVEMENT_SPEEDS.put(EntityType.PLAYER, 1F);
MOVEMENT_SPEEDS.put(EntityType.VILLAGER, 0.3F);
try {
SPEED_FIELD = EntityLiving.class.getDeclaredField("bw");
SPEED_FIELD.setAccessible(true);
PATHFINDING_RANGE = Navigation.class.getDeclaredField("e");
PATHFINDING_RANGE.setAccessible(true);
} catch (Exception ex) {
ex.printStackTrace();
PATHFINDING_RANGE = null;
SPEED_FIELD = null;
}
NMSReflection.updatePathfindingRange(npc, pathfindingRange);
}
}

View File

@ -5,6 +5,7 @@ import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
import net.citizensnpcs.npc.ai.NPCHolder;
import net.citizensnpcs.util.NMSReflection;
import net.citizensnpcs.util.Util;
import net.minecraft.server.EntityBlaze;
import net.minecraft.server.World;
@ -34,7 +35,7 @@ public class CitizensBlazeNPC extends CitizensMobNPC {
super(world);
this.npc = (CitizensNPC) npc;
if (npc != null) {
Util.clearGoals(goalSelector, targetSelector);
NMSReflection.clearGoals(goalSelector, targetSelector);
}
}

View File

@ -5,6 +5,7 @@ import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
import net.citizensnpcs.npc.ai.NPCHolder;
import net.citizensnpcs.util.NMSReflection;
import net.citizensnpcs.util.Util;
import net.minecraft.server.EntityCaveSpider;
import net.minecraft.server.World;
@ -30,7 +31,7 @@ public class CitizensCaveSpiderNPC extends CitizensMobNPC {
super(world);
this.npc = (CitizensNPC) npc;
if (npc != null) {
Util.clearGoals(goalSelector, targetSelector);
NMSReflection.clearGoals(goalSelector, targetSelector);
}
}

View File

@ -5,6 +5,7 @@ import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
import net.citizensnpcs.npc.ai.NPCHolder;
import net.citizensnpcs.util.NMSReflection;
import net.citizensnpcs.util.Util;
import net.minecraft.server.EntityChicken;
import net.minecraft.server.World;
@ -34,7 +35,7 @@ public class CitizensChickenNPC extends CitizensMobNPC {
super(world);
this.npc = (CitizensNPC) npc;
if (npc != null) {
Util.clearGoals(goalSelector, targetSelector);
NMSReflection.clearGoals(goalSelector, targetSelector);
}
}

View File

@ -5,6 +5,7 @@ import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
import net.citizensnpcs.npc.ai.NPCHolder;
import net.citizensnpcs.util.NMSReflection;
import net.citizensnpcs.util.Util;
import net.minecraft.server.EntityCow;
import net.minecraft.server.World;
@ -34,7 +35,7 @@ public class CitizensCowNPC extends CitizensMobNPC {
super(world);
this.npc = (CitizensNPC) npc;
if (npc != null) {
Util.clearGoals(goalSelector, targetSelector);
NMSReflection.clearGoals(goalSelector, targetSelector);
}
}

View File

@ -5,6 +5,7 @@ import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
import net.citizensnpcs.npc.ai.NPCHolder;
import net.citizensnpcs.util.NMSReflection;
import net.citizensnpcs.util.Util;
import net.minecraft.server.EntityCreeper;
import net.minecraft.server.EntityLightning;
@ -35,7 +36,7 @@ public class CitizensCreeperNPC extends CitizensMobNPC {
super(world);
this.npc = (CitizensNPC) npc;
if (npc != null) {
Util.clearGoals(goalSelector, targetSelector);
NMSReflection.clearGoals(goalSelector, targetSelector);
}
}

View File

@ -5,6 +5,7 @@ import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
import net.citizensnpcs.npc.ai.NPCHolder;
import net.citizensnpcs.util.NMSReflection;
import net.citizensnpcs.util.Util;
import net.minecraft.server.EntityEnderDragon;
import net.minecraft.server.World;
@ -30,7 +31,7 @@ public class CitizensEnderDragonNPC extends CitizensMobNPC {
super(world);
this.npc = (CitizensNPC) npc;
if (npc != null) {
Util.clearGoals(goalSelector, targetSelector);
NMSReflection.clearGoals(goalSelector, targetSelector);
}
}

View File

@ -8,6 +8,7 @@ import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
import net.citizensnpcs.npc.ai.NPCHolder;
import net.citizensnpcs.util.Messaging;
import net.citizensnpcs.util.NMSReflection;
import net.citizensnpcs.util.Util;
import net.minecraft.server.EntityEnderman;
import net.minecraft.server.World;
@ -72,7 +73,7 @@ public class CitizensEndermanNPC extends CitizensMobNPC implements Equipable {
super(world);
this.npc = (CitizensNPC) npc;
if (npc != null) {
Util.clearGoals(goalSelector, targetSelector);
NMSReflection.clearGoals(goalSelector, targetSelector);
}
}

View File

@ -5,6 +5,7 @@ import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
import net.citizensnpcs.npc.ai.NPCHolder;
import net.citizensnpcs.util.NMSReflection;
import net.citizensnpcs.util.Util;
import net.minecraft.server.EntityGhast;
import net.minecraft.server.World;
@ -34,7 +35,7 @@ public class CitizensGhastNPC extends CitizensMobNPC {
super(world);
this.npc = (CitizensNPC) npc;
if (npc != null) {
Util.clearGoals(goalSelector, targetSelector);
NMSReflection.clearGoals(goalSelector, targetSelector);
}
}

View File

@ -5,6 +5,7 @@ import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
import net.citizensnpcs.npc.ai.NPCHolder;
import net.citizensnpcs.util.NMSReflection;
import net.citizensnpcs.util.Util;
import net.minecraft.server.EntityGiantZombie;
import net.minecraft.server.World;
@ -30,7 +31,7 @@ public class CitizensGiantNPC extends CitizensMobNPC {
super(world);
this.npc = (CitizensNPC) npc;
if (npc != null) {
Util.clearGoals(goalSelector, targetSelector);
NMSReflection.clearGoals(goalSelector, targetSelector);
}
}

View File

@ -5,6 +5,7 @@ import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
import net.citizensnpcs.npc.ai.NPCHolder;
import net.citizensnpcs.util.NMSReflection;
import net.citizensnpcs.util.Util;
import net.minecraft.server.EntityIronGolem;
import net.minecraft.server.World;
@ -30,7 +31,7 @@ public class CitizensIronGolemNPC extends CitizensMobNPC {
super(world);
this.npc = (CitizensNPC) npc;
if (npc != null) {
Util.clearGoals(goalSelector, targetSelector);
NMSReflection.clearGoals(goalSelector, targetSelector);
}
}

View File

@ -5,6 +5,7 @@ import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
import net.citizensnpcs.npc.ai.NPCHolder;
import net.citizensnpcs.util.NMSReflection;
import net.citizensnpcs.util.Util;
import net.minecraft.server.EntityMagmaCube;
import net.minecraft.server.World;
@ -35,7 +36,7 @@ public class CitizensMagmaCubeNPC extends CitizensMobNPC {
this.npc = (CitizensNPC) npc;
if (npc != null) {
setSize(3);
Util.clearGoals(goalSelector, targetSelector);
NMSReflection.clearGoals(goalSelector, targetSelector);
}
}

View File

@ -5,6 +5,7 @@ import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
import net.citizensnpcs.npc.ai.NPCHolder;
import net.citizensnpcs.util.NMSReflection;
import net.citizensnpcs.util.Util;
import net.minecraft.server.EntityMushroomCow;
import net.minecraft.server.World;
@ -34,7 +35,7 @@ public class CitizensMushroomCowNPC extends CitizensMobNPC {
super(world);
this.npc = (CitizensNPC) npc;
if (npc != null) {
Util.clearGoals(goalSelector, targetSelector);
NMSReflection.clearGoals(goalSelector, targetSelector);
}
}

View File

@ -5,6 +5,7 @@ import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
import net.citizensnpcs.npc.ai.NPCHolder;
import net.citizensnpcs.util.NMSReflection;
import net.citizensnpcs.util.Util;
import net.minecraft.server.EntityOcelot;
import net.minecraft.server.World;
@ -34,7 +35,7 @@ public class CitizensOcelotNPC extends CitizensMobNPC {
super(world);
this.npc = (CitizensNPC) npc;
if (npc != null) {
Util.clearGoals(goalSelector, targetSelector);
NMSReflection.clearGoals(goalSelector, targetSelector);
}
}

View File

@ -8,6 +8,7 @@ import net.citizensnpcs.npc.CitizensNPC;
import net.citizensnpcs.npc.ai.NPCHolder;
import net.citizensnpcs.trait.Saddle;
import net.citizensnpcs.util.Messaging;
import net.citizensnpcs.util.NMSReflection;
import net.citizensnpcs.util.StringHelper;
import net.citizensnpcs.util.Util;
import net.minecraft.server.EntityLightning;
@ -61,7 +62,7 @@ public class CitizensPigNPC extends CitizensMobNPC implements Equipable {
super(world);
this.npc = (CitizensNPC) npc;
if (npc != null) {
Util.clearGoals(goalSelector, targetSelector);
NMSReflection.clearGoals(goalSelector, targetSelector);
}
}

View File

@ -5,6 +5,7 @@ import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
import net.citizensnpcs.npc.ai.NPCHolder;
import net.citizensnpcs.util.NMSReflection;
import net.citizensnpcs.util.Util;
import net.minecraft.server.EntityPigZombie;
import net.minecraft.server.World;
@ -34,7 +35,7 @@ public class CitizensPigZombieNPC extends CitizensMobNPC {
super(world);
this.npc = (CitizensNPC) npc;
if (npc != null) {
Util.clearGoals(goalSelector, targetSelector);
NMSReflection.clearGoals(goalSelector, targetSelector);
}
}

View File

@ -9,6 +9,7 @@ import net.citizensnpcs.npc.ai.NPCHolder;
import net.citizensnpcs.trait.Sheared;
import net.citizensnpcs.trait.WoolColor;
import net.citizensnpcs.util.Messaging;
import net.citizensnpcs.util.NMSReflection;
import net.citizensnpcs.util.StringHelper;
import net.citizensnpcs.util.Util;
import net.minecraft.server.EntitySheep;
@ -72,7 +73,7 @@ public class CitizensSheepNPC extends CitizensMobNPC implements Equipable {
super(world);
this.npc = (CitizensNPC) npc;
if (npc != null) {
Util.clearGoals(goalSelector, targetSelector);
NMSReflection.clearGoals(goalSelector, targetSelector);
}
}

View File

@ -5,6 +5,7 @@ import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
import net.citizensnpcs.npc.ai.NPCHolder;
import net.citizensnpcs.util.NMSReflection;
import net.citizensnpcs.util.Util;
import net.minecraft.server.EntitySilverfish;
import net.minecraft.server.World;
@ -34,7 +35,7 @@ public class CitizensSilverfishNPC extends CitizensMobNPC {
super(world);
this.npc = (CitizensNPC) npc;
if (npc != null) {
Util.clearGoals(goalSelector, targetSelector);
NMSReflection.clearGoals(goalSelector, targetSelector);
}
}

View File

@ -5,6 +5,7 @@ import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
import net.citizensnpcs.npc.ai.NPCHolder;
import net.citizensnpcs.util.NMSReflection;
import net.citizensnpcs.util.Util;
import net.minecraft.server.EntitySkeleton;
import net.minecraft.server.World;
@ -34,7 +35,7 @@ public class CitizensSkeletonNPC extends CitizensMobNPC {
super(world);
this.npc = (CitizensNPC) npc;
if (npc != null) {
Util.clearGoals(goalSelector, targetSelector);
NMSReflection.clearGoals(goalSelector, targetSelector);
}
}

View File

@ -5,6 +5,7 @@ import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
import net.citizensnpcs.npc.ai.NPCHolder;
import net.citizensnpcs.util.NMSReflection;
import net.citizensnpcs.util.Util;
import net.minecraft.server.EntitySlime;
import net.minecraft.server.World;
@ -35,7 +36,7 @@ public class CitizensSlimeNPC extends CitizensMobNPC {
this.npc = (CitizensNPC) npc;
if (npc != null) {
setSize(3);
Util.clearGoals(goalSelector, targetSelector);
NMSReflection.clearGoals(goalSelector, targetSelector);
}
}

View File

@ -5,6 +5,7 @@ import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
import net.citizensnpcs.npc.ai.NPCHolder;
import net.citizensnpcs.util.NMSReflection;
import net.citizensnpcs.util.Util;
import net.minecraft.server.EntitySnowman;
import net.minecraft.server.World;
@ -30,7 +31,7 @@ public class CitizensSnowmanNPC extends CitizensMobNPC {
super(world);
this.npc = (CitizensNPC) npc;
if (npc != null) {
Util.clearGoals(goalSelector, targetSelector);
NMSReflection.clearGoals(goalSelector, targetSelector);
}
}

View File

@ -5,6 +5,7 @@ import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
import net.citizensnpcs.npc.ai.NPCHolder;
import net.citizensnpcs.util.NMSReflection;
import net.citizensnpcs.util.Util;
import net.minecraft.server.EntitySpider;
import net.minecraft.server.World;
@ -33,7 +34,7 @@ public class CitizensSpiderNPC extends CitizensMobNPC {
super(world);
this.npc = (CitizensNPC) npc;
if (npc != null) {
Util.clearGoals(goalSelector, targetSelector);
NMSReflection.clearGoals(goalSelector, targetSelector);
}
}

View File

@ -5,6 +5,7 @@ import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
import net.citizensnpcs.npc.ai.NPCHolder;
import net.citizensnpcs.util.NMSReflection;
import net.citizensnpcs.util.Util;
import net.minecraft.server.EntitySquid;
import net.minecraft.server.World;
@ -34,7 +35,7 @@ public class CitizensSquidNPC extends CitizensMobNPC {
super(world);
this.npc = (CitizensNPC) npc;
if (npc != null) {
Util.clearGoals(goalSelector, targetSelector);
NMSReflection.clearGoals(goalSelector, targetSelector);
}
}

View File

@ -5,6 +5,7 @@ import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
import net.citizensnpcs.npc.ai.NPCHolder;
import net.citizensnpcs.util.NMSReflection;
import net.citizensnpcs.util.Util;
import net.minecraft.server.EntityHuman;
import net.minecraft.server.EntityVillager;
@ -35,7 +36,7 @@ public class CitizensVillagerNPC extends CitizensMobNPC {
super(world);
this.npc = (CitizensNPC) npc;
if (npc != null) {
Util.clearGoals(goalSelector, targetSelector);
NMSReflection.clearGoals(goalSelector, targetSelector);
}
}
@ -46,6 +47,13 @@ public class CitizensVillagerNPC extends CitizensMobNPC {
npc.update();
}
@Override
public boolean c(EntityHuman entityhuman) {
if (npc == null)
return super.c(entityhuman);
return false; // block trades
}
@Override
public void collide(net.minecraft.server.Entity entity) {
// this method is called by both the entities involved - cancelling
@ -54,13 +62,6 @@ public class CitizensVillagerNPC extends CitizensMobNPC {
Util.callCollisionEvent(npc, entity);
}
@Override
public boolean c(EntityHuman entityhuman) {
if (npc == null)
return super.c(entityhuman);
return false; // block trades
}
@Override
public void g(double x, double y, double z) {
if (npc == null) {

View File

@ -5,6 +5,7 @@ import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
import net.citizensnpcs.npc.ai.NPCHolder;
import net.citizensnpcs.util.NMSReflection;
import net.citizensnpcs.util.Util;
import net.minecraft.server.EntityWolf;
import net.minecraft.server.World;
@ -34,7 +35,7 @@ public class CitizensWolfNPC extends CitizensMobNPC {
super(world);
this.npc = (CitizensNPC) npc;
if (npc != null) {
Util.clearGoals(goalSelector, targetSelector);
NMSReflection.clearGoals(goalSelector, targetSelector);
}
}

View File

@ -5,6 +5,7 @@ import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
import net.citizensnpcs.npc.ai.NPCHolder;
import net.citizensnpcs.util.NMSReflection;
import net.citizensnpcs.util.Util;
import net.minecraft.server.EntityZombie;
import net.minecraft.server.World;
@ -34,7 +35,7 @@ public class CitizensZombieNPC extends CitizensMobNPC {
super(world);
this.npc = (CitizensNPC) npc;
if (npc != null) {
Util.clearGoals(goalSelector, targetSelector);
NMSReflection.clearGoals(goalSelector, targetSelector);
}
}

View File

@ -8,7 +8,7 @@ import net.citizensnpcs.npc.CitizensNPC;
import net.citizensnpcs.npc.ai.NPCHolder;
import net.citizensnpcs.npc.network.EmptyNetHandler;
import net.citizensnpcs.npc.network.EmptyNetworkManager;
import net.citizensnpcs.npc.network.NPCSocket;
import net.citizensnpcs.npc.network.EmptySocket;
import net.citizensnpcs.util.Util;
import net.minecraft.server.EntityPlayer;
import net.minecraft.server.EnumGamemode;
@ -30,7 +30,7 @@ public class EntityHumanNPC extends EntityPlayer implements NPCHolder {
this.npc = (CitizensNPC) npc;
itemInWorldManager.setGameMode(EnumGamemode.SURVIVAL);
NPCSocket socket = new NPCSocket();
EmptySocket socket = new EmptySocket();
NetworkManager netMgr = new EmptyNetworkManager(socket, "npc mgr", new NetHandler() {
@Override
public boolean a() {

View File

@ -1,9 +1,9 @@
package net.citizensnpcs.npc.network;
import java.lang.reflect.Field;
import java.net.Socket;
import java.security.PrivateKey;
import net.citizensnpcs.util.NMSReflection;
import net.minecraft.server.NetHandler;
import net.minecraft.server.NetworkManager;
import net.minecraft.server.Packet;
@ -13,13 +13,7 @@ public class EmptyNetworkManager extends NetworkManager {
public EmptyNetworkManager(Socket socket, String string, NetHandler netHandler, PrivateKey key) {
super(socket, string, netHandler, key);
try {
// the field above the 3 synchronized lists
Field f = NetworkManager.class.getDeclaredField("l");
f.setAccessible(true);
f.set(this, false);
} catch (Exception e) {
}
NMSReflection.stopNetworkThreads(this);
}
@Override

View File

@ -1,20 +0,0 @@
package net.citizensnpcs.npc.network;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class NPCSocket extends Socket {
@Override
public InputStream getInputStream() {
return new ByteArrayInputStream(new byte[10]);
}
@Override
public OutputStream getOutputStream() {
return new ByteArrayOutputStream();
}
}

View File

@ -0,0 +1,141 @@
package net.citizensnpcs.util;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
import net.citizensnpcs.npc.CitizensNPC;
import net.minecraft.server.Entity;
import net.minecraft.server.EntityLiving;
import net.minecraft.server.EntityTypes;
import net.minecraft.server.Navigation;
import net.minecraft.server.NetworkManager;
import net.minecraft.server.PathfinderGoalSelector;
import org.bukkit.entity.EntityType;
import com.google.common.collect.Maps;
@SuppressWarnings("unchecked")
public class NMSReflection {
private NMSReflection() {
// util class
}
private static final float DEFAULT_SPEED = 0.4F;
private static Map<Class<? extends Entity>, Integer> ENTITY_CLASS_TO_INT;
private static Map<Integer, Class<? extends Entity>> ENTITY_INT_TO_CLASS;
private static Field GOAL_FIELD;
private static final Map<EntityType, Float> MOVEMENT_SPEEDS = Maps.newEnumMap(EntityType.class);
private static Field PATHFINDING_RANGE;
private static Field SPEED_FIELD;
private static Field THREAD_STOPPER;
public static void clearGoals(PathfinderGoalSelector... goalSelectors) {
if (NMSReflection.GOAL_FIELD == null || goalSelectors == null)
return;
for (PathfinderGoalSelector selector : goalSelectors) {
try {
List<?> list = (List<?>) NMSReflection.GOAL_FIELD.get(selector);
list.clear();
} catch (Exception e) {
}
}
}
private static Field getField(Class<?> clazz, String field) {
Field f = null;
try {
f = clazz.getDeclaredField(field);
f.setAccessible(true);
} catch (Exception e) {
}
return f;
}
public static float getSpeedFor(EntityLiving from) {
EntityType entityType = from.getBukkitEntity().getType();
Float cached = MOVEMENT_SPEEDS.get(entityType);
if (cached != null)
return cached;
if (SPEED_FIELD == null) {
MOVEMENT_SPEEDS.put(entityType, DEFAULT_SPEED);
return DEFAULT_SPEED;
}
try {
float speed = SPEED_FIELD.getFloat(from);
MOVEMENT_SPEEDS.put(entityType, speed);
return speed;
} catch (IllegalAccessException ex) {
ex.printStackTrace();
return DEFAULT_SPEED;
}
}
public static void registerEntityClass(Class<? extends Entity> clazz) {
if (ENTITY_CLASS_TO_INT.containsKey(clazz))
return;
Class<?> search = clazz;
while ((search = search.getSuperclass()) != null && Entity.class.isAssignableFrom(search)) {
if (!ENTITY_CLASS_TO_INT.containsKey(search))
continue;
int code = ENTITY_CLASS_TO_INT.get(search);
ENTITY_INT_TO_CLASS.put(code, clazz);
ENTITY_CLASS_TO_INT.put(clazz, code);
return;
}
throw new IllegalArgumentException("unable to find valid entity superclass");
}
public static void stopNetworkThreads(NetworkManager manager) {
if (THREAD_STOPPER == null)
return;
try {
THREAD_STOPPER.set(manager, false);
} catch (Exception e) {
}
}
public static void updatePathfindingRange(CitizensNPC npc, float pathfindingRange) {
if (PATHFINDING_RANGE == null)
return;
Navigation navigation = npc.getHandle().getNavigation();
try {
PATHFINDING_RANGE.set(navigation, pathfindingRange);
} catch (Exception ex) {
Messaging.logF("Could not update pathfinding range: %s.", ex.getMessage());
}
}
static {
// true field above false and three synchronised lists
THREAD_STOPPER = getField(NetworkManager.class, "m");
// constants taken from source code
MOVEMENT_SPEEDS.put(EntityType.CHICKEN, 0.25F);
MOVEMENT_SPEEDS.put(EntityType.COW, 0.2F);
MOVEMENT_SPEEDS.put(EntityType.CREEPER, 0.3F);
MOVEMENT_SPEEDS.put(EntityType.IRON_GOLEM, 0.15F);
MOVEMENT_SPEEDS.put(EntityType.MUSHROOM_COW, 0.2F);
MOVEMENT_SPEEDS.put(EntityType.OCELOT, 0.23F);
MOVEMENT_SPEEDS.put(EntityType.SHEEP, 0.25F);
MOVEMENT_SPEEDS.put(EntityType.SNOWMAN, 0.25F);
MOVEMENT_SPEEDS.put(EntityType.PIG, 0.27F);
MOVEMENT_SPEEDS.put(EntityType.PLAYER, 1F);
MOVEMENT_SPEEDS.put(EntityType.VILLAGER, 0.3F);
SPEED_FIELD = getField(EntityLiving.class, "bw");
PATHFINDING_RANGE = getField(Navigation.class, "e");
GOAL_FIELD = getField(PathfinderGoalSelector.class, "a");
try {
Field field = getField(EntityTypes.class, "d");
field.setAccessible(true);
ENTITY_INT_TO_CLASS = (Map<Integer, Class<? extends Entity>>) field.get(null);
field = getField(EntityTypes.class, "e");
field.setAccessible(true);
ENTITY_CLASS_TO_INT = (Map<Class<? extends Entity>, Integer>) field.get(null);
} catch (Exception e) {
}
}
}

View File

@ -1,19 +1,10 @@
package net.citizensnpcs.util;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import net.citizensnpcs.Settings.Setting;
import net.citizensnpcs.api.event.NPCCollisionEvent;
import net.citizensnpcs.api.event.NPCPushEvent;
import net.citizensnpcs.api.npc.NPC;
import net.minecraft.server.Packet;
import net.minecraft.server.PathfinderGoalSelector;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
@ -26,18 +17,12 @@ import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
import com.google.common.base.Splitter;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
public class Util {
// Static class for small (emphasis small) utility methods
private Util() {
}
private static Field GOAL_FIELD;
private static final Map<Class<?>, Class<?>> primitiveClassMap = Maps.newHashMap();
public static void callCollisionEvent(NPC npc, net.minecraft.server.Entity entity) {
if (NPCCollisionEvent.getHandlerList().getRegisteredListeners().length > 0)
Bukkit.getPluginManager().callEvent(new NPCCollisionEvent(npc, entity.getBukkitEntity()));
@ -49,78 +34,6 @@ public class Util {
return event;
}
public static void clearGoals(PathfinderGoalSelector... goalSelectors) {
if (GOAL_FIELD == null || goalSelectors == null)
return;
for (PathfinderGoalSelector selector : goalSelectors) {
try {
List<?> list = (List<?>) GOAL_FIELD.get(selector);
list.clear();
} catch (Exception e) {
}
}
}
/**
* Given a set of instantiation parameters, attempts to find a matching
* constructor with the greatest number of matching class parameters and
* invokes it.
*
* @param clazz
* @param params
* @return null if no instance could be created with the given parameters
*/
public static <T> T createInstance(Class<? extends T> clazz, Object... params) {
Validate.notNull(params);
Validate.noNullElements(params);
try {
if (params.length == 0) {
return clazz.newInstance();
}
return createInstance0(clazz, params);
} catch (Exception e) {
return null;
}
}
private static <T> T createInstance0(Class<? extends T> clazz, Object[] params)
throws InstantiationException, IllegalAccessException, IllegalArgumentException,
InvocationTargetException {
@SuppressWarnings("unchecked")
Constructor<? extends T>[] constructors = (Constructor<? extends T>[]) clazz.getConstructors();
Arrays.sort(constructors, new Comparator<Constructor<?>>() {
@Override
public int compare(Constructor<?> o1, Constructor<?> o2) {
return o2.getParameterTypes().length - o1.getParameterTypes().length;
}
});
constructorLoop: for (Constructor<? extends T> constructor : constructors) {
Class<?>[] types = constructor.getParameterTypes();
if (Sets.newHashSet(types).size() != types.length)
continue;
// we can't resolve the order of the constructor parameters
if (types.length == 0)
return clazz.newInstance();
Object[] rebuild = new Object[types.length];
for (Object param : params) {
for (int i = 0; i < types.length; ++i) {
if (param.getClass() == types[i] || primitiveClassMap.get(param.getClass()) == types[i]
|| searchInterfaces(param.getClass(), types[i])) {
rebuild[i] = param;
}
}
}
for (Object constructorParam : rebuild) {
if (constructorParam == null)
continue constructorLoop;
}
return constructor.newInstance(rebuild);
}
return null;
}
public static boolean isSettingFulfilled(Player player, Setting setting) {
String parts = setting.asString();
if (parts.contains("*"))
@ -146,13 +59,6 @@ public class Util {
return type;
}
private static boolean searchInterfaces(Class<?> class1, Class<?> class2) {
for (Class<?> test : class1.getInterfaces())
if (test == class2)
return true;
return false;
}
public static void sendPacketNearby(Location location, Packet packet, double radius) {
radius *= radius;
final World world = location.getWorld();
@ -177,28 +83,4 @@ public class Util {
}
}
}
static {
primitiveClassMap.put(Boolean.class, boolean.class);
primitiveClassMap.put(Byte.class, byte.class);
primitiveClassMap.put(Short.class, short.class);
primitiveClassMap.put(Character.class, char.class);
primitiveClassMap.put(Integer.class, int.class);
primitiveClassMap.put(Long.class, long.class);
primitiveClassMap.put(Float.class, float.class);
primitiveClassMap.put(Double.class, double.class);
primitiveClassMap.put(boolean.class, Boolean.class);
primitiveClassMap.put(byte.class, Byte.class);
primitiveClassMap.put(short.class, Short.class);
primitiveClassMap.put(char.class, Character.class);
primitiveClassMap.put(int.class, Integer.class);
primitiveClassMap.put(long.class, Long.class);
primitiveClassMap.put(float.class, Float.class);
primitiveClassMap.put(double.class, Double.class);
try {
GOAL_FIELD = PathfinderGoalSelector.class.getDeclaredField("a");
} catch (Exception e) {
GOAL_FIELD = null;
}
}
}