From a27bb63dae78569af1fab0dd077dcd4af85f58af Mon Sep 17 00:00:00 2001 From: Jerozgen Date: Sat, 21 Jan 2023 16:35:39 +0300 Subject: [PATCH 1/4] Create a new branch for 1.19.3 --- .github/workflows/publish.yml | 4 +++- src/main/resources/fabric.mod.json | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 747058d..3b0ce55 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -39,7 +39,9 @@ jobs: dependencies: | fabric-api | depends | * modmenu | suggests | * - version-resolver: latest + game-versions: | + 1.19.3 + version-resolver: exact github-token: ${{ secrets.GITHUB_TOKEN }} github-files-primary: build/libs/*-@(dev|sources|javadoc).jar diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index e8c8d50..e0976bd 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -41,7 +41,7 @@ "depends": { "fabric-resource-loader-v0": "*", "fabricloader": ">=0.14.6", - "minecraft": ">=1.19.3", + "minecraft": "1.19.3", "java": ">=17" }, "suggests": { From 6fcb733dc7008c327c3147a8901a023cf6b59ba0 Mon Sep 17 00:00:00 2001 From: Jerozgen Date: Fri, 10 Mar 2023 02:44:40 +0300 Subject: [PATCH 2/4] Update to 1.19.4, add keyboard navigation --- build.gradle | 4 +- gradle.properties | 12 +- .../languagereload/LanguageReload.java | 9 +- .../access/ILanguageOptionsScreen.java | 10 ++ .../languagereload/gui/LanguageEntry.java | 100 ++++++++------ .../gui/LanguageListWidget.java | 103 +++++++++++--- .../gui/LockedLanguageEntry.java | 25 ++-- .../gui/MovableLanguageEntry.java | 91 +++++++----- .../mixin/EntryListWidgetAccessor.java | 11 ++ .../languagereload/mixin/KeyboardMixin.java | 38 ++--- .../mixin/LanguageManagerMixin.java | 19 ++- .../mixin/LanguageOptionsScreenMixin.java | 130 ++++++++++-------- .../mixin/RecipeBookWidgetMixin.java | 14 +- .../mixin/TranslationStorageMixin.java | 9 +- src/main/resources/fabric.mod.json | 5 +- .../resources/languagereload.accesswidener | 2 + src/main/resources/languagereload.mixins.json | 1 + 17 files changed, 360 insertions(+), 223 deletions(-) create mode 100644 src/main/java/jerozgen/languagereload/access/ILanguageOptionsScreen.java create mode 100644 src/main/java/jerozgen/languagereload/mixin/EntryListWidgetAccessor.java diff --git a/build.gradle b/build.gradle index e3fb4f8..2e82a4b 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ plugins { - id 'fabric-loom' version '1.0-SNAPSHOT' - id 'io.github.juuxel.loom-quiltflower' version '1.7.4' + id 'fabric-loom' version '1.1.9' + id 'io.github.juuxel.loom-quiltflower' version '1.8.0' id 'maven-publish' } diff --git a/gradle.properties b/gradle.properties index e640696..5225ff5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,15 +3,15 @@ org.gradle.jvmargs=-Xmx1G # Fabric Properties # check these on https://modmuss50.me/fabric.html -minecraft_version=1.19.3 -yarn_mappings=1.19.3+build.5 -loader_version=0.14.12 -fabric_version=0.72.0+1.19.3 +minecraft_version=1.19.4-rc1 +yarn_mappings=1.19.4-rc1+build.1 +loader_version=0.14.17 +fabric_version=0.75.3+1.19.4 # Mod Properties -mod_version=1.5.4+1.19.3 +mod_version=1.5.4+1.19.4 maven_group=jerozgen archives_base_name=language-reload # Dependencies -modmenu_version=5.0.2 +modmenu_version=6.1.0-beta.3 diff --git a/src/main/java/jerozgen/languagereload/LanguageReload.java b/src/main/java/jerozgen/languagereload/LanguageReload.java index e79e425..ccac5c5 100644 --- a/src/main/java/jerozgen/languagereload/LanguageReload.java +++ b/src/main/java/jerozgen/languagereload/LanguageReload.java @@ -9,7 +9,6 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.advancement.AdvancementsScreen; import net.minecraft.client.gui.screen.ingame.BookScreen; -import net.minecraft.client.resource.language.LanguageDefinition; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -59,7 +58,7 @@ public static void reloadSearch() { ((MinecraftClientAccessor) client).getSearchManager().reload(client.getResourceManager()); } - public static void setLanguage(LanguageDefinition language, LinkedList fallbacks) { + public static void setLanguage(String language, LinkedList fallbacks) { var client = MinecraftClient.getInstance(); var languageManager = client.getLanguageManager(); var config = Config.getInstance(); @@ -68,14 +67,14 @@ public static void setLanguage(LanguageDefinition language, LinkedList f var fallbacksAreSame = config.fallbacks.equals(fallbacks); if (languageIsSame && fallbacksAreSame) return; - config.previousLanguage = languageManager.getLanguage().getCode(); + config.previousLanguage = languageManager.getLanguage(); config.previousFallbacks = config.fallbacks; - config.language = language.getCode(); + config.language = language; config.fallbacks = fallbacks; Config.save(); languageManager.setLanguage(language); - client.options.language = language.getCode(); + client.options.language = language; client.options.write(); reloadLanguages(); diff --git a/src/main/java/jerozgen/languagereload/access/ILanguageOptionsScreen.java b/src/main/java/jerozgen/languagereload/access/ILanguageOptionsScreen.java new file mode 100644 index 0000000..dfa62ea --- /dev/null +++ b/src/main/java/jerozgen/languagereload/access/ILanguageOptionsScreen.java @@ -0,0 +1,10 @@ +package jerozgen.languagereload.access; + +import jerozgen.languagereload.gui.LanguageEntry; +import jerozgen.languagereload.gui.LanguageListWidget; + +public interface ILanguageOptionsScreen { + void focusList(LanguageListWidget list); + + void focusEntry(LanguageEntry entry); +} diff --git a/src/main/java/jerozgen/languagereload/gui/LanguageEntry.java b/src/main/java/jerozgen/languagereload/gui/LanguageEntry.java index e2b99e3..1f7a6eb 100644 --- a/src/main/java/jerozgen/languagereload/gui/LanguageEntry.java +++ b/src/main/java/jerozgen/languagereload/gui/LanguageEntry.java @@ -1,96 +1,112 @@ package jerozgen.languagereload.gui; import jerozgen.languagereload.LanguageReload; +import jerozgen.languagereload.access.ILanguageOptionsScreen; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawableHelper; -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.AlwaysSelectedEntryListWidget; import net.minecraft.client.gui.widget.ButtonWidget; import net.minecraft.client.gui.widget.ClickableWidget; -import net.minecraft.client.gui.widget.ElementListWidget; +import net.minecraft.client.gui.widget.TexturedButtonWidget; import net.minecraft.client.resource.language.LanguageDefinition; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.Text; import net.minecraft.util.Identifier; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; +import java.util.*; -public abstract class LanguageEntry extends ElementListWidget.Entry { +public abstract class LanguageEntry extends AlwaysSelectedEntryListWidget.Entry { protected static final Identifier TEXTURE = new Identifier(LanguageReload.MOD_ID, "textures/gui/language_selection.png"); protected static final int TEXTURE_WIDTH = 64; protected static final int TEXTURE_HEIGHT = 64; protected static final int HOVERED_V_OFFSET = 24; - private final static int SCROLLBAR_WIDTH = 6; - private final static int LEFT_MARGIN = 2; - private final static int ENTRY_HEIGHT = 24; - protected final MinecraftClient client = MinecraftClient.getInstance(); + + protected final String code; protected final LanguageDefinition language; - protected final LinkedList selectedLanguages; + protected final LinkedList selectedLanguages; protected final Runnable refreshListsAction; private final List buttons = new ArrayList<>(); - public LanguageEntry(Runnable refreshListsAction, LanguageDefinition language, LinkedList selectedLanguages) { + protected LanguageListWidget parentList; + + public LanguageEntry(Runnable refreshListsAction, String code, LanguageDefinition language, LinkedList selectedLanguages) { + this.code = code; this.language = language; this.selectedLanguages = selectedLanguages; this.refreshListsAction = refreshListsAction; } - protected ButtonWidget addChild(ButtonWidget button) { + protected ButtonWidget addButton(int width, int height, int u, int v, ButtonWidget.PressAction action) { + return addButton(width, height, u, v, HOVERED_V_OFFSET, action); + } + + protected ButtonWidget addButton(int width, int height, int u, int v, int hoveredVOffset, ButtonWidget.PressAction action) { + var button = new TexturedButtonWidget(0, 0, width, height, u, v, hoveredVOffset, TEXTURE, TEXTURE_WIDTH, TEXTURE_HEIGHT, action); button.visible = false; buttons.add(button); return button; } - protected abstract void renderButtons(ButtonRenderer buttonRenderer, int top, int left); + public void toggle() {} - public LanguageDefinition getLanguage() { - return language; - } + public void moveUp() {} + + public void moveDown() {} + + protected abstract void renderButtons(ButtonRenderer buttonRenderer, int x, int y); @Override - public void render(MatrixStack matrices, int index, int top, int left, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) { - if (client.options.getTouchscreen().getValue() || hovered) { - if (hovered) { - var right = left + entryWidth - SCROLLBAR_WIDTH - LEFT_MARGIN; - DrawableHelper.fill(matrices, left, top, right, top + ENTRY_HEIGHT, 0xA0909090); - } + public void render(MatrixStack matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) { + x -= 2; + y -= 2; + if (hovered || isFocused() || client.options.getTouchscreen().getValue()) { + DrawableHelper.fill(matrices, + x + 1, y + 1, x + entryWidth - 1, y + entryHeight + 3, + (hovered || isFocused()) ? 0xA0909090 : 0x50909090); buttons.forEach(button -> button.visible = false); - ButtonRenderer buttonRenderer = (button, x, y) -> { - button.setX(x); - button.setY(y); + renderButtons((button, buttonX, buttonY) -> { + button.setX(buttonX); + button.setY(buttonY); button.visible = true; button.render(matrices, mouseX, mouseY, tickDelta); - }; - renderButtons(buttonRenderer, top, left); + }, x, y); } - client.textRenderer.drawWithShadow(matrices, language.getName(), left + 29, top + 3, 0xFFFFFF); - client.textRenderer.drawWithShadow(matrices, language.getRegion(), left + 29, top + 14, 0x808080); + client.textRenderer.drawWithShadow(matrices, language.name(), x + 29, y + 3, 0xFFFFFF); + client.textRenderer.drawWithShadow(matrices, language.region(), x + 29, y + 14, 0x808080); } - public void appendNarrations(NarrationMessageBuilder builder) { - builder.put(NarrationPart.TITLE, Text.translatable("narrator.select", language)); + @Override + public Text getNarration() { + return Text.translatable("narrator.select", language.getDisplayText()); } @Override - public boolean changeFocus(boolean lookForwards) { + public boolean mouseClicked(double mouseX, double mouseY, int button) { + for (var widget : buttons) + if (widget.mouseClicked(mouseX, mouseY, button)) { + ((ILanguageOptionsScreen) parentList.getScreen()).focusList(parentList); + return true; + } return false; } - @Override - public List children() { - return buttons; + public void setParent(LanguageListWidget list) { + this.parentList = list; } - @Override - public List selectableChildren() { - return buttons; + public LanguageListWidget getParent() { + return parentList; + } + + public String getCode() { + return code; + } + + public LanguageDefinition getLanguage() { + return language; } @FunctionalInterface diff --git a/src/main/java/jerozgen/languagereload/gui/LanguageListWidget.java b/src/main/java/jerozgen/languagereload/gui/LanguageListWidget.java index 98729c6..d69ee2b 100644 --- a/src/main/java/jerozgen/languagereload/gui/LanguageListWidget.java +++ b/src/main/java/jerozgen/languagereload/gui/LanguageListWidget.java @@ -1,27 +1,36 @@ package jerozgen.languagereload.gui; +import jerozgen.languagereload.access.ILanguageOptionsScreen; +import jerozgen.languagereload.mixin.EntryListWidgetAccessor; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; -import net.minecraft.client.gui.widget.ElementListWidget; -import net.minecraft.client.render.Tessellator; +import net.minecraft.client.gui.ParentElement; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screen.option.LanguageOptionsScreen; +import net.minecraft.client.gui.widget.AlwaysSelectedEntryListWidget; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.Text; import net.minecraft.util.Formatting; +import net.minecraft.util.math.MathHelper; +import org.jetbrains.annotations.Nullable; -public class LanguageListWidget extends ElementListWidget { +import static org.lwjgl.glfw.GLFW.*; + +public class LanguageListWidget extends AlwaysSelectedEntryListWidget { private final Text title; + private final LanguageOptionsScreen screen; - public LanguageListWidget(MinecraftClient client, int width, int height, Text title) { + public LanguageListWidget(MinecraftClient client, LanguageOptionsScreen screen, int width, int height, Text title) { super(client, width, height, 48, height - 55 + 4, 24); this.title = title; + this.screen = screen; - setRenderHeader(true, (int) (9.0f * 1.5f)); + setRenderHeader(true, (int) (9f * 1.5f)); centerListVertically = false; } @Override - protected void renderHeader(MatrixStack matrices, int x, int y, Tessellator tessellator) { + protected void renderHeader(MatrixStack matrices, int x, int y) { var headerText = title.copy().formatted(Formatting.UNDERLINE, Formatting.BOLD); int headerPosX = x + width / 2 - client.textRenderer.getWidth(headerText) / 2; int headerPosY = Math.min(top + 3, y); @@ -29,8 +38,75 @@ protected void renderHeader(MatrixStack matrices, int x, int y, Tessellator tess } @Override - public int getRowTop(int index) { - return super.getRowTop(index); + public boolean keyPressed(int keyCode, int scanCode, int modifiers) { + var selectedEntry = this.getSelectedOrNull(); + if (selectedEntry == null) return super.keyPressed(keyCode, scanCode, modifiers); + + if (keyCode == GLFW_KEY_SPACE || keyCode == GLFW_KEY_ENTER) { + selectedEntry.toggle(); + this.setFocused(null); + ((ILanguageOptionsScreen) screen).focusEntry(selectedEntry); + return true; + } + + if (Screen.hasShiftDown()) { + if (keyCode == GLFW_KEY_DOWN) { + selectedEntry.moveDown(); + return true; + } + if (keyCode == GLFW_KEY_UP) { + selectedEntry.moveUp(); + return true; + } + } + + return super.keyPressed(keyCode, scanCode, modifiers); + } + + // Remove focusing on entry click + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + this.updateScrollingState(mouseX, mouseY, button); + if (!this.isMouseOver(mouseX, mouseY)) return false; + + var entry = this.getEntryAtPosition(mouseX, mouseY); + if (entry == null && button == 0) return true; + + if (entry != null && entry.mouseClicked(mouseX, mouseY, button)) { + var focusedEntry = this.getFocused(); + if (focusedEntry != entry && focusedEntry instanceof ParentElement parentElement) + parentElement.setFocused(null); + this.setDragging(true); + return true; + } + + return ((EntryListWidgetAccessor) this).isScrolling(); + } + + @Override + @Nullable + protected LanguageEntry getEntryAtPosition(double x, double y) { + int halfRowWidth = this.getRowWidth() / 2; + int center = left + width / 2; + int minX = center - halfRowWidth; + int maxX = center + halfRowWidth; + var scrollbarPositionX = this.getScrollbarPositionX(); + int m = MathHelper.floor(y - top) - headerHeight + (int) this.getScrollAmount() - 4 + 2; + int entryIndex = m / itemHeight; + return (x < scrollbarPositionX && x >= minX && x <= maxX && entryIndex >= 0 && m >= 0 + && entryIndex < this.getEntryCount() ? this.children().get(entryIndex) : null); + } + + public LanguageOptionsScreen getScreen() { + return screen; + } + + public int getBottom() { + return bottom; + } + + public int getRowHeight() { + return itemHeight; } @Override @@ -42,13 +118,4 @@ public int getRowWidth() { protected int getScrollbarPositionX() { return right - 6; } - - @Override - public void appendNarrations(NarrationMessageBuilder builder) { - var hoveredEntry = getHoveredEntry(); - if (hoveredEntry != null) { - appendNarrations(builder.nextMessage(), hoveredEntry); - hoveredEntry.appendNarrations(builder); - } - } } diff --git a/src/main/java/jerozgen/languagereload/gui/LockedLanguageEntry.java b/src/main/java/jerozgen/languagereload/gui/LockedLanguageEntry.java index 6881bfd..08e734a 100644 --- a/src/main/java/jerozgen/languagereload/gui/LockedLanguageEntry.java +++ b/src/main/java/jerozgen/languagereload/gui/LockedLanguageEntry.java @@ -2,26 +2,35 @@ import net.minecraft.client.gui.tooltip.Tooltip; import net.minecraft.client.gui.widget.ButtonWidget; -import net.minecraft.client.gui.widget.TexturedButtonWidget; import net.minecraft.client.resource.language.LanguageDefinition; import net.minecraft.text.Text; +import org.joml.Vector2i; import java.util.LinkedList; public class LockedLanguageEntry extends LanguageEntry { - private final Text LOCK_BUTTON_TOOLTIP = Text.translatable("language.default.tooltip"); + private static final Text LOCK_BUTTON_TOOLTIP = Text.translatable("language.default.tooltip"); - private final ButtonWidget lockButton = addChild(new TexturedButtonWidget(0, 0, 16, 24, 43, 0, 0, - TEXTURE, TEXTURE_WIDTH, TEXTURE_HEIGHT, __ -> {})); + private final ButtonWidget lockButton = addButton(16, 24, 43, 0, 0, __ -> {}); - public LockedLanguageEntry(Runnable refreshListsAction, LanguageDefinition language, LinkedList selectedLanguages) { - super(refreshListsAction, language, selectedLanguages); + public LockedLanguageEntry(Runnable refreshListsAction, String code, LanguageDefinition language, LinkedList selectedLanguages) { + super(refreshListsAction, code, language, selectedLanguages); lockButton.active = false; lockButton.setTooltip(Tooltip.of(LOCK_BUTTON_TOOLTIP)); } @Override - protected void renderButtons(ButtonRenderer buttonRenderer, int top, int left) { - buttonRenderer.render(lockButton, left + 6, top); + protected void renderButtons(ButtonRenderer renderer, int x, int y) { + renderer.render(lockButton, x + 6, y); + if (this.isFocused()) { + var tooltip = client.textRenderer.wrapLines(LOCK_BUTTON_TOOLTIP, parentList.getRowWidth() - 6); + parentList.getScreen().setTooltip(tooltip, (screen, mouseX, mouseY, width, height) -> { + var pos = new Vector2i(x + 3, y + parentList.getRowHeight() + 4); + if (pos.y > parentList.getBottom() + 2 || pos.y + height + 5 > screen.height) { + pos.y = y - height - 6; + } + return pos; + }, true); + } } } diff --git a/src/main/java/jerozgen/languagereload/gui/MovableLanguageEntry.java b/src/main/java/jerozgen/languagereload/gui/MovableLanguageEntry.java index f11d1e6..5839425 100644 --- a/src/main/java/jerozgen/languagereload/gui/MovableLanguageEntry.java +++ b/src/main/java/jerozgen/languagereload/gui/MovableLanguageEntry.java @@ -1,53 +1,76 @@ package jerozgen.languagereload.gui; import net.minecraft.client.gui.widget.ButtonWidget; -import net.minecraft.client.gui.widget.TexturedButtonWidget; import net.minecraft.client.resource.language.LanguageDefinition; import java.util.LinkedList; public class MovableLanguageEntry extends LanguageEntry { - private final ButtonWidget addButton = addChild(createButton(15, 24, 0, 0, __ -> { - selectedLanguages.add(language); - })); + private final ButtonWidget addButton = addButton(15, 24, 0, 0, __ -> add()); + private final ButtonWidget removeButton = addButton(15, 24, 15, 0, __ -> remove()); + private final ButtonWidget moveUpButton = addButton(11, 11, 31, 0, __ -> moveUp()); + private final ButtonWidget moveDownButton = addButton(11, 11, 31, 13, __ -> moveDown()); - private final ButtonWidget removeButton = addChild(createButton(15, 24, 15, 0, __ -> { - selectedLanguages.remove(language); - })); + public MovableLanguageEntry(Runnable refreshListsAction, String code, LanguageDefinition language, LinkedList selectedLanguages) { + super(refreshListsAction, code, language, selectedLanguages); + } - private final ButtonWidget moveUpButton = addChild(createButton(11, 11, 31, 0, __ -> { - var index = selectedLanguages.indexOf(language); - selectedLanguages.add(index - 1, selectedLanguages.remove(index)); - })); + private boolean isSelected() { + return selectedLanguages.contains(code); + } - private final ButtonWidget moveDownButton = addChild(createButton(11, 11, 31, 12, __ -> { - var index = selectedLanguages.indexOf(language); - selectedLanguages.add(index + 1, selectedLanguages.remove(index)); - })); + private boolean isFirst() { + return code.equals(selectedLanguages.peekFirst()); + } + + private boolean isLast() { + return code.equals(selectedLanguages.peekLast()); + } + + private void add() { + if (isFocused()) + parentList.setFocused(null); + selectedLanguages.add(code); + refreshListsAction.run(); + } - public MovableLanguageEntry(Runnable refreshListsAction, LanguageDefinition language, LinkedList selectedLanguages) { - super(refreshListsAction, language, selectedLanguages); + private void remove() { + if (isFocused()) + parentList.setFocused(null); + selectedLanguages.remove(code); + refreshListsAction.run(); } - private ButtonWidget createButton(int width, int height, int u, int v, ButtonWidget.PressAction pressAction) { - return new TexturedButtonWidget(0, 0, width, height, u, v, HOVERED_V_OFFSET, TEXTURE, TEXTURE_WIDTH, TEXTURE_HEIGHT, button -> { - pressAction.onPress(button); - this.refreshListsAction.run(); - }); + @Override + public void toggle() { + if (!isSelected()) add(); + else remove(); + } + + @Override + public void moveUp() { + if (!isSelected()) return; + if (isFirst()) return; + var index = selectedLanguages.indexOf(code); + selectedLanguages.add(index - 1, selectedLanguages.remove(index)); + refreshListsAction.run(); + } + + @Override + public void moveDown() { + if (!isSelected()) return; + if (isLast()) return; + var index = selectedLanguages.indexOf(code); + selectedLanguages.add(index + 1, selectedLanguages.remove(index)); + refreshListsAction.run(); } @Override - protected void renderButtons(ButtonRenderer buttonRenderer, int top, int left) { - if (selectedLanguages.contains(language)) { - buttonRenderer.render(removeButton, left, top); - var mainLanguage = selectedLanguages.peekFirst(); - if (!language.equals(mainLanguage)) { - buttonRenderer.render(moveUpButton, left + removeButton.getWidth() + 1, top); - } - var lastFallback = selectedLanguages.peekLast(); - if (!language.equals(lastFallback)) { - buttonRenderer.render(moveDownButton, left + removeButton.getWidth() + 1, top + moveUpButton.getHeight() + 2); - } - } else buttonRenderer.render(addButton, left + 7, top); + protected void renderButtons(ButtonRenderer renderer, int x, int y) { + if (isSelected()) { + renderer.render(removeButton, x, y); + if (!isFirst()) renderer.render(moveUpButton, x + removeButton.getWidth() + 1, y); + if (!isLast()) renderer.render(moveDownButton, x + removeButton.getWidth() + 1, y + moveUpButton.getHeight() + 2); + } else renderer.render(addButton, x + 7, y); } } diff --git a/src/main/java/jerozgen/languagereload/mixin/EntryListWidgetAccessor.java b/src/main/java/jerozgen/languagereload/mixin/EntryListWidgetAccessor.java new file mode 100644 index 0000000..17ccf3d --- /dev/null +++ b/src/main/java/jerozgen/languagereload/mixin/EntryListWidgetAccessor.java @@ -0,0 +1,11 @@ +package jerozgen.languagereload.mixin; + +import net.minecraft.client.gui.widget.EntryListWidget; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(EntryListWidget.class) +public interface EntryListWidgetAccessor { + @Accessor + boolean isScrolling(); +} diff --git a/src/main/java/jerozgen/languagereload/mixin/KeyboardMixin.java b/src/main/java/jerozgen/languagereload/mixin/KeyboardMixin.java index 400ce32..5e22cac 100644 --- a/src/main/java/jerozgen/languagereload/mixin/KeyboardMixin.java +++ b/src/main/java/jerozgen/languagereload/mixin/KeyboardMixin.java @@ -8,6 +8,7 @@ import net.minecraft.client.resource.language.LanguageDefinition; import net.minecraft.client.util.InputUtil; import net.minecraft.text.Text; +import net.minecraft.text.Texts; import org.lwjgl.glfw.GLFW; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -35,34 +36,21 @@ private void processLanguageReloadKeys() { if (Screen.hasShiftDown()) { var config = Config.getInstance(); var languageManager = client.getLanguageManager(); - var previousLangCode = config.previousLanguage; - var previousLanguage = languageManager.getLanguage(previousLangCode); - var previousFallbacks = config.previousFallbacks; - if (previousLanguage == null) { + var language = languageManager.getLanguage(config.previousLanguage); + if (language == null) { debugError("debug.reload_languages.switch.failure"); } else { - config.previousFallbacks = config.fallbacks; - config.fallbacks = previousFallbacks; - - config.previousLanguage = languageManager.getLanguage().getCode(); - config.language = previousLangCode; - client.options.language = previousLangCode; - languageManager.setLanguage(previousLanguage); - - LanguageReload.reloadLanguages(); - - var languages = new ArrayList(); - languages.add(previousLanguage.toString()); - languages.addAll(previousFallbacks.stream() - .map(languageManager::getLanguage) - .filter(Objects::nonNull) - .map(LanguageDefinition::toString) - .toList()); - debugLog("debug.reload_languages.switch.success", String.join(", ", languages)); - - client.options.write(); - Config.save(); + LanguageReload.setLanguage(config.previousLanguage, config.previousFallbacks); + var languages = new ArrayList() {{ + add(language.getDisplayText()); + addAll(config.previousFallbacks.stream() + .map(languageManager::getLanguage) + .filter(Objects::nonNull) + .map(LanguageDefinition::getDisplayText) + .toList()); + }}; + debugLog("debug.reload_languages.switch.success", Texts.join(languages, Text.of(", "))); } } else { LanguageReload.reloadLanguages(); diff --git a/src/main/java/jerozgen/languagereload/mixin/LanguageManagerMixin.java b/src/main/java/jerozgen/languagereload/mixin/LanguageManagerMixin.java index 2431a53..882a9f2 100644 --- a/src/main/java/jerozgen/languagereload/mixin/LanguageManagerMixin.java +++ b/src/main/java/jerozgen/languagereload/mixin/LanguageManagerMixin.java @@ -21,30 +21,29 @@ abstract class LanguageManagerMixin { @Shadow public abstract LanguageDefinition getLanguage(String code); - @Inject(method = "reload", at = @At(value = "INVOKE", target = "Ljava/util/List;add(Ljava/lang/Object;)Z", - remap = false), locals = LocalCapture.CAPTURE_FAILHARD) - void onReload$addFallbacks(ResourceManager manager, CallbackInfo ci, LanguageDefinition languageDefinition, List list) { + @Inject(method = "reload", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", ordinal = 0, + remap = false, target = "Ljava/util/List;add(Ljava/lang/Object;)Z")) + void onReload$addFallbacks(ResourceManager manager, CallbackInfo ci, List list) { Lists.reverse(Config.getInstance().fallbacks).stream() - .map(this::getLanguage) - .filter(Objects::nonNull) + .filter(code -> Objects.nonNull(getLanguage(code))) .forEach(list::add); } @Inject(method = "reload", at = @At(value = "INVOKE", ordinal = 0, remap = false, - target = "Ljava/util/Map;getOrDefault(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;")) + target = "Ljava/util/List;add(Ljava/lang/Object;)Z")) void onReload$setSystemLanguage(ResourceManager manager, CallbackInfo ci) { if (LanguageReload.shouldSetSystemLanguage) { LanguageReload.shouldSetSystemLanguage = false; LanguageReload.LOGGER.info("Language is not set. Setting it to system language"); var locale = Locale.getDefault(); - var matchingLanguages = languageDefs.values().stream() - .filter(lang -> lang.getCode().split("_")[0].equalsIgnoreCase(locale.getLanguage())) + var matchingLanguages = languageDefs.keySet().stream() + .filter(code -> code.split("_")[0].equalsIgnoreCase(locale.getLanguage())) .toList(); var count = matchingLanguages.size(); if (count > 1) matchingLanguages.stream() - .filter(lang -> { - var split = lang.getCode().split("_"); + .filter(code -> { + var split = code.split("_"); if (split.length < 2) return false; return split[1].equalsIgnoreCase(locale.getCountry()); }) diff --git a/src/main/java/jerozgen/languagereload/mixin/LanguageOptionsScreenMixin.java b/src/main/java/jerozgen/languagereload/mixin/LanguageOptionsScreenMixin.java index b4fb8eb..d193b21 100644 --- a/src/main/java/jerozgen/languagereload/mixin/LanguageOptionsScreenMixin.java +++ b/src/main/java/jerozgen/languagereload/mixin/LanguageOptionsScreenMixin.java @@ -1,17 +1,16 @@ package jerozgen.languagereload.mixin; import jerozgen.languagereload.LanguageReload; +import jerozgen.languagereload.access.ILanguageOptionsScreen; import jerozgen.languagereload.config.Config; -import jerozgen.languagereload.gui.LanguageListWidget; -import jerozgen.languagereload.gui.LockedLanguageEntry; -import jerozgen.languagereload.gui.MovableLanguageEntry; +import jerozgen.languagereload.gui.*; +import net.minecraft.client.gui.navigation.GuiNavigationPath; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.option.GameOptionsScreen; import net.minecraft.client.gui.screen.option.LanguageOptionsScreen; import net.minecraft.client.gui.widget.ButtonWidget; import net.minecraft.client.gui.widget.TextFieldWidget; import net.minecraft.client.option.GameOptions; -import net.minecraft.client.resource.language.LanguageDefinition; import net.minecraft.client.resource.language.LanguageManager; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.screen.ScreenTexts; @@ -24,18 +23,17 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import java.util.*; -import java.util.stream.Collectors; +import java.util.stream.Stream; @Mixin(LanguageOptionsScreen.class) -public abstract class LanguageOptionsScreenMixin extends GameOptionsScreen { +public abstract class LanguageOptionsScreenMixin extends GameOptionsScreen implements ILanguageOptionsScreen { @Shadow @Final private static Text LANGUAGE_WARNING_TEXT; - @Shadow @Final LanguageManager languageManager; private LanguageListWidget availableLanguageList; private LanguageListWidget selectedLanguageList; private TextFieldWidget searchBox; - private final LinkedList selectedLanguages = new LinkedList<>(); - private final Map languageEntries = new LinkedHashMap<>(); + private final LinkedList selectedLanguages = new LinkedList<>(); + private final Map languageEntries = new LinkedHashMap<>(); private LockedLanguageEntry defaultLanguageEntry; LanguageOptionsScreenMixin(Screen parent, GameOptions options, Text title) { @@ -44,41 +42,44 @@ public abstract class LanguageOptionsScreenMixin extends GameOptionsScreen { @Inject(method = "", at = @At("TAIL")) void onConstructed(Screen parent, GameOptions options, LanguageManager languageManager, CallbackInfo ci) { - var currentLang = languageManager.getLanguage(); - if (!currentLang.getCode().equals(LanguageManager.DEFAULT_LANGUAGE_CODE)) selectedLanguages.add(currentLang); - - var fallbacks = Config.getInstance().fallbacks.stream() - .map(languageManager::getLanguage) - .filter(Objects::nonNull) - .toList(); - selectedLanguages.addAll(fallbacks); - - for (var language : languageManager.getAllLanguages()) { - if (!language.getCode().equals(LanguageManager.DEFAULT_LANGUAGE_CODE)) { - languageEntries.put(language, new MovableLanguageEntry(this::refresh, language, selectedLanguages)); - } else { - defaultLanguageEntry = new LockedLanguageEntry(this::refresh, language, selectedLanguages); - } - } + var currentLangCode = languageManager.getLanguage(); + if (!currentLangCode.equals(LanguageManager.DEFAULT_LANGUAGE_CODE)) + selectedLanguages.add(currentLangCode); + selectedLanguages.addAll(Config.getInstance().fallbacks); + languageManager.getAllLanguages().forEach((code, language) -> { + if (!code.equals(LanguageManager.DEFAULT_LANGUAGE_CODE)) + languageEntries.put(code, new MovableLanguageEntry(this::refresh, code, language, selectedLanguages)); + else defaultLanguageEntry = new LockedLanguageEntry(this::refresh, code, language, selectedLanguages); + }); } @Inject(method = "init", at = @At("HEAD"), cancellable = true) void onInit(CallbackInfo ci) { - searchBox = new TextFieldWidget(textRenderer, width / 2 - 100, 22, 200, 20, searchBox, Text.empty()); + searchBox = new TextFieldWidget(textRenderer, width / 2 - 100, 22, 200, 20, searchBox, Text.empty()) { + @Override + public void setFocused(boolean focused) { + if (!isFocused() && focused) { + super.setFocused(true); + focusSearch(); + } + else super.setFocused(focused); + } + }; searchBox.setChangedListener(__ -> refresh()); addSelectableChild(searchBox); setInitialFocus(searchBox); var listWidth = Math.min(width / 2 - 4, 200); - availableLanguageList = new LanguageListWidget(client, listWidth, height, Text.translatable("pack.available.title")); - selectedLanguageList = new LanguageListWidget(client, listWidth, height, Text.translatable("pack.selected.title")); + var it = (LanguageOptionsScreen) (Object) this; + availableLanguageList = new LanguageListWidget(client, it, listWidth, height, Text.translatable("pack.available.title")); + selectedLanguageList = new LanguageListWidget(client, it, listWidth, height, Text.translatable("pack.selected.title")); availableLanguageList.setLeftPos(width / 2 - 4 - listWidth); selectedLanguageList.setLeftPos(width / 2 + 4); addSelectableChild(availableLanguageList); addSelectableChild(selectedLanguageList); refresh(); - addDrawableChild(gameOptions.getForceUnicodeFont().createButton(gameOptions, width / 2 - 155, height - 28, 150)); + addDrawableChild(gameOptions.getForceUnicodeFont().createWidget(gameOptions, width / 2 - 155, height - 28, 150)); addDrawableChild(ButtonWidget.builder(ScreenTexts.DONE, this::onDone) .dimensions(width / 2 - 155 + 160, height - 28, 150, 20) .build()); @@ -92,46 +93,67 @@ private void onDone(ButtonWidget button) { client.setScreen(parent); var language = selectedLanguages.peekFirst(); - if (language == null) language = languageManager.getLanguage(LanguageManager.DEFAULT_LANGUAGE_CODE); - var fallbacks = selectedLanguages.stream() - .skip(1) - .map(LanguageDefinition::getCode) - .collect(Collectors.toCollection(LinkedList::new)); + if (language == null) { + LanguageReload.setLanguage(LanguageManager.DEFAULT_LANGUAGE_CODE, new LinkedList<>()); + } else { + var fallbacks = new LinkedList<>(selectedLanguages); + fallbacks.remove(0); + LanguageReload.setLanguage(language, fallbacks); + } + } - LanguageReload.setLanguage(language, fallbacks); + @Override + public void focusList(LanguageListWidget list) { + switchFocus(GuiNavigationPath.of(list, this)); + } + + @Override + public void focusEntry(LanguageEntry entry) { + switchFocus(GuiNavigationPath.of(entry, entry.getParent(), this)); + } + + public void focusSearch() { + switchFocus(GuiNavigationPath.of(searchBox, this)); } private void refresh() { - selectedLanguageList.children().clear(); - selectedLanguages.forEach(language -> { - var entry = languageEntries.get(language); - if (entry != null) selectedLanguageList.children().add(entry); - }); - selectedLanguageList.children().add(defaultLanguageEntry); - - availableLanguageList.children().clear(); - languageEntries.forEach((lang, entry) -> { - if (selectedLanguageList.children().contains(entry)) return; - var langName = entry.getLanguage().toString().toLowerCase(Locale.ROOT); - var langCode = entry.getLanguage().getCode().toLowerCase(Locale.ROOT); - var query = searchBox.getText().toLowerCase(Locale.ROOT); - if (langName.contains(query) || langCode.contains(query)) { - availableLanguageList.children().add(entry); + refreshList(selectedLanguageList, Stream.concat( + selectedLanguages.stream().map(languageEntries::get).filter(Objects::nonNull), + Stream.of(defaultLanguageEntry))); + refreshList(availableLanguageList, languageEntries.values().stream() + .filter(entry -> { + if (selectedLanguageList.children().contains(entry)) return false; + var query = searchBox.getText().toLowerCase(Locale.ROOT); + var langCode = entry.getCode().toLowerCase(Locale.ROOT); + var langName = entry.getLanguage().getDisplayText().getString().toLowerCase(Locale.ROOT); + return langCode.contains(query) || langName.contains(query); + })); + } + + private void refreshList(LanguageListWidget list, Stream entries) { + var selectedEntry = list.getSelectedOrNull(); + list.setSelected(null); + list.children().clear(); + entries.forEach(entry -> { + list.children().add(entry); + entry.setParent(list); + if (entry == selectedEntry) { + list.setSelected(entry); } }); - availableLanguageList.setScrollAmount(availableLanguageList.getScrollAmount()); + list.setScrollAmount(list.getScrollAmount()); } @Inject(method = "render", at = @At("HEAD"), cancellable = true) void onRender(MatrixStack matrices, int mouseX, int mouseY, float delta, CallbackInfo ci) { - renderBackgroundTexture(0); + renderBackgroundTexture(matrices); availableLanguageList.render(matrices, mouseX, mouseY, delta); selectedLanguageList.render(matrices, mouseX, mouseY, delta); searchBox.render(matrices, mouseX, mouseY, delta); - drawCenteredText(matrices, textRenderer, title, width / 2, 8, 0xFFFFFF); - drawCenteredText(matrices, textRenderer, LANGUAGE_WARNING_TEXT, width / 2, height - 46, 0x808080); + drawCenteredTextWithShadow(matrices, textRenderer, title, width / 2, 8, 0xFFFFFF); + drawCenteredTextWithShadow(matrices, textRenderer, LANGUAGE_WARNING_TEXT, width / 2, height - 46, 0x808080); super.render(matrices, mouseX, mouseY, delta); ci.cancel(); diff --git a/src/main/java/jerozgen/languagereload/mixin/RecipeBookWidgetMixin.java b/src/main/java/jerozgen/languagereload/mixin/RecipeBookWidgetMixin.java index 1cebae4..916bde9 100644 --- a/src/main/java/jerozgen/languagereload/mixin/RecipeBookWidgetMixin.java +++ b/src/main/java/jerozgen/languagereload/mixin/RecipeBookWidgetMixin.java @@ -2,27 +2,19 @@ import jerozgen.languagereload.LanguageReload; import net.minecraft.client.gui.screen.recipebook.RecipeBookWidget; -import net.minecraft.client.resource.language.LanguageDefinition; -import net.minecraft.client.resource.language.LanguageManager; 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.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import java.util.LinkedList; @Mixin(RecipeBookWidget.class) public class RecipeBookWidgetMixin { - @Redirect(method = "triggerPirateSpeakEasterEgg", at = @At(value = "INVOKE", - target = "Lnet/minecraft/client/resource/language/LanguageManager;setLanguage(Lnet/minecraft/client/resource/language/LanguageDefinition;)V")) - void onLanguageSwitching$redirect(LanguageManager instance, LanguageDefinition language) { - LanguageReload.setLanguage(language, new LinkedList<>()); - } - - @Inject(method = "triggerPirateSpeakEasterEgg", cancellable = true, at = @At(value = "INVOKE", shift = At.Shift.AFTER, - target = "Lnet/minecraft/client/resource/language/LanguageManager;setLanguage(Lnet/minecraft/client/resource/language/LanguageDefinition;)V")) + @Inject(method = "triggerPirateSpeakEasterEgg", cancellable = true, at = @At(value = "INVOKE", + target = "Lnet/minecraft/client/resource/language/LanguageManager;setLanguage(Ljava/lang/String;)V")) void onLanguageSwitching$cancel(String search, CallbackInfo ci) { + LanguageReload.setLanguage("en_pt", new LinkedList<>()); ci.cancel(); } } diff --git a/src/main/java/jerozgen/languagereload/mixin/TranslationStorageMixin.java b/src/main/java/jerozgen/languagereload/mixin/TranslationStorageMixin.java index c19b6bc..f5e8d13 100644 --- a/src/main/java/jerozgen/languagereload/mixin/TranslationStorageMixin.java +++ b/src/main/java/jerozgen/languagereload/mixin/TranslationStorageMixin.java @@ -3,7 +3,6 @@ import com.google.common.collect.Maps; import jerozgen.languagereload.access.ITranslationStorage; import jerozgen.languagereload.config.Config; -import net.minecraft.client.resource.language.LanguageDefinition; import net.minecraft.client.resource.language.TranslationStorage; import net.minecraft.resource.ResourceManager; import net.minecraft.util.Language; @@ -32,9 +31,9 @@ void onConstructed(Map translations, boolean rightToLeft, Callba separateTranslationsOnLoad = null; } - @Inject(method = "load(Lnet/minecraft/resource/ResourceManager;Ljava/util/List;)Lnet/minecraft/client/resource/language/TranslationStorage;", + @Inject(method = "load(Lnet/minecraft/resource/ResourceManager;Ljava/util/List;Z)Lnet/minecraft/client/resource/language/TranslationStorage;", at = @At("HEAD")) - private static void onLoad(ResourceManager resourceManager, List definitions, CallbackInfoReturnable cir) { + private static void onLoad(ResourceManager resourceManager, List definitions, boolean rightToLeft, CallbackInfoReturnable cir) { separateTranslationsOnLoad = Maps.newHashMap(); } @@ -48,7 +47,7 @@ private static void onLoad(ResourceManager resourceManager, List cir) { + void onGet(String key, String fallback, CallbackInfoReturnable cir) { if (!Config.getInstance().multilingualItemSearch) return; if (targetLanguage == null) return; @@ -58,7 +57,7 @@ void onGet(String key, CallbackInfoReturnable cir) { var targetTranslations = separateTranslations.get(targetLanguage); if (targetTranslations == null) targetTranslations = defaultTranslations; - cir.setReturnValue(targetTranslations.getOrDefault(key, defaultTranslations.getOrDefault(key, key))); + cir.setReturnValue(targetTranslations.getOrDefault(key, defaultTranslations.getOrDefault(key, fallback))); } @Override diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index e8c8d50..2f82a2b 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -40,9 +40,8 @@ }, "depends": { "fabric-resource-loader-v0": "*", - "fabricloader": ">=0.14.6", - "minecraft": ">=1.19.3", - "java": ">=17" + "fabricloader": ">=0.14.14", + "minecraft": ">=1.19.4-" }, "suggests": { "modmenu": "*" diff --git a/src/main/resources/languagereload.accesswidener b/src/main/resources/languagereload.accesswidener index 66e2256..d0c701e 100644 --- a/src/main/resources/languagereload.accesswidener +++ b/src/main/resources/languagereload.accesswidener @@ -2,3 +2,5 @@ accessWidener v1 named accessible class net/minecraft/client/gui/screen/option/LanguageOptionsScreen$LanguageSelectionListWidget extendable class net/minecraft/client/world/ClientChunkManager$ClientChunkMap + +extendable method net/minecraft/client/gui/widget/EntryListWidget getEntryAtPosition (DD)Lnet/minecraft/client/gui/widget/EntryListWidget$Entry; diff --git a/src/main/resources/languagereload.mixins.json b/src/main/resources/languagereload.mixins.json index 4bbd63e..8cdfa8c 100644 --- a/src/main/resources/languagereload.mixins.json +++ b/src/main/resources/languagereload.mixins.json @@ -10,6 +10,7 @@ "BookScreenAccessor", "ClientChunkManagerAccessor", "ClientChunkMapAccessor", + "EntryListWidgetAccessor", "GameOptionsMixin", "KeyboardMixin", "LanguageManagerMixin", From b52408509a2eb0af328adf6070643feadf056054 Mon Sep 17 00:00:00 2001 From: Jerozgen Date: Mon, 13 Mar 2023 02:25:15 +0300 Subject: [PATCH 3/4] Backport to 1.19.3 --- gradle.properties | 12 +++---- .../languagereload/LanguageReload.java | 10 ++++-- .../access/ILanguageOptionsScreen.java | 3 -- .../languagereload/gui/LanguageEntry.java | 12 ++++--- .../gui/LanguageListWidget.java | 7 +++- .../gui/MovableLanguageEntry.java | 4 --- ...AlwaysSelectedEntryListWidgetAccessor.java | 11 +++++++ .../languagereload/mixin/KeyboardMixin.java | 7 ++-- .../mixin/LanguageManagerMixin.java | 7 ++-- .../mixin/LanguageOptionsScreenMixin.java | 33 ++++++++++--------- .../mixin/RecipeBookWidgetMixin.java | 2 +- .../mixin/TranslationStorageMixin.java | 9 ++--- src/main/resources/languagereload.mixins.json | 1 + 13 files changed, 69 insertions(+), 49 deletions(-) create mode 100644 src/main/java/jerozgen/languagereload/mixin/AlwaysSelectedEntryListWidgetAccessor.java diff --git a/gradle.properties b/gradle.properties index 5225ff5..dfb7b9b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,15 +3,15 @@ org.gradle.jvmargs=-Xmx1G # Fabric Properties # check these on https://modmuss50.me/fabric.html -minecraft_version=1.19.4-rc1 -yarn_mappings=1.19.4-rc1+build.1 -loader_version=0.14.17 -fabric_version=0.75.3+1.19.4 +minecraft_version=1.19.3 +yarn_mappings=1.19.3+build.5 +loader_version=0.14.12 +fabric_version=0.72.0+1.19.3 # Mod Properties -mod_version=1.5.4+1.19.4 +mod_version=1.5.4+1.19.3 maven_group=jerozgen archives_base_name=language-reload # Dependencies -modmenu_version=6.1.0-beta.3 +modmenu_version=5.0.2 \ No newline at end of file diff --git a/src/main/java/jerozgen/languagereload/LanguageReload.java b/src/main/java/jerozgen/languagereload/LanguageReload.java index ccac5c5..4925114 100644 --- a/src/main/java/jerozgen/languagereload/LanguageReload.java +++ b/src/main/java/jerozgen/languagereload/LanguageReload.java @@ -9,6 +9,7 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.advancement.AdvancementsScreen; import net.minecraft.client.gui.screen.ingame.BookScreen; +import net.minecraft.client.resource.language.LanguageManager; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -63,17 +64,20 @@ public static void setLanguage(String language, LinkedList fallbacks) { var languageManager = client.getLanguageManager(); var config = Config.getInstance(); - var languageIsSame = languageManager.getLanguage().equals(language); + var languageIsSame = languageManager.getLanguage().getCode().equals(language); var fallbacksAreSame = config.fallbacks.equals(fallbacks); if (languageIsSame && fallbacksAreSame) return; - config.previousLanguage = languageManager.getLanguage(); + if (languageManager.getLanguage(language) == null) + language = LanguageManager.DEFAULT_LANGUAGE_CODE; + + config.previousLanguage = languageManager.getLanguage().getCode(); config.previousFallbacks = config.fallbacks; config.language = language; config.fallbacks = fallbacks; Config.save(); - languageManager.setLanguage(language); + languageManager.setLanguage(languageManager.getLanguage(language)); client.options.language = language; client.options.write(); diff --git a/src/main/java/jerozgen/languagereload/access/ILanguageOptionsScreen.java b/src/main/java/jerozgen/languagereload/access/ILanguageOptionsScreen.java index dfa62ea..3116f08 100644 --- a/src/main/java/jerozgen/languagereload/access/ILanguageOptionsScreen.java +++ b/src/main/java/jerozgen/languagereload/access/ILanguageOptionsScreen.java @@ -1,10 +1,7 @@ package jerozgen.languagereload.access; import jerozgen.languagereload.gui.LanguageEntry; -import jerozgen.languagereload.gui.LanguageListWidget; public interface ILanguageOptionsScreen { - void focusList(LanguageListWidget list); - void focusEntry(LanguageEntry entry); } diff --git a/src/main/java/jerozgen/languagereload/gui/LanguageEntry.java b/src/main/java/jerozgen/languagereload/gui/LanguageEntry.java index 1f7a6eb..115a78a 100644 --- a/src/main/java/jerozgen/languagereload/gui/LanguageEntry.java +++ b/src/main/java/jerozgen/languagereload/gui/LanguageEntry.java @@ -1,7 +1,6 @@ package jerozgen.languagereload.gui; import jerozgen.languagereload.LanguageReload; -import jerozgen.languagereload.access.ILanguageOptionsScreen; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawableHelper; import net.minecraft.client.gui.widget.AlwaysSelectedEntryListWidget; @@ -50,6 +49,10 @@ protected ButtonWidget addButton(int width, int height, int u, int v, int hovere return button; } + public boolean isFocused() { + return parentList.getSelectedOrNull() == this && parentList.isFocused(); + } + public void toggle() {} public void moveUp() {} @@ -74,20 +77,19 @@ public void render(MatrixStack matrices, int index, int y, int x, int entryWidth button.render(matrices, mouseX, mouseY, tickDelta); }, x, y); } - client.textRenderer.drawWithShadow(matrices, language.name(), x + 29, y + 3, 0xFFFFFF); - client.textRenderer.drawWithShadow(matrices, language.region(), x + 29, y + 14, 0x808080); + client.textRenderer.drawWithShadow(matrices, language.getName(), x + 29, y + 3, 0xFFFFFF); + client.textRenderer.drawWithShadow(matrices, language.getRegion(), x + 29, y + 14, 0x808080); } @Override public Text getNarration() { - return Text.translatable("narrator.select", language.getDisplayText()); + return Text.translatable("narrator.select", language); } @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { for (var widget : buttons) if (widget.mouseClicked(mouseX, mouseY, button)) { - ((ILanguageOptionsScreen) parentList.getScreen()).focusList(parentList); return true; } return false; diff --git a/src/main/java/jerozgen/languagereload/gui/LanguageListWidget.java b/src/main/java/jerozgen/languagereload/gui/LanguageListWidget.java index d69ee2b..c916a56 100644 --- a/src/main/java/jerozgen/languagereload/gui/LanguageListWidget.java +++ b/src/main/java/jerozgen/languagereload/gui/LanguageListWidget.java @@ -8,6 +8,7 @@ import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.option.LanguageOptionsScreen; import net.minecraft.client.gui.widget.AlwaysSelectedEntryListWidget; +import net.minecraft.client.render.Tessellator; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.Text; import net.minecraft.util.Formatting; @@ -30,7 +31,7 @@ public LanguageListWidget(MinecraftClient client, LanguageOptionsScreen screen, } @Override - protected void renderHeader(MatrixStack matrices, int x, int y) { + protected void renderHeader(MatrixStack matrices, int x, int y, Tessellator tessellator) { var headerText = title.copy().formatted(Formatting.UNDERLINE, Formatting.BOLD); int headerPosX = x + width / 2 - client.textRenderer.getWidth(headerText) / 2; int headerPosY = Math.min(top + 3, y); @@ -118,4 +119,8 @@ public int getRowWidth() { protected int getScrollbarPositionX() { return right - 6; } + + protected boolean isFocused() { + return screen.getFocused() == this; + } } diff --git a/src/main/java/jerozgen/languagereload/gui/MovableLanguageEntry.java b/src/main/java/jerozgen/languagereload/gui/MovableLanguageEntry.java index 5839425..ffc8b6e 100644 --- a/src/main/java/jerozgen/languagereload/gui/MovableLanguageEntry.java +++ b/src/main/java/jerozgen/languagereload/gui/MovableLanguageEntry.java @@ -28,15 +28,11 @@ private boolean isLast() { } private void add() { - if (isFocused()) - parentList.setFocused(null); selectedLanguages.add(code); refreshListsAction.run(); } private void remove() { - if (isFocused()) - parentList.setFocused(null); selectedLanguages.remove(code); refreshListsAction.run(); } diff --git a/src/main/java/jerozgen/languagereload/mixin/AlwaysSelectedEntryListWidgetAccessor.java b/src/main/java/jerozgen/languagereload/mixin/AlwaysSelectedEntryListWidgetAccessor.java new file mode 100644 index 0000000..a20d630 --- /dev/null +++ b/src/main/java/jerozgen/languagereload/mixin/AlwaysSelectedEntryListWidgetAccessor.java @@ -0,0 +1,11 @@ +package jerozgen.languagereload.mixin; + +import net.minecraft.client.gui.widget.AlwaysSelectedEntryListWidget; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(AlwaysSelectedEntryListWidget.class) +public interface AlwaysSelectedEntryListWidgetAccessor { + @Accessor + void setInFocus(boolean value); +} diff --git a/src/main/java/jerozgen/languagereload/mixin/KeyboardMixin.java b/src/main/java/jerozgen/languagereload/mixin/KeyboardMixin.java index 5e22cac..69c7269 100644 --- a/src/main/java/jerozgen/languagereload/mixin/KeyboardMixin.java +++ b/src/main/java/jerozgen/languagereload/mixin/KeyboardMixin.java @@ -43,11 +43,12 @@ private void processLanguageReloadKeys() { } else { LanguageReload.setLanguage(config.previousLanguage, config.previousFallbacks); var languages = new ArrayList() {{ - add(language.getDisplayText()); - addAll(config.previousFallbacks.stream() + add(Text.of(language.toString())); + addAll(config.fallbacks.stream() .map(languageManager::getLanguage) .filter(Objects::nonNull) - .map(LanguageDefinition::getDisplayText) + .map(LanguageDefinition::toString) + .map(Text::of) .toList()); }}; debugLog("debug.reload_languages.switch.success", Texts.join(languages, Text.of(", "))); diff --git a/src/main/java/jerozgen/languagereload/mixin/LanguageManagerMixin.java b/src/main/java/jerozgen/languagereload/mixin/LanguageManagerMixin.java index 882a9f2..b727ea6 100644 --- a/src/main/java/jerozgen/languagereload/mixin/LanguageManagerMixin.java +++ b/src/main/java/jerozgen/languagereload/mixin/LanguageManagerMixin.java @@ -23,14 +23,15 @@ abstract class LanguageManagerMixin { @Inject(method = "reload", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", ordinal = 0, remap = false, target = "Ljava/util/List;add(Ljava/lang/Object;)Z")) - void onReload$addFallbacks(ResourceManager manager, CallbackInfo ci, List list) { + void onReload$addFallbacks(ResourceManager manager, CallbackInfo ci, LanguageDefinition languageDefinition, List list) { Lists.reverse(Config.getInstance().fallbacks).stream() - .filter(code -> Objects.nonNull(getLanguage(code))) + .map(this::getLanguage) + .filter(Objects::nonNull) .forEach(list::add); } @Inject(method = "reload", at = @At(value = "INVOKE", ordinal = 0, remap = false, - target = "Ljava/util/List;add(Ljava/lang/Object;)Z")) + target = "Ljava/util/Map;getOrDefault(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;")) void onReload$setSystemLanguage(ResourceManager manager, CallbackInfo ci) { if (LanguageReload.shouldSetSystemLanguage) { LanguageReload.shouldSetSystemLanguage = false; diff --git a/src/main/java/jerozgen/languagereload/mixin/LanguageOptionsScreenMixin.java b/src/main/java/jerozgen/languagereload/mixin/LanguageOptionsScreenMixin.java index d193b21..09b2719 100644 --- a/src/main/java/jerozgen/languagereload/mixin/LanguageOptionsScreenMixin.java +++ b/src/main/java/jerozgen/languagereload/mixin/LanguageOptionsScreenMixin.java @@ -4,7 +4,6 @@ import jerozgen.languagereload.access.ILanguageOptionsScreen; import jerozgen.languagereload.config.Config; import jerozgen.languagereload.gui.*; -import net.minecraft.client.gui.navigation.GuiNavigationPath; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.option.GameOptionsScreen; import net.minecraft.client.gui.screen.option.LanguageOptionsScreen; @@ -42,15 +41,16 @@ public abstract class LanguageOptionsScreenMixin extends GameOptionsScreen imple @Inject(method = "", at = @At("TAIL")) void onConstructed(Screen parent, GameOptions options, LanguageManager languageManager, CallbackInfo ci) { - var currentLangCode = languageManager.getLanguage(); + var currentLangCode = languageManager.getLanguage().getCode(); if (!currentLangCode.equals(LanguageManager.DEFAULT_LANGUAGE_CODE)) selectedLanguages.add(currentLangCode); selectedLanguages.addAll(Config.getInstance().fallbacks); - languageManager.getAllLanguages().forEach((code, language) -> { + for (var language : languageManager.getAllLanguages()) { + var code = language.getCode(); if (!code.equals(LanguageManager.DEFAULT_LANGUAGE_CODE)) languageEntries.put(code, new MovableLanguageEntry(this::refresh, code, language, selectedLanguages)); else defaultLanguageEntry = new LockedLanguageEntry(this::refresh, code, language, selectedLanguages); - }); + } } @Inject(method = "init", at = @At("HEAD"), cancellable = true) @@ -79,7 +79,7 @@ public void setFocused(boolean focused) { addSelectableChild(selectedLanguageList); refresh(); - addDrawableChild(gameOptions.getForceUnicodeFont().createWidget(gameOptions, width / 2 - 155, height - 28, 150)); + addDrawableChild(gameOptions.getForceUnicodeFont().createButton(gameOptions, width / 2 - 155, height - 28, 150)); addDrawableChild(ButtonWidget.builder(ScreenTexts.DONE, this::onDone) .dimensions(width / 2 - 155 + 160, height - 28, 150, 20) .build()); @@ -102,18 +102,19 @@ private void onDone(ButtonWidget button) { } } - @Override - public void focusList(LanguageListWidget list) { - switchFocus(GuiNavigationPath.of(list, this)); - } - @Override public void focusEntry(LanguageEntry entry) { - switchFocus(GuiNavigationPath.of(entry, entry.getParent(), this)); + ((AlwaysSelectedEntryListWidgetAccessor) availableLanguageList).setInFocus(false); + ((AlwaysSelectedEntryListWidgetAccessor) selectedLanguageList).setInFocus(false); + entry.getParent().setSelected(entry); + entry.getParent().changeFocus(true); + setFocused(entry.getParent()); } public void focusSearch() { - switchFocus(GuiNavigationPath.of(searchBox, this)); + ((AlwaysSelectedEntryListWidgetAccessor) availableLanguageList).setInFocus(false); + ((AlwaysSelectedEntryListWidgetAccessor) selectedLanguageList).setInFocus(false); + setFocused(searchBox); } private void refresh() { @@ -125,7 +126,7 @@ private void refresh() { if (selectedLanguageList.children().contains(entry)) return false; var query = searchBox.getText().toLowerCase(Locale.ROOT); var langCode = entry.getCode().toLowerCase(Locale.ROOT); - var langName = entry.getLanguage().getDisplayText().getString().toLowerCase(Locale.ROOT); + var langName = entry.getLanguage().toString().toLowerCase(Locale.ROOT); return langCode.contains(query) || langName.contains(query); })); } @@ -146,14 +147,14 @@ private void refreshList(LanguageListWidget list, Stream()); ci.cancel(); diff --git a/src/main/java/jerozgen/languagereload/mixin/TranslationStorageMixin.java b/src/main/java/jerozgen/languagereload/mixin/TranslationStorageMixin.java index f5e8d13..c19b6bc 100644 --- a/src/main/java/jerozgen/languagereload/mixin/TranslationStorageMixin.java +++ b/src/main/java/jerozgen/languagereload/mixin/TranslationStorageMixin.java @@ -3,6 +3,7 @@ import com.google.common.collect.Maps; import jerozgen.languagereload.access.ITranslationStorage; import jerozgen.languagereload.config.Config; +import net.minecraft.client.resource.language.LanguageDefinition; import net.minecraft.client.resource.language.TranslationStorage; import net.minecraft.resource.ResourceManager; import net.minecraft.util.Language; @@ -31,9 +32,9 @@ void onConstructed(Map translations, boolean rightToLeft, Callba separateTranslationsOnLoad = null; } - @Inject(method = "load(Lnet/minecraft/resource/ResourceManager;Ljava/util/List;Z)Lnet/minecraft/client/resource/language/TranslationStorage;", + @Inject(method = "load(Lnet/minecraft/resource/ResourceManager;Ljava/util/List;)Lnet/minecraft/client/resource/language/TranslationStorage;", at = @At("HEAD")) - private static void onLoad(ResourceManager resourceManager, List definitions, boolean rightToLeft, CallbackInfoReturnable cir) { + private static void onLoad(ResourceManager resourceManager, List definitions, CallbackInfoReturnable cir) { separateTranslationsOnLoad = Maps.newHashMap(); } @@ -47,7 +48,7 @@ private static void onLoad(ResourceManager resourceManager, List definit } @Inject(method = "get", at = @At(value = "HEAD"), cancellable = true) - void onGet(String key, String fallback, CallbackInfoReturnable cir) { + void onGet(String key, CallbackInfoReturnable cir) { if (!Config.getInstance().multilingualItemSearch) return; if (targetLanguage == null) return; @@ -57,7 +58,7 @@ void onGet(String key, String fallback, CallbackInfoReturnable cir) { var targetTranslations = separateTranslations.get(targetLanguage); if (targetTranslations == null) targetTranslations = defaultTranslations; - cir.setReturnValue(targetTranslations.getOrDefault(key, defaultTranslations.getOrDefault(key, fallback))); + cir.setReturnValue(targetTranslations.getOrDefault(key, defaultTranslations.getOrDefault(key, key))); } @Override diff --git a/src/main/resources/languagereload.mixins.json b/src/main/resources/languagereload.mixins.json index 8cdfa8c..52a37a6 100644 --- a/src/main/resources/languagereload.mixins.json +++ b/src/main/resources/languagereload.mixins.json @@ -7,6 +7,7 @@ "AdvancementsScreenMixin", "AdvancementTabMixin", "AdvancementWidgetAccessor", + "AlwaysSelectedEntryListWidgetAccessor", "BookScreenAccessor", "ClientChunkManagerAccessor", "ClientChunkMapAccessor", From 0d19007d42542d26ba6ec8ef6cb3f5cc2c4d0056 Mon Sep 17 00:00:00 2001 From: Jerozgen Date: Mon, 13 Mar 2023 02:59:26 +0300 Subject: [PATCH 4/4] Bump version --- gradle.properties | 2 +- src/main/java/jerozgen/languagereload/mixin/KeyboardMixin.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 5225ff5..448bf61 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ loader_version=0.14.17 fabric_version=0.75.3+1.19.4 # Mod Properties -mod_version=1.5.4+1.19.4 +mod_version=1.5.5+1.19.4 maven_group=jerozgen archives_base_name=language-reload diff --git a/src/main/java/jerozgen/languagereload/mixin/KeyboardMixin.java b/src/main/java/jerozgen/languagereload/mixin/KeyboardMixin.java index 5e22cac..78cc58c 100644 --- a/src/main/java/jerozgen/languagereload/mixin/KeyboardMixin.java +++ b/src/main/java/jerozgen/languagereload/mixin/KeyboardMixin.java @@ -44,7 +44,7 @@ private void processLanguageReloadKeys() { LanguageReload.setLanguage(config.previousLanguage, config.previousFallbacks); var languages = new ArrayList() {{ add(language.getDisplayText()); - addAll(config.previousFallbacks.stream() + addAll(config.fallbacks.stream() .map(languageManager::getLanguage) .filter(Objects::nonNull) .map(LanguageDefinition::getDisplayText)