77import org .bukkit .event .inventory .InventoryEvent ;
88
99import java .lang .invoke .MethodHandle ;
10- import java .lang .reflect .Field ;
1110
1211/**
1312 * Helper for NMS-based actions.
@@ -29,6 +28,34 @@ public static Class<?> getOptionalFieldType(Class<?> clazz, String fieldName) {
2928 }
3029 }
3130
31+ /**
32+ * Returns the first of the given class names that exists (multi-mapping support: Mojang-mapped vs legacy Spigot-remapped NMS).
33+ */
34+ private static Class <?> classForFirst (String ... classNames ) throws ClassNotFoundException {
35+ for (String name : classNames ) {
36+ try {
37+ return Class .forName (name );
38+ }
39+ catch (ClassNotFoundException ex ) {
40+ // Try the next candidate name.
41+ }
42+ }
43+ throw new ClassNotFoundException ("None of the candidate NMS classes exist: " + String .join (", " , classNames ));
44+ }
45+
46+ /**
47+ * Returns a handle for the first of the given method names that exists on the class (multi-mapping support: Mojang names vs obfuscated/Spigot names).
48+ */
49+ private static MethodHandle methodHandleForFirst (Class <?> clazz , Class <?>[] params , String ... methodNames ) {
50+ for (String name : methodNames ) {
51+ MethodHandle handle = NMS .getMethodHandle (clazz , name , false , params ); // log=false: missing candidates are expected, don't spam the console
52+ if (handle != null ) {
53+ return handle ;
54+ }
55+ }
56+ return null ;
57+ }
58+
3259 public static void init () {
3360 try {
3461 if (SentinelVersionCompat .v1_10 ) {
@@ -47,9 +74,10 @@ public static void init() {
4774 String broadcastEffectMethod = "broadcastEntityEffect" , dataWatcherSet = "set" ;
4875 if (SentinelVersionCompat .v1_17 ) { // 1.17+ - Mojang mappings update
4976 nmsEntity = Class .forName ("net.minecraft.world.entity.Entity" );
50- nmsWorld = Class .forName ("net.minecraft.world.level.World" ); // Level
51- nmsDataWatcher = Class .forName ("net.minecraft.network.syncher.DataWatcher" ); // SynchedEntityData
52- nmsDataWatcherObject = Class .forName ("net.minecraft.network.syncher.DataWatcherObject" ); // EntityDataAccessor
77+ // Try Mojang-mapped names first (server runtime mappings since 1.20.5+, including 26.1), then the legacy Spigot-remapped names (1.17-1.21).
78+ nmsWorld = classForFirst ("net.minecraft.world.level.Level" , "net.minecraft.world.level.World" );
79+ nmsDataWatcher = classForFirst ("net.minecraft.network.syncher.SynchedEntityData" , "net.minecraft.network.syncher.DataWatcher" );
80+ nmsDataWatcherObject = classForFirst ("net.minecraft.network.syncher.EntityDataAccessor" , "net.minecraft.network.syncher.DataWatcherObject" );
5381 if (SentinelVersionCompat .v1_21 && !SentinelVersionCompat .vFuture ) { // 1.21 names
5482 broadcastEffectMethod = "a" ; // net.minecraft.world.level.Level#broadcastEntityEvent(Entity,byte)
5583 dataWatcherSet = "a" ; // net.minecraft.network.syncher.SynchedEntityData#set
@@ -80,8 +108,12 @@ else if (SentinelVersionCompat.v1_18 && !SentinelVersionCompat.v1_19) { // 1.18
80108 }
81109 NMSENTITY_WORLDGETTER = NMS .getFirstGetter (nmsEntity , nmsWorld );
82110 NMSENTITY_GETDATAWATCHER = NMS .getFirstGetter (nmsEntity , nmsDataWatcher );
83- NMSWORLD_BROADCASTENTITYEFFECT = NMS .getMethodHandle (nmsWorld , broadcastEffectMethod , true , nmsEntity , byte .class );
84- DATWATCHER_SET = NMS .getMethodHandle (nmsDataWatcher , dataWatcherSet , true , nmsDataWatcherObject , Object .class );
111+ // Try the Mojang-mapped method name first (26.1+ runs on Mojang mappings), then fall back to the per-version Spigot/obfuscated name selected above.
112+ NMSWORLD_BROADCASTENTITYEFFECT = methodHandleForFirst (nmsWorld , new Class <?>[]{nmsEntity , byte .class }, "broadcastEntityEvent" , broadcastEffectMethod );
113+ DATWATCHER_SET = methodHandleForFirst (nmsDataWatcher , new Class <?>[]{nmsDataWatcherObject , Object .class }, "set" , dataWatcherSet );
114+ if (NMSWORLD_BROADCASTENTITYEFFECT == null || DATWATCHER_SET == null ) {
115+ nmsWorks = false ; // Couldn't resolve the NMS methods on this version; cosmetic NMS effects will be skipped (plugin otherwise functions normally).
116+ }
85117 }
86118 catch (Throwable ex ) {
87119 ex .printStackTrace ();
0 commit comments