Skip to content

Commit 4991ce9

Browse files
authored
feat: Show modflared indicator in server list (#96)
* feat: Show modflared indicator in server list Add a client mixin for multiplayer server-list entries so servers routed through modflared display the existing indicator icon. Position the indicator away from the Forge modded-server compatibility badge and use direct visible strings for the hover and connection status text to avoid untranslated lang keys appearing in-game. Register the new mixin and keep the language entry for the server-list tooltip resource. * fix: Reset GL color before drawing indicator Reset the render color to white before binding and drawing the modflared server-list indicator. This prevents the indicator texture from inheriting tint from previous server-list rendering state or other modded indicators. * fix: Use localized tunnel text with fallbacks Restore localization lookups for the server-list tooltip and connection feedback while preserving English fallbacks when the legacy client returns unresolved translation keys. This addresses the review feedback without reintroducing the in-game issue where raw translation keys appeared in the UI. * chore: Remove legacy label from Forge version Update the Forge 1.12.2 artifact version from 1.12.2-legacy.1 to 1.12.2-1 now that the branch is tested and feature complete. This changes the generated jar names to drop the legacy qualifier while preserving the mod id and build configuration.
1 parent a66219b commit 4991ce9

5 files changed

Lines changed: 104 additions & 6 deletions

File tree

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ mcp_mappings=stable_39
88
mod_id=modflared
99
mod_name=Modflared
1010
mod_license=MIT
11-
mod_version=1.12.2-legacy.1
11+
mod_version=1.12.2-1
1212
mod_group_id=dev.httxrafa.modflared
1313
mod_authors=HttpRafa, Contributors
1414
mod_description=Automatically connects you to a Cloudflare tunnel without having to install cloudflared separately.
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package dev.httxrafa.modflared.mixin.client;
2+
3+
import dev.httxrafa.modflared.Modflared;
4+
import dev.httxrafa.modflared.interfaces.mixin.IServerData;
5+
import dev.httxrafa.modflared.tunnel.TunnelStatus;
6+
import net.minecraft.client.Minecraft;
7+
import net.minecraft.client.gui.Gui;
8+
import net.minecraft.client.gui.GuiMultiplayer;
9+
import net.minecraft.client.gui.ServerListEntryNormal;
10+
import net.minecraft.client.multiplayer.ServerData;
11+
import net.minecraft.client.renderer.GlStateManager;
12+
import net.minecraft.client.resources.I18n;
13+
import net.minecraft.util.ResourceLocation;
14+
import org.spongepowered.asm.mixin.Final;
15+
import org.spongepowered.asm.mixin.Mixin;
16+
import org.spongepowered.asm.mixin.Shadow;
17+
import org.spongepowered.asm.mixin.Unique;
18+
import org.spongepowered.asm.mixin.injection.At;
19+
import org.spongepowered.asm.mixin.injection.Inject;
20+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
21+
22+
@Mixin(ServerListEntryNormal.class)
23+
public abstract class ServerListEntryNormalMixin {
24+
25+
@Shadow
26+
@Final
27+
private GuiMultiplayer owner;
28+
29+
@Shadow
30+
@Final
31+
private ServerData server;
32+
33+
@Unique
34+
private static final ResourceLocation MODFLARED_INDICATOR_TEXTURE = new ResourceLocation(
35+
Modflared.MOD_ID,
36+
"textures/gui/sprites/icon/indicator.png"
37+
);
38+
39+
@Unique
40+
private static final int MODFLARED_INDICATOR_SIZE = 10;
41+
42+
@Unique
43+
private static final int MODFLARED_INDICATOR_RIGHT_OFFSET = 28;
44+
45+
@Unique
46+
private static final String MODFLARED_INDICATOR_TOOLTIP_KEY = "gui.multiplayer.tunnel.status.0";
47+
48+
@Unique
49+
private static final String MODFLARED_INDICATOR_TOOLTIP_FALLBACK = "Modflared in use";
50+
51+
@Inject(method = "drawEntry", at = @At("TAIL"))
52+
private void modflared$drawTunnelIndicator(int slotIndex, int x, int y, int listWidth, int slotHeight, int mouseX, int mouseY, boolean isSelected, float partialTicks, CallbackInfo callbackInfo) {
53+
TunnelStatus tunnelStatus = ((IServerData) this.server).getTunnelStatus();
54+
if (tunnelStatus == null || tunnelStatus.getState() != TunnelStatus.State.USE) {
55+
return;
56+
}
57+
58+
int indicatorX = x + listWidth - MODFLARED_INDICATOR_RIGHT_OFFSET;
59+
int indicatorY = y + 11;
60+
61+
GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
62+
Minecraft.getMinecraft().getTextureManager().bindTexture(MODFLARED_INDICATOR_TEXTURE);
63+
Gui.drawModalRectWithCustomSizedTexture(
64+
indicatorX,
65+
indicatorY,
66+
0.0F,
67+
0.0F,
68+
MODFLARED_INDICATOR_SIZE,
69+
MODFLARED_INDICATOR_SIZE,
70+
MODFLARED_INDICATOR_SIZE,
71+
MODFLARED_INDICATOR_SIZE
72+
);
73+
74+
if (mouseX >= indicatorX && mouseX <= indicatorX + MODFLARED_INDICATOR_SIZE && mouseY >= indicatorY && mouseY <= indicatorY + MODFLARED_INDICATOR_SIZE) {
75+
this.owner.setHoveringText(modflared$translate(MODFLARED_INDICATOR_TOOLTIP_KEY, MODFLARED_INDICATOR_TOOLTIP_FALLBACK));
76+
}
77+
}
78+
79+
@Unique
80+
private static String modflared$translate(String key, String fallback) {
81+
String translated = I18n.format(key);
82+
if (translated == null || translated.equals(key)) {
83+
return fallback;
84+
}
85+
return translated;
86+
}
87+
}

src/main/java/dev/httxrafa/modflared/tunnel/TunnelStatus.java

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
package dev.httxrafa.modflared.tunnel;
22

3+
import net.minecraft.util.text.ITextComponent;
4+
import net.minecraft.util.text.TextComponentString;
35
import net.minecraft.util.text.TextComponentTranslation;
46
import net.minecraft.util.text.TextFormatting;
5-
import net.minecraft.util.text.ITextComponent;
67

78
import java.util.ArrayList;
89
import java.util.Collections;
@@ -29,15 +30,23 @@ public State getState() {
2930
public List<ITextComponent> generateFeedback() {
3031
List<ITextComponent> feedback = new ArrayList<ITextComponent>();
3132
if (state == State.USE) {
32-
feedback.add(new TextComponentTranslation("gui.tunnel.status.use").setStyle(new net.minecraft.util.text.Style().setColor(TextFormatting.AQUA)));
33+
feedback.add(translate("gui.tunnel.status.use", "Using Cloudflare tunnel", TextFormatting.AQUA));
3334
} else if (state == State.FAILED_TO_DETERMINE) {
34-
feedback.add(new TextComponentTranslation("gui.tunnel.status.failed.0").setStyle(new net.minecraft.util.text.Style().setColor(TextFormatting.RED)));
35-
feedback.add(new TextComponentTranslation("gui.tunnel.status.failed.1").setStyle(new net.minecraft.util.text.Style().setColor(TextFormatting.RED)));
36-
feedback.add(new TextComponentTranslation("gui.tunnel.status.failed.2").setStyle(new net.minecraft.util.text.Style().setColor(TextFormatting.RED)));
35+
feedback.add(translate("gui.tunnel.status.failed.0", "Modflared could not determine if a tunnel is required.", TextFormatting.RED));
36+
feedback.add(translate("gui.tunnel.status.failed.1", "The connection will continue without a tunnel.", TextFormatting.RED));
37+
feedback.add(translate("gui.tunnel.status.failed.2", "Add this server to forced_tunnels.json if it must use a tunnel.", TextFormatting.RED));
3738
}
3839
return Collections.unmodifiableList(feedback);
3940
}
4041

42+
private static ITextComponent translate(String key, String fallback, TextFormatting formatting) {
43+
ITextComponent component = new TextComponentTranslation(key);
44+
if (component.getUnformattedText().equals(key)) {
45+
component = new TextComponentString(fallback);
46+
}
47+
return component.setStyle(new net.minecraft.util.text.Style().setColor(formatting));
48+
}
49+
4150
public enum State {
4251
USE,
4352
DONT_USE,

src/main/resources/assets/modflared/lang/en_us.lang

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
gui.tunnel.status.use=Using Cloudflare tunnel
2+
gui.multiplayer.tunnel.status.0=Modflared in use
23
gui.tunnel.status.failed.0=Modflared could not determine if a tunnel is required.
34
gui.tunnel.status.failed.1=The connection will continue without a tunnel.
45
gui.tunnel.status.failed.2=Add this server to forced_tunnels.json if it must use a tunnel.

src/main/resources/modflared.mixins.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
"client.GuiConnectingMixin",
1010
"client.GuiConnectingThreadMixin",
1111
"client.ServerDataMixin",
12+
"client.ServerListEntryNormalMixin",
1213
"client.ServerPingerMixin"
1314
],
1415
"client": [],

0 commit comments

Comments
 (0)