aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/SkyblockerInitializer.java2
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java22
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/itemlist/Entry.java138
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/itemlist/ItemFixerUpper.java152
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/itemlist/ItemListWidget.java192
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/itemlist/ItemRegistry.java78
-rw-r--r--src/main/resources/skyblocker.mixins.json3
7 files changed, 586 insertions, 1 deletions
diff --git a/src/main/java/me/xmrvizzy/skyblocker/SkyblockerInitializer.java b/src/main/java/me/xmrvizzy/skyblocker/SkyblockerInitializer.java
index 93eac100..46cd0bb2 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/SkyblockerInitializer.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/SkyblockerInitializer.java
@@ -4,6 +4,7 @@ import me.xmrvizzy.skyblocker.config.SkyblockerConfig;
import me.xmrvizzy.skyblocker.skyblock.HotbarSlotLock;
import me.xmrvizzy.skyblocker.skyblock.item.PriceInfoTooltip;
import me.xmrvizzy.skyblocker.skyblock.item.WikiLookup;
+import me.xmrvizzy.skyblocker.skyblock.itemlist.ItemRegistry;
import net.fabricmc.api.ClientModInitializer;
public class SkyblockerInitializer implements ClientModInitializer {
@@ -13,5 +14,6 @@ public class SkyblockerInitializer implements ClientModInitializer {
SkyblockerConfig.init();
PriceInfoTooltip.init();
WikiLookup.init();
+ ItemRegistry.init();
}
}
diff --git a/src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java b/src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java
new file mode 100644
index 00000000..a1683701
--- /dev/null
+++ b/src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java
@@ -0,0 +1,22 @@
+package me.xmrvizzy.skyblocker.mixin;
+
+import me.xmrvizzy.skyblocker.skyblock.itemlist.ItemListWidget;
+import net.minecraft.client.gui.screen.Screen;
+import net.minecraft.client.gui.screen.ingame.HandledScreen;
+import net.minecraft.text.Text;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+@Mixin(HandledScreen.class)
+public abstract class HandledScreenMixin extends Screen {
+ protected HandledScreenMixin(Text title) {
+ super(title);
+ }
+
+ @Inject(method = "init()V", at = @At("TAIL"))
+ private void init(CallbackInfo ci) {
+ super.addDrawableChild(new ItemListWidget((HandledScreen)(Object)this));
+ }
+}
diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/itemlist/Entry.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/itemlist/Entry.java
new file mode 100644
index 00000000..4260aa4a
--- /dev/null
+++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/itemlist/Entry.java
@@ -0,0 +1,138 @@
+package me.xmrvizzy.skyblocker.skyblock.itemlist;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import net.minecraft.item.ItemStack;
+import net.minecraft.item.Items;
+import net.minecraft.nbt.*;
+import net.minecraft.text.Text;
+import net.minecraft.util.Pair;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public final class Entry implements Comparable<Entry> {
+ final ItemStack itemStack;
+ final String internalName;
+ final String familyName;
+ final int tierNumber;
+ final String clickCommand;
+
+ public Entry(JsonObject obj) {
+ this.internalName = obj.get("internalname").getAsString();
+ this.familyName = this.internalName.replaceAll(".(\\d+)$", "");
+ this.tierNumber = Integer.parseInt("0" + this.internalName.replaceAll("[^\\d]", ""));
+ String cmd = obj.get("clickcommand").getAsString();
+ this.clickCommand = cmd.isBlank() ? null : "/" + cmd + " " + this.internalName.replaceAll(";(\\d+)$", "");
+
+ List<Pair<String, String>> injectors = new ArrayList<>();
+ injectors.addAll(petData(internalName));
+
+ NbtCompound root = new NbtCompound();
+ root.put("Count", NbtByte.of((byte)1));
+
+ String id = obj.get("itemid").getAsString();
+ int damage = obj.get("damage").getAsInt();
+ root.put("id", NbtString.of(ItemFixerUpper.convert(id, damage)));
+
+ NbtCompound tag = new NbtCompound();
+ root.put("tag", tag);
+
+ if (internalName.contains("ENCHANTED")) {
+ NbtList enchantments = new NbtList();
+ enchantments.add(new NbtCompound());
+ tag.put("Enchantments", enchantments);
+ }
+
+ NbtCompound display = new NbtCompound();
+ tag.put("display", display);
+
+ String name = injectData(obj.get("displayname").getAsString(), injectors);
+ display.put("Name", NbtString.of(Text.Serializer.toJson(Text.of(name))));
+
+ NbtList lore = new NbtList();
+ display.put("Lore", lore);
+ obj.get("lore").getAsJsonArray().forEach(el ->
+ lore.add(NbtString.of(Text.Serializer.toJson(Text.of(injectData(el.getAsString(), injectors)))))
+ );
+
+ String nbttag = obj.get("nbttag").getAsString();
+ Matcher matcher = Pattern.compile("SkullOwner:\\{Id:\"(.{36})\",Properties:\\{textures:\\[0:\\{Value:\"(.+)\"\\}\\]\\}\\}").matcher(nbttag);
+ if (matcher.find()) {
+ NbtCompound skullOwner = new NbtCompound();
+ tag.put("SkullOwner", skullOwner);
+ UUID uuid = UUID.fromString(matcher.group(1));
+ skullOwner.put("Id", NbtHelper.fromUuid(uuid));
+ skullOwner.put("Name", NbtString.of(this.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(matcher.group(2)));
+ }
+
+ this.itemStack = ItemStack.fromNbt(root);
+ if (this.itemStack.getItem().equals(Items.AIR)) {
+ System.err.println("ItemList: cannot register: " + this.internalName + " (" + id + ")");
+ }
+ }
+
+ // TODO: fix stats for GOLDEN_DRAGON (lv1 -> lv200)
+ private static List<Pair<String, String>> petData(String internalName) {
+ List<Pair<String, String>> list = new ArrayList<>();
+
+ String petName = internalName.split(";")[0];
+ if (!internalName.contains(";") || !ItemRegistry.petNums.has(petName)) return list;
+
+ list.add(new Pair("\\{LVL\\}", "1 ➡ 100"));
+
+ final String[] rarities = {
+ "COMMON",
+ "UNCOMMON",
+ "RARE",
+ "EPIC",
+ "LEGENDARY",
+ "MYTHIC"
+ };
+ String rarity = rarities[Integer.parseInt(internalName.split(";")[1])];
+ JsonObject data = ItemRegistry.petNums.get(petName).getAsJsonObject().get(rarity).getAsJsonObject();
+
+ JsonObject statNumsMin = data.get("1").getAsJsonObject().get("statNums").getAsJsonObject();
+ JsonObject statNumsMax = data.get("100").getAsJsonObject().get("statNums").getAsJsonObject();
+ Set<Map.Entry<String, JsonElement>> entrySet = statNumsMin.entrySet();
+ for (Map.Entry<String, JsonElement> entry : entrySet) {
+ String key = entry.getKey();
+ String left = "\\{" + key+ "\\}";
+ String right = statNumsMin.get(key).getAsString() + " ➡ " + statNumsMax.get(key).getAsString();
+ list.add(new Pair(left, right));
+ }
+
+ JsonArray otherNumsMin = data.get("1").getAsJsonObject().get("otherNums").getAsJsonArray();
+ JsonArray otherNumsMax = data.get("100").getAsJsonObject().get("otherNums").getAsJsonArray();
+ for (int i = 0; i < otherNumsMin.size(); ++i) {
+ String left = "\\{" + i + "\\}";
+ String right = otherNumsMin.get(i).getAsString() + " ➡ " + otherNumsMax.get(i).getAsString();
+ list.add(new Pair(left, right));
+ }
+
+ return list;
+ }
+
+ private static String injectData(String string, List<Pair<String, String>> injectors) {
+ for (Pair<String, String> injector : injectors)
+ string = string.replaceAll(injector.getLeft(), injector.getRight());
+ return string;
+ }
+
+ @Override
+ public int compareTo(@NotNull Entry rhs) {
+ if (this.familyName.equals(rhs.familyName)) return this.tierNumber - rhs.tierNumber;
+ else return this.familyName.compareTo(rhs.familyName);
+ }
+}
diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/itemlist/ItemFixerUpper.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/itemlist/ItemFixerUpper.java
new file mode 100644
index 00000000..c0ba1262
--- /dev/null
+++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/itemlist/ItemFixerUpper.java
@@ -0,0 +1,152 @@
+package me.xmrvizzy.skyblocker.skyblock.itemlist;
+
+import net.minecraft.item.Items;
+import net.minecraft.util.Identifier;
+import net.minecraft.util.registry.Registry;
+
+import java.util.Map;
+
+public class ItemFixerUpper {
+ private final static Map<String, String> MAPPING = Map.ofEntries(
+ Map.entry("minecraft:golden_rail", "minecraft:powered_rail"),
+ Map.entry("minecraft:lit_pumpkin", "minecraft:jack_o_lantern"),
+ Map.entry("minecraft:snow_layer", "minecraft:snow"),
+ Map.entry("minecraft:hardened_clay", "minecraft:terracotta"),
+ Map.entry("minecraft:speckled_melon", "minecraft:glistering_melon_slice"),
+ Map.entry("minecraft:mob_spawner", "minecraft:spawner"),
+ Map.entry("minecraft:brick_block", "minecraft:bricks"),
+ Map.entry("minecraft:deadbush", "minecraft:dead_bush"),
+ Map.entry("minecraft:slime", "minecraft:slime_block"),
+ Map.entry("minecraft:melon_block", "minecraft:melon"),
+ Map.entry("minecraft:reeds", "minecraft:sugar_cane"),
+ Map.entry("minecraft:yellow_flower", "minecraft:dandelion"),
+ Map.entry("minecraft:firework_charge", "minecraft:firework_star"),
+ Map.entry("minecraft:noteblock", "minecraft:note_block"),
+ Map.entry("minecraft:web", "minecraft:cobweb"),
+ Map.entry("minecraft:fireworks", "minecraft:firework_rocket"),
+ Map.entry("minecraft:netherbrick", "minecraft:nether_brick"),
+ Map.entry("minecraft:stained_hardened_clay", "minecraft:terracotta"),
+ Map.entry("minecraft:quartz_ore", "minecraft:nether_quartz_ore"),
+ Map.entry("minecraft:skull", "minecraft:player_head"),
+ Map.entry("minecraft:fish", "minecraft:cod"),
+ Map.entry("minecraft:cooked_fish", "minecraft:cooked_cod"),
+ Map.entry("minecraft:red_flower", "minecraft:poppy"),
+ Map.entry("minecraft:tallgrass", "minecraft:grass"),
+ Map.entry("minecraft:stone_slab2", "minecraft:red_sandstone_slab"),
+ Map.entry("minecraft:waterlily", "minecraft:lily_pad")
+ );
+
+ private final static String[] DYE_COLORS = {
+ "minecraft:ink_sac",
+ "minecraft:red_dye",
+ "minecraft:green_dye",
+ "minecraft:cocoa_beans",
+ "minecraft:lapis_lazuli",
+ "minecraft:purple_dye",
+ "minecraft:cyan_dye",
+ "minecraft:light_gray_dye",
+ "minecraft:gray_dye",
+ "minecraft:pink_dye",
+ "minecraft:lime_dye",
+ "minecraft:yellow_dye",
+ "minecraft:light_blue_dye",
+ "minecraft:magenta_dye",
+ "minecraft:orange_dye",
+ "minecraft:bone_meal"
+ };
+
+ private final static String[] BLOCK_COLORS = {
+ "white_",
+ "orange_",
+ "magenta_",
+ "light_blue_",
+ "yellow_",
+ "lime_",
+ "pink_",
+ "gray_",
+ "light_gray_",
+ "cyan_",
+ "purple_",
+ "blue_",
+ "brown_",
+ "green_",
+ "red_",
+ "black_"
+ };
+
+ private final static String[] TREE_VARIANTS = {
+ "oak_",
+ "spruce_",
+ "birch_",
+ "jungle_",
+ "acacia_",
+ "dark_oak_"
+ };
+
+ private final static String[] STONE_BRICK_VARIANTS = {
+ "minecraft:stone_bricks",
+ "minecraft:mossy_stone_bricks",
+ "minecraft:cracked_stone_bricks",
+ "minecraft:chiseled_stone_bricks"
+ };
+
+ private final static String[] DOUBLE_PLANT_VARIANTS = {
+ "minecraft:sunflower",
+ "minecraft:lilac",
+ "minecraft:tall_grass",
+ "minecraft:large_fern",
+ "minecraft:rose_bush",
+ "minecraft:peony"
+ };
+
+ private final static Map<Integer, String> SPAWN_EGG_VARIANTS = Map.ofEntries(
+ Map.entry(50, "minecraft:creeper_spawn_egg"),
+ Map.entry(51, "minecraft:skeleton_spawn_egg"),
+ Map.entry(52, "minecraft:spider_spawn_egg"),
+ Map.entry(54, "minecraft:zombie_spawn_egg"),
+ Map.entry(55, "minecraft:slime_spawn_egg"),
+ Map.entry(56, "minecraft:ghast_spawn_egg"),
+ Map.entry(57, "minecraft:zombified_piglin_spawn_egg"),
+ Map.entry(58, "minecraft:enderman_spawn_egg"),
+ Map.entry(59, "minecraft:cave_spider_spawn_egg"),
+ Map.entry(60, "minecraft:silverfish_spawn_egg"),
+ Map.entry(61, "minecraft:blaze_spawn_egg"),
+ Map.entry(62, "minecraft:magma_cube_spawn_egg"),
+ Map.entry(65, "minecraft:bat_spawn_egg"),
+ Map.entry(66, "minecraft:witch_spawn_egg"),
+ Map.entry(67, "minecraft:endermite_spawn_egg"),
+ Map.entry(68, "minecraft:guardian_spawn_egg"),
+ Map.entry(90, "minecraft:pig_spawn_egg"),
+ Map.entry(91, "minecraft:sheep_spawn_egg"),
+ Map.entry(92, "minecraft:cow_spawn_egg"),
+ Map.entry(93, "minecraft:chicken_spawn_egg"),
+ Map.entry(94, "minecraft:squid_spawn_egg"),
+ Map.entry(95, "minecraft:wolf_spawn_egg"),
+ Map.entry(96, "minecraft:mooshroom_spawn_egg"),
+ Map.entry(98, "minecraft:ocelot_spawn_egg"),
+ Map.entry(100, "minecraft:horse_spawn_egg"),
+ Map.entry(101, "minecraft:rabbit_spawn_egg"),
+ Map.entry(120, "minecraft:villager_spawn_egg")
+ );
+
+ public static String convert(String id, int damage) {
+ if (id.equals("minecraft:dye")) return DYE_COLORS[damage];
+ if (id.equals("minecraft:log2")) return "minecraft:" + TREE_VARIANTS[damage + 4] + "log";
+ if (id.equals("minecraft:leaves2")) return "minecraft:" + TREE_VARIANTS[damage + 4] + "leaves";
+ if (id.equals("minecraft:stonebrick")) return STONE_BRICK_VARIANTS[damage];
+ if (id.equals("minecraft:double_plant")) return DOUBLE_PLANT_VARIANTS[damage];
+ if (id.equals("minecraft:spawn_egg")) return SPAWN_EGG_VARIANTS.getOrDefault(damage, "minecraft:ghast_spawn_egg");
+ if (id.equals("minecraft:banner")) return "minecraft:" + BLOCK_COLORS[15 - damage] + "banner";
+ id = MAPPING.getOrDefault(id, id);
+ if (Registry.ITEM.get(new Identifier(id)).equals(Items.AIR)) {
+ String shortId = id.split(":")[1];
+ if (damage < BLOCK_COLORS.length && !Registry.ITEM.get(new Identifier("minecraft:" + BLOCK_COLORS[damage] + shortId)).equals(Items.AIR))
+ return "minecraft:" + BLOCK_COLORS[damage] + shortId;
+ if (damage < TREE_VARIANTS.length && !Registry.ITEM.get(new Identifier("minecraft:" + TREE_VARIANTS[damage] + shortId)).equals(Items.AIR))
+ return "minecraft:" + TREE_VARIANTS[damage] + shortId;
+ if (id.contains("wooden_")) return id.replaceFirst("wooden_", TREE_VARIANTS[damage]);
+ if (id.contains("minecraft:record")) return id.replaceFirst("minecraft:record", "minecraft:music_disc");
+ }
+ return id;
+ }
+}
diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/itemlist/ItemListWidget.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/itemlist/ItemListWidget.java
new file mode 100644
index 00000000..f7e196d5
--- /dev/null
+++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/itemlist/ItemListWidget.java
@@ -0,0 +1,192 @@
+package me.xmrvizzy.skyblocker.skyblock.itemlist;
+
+import com.google.common.collect.Lists;
+import com.mojang.blaze3d.systems.RenderSystem;
+import net.fabricmc.api.EnvType;
+import net.fabricmc.api.Environment;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.gui.AbstractParentElement;
+import net.minecraft.client.gui.Drawable;
+import net.minecraft.client.gui.Element;
+import net.minecraft.client.gui.Selectable;
+import net.minecraft.client.gui.screen.ingame.HandledScreen;
+import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder;
+import net.minecraft.client.gui.widget.TextFieldWidget;
+import net.minecraft.client.render.item.ItemRenderer;
+import net.minecraft.client.util.math.MatrixStack;
+import net.minecraft.item.ItemStack;
+import net.minecraft.text.Text;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+@Environment(value= EnvType.CLIENT)
+public class ItemListWidget extends AbstractParentElement implements Drawable, Selectable {
+ private static final List<Entry> entries = new ArrayList<>();
+ private static String searchString = "";
+ private static double scroll = 0.0;
+
+ private final int gridX;
+ private final int gridY;
+ private final int rows;
+ private final int cols;
+
+ private double maxScroll;
+
+ private final HandledScreen screen;
+ private final MinecraftClient client;
+ private final List<Element> children = Lists.newArrayList();
+ private final List<Selectable> selectables = Lists.newArrayList();
+ private final List<Drawable> drawables = Lists.newArrayList();
+ private final TextFieldWidget search;
+
+ public ItemListWidget(HandledScreen screen) {
+ this.client = MinecraftClient.getInstance();
+ this.screen = screen;
+
+ this.cols = (screen.width - 200) / 2 / 16;
+ this.rows = (screen.height - 40) / 16;
+ this.gridX = 8;
+ this.gridY = 40;
+
+ this.maxScroll = Math.max(0, entries.size() / this.cols - this.rows + 1);
+
+ int searchX = this.gridX + 1;
+ int searchY = 18;
+ int searchWidth = this.cols * 16 - 2;
+ int searchHeight = 16;
+
+ this.search = new TextFieldWidget(this.client.textRenderer, searchX, searchY, searchWidth, searchHeight, Text.of("Search"));
+ this.search.setText(searchString);
+ this.search.setChangedListener(this::setSearch);
+ this.addDrawableChild(search);
+
+ this.setSearch(searchString);
+ }
+
+ private void setSearch(String search) {
+ searchString = search;
+ entries.clear();
+ search = search.toLowerCase();
+ for (Entry entry : ItemRegistry.registry) {
+ String name = entry.itemStack.getName().toString().toLowerCase();
+ String lore = entry.itemStack.getNbt().toString().toLowerCase();
+ if (name.contains(search) || lore.contains(search))
+ entries.add(entry);
+ }
+ this.maxScroll = Math.max(0, entries.size() / this.cols - this.rows + 1);
+ scroll = Math.min(scroll, this.maxScroll);
+ }
+
+ protected <T extends Element & Drawable & Selectable> T addDrawableChild(T drawableElement) {
+ this.drawables.add((Drawable)drawableElement);
+ return this.addSelectableChild(drawableElement);
+ }
+
+ protected <T extends Drawable> T addDrawable(T drawable) {
+ this.drawables.add(drawable);
+ return drawable;
+ }
+
+ protected <T extends Element & Selectable> T addSelectableChild(T child) {
+ this.children.add(child);
+ this.selectables.add((Selectable)child);
+ return child;
+ }
+
+ @Override
+ public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) {
+ ItemRenderer itemRenderer = client.getItemRenderer();
+ RenderSystem.disableDepthTest();
+ // search box title
+ client.textRenderer.drawWithShadow(matrices, "Search", this.gridX, 6, 0xff9e9e9e);
+ // slot hover
+ int mouseOverIndex = getMouseOverIndex(mouseX, mouseY);
+ if (mouseOverIndex != -1) {
+ int x = this.gridX + mouseOverIndex % this.cols * 16;
+ int y = this.gridY + (mouseOverIndex / this.cols - (int)scroll) * 16;
+ fill(matrices, x, y, x + 16, y + 16, 0x20ffffff);
+ }
+ // item list
+ for (int i = 0; i < rows; ++i)
+ for (int j = 0; j < cols; ++j) {
+ int index = (i + (int)scroll) * cols + j;
+ if (index < entries.size()) {
+ int x = gridX + j * 16;
+ int y = gridY + i * 16;
+ itemRenderer.renderInGui(entries.get(index).itemStack, x, y);
+ }
+ }
+ // item tooltip
+ if (mouseOverIndex != -1) {
+ ItemStack stack = entries.get(mouseOverIndex).itemStack;
+ List<Text> tooltip = this.screen.getTooltipFromItem(stack);
+ this.screen.renderTooltip(matrices, tooltip, mouseX, mouseY);
+ }
+ RenderSystem.enableDepthTest();
+ // render children
+ Iterator iter = this.drawables.iterator();
+ while(iter.hasNext()) {
+ Drawable drawable = (Drawable)iter.next();
+ drawable.render(matrices, mouseX, mouseY, delta);
+ }
+ }
+
+ private boolean isMouseOverList(double mouseX, double mouseY) {
+ return gridX <= mouseX && mouseX < gridX + cols * 16 && gridY <= mouseY && mouseY < gridY + rows * 16;
+ }
+
+ private int getMouseOverIndex(double mouseX, double mouseY) {
+ if (isMouseOverList(mouseX, mouseY)) {
+ int i = (int)(mouseY - this.gridY) / 16;
+ int j = (int)(mouseX - this.gridX) / 16;
+ int index = (i + (int)scroll) * this.cols + j;
+ if (index < entries.size()) return index;
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean mouseScrolled(double mouseX, double mouseY, double amount) {
+ if (super.mouseScrolled(mouseX, mouseY, amount)) {
+ return true;
+ } else if (this.isMouseOverList(mouseX, mouseY)) {
+ scroll = Math.min(this.maxScroll, Math.max(0.0, scroll - amount));
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
+ if (super.keyPressed(keyCode, scanCode, modifiers)) return true;
+ return this.getFocused() instanceof TextFieldWidget && ((TextFieldWidget) this.getFocused()).isFocused() && keyCode != 256;
+ }
+
+ @Override
+ public List<? extends Element> children() {
+ return this.children;
+ }
+
+ @Override
+ public boolean mouseClicked(double mouseX, double mouseY, int button) {
+ if (super.mouseClicked(mouseX, mouseY, button)) return true;
+ int index = getMouseOverIndex(mouseX, mouseY);
+ if (index != -1 && entries.get(index).clickCommand != null) {
+ this.client.player.sendChatMessage(entries.get(index).clickCommand);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void appendNarrations(NarrationMessageBuilder builder) {
+
+ }
+
+ @Override
+ public SelectionType getType() {
+ return SelectionType.NONE;
+ }
+}
diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/itemlist/ItemRegistry.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/itemlist/ItemRegistry.java
new file mode 100644
index 00000000..b94ea72d
--- /dev/null
+++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/itemlist/ItemRegistry.java
@@ -0,0 +1,78 @@
+package me.xmrvizzy.skyblocker.skyblock.itemlist;
+
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.errors.GitAPIException;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+public class ItemRegistry {
+ private static final String ITEM_REPO_URI = "https://github.com/KonaeAkira/NotEnoughUpdates-REPO.git";
+
+ private static final String ITEM_REPO_DIR = "./config/skypixel/items-repo/";
+ private static final String ITEM_LIST_DIR = ITEM_REPO_DIR + "items/";
+ private static final String CONSTANTS_DIR = ITEM_REPO_DIR + "constants/";
+ private static final String PETNUMS_FILE = CONSTANTS_DIR + "petnums.json";
+
+ private static final JsonParser JSON_PARSER = new JsonParser();
+
+ protected static SortedSet<Entry> registry = new TreeSet<Entry>();
+ protected static JsonObject petNums;
+
+ // TODO: make async
+ public static void init() {
+ updateItemRepo();
+ try {
+ petNums = JSON_PARSER.parse(Files.readString(Paths.get(PETNUMS_FILE))).getAsJsonObject();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ importItemFiles();
+ }
+
+ private static void updateItemRepo() {
+ if (!Files.isDirectory(Paths.get(ITEM_REPO_DIR))) {
+ try {
+ Git.cloneRepository()
+ .setURI(ITEM_REPO_URI)
+ .setDirectory(new File(ITEM_REPO_DIR))
+ .setBranchesToClone(Arrays.asList("refs/heads/master"))
+ .setBranch("refs/heads/master")
+ .call();
+ } catch (GitAPIException e) {
+ e.printStackTrace();
+ }
+ } else {
+ try {
+ Git.open(new File(ITEM_REPO_DIR)).pull().call();
+ } catch (GitAPIException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private static void importItemFiles() {
+ File dir = new File(ITEM_LIST_DIR);
+ File[] files = dir.listFiles();
+ for (File file : files) {
+ String path = ITEM_LIST_DIR + "/" + file.getName();
+ try {
+ String fileContent = Files.readString(Paths.get(path));
+ JsonObject json = JSON_PARSER.parse(fileContent).getAsJsonObject();
+ registry.add(new Entry(json));
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+}
+
diff --git a/src/main/resources/skyblocker.mixins.json b/src/main/resources/skyblocker.mixins.json
index abc219fa..6da4efb2 100644
--- a/src/main/resources/skyblocker.mixins.json
+++ b/src/main/resources/skyblocker.mixins.json
@@ -11,7 +11,8 @@
"AccessorWorldRenderer",
"GenericContainerScreenMixin",
"GenericContainerScreenHandlerMixin",
- "LeverBlockMixin"
+ "LeverBlockMixin",
+ "HandledScreenMixin"
],
"injectors": {
"defaultRequire": 1