aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron <51387595+AzureAaron@users.noreply.github.com>2024-03-02 15:16:27 -0500
committerAaron <51387595+AzureAaron@users.noreply.github.com>2024-04-26 16:23:20 -0400
commit4e2924407645b04c30d4a2823a1d9d0983c2c790 (patch)
treeee6d4ba29f50d3cdd76216fee0193dad07752627
parentcc00542e78fd87e0b554ab2a74d1cb193feabbb2 (diff)
downloadSkyblocker-4e2924407645b04c30d4a2823a1d9d0983c2c790.tar.gz
Skyblocker-4e2924407645b04c30d4a2823a1d9d0983c2c790.tar.bz2
Skyblocker-4e2924407645b04c30d4a2823a1d9d0983c2c790.zip
24w09a
-rw-r--r--build.gradle7
-rw-r--r--gradle.properties10
-rw-r--r--src/main/java/de/hysky/skyblocker/debug/Debug.java2
-rw-r--r--src/main/java/de/hysky/skyblocker/mixin/ArmorTrimMixin.java34
-rw-r--r--src/main/java/de/hysky/skyblocker/mixin/ComponentHolderMixin.java39
-rw-r--r--src/main/java/de/hysky/skyblocker/mixin/DyedColorComponentMixin.java (renamed from src/main/java/de/hysky/skyblocker/mixin/DyeableItemMixin.java)17
-rw-r--r--src/main/java/de/hysky/skyblocker/mixin/HandledScreenMixin.java2
-rw-r--r--src/main/java/de/hysky/skyblocker/mixin/accessor/ItemStackAccessor.java14
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/dungeon/CroesusHelper.java8
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/dungeon/CroesusProfit.java7
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonMap.java25
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/dungeon/partyfinder/OptionDropdownWidget.java1
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/dungeon/partyfinder/PartyEntry.java20
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/dungeon/partyfinder/PartyFinderScreen.java12
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/DungeonManager.java5
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/end/EndHudWidget.java7
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/entity/MobGlow.java22
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/garden/FarmingHud.java2
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/garden/VisitorHelper.java28
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/item/CustomArmorDyeColors.java4
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/item/CustomArmorTrims.java6
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/BackpackPreview.java69
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/ItemTooltip.java14
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/itemlist/ItemStackBuilder.java83
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/itemlist/SearchResultsWidget.java10
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/quicknav/QuickNav.java7
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/special/SpecialEffects.java58
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/ItemUtils.java64
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/datafixer/ItemStackComponentizationFixer.java26
-rw-r--r--src/main/resources/fabric.mod.json6
-rw-r--r--src/main/resources/skyblocker.mixins.json5
-rw-r--r--src/test/java/de/hysky/skyblocker/utils/ItemUtilsTest.java12
-rw-r--r--src/test/java/de/hysky/skyblocker/utils/datafixer/ItemStackComponentizationFixerTest.java47
33 files changed, 387 insertions, 286 deletions
diff --git a/build.gradle b/build.gradle
index d7b37bfe..d5bb8008 100644
--- a/build.gradle
+++ b/build.gradle
@@ -36,7 +36,12 @@ dependencies {
testImplementation "net.fabricmc:fabric-loader-junit:${project.loader_version}"
// To change the versions see the gradle.properties file
minecraft "com.mojang:minecraft:${project.minecraft_version}"
- mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
+ //Layered Yarn & Mojmap - used to fill in intermediary names
+ mappings loom.layered {
+ //Using Mojmap breaks runClient, so uncomment only for snapshots when temp mappings are needed
+ //officialMojangMappings()
+ mappings("net.fabricmc:yarn:${project.yarn_mappings}:v2")
+ }
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
// Fabric API
diff --git a/gradle.properties b/gradle.properties
index 9543d5cc..66191411 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -3,19 +3,19 @@ org.gradle.parallel=true
# Fabric Properties (https://fabricmc.net/versions.html)
## 1.20
-minecraft_version=24w07a
-yarn_mappings=24w07a+build.4
+minecraft_version=24w09a
+yarn_mappings=24w09a+build.5
loader_version=0.15.7
#Fabric api
## 1.20
-fabric_api_version=0.96.2+1.20.5
+fabric_api_version=0.96.5+1.20.5
# Minecraft Mods
## YACL (https://github.com/isXander/YetAnotherConfigLib)
-yacl_version=3.3.2+1.20.4
+yacl_version=3.3.3+1.20.4+update.1.20.5-SNAPSHOT+update.1.20.5-SNAPSHOT
## Mod Menu (https://modrinth.com/mod/modmenu/versions)
-mod_menu_version = 9.0.0-alpha.3
+mod_menu_version = 10.0.0-alpha.1
## REI (https://modrinth.com/mod/rei/versions?l=fabric)
rei_version = 13.0.666
## EMI (https://modrinth.com/mod/emi/versions)
diff --git a/src/main/java/de/hysky/skyblocker/debug/Debug.java b/src/main/java/de/hysky/skyblocker/debug/Debug.java
index 5a9d221b..31823ab0 100644
--- a/src/main/java/de/hysky/skyblocker/debug/Debug.java
+++ b/src/main/java/de/hysky/skyblocker/debug/Debug.java
@@ -23,7 +23,7 @@ public class Debug {
SnapshotDebug.init();
ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> dispatcher.register(literal(SkyblockerMod.NAMESPACE).then(literal("debug")
.then(dumpPlayersCommand())
- .then(ItemUtils.dumpHeldItemNbtCommand())
+ .then(ItemUtils.dumpHeldItemCommand())
)));
}
}
diff --git a/src/main/java/de/hysky/skyblocker/mixin/ArmorTrimMixin.java b/src/main/java/de/hysky/skyblocker/mixin/ArmorTrimMixin.java
deleted file mode 100644
index e13c41ee..00000000
--- a/src/main/java/de/hysky/skyblocker/mixin/ArmorTrimMixin.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package de.hysky.skyblocker.mixin;
-
-import com.llamalad7.mixinextras.injector.ModifyReturnValue;
-import com.llamalad7.mixinextras.sugar.Local;
-import de.hysky.skyblocker.config.SkyblockerConfigManager;
-import de.hysky.skyblocker.skyblock.item.CustomArmorTrims;
-import de.hysky.skyblocker.utils.ItemUtils;
-import de.hysky.skyblocker.utils.Utils;
-import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
-import net.minecraft.item.ItemStack;
-import net.minecraft.item.trim.ArmorTrim;
-import org.spongepowered.asm.mixin.Mixin;
-import org.spongepowered.asm.mixin.injection.At;
-
-import java.util.Optional;
-
-@Mixin(ArmorTrim.class)
-public class ArmorTrimMixin {
-
- @ModifyReturnValue(method = "getTrim", at = @At("RETURN"))
- private static Optional<ArmorTrim> skyblocker$customArmorTrims(@SuppressWarnings("OptionalUsedAsFieldOrParameterType") Optional<ArmorTrim> original, @Local(argsOnly = true) ItemStack stack) {
- if (Utils.isOnSkyblock()) {
- Object2ObjectOpenHashMap<String, CustomArmorTrims.ArmorTrimId> customTrims = SkyblockerConfigManager.get().general.customArmorTrims;
- String itemUuid = ItemUtils.getItemUuid(stack);
-
- if (customTrims.containsKey(itemUuid)) {
- CustomArmorTrims.ArmorTrimId trimKey = customTrims.get(itemUuid);
- return CustomArmorTrims.TRIMS_CACHE.getOrDefault(trimKey, original);
- }
- }
-
- return original;
- }
-}
diff --git a/src/main/java/de/hysky/skyblocker/mixin/ComponentHolderMixin.java b/src/main/java/de/hysky/skyblocker/mixin/ComponentHolderMixin.java
new file mode 100644
index 00000000..c8c57d6d
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/mixin/ComponentHolderMixin.java
@@ -0,0 +1,39 @@
+package de.hysky.skyblocker.mixin;
+
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+
+import com.llamalad7.mixinextras.injector.ModifyReturnValue;
+
+import de.hysky.skyblocker.config.SkyblockerConfigManager;
+import de.hysky.skyblocker.skyblock.item.CustomArmorTrims;
+import de.hysky.skyblocker.utils.ItemUtils;
+import de.hysky.skyblocker.utils.Utils;
+import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
+import net.minecraft.component.ComponentHolder;
+import net.minecraft.component.DataComponentType;
+import net.minecraft.component.DataComponentTypes;
+import net.minecraft.item.ItemStack;
+import net.minecraft.item.trim.ArmorTrim;
+
+@Mixin(ComponentHolder.class)
+public interface ComponentHolderMixin {
+
+ @SuppressWarnings("unchecked")
+ @ModifyReturnValue(method = "get", at = @At("RETURN"))
+ private <T> T skyblocker$customArmorTrims(T original, DataComponentType<? extends T> dataComponentType) {
+ if (Utils.isOnSkyblock() && ((Object) this) instanceof ItemStack stack) {
+ if (dataComponentType == DataComponentTypes.TRIM) {
+ Object2ObjectOpenHashMap<String, CustomArmorTrims.ArmorTrimId> customTrims = SkyblockerConfigManager.get().general.customArmorTrims;
+ String itemUuid = ItemUtils.getItemUuid(stack);
+
+ if (customTrims.containsKey(itemUuid)) {
+ CustomArmorTrims.ArmorTrimId trimKey = customTrims.get(itemUuid);
+ return (T) CustomArmorTrims.TRIMS_CACHE.getOrDefault(trimKey, (ArmorTrim) original);
+ }
+ }
+ }
+
+ return original;
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/mixin/DyeableItemMixin.java b/src/main/java/de/hysky/skyblocker/mixin/DyedColorComponentMixin.java
index b20b58b5..2682fc6d 100644
--- a/src/main/java/de/hysky/skyblocker/mixin/DyeableItemMixin.java
+++ b/src/main/java/de/hysky/skyblocker/mixin/DyedColorComponentMixin.java
@@ -1,27 +1,32 @@
package de.hysky.skyblocker.mixin;
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
+import com.llamalad7.mixinextras.sugar.Local;
+
import de.hysky.skyblocker.config.SkyblockerConfigManager;
import de.hysky.skyblocker.skyblock.item.CustomArmorAnimatedDyes;
import de.hysky.skyblocker.utils.ItemUtils;
import de.hysky.skyblocker.utils.Utils;
-import net.minecraft.item.DyeableItem;
+import net.minecraft.component.type.DyedColorComponent;
import net.minecraft.item.ItemStack;
+import net.minecraft.util.math.ColorHelper;
+
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
-@Mixin(DyeableItem.class)
-public interface DyeableItemMixin {
+@Mixin(DyedColorComponent.class)
+public record DyedColorComponentMixin() {
+
@ModifyReturnValue(method = "getColor", at = @At("RETURN"))
- private static int skyblocker$customDyeColor(int originalColor, ItemStack stack) {
+ private static int skyblocker$customDyeColor(int originalColor, @Local(argsOnly = true) ItemStack stack) {
if (Utils.isOnSkyblock()) {
String itemUuid = ItemUtils.getItemUuid(stack);
if (SkyblockerConfigManager.get().general.customAnimatedDyes.containsKey(itemUuid)) {
- return CustomArmorAnimatedDyes.animateColorTransition(SkyblockerConfigManager.get().general.customAnimatedDyes.get(itemUuid));
+ return ColorHelper.Argb.fullAlpha(CustomArmorAnimatedDyes.animateColorTransition(SkyblockerConfigManager.get().general.customAnimatedDyes.get(itemUuid)));
}
- return SkyblockerConfigManager.get().general.customDyeColors.getOrDefault(itemUuid, originalColor);
+ return ColorHelper.Argb.fullAlpha(SkyblockerConfigManager.get().general.customDyeColors.getOrDefault(itemUuid, originalColor));
}
return originalColor;
diff --git a/src/main/java/de/hysky/skyblocker/mixin/HandledScreenMixin.java b/src/main/java/de/hysky/skyblocker/mixin/HandledScreenMixin.java
index 7d2f849e..73a0bfdb 100644
--- a/src/main/java/de/hysky/skyblocker/mixin/HandledScreenMixin.java
+++ b/src/main/java/de/hysky/skyblocker/mixin/HandledScreenMixin.java
@@ -205,7 +205,7 @@ public abstract class HandledScreenMixin<T extends ScreenHandler> extends Screen
// Prevent selling to NPC shops
ItemStack sellStack = this.handler.slots.get(49).getStack();
- if (sellStack.getName().getString().equals("Sell Item") || ItemUtils.getNbtTooltip(sellStack, text -> text.contains("buyback")) != null) {
+ if (sellStack.getName().getString().equals("Sell Item") || ItemUtils.getLoreLineIf(sellStack, text -> text.contains("buyback")) != null) {
if (slotId != 49 && ItemProtection.isItemProtected(stack)) {
ci.cancel();
return;
diff --git a/src/main/java/de/hysky/skyblocker/mixin/accessor/ItemStackAccessor.java b/src/main/java/de/hysky/skyblocker/mixin/accessor/ItemStackAccessor.java
deleted file mode 100644
index e3bd69aa..00000000
--- a/src/main/java/de/hysky/skyblocker/mixin/accessor/ItemStackAccessor.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package de.hysky.skyblocker.mixin.accessor;
-
-import net.minecraft.item.ItemStack;
-import net.minecraft.text.Style;
-import org.spongepowered.asm.mixin.Mixin;
-import org.spongepowered.asm.mixin.gen.Accessor;
-
-@Mixin(ItemStack.class)
-public interface ItemStackAccessor {
- @Accessor
- static Style getLORE_STYLE() {
- throw new UnsupportedOperationException();
- }
-}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/CroesusHelper.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/CroesusHelper.java
index 01422770..5bd44707 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/CroesusHelper.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/CroesusHelper.java
@@ -1,8 +1,10 @@
package de.hysky.skyblocker.skyblock.dungeon;
import de.hysky.skyblocker.config.SkyblockerConfigManager;
+import de.hysky.skyblocker.utils.ItemUtils;
import de.hysky.skyblocker.utils.render.gui.ColorHighlight;
import de.hysky.skyblocker.utils.render.gui.ContainerSolver;
+import net.minecraft.component.DataComponentTypes;
import net.minecraft.item.ItemStack;
import java.util.ArrayList;
@@ -25,10 +27,10 @@ public class CroesusHelper extends ContainerSolver {
List<ColorHighlight> highlights = new ArrayList<>();
for (Map.Entry<Integer, ItemStack> entry : slots.entrySet()) {
ItemStack stack = entry.getValue();
- if (stack != null && stack.getNbt() != null) {
- if (stack.getNbt().toString().contains("Opened Chest:")) {
+ if (stack != null && stack.contains(DataComponentTypes.LORE)) {
+ if (ItemUtils.getLoreLineIf(stack, s -> s.contains("Opened Chest:")) != null) {
highlights.add(ColorHighlight.gray(entry.getKey()));
- } else if (stack.getNbt().toString().contains("No more Chests to open!")) {
+ } else if (ItemUtils.getLoreLineIf(stack, s -> s.contains("No more Chests to open!")) != null) {
highlights.add(ColorHighlight.red(entry.getKey()));
}
}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/CroesusProfit.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/CroesusProfit.java
index ca166915..8933a447 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/CroesusProfit.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/CroesusProfit.java
@@ -6,6 +6,7 @@ import de.hysky.skyblocker.skyblock.item.tooltip.TooltipInfoType;
import de.hysky.skyblocker.utils.ItemUtils;
import de.hysky.skyblocker.utils.render.gui.ColorHighlight;
import de.hysky.skyblocker.utils.render.gui.ContainerSolver;
+import net.minecraft.component.DataComponentTypes;
import net.minecraft.item.ItemStack;
import net.minecraft.text.Text;
import org.jetbrains.annotations.NotNull;
@@ -37,7 +38,7 @@ public class CroesusProfit extends ContainerSolver {
for (Map.Entry<Integer, ItemStack> entry : slots.entrySet()) {
ItemStack stack = entry.getValue();
- if (stack != null && stack.getNbt() != null && stack.getName().toString().contains("Chest")) {
+ if (stack != null && stack.contains(DataComponentTypes.LORE) && ItemUtils.getLoreLineIf(stack, s -> s.contains("Chest")) != null) {
long value = valueChest(stack);
if (value > bestValue) {
secondBestChest = bestChest;
@@ -53,7 +54,7 @@ public class CroesusProfit extends ContainerSolver {
for (Map.Entry<Integer, ItemStack> entry : slots.entrySet()) {
ItemStack stack = entry.getValue();
- if (stack != null && stack.getNbt() != null) {
+ if (stack != null && stack.contains(DataComponentTypes.LORE)) {
if (stack.equals(bestChest)) {
highlights.add(ColorHighlight.green(entry.getKey()));
} else if (stack.equals(secondBestChest) && secondBestValue > dungeonKeyPriceData) {
@@ -71,7 +72,7 @@ public class CroesusProfit extends ContainerSolver {
List<String> chestItems = new ArrayList<>();
boolean processingContents = false;
- for (Text line : ItemUtils.getNbtTooltips(chest)) {
+ for (Text line : ItemUtils.getLore(chest)) {
String lineString = line.getString();
if (lineString.contains("Contents")) {
processingContents = true;
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonMap.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonMap.java
index 878b7a35..7a6cdcd0 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonMap.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonMap.java
@@ -14,14 +14,16 @@ import net.minecraft.client.render.LightmapTextureManager;
import net.minecraft.client.render.MapRenderer;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.util.math.MatrixStack;
+import net.minecraft.component.DataComponentTypes;
+import net.minecraft.component.type.MapIdComponent;
import net.minecraft.item.FilledMapItem;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.item.map.MapState;
public class DungeonMap {
- private static final int DEFAULT_MAP_ID = 1024;
- private static Integer cachedMapId = null;
+ private static final MapIdComponent DEFAULT_MAP_ID_COMPONENT = new MapIdComponent(1024);
+ private static MapIdComponent cachedMapIdComponent = null;
public static void init() {
HudRenderEvents.AFTER_MAIN_HUD.register((context, tickDelta) -> render(context));
@@ -35,11 +37,11 @@ public class DungeonMap {
ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> reset());
}
- private static void render(MatrixStack matrices) {
+ public static void render(MatrixStack matrices) {
MinecraftClient client = MinecraftClient.getInstance();
if (client.player == null || client.world == null) return;
- int mapId = getMapId(client.player.getInventory().main.get(8));
+ MapIdComponent mapId = getMapIdComponent(client.player.getInventory().main.get(8));
MapState state = FilledMapItem.getMapState(mapId, client.world);
if (state == null) return;
@@ -58,13 +60,12 @@ public class DungeonMap {
matrices.pop();
}
- public static int getMapId(ItemStack stack) {
- if (stack.isOf(Items.FILLED_MAP)) {
- @SuppressWarnings("DataFlowIssue")
- int mapId = FilledMapItem.getMapId(stack);
- cachedMapId = mapId;
- return mapId;
- } else return cachedMapId != null ? cachedMapId : DEFAULT_MAP_ID;
+ public static MapIdComponent getMapIdComponent(ItemStack stack) {
+ if (stack.isOf(Items.FILLED_MAP) && stack.contains(DataComponentTypes.MAP_ID)) {
+ MapIdComponent mapIdComponent = stack.get(DataComponentTypes.MAP_ID);
+ cachedMapIdComponent = mapIdComponent;
+ return mapIdComponent;
+ } else return cachedMapIdComponent != null ? cachedMapIdComponent : DEFAULT_MAP_ID_COMPONENT;
}
private static void render(DrawContext context) {
@@ -74,6 +75,6 @@ public class DungeonMap {
}
private static void reset() {
- cachedMapId = null;
+ cachedMapIdComponent = null;
}
}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/partyfinder/OptionDropdownWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/partyfinder/OptionDropdownWidget.java
index 64e45283..19241d58 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/partyfinder/OptionDropdownWidget.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/partyfinder/OptionDropdownWidget.java
@@ -29,7 +29,6 @@ public class OptionDropdownWidget extends ElementListWidget<OptionDropdownWidget
this.screen = screen;
this.slotId = slotId;
setX(x);
- setRenderBackground(false);
setRenderHeader(true, 25);
this.name = name;
this.selectedOption = selectedOption;
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/partyfinder/PartyEntry.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/partyfinder/PartyEntry.java
index b53047d8..ab77d122 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/partyfinder/PartyEntry.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/partyfinder/PartyEntry.java
@@ -1,6 +1,6 @@
package de.hysky.skyblocker.skyblock.dungeon.partyfinder;
-import com.mojang.brigadier.exceptions.CommandSyntaxException;
+import com.mojang.authlib.properties.PropertyMap;
import de.hysky.skyblocker.SkyblockerMod;
import de.hysky.skyblocker.mixin.accessor.SkullBlockEntityAccessor;
import net.minecraft.client.MinecraftClient;
@@ -12,10 +12,10 @@ import net.minecraft.client.gui.Selectable;
import net.minecraft.client.gui.widget.ElementListWidget;
import net.minecraft.client.util.DefaultSkinHelper;
import net.minecraft.client.util.math.MatrixStack;
+import net.minecraft.component.DataComponentTypes;
+import net.minecraft.component.type.ProfileComponent;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
-import net.minecraft.nbt.NbtCompound;
-import net.minecraft.nbt.StringNbtReader;
import net.minecraft.text.Style;
import net.minecraft.text.Text;
import net.minecraft.text.TextColor;
@@ -25,6 +25,8 @@ import net.minecraft.util.Identifier;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
+import java.util.Optional;
+import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -38,7 +40,7 @@ public class PartyEntry extends ElementListWidget.Entry<PartyEntry> {
String floor = "???";
String dungeon = "???";
String note = "";
- NbtCompound floorSkullNBT = new NbtCompound();
+ PropertyMap floorSkullProperties = new PropertyMap();
Identifier partyLeaderSkin = DefaultSkinHelper.getTexture();
Player[] partyMembers = new Player[4];
@@ -87,14 +89,14 @@ public class PartyEntry extends ElementListWidget.Entry<PartyEntry> {
if (PartyFinderScreen.floorIconsMaster == null || PartyFinderScreen.floorIconsNormal == null) continue;
if (dungeon.contains("Master Mode")) {
try {
- floorSkullNBT = StringNbtReader.parse(PartyEntryListWidget.BASE_SKULL_NBT.replace("%TEXTURE%", PartyFinderScreen.floorIconsMaster.getOrDefault(floor.toLowerCase(), "")));
- } catch (CommandSyntaxException e) {
+ floorSkullProperties = PartyFinderScreen.floorIconsMaster.getOrDefault(floor.toLowerCase(), new PropertyMap());
+ } catch (Exception e) {
throw new RuntimeException(e);
}
} else {
try {
- floorSkullNBT = StringNbtReader.parse(PartyEntryListWidget.BASE_SKULL_NBT.replace("%TEXTURE%", PartyFinderScreen.floorIconsNormal.getOrDefault(floor.toLowerCase(), "")));
- } catch (CommandSyntaxException e) {
+ floorSkullProperties = PartyFinderScreen.floorIconsNormal.getOrDefault(floor.toLowerCase(), new PropertyMap());
+ } catch (Exception e) {
throw new RuntimeException(e);
}
}
@@ -226,7 +228,7 @@ public class PartyEntry extends ElementListWidget.Entry<PartyEntry> {
}
}
ItemStack stack = new ItemStack(Items.PLAYER_HEAD);
- stack.setNbt(floorSkullNBT);
+ stack.set(DataComponentTypes.PROFILE, new ProfileComponent("SkyblockerCustomPF", Optional.of(UUID.randomUUID()), floorSkullProperties));
context.drawItem(stack, 317, 3);
int textWidth = textRenderer.getWidth(floor);
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/partyfinder/PartyFinderScreen.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/partyfinder/PartyFinderScreen.java
index 16be2b67..98ab88c0 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/partyfinder/PartyFinderScreen.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/partyfinder/PartyFinderScreen.java
@@ -1,7 +1,10 @@
package de.hysky.skyblocker.skyblock.dungeon.partyfinder;
import com.google.gson.JsonObject;
+import com.mojang.authlib.properties.PropertyMap;
+
import de.hysky.skyblocker.SkyblockerMod;
+import de.hysky.skyblocker.utils.ItemUtils;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents;
import net.minecraft.block.entity.SignBlockEntity;
import net.minecraft.client.MinecraftClient;
@@ -99,8 +102,8 @@ public class PartyFinderScreen extends Screen {
private boolean waitingForServer = false;
- public static Map<String, String> floorIconsNormal = null;
- public static Map<String, String> floorIconsMaster = null;
+ public static Map<String, PropertyMap> floorIconsNormal = null;
+ public static Map<String, PropertyMap> floorIconsMaster = null;
public static void initClass() {
ClientLifecycleEvents.CLIENT_STARTED.register(client -> {
@@ -110,8 +113,8 @@ public class PartyFinderScreen extends Screen {
floorIconsMaster = new HashMap<>();
try (BufferedReader skullTextureReader = client.getResourceManager().openAsReader(new Identifier(SkyblockerMod.NAMESPACE, "dungeons/catacombs/floorskulls.json"))) {
JsonObject json = SkyblockerMod.GSON.fromJson(skullTextureReader, JsonObject.class);
- json.getAsJsonObject("normal").asMap().forEach((s, jsonElement) -> floorIconsNormal.put(s, jsonElement.getAsString()));
- json.getAsJsonObject("master").asMap().forEach((s, jsonElement) -> floorIconsMaster.put(s, jsonElement.getAsString()));
+ json.getAsJsonObject("normal").asMap().forEach((s, tex) -> floorIconsNormal.put(s, ItemUtils.propertyMapWithTexture(tex.getAsString())));
+ json.getAsJsonObject("master").asMap().forEach((s, tex) -> floorIconsMaster.put(s, ItemUtils.propertyMapWithTexture(tex.getAsString())));
LOGGER.debug("[Skyblocker] Dungeons floor skull textures json loaded");
} catch (Exception e) {
LOGGER.error("[Skyblocker] Failed to load dungeons floor skull textures json", e);
@@ -136,7 +139,6 @@ public class PartyFinderScreen extends Screen {
int widget_height = (int) (this.height * 0.8);
int entryListTopY = Math.max(43, (int) (height * 0.1));
this.partyEntryListWidget = new PartyEntryListWidget(client, width, widget_height, entryListTopY, 68);
- partyEntryListWidget.setRenderBackground(false);
// Search field
this.searchField = new TextFieldWidget(textRenderer, partyEntryListWidget.getRowLeft() + 12, entryListTopY - 12, partyEntryListWidget.getRowWidth() - 12 * 3 - 6, 12, Text.literal("Search..."));
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/DungeonManager.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/DungeonManager.java
index c90f1134..8bb22e7e 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/DungeonManager.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/DungeonManager.java
@@ -40,6 +40,7 @@ import net.minecraft.command.CommandSource;
import net.minecraft.command.argument.BlockPosArgumentType;
import net.minecraft.command.argument.PosArgument;
import net.minecraft.command.argument.TextArgumentType;
+import net.minecraft.component.DataComponentTypes;
import net.minecraft.entity.Entity;
import net.minecraft.entity.ItemEntity;
import net.minecraft.entity.LivingEntity;
@@ -462,7 +463,7 @@ public class DungeonManager {
context.getSource().sendError(Constants.PREFIX.get().append("§cFailed to get dungeon map."));
return Command.SINGLE_SUCCESS;
}
- MapState map = FilledMapItem.getMapState(FilledMapItem.getMapId(stack), client.world);
+ MapState map = FilledMapItem.getMapState(stack.get(DataComponentTypes.MAP_ID), client.world);
if (map == null) {
context.getSource().sendError(Constants.PREFIX.get().append("§cFailed to get dungeon map state."));
return Command.SINGLE_SUCCESS;
@@ -539,7 +540,7 @@ public class DungeonManager {
physicalEntrancePos = DungeonMapUtils.getPhysicalRoomPos(playerPos);
currentRoom = newRoom(Room.Type.ENTRANCE, physicalEntrancePos);
}
- MapState map = FilledMapItem.getMapState(DungeonMap.getMapId(client.player.getInventory().main.get(8)), client.world);
+ MapState map = FilledMapItem.getMapState(DungeonMap.getMapIdComponent(client.player.getInventory().main.get(8)), client.world);
if (map == null) {
return;
}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/end/EndHudWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/end/EndHudWidget.java
index 30de9a48..10dc2b5c 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/end/EndHudWidget.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/end/EndHudWidget.java
@@ -4,6 +4,8 @@ import de.hysky.skyblocker.config.SkyblockerConfigManager;
import de.hysky.skyblocker.skyblock.tabhud.widget.Widget;
import de.hysky.skyblocker.skyblock.tabhud.widget.component.IcoTextComponent;
import de.hysky.skyblocker.skyblock.tabhud.widget.component.PlainTextComponent;
+import net.minecraft.component.DataComponentTypes;
+import net.minecraft.component.type.ProfileComponent;
import net.minecraft.enchantment.Enchantments;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
@@ -12,6 +14,9 @@ import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import java.text.NumberFormat;
+import java.util.Optional;
+
+import com.mojang.authlib.properties.PropertyMap;
public class EndHudWidget extends Widget {
private static final MutableText TITLE = Text.literal("The End").formatted(Formatting.LIGHT_PURPLE, Formatting.BOLD);
@@ -29,7 +34,7 @@ public class EndHudWidget extends Widget {
private static final ItemStack POPPY = new ItemStack(Items.POPPY);
static {
- ENDERMAN_HEAD.getOrCreateNbt().putString("SkullOwner", "MHF_Enderman");
+ ENDERMAN_HEAD.set(DataComponentTypes.PROFILE, new ProfileComponent("MHF_Enderman", Optional.empty(), new PropertyMap()));
POPPY.addEnchantment(Enchantments.INFINITY, 1);
INSTANCE.setX(SkyblockerConfigManager.get().locations.end.x);
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/entity/MobGlow.java b/src/main/java/de/hysky/skyblocker/skyblock/entity/MobGlow.java
index 12ae468f..9650e39b 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/entity/MobGlow.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/entity/MobGlow.java
@@ -6,14 +6,15 @@ import de.hysky.skyblocker.skyblock.dungeon.LividColor;
import de.hysky.skyblocker.utils.SlayerUtils;
import de.hysky.skyblocker.utils.Utils;
import de.hysky.skyblocker.utils.render.culling.OcclusionCulling;
+import net.minecraft.component.DataComponentTypes;
+import net.minecraft.component.type.ProfileComponent;
import net.minecraft.entity.Entity;
import net.minecraft.entity.decoration.ArmorStandEntity;
import net.minecraft.entity.mob.EndermanEntity;
import net.minecraft.entity.passive.BatEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
-import net.minecraft.nbt.NbtCompound;
-import net.minecraft.nbt.NbtElement;
+import net.minecraft.item.Items;
import net.minecraft.predicate.entity.EntityPredicates;
import net.minecraft.util.Formatting;
import net.minecraft.util.math.Box;
@@ -21,6 +22,8 @@ import net.minecraft.world.World;
import java.util.List;
+import com.mojang.authlib.properties.Property;
+
public class MobGlow {
public static boolean shouldMobGlow(Entity entity) {
@@ -114,19 +117,18 @@ public class MobGlow {
for (ItemStack armorItem : entity.getArmorItems()) {
// hacky way to check if an item is a player head w/o
// some shenanigans
- if (!armorItem.toString().startsWith("1 player_head"))
+ if (!armorItem.isOf(Items.PLAYER_HEAD))
continue;
// eb07594e2df273921a77c101d0bfdfa1115abed5b9b2029eb496ceba9bdbb4b3 is texture id for the nukekubi head,
// compare against it to exclusively find armorstands that are nukekubi heads
- NbtCompound skullOwner = armorItem.getSubNbt("SkullOwner");
- if (skullOwner != null) {
+ ProfileComponent profile = armorItem.get(DataComponentTypes.PROFILE);
+ if (profile != null) {
// get the texture of the nukekubi head item itself and compare it
- String texture = skullOwner
- .getCompound("Properties")
- .getList("textures", NbtElement.COMPOUND_TYPE)
- .getCompound(0)
- .getString("Value");
+ String texture = profile.properties().get("textures").stream()
+ .map(Property::value)
+ .findFirst()
+ .orElse("None");
return texture.contains("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZWIwNzU5NGUyZGYyNzM5MjFhNzdjMTAxZDBiZmRmYTExMTVhYmVkNWI5YjIwMjllYjQ5NmNlYmE5YmRiYjRiMyJ9fX0=");
}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/garden/FarmingHud.java b/src/main/java/de/hysky/skyblocker/skyblock/garden/FarmingHud.java
index 95c72241..374e9e12 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/garden/FarmingHud.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/garden/FarmingHud.java
@@ -54,7 +54,7 @@ public class FarmingHud {
}
ItemStack stack = MinecraftClient.getInstance().player.getMainHandStack();
- Matcher matcher = ItemUtils.getNbtTooltip(stack, FarmingHud.COUNTER);
+ Matcher matcher = ItemUtils.getLoreLineIfMatch(stack, FarmingHud.COUNTER);
if (matcher != null) {
try {
int count = NUMBER_FORMAT.parse(matcher.group("count")).intValue();
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/garden/VisitorHelper.java b/src/main/java/de/hysky/skyblocker/skyblock/garden/VisitorHelper.java
index 6640d413..2805cb0e 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/garden/VisitorHelper.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/garden/VisitorHelper.java
@@ -2,6 +2,7 @@ package de.hysky.skyblocker.skyblock.garden;
import de.hysky.skyblocker.config.SkyblockerConfigManager;
import de.hysky.skyblocker.skyblock.itemlist.ItemRepository;
+import de.hysky.skyblocker.utils.ItemUtils;
import de.hysky.skyblocker.utils.NEURepoManager;
import de.hysky.skyblocker.utils.Utils;
import de.hysky.skyblocker.utils.scheduler.MessageScheduler;
@@ -12,14 +13,11 @@ import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.ingame.HandledScreen;
+import net.minecraft.component.DataComponentTypes;
import net.minecraft.item.ItemStack;
-import net.minecraft.nbt.NbtCompound;
-import net.minecraft.nbt.NbtElement;
-import net.minecraft.nbt.NbtList;
import net.minecraft.screen.ScreenHandler;
import net.minecraft.screen.slot.Slot;
import net.minecraft.text.Text;
-import net.minecraft.text.Text.Serialization;
import net.minecraft.util.Formatting;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
@@ -27,6 +25,7 @@ import org.slf4j.LoggerFactory;
import java.text.NumberFormat;
import java.util.HashMap;
+import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -85,30 +84,27 @@ public class VisitorHelper {
private static void processVisitorItem(String visitorName, ScreenHandler handler) {
ItemStack visitorItem = handler.getSlot(13).getStack();
- if (visitorItem == null || !visitorItem.hasNbt() || !visitorItem.getNbt().asString().contains("Times Visited")) return;
+ if (visitorItem == null || !visitorItem.contains(DataComponentTypes.LORE) || ItemUtils.getLoreLineIf(visitorItem, t -> t.contains("Times Visited")) == null) return;
ItemStack acceptButton = handler.getSlot(29).getStack();
if (acceptButton == null) return;
- NbtCompound acceptButtonNbt = acceptButton.getSubNbt("display");
- if (acceptButtonNbt == null || !acceptButtonNbt.contains("Lore", NbtElement.LIST_TYPE)) return;
- processLore(visitorName, acceptButtonNbt.getList("Lore", NbtElement.STRING_TYPE));
+ processLore(visitorName, ItemUtils.getLore(acceptButton));
}
- private static void processLore(String visitorName, NbtList loreList) {
+ private static void processLore(String visitorName, List<Text> loreList) {
boolean saveRequiredItems = false;
for (int i = 0; i < loreList.size(); i++) {
- String lore = loreList.getString(i);
+ String lore = loreList.get(i).getString();
if (lore.contains("Items Required"))
saveRequiredItems = true;
else if (lore.contains("Rewards"))
break;
else if (saveRequiredItems)
- updateItemMap(visitorName, lore);
+ updateItemMap(visitorName, loreList.get(i));
}
}
- private static void updateItemMap(String visitorName, String lore) {
- Text itemText = Serialization.fromJson(lore);
- String[] splitItemText = itemText.getString().split(" x");
+ private static void updateItemMap(String visitorName, Text lore) {
+ String[] splitItemText = lore.getString().split(" x");
String itemName = splitItemText[0].trim();
if (itemName.isEmpty()) return;
try {
@@ -117,7 +113,7 @@ public class VisitorHelper {
visitorMap.putIfAbsent(itemName, amount);
itemMap.putIfAbsent(visitorName, visitorMap);
} catch (Exception e) {
- LOGGER.error("[Skyblocker Visitor Helper] Failed to parse item: " + itemText.getString(), e);
+ LOGGER.error("[Skyblocker Visitor Helper] Failed to parse item: " + lore.getString(), e);
}
}
@@ -163,7 +159,7 @@ public class VisitorHelper {
}
private static void drawItemEntryWithHover(DrawContext context, TextRenderer textRenderer, @Nullable ItemStack stack, String itemName, int amount, int index, int mouseX, int mousseY) {
- Text text = stack != null ? Serialization.fromJson(stack.getSubNbt("display").getString("Name")).append(" x" + amount) : Text.literal(itemName + " x" + amount);
+ Text text = stack != null ? stack.getName().copy().append(" x" + amount) : Text.literal(itemName + " x" + amount);
drawTextWithOptionalUnderline(context, textRenderer, text, TEXT_START_X + TEXT_INDENT, TEXT_START_Y + (index * (LINE_SPACING + textRenderer.fontHeight)), mouseX, mousseY);
// drawItem adds 150 to the z, which puts our z at 350, above the item in the slot (250) and their text (300) and below the cursor stack (382) and their text (432)
if (stack != null) {
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/CustomArmorDyeColors.java b/src/main/java/de/hysky/skyblocker/skyblock/item/CustomArmorDyeColors.java
index 639e98ed..97311220 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/item/CustomArmorDyeColors.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/item/CustomArmorDyeColors.java
@@ -12,8 +12,8 @@ import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager;
import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
import net.minecraft.command.CommandRegistryAccess;
-import net.minecraft.item.DyeableItem;
import net.minecraft.item.ItemStack;
+import net.minecraft.registry.tag.ItemTags;
import net.minecraft.text.Text;
public class CustomArmorDyeColors {
@@ -40,7 +40,7 @@ public class CustomArmorDyeColors {
}
if (Utils.isOnSkyblock() && heldItem != null) {
- if (heldItem.getItem() instanceof DyeableItem) {
+ if (heldItem.isIn(ItemTags.DYEABLE)) {
String itemUuid = ItemUtils.getItemUuid(heldItem);
if (!itemUuid.isEmpty()) {
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/CustomArmorTrims.java b/src/main/java/de/hysky/skyblocker/skyblock/item/CustomArmorTrims.java
index 3434f026..270622ff 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/item/CustomArmorTrims.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/item/CustomArmorTrims.java
@@ -34,11 +34,9 @@ import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.Optional;
-
public class CustomArmorTrims {
private static final Logger LOGGER = LoggerFactory.getLogger(CustomArmorTrims.class);
- public static final Object2ObjectOpenHashMap<ArmorTrimId, Optional<ArmorTrim>> TRIMS_CACHE = new Object2ObjectOpenHashMap<>();
+ public static final Object2ObjectOpenHashMap<ArmorTrimId, ArmorTrim> TRIMS_CACHE = new Object2ObjectOpenHashMap<>();
private static boolean trimsInitialized = false;
public static void init() {
@@ -65,7 +63,7 @@ public class CustomArmorTrims {
// Something went terribly wrong
if (trim == null) throw new IllegalStateException("Trim shouldn't be null! [" + "\"" + material + "\",\"" + pattern + "\"]");
- TRIMS_CACHE.put(new ArmorTrimId(material, pattern), Optional.of(trim));
+ TRIMS_CACHE.put(new ArmorTrimId(material, pattern), trim);
}
}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/BackpackPreview.java b/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/BackpackPreview.java
index 37de58e6..77cbc953 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/BackpackPreview.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/BackpackPreview.java
@@ -1,6 +1,11 @@
package de.hysky.skyblocker.skyblock.item.tooltip;
+import com.google.gson.JsonParser;
import com.mojang.blaze3d.systems.RenderSystem;
+import com.mojang.serialization.Codec;
+import com.mojang.serialization.JsonOps;
+import com.mojang.serialization.codecs.RecordCodecBuilder;
+
import de.hysky.skyblocker.SkyblockerMod;
import de.hysky.skyblocker.config.SkyblockerConfigManager;
import de.hysky.skyblocker.skyblock.item.ItemRarityBackgrounds;
@@ -15,18 +20,16 @@ import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.inventory.Inventory;
import net.minecraft.inventory.SimpleInventory;
import net.minecraft.item.ItemStack;
-import net.minecraft.nbt.NbtCompound;
-import net.minecraft.nbt.NbtInt;
-import net.minecraft.nbt.NbtIo;
-import net.minecraft.nbt.NbtList;
import net.minecraft.util.Identifier;
-import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
import java.nio.file.Files;
import java.nio.file.Path;
-import java.util.Objects;
+import java.util.ArrayList;
+import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -61,8 +64,13 @@ public class BackpackPreview {
String id = MinecraftClient.getInstance().getSession().getUuidOrNull().toString().replaceAll("-", "") + "/" + Utils.getProfileId();
if (!id.equals(loaded)) {
saveDir = SkyblockerMod.CONFIG_DIR.resolve("backpack-preview/" + id);
- //noinspection ResultOfMethodCallIgnored
- saveDir.toFile().mkdirs();
+
+ try {
+ Files.createDirectories(saveDir);
+ } catch (Exception e) {
+ LOGGER.error("[Skyblocker] Failed to create the backpack preview save directory! Path: {}", saveDir, e);
+ }
+
// load storage again because profile id changed
loaded = id;
loadStorages();
@@ -73,10 +81,10 @@ public class BackpackPreview {
private static void loadStorages() {
for (int index = 0; index < STORAGE_SIZE; ++index) {
storages[index] = null;
- Path storageFile = saveDir.resolve(index + ".nbt");
+ Path storageFile = saveDir.resolve(index + ".json");
if (Files.isRegularFile(storageFile)) {
- try {
- storages[index] = Storage.fromNbt(Objects.requireNonNull(NbtIo.read(storageFile)));
+ try (BufferedReader reader = Files.newBufferedReader(storageFile)) {
+ storages[index] = Storage.CODEC.parse(JsonOps.INSTANCE, JsonParser.parseReader(reader)).result().orElseThrow();
} catch (Exception e) {
LOGGER.error("Failed to load backpack preview file: " + storageFile.getFileName().toString(), e);
}
@@ -93,11 +101,12 @@ public class BackpackPreview {
}
private static void saveStorage(int index) {
- try {
- NbtIo.write(storages[index].toNbt(), saveDir.resolve(index + ".nbt"));
+ Path storageFile = saveDir.resolve(index + ".json");
+ try (BufferedWriter writer = Files.newBufferedWriter(storageFile)) {
+ SkyblockerMod.GSON.toJson(Storage.CODEC.encodeStart(JsonOps.INSTANCE, storages[index]).result().orElseThrow(), writer);
storages[index].markClean();
} catch (Exception e) {
- LOGGER.error("Failed to save backpack preview file: " + index + ".nbt", e);
+ LOGGER.error("Failed to save backpack preview file: " + index + ".json", e);
}
}
@@ -129,7 +138,7 @@ public class BackpackPreview {
context.drawTexture(TEXTURE, x, y + rows * 18 + 17, 0, 215, 176, 7);
TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer;
- context.drawText(textRenderer, storages[index].name, x + 8, y + 6, 0x404040, false);
+ context.drawText(textRenderer, storages[index].name(), x + 8, y + 6, 0x404040, false);
matrices.translate(0f, 0f, 200f);
for (int i = 9; i < storages[index].size(); ++i) {
@@ -159,6 +168,10 @@ public class BackpackPreview {
}
static class Storage {
+ private static final Codec<Storage> CODEC = RecordCodecBuilder.create(instance -> instance.group(
+ Codec.STRING.fieldOf("name").forGetter(Storage::name),
+ ItemStack.CODEC.listOf().fieldOf("items").forGetter(Storage::getItemList))
+ .apply(instance, (name, items) -> Storage.create(name, items)));
private final Inventory inventory;
private final String name;
private boolean dirty;
@@ -168,6 +181,10 @@ public class BackpackPreview {
this.name = name;
this.dirty = dirty;
}
+
+ private String name() {
+ return name;
+ }
private int size() {
return inventory.size();
@@ -181,23 +198,19 @@ public class BackpackPreview {
dirty = false;
}
- @NotNull
- private static Storage fromNbt(NbtCompound root) {
- SimpleInventory inventory = new SimpleInventory(root.getList("list", NbtCompound.COMPOUND_TYPE).stream().map(NbtCompound.class::cast).map(ItemStack::fromNbt).toArray(ItemStack[]::new));
- return new Storage(inventory, root.getString("name"), false);
+ private static Storage create(String name, List<ItemStack> items) {
+ SimpleInventory inventory = new SimpleInventory(items.toArray(ItemStack[]::new));
+ return new Storage(inventory, name, false);
}
- @NotNull
- private NbtCompound toNbt() {
- NbtCompound root = new NbtCompound();
- NbtList list = new NbtList();
+ private List<ItemStack> getItemList() {
+ List<ItemStack> items = new ArrayList<>();
+
for (int i = 0; i < size(); ++i) {
- list.add(getStack(i).writeNbt(new NbtCompound()));
+ items.add(getStack(i));
}
- root.put("list", list);
- root.put("size", NbtInt.of(size()));
- root.putString("name", name);
- return root;
+
+ return items;
}
}
}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/ItemTooltip.java b/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/ItemTooltip.java
index 562c244c..855a4760 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/ItemTooltip.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/ItemTooltip.java
@@ -13,13 +13,14 @@ import de.hysky.skyblocker.utils.scheduler.Scheduler;
import it.unimi.dsi.fastutil.Pair;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.item.TooltipContext;
-import net.minecraft.item.DyeableItem;
+import net.minecraft.component.type.DyedColorComponent;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtElement;
import net.minecraft.text.MutableText;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
+
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -198,12 +199,13 @@ public class ItemTooltip {
}
}
- if (TooltipInfoType.COLOR.isTooltipEnabledAndHasOrNullWarning(internalID) && stack.getNbt() != null) {
+ if (TooltipInfoType.COLOR.isTooltipEnabledAndHasOrNullWarning(internalID)) {
String uuid = ItemUtils.getItemUuid(stack);
boolean hasCustomDye = SkyblockerConfigManager.get().general.customDyeColors.containsKey(uuid) || SkyblockerConfigManager.get().general.customAnimatedDyes.containsKey(uuid);
+ int dyeColor = DyedColorComponent.getColor(stack, -1);
- if (!hasCustomDye && DyeableItem.hasColor(stack)) {
- String colorHex = String.format("%06X", DyeableItem.getColor(stack));
+ if (!hasCustomDye && dyeColor != -1) {
+ String colorHex = String.format("%06X", dyeColor);
String expectedHex = ExoticTooltip.getExpectedHex(internalID);
boolean correctLine = false;
@@ -212,13 +214,13 @@ public class ItemTooltip {
if (existingTooltip.startsWith("Color: ")) {
correctLine = true;
- addExoticTooltip(lines, internalID, stack.getNbt(), colorHex, expectedHex, existingTooltip);
+ addExoticTooltip(lines, internalID, ItemUtils.getCustomData(stack).copyNbt(), colorHex, expectedHex, existingTooltip);
break;
}
}
if (!correctLine) {
- addExoticTooltip(lines, internalID, stack.getNbt(), colorHex, expectedHex, "");
+ addExoticTooltip(lines, internalID, ItemUtils.getCustomData(stack).copyNbt(), colorHex, expectedHex, "");
}
}
}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/ItemStackBuilder.java b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/ItemStackBuilder.java
index c1eea23a..11c3687e 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/ItemStackBuilder.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/ItemStackBuilder.java
@@ -5,15 +5,25 @@ import de.hysky.skyblocker.utils.NEURepoManager;
import io.github.moulberry.repo.constants.PetNumbers;
import io.github.moulberry.repo.data.NEUItem;
import io.github.moulberry.repo.data.Rarity;
-import net.minecraft.item.FireworkRocketItem;
+import it.unimi.dsi.fastutil.ints.IntArrayList;
+import net.minecraft.component.DataComponentTypes;
+import net.minecraft.component.type.AttributeModifiersComponent;
+import net.minecraft.component.type.DyedColorComponent;
+import net.minecraft.component.type.FireworkExplosionComponent;
+import net.minecraft.component.type.LoreComponent;
+import net.minecraft.component.type.NbtComponent;
+import net.minecraft.component.type.ProfileComponent;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.*;
+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;
+import java.util.stream.Collectors;
public class ItemStackBuilder {
private static Map<String, Map<Rarity, PetNumbers>> petNums;
@@ -31,73 +41,62 @@ public class ItemStackBuilder {
List<Pair<String, String>> injectors = new ArrayList<>(petData(internalName));
- NbtCompound root = new NbtCompound();
- root.put("Count", NbtByte.of((byte) 1));
+ String legacyId = item.getMinecraftItemId();
+ Identifier itemId = new Identifier(ItemFixerUpper.convertItemId(legacyId, item.getDamage()));
+
+ ItemStack stack = new ItemStack(Registries.ITEM.get(itemId));
- String id = item.getMinecraftItemId();
- int damage = item.getDamage();
- root.put("id", NbtString.of(ItemFixerUpper.convertItemId(id, damage)));
+ // Create & Attach ExtraAttributes tag
+ NbtCompound customData = new NbtCompound();
+ NbtCompound extraAttributes = new NbtCompound();
+ customData.put(ItemUtils.EXTRA_ATTRIBUTES, extraAttributes);
- NbtCompound tag = new NbtCompound();
- root.put("tag", tag);
-
- NbtCompound extra = new NbtCompound();
- tag.put(ItemUtils.EXTRA_ATTRIBUTES, extra);
- extra.put(ItemUtils.ID, NbtString.of(internalName));
-
- NbtCompound display = new NbtCompound();
- tag.put("display", display);
+ // Add Skyblock Item Id
+ extraAttributes.put(ItemUtils.ID, NbtString.of(internalName));
+ // Item Name
String name = injectData(item.getDisplayName(), injectors);
- display.put("Name", NbtString.of(Text.Serialization.toJsonString(Text.of(name))));
+ stack.set(DataComponentTypes.CUSTOM_NAME, Text.of(name));
- NbtList lore = new NbtList();
- display.put("Lore", lore);
- item.getLore().forEach(el -> lore.add(NbtString.of(Text.Serialization.toJsonString(Text.of(injectData(el, injectors))))));
+ // Lore
+ stack.set(DataComponentTypes.LORE, new LoreComponent(item.getLore().stream().map(line -> Text.of(injectData(line, injectors))).collect(Collectors.toCollection(() -> new ArrayList<>()))));
String nbttag = item.getNbttag();
// add skull texture
Matcher skullUuid = Pattern.compile("(?<=SkullOwner:\\{)Id:\"(.{36})\"").matcher(nbttag);
Matcher skullTexture = Pattern.compile("(?<=Properties:\\{textures:\\[0:\\{Value:)\"(.+?)\"").matcher(nbttag);
if (skullUuid.find() && skullTexture.find()) {
- NbtCompound skullOwner = new NbtCompound();
- tag.put("SkullOwner", skullOwner);
UUID uuid = UUID.fromString(skullUuid.group(1));
- skullOwner.put("Id", NbtHelper.fromUuid(uuid));
- skullOwner.put("Name", NbtString.of(internalName));
-
- NbtCompound properties = new NbtCompound();
- skullOwner.put("Properties", properties);
- NbtList textures = new NbtList();
- properties.put("textures", textures);
- NbtCompound texture = new NbtCompound();
- textures.add(texture);
- texture.put("Value", NbtString.of(skullTexture.group(1)));
+ String textureValue = skullTexture.group(1);
+
+ stack.set(DataComponentTypes.PROFILE, new ProfileComponent(internalName, Optional.of(uuid), ItemUtils.propertyMapWithTexture(textureValue)));
}
+
// add leather armor dye color
Matcher colorMatcher = Pattern.compile("color:(\\d+)").matcher(nbttag);
if (colorMatcher.find()) {
- NbtInt color = NbtInt.of(Integer.parseInt(colorMatcher.group(1)));
- display.put("color", color);
+ int color = Integer.parseInt(colorMatcher.group(1));
+ stack.set(DataComponentTypes.DYED_COLOR, new DyedColorComponent(color, false));
}
// add enchantment glint
if (nbttag.contains("ench:")) {
- NbtList enchantments = new NbtList();
- enchantments.add(new NbtCompound());
- tag.put("Enchantments", enchantments);
+ 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 = Pattern.compile("\\{Explosion:\\{(?:Type:[0-9a-z]+,)?Colors:\\[(?<color>[0-9]+)]\\}").matcher(nbttag);
if (explosionColorMatcher.find()) {
- NbtCompound explosion = new NbtCompound();
-
- explosion.putInt("Type", FireworkRocketItem.Type.SMALL_BALL.getId()); //Forget about the actual ball type because it probably doesn't matter
- explosion.putIntArray("Colors", new int[]{Integer.parseInt(explosionColorMatcher.group("color"))});
- tag.put("Explosion", explosion);
+ //Forget about the actual ball type because it probably doesn't matter
+ stack.set(DataComponentTypes.FIREWORK_EXPLOSION, new FireworkExplosionComponent(FireworkExplosionComponent.Type.SMALL_BALL, new IntArrayList(Integer.parseInt(explosionColorMatcher.group("color"))), new IntArrayList(), false, false));
}
+
+ // Attach custom nbt data
+ stack.set(DataComponentTypes.CUSTOM_DATA, NbtComponent.of(customData));
- return ItemStack.fromNbt(root);
+ return stack;
}
private static List<Pair<String, String>> petData(String internalName) {
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/SearchResultsWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/SearchResultsWidget.java
index 44e336d9..961a2cc2 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/SearchResultsWidget.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/SearchResultsWidget.java
@@ -8,10 +8,13 @@ import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.Drawable;
import net.minecraft.client.gui.screen.ButtonTextures;
import net.minecraft.client.gui.widget.ToggleButtonWidget;
+import net.minecraft.component.DataComponentTypes;
+import net.minecraft.component.type.LoreComponent;
import net.minecraft.item.ItemStack;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.minecraft.util.Identifier;
+
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
@@ -74,11 +77,8 @@ public class SearchResultsWidget implements Drawable {
this.searchResults.clear();
for (ItemStack entry : ItemRepository.getItems()) {
String name = entry.getName().toString().toLowerCase(Locale.ENGLISH);
- if (entry.getNbt() == null) {
- continue;
- }
- String disp = entry.getNbt().getCompound("display").toString().toLowerCase(Locale.ENGLISH);
- if (name.contains(this.searchText) || disp.contains(this.searchText))
+ LoreComponent lore = entry.getOrDefault(DataComponentTypes.LORE, LoreComponent.DEFAULT);
+ if (name.contains(this.searchText) || lore.lines().stream().map(Text::getString).anyMatch(s -> s.contains(this.searchText)))
this.searchResults.add(entry);
}
this.currentPage = 0;
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/quicknav/QuickNav.java b/src/main/java/de/hysky/skyblocker/skyblock/quicknav/QuickNav.java
index 51a3d409..8e203b84 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/quicknav/QuickNav.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/quicknav/QuickNav.java
@@ -5,12 +5,12 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException;
import de.hysky.skyblocker.config.SkyblockerConfig;
import de.hysky.skyblocker.config.SkyblockerConfigManager;
import de.hysky.skyblocker.utils.Utils;
+import de.hysky.skyblocker.utils.datafixer.ItemStackComponentizationFixer;
import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents;
import net.fabricmc.fabric.api.client.screen.v1.Screens;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.ingame.HandledScreen;
import net.minecraft.client.network.ClientPlayerEntity;
-import net.minecraft.item.ItemStack;
import net.minecraft.nbt.StringNbtReader;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
@@ -21,8 +21,6 @@ import java.util.Locale;
import java.util.regex.PatternSyntaxException;
public class QuickNav {
- private static final String skyblockHubIconNbt = "{id:\"minecraft:player_head\",Count:1,tag:{SkullOwner:{Id:[I;-300151517,-631415889,-1193921967,-1821784279],Properties:{textures:[{Value:\"e3RleHR1cmVzOntTS0lOOnt1cmw6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDdjYzY2ODc0MjNkMDU3MGQ1NTZhYzUzZTA2NzZjYjU2M2JiZGQ5NzE3Y2Q4MjY5YmRlYmVkNmY2ZDRlN2JmOCJ9fX0=\"}]}}}}";
- private static final String dungeonHubIconNbt = "{id:\"minecraft:player_head\",Count:1,tag:{SkullOwner:{Id:[I;1605800870,415127827,-1236127084,15358548],Properties:{textures:[{Value:\"e3RleHR1cmVzOntTS0lOOnt1cmw6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzg5MWQ1YjI3M2ZmMGJjNTBjOTYwYjJjZDg2ZWVmMWM0MGExYjk0MDMyYWU3MWU3NTQ3NWE1NjhhODI1NzQyMSJ9fX0=\"}]}}}}";
public static void init() {
ScreenEvents.AFTER_INIT.register((client, screen, scaledWidth, scaledHeight) -> {
@@ -74,7 +72,6 @@ public class QuickNav {
return new QuickNavButton(id,
uiTitleMatches,
buttonInfo.clickEvent,
- ItemStack.fromNbt(StringNbtReader.parse(nbtString))
- );
+ ItemStackComponentizationFixer.fixUpItem(StringNbtReader.parse(nbtString)));
}
}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/special/SpecialEffects.java b/src/main/java/de/hysky/skyblocker/skyblock/special/SpecialEffects.java
index bc4f98c2..8e10086f 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/special/SpecialEffects.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/special/SpecialEffects.java
@@ -1,42 +1,24 @@
package de.hysky.skyblocker.skyblock.special;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import de.hysky.skyblocker.config.SkyblockerConfigManager;
+import de.hysky.skyblocker.skyblock.itemlist.ItemRepository;
import de.hysky.skyblocker.utils.Utils;
import de.hysky.skyblocker.utils.render.RenderHelper;
import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents;
import net.minecraft.client.MinecraftClient;
-import net.minecraft.enchantment.Enchantments;
import net.minecraft.item.ItemStack;
-import net.minecraft.item.Items;
-import net.minecraft.nbt.StringNbtReader;
import net.minecraft.particle.ParticleTypes;
import net.minecraft.text.Text;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
public class SpecialEffects {
private static final Logger LOGGER = LoggerFactory.getLogger(SpecialEffects.class);
private static final Pattern DROP_PATTERN = Pattern.compile("(?:\\[[A-Z+]+] )?(?<player>[A-Za-z0-9_]+) unlocked (?<item>.+)!");
- private static final ItemStack NECRON_HANDLE = new ItemStack(Items.STICK);
- private static final ItemStack SCROLL = new ItemStack(Items.WRITABLE_BOOK);
- private static ItemStack TIER_5_SKULL;
- private static ItemStack FIFTH_STAR;
-
- static {
- NECRON_HANDLE.addEnchantment(Enchantments.PROTECTION, 1);
- SCROLL.addEnchantment(Enchantments.PROTECTION, 1);
- try {
- TIER_5_SKULL = ItemStack.fromNbt(StringNbtReader.parse("{id:\"minecraft:player_head\",Count:1,tag:{SkullOwner:{Id:[I;-1613868903,-527154034,-1445577520,748807544],Properties:{textures:[{Value:\"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOTEwZjlmMTA4NWQ0MDcxNDFlYjc3NjE3YTRhYmRhYWEwOGQ4YWYzM2I5NjAyMDBmZThjMTI2YzFkMTQ0NTY4MiJ9fX0=\"}]}}}}"));
- FIFTH_STAR = ItemStack.fromNbt(StringNbtReader.parse("{id:\"minecraft:player_head\",Count:1,tag:{SkullOwner:{Id:[I;1904417095,756174249,-1302927470,1407004198],Properties:{textures:[{Value:\"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzFjODA0MjUyN2Y4MWM4ZTI5M2UyODEwMTEzNDg5ZjQzOTRjYzZlZmUxNWQxYWZhYzQzMTU3MWM3M2I2MmRjNCJ9fX0=\"}]}}}}"));
- } catch (Exception e) {
- TIER_5_SKULL = ItemStack.EMPTY;
- FIFTH_STAR = ItemStack.EMPTY;
- LOGGER.error("[Skyblocker Special Effects] Failed to parse NBT for a player head!", e);
- }
- }
public static void init() {
ClientReceiveMessageEvents.GAME.register(SpecialEffects::displayRareDropEffect);
@@ -45,7 +27,7 @@ public class SpecialEffects {
private static void displayRareDropEffect(Text message, boolean overlay) {
//We don't check if we're in dungeons because that check doesn't work in m7 which defeats the point of this
//It might also allow it to work with Croesus
- if (Utils.isOnSkyblock() && SkyblockerConfigManager.get().general.specialEffects.rareDungeonDropEffects) {
+ if (Utils.isOnSkyblock() && SkyblockerConfigManager.get().general.specialEffects.rareDungeonDropEffects && !overlay) {
try {
String stringForm = message.getString();
Matcher matcher = DROP_PATTERN.matcher(stringForm);
@@ -57,7 +39,7 @@ public class SpecialEffects {
if (player.equals(client.getSession().getUsername())) {
ItemStack stack = getStackFromName(matcher.group("item"));
- if (!stack.isEmpty()) {
+ if (stack != null && !stack.isEmpty()) {
RenderHelper.runOnRenderThread(() -> {
client.particleManager.addEmitter(client.player, ParticleTypes.PORTAL, 30);
client.gameRenderer.showFloatingItem(stack);
@@ -72,20 +54,22 @@ public class SpecialEffects {
}
private static ItemStack getStackFromName(String itemName) {
- return switch (itemName) {
+ String itemId = switch (itemName) {
//M7
- case "Necron Dye" -> new ItemStack(Items.ORANGE_DYE);
- case "Dark Claymore" -> new ItemStack(Items.STONE_SWORD);
- case "Necron's Handle", "Shiny Necron's Handle" -> NECRON_HANDLE;
- case "Enchanted Book (Thunderlord VII)" -> new ItemStack(Items.ENCHANTED_BOOK);
- case "Master Skull - Tier 5" -> TIER_5_SKULL;
- case "Shadow Warp", "Wither Shield", "Implosion" -> SCROLL;
- case "Fifth Master Star" -> FIFTH_STAR;
+ case "Necron Dye" -> "NECRON_DYE";
+ case "Dark Claymore" -> "DARK_CLAYMORE";
+ case "Necron's Handle", "Shiny Necron's Handle" -> "NECRON_HANDLE";
+ case "Enchanted Book (Thunderlord VII)" -> "ENCHANTED_BOOK";
+ case "Master Skull - Tier 5" -> "MASTER_SKULL_TIER_5";
+ case "Shadow Warp", "Wither Shield", "Implosion" -> "IMPLOSION_SCROLL";
+ case "Fifth Master Star" -> "FIFTH_MASTER_STAR";
//M6
- case "Giant's Sword" -> new ItemStack(Items.IRON_SWORD);
+ case "Giant's Sword" -> "GIANTS_SWORD";
- default -> ItemStack.EMPTY;
+ default -> "NONE";
};
+
+ return ItemRepository.getItemStack(itemId);
}
}
diff --git a/src/main/java/de/hysky/skyblocker/utils/ItemUtils.java b/src/main/java/de/hysky/skyblocker/utils/ItemUtils.java
index 70a8c241..9768ff11 100644
--- a/src/main/java/de/hysky/skyblocker/utils/ItemUtils.java
+++ b/src/main/java/de/hysky/skyblocker/utils/ItemUtils.java
@@ -1,18 +1,26 @@
package de.hysky.skyblocker.utils;
+import com.google.gson.Gson;
+import com.google.gson.JsonParser;
+import com.mojang.authlib.properties.PropertyMap;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
-import com.mojang.brigadier.exceptions.CommandSyntaxException;
-import de.hysky.skyblocker.mixin.accessor.ItemStackAccessor;
+import com.mojang.serialization.JsonOps;
+
import it.unimi.dsi.fastutil.ints.IntIntPair;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
+import net.minecraft.component.DataComponentTypes;
+import net.minecraft.component.type.LoreComponent;
+import net.minecraft.component.type.NbtComponent;
+import net.minecraft.component.type.ProfileComponent;
import net.minecraft.item.ItemStack;
+import net.minecraft.item.Items;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtElement;
-import net.minecraft.nbt.StringNbtReader;
import net.minecraft.text.Text;
-import net.minecraft.text.Texts;
import net.minecraft.util.Formatting;
+import net.minecraft.util.dynamic.Codecs;
+
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
@@ -39,13 +47,18 @@ public class ItemUtils {
private static final SimpleDateFormat OLD_OBTAINED_DATE_FORMAT = new SimpleDateFormat("MM/dd/yy");
public static final Pattern NOT_DURABILITY = Pattern.compile("[^0-9 /]");
public static final Predicate<String> FUEL_PREDICATE = line -> line.contains("Fuel: ");
+ private static final Gson GSON = new Gson(); //GSON Instance with no config
- public static LiteralArgumentBuilder<FabricClientCommandSource> dumpHeldItemNbtCommand() {
- return literal("dumpHeldItemNbt").executes(context -> {
- context.getSource().sendFeedback(Text.literal("[Skyblocker Debug] Held Item Nbt: " + context.getSource().getPlayer().getMainHandStack().writeNbt(new NbtCompound())));
+ public static LiteralArgumentBuilder<FabricClientCommandSource> dumpHeldItemCommand() {
+ return literal("dumpHeldItem").executes(context -> {
+ context.getSource().sendFeedback(Text.literal("[Skyblocker Debug] Held Item: " + GSON.toJson(ItemStack.CODEC.encodeStart(JsonOps.INSTANCE, context.getSource().getPlayer().getMainHandStack()).result().orElseThrow())));
return Command.SINGLE_SUCCESS;
});
}
+
+ public static NbtComponent getCustomData(@NotNull ItemStack stack) {
+ return stack.getOrDefault(DataComponentTypes.CUSTOM_DATA, NbtComponent.DEFAULT);
+ }
/**
* Gets the {@code ExtraAttributes} NBT tag from the item stack.
@@ -54,7 +67,7 @@ public class ItemUtils {
* @return an optional containing the {@code ExtraAttributes} NBT tag of the item stack
*/
public static Optional<NbtCompound> getExtraAttributesOptional(@NotNull ItemStack stack) {
- return Optional.ofNullable(stack.getSubNbt(EXTRA_ATTRIBUTES));
+ return Optional.ofNullable(getExtraAttributes(stack));
}
/**
@@ -65,7 +78,9 @@ public class ItemUtils {
*/
@Nullable
public static NbtCompound getExtraAttributes(@NotNull ItemStack stack) {
- return stack.getSubNbt(EXTRA_ATTRIBUTES);
+ NbtComponent customData = getCustomData(stack);
+ NbtCompound customNbt = customData.copyNbt();
+ return customNbt.contains(EXTRA_ATTRIBUTES) ? customNbt.getCompound(EXTRA_ATTRIBUTES) : null;
}
/**
@@ -166,7 +181,7 @@ public class ItemUtils {
return IntIntPair.of(pickonimbusDurability, 5000);
}
- String drillFuel = Formatting.strip(getNbtTooltip(stack, FUEL_PREDICATE));
+ String drillFuel = Formatting.strip(getLoreLineIf(stack, FUEL_PREDICATE));
if (drillFuel != null) {
String[] drillFuelStrings = NOT_DURABILITY.matcher(drillFuel).replaceAll("").trim().split("/");
return IntIntPair.of(Integer.parseInt(drillFuelStrings[0]), Integer.parseInt(drillFuelStrings[1]) * 1000);
@@ -176,8 +191,8 @@ public class ItemUtils {
}
@Nullable
- public static String getNbtTooltip(ItemStack item, Predicate<String> predicate) {
- for (Text line : getNbtTooltips(item)) {
+ public static String getLoreLineIf(ItemStack item, Predicate<String> predicate) {
+ for (Text line : getLore(item)) {
String string = line.getString();
if (predicate.test(string)) {
return string;
@@ -188,8 +203,8 @@ public class ItemUtils {
}
@Nullable
- public static Matcher getNbtTooltip(ItemStack item, Pattern pattern) {
- for (Text line : getNbtTooltips(item)) {
+ public static Matcher getLoreLineIfMatch(ItemStack item, Pattern pattern) {
+ for (Text line : getLore(item)) {
String string = line.getString();
Matcher matcher = pattern.matcher(string);
if (matcher.matches()) {
@@ -200,19 +215,24 @@ public class ItemUtils {
return null;
}
- public static List<Text> getNbtTooltips(ItemStack item) {
- NbtCompound displayNbt = item.getSubNbt("display");
- if (displayNbt == null || !displayNbt.contains("Lore", NbtElement.LIST_TYPE)) {
- return Collections.emptyList();
- }
+ public static List<Text> getLore(ItemStack item) {
+ LoreComponent lore = item.getOrDefault(DataComponentTypes.LORE, LoreComponent.DEFAULT);
- return displayNbt.getList("Lore", NbtElement.STRING_TYPE).stream().map(NbtElement::asString).map(Text.Serialization::fromJson).filter(Objects::nonNull).map(text -> Texts.setStyleIfAbsent(text, ItemStackAccessor.getLORE_STYLE())).map(Text.class::cast).toList();
+ return lore.styledLines();
+ }
+
+ public static PropertyMap propertyMapWithTexture(String textureValue) {
+ return Codecs.GAME_PROFILE_PROPERTY_MAP.parse(JsonOps.INSTANCE, JsonParser.parseString("[{\"name\":\"textures\",\"value\":\"" + textureValue + "\"}]")).result().orElseThrow();
}
public static ItemStack getSkyblockerStack() {
try {
- return ItemStack.fromNbt(StringNbtReader.parse("{id:\"minecraft:player_head\",Count:1,tag:{SkullOwner:{Id:[I;-300151517,-631415889,-1193921967,-1821784279],Properties:{textures:[{Value:\"e3RleHR1cmVzOntTS0lOOnt1cmw6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDdjYzY2ODc0MjNkMDU3MGQ1NTZhYzUzZTA2NzZjYjU2M2JiZGQ5NzE3Y2Q4MjY5YmRlYmVkNmY2ZDRlN2JmOCJ9fX0=\"}]}}}}"));
- } catch (CommandSyntaxException e) {
+ ItemStack stack = new ItemStack(Items.PLAYER_HEAD);
+ stack.set(DataComponentTypes.PROFILE, new ProfileComponent("SkyblockerStack", Optional.of(java.util.UUID.randomUUID()), propertyMapWithTexture("e3RleHR1cmVzOntTS0lOOnt1cmw6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDdjYzY2ODc0MjNkMDU3MGQ1NTZhYzUzZTA2NzZjYjU2M2JiZGQ5NzE3Y2Q4MjY5YmRlYmVkNmY2ZDRlN2JmOCJ9fX0=")));
+
+ return stack;
+ //return ItemStack.parseOptional(MinecraftClient.getInstance().player.getRegistryManager(), StringNbtReader.parse("{id:\"minecraft:player_head\",Count:1,tag:{SkullOwner:{Id:[I;-300151517,-631415889,-1193921967,-1821784279],Properties:{textures:[{Value:\"e3RleHR1cmVzOntTS0lOOnt1cmw6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDdjYzY2ODc0MjNkMDU3MGQ1NTZhYzUzZTA2NzZjYjU2M2JiZGQ5NzE3Y2Q4MjY5YmRlYmVkNmY2ZDRlN2JmOCJ9fX0=\"}]}}}}"));
+ } catch (Exception e) {
throw new RuntimeException(e);
}
}
diff --git a/src/main/java/de/hysky/skyblocker/utils/datafixer/ItemStackComponentizationFixer.java b/src/main/java/de/hysky/skyblocker/utils/datafixer/ItemStackComponentizationFixer.java
new file mode 100644
index 00000000..f1306ad5
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/utils/datafixer/ItemStackComponentizationFixer.java
@@ -0,0 +1,26 @@
+package de.hysky.skyblocker.utils.datafixer;
+
+import com.mojang.serialization.Dynamic;
+
+import net.minecraft.datafixer.Schemas;
+import net.minecraft.datafixer.TypeReferences;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NbtCompound;
+import net.minecraft.nbt.NbtElement;
+import net.minecraft.nbt.NbtOps;
+
+/**
+ * Contains a data fixer to convert legacy item NBT to the new components system.
+ *
+ * @see {@link net.minecraft.datafixer.fix.ItemStackComponentizationFix}
+ */
+public class ItemStackComponentizationFixer {
+ private static final int ITEM_NBT_DATA_VERSION = 3817;
+ private static final int ITEM_COMPONENTS_DATA_VERSION = 3818;
+
+ public static ItemStack fixUpItem(NbtCompound nbt) {
+ Dynamic<NbtElement> dynamic = Schemas.getFixer().update(TypeReferences.ITEM_STACK, new Dynamic<NbtElement>(NbtOps.INSTANCE, nbt), ITEM_NBT_DATA_VERSION, ITEM_COMPONENTS_DATA_VERSION);
+
+ return ItemStack.CODEC.parse(dynamic).result().orElseThrow();
+ }
+}
diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json
index 451cd684..e5ed5db4 100644
--- a/src/main/resources/fabric.mod.json
+++ b/src/main/resources/fabric.mod.json
@@ -34,9 +34,9 @@
"accessWidener": "skyblocker.accesswidener",
"depends": {
"fabricloader": ">=0.15.7",
- "fabric-api": ">=0.96.2+1.20.5",
- "yet_another_config_lib_v3": ">=3.3.2+1.20.4",
- "minecraft": "~1.20.5-alpha.24.7.a"
+ "fabric-api": ">=0.96.5+1.20.5",
+ "yet_another_config_lib_v3": ">=3.3.3+1.20.4+update.1.20.5-SNAPSHOT+update.1.20.5-SNAPSHOT",
+ "minecraft": "~1.20.5-alpha.24.9.a"
},
"conflicts": {
"immediatelyfast": "<=1.2.11+1.20.4"
diff --git a/src/main/resources/skyblocker.mixins.json b/src/main/resources/skyblocker.mixins.json
index 07168300..8a2205d4 100644
--- a/src/main/resources/skyblocker.mixins.json
+++ b/src/main/resources/skyblocker.mixins.json
@@ -5,14 +5,14 @@
"compatibilityLevel": "JAVA_17",
"client": [
"AbstractInventoryScreenMixin",
- "ArmorTrimMixin",
"BatEntityMixin",
"ClientPlayerEntityMixin",
"ClientPlayNetworkHandlerMixin",
"CommandTreeS2CPacketMixin",
+ "ComponentHolderMixin",
"DataTrackerMixin",
"DrawContextMixin",
- "DyeableItemMixin",
+ "DyedColorComponentMixin",
"EntityRenderDispatcherMixin",
"FarmlandBlockMixin",
"GenericContainerScreenHandlerMixin",
@@ -43,7 +43,6 @@
"accessor.EndermanEntityAccessor",
"accessor.FrustumInvoker",
"accessor.HandledScreenAccessor",
- "accessor.ItemStackAccessor",
"accessor.LayeredDrawerAccessor",
"accessor.MessageHandlerAccessor",
"accessor.PlayerListHudAccessor",
diff --git a/src/test/java/de/hysky/skyblocker/utils/ItemUtilsTest.java b/src/test/java/de/hysky/skyblocker/utils/ItemUtilsTest.java
index 71ff29ef..e5025d7a 100644
--- a/src/test/java/de/hysky/skyblocker/utils/ItemUtilsTest.java
+++ b/src/test/java/de/hysky/skyblocker/utils/ItemUtilsTest.java
@@ -1,20 +1,23 @@
package de.hysky.skyblocker.utils;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
+
+import de.hysky.skyblocker.utils.datafixer.ItemStackComponentizationFixer;
import it.unimi.dsi.fastutil.ints.IntIntPair;
import net.minecraft.Bootstrap;
import net.minecraft.SharedConstants;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.StringNbtReader;
+
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
public class ItemUtilsTest {
- private final ItemStack JUJU_SHORTBOW_OLD = ItemStack.fromNbt(StringNbtReader.parse("{Count:1b,id:\"minecraft:bow\",tag:{Damage:0,Enchantments:[{id:\"minecraft:protection\",lvl:0s}],ExtraAttributes:{art_of_war_count:1,dungeon_item_level:5,enchantments:{aiming:5,chance:4,cubism:5,impaling:3,infinite_quiver:10,overload:5,piercing:1,power:6,snipe:3,telekinesis:1,ultimate_soul_eater:5},hot_potato_count:15,id:\"JUJU_SHORTBOW\",modifier:\"spiritual\",originTag:\"QUICK_CRAFTING\",rarity_upgrades:1,runes:{DRAGON:3},stats_book:54778,timestamp:\"6/5/21 4:41 AM\",uuid:\"b06b8fe2-470a-43f3-b844-658472f20996\"},HideFlags:255,Unbreakable:1b,display:{Lore:['{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Gear Score: \"},{\"color\":\"light_purple\",\"text\":\"724 \"},{\"color\":\"dark_gray\",\"text\":\"(2297)\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Damage: \"},{\"color\":\"red\",\"text\":\"+371 \"},{\"color\":\"yellow\",\"text\":\"(+30) \"},{\"color\":\"dark_gray\",\"text\":\"(+1,275)\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Strength: \"},{\"color\":\"red\",\"text\":\"+107 \"},{\"color\":\"yellow\",\"text\":\"(+30) \"},{\"color\":\"gold\",\"text\":\"[+5] \"},{\"color\":\"blue\",\"text\":\"(+28) \"},{\"color\":\"dark_gray\",\"text\":\"(+386.25)\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Crit Chance: \"},{\"color\":\"red\",\"text\":\"+28% \"},{\"color\":\"blue\",\"text\":\"(+12%) \"},{\"color\":\"dark_gray\",\"text\":\"(+40.5%)\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Crit Damage: \"},{\"color\":\"red\",\"text\":\"+181% \"},{\"color\":\"blue\",\"text\":\"(+55%) \"},{\"color\":\"dark_gray\",\"text\":\"(+637.5%)\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Shot Cooldown: \"},{\"color\":\"green\",\"text\":\"0.5s\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"bold\":true,\"color\":\"light_purple\",\"text\":\"\"},{\"bold\":true,\"color\":\"light_purple\",\"text\":\"Soul Eater V\"},{\"color\":\"blue\",\"text\":\", \"},{\"color\":\"blue\",\"text\":\"Chance IV\"},{\"color\":\"blue\",\"text\":\", \"},{\"color\":\"blue\",\"text\":\"Cubism V\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"blue\",\"text\":\"Dragon Tracer V\"},{\"color\":\"blue\",\"text\":\", \"},{\"color\":\"blue\",\"text\":\"Impaling III\"},{\"color\":\"blue\",\"text\":\", \"},{\"color\":\"blue\",\"text\":\"Infinite Quiver X\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"blue\",\"text\":\"Overload V\"},{\"color\":\"blue\",\"text\":\", \"},{\"color\":\"blue\",\"text\":\"Piercing I\"},{\"color\":\"blue\",\"text\":\", \"},{\"color\":\"blue\",\"text\":\"Power VI\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"blue\",\"text\":\"Snipe III\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"dark_purple\",\"text\":\"◆ End Rune III\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Hits \"},{\"color\":\"red\",\"text\":\"3 \"},{\"color\":\"gray\",\"text\":\"mobs on impact.\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Can damage endermen.\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"white\",\"text\":\"Kills: \"},{\"color\":\"gold\",\"text\":\"54,778\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"blue\",\"text\":\"Spiritual Bonus\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Grants a \"},{\"color\":\"green\",\"text\":\"10% \"},{\"color\":\"gray\",\"text\":\"chance to spawn\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"a Spirit Decoy when you kill an\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"enemy in a dungeon.\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gold\",\"text\":\"Shortbow: Instantly shoots!\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"\"},{\"color\":\"dark_red\",\"text\":\"☠ \"},{\"color\":\"red\",\"text\":\"Requires \"},{\"color\":\"dark_purple\",\"text\":\"Enderman Slayer\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"dark_purple\",\"text\":\"5\"},{\"color\":\"red\",\"text\":\".\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"bold\":true,\"obfuscated\":true,\"color\":\"gold\",\"text\":\"a\"},{\"text\":\"\"},{\"bold\":false,\"italic\":false,\"underlined\":false,\"obfuscated\":false,\"strikethrough\":false,\"extra\":[{\"text\":\" \"}],\"text\":\"\"},{\"bold\":true,\"color\":\"gold\",\"text\":\"\"},{\"bold\":true,\"color\":\"gold\",\"text\":\"LEGENDARY DUNGEON BOW \"},{\"bold\":true,\"obfuscated\":true,\"color\":\"gold\",\"text\":\"a\"}],\"text\":\"\"}'],Name:'{\"italic\":false,\"extra\":[{\"color\":\"gold\",\"text\":\"Spiritual Juju Shortbow \"},{\"color\":\"gold\",\"text\":\"✪\"},{\"color\":\"gold\",\"text\":\"✪\"},{\"color\":\"gold\",\"text\":\"✪\"},{\"color\":\"gold\",\"text\":\"✪\"},{\"color\":\"gold\",\"text\":\"✪\"}],\"text\":\"\"}'}}}"));
- private final ItemStack JUJU_SHORTBOW = ItemStack.fromNbt(StringNbtReader.parse("{Count:1b,id:\"minecraft:bow\",tag:{Damage:0,Enchantments:[{id:\"minecraft:protection\",lvl:0s}],ExtraAttributes:{art_of_war_count:1,dungeon_item_level:5,enchantments:{aiming:5,chance:4,cubism:5,impaling:3,infinite_quiver:10,overload:5,piercing:1,power:6,snipe:3,telekinesis:1,ultimate_soul_eater:5},hot_potato_count:15,id:\"JUJU_SHORTBOW\",modifier:\"spiritual\",originTag:\"QUICK_CRAFTING\",rarity_upgrades:1,runes:{DRAGON:3},stats_book:54778,timestamp:1622882460000L,uuid:\"b06b8fe2-470a-43f3-b844-658472f20996\"},HideFlags:255,Unbreakable:1b,display:{Lore:['{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Gear Score: \"},{\"color\":\"light_purple\",\"text\":\"724 \"},{\"color\":\"dark_gray\",\"text\":\"(2297)\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Damage: \"},{\"color\":\"red\",\"text\":\"+371 \"},{\"color\":\"yellow\",\"text\":\"(+30) \"},{\"color\":\"dark_gray\",\"text\":\"(+1,275)\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Strength: \"},{\"color\":\"red\",\"text\":\"+107 \"},{\"color\":\"yellow\",\"text\":\"(+30) \"},{\"color\":\"gold\",\"text\":\"[+5] \"},{\"color\":\"blue\",\"text\":\"(+28) \"},{\"color\":\"dark_gray\",\"text\":\"(+386.25)\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Crit Chance: \"},{\"color\":\"red\",\"text\":\"+28% \"},{\"color\":\"blue\",\"text\":\"(+12%) \"},{\"color\":\"dark_gray\",\"text\":\"(+40.5%)\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Crit Damage: \"},{\"color\":\"red\",\"text\":\"+181% \"},{\"color\":\"blue\",\"text\":\"(+55%) \"},{\"color\":\"dark_gray\",\"text\":\"(+637.5%)\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Shot Cooldown: \"},{\"color\":\"green\",\"text\":\"0.5s\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"bold\":true,\"color\":\"light_purple\",\"text\":\"\"},{\"bold\":true,\"color\":\"light_purple\",\"text\":\"Soul Eater V\"},{\"color\":\"blue\",\"text\":\", \"},{\"color\":\"blue\",\"text\":\"Chance IV\"},{\"color\":\"blue\",\"text\":\", \"},{\"color\":\"blue\",\"text\":\"Cubism V\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"blue\",\"text\":\"Dragon Tracer V\"},{\"color\":\"blue\",\"text\":\", \"},{\"color\":\"blue\",\"text\":\"Impaling III\"},{\"color\":\"blue\",\"text\":\", \"},{\"color\":\"blue\",\"text\":\"Infinite Quiver X\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"blue\",\"text\":\"Overload V\"},{\"color\":\"blue\",\"text\":\", \"},{\"color\":\"blue\",\"text\":\"Piercing I\"},{\"color\":\"blue\",\"text\":\", \"},{\"color\":\"blue\",\"text\":\"Power VI\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"blue\",\"text\":\"Snipe III\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"dark_purple\",\"text\":\"◆ End Rune III\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Hits \"},{\"color\":\"red\",\"text\":\"3 \"},{\"color\":\"gray\",\"text\":\"mobs on impact.\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Can damage endermen.\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gold\",\"text\":\"Shortbow: Instantly shoots!\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"white\",\"text\":\"Kills: \"},{\"color\":\"gold\",\"text\":\"54,778\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"blue\",\"text\":\"Spiritual Bonus\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Grants a \"},{\"color\":\"green\",\"text\":\"10% \"},{\"color\":\"gray\",\"text\":\"chance to spawn a\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Spirit Decoy when you kill an enemy\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"in a dungeon.\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"\"},{\"color\":\"dark_red\",\"text\":\"☠ \"},{\"color\":\"red\",\"text\":\"Requires \"},{\"color\":\"dark_purple\",\"text\":\"Enderman Slayer 5\"},{\"color\":\"red\",\"text\":\".\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"bold\":true,\"obfuscated\":true,\"color\":\"gold\",\"text\":\"a\"},{\"text\":\"\"},{\"bold\":false,\"italic\":false,\"underlined\":false,\"obfuscated\":false,\"strikethrough\":false,\"extra\":[{\"text\":\" \"}],\"text\":\"\"},{\"bold\":true,\"color\":\"gold\",\"text\":\"\"},{\"bold\":true,\"color\":\"gold\",\"text\":\"LEGENDARY DUNGEON BOW \"},{\"bold\":true,\"obfuscated\":true,\"color\":\"gold\",\"text\":\"a\"}],\"text\":\"\"}'],Name:'{\"italic\":false,\"extra\":[{\"color\":\"gold\",\"text\":\"Spiritual Juju Shortbow \"},{\"color\":\"gold\",\"text\":\"✪\"},{\"color\":\"gold\",\"text\":\"✪\"},{\"color\":\"gold\",\"text\":\"✪\"},{\"color\":\"gold\",\"text\":\"✪\"},{\"color\":\"gold\",\"text\":\"✪\"}],\"text\":\"\"}'}}}"));
- private final ItemStack LIVID_DAGGER = ItemStack.fromNbt(StringNbtReader.parse("{Count:1b,id:\"minecraft:iron_sword\",tag:{Damage:0,Enchantments:[{id:\"minecraft:protection\",lvl:0s}],ExtraAttributes:{dungeon_item_level:5,enchantments:{telekinesis:1,ultimate_one_for_all:1},gems:{JASPER_0:\"FLAWLESS\"},hot_potato_count:15,id:\"LIVID_DAGGER\",modifier:\"fabled\",originTag:\"UNKNOWN\",rarity_upgrades:1,timestamp:\"2/20/21 3:09 PM\",uuid:\"214333db-d71c-4080-8487-00b4666bb9a4\"},HideFlags:255,Unbreakable:1b,display:{Lore:['{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Gear Score: \"},{\"color\":\"light_purple\",\"text\":\"933 \"},{\"color\":\"dark_gray\",\"text\":\"(2389)\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Damage: \"},{\"color\":\"red\",\"text\":\"+261 \"},{\"color\":\"yellow\",\"text\":\"(+30) \"},{\"color\":\"dark_gray\",\"text\":\"(+900)\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Strength: \"},{\"color\":\"red\",\"text\":\"+183 \"},{\"color\":\"yellow\",\"text\":\"(+30) \"},{\"color\":\"blue\",\"text\":\"(+75) \"},{\"color\":\"light_purple\",\"text\":\"(+12) \"},{\"color\":\"dark_gray\",\"text\":\"(+663.75)\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Crit Chance: \"},{\"color\":\"red\",\"text\":\"+100% \"},{\"color\":\"dark_gray\",\"text\":\"(+150%)\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Crit Damage: \"},{\"color\":\"red\",\"text\":\"+105% \"},{\"color\":\"blue\",\"text\":\"(+50%) \"},{\"color\":\"dark_gray\",\"text\":\"(+375%)\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Bonus Attack Speed: \"},{\"color\":\"red\",\"text\":\"+55% \"},{\"color\":\"dark_gray\",\"text\":\"(+75%)\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"text\":\" \"},{\"color\":\"dark_purple\",\"text\":\"[\"},{\"color\":\"light_purple\",\"text\":\"❁\"},{\"color\":\"dark_purple\",\"text\":\"]\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"bold\":true,\"color\":\"light_purple\",\"text\":\"\"},{\"bold\":true,\"color\":\"light_purple\",\"text\":\"One For All I\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gold\",\"text\":\"Ability: Throw \"},{\"bold\":true,\"color\":\"yellow\",\"text\":\"RIGHT CLICK\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Throw your dagger at your\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"enemies!\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"dark_gray\",\"text\":\"Mana Cost: \"},{\"color\":\"dark_aqua\",\"text\":\"150\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"dark_gray\",\"text\":\"Cooldown: \"},{\"color\":\"green\",\"text\":\"5s\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Your Critical Hits deal \"},{\"color\":\"blue\",\"text\":\"100%\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"blue\",\"text\":\"\"},{\"color\":\"gray\",\"text\":\"more damage if you are behind\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"your target.\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"blue\",\"text\":\"Fabled Bonus\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Critical hits have a chance to\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"deal up to \"},{\"color\":\"green\",\"text\":\"15% \"},{\"color\":\"gray\",\"text\":\"extra damage.\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"bold\":true,\"obfuscated\":true,\"color\":\"light_purple\",\"text\":\"a\"},{\"text\":\"\"},{\"bold\":false,\"italic\":false,\"underlined\":false,\"obfuscated\":false,\"strikethrough\":false,\"extra\":[{\"text\":\" \"}],\"text\":\"\"},{\"bold\":true,\"color\":\"light_purple\",\"text\":\"\"},{\"bold\":true,\"color\":\"light_purple\",\"text\":\"MYTHIC DUNGEON SWORD \"},{\"bold\":true,\"obfuscated\":true,\"color\":\"light_purple\",\"text\":\"a\"}],\"text\":\"\"}'],Name:'{\"italic\":false,\"extra\":[{\"color\":\"light_purple\",\"text\":\"Fabled Livid Dagger \"},{\"color\":\"gold\",\"text\":\"✪\"},{\"color\":\"gold\",\"text\":\"✪\"},{\"color\":\"gold\",\"text\":\"✪\"},{\"color\":\"gold\",\"text\":\"✪\"},{\"color\":\"gold\",\"text\":\"✪\"}],\"text\":\"\"}'}}}"));
- private final ItemStack MITHRIL_DRILL_1 = ItemStack.fromNbt(StringNbtReader.parse("{Count:1b,id:\"minecraft:prismarine_shard\",tag:{Damage:21,Enchantments:[{id:\"minecraft:protection\",lvl:0s}],ExtraAttributes:{compact_blocks:97683,drill_fuel:2979,enchantments:{compact:7,efficiency:5,experience:3,fortune:3,telekinesis:1},id:\"MITHRIL_DRILL_1\",modifier:\"fleet\",originTag:\"UNKNOWN\",timestamp:\"1/30/21 5:52 AM\",uuid:\"575ce2c9-251e-4435-9020-de1a2e24b1d0\"},HideFlags:255,display:{Lore:['{\"italic\":false,\"extra\":[{\"color\":\"dark_gray\",\"text\":\"Breaking Power 5\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Damage: \"},{\"color\":\"red\",\"text\":\"+65\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Mining Speed: \"},{\"color\":\"green\",\"text\":\"+585 \"},{\"color\":\"blue\",\"text\":\"(+25)\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Mining Fortune: \"},{\"color\":\"green\",\"text\":\"+30\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Mining Wisdom: \"},{\"color\":\"green\",\"text\":\"+7\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"blue\",\"text\":\"Compact VII \"},{\"color\":\"dark_gray\",\"text\":\"97,683\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Gain \"},{\"color\":\"dark_aqua\",\"text\":\"+7☯ Mining Wisdom \"},{\"color\":\"gray\",\"text\":\"and a \"},{\"color\":\"green\",\"text\":\"0.4%\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"green\",\"text\":\"\"},{\"color\":\"gray\",\"text\":\"chance to drop an enchanted item.\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"dark_gray\",\"text\":\"150k blocks to tier up!\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"blue\",\"text\":\"Efficiency V\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Grants \"},{\"color\":\"green\",\"text\":\"+110 \"},{\"color\":\"gold\",\"text\":\"⸕ Mining Speed\"},{\"color\":\"gray\",\"text\":\".\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"blue\",\"text\":\"Experience III\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Grants a \"},{\"color\":\"green\",\"text\":\"37.5% \"},{\"color\":\"gray\",\"text\":\"chance for mobs and\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"ores to drop double experience.\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"blue\",\"text\":\"Fortune III\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Grants \"},{\"color\":\"gold\",\"text\":\"+30☘ Mining Fortune\"},{\"color\":\"gray\",\"text\":\", which\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"increases your chance for multiple\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"drops.\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Gain \"},{\"color\":\"green\",\"text\":\"+15% \"},{\"color\":\"dark_green\",\"text\":\"Mithril Powder\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"when using this Drill!\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Fuel Tank: \"},{\"color\":\"red\",\"text\":\"Not Installed\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"\"},{\"color\":\"gray\",\"text\":\"Increases fuel capacity with part\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"installed.\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Drill Engine: \"},{\"color\":\"red\",\"text\":\"Not Installed\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"\"},{\"color\":\"gray\",\"text\":\"Increases \"},{\"color\":\"gold\",\"text\":\"⸕ Mining Speed \"},{\"color\":\"gray\",\"text\":\"with part\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"installed.\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Upgrade Module: \"},{\"color\":\"red\",\"text\":\"Not Installed\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"\"},{\"color\":\"gray\",\"text\":\"Applies a passive upgrade with part\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"installed.\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Apply Drill Parts to this Drill by\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"talking to a \"},{\"color\":\"dark_green\",\"text\":\"Drill Mechanic\"},{\"color\":\"gray\",\"text\":\"!\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Fuel: \"},{\"color\":\"dark_green\",\"text\":\"2,979\"},{\"color\":\"dark_gray\",\"text\":\"/3k\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gold\",\"text\":\"Ability: Mining Speed Boost \"},{\"bold\":true,\"color\":\"yellow\",\"text\":\"RIGHT CLICK\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Grants \"},{\"color\":\"green\",\"text\":\"+\"},{\"color\":\"green\",\"text\":\"200% \"},{\"color\":\"gold\",\"text\":\"⸕ Mining Speed \"},{\"color\":\"gray\",\"text\":\"for\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"\"},{\"color\":\"green\",\"text\":\"15s\"},{\"color\":\"gray\",\"text\":\".\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"dark_gray\",\"text\":\"Cooldown: \"},{\"color\":\"green\",\"text\":\"120s\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"bold\":true,\"color\":\"blue\",\"text\":\"RARE DRILL\"}],\"text\":\"\"}'],Name:'{\"italic\":false,\"extra\":[{\"color\":\"blue\",\"text\":\"Fleet Mithril Drill SX-R226\"}],\"text\":\"\"}'}}}"));
+ private final ItemStack JUJU_SHORTBOW_OLD = ItemStackComponentizationFixer.fixUpItem(StringNbtReader.parse("{Count:1b,id:\"minecraft:bow\",tag:{Damage:0,Enchantments:[{id:\"minecraft:protection\",lvl:0s}],ExtraAttributes:{art_of_war_count:1,dungeon_item_level:5,enchantments:{aiming:5,chance:4,cubism:5,impaling:3,infinite_quiver:10,overload:5,piercing:1,power:6,snipe:3,telekinesis:1,ultimate_soul_eater:5},hot_potato_count:15,id:\"JUJU_SHORTBOW\",modifier:\"spiritual\",originTag:\"QUICK_CRAFTING\",rarity_upgrades:1,runes:{DRAGON:3},stats_book:54778,timestamp:\"6/5/21 4:41 AM\",uuid:\"b06b8fe2-470a-43f3-b844-658472f20996\"},HideFlags:255,Unbreakable:1b,display:{Lore:['{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Gear Score: \"},{\"color\":\"light_purple\",\"text\":\"724 \"},{\"color\":\"dark_gray\",\"text\":\"(2297)\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Damage: \"},{\"color\":\"red\",\"text\":\"+371 \"},{\"color\":\"yellow\",\"text\":\"(+30) \"},{\"color\":\"dark_gray\",\"text\":\"(+1,275)\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Strength: \"},{\"color\":\"red\",\"text\":\"+107 \"},{\"color\":\"yellow\",\"text\":\"(+30) \"},{\"color\":\"gold\",\"text\":\"[+5] \"},{\"color\":\"blue\",\"text\":\"(+28) \"},{\"color\":\"dark_gray\",\"text\":\"(+386.25)\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Crit Chance: \"},{\"color\":\"red\",\"text\":\"+28% \"},{\"color\":\"blue\",\"text\":\"(+12%) \"},{\"color\":\"dark_gray\",\"text\":\"(+40.5%)\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Crit Damage: \"},{\"color\":\"red\",\"text\":\"+181% \"},{\"color\":\"blue\",\"text\":\"(+55%) \"},{\"color\":\"dark_gray\",\"text\":\"(+637.5%)\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Shot Cooldown: \"},{\"color\":\"green\",\"text\":\"0.5s\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"bold\":true,\"color\":\"light_purple\",\"text\":\"\"},{\"bold\":true,\"color\":\"light_purple\",\"text\":\"Soul Eater V\"},{\"color\":\"blue\",\"text\":\", \"},{\"color\":\"blue\",\"text\":\"Chance IV\"},{\"color\":\"blue\",\"text\":\", \"},{\"color\":\"blue\",\"text\":\"Cubism V\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"blue\",\"text\":\"Dragon Tracer V\"},{\"color\":\"blue\",\"text\":\", \"},{\"color\":\"blue\",\"text\":\"Impaling III\"},{\"color\":\"blue\",\"text\":\", \"},{\"color\":\"blue\",\"text\":\"Infinite Quiver X\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"blue\",\"text\":\"Overload V\"},{\"color\":\"blue\",\"text\":\", \"},{\"color\":\"blue\",\"text\":\"Piercing I\"},{\"color\":\"blue\",\"text\":\", \"},{\"color\":\"blue\",\"text\":\"Power VI\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"blue\",\"text\":\"Snipe III\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"dark_purple\",\"text\":\"◆ End Rune III\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Hits \"},{\"color\":\"red\",\"text\":\"3 \"},{\"color\":\"gray\",\"text\":\"mobs on impact.\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Can damage endermen.\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"white\",\"text\":\"Kills: \"},{\"color\":\"gold\",\"text\":\"54,778\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"blue\",\"text\":\"Spiritual Bonus\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Grants a \"},{\"color\":\"green\",\"text\":\"10% \"},{\"color\":\"gray\",\"text\":\"chance to spawn\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"a Spirit Decoy when you kill an\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"enemy in a dungeon.\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gold\",\"text\":\"Shortbow: Instantly shoots!\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"\"},{\"color\":\"dark_red\",\"text\":\"☠ \"},{\"color\":\"red\",\"text\":\"Requires \"},{\"color\":\"dark_purple\",\"text\":\"Enderman Slayer\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"dark_purple\",\"text\":\"5\"},{\"color\":\"red\",\"text\":\".\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"bold\":true,\"obfuscated\":true,\"color\":\"gold\",\"text\":\"a\"},{\"text\":\"\"},{\"bold\":false,\"italic\":false,\"underlined\":false,\"obfuscated\":false,\"strikethrough\":false,\"extra\":[{\"text\":\" \"}],\"text\":\"\"},{\"bold\":true,\"color\":\"gold\",\"text\":\"\"},{\"bold\":true,\"color\":\"gold\",\"text\":\"LEGENDARY DUNGEON BOW \"},{\"bold\":true,\"obfuscated\":true,\"color\":\"gold\",\"text\":\"a\"}],\"text\":\"\"}'],Name:'{\"italic\":false,\"extra\":[{\"color\":\"gold\",\"text\":\"Spiritual Juju Shortbow \"},{\"color\":\"gold\",\"text\":\"✪\"},{\"color\":\"gold\",\"text\":\"✪\"},{\"color\":\"gold\",\"text\":\"✪\"},{\"color\":\"gold\",\"text\":\"✪\"},{\"color\":\"gold\",\"text\":\"✪\"}],\"text\":\"\"}'}}}"));
+ private final ItemStack JUJU_SHORTBOW = ItemStackComponentizationFixer.fixUpItem(StringNbtReader.parse("{Count:1b,id:\"minecraft:bow\",tag:{Damage:0,Enchantments:[{id:\"minecraft:protection\",lvl:0s}],ExtraAttributes:{art_of_war_count:1,dungeon_item_level:5,enchantments:{aiming:5,chance:4,cubism:5,impaling:3,infinite_quiver:10,overload:5,piercing:1,power:6,snipe:3,telekinesis:1,ultimate_soul_eater:5},hot_potato_count:15,id:\"JUJU_SHORTBOW\",modifier:\"spiritual\",originTag:\"QUICK_CRAFTING\",rarity_upgrades:1,runes:{DRAGON:3},stats_book:54778,timestamp:1622882460000L,uuid:\"b06b8fe2-470a-43f3-b844-658472f20996\"},HideFlags:255,Unbreakable:1b,display:{Lore:['{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Gear Score: \"},{\"color\":\"light_purple\",\"text\":\"724 \"},{\"color\":\"dark_gray\",\"text\":\"(2297)\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Damage: \"},{\"color\":\"red\",\"text\":\"+371 \"},{\"color\":\"yellow\",\"text\":\"(+30) \"},{\"color\":\"dark_gray\",\"text\":\"(+1,275)\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Strength: \"},{\"color\":\"red\",\"text\":\"+107 \"},{\"color\":\"yellow\",\"text\":\"(+30) \"},{\"color\":\"gold\",\"text\":\"[+5] \"},{\"color\":\"blue\",\"text\":\"(+28) \"},{\"color\":\"dark_gray\",\"text\":\"(+386.25)\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Crit Chance: \"},{\"color\":\"red\",\"text\":\"+28% \"},{\"color\":\"blue\",\"text\":\"(+12%) \"},{\"color\":\"dark_gray\",\"text\":\"(+40.5%)\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Crit Damage: \"},{\"color\":\"red\",\"text\":\"+181% \"},{\"color\":\"blue\",\"text\":\"(+55%) \"},{\"color\":\"dark_gray\",\"text\":\"(+637.5%)\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Shot Cooldown: \"},{\"color\":\"green\",\"text\":\"0.5s\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"bold\":true,\"color\":\"light_purple\",\"text\":\"\"},{\"bold\":true,\"color\":\"light_purple\",\"text\":\"Soul Eater V\"},{\"color\":\"blue\",\"text\":\", \"},{\"color\":\"blue\",\"text\":\"Chance IV\"},{\"color\":\"blue\",\"text\":\", \"},{\"color\":\"blue\",\"text\":\"Cubism V\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"blue\",\"text\":\"Dragon Tracer V\"},{\"color\":\"blue\",\"text\":\", \"},{\"color\":\"blue\",\"text\":\"Impaling III\"},{\"color\":\"blue\",\"text\":\", \"},{\"color\":\"blue\",\"text\":\"Infinite Quiver X\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"blue\",\"text\":\"Overload V\"},{\"color\":\"blue\",\"text\":\", \"},{\"color\":\"blue\",\"text\":\"Piercing I\"},{\"color\":\"blue\",\"text\":\", \"},{\"color\":\"blue\",\"text\":\"Power VI\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"blue\",\"text\":\"Snipe III\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"dark_purple\",\"text\":\"◆ End Rune III\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Hits \"},{\"color\":\"red\",\"text\":\"3 \"},{\"color\":\"gray\",\"text\":\"mobs on impact.\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Can damage endermen.\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gold\",\"text\":\"Shortbow: Instantly shoots!\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"white\",\"text\":\"Kills: \"},{\"color\":\"gold\",\"text\":\"54,778\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"blue\",\"text\":\"Spiritual Bonus\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Grants a \"},{\"color\":\"green\",\"text\":\"10% \"},{\"color\":\"gray\",\"text\":\"chance to spawn a\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Spirit Decoy when you kill an enemy\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"in a dungeon.\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"\"},{\"color\":\"dark_red\",\"text\":\"☠ \"},{\"color\":\"red\",\"text\":\"Requires \"},{\"color\":\"dark_purple\",\"text\":\"Enderman Slayer 5\"},{\"color\":\"red\",\"text\":\".\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"bold\":true,\"obfuscated\":true,\"color\":\"gold\",\"text\":\"a\"},{\"text\":\"\"},{\"bold\":false,\"italic\":false,\"underlined\":false,\"obfuscated\":false,\"strikethrough\":false,\"extra\":[{\"text\":\" \"}],\"text\":\"\"},{\"bold\":true,\"color\":\"gold\",\"text\":\"\"},{\"bold\":true,\"color\":\"gold\",\"text\":\"LEGENDARY DUNGEON BOW \"},{\"bold\":true,\"obfuscated\":true,\"color\":\"gold\",\"text\":\"a\"}],\"text\":\"\"}'],Name:'{\"italic\":false,\"extra\":[{\"color\":\"gold\",\"text\":\"Spiritual Juju Shortbow \"},{\"color\":\"gold\",\"text\":\"✪\"},{\"color\":\"gold\",\"text\":\"✪\"},{\"color\":\"gold\",\"text\":\"✪\"},{\"color\":\"gold\",\"text\":\"✪\"},{\"color\":\"gold\",\"text\":\"✪\"}],\"text\":\"\"}'}}}"));
+ private final ItemStack LIVID_DAGGER = ItemStackComponentizationFixer.fixUpItem(StringNbtReader.parse("{Count:1b,id:\"minecraft:iron_sword\",tag:{Damage:0,Enchantments:[{id:\"minecraft:protection\",lvl:0s}],ExtraAttributes:{dungeon_item_level:5,enchantments:{telekinesis:1,ultimate_one_for_all:1},gems:{JASPER_0:\"FLAWLESS\"},hot_potato_count:15,id:\"LIVID_DAGGER\",modifier:\"fabled\",originTag:\"UNKNOWN\",rarity_upgrades:1,timestamp:\"2/20/21 3:09 PM\",uuid:\"214333db-d71c-4080-8487-00b4666bb9a4\"},HideFlags:255,Unbreakable:1b,display:{Lore:['{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Gear Score: \"},{\"color\":\"light_purple\",\"text\":\"933 \"},{\"color\":\"dark_gray\",\"text\":\"(2389)\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Damage: \"},{\"color\":\"red\",\"text\":\"+261 \"},{\"color\":\"yellow\",\"text\":\"(+30) \"},{\"color\":\"dark_gray\",\"text\":\"(+900)\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Strength: \"},{\"color\":\"red\",\"text\":\"+183 \"},{\"color\":\"yellow\",\"text\":\"(+30) \"},{\"color\":\"blue\",\"text\":\"(+75) \"},{\"color\":\"light_purple\",\"text\":\"(+12) \"},{\"color\":\"dark_gray\",\"text\":\"(+663.75)\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Crit Chance: \"},{\"color\":\"red\",\"text\":\"+100% \"},{\"color\":\"dark_gray\",\"text\":\"(+150%)\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Crit Damage: \"},{\"color\":\"red\",\"text\":\"+105% \"},{\"color\":\"blue\",\"text\":\"(+50%) \"},{\"color\":\"dark_gray\",\"text\":\"(+375%)\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Bonus Attack Speed: \"},{\"color\":\"red\",\"text\":\"+55% \"},{\"color\":\"dark_gray\",\"text\":\"(+75%)\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"text\":\" \"},{\"color\":\"dark_purple\",\"text\":\"[\"},{\"color\":\"light_purple\",\"text\":\"❁\"},{\"color\":\"dark_purple\",\"text\":\"]\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"bold\":true,\"color\":\"light_purple\",\"text\":\"\"},{\"bold\":true,\"color\":\"light_purple\",\"text\":\"One For All I\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gold\",\"text\":\"Ability: Throw \"},{\"bold\":true,\"color\":\"yellow\",\"text\":\"RIGHT CLICK\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Throw your dagger at your\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"enemies!\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"dark_gray\",\"text\":\"Mana Cost: \"},{\"color\":\"dark_aqua\",\"text\":\"150\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"dark_gray\",\"text\":\"Cooldown: \"},{\"color\":\"green\",\"text\":\"5s\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Your Critical Hits deal \"},{\"color\":\"blue\",\"text\":\"100%\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"blue\",\"text\":\"\"},{\"color\":\"gray\",\"text\":\"more damage if you are behind\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"your target.\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"blue\",\"text\":\"Fabled Bonus\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Critical hits have a chance to\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"deal up to \"},{\"color\":\"green\",\"text\":\"15% \"},{\"color\":\"gray\",\"text\":\"extra damage.\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"bold\":true,\"obfuscated\":true,\"color\":\"light_purple\",\"text\":\"a\"},{\"text\":\"\"},{\"bold\":false,\"italic\":false,\"underlined\":false,\"obfuscated\":false,\"strikethrough\":false,\"extra\":[{\"text\":\" \"}],\"text\":\"\"},{\"bold\":true,\"color\":\"light_purple\",\"text\":\"\"},{\"bold\":true,\"color\":\"light_purple\",\"text\":\"MYTHIC DUNGEON SWORD \"},{\"bold\":true,\"obfuscated\":true,\"color\":\"light_purple\",\"text\":\"a\"}],\"text\":\"\"}'],Name:'{\"italic\":false,\"extra\":[{\"color\":\"light_purple\",\"text\":\"Fabled Livid Dagger \"},{\"color\":\"gold\",\"text\":\"✪\"},{\"color\":\"gold\",\"text\":\"✪\"},{\"color\":\"gold\",\"text\":\"✪\"},{\"color\":\"gold\",\"text\":\"✪\"},{\"color\":\"gold\",\"text\":\"✪\"}],\"text\":\"\"}'}}}"));
+ private final ItemStack MITHRIL_DRILL_1 = ItemStackComponentizationFixer.fixUpItem(StringNbtReader.parse("{Count:1b,id:\"minecraft:prismarine_shard\",tag:{Damage:21,Enchantments:[{id:\"minecraft:protection\",lvl:0s}],ExtraAttributes:{compact_blocks:97683,drill_fuel:2979,enchantments:{compact:7,efficiency:5,experience:3,fortune:3,telekinesis:1},id:\"MITHRIL_DRILL_1\",modifier:\"fleet\",originTag:\"UNKNOWN\",timestamp:\"1/30/21 5:52 AM\",uuid:\"575ce2c9-251e-4435-9020-de1a2e24b1d0\"},HideFlags:255,display:{Lore:['{\"italic\":false,\"extra\":[{\"color\":\"dark_gray\",\"text\":\"Breaking Power 5\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Damage: \"},{\"color\":\"red\",\"text\":\"+65\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Mining Speed: \"},{\"color\":\"green\",\"text\":\"+585 \"},{\"color\":\"blue\",\"text\":\"(+25)\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Mining Fortune: \"},{\"color\":\"green\",\"text\":\"+30\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Mining Wisdom: \"},{\"color\":\"green\",\"text\":\"+7\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"blue\",\"text\":\"Compact VII \"},{\"color\":\"dark_gray\",\"text\":\"97,683\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Gain \"},{\"color\":\"dark_aqua\",\"text\":\"+7☯ Mining Wisdom \"},{\"color\":\"gray\",\"text\":\"and a \"},{\"color\":\"green\",\"text\":\"0.4%\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"green\",\"text\":\"\"},{\"color\":\"gray\",\"text\":\"chance to drop an enchanted item.\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"dark_gray\",\"text\":\"150k blocks to tier up!\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"blue\",\"text\":\"Efficiency V\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Grants \"},{\"color\":\"green\",\"text\":\"+110 \"},{\"color\":\"gold\",\"text\":\"⸕ Mining Speed\"},{\"color\":\"gray\",\"text\":\".\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"blue\",\"text\":\"Experience III\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Grants a \"},{\"color\":\"green\",\"text\":\"37.5% \"},{\"color\":\"gray\",\"text\":\"chance for mobs and\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"ores to drop double experience.\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"blue\",\"text\":\"Fortune III\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Grants \"},{\"color\":\"gold\",\"text\":\"+30☘ Mining Fortune\"},{\"color\":\"gray\",\"text\":\", which\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"increases your chance for multiple\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"drops.\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Gain \"},{\"color\":\"green\",\"text\":\"+15% \"},{\"color\":\"dark_green\",\"text\":\"Mithril Powder\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"when using this Drill!\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Fuel Tank: \"},{\"color\":\"red\",\"text\":\"Not Installed\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"\"},{\"color\":\"gray\",\"text\":\"Increases fuel capacity with part\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"installed.\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Drill Engine: \"},{\"color\":\"red\",\"text\":\"Not Installed\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"\"},{\"color\":\"gray\",\"text\":\"Increases \"},{\"color\":\"gold\",\"text\":\"⸕ Mining Speed \"},{\"color\":\"gray\",\"text\":\"with part\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"installed.\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Upgrade Module: \"},{\"color\":\"red\",\"text\":\"Not Installed\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"\"},{\"color\":\"gray\",\"text\":\"Applies a passive upgrade with part\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"installed.\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Apply Drill Parts to this Drill by\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"talking to a \"},{\"color\":\"dark_green\",\"text\":\"Drill Mechanic\"},{\"color\":\"gray\",\"text\":\"!\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Fuel: \"},{\"color\":\"dark_green\",\"text\":\"2,979\"},{\"color\":\"dark_gray\",\"text\":\"/3k\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gold\",\"text\":\"Ability: Mining Speed Boost \"},{\"bold\":true,\"color\":\"yellow\",\"text\":\"RIGHT CLICK\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"Grants \"},{\"color\":\"green\",\"text\":\"+\"},{\"color\":\"green\",\"text\":\"200% \"},{\"color\":\"gold\",\"text\":\"⸕ Mining Speed \"},{\"color\":\"gray\",\"text\":\"for\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"gray\",\"text\":\"\"},{\"color\":\"green\",\"text\":\"15s\"},{\"color\":\"gray\",\"text\":\".\"}],\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"color\":\"dark_gray\",\"text\":\"Cooldown: \"},{\"color\":\"green\",\"text\":\"120s\"}],\"text\":\"\"}','{\"italic\":false,\"text\":\"\"}','{\"italic\":false,\"extra\":[{\"bold\":true,\"color\":\"blue\",\"text\":\"RARE DRILL\"}],\"text\":\"\"}'],Name:'{\"italic\":false,\"extra\":[{\"color\":\"blue\",\"text\":\"Fleet Mithril Drill SX-R226\"}],\"text\":\"\"}'}}}"));
public ItemUtilsTest() throws CommandSyntaxException {
}
@@ -25,6 +28,7 @@ public class ItemUtilsTest {
Bootstrap.initialize();
}
+ //TODO fix this
@Test
void testGetExtraAttributes() {
Assertions.assertEquals("{art_of_war_count:1,dungeon_item_level:5,enchantments:{aiming:5,chance:4,cubism:5,impaling:3,infinite_quiver:10,overload:5,piercing:1,power:6,snipe:3,telekinesis:1,ultimate_soul_eater:5},hot_potato_count:15,id:\"JUJU_SHORTBOW\",modifier:\"spiritual\",originTag:\"QUICK_CRAFTING\",rarity_upgrades:1,runes:{DRAGON:3},stats_book:54778,timestamp:1622882460000L,uuid:\"b06b8fe2-470a-43f3-b844-658472f20996\"}", ItemUtils.getExtraAttributes(JUJU_SHORTBOW).toString());
diff --git a/src/test/java/de/hysky/skyblocker/utils/datafixer/ItemStackComponentizationFixerTest.java b/src/test/java/de/hysky/skyblocker/utils/datafixer/ItemStackComponentizationFixerTest.java
new file mode 100644
index 00000000..11951c44
--- /dev/null
+++ b/src/test/java/de/hysky/skyblocker/utils/datafixer/ItemStackComponentizationFixerTest.java
@@ -0,0 +1,47 @@
+package de.hysky.skyblocker.utils.datafixer;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonElement;
+import com.mojang.serialization.JsonOps;
+
+import net.minecraft.Bootstrap;
+import net.minecraft.SharedConstants;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NbtCompound;
+import net.minecraft.nbt.StringNbtReader;
+
+public class ItemStackComponentizationFixerTest {
+ private final NbtCompound NBT = convertToNbt("{id:\"minecraft:diamond_sword\",Count:1,tag:{ExtraAttributes:{id:\"TEST\"}}}");
+ private final Gson GSON = new Gson();
+
+ @BeforeAll
+ public static void setup() {
+ SharedConstants.createGameVersion();
+ Bootstrap.initialize();
+ }
+
+ @Test
+ void testNbtConversion() {
+ Assertions.assertNotEquals(NBT, new NbtCompound());
+ }
+
+ @Test
+ void testDataFixer() {
+ ItemStack fixedStack = ItemStackComponentizationFixer.fixUpItem(NBT);
+ JsonElement stackJson = ItemStack.CODEC.encodeStart(JsonOps.INSTANCE, fixedStack).result().orElseThrow();
+
+ Assertions.assertEquals("{\"id\":\"minecraft:diamond_sword\",\"components\":{\"minecraft:custom_data\":{\"ExtraAttributes\":{\"id\":\"TEST\"}}}}", GSON.toJson(stackJson));
+ }
+
+ private static NbtCompound convertToNbt(String nbt) {
+ try {
+ return StringNbtReader.parse(nbt);
+ } catch (Exception e) {
+ return new NbtCompound();
+ }
+ }
+}