Skip to content

Commit 68c8f30

Browse files
authored
Fix disconnect screen layout for long kick messages (#837)
1 parent 22cffb4 commit 68c8f30

3 files changed

Lines changed: 105 additions & 0 deletions

File tree

src/main/java/com/mitchej123/hodgepodge/config/FixesConfig.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ public class FixesConfig {
4040
@Config.DefaultBoolean(true)
4141
public static boolean fixCommandFormattingLoss;
4242

43+
@Config.Comment("Fix disconnect screen button overlapping long kick messages")
44+
@Config.DefaultBoolean(true)
45+
@Config.RequiresMcRestart
46+
public static boolean fixDisconnectScreenLayout;
47+
4348
@Config.Comment("Prevents crash if server sends container with wrong itemStack size")
4449
@Config.DefaultBoolean(true)
4550
public static boolean fixContainerPutStacksInSlots;

src/main/java/com/mitchej123/hodgepodge/mixins/Mixins.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -659,6 +659,10 @@ public enum Mixins implements IMixins {
659659
.addCommonMixins("minecraft.MixinCommandBase_JoinArgs")
660660
.setApplyIf(() -> FixesConfig.fixCommandFormattingLoss)
661661
.setPhase(Phase.EARLY)),
662+
FIX_DISCONNECT_SCREEN_LAYOUT(new MixinBuilder("Fix disconnect screen button overlapping long kick messages")
663+
.addClientMixins("minecraft.MixinGuiDisconnected_FixLayout")
664+
.setApplyIf(() -> FixesConfig.fixDisconnectScreenLayout)
665+
.setPhase(Phase.EARLY)),
662666
COMPACT_CHAT(new MixinBuilder()
663667
.addClientMixins("minecraft.MixinGuiNewChat_CompactChat")
664668
.setApplyIf(() -> TweaksConfig.compactChat)
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package com.mitchej123.hodgepodge.mixins.early.minecraft;
2+
3+
import java.util.Iterator;
4+
import java.util.List;
5+
6+
import net.minecraft.client.gui.GuiButton;
7+
import net.minecraft.client.gui.GuiDisconnected;
8+
import net.minecraft.client.gui.GuiScreen;
9+
10+
import org.spongepowered.asm.mixin.Mixin;
11+
import org.spongepowered.asm.mixin.Shadow;
12+
import org.spongepowered.asm.mixin.Unique;
13+
import org.spongepowered.asm.mixin.injection.At;
14+
import org.spongepowered.asm.mixin.injection.Inject;
15+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
16+
17+
/**
18+
* Vertically centers the disconnect screen as a group so the button doesn't overlap long kick messages.
19+
*
20+
* <pre>
21+
* Layout (top to bottom, group centered on the screen):
22+
* Title (FONT_HEIGHT = 9px)
23+
* 20px gap (padding: 10 below title + 10 above text)
24+
* Wrapped reason text (n * FONT_HEIGHT)
25+
* 12px gap (padding: 10 below text + 2 above button)
26+
* Button (20px tall)
27+
* </pre>
28+
*/
29+
@Mixin(GuiDisconnected.class)
30+
public class MixinGuiDisconnected_FixLayout extends GuiScreen {
31+
32+
@Shadow
33+
private String field_146306_a; // title string
34+
35+
@Shadow
36+
private List field_146305_g; // wrapped text lines
37+
38+
@Unique
39+
private int hodgepodge$titleY;
40+
41+
@Unique
42+
private int hodgepodge$textStartY;
43+
44+
@Inject(method = "initGui", at = @At("TAIL"))
45+
private void hodgepodge$centerLayout(CallbackInfo ci) {
46+
int lineHeight = this.fontRendererObj.FONT_HEIGHT;
47+
int textLines = field_146305_g != null ? field_146305_g.size() : 0;
48+
49+
// Inter-element gap = bottom padding of previous + top padding of next.
50+
// title→text = 10+10 = 20, text→button = 10+2 = 12.
51+
int totalHeight = lineHeight + 20 + (textLines * lineHeight) + 12 + 20;
52+
53+
int topY = Math.max(5, (this.height - totalHeight) / 2);
54+
55+
hodgepodge$titleY = topY;
56+
hodgepodge$textStartY = topY + lineHeight + 20;
57+
int buttonY = hodgepodge$textStartY + (textLines * lineHeight) + 12;
58+
59+
// Clamp so button stays on screen (button is 20px tall)
60+
if (buttonY + 20 > this.height - 5) {
61+
buttonY = this.height - 25;
62+
}
63+
64+
for (Object obj : this.buttonList) {
65+
GuiButton button = (GuiButton) obj;
66+
if (button.id == 0) {
67+
button.yPosition = buttonY;
68+
break;
69+
}
70+
}
71+
}
72+
73+
/**
74+
* Vanilla hardcodes title at height/2-50 and text at height/2-30. We cancel and redraw at the centered positions,
75+
* then let super render the buttons from buttonList.
76+
*/
77+
@Inject(method = "drawScreen", at = @At("HEAD"), cancellable = true)
78+
private void hodgepodge$drawScreen(int mouseX, int mouseY, float partialTicks, CallbackInfo ci) {
79+
ci.cancel();
80+
81+
this.drawDefaultBackground();
82+
83+
this.drawCenteredString(this.fontRendererObj, this.field_146306_a, this.width / 2, hodgepodge$titleY, 0xAAAAAA);
84+
85+
if (this.field_146305_g != null) {
86+
int y = hodgepodge$textStartY;
87+
for (Iterator<?> iterator = this.field_146305_g.iterator(); iterator
88+
.hasNext(); y += this.fontRendererObj.FONT_HEIGHT) {
89+
String s = (String) iterator.next();
90+
this.drawCenteredString(this.fontRendererObj, s, this.width / 2, y, 0xFFFFFF);
91+
}
92+
}
93+
94+
super.drawScreen(mouseX, mouseY, partialTicks);
95+
}
96+
}

0 commit comments

Comments
 (0)