Allow on the fly /npc trackingrange

This commit is contained in:
fullwall 2023-03-27 02:52:56 +08:00
parent 4f0cf51cbd
commit 84c581dd09
25 changed files with 290 additions and 108 deletions

View File

@ -415,7 +415,6 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
return new ShopTrait(shops);
}));
selector = new NPCSelector(this);
Bukkit.getPluginManager().registerEvents(new EventListen(storedRegistries), this);
Bukkit.getPluginManager().registerEvents(new Placeholders(), this);
Placeholders.registerNPCPlaceholder(Pattern.compile("command_[a-zA-Z_0-9]+"), (npc, sender, input) -> {

View File

@ -182,8 +182,13 @@ public class NMS {
return getFinalSetter(clazz, field, true);
}
public static MethodHandle getFinalSetter(Class<?> clazz, String fieldName, boolean log) {
Field field;
public static MethodHandle getFinalSetter(Class<?> clazz, String field, boolean log) {
return getFinalSetter(NMS.getField(clazz, field, log), log);
}
public static MethodHandle getFinalSetter(Field field, boolean log) {
if (field == null)
return null;
if (MODIFIERS_FIELD == null) {
if (UNSAFE == null) {
try {
@ -191,7 +196,7 @@ public class NMS {
} catch (Exception e) {
e.printStackTrace();
if (log) {
Messaging.logTr(Messages.ERROR_GETTING_FIELD, fieldName, e.getLocalizedMessage());
Messaging.logTr(Messages.ERROR_GETTING_FIELD, field.getName(), e.getLocalizedMessage());
}
return null;
}
@ -201,34 +206,41 @@ public class NMS {
.bindTo(UNSAFE);
UNSAFE_PUT_OBJECT = getMethodHandle(UNSAFE.getClass(), "putObject", true, Object.class, long.class,
Object.class).bindTo(UNSAFE);
}
field = NMS.getField(clazz, fieldName, log);
if (field == null) {
return null;
UNSAFE_PUT_INT = getMethodHandle(UNSAFE.getClass(), "putInt", true, Object.class, long.class, int.class)
.bindTo(UNSAFE);
UNSAFE_PUT_FLOAT = getMethodHandle(UNSAFE.getClass(), "putFloat", true, Object.class, long.class,
float.class).bindTo(UNSAFE);
UNSAFE_PUT_DOUBLE = getMethodHandle(UNSAFE.getClass(), "putDouble", true, Object.class, long.class,
double.class).bindTo(UNSAFE);
UNSAFE_PUT_BOOLEAN = getMethodHandle(UNSAFE.getClass(), "putBoolean", true, Object.class, long.class,
boolean.class).bindTo(UNSAFE);
UNSAFE_PUT_LONG = getMethodHandle(UNSAFE.getClass(), "putLong", true, Object.class, long.class,
long.class).bindTo(UNSAFE);
}
try {
boolean isStatic = Modifier.isStatic(field.getModifiers());
long offset = (long) (isStatic ? UNSAFE_STATIC_FIELD_OFFSET.invoke(field)
: UNSAFE_FIELD_OFFSET.invoke(field));
return isStatic ? MethodHandles.insertArguments(UNSAFE_PUT_OBJECT, 0, clazz, offset)
: MethodHandles.insertArguments(UNSAFE_PUT_OBJECT, 1, offset);
MethodHandle mh = field.getType() == int.class ? UNSAFE_PUT_INT
: field.getType() == boolean.class ? UNSAFE_PUT_BOOLEAN
: field.getType() == double.class ? UNSAFE_PUT_DOUBLE
: field.getType() == float.class ? UNSAFE_PUT_FLOAT
: field.getType() == long.class ? UNSAFE_PUT_LONG : UNSAFE_PUT_OBJECT;
return isStatic ? MethodHandles.insertArguments(mh, 0, field.getDeclaringClass(), offset)
: MethodHandles.insertArguments(mh, 1, offset);
} catch (Throwable t) {
t.printStackTrace();
if (log) {
Messaging.logTr(Messages.ERROR_GETTING_FIELD, fieldName, t.getLocalizedMessage());
Messaging.logTr(Messages.ERROR_GETTING_FIELD, field.getName(), t.getLocalizedMessage());
}
return null;
}
}
field = getField(clazz, fieldName, log);
if (field == null) {
return null;
}
try {
MODIFIERS_FIELD.setInt(field, field.getModifiers() & ~Modifier.FINAL);
} catch (Exception e) {
if (log) {
Messaging.logTr(Messages.ERROR_GETTING_FIELD, fieldName, e.getLocalizedMessage());
Messaging.logTr(Messages.ERROR_GETTING_FIELD, field.getName(), e.getLocalizedMessage());
}
return null;
}
@ -236,7 +248,7 @@ public class NMS {
return LOOKUP.unreflectSetter(field);
} catch (Exception e) {
if (log) {
Messaging.logTr(Messages.ERROR_GETTING_FIELD, fieldName, e.getLocalizedMessage());
Messaging.logTr(Messages.ERROR_GETTING_FIELD, field.getName(), e.getLocalizedMessage());
}
}
return null;
@ -247,7 +259,7 @@ public class NMS {
List<Field> found = getFieldsMatchingType(clazz, type, false);
if (found.isEmpty())
return null;
return getFinalSetter(clazz, found.get(0).getName());
return getFinalSetter(found.get(0), true);
} catch (Exception e) {
Messaging.logTr(Messages.ERROR_GETTING_FIELD, type, e.getLocalizedMessage());
}
@ -774,6 +786,11 @@ public class NMS {
private static Field MODIFIERS_FIELD;
private static Object UNSAFE;
private static MethodHandle UNSAFE_FIELD_OFFSET;
private static MethodHandle UNSAFE_PUT_BOOLEAN;
private static MethodHandle UNSAFE_PUT_DOUBLE;
private static MethodHandle UNSAFE_PUT_FLOAT;
private static MethodHandle UNSAFE_PUT_INT;
private static MethodHandle UNSAFE_PUT_LONG;
private static MethodHandle UNSAFE_PUT_OBJECT;
private static MethodHandle UNSAFE_STATIC_FIELD_OFFSET;

View File

@ -253,5 +253,5 @@ public interface NMSBridge {
public void updateNavigationWorld(Entity entity, World world);
public void updatePathfindingRange(NPC npc, float pathfindingRange);;
public void updatePathfindingRange(NPC npc, float pathfindingRange);
}

View File

@ -195,6 +195,7 @@ import net.minecraft.server.v1_10_R1.ChatMessage;
import net.minecraft.server.v1_10_R1.Container;
import net.minecraft.server.v1_10_R1.ContainerAnvil;
import net.minecraft.server.v1_10_R1.ControllerJump;
import net.minecraft.server.v1_10_R1.ControllerLook;
import net.minecraft.server.v1_10_R1.ControllerMove;
import net.minecraft.server.v1_10_R1.CrashReport;
import net.minecraft.server.v1_10_R1.CrashReportSystemDetails;
@ -349,6 +350,7 @@ public class NMSImpl implements NMSBridge {
@Override
public void unlinkAll(Consumer<Player> callback) {
handle.die();
for (EntityPlayer link : Lists.newArrayList(tracker.trackedPlayers)) {
Player entity = link.getBukkitEntity();
unlink(entity);
@ -356,6 +358,7 @@ public class NMSImpl implements NMSBridge {
callback.accept(entity);
}
}
tracker.trackedPlayers.clear();
}
};
}
@ -1845,6 +1848,14 @@ public class NMSImpl implements NMSBridge {
NMSImpl.sendPacketsNearby(from, location, Arrays.asList(packets), 64);
}
public static void setLookControl(EntityInsentient mob, ControllerLook control) {
try {
LOOK_CONTROL_SETTER.invoke(mob, control);
} catch (Throwable e) {
e.printStackTrace();
}
}
public static void setSize(Entity entity, float f, float f1, boolean justCreated) {
if ((f != entity.width) || (f1 != entity.length)) {
float f2 = entity.width;
@ -1882,6 +1893,7 @@ public class NMSImpl implements NMSBridge {
private static final Set<EntityType> BAD_CONTROLLER_LOOK = EnumSet.of(EntityType.POLAR_BEAR, EntityType.SILVERFISH,
EntityType.ENDERMITE, EntityType.ENDER_DRAGON, EntityType.BAT, EntityType.SLIME, EntityType.MAGMA_CUBE,
EntityType.HORSE, EntityType.GHAST);
private static final Field CRAFT_BOSSBAR_HANDLE_FIELD = NMS.getField(CraftBossBar.class, "handle");
private static final float DEFAULT_SPEED = 1F;
private static final Field ENDERDRAGON_BATTLE_BAR_FIELD = NMS.getField(EnderDragonBattle.class, "c");
@ -1892,6 +1904,8 @@ public class NMSImpl implements NMSBridge {
private static final Location FROM_LOCATION = new Location(null, 0, 0, 0);
public static Field GOAL_FIELD = NMS.getField(PathfinderGoalSelector.class, "b");
private static final Field JUMP_FIELD = NMS.getField(EntityLiving.class, "be");
private static final MethodHandle LOOK_CONTROL_SETTER = NMS.getFirstSetter(EntityInsentient.class,
ControllerLook.class);
private static Method MAKE_REQUEST;
private static MethodHandle MOVE_CONTROLLER_MOVING = NMS.getSetter(ControllerMove.class, "h");
private static Field NAVIGATION_WORLD_FIELD = NMS.getField(NavigationAbstract.class, "b");

View File

@ -212,6 +212,7 @@ import net.minecraft.server.v1_11_R1.ChatMessage;
import net.minecraft.server.v1_11_R1.Container;
import net.minecraft.server.v1_11_R1.ContainerAnvil;
import net.minecraft.server.v1_11_R1.ControllerJump;
import net.minecraft.server.v1_11_R1.ControllerLook;
import net.minecraft.server.v1_11_R1.ControllerMove;
import net.minecraft.server.v1_11_R1.CrashReport;
import net.minecraft.server.v1_11_R1.CrashReportSystemDetails;
@ -370,6 +371,7 @@ public class NMSImpl implements NMSBridge {
@Override
public void unlinkAll(Consumer<Player> callback) {
handle.die();
for (EntityPlayer link : Lists.newArrayList(tracker.trackedPlayers)) {
Player entity = link.getBukkitEntity();
unlink(entity);
@ -377,6 +379,7 @@ public class NMSImpl implements NMSBridge {
callback.accept(entity);
}
}
tracker.trackedPlayers.clear();
}
};
}
@ -1906,6 +1909,14 @@ public class NMSImpl implements NMSBridge {
NMSImpl.sendPacketsNearby(from, location, Arrays.asList(packets), 64);
}
public static void setLookControl(EntityInsentient mob, ControllerLook control) {
try {
LOOK_CONTROL_SETTER.invoke(mob, control);
} catch (Throwable e) {
e.printStackTrace();
}
}
public static void setSize(Entity entity, float f, float f1, boolean justCreated) {
if ((f != entity.width) || (f1 != entity.length)) {
float f2 = entity.width;
@ -1943,6 +1954,7 @@ public class NMSImpl implements NMSBridge {
private static final Set<EntityType> BAD_CONTROLLER_LOOK = EnumSet.of(EntityType.POLAR_BEAR, EntityType.SILVERFISH,
EntityType.ENDERMITE, EntityType.ENDER_DRAGON, EntityType.BAT, EntityType.SLIME, EntityType.MAGMA_CUBE,
EntityType.HORSE, EntityType.GHAST);
private static final Field CRAFT_BOSSBAR_HANDLE_FIELD = NMS.getField(CraftBossBar.class, "handle");
private static final float DEFAULT_SPEED = 1F;
private static final Field ENDERDRAGON_BATTLE_BAR_FIELD = NMS.getField(EnderDragonBattle.class, "c");
@ -1952,6 +1964,8 @@ public class NMSImpl implements NMSBridge {
private static final Location FROM_LOCATION = new Location(null, 0, 0, 0);
public static Field GOAL_FIELD = NMS.getField(PathfinderGoalSelector.class, "b");
private static final Field JUMP_FIELD = NMS.getField(EntityLiving.class, "bd");
private static final MethodHandle LOOK_CONTROL_SETTER = NMS.getFirstSetter(EntityInsentient.class,
ControllerLook.class);
private static Method MAKE_REQUEST;
private static MethodHandle MOVE_CONTROLLER_MOVING = NMS.getSetter(ControllerMove.class, "h");
private static Field NAVIGATION_WORLD_FIELD = NMS.getField(NavigationAbstract.class, "b");

View File

@ -215,6 +215,7 @@ import net.minecraft.server.v1_12_R1.ChatMessage;
import net.minecraft.server.v1_12_R1.Container;
import net.minecraft.server.v1_12_R1.ContainerAnvil;
import net.minecraft.server.v1_12_R1.ControllerJump;
import net.minecraft.server.v1_12_R1.ControllerLook;
import net.minecraft.server.v1_12_R1.ControllerMove;
import net.minecraft.server.v1_12_R1.CrashReport;
import net.minecraft.server.v1_12_R1.CrashReportSystemDetails;
@ -375,6 +376,7 @@ public class NMSImpl implements NMSBridge {
@Override
public void unlinkAll(Consumer<Player> callback) {
handle.die();
for (EntityPlayer link : Lists.newArrayList(tracker.trackedPlayers)) {
Player entity = link.getBukkitEntity();
unlink(entity);
@ -382,6 +384,7 @@ public class NMSImpl implements NMSBridge {
callback.accept(entity);
}
}
tracker.trackedPlayers.clear();
}
};
}
@ -1913,6 +1916,14 @@ public class NMSImpl implements NMSBridge {
NMSImpl.sendPacketsNearby(from, location, Arrays.asList(packets), 64);
}
public static void setLookControl(EntityInsentient mob, ControllerLook control) {
try {
LOOK_CONTROL_SETTER.invoke(mob, control);
} catch (Throwable e) {
e.printStackTrace();
}
}
public static void setSize(Entity entity, float f, float f1, boolean justCreated) {
if ((f != entity.width) || (f1 != entity.length)) {
float f2 = entity.width;
@ -1960,6 +1971,8 @@ public class NMSImpl implements NMSBridge {
private static final Location FROM_LOCATION = new Location(null, 0, 0, 0);
public static Field GOAL_FIELD = NMS.getField(PathfinderGoalSelector.class, "b");
private static final Field JUMP_FIELD = NMS.getField(EntityLiving.class, "bd");
private static final MethodHandle LOOK_CONTROL_SETTER = NMS.getFirstSetter(EntityInsentient.class,
ControllerLook.class);
private static Method MAKE_REQUEST;
private static MethodHandle MOVE_CONTROLLER_MOVING = NMS.getSetter(ControllerMove.class, "h");
private static Field NAVIGATION_WORLD_FIELD = NMS.getField(NavigationAbstract.class, "b");

View File

@ -1,5 +1,6 @@
package net.citizensnpcs.nms.v1_12_R1.util;
import java.lang.invoke.MethodHandle;
import java.lang.reflect.Field;
import org.bukkit.Bukkit;
@ -14,6 +15,7 @@ import net.citizensnpcs.npc.ai.NPCHolder;
import net.citizensnpcs.util.NMS;
import net.minecraft.server.v1_12_R1.Entity;
import net.minecraft.server.v1_12_R1.EntityPlayer;
import net.minecraft.server.v1_12_R1.EntityTracker;
import net.minecraft.server.v1_12_R1.EntityTrackerEntry;
public class PlayerlistTrackerEntry extends EntityTrackerEntry {
@ -52,21 +54,31 @@ public class PlayerlistTrackerEntry extends EntityTrackerEntry {
@Override
public void updatePlayer(final EntityPlayer entityplayer) {
// prevent updates to NPC "viewers"
if ((entityplayer instanceof EntityHumanNPC) || (tracker instanceof NPCHolder
&& ((NPCHolder) tracker).getNPC().isHiddenFrom(entityplayer.getBukkitEntity())))
if (tracker instanceof NPCHolder) {
NPC npc = ((NPCHolder) tracker).getNPC();
if (npc.isHiddenFrom(entityplayer.getBukkitEntity()))
return;
Integer trackingRange = npc.data().<Integer> get(NPC.Metadata.TRACKING_RANGE);
if (TRACKING_RANGE_SETTER != null && trackingRange != null
&& npc.data().get("last-tracking-range", -1) != trackingRange.intValue()) {
try {
TRACKING_RANGE_SETTER.invoke(this, trackingRange);
npc.data().set("last-tracking-range", trackingRange);
} catch (Throwable e) {
e.printStackTrace();
}
}
}
if (entityplayer instanceof EntityHumanNPC)
return;
lastUpdatedPlayer = entityplayer;
this.lastUpdatedPlayer = entityplayer;
super.updatePlayer(entityplayer);
lastUpdatedPlayer = null;
}
private static int getE(EntityTrackerEntry entry) {
try {
Entity entity = getTracker(entry);
if (entity instanceof NPCHolder) {
return ((NPCHolder) entity).getNPC().data().get(NPC.Metadata.TRACKING_RANGE, (Integer) E.get(entry));
}
return (Integer) E.get(entry);
} catch (IllegalArgumentException e) {
e.printStackTrace();
@ -124,5 +136,6 @@ public class PlayerlistTrackerEntry extends EntityTrackerEntry {
private static Field F = NMS.getField(EntityTrackerEntry.class, "f");
private static Field G = NMS.getField(EntityTrackerEntry.class, "g");
private static Field TRACKER = NMS.getField(EntityTrackerEntry.class, "tracker");
private static final MethodHandle TRACKING_RANGE_SETTER = NMS.getFirstFinalSetter(EntityTracker.class, int.class);
private static Field U = NMS.getField(EntityTrackerEntry.class, "u");
}

View File

@ -228,6 +228,7 @@ import net.minecraft.server.v1_13_R2.ChatMessage;
import net.minecraft.server.v1_13_R2.Container;
import net.minecraft.server.v1_13_R2.ContainerAnvil;
import net.minecraft.server.v1_13_R2.ControllerJump;
import net.minecraft.server.v1_13_R2.ControllerLook;
import net.minecraft.server.v1_13_R2.ControllerMove;
import net.minecraft.server.v1_13_R2.CrashReport;
import net.minecraft.server.v1_13_R2.CrashReportSystemDetails;
@ -396,6 +397,7 @@ public class NMSImpl implements NMSBridge {
@Override
public void unlinkAll(Consumer<Player> callback) {
handle.die();
for (EntityPlayer link : Lists.newArrayList(tracker.trackedPlayers)) {
Player entity = link.getBukkitEntity();
unlink(entity);
@ -403,6 +405,7 @@ public class NMSImpl implements NMSBridge {
callback.accept(entity);
}
}
tracker.trackedPlayers.clear();
}
};
}
@ -2047,6 +2050,14 @@ public class NMSImpl implements NMSBridge {
NMSImpl.sendPacketsNearby(from, location, Arrays.asList(packets), 64);
}
public static void setLookControl(EntityInsentient mob, ControllerLook control) {
try {
LOOK_CONTROL_SETTER.invoke(mob, control);
} catch (Throwable e) {
e.printStackTrace();
}
}
public static void setNotInSchool(EntityFish entity) {
try {
if (ENTITY_FISH_NUM_IN_SCHOOL != null) {
@ -2111,6 +2122,8 @@ public class NMSImpl implements NMSBridge {
private static final Location FROM_LOCATION = new Location(null, 0, 0, 0);
public static Field GOAL_FIELD = NMS.getField(PathfinderGoalSelector.class, "b");
private static final Field JUMP_FIELD = NMS.getField(EntityLiving.class, "bg");
private static final MethodHandle LOOK_CONTROL_SETTER = NMS.getFirstSetter(EntityInsentient.class,
ControllerLook.class);
private static Method MAKE_REQUEST;
private static MethodHandle MOVE_CONTROLLER_MOVING = NMS.getSetter(ControllerMove.class, "h");
private static Field NAVIGATION_WORLD_FIELD = NMS.getField(NavigationAbstract.class, "b");

View File

@ -1,5 +1,6 @@
package net.citizensnpcs.nms.v1_13_R2.util;
import java.lang.invoke.MethodHandle;
import java.lang.reflect.Field;
import org.bukkit.Bukkit;
@ -14,6 +15,7 @@ import net.citizensnpcs.npc.ai.NPCHolder;
import net.citizensnpcs.util.NMS;
import net.minecraft.server.v1_13_R2.Entity;
import net.minecraft.server.v1_13_R2.EntityPlayer;
import net.minecraft.server.v1_13_R2.EntityTracker;
import net.minecraft.server.v1_13_R2.EntityTrackerEntry;
public class PlayerlistTrackerEntry extends EntityTrackerEntry {
@ -51,21 +53,31 @@ public class PlayerlistTrackerEntry extends EntityTrackerEntry {
@Override
public void updatePlayer(final EntityPlayer entityplayer) {
// prevent updates to NPC "viewers"
if ((entityplayer instanceof EntityHumanNPC) || (tracker instanceof NPCHolder
&& ((NPCHolder) tracker).getNPC().isHiddenFrom(entityplayer.getBukkitEntity())))
if (tracker instanceof NPCHolder) {
NPC npc = ((NPCHolder) tracker).getNPC();
if (npc.isHiddenFrom(entityplayer.getBukkitEntity()))
return;
Integer trackingRange = npc.data().<Integer> get(NPC.Metadata.TRACKING_RANGE);
if (TRACKING_RANGE_SETTER != null && trackingRange != null
&& npc.data().get("last-tracking-range", -1) != trackingRange.intValue()) {
try {
TRACKING_RANGE_SETTER.invoke(this, trackingRange);
npc.data().set("last-tracking-range", trackingRange);
} catch (Throwable e) {
e.printStackTrace();
}
}
}
if (entityplayer instanceof EntityHumanNPC)
return;
lastUpdatedPlayer = entityplayer;
this.lastUpdatedPlayer = entityplayer;
super.updatePlayer(entityplayer);
lastUpdatedPlayer = null;
}
private static int getE(EntityTrackerEntry entry) {
try {
Entity entity = getTracker(entry);
if (entity instanceof NPCHolder) {
return ((NPCHolder) entity).getNPC().data().get(NPC.Metadata.TRACKING_RANGE, (Integer) E.get(entry));
}
return (Integer) E.get(entry);
} catch (IllegalArgumentException e) {
e.printStackTrace();
@ -123,5 +135,6 @@ public class PlayerlistTrackerEntry extends EntityTrackerEntry {
private static Field F = NMS.getField(EntityTrackerEntry.class, "f");
private static Field G = NMS.getField(EntityTrackerEntry.class, "g");
private static Field TRACKER = NMS.getField(EntityTrackerEntry.class, "tracker");
private static final MethodHandle TRACKING_RANGE_SETTER = NMS.getFirstFinalSetter(EntityTracker.class, int.class);
private static Field U = NMS.getField(EntityTrackerEntry.class, "u");
}

View File

@ -436,6 +436,7 @@ public class NMSImpl implements NMSBridge {
@Override
public void unlinkAll(Consumer<Player> callback) {
handle.die();
for (EntityPlayer link : Lists.newArrayList(linked)) {
Player entity = link.getBukkitEntity();
unlink(entity);
@ -443,6 +444,7 @@ public class NMSImpl implements NMSBridge {
callback.accept(entity);
}
}
linked.clear();
}
};
}

View File

@ -48,14 +48,27 @@ public class PlayerlistTracker extends PlayerChunkMap.EntityTracker {
@Override
public void updatePlayer(final EntityPlayer entityplayer) {
if (!(entityplayer instanceof EntityHumanNPC)) {
// prevent updates to NPC "viewers"
if (tracker instanceof NPCHolder
&& ((NPCHolder) tracker).getNPC().isHiddenFrom(entityplayer.getBukkitEntity()))
if (tracker instanceof NPCHolder) {
NPC npc = ((NPCHolder) tracker).getNPC();
if (npc.isHiddenFrom(entityplayer.getBukkitEntity()))
return;
lastUpdatedPlayer = entityplayer;
super.updatePlayer(entityplayer);
Integer trackingRange = npc.data().<Integer> get(NPC.Metadata.TRACKING_RANGE);
if (TRACKING_RANGE_SETTER != null && trackingRange != null
&& npc.data().get("last-tracking-range", -1) != trackingRange.intValue()) {
try {
TRACKING_RANGE_SETTER.invoke(this, trackingRange);
npc.data().set("last-tracking-range", trackingRange);
} catch (Throwable e) {
e.printStackTrace();
}
}
}
if (entityplayer instanceof EntityHumanNPC)
return;
this.lastUpdatedPlayer = entityplayer;
super.updatePlayer(entityplayer);
}
private static int getD(EntityTracker entry) {
@ -87,11 +100,6 @@ public class PlayerlistTracker extends PlayerChunkMap.EntityTracker {
private static int getTrackingDistance(EntityTracker entry) {
try {
Entity entity = getTracker(entry);
if (entity instanceof NPCHolder) {
return ((NPCHolder) entity).getNPC().data().get(NPC.Metadata.TRACKING_RANGE,
(Integer) TRACKING_RANGE.invoke(entry));
}
return (Integer) TRACKING_RANGE.invoke(entry);
} catch (Throwable e) {
e.printStackTrace();
@ -104,4 +112,5 @@ public class PlayerlistTracker extends PlayerChunkMap.EntityTracker {
private static final MethodHandle TRACKER = NMS.getGetter(EntityTracker.class, "tracker");
private static final MethodHandle TRACKER_ENTRY = NMS.getGetter(EntityTracker.class, "trackerEntry");
private static final MethodHandle TRACKING_RANGE = NMS.getGetter(EntityTracker.class, "trackingDistance");
private static final MethodHandle TRACKING_RANGE_SETTER = NMS.getFirstFinalSetter(EntityTracker.class, int.class);
}

View File

@ -451,6 +451,7 @@ public class NMSImpl implements NMSBridge {
@Override
public void unlinkAll(Consumer<Player> callback) {
handle.die();
for (EntityPlayer link : Lists.newArrayList(linked)) {
Player entity = link.getBukkitEntity();
unlink(entity);
@ -458,6 +459,7 @@ public class NMSImpl implements NMSBridge {
callback.accept(entity);
}
}
linked.clear();
}
};
}

View File

@ -48,14 +48,27 @@ public class PlayerlistTracker extends PlayerChunkMap.EntityTracker {
@Override
public void updatePlayer(final EntityPlayer entityplayer) {
if (!(entityplayer instanceof EntityHumanNPC)) {
if (tracker instanceof NPCHolder
&& ((NPCHolder) tracker).getNPC().isHiddenFrom(entityplayer.getBukkitEntity()))
if (tracker instanceof NPCHolder) {
NPC npc = ((NPCHolder) tracker).getNPC();
if (npc.isHiddenFrom(entityplayer.getBukkitEntity()))
return;
// prevent updates to NPC "viewers"
this.lastUpdatedPlayer = entityplayer;
super.updatePlayer(entityplayer);
Integer trackingRange = npc.data().<Integer> get(NPC.Metadata.TRACKING_RANGE);
if (TRACKING_RANGE_SETTER != null && trackingRange != null
&& npc.data().get("last-tracking-range", -1) != trackingRange.intValue()) {
try {
TRACKING_RANGE_SETTER.invoke(this, trackingRange);
npc.data().set("last-tracking-range", trackingRange);
} catch (Throwable e) {
e.printStackTrace();
}
}
}
if (entityplayer instanceof EntityHumanNPC)
return;
this.lastUpdatedPlayer = entityplayer;
super.updatePlayer(entityplayer);
}
private static int getD(EntityTracker entry) {
@ -87,11 +100,6 @@ public class PlayerlistTracker extends PlayerChunkMap.EntityTracker {
private static int getTrackingDistance(EntityTracker entry) {
try {
Entity entity = getTracker(entry);
if (entity instanceof NPCHolder) {
return ((NPCHolder) entity).getNPC().data().get(NPC.Metadata.TRACKING_RANGE,
(Integer) TRACKING_RANGE.invoke(entry));
}
return (Integer) TRACKING_RANGE.invoke(entry);
} catch (Throwable e) {
e.printStackTrace();
@ -104,4 +112,5 @@ public class PlayerlistTracker extends PlayerChunkMap.EntityTracker {
private static final MethodHandle TRACKER = NMS.getGetter(EntityTracker.class, "tracker");
private static final MethodHandle TRACKER_ENTRY = NMS.getGetter(EntityTracker.class, "trackerEntry");
private static final MethodHandle TRACKING_RANGE = NMS.getGetter(EntityTracker.class, "trackingDistance");
private static final MethodHandle TRACKING_RANGE_SETTER = NMS.getFirstFinalSetter(EntityTracker.class, int.class);
}

View File

@ -465,6 +465,7 @@ public class NMSImpl implements NMSBridge {
@Override
public void unlinkAll(Consumer<Player> callback) {
handle.die();
for (EntityPlayer link : Lists.newArrayList(linked)) {
Player entity = link.getBukkitEntity();
unlink(entity);
@ -472,6 +473,7 @@ public class NMSImpl implements NMSBridge {
callback.accept(entity);
}
}
linked.clear();
}
};
}

View File

@ -50,9 +50,25 @@ public class PlayerlistTracker extends PlayerChunkMap.EntityTracker {
@Override
public void updatePlayer(final EntityPlayer entityplayer) {
if ((entityplayer instanceof EntityHumanNPC) || (tracker instanceof NPCHolder
&& ((NPCHolder) tracker).getNPC().isHiddenFrom(entityplayer.getBukkitEntity())))
if (tracker instanceof NPCHolder) {
NPC npc = ((NPCHolder) tracker).getNPC();
if (npc.isHiddenFrom(entityplayer.getBukkitEntity()))
return;
Integer trackingRange = npc.data().<Integer> get(NPC.Metadata.TRACKING_RANGE);
if (TRACKING_RANGE_SETTER != null && trackingRange != null
&& npc.data().get("last-tracking-range", -1) != trackingRange.intValue()) {
try {
TRACKING_RANGE_SETTER.invoke(this, trackingRange);
npc.data().set("last-tracking-range", trackingRange);
} catch (Throwable e) {
e.printStackTrace();
}
}
}
if (entityplayer instanceof EntityHumanNPC)
return;
this.lastUpdatedPlayer = entityplayer;
super.updatePlayer(entityplayer);
}
@ -86,11 +102,6 @@ public class PlayerlistTracker extends PlayerChunkMap.EntityTracker {
private static int getTrackingDistance(EntityTracker entry) {
try {
Entity entity = getTracker(entry);
if (entity instanceof NPCHolder) {
return ((NPCHolder) entity).getNPC().data().get(NPC.Metadata.TRACKING_RANGE,
(Integer) TRACKING_RANGE.invoke(entry));
}
return (Integer) TRACKING_RANGE.invoke(entry);
} catch (Throwable e) {
e.printStackTrace();
@ -103,4 +114,5 @@ public class PlayerlistTracker extends PlayerChunkMap.EntityTracker {
private static final MethodHandle TRACKER = NMS.getGetter(EntityTracker.class, "tracker");
private static final MethodHandle TRACKER_ENTRY = NMS.getGetter(EntityTracker.class, "trackerEntry");
private static final MethodHandle TRACKING_RANGE = NMS.getGetter(EntityTracker.class, "trackingDistance");
private static final MethodHandle TRACKING_RANGE_SETTER = NMS.getFirstFinalSetter(EntityTracker.class, int.class);
}

View File

@ -478,6 +478,7 @@ public class NMSImpl implements NMSBridge {
@Override
public void unlinkAll(Consumer<Player> callback) {
handle.remove(RemovalReason.KILLED);
for (ServerPlayerConnection link : Lists.newArrayList(linked)) {
Player entity = link.getPlayer().getBukkitEntity();
unlink(entity);
@ -485,6 +486,7 @@ public class NMSImpl implements NMSBridge {
callback.accept(entity);
}
}
linked.clear();
}
};
}

View File

@ -51,9 +51,25 @@ public class PlayerlistTracker extends ChunkMap.TrackedEntity {
@Override
public void updatePlayer(final ServerPlayer entityplayer) {
if ((entityplayer instanceof EntityHumanNPC) || (tracker instanceof NPCHolder
&& ((NPCHolder) tracker).getNPC().isHiddenFrom(entityplayer.getBukkitEntity())))
if (tracker instanceof NPCHolder) {
NPC npc = ((NPCHolder) tracker).getNPC();
if (npc.isHiddenFrom(entityplayer.getBukkitEntity()))
return;
Integer trackingRange = npc.data().<Integer> get(NPC.Metadata.TRACKING_RANGE);
if (TRACKING_RANGE_SETTER != null && trackingRange != null
&& npc.data().get("last-tracking-range", -1) != trackingRange.intValue()) {
try {
TRACKING_RANGE_SETTER.invoke(this, trackingRange);
npc.data().set("last-tracking-range", trackingRange);
} catch (Throwable e) {
e.printStackTrace();
}
}
}
if (entityplayer instanceof EntityHumanNPC)
return;
this.lastUpdatedPlayer = entityplayer;
super.updatePlayer(entityplayer);
}
@ -87,11 +103,6 @@ public class PlayerlistTracker extends ChunkMap.TrackedEntity {
private static int getTrackingDistance(TrackedEntity entry) {
try {
Entity entity = getTracker(entry);
if (entity instanceof NPCHolder) {
return ((NPCHolder) entity).getNPC().data().get(NPC.Metadata.TRACKING_RANGE,
(Integer) TRACKING_RANGE.invoke(entry));
}
return (Integer) TRACKING_RANGE.invoke(entry);
} catch (Throwable e) {
e.printStackTrace();
@ -104,4 +115,5 @@ public class PlayerlistTracker extends ChunkMap.TrackedEntity {
private static final MethodHandle TRACKER = NMS.getFirstGetter(TrackedEntity.class, Entity.class);
private static final MethodHandle TRACKER_ENTRY = NMS.getFirstGetter(TrackedEntity.class, ServerEntity.class);
private static final MethodHandle TRACKING_RANGE = NMS.getFirstGetter(TrackedEntity.class, int.class);
private static final MethodHandle TRACKING_RANGE_SETTER = NMS.getFirstFinalSetter(TrackedEntity.class, int.class);
}

View File

@ -484,6 +484,7 @@ public class NMSImpl implements NMSBridge {
@Override
public void unlinkAll(Consumer<Player> callback) {
handle.remove(RemovalReason.KILLED);
for (ServerPlayerConnection link : Lists.newArrayList(linked)) {
Player entity = link.getPlayer().getBukkitEntity();
unlink(entity);
@ -491,6 +492,7 @@ public class NMSImpl implements NMSBridge {
callback.accept(entity);
}
}
linked.clear();
}
};
}

View File

@ -51,9 +51,25 @@ public class PlayerlistTracker extends ChunkMap.TrackedEntity {
@Override
public void updatePlayer(final ServerPlayer entityplayer) {
if ((entityplayer instanceof EntityHumanNPC) || (tracker instanceof NPCHolder
&& ((NPCHolder) tracker).getNPC().isHiddenFrom(entityplayer.getBukkitEntity())))
if (tracker instanceof NPCHolder) {
NPC npc = ((NPCHolder) tracker).getNPC();
if (npc.isHiddenFrom(entityplayer.getBukkitEntity()))
return;
Integer trackingRange = npc.data().<Integer> get(NPC.Metadata.TRACKING_RANGE);
if (TRACKING_RANGE_SETTER != null && trackingRange != null
&& npc.data().get("last-tracking-range", -1) != trackingRange.intValue()) {
try {
TRACKING_RANGE_SETTER.invoke(this, trackingRange);
npc.data().set("last-tracking-range", trackingRange);
} catch (Throwable e) {
e.printStackTrace();
}
}
}
if (entityplayer instanceof EntityHumanNPC)
return;
this.lastUpdatedPlayer = entityplayer;
super.updatePlayer(entityplayer);
}
@ -87,11 +103,6 @@ public class PlayerlistTracker extends ChunkMap.TrackedEntity {
private static int getTrackingDistance(TrackedEntity entry) {
try {
Entity entity = getTracker(entry);
if (entity instanceof NPCHolder) {
return ((NPCHolder) entity).getNPC().data().get(NPC.Metadata.TRACKING_RANGE,
(Integer) TRACKING_RANGE.invoke(entry));
}
return (Integer) TRACKING_RANGE.invoke(entry);
} catch (Throwable e) {
e.printStackTrace();
@ -104,4 +115,5 @@ public class PlayerlistTracker extends ChunkMap.TrackedEntity {
private static final MethodHandle TRACKER = NMS.getFirstGetter(TrackedEntity.class, Entity.class);
private static final MethodHandle TRACKER_ENTRY = NMS.getFirstGetter(TrackedEntity.class, ServerEntity.class);
private static final MethodHandle TRACKING_RANGE = NMS.getFirstGetter(TrackedEntity.class, int.class);
private static final MethodHandle TRACKING_RANGE_SETTER = NMS.getFirstFinalSetter(TrackedEntity.class, int.class);
}

View File

@ -61,8 +61,8 @@ public class EnderDragonController extends MobEntityController {
@Override
public void aiStep() {
if (npc != null) {
npc.update();
NMSImpl.updateMinecraftAIState(npc, this);
npc.update();
}
if (npc != null && !npc.useMinecraftAI()) {
if (getFirstPassenger() != null) {
@ -97,8 +97,6 @@ public class EnderDragonController extends MobEntityController {
}
}
@Override
protected SoundEvent getAmbientSound() {
return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND);

View File

@ -117,12 +117,9 @@ public class EntityHumanNPC extends ServerPlayer implements NPCHolder, Skinnable
return;
}
super.die(damagesource);
Bukkit.getScheduler().runTaskLater(CitizensAPI.getPlugin(), new Runnable() {
@Override
public void run() {
EntityHumanNPC.this.getLevel().removePlayerImmediately(EntityHumanNPC.this, RemovalReason.KILLED);
((ServerLevel) level).getChunkSource().removeEntity(EntityHumanNPC.this);
}
Bukkit.getScheduler().runTaskLater(CitizensAPI.getPlugin(), () -> {
EntityHumanNPC.this.getLevel().removePlayerImmediately(EntityHumanNPC.this, RemovalReason.KILLED);
((ServerLevel) level).getChunkSource().removeEntity(EntityHumanNPC.this);
}, 15); // give enough time for death and smoke animation
}

View File

@ -75,8 +75,23 @@ public class CitizensEntityTracker extends ChunkMap.TrackedEntity {
@Override
public void updatePlayer(final ServerPlayer entityplayer) {
if ((entityplayer instanceof EntityHumanNPC) || (tracker instanceof NPCHolder
&& ((NPCHolder) tracker).getNPC().isHiddenFrom(entityplayer.getBukkitEntity())))
if (tracker instanceof NPCHolder) {
NPC npc = ((NPCHolder) tracker).getNPC();
if (npc.isHiddenFrom(entityplayer.getBukkitEntity()))
return;
Integer trackingRange = npc.data().<Integer> get(NPC.Metadata.TRACKING_RANGE);
if (TRACKING_RANGE_SETTER != null && trackingRange != null
&& npc.data().get("last-tracking-range", -1) != trackingRange.intValue()) {
try {
TRACKING_RANGE_SETTER.invoke(this, trackingRange);
npc.data().set("last-tracking-range", trackingRange);
} catch (Throwable e) {
e.printStackTrace();
}
}
}
if (entityplayer instanceof EntityHumanNPC)
return;
this.lastUpdatedPlayer = entityplayer;
@ -112,11 +127,6 @@ public class CitizensEntityTracker extends ChunkMap.TrackedEntity {
private static int getTrackingDistance(TrackedEntity entry) {
try {
Entity entity = getTracker(entry);
if (entity instanceof NPCHolder) {
return ((NPCHolder) entity).getNPC().data().get(NPC.Metadata.TRACKING_RANGE,
(Integer) TRACKING_RANGE.invoke(entry));
}
return (Integer) TRACKING_RANGE.invoke(entry);
} catch (Throwable e) {
e.printStackTrace();
@ -129,6 +139,7 @@ public class CitizensEntityTracker extends ChunkMap.TrackedEntity {
private static final MethodHandle TRACKER = NMS.getFirstGetter(TrackedEntity.class, Entity.class);
private static final MethodHandle TRACKER_ENTRY = NMS.getFirstGetter(TrackedEntity.class, ServerEntity.class);
private static final MethodHandle TRACKING_RANGE = NMS.getFirstGetter(TrackedEntity.class, int.class);
private static final MethodHandle TRACKING_RANGE_SETTER = NMS.getFirstFinalSetter(TrackedEntity.class, int.class);
private static final MethodHandle TRACKING_SET_GETTER = NMS.getFirstGetter(TrackedEntity.class, Set.class);
private static final MethodHandle TRACKING_SET_SETTER = NMS.getFirstFinalSetter(TrackedEntity.class, Set.class);
}

View File

@ -508,6 +508,7 @@ public class NMSImpl implements NMSBridge {
@Override
public void unlinkAll(Consumer<Player> callback) {
handle.remove(RemovalReason.KILLED);
for (ServerPlayerConnection link : Lists.newArrayList(linked)) {
Player entity = link.getPlayer().getBukkitEntity();
unlink(entity);
@ -515,6 +516,7 @@ public class NMSImpl implements NMSBridge {
callback.accept(entity);
}
}
linked.clear();
}
};
}
@ -2288,7 +2290,7 @@ public class NMSImpl implements NMSBridge {
public static void setAdvancement(Player entity, PlayerAdvancements instance) {
try {
ADVANCEMENTS_PLAYER_FIELD.invoke(getHandle(entity), instance);
ADVANCEMENTS_PLAYER_SETTER.invoke(getHandle(entity), instance);
} catch (Throwable e) {
e.printStackTrace();
}
@ -2452,10 +2454,11 @@ public class NMSImpl implements NMSBridge {
}
}
private static final MethodHandle ADVANCEMENTS_PLAYER_FIELD = NMS.getFirstFinalSetter(ServerPlayer.class,
private static final MethodHandle ADVANCEMENTS_PLAYER_SETTER = NMS.getFirstFinalSetter(ServerPlayer.class,
PlayerAdvancements.class);
private static final MethodHandle ATTRIBUTE_PROVIDER_MAP = NMS.getFirstGetter(AttributeSupplier.class, Map.class);
private static final MethodHandle ATTRIBUTE_PROVIDER_MAP_SETTER = NMS.getFinalSetter(AttributeSupplier.class, "a");
private static final MethodHandle ATTRIBUTE_PROVIDER_MAP_SETTER = NMS.getFirstFinalSetter(AttributeSupplier.class,
Map.class);
private static final MethodHandle ATTRIBUTE_SUPPLIER = NMS.getFirstGetter(AttributeMap.class,
AttributeSupplier.class);
private static final Set<EntityType> BAD_CONTROLLER_LOOK = EnumSet.of(EntityType.POLAR_BEAR, EntityType.BEE,
@ -2468,7 +2471,8 @@ public class NMSImpl implements NMSBridge {
ServerPlayer.class, boolean.class);
private static final Map<Class<?>, net.minecraft.world.entity.EntityType<?>> CITIZENS_ENTITY_TYPES = Maps
.newHashMap();
private static final MethodHandle CRAFT_BOSSBAR_HANDLE_FIELD = NMS.getSetter(CraftBossBar.class, "handle");
private static final MethodHandle CRAFT_BOSSBAR_HANDLE_FIELD = NMS.getFirstSetter(CraftBossBar.class,
ServerBossEvent.class);
private static final float DEFAULT_SPEED = 1F;
private static EntityDataAccessor<Boolean> ENDERMAN_CREEPY = null;
private static final MethodHandle ENTITY_FISH_NUM_IN_SCHOOL = NMS.getFirstSetter(AbstractSchoolingFish.class,
@ -2501,10 +2505,12 @@ public class NMSImpl implements NMSBridge {
PathFinder.class);
private static final MethodHandle NAVIGATION_WORLD_FIELD = NMS.getFirstSetter(PathNavigation.class, Level.class);
private static final Location PACKET_CACHE_LOCATION = new Location(null, 0, 0, 0);
private static final MethodHandle PLAYER_CHUNK_MAP_VIEW_DISTANCE_GETTER = NMS.getGetter(ChunkMap.class, "P");
private static final MethodHandle PLAYER_CHUNK_MAP_VIEW_DISTANCE_SETTER = NMS.getSetter(ChunkMap.class, "P");
private static final MethodHandle PLAYER_CHUNK_MAP_VIEW_DISTANCE_GETTER = NMS.getFirstGetter(ChunkMap.class,
int.class);
private static final MethodHandle PLAYER_CHUNK_MAP_VIEW_DISTANCE_SETTER = NMS.getFirstSetter(ChunkMap.class,
int.class);
private static final MethodHandle PLAYER_INFO_ENTRIES_LIST = NMS
.getFinalSetter(ClientboundPlayerInfoUpdatePacket.class, "b");
.getFirstFinalSetter(ClientboundPlayerInfoUpdatePacket.class, List.class);
private static final MethodHandle PLAYERINFO_ENTRIES = PLAYER_INFO_ENTRIES_LIST;
private static MethodHandle PORTAL_ENTRANCE_POS_GETTER = NMS.getGetter(Entity.class, "aw");
private static MethodHandle PORTAL_ENTRANCE_POS_SETTER = NMS.getSetter(Entity.class, "aw");
@ -2529,9 +2535,7 @@ public class NMSImpl implements NMSBridge {
try {
// Middle one
ENDERMAN_CREEPY = (EntityDataAccessor<Boolean>) NMS.getField(EnderMan.class, "bU").get(null);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
} catch (Exception e) {
e.printStackTrace();
}
try {

View File

@ -108,8 +108,6 @@ public class EnderDragonController extends MobEntityController {
}
}
@Override
public void g(double x, double y, double z) {
Vector vector = Util.callPushEvent(npc, x, y, z);

View File

@ -178,6 +178,7 @@ import net.minecraft.server.v1_8_R3.ChatMessage;
import net.minecraft.server.v1_8_R3.Container;
import net.minecraft.server.v1_8_R3.ContainerAnvil;
import net.minecraft.server.v1_8_R3.ControllerJump;
import net.minecraft.server.v1_8_R3.ControllerLook;
import net.minecraft.server.v1_8_R3.ControllerMove;
import net.minecraft.server.v1_8_R3.CrashReport;
import net.minecraft.server.v1_8_R3.CrashReportSystemDetails;
@ -329,6 +330,7 @@ public class NMSImpl implements NMSBridge {
@Override
public void unlinkAll(Consumer<Player> callback) {
handle.die();
for (EntityPlayer link : Lists.newArrayList(tracker.trackedPlayers)) {
Player entity = link.getBukkitEntity();
unlink(entity);
@ -336,6 +338,7 @@ public class NMSImpl implements NMSBridge {
callback.accept(entity);
}
}
tracker.trackedPlayers.clear();
}
};
}
@ -1704,6 +1707,14 @@ public class NMSImpl implements NMSBridge {
NMSImpl.sendPacketsNearby(from, location, Arrays.asList(packets), 64);
}
public static void setLookControl(EntityInsentient mob, ControllerLook control) {
try {
LOOK_CONTROL_SETTER.invoke(mob, control);
} catch (Throwable e) {
e.printStackTrace();
}
}
public static void setSize(Entity entity, float f, float f1, boolean justCreated) {
if ((f != entity.width) || (f1 != entity.length)) {
float f2 = entity.width;
@ -1741,6 +1752,7 @@ public class NMSImpl implements NMSBridge {
private static final Set<EntityType> BAD_CONTROLLER_LOOK = EnumSet.of(EntityType.SILVERFISH, EntityType.ENDERMITE,
EntityType.ENDER_DRAGON, EntityType.BAT, EntityType.SLIME, EntityType.MAGMA_CUBE, EntityType.HORSE,
EntityType.GHAST);
private static final float DEFAULT_SPEED = 1F;
private static Method ENTITY_ATTACK_A = NMS.getMethod(Entity.class, "a", true, EntityLiving.class, Entity.class);
private static Map<Class<?>, Integer> ENTITY_CLASS_TO_INT;
@ -1749,6 +1761,8 @@ public class NMSImpl implements NMSBridge {
private static Method GET_NMS_BLOCK = NMS.getMethod(CraftBlock.class, "getNMSBlock", false);
private static Field GOAL_FIELD = NMS.getField(PathfinderGoalSelector.class, "b");
private static final Field JUMP_FIELD = NMS.getField(EntityLiving.class, "aY");
private static final MethodHandle LOOK_CONTROL_SETTER = NMS.getFirstSetter(EntityInsentient.class,
ControllerLook.class);
private static Method MAKE_REQUEST;
private static Field MOVE_CONTROLLER_MOVING = NMS.getField(ControllerMove.class, "f");
private static Field NAVIGATION_WORLD_FIELD = NMS.getField(NavigationAbstract.class, "c");