mirror of
https://github.com/dmulloy2/ProtocolLib.git
synced 2024-11-27 05:05:24 +01:00
Fix data watchers and particles
This commit is contained in:
parent
052e7a3dc0
commit
f0468e04d9
@ -26,6 +26,7 @@ import com.comphenix.protocol.utility.MinecraftVersion;
|
|||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import com.google.common.collect.ComparisonChain;
|
import com.google.common.collect.ComparisonChain;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the type of a packet in a specific protocol.
|
* Represents the type of a packet in a specific protocol.
|
||||||
* <p>
|
* <p>
|
||||||
@ -477,8 +478,8 @@ public class PacketType implements Serializable, Cloneable, Comparable<PacketTyp
|
|||||||
public static final PacketType UPDATE_SIGN = new PacketType(PROTOCOL, SENDER, 0x35, "SignUpdate", "UpdateSign", "CPacketUpdateSign");
|
public static final PacketType UPDATE_SIGN = new PacketType(PROTOCOL, SENDER, 0x35, "SignUpdate", "UpdateSign", "CPacketUpdateSign");
|
||||||
public static final PacketType ARM_ANIMATION = new PacketType(PROTOCOL, SENDER, 0x36, "Swing", "ArmAnimation", "CPacketAnimation");
|
public static final PacketType ARM_ANIMATION = new PacketType(PROTOCOL, SENDER, 0x36, "Swing", "ArmAnimation", "CPacketAnimation");
|
||||||
public static final PacketType SPECTATE = new PacketType(PROTOCOL, SENDER, 0x37, "TeleportToEntity", "Spectate", "CPacketSpectate");
|
public static final PacketType SPECTATE = new PacketType(PROTOCOL, SENDER, 0x37, "TeleportToEntity", "Spectate", "CPacketSpectate");
|
||||||
public static final PacketType USE_ITEM = new PacketType(PROTOCOL, SENDER, 0x38, "UseItemOn", "UseItem", "CPacketPlayerTryUseItemOnBlock");
|
public static final PacketType USE_ITEM = new PacketType(PROTOCOL, SENDER, 0x38, "UseItemOn", "CPacketPlayerTryUseItemOnBlock");
|
||||||
public static final PacketType BLOCK_PLACE = new PacketType(PROTOCOL, SENDER, 0x39, "BlockPlace", "CPacketPlayerTryUseItem");
|
public static final PacketType BLOCK_PLACE = new PacketType(PROTOCOL, SENDER, 0x39, "UseItem", "BlockPlace", "CPacketPlayerTryUseItem");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated Removed in 1.17
|
* @deprecated Removed in 1.17
|
||||||
|
@ -535,15 +535,15 @@ public class ProtocolLib extends JavaPlugin {
|
|||||||
|
|
||||||
// that reloading the server might break ProtocolLib / plugins depending on it
|
// that reloading the server might break ProtocolLib / plugins depending on it
|
||||||
if (Util.isCurrentlyReloading()) {
|
if (Util.isCurrentlyReloading()) {
|
||||||
logger.severe("╔══════════════════════════════════════════════════════════════════╗");
|
highlyVisibleError(
|
||||||
logger.severe("║ WARNING ║");
|
" WARNING ",
|
||||||
logger.severe("║ RELOADING THE SERVER WHILE PROTOCOL LIB IS ENABLED MIGHT ║");
|
" RELOADING THE SERVER WHILE PROTOCOLLIB IS ENABLED MIGHT ",
|
||||||
logger.severe("║ LEAD TO UNEXPECTED ERRORS! ║");
|
" LEAD TO UNEXPECTED ERRORS! ",
|
||||||
logger.severe("║ ║");
|
" ",
|
||||||
logger.severe("║ Consider to cleanly restart your server if you encounter ║");
|
" Consider cleanly restarting your server if you encounter ",
|
||||||
logger.severe("║ any issues related to Protocol Lib before opening an issue ║");
|
" any issues related to ProtocolLib before opening an issue ",
|
||||||
logger.severe("║ on GitHub! ║");
|
" on GitHub! "
|
||||||
logger.severe("╚══════════════════════════════════════════════════════════════════╝");
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean up
|
// Clean up
|
||||||
|
@ -19,6 +19,7 @@ package com.comphenix.protocol.utility;
|
|||||||
|
|
||||||
import java.lang.reflect.Array;
|
import java.lang.reflect.Array;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.lang.reflect.ParameterizedType;
|
import java.lang.reflect.ParameterizedType;
|
||||||
@ -26,6 +27,7 @@ import java.util.HashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.function.Supplier;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
@ -115,6 +117,8 @@ public final class MinecraftReflection {
|
|||||||
private static MethodAccessor asCraftMirror = null;
|
private static MethodAccessor asCraftMirror = null;
|
||||||
private static MethodAccessor isEmpty = null;
|
private static MethodAccessor isEmpty = null;
|
||||||
|
|
||||||
|
private static boolean isMojangMapped = false;
|
||||||
|
|
||||||
private MinecraftReflection() {
|
private MinecraftReflection() {
|
||||||
// No need to make this constructable.
|
// No need to make this constructable.
|
||||||
}
|
}
|
||||||
@ -204,6 +208,9 @@ public final class MinecraftReflection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for now, we're going to say that it's Mojang mapped if the nms world was renamed to ServerLevel
|
||||||
|
isMojangMapped = getNmsWorldClass().getName().contains("ServerLevel");
|
||||||
|
|
||||||
return MINECRAFT_FULL_PACKAGE;
|
return MINECRAFT_FULL_PACKAGE;
|
||||||
} catch (NoSuchMethodException exception) {
|
} catch (NoSuchMethodException exception) {
|
||||||
throw new IllegalStateException("Cannot find getHandle() in CraftEntity", exception);
|
throw new IllegalStateException("Cannot find getHandle() in CraftEntity", exception);
|
||||||
@ -1109,19 +1116,37 @@ public final class MinecraftReflection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Class<?> getOrInferMinecraftClass(String className, Supplier<Class<?>> supplier) {
|
||||||
|
return getOptionalNMS(className).orElseGet(() -> {
|
||||||
|
Class<?> clazz = supplier.get();
|
||||||
|
return setMinecraftClass(className, clazz);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the entity use action class in 1.17.
|
* Retrieves the entity use action class in 1.17.
|
||||||
*
|
*
|
||||||
* @return The EntityUseAction class
|
* @return The EntityUseAction class
|
||||||
*/
|
*/
|
||||||
public static Class<?> getEnumEntityUseActionClass() {
|
public static Class<?> getEnumEntityUseActionClass() {
|
||||||
Class<?> packetClass = PacketType.Play.Client.USE_ENTITY.getPacketClass();
|
return getOrInferMinecraftClass("ServerboundInteractPacket.Action", () -> {
|
||||||
FuzzyReflection fuzzyReflection = FuzzyReflection.fromClass(packetClass, true);
|
Class<?> packetClass = PacketType.Play.Client.USE_ENTITY.getPacketClass();
|
||||||
try {
|
FuzzyReflection fuzzyReflection = FuzzyReflection.fromClass(packetClass, true);
|
||||||
return fuzzyReflection.getFieldByType("^.*(EnumEntityUseAction)").getType();
|
|
||||||
} catch (IllegalArgumentException ignored) {
|
Field field = fuzzyReflection.getField(FuzzyFieldContract.newBuilder()
|
||||||
return fuzzyReflection.getFieldByType("^.*(Action)").getType();
|
.banModifier(Modifier.STATIC)
|
||||||
}
|
.typeDerivedOf(Object.class)
|
||||||
|
.build());
|
||||||
|
if (field != null) {
|
||||||
|
return field.getType();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return fuzzyReflection.getFieldByType("^.*(EnumEntityUseAction)").getType();
|
||||||
|
} catch (IllegalArgumentException ignored) {
|
||||||
|
return fuzzyReflection.getFieldByType("^.*(Action)").getType();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1763,4 +1788,8 @@ public final class MinecraftReflection {
|
|||||||
public static Optional<Class<?>> getRegistryFriendlyByteBufClass() {
|
public static Optional<Class<?>> getRegistryFriendlyByteBufClass() {
|
||||||
return getOptionalNMS("network.RegistryFriendlyByteBuf");
|
return getOptionalNMS("network.RegistryFriendlyByteBuf");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isMojangMapped() {
|
||||||
|
return isMojangMapped;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,12 +7,15 @@ import com.comphenix.protocol.reflect.EquivalentConverter;
|
|||||||
import com.comphenix.protocol.reflect.ExactReflection;
|
import com.comphenix.protocol.reflect.ExactReflection;
|
||||||
import com.comphenix.protocol.reflect.FuzzyReflection;
|
import com.comphenix.protocol.reflect.FuzzyReflection;
|
||||||
import com.comphenix.protocol.reflect.accessors.Accessors;
|
import com.comphenix.protocol.reflect.accessors.Accessors;
|
||||||
|
import com.comphenix.protocol.reflect.fuzzy.FuzzyMatchers;
|
||||||
|
import com.comphenix.protocol.reflect.fuzzy.FuzzyMethodContract;
|
||||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||||
import com.comphenix.protocol.utility.MinecraftVersion;
|
import com.comphenix.protocol.utility.MinecraftVersion;
|
||||||
import org.apache.commons.lang.Validate;
|
import org.apache.commons.lang.Validate;
|
||||||
import org.bukkit.GameMode;
|
import org.bukkit.GameMode;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@ -549,8 +552,14 @@ public abstract class EnumWrappers {
|
|||||||
// In 1.17 the hand and use action class is no longer a field in the packet
|
// In 1.17 the hand and use action class is no longer a field in the packet
|
||||||
if (MinecraftVersion.CAVES_CLIFFS_1.atOrAbove()) {
|
if (MinecraftVersion.CAVES_CLIFFS_1.atOrAbove()) {
|
||||||
HAND_CLASS = MinecraftReflection.getMinecraftClass("world.EnumHand", "world.InteractionHand");
|
HAND_CLASS = MinecraftReflection.getMinecraftClass("world.EnumHand", "world.InteractionHand");
|
||||||
// class is named 'b' in the packet but class order differs in spigot and paper so we can only use the first method's return type (safest way)
|
|
||||||
ENTITY_USE_ACTION_CLASS = MinecraftReflection.getEnumEntityUseActionClass().getMethods()[0].getReturnType();
|
FuzzyReflection fuzzy = FuzzyReflection.fromClass(MinecraftReflection.getEnumEntityUseActionClass(), true);
|
||||||
|
Method getType = fuzzy.getMethod(FuzzyMethodContract.newBuilder()
|
||||||
|
.parameterCount(0)
|
||||||
|
.returnTypeMatches(FuzzyMatchers.except(Void.class))
|
||||||
|
.build());
|
||||||
|
|
||||||
|
ENTITY_USE_ACTION_CLASS = getType.getReturnType();
|
||||||
} else {
|
} else {
|
||||||
HAND_CLASS = getEnum(PacketType.Play.Client.USE_ENTITY.getPacketClass(), 1);
|
HAND_CLASS = getEnum(PacketType.Play.Client.USE_ENTITY.getPacketClass(), 1);
|
||||||
ENTITY_USE_ACTION_CLASS = getEnum(PacketType.Play.Client.USE_ENTITY.getPacketClass(), 0);
|
ENTITY_USE_ACTION_CLASS = getEnum(PacketType.Play.Client.USE_ENTITY.getPacketClass(), 0);
|
||||||
|
@ -18,8 +18,11 @@ package com.comphenix.protocol.wrappers;
|
|||||||
|
|
||||||
import java.lang.reflect.*;
|
import java.lang.reflect.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
import com.comphenix.protocol.injector.BukkitUnwrapper;
|
import com.comphenix.protocol.injector.BukkitUnwrapper;
|
||||||
|
import com.comphenix.protocol.reflect.EquivalentConverter;
|
||||||
import com.comphenix.protocol.reflect.FieldAccessException;
|
import com.comphenix.protocol.reflect.FieldAccessException;
|
||||||
import com.comphenix.protocol.reflect.FuzzyReflection;
|
import com.comphenix.protocol.reflect.FuzzyReflection;
|
||||||
import com.comphenix.protocol.reflect.StructureModifier;
|
import com.comphenix.protocol.reflect.StructureModifier;
|
||||||
@ -30,6 +33,7 @@ import com.comphenix.protocol.reflect.accessors.MethodAccessor;
|
|||||||
import com.comphenix.protocol.reflect.fuzzy.FuzzyFieldContract;
|
import com.comphenix.protocol.reflect.fuzzy.FuzzyFieldContract;
|
||||||
import com.comphenix.protocol.reflect.fuzzy.FuzzyMethodContract;
|
import com.comphenix.protocol.reflect.fuzzy.FuzzyMethodContract;
|
||||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||||
|
import com.comphenix.protocol.utility.MinecraftVersion;
|
||||||
import com.comphenix.protocol.wrappers.collection.ConvertedMap;
|
import com.comphenix.protocol.wrappers.collection.ConvertedMap;
|
||||||
import com.google.common.base.Optional;
|
import com.google.common.base.Optional;
|
||||||
import com.google.common.collect.ImmutableBiMap;
|
import com.google.common.collect.ImmutableBiMap;
|
||||||
@ -45,6 +49,11 @@ import org.bukkit.inventory.ItemStack;
|
|||||||
*/
|
*/
|
||||||
public class WrappedDataWatcher extends AbstractWrapper implements Iterable<WrappedWatchableObject>, ClonableWrapper {
|
public class WrappedDataWatcher extends AbstractWrapper implements Iterable<WrappedWatchableObject>, ClonableWrapper {
|
||||||
private static final Class<?> HANDLE_TYPE = MinecraftReflection.getDataWatcherClass();
|
private static final Class<?> HANDLE_TYPE = MinecraftReflection.getDataWatcherClass();
|
||||||
|
private static final boolean ARRAY_BACKED = MinecraftVersion.CONFIG_PHASE_PROTOCOL_UPDATE.atOrAbove();
|
||||||
|
|
||||||
|
private static Class<?> SYNCHED_DATA_HOLDER_CLASS = ARRAY_BACKED
|
||||||
|
? MinecraftReflection.getMinecraftClass("network.syncher.SyncedDataHolder")
|
||||||
|
: MinecraftReflection.getEntityClass();
|
||||||
|
|
||||||
private static MethodAccessor GETTER = null;
|
private static MethodAccessor GETTER = null;
|
||||||
private static MethodAccessor SETTER = null;
|
private static MethodAccessor SETTER = null;
|
||||||
@ -53,6 +62,7 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
|
|||||||
private static FieldAccessor ENTITY_DATA_FIELD = null;
|
private static FieldAccessor ENTITY_DATA_FIELD = null;
|
||||||
private static FieldAccessor ENTITY_FIELD = null;
|
private static FieldAccessor ENTITY_FIELD = null;
|
||||||
private static FieldAccessor MAP_FIELD = null;
|
private static FieldAccessor MAP_FIELD = null;
|
||||||
|
private static FieldAccessor ARRAY_FIELD = null;
|
||||||
|
|
||||||
private static ConstructorAccessor constructor = null;
|
private static ConstructorAccessor constructor = null;
|
||||||
private static ConstructorAccessor eggConstructor = null;
|
private static ConstructorAccessor eggConstructor = null;
|
||||||
@ -78,8 +88,9 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
|
|||||||
* resulting DataWatcher will not have any keys or values and new ones will
|
* resulting DataWatcher will not have any keys or values and new ones will
|
||||||
* have to be added using watcher objects.
|
* have to be added using watcher objects.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public WrappedDataWatcher() {
|
public WrappedDataWatcher() {
|
||||||
this(newHandle(fakeEntity()));
|
this(new ArrayList<>());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -89,8 +100,9 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
|
|||||||
*
|
*
|
||||||
* @param entity The entity
|
* @param entity The entity
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public WrappedDataWatcher(Entity entity) {
|
public WrappedDataWatcher(Entity entity) {
|
||||||
this(newHandle(BukkitUnwrapper.getInstance().unwrapItem(entity)));
|
this(getHandleFromEntity(entity));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -99,26 +111,51 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
|
|||||||
*
|
*
|
||||||
* @param objects The list of objects
|
* @param objects The list of objects
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public WrappedDataWatcher(List<WrappedWatchableObject> objects) {
|
public WrappedDataWatcher(List<WrappedWatchableObject> objects) {
|
||||||
this();
|
this(newHandle(fakeEntity(), objects));
|
||||||
|
|
||||||
if (MinecraftReflection.watcherObjectExists()) {
|
|
||||||
for (WrappedWatchableObject object : objects) {
|
|
||||||
setObject(object.getWatcherObject(), object);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (WrappedWatchableObject object : objects) {
|
|
||||||
setObject(object.getIndex(), object);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Object newHandle(Object entity) {
|
private static final EquivalentConverter<List<WrappedWatchableObject>> ITEMS_CONVERTER = new EquivalentConverter<List<WrappedWatchableObject>>() {
|
||||||
if (constructor == null) {
|
@Override
|
||||||
constructor = Accessors.getConstructorAccessor(HANDLE_TYPE, MinecraftReflection.getEntityClass());
|
public Object getGeneric(List<WrappedWatchableObject> specific) {
|
||||||
|
Object[] generic = (Object[]) Array.newInstance(MinecraftReflection.getDataWatcherItemClass(), specific.size());
|
||||||
|
for (int i = 0; i < specific.size(); i++) {
|
||||||
|
generic[i] = specific.get(i).getHandle();
|
||||||
|
}
|
||||||
|
return generic;
|
||||||
}
|
}
|
||||||
|
|
||||||
return constructor.invoke(entity);
|
@Override
|
||||||
|
public List<WrappedWatchableObject> getSpecific(Object generic) {
|
||||||
|
Object[] genericArray = (Object[]) generic;
|
||||||
|
List<WrappedWatchableObject> specific = new ArrayList<>(genericArray.length);
|
||||||
|
for (Object genericObj : genericArray) {
|
||||||
|
specific.add(new WrappedWatchableObject(genericObj));
|
||||||
|
}
|
||||||
|
return specific;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public Class<List<WrappedWatchableObject>> getSpecificType() {
|
||||||
|
Class<?> dummy = List.class;
|
||||||
|
return (Class<List<WrappedWatchableObject>>) dummy;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public static WrappedDataWatcher create(Entity entity, List<WrappedWatchableObject> objects) {
|
||||||
|
return new WrappedDataWatcher(newHandle(entity, objects));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Object newHandle(Object entity, List<WrappedWatchableObject> objects) {
|
||||||
|
if (constructor == null) {
|
||||||
|
constructor = Accessors.getConstructorAccessor(HANDLE_TYPE, SYNCHED_DATA_HOLDER_CLASS,
|
||||||
|
MinecraftReflection.getArrayClass(MinecraftReflection.getDataWatcherItemClass()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Object[] genericItems = (Object[]) ITEMS_CONVERTER.getGeneric(objects);
|
||||||
|
return constructor.invoke(entity, genericItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Object fakeEntity() {
|
private static Object fakeEntity() {
|
||||||
@ -142,6 +179,7 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
|
|||||||
// ---- Collection Methods
|
// ---- Collection Methods
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
@Deprecated
|
||||||
private Map<Integer, Object> getMap() {
|
private Map<Integer, Object> getMap() {
|
||||||
if (MAP_FIELD == null) {
|
if (MAP_FIELD == null) {
|
||||||
try {
|
try {
|
||||||
@ -152,19 +190,49 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
|
|||||||
.typeDerivedOf(Map.class)
|
.typeDerivedOf(Map.class)
|
||||||
.build()));
|
.build()));
|
||||||
} catch (IllegalArgumentException ex) {
|
} catch (IllegalArgumentException ex) {
|
||||||
throw new FieldAccessException("Failed to find watchable object map");
|
throw new FieldAccessException("Failed to find watchable object map", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (Map<Integer, Object>) MAP_FIELD.get(handle);
|
return (Map<Integer, Object>) MAP_FIELD.get(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Object[] getBackingArray() {
|
||||||
|
if (ARRAY_FIELD == null) {
|
||||||
|
try {
|
||||||
|
FuzzyReflection fuzzy = FuzzyReflection.fromClass(handleType, true);
|
||||||
|
ARRAY_FIELD = Accessors.getFieldAccessor(fuzzy.getField(FuzzyFieldContract
|
||||||
|
.newBuilder()
|
||||||
|
.banModifier(Modifier.STATIC)
|
||||||
|
.typeDerivedOf(Object[].class)
|
||||||
|
.build()));
|
||||||
|
} catch (IllegalArgumentException ex) {
|
||||||
|
throw new FieldAccessException("Failed to find watchable object array", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Object[] backing = (Object[]) ARRAY_FIELD.get(handle);
|
||||||
|
return backing;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the contents of this DataWatcher as a map.
|
* Gets the contents of this DataWatcher as a map.
|
||||||
* @return The contents
|
* @return The contents
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public Map<Integer, WrappedWatchableObject> asMap() {
|
public Map<Integer, WrappedWatchableObject> asMap() {
|
||||||
return new ConvertedMap<Integer, Object, WrappedWatchableObject>(getMap()) {
|
Map<Integer, Object> backingMap;
|
||||||
|
if (ARRAY_BACKED) {
|
||||||
|
Object[] backingArray = getBackingArray();
|
||||||
|
backingMap = new HashMap<>(backingArray.length);
|
||||||
|
for (int i = 0; i < backingArray.length; i++) {
|
||||||
|
backingMap.put(i, backingArray[i]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
backingMap = getMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ConvertedMap<Integer, Object, WrappedWatchableObject>(backingMap) {
|
||||||
@Override
|
@Override
|
||||||
protected WrappedWatchableObject toOuter(Object inner) {
|
protected WrappedWatchableObject toOuter(Object inner) {
|
||||||
return inner != null ? new WrappedWatchableObject(inner) : null;
|
return inner != null ? new WrappedWatchableObject(inner) : null;
|
||||||
@ -181,7 +249,12 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
|
|||||||
* Gets a set containing the registered indexes.
|
* Gets a set containing the registered indexes.
|
||||||
* @return The set
|
* @return The set
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public Set<Integer> getIndexes() {
|
public Set<Integer> getIndexes() {
|
||||||
|
if (ARRAY_BACKED) {
|
||||||
|
return IntStream.range(0, size()).boxed().collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
return getMap().keySet();
|
return getMap().keySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,7 +262,12 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
|
|||||||
* Gets a list of the contents of this DataWatcher.
|
* Gets a list of the contents of this DataWatcher.
|
||||||
* @return The contents
|
* @return The contents
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public List<WrappedWatchableObject> getWatchableObjects() {
|
public List<WrappedWatchableObject> getWatchableObjects() {
|
||||||
|
if (ARRAY_BACKED) {
|
||||||
|
return (List<WrappedWatchableObject>)ITEMS_CONVERTER.getSpecific(getBackingArray());
|
||||||
|
}
|
||||||
|
|
||||||
return new ArrayList<>(asMap().values());
|
return new ArrayList<>(asMap().values());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,6 +281,10 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
|
|||||||
* @return The size
|
* @return The size
|
||||||
*/
|
*/
|
||||||
public int size() {
|
public int size() {
|
||||||
|
if (ARRAY_BACKED) {
|
||||||
|
return getBackingArray().length;
|
||||||
|
}
|
||||||
|
|
||||||
return getMap().size();
|
return getMap().size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,7 +295,10 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
|
|||||||
* @return The watchable object, or null if none exists
|
* @return The watchable object, or null if none exists
|
||||||
*/
|
*/
|
||||||
public WrappedWatchableObject getWatchableObject(int index) {
|
public WrappedWatchableObject getWatchableObject(int index) {
|
||||||
Object handle = getMap().get(index);
|
Object handle = ARRAY_BACKED
|
||||||
|
? getBackingArray()[index]
|
||||||
|
: getMap().get(index);
|
||||||
|
|
||||||
if (handle != null) {
|
if (handle != null) {
|
||||||
return new WrappedWatchableObject(handle);
|
return new WrappedWatchableObject(handle);
|
||||||
} else {
|
} else {
|
||||||
@ -247,6 +332,10 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
|
|||||||
* @return True if it does, false if not
|
* @return True if it does, false if not
|
||||||
*/
|
*/
|
||||||
public boolean hasIndex(int index) {
|
public boolean hasIndex(int index) {
|
||||||
|
if (ARRAY_BACKED) {
|
||||||
|
return index < size();
|
||||||
|
}
|
||||||
|
|
||||||
return getMap().containsKey(index);
|
return getMap().containsKey(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,14 +343,16 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
|
|||||||
* Returns a set containing all the registered indexes
|
* Returns a set containing all the registered indexes
|
||||||
* @return The set
|
* @return The set
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public Set<Integer> indexSet() {
|
public Set<Integer> indexSet() {
|
||||||
return getMap().keySet();
|
return getIndexes();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears the contents of this DataWatcher. The watcher will be empty after
|
* Clears the contents of this DataWatcher. The watcher will be empty after
|
||||||
* this operation is called.
|
* this operation is called.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public void clear() {
|
public void clear() {
|
||||||
getMap().clear();
|
getMap().clear();
|
||||||
}
|
}
|
||||||
@ -523,6 +614,10 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
|
|||||||
* @return A cloned data watcher.
|
* @return A cloned data watcher.
|
||||||
*/
|
*/
|
||||||
public WrappedDataWatcher deepClone() {
|
public WrappedDataWatcher deepClone() {
|
||||||
|
if (ARRAY_BACKED) {
|
||||||
|
return new WrappedDataWatcher(newHandle(getEntityHandle(), getWatchableObjects()));
|
||||||
|
}
|
||||||
|
|
||||||
WrappedDataWatcher clone = new WrappedDataWatcher(getEntity());
|
WrappedDataWatcher clone = new WrappedDataWatcher(getEntity());
|
||||||
|
|
||||||
if (MinecraftReflection.watcherObjectExists()) {
|
if (MinecraftReflection.watcherObjectExists()) {
|
||||||
@ -545,22 +640,23 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
|
|||||||
* @return Associated data watcher.
|
* @return Associated data watcher.
|
||||||
*/
|
*/
|
||||||
public static WrappedDataWatcher getEntityWatcher(Entity entity) {
|
public static WrappedDataWatcher getEntityWatcher(Entity entity) {
|
||||||
|
Object handle = getHandleFromEntity(entity);
|
||||||
|
return handle != null ? new WrappedDataWatcher(handle) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Object getHandleFromEntity(Entity entity) {
|
||||||
if (ENTITY_DATA_FIELD == null) {
|
if (ENTITY_DATA_FIELD == null) {
|
||||||
ENTITY_DATA_FIELD = Accessors.getFieldAccessor(MinecraftReflection.getEntityClass(), MinecraftReflection.getDataWatcherClass(), true);
|
ENTITY_DATA_FIELD = Accessors.getFieldAccessor(MinecraftReflection.getEntityClass(), MinecraftReflection.getDataWatcherClass(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
BukkitUnwrapper unwrapper = new BukkitUnwrapper();
|
BukkitUnwrapper unwrapper = new BukkitUnwrapper();
|
||||||
Object handle = ENTITY_DATA_FIELD.get(unwrapper.unwrapItem(entity));
|
Object handle = ENTITY_DATA_FIELD.get(unwrapper.unwrapItem(entity));
|
||||||
return handle != null ? new WrappedDataWatcher(handle) : null;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private Object getEntityHandle() {
|
||||||
* Retrieve the entity associated with this data watcher.
|
|
||||||
* @return The entity, or NULL.
|
|
||||||
*/
|
|
||||||
public Entity getEntity() {
|
|
||||||
if (ENTITY_FIELD == null) {
|
if (ENTITY_FIELD == null) {
|
||||||
ENTITY_FIELD = Accessors.getFieldAccessor(HANDLE_TYPE, MinecraftReflection.getEntityClass(), true);
|
ENTITY_FIELD = Accessors.getFieldAccessor(HANDLE_TYPE, SYNCHED_DATA_HOLDER_CLASS, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Object entity = ENTITY_FIELD.get(handle);
|
Object entity = ENTITY_FIELD.get(handle);
|
||||||
@ -568,6 +664,15 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
|
|||||||
throw new NullPointerException(handle + "." + ENTITY_FIELD);
|
throw new NullPointerException(handle + "." + ENTITY_FIELD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the entity associated with this data watcher.
|
||||||
|
* @return The entity, or NULL.
|
||||||
|
*/
|
||||||
|
public Entity getEntity() {
|
||||||
|
Object entity = getEntityHandle();
|
||||||
return (Entity) MinecraftReflection.getBukkitEntity(entity);
|
return (Entity) MinecraftReflection.getBukkitEntity(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +36,9 @@ public class WrappedParticle<T> {
|
|||||||
.newBuilder()
|
.newBuilder()
|
||||||
.requireModifier(Modifier.STATIC)
|
.requireModifier(Modifier.STATIC)
|
||||||
.returnTypeExact(Particle.class)
|
.returnTypeExact(Particle.class)
|
||||||
.parameterExactArray(MinecraftReflection.getParticleClass())
|
.parameterExactArray(MinecraftReflection.isMojangMapped()
|
||||||
|
? MinecraftReflection.getParticleTypeClass()
|
||||||
|
: MinecraftReflection.getParticleClass())
|
||||||
.build();
|
.build();
|
||||||
toBukkit = Accessors.getMethodAccessor(fuzzy.getMethod(contract));
|
toBukkit = Accessors.getMethodAccessor(fuzzy.getMethod(contract));
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user