1+ package net .imprex .zip .nms .v1_21_R3 ;
2+
3+ import java .io .ByteArrayInputStream ;
4+ import java .io .ByteArrayOutputStream ;
5+ import java .lang .reflect .InvocationTargetException ;
6+ import java .lang .reflect .Method ;
7+ import java .util .ArrayList ;
8+ import java .util .List ;
9+ import java .util .Optional ;
10+ import java .util .UUID ;
11+ import java .util .function .BiConsumer ;
12+
13+ import org .bukkit .Material ;
14+ import org .bukkit .craftbukkit .v1_21_R3 .CraftRegistry ;
15+ import org .bukkit .craftbukkit .v1_21_R3 .inventory .CraftItemStack ;
16+ import org .bukkit .inventory .ItemStack ;
17+ import org .bukkit .inventory .meta .SkullMeta ;
18+
19+ import com .mojang .authlib .GameProfile ;
20+ import com .mojang .authlib .properties .Property ;
21+
22+ import net .imprex .zip .common .ReflectionUtil ;
23+ import net .imprex .zip .nms .api .NmsManager ;
24+ import net .minecraft .core .RegistryAccess ;
25+ import net .minecraft .nbt .CompoundTag ;
26+ import net .minecraft .nbt .ListTag ;
27+ import net .minecraft .nbt .NbtAccounter ;
28+ import net .minecraft .nbt .NbtIo ;
29+ import net .minecraft .nbt .Tag ;
30+ import net .minecraft .world .item .component .ResolvableProfile ;
31+
32+ public class ZipNmsManager implements NmsManager {
33+
34+ private static final BiConsumer <SkullMeta , GameProfile > SET_PROFILE ;
35+
36+ private static final RegistryAccess DEFAULT_REGISTRY = CraftRegistry .getMinecraftRegistry ();
37+
38+ private static final CompoundTag NBT_EMPTY_ITEMSTACK = new CompoundTag ();
39+
40+ static {
41+ NBT_EMPTY_ITEMSTACK .putString ("id" , "minecraft:air" );
42+
43+ BiConsumer <SkullMeta , GameProfile > setProfile = (meta , profile ) -> {
44+ throw new NullPointerException ("Unable to find 'setProfile' method!" );
45+ };
46+
47+ Class <?> craftMetaSkullClass = new ItemStack (Material .PLAYER_HEAD )
48+ .getItemMeta ()
49+ .getClass ();
50+
51+ Method setResolvableProfileMethod = ReflectionUtil .searchMethod (craftMetaSkullClass , void .class , ResolvableProfile .class );
52+ if (setResolvableProfileMethod != null ) {
53+ setProfile = (meta , profile ) -> {
54+ try {
55+ setResolvableProfileMethod .invoke (meta , new ResolvableProfile (profile ));
56+ } catch (IllegalAccessException | InvocationTargetException e ) {
57+ e .printStackTrace ();
58+ }
59+ };
60+ } else {
61+ Method setProfileMethod = ReflectionUtil .searchMethod (craftMetaSkullClass , void .class , GameProfile .class );
62+ if (setProfileMethod != null ) {
63+ setProfile = (meta , profile ) -> {
64+ try {
65+ setProfileMethod .invoke (meta , profile );
66+ } catch (IllegalAccessException | InvocationTargetException e ) {
67+ e .printStackTrace ();
68+ }
69+ };
70+ }
71+ }
72+
73+ SET_PROFILE = setProfile ;
74+ }
75+
76+ public byte [] nbtToBinary (CompoundTag compound ) {
77+ try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream ()) {
78+ NbtIo .writeCompressed (compound , outputStream );
79+ return outputStream .toByteArray ();
80+ } catch (Exception e ) {
81+ e .printStackTrace ();
82+ }
83+ return null ;
84+ }
85+
86+ public CompoundTag binaryToNBT (byte [] binary ) {
87+ try (ByteArrayInputStream inputStream = new ByteArrayInputStream (binary )) {
88+ return NbtIo .readCompressed (inputStream , NbtAccounter .unlimitedHeap ());
89+ } catch (Exception e ) {
90+ e .printStackTrace ();
91+ }
92+ return new CompoundTag ();
93+ }
94+
95+ @ Override
96+ public byte [] itemstackToBinary (ItemStack [] items ) {
97+ CompoundTag inventory = new CompoundTag ();
98+ ListTag list = new ListTag ();
99+ for (ItemStack itemStack : items ) {
100+ if (itemStack == null || itemStack .getType () == Material .AIR ) {
101+ list .add (NBT_EMPTY_ITEMSTACK );
102+ } else {
103+ net .minecraft .world .item .ItemStack craftItem = CraftItemStack .asNMSCopy (itemStack );
104+ Tag tag = craftItem .save (DEFAULT_REGISTRY );
105+ list .add (tag );
106+ }
107+ }
108+ inventory .put ("i" , list );
109+ return nbtToBinary (inventory );
110+ }
111+
112+ @ Override
113+ public List <ItemStack > binaryToItemStack (byte [] binary ) {
114+ CompoundTag nbt = binaryToNBT (binary );
115+ List <ItemStack > items = new ArrayList <>();
116+ if (nbt .contains ("i" , 9 )) {
117+ ListTag list = nbt .getList ("i" , 10 );
118+ for (Tag base : list ) {
119+ if (base instanceof CompoundTag itemTag ) {
120+ if (itemTag .getString ("id" ).equals ("minecraft:air" )) {
121+ items .add (new ItemStack (Material .AIR ));
122+ } else {
123+ Optional <net .minecraft .world .item .ItemStack > optional = net .minecraft .world .item .ItemStack .parse (DEFAULT_REGISTRY , itemTag );
124+ if (optional .isPresent ()) {
125+ items .add (CraftItemStack .asBukkitCopy (optional .get ()));
126+ }
127+ }
128+ }
129+ }
130+ }
131+ return items ;
132+ }
133+
134+ @ Override
135+ public void setSkullProfile (SkullMeta meta , String texture ) {
136+ try {
137+ GameProfile gameProfile = new GameProfile (UUID .randomUUID (), "" );
138+ gameProfile .getProperties ().put ("textures" , new Property ("textures" , texture ));
139+
140+ SET_PROFILE .accept (meta , gameProfile );
141+ } catch (Exception e ) {
142+ e .printStackTrace ();
143+ }
144+ }
145+
146+ @ Override
147+ public boolean isAir (Material material ) {
148+ return material == null || material == Material .AIR ;
149+ }
150+ }
0 commit comments