From 59e80ec6a01edcfc1a27a98dced7793cffadb70b Mon Sep 17 00:00:00 2001 From: mudkip989 Date: Fri, 15 Dec 2023 16:42:06 -0600 Subject: [PATCH 01/53] Nbs Decoder now handles Custom Instruments with names --- .../mod/commands/impl/other/NBSCommand.java | 6 +++++ .../mod/features/commands/NbsSearchMenu.java | 2 +- .../mod/features/commands/nbs/NBSDecoder.java | 8 ++++-- .../features/commands/nbs/NBSToTemplate.java | 27 +++++++++++++------ .../mod/features/commands/nbs/SongData.java | 8 +++++- 5 files changed, 39 insertions(+), 12 deletions(-) diff --git a/src/main/java/io/github/homchom/recode/mod/commands/impl/other/NBSCommand.java b/src/main/java/io/github/homchom/recode/mod/commands/impl/other/NBSCommand.java index 7eaa7f32b..fe04a678f 100644 --- a/src/main/java/io/github/homchom/recode/mod/commands/impl/other/NBSCommand.java +++ b/src/main/java/io/github/homchom/recode/mod/commands/impl/other/NBSCommand.java @@ -27,14 +27,20 @@ import java.io.File; import java.io.IOException; +import static io.github.homchom.recode.RecodeKt.logDebug; + public class NBSCommand extends Command { public static void loadNbs(File file, String fileName) { LegacyRecode.executor.submit(() -> { try { + SongData d = NBSDecoder.parse(file); + String code = new NBSToTemplate(d).convert(); + ItemStack stack = new ItemStack(Items.NOTE_BLOCK); + TemplateUtil.compressTemplateNBT(stack, d.getName(), d.getAuthor(), code); if (d.getName().length() == 0) { diff --git a/src/main/java/io/github/homchom/recode/mod/features/commands/NbsSearchMenu.java b/src/main/java/io/github/homchom/recode/mod/features/commands/NbsSearchMenu.java index eadcdcd57..7bd18eebd 100644 --- a/src/main/java/io/github/homchom/recode/mod/features/commands/NbsSearchMenu.java +++ b/src/main/java/io/github/homchom/recode/mod/features/commands/NbsSearchMenu.java @@ -126,7 +126,7 @@ public void open(String... args) throws CommandSyntaxException { int length = Integer .parseInt(notearr[notearr.length - 1].split(":")[0]); SongData d = new SongData("Song " + id, "Recode", 20f, - length, notes, "", "", 1, 0, 0); + length, notes, "", "", 1, 0, 0, new String[1]); String code = new NBSToTemplate(d).convert(); diff --git a/src/main/java/io/github/homchom/recode/mod/features/commands/nbs/NBSDecoder.java b/src/main/java/io/github/homchom/recode/mod/features/commands/nbs/NBSDecoder.java index b03331b8a..795034231 100644 --- a/src/main/java/io/github/homchom/recode/mod/features/commands/nbs/NBSDecoder.java +++ b/src/main/java/io/github/homchom/recode/mod/features/commands/nbs/NBSDecoder.java @@ -6,6 +6,8 @@ import java.io.*; import java.math.BigDecimal; +import static io.github.homchom.recode.RecodeKt.logDebug; + // Credit to https://github.com/koca2000/NoteBlockAPI/blob/master/src/main/java/com/xxmicloxx/NoteBlockAPI/NBSDecoder.java public class NBSDecoder { @@ -165,19 +167,21 @@ private static SongData parse(InputStream inputStream, File songFile) throws IOE customInstruments = dataInputStream.readByte(); int[] customPitchList = new int[customInstruments]; + String[] customNameList = new String[customInstruments]; if (customInstruments >= 1) { for (int i = 0; i < customInstruments; i++) { int instrumentOffset = vanillaInstruments + customInstruments; int instrumentPitch = 0; - readString(dataInputStream); //Instrument name + customNameList[i] = readString(dataInputStream); //Instrument name readString(dataInputStream); //Sound file instrumentPitch = dataInputStream.readByte(); //Sound pitch customPitchList[i] = instrumentPitch; + dataInputStream.readByte(); //Press key } } @@ -223,7 +227,7 @@ private static SongData parse(InputStream inputStream, File songFile) throws IOE } - return new SongData(title, author, speed, (int) Math.ceil((length + 1.0) / (4 * timeSignature)) * (4 * timeSignature), stringBuilder.toString(), file, layerStringBuilder.toString(), (loopTick + 1), loopCount, customInstruments); + return new SongData(title, author, speed, (int) Math.ceil((length + 1.0) / (4 * timeSignature)) * (4 * timeSignature), stringBuilder.toString(), file, layerStringBuilder.toString(), (loopTick + 1), loopCount, customInstruments, customNameList); } private static short readShort(DataInputStream dataInputStream) throws IOException { diff --git a/src/main/java/io/github/homchom/recode/mod/features/commands/nbs/NBSToTemplate.java b/src/main/java/io/github/homchom/recode/mod/features/commands/nbs/NBSToTemplate.java index 37f9f3fa6..c87f9dc25 100644 --- a/src/main/java/io/github/homchom/recode/mod/features/commands/nbs/NBSToTemplate.java +++ b/src/main/java/io/github/homchom/recode/mod/features/commands/nbs/NBSToTemplate.java @@ -1,7 +1,12 @@ package io.github.homchom.recode.mod.features.commands.nbs; +import io.github.homchom.recode.*; +import org.slf4j.*; + import java.math.BigDecimal; +import static io.github.homchom.recode.RecodeKt.logDebug; + public class NBSToTemplate { private static final String SONG_PARSER_VERSION = "4"; @@ -16,6 +21,7 @@ public class NBSToTemplate { final int loopTick; final int loopCount; final int customInstrumentCount; + final String[] customInstrumentNames; String name; String author; @@ -33,6 +39,7 @@ public NBSToTemplate(SongData song) { this.loopTick = song.getLoopTick(); this.loopCount = song.getLoopCount(); this.customInstrumentCount = song.getCustomInstrumentCount(); + this.customInstrumentNames = song.getCustomInstrumentNames(); } public String convert() { @@ -43,7 +50,6 @@ public String convert() { StringBuilder instList = new StringBuilder(); String songTempo = new BigDecimal(this.speed).stripTrailingZeros().toPlainString(); - if (name.length() == 0) { if (filename.indexOf(".") > 0) { name = filename.substring(0, filename.lastIndexOf(".")); @@ -60,7 +66,6 @@ public String convert() { boolean chestInited = false; int noteCount = 0; boolean finalNote = false; - for (int i = 0; i < songData.length; i++) { boolean closeChest = false; if (slot == 1) { @@ -73,7 +78,6 @@ public String convert() { if (slot >= 27) { closeChest = true; } - if (!closeChest) { String currentNote = songData[i]; String revertString = currentNotes.toString(); @@ -84,7 +88,6 @@ public String convert() { currentNotes.append("=").append(currentNote); } noteCount++; - if (currentNotes.length() > 1930) { currentNotes = new StringBuilder(revertString); currentBlock.append(String.format(",{\"item\":{\"id\":\"txt\",\"data\":{\"name\":\"%s\"}},\"slot\":%d}", currentNotes, slot)); @@ -111,7 +114,6 @@ public String convert() { } else { varActionType = "AppendValue"; } - currentBlock.append(String.format("]},\"action\":\"%s\"},", varActionType)); code.append(currentBlock); currentBlock.setLength(0); @@ -124,7 +126,6 @@ public String convert() { slot = 1; } } - //CreateList: instrumentNames if (customInstrumentCount == 0) { code.append("{\"id\":\"block\",\"block\":\"set_var\",\"args\":{\"items\":[{\"item\":{\"id\":\"var\",\"data\":{\"name\":\"instrumentNames\",\"scope\":\"local\"}},\"slot\":0},{\"item\":{\"id\":\"txt\",\"data\":{\"name\":\"Harp\"}},\"slot\":1},{\"item\":{\"id\":\"txt\",\"data\":{\"name\":\"Bass\"}},\"slot\":2},{\"item\":{\"id\":\"txt\",\"data\":{\"name\":\"Bass Drum\"}},\"slot\":3},{\"item\":{\"id\":\"txt\",\"data\":{\"name\":\"Snare Drum\"}},\"slot\":4},{\"item\":{\"id\":\"txt\",\"data\":{\"name\":\"Click\"}},\"slot\":5},{\"item\":{\"id\":\"txt\",\"data\":{\"name\":\"Guitar\"}},\"slot\":6},{\"item\":{\"id\":\"txt\",\"data\":{\"name\":\"Flute\"}},\"slot\":7},{\"item\":{\"id\":\"txt\",\"data\":{\"name\":\"Bell\"}},\"slot\":8},{\"item\":{\"id\":\"txt\",\"data\":{\"name\":\"Chime\"}},\"slot\":9},{\"item\":{\"id\":\"txt\",\"data\":{\"name\":\"Xylophone\"}},\"slot\":10},{\"item\":{\"id\":\"txt\",\"data\":{\"name\":\"Iron Xylophone\"}},\"slot\":11},{\"item\":{\"id\":\"txt\",\"data\":{\"name\":\"Cow Bell\"}},\"slot\":12},{\"item\":{\"id\":\"txt\",\"data\":{\"name\":\"Didgeridoo\"}},\"slot\":13},{\"item\":{\"id\":\"txt\",\"data\":{\"name\":\"Bit\"}},\"slot\":14},{\"item\":{\"id\":\"txt\",\"data\":{\"name\":\"Banjo\"}},\"slot\":15},{\"item\":{\"id\":\"txt\",\"data\":{\"name\":\"Pling\"}},\"slot\":16}]},\"action\":\"CreateList\"},"); @@ -134,12 +135,22 @@ public String convert() { int currentSlot; currentSlot = 17; + int currentFails = 0; + for (int currentInstID = 1; currentInstID <= customInstrumentCount; currentInstID++) { + String currentName = "Custom Instrument"; + currentName = customInstrumentNames[currentInstID - 1]; + if(currentName == null || currentName.matches("^(\\s+)$") || currentName == ""){ + currentFails++; + currentName = ""; + } + String formatted; if (currentInstID == customInstrumentCount) { - instList.append(String.format("{\"item\":{\"id\":\"txt\",\"data\":{\"name\":\"\"}},\"slot\":%d}", currentInstID, currentSlot)); + formatted = "{\"item\":{\"id\":\"txt\",\"data\":{\"name\":\"" + currentName + "\"}},\"slot\":" + currentSlot + "}"; } else { - instList.append(String.format("{\"item\":{\"id\":\"txt\",\"data\":{\"name\":\"\"}},\"slot\":%d},", currentInstID, currentSlot)); + formatted = "{\"item\":{\"id\":\"txt\",\"data\":{\"name\":\"" + currentName + "\"}},\"slot\":" + currentSlot + "},"; } + instList.append(formatted); currentSlot++; } instList.append("]},\"action\":\"CreateList\"},"); diff --git a/src/main/java/io/github/homchom/recode/mod/features/commands/nbs/SongData.java b/src/main/java/io/github/homchom/recode/mod/features/commands/nbs/SongData.java index 802634d13..913de8a43 100644 --- a/src/main/java/io/github/homchom/recode/mod/features/commands/nbs/SongData.java +++ b/src/main/java/io/github/homchom/recode/mod/features/commands/nbs/SongData.java @@ -7,13 +7,14 @@ public class SongData { final int loopTick; final int loopCount; final int customInstrumentCount; + final String[] customInstrumentNames; String name; String author; float speed; String fileName; String notes; - public SongData(String name, String author, float speed, int length, String notes, String fileName, String layers, int loopTick, int loopCount, int customInstrumentCount) { + public SongData(String name, String author, float speed, int length, String notes, String fileName, String layers, int loopTick, int loopCount, int customInstrumentCount, String[] customInstrumentNames) { this.name = name; this.author = author; this.speed = speed; @@ -24,6 +25,7 @@ public SongData(String name, String author, float speed, int length, String note this.loopTick = loopTick; this.loopCount = loopCount; this.customInstrumentCount = customInstrumentCount; + this.customInstrumentNames = customInstrumentNames; } public String getName() { @@ -85,4 +87,8 @@ public int getLoopCount() { public int getCustomInstrumentCount() { return customInstrumentCount; } + + public String[] getCustomInstrumentNames() { + return customInstrumentNames; + } } From bda6a4ac2525693f7648e0ea97123de0279a9c2f Mon Sep 17 00:00:00 2001 From: mudkip989 Date: Fri, 15 Dec 2023 17:32:54 -0600 Subject: [PATCH 02/53] Cleaned up commit before pull request --- .../homchom/recode/mod/commands/impl/other/NBSCommand.java | 6 ------ .../recode/mod/features/commands/nbs/NBSDecoder.java | 3 --- .../recode/mod/features/commands/nbs/NBSToTemplate.java | 5 ----- 3 files changed, 14 deletions(-) diff --git a/src/main/java/io/github/homchom/recode/mod/commands/impl/other/NBSCommand.java b/src/main/java/io/github/homchom/recode/mod/commands/impl/other/NBSCommand.java index fe04a678f..7eaa7f32b 100644 --- a/src/main/java/io/github/homchom/recode/mod/commands/impl/other/NBSCommand.java +++ b/src/main/java/io/github/homchom/recode/mod/commands/impl/other/NBSCommand.java @@ -27,20 +27,14 @@ import java.io.File; import java.io.IOException; -import static io.github.homchom.recode.RecodeKt.logDebug; - public class NBSCommand extends Command { public static void loadNbs(File file, String fileName) { LegacyRecode.executor.submit(() -> { try { - SongData d = NBSDecoder.parse(file); - String code = new NBSToTemplate(d).convert(); - ItemStack stack = new ItemStack(Items.NOTE_BLOCK); - TemplateUtil.compressTemplateNBT(stack, d.getName(), d.getAuthor(), code); if (d.getName().length() == 0) { diff --git a/src/main/java/io/github/homchom/recode/mod/features/commands/nbs/NBSDecoder.java b/src/main/java/io/github/homchom/recode/mod/features/commands/nbs/NBSDecoder.java index 795034231..957d4c4f4 100644 --- a/src/main/java/io/github/homchom/recode/mod/features/commands/nbs/NBSDecoder.java +++ b/src/main/java/io/github/homchom/recode/mod/features/commands/nbs/NBSDecoder.java @@ -6,8 +6,6 @@ import java.io.*; import java.math.BigDecimal; -import static io.github.homchom.recode.RecodeKt.logDebug; - // Credit to https://github.com/koca2000/NoteBlockAPI/blob/master/src/main/java/com/xxmicloxx/NoteBlockAPI/NBSDecoder.java public class NBSDecoder { @@ -181,7 +179,6 @@ private static SongData parse(InputStream inputStream, File songFile) throws IOE customPitchList[i] = instrumentPitch; - dataInputStream.readByte(); //Press key } } diff --git a/src/main/java/io/github/homchom/recode/mod/features/commands/nbs/NBSToTemplate.java b/src/main/java/io/github/homchom/recode/mod/features/commands/nbs/NBSToTemplate.java index c87f9dc25..3363fb009 100644 --- a/src/main/java/io/github/homchom/recode/mod/features/commands/nbs/NBSToTemplate.java +++ b/src/main/java/io/github/homchom/recode/mod/features/commands/nbs/NBSToTemplate.java @@ -1,12 +1,7 @@ package io.github.homchom.recode.mod.features.commands.nbs; -import io.github.homchom.recode.*; -import org.slf4j.*; - import java.math.BigDecimal; -import static io.github.homchom.recode.RecodeKt.logDebug; - public class NBSToTemplate { private static final String SONG_PARSER_VERSION = "4"; From 2cd20ab7eb9bd7112b1af6cbb23530cde9b62ab9 Mon Sep 17 00:00:00 2001 From: pomchom Date: Sat, 16 Dec 2023 16:51:25 -0500 Subject: [PATCH 03/53] add support --- CHANGELOG.md | 2 +- .../feature/visual/ExpressionHighlighting.kt | 12 +++--- .../homchom/recode/hypercube/DFMiniMessage.kt | 38 +++++++++++++++++++ .../recode/hypercube/HypercubeConstants.kt | 9 +---- .../recode/ui/text/MiniMessageHighlighter.kt | 5 +-- 5 files changed, 47 insertions(+), 19 deletions(-) create mode 100644 src/main/java/io/github/homchom/recode/hypercube/DFMiniMessage.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index 669c37375..84c3533c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,5 +18,5 @@ For Minecraft 1.20.2, Fabric API 0.90.7 or newer - More obscure fixes to location overlay and state-related features (thanks ShadowEmpress_) ### Removals -- Removed `/schem` +- Removed `/schem` (#65) - Removed `/gradient` in favor of `` \ No newline at end of file diff --git a/src/main/java/io/github/homchom/recode/feature/visual/ExpressionHighlighting.kt b/src/main/java/io/github/homchom/recode/feature/visual/ExpressionHighlighting.kt index c7bc077b2..c5b15e15b 100644 --- a/src/main/java/io/github/homchom/recode/feature/visual/ExpressionHighlighting.kt +++ b/src/main/java/io/github/homchom/recode/feature/visual/ExpressionHighlighting.kt @@ -1,9 +1,6 @@ package io.github.homchom.recode.feature.visual -import io.github.homchom.recode.hypercube.CommandAliasGroup -import io.github.homchom.recode.hypercube.DFValueMeta -import io.github.homchom.recode.hypercube.dfMiniMessage -import io.github.homchom.recode.hypercube.dfValueMeta +import io.github.homchom.recode.hypercube.* import io.github.homchom.recode.ui.text.* import io.github.homchom.recode.util.regex.regex import net.kyori.adventure.text.BuildableComponent @@ -77,6 +74,9 @@ class ExpressionHighlighter { 0xff4242 ) + private val miniMessage = dfMiniMessage + private val miniMessageHighlighter = MiniMessageHighlighter(DFMiniMessageTags.all) + private val codeRegex = regex { group { str("%") @@ -171,7 +171,7 @@ class ExpressionHighlighter { if (parseMiniMessage) builder.raw.mapChildren { text -> if (text is TextComponent && text.style().isEmpty) { - MiniMessageHighlighter.highlight(text.content()) as BuildableComponent<*, *> + miniMessageHighlighter.highlight(text.content()) as BuildableComponent<*, *> } else { text } @@ -179,7 +179,7 @@ class ExpressionHighlighter { val text = builder.build().toFormattedCharSequence(false) val preview = if (parseMiniMessage) { - dfMiniMessage.deserialize(string).toFormattedCharSequence() + miniMessage.deserialize(string).toFormattedCharSequence() } else null return HighlightedExpression(text, preview) } diff --git a/src/main/java/io/github/homchom/recode/hypercube/DFMiniMessage.kt b/src/main/java/io/github/homchom/recode/hypercube/DFMiniMessage.kt new file mode 100644 index 000000000..a3264e8d1 --- /dev/null +++ b/src/main/java/io/github/homchom/recode/hypercube/DFMiniMessage.kt @@ -0,0 +1,38 @@ +package io.github.homchom.recode.hypercube + +import io.github.homchom.recode.ui.text.literalText +import net.kyori.adventure.text.minimessage.MiniMessage +import net.kyori.adventure.text.minimessage.tag.Tag +import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver +import net.kyori.adventure.text.minimessage.tag.standard.StandardTags + +/** + * A [MiniMessage] instance to match DiamondFire's MiniMessage behavior. + */ +val dfMiniMessage = MiniMessage.builder().run { + tags(DFMiniMessageTags.all) + build() +} + +/** + * An object providing access to DiamondFire's MiniMessage [TagResolver]s. + * + * @see dfMiniMessage + * @see StandardTags + */ +@Suppress("MemberVisibilityCanBePrivate") +object DFMiniMessageTags { + inline val standard get() = StandardTags.defaults() + + val space = TagResolver.resolver("space") { args, context -> + val count = if (args.hasNext()) { + args.pop().asInt().orElseThrow { + context.newException("Count must be a number") + } + } else 1 + if (count < 0) throw context.newException("Count must be non-negative") + Tag.inserting(literalText(" ".repeat(count))) + } + + val all = TagResolver.resolver(standard, space) +} \ No newline at end of file diff --git a/src/main/java/io/github/homchom/recode/hypercube/HypercubeConstants.kt b/src/main/java/io/github/homchom/recode/hypercube/HypercubeConstants.kt index 0cff9390d..8e7b3adc9 100644 --- a/src/main/java/io/github/homchom/recode/hypercube/HypercubeConstants.kt +++ b/src/main/java/io/github/homchom/recode/hypercube/HypercubeConstants.kt @@ -2,8 +2,6 @@ package io.github.homchom.recode.hypercube -import net.kyori.adventure.text.minimessage.MiniMessage - const val SERVER_ADDRESS = "mcdiamondfire.com" const val DIAMOND = '◆' @@ -14,9 +12,4 @@ const val BOOSTER_ARROW = '⏵' const val TOKEN_NOTCH_CHAR = '□' -const val LAGSLAYER_PREFIX = """[LagSlayer]""" - -/** - * A [MiniMessage] instance to match DiamondFire's MiniMessage behavior. - */ -val dfMiniMessage = MiniMessage.miniMessage() \ No newline at end of file +const val LAGSLAYER_PREFIX = """[LagSlayer]""" \ No newline at end of file diff --git a/src/main/java/io/github/homchom/recode/ui/text/MiniMessageHighlighter.kt b/src/main/java/io/github/homchom/recode/ui/text/MiniMessageHighlighter.kt index 7d0ea4cd5..92639ab34 100644 --- a/src/main/java/io/github/homchom/recode/ui/text/MiniMessageHighlighter.kt +++ b/src/main/java/io/github/homchom/recode/ui/text/MiniMessageHighlighter.kt @@ -1,6 +1,5 @@ package io.github.homchom.recode.ui.text -import io.github.homchom.recode.ui.text.MiniMessageHighlighter.highlight import io.github.homchom.recode.util.interpolate import net.kyori.adventure.text.Component import net.kyori.adventure.text.format.TextDecoration @@ -20,7 +19,7 @@ import net.kyori.adventure.text.minimessage.tree.Node * * @see highlight */ -object MiniMessageHighlighter { +class MiniMessageHighlighter(private val standardTags: TagResolver) { // a resolver for tags that determine their own style private val nonLiteralTags = TagResolver.resolver( StandardTags.color(), @@ -33,8 +32,6 @@ object MiniMessageHighlighter { StandardTags.rainbow() ) - private val standardTags = TagResolver.standard() - private val instance = MiniMessage.builder().run { tags(object : TagResolver { override fun resolve(name: String, arguments: ArgumentQueue, ctx: Context): Tag? { From 86d06749977874d10a274b5a390f53099297feeb Mon Sep 17 00:00:00 2001 From: pomchom Date: Sat, 16 Dec 2023 17:20:47 -0500 Subject: [PATCH 04/53] a very partial fix for the /recode icon --- .../commands/recode/ContributorsUI.java | 5 ++--- .../features/commands/recode/RecodeUI.java | 8 ++++---- .../recode/sys/renderer/widgets/CImage.java | 19 ------------------- 3 files changed, 6 insertions(+), 26 deletions(-) delete mode 100644 src/main/java/io/github/homchom/recode/sys/renderer/widgets/CImage.java diff --git a/src/main/java/io/github/homchom/recode/mod/features/commands/recode/ContributorsUI.java b/src/main/java/io/github/homchom/recode/mod/features/commands/recode/ContributorsUI.java index 2e0d69ced..78d6fd4f4 100644 --- a/src/main/java/io/github/homchom/recode/mod/features/commands/recode/ContributorsUI.java +++ b/src/main/java/io/github/homchom/recode/mod/features/commands/recode/ContributorsUI.java @@ -10,7 +10,6 @@ import io.github.cottonmc.cotton.gui.widget.WScrollPanel; import io.github.homchom.recode.sys.networking.WebUtil; import io.github.homchom.recode.sys.renderer.IMenu; -import io.github.homchom.recode.sys.renderer.widgets.CImage; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.texture.DynamicTexture; import net.minecraft.network.chat.Component; @@ -32,7 +31,7 @@ public static ContributorsUI getInstance() { @Override public void open(String... args) { - INSTANCE = this; + /*INSTANCE = this; WPlainPanel root = new WPlainPanel(); root.setHost(this); @@ -86,6 +85,6 @@ public void open(String... args) { panel.setHost(this); setRootPanel(root); - + */ } } \ No newline at end of file diff --git a/src/main/java/io/github/homchom/recode/mod/features/commands/recode/RecodeUI.java b/src/main/java/io/github/homchom/recode/mod/features/commands/recode/RecodeUI.java index 0b7163862..ab90c62be 100644 --- a/src/main/java/io/github/homchom/recode/mod/features/commands/recode/RecodeUI.java +++ b/src/main/java/io/github/homchom/recode/mod/features/commands/recode/RecodeUI.java @@ -4,10 +4,10 @@ import io.github.cottonmc.cotton.gui.widget.WButton; import io.github.cottonmc.cotton.gui.widget.WLabel; import io.github.cottonmc.cotton.gui.widget.WPlainPanel; +import io.github.cottonmc.cotton.gui.widget.WSprite; import io.github.homchom.recode.Recode; import io.github.homchom.recode.mod.config.menu.ConfigScreen; import io.github.homchom.recode.sys.renderer.IMenu; -import io.github.homchom.recode.sys.renderer.widgets.CImage; import net.minecraft.Util; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screens.ConfirmLinkScreen; @@ -23,9 +23,9 @@ public void open(String... args) { WPlainPanel root = new WPlainPanel(); root.setSize(220, 220); - CImage cImage = new CImage(RECODE_ICON); - cImage.setSize(120, 120); - root.add(cImage, 46, 0); + WSprite sprite = new WSprite(RECODE_ICON); + sprite.setSize(120, 120); + root.add(sprite, 8, 8); root.add(new WLabel(Component.literal("recode")), (220 - Minecraft.getInstance().font.width("recode")) / 2, 110); root.add(new WLabel(Component.literal("v" + Recode.INSTANCE.getVersion())), (220 - Minecraft.getInstance().font.width("v" + Recode.INSTANCE.getVersion())) / 2, 120); diff --git a/src/main/java/io/github/homchom/recode/sys/renderer/widgets/CImage.java b/src/main/java/io/github/homchom/recode/sys/renderer/widgets/CImage.java deleted file mode 100644 index 8e0866640..000000000 --- a/src/main/java/io/github/homchom/recode/sys/renderer/widgets/CImage.java +++ /dev/null @@ -1,19 +0,0 @@ -package io.github.homchom.recode.sys.renderer.widgets; - -import io.github.cottonmc.cotton.gui.client.ScreenDrawing; -import io.github.cottonmc.cotton.gui.widget.WWidget; -import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.resources.ResourceLocation; - -public class CImage extends WWidget { - private final ResourceLocation identifier; - - public CImage(ResourceLocation identifier) { - this.identifier = identifier; - } - - @Override - public void paint(GuiGraphics guiGraphics, int x, int y, int mouseX, int mouseY) { - ScreenDrawing.texturedRect(guiGraphics, x, y, getWidth(), getHeight(), identifier, 0, 0, 1, 1, 0xffffff, 1f); - } -} From a368197028d29db5be21be614c7e566c168d8e40 Mon Sep 17 00:00:00 2001 From: pomchom Date: Sun, 17 Dec 2023 22:03:11 -0500 Subject: [PATCH 05/53] partial formatting fix --- .../visual/EditBoxExpressionFormatter.kt | 159 +++++++++++++++ .../feature/visual/ExpressionHighlighting.kt | 189 +++++------------- .../homchom/recode/hypercube/DFValueMeta.kt | 2 + .../render/chat/MCommandSuggestions.java | 43 ++-- .../commands/recode/ContributorsUI.java | 7 +- .../ui/text/FormattedCharSequenceBuilder.kt | 13 +- .../FormattedCharSequenceTransformations.kt | 21 +- .../recode/util/BasicTypeExtensions.kt | 4 + 8 files changed, 250 insertions(+), 188 deletions(-) create mode 100644 src/main/java/io/github/homchom/recode/feature/visual/EditBoxExpressionFormatter.kt diff --git a/src/main/java/io/github/homchom/recode/feature/visual/EditBoxExpressionFormatter.kt b/src/main/java/io/github/homchom/recode/feature/visual/EditBoxExpressionFormatter.kt new file mode 100644 index 000000000..9315656da --- /dev/null +++ b/src/main/java/io/github/homchom/recode/feature/visual/EditBoxExpressionFormatter.kt @@ -0,0 +1,159 @@ +package io.github.homchom.recode.feature.visual + +import io.github.homchom.recode.hypercube.CommandAliasGroup +import io.github.homchom.recode.ui.text.formattedCharSequence +import io.github.homchom.recode.ui.text.subSequence +import io.github.homchom.recode.util.regex.regex +import net.minecraft.util.FormattedCharSequence +import kotlin.math.max +import kotlin.math.min + +private val highlightedCommands = buildList { + fun addGroup( + group: CommandAliasGroup, + highlightedArgumentIndex: Int = 0, + hasCount: Boolean = false, + parseMiniMessage: Boolean = true + ) { + addAll(group.map { prefix -> + CommandInfo(prefix, highlightedArgumentIndex, hasCount, parseMiniMessage) + }) + } + + addGroup(CommandAliasGroup.NUMBER, hasCount = true, parseMiniMessage = false) + addGroup(CommandAliasGroup.STRING, hasCount = true, parseMiniMessage = false) + addGroup(CommandAliasGroup.TEXT, hasCount = true) + addGroup(CommandAliasGroup.VARIABLE, hasCount = true, parseMiniMessage = false) + addGroup(CommandAliasGroup.ITEM_NAME) + addGroup(CommandAliasGroup.ITEM_LORE_ADD) + addGroup(CommandAliasGroup.ITEM_LORE_SET, highlightedArgumentIndex = 1) + addGroup(CommandAliasGroup.PLOT_NAME) + addGroup(CommandAliasGroup.RELORE) +} + +/** + * An object that retrofits [net.minecraft.client.gui.components.EditBox] for expression highlighting. + * + * @param formatCommands Whether to format commands for highlighting. + * @param formatValues Should return `true` to parse MiniMessage when formatting values, `false` to not, + * or `null` to not format values at all. + * + * @see format + * @see ExpressionHighlighter + */ +class EditBoxExpressionFormatter( + private val formatCommands: Boolean, + private val formatValues: () -> Boolean? +) { + private val highlighter = ExpressionHighlighter() + + /** + * Formats [chatInput] for highlighting. + * + * @param partialParentFormat The partial [FormattedCharSequence] of the parent formatter. + * @param partialRange The range of [partialParentFormat] within the complete sequence. + * + * @see [net.minecraft.client.gui.components.EditBox.setFormatter] + */ + fun format( + chatInput: String, + partialParentFormat: FormattedCharSequence, + partialRange: IntRange + ): HighlightedExpression? { + // highlight commands + if (formatCommands && chatInput.startsWith('/')) { + val command = highlightedCommands.firstNotNullOfOrNull { info -> + info.takeIf { chatInput.startsWith(info.prefix, 1) } + } ?: return null + return formatCommand(chatInput, partialParentFormat, partialRange, command) + } + + // highlight values + formatValues()?.let { parseMiniMessage -> + val highlighted = highlighter.highlightString( + chatInput, + parseMiniMessage + ) + val subSequence = highlighted.text.subSequence(partialRange) + return HighlightedExpression(subSequence, highlighted.preview) + } + + return null + } + + private fun formatCommand( + chatInput: String, + partialParentFormat: FormattedCharSequence, + partialRange: IntRange, + info: CommandInfo + ): HighlightedExpression? { + var startIndex = info.prefix.length + 2 + var endIndex = chatInput.length + if (startIndex > chatInput.lastIndex) return null + + if (info.highlightedArgumentIndex > 0) { + val regex = leadingArgumentsRegex(info.highlightedArgumentIndex) + regex.find(chatInput, startIndex)?.let { match -> + startIndex = match.range.last + 1 + if (startIndex > chatInput.lastIndex) return null + } + } + if (info.hasCount) { + countRegex.find(chatInput, startIndex)?.let { match -> + endIndex = match.range.first + } + } + + val highlighted = highlighter.highlightString( + chatInput.substring(startIndex, endIndex), + info.parseMiniMessage + ) + + // combine highlight and partial parent format + val combined = formattedCharSequence { + val partialStart = partialRange.first + val partialEnd = partialRange.last + 1 + + if (partialStart < startIndex) append(partialParentFormat.subSequence( + 0, + min(startIndex, partialEnd) - partialStart + )) + + if (partialRange.first in startIndex.. endIndex) append(partialParentFormat.subSequence( + max(endIndex, partialStart) - partialStart, + partialEnd - partialStart + )) + } + + return HighlightedExpression(combined, highlighted.preview) + } +} + +private data class CommandInfo( + val prefix: String, + val highlightedArgumentIndex: Int, + val hasCount: Boolean, + val parseMiniMessage: Boolean +) + +private val countRegex = regex { + space + digit.oneOrMore() + end +} + +private fun leadingArgumentsRegex(highlightIndex: Int) = regex { + group { + none(" ").oneOrMore() + space + } * (highlightIndex - 1) + none(" ").oneOrMore() + space.optional() +} \ No newline at end of file diff --git a/src/main/java/io/github/homchom/recode/feature/visual/ExpressionHighlighting.kt b/src/main/java/io/github/homchom/recode/feature/visual/ExpressionHighlighting.kt index c5b15e15b..b746273ef 100644 --- a/src/main/java/io/github/homchom/recode/feature/visual/ExpressionHighlighting.kt +++ b/src/main/java/io/github/homchom/recode/feature/visual/ExpressionHighlighting.kt @@ -1,78 +1,57 @@ package io.github.homchom.recode.feature.visual -import io.github.homchom.recode.hypercube.* -import io.github.homchom.recode.ui.text.* +import io.github.homchom.recode.hypercube.DFMiniMessageTags +import io.github.homchom.recode.hypercube.dfMiniMessage +import io.github.homchom.recode.ui.text.MiniMessageHighlighter +import io.github.homchom.recode.ui.text.TextBuilder +import io.github.homchom.recode.ui.text.style +import io.github.homchom.recode.ui.text.toFormattedCharSequence import io.github.homchom.recode.util.regex.regex import net.kyori.adventure.text.BuildableComponent import net.kyori.adventure.text.TextComponent import net.minecraft.util.FormattedCharSequence -import net.minecraft.world.entity.player.Player -import net.minecraft.world.item.ItemStack data class HighlightedExpression(val text: FormattedCharSequence, val preview: FormattedCharSequence?) +private val codes = setOf( + "default", + "selected", + "uuid", + "var", + "math", + "damager", + "killer", + "shooter", + "victim", + "projectile", + "random", + "round", + "index", + "entry" +) + +// TODO: new color scheme? +private val colors = listOf( + 0xffd600, + 0x33ff00, + 0x00ffe0, + 0x5e77f7, + 0xca64fa, + 0xff4242 +) + /** - * An object that highlights and caches DF value and MiniMessage expressions. + * An object that highlights and previews DF value and MiniMessage expressions. + * + * For specialized [net.minecraft.client.gui.components.EditBox] highlighting, + * use [EditBoxExpressionFormatter]. * - * @see runHighlighting + * @see highlightString */ class ExpressionHighlighter { - private val codes = setOf( - "default", - "selected", - "uuid", - "var", - "math", - "damager", - "killer", - "shooter", - "victim", - "projectile", - "random", - "round", - "index", - "entry" - ) - - private val highlightedCommands = buildList { - fun addGroup( - group: CommandAliasGroup, - highlightedArgumentIndex: Int = 0, - hasCount: Boolean = false, - parseMiniMessage: Boolean = true - ) { - addAll(group.map { prefix -> - CommandInfo(prefix, highlightedArgumentIndex, hasCount, parseMiniMessage) - }) - } - - addGroup(CommandAliasGroup.NUMBER, hasCount = true, parseMiniMessage = false) - addGroup(CommandAliasGroup.STRING, hasCount = true, parseMiniMessage = false) - addGroup(CommandAliasGroup.TEXT, hasCount = true) - addGroup(CommandAliasGroup.VARIABLE, hasCount = true, parseMiniMessage = false) - addGroup(CommandAliasGroup.ITEM_NAME) - addGroup(CommandAliasGroup.ITEM_LORE_ADD) - addGroup(CommandAliasGroup.ITEM_LORE_SET, highlightedArgumentIndex = 1) - addGroup(CommandAliasGroup.PLOT_NAME) - addGroup(CommandAliasGroup.RELORE) - } - - private data class CommandInfo( - val prefix: String, - val highlightedArgumentIndex: Int, - val hasCount: Boolean, - val parseMiniMessage: Boolean - ) - - // TODO: new color scheme? - private val colors = listOf( - 0xffd600, - 0x33ff00, - 0x00ffe0, - 0x5e77f7, - 0xca64fa, - 0xff4242 - ) + private var cachedString = "" + private var cachedParseMiniMessage = true + private var cachedHighlight = HighlightedExpression(FormattedCharSequence.EMPTY, null) private val miniMessage = dfMiniMessage private val miniMessageHighlighter = MiniMessageHighlighter(DFMiniMessageTags.all) @@ -87,62 +66,17 @@ class ExpressionHighlighter { or; end } - private var cachedInput = "" - private var cachedHighlight = HighlightedExpression(FormattedCharSequence.EMPTY, null) - - private val countRegex = regex { - space - digit.oneOrMore() - end - } - - private fun leadingArgumentsRegex(highlightIndex: Int) = regex { - group { - none(" ").oneOrMore() - space - } * (highlightIndex - 1) - none(" ").oneOrMore() - space.optional() - } - - fun runHighlighting( - chatInput: String, - formatted: FormattedCharSequence, - player: Player - ): HighlightedExpression? { - if (cachedInput == chatInput) return cachedHighlight - - val highlight = highlight(chatInput, formatted, player.mainHandItem) - if (highlight != null) { - cachedInput = chatInput - cachedHighlight = highlight - } - return highlight - } - - private fun highlight( - chatInput: String, - formatted: FormattedCharSequence, - mainHandItem: ItemStack - ): HighlightedExpression? { - // highlight commands - if (chatInput.startsWith('/')) { - val command = highlightedCommands.firstNotNullOfOrNull { info -> - info.takeIf { chatInput.startsWith(info.prefix, 1) } - } ?: return null - return highlightCommand(chatInput, formatted, command) + fun highlightString(string: String, parseMiniMessage: Boolean = true): HighlightedExpression { + if (string != cachedString || parseMiniMessage != cachedParseMiniMessage) { + cachedString = string + cachedParseMiniMessage = parseMiniMessage + cachedHighlight = highlightUncached(string, parseMiniMessage) } - // highlight values - val valueMeta = mainHandItem.dfValueMeta() - if (valueMeta is DFValueMeta.Primitive || valueMeta is DFValueMeta.Variable) { - return highlightString(chatInput, valueMeta.type == "comp") - } - - return null + return cachedHighlight } - private fun highlightString(string: String, parseMiniMessage: Boolean = true): HighlightedExpression { + private fun highlightUncached(string: String, parseMiniMessage: Boolean = true): HighlightedExpression { val builder = TextBuilder() var sliceStart = 0 var depth = 0 @@ -184,33 +118,6 @@ class ExpressionHighlighter { return HighlightedExpression(text, preview) } - private fun highlightCommand( - input: String, - formatted: FormattedCharSequence, - info: CommandInfo - ): HighlightedExpression? { - var startIndex = info.prefix.length + 2 - var endIndex = input.length - if (startIndex > input.lastIndex) return null - - if (info.highlightedArgumentIndex > 0) { - val regex = leadingArgumentsRegex(info.highlightedArgumentIndex) - regex.find(input, startIndex)?.let { match -> - startIndex = match.range.last + 1 - if (startIndex > input.lastIndex) return null - } - } - if (info.hasCount) { - countRegex.find(input, startIndex)?.let { match -> - endIndex = match.range.first - } - } - - val highlighted = highlightString(input.substring(startIndex, endIndex), info.parseMiniMessage) - val combined = formatted.replaceRange(startIndex.. { + var player = Objects.requireNonNull(Minecraft.getInstance().player); + var meta = DFValues.dfValueMeta(player.getMainHandItem()); + if (meta instanceof DFValueMeta.Primitive || meta instanceof DFValueMeta.Variable) { + return meta.getType().equals("comp"); + } + return null; + }); @Unique private @Nullable FormattedCharSequence preview = null; @Shadow @Final EditBox input; + // expression highlighting and preview @Inject(method = "formatChat", at = @At("RETURN"), cancellable = true) private void highlightAndPreview( String partialInput, int position, CallbackInfoReturnable cir ) { - var formatted = cir.getReturnValue(); - var player = Objects.requireNonNull(Minecraft.getInstance().player); - var highlighted = highlighter.runHighlighting(input.getValue(), formatted, player); - if (highlighted == null) return; - - if (highlighted.getPreview() != null) preview = highlighted.getPreview(); - - FormattedCharSequence subSequence; - if (position == 0 && partialInput.length() == input.getValue().length()) { - subSequence = highlighted.getText(); - } else { - subSequence = FormattedCharSequenceTransformations.subSequence( - highlighted.getText(), - position, - position + partialInput.length() - ); + var formatted = highlighter.format( + input.getValue(), + cir.getReturnValue(), + new IntRange(position, position + partialInput.length() - 1) + ); + if (formatted != null) { + cir.setReturnValue(formatted.getText()); + preview = formatted.getPreview(); } - - cir.setReturnValue(subSequence); } @Inject(method = "render", at = @At("HEAD")) diff --git a/src/main/java/io/github/homchom/recode/mod/features/commands/recode/ContributorsUI.java b/src/main/java/io/github/homchom/recode/mod/features/commands/recode/ContributorsUI.java index 78d6fd4f4..1014289e5 100644 --- a/src/main/java/io/github/homchom/recode/mod/features/commands/recode/ContributorsUI.java +++ b/src/main/java/io/github/homchom/recode/mod/features/commands/recode/ContributorsUI.java @@ -1,6 +1,6 @@ package io.github.homchom.recode.mod.features.commands.recode; -import com.google.gson.JsonArray; +/*import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.mojang.blaze3d.platform.NativeImage; @@ -31,7 +31,7 @@ public static ContributorsUI getInstance() { @Override public void open(String... args) { - /*INSTANCE = this; + INSTANCE = this; WPlainPanel root = new WPlainPanel(); root.setHost(this); @@ -85,6 +85,5 @@ public void open(String... args) { panel.setHost(this); setRootPanel(root); - */ } -} \ No newline at end of file +}*/ \ No newline at end of file diff --git a/src/main/java/io/github/homchom/recode/ui/text/FormattedCharSequenceBuilder.kt b/src/main/java/io/github/homchom/recode/ui/text/FormattedCharSequenceBuilder.kt index a2f0597c1..ed7c5c7ae 100644 --- a/src/main/java/io/github/homchom/recode/ui/text/FormattedCharSequenceBuilder.kt +++ b/src/main/java/io/github/homchom/recode/ui/text/FormattedCharSequenceBuilder.kt @@ -40,23 +40,30 @@ value class FormattedCharSequenceBuilder private constructor(private val list: M /** * Appends [string] in forward order with [style]. */ - fun forward(string: String, style: StyleWrapper) { + fun forward(string: String, style: StyleWrapper = style()) { list += FormattedCharSequence.forward(string, style.build().toVanilla()) } /** * Appends [string] in backward order with [style]. */ - fun backward(string: String, style: StyleWrapper) { + fun backward(string: String, style: StyleWrapper = style()) { list += FormattedCharSequence.backward(string, style.build().toVanilla()) } /** * Appends the character with code point [code], with [style]. */ - fun codepoint(code: Int, style: StyleWrapper) { + fun codepoint(code: Int, style: StyleWrapper = style()) { list += FormattedCharSequence.codepoint(code, style.build().toVanilla()) } + + /** + * Appends a pre-existing [formattedCharSequence]. + */ + fun append(formattedCharSequence: FormattedCharSequence) { + list += formattedCharSequence + } } /** diff --git a/src/main/java/io/github/homchom/recode/ui/text/FormattedCharSequenceTransformations.kt b/src/main/java/io/github/homchom/recode/ui/text/FormattedCharSequenceTransformations.kt index e40f56b10..288657884 100644 --- a/src/main/java/io/github/homchom/recode/ui/text/FormattedCharSequenceTransformations.kt +++ b/src/main/java/io/github/homchom/recode/ui/text/FormattedCharSequenceTransformations.kt @@ -18,23 +18,6 @@ fun FormattedCharSequence.subSequence(startIndex: Int, endIndex: Int) = Formatte } /** - * @see CharSequence.replaceRange + * @see CharSequence.subSequence */ -fun FormattedCharSequence.replaceRange( - range: IntRange, - replacement: FormattedCharSequence -): FormattedCharSequence { - return FormattedCharSequence { sink -> - var index = 0 - var adjustedIndex = 0 - accept { _, style, codePoint -> - when (index++) { - range.first -> replacement.accept { _, style2, codePoint2 -> - sink.accept(adjustedIndex++, style2, codePoint2) - } - in range -> true - else -> sink.accept(adjustedIndex++, style, codePoint) - } - } - } -} \ No newline at end of file +fun FormattedCharSequence.subSequence(range: IntRange) = subSequence(range.first, range.last) \ No newline at end of file diff --git a/src/main/java/io/github/homchom/recode/util/BasicTypeExtensions.kt b/src/main/java/io/github/homchom/recode/util/BasicTypeExtensions.kt index f2a312fad..06d1c4f09 100644 --- a/src/main/java/io/github/homchom/recode/util/BasicTypeExtensions.kt +++ b/src/main/java/io/github/homchom/recode/util/BasicTypeExtensions.kt @@ -2,11 +2,15 @@ package io.github.homchom.recode.util +// booleans + /** * @return [Unit] if this boolean is true, or `null` otherwise. */ fun Boolean.unitOrNull() = if (this) Unit else null +// strings + /** * Appends multiple [substrings] to this [StringBuilder]. */ From e948bf79d5e16b3e482bbc0ae7ecf94703c936d9 Mon Sep 17 00:00:00 2001 From: pomchom Date: Sun, 17 Dec 2023 22:24:53 -0500 Subject: [PATCH 06/53] minimessage try/catch --- .../recode/feature/visual/ExpressionHighlighting.kt | 6 +++++- .../homchom/recode/ui/text/MiniMessageHighlighter.kt | 9 ++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/github/homchom/recode/feature/visual/ExpressionHighlighting.kt b/src/main/java/io/github/homchom/recode/feature/visual/ExpressionHighlighting.kt index b746273ef..1d6f3faaa 100644 --- a/src/main/java/io/github/homchom/recode/feature/visual/ExpressionHighlighting.kt +++ b/src/main/java/io/github/homchom/recode/feature/visual/ExpressionHighlighting.kt @@ -113,7 +113,11 @@ class ExpressionHighlighter { val text = builder.build().toFormattedCharSequence(false) val preview = if (parseMiniMessage) { - miniMessage.deserialize(string).toFormattedCharSequence() + try { + miniMessage.deserialize(string).toFormattedCharSequence() + } catch (e: Exception) { + null + } } else null return HighlightedExpression(text, preview) } diff --git a/src/main/java/io/github/homchom/recode/ui/text/MiniMessageHighlighter.kt b/src/main/java/io/github/homchom/recode/ui/text/MiniMessageHighlighter.kt index 92639ab34..d07e66819 100644 --- a/src/main/java/io/github/homchom/recode/ui/text/MiniMessageHighlighter.kt +++ b/src/main/java/io/github/homchom/recode/ui/text/MiniMessageHighlighter.kt @@ -112,7 +112,14 @@ class MiniMessageHighlighter(private val standardTags: TagResolver) { } } - buildNewInput(instance.deserializeToTree(input)) + val root = try { + instance.deserializeToTree(input) + } catch (e: Exception) { + // highlight red for exceptional parses, such as unclosed double quotes + // TODO: something better after ui update? + return literalText(input, style().red()) + } + buildNewInput(root) return instance.deserialize(newInput.toString()) } From 02ad88a1a055e4e36bca94d77522269ea8cb80e6 Mon Sep 17 00:00:00 2001 From: pomchom Date: Sun, 17 Dec 2023 22:37:08 -0500 Subject: [PATCH 07/53] don't render scope for unnamed var, fix value highlighting bounds --- .../homchom/recode/mod/mixin/inventory/MHeldItemTooltip.java | 2 +- .../recode/ui/text/FormattedCharSequenceTransformations.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/github/homchom/recode/mod/mixin/inventory/MHeldItemTooltip.java b/src/main/java/io/github/homchom/recode/mod/mixin/inventory/MHeldItemTooltip.java index 2149db85c..a6bd13df3 100644 --- a/src/main/java/io/github/homchom/recode/mod/mixin/inventory/MHeldItemTooltip.java +++ b/src/main/java/io/github/homchom/recode/mod/mixin/inventory/MHeldItemTooltip.java @@ -59,7 +59,7 @@ public void renderSelectedItemName(GuiGraphics guiGraphics, CallbackInfo callbac guiGraphics.drawString(font, nameText, x1, y1, 0xffffff, true); var lore = ItemExtensions.lore(lastToolHighlight); - if (!lore.isEmpty()) { + if (lore.size() == 1) { var scope = TextInterop.toVanilla(lore.get(0)); var x2 = (scaledWidth - font.width(scope)) / 2; var y2 = scaledHeight - 35; diff --git a/src/main/java/io/github/homchom/recode/ui/text/FormattedCharSequenceTransformations.kt b/src/main/java/io/github/homchom/recode/ui/text/FormattedCharSequenceTransformations.kt index 288657884..27544bdf0 100644 --- a/src/main/java/io/github/homchom/recode/ui/text/FormattedCharSequenceTransformations.kt +++ b/src/main/java/io/github/homchom/recode/ui/text/FormattedCharSequenceTransformations.kt @@ -20,4 +20,4 @@ fun FormattedCharSequence.subSequence(startIndex: Int, endIndex: Int) = Formatte /** * @see CharSequence.subSequence */ -fun FormattedCharSequence.subSequence(range: IntRange) = subSequence(range.first, range.last) \ No newline at end of file +fun FormattedCharSequence.subSequence(range: IntRange) = subSequence(range.first, range.last + 1) \ No newline at end of file From 3bc1f0fce606bfaf5a05321717d5fcd9cdff3d48 Mon Sep 17 00:00:00 2001 From: pomchom Date: Tue, 19 Dec 2023 13:34:32 -0500 Subject: [PATCH 08/53] repeatable newline, df parity/crash fix, duck cleanup --- .../homchom/recode/feature/social/SideChat.kt | 4 +-- .../homchom/recode/hypercube/DFMiniMessage.kt | 30 ++++++++++++------- .../mixin/multiplayer/MChatListener.java | 2 +- .../optional/sodium/MSodiumWorldRenderer.java | 6 ++-- .../render/MBlockEntityRenderDispatcher.java | 4 +-- .../homchom/recode/mixin/render/MGui.java | 3 +- .../recode/mixin/render/MLevelRenderer.java | 4 +-- .../homchom/recode/mixin/render/MWindow.java | 2 +- .../mixin/render/chat/MChatComponent.java | 2 +- .../recode/mixin/render/chat/MChatScreen.java | 6 +++- .../homchom/recode/render/RenderEvents.kt | 4 +-- .../recode/ui/text/MiniMessageHighlighter.kt | 1 - 12 files changed, 39 insertions(+), 29 deletions(-) diff --git a/src/main/java/io/github/homchom/recode/feature/social/SideChat.kt b/src/main/java/io/github/homchom/recode/feature/social/SideChat.kt index afd432e36..c45165c5a 100644 --- a/src/main/java/io/github/homchom/recode/feature/social/SideChat.kt +++ b/src/main/java/io/github/homchom/recode/feature/social/SideChat.kt @@ -45,7 +45,7 @@ class SideChat(private val mc: Minecraft) : ChatComponent(mc) { /** * A duck interface applied to [net.minecraft.client.gui.Gui]. */ -@Suppress("FunctionName") +@Suppress("PropertyName") interface DGuiWithSideChat { - fun `recode$getSideChat`(): SideChat + val `recode$sideChat`: SideChat } \ No newline at end of file diff --git a/src/main/java/io/github/homchom/recode/hypercube/DFMiniMessage.kt b/src/main/java/io/github/homchom/recode/hypercube/DFMiniMessage.kt index a3264e8d1..bc8a048a6 100644 --- a/src/main/java/io/github/homchom/recode/hypercube/DFMiniMessage.kt +++ b/src/main/java/io/github/homchom/recode/hypercube/DFMiniMessage.kt @@ -22,17 +22,25 @@ val dfMiniMessage = MiniMessage.builder().run { */ @Suppress("MemberVisibilityCanBePrivate") object DFMiniMessageTags { + private const val MAX_REPETITION_COUNT = 32 + + // TODO: remove this when adventure 5.15.0 inline val standard get() = StandardTags.defaults() - val space = TagResolver.resolver("space") { args, context -> - val count = if (args.hasNext()) { - args.pop().asInt().orElseThrow { - context.newException("Count must be a number") - } - } else 1 - if (count < 0) throw context.newException("Count must be non-negative") - Tag.inserting(literalText(" ".repeat(count))) - } - - val all = TagResolver.resolver(standard, space) + val space = repetitionTagResolver("space", " ") + val repeatableNewline = repetitionTagResolver("newline", "\n") + + val all = TagResolver.resolver(standard, space, repeatableNewline) + + private fun repetitionTagResolver(name: String, literal: String) = + TagResolver.resolver(name) { args, context -> + val count = if (args.hasNext()) { + args.pop().asInt().orElseThrow { + context.newException("Count must be a number") + } + } else 1 + + val repeated = literal.repeat(count.coerceAtMost(MAX_REPETITION_COUNT)) + Tag.selfClosingInserting(literalText(repeated)) + } } \ No newline at end of file diff --git a/src/main/java/io/github/homchom/recode/mixin/multiplayer/MChatListener.java b/src/main/java/io/github/homchom/recode/mixin/multiplayer/MChatListener.java index c2eda870d..938ce6546 100644 --- a/src/main/java/io/github/homchom/recode/mixin/multiplayer/MChatListener.java +++ b/src/main/java/io/github/homchom/recode/mixin/multiplayer/MChatListener.java @@ -66,6 +66,6 @@ private ChatRule.ChatSide matchToChatSide(Component message) { @Unique private SideChat getSideChat() { var gui = (DGuiWithSideChat) Minecraft.getInstance().gui; - return gui.recode$getSideChat(); + return gui.getRecode$sideChat(); } } diff --git a/src/main/java/io/github/homchom/recode/mixin/optional/sodium/MSodiumWorldRenderer.java b/src/main/java/io/github/homchom/recode/mixin/optional/sodium/MSodiumWorldRenderer.java index 757063a18..d6d78e715 100644 --- a/src/main/java/io/github/homchom/recode/mixin/optional/sodium/MSodiumWorldRenderer.java +++ b/src/main/java/io/github/homchom/recode/mixin/optional/sodium/MSodiumWorldRenderer.java @@ -3,7 +3,7 @@ import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import io.github.homchom.recode.mixin.MixinConditional; -import io.github.homchom.recode.render.RecodeLevelRenderer; +import io.github.homchom.recode.render.DRecodeLevelRenderer; import me.jellysquid.mods.sodium.client.render.SodiumWorldRenderer; import me.jellysquid.mods.sodium.client.render.chunk.RenderSection; import net.minecraft.client.Minecraft; @@ -34,7 +34,7 @@ public abstract class MSodiumWorldRenderer { var blockEntityList = List.of(blockEntities); var chunkPos = SectionPos.of(blockEntityList.get(0).getBlockPos()); - var levelRenderer = (RecodeLevelRenderer) Minecraft.getInstance().levelRenderer; + var levelRenderer = (DRecodeLevelRenderer) Minecraft.getInstance().levelRenderer; return levelRenderer.recode$runBlockEntityEvents(blockEntityList, chunkPos) .toArray(new BlockEntity[0]); } @@ -49,7 +49,7 @@ public abstract class MSodiumWorldRenderer { var blockEntities = operation.call(section); if (blockEntities == null || blockEntities.length == 0) return blockEntities; - var levelRenderer = (RecodeLevelRenderer) Minecraft.getInstance().levelRenderer; + var levelRenderer = (DRecodeLevelRenderer) Minecraft.getInstance().levelRenderer; return levelRenderer.recode$runBlockEntityEvents(List.of(blockEntities), null) .toArray(new BlockEntity[0]); } diff --git a/src/main/java/io/github/homchom/recode/mixin/render/MBlockEntityRenderDispatcher.java b/src/main/java/io/github/homchom/recode/mixin/render/MBlockEntityRenderDispatcher.java index 2189316bc..2ffa80b51 100644 --- a/src/main/java/io/github/homchom/recode/mixin/render/MBlockEntityRenderDispatcher.java +++ b/src/main/java/io/github/homchom/recode/mixin/render/MBlockEntityRenderDispatcher.java @@ -1,7 +1,7 @@ package io.github.homchom.recode.mixin.render; import io.github.homchom.recode.render.Blaze3DExtensions; -import io.github.homchom.recode.render.RecodeLevelRenderer; +import io.github.homchom.recode.render.DRecodeLevelRenderer; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher; @@ -14,7 +14,7 @@ public abstract class MBlockEntityRenderDispatcher { @ModifyVariable(method = "render", at = @At("HEAD"), ordinal = 0, argsOnly = true) private MultiBufferSource outlineBlockEntities(MultiBufferSource multiBufferSource, BlockEntity blockEntity) { - var processor = (RecodeLevelRenderer) Minecraft.getInstance().levelRenderer; + var processor = (DRecodeLevelRenderer) Minecraft.getInstance().levelRenderer; var outlineColor = processor.recode$getBlockEntityOutlineColor(blockEntity); if (outlineColor != null) { return Blaze3DExtensions.withOutline(multiBufferSource, outlineColor); diff --git a/src/main/java/io/github/homchom/recode/mixin/render/MGui.java b/src/main/java/io/github/homchom/recode/mixin/render/MGui.java index ef7070fa2..e5119a6e5 100644 --- a/src/main/java/io/github/homchom/recode/mixin/render/MGui.java +++ b/src/main/java/io/github/homchom/recode/mixin/render/MGui.java @@ -32,10 +32,9 @@ private void renderSideChat( sideChat.render(graphics, tickDelta, x, y); } - @Unique @NotNull @Override - public SideChat recode$getSideChat() { + public SideChat getRecode$sideChat() { return sideChat; } } diff --git a/src/main/java/io/github/homchom/recode/mixin/render/MLevelRenderer.java b/src/main/java/io/github/homchom/recode/mixin/render/MLevelRenderer.java index 4cab5cadc..5dc026de6 100644 --- a/src/main/java/io/github/homchom/recode/mixin/render/MLevelRenderer.java +++ b/src/main/java/io/github/homchom/recode/mixin/render/MLevelRenderer.java @@ -5,7 +5,7 @@ import io.github.homchom.recode.event.SimpleValidated; import io.github.homchom.recode.render.BlockEntityOutlineContext; import io.github.homchom.recode.render.RGBAColor; -import io.github.homchom.recode.render.RecodeLevelRenderer; +import io.github.homchom.recode.render.DRecodeLevelRenderer; import io.github.homchom.recode.render.RenderEvents; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.LevelRenderer; @@ -28,7 +28,7 @@ import java.util.*; @Mixin(value = LevelRenderer.class) -public abstract class MLevelRenderer implements RecodeLevelRenderer { +public abstract class MLevelRenderer implements DRecodeLevelRenderer { @Shadow @Nullable private PostChain entityEffect; @Unique diff --git a/src/main/java/io/github/homchom/recode/mixin/render/MWindow.java b/src/main/java/io/github/homchom/recode/mixin/render/MWindow.java index 3c8fae036..cf84a27cd 100644 --- a/src/main/java/io/github/homchom/recode/mixin/render/MWindow.java +++ b/src/main/java/io/github/homchom/recode/mixin/render/MWindow.java @@ -13,6 +13,6 @@ public abstract class MWindow { @Inject(method = "setGuiScale", at = @At("TAIL")) private void rescaleSideChat(CallbackInfo ci) { var gui = (DGuiWithSideChat) Minecraft.getInstance().gui; - gui.recode$getSideChat().rescaleChat(); + gui.getRecode$sideChat().rescaleChat(); } } \ No newline at end of file diff --git a/src/main/java/io/github/homchom/recode/mixin/render/chat/MChatComponent.java b/src/main/java/io/github/homchom/recode/mixin/render/chat/MChatComponent.java index 8e89cc777..8eb84fc81 100644 --- a/src/main/java/io/github/homchom/recode/mixin/render/chat/MChatComponent.java +++ b/src/main/java/io/github/homchom/recode/mixin/render/chat/MChatComponent.java @@ -73,7 +73,7 @@ private void clearSideChat(boolean refresh, CallbackInfo ci) { @Unique private SideChat getSideChat() { var gui = (DGuiWithSideChat) Minecraft.getInstance().gui; - return gui.recode$getSideChat(); + return gui.getRecode$sideChat(); } @Unique diff --git a/src/main/java/io/github/homchom/recode/mixin/render/chat/MChatScreen.java b/src/main/java/io/github/homchom/recode/mixin/render/chat/MChatScreen.java index 2ad1f8938..e3f542fef 100644 --- a/src/main/java/io/github/homchom/recode/mixin/render/chat/MChatScreen.java +++ b/src/main/java/io/github/homchom/recode/mixin/render/chat/MChatScreen.java @@ -6,12 +6,16 @@ import net.minecraft.client.GuiMessageTag; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.components.ChatComponent; +import net.minecraft.client.gui.components.EditBox; import net.minecraft.client.gui.screens.ChatScreen; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @Mixin(ChatScreen.class) public abstract class MChatScreen { + @Shadow protected EditBox input; + @WrapOperation(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/components/ChatComponent;getMessageTagAt(DD)Lnet/minecraft/client/GuiMessageTag;" )) @@ -24,6 +28,6 @@ private GuiMessageTag recognizeSideChatTags( var mainTag = operation.call(mainChat, screenX, screenY); if (mainTag != null) return mainTag; var gui = (DGuiWithSideChat) Minecraft.getInstance().gui; - return gui.recode$getSideChat().getMessageTagAt(screenX, screenY); + return gui.getRecode$sideChat().getMessageTagAt(screenX, screenY); } } diff --git a/src/main/java/io/github/homchom/recode/render/RenderEvents.kt b/src/main/java/io/github/homchom/recode/render/RenderEvents.kt index 642565c31..0b94452f4 100644 --- a/src/main/java/io/github/homchom/recode/render/RenderEvents.kt +++ b/src/main/java/io/github/homchom/recode/render/RenderEvents.kt @@ -50,7 +50,7 @@ val OutlineBlockEntitiesEvent = event.use(Power( onEnable = { BeforeOutlineBlockEvent.listenEach { context -> - val processor = context.worldRenderContext.worldRenderer() as RecodeLevelRenderer + val processor = context.worldRenderContext.worldRenderer() as DRecodeLevelRenderer processor.`recode$processOutlines`(mc.frameTime) } } @@ -68,7 +68,7 @@ data class BlockEntityOutlineContext @JvmOverloads constructor( * An [net.minecraft.client.renderer.LevelRenderer] that is augmented by recode. */ @Suppress("FunctionName") -interface RecodeLevelRenderer { +interface DRecodeLevelRenderer { /** * @returns A filtered list of block entities that should still be rendered. */ diff --git a/src/main/java/io/github/homchom/recode/ui/text/MiniMessageHighlighter.kt b/src/main/java/io/github/homchom/recode/ui/text/MiniMessageHighlighter.kt index d07e66819..9c616decd 100644 --- a/src/main/java/io/github/homchom/recode/ui/text/MiniMessageHighlighter.kt +++ b/src/main/java/io/github/homchom/recode/ui/text/MiniMessageHighlighter.kt @@ -27,7 +27,6 @@ class MiniMessageHighlighter(private val standardTags: TagResolver) { StandardTags.decorations(TextDecoration.OBFUSCATED) ), StandardTags.reset(), - StandardTags.font(), StandardTags.gradient(), StandardTags.rainbow() ) From 513f28519d8d60a256f9b420c542a5af623aef9b Mon Sep 17 00:00:00 2001 From: pomchom Date: Tue, 19 Dec 2023 14:01:04 -0500 Subject: [PATCH 09/53] fix highlight setting --- .../github/homchom/recode/mixin/render/chat/MChatScreen.java | 4 ---- .../homchom/recode/mixin/render/chat/MCommandSuggestions.java | 2 ++ src/main/resources/assets/recode/lang/en_us.json | 4 ++-- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/main/java/io/github/homchom/recode/mixin/render/chat/MChatScreen.java b/src/main/java/io/github/homchom/recode/mixin/render/chat/MChatScreen.java index e3f542fef..bf116edcd 100644 --- a/src/main/java/io/github/homchom/recode/mixin/render/chat/MChatScreen.java +++ b/src/main/java/io/github/homchom/recode/mixin/render/chat/MChatScreen.java @@ -6,16 +6,12 @@ import net.minecraft.client.GuiMessageTag; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.components.ChatComponent; -import net.minecraft.client.gui.components.EditBox; import net.minecraft.client.gui.screens.ChatScreen; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @Mixin(ChatScreen.class) public abstract class MChatScreen { - @Shadow protected EditBox input; - @WrapOperation(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/components/ChatComponent;getMessageTagAt(DD)Lnet/minecraft/client/GuiMessageTag;" )) diff --git a/src/main/java/io/github/homchom/recode/mixin/render/chat/MCommandSuggestions.java b/src/main/java/io/github/homchom/recode/mixin/render/chat/MCommandSuggestions.java index 8ed30a515..250c78a9d 100644 --- a/src/main/java/io/github/homchom/recode/mixin/render/chat/MCommandSuggestions.java +++ b/src/main/java/io/github/homchom/recode/mixin/render/chat/MCommandSuggestions.java @@ -3,6 +3,7 @@ import io.github.homchom.recode.feature.visual.EditBoxExpressionFormatter; import io.github.homchom.recode.hypercube.DFValueMeta; import io.github.homchom.recode.hypercube.DFValues; +import io.github.homchom.recode.mod.config.Config; import kotlin.ranges.IntRange; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; @@ -46,6 +47,7 @@ private void highlightAndPreview( int position, CallbackInfoReturnable cir ) { + if (!Config.getBoolean("highlightVarSyntax")) return; var formatted = highlighter.format( input.getValue(), cir.getReturnValue(), diff --git a/src/main/resources/assets/recode/lang/en_us.json b/src/main/resources/assets/recode/lang/en_us.json index 5f339a920..f1613853c 100644 --- a/src/main/resources/assets/recode/lang/en_us.json +++ b/src/main/resources/assets/recode/lang/en_us.json @@ -55,8 +55,8 @@ "config.recode.option.itemApi.tooltip": "Used for sending items from third party programs.", "config.recode.option.variableScopeView": "Variable Scope View", "config.recode.option.variableScopeView.tooltip": "Shows the variable scope under the item name.\n(GAME, SAVE, LOCAL)", - "config.recode.option.highlightVarSyntax": "Highlight Variable Syntax", - "config.recode.option.highlightVarSyntax.tooltip": "Highlights text, num and var syntax\nlike percent and color codes", + "config.recode.option.highlightVarSyntax": "Highlight Expressions", + "config.recode.option.highlightVarSyntax.tooltip": "Highlights and previews expression syntax,\nlike percent codes and MiniMessage", "config.recode.option.showCodeblockDescription": "Show Code Block Description", "config.recode.option.showCodeblockDescription.tooltip": "Shows a description of the currently opened code block.", "config.recode.option.showParameterErrors": "Show Parameter Errors", From cb811a109d4cb2f971d0eb31adb7182d9615fe91 Mon Sep 17 00:00:00 2001 From: pomchom Date: Wed, 20 Dec 2023 12:53:57 -0500 Subject: [PATCH 10/53] sigh --- .../homchom/recode/mixin/render/chat/MCommandSuggestions.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/io/github/homchom/recode/mixin/render/chat/MCommandSuggestions.java b/src/main/java/io/github/homchom/recode/mixin/render/chat/MCommandSuggestions.java index 250c78a9d..dcf516d86 100644 --- a/src/main/java/io/github/homchom/recode/mixin/render/chat/MCommandSuggestions.java +++ b/src/main/java/io/github/homchom/recode/mixin/render/chat/MCommandSuggestions.java @@ -3,6 +3,8 @@ import io.github.homchom.recode.feature.visual.EditBoxExpressionFormatter; import io.github.homchom.recode.hypercube.DFValueMeta; import io.github.homchom.recode.hypercube.DFValues; +import io.github.homchom.recode.hypercube.state.DF; +import io.github.homchom.recode.hypercube.state.PlotMode; import io.github.homchom.recode.mod.config.Config; import kotlin.ranges.IntRange; import net.minecraft.client.Minecraft; @@ -48,6 +50,7 @@ private void highlightAndPreview( CallbackInfoReturnable cir ) { if (!Config.getBoolean("highlightVarSyntax")) return; + if (!DF.isInMode(DF.getCurrentDFState(), PlotMode.Dev.ID)) return; var formatted = highlighter.format( input.getValue(), cir.getReturnValue(), From bc8eaa02a2c61ed5cdd458fda80becfc9f91a709 Mon Sep 17 00:00:00 2001 From: pomchom Date: Wed, 20 Dec 2023 23:45:12 -0500 Subject: [PATCH 11/53] two highlighting fixes (counts and surrogates) --- .../visual/EditBoxExpressionFormatter.kt | 2 +- .../FormattedCharSequenceTransformations.kt | 8 +++----- .../homchom/recode/ui/text/TextBuilders.kt | 6 +++--- .../homchom/recode/ui/text/TextFunctions.kt | 19 ++++++++++++++++++- .../recode/util/BasicTypeExtensions.kt | 5 +++++ 5 files changed, 30 insertions(+), 10 deletions(-) diff --git a/src/main/java/io/github/homchom/recode/feature/visual/EditBoxExpressionFormatter.kt b/src/main/java/io/github/homchom/recode/feature/visual/EditBoxExpressionFormatter.kt index 9315656da..0ff61f9dc 100644 --- a/src/main/java/io/github/homchom/recode/feature/visual/EditBoxExpressionFormatter.kt +++ b/src/main/java/io/github/homchom/recode/feature/visual/EditBoxExpressionFormatter.kt @@ -119,7 +119,7 @@ class EditBoxExpressionFormatter( min(startIndex, partialEnd) - partialStart )) - if (partialRange.first in startIndex.. - var index = 0 - var adjustedIndex = 0 - accept { _, style, codePoint -> - if (index++ in startIndex.. + if (index in startIndex.. + val shouldContinue = sink.accept(absoluteIndex++, style, codePoint) + if (String.fromCodePoint(codePoint)[0].isHighSurrogate()) { + absoluteIndex++ + } + shouldContinue + } +} \ No newline at end of file diff --git a/src/main/java/io/github/homchom/recode/util/BasicTypeExtensions.kt b/src/main/java/io/github/homchom/recode/util/BasicTypeExtensions.kt index 06d1c4f09..05fd42f6e 100644 --- a/src/main/java/io/github/homchom/recode/util/BasicTypeExtensions.kt +++ b/src/main/java/io/github/homchom/recode/util/BasicTypeExtensions.kt @@ -11,6 +11,11 @@ fun Boolean.unitOrNull() = if (this) Unit else null // strings +/** + * @see Character.toString + */ +fun String.Companion.fromCodePoint(codePoint: Int): String = Character.toString(codePoint) + /** * Appends multiple [substrings] to this [StringBuilder]. */ From 509b9bc068210285d36546b849471256caaf5dde Mon Sep 17 00:00:00 2001 From: pomchom Date: Thu, 21 Dec 2023 00:06:53 -0500 Subject: [PATCH 12/53] update scope highlighting description, remove a bunch of periods --- .../resources/assets/recode/lang/en_us.json | 216 +++++++++--------- 1 file changed, 108 insertions(+), 108 deletions(-) diff --git a/src/main/resources/assets/recode/lang/en_us.json b/src/main/resources/assets/recode/lang/en_us.json index f1613853c..4a6e7426a 100644 --- a/src/main/resources/assets/recode/lang/en_us.json +++ b/src/main/resources/assets/recode/lang/en_us.json @@ -30,188 +30,188 @@ "config.recode.category.sidedchat": "Chat Splitting", "config.recode.subcategory.screen_world_rendering": "World Rendering", - "config.recode.subcategory.screen_world_rendering.tooltip": "Features related to rendering a world.", + "config.recode.subcategory.screen_world_rendering.tooltip": "Features related to rendering a world", "config.recode.option.chestReplacement": "Render Chests as Barrels", - "config.recode.option.chestReplacement.tooltip": "Render all chests as a barrel.", + "config.recode.option.chestReplacement.tooltip": "Render all chests as a barrel", "config.recode.option.signRenderDistance": "Sign Render Distance", - "config.recode.option.signRenderDistance.tooltip": "Maximum distance for signs to render.", + "config.recode.option.signRenderDistance.tooltip": "Maximum distance for signs to render", "config.recode.option.plotInfoOverlay": "Location Overlay", - "config.recode.option.plotInfoOverlay.tooltip": "Displays your current DiamondFire location on the screen.", + "config.recode.option.plotInfoOverlay.tooltip": "Displays your current DiamondFire location on the screen", "config.recode.subcategory.screen_title_screen": "Title Screen", - "config.recode.subcategory.screen_title_screen.tooltip": "Options related to the Minecraft title screen.", + "config.recode.subcategory.screen_title_screen.tooltip": "Options related to the Minecraft title screen", "config.recode.subcategory.screen_code": "Code", - "config.recode.subcategory.screen_code.tooltip": "Options that can help render information while coding.", + "config.recode.subcategory.screen_code.tooltip": "Options that can help render information while coding", "config.recode.option.dfButton": "DiamondFire Menu Button", - "config.recode.option.dfButton.tooltip": "Adds a button in the title screen to join DiamondFire.", + "config.recode.option.dfButton.tooltip": "Adds a button in the title screen to join DiamondFire", "config.recode.option.dfNodeButtons": "DiamondFire Node Buttons", - "config.recode.option.dfNodeButtons.tooltip": "Adds node specific buttons in the title screen to join DiamondFire.", + "config.recode.option.dfNodeButtons.tooltip": "Adds node specific buttons in the title screen to join DiamondFire", "config.recode.option.debugMode": "Debug Mode", - "config.recode.option.debugMode.tooltip": "Enables a debug mode for developers. Only if you know what you're doing.", + "config.recode.option.debugMode.tooltip": "Enables a debug mode for developers. Only if you know what you're doing", "config.recode.option.incomingReportSound": "Incoming Report Sound", - "config.recode.option.incomingReportSound.tooltip": "Selects the sound to play upon receiving an incoming report.", + "config.recode.option.incomingReportSound.tooltip": "Selects the sound to play upon receiving an incoming report", "config.recode.option.itemApi": "Item API", - "config.recode.option.itemApi.tooltip": "Used for sending items from third party programs.", + "config.recode.option.itemApi.tooltip": "Used for sending items from third party programs", "config.recode.option.variableScopeView": "Variable Scope View", - "config.recode.option.variableScopeView.tooltip": "Shows the variable scope under the item name.\n(GAME, SAVE, LOCAL)", + "config.recode.option.variableScopeView.tooltip": "Shows the variable scope under the item name", "config.recode.option.highlightVarSyntax": "Highlight Expressions", "config.recode.option.highlightVarSyntax.tooltip": "Highlights and previews expression syntax,\nlike percent codes and MiniMessage", "config.recode.option.showCodeblockDescription": "Show Code Block Description", - "config.recode.option.showCodeblockDescription.tooltip": "Shows a description of the currently opened code block.", + "config.recode.option.showCodeblockDescription.tooltip": "Shows a description of the currently opened code block", "config.recode.option.showParameterErrors": "Show Parameter Errors", - "config.recode.option.showParameterErrors.tooltip": "Shows an alert on your screen when the parameters in the current code block are invalid.", + "config.recode.option.showParameterErrors.tooltip": "Shows an alert on your screen when the parameters in the current code block are invalid", "config.recode.option.previewHeadSkins": "Preview Head Skins", - "config.recode.option.previewHeadSkins.tooltip": "Shows a preview of the skin from a player head when hovering over one.", + "config.recode.option.previewHeadSkins.tooltip": "Shows a preview of the skin from a player head when hovering over one", "config.recode.option.templatePeeking": "Template Peeking", "config.recode.option.templatePeeking.tooltip": "Preview a code template without the\n need of having to place it down\n(NOTE: currently not working)", "config.recode.option.cpuOnScreen": "Show LagSlayer on Screen", - "config.recode.option.cpuOnScreen.tooltip": "Display the LagSlayer CPU bar on the screen\ndirectly instead of the action bar.", + "config.recode.option.cpuOnScreen.tooltip": "Display the LagSlayer CPU bar on the screen\ndirectly instead of the action bar", "config.recode.subcategory.commands_automsg": "Auto /msg", - "config.recode.subcategory.commands_automsg.tooltip": "Will set a conversation with someone when\ndoing /msg , any message sent in chat\nwill automatically be sent to that person only.", + "config.recode.subcategory.commands_automsg.tooltip": "Will set a conversation with someone when\ndoing /msg , any message sent in chat\nwill automatically be sent to that person only", "config.recode.option.automsg": "Enabled", "config.recode.option.automsg.tooltip": "Enable this feature.", "config.recode.option.automsg_timeout": "Timeout Enabled", - "config.recode.option.automsg_timeout.tooltip": "Enable the timeout feature, ending\nautomatically a conversation if it\nis inactive for too long.", - "config.recode.option.automsg_timeoutNumber": "Timeout (in milliseconds).", - "config.recode.option.automsg_timeoutNumber.tooltip": "The time it takes for an inactive\nconversation to end.", + "config.recode.option.automsg_timeout.tooltip": "Enable the timeout feature, ending\nautomatically a conversation if it\nis inactive for too long", + "config.recode.option.automsg_timeoutNumber": "Timeout (in milliseconds)", + "config.recode.option.automsg_timeoutNumber.tooltip": "The time it takes for an inactive\nconversation to end", "config.recode.subcategory.automation_time": "Auto /time", - "config.recode.subcategory.automation_time.tooltip": "Automatically runs /time upon\nentering dev or build mode.", + "config.recode.subcategory.automation_time.tooltip": "Automatically runs /time upon\nentering dev or build mode", "config.recode.option.autotime": "Enabled", - "config.recode.option.autotime.tooltip": "Enable this feature.", + "config.recode.option.autotime.tooltip": "Enable this feature", "config.recode.option.autotimeval": "Auto /time value", - "config.recode.option.autotimeval.tooltip": "Value to use in auto /time.", + "config.recode.option.autotimeval.tooltip": "Value to use in auto /time", "config.recode.option.autowand": "Auto //wand", - "config.recode.option.autowand.tooltip": "Automatically runs //wand upon\nentering build mode.", + "config.recode.option.autowand.tooltip": "Automatically runs //wand upon\nentering build mode", "config.recode.option.autoRC": "Auto /rc", - "config.recode.option.autoRC.tooltip": "Automatically runs /rc upon\nentering dev mode.", + "config.recode.option.autoRC.tooltip": "Automatically runs /rc upon\nentering dev mode", "config.recode.option.autonightvis": "Auto /nightvis", - "config.recode.option.autonightvis.tooltip": "Automatically enables Night Vision\nupon entering dev or build mode.", + "config.recode.option.autonightvis.tooltip": "Automatically enables Night Vision\nupon entering dev or build mode", "config.recode.option.autofly": "Auto /fly", - "config.recode.option.autofly.tooltip": "Automatically runs /fly at spawn.", + "config.recode.option.autofly.tooltip": "Automatically runs /fly at spawn", "config.recode.option.autolagslayer": "Auto /lagslayer", - "config.recode.option.autolagslayer.tooltip": "Automatically display CPU usage upon\njoining one of your plots.", + "config.recode.option.autolagslayer.tooltip": "Automatically display CPU usage upon\njoining one of your plots", "config.recode.option.autoChatLocal": "Auto /chat local", - "config.recode.option.autoChatLocal.tooltip": "Automatically runs /chat local.", + "config.recode.option.autoChatLocal.tooltip": "Automatically runs /chat local", "config.recode.option.autoClickEditMsgs": "Auto click edit msgs", "config.recode.option.autoClickEditMsgs.tooltip": "Automatically click messages like\nthe ones that appear when you\nshift l-click a text", "config.recode.option.autoTip": "Auto Tip", "config.recode.option.autoTip.tooltip": "Automatically runs /tip ", "config.recode.option.dfCommands": "DF Commands", - "config.recode.option.dfCommands.tooltip": "Enables the commands that work only in DiamondFire.", + "config.recode.option.dfCommands.tooltip": "Enables the commands that work only in DiamondFire", "config.recode.option.errorSound": "Error Message Sound", - "config.recode.option.errorSound.tooltip": "Plays a sound when the mod sends error messages.", + "config.recode.option.errorSound.tooltip": "Plays a sound when the mod sends error messages", "config.recode.subcategory.commands_heads": "/heads Command", - "config.recode.subcategory.commands_heads.tooltip": "Settings that apply to the /heads command.", + "config.recode.subcategory.commands_heads.tooltip": "Settings that apply to the /heads command", "config.recode.option.headsEnabled": "Enabled", - "config.recode.option.headsEnabled.tooltip": "Enable this feature.", + "config.recode.option.headsEnabled.tooltip": "Enable this feature", "config.recode.option.headMenuMaxRender": "Maximum Heads in /heads", - "config.recode.option.headMenuMaxRender.tooltip": "Amount of heads to display in the /heads menu.", + "config.recode.option.headMenuMaxRender.tooltip": "Amount of heads to display in the /heads menu", "config.recode.option.colorReplacePicker": "Replace Color Picker", - "config.recode.option.colorReplacePicker.tooltip": "Replaces the color picker with\nDiamondFire's built-in command.", + "config.recode.option.colorReplacePicker.tooltip": "Replaces the color picker with\nDiamondFire's built-in command", "config.recode.subcategory.keybinds_flightspeed": "Flight Speed Keybind Values", - "config.recode.subcategory.keybinds_flightspeed.tooltip": "Values used for the Flight Speed keybinds found\nin the \"Options -> Controls -> Recode\" menu.", + "config.recode.subcategory.keybinds_flightspeed.tooltip": "Values used for the Flight Speed keybinds found\nin the \"Options -> Controls -> Recode\" menu", "config.recode.option.fsNormal": "Flight Speed Normal", - "config.recode.option.fsNormal.tooltip": "Flight speed used for the \"Flight Speed Normal\" keybind.", + "config.recode.option.fsNormal.tooltip": "Flight speed used for the \"Flight Speed Normal\" keybind", "config.recode.option.fsMed": "Flight Speed Medium", - "config.recode.option.fsMed.tooltip": "Flight speed used for the \"Flight Speed Medium\" keybind.", + "config.recode.option.fsMed.tooltip": "Flight speed used for the \"Flight Speed Medium\" keybind", "config.recode.option.fsFast": "Flight Speed Fast", - "config.recode.option.fsFast.tooltip": "Flight speed used for the \"Flight Speed Fast\" keybind.", + "config.recode.option.fsFast.tooltip": "Flight speed used for the \"Flight Speed Fast\" keybind", "config.recode.option.highlight": "Highlight Text in Chat", - "config.recode.option.highlight.tooltip": "Highlights the text below in chat if it gets mentioned\nin a chat message sent by a player.", + "config.recode.option.highlight.tooltip": "Highlights the text below in chat if it gets mentioned\nin a chat message sent by a player", "config.recode.option.highlightIgnoreSender": "Highlight Ignore Message Sender", - "config.recode.option.highlightIgnoreSender.tooltip": "Ignores the sender of the\nchat message for highlighting.", + "config.recode.option.highlightIgnoreSender.tooltip": "Ignores the sender of the\nchat message for highlighting", "config.recode.subcategory.highlight_text": "Text", - "config.recode.subcategory.highlight_text.tooltip": "Settings for text highlighting.", + "config.recode.subcategory.highlight_text.tooltip": "Settings for text highlighting", "config.recode.option.highlightMatcher": "Matcher", - "config.recode.option.highlightMatcher.tooltip": "Text to highlight.\n{name} is replaced with your username.", + "config.recode.option.highlightMatcher.tooltip": "Text to highlight.\n{name} is replaced with your username", "config.recode.option.highlightPrefix": "Prefix", - "config.recode.option.highlightPrefix.tooltip": "The text to put in front of the\nhighlighted text. Supports (hex) color codes.", + "config.recode.option.highlightPrefix.tooltip": "The text to put in front of the\nhighlighted text. Supports (hex) color codes", "config.recode.subcategory.highlight_sound": "Highlight Sound", - "config.recode.subcategory.highlight_sound.tooltip": "Sound settings for when a\ntext highlight is triggered.", + "config.recode.subcategory.highlight_sound.tooltip": "Sound settings for when a\ntext highlight is triggered", "config.recode.option.highlightSound": "Sound to Play", - "config.recode.option.highlightSound.tooltip": "Sound to play when a text highlight\nis triggered. Select \"None\" to disable.", + "config.recode.option.highlightSound.tooltip": "Sound to play when a text highlight\nis triggered. Select \"None\" to disable", "config.recode.option.highlightSoundVolume": "Volume", - "config.recode.option.highlightSoundVolume.tooltip": "Volume of the sound above.", + "config.recode.option.highlightSoundVolume.tooltip": "Volume of the sound above", "config.recode.option.highlightOwnSenderSound": "Play Sound if Sender", "config.recode.option.highlightOwnSenderSound.tooltip": "Plays a sound if you are the message sender. Requires:\n- A sound to be selected\n- The message sender to be ignored", "config.recode.option.hideJoinLeaveMessages": "Hide Join/Leave Messages", - "config.recode.option.hideJoinLeaveMessages.tooltip": "Hides messages of players joining\nor leaving the current node.", + "config.recode.option.hideJoinLeaveMessages.tooltip": "Hides messages of players joining\nor leaving the current node", "config.recode.option.hideVarScopeMessages": "Hide Variable Scope Messages", - "config.recode.option.hideVarScopeMessages.tooltip": "Hides messages about changing variable scopes.", + "config.recode.option.hideVarScopeMessages.tooltip": "Hides messages about changing variable scopes", "config.recode.option.stackDuplicateMsgs": "Message Stacker", - "config.recode.option.stackDuplicateMsgs.tooltip": "Merges multiple messages into one\nif they're the same.", + "config.recode.option.stackDuplicateMsgs.tooltip": "Merges multiple messages into one\nif they're the same", "config.recode.option.hideScoreboardOnF3": "Hide Scoreboard on F3", - "config.recode.option.hideScoreboardOnF3.tooltip": "Hides the scoreboard when the F3 menu is active.", + "config.recode.option.hideScoreboardOnF3.tooltip": "Hides the scoreboard when the F3 menu is active", "config.recode.subcategory.hiding_regex": "Hide Messages Matching Regex", - "config.recode.subcategory.hiding_regex.tooltip": "Hides all messages that match a custom regex.", + "config.recode.subcategory.hiding_regex.tooltip": "Hides all messages that match a custom regex", "config.recode.option.hideMsgMatchingRegex": "Enabled", - "config.recode.option.hideMsgMatchingRegex.tooltip": "Enable this feature.", + "config.recode.option.hideMsgMatchingRegex.tooltip": "Enable this feature", "config.recode.option.hideMsgRegex": "Regex", - "config.recode.option.hideMsgRegex.tooltip": "Regex the message has to match.", + "config.recode.option.hideMsgRegex.tooltip": "Regex the message has to match", "config.recode.subcategory.hiding_staff": "Staff Message Hiding", - "config.recode.subcategory.hiding_staff.tooltip": "Hiding features exclusive\nfor DiamondFire staff members.", + "config.recode.subcategory.hiding_staff.tooltip": "Hiding features exclusive\nfor DiamondFire staff members", "config.recode.option.hideSessionSpy": "[Expert] Hide Session Spy", - "config.recode.option.hideSessionSpy.tooltip": "Hides session spy messages for experts.", + "config.recode.option.hideSessionSpy.tooltip": "Hides session spy messages for experts", "config.recode.option.hideMutedChat": "[Mod] Hide Muted Chat", - "config.recode.option.hideMutedChat.tooltip": "Hides chat messages from\nmuted players for moderators.", + "config.recode.option.hideMutedChat.tooltip": "Hides chat messages from\nmuted players for moderators", "config.recode.option.destroyItemReset": "Destroy Item Reset", - "config.recode.option.destroyItemReset.tooltip": "Resets your inventory to the specified set of items after shift clicking the destroy item slot while in dev mode.", + "config.recode.option.destroyItemReset.tooltip": "Resets your inventory to the specified\nset of items after shift clicking the\ndestroy item slot while in dev mode", "config.recode.option.destroyitemresettype.off": "Off", "config.recode.option.destroyitemresettype.standard": "Standard Items", "config.recode.option.destroyitemresettype.compact": "Compact Items", "config.recode.subcategory.misc_quicknum": "Quick Number Change", - "config.recode.subcategory.misc_quicknum.tooltip": "Allows you to change a number variable\nsimply by scrolling.", + "config.recode.subcategory.misc_quicknum.tooltip": "Allows you to change a number variable\nsimply by scrolling", "config.recode.option.quicknum": "Enable", - "config.recode.option.quicknum.tooltip": "Enable this feature.", + "config.recode.option.quicknum.tooltip": "Enable this feature", "config.recode.option.quicknumSound": "Play sound", - "config.recode.option.quicknumSound.tooltip": "Plays a sound when changing the number.", + "config.recode.option.quicknumSound.tooltip": "Plays a sound when changing the number", "config.recode.option.quicknumPrimaryAmount": "Primary Amount", - "config.recode.option.quicknumPrimaryAmount.tooltip": "Change how much a scroll changes the number.", + "config.recode.option.quicknumPrimaryAmount.tooltip": "Change how much a scroll changes the number", "config.recode.option.quicknumSecondaryAmount": "Secondary Amount", - "config.recode.option.quicknumSecondaryAmount.tooltip": "Change how much a scroll changes the number. (When holding CTRL)", + "config.recode.option.quicknumSecondaryAmount.tooltip": "Change how much a scroll changes the number (When holding CTRL)", "config.recode.option.quicknumTertiaryAmount": "Secondary Amount", - "config.recode.option.quicknumTertiaryAmount.tooltip": "Change how much a scroll changes the number. (When holding SHIFT)", + "config.recode.option.quicknumTertiaryAmount.tooltip": "Change how much a scroll changes the number (When holding SHIFT)", "config.recode.option.chestToolTip": "Chest Tooltip", "config.recode.option.chestToolTip.tooltip": "Display chest params when you are in dev", "config.recode.option.chestToolTipType": "Chest Tooltip Style", - "config.recode.option.chestToolTipType.tooltip": "Choose between regular Minecraft tooltip style \nor raw text in the top left corner.", + "config.recode.option.chestToolTipType.tooltip": "Choose between regular Minecraft tooltip style \nor raw text in the top left corner", - "config.recode.option.streamerDescription": "§9§l§nStreamer Mode\n\n§7Below are options to help make the stream experience better.\n§oExclusive to Jeremaster.", + "config.recode.option.streamerDescription": "§9§l§nStreamer Mode\n\n§7Below are options to help make the stream experience better", "config.recode.option.streamer": "Enabled", - "config.recode.option.streamer.tooltip": "Enable Streamer Mode.\nTurning this option off will make\nall other options no longer work.", + "config.recode.option.streamer.tooltip": "Enable Streamer Mode.\nTurning this option off will make\nall other options no longer work", "config.recode.subcategory.streamer_streamerModules": "Modules", - "config.recode.subcategory.streamer_streamerModules.tooltip": "The individual configurable\nparts of the Streamer Mode.", + "config.recode.subcategory.streamer_streamerModules.tooltip": "The individual configurable\nparts of the Streamer Mode", "config.recode.option.streamerAutoAdminV": "Auto /adminv off", - "config.recode.option.streamerAutoAdminV.tooltip": "Automatically runs \"/adminv off\" silently\nwhen you join a node.", + "config.recode.option.streamerAutoAdminV.tooltip": "Automatically runs \"/adminv off\" silently\nwhen you join a node", "config.recode.option.streamerAutoChatLocal": "Auto /chat local", - "config.recode.option.streamerAutoChatLocal.tooltip": "Automatically runs \"/chat local\" silently\nwhen you join a node or join a plot.", + "config.recode.option.streamerAutoChatLocal.tooltip": "Automatically runs \"/chat local\" silently\nwhen you join a node or join a plot", "config.recode.option.streamerSpies": "Hide Spies", - "config.recode.option.streamerSpies.tooltip": "Hides spy (*) messages, including\nsession spy, muted spy, and DM spy.", + "config.recode.option.streamerSpies.tooltip": "Hides spy (*) messages, including\nsession spy, muted spy, and DM spy", "config.recode.option.streamerHideDMs": "Hide DMs", - "config.recode.option.streamerHideDMs.tooltip": "Hides all incoming private messages.", + "config.recode.option.streamerHideDMs.tooltip": "Hides all incoming private messages", "config.recode.option.streamerHidePlotAds": "Hide Plot Ads", - "config.recode.option.streamerHidePlotAds.tooltip": "Hides plot ads and blocks it's sound.", + "config.recode.option.streamerHidePlotAds.tooltip": "Hides plot ads and blocks it's sound", "config.recode.option.streamerHideBuycraftUpdate": "Hide BuycraftX Update", - "config.recode.option.streamerHideBuycraftUpdate.tooltip": "Hides the BuycraftX plugin update message.", + "config.recode.option.streamerHideBuycraftUpdate.tooltip": "Hides the BuycraftX plugin update message", "config.recode.option.streamerHideSupport": "Hide Support", "config.recode.option.streamerHideSupport.tooltip": "Blocks all support messages and sounds, including:\n- Support broadcast\n- Support queue\n- Support question\n- Support answer", "config.recode.option.streamerHideModeration": "Hide Moderation", @@ -219,37 +219,37 @@ "config.recode.option.streamerHideAdmin": "Hide Admin", "config.recode.option.streamerHideAdmin.tooltip": "Blocks all admin messages and sounds, including:\n- Admin broadcast", "config.recode.subcategory.streamer_streamerRegex": "Hide Messages Matching Regex", - "config.recode.subcategory.streamer_streamerRegex.tooltip": "Option to add your own regex to hide additional messages.", + "config.recode.subcategory.streamer_streamerRegex.tooltip": "Option to add your own regex to hide additional messages", "config.recode.option.streamerHideRegexEnabled": "Enabled", - "config.recode.option.streamerHideRegexEnabled.tooltip": "Enable this feature. Effective only if streamer mode is on.", + "config.recode.option.streamerHideRegexEnabled.tooltip": "Enable this feature. Effective only if streamer mode is on", "config.recode.option.streamerHideRegex": "Regex", - "config.recode.option.streamerHideRegex.tooltip": "Regex the message has to fully match.", + "config.recode.option.streamerHideRegex.tooltip": "Regex the message has to fully match", "config.recode.option.discordRPCDescription": "§9§l§nDiscord Rich Presence\n\n§7Shows where you are in DiamondFire on your Discord user profile.\nThe text fields support a few variables:\n§8- §f${plot.name}\n§8- §f${plot.id}\n§8- §f${plot.status}\n§8- §f${node.id}", "config.recode.option.discordRPC": "Enabled", - "config.recode.option.discordRPC.tooltip": "Enable this feature.", + "config.recode.option.discordRPC.tooltip": "Enable this feature", "config.recode.option.discordRPCShowSession": "Show Support Session", - "config.recode.option.discordRPCShowSession.tooltip": "Shows active support sessions in the presence.", + "config.recode.option.discordRPCShowSession.tooltip": "Shows active support sessions in the presence", "config.recode.subcategory.discordRPC_discordRPCSpawn": "In Spawn", - "config.recode.subcategory.discordRPC_discordRPCSpawn.tooltip": "Settings applied when in spawn.", + "config.recode.subcategory.discordRPC_discordRPCSpawn.tooltip": "Settings applied when in spawn", "config.recode.option.discordRPCSpawnDetails": "Row 1", - "config.recode.option.discordRPCSpawnDetails.tooltip": "Text shown on the first row of the presence.", + "config.recode.option.discordRPCSpawnDetails.tooltip": "Text shown on the first row of the presence", "config.recode.option.discordRPCSpawnState": "Row 2", - "config.recode.option.discordRPCSpawnState.tooltip": "Text shown on the second row of the presence.", + "config.recode.option.discordRPCSpawnState.tooltip": "Text shown on the second row of the presence", "config.recode.subcategory.discordRPC_discordRPCPlot": "In Plot", - "config.recode.subcategory.discordRPC_discordRPCPlot.tooltip": "Settings applied when in a plot.", + "config.recode.subcategory.discordRPC_discordRPCPlot.tooltip": "Settings applied when in a plot", "config.recode.option.discordRPCPlotDetails": "Row 1", - "config.recode.option.discordRPCPlotDetails.tooltip": "Text shown on the first row of the presence.", + "config.recode.option.discordRPCPlotDetails.tooltip": "Text shown on the first row of the presence", "config.recode.option.discordRPCPlotState": "Row 2", - "config.recode.option.discordRPCPlotState.tooltip": "Text shown on the second row of the presence.", + "config.recode.option.discordRPCPlotState.tooltip": "Text shown on the second row of the presence", "config.recode.option.discordRPCShowPlotMode": "Show Plot Mode", - "config.recode.option.discordRPCShowPlotMode.tooltip": "Shows what mode you are currently in.", + "config.recode.option.discordRPCShowPlotMode.tooltip": "Shows what mode you are currently in", "config.recode.subcategory.discordRPC_discordActivityTimeMeasurement": "Elapsed", - "config.recode.subcategory.discordRPC_discordActivityTimeMeasurement.tooltip": "Settings related to the elapsed section on the presence.", + "config.recode.subcategory.discordRPC_discordActivityTimeMeasurement.tooltip": "Settings related to the elapsed section on the presence", "config.recode.option.discordRPCShowElapsed": "Show Elapsed", - "config.recode.option.discordRPCShowElapsed.tooltip": "Shows an elapsed section in the presence.", + "config.recode.option.discordRPCShowElapsed.tooltip": "Shows an elapsed section in the presence", "config.recode.option.discordActivityTimeMeasurement": "Time Measurement", - "config.recode.option.discordActivityTimeMeasurement.tooltip": "The property the elapsed timestamp should be based on.", + "config.recode.option.discordActivityTimeMeasurement.tooltip": "The property the elapsed timestamp should be based on", "config.recode.option.discordActivityTimeMeasurement.in_game": "In game", "config.recode.option.discordActivityTimeMeasurement.on_server": "On DiamondFire", "config.recode.option.discordActivityTimeMeasurement.on_plot": "On current plot", @@ -281,25 +281,25 @@ "config.recode.option.chatside.either": "Remain", "config.recode.option.sidechat_width.tooltip": "The width to be used by the second chat.\nIf set to 0, the width will be calculated from the\nlower of main chat width & window space remaining.", - "config.recode.subcategory.sidedchat_custom_chat.tooltip": "Filter that matches text with a pattern defined by you.", - "config.recode.subcategory.sidedchat_messages.tooltip": "Filter that matches text that comes from the /msg command.", - "config.recode.subcategory.sidedchat_support_chat.tooltip": "Filter that matches text that comes from Support Chat.", - "config.recode.subcategory.sidedchat_session_chat.tooltip": "Filter that matches text that comes from Expert Session Spy.", - "config.recode.subcategory.sidedchat_mod_chat.tooltip": "Filter that matches text that comes from Mod Chat.", - "config.recode.subcategory.sidedchat_admin_chat.tooltip": "Filter that matches text that comes from Admin Chat.", - "config.recode.option.custom_chat.side.tooltip": "Side for chat matching the Custom Chat filter.", - "config.recode.option.custom_filter.tooltip": "Messages containing these phrases are filtered\ninto the 'Custom' Chat Side.\nSeperate phrases with commas.", - "config.recode.option.messages.side.tooltip": "Side for chat matching the /msg filter.", - "config.recode.option.support_chat.side.tooltip": "Side for chat matching the Support Chat filter.", - "config.recode.option.session_chat.side.tooltip": "Side for chat matching the Session Spy filter.", - "config.recode.option.mod_chat.side.tooltip": "Side for chat matching the Mod Chat filter.", - "config.recode.option.admin_chat.side.tooltip": "Side for chat matching the Admin Chat filter.", - "config.recode.option.custom_chat.sound.tooltip": "Sound for chat matching the Custom Chat filter.", - "config.recode.option.messages.sound.tooltip": "Sound for chat matching the /msg filter.", - "config.recode.option.support_chat.sound.tooltip": "Sound for chat matching the Support Chat filter.", - "config.recode.option.session_chat.sound.tooltip": "Sound for chat matching the Session Spy filter.", - "config.recode.option.mod_chat.sound.tooltip": "Sound for chat matching the Mod Chat filter.", - "config.recode.option.admin_chat.sound.tooltip": "Sound for chat matching the Admin Chat filter.", + "config.recode.subcategory.sidedchat_custom_chat.tooltip": "Filter that matches text with a pattern defined by you", + "config.recode.subcategory.sidedchat_messages.tooltip": "Filter that matches text that comes from the /msg command", + "config.recode.subcategory.sidedchat_support_chat.tooltip": "Filter that matches text that comes from Support Chat", + "config.recode.subcategory.sidedchat_session_chat.tooltip": "Filter that matches text that comes from Expert Session Spy", + "config.recode.subcategory.sidedchat_mod_chat.tooltip": "Filter that matches text that comes from Mod Chat", + "config.recode.subcategory.sidedchat_admin_chat.tooltip": "Filter that matches text that comes from Admin Chat", + "config.recode.option.custom_chat.side.tooltip": "Side for chat matching the Custom Chat filter", + "config.recode.option.custom_filter.tooltip": "Messages containing these phrases are filtered\ninto the 'Custom' Chat Side.\nSeperate phrases with commas", + "config.recode.option.messages.side.tooltip": "Side for chat matching the /msg filter", + "config.recode.option.support_chat.side.tooltip": "Side for chat matching the Support Chat filter", + "config.recode.option.session_chat.side.tooltip": "Side for chat matching the Session Spy filter", + "config.recode.option.mod_chat.side.tooltip": "Side for chat matching the Mod Chat filter", + "config.recode.option.admin_chat.side.tooltip": "Side for chat matching the Admin Chat filter", + "config.recode.option.custom_chat.sound.tooltip": "Sound for chat matching the Custom Chat filter", + "config.recode.option.messages.sound.tooltip": "Sound for chat matching the /msg filter", + "config.recode.option.support_chat.sound.tooltip": "Sound for chat matching the Support Chat filter", + "config.recode.option.session_chat.sound.tooltip": "Sound for chat matching the Session Spy filter", + "config.recode.option.mod_chat.sound.tooltip": "Sound for chat matching the Mod Chat filter", + "config.recode.option.admin_chat.sound.tooltip": "Sound for chat matching the Admin Chat filter", "key.category.recode": "Recode", From 471cd9443ac041162de10d28a4fa4174a1dd9c66 Mon Sep 17 00:00:00 2001 From: pomchom Date: Thu, 21 Dec 2023 00:26:10 -0500 Subject: [PATCH 13/53] order of operations my beloved --- .../homchom/recode/feature/visual/ExpressionHighlighting.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/io/github/homchom/recode/feature/visual/ExpressionHighlighting.kt b/src/main/java/io/github/homchom/recode/feature/visual/ExpressionHighlighting.kt index 1d6f3faaa..f8d9f5a4f 100644 --- a/src/main/java/io/github/homchom/recode/feature/visual/ExpressionHighlighting.kt +++ b/src/main/java/io/github/homchom/recode/feature/visual/ExpressionHighlighting.kt @@ -125,6 +125,6 @@ class ExpressionHighlighter { private fun styleAt(depth: Int) = if (depth == 0) { style() } else { - style().color(colors[depth - 1 % colors.size]) + style().color(colors[(depth - 1) % colors.size]) } } \ No newline at end of file From 181a7a1bd40296d349cbe0fd6afc9b80590310fc Mon Sep 17 00:00:00 2001 From: pomchom Date: Thu, 21 Dec 2023 15:52:31 -0500 Subject: [PATCH 14/53] migrate /colors copy to minimessage --- .../homchom/recode/mod/config/structure/ConfigManager.java | 1 - .../homchom/recode/mod/features/commands/ColorsMenu.java | 6 ++---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/main/java/io/github/homchom/recode/mod/config/structure/ConfigManager.java b/src/main/java/io/github/homchom/recode/mod/config/structure/ConfigManager.java index 96713a3bf..2279685d4 100644 --- a/src/main/java/io/github/homchom/recode/mod/config/structure/ConfigManager.java +++ b/src/main/java/io/github/homchom/recode/mod/config/structure/ConfigManager.java @@ -21,7 +21,6 @@ private ConfigManager() {} @Override public void initialize() { // Initial settings and creation of memory placements - // NOTICE: Hi hacker! If you are willing to add your name below, please refrain from doing so as it is against the DiamondFire rules. this.register(new StreamerModeGroup("streamer")); this.register(new AutomationGroup("automation")); this.register(new CommandsGroup("commands")); diff --git a/src/main/java/io/github/homchom/recode/mod/features/commands/ColorsMenu.java b/src/main/java/io/github/homchom/recode/mod/features/commands/ColorsMenu.java index d30bf1151..de1b8fa8a 100644 --- a/src/main/java/io/github/homchom/recode/mod/features/commands/ColorsMenu.java +++ b/src/main/java/io/github/homchom/recode/mod/features/commands/ColorsMenu.java @@ -8,7 +8,6 @@ import io.github.cottonmc.cotton.gui.widget.WTextField; import io.github.homchom.recode.sys.player.chat.color.ColorUtil; import io.github.homchom.recode.sys.player.chat.color.HSBColor; -import io.github.homchom.recode.sys.player.chat.color.MinecraftColors; import io.github.homchom.recode.sys.renderer.IMenu; import io.github.homchom.recode.sys.renderer.widgets.CColorPicker; import io.github.homchom.recode.sys.renderer.widgets.CColorPreset; @@ -48,9 +47,8 @@ public void open(String... args) { copyButton = new WButton(Component.literal("Copy")).setOnClick(() -> { Color color = colorPicker.getColor(); - var formatted = String.format("#%02x%02x%02x", color.getRed(), color.getGreen(), color.getBlue()); - var copy = MinecraftColors.hexToMc(formatted).replaceAll("§", "&"); - Minecraft.getInstance().keyboardHandler.setClipboard(copy); + var formatted = String.format("<#%02x%02x%02x>", color.getRed(), color.getGreen(), color.getBlue()); + Minecraft.getInstance().keyboardHandler.setClipboard(formatted); ColorUtil.recentColors.remove(color); ColorUtil.recentColors.add(0, color); From 1f37f2fe0c94bf38be7d337d71b3cff081f22b8f Mon Sep 17 00:00:00 2001 From: pomchom Date: Thu, 21 Dec 2023 23:46:20 -0500 Subject: [PATCH 15/53] fix title screen Resource Packs crash --- src/main/java/io/github/homchom/recode/Main.java | 2 +- .../feature/visual/BuiltInResourcePacks.kt | 16 +++++++++------- .../feature/visual/ExpressionHighlighting.kt | 1 + .../recode/ui/text/MiniMessageHighlighter.kt | 3 +-- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/main/java/io/github/homchom/recode/Main.java b/src/main/java/io/github/homchom/recode/Main.java index 2b002c0bb..c2f848085 100644 --- a/src/main/java/io/github/homchom/recode/Main.java +++ b/src/main/java/io/github/homchom/recode/Main.java @@ -5,7 +5,7 @@ import net.fabricmc.loader.api.entrypoint.PreLaunchEntrypoint; // keep this file as a .java file! -public class Main implements ClientModInitializer, PreLaunchEntrypoint { +public final class Main implements ClientModInitializer, PreLaunchEntrypoint { @Override public void onInitializeClient() { Recode.INSTANCE.initialize(); diff --git a/src/main/java/io/github/homchom/recode/feature/visual/BuiltInResourcePacks.kt b/src/main/java/io/github/homchom/recode/feature/visual/BuiltInResourcePacks.kt index 3919eec10..e05054742 100644 --- a/src/main/java/io/github/homchom/recode/feature/visual/BuiltInResourcePacks.kt +++ b/src/main/java/io/github/homchom/recode/feature/visual/BuiltInResourcePacks.kt @@ -6,11 +6,10 @@ import io.github.homchom.recode.feature.feature import io.github.homchom.recode.id import io.github.homchom.recode.render.IntegralColor import io.github.homchom.recode.render.toColor -import io.github.homchom.recode.ui.text.style -import io.github.homchom.recode.ui.text.text -import io.github.homchom.recode.ui.text.toVanilla +import io.github.homchom.recode.ui.text.VanillaComponent import net.fabricmc.fabric.api.resource.ResourceManagerHelper import net.fabricmc.fabric.api.resource.ResourcePackActivationType +import net.minecraft.network.chat.Style val FBuiltInResourcePacks = feature("Built-in Resource Packs") { registerBuiltInResourcePack("better_unicode", 0x6770ff.toColor()) @@ -21,13 +20,16 @@ private fun registerBuiltInResourcePack( displayColor: IntegralColor, activationType: ResourcePackActivationType = ResourcePackActivationType.DEFAULT_ENABLED ) { + // https://github.com/KyoriPowered/adventure-platform-fabric/issues/122 + val packDescription = VanillaComponent.literal("[$MOD_ID] ") + .append(VanillaComponent.translatable("resourcePack.recode.$id") + .withStyle(Style.EMPTY.withColor(displayColor.toInt())) + ) + ResourceManagerHelper.registerBuiltinResourcePack( id(id), Recode, - text { - literal("[$MOD_ID] ") - translate("resourcePack.recode.$id", style().color(displayColor)) - }.toVanilla(), + packDescription, activationType ) } \ No newline at end of file diff --git a/src/main/java/io/github/homchom/recode/feature/visual/ExpressionHighlighting.kt b/src/main/java/io/github/homchom/recode/feature/visual/ExpressionHighlighting.kt index f8d9f5a4f..4137401a7 100644 --- a/src/main/java/io/github/homchom/recode/feature/visual/ExpressionHighlighting.kt +++ b/src/main/java/io/github/homchom/recode/feature/visual/ExpressionHighlighting.kt @@ -116,6 +116,7 @@ class ExpressionHighlighter { try { miniMessage.deserialize(string).toFormattedCharSequence() } catch (e: Exception) { + // https://github.com/KyoriPowered/adventure/issues/1011 null } } else null diff --git a/src/main/java/io/github/homchom/recode/ui/text/MiniMessageHighlighter.kt b/src/main/java/io/github/homchom/recode/ui/text/MiniMessageHighlighter.kt index 9c616decd..489a69e6b 100644 --- a/src/main/java/io/github/homchom/recode/ui/text/MiniMessageHighlighter.kt +++ b/src/main/java/io/github/homchom/recode/ui/text/MiniMessageHighlighter.kt @@ -114,8 +114,7 @@ class MiniMessageHighlighter(private val standardTags: TagResolver) { val root = try { instance.deserializeToTree(input) } catch (e: Exception) { - // highlight red for exceptional parses, such as unclosed double quotes - // TODO: something better after ui update? + // https://github.com/KyoriPowered/adventure/issues/1011 return literalText(input, style().red()) } buildNewInput(root) From 9745a8697e3a8b66c77dc743fdeacb51eef9da8f Mon Sep 17 00:00:00 2001 From: pomchom Date: Mon, 25 Dec 2023 17:06:21 -0500 Subject: [PATCH 16/53] mixin cleanup, improve message stacking performance --- .../recode/feature/social/MessageStacking.kt | 37 +++----- .../feature/visual/BuiltInResourcePacks.kt | 4 +- .../optional/sodium/MSodiumWorldRenderer.java | 4 +- .../recode/mixin/render/MLevelRenderer.java | 12 +-- .../mixin/render/chat/MChatComponent.java | 91 ++++++++++--------- .../render/chat/MCommandSuggestions.java | 19 ++-- 6 files changed, 80 insertions(+), 87 deletions(-) diff --git a/src/main/java/io/github/homchom/recode/feature/social/MessageStacking.kt b/src/main/java/io/github/homchom/recode/feature/social/MessageStacking.kt index b353d2c02..7ca5c115d 100644 --- a/src/main/java/io/github/homchom/recode/feature/social/MessageStacking.kt +++ b/src/main/java/io/github/homchom/recode/feature/social/MessageStacking.kt @@ -8,30 +8,19 @@ import io.github.homchom.recode.ui.text.literalText import io.github.homchom.recode.ui.text.style import io.github.homchom.recode.ui.text.toVanilla import io.github.homchom.recode.ui.text.translatedText -import io.github.homchom.recode.util.regex.regex import net.minecraft.client.GuiMessageTag -private val stackTagPrefix get() = "$MOD_NAME stacked x" +object MessageStacks { + private const val STACK_TAG_PREFIX = "$MOD_NAME stacked x" -private val stackRegex = regex { - str(stackTagPrefix) - val amount by digit.oneOrMore() -} - -fun stackedMessageTag(amount: Int) = GuiMessageTag( - ColorPalette.AQUA.hex, - GuiMessageTag.Icon.CHAT_MODIFIED, - translatedText( - "chat.tag.recode.stacked", - style().aqua(), - arrayOf(literalText(amount)) - ).toVanilla(), - "$stackTagPrefix$amount" -) - -val GuiMessageTag.stackAmount: Int - get() { - val description = logTag ?: return 1 - val match = stackRegex.find(description) ?: return 1 - return match.groupValues[1].toInt() - } \ No newline at end of file + fun tag(amount: Int) = GuiMessageTag( + ColorPalette.AQUA.hex, + GuiMessageTag.Icon.CHAT_MODIFIED, + translatedText( + "chat.tag.recode.stacked", + style().aqua(), + arrayOf(literalText(amount)) + ).toVanilla(), + "$STACK_TAG_PREFIX$amount" + ) +} \ No newline at end of file diff --git a/src/main/java/io/github/homchom/recode/feature/visual/BuiltInResourcePacks.kt b/src/main/java/io/github/homchom/recode/feature/visual/BuiltInResourcePacks.kt index e05054742..020eb9d0a 100644 --- a/src/main/java/io/github/homchom/recode/feature/visual/BuiltInResourcePacks.kt +++ b/src/main/java/io/github/homchom/recode/feature/visual/BuiltInResourcePacks.kt @@ -7,9 +7,9 @@ import io.github.homchom.recode.id import io.github.homchom.recode.render.IntegralColor import io.github.homchom.recode.render.toColor import io.github.homchom.recode.ui.text.VanillaComponent +import io.github.homchom.recode.ui.text.VanillaStyle import net.fabricmc.fabric.api.resource.ResourceManagerHelper import net.fabricmc.fabric.api.resource.ResourcePackActivationType -import net.minecraft.network.chat.Style val FBuiltInResourcePacks = feature("Built-in Resource Packs") { registerBuiltInResourcePack("better_unicode", 0x6770ff.toColor()) @@ -23,7 +23,7 @@ private fun registerBuiltInResourcePack( // https://github.com/KyoriPowered/adventure-platform-fabric/issues/122 val packDescription = VanillaComponent.literal("[$MOD_ID] ") .append(VanillaComponent.translatable("resourcePack.recode.$id") - .withStyle(Style.EMPTY.withColor(displayColor.toInt())) + .withStyle(VanillaStyle.EMPTY.withColor(displayColor.toInt())) ) ResourceManagerHelper.registerBuiltinResourcePack( diff --git a/src/main/java/io/github/homchom/recode/mixin/optional/sodium/MSodiumWorldRenderer.java b/src/main/java/io/github/homchom/recode/mixin/optional/sodium/MSodiumWorldRenderer.java index d6d78e715..7d420e4e5 100644 --- a/src/main/java/io/github/homchom/recode/mixin/optional/sodium/MSodiumWorldRenderer.java +++ b/src/main/java/io/github/homchom/recode/mixin/optional/sodium/MSodiumWorldRenderer.java @@ -7,7 +7,6 @@ import me.jellysquid.mods.sodium.client.render.SodiumWorldRenderer; import me.jellysquid.mods.sodium.client.render.chunk.RenderSection; import net.minecraft.client.Minecraft; -import net.minecraft.core.SectionPos; import net.minecraft.world.level.block.entity.BlockEntity; import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; @@ -33,9 +32,8 @@ public abstract class MSodiumWorldRenderer { if (blockEntities == null || blockEntities.length == 0) return blockEntities; var blockEntityList = List.of(blockEntities); - var chunkPos = SectionPos.of(blockEntityList.get(0).getBlockPos()); var levelRenderer = (DRecodeLevelRenderer) Minecraft.getInstance().levelRenderer; - return levelRenderer.recode$runBlockEntityEvents(blockEntityList, chunkPos) + return levelRenderer.recode$runBlockEntityEvents(blockEntityList, section.getPosition()) .toArray(new BlockEntity[0]); } diff --git a/src/main/java/io/github/homchom/recode/mixin/render/MLevelRenderer.java b/src/main/java/io/github/homchom/recode/mixin/render/MLevelRenderer.java index 5dc026de6..cd22de9eb 100644 --- a/src/main/java/io/github/homchom/recode/mixin/render/MLevelRenderer.java +++ b/src/main/java/io/github/homchom/recode/mixin/render/MLevelRenderer.java @@ -1,16 +1,16 @@ package io.github.homchom.recode.mixin.render; +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import io.github.homchom.recode.event.SimpleValidated; import io.github.homchom.recode.render.BlockEntityOutlineContext; -import io.github.homchom.recode.render.RGBAColor; import io.github.homchom.recode.render.DRecodeLevelRenderer; +import io.github.homchom.recode.render.RGBAColor; import io.github.homchom.recode.render.RenderEvents; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.LevelRenderer; import net.minecraft.client.renderer.PostChain; -import net.minecraft.client.renderer.chunk.SectionRenderDispatcher; import net.minecraft.core.BlockPos; import net.minecraft.core.SectionPos; import net.minecraft.world.level.block.entity.BlockEntity; @@ -50,14 +50,10 @@ private Set interceptGlobalBlockEntities( return Set.copyOf(recode$runBlockEntityEvents(blockEntities, null)); } - @WrapOperation(method = "renderLevel", at = @At(value = "INVOKE", + @ModifyExpressionValue(method = "renderLevel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/chunk/SectionRenderDispatcher$CompiledSection;getRenderableBlockEntities()Ljava/util/List;" )) - private List interceptSectionBlockEntities( - SectionRenderDispatcher.CompiledSection section, - Operation> operation - ) { - var blockEntities = operation.call(section); + private List interceptSectionBlockEntities(List blockEntities) { if (blockEntities.isEmpty()) return blockEntities; var chunkPos = SectionPos.of(blockEntities.get(0).getBlockPos()); diff --git a/src/main/java/io/github/homchom/recode/mixin/render/chat/MChatComponent.java b/src/main/java/io/github/homchom/recode/mixin/render/chat/MChatComponent.java index 8eb84fc81..844feded8 100644 --- a/src/main/java/io/github/homchom/recode/mixin/render/chat/MChatComponent.java +++ b/src/main/java/io/github/homchom/recode/mixin/render/chat/MChatComponent.java @@ -1,9 +1,10 @@ package io.github.homchom.recode.mixin.render.chat; -import com.llamalad7.mixinextras.injector.wrapoperation.Operation; -import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.sugar.Share; +import com.llamalad7.mixinextras.sugar.ref.LocalBooleanRef; import io.github.homchom.recode.feature.social.DGuiWithSideChat; -import io.github.homchom.recode.feature.social.MessageStacking; +import io.github.homchom.recode.feature.social.MessageStacks; import io.github.homchom.recode.feature.social.SideChat; import io.github.homchom.recode.mod.config.Config; import io.github.homchom.recode.ui.ChatUI; @@ -12,9 +13,9 @@ import net.minecraft.client.GuiMessageTag; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.components.ChatComponent; -import net.minecraft.client.multiplayer.chat.ChatListener; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MessageSignature; +import net.minecraft.util.FormattedCharSequence; import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -25,8 +26,8 @@ import org.spongepowered.asm.mixin.injection.ModifyVariable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import java.util.Collections; import java.util.List; -import java.util.Objects; @Mixin(ChatComponent.class) public abstract class MChatComponent { @@ -44,11 +45,11 @@ private double overrideScreenToChatX(double screenX) { // side chat redirects // TODO: improve handling of chat queue (partition it?) - @WrapOperation(method = "render", at = @At(value = "INVOKE", + @ModifyExpressionValue(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/multiplayer/chat/ChatListener;queueSize()J" )) - private long wrapMessageQueueSize(ChatListener listener, Operation operation) { - return isSideChat() ? 0 : operation.call(listener); + private long wrapMessageQueueSize(long size) { + return isSideChat() ? 0 : size; } // actions synced between main chat and side chat @@ -97,53 +98,46 @@ private boolean isSideChat() { // message stacking @Unique - private int trimmedMessageCount = 0; + private int messageStackAmount = 1; - @Inject( + @ModifyExpressionValue( method = "addMessage(Lnet/minecraft/network/chat/Component;Lnet/minecraft/network/chat/MessageSignature;ILnet/minecraft/client/GuiMessageTag;Z)V", - at = @At("HEAD") + at = @At(value = "INVOKE", + target = "Lnet/minecraft/client/gui/components/ComponentRenderUtils;wrapComponents(Lnet/minecraft/network/chat/FormattedText;ILnet/minecraft/client/gui/Font;)Ljava/util/List;" + ) ) - private void countTrimmedMessagesBeforeMessageStacking(CallbackInfo ci) { - trimmedMessageCount = trimmedMessages.size(); - } - - @Inject( - method = "addMessage(Lnet/minecraft/network/chat/Component;Lnet/minecraft/network/chat/MessageSignature;ILnet/minecraft/client/GuiMessageTag;Z)V", - at = @At("TAIL") - ) - private void stackMessages( - Component message, + private List stackMessages( + List lineMessages, + Component fullMessage, MessageSignature signature, int tickDelta, GuiMessageTag tag, boolean refresh, - CallbackInfo ci + @Share("cancel") LocalBooleanRef cancel ) { - if (!Config.getBoolean("stackDuplicateMsgs")) return; - if (trimmedMessageCount == 0) return; + cancel.set(false); + if (!Config.getBoolean("stackDuplicateMsgs")) return lineMessages; // trimmedMessages[0] is the most recent message - var lineCount = trimmedMessages.size() - trimmedMessageCount; - if (trimmedMessageCount < lineCount) return; - if (trimmedMessageCount > lineCount) { - if (!trimmedMessages.get(lineCount * 2).endOfEntry()) return; + var lineCount = lineMessages.size(); + if (trimmedMessages.size() < lineCount) return lineMessages; + if (trimmedMessages.size() > lineCount) { + if (!trimmedMessages.get(lineCount).endOfEntry()) return lineMessages; } - // return if messages aren't equal - for (var index = lineCount; index < lineCount * 2; index++) { - var firstLine = trimmedMessages.get(index); - var secondLine = trimmedMessages.get(index - lineCount); - if (!TextFunctions.looksLike(firstLine.content(), secondLine.content())) return; - if (firstLine.endOfEntry() != secondLine.endOfEntry()) return; + // reset and return if messages aren't equal + for (var index = 0; index < lineCount; index++) { + var line1 = trimmedMessages.get(index); + var line2 = lineMessages.get(lineCount - 1 - index); + var endsEarly = index != 0 && line1.endOfEntry(); + if (!TextFunctions.looksLike(line1.content(), line2) || endsEarly) { + messageStackAmount = 1; + return lineMessages; + } } - // remove new message and update tags - var oldTag = Objects.requireNonNull(trimmedMessages.get(lineCount).tag()); - var stackAmount = MessageStacking.getStackAmount(oldTag) + 1; - - trimmedMessages.subList(0, lineCount).clear(); - - var newTag = ChatUI.plus(tag, MessageStacking.stackedMessageTag(stackAmount)); + // replace old message, with updated tags + var newTag = ChatUI.plus(tag, MessageStacks.INSTANCE.tag(++messageStackAmount)); for (var index = 0; index < lineCount; index++) { var oldLine = trimmedMessages.get(index); var newLine = new GuiMessage.Line( @@ -154,5 +148,20 @@ private void stackMessages( ); trimmedMessages.set(index, newLine); } + + // cancel in the next handler and return a dummy value + cancel.set(true); + return Collections.emptyList(); + } + + @Inject(method = "addMessage(Lnet/minecraft/network/chat/Component;Lnet/minecraft/network/chat/MessageSignature;ILnet/minecraft/client/GuiMessageTag;Z)V", + at = @At(value = "INVOKE", + target = "Lnet/minecraft/client/gui/components/ComponentRenderUtils;wrapComponents(Lnet/minecraft/network/chat/FormattedText;ILnet/minecraft/client/gui/Font;)Ljava/util/List;", + shift = At.Shift.AFTER + ), + cancellable = true + ) + private void cancelAfterMessageStacking(CallbackInfo ci, @Share("cancel") LocalBooleanRef cancel) { + if (cancel.get()) ci.cancel(); } } diff --git a/src/main/java/io/github/homchom/recode/mixin/render/chat/MCommandSuggestions.java b/src/main/java/io/github/homchom/recode/mixin/render/chat/MCommandSuggestions.java index dcf516d86..728eb8912 100644 --- a/src/main/java/io/github/homchom/recode/mixin/render/chat/MCommandSuggestions.java +++ b/src/main/java/io/github/homchom/recode/mixin/render/chat/MCommandSuggestions.java @@ -1,5 +1,6 @@ package io.github.homchom.recode.mixin.render.chat; +import com.llamalad7.mixinextras.injector.ModifyReturnValue; import io.github.homchom.recode.feature.visual.EditBoxExpressionFormatter; import io.github.homchom.recode.hypercube.DFValueMeta; import io.github.homchom.recode.hypercube.DFValues; @@ -20,7 +21,6 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import java.util.Objects; @@ -43,23 +43,24 @@ public abstract class MCommandSuggestions { @Shadow @Final EditBox input; // expression highlighting and preview - @Inject(method = "formatChat", at = @At("RETURN"), cancellable = true) - private void highlightAndPreview( + @ModifyReturnValue(method = "formatChat", at = @At("RETURN")) + private FormattedCharSequence highlightAndPreview( + FormattedCharSequence returnValue, String partialInput, - int position, - CallbackInfoReturnable cir + int position ) { - if (!Config.getBoolean("highlightVarSyntax")) return; - if (!DF.isInMode(DF.getCurrentDFState(), PlotMode.Dev.ID)) return; + if (!Config.getBoolean("highlightVarSyntax")) return returnValue; + if (!DF.isInMode(DF.getCurrentDFState(), PlotMode.Dev.ID)) return returnValue; var formatted = highlighter.format( input.getValue(), - cir.getReturnValue(), + returnValue, new IntRange(position, position + partialInput.length() - 1) ); if (formatted != null) { - cir.setReturnValue(formatted.getText()); preview = formatted.getPreview(); + return formatted.getText(); } + return returnValue; } @Inject(method = "render", at = @At("HEAD")) From 51fe9479f8168187bd7fe3d9e0913a8c286095da Mon Sep 17 00:00:00 2001 From: pomchom Date: Tue, 26 Dec 2023 23:54:24 -0500 Subject: [PATCH 17/53] lazy trials, detector logic change, improve chat performance --- .../java/io/github/homchom/recode/Logging.kt | 35 +++++++ .../java/io/github/homchom/recode/Recode.kt | 31 ------ .../github/homchom/recode/event/Validation.kt | 4 +- .../recode/event/trial/DetectorImpl.kt | 95 +++++++++--------- .../event/trial/ToggleRequesterGroup.kt | 2 +- .../homchom/recode/event/trial/Trial.kt | 13 +-- .../homchom/recode/event/trial/TrialScope.kt | 45 +++------ .../recode/hypercube/HypercubeEvents.kt | 6 +- .../recode/hypercube/SettingRequesters.kt | 16 +-- .../recode/hypercube/message/CodeMessages.kt | 13 +-- .../recode/hypercube/message/MessageParser.kt | 14 ++- .../homchom/recode/hypercube/state/DFState.kt | 15 +-- .../hypercube/state/DFStateDetectors.kt | 85 ++++++++-------- .../impl/LegacyReceiveChatMessageEvent.java | 4 +- .../recode/mod/features/LagslayerHUD.java | 4 +- .../social/chat/message/LegacyMessage.java | 8 +- ...essageType.java => LegacyMessageType.java} | 12 +-- .../social/chat/message/MessageCheck.java | 6 +- .../chat/message/checks/AdminCheck.java | 6 +- .../message/checks/BuycraftXUpdateCheck.java | 10 +- .../message/checks/DirectMessageCheck.java | 6 +- .../message/checks/IncomingReportCheck.java | 6 +- .../chat/message/checks/JoinFailCheck.java | 6 +- .../chat/message/checks/ModerationCheck.java | 7 +- .../chat/message/checks/PlotAdCheck.java | 12 ++- .../chat/message/checks/ScanningCheck.java | 12 ++- .../message/checks/SilentPunishmentCheck.java | 6 +- .../chat/message/checks/SpiesCheck.java | 6 +- .../checks/StreamerModeRegexCheck.java | 6 +- .../message/checks/SupportAnswerCheck.java | 12 ++- .../chat/message/checks/SupportCheck.java | 6 +- .../message/checks/SupportQuestionCheck.java | 12 ++- .../chat/message/checks/TeleportCheck.java | 12 ++- .../message/finalizers/DebugFinalizer.java | 4 +- .../finalizers/StreamerModeFinalizer.java | 4 +- .../mod/mixin/inventory/MHeldItemTooltip.java | 4 +- .../mod/mixin/message/MMessageListener.java | 63 ++---------- .../recode/multiplayer/MultiplayerEvents.kt | 26 +++-- .../homchom/recode/render/RenderEvents.kt | 2 +- .../recode/sys/player/chat/ChatUtil.java | 35 ------- .../sys/player/chat/MessageGrabber.java | 6 +- .../sys/player/chat/MessageGrabberTask.java | 6 +- .../homchom/recode/sys/util/StringUtil.java | 3 +- .../recode/ui/text/MiniMessageHighlighter.kt | 2 +- .../homchom/recode/ui/text/TextFunctions.kt | 8 +- .../homchom/recode/ui/text/TextInterop.kt | 56 ++++++++--- .../github/homchom/recode/util/Computation.kt | 22 +++++ .../homchom/recode/util/Computations.kt | 98 ------------------- .../homchom/recode/util/GenericWrappers.kt | 4 +- .../github/homchom/recode/util/PrevCached.kt | 43 -------- .../coroutines/CoroutineContextExtensions.kt | 14 --- .../CollectionsFunctions.kt} | 2 +- .../recode/util/lib/CoroutinesFunctions.kt | 15 +++ .../StdlibFunctions.kt} | 2 +- .../homchom/recode/util/regex/DynamicRegex.kt | 44 +++++++++ .../recode/util/regex/RegexFunctions.kt | 13 +-- .../recode/util/regex/RegexPatternBuilder.kt | 2 +- 57 files changed, 438 insertions(+), 573 deletions(-) create mode 100644 src/main/java/io/github/homchom/recode/Logging.kt rename src/main/java/io/github/homchom/recode/mod/features/social/chat/message/{MessageType.java => LegacyMessageType.java} (78%) create mode 100644 src/main/java/io/github/homchom/recode/util/Computation.kt delete mode 100644 src/main/java/io/github/homchom/recode/util/Computations.kt delete mode 100644 src/main/java/io/github/homchom/recode/util/PrevCached.kt delete mode 100644 src/main/java/io/github/homchom/recode/util/coroutines/CoroutineContextExtensions.kt rename src/main/java/io/github/homchom/recode/util/{collections/CollectionExtensions.kt => lib/CollectionsFunctions.kt} (82%) create mode 100644 src/main/java/io/github/homchom/recode/util/lib/CoroutinesFunctions.kt rename src/main/java/io/github/homchom/recode/util/{BasicTypeExtensions.kt => lib/StdlibFunctions.kt} (92%) create mode 100644 src/main/java/io/github/homchom/recode/util/regex/DynamicRegex.kt diff --git a/src/main/java/io/github/homchom/recode/Logging.kt b/src/main/java/io/github/homchom/recode/Logging.kt new file mode 100644 index 000000000..8567ba555 --- /dev/null +++ b/src/main/java/io/github/homchom/recode/Logging.kt @@ -0,0 +1,35 @@ +@file:JvmName("Logging") + +package io.github.homchom.recode + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.cancel +import org.slf4j.LoggerFactory +import org.slf4j.event.Level + +private val logger = LoggerFactory.getLogger(MOD_ID).apply { isEnabledForLevel(Level.DEBUG) } + +fun logInfo(message: String) = logger.info("[$MOD_NAME] $message") + +@JvmOverloads +fun logError(message: String, mentionBugReport: Boolean = false) { + val bugString = if (mentionBugReport) { + "\nIf you believe this is a bug, you can report it here: https://github.com/homchom/recode/issues)" + } else "" + logger.error("[$MOD_NAME] $message$bugString") +} + +fun logDebug(message: String) = logDebug { message } + +inline fun logDebug(lazyMessage: () -> String) { + if (debug) logInfo("[debug] ${lazyMessage()}") +} + +/** + * @see cancel + * @see logDebug + */ +fun CoroutineScope.cancelAndLog(message: String) { + logDebug(message) + cancel(message) +} \ No newline at end of file diff --git a/src/main/java/io/github/homchom/recode/Recode.kt b/src/main/java/io/github/homchom/recode/Recode.kt index e56c22642..8626684ea 100644 --- a/src/main/java/io/github/homchom/recode/Recode.kt +++ b/src/main/java/io/github/homchom/recode/Recode.kt @@ -29,25 +29,14 @@ import net.fabricmc.loader.api.FabricLoader import net.fabricmc.loader.api.ModContainer import net.fabricmc.loader.api.metadata.ModMetadata import net.fabricmc.loader.api.metadata.ModOrigin -import org.slf4j.LoggerFactory -import org.slf4j.event.Level import java.nio.file.Path import java.util.* import java.util.concurrent.ExecutorService import java.util.concurrent.Executors -import kotlin.random.Random - -private val logger = LoggerFactory.getLogger(MOD_ID).apply { isEnabledForLevel(Level.DEBUG) } object Recode : ModContainer { val version: String get() = metadata.version.friendlyString - @Deprecated( - "Use kotlin.random.Random instead", - ReplaceWith("Random", "kotlin.random.Random") - ) - val random get() = Random - private val container by lazy { FabricLoader.getInstance().getModContainer(MOD_ID).get() } private var isInitialized = false @@ -148,24 +137,4 @@ object LegacyRecode { CommandHandler.load(dispatcher, registryAccess) } } - - @JvmStatic - fun info(message: String) = logInfo("[$MOD_NAME] $message") - - @JvmStatic - fun error(message: String) = logError("[$MOD_NAME] $message") -} - -fun logInfo(message: String) = logger.info("[$MOD_NAME] $message") - -@JvmOverloads -fun logError(message: String, mentionBugReport: Boolean = false) { - val bugString = if (mentionBugReport) { - "\nIf you believe this is a bug, you can report it here: https://github.com/homchom/recode/issues)" - } else "" - logger.error("[$MOD_NAME] $message$bugString") -} - -fun logDebug(message: String) { - if (debug) logger.info("[$MOD_NAME debug] $message") } \ No newline at end of file diff --git a/src/main/java/io/github/homchom/recode/event/Validation.kt b/src/main/java/io/github/homchom/recode/event/Validation.kt index a3cd81438..64f789603 100644 --- a/src/main/java/io/github/homchom/recode/event/Validation.kt +++ b/src/main/java/io/github/homchom/recode/event/Validation.kt @@ -42,6 +42,4 @@ data class SimpleValidated @JvmOverloads constructor( override var validity: MixedInt = MixedInt(1) ) : Validated, InvokableWrapper -fun Iterable>.mapValid() = mapNotNull { if (it.isValid) it.value else null } - -fun Array>.mapValid() = mapNotNull { if (it.isValid) it.value else null } \ No newline at end of file +fun Iterable>.mapValid() = mapNotNull { if (it.isValid) it.value else null } \ No newline at end of file diff --git a/src/main/java/io/github/homchom/recode/event/trial/DetectorImpl.kt b/src/main/java/io/github/homchom/recode/event/trial/DetectorImpl.kt index 34ff92da4..660702000 100644 --- a/src/main/java/io/github/homchom/recode/event/trial/DetectorImpl.kt +++ b/src/main/java/io/github/homchom/recode/event/trial/DetectorImpl.kt @@ -7,8 +7,7 @@ import io.github.homchom.recode.event.Requester import io.github.homchom.recode.event.createEvent import io.github.homchom.recode.ui.sendSystemToast import io.github.homchom.recode.ui.text.translatedText -import io.github.homchom.recode.util.computeNullable -import io.github.homchom.recode.util.coroutines.cancelAndLog +import io.github.homchom.recode.util.lib.lazyJob import kotlinx.coroutines.* import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.channels.SendChannel @@ -56,32 +55,9 @@ private open class TrialDetector( ) : Detector { private val event = createEvent { it } - @OptIn(DelicateCoroutinesApi::class, ExperimentalCoroutinesApi::class) private val power = Power( onEnable = { - for (trialIndex in trials.indices) trials[trialIndex].results.listenEach { supplier -> - val successContext = CompletableDeferred(coroutineContext.job) - if (entries.isEmpty()) { - considerEntry(trialIndex, null, supplier, successContext) - } - - val iterator = entries.iterator() - for (entry in iterator) { - if (entry.responses.isClosedForSend) { - iterator.remove() - continue - } - considerEntry(trialIndex, entry, supplier, successContext) - } - - successContext.invokeOnCompletion { exception -> - if (exception == null) { - val completed = successContext.getCompleted() - logDebug("${this@TrialDetector} succeeded; running with context $completed") - event.run(completed) - } - } - } + listenToTrials() } ) @@ -114,45 +90,64 @@ private open class TrialDetector( } } + // TODO: this is arguably ioc hell. someone with more experience in concurrency should review this + // TODO: add more comments @OptIn(DelicateCoroutinesApi::class) - fun considerEntry( + private fun Power.listenToTrials() { + for (trialIndex in trials.indices) trials[trialIndex].results.listenEach { supplier -> + if (entries.isEmpty()) { + considerEntry(trialIndex, null, supplier) + } + + val iterator = entries.iterator() + for (entry in iterator) { + if (entry.responses.isClosedForSend) { + iterator.remove() + continue + } + considerEntry(trialIndex, entry, supplier) + } + } + } + + @OptIn(DelicateCoroutinesApi::class) + private fun considerEntry( trialIndex: Int, entry: DetectEntry?, - supplier: Trial.ResultSupplier, - successContext: CompletableDeferred, + supplier: Trial.ResultSupplier ) { - val entryScope = CoroutineScope(power.coroutineContext + Job(successContext)) - val result = computeNullable { - val trialScope = TrialScope( - this@computeNullable, - entryScope, - entry?.hidden ?: false - ) - logDebug("trial $trialIndex started for ${debugString(entry?.input, entry?.hidden)}") - supplier.supplyIn(trialScope, entry?.input, entry?.isRequest ?: false) - } + val entryScope = CoroutineScope(power.coroutineContext + lazyJob()) - val entryJob = entryScope.launch { - if (result == null) { - entry?.responses?.trySend(null) - return@launch - } - - val awaited = result.await() - entry?.responses?.trySend(awaited) - awaited?.let(successContext::complete) + val result = try { + val trialScope = TrialScope(entryScope, entry?.hidden ?: false) + logDebug { "trial $trialIndex started for ${debugString(entry?.input, entry?.hidden)}" } + supplier.supplyIn(trialScope, entry?.input, entry?.isRequest ?: false) + } catch (e: TrialScopeException) { + null } - entryJob.invokeOnCompletion { exception -> + if (result == null) { + entry?.responses?.trySend(null) + } else result.invokeOnCompletion { exception -> val state = when (exception) { is CancellationException -> "cancelled" - null -> "ended" + null -> "ended".also { succeed(result, entry) } else -> "ended with exception $exception" } entryScope.cancelAndLog("trial $trialIndex $state for ${debugString(entry?.input, entry?.hidden)}") } } + @OptIn(ExperimentalCoroutinesApi::class) + private fun succeed(result: TrialResult, entry: DetectEntry?) { + val awaited = result.getCompleted() + entry?.responses?.trySend(awaited) + if (awaited != null) { + logDebug("$this succeeded; running with context $awaited") + event.run(awaited) + } + } + override fun use(source: Power) = power.use(source) override fun toString() = "$name detector" diff --git a/src/main/java/io/github/homchom/recode/event/trial/ToggleRequesterGroup.kt b/src/main/java/io/github/homchom/recode/event/trial/ToggleRequesterGroup.kt index 8900057f8..93ad11433 100644 --- a/src/main/java/io/github/homchom/recode/event/trial/ToggleRequesterGroup.kt +++ b/src/main/java/io/github/homchom/recode/event/trial/ToggleRequesterGroup.kt @@ -3,7 +3,7 @@ package io.github.homchom.recode.event.trial import io.github.homchom.recode.Power import io.github.homchom.recode.event.Listenable import io.github.homchom.recode.event.Requester -import io.github.homchom.recode.util.unitOrNull +import io.github.homchom.recode.util.lib.unitOrNull import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch diff --git a/src/main/java/io/github/homchom/recode/event/trial/Trial.kt b/src/main/java/io/github/homchom/recode/event/trial/Trial.kt index 8965ebefc..2a892b080 100644 --- a/src/main/java/io/github/homchom/recode/event/trial/Trial.kt +++ b/src/main/java/io/github/homchom/recode/event/trial/Trial.kt @@ -3,7 +3,6 @@ package io.github.homchom.recode.event.trial import io.github.homchom.recode.event.Listenable import io.github.homchom.recode.event.Validated import io.github.homchom.recode.event.map -import io.github.homchom.recode.util.computeNullable import kotlinx.coroutines.* /** @@ -141,16 +140,14 @@ class TrialResult private constructor(private val deferred: Deferred