1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
|
package de.hysky.skyblocker.skyblock.itemlist;
import de.hysky.skyblocker.utils.ItemUtils;
import de.hysky.skyblocker.utils.NEURepoManager;
import de.hysky.skyblocker.utils.TextTransformer;
import io.github.moulberry.repo.constants.PetNumbers;
import io.github.moulberry.repo.data.NEUItem;
import io.github.moulberry.repo.data.Rarity;
import it.unimi.dsi.fastutil.ints.IntList;
import net.minecraft.component.DataComponentTypes;
import net.minecraft.component.type.*;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtString;
import net.minecraft.registry.Registries;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import net.minecraft.util.Pair;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ItemStackBuilder {
public static final Pattern SKULL_UUID_PATTERN = Pattern.compile("(?<=SkullOwner:\\{)Id:\"(.{36})\"");
public static final Pattern SKULL_TEXTURE_PATTERN = Pattern.compile("(?<=Properties:\\{textures:\\[0:\\{Value:)\"(.+?)\"");
private static final Pattern COLOR_PATTERN = Pattern.compile("color:(\\d+)");
private static final Pattern EXPLOSION_COLOR_PATTERN = Pattern.compile("\\{Explosion:\\{(?:Type:[0-9a-z]+,)?Colors:\\[(?<color>[0-9]+)]\\}");
private static Map<String, Map<Rarity, PetNumbers>> petNums;
public static void loadPetNums() {
try {
petNums = NEURepoManager.NEU_REPO.getConstants().getPetNumbers();
} catch (Exception e) {
ItemRepository.LOGGER.error("Failed to load petnums.json");
}
}
public static ItemStack fromNEUItem(NEUItem item) {
String internalName = item.getSkyblockItemId();
List<Pair<String, String>> injectors = new ArrayList<>(petData(internalName));
String legacyId = item.getMinecraftItemId();
Identifier itemId = Identifier.of(ItemFixerUpper.convertItemId(legacyId, item.getDamage()));
ItemStack stack = new ItemStack(Registries.ITEM.get(itemId));
// Custom Data
NbtCompound customData = new NbtCompound();
// Add Skyblock Item Id
customData.put(ItemUtils.ID, NbtString.of(internalName));
// Item Name
String name = injectData(item.getDisplayName(), injectors);
stack.set(DataComponentTypes.CUSTOM_NAME, TextTransformer.fromLegacy(name));
// Lore
stack.set(DataComponentTypes.LORE, new LoreComponent(item.getLore().stream().map(line -> TextTransformer.fromLegacy(injectData(line, injectors))).map(Text.class::cast).toList()));
String nbttag = item.getNbttag();
// add skull texture
Matcher skullUuid = SKULL_UUID_PATTERN.matcher(nbttag);
Matcher skullTexture = SKULL_TEXTURE_PATTERN.matcher(nbttag);
if (skullUuid.find() && skullTexture.find()) {
UUID uuid = UUID.fromString(skullUuid.group(1));
String textureValue = skullTexture.group(1);
stack.set(DataComponentTypes.PROFILE, new ProfileComponent(Optional.of(internalName), Optional.of(uuid), ItemUtils.propertyMapWithTexture(textureValue)));
}
// add leather armor dye color
Matcher colorMatcher = COLOR_PATTERN.matcher(nbttag);
if (colorMatcher.find()) {
int color = Integer.parseInt(colorMatcher.group(1));
stack.set(DataComponentTypes.DYED_COLOR, new DyedColorComponent(color, false));
}
// add enchantment glint
if (nbttag.contains("ench:")) {
stack.set(DataComponentTypes.ENCHANTMENT_GLINT_OVERRIDE, true);
}
//Hide weapon damage and other useless info
stack.set(DataComponentTypes.ATTRIBUTE_MODIFIERS, new AttributeModifiersComponent(List.of(), false));
// Add firework star color
Matcher explosionColorMatcher = EXPLOSION_COLOR_PATTERN.matcher(nbttag);
if (explosionColorMatcher.find()) {
//We used create an IntArrayList and took the color as the list's capacity and not add anything to the list which y'know casually leaked a lot of memory...
IntList color = IntList.of(Integer.parseInt(explosionColorMatcher.group("color")));
//Forget about the actual ball type because it probably doesn't matter
stack.set(DataComponentTypes.FIREWORK_EXPLOSION, new FireworkExplosionComponent(FireworkExplosionComponent.Type.SMALL_BALL, color, IntList.of(), false, false));
}
// Attach custom nbt data
stack.set(DataComponentTypes.CUSTOM_DATA, NbtComponent.of(customData));
return stack;
}
private static List<Pair<String, String>> petData(String internalName) {
List<Pair<String, String>> list = new ArrayList<>();
String petName = internalName.split(";")[0];
if (!internalName.contains(";") || !petNums.containsKey(petName)) return list;
final Rarity[] rarities = {
Rarity.COMMON,
Rarity.UNCOMMON,
Rarity.RARE,
Rarity.EPIC,
Rarity.LEGENDARY,
Rarity.MYTHIC,
};
Rarity rarity = rarities[Integer.parseInt(internalName.split(";")[1])];
PetNumbers data = petNums.get(petName).get(rarity);
int minLevel = data.getLowLevel();
int maxLevel = data.getHighLevel();
list.add(new Pair<>("\\{LVL\\}", minLevel + " ➡ " + maxLevel));
Map<String, Double> statNumsMin = data.getStatsAtLowLevel().getStatNumbers();
Map<String, Double> statNumsMax = data.getStatsAtHighLevel().getStatNumbers();
Set<Map.Entry<String, Double>> entrySet = statNumsMin.entrySet();
for (Map.Entry<String, Double> entry : entrySet) {
String key = entry.getKey();
String left = "\\{" + key + "\\}";
String right = statNumsMin.get(key) + " ➡ " + statNumsMax.get(key);
list.add(new Pair<>(left, right));
}
List<Double> otherNumsMin = data.getStatsAtLowLevel().getOtherNumbers();
List<Double> otherNumsMax = data.getStatsAtHighLevel().getOtherNumbers();
for (int i = 0; i < otherNumsMin.size(); ++i) {
String left = "\\{" + i + "\\}";
String right = otherNumsMin.get(i) + " ➡ " + otherNumsMax.get(i);
list.add(new Pair<>(left, right));
}
return list;
}
public static String injectData(String string, List<Pair<String, String>> injectors) {
for (Pair<String, String> injector : injectors) {
string = string.replaceAll(injector.getLeft(), injector.getRight());
}
return string;
}
}
|