4545 * All the parameters are non-null. 
4646 * 
4747 * @author Crypto Morin 
48-  * @version 5.3.0  
48+  * @version 5.3.1  
4949 */ 
5050public  final  class  NMSExtras  {
51+     public  static  final  Class <?> EntityLivingClass  = getNMSClass ("world.entity" , "EntityLiving" );
5152    public  static  final  MethodHandle  EXP_PACKET ;
5253    public  static  final  MethodHandle  ENTITY_PACKET ;
5354    public  static  final  MethodHandle  WORLD_HANDLE , ENTITY_HANDLE ;
5455    public  static  final  MethodHandle  LIGHTNING_ENTITY ;
5556    public  static  final  MethodHandle  VEC3D ;
57+     public  static  final  MethodHandle  GET_DATA_WATCHER , DATA_WATCHER_GET_ITEM , DATA_WATCHER_SET_ITEM ;
5658    public  static  final  MethodHandle  PACKET_PLAY_OUT_OPEN_SIGN_EDITOR , PACKET_PLAY_OUT_BLOCK_CHANGE ;
5759
5860    public  static  final  MethodHandle  ANIMATION_PACKET , ANIMATION_TYPE , ANIMATION_ENTITY_ID ;
@@ -94,7 +96,7 @@ public final class NMSExtras {
9496        MethodHandle  tileEntitySign  = null , tileEntitySign_getUpdatePacket  = null , tileEntitySign_setLine  = null , signText  = null ;
9597
9698        MethodHandle  playOutMultiBlockChange  = null , multiBlockChangeInfo  = null , chunkWrapper  = null , chunkWrapperSet  = null ,
97-                 shortsOrInfo  = null , setBlockData  = null ;
99+                 shortsOrInfo  = null , setBlockData  = null ,  getDataWatcher  =  null ,  dataWatcherGetItem  =  null ,  dataWatcherSetItem  =  null ;
98100
99101        try  {
100102            Class <?> nmsEntityType  = getNMSClass ("world.entity" , "EntityTypes" );
@@ -109,6 +111,13 @@ public final class NMSExtras {
109111            Class <?> IChatBaseComponent  = getNMSClass ("network.chat" , "IChatBaseComponent" );
110112            Class <?> TileEntitySign  = getNMSClass ("world.level.block.entity" , "TileEntitySign" );
111113            Class <?> PacketPlayOutTileEntityData  = getNMSClass ("network.protocol.game" , "PacketPlayOutTileEntityData" );
114+             Class <?> DataWatcherClass  = getNMSClass ("network.syncher" , "DataWatcher" );
115+             Class <?> DataWatcherItemClass  = getNMSClass ("network.syncher" , "DataWatcher$Item" );
116+             Class <?> DataWatcherObjectClass  = getNMSClass ("network.syncher" , "DataWatcherObject" );
117+ 
118+ //            getDataWatcher = lookup.findVirtual(EntityLivingClass, "al", MethodType.methodType(DataWatcherClass)); 
119+ //            dataWatcherGetItem = lookup.findVirtual(DataWatcherClass, "b", MethodType.methodType(Object.class, DataWatcherObjectClass)); //  private <T> Item<T> c(DataWatcherObject<T> datawatcherobject) 
120+ //            dataWatcherSetItem = lookup.findVirtual(DataWatcherClass, "b", MethodType.methodType(void.class, DataWatcherItemClass, Object.class)); //  private <T> Item<T> c(DataWatcherObject<T> datawatcherobject) 
112121
113122            getBukkitEntity  = lookup .findVirtual (nmsEntity , "getBukkitEntity" , MethodType .methodType (craftEntity ));
114123            entityHandle  = lookup .findVirtual (craftEntity , "getHandle" , MethodType .methodType (nmsEntity ));
@@ -236,6 +245,9 @@ public final class NMSExtras {
236245            ex .printStackTrace ();
237246        }
238247
248+         GET_DATA_WATCHER  = getDataWatcher ;
249+         DATA_WATCHER_GET_ITEM  = dataWatcherGetItem ;
250+         DATA_WATCHER_SET_ITEM  = dataWatcherSetItem ;
239251        EXP_PACKET  = expPacket ;
240252        ENTITY_PACKET  = entityPacket ;
241253        WORLD_HANDLE  = worldHandle ;
@@ -327,6 +339,67 @@ public static void lightning(Collection<Player> players, Location location, bool
327339        }
328340    }
329341
342+     public  static  void  getData (LivingEntity  entity , DataWatcherItemType  id ) {
343+         try  {
344+             Object  dataWatcher  = GET_DATA_WATCHER .invoke (entity );
345+             DATA_WATCHER_GET_ITEM .invoke (dataWatcher , id );
346+         } catch  (Throwable  e ) {
347+             throw  new  RuntimeException (e );
348+         }
349+     }
350+ 
351+     public  static  Object  setData (LivingEntity  entity , DataWatcherItemType  id , Object  value ) {
352+         try  {
353+             Object  dataWatcher  = GET_DATA_WATCHER .invoke (entity );
354+             return  DATA_WATCHER_SET_ITEM .invoke (dataWatcher , id , value );
355+         } catch  (Throwable  e ) {
356+             throw  new  RuntimeException (e );
357+         }
358+     }
359+ 
360+     public  static  Object  getStaticField (Class <?> clazz , String  name ) {
361+         try  {
362+             Field  field  = clazz .getDeclaredField (name );
363+             field .setAccessible (true );
364+             return  field .get (null );
365+         } catch  (Throwable  e ) {
366+             throw  new  RuntimeException (e );
367+         }
368+     }
369+ 
370+     public  enum  DataWatcherItemType  {
371+         // protected static final DataWatcherObject<Byte> DATA_LIVING_ENTITY_FLAGS = DataWatcher.defineId(EntityLiving.class, DataWatcherRegistry.BYTE); 
372+         DATA_LIVING_ENTITY_FLAGS (getStaticField (EntityLivingClass , "t" ));
373+ 
374+         private  final  Object  id ;
375+ 
376+         DataWatcherItemType (Object  DataWatcherObject ) {
377+             try  {
378+                 // public int a() { return this.a; } 
379+                 // Method idMethod = DataWatcherObject.getClass().getMethod("a"); 
380+                 this .id  = DataWatcherObject ;
381+             } catch  (Throwable  e ) {
382+                 throw  new  RuntimeException (e );
383+             }
384+         }
385+ 
386+         public  Object  getId () {
387+             return  id ;
388+         }
389+     }
390+ 
391+     public  static  void  spinEntity (LivingEntity  entity , float  ticks ) {
392+         // https://wiki.vg/Entity_metadata#Living_Entity 
393+         // Referenced as "Riptiding" or "AutoSpinAttack" modes in code. 
394+         // EntityLiving.r(int ticks) doesn't exist in newer versions. 
395+ //        EntityLiving entityLiv = ((CraftPlayer) entity).getHandle(); 
396+ //        DataWatcher dataWatcher = entityLiv.al(); 
397+ //        dataWatcher.b((DataWatcherObject<Byte>) DataWatcherItemType.DATA_LIVING_ENTITY_FLAGS.getId(), (byte) 0x04); 
398+     }
399+ 
400+     /** 
401+      * For the trident riptide animation use {@link #spinEntity(LivingEntity, float)} instead. 
402+      */ 
330403    public  static  void  animation (Collection <? extends  Player > players , LivingEntity  entity , Animation  animation ) {
331404        try  {
332405            // https://wiki.vg/Protocol#Entity_Animation_.28clientbound.29 
0 commit comments