mirror of
https://github.com/CitizensDev/Citizens2.git
synced 2024-11-25 12:15:53 +01:00
Replace entity tracked fields as well as chunk map ones
This commit is contained in:
parent
ec51df24b5
commit
6d18bc16c7
@ -912,8 +912,8 @@ public class NPCCommands {
|
||||
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);
|
||||
@ -1263,7 +1263,7 @@ public class NPCCommands {
|
||||
|
||||
@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,
|
||||
@ -3661,7 +3661,7 @@ public class NPCCommands {
|
||||
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) {
|
||||
|
@ -44,7 +44,7 @@ public class TemplateCommands {
|
||||
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())
|
||||
@ -73,9 +73,9 @@ public class TemplateCommands {
|
||||
@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);
|
||||
|
@ -20,7 +20,7 @@ import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
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;
|
||||
@ -381,7 +381,8 @@ public class CitizensNPC extends AbstractNPC {
|
||||
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) {
|
||||
@ -389,7 +390,6 @@ public class CitizensNPC extends AbstractNPC {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
// Replace the entity tracker
|
||||
NMS.replaceTracker(getEntity());
|
||||
EntityType type = getEntity().getType();
|
||||
if (type.isAlive()) {
|
||||
@ -479,21 +479,21 @@ public class CitizensNPC extends AbstractNPC {
|
||||
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());
|
||||
}
|
||||
}
|
||||
@ -504,23 +504,15 @@ public class CitizensNPC extends AbstractNPC {
|
||||
}
|
||||
}
|
||||
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);
|
||||
@ -538,11 +530,7 @@ public class CitizensNPC extends AbstractNPC {
|
||||
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());
|
||||
@ -622,9 +610,31 @@ public class CitizensNPC extends AbstractNPC {
|
||||
}
|
||||
|
||||
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) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -177,7 +177,7 @@ public class CitizensTraitFactory implements TraitFactory {
|
||||
@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);
|
||||
@ -185,7 +185,7 @@ public class CitizensTraitFactory implements TraitFactory {
|
||||
|
||||
@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();
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
@ -111,22 +109,19 @@ public class HorseModifiers extends Trait {
|
||||
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) {
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import java.lang.reflect.Field;
|
||||
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;
|
||||
@ -273,7 +274,7 @@ public class NMS {
|
||||
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);
|
||||
@ -585,6 +586,20 @@ public class NMS {
|
||||
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);
|
||||
}
|
||||
@ -988,7 +1003,6 @@ public class NMS {
|
||||
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 {
|
||||
|
@ -333,7 +333,7 @@ public class Util {
|
||||
}
|
||||
|
||||
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) {
|
||||
@ -345,7 +345,7 @@ public class Util {
|
||||
|
||||
}
|
||||
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;
|
||||
|
||||
@ -422,7 +422,7 @@ public class Util {
|
||||
}
|
||||
|
||||
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) {
|
||||
|
@ -626,9 +626,19 @@ public class NMSImpl implements NMSBridge {
|
||||
@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) {
|
||||
@ -1335,7 +1345,16 @@ public class NMSImpl implements NMSBridge {
|
||||
|
||||
@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;
|
||||
@ -2520,7 +2539,9 @@ public class NMSImpl implements NMSBridge {
|
||||
|
||||
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);
|
||||
@ -2572,10 +2593,10 @@ public class NMSImpl implements NMSBridge {
|
||||
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;
|
||||
@ -2592,6 +2613,9 @@ public class NMSImpl implements NMSBridge {
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user