Skip to content

Commit 0d3ef90

Browse files
committed
feat: moved from binary format to json
feat: added migrate command for converting all existing backpacks at once fix: giveUnsueableContent is now saving after the payer recived there items
1 parent 301b6aa commit 0d3ef90

File tree

33 files changed

+2188
-624
lines changed

33 files changed

+2188
-624
lines changed

zip-api/src/main/java/net/imprex/zip/api/ZIPHandler.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,6 @@ public interface ZIPHandler {
1616
ZIPBackpackType getBackpackType(ItemStack item);
1717

1818
boolean isBackpack(ItemStack item);
19+
20+
ZIPUniqueId getUniqueId(ItemStack item);
1921
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package net.imprex.zip.common;
2+
3+
public class BPKey {
4+
5+
public static final String VERSION = "version";
6+
7+
public static final String ID = "id";
8+
public static final String TYPE_RAW = "typeRaw";
9+
public static final String INVENTORY = "inventory";
10+
11+
public static final String INVENTORY_VERSION = "version";
12+
public static final String INVENTORY_DATA_VERSION = "dataVersion";
13+
public static final String INVENTORY_ITEMS = "items";
14+
public static final String INVENTORY_ITEMS_SIZE = "itemsSize";
15+
public static final String INVENTORY_SLOT = "ZIPslot";
16+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package net.imprex.zip.common;
2+
3+
import org.bukkit.inventory.ItemStack;
4+
5+
public record ItemStackWithSlot(ItemStack item, int slot) {
6+
}

zip-plugin/src/main/java/net/imprex/zip/util/ZIPLogger.java renamed to zip-common/src/main/java/net/imprex/zip/common/ZIPLogger.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package net.imprex.zip.util;
1+
package net.imprex.zip.common;
22

33
import java.util.logging.Level;
44
import java.util.logging.Logger;

zip-nms/zip-nms-api/src/main/java/net/imprex/zip/nms/api/NmsManager.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
package net.imprex.zip.nms.api;
22

3-
import java.util.List;
4-
53
import org.bukkit.Material;
64
import org.bukkit.inventory.ItemStack;
75
import org.bukkit.inventory.meta.SkullMeta;
86

7+
import com.google.gson.JsonObject;
8+
99
public interface NmsManager {
1010

11-
byte[] itemstackToBinary(ItemStack[] items);
11+
JsonObject itemstackToJsonElement(ItemStack[] items);
1212

13-
List<ItemStack> binaryToItemStack(byte[] binary);
13+
ItemStack[] jsonElementToItemStack(JsonObject jsonElement);
14+
15+
JsonObject migrateToJsonElement(byte[] binary);
1416

1517
void setSkullProfile(SkullMeta meta, String texture);
1618

zip-nms/zip-nms-v1_19_R1/src/main/java/net/imprex/zip/nms/v1_19_R1/ZipNmsManager.java

Lines changed: 163 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
package net.imprex.zip.nms.v1_19_R1;
22

33
import java.io.ByteArrayInputStream;
4-
import java.io.ByteArrayOutputStream;
4+
import java.io.IOException;
55
import java.lang.reflect.Method;
66
import java.util.ArrayList;
7+
import java.util.Arrays;
8+
import java.util.Iterator;
79
import java.util.List;
810
import java.util.UUID;
911

@@ -12,67 +14,194 @@
1214
import org.bukkit.inventory.ItemStack;
1315
import org.bukkit.inventory.meta.SkullMeta;
1416

17+
import com.google.gson.JsonArray;
18+
import com.google.gson.JsonElement;
19+
import com.google.gson.JsonObject;
1520
import com.mojang.authlib.GameProfile;
1621
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;
1726

27+
import net.imprex.zip.common.BPKey;
1828
import net.imprex.zip.common.ReflectionUtil;
29+
import net.imprex.zip.common.ZIPLogger;
1930
import net.imprex.zip.nms.api.NmsManager;
31+
import net.minecraft.SharedConstants;
32+
import net.minecraft.core.RegistryAccess;
2033
import net.minecraft.nbt.CompoundTag;
2134
import net.minecraft.nbt.ListTag;
2235
import net.minecraft.nbt.NbtIo;
36+
import net.minecraft.nbt.NbtOps;
2337
import net.minecraft.nbt.Tag;
38+
import net.minecraft.resources.RegistryOps;
39+
import net.minecraft.server.MinecraftServer;
40+
import net.minecraft.util.datafix.DataFixers;
41+
import net.minecraft.util.datafix.fixes.References;
2442

2543
public class ZipNmsManager implements NmsManager {
2644

2745
private static final Class<?> CRAFTMETASKULL_CLASS = ReflectionUtil.getCraftBukkitClass("inventory.CraftMetaSkull");
2846
private static final Method CRAFTMETASKULL_SET_PROFILE = ReflectionUtil.getMethod(CRAFTMETASKULL_CLASS,
2947
"setProfile", GameProfile.class);
3048

31-
public byte[] nbtToBinary(CompoundTag compound) {
32-
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
33-
NbtIo.writeCompressed(compound, outputStream);
34-
return outputStream.toByteArray();
35-
} catch (Exception e) {
36-
e.printStackTrace();
37-
}
38-
return null;
39-
}
49+
private static final int DATA_VERSION = SharedConstants.getCurrentVersion().getDataVersion().getVersion();
4050

41-
public CompoundTag binaryToNBT(byte[] binary) {
42-
try (ByteArrayInputStream inputStream = new ByteArrayInputStream(binary)) {
43-
return NbtIo.readCompressed(inputStream);
44-
} catch (Exception e) {
45-
e.printStackTrace();
46-
}
47-
return new CompoundTag();
48-
}
51+
@SuppressWarnings("deprecation")
52+
private static final RegistryAccess DEFAULT_REGISTRY = MinecraftServer.getServer().registryAccess();
53+
54+
private static final DynamicOps<Tag> DYNAMIC_OPS_NBT = RegistryOps.create(NbtOps.INSTANCE, DEFAULT_REGISTRY);
55+
private static final DynamicOps<JsonElement> DYNAMIC_OPS_JSON = RegistryOps.create(JsonOps.INSTANCE, DEFAULT_REGISTRY);
4956

5057
@Override
51-
public byte[] itemstackToBinary(ItemStack[] items) {
52-
CompoundTag inventory = new CompoundTag();
53-
ListTag list = new ListTag();
54-
for (ItemStack itemStack : items) {
55-
net.minecraft.world.item.ItemStack craftItem = CraftItemStack.asNMSCopy(itemStack);
56-
list.add(craftItem.save(new CompoundTag()));
58+
public JsonObject itemstackToJsonElement(ItemStack[] items) {
59+
JsonArray jsonItems = new JsonArray();
60+
for (int slot = 0; slot < items.length; slot++) {
61+
ItemStack item = items[slot];
62+
if (item == null || item.getType() == Material.AIR) {
63+
continue;
64+
}
65+
net.minecraft.world.item.ItemStack minecraftItem = CraftItemStack.asNMSCopy(item);
66+
67+
DataResult<JsonElement> result = net.minecraft.world.item.ItemStack.CODEC.encodeStart(DYNAMIC_OPS_JSON, minecraftItem);
68+
JsonObject resultJson = result.getOrThrow(false, error -> {}).getAsJsonObject();
69+
70+
resultJson.addProperty(BPKey.INVENTORY_SLOT, slot);
71+
jsonItems.add(resultJson);
5772
}
58-
inventory.put("i", list);
59-
return nbtToBinary(inventory);
73+
74+
JsonObject outputJson = new JsonObject();
75+
outputJson.addProperty(BPKey.INVENTORY_VERSION, 2);
76+
outputJson.addProperty(BPKey.INVENTORY_DATA_VERSION, DATA_VERSION);
77+
outputJson.addProperty(BPKey.INVENTORY_ITEMS_SIZE, items.length);
78+
outputJson.add(BPKey.INVENTORY_ITEMS, jsonItems);
79+
return outputJson;
6080
}
6181

6282
@Override
63-
public List<ItemStack> binaryToItemStack(byte[] binary) {
64-
CompoundTag nbt = binaryToNBT(binary);
65-
List<ItemStack> items = new ArrayList<>();
66-
if (nbt.contains("i", 9)) {
67-
ListTag list = nbt.getList("i", 10);
68-
for (Tag base : list) {
69-
if (base instanceof CompoundTag) {
70-
items.add(CraftItemStack.asBukkitCopy(net.minecraft.world.item.ItemStack.of((CompoundTag) base)));
83+
public ItemStack[] jsonElementToItemStack(JsonObject json) {
84+
// check if current version the same
85+
if (json.get(BPKey.INVENTORY_VERSION).getAsInt() != 2) {
86+
throw new IllegalStateException("Unable to convert binary to itemstack because zip version is missmatching");
87+
}
88+
89+
int dataVersion = json.get(BPKey.INVENTORY_DATA_VERSION).getAsInt();
90+
int itemsSize = json.get(BPKey.INVENTORY_ITEMS_SIZE).getAsInt();
91+
92+
// convert json into bukkit item
93+
ItemStack[] items = new ItemStack[itemsSize];
94+
Arrays.fill(items, new ItemStack(Material.AIR));
95+
96+
List<ItemStack> duplicateSlot = null;
97+
98+
JsonArray jsonItems = json.get(BPKey.INVENTORY_ITEMS).getAsJsonArray();
99+
for (JsonElement item : jsonItems) {
100+
Dynamic<JsonElement> dynamicItem = new Dynamic<>(JsonOps.INSTANCE, item);
101+
Dynamic<JsonElement> dynamicItemFixed = DataFixers.getDataFixer()
102+
.update(References.ITEM_STACK, dynamicItem, dataVersion, DATA_VERSION);
103+
104+
net.minecraft.world.item.ItemStack minecraftItem = net.minecraft.world.item.ItemStack.CODEC
105+
.parse(DYNAMIC_OPS_JSON, dynamicItemFixed.getValue())
106+
.getOrThrow(false, error -> {});
107+
108+
ItemStack bukkitItem = CraftItemStack.asCraftMirror(minecraftItem);
109+
int slot = item.getAsJsonObject().get(BPKey.INVENTORY_SLOT).getAsInt();
110+
111+
if (itemsSize <= slot) {
112+
// something went wrong !? maybe user modified it him self
113+
ZIPLogger.warn("Slot size was extended from " + itemsSize + " to " + slot + " this shoudt not happen. Do not change the slot number inside the config manuel!?");
114+
115+
ItemStack[] newItems = new ItemStack[slot + 1];
116+
System.arraycopy(items, 0, newItems, 0, items.length);
117+
Arrays.fill(newItems, items.length, newItems.length, new ItemStack(Material.AIR));
118+
items = newItems;
119+
}
120+
121+
if (items[slot].getType() != Material.AIR) {
122+
if (duplicateSlot == null) {
123+
duplicateSlot = new ArrayList<>();
71124
}
125+
duplicateSlot.add(bukkitItem);
126+
ZIPLogger.warn("Duplicate item found on slot " + slot + " this shoudt not happen. Do not change the slot number inside the config manuel!?");
127+
} else {
128+
items[slot] = bukkitItem;
72129
}
73130
}
131+
132+
// fill existing empty slots with duplicate item
133+
while (duplicateSlot != null && !duplicateSlot.isEmpty()) {
134+
outher: for (Iterator<ItemStack> iterator = duplicateSlot.iterator(); iterator.hasNext();) {
135+
ItemStack itemStack = (ItemStack) iterator.next();
136+
137+
for (int i = 0; i < items.length; i++) {
138+
if (items[i].getType() == Material.AIR) {
139+
items[i] = itemStack;
140+
iterator.remove();
141+
break;
142+
} else if (i == items.length - 1) {
143+
break outher;
144+
}
145+
}
146+
}
147+
148+
// extend slot limit and try again
149+
if (!duplicateSlot.isEmpty()) {
150+
int extendedSlots = items.length + duplicateSlot.size();
151+
ItemStack[] newItems = new ItemStack[extendedSlots];
152+
System.arraycopy(items, 0, newItems, 0, items.length);
153+
Arrays.fill(newItems, items.length, newItems.length, new ItemStack(Material.AIR));
154+
items = newItems;
155+
}
156+
}
157+
74158
return items;
75159
}
160+
161+
@Override
162+
public JsonObject migrateToJsonElement(byte[] binary) {
163+
CompoundTag compound;
164+
try (ByteArrayInputStream inputStream = new ByteArrayInputStream(binary)) {
165+
compound = NbtIo.readCompressed(inputStream);
166+
} catch (IOException e) {
167+
throw new IllegalStateException("Unable to parse binary to nbt", e);
168+
}
169+
170+
ListTag list = compound.getList("i", 10);
171+
172+
int currentSlot = 0;
173+
174+
JsonArray jsonItems = new JsonArray();
175+
for (Tag base : list) {
176+
if (base instanceof CompoundTag itemTag) {
177+
String itemType = itemTag.getString("id");
178+
if (itemType.equals("minecraft:air")) {
179+
currentSlot++;
180+
continue;
181+
}
182+
183+
Dynamic<Tag> dynamicItem = new Dynamic<>(NbtOps.INSTANCE, itemTag);
184+
net.minecraft.world.item.ItemStack minecraftItem = net.minecraft.world.item.ItemStack.CODEC
185+
.parse(DYNAMIC_OPS_NBT, dynamicItem.getValue())
186+
.getOrThrow(false, error -> {});
187+
188+
DataResult<JsonElement> result = net.minecraft.world.item.ItemStack.CODEC.encodeStart(DYNAMIC_OPS_JSON, minecraftItem);
189+
JsonObject resultJson = result.getOrThrow(false, error -> {}).getAsJsonObject();
190+
191+
resultJson.addProperty(BPKey.INVENTORY_SLOT, currentSlot);
192+
jsonItems.add(resultJson);
193+
194+
currentSlot++;
195+
}
196+
}
197+
198+
JsonObject json = new JsonObject();
199+
json.addProperty(BPKey.INVENTORY_VERSION, 2);
200+
json.addProperty(BPKey.INVENTORY_DATA_VERSION, DATA_VERSION);
201+
json.addProperty(BPKey.INVENTORY_ITEMS_SIZE, list.size());
202+
json.add(BPKey.INVENTORY_ITEMS, jsonItems);
203+
return json;
204+
}
76205

77206
@Override
78207
public void setSkullProfile(SkullMeta meta, String texture) {

0 commit comments

Comments
 (0)