Skip to content

Commit

Permalink
Replace entity tracked fields as well as chunk map ones
Browse files Browse the repository at this point in the history
  • Loading branch information
fullwall committed Jul 12, 2024
1 parent ec51df2 commit 6d18bc1
Show file tree
Hide file tree
Showing 8 changed files with 100 additions and 57 deletions.
8 changes: 4 additions & 4 deletions main/src/main/java/net/citizensnpcs/commands/NPCCommands.java
Original file line number Diff line number Diff line change
Expand Up @@ -912,8 +912,8 @@ else if (!EntityControllers.controllerExistsForType(type))
for (String part : parts) {
if (part.contains(":")) {
int idx = part.indexOf(':');
Template template = templateRegistry.getTemplateByKey(
new NamespacedKey(part.substring(0, idx), part.substring(idx + 1).toLowerCase(Locale.US)));
Template template = templateRegistry.getTemplateByKey(new NamespacedKey(part.substring(0, idx),
part.substring(idx + 1).toLowerCase(Locale.ROOT)));
if (template == null)
continue;
template.apply(npc);
Expand Down Expand Up @@ -1263,7 +1263,7 @@ public void hitbox(CommandContext args, CommandSender sender, NPC npc, @Flag("sc

@Command(
aliases = { "npc" },
usage = "hologram add [text] | set [line #] [text] | remove [line #] | bgcolor [line #] (color) | clear | lineheight [height] | viewrange [range] | margintop [line #] [margin] | marginbottom [line #] [margin]",
usage = "hologram add [text] | set [line #] [text] | remove [line #] | bgcolor [line #] (red,green,blue(,alpha)) | clear | lineheight [height] | viewrange [range] | margintop [line #] [margin] | marginbottom [line #] [margin]",
desc = "",
modifiers = { "hologram" },
min = 1,
Expand Down Expand Up @@ -3661,7 +3661,7 @@ public void wolf(CommandContext args, CommandSender sender, NPC npc, @Flag("coll
trait.setInterested(!trait.isInterested());
}
if (variant != null) {
variant = variant.toUpperCase(Locale.US);
variant = variant.toUpperCase(Locale.ROOT);
try {
Wolf.Variant.class.getField(variant);
} catch (Throwable t) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public void apply(CommandContext args, CommandSender sender, NPC npc,
if (templateKey.contains(":")) {
int idx = templateKey.indexOf(':');
template = registry.getTemplateByKey(new NamespacedKey(templateKey.substring(0, idx),
templateKey.substring(idx + 1).toLowerCase(Locale.US)));
templateKey.substring(idx + 1).toLowerCase(Locale.ROOT)));
} else {
Collection<Template> templates = registry.getTemplates(templateKey);
if (templates.isEmpty())
Expand Down Expand Up @@ -73,9 +73,9 @@ public void generate(CommandContext args, CommandSender sender, NPC npc,
@Arg(value = 1, completionsProvider = TemplateCompletions.class) String templateName)
throws CommandException {
int idx = templateName.indexOf(':');
NamespacedKey key = idx == -1 ? new NamespacedKey("generated", templateName.toLowerCase(Locale.US))
NamespacedKey key = idx == -1 ? new NamespacedKey("generated", templateName.toLowerCase(Locale.ROOT))
: new NamespacedKey(templateName.substring(0, idx),
templateName.substring(idx + 1).toLowerCase(Locale.US));
templateName.substring(idx + 1).toLowerCase(Locale.ROOT));
if (registry.getTemplateByKey(key) != null)
throw new CommandException(Messages.TEMPLATE_CONFLICT);
registry.generateTemplateFromNPC(key, npc);
Expand Down
64 changes: 37 additions & 27 deletions main/src/main/java/net/citizensnpcs/npc/CitizensNPC.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

import com.google.common.base.Throwables;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Iterables;
import com.google.common.collect.ObjectArrays;
import com.google.common.collect.SetMultimap;

import net.citizensnpcs.NPCNeedsRespawnEvent;
Expand Down Expand Up @@ -381,15 +381,15 @@ public void accept(Runnable cancel) {
return;
}
navigator.onSpawn();
for (Trait trait : Iterables.toArray(traits.values(), Trait.class)) {

for (Trait trait : traits.values().toArray(ObjectArrays.newArray(Trait.class, traits.size()))) {
try {
trait.onSpawn();
} catch (Throwable ex) {
Messaging.severeTr(Messages.TRAIT_ONSPAWN_FAILED, trait.getName(), getId());
ex.printStackTrace();
}
}
// Replace the entity tracker
NMS.replaceTracker(getEntity());
EntityType type = getEntity().getType();
if (type.isAlive()) {
Expand Down Expand Up @@ -479,21 +479,21 @@ public void update() {
resetCachedCoord();
return;
}
Location loc = getEntity().getLocation();
if (data().has(NPC.Metadata.ACTIVATION_RANGE)) {
int range = data().get(NPC.Metadata.ACTIVATION_RANGE);
if (range == -1 || CitizensAPI.getLocationLookup().getNearbyPlayers(getStoredLocation(), range)
.iterator().hasNext()) {
if (range == -1 || CitizensAPI.getLocationLookup().getNearbyPlayers(loc, range).iterator().hasNext()) {
NMS.activate(getEntity());
}
}
boolean shouldSwim = data().get(NPC.Metadata.SWIM, SwimmingExaminer.isWaterMob(getEntity()))
&& MinecraftBlockExaminer.isLiquid(getEntity().getLocation().getBlock().getType());
&& MinecraftBlockExaminer.isLiquid(loc.getBlock().getType());
if (navigator.isNavigating()) {
if (shouldSwim) {
getEntity().setVelocity(getEntity().getVelocity().multiply(
data().get(NPC.Metadata.WATER_SPEED_MODIFIER, Setting.NPC_WATER_SPEED_MODIFIER.asFloat())));
Location currentDest = navigator.getPathStrategy().getCurrentDestination();
if (currentDest == null || currentDest.getY() > getStoredLocation().getY()) {
if (currentDest == null || currentDest.getY() > loc.getY()) {
NMS.trySwim(getEntity());
}
}
Expand All @@ -504,23 +504,15 @@ public void update() {
}
}
if (SUPPORT_GLOWING && data().has(NPC.Metadata.GLOWING)) {
try {
getEntity().setGlowing(data().get(NPC.Metadata.GLOWING, false));
} catch (NoSuchMethodError e) {
SUPPORT_GLOWING = false;
}
getEntity().setGlowing(data().get(NPC.Metadata.GLOWING, false));
}
if (SUPPORT_SILENT && data().has(NPC.Metadata.SILENT)) {
try {
getEntity().setSilent(Boolean.parseBoolean(data().get(NPC.Metadata.SILENT).toString()));
} catch (NoSuchMethodError e) {
SUPPORT_SILENT = false;
}
getEntity().setSilent(Boolean.parseBoolean(data().get(NPC.Metadata.SILENT).toString()));
}
boolean isLiving = getEntity() instanceof LivingEntity;
if (isUpdating(NPCUpdate.PACKET)) {
if (data().get(NPC.Metadata.KEEP_CHUNK_LOADED, Setting.KEEP_CHUNKS_LOADED.asBoolean())) {
ChunkCoord currentCoord = new ChunkCoord(getStoredLocation());
ChunkCoord currentCoord = new ChunkCoord(loc);
if (!currentCoord.equals(cachedCoord)) {
resetCachedCoord();
currentCoord.setForceLoaded(true);
Expand All @@ -538,11 +530,7 @@ public void update() {
if (isLiving) {
NMS.setKnockbackResistance((LivingEntity) getEntity(), isProtected() ? 1D : 0D);
if (SUPPORT_PICKUP_ITEMS) {
try {
((LivingEntity) getEntity()).setCanPickupItems(data().get(NPC.Metadata.PICKUP_ITEMS, false));
} catch (Throwable t) {
SUPPORT_PICKUP_ITEMS = false;
}
((LivingEntity) getEntity()).setCanPickupItems(data().get(NPC.Metadata.PICKUP_ITEMS, false));
}
if (getEntity() instanceof Player) {
updateUsingItemState((Player) getEntity());
Expand Down Expand Up @@ -622,9 +610,31 @@ private void updateUsingItemState(Player player) {
}

private static SetMultimap<ChunkCoord, NPC> CHUNK_LOADERS = HashMultimap.create();
private static boolean SUPPORT_GLOWING = true;
private static boolean SUPPORT_NODAMAGE_TICKS = true;
private static boolean SUPPORT_PICKUP_ITEMS = true;
private static boolean SUPPORT_SILENT = true;
private static boolean SUPPORT_GLOWING = false;
private static boolean SUPPORT_NODAMAGE_TICKS = false;
private static boolean SUPPORT_PICKUP_ITEMS = false;
private static boolean SUPPORT_SILENT = false;
private static boolean SUPPORT_USE_ITEM = true;
static {
try {
Entity.class.getMethod("setNoDamageTicks", int.class);
SUPPORT_NODAMAGE_TICKS = true;
} catch (NoSuchMethodException | SecurityException e) {
}
try {
Entity.class.getMethod("setGlowing", boolean.class);
SUPPORT_GLOWING = true;
} catch (NoSuchMethodException | SecurityException e) {
}
try {
Entity.class.getMethod("setSilent", boolean.class);
SUPPORT_SILENT = true;
} catch (NoSuchMethodException | SecurityException e) {
}
try {
LivingEntity.class.getMethod("setCanPickupItems", boolean.class);
SUPPORT_PICKUP_ITEMS = true;
} catch (NoSuchMethodException | SecurityException e) {
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -177,15 +177,15 @@ public <T extends Trait> T getTrait(Class<T> clazz) {
@Override
@SuppressWarnings("unchecked")
public <T extends Trait> T getTrait(String name) {
TraitInfo info = registered.get(name.toLowerCase(Locale.US));
TraitInfo info = registered.get(name.toLowerCase(Locale.ROOT));
if (info == null)
return null;
return (T) create(info);
}

@Override
public Class<? extends Trait> getTraitClass(String name) {
TraitInfo info = registered.get(name.toLowerCase(Locale.US));
TraitInfo info = registered.get(name.toLowerCase(Locale.ROOT));
return info == null ? null : info.getTraitClass();
}

Expand Down
19 changes: 7 additions & 12 deletions main/src/main/java/net/citizensnpcs/trait/HorseModifiers.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package net.citizensnpcs.trait;

import java.lang.invoke.MethodHandle;

import org.bukkit.entity.ChestedHorse;
import org.bukkit.entity.Horse;
import org.bukkit.entity.Horse.Color;
Expand Down Expand Up @@ -111,22 +109,19 @@ private void updateModifiers() {
horse.getInventory().setArmor(armor);
horse.getInventory().setSaddle(saddle);
}
if (CARRYING_CHEST_METHOD == null)
return;
if (npc.getEntity() instanceof ChestedHorse) {
try {
CARRYING_CHEST_METHOD.invoke(npc.getEntity(), carryingChest);
} catch (Throwable e) {
}
if (SUPPORTS_CARRYING_CHEST && npc.getEntity() instanceof ChestedHorse) {
((ChestedHorse) npc.getEntity()).setCarryingChest(carryingChest);
}
}

private static MethodHandle CARRYING_CHEST_METHOD;
private static boolean SUPPORTS_CARRYING_CHEST;

static {
try {
CARRYING_CHEST_METHOD = NMS.getMethodHandle(Class.forName("org.bukkit.entity.ChestedHorse"),
"setCarryingChest", false, boolean.class);
if (NMS.getMethodHandle(Class.forName("org.bukkit.entity.ChestedHorse"), "setCarryingChest", false,
boolean.class) != null) {
SUPPORTS_CARRYING_CHEST = true;
}
} catch (Throwable e) {
}
}
Expand Down
18 changes: 16 additions & 2 deletions main/src/main/java/net/citizensnpcs/util/NMS.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.UUID;
Expand Down Expand Up @@ -273,7 +274,7 @@ private static List<Field> getFieldsMatchingType(Class<?> clazz, Class<?> type,
public static List<MethodHandle> getFieldsOfType(Class<?> clazz, Class<?> type) {
List<Field> found = getFieldsMatchingType(clazz, type, false);
if (found.isEmpty())
return null;
return Collections.emptyList();
return found.stream().map(f -> {
try {
return LOOKUP.unreflectGetter(f);
Expand Down Expand Up @@ -585,6 +586,20 @@ public static MethodHandle getSetter(Class<?> clazz, String name, boolean log) {
return null;
}

public static Collection<MethodHandle> getSettersOfType(Class<?> clazz, Class<?> fieldType) {
List<Field> found = getFieldsMatchingType(clazz, fieldType, false);
if (found.isEmpty())
return Collections.emptyList();
return found.stream().map(f -> {
try {
return LOOKUP.unreflectSetter(f);
} catch (Throwable e) {
e.printStackTrace();
}
return null;
}).filter(f -> f != null).collect(Collectors.toList());
}

public static String getSoundPath(Sound flag) throws CommandException {
return BRIDGE.getSoundPath(flag);
}
Expand Down Expand Up @@ -988,7 +1003,6 @@ public static void updatePathfindingRange(NPC npc, float pathfindingRange) {
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;

static {
Expand Down
6 changes: 3 additions & 3 deletions main/src/main/java/net/citizensnpcs/util/Util.java
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ public static boolean isOffHand(PlayerInteractEvent event) {
}

public static String listValuesPretty(Object[] values) {
return "<yellow>" + Joiner.on("<green>, <yellow>").join(values).replace('_', ' ').toLowerCase(Locale.US);
return "<yellow>" + Joiner.on("<green>, <yellow>").join(values).replace('_', ' ').toLowerCase(Locale.ROOT);
}

public static <T extends Enum<?>> T matchEnum(T[] values, String toMatch) {
Expand All @@ -345,7 +345,7 @@ public static <T extends Enum<?>> T matchEnum(T[] values, String toMatch) {

}
for (T check : values) {
String name = check.name().toLowerCase(Locale.US);
String name = check.name().toLowerCase(Locale.ROOT);
if (name.replace("_", "").equals(toMatch) || name.startsWith(toMatch))
return check;

Expand Down Expand Up @@ -422,7 +422,7 @@ public static int parseTicks(String raw) {
}

public static String prettyEnum(Enum<?> e) {
return e.name().toLowerCase(Locale.US).replace('_', ' ');
return e.name().toLowerCase(Locale.ROOT).replace('_', ' ');
}

public static String prettyPrintLocation(Location to) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -626,9 +626,19 @@ public NPC getNPC(org.bukkit.entity.Entity entity) {
@Override
public EntityPacketTracker getPacketTracker(org.bukkit.entity.Entity entity) {
ServerLevel server = (ServerLevel) getHandle(entity).level();
TrackedEntity entry = server.getChunkSource().chunkMap.entityMap.get(entity.getEntityId());
if (entry == null)
TrackedEntity tracked = null;
if (TRACKED_ENTITY_GETTER != null) {
try {
tracked = (TrackedEntity) TRACKED_ENTITY_GETTER.invoke(getHandle(entity));
} catch (Throwable e) {
e.printStackTrace();
}
} else {
tracked = server.getChunkSource().chunkMap.entityMap.get(entity.getEntityId());
}
if (tracked == null)
return null;
TrackedEntity entry = tracked;
return new EntityPacketTracker() {
@Override
public void link(Player player) {
Expand Down Expand Up @@ -1335,7 +1345,16 @@ public void removeHookIfNecessary(FishHook entity) {

@Override
public void replaceTrackerEntry(org.bukkit.entity.Entity entity) {
ServerLevel server = (ServerLevel) getHandle(entity).level();
Entity handle = getHandle(entity);
ServerLevel server = (ServerLevel) handle.level();
for (MethodHandle setter : TRACKED_ENTITY_SETTERS) {
try {
setter.invoke(handle, new CitizensEntityTracker(server.getChunkSource().chunkMap,
(TrackedEntity) TRACKED_ENTITY_GETTER.invoke(handle)));
} catch (Throwable e) {
e.printStackTrace();
}
}
TrackedEntity entry = server.getChunkSource().chunkMap.entityMap.get(entity.getEntityId());
if (entry == null)
return;
Expand Down Expand Up @@ -2520,7 +2539,9 @@ public static void updateMinecraftAIState(NPC npc, Mob entity) {

private static final MethodHandle ADVANCEMENTS_PLAYER_SETTER = NMS.getFirstFinalSetter(ServerPlayer.class,
PlayerAdvancements.class);

private static final MethodHandle ARMADILLO_SCUTE_TIME = NMS.getSetter(Armadillo.class, "cn");

private static final MethodHandle ATTRIBUTE_PROVIDER_MAP = NMS.getFirstGetter(AttributeSupplier.class, Map.class);
private static final MethodHandle ATTRIBUTE_PROVIDER_MAP_SETTER = NMS.getFirstFinalSetter(AttributeSupplier.class,
Map.class);
Expand Down Expand Up @@ -2572,10 +2593,10 @@ public static void updateMinecraftAIState(NPC npc, Mob entity) {
private static final MethodHandle NAVIGATION_CREATE_PATHFINDER = NMS
.getFirstMethodHandleWithReturnType(PathNavigation.class, true, PathFinder.class, int.class);
private static final MethodHandle NAVIGATION_PATH = NMS.getFirstGetter(PathNavigation.class, Path.class);

private static final MethodHandle NAVIGATION_PATHFINDER = NMS.getFirstFinalSetter(PathNavigation.class,
PathFinder.class);
private static final MethodHandle NAVIGATION_WORLD_FIELD = NMS.getFirstSetter(PathNavigation.class, Level.class);

private static final MethodHandle PLAYER_INFO_ENTRIES_LIST = NMS
.getFirstFinalSetter(ClientboundPlayerInfoUpdatePacket.class, List.class);
private static final MethodHandle PLAYERINFO_ENTRIES = PLAYER_INFO_ENTRIES_LIST;
Expand All @@ -2592,6 +2613,9 @@ public static void updateMinecraftAIState(NPC npc, Mob entity) {
private static final MethodHandle SIZE_FIELD_SETTER = NMS.getFirstSetter(Entity.class, EntityDimensions.class);
private static MethodHandle SKULL_META_PROFILE;
private static MethodHandle TEAM_FIELD;
private static final MethodHandle TRACKED_ENTITY_GETTER = NMS.getFirstGetter(Entity.class, TrackedEntity.class);
private static final Collection<MethodHandle> TRACKED_ENTITY_SETTERS = NMS.getSettersOfType(Entity.class,
TrackedEntity.class);
static {
try {
ENTITY_REGISTRY = new CustomEntityRegistry(BuiltInRegistries.ENTITY_TYPE);
Expand Down

0 comments on commit 6d18bc1

Please sign in to comment.