Skip to content

Commit d9511ca

Browse files
committed
feat: 1.21.9 support
1 parent 9121bc4 commit d9511ca

File tree

5 files changed

+287
-1
lines changed

5 files changed

+287
-1
lines changed

.github/workflows/buildtools.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,5 @@ checkVersion "1.21" "21"
3636
checkVersion "1.21.3" "21"
3737
checkVersion "1.21.4" "21"
3838
checkVersion "1.21.5" "21"
39-
checkVersion "1.21.6" "21"
39+
checkVersion "1.21.6" "21"
40+
checkVersion "1.21.9" "21"

zip-nms/pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,6 @@
2424
<module>zip-nms-v1_21_R3</module>
2525
<module>zip-nms-v1_21_R4</module>
2626
<module>zip-nms-v1_21_R5</module>
27+
<module>zip-nms-v1_21_R6</module>
2728
</modules>
2829
</project>

zip-nms/zip-nms-v1_21_R6/pom.xml

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
2+
<modelVersion>4.0.0</modelVersion>
3+
4+
<parent>
5+
<groupId>net.imprex</groupId>
6+
<artifactId>zip-nms</artifactId>
7+
<version>${revision}</version>
8+
</parent>
9+
10+
<artifactId>zip-nms-v1_21_R5</artifactId>
11+
12+
<dependencies>
13+
<dependency>
14+
<groupId>net.imprex</groupId>
15+
<artifactId>zip-nms-api</artifactId>
16+
<version>${revision}</version>
17+
<scope>provided</scope>
18+
</dependency>
19+
<dependency>
20+
<groupId>org.spigotmc</groupId>
21+
<artifactId>spigot</artifactId>
22+
<version>1.21.9-R0.1-SNAPSHOT</version>
23+
<classifier>remapped-mojang</classifier>
24+
<scope>provided</scope>
25+
</dependency>
26+
</dependencies>
27+
28+
<build>
29+
<plugins>
30+
<plugin>
31+
<groupId>net.md-5</groupId>
32+
<artifactId>specialsource-maven-plugin</artifactId>
33+
<version>${plugin.specialsource.version}</version>
34+
<executions>
35+
<execution>
36+
<phase>package</phase>
37+
<goals>
38+
<goal>remap</goal>
39+
</goals>
40+
<id>remap-obf</id>
41+
<configuration>
42+
<srgIn>
43+
org.spigotmc:minecraft-server:1.21.9-R0.1-SNAPSHOT:txt:maps-mojang</srgIn>
44+
<reverse>true</reverse>
45+
<remappedDependencies>
46+
org.spigotmc:spigot:1.21.9-R0.1-SNAPSHOT:jar:remapped-mojang</remappedDependencies>
47+
<remappedArtifactAttached>true</remappedArtifactAttached>
48+
<remappedClassifierName>remapped-obf</remappedClassifierName>
49+
</configuration>
50+
</execution>
51+
<execution>
52+
<phase>package</phase>
53+
<goals>
54+
<goal>remap</goal>
55+
</goals>
56+
<id>remap-spigot</id>
57+
<configuration>
58+
<inputFile>
59+
${project.build.directory}/${project.artifactId}-${project.version}-remapped-obf.jar</inputFile>
60+
<srgIn>
61+
org.spigotmc:minecraft-server:1.21.9-R0.1-SNAPSHOT:csrg:maps-spigot</srgIn>
62+
<remappedDependencies>
63+
org.spigotmc:spigot:1.21.9-R0.1-SNAPSHOT:jar:remapped-obf</remappedDependencies>
64+
</configuration>
65+
</execution>
66+
</executions>
67+
</plugin>
68+
</plugins>
69+
</build>
70+
</project>
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
package net.imprex.zip.nms.v1_21_R6;
2+
3+
import java.io.ByteArrayInputStream;
4+
import java.io.IOException;
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.UUID;
10+
import java.util.function.BiConsumer;
11+
12+
import org.bukkit.Material;
13+
import org.bukkit.craftbukkit.v1_21_R6.inventory.CraftItemStack;
14+
import org.bukkit.inventory.ItemStack;
15+
import org.bukkit.inventory.meta.SkullMeta;
16+
17+
import com.google.gson.JsonArray;
18+
import com.google.gson.JsonElement;
19+
import com.google.gson.JsonObject;
20+
import com.mojang.authlib.GameProfile;
21+
import com.mojang.authlib.properties.Property;
22+
import com.mojang.serialization.DataResult;
23+
import com.mojang.serialization.Dynamic;
24+
import com.mojang.serialization.DynamicOps;
25+
import com.mojang.serialization.JsonOps;
26+
27+
import net.imprex.zip.common.BPConstants;
28+
import net.imprex.zip.common.ReflectionUtil;
29+
import net.imprex.zip.nms.api.ItemStackContainerResult;
30+
import net.imprex.zip.nms.api.ItemStackWithSlot;
31+
import net.imprex.zip.nms.api.NmsManager;
32+
import net.minecraft.SharedConstants;
33+
import net.minecraft.core.RegistryAccess;
34+
import net.minecraft.nbt.CompoundTag;
35+
import net.minecraft.nbt.ListTag;
36+
import net.minecraft.nbt.NbtAccounter;
37+
import net.minecraft.nbt.NbtIo;
38+
import net.minecraft.nbt.NbtOps;
39+
import net.minecraft.nbt.Tag;
40+
import net.minecraft.server.MinecraftServer;
41+
import net.minecraft.util.datafix.DataFixers;
42+
import net.minecraft.util.datafix.fixes.References;
43+
import net.minecraft.world.item.component.ResolvableProfile;
44+
45+
public class ZipNmsManager implements NmsManager {
46+
47+
private static final int DATA_VERSION = SharedConstants.getCurrentVersion().dataVersion().version();
48+
49+
@SuppressWarnings("deprecation")
50+
private static final RegistryAccess DEFAULT_REGISTRY = MinecraftServer.getServer().registryAccess();
51+
52+
private static final DynamicOps<Tag> DYNAMIC_OPS_NBT = DEFAULT_REGISTRY.createSerializationContext(NbtOps.INSTANCE);
53+
private static final DynamicOps<JsonElement> DYNAMIC_OPS_JSON = DEFAULT_REGISTRY.createSerializationContext(JsonOps.INSTANCE);
54+
55+
private static final BiConsumer<SkullMeta, GameProfile> SET_PROFILE;
56+
57+
static {
58+
BiConsumer<SkullMeta, GameProfile> setProfile = (meta, profile) -> {
59+
throw new NullPointerException("Unable to find 'setProfile' method!");
60+
};
61+
62+
Class<?> craftMetaSkullClass = new ItemStack(Material.PLAYER_HEAD)
63+
.getItemMeta()
64+
.getClass();
65+
66+
Method setResolvableProfileMethod = ReflectionUtil.searchMethod(craftMetaSkullClass, void.class, ResolvableProfile.class);
67+
if (setResolvableProfileMethod != null) {
68+
setProfile = (meta, profile) -> {
69+
try {
70+
setResolvableProfileMethod.invoke(meta, new ResolvableProfile(profile));
71+
} catch (IllegalAccessException | InvocationTargetException e) {
72+
e.printStackTrace();
73+
}
74+
};
75+
} else {
76+
Method setProfileMethod = ReflectionUtil.searchMethod(craftMetaSkullClass, void.class, GameProfile.class);
77+
if (setProfileMethod != null) {
78+
setProfile = (meta, profile) -> {
79+
try {
80+
setProfileMethod.invoke(meta, profile);
81+
} catch (IllegalAccessException | InvocationTargetException e) {
82+
e.printStackTrace();
83+
}
84+
};
85+
}
86+
}
87+
88+
SET_PROFILE = setProfile;
89+
}
90+
91+
@Override
92+
public JsonObject itemstackToJsonElement(ItemStack[] items) {
93+
JsonArray jsonItems = new JsonArray();
94+
for (int slot = 0; slot < items.length; slot++) {
95+
ItemStack item = items[slot];
96+
if (item == null || item.getType() == Material.AIR) {
97+
continue;
98+
}
99+
net.minecraft.world.item.ItemStack minecraftItem = CraftItemStack.asNMSCopy(item);
100+
101+
DataResult<JsonElement> result = net.minecraft.world.item.ItemStack.CODEC.encodeStart(DYNAMIC_OPS_JSON, minecraftItem);
102+
JsonObject resultJson = result.getOrThrow().getAsJsonObject();
103+
104+
resultJson.addProperty(BPConstants.KEY_INVENTORY_SLOT, slot);
105+
jsonItems.add(resultJson);
106+
}
107+
108+
JsonObject outputJson = new JsonObject();
109+
outputJson.addProperty(BPConstants.KEY_INVENTORY_VERSION, BPConstants.INVENTORY_VERSION);
110+
outputJson.addProperty(BPConstants.KEY_INVENTORY_DATA_VERSION, DATA_VERSION);
111+
outputJson.addProperty(BPConstants.KEY_INVENTORY_ITEMS_SIZE, items.length);
112+
outputJson.add(BPConstants.KEY_INVENTORY_ITEMS, jsonItems);
113+
return outputJson;
114+
}
115+
116+
@Override
117+
public ItemStackContainerResult jsonElementToItemStack(JsonObject json) {
118+
// check if current version the same
119+
if (json.get(BPConstants.KEY_INVENTORY_VERSION).getAsInt() != BPConstants.INVENTORY_VERSION) {
120+
throw new IllegalStateException("Unable to convert binary to itemstack because zip version is missmatching");
121+
}
122+
123+
int dataVersion = json.get(BPConstants.KEY_INVENTORY_DATA_VERSION).getAsInt();
124+
int itemsSize = json.get(BPConstants.KEY_INVENTORY_ITEMS_SIZE).getAsInt();
125+
126+
List<ItemStackWithSlot> items = new ArrayList<>();
127+
128+
JsonArray jsonItems = json.get(BPConstants.KEY_INVENTORY_ITEMS).getAsJsonArray();
129+
for (JsonElement item : jsonItems) {
130+
Dynamic<JsonElement> dynamicItem = new Dynamic<>(JsonOps.INSTANCE, item);
131+
Dynamic<JsonElement> dynamicItemFixed = DataFixers.getDataFixer()
132+
.update(References.ITEM_STACK, dynamicItem, dataVersion, DATA_VERSION);
133+
134+
net.minecraft.world.item.ItemStack minecraftItem = net.minecraft.world.item.ItemStack.CODEC
135+
.parse(DYNAMIC_OPS_JSON, dynamicItemFixed.getValue())
136+
.getOrThrow();
137+
138+
ItemStack bukkitItem = CraftItemStack.asCraftMirror(minecraftItem);
139+
int slot = item.getAsJsonObject().get(BPConstants.KEY_INVENTORY_SLOT).getAsInt();
140+
141+
items.add(new ItemStackWithSlot(slot, bukkitItem));
142+
}
143+
144+
return new ItemStackContainerResult(itemsSize, items);
145+
}
146+
147+
@Override
148+
public JsonObject migrateToJsonElement(byte[] binary) {
149+
CompoundTag compound;
150+
try (ByteArrayInputStream inputStream = new ByteArrayInputStream(binary)) {
151+
compound = NbtIo.readCompressed(inputStream, NbtAccounter.unlimitedHeap());
152+
} catch (IOException e) {
153+
throw new IllegalStateException("Unable to parse binary to nbt", e);
154+
}
155+
156+
ListTag list = compound.getListOrEmpty("i");
157+
158+
int currentSlot = 0;
159+
160+
JsonArray jsonItems = new JsonArray();
161+
for (Tag base : list) {
162+
if (base instanceof CompoundTag itemTag) {
163+
String itemType = itemTag.getString("id").orElse("");
164+
if (itemType.equals("minecraft:air")) {
165+
currentSlot++;
166+
continue;
167+
}
168+
169+
Dynamic<Tag> dynamicItem = new Dynamic<>(NbtOps.INSTANCE, itemTag);
170+
net.minecraft.world.item.ItemStack minecraftItem = net.minecraft.world.item.ItemStack.CODEC
171+
.parse(DYNAMIC_OPS_NBT, dynamicItem.getValue())
172+
.getOrThrow();
173+
174+
DataResult<JsonElement> result = net.minecraft.world.item.ItemStack.CODEC.encodeStart(DYNAMIC_OPS_JSON, minecraftItem);
175+
JsonObject resultJson = result.getOrThrow().getAsJsonObject();
176+
177+
resultJson.addProperty(BPConstants.KEY_INVENTORY_SLOT, currentSlot);
178+
jsonItems.add(resultJson);
179+
180+
currentSlot++;
181+
}
182+
}
183+
184+
JsonObject json = new JsonObject();
185+
json.addProperty(BPConstants.KEY_INVENTORY_VERSION, BPConstants.INVENTORY_VERSION);
186+
json.addProperty(BPConstants.KEY_INVENTORY_DATA_VERSION, DATA_VERSION);
187+
json.addProperty(BPConstants.KEY_INVENTORY_ITEMS_SIZE, list.size());
188+
json.add(BPConstants.KEY_INVENTORY_ITEMS, jsonItems);
189+
return json;
190+
}
191+
192+
@Override
193+
public void setSkullProfile(SkullMeta meta, String texture) {
194+
try {
195+
GameProfile gameProfile = new GameProfile(UUID.randomUUID(), "");
196+
gameProfile.getProperties().put("textures", new Property("textures", texture));
197+
198+
SET_PROFILE.accept(meta, gameProfile);
199+
} catch (Exception e) {
200+
e.printStackTrace();
201+
}
202+
}
203+
204+
@Override
205+
public boolean isAir(Material material) {
206+
return material == null || material == Material.AIR;
207+
}
208+
}

zip-plugin/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,5 +119,11 @@
119119
<version>${revision}</version>
120120
<scope>compile</scope>
121121
</dependency>
122+
<dependency>
123+
<groupId>net.imprex</groupId>
124+
<artifactId>zip-nms-v1_21_R6</artifactId>
125+
<version>${revision}</version>
126+
<scope>compile</scope>
127+
</dependency>
122128
</dependencies>
123129
</project>

0 commit comments

Comments
 (0)