Skip to content

Commit 9c54a32

Browse files
authored
feat: 1.21.9 support (#46)
1 parent 9121bc4 commit 9c54a32

File tree

6 files changed

+294
-1
lines changed

6 files changed

+294
-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-common/src/main/java/net/imprex/zip/common/MinecraftVersion.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ private static final class NmsMapping {
1818
private static final List<NmsMapping> MAPPINGS = new ArrayList<>();
1919

2020
static {
21+
MAPPINGS.add(new NmsMapping("1.21.9", "v1_21_R6"));
2122
MAPPINGS.add(new NmsMapping("1.21.6", "v1_21_R5"));
2223
MAPPINGS.add(new NmsMapping("1.21.5", "v1_21_R4"));
2324
MAPPINGS.add(new NmsMapping("1.21.4", "v1_21_R3"));

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

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)