aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/de/hysky/skyblocker/skyblock/shortcut
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/de/hysky/skyblocker/skyblock/shortcut')
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/shortcut/Shortcuts.java208
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/shortcut/ShortcutsConfigListWidget.java232
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/shortcut/ShortcutsConfigScreen.java113
3 files changed, 553 insertions, 0 deletions
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/shortcut/Shortcuts.java b/src/main/java/de/hysky/skyblocker/skyblock/shortcut/Shortcuts.java
new file mode 100644
index 00000000..9c058a4f
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/skyblock/shortcut/Shortcuts.java
@@ -0,0 +1,208 @@
+package de.hysky.skyblocker.skyblock.shortcut;
+
+import com.google.gson.JsonObject;
+import com.google.gson.reflect.TypeToken;
+import com.mojang.brigadier.Command;
+import com.mojang.brigadier.CommandDispatcher;
+import com.mojang.brigadier.arguments.StringArgumentType;
+import de.hysky.skyblocker.SkyblockerMod;
+import de.hysky.skyblocker.config.SkyblockerConfigManager;
+import de.hysky.skyblocker.utils.scheduler.Scheduler;
+import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
+import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
+import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents;
+import net.fabricmc.fabric.api.client.message.v1.ClientSendMessageEvents;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.command.CommandRegistryAccess;
+import net.minecraft.text.Text;
+import org.jetbrains.annotations.Nullable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.*;
+import java.lang.reflect.Type;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+
+import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.argument;
+import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal;
+
+public class Shortcuts {
+ private static final Logger LOGGER = LoggerFactory.getLogger(Shortcuts.class);
+ private static final File SHORTCUTS_FILE = SkyblockerMod.CONFIG_DIR.resolve("shortcuts.json").toFile();
+ @Nullable
+ private static CompletableFuture<Void> shortcutsLoaded;
+ public static final Map<String, String> commands = new HashMap<>();
+ public static final Map<String, String> commandArgs = new HashMap<>();
+
+ public static boolean isShortcutsLoaded() {
+ return shortcutsLoaded != null && shortcutsLoaded.isDone();
+ }
+
+ public static void init() {
+ loadShortcuts();
+ ClientLifecycleEvents.CLIENT_STOPPING.register(Shortcuts::saveShortcuts);
+ ClientCommandRegistrationCallback.EVENT.register(Shortcuts::registerCommands);
+ ClientSendMessageEvents.MODIFY_COMMAND.register(Shortcuts::modifyCommand);
+ }
+
+ protected static void loadShortcuts() {
+ if (shortcutsLoaded != null && !isShortcutsLoaded()) {
+ return;
+ }
+ shortcutsLoaded = CompletableFuture.runAsync(() -> {
+ try (BufferedReader reader = new BufferedReader(new FileReader(SHORTCUTS_FILE))) {
+ Type shortcutsType = new TypeToken<Map<String, Map<String, String>>>() {
+ }.getType();
+ Map<String, Map<String, String>> shortcuts = SkyblockerMod.GSON.fromJson(reader, shortcutsType);
+ commands.clear();
+ commandArgs.clear();
+ commands.putAll(shortcuts.get("commands"));
+ commandArgs.putAll(shortcuts.get("commandArgs"));
+ LOGGER.info("[Skyblocker] Loaded {} command shortcuts and {} command argument shortcuts", commands.size(), commandArgs.size());
+ } catch (FileNotFoundException e) {
+ registerDefaultShortcuts();
+ LOGGER.warn("[Skyblocker] Shortcuts file not found, using default shortcuts. This is normal when using for the first time.");
+ } catch (IOException e) {
+ LOGGER.error("[Skyblocker] Failed to load shortcuts file", e);
+ }
+ });
+ }
+
+ private static void registerDefaultShortcuts() {
+ commands.clear();
+ commandArgs.clear();
+
+ // Skyblock
+ commands.put("/s", "/skyblock");
+ commands.put("/i", "/is");
+ commands.put("/h", "/hub");
+
+ // Dungeon
+ commands.put("/d", "/warp dungeon_hub");
+
+ // Chat channels
+ commands.put("/ca", "/chat all");
+ commands.put("/cp", "/chat party");
+ commands.put("/cg", "/chat guild");
+ commands.put("/co", "/chat officer");
+ commands.put("/cc", "/chat coop");
+
+ // Message
+ commandArgs.put("/m", "/msg");
+
+ // Party
+ commandArgs.put("/pa", "/p accept");
+ commands.put("/pv", "/p leave");
+ commands.put("/pd", "/p disband");
+ commands.put("/rp", "/reparty");
+
+ // Visit
+ commandArgs.put("/v", "/visit");
+ commands.put("/vp", "/visit portalhub");
+ }
+
+ @SuppressWarnings("unused")
+ private static void registerMoreDefaultShortcuts() {
+ // Combat
+ commands.put("/spider", "/warp spider");
+ commands.put("/crimson", "/warp nether");
+ commands.put("/end", "/warp end");
+
+ // Mining
+ commands.put("/gold", "/warp gold");
+ commands.put("/cavern", "/warp deep");
+ commands.put("/dwarven", "/warp mines");
+ commands.put("/fo", "/warp forge");
+ commands.put("/ch", "/warp crystals");
+
+ // Foraging & Farming
+ commands.put("/park", "/warp park");
+ commands.put("/barn", "/warp barn");
+ commands.put("/desert", "/warp desert");
+ commands.put("/ga", "/warp garden");
+
+ // Other warps
+ commands.put("/castle", "/warp castle");
+ commands.put("/museum", "/warp museum");
+ commands.put("/da", "/warp da");
+ commands.put("/crypt", "/warp crypt");
+ commands.put("/nest", "/warp nest");
+ commands.put("/magma", "/warp magma");
+ commands.put("/void", "/warp void");
+ commands.put("/drag", "/warp drag");
+ commands.put("/jungle", "/warp jungle");
+ commands.put("/howl", "/warp howl");
+ }
+
+ protected static void saveShortcuts(MinecraftClient client) {
+ JsonObject shortcutsJson = new JsonObject();
+ shortcutsJson.add("commands", SkyblockerMod.GSON.toJsonTree(commands));
+ shortcutsJson.add("commandArgs", SkyblockerMod.GSON.toJsonTree(commandArgs));
+ try (BufferedWriter writer = new BufferedWriter(new FileWriter(SHORTCUTS_FILE))) {
+ SkyblockerMod.GSON.toJson(shortcutsJson, writer);
+ LOGGER.info("[Skyblocker] Saved {} command shortcuts and {} command argument shortcuts", commands.size(), commandArgs.size());
+ } catch (IOException e) {
+ LOGGER.error("[Skyblocker] Failed to save shortcuts file", e);
+ }
+ }
+
+ private static void registerCommands(CommandDispatcher<FabricClientCommandSource> dispatcher, CommandRegistryAccess registryAccess) {
+ for (String key : commands.keySet()) {
+ if (key.startsWith("/")) {
+ dispatcher.register(literal(key.substring(1)));
+ }
+ }
+ for (String key : commandArgs.keySet()) {
+ if (key.startsWith("/")) {
+ dispatcher.register(literal(key.substring(1)).then(argument("args", StringArgumentType.greedyString())));
+ }
+ }
+ dispatcher.register(literal(SkyblockerMod.NAMESPACE).then(literal("help").executes(context -> {
+ FabricClientCommandSource source = context.getSource();
+ String status = SkyblockerConfigManager.get().general.shortcuts.enableShortcuts && SkyblockerConfigManager.get().general.shortcuts.enableCommandShortcuts ? "§a§l (Enabled)" : "§c§l (Disabled)";
+ source.sendFeedback(Text.of("§e§lSkyblocker §fCommand Shortcuts" + status));
+ if (!isShortcutsLoaded()) {
+ source.sendFeedback(Text.translatable("skyblocker.shortcuts.notLoaded"));
+ } else for (Map.Entry<String, String> command : commands.entrySet()) {
+ source.sendFeedback(Text.of("§7" + command.getKey() + " §f→ §7" + command.getValue()));
+ }
+ status = SkyblockerConfigManager.get().general.shortcuts.enableShortcuts && SkyblockerConfigManager.get().general.shortcuts.enableCommandArgShortcuts ? "§a§l (Enabled)" : "§c§l (Disabled)";
+ source.sendFeedback(Text.of("§e§lSkyblocker §fCommand Argument Shortcuts" + status));
+ if (!isShortcutsLoaded()) {
+ source.sendFeedback(Text.translatable("skyblocker.shortcuts.notLoaded"));
+ } else for (Map.Entry<String, String> commandArg : commandArgs.entrySet()) {
+ source.sendFeedback(Text.of("§7" + commandArg.getKey() + " §f→ §7" + commandArg.getValue()));
+ }
+ source.sendFeedback(Text.of("§e§lSkyblocker §fCommands"));
+ for (String command : dispatcher.getSmartUsage(dispatcher.getRoot().getChild(SkyblockerMod.NAMESPACE), source).values()) {
+ source.sendFeedback(Text.of("§7/" + SkyblockerMod.NAMESPACE + " " + command));
+ }
+ return Command.SINGLE_SUCCESS;
+ // Queue the screen or else the screen will be immediately closed after executing this command
+ })).then(literal("shortcuts").executes(Scheduler.queueOpenScreenCommand(ShortcutsConfigScreen::new))));
+ }
+
+ private static String modifyCommand(String command) {
+ if (SkyblockerConfigManager.get().general.shortcuts.enableShortcuts) {
+ if (!isShortcutsLoaded()) {
+ LOGGER.warn("[Skyblocker] Shortcuts not loaded yet, skipping shortcut for command: {}", command);
+ return command;
+ }
+ command = '/' + command;
+ if (SkyblockerConfigManager.get().general.shortcuts.enableCommandShortcuts) {
+ command = commands.getOrDefault(command, command);
+ }
+ if (SkyblockerConfigManager.get().general.shortcuts.enableCommandArgShortcuts) {
+ String[] messageArgs = command.split(" ");
+ for (int i = 0; i < messageArgs.length; i++) {
+ messageArgs[i] = commandArgs.getOrDefault(messageArgs[i], messageArgs[i]);
+ }
+ command = String.join(" ", messageArgs);
+ }
+ return command.substring(1);
+ }
+ return command;
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/shortcut/ShortcutsConfigListWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/shortcut/ShortcutsConfigListWidget.java
new file mode 100644
index 00000000..5ebe4c1a
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/skyblock/shortcut/ShortcutsConfigListWidget.java
@@ -0,0 +1,232 @@
+package de.hysky.skyblocker.skyblock.shortcut;
+
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.gui.DrawContext;
+import net.minecraft.client.gui.Element;
+import net.minecraft.client.gui.Selectable;
+import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder;
+import net.minecraft.client.gui.screen.narration.NarrationPart;
+import net.minecraft.client.gui.widget.ElementListWidget;
+import net.minecraft.client.gui.widget.TextFieldWidget;
+import net.minecraft.text.Text;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+import java.util.stream.Stream;
+
+public class ShortcutsConfigListWidget extends ElementListWidget<ShortcutsConfigListWidget.AbstractShortcutEntry> {
+ private final ShortcutsConfigScreen screen;
+ private final List<Map<String, String>> shortcutMaps = new ArrayList<>();
+
+ public ShortcutsConfigListWidget(MinecraftClient minecraftClient, ShortcutsConfigScreen screen, int width, int height, int top, int bottom, int itemHeight) {
+ super(minecraftClient, width, height, top, bottom, itemHeight);
+ this.screen = screen;
+ ShortcutCategoryEntry commandCategory = new ShortcutCategoryEntry(Shortcuts.commands, "skyblocker.shortcuts.command.target", "skyblocker.shortcuts.command.replacement");
+ if (Shortcuts.isShortcutsLoaded()) {
+ commandCategory.shortcutsMap.keySet().stream().sorted().forEach(commandTarget -> addEntry(new ShortcutEntry(commandCategory, commandTarget)));
+ } else {
+ addEntry(new ShortcutLoadingEntry());
+ }
+ ShortcutCategoryEntry commandArgCategory = new ShortcutCategoryEntry(Shortcuts.commandArgs, "skyblocker.shortcuts.commandArg.target", "skyblocker.shortcuts.commandArg.replacement", "skyblocker.shortcuts.commandArg.tooltip");
+ if (Shortcuts.isShortcutsLoaded()) {
+ commandArgCategory.shortcutsMap.keySet().stream().sorted().forEach(commandArgTarget -> addEntry(new ShortcutEntry(commandArgCategory, commandArgTarget)));
+ } else {
+ addEntry(new ShortcutLoadingEntry());
+ }
+ }
+
+ @Override
+ public int getRowWidth() {
+ return super.getRowWidth() + 100;
+ }
+
+ @Override
+ protected int getScrollbarPositionX() {
+ return super.getScrollbarPositionX() + 50;
+ }
+
+ protected Optional<ShortcutCategoryEntry> getCategory() {
+ if (getSelectedOrNull() instanceof ShortcutCategoryEntry category) {
+ return Optional.of(category);
+ } else if (getSelectedOrNull() instanceof ShortcutEntry shortcutEntry) {
+ return Optional.of(shortcutEntry.category);
+ }
+ return Optional.empty();
+ }
+
+ @Override
+ public void setSelected(@Nullable ShortcutsConfigListWidget.AbstractShortcutEntry entry) {
+ super.setSelected(entry);
+ screen.updateButtons();
+ }
+
+ protected void addShortcutAfterSelected() {
+ getCategory().ifPresent(category -> children().add(children().indexOf(getSelectedOrNull()) + 1, new ShortcutEntry(category)));
+ }
+
+ @Override
+ protected boolean removeEntry(AbstractShortcutEntry entry) {
+ return super.removeEntry(entry);
+ }
+
+ protected boolean hasChanges() {
+ ShortcutEntry[] notEmptyShortcuts = getNotEmptyShortcuts().toArray(ShortcutEntry[]::new);
+ return notEmptyShortcuts.length != shortcutMaps.stream().mapToInt(Map::size).sum() || Arrays.stream(notEmptyShortcuts).anyMatch(ShortcutEntry::isChanged);
+ }
+
+ protected void saveShortcuts() {
+ shortcutMaps.forEach(Map::clear);
+ getNotEmptyShortcuts().forEach(ShortcutEntry::save);
+ Shortcuts.saveShortcuts(MinecraftClient.getInstance()); // Save shortcuts to disk
+ }
+
+ private Stream<ShortcutEntry> getNotEmptyShortcuts() {
+ return children().stream().filter(ShortcutEntry.class::isInstance).map(ShortcutEntry.class::cast).filter(ShortcutEntry::isNotEmpty);
+ }
+
+ protected static abstract class AbstractShortcutEntry extends ElementListWidget.Entry<AbstractShortcutEntry> {
+ }
+
+ private class ShortcutCategoryEntry extends AbstractShortcutEntry {
+ private final Map<String, String> shortcutsMap;
+ private final Text targetName;
+ private final Text replacementName;
+ @Nullable
+ private final Text tooltip;
+
+ private ShortcutCategoryEntry(Map<String, String> shortcutsMap, String targetName, String replacementName) {
+ this(shortcutsMap, targetName, replacementName, (Text) null);
+ }
+
+ private ShortcutCategoryEntry(Map<String, String> shortcutsMap, String targetName, String replacementName, String tooltip) {
+ this(shortcutsMap, targetName, replacementName, Text.translatable(tooltip));
+ }
+
+ private ShortcutCategoryEntry(Map<String, String> shortcutsMap, String targetName, String replacementName, @Nullable Text tooltip) {
+ this.shortcutsMap = shortcutsMap;
+ this.targetName = Text.translatable(targetName);
+ this.replacementName = Text.translatable(replacementName);
+ this.tooltip = tooltip;
+ shortcutMaps.add(shortcutsMap);
+ addEntry(this);
+ }
+
+ @Override
+ public List<? extends Element> children() {
+ return List.of();
+ }
+
+ @Override
+ public List<? extends Selectable> selectableChildren() {
+ return List.of(new Selectable() {
+ @Override
+ public SelectionType getType() {
+ return SelectionType.HOVERED;
+ }
+
+ @Override
+ public void appendNarrations(NarrationMessageBuilder builder) {
+ builder.put(NarrationPart.TITLE, targetName, replacementName);
+ }
+ });
+ }
+
+ @Override
+ public void render(DrawContext context, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) {
+ context.drawCenteredTextWithShadow(client.textRenderer, targetName, width / 2 - 85, y + 5, 0xFFFFFF);
+ context.drawCenteredTextWithShadow(client.textRenderer, replacementName, width / 2 + 85, y + 5, 0xFFFFFF);
+ if (tooltip != null && isMouseOver(mouseX, mouseY)) {
+ screen.setTooltip(tooltip);
+ }
+ }
+ }
+
+ private class ShortcutLoadingEntry extends AbstractShortcutEntry {
+ private final Text text;
+
+ private ShortcutLoadingEntry() {
+ this.text = Text.translatable("skyblocker.shortcuts.notLoaded");
+ }
+
+ @Override
+ public List<? extends Element> children() {
+ return List.of();
+ }
+
+ @Override
+ public List<? extends Selectable> selectableChildren() {
+ return List.of(new Selectable() {
+ @Override
+ public SelectionType getType() {
+ return SelectionType.HOVERED;
+ }
+
+ @Override
+ public void appendNarrations(NarrationMessageBuilder builder) {
+ builder.put(NarrationPart.TITLE, text);
+ }
+ });
+ }
+
+ @Override
+ public void render(DrawContext context, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) {
+ context.drawCenteredTextWithShadow(client.textRenderer, text, width / 2, y + 5, 0xFFFFFF);
+ }
+ }
+
+ protected class ShortcutEntry extends AbstractShortcutEntry {
+ private final List<TextFieldWidget> children;
+ private final ShortcutCategoryEntry category;
+ private final TextFieldWidget target;
+ private final TextFieldWidget replacement;
+
+ private ShortcutEntry(ShortcutCategoryEntry category) {
+ this(category, "");
+ }
+
+ private ShortcutEntry(ShortcutCategoryEntry category, String targetString) {
+ this.category = category;
+ target = new TextFieldWidget(MinecraftClient.getInstance().textRenderer, width / 2 - 160, 5, 150, 20, category.targetName);
+ replacement = new TextFieldWidget(MinecraftClient.getInstance().textRenderer, width / 2 + 10, 5, 150, 20, category.replacementName);
+ target.setText(targetString);
+ replacement.setText(category.shortcutsMap.getOrDefault(targetString, ""));
+ children = List.of(target, replacement);
+ }
+
+ @Override
+ public String toString() {
+ return target.getText() + " → " + replacement.getText();
+ }
+
+ @Override
+ public List<? extends Element> children() {
+ return children;
+ }
+
+ @Override
+ public List<? extends Selectable> selectableChildren() {
+ return children;
+ }
+
+ private boolean isNotEmpty() {
+ return !target.getText().isEmpty() && !replacement.getText().isEmpty();
+ }
+
+ private boolean isChanged() {
+ return !category.shortcutsMap.containsKey(target.getText()) || !category.shortcutsMap.get(target.getText()).equals(replacement.getText());
+ }
+
+ private void save() {
+ category.shortcutsMap.put(target.getText(), replacement.getText());
+ }
+
+ @Override
+ public void render(DrawContext context, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) {
+ target.setY(y);
+ replacement.setY(y);
+ target.render(context, mouseX, mouseY, tickDelta);
+ replacement.render(context, mouseX, mouseY, tickDelta);
+ context.drawCenteredTextWithShadow(client.textRenderer, "→", width / 2, y + 5, 0xFFFFFF);
+ }
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/shortcut/ShortcutsConfigScreen.java b/src/main/java/de/hysky/skyblocker/skyblock/shortcut/ShortcutsConfigScreen.java
new file mode 100644
index 00000000..196ad0d6
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/skyblock/shortcut/ShortcutsConfigScreen.java
@@ -0,0 +1,113 @@
+package de.hysky.skyblocker.skyblock.shortcut;
+
+import net.minecraft.client.gui.DrawContext;
+import net.minecraft.client.gui.screen.ConfirmScreen;
+import net.minecraft.client.gui.screen.Screen;
+import net.minecraft.client.gui.tooltip.Tooltip;
+import net.minecraft.client.gui.widget.ButtonWidget;
+import net.minecraft.client.gui.widget.GridWidget;
+import net.minecraft.client.gui.widget.SimplePositioningWidget;
+import net.minecraft.screen.ScreenTexts;
+import net.minecraft.text.Text;
+
+public class ShortcutsConfigScreen extends Screen {
+
+ private ShortcutsConfigListWidget shortcutsConfigListWidget;
+ private ButtonWidget buttonDelete;
+ private ButtonWidget buttonNew;
+ private ButtonWidget buttonDone;
+ private boolean initialized;
+ private double scrollAmount;
+ private final Screen parent;
+
+ public ShortcutsConfigScreen() {
+ this(null);
+ }
+
+ public ShortcutsConfigScreen(Screen parent) {
+ super(Text.translatable("skyblocker.shortcuts.config"));
+ this.parent = parent;
+ }
+
+ @Override
+ public void setTooltip(Text tooltip) {
+ super.setTooltip(tooltip);
+ }
+
+ @Override
+ protected void init() {
+ super.init();
+ if (initialized) {
+ shortcutsConfigListWidget.updateSize(width, height, 32, height - 64);
+ } else {
+ shortcutsConfigListWidget = new ShortcutsConfigListWidget(client, this, width, height, 32, height - 64, 25);
+ initialized = true;
+ }
+ addDrawableChild(shortcutsConfigListWidget);
+ GridWidget gridWidget = new GridWidget();
+ gridWidget.getMainPositioner().marginX(5).marginY(2);
+ GridWidget.Adder adder = gridWidget.createAdder(2);
+ buttonDelete = ButtonWidget.builder(Text.translatable("selectServer.delete"), button -> {
+ if (client != null && shortcutsConfigListWidget.getSelectedOrNull() instanceof ShortcutsConfigListWidget.ShortcutEntry shortcutEntry) {
+ scrollAmount = shortcutsConfigListWidget.getScrollAmount();
+ client.setScreen(new ConfirmScreen(this::deleteEntry, Text.translatable("skyblocker.shortcuts.deleteQuestion"), Text.translatable("skyblocker.shortcuts.deleteWarning", shortcutEntry), Text.translatable("selectServer.deleteButton"), ScreenTexts.CANCEL));
+ }
+ }).build();
+ adder.add(buttonDelete);
+ buttonNew = ButtonWidget.builder(Text.translatable("skyblocker.shortcuts.new"), buttonNew -> shortcutsConfigListWidget.addShortcutAfterSelected()).build();
+ adder.add(buttonNew);
+ adder.add(ButtonWidget.builder(ScreenTexts.CANCEL, button -> {
+ if (client != null) {
+ close();
+ }
+ }).build());
+ buttonDone = ButtonWidget.builder(ScreenTexts.DONE, button -> {
+ shortcutsConfigListWidget.saveShortcuts();
+ if (client != null) {
+ close();
+ }
+ }).tooltip(Tooltip.of(Text.translatable("skyblocker.shortcuts.commandSuggestionTooltip"))).build();
+ adder.add(buttonDone);
+ gridWidget.refreshPositions();
+ SimplePositioningWidget.setPos(gridWidget, 0, this.height - 64, this.width, 64);
+ gridWidget.forEachChild(this::addDrawableChild);
+ updateButtons();
+ }
+
+ private void deleteEntry(boolean confirmedAction) {
+ if (client != null) {
+ if (confirmedAction && shortcutsConfigListWidget.getSelectedOrNull() instanceof ShortcutsConfigListWidget.ShortcutEntry shortcutEntry) {
+ shortcutsConfigListWidget.removeEntry(shortcutEntry);
+ }
+ client.setScreen(this); // Re-inits the screen and keeps the old instance of ShortcutsConfigListWidget
+ shortcutsConfigListWidget.setScrollAmount(scrollAmount);
+ }
+ }
+
+ @Override
+ public void render(DrawContext context, int mouseX, int mouseY, float delta) {
+ super.render(context, mouseX, mouseY, delta);
+ context.drawCenteredTextWithShadow(this.textRenderer, this.title, this.width / 2, 16, 0xFFFFFF);
+ }
+
+ @Override
+ public void close() {
+ if (client != null && shortcutsConfigListWidget.hasChanges()) {
+ client.setScreen(new ConfirmScreen(confirmedAction -> {
+ if (confirmedAction) {
+ this.client.setScreen(parent);
+ } else {
+ client.setScreen(this);
+ }
+ }, Text.translatable("text.skyblocker.quit_config"), Text.translatable("text.skyblocker.quit_config_sure"), Text.translatable("text.skyblocker.quit_discard"), ScreenTexts.CANCEL));
+ } else {
+ this.client.setScreen(parent);
+ }
+ }
+
+ protected void updateButtons() {
+ buttonDelete.active = Shortcuts.isShortcutsLoaded() && shortcutsConfigListWidget.getSelectedOrNull() instanceof ShortcutsConfigListWidget.ShortcutEntry;
+ buttonNew.active = Shortcuts.isShortcutsLoaded() && shortcutsConfigListWidget.getCategory().isPresent();
+ buttonDone.active = Shortcuts.isShortcutsLoaded();
+ }
+}