From d07a8dabd4ffa59ac087678d71d79c1f15c7dc75 Mon Sep 17 00:00:00 2001 From: JFronny Date: Wed, 22 Mar 2023 18:59:42 +0100 Subject: [PATCH] clean up --- gradle.properties | 2 +- .../io/gitlab/jfronny/chattransform/Cfg.java | 19 ++++- .../jfronny/chattransform/Substitution.java | 11 +++ .../jfronny/chattransform/TransformStart.java | 50 +++++++++++ .../mixin/TextFieldWidgetMixin.java | 83 ++++++++++++++----- .../assets/chat-transform/lang/en_us.json | 2 + 6 files changed, 140 insertions(+), 27 deletions(-) create mode 100644 src/client/java/io/gitlab/jfronny/chattransform/Substitution.java create mode 100644 src/client/java/io/gitlab/jfronny/chattransform/TransformStart.java diff --git a/gradle.properties b/gradle.properties index a8cef7c..098bc14 100644 --- a/gradle.properties +++ b/gradle.properties @@ -13,5 +13,5 @@ curseforge_id=839175 curseforge_required_dependencies=libjf curseforge_optional_dependencies=modmenu -libjf_version=3.7.0 +libjf_version=3.7.1 fabric_version=0.75.3+1.19.4 diff --git a/src/client/java/io/gitlab/jfronny/chattransform/Cfg.java b/src/client/java/io/gitlab/jfronny/chattransform/Cfg.java index 4cb8ef3..d849d9b 100644 --- a/src/client/java/io/gitlab/jfronny/chattransform/Cfg.java +++ b/src/client/java/io/gitlab/jfronny/chattransform/Cfg.java @@ -8,8 +8,9 @@ import java.util.Map; @JfConfig public class Cfg { - @Entry public static Map substitutions = new LinkedHashMap<>(); + @Entry public static Map substitutions = Map.of(); @Entry public static Mode mode = Mode.Live; + @Entry public static boolean visualize = true; public enum Mode { Live, OnSend @@ -17,7 +18,7 @@ public class Cfg { @Preset public static void owo() { - substitutions.clear(); + substitutions = new LinkedHashMap<>(); substitutions.put("r", "w"); substitutions.put("l", "w"); substitutions.put("R", "W"); @@ -30,6 +31,14 @@ public class Cfg { substitutions.put("The ", "Da "); } + @Preset + public static void demonstrationPurposesOnly() { + substitutions = new LinkedHashMap<>(); + substitutions.put("chat-transform", "Chat-Transform (this mod)"); + substitutions.put(":tm:", "™"); + substitutions.put("(c)", "©"); + } + @Ignore private static final String katakanaTable = """ a i u e o n ア イ ウ エ オ ン @@ -120,23 +129,25 @@ public class Cfg { @Preset public static void katakana() { - substitutions.clear(); + substitutions = new LinkedHashMap<>(); substitutions.put("-", "ー"); for (char c : consonants) { substitutions.put("" + c + c, "ッ" + c); } substitutions.put("nn", "ン"); fromTable(katakanaTable); + System.out.println("katakana " + substitutions); } @Preset public static void hiragana() { - substitutions.clear(); + substitutions = new LinkedHashMap<>(); substitutions.put("-", "ー"); for (char c : consonants) { substitutions.put("" + c + c, "っ" + c); } substitutions.put("nn", "ん"); fromTable(hiraganaTable); + System.out.println("hiragana " + substitutions); } } diff --git a/src/client/java/io/gitlab/jfronny/chattransform/Substitution.java b/src/client/java/io/gitlab/jfronny/chattransform/Substitution.java new file mode 100644 index 0000000..82cecc7 --- /dev/null +++ b/src/client/java/io/gitlab/jfronny/chattransform/Substitution.java @@ -0,0 +1,11 @@ +package io.gitlab.jfronny.chattransform; + +public record Substitution(int start, int end, long time) { + public Substitution(int start, int end) { + this(start, end, System.currentTimeMillis()); + } + + public boolean shouldShow() { + return time >= System.currentTimeMillis() - 500; + } +} diff --git a/src/client/java/io/gitlab/jfronny/chattransform/TransformStart.java b/src/client/java/io/gitlab/jfronny/chattransform/TransformStart.java new file mode 100644 index 0000000..2987f83 --- /dev/null +++ b/src/client/java/io/gitlab/jfronny/chattransform/TransformStart.java @@ -0,0 +1,50 @@ +package io.gitlab.jfronny.chattransform; + +public class TransformStart { + private boolean available = false; + private int value = -1; + private boolean hasPrevious = false; + private int previous = -1; + private long previousTime; + + public void clear() { + this.available = false; + this.hasPrevious = false; + } + + public void set(int value) { + if (available) { + previous = this.value; + previousTime = System.currentTimeMillis(); + hasPrevious = true; + } else available = true; + if (value < 0) value = 0; + this.value = value; + } + + public int get() { + if (!available) throw new IllegalStateException("TransformStart is not set"); + return value; + } + + public void increment() { + set(get() + 1); + } + + public boolean isAvailable() { + return available; + } + + public boolean hasPrevious() { + return hasPrevious; + } + + public int getPrevious() { + if (!hasPrevious) throw new IllegalStateException("TransformStart has no previous"); + return previous; + } + + public boolean showPrevious() { + return hasPrevious() && previousTime >= System.currentTimeMillis() - 500; + } +} diff --git a/src/client/java/io/gitlab/jfronny/chattransform/mixin/TextFieldWidgetMixin.java b/src/client/java/io/gitlab/jfronny/chattransform/mixin/TextFieldWidgetMixin.java index ecc3530..9e73e45 100644 --- a/src/client/java/io/gitlab/jfronny/chattransform/mixin/TextFieldWidgetMixin.java +++ b/src/client/java/io/gitlab/jfronny/chattransform/mixin/TextFieldWidgetMixin.java @@ -1,6 +1,7 @@ package io.gitlab.jfronny.chattransform.mixin; import io.gitlab.jfronny.chattransform.*; +import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawableHelper; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.widget.ClickableWidget; @@ -33,6 +34,7 @@ public abstract class TextFieldWidgetMixin extends ClickableWidget implements IT @Shadow public abstract void setCursor(int cursor); @Shadow private Predicate textPredicate; + @Shadow @Final private TextRenderer textRenderer; @Unique private boolean chattransform$active = false; @Override public void chattransform$activate() { @@ -47,7 +49,7 @@ public abstract class TextFieldWidgetMixin extends ClickableWidget implements IT if (selectionStart == selectionEnd && tx.length() == 1 && !Screen.hasAltDown() && !getText().startsWith("/")) { chattransform$shouldTransform = true; } else { - chattransform$start = null; + transformStart.clear(); } } this.text = value; @@ -63,36 +65,37 @@ public abstract class TextFieldWidgetMixin extends ClickableWidget implements IT @Inject(method = "setCursor(I)V", at = @At("TAIL")) void updateStartOnSetCursor(int cursor, CallbackInfo ci) { - chattransform$start = null; + transformStart.clear(); + lastSubstitution = null; } - @Unique private Integer chattransform$start = null; + @Unique private final TransformStart transformStart = new TransformStart(); + @Unique private Substitution lastSubstitution = null; void transform() { - if (chattransform$start == null) chattransform$start = selectionStart - 1; - if (chattransform$start < 0) chattransform$start = 0; - if (chattransform$start >= selectionStart) return; - String currentString = getText().substring(chattransform$start, selectionStart); + if (!transformStart.isAvailable()) transformStart.set(selectionStart - 1); + if (transformStart.get() >= selectionStart) return; + String currentString = getText().substring(transformStart.get(), selectionStart); Set> complete = getStartingWith(currentString); // Exact match if (Cfg.substitutions.containsKey(currentString) && complete.size() == 1 - && substitute(chattransform$start, selectionStart, Cfg.substitutions.get(currentString))) { - chattransform$start = selectionStart; + && substitute(transformStart.get(), selectionStart, Cfg.substitutions.get(currentString))) { + transformStart.set(selectionStart); return; } if (complete.isEmpty()) { - if (chattransform$start == selectionStart - 1) { + if (transformStart.get() == selectionStart - 1) { // Nothing starts with this char - chattransform$start++; + transformStart.increment(); } else { // Something previously started with this... - String previousString = getText().substring(chattransform$start, selectionStart - 1); + String previousString = getText().substring(transformStart.get(), selectionStart - 1); if (Cfg.substitutions.containsKey(previousString) // ...and matched -> replace - && substitute(chattransform$start, selectionStart - 1, Cfg.substitutions.get(previousString))) { + && substitute(transformStart.get(), selectionStart - 1, Cfg.substitutions.get(previousString))) { setCursor(selectionStart + 1); } else { // ...and didn't match -> move transform start and call transform again (substring might have matched) - chattransform$start++; + transformStart.increment(); transform(); } } @@ -102,11 +105,11 @@ public abstract class TextFieldWidgetMixin extends ClickableWidget implements IT @Override public String chattransform$finalize() { String str = getText(); - if (chattransform$start == null || chattransform$start >= selectionStart) return str; - String currentString = str.substring(chattransform$start, selectionStart); + if (!transformStart.isAvailable() || transformStart.get() >= selectionStart) return str; + String currentString = str.substring(transformStart.get(), selectionStart); if (!Cfg.substitutions.containsKey(currentString) - || !substitute(chattransform$start, selectionStart, Cfg.substitutions.get(currentString))) { - chattransform$start++; + || !substitute(transformStart.get(), selectionStart, Cfg.substitutions.get(currentString))) { + transformStart.increment(); return chattransform$finalize(); } return str; @@ -119,9 +122,10 @@ public abstract class TextFieldWidgetMixin extends ClickableWidget implements IT this.text = sub; int oldLen = end - start; int newLen = substitution.length(); - if (selectionStart > end) selectionStart -= oldLen + newLen; + if (selectionStart > end) selectionStart += newLen - oldLen; else if (selectionStart > start) selectionStart = start + newLen; selectionEnd = selectionStart; + lastSubstitution = new Substitution(start, start + newLen); return true; } else return false; } @@ -132,10 +136,45 @@ public abstract class TextFieldWidgetMixin extends ClickableWidget implements IT @Inject(method = "renderButton(Lnet/minecraft/client/util/math/MatrixStack;IIF)V", at = @At(value = "TAIL")) void renderTransformStart(MatrixStack matrices, int mouseX, int mouseY, float delta, CallbackInfo ci) { - if (isVisible() && chattransform$start != null) { - int x = getCharacterX(chattransform$start); + if (isVisible() && Cfg.visualize) { int y = this.drawsBackground ? this.getY() + (this.height - 8) / 2 : this.getY(); - DrawableHelper.fill(matrices, x, y - 1, x + 1, y + 1 + 9, 0x7f0000ff); + if (transformStart.isAvailable()) { + int x = getCharacterX(transformStart.get()); + chattransform$fill(matrices, x, y - 1, x + 1, y + 1 + 9, 0x7f0000ff); + } + if (transformStart.showPrevious()) { + int x = getCharacterX(transformStart.getPrevious()); + chattransform$fill(matrices, x, y - 1, x + 1, y + 1 + 9, 0x7fff0000); + } + if (lastSubstitution != null && lastSubstitution.shouldShow()) { + int start = getCharacterX(lastSubstitution.start()); + int end = getCharacterX(Math.min(lastSubstitution.end() + 1, text.length())); + chattransform$fill(matrices, start, y - 1, end, y + 1 + 9, 0x7fffff00); + } } } + + @Unique + private void chattransform$fill(MatrixStack matrices, int x1, int y1, int x2, int y2, int color) { + if (x1 < 0) x1 = 0; + if (x2 < 0) x2 = 0; + int maxX = getX() + getWidth(); + if (x1 > maxX) x1 = maxX; + if (x2 > maxX) x2 = maxX; + + if (x1 < x2) { + int i = x1; + x1 = x2; + x2 = i; + } + + if (y1 < y2) { + int i = y1; + y1 = y2; + y2 = i; + } + + textRenderer.draw(matrices, "X={" + x1 + ";" + x2 + "} Y={" + y1 + ";" + y2 + "}", 0, 0, 0xFF000000); + fill(matrices, x1, y1, x2, y2, color); + } } diff --git a/src/client/resources/assets/chat-transform/lang/en_us.json b/src/client/resources/assets/chat-transform/lang/en_us.json index 32f937c..953c8f6 100644 --- a/src/client/resources/assets/chat-transform/lang/en_us.json +++ b/src/client/resources/assets/chat-transform/lang/en_us.json @@ -4,6 +4,8 @@ "chat-transform.jfconfig.substitutions.tooltip": "The substitutions to perform on text sent in the chat. See the presets for examples", "chat-transform.jfconfig.mode": "Mode", "chat-transform.jfconfig.mode.tooltip": "When to perform replacements", + "chat-transform.jfconfig.visualize": "Visualize", + "chat-transform.jfconfig.visualize.tooltip": "Visualize transformations as you type in live mode", "chat-transform.jfconfig.enum.Mode.Live": "Live", "chat-transform.jfconfig.enum.Mode.OnSend": "On Send" } \ No newline at end of file