aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/at/hannibal2
diff options
context:
space:
mode:
authorLinnea Gräf <nea@nea.moe>2024-06-16 14:48:12 +0200
committerGitHub <noreply@github.com>2024-06-16 14:48:12 +0200
commit37bb14382e8aac7798de1e567b8e9410727ef5fd (patch)
treea2751e981625c215e62e83fcb1d372948898519d /src/main/java/at/hannibal2
parent7da2cd817f8f876100be1211990a4e80a066ac42 (diff)
downloadskyhanni-37bb14382e8aac7798de1e567b8e9410727ef5fd.tar.gz
skyhanni-37bb14382e8aac7798de1e567b8e9410727ef5fd.tar.bz2
skyhanni-37bb14382e8aac7798de1e567b8e9410727ef5fd.zip
Backend: Add true color support to chat formatting codes (#1397)
Co-authored-by: Cal <cwolfson58@gmail.com>
Diffstat (limited to 'src/main/java/at/hannibal2')
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt5
-rw-r--r--src/main/java/at/hannibal2/skyhanni/mixins/transformers/ExtendedColorPatch.java129
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/ExtendedChatColor.kt34
3 files changed, 168 insertions, 0 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt b/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt
index a0a6e60d4..bd94462c4 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt
+++ b/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt
@@ -83,6 +83,7 @@ import at.hannibal2.skyhanni.test.command.TrackParticlesCommand
import at.hannibal2.skyhanni.test.command.TrackSoundsCommand
import at.hannibal2.skyhanni.utils.APIUtil
import at.hannibal2.skyhanni.utils.ChatUtils
+import at.hannibal2.skyhanni.utils.ExtendedChatColor
import at.hannibal2.skyhanni.utils.LorenzUtils
import at.hannibal2.skyhanni.utils.SoundUtils
import at.hannibal2.skyhanni.utils.TabListData
@@ -507,6 +508,10 @@ object Commands {
"Sends a custom chat message client side in the chat",
) { TestChatCommand.command(it) }
registerCommand(
+ "shtestrainbow",
+ "Sends a rainbow in chat"
+ ) { ExtendedChatColor.testCommand() }
+ registerCommand(
"shcopyinternalname",
"Copies the internal name of the item in hand to the clipboard.",
) { SkyHanniDebugsAndTests.copyItemInternalName() }
diff --git a/src/main/java/at/hannibal2/skyhanni/mixins/transformers/ExtendedColorPatch.java b/src/main/java/at/hannibal2/skyhanni/mixins/transformers/ExtendedColorPatch.java
new file mode 100644
index 000000000..eb975b251
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/mixins/transformers/ExtendedColorPatch.java
@@ -0,0 +1,129 @@
+package at.hannibal2.skyhanni.mixins.transformers;
+
+import net.minecraft.client.gui.FontRenderer;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Shadow;
+import org.spongepowered.asm.mixin.Unique;
+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 org.spongepowered.asm.mixin.injection.callback.LocalCapture;
+
+@Mixin(FontRenderer.class)
+public abstract class ExtendedColorPatch {
+
+ @Shadow
+ protected abstract void setColor(float r, float g, float b, float a2);
+
+ @Shadow
+ private int textColor;
+ @Shadow
+ private float alpha;
+ @Unique
+ private int skyhanni$colorSR;
+ @Unique
+ private int skyhanni$colorState;
+
+ @Inject(method = "renderStringAtPos", at = @At("HEAD"))
+ private void resetStateWhenRendering(String text, boolean shadow, CallbackInfo ci) {
+ skyhanni$colorSR = 0;
+ skyhanni$colorState = -1;
+ }
+
+ @Unique
+ private static boolean skyhanni$isSpecial = false;
+
+ @Inject(
+ method = "isFormatSpecial",
+ at = @At(value = "HEAD"),
+ cancellable = true
+ )
+ private static void protectFormatCodesSpecial(char formatChar, CallbackInfoReturnable<Boolean> cir) {
+ if (formatChar == '/') {
+ skyhanni$isSpecial = false;
+ cir.setReturnValue(true);
+ } else if (skyhanni$isSpecial) {
+ cir.setReturnValue(true);
+ }
+ }
+
+ @Inject(
+ method = "isFormatColor",
+ at = @At(value = "HEAD"),
+ cancellable = true
+ )
+ private static void protectFormatCodesSimple(char formatChar, CallbackInfoReturnable<Boolean> cir) {
+ if (formatChar == '#') {
+ skyhanni$isSpecial = true;
+ cir.setReturnValue(true);
+ } else if (skyhanni$isSpecial) {
+ cir.setReturnValue(false);
+ }
+ }
+
+ @Inject(
+ method = "getFormatFromString",
+ at = @At(value = "TAIL")
+ )
+ private static void resetState(String text, CallbackInfoReturnable<String> cir) {
+ skyhanni$isSpecial = false;
+ }
+
+ @Inject(
+ method = "getFormatFromString",
+ at = @At(value = "HEAD")
+ )
+ private static void resetStateAtHead(String text, CallbackInfoReturnable<String> cir) {
+ skyhanni$isSpecial = false;
+ }
+
+ @Inject(
+ method = "renderStringAtPos",
+ at = @At(
+ value = "INVOKE",
+ target = "Lnet/minecraft/client/gui/FontRenderer;setColor(FFFF)V",
+ ordinal = 0,
+ shift = At.Shift.AFTER
+ ),
+ locals = LocalCapture.CAPTURE_FAILHARD
+ )
+ private void onChooseColor(
+ String text,
+ boolean shadow,
+ CallbackInfo ci,
+ int i,
+ char c0,
+ int i1
+ ) {
+
+ char c = text.charAt(i + 1);
+ int hexCode = "0123456789abcdef".indexOf(c);
+ if (c == '#') {
+ if (skyhanni$colorState != -1) {
+ throw new IllegalStateException("Encountered §# while inside push sequence");
+ }
+ skyhanni$colorState = 0;
+ skyhanni$colorSR = 0;
+ } else if (c == '/') {
+ if (skyhanni$colorState != 8 && skyhanni$colorState != 6) {
+ throw new IllegalStateException("Encountered §/ without encountering enough pushes: " + skyhanni$colorState);
+ }
+ textColor = skyhanni$colorSR;
+ int shadowDivisor = shadow ? 4 : 1;
+ setColor(
+ (skyhanni$colorSR >> 16 & 0xFF) / 255.0f / shadowDivisor,
+ (skyhanni$colorSR >> 8 & 0xFF) / 255.0f / shadowDivisor,
+ (skyhanni$colorSR & 0xFF) / 255.0f / shadowDivisor,
+ (skyhanni$colorState == 8 ? (skyhanni$colorSR >> 24 & 0xFF) / 255.0f : this.alpha)
+ );
+ skyhanni$colorState = -1;
+ } else if (0 <= hexCode && skyhanni$colorState != -1) {
+ skyhanni$colorState++;
+ if (skyhanni$colorState > 8)
+ throw new IllegalStateException("Encountered too many pushes inside of §#§/ sequence");
+ skyhanni$colorSR = (skyhanni$colorSR << 4) | hexCode;
+ }
+ }
+
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/ExtendedChatColor.kt b/src/main/java/at/hannibal2/skyhanni/utils/ExtendedChatColor.kt
new file mode 100644
index 000000000..f4a64017d
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/utils/ExtendedChatColor.kt
@@ -0,0 +1,34 @@
+package at.hannibal2.skyhanni.utils
+
+import java.awt.Color
+
+class ExtendedChatColor(
+ val rgb: Int,
+ val hasAlpha: Boolean,
+) {
+ override fun toString(): String {
+ val stringBuilder = StringBuilder()
+ val hexCode = rgb.toUInt().toString(16)
+ .padStart(8, '0')
+ .drop(if (hasAlpha) 0 else 2)
+ stringBuilder.append("§#")
+ for (code in hexCode) {
+ stringBuilder.append('§').append(code)
+ }
+ stringBuilder.append("§/")
+ return stringBuilder.toString()
+ }
+
+ companion object {
+
+ fun testCommand() {
+ val string = StringBuilder()
+ for (i in (0 until 100)) {
+ val color = Color.HSBtoRGB(i / 100F, 1f, 1f)
+ val extendedChatColor = ExtendedChatColor(color, false)
+ string.append("$extendedChatColor§m ")
+ }
+ ChatUtils.chat(string.toString())
+ }
+ }
+}