Skip to content

Commit

Permalink
NMS changes, 1.19.3 Support
Browse files Browse the repository at this point in the history
  • Loading branch information
d0by1 committed Dec 16, 2022
1 parent cd5f527 commit 8ae60c0
Showing 1 changed file with 83 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,25 +24,21 @@ public class NMS_1_17 extends NMS {
private static final Class<?> ENUM_ITEM_SLOT_CLASS;
private static final Class<?> ENTITY_TYPES_CLASS;
private static final Class<?> VEC_3D_CLASS;
private static final ReflectField<?> I_REGISTRY_Y_FIELD;
private static final ReflectField<?> ENTITY_TYPES_REGISTRY_FIELD;
private static final ReflectMethod REGISTRY_BLOCKS_FROM_ID_METHOD;
private static final ReflectMethod ENUM_ITEM_SLOT_FROM_NAME_METHOD;
private static final ReflectMethod CRAFT_ITEM_NMS_COPY_METHOD;
private static final ReflectMethod CRAFT_CHAT_MESSAGE_FROM_STRING_METHOD;
private static final ReflectMethod PAIR_OF_METHOD;
// DATA WATCHER
private static final Class<?> DATA_WATCHER_CLASS;
private static final ReflectConstructor DATA_WATCHER_CONSTRUCTOR;
private static final ReflectMethod DATA_WATCHER_REGISTER_METHOD;
// MATH HELPER
private static final Class<?> MATH_HELPER_CLASS;
private static final ReflectMethod MATH_HELPER_A_METHOD;
// PACKET DATA SERIALIZER
private static final Class<?> PACKET_DATA_SERIALIZER_CLASS;
private static final ReflectConstructor PACKET_DATA_SERIALIZER_CONSTRUCTOR;
private static final ReflectMethod PACKET_DATA_SERIALIZER_D_METHOD;
private static final ReflectMethod PACKET_DATA_SERIALIZER_A_UUID_METHOD;
private static final ReflectMethod PACKET_DATA_SERIALIZER_A_INTS_METHOD;
private static final ReflectMethod PACKET_DATA_SERIALIZER_WRITE_INT_METHOD;
private static final ReflectMethod PACKET_DATA_SERIALIZER_WRITE_UUID_METHOD;
private static final ReflectMethod PACKET_DATA_SERIALIZER_WRITE_INTS_METHOD;
private static final ReflectMethod PACKET_DATA_SERIALIZER_WRITE_DOUBLE_METHOD;
private static final ReflectMethod PACKET_DATA_SERIALIZER_WRITE_BYTE_METHOD;
private static final ReflectMethod PACKET_DATA_SERIALIZER_WRITE_SHORT_METHOD;
Expand All @@ -57,11 +53,14 @@ public class NMS_1_17 extends NMS {
private static final ReflectConstructor PACKET_ENTITY_DESTROY_CONSTRUCTOR;
// DATA WATCHER OBJECT
private static final Class<?> DWO_CLASS;
private static final Class<?> DWS_CLASS;
private static final Class<?> DWI_CLASS;
private static final Object DWO_CUSTOM_NAME;
private static final Object DWO_CUSTOM_NAME_VISIBLE;
private static final Object DWO_ENTITY_DATA;
private static final Object DWO_ARMOR_STAND_DATA;
private static final Object DWO_ITEM;
private static final ReflectConstructor DATA_WATCHER_ITEM_CONSTRUCTOR;
// ENTITY TYPES
private static final ReflectMethod ENTITY_TYPES_A_METHOD;
private static final ReflectMethod ENTITY_TYPE_GET_KEY_METHOD;
Expand All @@ -75,6 +74,8 @@ public class NMS_1_17 extends NMS {

static {
DWO_CLASS = ReflectionUtil.getNMClass("network.syncher.DataWatcherObject");
DWS_CLASS = ReflectionUtil.getNMClass("network.syncher.DataWatcherSerializer");
DWI_CLASS = ReflectionUtil.getNMClass("network.syncher.DataWatcher$Item");
// UTILITY
ENTITY_CLASS = ReflectionUtil.getNMClass("world.entity.Entity");
ENTITY_ARMOR_STAND_CLASS = ReflectionUtil.getNMClass("world.entity.decoration.EntityArmorStand");
Expand All @@ -86,34 +87,33 @@ public class NMS_1_17 extends NMS {
CRAFT_CHAT_MESSAGE_FROM_STRING_METHOD = new ReflectMethod(ReflectionUtil.getObcClass("util.CraftChatMessage"), "fromStringOrNull", String.class);
PAIR_OF_METHOD = new ReflectMethod(ReflectionUtil.getClass("com.mojang.datafixers.util.Pair"), "of", Object.class, Object.class);
// DATA WATCHER
DATA_WATCHER_CLASS = ReflectionUtil.getNMClass("network.syncher.DataWatcher");
DATA_WATCHER_CONSTRUCTOR = new ReflectConstructor(DATA_WATCHER_CLASS, ENTITY_CLASS);
DATA_WATCHER_ITEM_CONSTRUCTOR = new ReflectConstructor(DWI_CLASS, DWO_CLASS, Object.class);
if (Version.afterOrEqual(18)) {
if (Version.CURRENT.equals(Version.v1_18_R2)) {
I_REGISTRY_Y_FIELD = new ReflectField<>(ReflectionUtil.getNMClass("core.IRegistry"), "W");
if (Version.afterOrEqual(Version.v1_19_R2)) {
ENTITY_TYPES_REGISTRY_FIELD = new ReflectField<>(ReflectionUtil.getNMClass("core.registries.BuiltInRegistries"), "h");
} else if (Version.afterOrEqual(19)) {
I_REGISTRY_Y_FIELD = new ReflectField<>(ReflectionUtil.getNMClass("core.IRegistry"), "X");
ENTITY_TYPES_REGISTRY_FIELD = new ReflectField<>(ReflectionUtil.getNMClass("core.IRegistry"), "X");
} else if (Version.is(Version.v1_18_R2)) {
ENTITY_TYPES_REGISTRY_FIELD = new ReflectField<>(ReflectionUtil.getNMClass("core.IRegistry"), "W");
} else {
I_REGISTRY_Y_FIELD = new ReflectField<>(ReflectionUtil.getNMClass("core.IRegistry"), "Z");
ENTITY_TYPES_REGISTRY_FIELD = new ReflectField<>(ReflectionUtil.getNMClass("core.IRegistry"), "Z");
}
REGISTRY_BLOCKS_FROM_ID_METHOD = new ReflectMethod(ReflectionUtil.getNMClass("core.RegistryBlocks"), "a", int.class);
ENUM_ITEM_SLOT_FROM_NAME_METHOD = new ReflectMethod(ENUM_ITEM_SLOT_CLASS, "a", String.class);
DATA_WATCHER_REGISTER_METHOD = new ReflectMethod(DATA_WATCHER_CLASS, "a", DWO_CLASS, Object.class);
} else {
I_REGISTRY_Y_FIELD = new ReflectField<>(ReflectionUtil.getNMClass("core.IRegistry"), "Y");
ENTITY_TYPES_REGISTRY_FIELD = new ReflectField<>(ReflectionUtil.getNMClass("core.IRegistry"), "Y");
REGISTRY_BLOCKS_FROM_ID_METHOD = new ReflectMethod(ReflectionUtil.getNMClass("core.RegistryBlocks"), "fromId", int.class);
ENUM_ITEM_SLOT_FROM_NAME_METHOD = new ReflectMethod(ENUM_ITEM_SLOT_CLASS, "fromName", String.class);
DATA_WATCHER_REGISTER_METHOD = new ReflectMethod(DATA_WATCHER_CLASS, "register", DWO_CLASS, Object.class);
}
// MATH HELPER
MATH_HELPER_CLASS = ReflectionUtil.getNMClass("util.MathHelper");
MATH_HELPER_A_METHOD = new ReflectMethod(MATH_HELPER_CLASS, "a", Random.class);
// PACKET DATA SERIALIZER
PACKET_DATA_SERIALIZER_CLASS = ReflectionUtil.getNMClass("network.PacketDataSerializer");
PACKET_DATA_SERIALIZER_CONSTRUCTOR = new ReflectConstructor(PACKET_DATA_SERIALIZER_CLASS, ByteBuf.class);
PACKET_DATA_SERIALIZER_D_METHOD = new ReflectMethod(PACKET_DATA_SERIALIZER_CLASS, "d", int.class);
PACKET_DATA_SERIALIZER_A_UUID_METHOD = new ReflectMethod(PACKET_DATA_SERIALIZER_CLASS, "a", UUID.class);
PACKET_DATA_SERIALIZER_A_INTS_METHOD = new ReflectMethod(PACKET_DATA_SERIALIZER_CLASS, "a", int[].class);
PACKET_DATA_SERIALIZER_WRITE_INT_METHOD = new ReflectMethod(PACKET_DATA_SERIALIZER_CLASS, "d", int.class);
PACKET_DATA_SERIALIZER_WRITE_UUID_METHOD = new ReflectMethod(PACKET_DATA_SERIALIZER_CLASS, "a", UUID.class);
PACKET_DATA_SERIALIZER_WRITE_INTS_METHOD = new ReflectMethod(PACKET_DATA_SERIALIZER_CLASS, "a", int[].class);
PACKET_DATA_SERIALIZER_WRITE_DOUBLE_METHOD = new ReflectMethod(PACKET_DATA_SERIALIZER_CLASS, "writeDouble", double.class);
PACKET_DATA_SERIALIZER_WRITE_BYTE_METHOD = new ReflectMethod(PACKET_DATA_SERIALIZER_CLASS, "writeByte", int.class);
PACKET_DATA_SERIALIZER_WRITE_SHORT_METHOD = new ReflectMethod(PACKET_DATA_SERIALIZER_CLASS, "writeShort", int.class);
Expand All @@ -130,7 +130,7 @@ public class NMS_1_17 extends NMS {
int.class, UUID.class, double.class, double.class, double.class, float.class, float.class, ENTITY_TYPES_CLASS, int.class, VEC_3D_CLASS, double.class);
}
PACKET_ENTITY_METADATA_CONSTRUCTOR = new ReflectConstructor(ReflectionUtil.getNMClass("network.protocol.game.PacketPlayOutEntityMetadata"),
int.class, DATA_WATCHER_CLASS, boolean.class);
PACKET_DATA_SERIALIZER_CLASS);
PACKET_ENTITY_TELEPORT_CONSTRUCTOR = new ReflectConstructor(ReflectionUtil.getNMClass("network.protocol.game.PacketPlayOutEntityTeleport"),
PACKET_DATA_SERIALIZER_CLASS);
PACKET_MOUNT_CONSTRUCTOR = new ReflectConstructor(ReflectionUtil.getNMClass("network.protocol.game.PacketPlayOutMount"),
Expand All @@ -141,7 +141,7 @@ public class NMS_1_17 extends NMS {
int[].class);
// DATA WATCHER OBJECT
if (Version.afterOrEqual(18)) {
if (Version.CURRENT.equals(Version.v1_18_R2) || Version.afterOrEqual(19)) {
if (Version.afterOrEqual(Version.v1_18_R2)) {
DWO_ENTITY_DATA = new ReflectField<>(ENTITY_CLASS, "Z").getValue(null);
DWO_CUSTOM_NAME = new ReflectField<>(ENTITY_CLASS, "aM").getValue(null);
DWO_CUSTOM_NAME_VISIBLE = new ReflectField<>(ENTITY_CLASS, "aN").getValue(null);
Expand All @@ -162,10 +162,13 @@ public class NMS_1_17 extends NMS {
// ENTITY TYPES
ENTITY_TYPES_A_METHOD = new ReflectMethod(ENTITY_TYPES_CLASS, "a", String.class);
ENTITY_TYPE_GET_KEY_METHOD = new ReflectMethod(EntityType.class, "getKey");
REGISTRY_BLOCKS_GET_ID_METHOD = new ReflectMethod(ReflectionUtil.getNMClass("core.RegistryBlocks"),
Version.afterOrEqual(18) ? "a" : "getId", Object.class);
if (Version.afterOrEqual(18)) {
REGISTRY_BLOCKS_GET_ID_METHOD = new ReflectMethod(ReflectionUtil.getNMClass("core.Registry"), "a", Object.class);
} else {
REGISTRY_BLOCKS_GET_ID_METHOD = new ReflectMethod(ReflectionUtil.getNMClass("core.Registry"), "getId", Object.class);
}
NAMESPACED_KEY_GET_KEY_METHOD = new ReflectMethod(ReflectionUtil.getClass("org.bukkit.NamespacedKey"), "getKey");
ENTITY_TYPES_GET_SIZE_METHOD = new ReflectMethod(ENTITY_TYPES_CLASS, "m");
ENTITY_TYPES_GET_SIZE_METHOD = new ReflectMethod(ENTITY_TYPES_CLASS, Version.afterOrEqual(Version.v1_19_R2) ? "n" : "m");
ENTITY_SIZE_HEIGHT_FIELD = new ReflectField<>(ReflectionUtil.getNMClass("world.entity.EntitySize"), "b");

ENTITY_COUNTER_FIELD = new ReflectField<>(ENTITY_CLASS, Version.CURRENT.equals(Version.v1_18_R2) || Version.afterOrEqual(19) ? "c" : "b");
Expand All @@ -184,7 +187,7 @@ public int getEntityTypeId(EntityType type) {
String key = NAMESPACED_KEY_GET_KEY_METHOD.invoke(namespacedKey);
Optional<?> entityTypes = ENTITY_TYPES_A_METHOD.invokeStatic(key.toLowerCase());
return entityTypes.map((entityType) -> {
Object registryBlocks = I_REGISTRY_Y_FIELD.getValue(null);
Object registryBlocks = ENTITY_TYPES_REGISTRY_FIELD.getValue(null);
return REGISTRY_BLOCKS_GET_ID_METHOD.<Integer>invoke(registryBlocks, entityType);
}).orElse(-1);
}
Expand Down Expand Up @@ -225,7 +228,7 @@ private void showFakeEntity(Player player, Location location, int entityTypeId,
location.getZ(),
location.getYaw(),
location.getPitch(),
REGISTRY_BLOCKS_FROM_ID_METHOD.invoke(I_REGISTRY_Y_FIELD.getValue(null), entityTypeId),
REGISTRY_BLOCKS_FROM_ID_METHOD.invoke(ENTITY_TYPES_REGISTRY_FIELD.getValue(null), entityTypeId),
0,
VEC_3D_A,
location.getYaw()
Expand All @@ -239,7 +242,7 @@ private void showFakeEntity(Player player, Location location, int entityTypeId,
location.getZ(),
location.getYaw(),
location.getPitch(),
REGISTRY_BLOCKS_FROM_ID_METHOD.invoke(I_REGISTRY_Y_FIELD.getValue(null), entityTypeId),
REGISTRY_BLOCKS_FROM_ID_METHOD.invoke(ENTITY_TYPES_REGISTRY_FIELD.getValue(null), entityTypeId),
0,
VEC_3D_A
));
Expand Down Expand Up @@ -267,9 +270,9 @@ private void showFakeEntityLiving(Player player, Location location, int entityTy
Validate.notNull(location);

Object packetDataSerializer = PACKET_DATA_SERIALIZER_CONSTRUCTOR.newInstance(Unpooled.buffer());
PACKET_DATA_SERIALIZER_D_METHOD.invoke(packetDataSerializer, entityId);
PACKET_DATA_SERIALIZER_A_UUID_METHOD.invoke(packetDataSerializer, MATH_HELPER_A_METHOD.<UUID>invokeStatic(RandomUtils.RANDOM));
PACKET_DATA_SERIALIZER_D_METHOD.invoke(packetDataSerializer, entityTypeId);
PACKET_DATA_SERIALIZER_WRITE_INT_METHOD.invoke(packetDataSerializer, entityId);
PACKET_DATA_SERIALIZER_WRITE_UUID_METHOD.invoke(packetDataSerializer, MATH_HELPER_A_METHOD.<UUID>invokeStatic(RandomUtils.RANDOM));
PACKET_DATA_SERIALIZER_WRITE_INT_METHOD.invoke(packetDataSerializer, entityTypeId);
PACKET_DATA_SERIALIZER_WRITE_DOUBLE_METHOD.invoke(packetDataSerializer, location.getX());
PACKET_DATA_SERIALIZER_WRITE_DOUBLE_METHOD.invoke(packetDataSerializer, location.getY());
PACKET_DATA_SERIALIZER_WRITE_DOUBLE_METHOD.invoke(packetDataSerializer, location.getZ());
Expand All @@ -282,19 +285,51 @@ private void showFakeEntityLiving(Player player, Location location, int entityTy
sendPacket(player, PACKET_SPAWN_ENTITY_LIVING_CONSTRUCTOR.newInstance(packetDataSerializer));
}

private static final Class<?> DWR_CLASS = ReflectionUtil.getNMClass("network.syncher.DataWatcherRegistry");
private static final ReflectMethod DWI_GET_OBJECT_METHOD = new ReflectMethod(DWI_CLASS, "a");
private static final ReflectMethod DWI_GET_VALUE_METHOD = new ReflectMethod(DWI_CLASS, "b");
private static final ReflectMethod DWO_GET_SERIALIZER_METHOD = new ReflectMethod(DWO_CLASS, "b");
private static final ReflectMethod DWO_GET_INDEX_METHOD = new ReflectMethod(DWO_CLASS, "a");
private static final ReflectMethod DWS_GET_TYPE_ID_METHOD = new ReflectMethod(DWR_CLASS, "b", DWS_CLASS);
private static final ReflectMethod DWS_SERIALIZE_METHOD = new ReflectMethod(DWS_CLASS, "a",
PACKET_DATA_SERIALIZER_CLASS, Object.class);

private void sendEntityMetadata(Player player, int entityId, List<Object> items) {
Validate.notNull(player);
Validate.notNull(items);

Object packetDataSerializer = PACKET_DATA_SERIALIZER_CONSTRUCTOR.newInstance(Unpooled.buffer());
PACKET_DATA_SERIALIZER_WRITE_INT_METHOD.invoke(packetDataSerializer, entityId);
for (Object item : items) {
if (!item.getClass().isAssignableFrom(DWI_CLASS)) {
continue;
}

Object object = DWI_GET_OBJECT_METHOD.invoke(item);
Object value = DWI_GET_VALUE_METHOD.invoke(item);
Object serializer = DWO_GET_SERIALIZER_METHOD.invoke(object);
int serializerIndex = DWO_GET_INDEX_METHOD.invoke(object);
int serializerTypeId = DWS_GET_TYPE_ID_METHOD.invokeStatic(serializer);

PACKET_DATA_SERIALIZER_WRITE_BYTE_METHOD.invoke(packetDataSerializer, (byte) serializerIndex);
PACKET_DATA_SERIALIZER_WRITE_INT_METHOD.invoke(packetDataSerializer, serializerTypeId);
DWS_SERIALIZE_METHOD.invoke(serializer, packetDataSerializer, value);

}
PACKET_DATA_SERIALIZER_WRITE_BYTE_METHOD.invoke(packetDataSerializer, 0xFF);
sendPacket(player, PACKET_ENTITY_METADATA_CONSTRUCTOR.newInstance(packetDataSerializer));
}

@Override
public void showFakeEntityArmorStand(Player player, Location location, int entityId, boolean invisible, boolean small, boolean clickable) {
Validate.notNull(player);
Validate.notNull(location);

Object dataWatcher = DATA_WATCHER_CONSTRUCTOR.newInstance(ENTITY_CLASS.cast(null));
DATA_WATCHER_REGISTER_METHOD.invoke(dataWatcher, DWO_ENTITY_DATA, (byte) (invisible ? 0x20 : 0x00)); // Invisible
byte data = 0x08;
if (small) data += 0x01;
if (!clickable) data += 0x10;
DATA_WATCHER_REGISTER_METHOD.invoke(dataWatcher, DWO_ARMOR_STAND_DATA, data);
List<Object> dataWatcherItems = new ArrayList<>();
dataWatcherItems.add(DATA_WATCHER_ITEM_CONSTRUCTOR.newInstance(DWO_ENTITY_DATA, (byte) (invisible ? 0x20 : 0)));
dataWatcherItems.add(DATA_WATCHER_ITEM_CONSTRUCTOR.newInstance(DWO_ARMOR_STAND_DATA, (byte) (0x08 | (small ? 0x01 : 0) | (clickable ? 0 : 0x10))));
showFakeEntityLiving(player, location, EntityType.ARMOR_STAND, entityId);
sendPacket(player, PACKET_ENTITY_METADATA_CONSTRUCTOR.newInstance(entityId, dataWatcher, true));
sendEntityMetadata(player, entityId, dataWatcherItems);
}

@Override
Expand All @@ -303,10 +338,10 @@ public void showFakeEntityItem(Player player, Location location, ItemStack itemS
Validate.notNull(location);
Validate.notNull(itemStack);

Object dataWatcher = DATA_WATCHER_CONSTRUCTOR.newInstance(ENTITY_CLASS.cast(null));
DATA_WATCHER_REGISTER_METHOD.invoke(dataWatcher, DWO_ITEM, CRAFT_ITEM_NMS_COPY_METHOD.invokeStatic(itemStack));
List<Object> dataWatcherItems = new ArrayList<>();
dataWatcherItems.add(DATA_WATCHER_ITEM_CONSTRUCTOR.newInstance(DWO_ITEM, CRAFT_ITEM_NMS_COPY_METHOD.invokeStatic(itemStack)));
showFakeEntity(player, location, getEntityTypeId(EntityType.DROPPED_ITEM), entityId);
sendPacket(player, PACKET_ENTITY_METADATA_CONSTRUCTOR.newInstance(entityId, dataWatcher, true));
sendEntityMetadata(player, entityId, dataWatcherItems);
teleportFakeEntity(player, location, entityId);
}

Expand All @@ -315,10 +350,10 @@ public void updateFakeEntityCustomName(Player player, String name, int entityId)
Validate.notNull(player);
Validate.notNull(name);

Object dataWatcher = DATA_WATCHER_CONSTRUCTOR.newInstance(ENTITY_CLASS.cast(null));
DATA_WATCHER_REGISTER_METHOD.invoke(dataWatcher, DWO_CUSTOM_NAME, Optional.ofNullable(CRAFT_CHAT_MESSAGE_FROM_STRING_METHOD.invokeStatic(name)));
DATA_WATCHER_REGISTER_METHOD.invoke(dataWatcher, DWO_CUSTOM_NAME_VISIBLE, !ChatColor.stripColor(name).isEmpty());
sendPacket(player, PACKET_ENTITY_METADATA_CONSTRUCTOR.newInstance(entityId, dataWatcher, true));
List<Object> dataWatcherItems = new ArrayList<>();
dataWatcherItems.add(DATA_WATCHER_ITEM_CONSTRUCTOR.newInstance(DWO_CUSTOM_NAME, Optional.ofNullable(CRAFT_CHAT_MESSAGE_FROM_STRING_METHOD.invokeStatic(name))));
dataWatcherItems.add(DATA_WATCHER_ITEM_CONSTRUCTOR.newInstance(DWO_CUSTOM_NAME_VISIBLE, !ChatColor.stripColor(name).isEmpty()));
sendEntityMetadata(player, entityId, dataWatcherItems);
}

@Override
Expand All @@ -327,7 +362,7 @@ public void teleportFakeEntity(Player player, Location location, int entityId) {
Validate.notNull(location);

Object packetDataSerializer = PACKET_DATA_SERIALIZER_CONSTRUCTOR.newInstance(Unpooled.buffer());
PACKET_DATA_SERIALIZER_D_METHOD.invoke(packetDataSerializer, entityId);
PACKET_DATA_SERIALIZER_WRITE_INT_METHOD.invoke(packetDataSerializer, entityId);
PACKET_DATA_SERIALIZER_WRITE_DOUBLE_METHOD.invoke(packetDataSerializer, location.getX());
PACKET_DATA_SERIALIZER_WRITE_DOUBLE_METHOD.invoke(packetDataSerializer, location.getY());
PACKET_DATA_SERIALIZER_WRITE_DOUBLE_METHOD.invoke(packetDataSerializer, location.getZ());
Expand All @@ -352,8 +387,8 @@ public void helmetFakeEntity(Player player, ItemStack itemStack, int entityId) {
public void attachFakeEntity(Player player, int vehicleId, int entityId) {
Validate.notNull(player);
Object packetDataSerializer = PACKET_DATA_SERIALIZER_CONSTRUCTOR.newInstance(Unpooled.buffer());
PACKET_DATA_SERIALIZER_D_METHOD.invoke(packetDataSerializer, vehicleId);
PACKET_DATA_SERIALIZER_A_INTS_METHOD.invoke(packetDataSerializer, (Object) new int[] {entityId});
PACKET_DATA_SERIALIZER_WRITE_INT_METHOD.invoke(packetDataSerializer, vehicleId);
PACKET_DATA_SERIALIZER_WRITE_INTS_METHOD.invoke(packetDataSerializer, (Object) new int[] {entityId});
sendPacket(player, PACKET_MOUNT_CONSTRUCTOR.newInstance(packetDataSerializer));
}

Expand Down

0 comments on commit 8ae60c0

Please sign in to comment.