Skip to content

Commit

Permalink
Added 1.20.5 support to Bukkit
Browse files Browse the repository at this point in the history
  • Loading branch information
NEZNAMY committed Apr 23, 2024
1 parent 8693b4f commit c68e135
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 72 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,14 @@

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.*;

/**
* A class representing the n.m.s.DataWatcher class to make work with it much easier
*/
@ToString
public class DataWatcher implements EntityData {

/** NMS Fields */
public static Class<?> DataWatcher;
private static Constructor<?> newDataWatcher;
private static Method DataWatcher_register;
private static Method DataWatcher_markDirty;
public static Method DataWatcher_packDirty;

private static Class<?> DataWatcherObject;
private static Constructor<?> newDataWatcherObject;

private static Object DataWatcherSerializer_BYTE;
private static Object DataWatcherSerializer_FLOAT;
private static Object DataWatcherSerializer_STRING;
Expand All @@ -41,6 +29,15 @@ public class DataWatcher implements EntityData {

private static final int armorStandFlagsPosition = EntityData.getArmorStandFlagsPosition(BukkitReflection.getMinorVersion());

/** 1.19.3+ */
private static Constructor<?> newDataWatcher$Item;

/** 1.19.2- */
public static Class<?> DataWatcher;
private static Constructor<?> newDataWatcher;
private static Method DataWatcher_register;
private static Constructor<?> newDataWatcherObject;

/** Watched data */
private final Map<Integer, Item> dataValues = new HashMap<>();

Expand All @@ -52,58 +49,65 @@ public class DataWatcher implements EntityData {
*/
public static void load() throws ReflectiveOperationException {
int minorVersion = BukkitReflection.getMinorVersion();
DataWatcher = BukkitReflection.getClass("network.syncher.SynchedEntityData", "network.syncher.DataWatcher", "DataWatcher");
if (minorVersion >= 7) {
ComponentConverter.ensureAvailable();
newDataWatcher = DataWatcher.getConstructor(BukkitReflection.getClass("world.entity.Entity", "Entity"));
} else {
newDataWatcher = DataWatcher.getConstructor();
}
if (minorVersion >= 9) {
DataWatcherObject = BukkitReflection.getClass("network.syncher.EntityDataAccessor",
"network.syncher.DataWatcherObject", "DataWatcherObject");
Class<?> dataWatcherRegistry = BukkitReflection.getClass("network.syncher.EntityDataSerializers",
"network.syncher.DataWatcherRegistry", "DataWatcherRegistry");
loadSerializers();
}
if (BukkitReflection.is1_19_3Plus()) {
Class<?> dataWatcher$Item = BukkitReflection.getClass("network.syncher.SynchedEntityData$DataValue", "network.syncher.DataWatcher$c");
Class<?> dataWatcherSerializer = BukkitReflection.getClass("network.syncher.EntityDataSerializer",
"network.syncher.DataWatcherSerializer", "DataWatcherSerializer");
DataWatcher_register = ReflectionUtils.getMethod(
DataWatcher,
new String[]{"define", "register", "a", "m_135372_"}, // {Mojang, Bukkit, Bukkit 1.18+, Mohist 1.18.2}
DataWatcherObject, Object.class
);
newDataWatcherObject = DataWatcherObject.getConstructor(int.class, dataWatcherSerializer);
DataWatcherSerializer_BYTE = ReflectionUtils.getField(dataWatcherRegistry, "BYTE", "a", "f_135027_").get(null); // Mohist 1.18.2
DataWatcherSerializer_FLOAT = ReflectionUtils.getField(dataWatcherRegistry, "FLOAT", "c", "f_135029_").get(null); // Mohist 1.18.2
DataWatcherSerializer_STRING = ReflectionUtils.getField(dataWatcherRegistry, "STRING", "d", "f_135030_").get(null); // Mohist 1.18.2
if (BukkitReflection.is1_19_3Plus()) {
DataWatcherSerializer_OPTIONAL_COMPONENT = ReflectionUtils.getField(dataWatcherRegistry, "OPTIONAL_COMPONENT", "g").get(null);
if (BukkitReflection.is1_19_4Plus()) {
DataWatcherSerializer_BOOLEAN = ReflectionUtils.getField(dataWatcherRegistry, "BOOLEAN", "k").get(null);
} else {
DataWatcherSerializer_BOOLEAN = ReflectionUtils.getField(dataWatcherRegistry, "BOOLEAN", "j").get(null);
}
newDataWatcher$Item = dataWatcher$Item.getConstructor(int.class, dataWatcherSerializer, Object.class);
} else {
DataWatcher = BukkitReflection.getClass("network.syncher.SynchedEntityData", "network.syncher.DataWatcher", "DataWatcher");
if (minorVersion >= 7) {
ComponentConverter.ensureAvailable();
newDataWatcher = DataWatcher.getConstructor(BukkitReflection.getClass("world.entity.Entity", "Entity"));
} else {
if (minorVersion >= 13) {
DataWatcherSerializer_OPTIONAL_COMPONENT = ReflectionUtils.getField(dataWatcherRegistry,
"OPTIONAL_COMPONENT", "f", "f_135032_").get(null); // Mohist 1.18.2
DataWatcherSerializer_BOOLEAN = ReflectionUtils.getField(dataWatcherRegistry,
"BOOLEAN", "i", "f_135035_").get(null); // Mohist 1.18.2
} else {
DataWatcherSerializer_BOOLEAN = dataWatcherRegistry.getDeclaredField("h").get(null);
}
newDataWatcher = DataWatcher.getConstructor();
}
if (minorVersion >= 9) {
Class<?> dataWatcherObject = BukkitReflection.getClass("network.syncher.EntityDataAccessor",
"network.syncher.DataWatcherObject", "DataWatcherObject");
Class<?> dataWatcherSerializer = BukkitReflection.getClass("network.syncher.EntityDataSerializer",
"network.syncher.DataWatcherSerializer", "DataWatcherSerializer");
DataWatcher_register = ReflectionUtils.getMethod(
DataWatcher,
new String[]{"define", "register", "a", "m_135372_"}, // {Mojang, Bukkit, Bukkit 1.18+, Mohist 1.18.2}
dataWatcherObject, Object.class
);
newDataWatcherObject = dataWatcherObject.getConstructor(int.class, dataWatcherSerializer);
} else {
DataWatcher_register = ReflectionUtils.getMethod(
DataWatcher,
new String[]{"func_75682_a", "a"}, int.class, // {Thermos 1.7.10, Bukkit}
Object.class
);
}
} else {
DataWatcher_register = ReflectionUtils.getMethod(
DataWatcher,
new String[]{"func_75682_a", "a"}, int.class, // {Thermos 1.7.10, Bukkit}
Object.class
);
}
if (minorVersion >= 19) {
DataWatcher_packDirty = ReflectionUtils.getMethod(DataWatcher, new String[] {"packDirty", "b"}); // {Mojang, Bukkit}
}
}

private static void loadSerializers() throws ReflectiveOperationException {
Class<?> dataWatcherRegistry = BukkitReflection.getClass("network.syncher.EntityDataSerializers",
"network.syncher.DataWatcherRegistry", "DataWatcherRegistry");
DataWatcherSerializer_BYTE = ReflectionUtils.getField(dataWatcherRegistry, "BYTE", "a", "f_135027_").get(null); // Mohist 1.18.2
DataWatcherSerializer_FLOAT = ReflectionUtils.getField(dataWatcherRegistry, "FLOAT", "c", "f_135029_").get(null); // Mohist 1.18.2
DataWatcherSerializer_STRING = ReflectionUtils.getField(dataWatcherRegistry, "STRING", "d", "f_135030_").get(null); // Mohist 1.18.2
if (BukkitReflection.is1_19_3Plus()) {
DataWatcher_markDirty = ReflectionUtils.getMethods(DataWatcher, void.class, DataWatcherObject).get(0);
DataWatcherSerializer_OPTIONAL_COMPONENT = ReflectionUtils.getField(dataWatcherRegistry, "OPTIONAL_COMPONENT", "g").get(null);
if (BukkitReflection.is1_19_4Plus()) {
DataWatcherSerializer_BOOLEAN = ReflectionUtils.getField(dataWatcherRegistry, "BOOLEAN", "k").get(null);
} else {
DataWatcherSerializer_BOOLEAN = ReflectionUtils.getField(dataWatcherRegistry, "BOOLEAN", "j").get(null);
}
} else {
if (BukkitReflection.getMinorVersion() >= 13) {
DataWatcherSerializer_OPTIONAL_COMPONENT = ReflectionUtils.getField(dataWatcherRegistry,
"OPTIONAL_COMPONENT", "f", "f_135032_").get(null); // Mohist 1.18.2
DataWatcherSerializer_BOOLEAN = ReflectionUtils.getField(dataWatcherRegistry,
"BOOLEAN", "i", "f_135035_").get(null); // Mohist 1.18.2
} else {
DataWatcherSerializer_BOOLEAN = dataWatcherRegistry.getDeclaredField("h").get(null);
}
}
}

Expand Down Expand Up @@ -211,19 +215,27 @@ public void setWitherInvulnerableTime(int time) {
* @return an instance of NMS.DataWatcher with same data
*/
@SneakyThrows
public @NotNull Object build() {
Object nmsWatcher;
if (newDataWatcher.getParameterCount() == 1) { //1.7+
nmsWatcher = newDataWatcher.newInstance(new Object[] {null});
@NotNull
public Object build() {
if (BukkitReflection.is1_19_3Plus()) {
List<Object> items = new ArrayList<>();
for (Item item : dataValues.values()) {
items.add(newDataWatcher$Item.newInstance(item.position, item.serializer, item.value));
}
return items;
} else {
nmsWatcher = newDataWatcher.newInstance();
}
for (Item item : dataValues.values()) {
Object nmsObject = item.createObject();
DataWatcher_register.invoke(nmsWatcher, nmsObject, item.getValue());
if (BukkitReflection.is1_19_3Plus()) DataWatcher_markDirty.invoke(nmsWatcher, nmsObject);
Object nmsWatcher;
if (newDataWatcher.getParameterCount() == 1) { //1.7+
nmsWatcher = newDataWatcher.newInstance(new Object[] {null});
} else {
nmsWatcher = newDataWatcher.newInstance();
}
for (Item item : dataValues.values()) {
Object nmsObject = item.createObject();
DataWatcher_register.invoke(nmsWatcher, nmsObject, item.getValue());
}
return nmsWatcher;
}
return nmsWatcher;
}

/**
Expand All @@ -241,7 +253,7 @@ private static class Item {
private final Object serializer;

/** Item value */
@NotNull
@NonNull
private final Object value;

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ private static void loadEntityMetadata() throws ReflectiveOperationException {
"network.protocol.game.PacketPlayOutEntityMetadata", "PacketPlayOutEntityMetadata", "Packet40EntityMetadata");
if (BukkitReflection.is1_19_3Plus()) {
Constructor<?> constructor = entityMetadataClass.getConstructor(int.class, List.class);
newEntityMetadata = (entityId, data) -> constructor.newInstance(entityId, DataWatcher.DataWatcher_packDirty.invoke(data.build()));
newEntityMetadata = (entityId, data) -> constructor.newInstance(entityId, data.build());
} else {
Constructor<?> constructor = entityMetadataClass.getConstructor(int.class, DataWatcher.DataWatcher, boolean.class);
newEntityMetadata = (entityId, data) -> constructor.newInstance(entityId, data.build(), true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ public static Method getOnlyMethod(@NotNull Class<?> clazz, @NotNull Class<?> re
*/
@NotNull
public static Field getOnlyField(@NotNull Class<?> clazz) {
Field[] fields = clazz.getDeclaredFields();
Field[] fields = Arrays.stream(clazz.getDeclaredFields()).filter(f -> !Modifier.isStatic(f.getModifiers())).toArray(Field[]::new);
if (fields.length != 1) {
throw new IllegalStateException("Class " + clazz.getName() + " is expected to have 1 field, but has " +
fields.length + ": " + Arrays.stream(fields).map(Field::getName).collect(Collectors.toList()));
Expand Down

0 comments on commit c68e135

Please sign in to comment.