diff options
author | Kevinthegreat <92656833+kevinthegreat1@users.noreply.github.com> | 2023-06-30 18:39:32 +0800 |
---|---|---|
committer | Kevinthegreat <92656833+kevinthegreat1@users.noreply.github.com> | 2023-07-17 12:55:25 +0800 |
commit | 6e1dcf2861e6f084e75a9602cc270aaecb151bdc (patch) | |
tree | 1bc54f8557821b47681d7039f6d5c2cb745ca4da /src/main | |
parent | 04a598fa906928c0f706b0ce6cd3d3add30faed2 (diff) | |
download | Skyblocker-6e1dcf2861e6f084e75a9602cc270aaecb151bdc.tar.gz Skyblocker-6e1dcf2861e6f084e75a9602cc270aaecb151bdc.tar.bz2 Skyblocker-6e1dcf2861e6f084e75a9602cc270aaecb151bdc.zip |
Add shortcuts editing
Diffstat (limited to 'src/main')
4 files changed, 200 insertions, 44 deletions
diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/shortcut/Shortcuts.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/shortcut/Shortcuts.java index 2fbe4315..799eab7c 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/shortcut/Shortcuts.java +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/shortcut/Shortcuts.java @@ -14,6 +14,7 @@ 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; @@ -28,37 +29,48 @@ import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.lit 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.isDone(); + return shortcutsLoaded != null && shortcutsLoaded.isDone(); } public static void init() { - shortcutsLoaded = CompletableFuture.runAsync(Shortcuts::loadShortcuts); + loadShortcuts(); ClientLifecycleEvents.CLIENT_STOPPING.register(Shortcuts::saveShortcuts); ClientCommandRegistrationCallback.EVENT.register(Shortcuts::registerCommands); ClientSendMessageEvents.MODIFY_COMMAND.register(Shortcuts::modifyCommand); } - private static void loadShortcuts() { - 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.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.", e); - } catch (IOException e) { - LOGGER.error("[Skyblocker] Failed to load shortcuts file", e); + 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.", e); + } catch (IOException e) { + LOGGER.error("[Skyblocker] Failed to load shortcuts file", e); + } + }); } private static void registerDefaultShortcuts() { + commands.clear(); + commandArgs.clear(); commands.put("/s", "/skyblock"); commands.put("/sk", "/skyblock"); commands.put("/sky", "/skyblock"); @@ -156,7 +168,7 @@ public class Shortcuts { commands.put("/visit p", "/visit portalhub"); } - private static void saveShortcuts(MinecraftClient client) { + protected static void saveShortcuts(MinecraftClient client) { JsonObject shortcutsJson = new JsonObject(); shortcutsJson.add("commands", SkyblockerMod.GSON.toJsonTree(commands)); shortcutsJson.add("commandArgs", SkyblockerMod.GSON.toJsonTree(commandArgs)); @@ -183,15 +195,15 @@ public class Shortcuts { FabricClientCommandSource source = context.getSource(); String status = SkyblockerConfig.get().general.shortcuts.enableShortcuts && SkyblockerConfig.get().general.shortcuts.enableCommandShortcuts ? "§a§l (Enabled)" : "§c§l (Disabled)"; source.sendFeedback(Text.of("§e§lSkyblocker §fCommand Shortcuts" + status)); - if (!shortcutsLoaded.isDone()) { - source.sendFeedback(Text.of("§c§lShortcuts not loaded yet")); + 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 = SkyblockerConfig.get().general.shortcuts.enableShortcuts && SkyblockerConfig.get().general.shortcuts.enableCommandArgShortcuts ? "§a§l (Enabled)" : "§c§l (Disabled)"; source.sendFeedback(Text.of("§e§lSkyblocker §fCommand Argument Shortcuts" + status)); - if (!shortcutsLoaded.isDone()) { - source.sendFeedback(Text.of("§c§lShortcuts not loaded yet")); + 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())); } @@ -209,7 +221,7 @@ public class Shortcuts { private static String modifyCommand(String command) { if (Utils.isOnHypixel() && SkyblockerConfig.get().general.shortcuts.enableShortcuts) { - if (!shortcutsLoaded.isDone()) { + if (!isShortcutsLoaded()) { LOGGER.warn("[Skyblocker] Shortcuts not loaded yet, skipping shortcut for command: {}", command); return command; } diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/shortcut/ShortcutsConfigListWidget.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/shortcut/ShortcutsConfigListWidget.java index 893d9169..210f0bd6 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/shortcut/ShortcutsConfigListWidget.java +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/shortcut/ShortcutsConfigListWidget.java @@ -9,25 +9,35 @@ 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.ArrayList; import java.util.List; +import java.util.Map; +import java.util.Optional; public class ShortcutsConfigListWidget extends ElementListWidget<ShortcutsConfigListWidget.AbstractShortcutEntry> { - public ShortcutsConfigListWidget(MinecraftClient minecraftClient, int width, int height, int top, int bottom, int itemHeight) { + private final ShortcutsConfigScreen screen; + protected final List<ShortcutCategoryEntry> categories = 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); - ShortcutCategoryEntry commandCategory = new ShortcutCategoryEntry("skyblocker.shortcuts.targetCommand", "skyblocker.shortcuts.replacementCommand"); + this.screen = screen; + ShortcutCategoryEntry commandCategory = new ShortcutCategoryEntry("skyblocker.shortcuts.command.target", "skyblocker.shortcuts.command.replacement"); + categories.add(commandCategory); addEntry(commandCategory); if (!Shortcuts.isShortcutsLoaded()) { addEntry(new ShortcutLoadingEntry()); } else { - Shortcuts.commands.keySet().stream().sorted().forEach(commandTarget -> addEntry(new ShortcutEntry(commandTarget, Shortcuts.commands.get(commandTarget), commandCategory))); + Shortcuts.commands.keySet().stream().sorted().forEach(commandTarget -> addEntry(new ShortcutEntry(commandCategory, commandTarget, Shortcuts.commands.get(commandTarget)))); } - ShortcutCategoryEntry commandArgCategory = new ShortcutCategoryEntry("skyblocekr.shortcuts.targetCommandArg", "skyblocker.shortcuts.replacementCommandArg"); + ShortcutCategoryEntry commandArgCategory = new ShortcutCategoryEntry("skyblocker.shortcuts.commandArg.target", "skyblocker.shortcuts.commandArg.replacement", "skyblocker.shortcuts.commandArg.tooltip"); + categories.add(commandArgCategory); addEntry(commandArgCategory); if (!Shortcuts.isShortcutsLoaded()) { addEntry(new ShortcutLoadingEntry()); } else { - Shortcuts.commandArgs.keySet().stream().sorted().forEach(commandArgTarget -> addEntry(new ShortcutEntry(commandArgTarget, Shortcuts.commandArgs.get(commandArgTarget), commandArgCategory))); + Shortcuts.commandArgs.keySet().stream().sorted().forEach(commandArgTarget -> addEntry(new ShortcutEntry(commandArgCategory, commandArgTarget, Shortcuts.commandArgs.get(commandArgTarget)))); } } @@ -41,16 +51,62 @@ public class ShortcutsConfigListWidget extends ElementListWidget<ShortcutsConfig return super.getScrollbarPositionX() + 50; } - protected abstract static class AbstractShortcutEntry extends ElementListWidget.Entry<AbstractShortcutEntry> { + 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(); + } + + protected Map<String, String> getShortcutsMap(ShortcutCategoryEntry category) { + return switch (categories.indexOf(category)) { + case 0 -> Shortcuts.commands; + case 1 -> Shortcuts.commandArgs; + default -> throw new IllegalStateException("Unexpected category: " + category); + }; + } + + @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)); + getShortcutsMap(category).put("", ""); + }); + } + + @Override + protected boolean removeEntry(AbstractShortcutEntry entry) { + return super.removeEntry(entry); + } + + protected static abstract class AbstractShortcutEntry extends ElementListWidget.Entry<AbstractShortcutEntry> { } - private class ShortcutCategoryEntry extends AbstractShortcutEntry { + protected class ShortcutCategoryEntry extends AbstractShortcutEntry { private final Text targetName; private final Text replacementName; + @Nullable + private final Text tooltip; private ShortcutCategoryEntry(String targetName, String replacementName) { + this(targetName, replacementName, (Text) null); + } + + private ShortcutCategoryEntry(String targetName, String replacementName, String tooltip) { + this(targetName, replacementName, Text.translatable(tooltip)); + } + + private ShortcutCategoryEntry(String targetName, String replacementName, @Nullable Text tooltip) { this.targetName = Text.translatable(targetName); this.replacementName = Text.translatable(replacementName); + this.tooltip = tooltip; } @Override @@ -77,6 +133,9 @@ public class ShortcutsConfigListWidget extends ElementListWidget<ShortcutsConfig 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); + } } } @@ -84,7 +143,7 @@ public class ShortcutsConfigListWidget extends ElementListWidget<ShortcutsConfig private final Text text; private ShortcutLoadingEntry() { - this.text = Text.of("§c§lShortcuts not loaded yet"); + this.text = Text.translatable("skyblocker.shortcuts.notLoaded"); } @Override @@ -113,17 +172,32 @@ public class ShortcutsConfigListWidget extends ElementListWidget<ShortcutsConfig } } - private class ShortcutEntry extends AbstractShortcutEntry { + protected class ShortcutEntry extends AbstractShortcutEntry { private final List<TextFieldWidget> children; - private final TextFieldWidget target; - private final TextFieldWidget replacement; - - private ShortcutEntry(String target, String replacement, ShortcutCategoryEntry category) { - this.target = new TextFieldWidget(MinecraftClient.getInstance().textRenderer, width / 2 - 160, 5, 150, 20, category.targetName); - this.replacement = new TextFieldWidget(MinecraftClient.getInstance().textRenderer, width / 2 + 10, 5, 150, 20, category.replacementName); - this.target.setText(target); - this.replacement.setText(replacement); - children = List.of(this.target, this.replacement); + protected final ShortcutCategoryEntry category; + protected final TextFieldWidget target; + protected final TextFieldWidget replacement; + private String oldTarget; + + protected ShortcutEntry(ShortcutCategoryEntry category) { + this(category, "", ""); + } + + private ShortcutEntry(ShortcutCategoryEntry category, String targetString, String replacementString) { + 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); + oldTarget = targetString; + target.setText(targetString); + replacement.setText(replacementString); + target.setChangedListener(newTarget -> { + Map<String, String> map = getShortcutsMap(category); + map.remove(oldTarget); + map.put(newTarget, replacement.getText()); + oldTarget = newTarget; + }); + replacement.setChangedListener(newReplacement -> getShortcutsMap(category).put(target.getText(), newReplacement)); + children = List.of(target, replacement); } @Override diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/shortcut/ShortcutsConfigScreen.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/shortcut/ShortcutsConfigScreen.java index 2f020604..49581761 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/shortcut/ShortcutsConfigScreen.java +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/shortcut/ShortcutsConfigScreen.java @@ -1,18 +1,76 @@ package me.xmrvizzy.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 double scrollAmount; + public ShortcutsConfigScreen() { super(Text.translatable("skyblocker.shortcuts.config")); } @Override + public void setTooltip(Text tooltip) { + super.setTooltip(tooltip); + } + + @Override protected void init() { super.init(); - addDrawableChild(new ShortcutsConfigListWidget(client, width, height, 32, height - 32, 25)); + shortcutsConfigListWidget = new ShortcutsConfigListWidget(client, this, width, height, 32, height - 64, 25); + 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.target.getText() + " → " + shortcutEntry.replacement.getText()), 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) { + client.setScreen(null); + } + Shortcuts.loadShortcuts(); // Cancel changes by reloading shortcuts from disk + }).build()); + buttonDone = ButtonWidget.builder(ScreenTexts.DONE, button -> { + if (client != null) { + client.setScreen(null); + Shortcuts.saveShortcuts(client); // Save shortcuts to disk + } + }).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.getShortcutsMap(shortcutEntry.category).remove(shortcutEntry.target.getText()); + } + client.setScreen(this); // Re-inits the screen and creates a new instance of ShortcutsConfigListWidget + shortcutsConfigListWidget.setScrollAmount(scrollAmount); + } } @Override @@ -20,4 +78,10 @@ public class ShortcutsConfigScreen extends Screen { super.render(context, mouseX, mouseY, delta); context.drawCenteredTextWithShadow(this.textRenderer, this.title, this.width / 2, 16, 0xFFFFFF); } + + protected void updateButtons() { + buttonDelete.active = Shortcuts.isShortcutsLoaded() && shortcutsConfigListWidget.getSelectedOrNull() instanceof ShortcutsConfigListWidget.ShortcutEntry; + buttonNew.active = Shortcuts.isShortcutsLoaded() && shortcutsConfigListWidget.getCategory().isPresent(); + buttonDone.active = Shortcuts.isShortcutsLoaded(); + } } diff --git a/src/main/resources/assets/skyblocker/lang/en_us.json b/src/main/resources/assets/skyblocker/lang/en_us.json index d647c1e1..b907cf1b 100644 --- a/src/main/resources/assets/skyblocker/lang/en_us.json +++ b/src/main/resources/assets/skyblocker/lang/en_us.json @@ -35,7 +35,7 @@ "text.autoconfig.skyblocker.option.general.shortcuts.enableCommandShortcuts": "Enable Command Shortcuts", "text.autoconfig.skyblocker.option.general.shortcuts.enableCommandShortcuts.@Tooltip": "Shortcuts for commands consisting of only one word. Edit shortcuts with \"/skyblocker shortcuts\". Shortcuts must be enabled for this to take effect.", "text.autoconfig.skyblocker.option.general.shortcuts.enableCommandArgShortcuts": "Enable Command Argument Shortcuts", - "text.autoconfig.skyblocker.option.general.shortcuts.enableCommandArgShortcuts.@Tooltip": "Shortcuts that replace an argument/word of a command with multiple arguments/words. Edit shortcuts with \"/skyblocker shortcuts\". Shortcuts must be enabled for this to take effect.", + "text.autoconfig.skyblocker.option.general.shortcuts.enableCommandArgShortcuts.@Tooltip": "Shortcuts that replace one or more word(s)/argument(s) of a command which has multiple words/arguments. Edit shortcuts with \"/skyblocker shortcuts\". Shortcuts must be enabled for this to take effect.", "text.autoconfig.skyblocker.option.general.quicknav": "Quicknav", "text.autoconfig.skyblocker.option.general.quicknav.enableQuicknav": "Enable Quicknav", "text.autoconfig.skyblocker.option.general.backpackPreviewWithoutShift": "View backpack preview without holding Shift", @@ -274,8 +274,14 @@ "skyblocker.fairySouls.markAllFound": "Marked all fairy souls in the current island as found", "skyblocker.fairySouls.markAllMissing": "Marked all fairy souls in the current island as missing", "skyblocker.shortcuts.config": "Shortcuts Config", - "skyblocker.shortcuts.targetCommand": "Target Command", - "skyblocker.shortcuts.replacementCommand": "Replacement Command", - "skyblocekr.shortcuts.targetCommandArg": "Target Command Argument", - "skyblocker.shortcuts.replacementCommandArg": "Replacement Command Argument" + "skyblocker.shortcuts.notLoaded": "§c§lShortcuts not loaded yet", + "skyblocker.shortcuts.command.target": "Target Command", + "skyblocker.shortcuts.command.replacement": "Replacement Command", + "skyblocker.shortcuts.commandArg.target": "Target Command Argument", + "skyblocker.shortcuts.commandArg.replacement": "Replacement Command Argument", + "skyblocker.shortcuts.commandArg.tooltip": "Replace one or more word(s)/argument(s) of a command which has multiple words/arguments instead of matching the entire command.", + "skyblocker.shortcuts.deleteQuestion": "Are you sure you want to remove this shortcut?", + "skyblocker.shortcuts.deleteWarning": "Shortcut '%s' will be lost forever! (A long time!)", + "skyblocker.shortcuts.new": "New Shortcut", + "skyblocker.shortcuts.commandSuggestionTooltip": "Due to limitations of Minecraft, command suggestions will only work after a restart of the game." } |