diff --git a/src/main/java/de/hysky/skyblocker/SkyblockerMod.java b/src/main/java/de/hysky/skyblocker/SkyblockerMod.java index 3336cefb75..8d0e0a1108 100644 --- a/src/main/java/de/hysky/skyblocker/SkyblockerMod.java +++ b/src/main/java/de/hysky/skyblocker/SkyblockerMod.java @@ -3,6 +3,7 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import de.hysky.skyblocker.config.datafixer.ConfigDataFixer; import de.hysky.skyblocker.config.ImageRepoLoader; import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.debug.Debug; @@ -101,6 +102,7 @@ public static SkyblockerMod getInstance() { @Override public void onInitializeClient() { ClientTickEvents.END_CLIENT_TICK.register(this::tick); + ConfigDataFixer.apply(); Utils.init(); SkyblockerConfigManager.init(); SkyblockerScreen.initClass(); diff --git a/src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java b/src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java index c591ba14ab..b7a711abf1 100644 --- a/src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java +++ b/src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java @@ -5,7 +5,7 @@ public class SkyblockerConfig { @SerialEntry - public int version = 2; + public int version = SkyblockerConfigManager.CONFIG_VERSION; @SerialEntry public GeneralConfig general = new GeneralConfig(); diff --git a/src/main/java/de/hysky/skyblocker/config/SkyblockerConfigManager.java b/src/main/java/de/hysky/skyblocker/config/SkyblockerConfigManager.java index 4b8e56df6b..688b85aa11 100644 --- a/src/main/java/de/hysky/skyblocker/config/SkyblockerConfigManager.java +++ b/src/main/java/de/hysky/skyblocker/config/SkyblockerConfigManager.java @@ -26,10 +26,11 @@ import java.nio.file.Path; public class SkyblockerConfigManager { - private static final Path PATH = FabricLoader.getInstance().getConfigDir().resolve("skyblocker-2.json"); + public static final int CONFIG_VERSION = 2; + private static final Path CONFIG_FILE = FabricLoader.getInstance().getConfigDir().resolve("skyblocker.json"); private static final ConfigClassHandler HANDLER = ConfigClassHandler.createBuilder(SkyblockerConfig.class) .serializer(config -> GsonConfigSerializerBuilder.create(config) - .setPath(PATH) + .setPath(CONFIG_FILE) .setJson5(false) .appendGsonBuilder(builder -> builder .setFieldNamingPolicy(FieldNamingPolicy.IDENTITY) diff --git a/src/main/java/de/hysky/skyblocker/config/categories/QuickNavigationCategory.java b/src/main/java/de/hysky/skyblocker/config/categories/QuickNavigationCategory.java index 1200261d81..64c6741704 100644 --- a/src/main/java/de/hysky/skyblocker/config/categories/QuickNavigationCategory.java +++ b/src/main/java/de/hysky/skyblocker/config/categories/QuickNavigationCategory.java @@ -48,14 +48,14 @@ public static ConfigCategory create(SkyblockerConfig defaults, SkyblockerConfig .binding(defaults.quickNav.button1.item.count, () -> config.quickNav.button1.item.count, newValue -> config.quickNav.button1.item.count = newValue) - .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 64)) + .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 99)) .build()) .option(Option.createBuilder() - .name(Text.translatable("skyblocker.config.quickNav.button.item.nbt")) - .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.nbt.@Tooltip"))) - .binding(defaults.quickNav.button1.item.nbt, - () -> config.quickNav.button1.item.nbt, - newValue -> config.quickNav.button1.item.nbt = newValue) + .name(Text.translatable("skyblocker.config.quickNav.button.item.components")) + .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.components.@Tooltip"))) + .binding(defaults.quickNav.button1.item.components, + () -> config.quickNav.button1.item.components, + newValue -> config.quickNav.button1.item.components = newValue) .controller(StringControllerBuilder::create) .build()) .option(Option.createBuilder() @@ -97,14 +97,14 @@ public static ConfigCategory create(SkyblockerConfig defaults, SkyblockerConfig .binding(defaults.quickNav.button2.item.count, () -> config.quickNav.button2.item.count, newValue -> config.quickNav.button2.item.count = newValue) - .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 64)) + .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 99)) .build()) .option(Option.createBuilder() - .name(Text.translatable("skyblocker.config.quickNav.button.item.nbt")) - .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.nbt.@Tooltip"))) - .binding(defaults.quickNav.button2.item.nbt, - () -> config.quickNav.button2.item.nbt, - newValue -> config.quickNav.button2.item.nbt = newValue) + .name(Text.translatable("skyblocker.config.quickNav.button.item.components")) + .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.components.@Tooltip"))) + .binding(defaults.quickNav.button2.item.components, + () -> config.quickNav.button2.item.components, + newValue -> config.quickNav.button2.item.components = newValue) .controller(StringControllerBuilder::create) .build()) .option(Option.createBuilder() @@ -146,14 +146,14 @@ public static ConfigCategory create(SkyblockerConfig defaults, SkyblockerConfig .binding(defaults.quickNav.button3.item.count, () -> config.quickNav.button3.item.count, newValue -> config.quickNav.button3.item.count = newValue) - .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 64)) + .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 99)) .build()) .option(Option.createBuilder() - .name(Text.translatable("skyblocker.config.quickNav.button.item.nbt")) - .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.nbt.@Tooltip"))) - .binding(defaults.quickNav.button3.item.nbt, - () -> config.quickNav.button3.item.nbt, - newValue -> config.quickNav.button3.item.nbt = newValue) + .name(Text.translatable("skyblocker.config.quickNav.button.item.components")) + .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.components.@Tooltip"))) + .binding(defaults.quickNav.button3.item.components, + () -> config.quickNav.button3.item.components, + newValue -> config.quickNav.button3.item.components = newValue) .controller(StringControllerBuilder::create) .build()) .option(Option.createBuilder() @@ -195,14 +195,14 @@ public static ConfigCategory create(SkyblockerConfig defaults, SkyblockerConfig .binding(defaults.quickNav.button4.item.count, () -> config.quickNav.button4.item.count, newValue -> config.quickNav.button4.item.count = newValue) - .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 64)) + .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 99)) .build()) .option(Option.createBuilder() - .name(Text.translatable("skyblocker.config.quickNav.button.item.nbt")) - .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.nbt.@Tooltip"))) - .binding(defaults.quickNav.button4.item.nbt, - () -> config.quickNav.button4.item.nbt, - newValue -> config.quickNav.button4.item.nbt = newValue) + .name(Text.translatable("skyblocker.config.quickNav.button.item.components")) + .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.components.@Tooltip"))) + .binding(defaults.quickNav.button4.item.components, + () -> config.quickNav.button4.item.components, + newValue -> config.quickNav.button4.item.components = newValue) .controller(StringControllerBuilder::create) .build()) .option(Option.createBuilder() @@ -244,14 +244,14 @@ public static ConfigCategory create(SkyblockerConfig defaults, SkyblockerConfig .binding(defaults.quickNav.button5.item.count, () -> config.quickNav.button5.item.count, newValue -> config.quickNav.button5.item.count = newValue) - .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 64)) + .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 99)) .build()) .option(Option.createBuilder() - .name(Text.translatable("skyblocker.config.quickNav.button.item.nbt")) - .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.nbt.@Tooltip"))) - .binding(defaults.quickNav.button5.item.nbt, - () -> config.quickNav.button5.item.nbt, - newValue -> config.quickNav.button5.item.nbt = newValue) + .name(Text.translatable("skyblocker.config.quickNav.button.item.components")) + .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.components.@Tooltip"))) + .binding(defaults.quickNav.button5.item.components, + () -> config.quickNav.button5.item.components, + newValue -> config.quickNav.button5.item.components = newValue) .controller(StringControllerBuilder::create) .build()) .option(Option.createBuilder() @@ -293,14 +293,14 @@ public static ConfigCategory create(SkyblockerConfig defaults, SkyblockerConfig .binding(defaults.quickNav.button6.item.count, () -> config.quickNav.button6.item.count, newValue -> config.quickNav.button6.item.count = newValue) - .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 64)) + .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 99)) .build()) .option(Option.createBuilder() - .name(Text.translatable("skyblocker.config.quickNav.button.item.nbt")) - .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.nbt.@Tooltip"))) - .binding(defaults.quickNav.button6.item.nbt, - () -> config.quickNav.button6.item.nbt, - newValue -> config.quickNav.button6.item.nbt = newValue) + .name(Text.translatable("skyblocker.config.quickNav.button.item.components")) + .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.components.@Tooltip"))) + .binding(defaults.quickNav.button6.item.components, + () -> config.quickNav.button6.item.components, + newValue -> config.quickNav.button6.item.components = newValue) .controller(StringControllerBuilder::create) .build()) .option(Option.createBuilder() @@ -342,14 +342,14 @@ public static ConfigCategory create(SkyblockerConfig defaults, SkyblockerConfig .binding(defaults.quickNav.button7.item.count, () -> config.quickNav.button7.item.count, newValue -> config.quickNav.button7.item.count = newValue) - .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 64)) + .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 99)) .build()) .option(Option.createBuilder() - .name(Text.translatable("skyblocker.config.quickNav.button.item.nbt")) - .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.nbt.@Tooltip"))) - .binding(defaults.quickNav.button7.item.nbt, - () -> config.quickNav.button7.item.nbt, - newValue -> config.quickNav.button7.item.nbt = newValue) + .name(Text.translatable("skyblocker.config.quickNav.button.item.components")) + .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.components.@Tooltip"))) + .binding(defaults.quickNav.button7.item.components, + () -> config.quickNav.button7.item.components, + newValue -> config.quickNav.button7.item.components = newValue) .controller(StringControllerBuilder::create) .build()) .option(Option.createBuilder() @@ -391,14 +391,14 @@ public static ConfigCategory create(SkyblockerConfig defaults, SkyblockerConfig .binding(defaults.quickNav.button8.item.count, () -> config.quickNav.button8.item.count, newValue -> config.quickNav.button8.item.count = newValue) - .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 64)) + .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 99)) .build()) .option(Option.createBuilder() - .name(Text.translatable("skyblocker.config.quickNav.button.item.nbt")) - .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.nbt.@Tooltip"))) - .binding(defaults.quickNav.button8.item.nbt, - () -> config.quickNav.button8.item.nbt, - newValue -> config.quickNav.button8.item.nbt = newValue) + .name(Text.translatable("skyblocker.config.quickNav.button.item.components")) + .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.components.@Tooltip"))) + .binding(defaults.quickNav.button8.item.components, + () -> config.quickNav.button8.item.components, + newValue -> config.quickNav.button8.item.components = newValue) .controller(StringControllerBuilder::create) .build()) .option(Option.createBuilder() @@ -440,14 +440,14 @@ public static ConfigCategory create(SkyblockerConfig defaults, SkyblockerConfig .binding(defaults.quickNav.button9.item.count, () -> config.quickNav.button9.item.count, newValue -> config.quickNav.button9.item.count = newValue) - .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 64)) + .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 99)) .build()) .option(Option.createBuilder() - .name(Text.translatable("skyblocker.config.quickNav.button.item.nbt")) - .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.nbt.@Tooltip"))) - .binding(defaults.quickNav.button9.item.nbt, - () -> config.quickNav.button9.item.nbt, - newValue -> config.quickNav.button9.item.nbt = newValue) + .name(Text.translatable("skyblocker.config.quickNav.button.item.components")) + .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.components.@Tooltip"))) + .binding(defaults.quickNav.button9.item.components, + () -> config.quickNav.button9.item.components, + newValue -> config.quickNav.button9.item.components = newValue) .controller(StringControllerBuilder::create) .build()) .option(Option.createBuilder() @@ -489,14 +489,14 @@ public static ConfigCategory create(SkyblockerConfig defaults, SkyblockerConfig .binding(defaults.quickNav.button10.item.count, () -> config.quickNav.button10.item.count, newValue -> config.quickNav.button10.item.count = newValue) - .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 64)) + .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 99)) .build()) .option(Option.createBuilder() - .name(Text.translatable("skyblocker.config.quickNav.button.item.nbt")) - .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.nbt.@Tooltip"))) - .binding(defaults.quickNav.button10.item.nbt, - () -> config.quickNav.button10.item.nbt, - newValue -> config.quickNav.button10.item.nbt = newValue) + .name(Text.translatable("skyblocker.config.quickNav.button.item.components")) + .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.components.@Tooltip"))) + .binding(defaults.quickNav.button10.item.components, + () -> config.quickNav.button10.item.components, + newValue -> config.quickNav.button10.item.components = newValue) .controller(StringControllerBuilder::create) .build()) .option(Option.createBuilder() @@ -538,14 +538,14 @@ public static ConfigCategory create(SkyblockerConfig defaults, SkyblockerConfig .binding(defaults.quickNav.button11.item.count, () -> config.quickNav.button11.item.count, newValue -> config.quickNav.button11.item.count = newValue) - .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 64)) + .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 99)) .build()) .option(Option.createBuilder() - .name(Text.translatable("skyblocker.config.quickNav.button.item.nbt")) - .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.nbt.@Tooltip"))) - .binding(defaults.quickNav.button11.item.nbt, - () -> config.quickNav.button11.item.nbt, - newValue -> config.quickNav.button11.item.nbt = newValue) + .name(Text.translatable("skyblocker.config.quickNav.button.item.components")) + .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.components.@Tooltip"))) + .binding(defaults.quickNav.button11.item.components, + () -> config.quickNav.button11.item.components, + newValue -> config.quickNav.button11.item.components = newValue) .controller(StringControllerBuilder::create) .build()) .option(Option.createBuilder() @@ -587,14 +587,14 @@ public static ConfigCategory create(SkyblockerConfig defaults, SkyblockerConfig .binding(defaults.quickNav.button12.item.count, () -> config.quickNav.button12.item.count, newValue -> config.quickNav.button12.item.count = newValue) - .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 64)) + .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 99)) .build()) .option(Option.createBuilder() - .name(Text.translatable("skyblocker.config.quickNav.button.item.nbt")) - .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.nbt.@Tooltip"))) - .binding(defaults.quickNav.button12.item.nbt, - () -> config.quickNav.button12.item.nbt, - newValue -> config.quickNav.button12.item.nbt = newValue) + .name(Text.translatable("skyblocker.config.quickNav.button.item.components")) + .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.components.@Tooltip"))) + .binding(defaults.quickNav.button12.item.components, + () -> config.quickNav.button12.item.components, + newValue -> config.quickNav.button12.item.components = newValue) .controller(StringControllerBuilder::create) .build()) .option(Option.createBuilder() diff --git a/src/main/java/de/hysky/skyblocker/config/configs/QuickNavigationConfig.java b/src/main/java/de/hysky/skyblocker/config/configs/QuickNavigationConfig.java index 2c4347b657..ba863e33c7 100644 --- a/src/main/java/de/hysky/skyblocker/config/configs/QuickNavigationConfig.java +++ b/src/main/java/de/hysky/skyblocker/config/configs/QuickNavigationConfig.java @@ -25,12 +25,12 @@ public class QuickNavigationConfig { */ @SerialEntry public QuickNavItem button4 = new QuickNavItem(true, - new ItemData("leather_chestplate", 1, "tag:{display:{color:8991416}}"), "Wardrobe \\([12]/2\\)", + new ItemData("leather_chestplate", 1, "[minecraft:dyed_color={rgb:8991416}]"), "Wardrobe \\([12]/2\\)", "/wardrobe"); @SerialEntry public QuickNavItem button5 = new QuickNavItem(true, new ItemData("player_head", 1, - "tag:{SkullOwner:{Id:[I;-2081424676,-57521078,-2073572414,158072763],Properties:{textures:[{Value:\"ewogICJ0aW1lc3RhbXAiIDogMTU5MTMxMDU4NTYwOSwKICAicHJvZmlsZUlkIiA6ICI0MWQzYWJjMmQ3NDk0MDBjOTA5MGQ1NDM0ZDAzODMxYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNZWdha2xvb24iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODBhMDc3ZTI0OGQxNDI3NzJlYTgwMDg2NGY4YzU3OGI5ZDM2ODg1YjI5ZGFmODM2YjY0YTcwNjg4MmI2ZWMxMCIKICAgIH0KICB9Cn0=\"}]}}}"), + "[minecraft:profile={id:[I;-2081424676,-57521078,-2073572414,158072763],name:\"\",properties:[{name:\"textures\",value:\"ewogICJ0aW1lc3RhbXAiIDogMTU5MTMxMDU4NTYwOSwKICAicHJvZmlsZUlkIiA6ICI0MWQzYWJjMmQ3NDk0MDBjOTA5MGQ1NDM0ZDAzODMxYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNZWdha2xvb24iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODBhMDc3ZTI0OGQxNDI3NzJlYTgwMDg2NGY4YzU3OGI5ZDM2ODg1YjI5ZGFmODM2YjY0YTcwNjg4MmI2ZWMxMCIKICAgIH0KICB9Cn0=\"}]}]"), "Sack of Sacks", "/sacks"); /* REGEX Explanation @@ -44,17 +44,17 @@ public class QuickNavigationConfig { @SerialEntry public QuickNavItem button7 = new QuickNavItem(true, new ItemData("player_head", 1, - "tag:{SkullOwner:{Id:[I;-300151517,-631415889,-1193921967,-1821784279],Properties:{textures:[{Value:\"e3RleHR1cmVzOntTS0lOOnt1cmw6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDdjYzY2ODc0MjNkMDU3MGQ1NTZhYzUzZTA2NzZjYjU2M2JiZGQ5NzE3Y2Q4MjY5YmRlYmVkNmY2ZDRlN2JmOCJ9fX0=\"}]}}}"), + "[minecraft:profile={id:[I;-300151517,-631415889,-1193921967,-1821784279],name:\"\",properties:[{name:\"textures\",value:\"e3RleHR1cmVzOntTS0lOOnt1cmw6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDdjYzY2ODc0MjNkMDU3MGQ1NTZhYzUzZTA2NzZjYjU2M2JiZGQ5NzE3Y2Q4MjY5YmRlYmVkNmY2ZDRlN2JmOCJ9fX0=\"}]}]"), "none", "/hub"); @SerialEntry public QuickNavItem button8 = new QuickNavItem(true, new ItemData("player_head", 1, - "tag:{SkullOwner:{Id:[I;1605800870,415127827,-1236127084,15358548],Properties:{textures:[{Value:\"e3RleHR1cmVzOntTS0lOOnt1cmw6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzg5MWQ1YjI3M2ZmMGJjNTBjOTYwYjJjZDg2ZWVmMWM0MGExYjk0MDMyYWU3MWU3NTQ3NWE1NjhhODI1NzQyMSJ9fX0=\"}]}}}"), + "[minecraft:profile={id:[I;1605800870,415127827,-1236127084,15358548],name:\"\",properties:[{name:\"textures\",value:\"e3RleHR1cmVzOntTS0lOOnt1cmw6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzg5MWQ1YjI3M2ZmMGJjNTBjOTYwYjJjZDg2ZWVmMWM0MGExYjk0MDMyYWU3MWU3NTQ3NWE1NjhhODI1NzQyMSJ9fX0=\"}]}]"), "none", "/warp dungeon_hub"); @SerialEntry public QuickNavItem button9 = new QuickNavItem(true, new ItemData("player_head", 1, - "tag:{SkullOwner:{Id:[I;-562285948,532499670,-1705302742,775653035],Properties:{textures:[{Value:\"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjVkZjU1NTkyNjQzMGQ1ZDc1YWRlZDIxZGQ5NjE5Yjc2YzViN2NhMmM3ZjU0MDE0NDA1MjNkNTNhOGJjZmFhYiJ9fX0=\"}]}}}"), + "[minecraft:profile={id:[I;-562285948,532499670,-1705302742,775653035],name:\"\",properties:[{name:\"textures\",value:\"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjVkZjU1NTkyNjQzMGQ1ZDc1YWRlZDIxZGQ5NjE5Yjc2YzViN2NhMmM3ZjU0MDE0NDA1MjNkNTNhOGJjZmFhYiJ9fX0=\"}]}]"), "Visit prtl", "/visit prtl"); @SerialEntry @@ -68,73 +68,6 @@ public class QuickNavigationConfig { @SerialEntry public QuickNavItem button12 = new QuickNavItem(true, new ItemData("crafting_table"), "Craft Item", "/craft"); - public static class QuickNav { - @SerialEntry - public boolean enableQuickNav = true; - - @SerialEntry - public QuickNavItem button1 = new QuickNavItem(true, new ItemData("diamond_sword"), "Your Skills", "/skills"); - - @SerialEntry - public QuickNavItem button2 = new QuickNavItem(true, new ItemData("painting"), "Collections", "/collection"); - - /* REGEX Explanation - * "Pets" : simple match on letters - * "(?: \\(\\d+\\/\\d+\\))?" : optional match on the non-capturing group for the page in the format " ($number/$number)" - */ - @SerialEntry - public QuickNavItem button3 = new QuickNavItem(true, new ItemData("bone"), "Pets(:? \\(\\d+\\/\\d+\\))?", "/pets"); - - /* REGEX Explanation - * "Wardrobe" : simple match on letters - * " \\([12]\\/2\\)" : match on the page either " (1/2)" or " (2/2)" - */ - @SerialEntry - public QuickNavItem button4 = new QuickNavItem(true, - new ItemData("leather_chestplate", 1, "tag:{display:{color:8991416}}"), "Wardrobe \\([12]/2\\)", - "/wardrobe"); - - @SerialEntry - public QuickNavItem button5 = new QuickNavItem(true, new ItemData("player_head", 1, - "tag:{SkullOwner:{Id:[I;-2081424676,-57521078,-2073572414,158072763],Properties:{textures:[{Value:\"ewogICJ0aW1lc3RhbXAiIDogMTU5MTMxMDU4NTYwOSwKICAicHJvZmlsZUlkIiA6ICI0MWQzYWJjMmQ3NDk0MDBjOTA5MGQ1NDM0ZDAzODMxYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNZWdha2xvb24iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODBhMDc3ZTI0OGQxNDI3NzJlYTgwMDg2NGY4YzU3OGI5ZDM2ODg1YjI5ZGFmODM2YjY0YTcwNjg4MmI2ZWMxMCIKICAgIH0KICB9Cn0=\"}]}}}"), - "Sack of Sacks", "/sacks"); - - /* REGEX Explanation - * "(?:Rift )?" : optional match on the non-capturing group "Rift " - * "Storage" : simple match on letters - * "(?: \\([12]\\/2\\))?" : optional match on the non-capturing group " (1/2)" or " (2/2)" - */ - @SerialEntry - public QuickNavItem button6 = new QuickNavItem(true, new ItemData("ender_chest"), - "(?:Rift )?Storage(?: \\(1/2\\))?", "/storage"); - - @SerialEntry - public QuickNavItem button7 = new QuickNavItem(true, new ItemData("player_head", 1, - "tag:{SkullOwner:{Id:[I;-300151517,-631415889,-1193921967,-1821784279],Properties:{textures:[{Value:\"e3RleHR1cmVzOntTS0lOOnt1cmw6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDdjYzY2ODc0MjNkMDU3MGQ1NTZhYzUzZTA2NzZjYjU2M2JiZGQ5NzE3Y2Q4MjY5YmRlYmVkNmY2ZDRlN2JmOCJ9fX0=\"}]}}}"), - "none", "/hub"); - - @SerialEntry - public QuickNavItem button8 = new QuickNavItem(true, new ItemData("player_head", 1, - "tag:{SkullOwner:{Id:[I;1605800870,415127827,-1236127084,15358548],Properties:{textures:[{Value:\"e3RleHR1cmVzOntTS0lOOnt1cmw6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzg5MWQ1YjI3M2ZmMGJjNTBjOTYwYjJjZDg2ZWVmMWM0MGExYjk0MDMyYWU3MWU3NTQ3NWE1NjhhODI1NzQyMSJ9fX0=\"}]}}}"), - "none", "/warp dungeon_hub"); - - @SerialEntry - public QuickNavItem button9 = new QuickNavItem(true, new ItemData("player_head", 1, - "tag:{SkullOwner:{Id:[I;-562285948,532499670,-1705302742,775653035],Properties:{textures:[{Value:\"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjVkZjU1NTkyNjQzMGQ1ZDc1YWRlZDIxZGQ5NjE5Yjc2YzViN2NhMmM3ZjU0MDE0NDA1MjNkNTNhOGJjZmFhYiJ9fX0=\"}]}}}"), - "Visit prtl", "/visit prtl"); - - @SerialEntry - public QuickNavItem button10 = new QuickNavItem(true, new ItemData("enchanting_table"), "Enchant Item", - "/etable"); - - - @SerialEntry - public QuickNavItem button11 = new QuickNavItem(true, new ItemData("anvil"), "Anvil", "/anvil"); - - @SerialEntry - public QuickNavItem button12 = new QuickNavItem(true, new ItemData("crafting_table"), "Craft Item", "/craft"); - } - public static class QuickNavItem { public QuickNavItem(Boolean render, ItemData itemData, String uiTitle, String clickEvent) { this.render = render; @@ -157,16 +90,16 @@ public QuickNavItem(Boolean render, ItemData itemData, String uiTitle, String cl } public static class ItemData { - public ItemData(String id, int count, String nbt) { + public ItemData(String id, int count, String components) { this.id = id; this.count = count; - this.nbt = nbt; + this.components = components; } public ItemData(String id) { this.id = id; this.count = 1; - this.nbt = ""; + this.components = "[]"; } @SerialEntry @@ -176,6 +109,6 @@ public ItemData(String id) { public int count; @SerialEntry - public String nbt; + public String components; } } diff --git a/src/main/java/de/hysky/skyblocker/config/datafixer/ConfigDataFixer.java b/src/main/java/de/hysky/skyblocker/config/datafixer/ConfigDataFixer.java new file mode 100644 index 0000000000..97261c76a5 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/config/datafixer/ConfigDataFixer.java @@ -0,0 +1,90 @@ +package de.hysky.skyblocker.config.datafixer; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.mojang.datafixers.DSL; +import com.mojang.datafixers.DataFixer; +import com.mojang.datafixers.DataFixerBuilder; +import com.mojang.datafixers.schemas.Schema; +import com.mojang.logging.LogUtils; +import com.mojang.serialization.Dynamic; +import com.mojang.serialization.JsonOps; +import de.hysky.skyblocker.SkyblockerMod; +import de.hysky.skyblocker.config.SkyblockerConfigManager; +import de.hysky.skyblocker.utils.datafixer.JsonHelper; +import net.fabricmc.loader.api.FabricLoader; +import org.slf4j.Logger; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.nio.file.Files; +import java.nio.file.Path; + +public class ConfigDataFixer { + protected static final Logger LOGGER = LogUtils.getLogger(); + private static final Path CONFIG_DIR = FabricLoader.getInstance().getConfigDir(); + public static final DSL.TypeReference CONFIG_TYPE = () -> "config"; + + public static void apply() { + apply(CONFIG_DIR.resolve("skyblocker.json"), CONFIG_DIR.resolve("skyblocker.json.old")); + } + + public static void apply(Path configDir, Path backupDir) { + //User is new - has no config file (or maybe config folder) + if (!Files.exists(CONFIG_DIR) || !Files.exists(configDir)) return; + + //Should never be null if the file exists unless its malformed JSON or something in which case well it gets reset + JsonObject oldConfig = loadConfig(configDir); + if (oldConfig == null || JsonHelper.getInt(oldConfig, "version").orElse(1) == SkyblockerConfigManager.CONFIG_VERSION) return; + + JsonObject newConfig = apply(oldConfig); + + //Write the updated file + if (!writeConfig(configDir, newConfig)) { + LOGGER.error(LogUtils.FATAL_MARKER, "[Skyblocker Config Data Fixer] Failed to fix up config file!"); + writeConfig(backupDir, oldConfig); + } + } + + public static JsonObject apply(JsonObject oldConfig) { + long start = System.currentTimeMillis(); + + JsonObject newConfig = build().update(CONFIG_TYPE, new Dynamic<>(JsonOps.INSTANCE, oldConfig), JsonHelper.getInt(oldConfig, "version").orElse(1), SkyblockerConfigManager.CONFIG_VERSION).getValue().getAsJsonObject(); + + long end = System.currentTimeMillis(); + LOGGER.info("[Skyblocker Config Data Fixer] Applied datafixers in {} ms!", end - start); + return newConfig; + } + + private static DataFixer build() { + DataFixerBuilder builder = new DataFixerBuilder(SkyblockerConfigManager.CONFIG_VERSION); + + builder.addSchema(1, ConfigSchema::new); + Schema schema2 = builder.addSchema(2, Schema::new); + builder.addFixer(new ConfigFix1(schema2, true)); + + return builder.buildUnoptimized(); + } + + private static JsonObject loadConfig(Path path) { + try (BufferedReader reader = Files.newBufferedReader(path)) { + return JsonParser.parseReader(reader).getAsJsonObject(); + } catch (Throwable t) { + LOGGER.error("[Skyblocker Config Data Fixer] Failed to load config file!", t); + } + + return null; + } + + private static boolean writeConfig(Path path, JsonObject config) { + try (BufferedWriter writer = Files.newBufferedWriter(path)) { + SkyblockerMod.GSON.toJson(config, writer); + + return true; + } catch (Throwable t) { + LOGGER.error("[Skyblocker Config Data Fixer] Failed to save config file at {}!", path, t); + } + + return false; + } +} diff --git a/src/main/java/de/hysky/skyblocker/config/datafixer/ConfigFix1.java b/src/main/java/de/hysky/skyblocker/config/datafixer/ConfigFix1.java new file mode 100644 index 0000000000..405a278150 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/config/datafixer/ConfigFix1.java @@ -0,0 +1,227 @@ +package de.hysky.skyblocker.config.datafixer; + +import com.mojang.datafixers.DSL; +import com.mojang.datafixers.DataFix; +import com.mojang.datafixers.DataFixUtils; +import com.mojang.datafixers.TypeRewriteRule; +import com.mojang.datafixers.schemas.Schema; +import com.mojang.logging.LogUtils; +import com.mojang.serialization.Dynamic; +import com.mojang.serialization.OptionalDynamic; +import de.hysky.skyblocker.utils.datafixer.ItemStackComponentizationFixer; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.StringNbtReader; + +import java.util.Locale; + +public class ConfigFix1 extends DataFix { + public ConfigFix1(Schema outputSchema, boolean changesType) { + super(outputSchema, changesType); + } + + @Override + protected TypeRewriteRule makeRule() { + return fixTypeEverywhereTyped( + "ConfigFix1", + getInputSchema().getType(ConfigDataFixer.CONFIG_TYPE), + typed -> typed.update(DSL.remainderFinder(), this::fix) + ); + } + + private Dynamic fix(Dynamic dynamic) { + return fixMisc(fixQuickNav(fixChat(fixSlayers(fixOtherLocations(fixFarming(fixMining(fixCrimsonIsle(fixDungeons(fixHelpers(fixUIAndVisuals(fixGeneral(fixVersion(dynamic))))))))))))); + } + + private Dynamic fixVersion(Dynamic dynamic) { + return dynamic.set("version", dynamic.createInt(DataFixUtils.getVersion(getVersionKey()))); + } + + private static Dynamic fixGeneral(Dynamic dynamic) { + return dynamic.update("general", general -> general.update("itemTooltip", itemTooltip -> itemTooltip.setFieldIfPresent("dungeonQuality", general.get("dungeonQuality").result())).remove("dungeonQuality")); + } + + private static Dynamic fixUIAndVisuals(Dynamic dynamic) { + OptionalDynamic general = dynamic.get("general"); + return dynamic.set("uiAndVisuals", dynamic.emptyMap() + .setFieldIfPresent("compactorDeletorPreview", general.get("compactorDeletorPreview").result()) + .setFieldIfPresent("dontStripSkinAlphaValues", general.get("dontStripSkinAlphaValues").result()) + .setFieldIfPresent("backpackPreviewWithoutShift", general.get("backpackPreviewWithoutShift").result()) + .setFieldIfPresent("hideEmptyTooltips", general.get("hideEmptyTooltips").result()) + .setFieldIfPresent("fancyCraftingTable", general.get("fancyCraftingTable").result()) + .setFieldIfPresent("hideStatusEffectOverlay", general.get("hideStatusEffectOverlay").result()) + .setFieldIfPresent("chestValue", general.get("chestValue").result()) + .setFieldIfPresent("itemCooldown", general.get("itemCooldown").result()) + .setFieldIfPresent("titleContainer", general.get("titleContainer").result()) + .setFieldIfPresent("tabHud", general.get("tabHud").result()) + .setFieldIfPresent("fancyAuctionHouse", general.get("fancyAuctionHouse").result()) + .setFieldIfPresent("bars", general.get("bars").result()) + .setFieldIfPresent("waypoints", general.get("waypoints").result()) + .setFieldIfPresent("teleportOverlay", general.get("teleportOverlay").result()) + .setFieldIfPresent("searchOverlay", general.get("searchOverlay").result()) + .setFieldIfPresent("flameOverlay", general.get("flameOverlay").result()) + ).update("general", newGeneral -> newGeneral + .remove("compactorDeletorPreview") + .remove("dontStripSkinAlphaValues") + .remove("backpackPreviewWithoutShift") + .remove("hideEmptyTooltips") + .remove("fancyCraftingTable") + .remove("hideStatusEffectOverlay") + .remove("chestValue") + .remove("itemCooldown") + .remove("titleContainer") + .remove("tabHud") + .remove("fancyAuctionHouse") + .remove("bars") + .remove("waypoints") + .remove("teleportOverlay") + .remove("searchOverlay") + .remove("flameOverlay") + ); + } + + private static Dynamic fixHelpers(Dynamic dynamic) { + OptionalDynamic general = dynamic.get("general"); + return dynamic.set("helpers", dynamic.emptyMap() + .setFieldIfPresent("enableNewYearCakesHelper", general.get("enableNewYearCakesHelper").result()) + .setFieldIfPresent("mythologicalRitual", general.get("mythologicalRitual").result()) + .setFieldIfPresent("experiments", general.get("experiments").result()) + .setFieldIfPresent("fishing", general.get("fishing").result()) + .setFieldIfPresent("fairySouls", general.get("fairySouls").result()) + ).update("general", newGeneral -> newGeneral + .remove("enableNewYearCakesHelper") + .remove("mythologicalRitual") + .remove("experiments") + .remove("fishing") + .remove("fairySouls") + ); + } + + private static Dynamic fixDungeons(Dynamic dynamic) { + OptionalDynamic general = dynamic.get("general"); + OptionalDynamic dungeons = dynamic.get("locations").get("dungeons"); + return dynamic.set("dungeons", dynamic.emptyMap() + .setFieldIfPresent("fancyPartyFinder", general.get("betterPartyFinder").result()) + .setFieldIfPresent("croesusHelper", dungeons.get("croesusHelper").result()) + .setFieldIfPresent("playerSecretsTracker", dungeons.get("playerSecretsTracker").result()) + .setFieldIfPresent("starredMobGlow", dungeons.get("starredMobGlow").result()) + .setFieldIfPresent("starredMobBoundingBoxes", dungeons.get("starredMobBoundingBoxes").result()) + .setFieldIfPresent("allowDroppingProtectedItems", dungeons.get("allowDroppingProtectedItems").result()) + .set("dungeonMap", dynamic.emptyMap() + .setFieldIfPresent("enableMap", dungeons.get("enableMap").result()) + .setFieldIfPresent("mapScaling", dungeons.get("mapScaling").result()) + .setFieldIfPresent("mapX", dungeons.get("mapX").result()) + .setFieldIfPresent("mapY", dungeons.get("mapY").result()) + ) + .set("puzzleSolvers", dynamic.emptyMap() + .setFieldIfPresent("solveThreeWeirdos", dungeons.get("solveThreeWeirdos").result()) + .setFieldIfPresent("blazeSolver", dungeons.get("blazeSolver").result()) + .setFieldIfPresent("creeperSolver", dungeons.get("creeperSolver").result()) + .setFieldIfPresent("solveTrivia", dungeons.get("solveTrivia").result()) + .setFieldIfPresent("solveTicTacToe", dungeons.get("solveTicTacToe").result()) + .setFieldIfPresent("solveWaterboard", dungeons.get("solveWaterboard").result()) + .setFieldIfPresent("solveBoulder", dungeons.get("solveBoulder").result()) + .setFieldIfPresent("solveIceFill", dungeons.get("solveIceFill").result()) + .setFieldIfPresent("solveSilverfish", dungeons.get("solveSilverfish").result()) + ) + .set("theProfessor", dynamic.emptyMap() + .setFieldIfPresent("fireFreezeStaffTimer", dungeons.get("fireFreezeStaffTimer").result()) + .setFieldIfPresent("floor3GuardianHealthDisplay", dungeons.get("floor3GuardianHealthDisplay").result()) + ) + .setFieldIfPresent("livid", dungeons.get("lividColor").result()) + .setFieldIfPresent("terminals", dungeons.get("terminals").result()) + .setFieldIfPresent("secretWaypoints", dungeons.get("secretWaypoints").result()) + .setFieldIfPresent("mimicMessage", dungeons.get("mimicMessage").result()) + .setFieldIfPresent("doorHighlight", dungeons.get("doorHighlight").result()) + .setFieldIfPresent("dungeonScore", dungeons.get("dungeonScore").result()) + .setFieldIfPresent("dungeonChestProfit", dungeons.get("dungeonChestProfit").result()) + ).update("locations", locations -> locations.remove("dungeons")).update("general", newGeneral -> newGeneral.remove("betterPartyFinder")); + } + + private static Dynamic fixCrimsonIsle(Dynamic dynamic) { + return dynamic.setFieldIfPresent("crimsonIsle", dynamic.get("locations").get("crimsonIsle").result()).update("locations", locations -> locations.remove("crimsonIsle")); + } + + private static Dynamic fixMining(Dynamic dynamic) { + OptionalDynamic dwarvenMines = dynamic.get("locations").get("dwarvenMines"); + return dynamic.set("mining", dynamic.emptyMap() + .setFieldIfPresent("enableDrillFuel", dwarvenMines.get("enableDrillFuel").result()) + .set("dwarvenMines", dynamic.emptyMap() + .setFieldIfPresent("solveFetchur", dwarvenMines.get("solveFetchur").result()) + .setFieldIfPresent("solvePuzzler", dwarvenMines.get("solvePuzzler").result()) + ) + .set("dwarvenHud", dwarvenMines.get("dwarvenHud").result().orElseThrow() + .renameField("x", "commissionsX") + .renameField("y", "commissionsY") + ) + .setFieldIfPresent("crystalsHud", dwarvenMines.get("crystalsHud").result()) + .setFieldIfPresent("crystalsWaypoints", dwarvenMines.get("crystalsWaypoints").result()) + .set("crystalHollows", dynamic.emptyMap() + .setFieldIfPresent("metalDetectorHelper", dwarvenMines.get("metalDetectorHelper").result()) + ) + ).update("locations", locations -> locations.remove("dwarvenMines")); + } + + private static Dynamic fixFarming(Dynamic dynamic) { + return dynamic.set("farming", dynamic.emptyMap() + .setFieldIfPresent("garden", dynamic.get("locations").get("garden").result()) + ).update("locations", locations -> locations.remove("garden")); + } + + private static Dynamic fixOtherLocations(Dynamic dynamic) { + return dynamic.renameField("locations", "otherLocations"); + } + + private static Dynamic fixSlayers(Dynamic dynamic) { + return dynamic.renameField("slayer", "slayers"); + } + + private static Dynamic fixChat(Dynamic dynamic) { + return dynamic.renameField("messages", "chat"); + } + + private static Dynamic fixQuickNav(Dynamic dynamic) { + return dynamic.update("quickNav", quickNav -> quickNav + .update("button1", ConfigFix1::fixQuickNavButton) + .update("button2", ConfigFix1::fixQuickNavButton) + .update("button3", ConfigFix1::fixQuickNavButton) + .update("button4", ConfigFix1::fixQuickNavButton) + .update("button5", ConfigFix1::fixQuickNavButton) + .update("button6", ConfigFix1::fixQuickNavButton) + .update("button7", ConfigFix1::fixQuickNavButton) + .update("button8", ConfigFix1::fixQuickNavButton) + .update("button9", ConfigFix1::fixQuickNavButton) + .update("button10", ConfigFix1::fixQuickNavButton) + .update("button11", ConfigFix1::fixQuickNavButton) + .update("button12", ConfigFix1::fixQuickNavButton)); + } + + private static Dynamic fixQuickNavButton(Dynamic button) { + return button.update("item", item -> item + .renameField("itemName", "id") + .renameAndFixField("nbt", "components", nbt -> fixNbt(item.get("itemName"), nbt)) + ); + } + + private static Dynamic fixNbt(OptionalDynamic id, Dynamic nbt) { + try { + String itemNbt = "{id:\"minecraft:" + id.asString().getOrThrow().toLowerCase(Locale.ROOT) + "\",Count:1"; + String extraNbt = nbt.asString().getOrThrow(); + if (extraNbt.length() > 2) itemNbt += "," + extraNbt; + itemNbt += "}"; + + ItemStack fixed = ItemStackComponentizationFixer.fixUpItem(StringNbtReader.parse(itemNbt)); + + return nbt.createString(ItemStackComponentizationFixer.componentsAsString(fixed)); + } catch (Exception e) { + ConfigDataFixer.LOGGER.error(LogUtils.FATAL_MARKER, "[Skyblocker Config Data Fixer] Failed to convert nbt to components!", e); + } + + return nbt.createString("[]"); + } + + private static Dynamic fixMisc(Dynamic dynamic) { + return dynamic.set("misc", dynamic.emptyMap() + .setFieldIfPresent("richPresence", dynamic.get("richPresence").result()) + ).remove("richPresence"); + } +} diff --git a/src/main/java/de/hysky/skyblocker/config/datafixer/ConfigSchema.java b/src/main/java/de/hysky/skyblocker/config/datafixer/ConfigSchema.java new file mode 100644 index 0000000000..4c82116968 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/config/datafixer/ConfigSchema.java @@ -0,0 +1,29 @@ +package de.hysky.skyblocker.config.datafixer; + +import com.mojang.datafixers.DSL; +import com.mojang.datafixers.schemas.Schema; +import com.mojang.datafixers.types.templates.TypeTemplate; + +import java.util.Map; +import java.util.function.Supplier; + +public class ConfigSchema extends Schema { + public ConfigSchema(int versionKey, Schema parent) { + super(versionKey, parent); + } + + @Override + public void registerTypes(Schema schema, Map> entityTypes, Map> blockEntityTypes) { + schema.registerType(true, ConfigDataFixer.CONFIG_TYPE, DSL::remainder); + } + + @Override + public Map> registerEntities(Schema schema) { + return Map.of(); + } + + @Override + public Map> registerBlockEntities(Schema schema) { + return Map.of(); + } +} 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 5529e4666c..a6adf66bb9 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/quicknav/QuickNav.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/quicknav/QuickNav.java @@ -11,15 +11,15 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.nbt.StringNbtReader; +import net.minecraft.item.ItemStack; import net.minecraft.text.Text; import net.minecraft.util.Formatting; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.List; -import java.util.Locale; import java.util.regex.PatternSyntaxException; public class QuickNav { @@ -59,10 +59,9 @@ public static List init(String screenTitle) { private static QuickNavButton parseButton(QuickNavigationConfig.QuickNavItem buttonInfo, String screenTitle, int id) throws CommandSyntaxException { QuickNavigationConfig.ItemData itemData = buttonInfo.item; - String nbtString = "{id:\"minecraft:" + itemData.id.toLowerCase(Locale.ROOT) + "\",Count:1"; - if (itemData.nbt.length() > 2) nbtString += "," + itemData.nbt; - nbtString += "}"; + ItemStack stack = ItemStackComponentizationFixer.fromComponentsString(itemData.id, Math.clamp(itemData.count, 1, 99), itemData.components); boolean uiTitleMatches = false; + try { uiTitleMatches = screenTitle.matches(buttonInfo.uiTitle); } catch (PatternSyntaxException e) { @@ -75,6 +74,6 @@ private static QuickNavButton parseButton(QuickNavigationConfig.QuickNavItem but return new QuickNavButton(id, uiTitleMatches, buttonInfo.clickEvent, - ItemStackComponentizationFixer.fixUpItem(StringNbtReader.parse(nbtString))); + stack); } } diff --git a/src/main/java/de/hysky/skyblocker/utils/datafixer/JsonHelper.java b/src/main/java/de/hysky/skyblocker/utils/datafixer/JsonHelper.java new file mode 100644 index 0000000000..f7646d31d1 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/utils/datafixer/JsonHelper.java @@ -0,0 +1,107 @@ +package de.hysky.skyblocker.utils.datafixer; + +import java.util.Optional; +import java.util.OptionalInt; + +import com.google.gson.JsonObject; + +import net.minecraft.util.annotation.MethodsReturnNonnullByDefault; + +/** + * Helper methods to assist in retrieving values nested in JSON objects. + * + * All methods are fully null safe, whether it be from passing a {@code null} root object or from encountering a nonexistent or null object/value. + * + * @author AzureAaron + * @see Aaron's Mod's JSON Helper + */ +@MethodsReturnNonnullByDefault +public class JsonHelper { + + public static OptionalInt getInt(JsonObject root, String path) { + //If root is null + if (root == null) return OptionalInt.empty(); + + //Fast path for if we just want the field itself + if (!path.contains(".")) { + return root.has(path) && !root.get(path).isJsonNull() ? OptionalInt.of(root.get(path).getAsInt()) : OptionalInt.empty(); + } + + String[] split = path.split("\\."); + String propertyName = split[split.length - 1]; + String[] objects2Traverse = new String[split.length - 1]; + + //Get the traversal path + System.arraycopy(split, 0, objects2Traverse, 0, split.length - 1); + + JsonObject currentLevel = root; + + for (String objectName : objects2Traverse) { + if (currentLevel.has(objectName) && !currentLevel.get(objectName).isJsonNull()) { + currentLevel = currentLevel.getAsJsonObject(objectName); + } else { + return OptionalInt.empty(); + } + } + + return currentLevel.has(propertyName) && !currentLevel.get(propertyName).isJsonNull() ? OptionalInt.of(currentLevel.get(propertyName).getAsInt()) : OptionalInt.empty(); + } + + public static Optional getBoolean(JsonObject root, String path) { + //If root is null + if (root == null) return Optional.empty(); + + //Fast path for if we just want the field itself + if (!path.contains(".")) { + return root.has(path) && !root.get(path).isJsonNull() ? Optional.of(root.get(path).getAsBoolean()) : Optional.empty(); + } + + String[] split = path.split("\\."); + String propertyName = split[split.length - 1]; + String[] objects2Traverse = new String[split.length - 1]; + + //Get the traversal path + System.arraycopy(split, 0, objects2Traverse, 0, split.length - 1); + + JsonObject currentLevel = root; + + for (String objectName : objects2Traverse) { + if (currentLevel.has(objectName) && !currentLevel.get(objectName).isJsonNull()) { + currentLevel = currentLevel.getAsJsonObject(objectName); + } else { + return Optional.empty(); + } + } + + return currentLevel.has(propertyName) && !currentLevel.get(propertyName).isJsonNull() ? Optional.of(currentLevel.get(propertyName).getAsBoolean()) : Optional.empty(); + } + + public static Optional getString(JsonObject root, String path) { + //If root is null + if (root == null) return Optional.empty(); + + //Fast path for if we just want the field itself + if (!path.contains(".")) { + return root.has(path) && !root.get(path).isJsonNull() ? Optional.of(root.get(path).getAsString()) : Optional.empty(); + } + + String[] split = path.split("\\."); + String propertyName = split[split.length - 1]; + String[] objects2Traverse = new String[split.length - 1]; + + //Get the traversal path + System.arraycopy(split, 0, objects2Traverse, 0, split.length - 1); + + JsonObject currentLevel = root; + + for (String objectName : objects2Traverse) { + if (currentLevel.has(objectName) && !currentLevel.get(objectName).isJsonNull()) { + currentLevel = currentLevel.getAsJsonObject(objectName); + } else { + return Optional.empty(); + } + } + + return currentLevel.has(propertyName) && !currentLevel.get(propertyName).isJsonNull() ? Optional.of(currentLevel.get(propertyName).getAsString()) : Optional.empty(); + } +} diff --git a/src/main/resources/assets/skyblocker/lang/en_us.json b/src/main/resources/assets/skyblocker/lang/en_us.json index 283175d045..8f7bb2da29 100644 --- a/src/main/resources/assets/skyblocker/lang/en_us.json +++ b/src/main/resources/assets/skyblocker/lang/en_us.json @@ -455,10 +455,10 @@ "skyblocker.config.quickNav": "Quick Navigation", "skyblocker.config.quickNav.button": "Button %d", "skyblocker.config.quickNav.button.clickEvent": "Click event", + "skyblocker.config.quickNav.button.item.components": "Item Components", + "skyblocker.config.quickNav.button.item.components.@Tooltip": "A string of item components enclosed in square brackets, which is the same format as the /give command.\n\nExample: [minecraft:enchantment_glint_override=true]", "skyblocker.config.quickNav.button.item.count": "Item Count", "skyblocker.config.quickNav.button.item.itemName": "Item ID", - "skyblocker.config.quickNav.button.item.nbt": "NBT", - "skyblocker.config.quickNav.button.item.nbt.@Tooltip": "\u00a7c\u00a7lWARNING: THIS MUST BE CONFIGURED WITH ITEM NBT NOT ITEM COMPONENTS! \n\n\u00a7fIn the future we will automatically migrate your config to use item components!", "skyblocker.config.quickNav.button.render": "Render", "skyblocker.config.quickNav.button.uiTitle": "UI Title", "skyblocker.config.quickNav.enableQuickNav": "Enable Quick Navigation", diff --git a/src/test/java/de/hysky/skyblocker/config/datafixer/ConfigDataFixerTest.java b/src/test/java/de/hysky/skyblocker/config/datafixer/ConfigDataFixerTest.java new file mode 100644 index 0000000000..aab10084be --- /dev/null +++ b/src/test/java/de/hysky/skyblocker/config/datafixer/ConfigDataFixerTest.java @@ -0,0 +1,32 @@ +package de.hysky.skyblocker.config.datafixer; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonObject; +import net.minecraft.Bootstrap; +import net.minecraft.SharedConstants; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.io.InputStreamReader; + +public class ConfigDataFixerTest { + private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); + + @BeforeAll + public static void setupEnvironment() { + SharedConstants.createGameVersion(); + Bootstrap.initialize(); + } + + @Test + void testDataFixer1() { + @SuppressWarnings("DataFlowIssue") + JsonObject oldConfig = GSON.fromJson(new InputStreamReader(ConfigDataFixerTest.class.getResourceAsStream("/assets/skyblocker/config/skyblocker-v1.json")), JsonObject.class); + @SuppressWarnings("DataFlowIssue") + JsonObject expectedNewConfig = GSON.fromJson(new InputStreamReader(ConfigDataFixerTest.class.getResourceAsStream("/assets/skyblocker/config/skyblocker-v2.json")), JsonObject.class); + + Assertions.assertEquals(expectedNewConfig, ConfigDataFixer.apply(oldConfig)); + } +} diff --git a/src/test/resources/assets/skyblocker/config/skyblocker-v1.json b/src/test/resources/assets/skyblocker/config/skyblocker-v1.json new file mode 100644 index 0000000000..20620a57b7 --- /dev/null +++ b/src/test/resources/assets/skyblocker/config/skyblocker-v1.json @@ -0,0 +1,555 @@ +{ + "version": 1, + "general": { + "enableTips": true, + "acceptReparty": true, + "betterPartyFinder": true, + "fancyCraftingTable": true, + "backpackPreviewWithoutShift": true, + "compactorDeletorPreview": true, + "hideEmptyTooltips": true, + "hideStatusEffectOverlay": false, + "dontStripSkinAlphaValues": true, + "dungeonQuality": true, + "enableNewYearCakesHelper": true, + "tabHud": { + "tabHudEnabled": true, + "tabHudScale": 100, + "enableHudBackground": true, + "plainPlayerNames": false, + "nameSorting": "ALPHABETICAL" + }, + "bars": { + "enableBars": true, + "barPositions": { + "healthBarPosition": "LAYER1", + "manaBarPosition": "LAYER1", + "defenceBarPosition": "RIGHT", + "experienceBarPosition": "RIGHT" + } + }, + "experiments": { + "enableChronomatronSolver": true, + "enableSuperpairsSolver": true, + "enableUltrasequencerSolver": true + }, + "fishing": { + "enableFishingHelper": true, + "enableFishingTimer": false, + "changeTimerColor": true, + "fishingTimerScale": 1.0, + "hideOtherPlayersRods": false + }, + "fairySouls": { + "enableFairySoulsHelper": true, + "highlightFoundSouls": false, + "highlightOnlyNearbySouls": false + }, + "mythologicalRitual": { + "enableMythologicalRitualHelper": true + }, + "itemCooldown": { + "enableItemCooldowns": true + }, + "shortcuts": { + "enableShortcuts": true, + "enableCommandShortcuts": true, + "enableCommandArgShortcuts": true + }, + "waypoints": { + "enableWaypoints": true, + "waypointType": "WAYPOINT" + }, + "quiverWarning": { + "enableQuiverWarning": true, + "enableQuiverWarningInDungeons": true, + "enableQuiverWarningAfterDungeon": true + }, + "itemList": { + "enableItemList": true + }, + "itemTooltip": { + "enableNPCPrice": true, + "enableMotesPrice": true, + "enableAvgBIN": true, + "avg": "THREE_DAY", + "enableLowestBIN": true, + "enableBazaarPrice": true, + "enableObtainedDate": true, + "enableMuseumInfo": true, + "enableExoticTooltip": true, + "enableAccessoriesHelper": true + }, + "itemInfoDisplay": { + "attributeShardInfo": true, + "itemRarityBackgrounds": true, + "itemRarityBackgroundStyle": "CIRCULAR", + "itemRarityBackgroundsOpacity": 0.5 + }, + "itemProtection": { + "slotLockStyle": "FANCY" + }, + "wikiLookup": { + "enableWikiLookup": true, + "officialWiki": false + }, + "chestValue": { + "enableChestValue": true, + "color": "DARK_GREEN", + "incompleteColor": "BLUE" + }, + "specialEffects": { + "rareDungeonDropEffects": true + }, + "hitbox": { + "oldFarmlandHitbox": true, + "oldLeverHitbox": false + }, + "titleContainer": { + "titleContainerScale": 100.0, + "x": 482, + "y": 170, + "direction": "VERTICAL", + "alignment": "MIDDLE" + }, + "teleportOverlay": { + "enableTeleportOverlays": true, + "enableWeirdTransmission": true, + "enableInstantTransmission": true, + "enableEtherTransmission": true, + "enableSinrecallTransmission": true, + "enableWitherImpact": true + }, + "flameOverlay": { + "flameHeight": 0, + "flameOpacity": 0 + }, + "searchOverlay": { + "enableBazaar": true, + "enableAuctionHouse": true, + "keepPreviousSearches": false, + "maxSuggestions": 5, + "historyLength": 5, + "enableCommands": false, + "bazaarHistory": [ + "Enchanted Snow Block", + "Recombobulator 3000", + "Enchanted Snow Block", + "Recombobulator 3000", + "Enchanted Snow Block" + ], + "auctionHistory": [ + "God Potion", + "New Year Cake (Year 30", + "New Year Cake (Year 31", + "New Year Cake (Year 32", + "New Year Cake (Year 2" + ] + }, + "fancyAuctionHouse": { + "enabled": true, + "highlightCheapBIN": true + }, + "lockedSlots": [ + 3, + 8, + 0 + ], + "protectedItems": [ + "10f84455-c063-4e3e-b6eb-cc485fe74a06", + "64e491fa-64ed-4abf-829a-940e1fb295d2", + "23a619b6-f487-419e-8598-10b8f21dc80a", + "416aa42d-27d4-4284-913f-d03fa1f528c3", + "4e2a7f16-7d93-4069-bfbd-a8ff8e42f285", + "63ec4f84-2005-45e5-a4b7-0c9ae84dc612", + "aba2b017-91e8-4263-ae9e-5a10f8dc91fe", + "f1391873-5126-496d-b0fe-c861faeaf681", + "bb84cfea-3fdd-4579-b5fa-907cd8123593", + "a604f533-49f6-4190-b971-08f725231229", + "333cba8d-3136-4494-9fa0-40dff482ef66", + "91f49338-fc0b-4601-a704-aabc44853318", + "d76e5eca-be47-4d0b-973c-3ec30fd176dc", + "301c58a7-9b8a-4c4e-9e8d-3e8a9471a916", + "c8ab629e-fc5b-4af0-8053-acb155411c9b", + "333a079f-93d4-48f1-af9f-862b1ecc417c", + "0843d8b0-b6a6-47fc-afde-8eee8c5455d9", + "8bcf2a99-68e6-4646-ac04-4c72e55c6818", + "214333db-d71c-4080-8487-00b4666bb9a4", + "1eba38b5-e0f6-4862-bf19-e2df33e21ce4", + "6b42c77f-1891-43a4-a9ea-4454e299a059", + "71ce1812-d1fd-4e71-98ad-8b863759a82f", + "253489d9-49d0-46c8-b3f8-b70c3663c5d2", + "6033eff2-879d-494f-8dae-696fc8a3c82e", + "5f6090c8-cbc4-4030-97ac-5018c151cc15", + "64162e02-91fb-4ec3-a57c-866436a99a7a", + "a299c718-c66b-4de5-9747-71c172ac4601", + "e21172ce-0a41-426a-a445-84a28677cd65", + "4bfd23bf-ceb8-4951-874d-e61633e088d8", + "575ce2c9-251e-4435-9020-de1a2e24b1d0", + "b06b8fe2-470a-43f3-b844-658472f20996", + "e54dea3d-ca45-451e-9ae4-0e5fb87e97b2", + "67b47348-da46-4257-833a-dd23fb074cc6", + "9f7597ec-c3c9-46df-9f36-8e76c8745a9d", + "e297dcef-2f3d-4fb3-9781-aaff6017178c", + "ad9a598d-e5c9-4293-92c8-5e41bebe913c", + "fa51c660-b262-4826-bed8-6138236919cb" + ], + "customItemNames": {}, + "customDyeColors": {}, + "customArmorTrims": { + "f1391873-5126-496d-b0fe-c861faeaf681": { + "material": "minecraft:amethyst", + "pattern": "minecraft:raiser" + }, + "81409da1-610c-445a-aba2-4c95a3cabbf2": { + "material": "minecraft:amethyst", + "pattern": "minecraft:coast" + } + }, + "customAnimatedDyes": { + "f1391873-5126-496d-b0fe-c861faeaf681": { + "color1": 16711680, + "color2": 11154282, + "samples": 10, + "cycleBack": true, + "tickDelay": 4 + } + } + }, + "locations": { + "barn": { + "solveHungryHiker": true, + "solveTreasureHunter": true + }, + "crimsonIsle": { + "kuudra": { + "supplyWaypoints": true, + "fuelWaypoints": true, + "suppliesAndFuelWaypointType": "WAYPOINT", + "ballistaBuildWaypoints": true, + "safeSpotWaypoints": true, + "pearlWaypoints": true, + "noArrowPoisonWarning": true, + "arrowPoisonThreshold": 16 + } + }, + "dungeons": { + "secretWaypoints": { + "enableRoomMatching": true, + "enableSecretWaypoints": true, + "waypointType": "OUTLINED_HIGHLIGHT", + "showSecretText": true, + "enableEntranceWaypoints": true, + "enableSuperboomWaypoints": true, + "enableChestWaypoints": true, + "enableItemWaypoints": true, + "enableBatWaypoints": true, + "enableWitherWaypoints": true, + "enableLeverWaypoints": true, + "enableFairySoulWaypoints": true, + "enableStonkWaypoints": false, + "enableAotvWaypoints": true, + "enablePearlWaypoints": true, + "enableDefaultWaypoints": true + }, + "doorHighlight": { + "enableDoorHighlight": true, + "doorHighlightType": "OUTLINED_HIGHLIGHT" + }, + "dungeonScore": { + "enableDungeonScore270Message": false, + "enableDungeonScore270Title": false, + "enableDungeonScore270Sound": false, + "dungeonScore270Message": "270 Score Reached!", + "enableDungeonScore300Message": true, + "enableDungeonScore300Title": true, + "enableDungeonScore300Sound": true, + "dungeonScore300Message": "[做得好] 300 Social Credit has been added to your account. Enjoy your boss fight.", + "enableDungeonCryptsMessage": true, + "dungeonCryptsMessageThreshold": 250, + "dungeonCryptsMessage": "We only have [crypts] crypts out of 5, we need more!", + "enableScoreHUD": true, + "scoreX": 25, + "scoreY": 134, + "scoreScaling": 1.0 + }, + "dungeonChestProfit": { + "enableProfitCalculator": true, + "includeKismet": true, + "includeEssence": false, + "croesusProfit": true, + "neutralThreshold": 1000, + "neutralColor": "DARK_GRAY", + "profitColor": "DARK_GREEN", + "lossColor": "RED", + "incompleteColor": "BLUE" + }, + "mimicMessage": { + "sendMimicMessage": true, + "mimicMessage": "Mimic dead!" + }, + "croesusHelper": true, + "enableMap": true, + "mapScaling": 1.0, + "mapX": 2, + "mapY": 2, + "playerSecretsTracker": true, + "starredMobGlow": true, + "starredMobBoundingBoxes": true, + "solveThreeWeirdos": true, + "blazeSolver": true, + "creeperSolver": true, + "solveTrivia": true, + "solveTicTacToe": true, + "solveWaterboard": true, + "solveBoulder": true, + "solveIceFill": true, + "solveSilverfish": true, + "fireFreezeStaffTimer": true, + "floor3GuardianHealthDisplay": true, + "allowDroppingProtectedItems": false, + "lividColor": { + "enableLividColorGlow": true, + "enableLividColorText": true, + "enableLividColorTitle": true, + "lividColorText": "[color] is sus" + }, + "terminals": { + "solveColor": true, + "solveOrder": true, + "solveStartsWith": true + } + }, + "dwarvenMines": { + "enableDrillFuel": true, + "solveFetchur": true, + "solvePuzzler": true, + "metalDetectorHelper": true, + "dwarvenHud": { + "enabledCommissions": true, + "enabledPowder": true, + "style": "SIMPLE", + "x": 10, + "y": 10, + "powderX": 10, + "powderY": 70 + }, + "crystalsHud": { + "enabled": true, + "showLocations": true, + "locationSize": 8, + "x": 10, + "y": 130, + "mapScaling": 1.0 + }, + "crystalsWaypoints": { + "enabled": true, + "findInChat": true + } + }, + "rift": { + "mirrorverseWaypoints": true, + "blobbercystGlow": true, + "enigmaSoulWaypoints": false, + "highlightFoundEnigmaSouls": true, + "mcGrubberStacks": 0 + }, + "end": { + "enableEnderNodeHelper": true, + "hudEnabled": true, + "zealotKillsEnabled": true, + "protectorLocationEnabled": true, + "waypoint": true, + "x": 10, + "y": 10 + }, + "spidersDen": { + "relics": { + "enableRelicsHelper": true, + "highlightFoundRelics": false + } + }, + "garden": { + "farmingHud": { + "enableHud": true, + "x": 180, + "y": 0 + }, + "dicerTitlePrevent": true, + "visitorHelper": true, + "lockMouseTool": true, + "lockMouseGroundOnly": true + } + }, + "slayer": { + "endermanSlayer": { + "enableYangGlyphsNotification": true, + "highlightBeacons": true, + "highlightNukekubiHeads": true + }, + "vampireSlayer": { + "enableEffigyWaypoints": true, + "compactEffigyWaypoints": false, + "effigyUpdateFrequency": 5, + "enableHolyIceIndicator": true, + "holyIceIndicatorTickDelay": 10, + "holyIceUpdateFrequency": 5, + "enableHealingMelonIndicator": true, + "healingMelonHealthThreshold": 4.0, + "enableSteakStakeIndicator": true, + "steakStakeUpdateFrequency": 5, + "enableManiaIndicator": true, + "maniaUpdateFrequency": 5 + } + }, + "quickNav": { + "enableQuickNav": true, + "button1": { + "render": true, + "item": { + "itemName": "diamond_sword", + "count": 1, + "nbt": "" + }, + "uiTitle": "Your Skills", + "clickEvent": "/skills" + }, + "button2": { + "render": true, + "item": { + "itemName": "painting", + "count": 1, + "nbt": "" + }, + "uiTitle": "Collections", + "clickEvent": "/collection" + }, + "button3": { + "render": true, + "item": { + "itemName": "bone", + "count": 1, + "nbt": "" + }, + "uiTitle": "Pets(:? \\(\\d+\\/\\d+\\))?", + "clickEvent": "/pets" + }, + "button4": { + "render": true, + "item": { + "itemName": "leather_chestplate", + "count": 1, + "nbt": "tag:{display:{color:8991416}}" + }, + "uiTitle": "Wardrobe \\([12]/2\\)", + "clickEvent": "/wardrobe" + }, + "button5": { + "render": true, + "item": { + "itemName": "player_head", + "count": 1, + "nbt": "tag:{SkullOwner:{Id:[I;-2081424676,-57521078,-2073572414,158072763],Properties:{textures:[{Value:\"ewogICJ0aW1lc3RhbXAiIDogMTU5MTMxMDU4NTYwOSwKICAicHJvZmlsZUlkIiA6ICI0MWQzYWJjMmQ3NDk0MDBjOTA5MGQ1NDM0ZDAzODMxYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNZWdha2xvb24iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODBhMDc3ZTI0OGQxNDI3NzJlYTgwMDg2NGY4YzU3OGI5ZDM2ODg1YjI5ZGFmODM2YjY0YTcwNjg4MmI2ZWMxMCIKICAgIH0KICB9Cn0=\"}]}}}" + }, + "uiTitle": "Sack of Sacks", + "clickEvent": "/sacks" + }, + "button6": { + "render": true, + "item": { + "itemName": "ender_chest", + "count": 1, + "nbt": "" + }, + "uiTitle": "Storage", + "clickEvent": "/storage" + }, + "button7": { + "render": true, + "item": { + "itemName": "player_head", + "count": 1, + "nbt": "tag:{SkullOwner:{Id:[I;-300151517,-631415889,-1193921967,-1821784279],Properties:{textures:[{Value:\"e3RleHR1cmVzOntTS0lOOnt1cmw6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDdjYzY2ODc0MjNkMDU3MGQ1NTZhYzUzZTA2NzZjYjU2M2JiZGQ5NzE3Y2Q4MjY5YmRlYmVkNmY2ZDRlN2JmOCJ9fX0=\"}]}}}" + }, + "uiTitle": "none", + "clickEvent": "/hub" + }, + "button8": { + "render": true, + "item": { + "itemName": "player_head", + "count": 1, + "nbt": "tag:{SkullOwner:{Id:[I;1605800870,415127827,-1236127084,15358548],Properties:{textures:[{Value:\"e3RleHR1cmVzOntTS0lOOnt1cmw6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzg5MWQ1YjI3M2ZmMGJjNTBjOTYwYjJjZDg2ZWVmMWM0MGExYjk0MDMyYWU3MWU3NTQ3NWE1NjhhODI1NzQyMSJ9fX0=\"}]}}}" + }, + "uiTitle": "none", + "clickEvent": "/warp dungeon_hub" + }, + "button9": { + "render": true, + "item": { + "itemName": "player_head", + "count": 1, + "nbt": "tag:{SkullOwner:{Id:[I;-562285948,532499670,-1705302742,775653035],Properties:{textures:[{Value:\"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjVkZjU1NTkyNjQzMGQ1ZDc1YWRlZDIxZGQ5NjE5Yjc2YzViN2NhMmM3ZjU0MDE0NDA1MjNkNTNhOGJjZmFhYiJ9fX0=\"}]}}}" + }, + "uiTitle": "Visit prtl", + "clickEvent": "/visit prtl" + }, + "button10": { + "render": true, + "item": { + "itemName": "enchanting_table", + "count": 1, + "nbt": "" + }, + "uiTitle": "Enchant Item", + "clickEvent": "/etable" + }, + "button11": { + "render": true, + "item": { + "itemName": "anvil", + "count": 1, + "nbt": "" + }, + "uiTitle": "Anvil", + "clickEvent": "/anvil" + }, + "button12": { + "render": true, + "item": { + "itemName": "crafting_table", + "count": 1, + "nbt": "" + }, + "uiTitle": "Craft Item", + "clickEvent": "/craft" + } + }, + "messages": { + "hideAbility": "ACTION_BAR", + "hideHeal": "PASS", + "hideAOTE": "ACTION_BAR", + "hideImplosion": "PASS", + "hideMoltenWave": "PASS", + "hideAds": "FILTER", + "hideTeleportPad": "PASS", + "hideCombo": "PASS", + "hideAutopet": "PASS", + "hideShowOff": "FILTER", + "hideToggleSkyMall": "PASS", + "hideMimicKill": "PASS", + "hideDeath": "PASS", + "hideMana": false, + "hideDicer": "PASS", + "chatRuleConfig": { + "announcementLength": 60, + "announcementScale": 3 + } + }, + "richPresence": { + "enableRichPresence": false, + "info": "LOCATION", + "cycleMode": false, + "customMessage": "Playing Skyblock" + } +} \ No newline at end of file diff --git a/src/test/resources/assets/skyblocker/config/skyblocker-v2.json b/src/test/resources/assets/skyblocker/config/skyblocker-v2.json new file mode 100644 index 0000000000..e8489a5dd1 --- /dev/null +++ b/src/test/resources/assets/skyblocker/config/skyblocker-v2.json @@ -0,0 +1,573 @@ +{ + "version": 2, + "general": { + "enableTips": true, + "acceptReparty": true, + "shortcuts": { + "enableShortcuts": true, + "enableCommandShortcuts": true, + "enableCommandArgShortcuts": true + }, + "quiverWarning": { + "enableQuiverWarning": true, + "enableQuiverWarningInDungeons": true, + "enableQuiverWarningAfterDungeon": true + }, + "itemList": { + "enableItemList": true + }, + "itemTooltip": { + "enableNPCPrice": true, + "enableMotesPrice": true, + "enableAvgBIN": true, + "avg": "THREE_DAY", + "enableLowestBIN": true, + "enableBazaarPrice": true, + "enableObtainedDate": true, + "enableMuseumInfo": true, + "enableExoticTooltip": true, + "enableAccessoriesHelper": true, + "dungeonQuality": true + }, + "itemInfoDisplay": { + "attributeShardInfo": true, + "itemRarityBackgrounds": true, + "itemRarityBackgroundStyle": "CIRCULAR", + "itemRarityBackgroundsOpacity": 0.5 + }, + "itemProtection": { + "slotLockStyle": "FANCY" + }, + "wikiLookup": { + "enableWikiLookup": true, + "officialWiki": false + }, + "specialEffects": { + "rareDungeonDropEffects": true + }, + "hitbox": { + "oldFarmlandHitbox": true, + "oldLeverHitbox": false + }, + "lockedSlots": [ + 3, + 8, + 0 + ], + "protectedItems": [ + "10f84455-c063-4e3e-b6eb-cc485fe74a06", + "64e491fa-64ed-4abf-829a-940e1fb295d2", + "23a619b6-f487-419e-8598-10b8f21dc80a", + "416aa42d-27d4-4284-913f-d03fa1f528c3", + "4e2a7f16-7d93-4069-bfbd-a8ff8e42f285", + "63ec4f84-2005-45e5-a4b7-0c9ae84dc612", + "aba2b017-91e8-4263-ae9e-5a10f8dc91fe", + "f1391873-5126-496d-b0fe-c861faeaf681", + "bb84cfea-3fdd-4579-b5fa-907cd8123593", + "a604f533-49f6-4190-b971-08f725231229", + "333cba8d-3136-4494-9fa0-40dff482ef66", + "91f49338-fc0b-4601-a704-aabc44853318", + "d76e5eca-be47-4d0b-973c-3ec30fd176dc", + "301c58a7-9b8a-4c4e-9e8d-3e8a9471a916", + "c8ab629e-fc5b-4af0-8053-acb155411c9b", + "333a079f-93d4-48f1-af9f-862b1ecc417c", + "0843d8b0-b6a6-47fc-afde-8eee8c5455d9", + "8bcf2a99-68e6-4646-ac04-4c72e55c6818", + "214333db-d71c-4080-8487-00b4666bb9a4", + "1eba38b5-e0f6-4862-bf19-e2df33e21ce4", + "6b42c77f-1891-43a4-a9ea-4454e299a059", + "71ce1812-d1fd-4e71-98ad-8b863759a82f", + "253489d9-49d0-46c8-b3f8-b70c3663c5d2", + "6033eff2-879d-494f-8dae-696fc8a3c82e", + "5f6090c8-cbc4-4030-97ac-5018c151cc15", + "64162e02-91fb-4ec3-a57c-866436a99a7a", + "a299c718-c66b-4de5-9747-71c172ac4601", + "e21172ce-0a41-426a-a445-84a28677cd65", + "4bfd23bf-ceb8-4951-874d-e61633e088d8", + "575ce2c9-251e-4435-9020-de1a2e24b1d0", + "b06b8fe2-470a-43f3-b844-658472f20996", + "e54dea3d-ca45-451e-9ae4-0e5fb87e97b2", + "67b47348-da46-4257-833a-dd23fb074cc6", + "9f7597ec-c3c9-46df-9f36-8e76c8745a9d", + "e297dcef-2f3d-4fb3-9781-aaff6017178c", + "ad9a598d-e5c9-4293-92c8-5e41bebe913c", + "fa51c660-b262-4826-bed8-6138236919cb" + ], + "customItemNames": {}, + "customDyeColors": {}, + "customArmorTrims": { + "f1391873-5126-496d-b0fe-c861faeaf681": { + "material": "minecraft:amethyst", + "pattern": "minecraft:raiser" + }, + "81409da1-610c-445a-aba2-4c95a3cabbf2": { + "material": "minecraft:amethyst", + "pattern": "minecraft:coast" + } + }, + "customAnimatedDyes": { + "f1391873-5126-496d-b0fe-c861faeaf681": { + "color1": 16711680, + "color2": 11154282, + "samples": 10, + "cycleBack": true, + "tickDelay": 4 + } + } + }, + "uiAndVisuals": { + "compactorDeletorPreview": true, + "dontStripSkinAlphaValues": true, + "backpackPreviewWithoutShift": true, + "fancyCraftingTable": true, + "hideStatusEffectOverlay": false, + "chestValue": { + "enableChestValue": true, + "color": "DARK_GREEN", + "incompleteColor": "BLUE" + }, + "itemCooldown": { + "enableItemCooldowns": true + }, + "titleContainer": { + "titleContainerScale": 100.0, + "x": 482, + "y": 170, + "direction": "VERTICAL", + "alignment": "MIDDLE" + }, + "tabHud": { + "tabHudEnabled": true, + "tabHudScale": 100, + "enableHudBackground": true, + "plainPlayerNames": false, + "nameSorting": "ALPHABETICAL" + }, + "fancyAuctionHouse": { + "enabled": true, + "highlightCheapBIN": true + }, + "bars": { + "enableBars": true, + "barPositions": { + "healthBarPosition": "LAYER1", + "manaBarPosition": "LAYER1", + "defenceBarPosition": "RIGHT", + "experienceBarPosition": "RIGHT" + } + }, + "waypoints": { + "enableWaypoints": true, + "waypointType": "WAYPOINT" + }, + "teleportOverlay": { + "enableTeleportOverlays": true, + "enableWeirdTransmission": true, + "enableInstantTransmission": true, + "enableEtherTransmission": true, + "enableSinrecallTransmission": true, + "enableWitherImpact": true + }, + "searchOverlay": { + "enableBazaar": true, + "enableAuctionHouse": true, + "keepPreviousSearches": false, + "maxSuggestions": 5, + "historyLength": 5, + "enableCommands": false, + "bazaarHistory": [ + "Enchanted Snow Block", + "Recombobulator 3000", + "Enchanted Snow Block", + "Recombobulator 3000", + "Enchanted Snow Block" + ], + "auctionHistory": [ + "God Potion", + "New Year Cake (Year 30", + "New Year Cake (Year 31", + "New Year Cake (Year 32", + "New Year Cake (Year 2" + ] + }, + "flameOverlay": { + "flameHeight": 0, + "flameOpacity": 0 + }, + "hideEmptyTooltips": true + }, + "helpers": { + "enableNewYearCakesHelper": true, + "mythologicalRitual": { + "enableMythologicalRitualHelper": true + }, + "experiments": { + "enableChronomatronSolver": true, + "enableSuperpairsSolver": true, + "enableUltrasequencerSolver": true + }, + "fishing": { + "enableFishingHelper": true, + "enableFishingTimer": false, + "changeTimerColor": true, + "fishingTimerScale": 1.0, + "hideOtherPlayersRods": false + }, + "fairySouls": { + "enableFairySoulsHelper": true, + "highlightFoundSouls": false, + "highlightOnlyNearbySouls": false + } + }, + "dungeons": { + "fancyPartyFinder": true, + "croesusHelper": true, + "playerSecretsTracker": true, + "starredMobGlow": true, + "starredMobBoundingBoxes": true, + "allowDroppingProtectedItems": false, + "dungeonMap": { + "enableMap": true, + "mapScaling": 1.0, + "mapX": 2, + "mapY": 2 + }, + "puzzleSolvers": { + "solveThreeWeirdos": true, + "blazeSolver": true, + "creeperSolver": true, + "solveTrivia": true, + "solveTicTacToe": true, + "solveWaterboard": true, + "solveBoulder": true, + "solveIceFill": true, + "solveSilverfish": true + }, + "theProfessor": { + "fireFreezeStaffTimer": true, + "floor3GuardianHealthDisplay": true + }, + "livid": { + "enableLividColorGlow": true, + "enableLividColorText": true, + "enableLividColorTitle": true, + "lividColorText": "[color] is sus" + }, + "terminals": { + "solveColor": true, + "solveOrder": true, + "solveStartsWith": true + }, + "secretWaypoints": { + "enableRoomMatching": true, + "enableSecretWaypoints": true, + "waypointType": "OUTLINED_HIGHLIGHT", + "showSecretText": true, + "enableEntranceWaypoints": true, + "enableSuperboomWaypoints": true, + "enableChestWaypoints": true, + "enableItemWaypoints": true, + "enableBatWaypoints": true, + "enableWitherWaypoints": true, + "enableLeverWaypoints": true, + "enableFairySoulWaypoints": true, + "enableStonkWaypoints": false, + "enableAotvWaypoints": true, + "enablePearlWaypoints": true, + "enableDefaultWaypoints": true + }, + "mimicMessage": { + "sendMimicMessage": true, + "mimicMessage": "Mimic dead!" + }, + "doorHighlight": { + "enableDoorHighlight": true, + "doorHighlightType": "OUTLINED_HIGHLIGHT" + }, + "dungeonScore": { + "enableDungeonScore270Message": false, + "enableDungeonScore270Title": false, + "enableDungeonScore270Sound": false, + "dungeonScore270Message": "270 Score Reached!", + "enableDungeonScore300Message": true, + "enableDungeonScore300Title": true, + "enableDungeonScore300Sound": true, + "dungeonScore300Message": "[做得好] 300 Social Credit has been added to your account. Enjoy your boss fight.", + "enableDungeonCryptsMessage": true, + "dungeonCryptsMessageThreshold": 250, + "dungeonCryptsMessage": "We only have [crypts] crypts out of 5, we need more!", + "enableScoreHUD": true, + "scoreX": 25, + "scoreY": 134, + "scoreScaling": 1.0 + }, + "dungeonChestProfit": { + "enableProfitCalculator": true, + "includeKismet": true, + "includeEssence": false, + "croesusProfit": true, + "neutralThreshold": 1000, + "neutralColor": "DARK_GRAY", + "profitColor": "DARK_GREEN", + "lossColor": "RED", + "incompleteColor": "BLUE" + } + }, + "crimsonIsle": { + "kuudra": { + "supplyWaypoints": true, + "fuelWaypoints": true, + "suppliesAndFuelWaypointType": "WAYPOINT", + "ballistaBuildWaypoints": true, + "safeSpotWaypoints": true, + "pearlWaypoints": true, + "noArrowPoisonWarning": true, + "arrowPoisonThreshold": 16 + } + }, + "mining": { + "enableDrillFuel": true, + "dwarvenMines": { + "solveFetchur": true, + "solvePuzzler": true + }, + "dwarvenHud": { + "enabledCommissions": true, + "enabledPowder": true, + "style": "SIMPLE", + "commissionsX": 10, + "commissionsY": 10, + "powderX": 10, + "powderY": 70 + }, + "crystalsHud": { + "enabled": true, + "showLocations": true, + "locationSize": 8, + "x": 10, + "y": 130, + "mapScaling": 1.0 + }, + "crystalsWaypoints": { + "enabled": true, + "findInChat": true + }, + "crystalHollows": { + "metalDetectorHelper": true + } + }, + "farming": { + "garden": { + "farmingHud": { + "enableHud": true, + "x": 180, + "y": 0 + }, + "dicerTitlePrevent": true, + "visitorHelper": true, + "lockMouseTool": true, + "lockMouseGroundOnly": true + } + }, + "otherLocations": { + "barn": { + "solveHungryHiker": true, + "solveTreasureHunter": true + }, + "rift": { + "mirrorverseWaypoints": true, + "blobbercystGlow": true, + "enigmaSoulWaypoints": false, + "highlightFoundEnigmaSouls": true, + "mcGrubberStacks": 0 + }, + "end": { + "enableEnderNodeHelper": true, + "hudEnabled": true, + "zealotKillsEnabled": true, + "protectorLocationEnabled": true, + "waypoint": true, + "x": 10, + "y": 10 + }, + "spidersDen": { + "relics": { + "enableRelicsHelper": true, + "highlightFoundRelics": false + } + } + }, + "slayers": { + "endermanSlayer": { + "enableYangGlyphsNotification": true, + "highlightBeacons": true, + "highlightNukekubiHeads": true + }, + "vampireSlayer": { + "enableEffigyWaypoints": true, + "compactEffigyWaypoints": false, + "effigyUpdateFrequency": 5, + "enableHolyIceIndicator": true, + "holyIceIndicatorTickDelay": 10, + "holyIceUpdateFrequency": 5, + "enableHealingMelonIndicator": true, + "healingMelonHealthThreshold": 4.0, + "enableSteakStakeIndicator": true, + "steakStakeUpdateFrequency": 5, + "enableManiaIndicator": true, + "maniaUpdateFrequency": 5 + } + }, + "chat": { + "hideAbility": "ACTION_BAR", + "hideHeal": "PASS", + "hideAOTE": "ACTION_BAR", + "hideImplosion": "PASS", + "hideMoltenWave": "PASS", + "hideAds": "FILTER", + "hideTeleportPad": "PASS", + "hideCombo": "PASS", + "hideAutopet": "PASS", + "hideShowOff": "FILTER", + "hideToggleSkyMall": "PASS", + "hideMimicKill": "PASS", + "hideDeath": "PASS", + "hideMana": false, + "hideDicer": "PASS", + "chatRuleConfig": { + "announcementLength": 60, + "announcementScale": 3 + } + }, + "quickNav": { + "enableQuickNav": true, + "button1": { + "render": true, + "uiTitle": "Your Skills", + "clickEvent": "/skills", + "item": { + "id": "diamond_sword", + "count": 1, + "components": "[]" + } + }, + "button2": { + "render": true, + "uiTitle": "Collections", + "clickEvent": "/collection", + "item": { + "id": "painting", + "count": 1, + "components": "[]" + } + }, + "button3": { + "render": true, + "uiTitle": "Pets(:? \\(\\d+\\/\\d+\\))?", + "clickEvent": "/pets", + "item": { + "id": "bone", + "count": 1, + "components": "[]" + } + }, + "button4": { + "render": true, + "uiTitle": "Wardrobe \\([12]/2\\)", + "clickEvent": "/wardrobe", + "item": { + "id": "leather_chestplate", + "count": 1, + "components": "[minecraft:dyed_color\u003d{rgb:8991416}]" + } + }, + "button5": { + "render": true, + "uiTitle": "Sack of Sacks", + "clickEvent": "/sacks", + "item": { + "id": "player_head", + "count": 1, + "components": "[minecraft:profile\u003d{id:[I;-2081424676,-57521078,-2073572414,158072763],name:\"\",properties:[{name:\"textures\",value:\"ewogICJ0aW1lc3RhbXAiIDogMTU5MTMxMDU4NTYwOSwKICAicHJvZmlsZUlkIiA6ICI0MWQzYWJjMmQ3NDk0MDBjOTA5MGQ1NDM0ZDAzODMxYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNZWdha2xvb24iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODBhMDc3ZTI0OGQxNDI3NzJlYTgwMDg2NGY4YzU3OGI5ZDM2ODg1YjI5ZGFmODM2YjY0YTcwNjg4MmI2ZWMxMCIKICAgIH0KICB9Cn0\u003d\"}]}]" + } + }, + "button6": { + "render": true, + "uiTitle": "Storage", + "clickEvent": "/storage", + "item": { + "id": "ender_chest", + "count": 1, + "components": "[]" + } + }, + "button7": { + "render": true, + "uiTitle": "none", + "clickEvent": "/hub", + "item": { + "id": "player_head", + "count": 1, + "components": "[minecraft:profile\u003d{id:[I;-300151517,-631415889,-1193921967,-1821784279],name:\"\",properties:[{name:\"textures\",value:\"e3RleHR1cmVzOntTS0lOOnt1cmw6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDdjYzY2ODc0MjNkMDU3MGQ1NTZhYzUzZTA2NzZjYjU2M2JiZGQ5NzE3Y2Q4MjY5YmRlYmVkNmY2ZDRlN2JmOCJ9fX0\u003d\"}]}]" + } + }, + "button8": { + "render": true, + "uiTitle": "none", + "clickEvent": "/warp dungeon_hub", + "item": { + "id": "player_head", + "count": 1, + "components": "[minecraft:profile\u003d{id:[I;1605800870,415127827,-1236127084,15358548],name:\"\",properties:[{name:\"textures\",value:\"e3RleHR1cmVzOntTS0lOOnt1cmw6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzg5MWQ1YjI3M2ZmMGJjNTBjOTYwYjJjZDg2ZWVmMWM0MGExYjk0MDMyYWU3MWU3NTQ3NWE1NjhhODI1NzQyMSJ9fX0\u003d\"}]}]" + } + }, + "button9": { + "render": true, + "uiTitle": "Visit prtl", + "clickEvent": "/visit prtl", + "item": { + "id": "player_head", + "count": 1, + "components": "[minecraft:profile\u003d{id:[I;-562285948,532499670,-1705302742,775653035],name:\"\",properties:[{name:\"textures\",value:\"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjVkZjU1NTkyNjQzMGQ1ZDc1YWRlZDIxZGQ5NjE5Yjc2YzViN2NhMmM3ZjU0MDE0NDA1MjNkNTNhOGJjZmFhYiJ9fX0\u003d\"}]}]" + } + }, + "button10": { + "render": true, + "uiTitle": "Enchant Item", + "clickEvent": "/etable", + "item": { + "id": "enchanting_table", + "count": 1, + "components": "[]" + } + }, + "button11": { + "render": true, + "uiTitle": "Anvil", + "clickEvent": "/anvil", + "item": { + "id": "anvil", + "count": 1, + "components": "[]" + } + }, + "button12": { + "render": true, + "uiTitle": "Craft Item", + "clickEvent": "/craft", + "item": { + "id": "crafting_table", + "count": 1, + "components": "[]" + } + } + }, + "misc": { + "richPresence": { + "enableRichPresence": false, + "info": "LOCATION", + "cycleMode": false, + "customMessage": "Playing Skyblock" + } + } +} \ No newline at end of file