Skip to content

Commit a5b99d8

Browse files
committed
Fixed wrong text width calculation (now for real)
Figured out equation that describes the client's character scaling Specified scope of dependencies
1 parent b576dd0 commit a5b99d8

File tree

6 files changed

+77
-72
lines changed

6 files changed

+77
-72
lines changed

pom.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,16 +71,19 @@
7171
<groupId>org.spigotmc</groupId>
7272
<artifactId>spigot-api</artifactId>
7373
<version>1.16.1-R0.1-SNAPSHOT</version>
74+
<scope>provided</scope>
7475
</dependency>
7576
<dependency>
7677
<groupId>com.github.dmulloy2</groupId>
7778
<artifactId>ProtocolLib</artifactId>
7879
<version>7bac4ec634</version>
80+
<scope>provided</scope>
7981
</dependency>
8082
<dependency>
8183
<groupId>org.jetbrains</groupId>
8284
<artifactId>annotations-java5</artifactId>
8385
<version>21.0.1</version>
86+
<scope>provided</scope>
8487
</dependency>
8588
</dependencies>
8689
</project>

src/main/java/com/sentropic/guiapi/GUIManager.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@ public class GUIManager implements Listener {
1919
GUIManager() { task.runTaskTimer(GUIAPI.getPlugin(), 0, 1); }
2020

2121
void close() {
22-
try { task.cancel(); }
23-
catch (IllegalStateException ignored) { }
22+
try { task.cancel(); } catch (IllegalStateException ignored) { }
2423
}
2524

2625
public GUI getGUI(Player player) {
@@ -38,9 +37,7 @@ public GUI getGUI(Player player) {
3837
public class Task extends BukkitRunnable {
3938
@Override
4039
public void run() {
41-
GUIS.values().stream()
42-
.filter(gui -> !gui.getPlayer().getGameMode().equals(GameMode.CREATIVE))
43-
.forEach(GUI::play);
40+
GUIS.values().forEach(GUI::play);
4441
}
4542
}
4643
}

src/main/java/com/sentropic/guiapi/command/ReloadCommand.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
package com.sentropic.guiapi.command;
22

33
import com.sentropic.guiapi.GUIAPI;
4-
import com.sentropic.guiapi.GUIManager;
54
import com.sentropic.guiapi.gui.GUI;
6-
import org.bukkit.Bukkit;
75
import org.bukkit.ChatColor;
86
import org.bukkit.command.Command;
97
import org.bukkit.command.CommandExecutor;

src/main/java/com/sentropic/guiapi/gui/Font.java

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
import java.util.HashMap;
77
import java.util.Map;
8-
import java.util.Objects;
98

109
public class Font {
1110

@@ -15,14 +14,39 @@ public class Font {
1514
private static final Map<String,Font> registeredFonts = new HashMap<>();
1615

1716
static {
18-
DEFAULT.registerWidth('I', 4);
17+
// Register default char widths (width = horizontal pixels + 1)
18+
DEFAULT.registerWidth(' ', 4);
1919
DEFAULT.registerWidth('f', 5);
2020
DEFAULT.registerWidth('i', 2);
2121
DEFAULT.registerWidth('k', 5);
2222
DEFAULT.registerWidth('l', 3);
2323
DEFAULT.registerWidth('t', 4);
24-
DEFAULT.registerWidth(' ', 4);
24+
DEFAULT.registerWidth('I', 4);
25+
DEFAULT.registerWidth('í', 3);
26+
DEFAULT.registerWidth('Í', 4);
27+
DEFAULT.registerWidth('´', 3);
2528
DEFAULT.registerWidth('.', 2);
29+
DEFAULT.registerWidth(',', 2);
30+
DEFAULT.registerWidth(';', 2);
31+
DEFAULT.registerWidth(':', 2);
32+
DEFAULT.registerWidth('[', 4);
33+
DEFAULT.registerWidth(']', 4);
34+
DEFAULT.registerWidth('{', 4);
35+
DEFAULT.registerWidth('}', 4);
36+
DEFAULT.registerWidth('*', 4);
37+
DEFAULT.registerWidth('!', 2);
38+
DEFAULT.registerWidth('¡', 2);
39+
DEFAULT.registerWidth('"', 4);
40+
DEFAULT.registerWidth('(', 4);
41+
DEFAULT.registerWidth(')', 4);
42+
DEFAULT.registerWidth('°', 5);
43+
DEFAULT.registerWidth('|', 2);
44+
DEFAULT.registerWidth('`', 3);
45+
DEFAULT.registerWidth('\'', 2);
46+
DEFAULT.registerWidth('<', 5);
47+
DEFAULT.registerWidth('>', 5);
48+
DEFAULT.registerWidth('@', 7);
49+
DEFAULT.registerWidth('~', 7);
2650

2751
register(DEFAULT);
2852
}
@@ -52,7 +76,6 @@ public static boolean unregister(Font font) {
5276

5377
public Font(@NotNull String id, int height) {
5478
this.id = id;
55-
if (height < 5) { height += 1; } // Correction necessary for some reason
5679
this.height = height;
5780
}
5881

@@ -62,22 +85,22 @@ public void registerWidth(char character, int width) {
6285
}
6386

6487
public int getWidth(char character, boolean scale) {
65-
int result;
66-
if (this == DEFAULT) {
67-
result = widths.getOrDefault(character, 6);
68-
} else {
69-
result = widths == null ?
70-
DEFAULT.getWidth(character, scale) :
71-
widths.getOrDefault(character, DEFAULT.getWidth(character, scale));
88+
Integer result = null;
89+
if (this == DEFAULT) { result = widths.getOrDefault(character, 6); } else {
90+
try { result = widths.get(character); } catch (NullPointerException ignored) { }
91+
if (result == null) { result = DEFAULT.getWidth(character, false); }
92+
}
93+
if (scale && this != DEFAULT && character != ' ') {
94+
// Formula figured out experimentally (pain)
95+
result = (int) Math.round(1.1249999d+(result-1)*height/8d);
7296
}
73-
if (scale) { result = (int) Math.ceil(result*height/8f); }
7497
return result;
7598
}
7699

77100
public int getWidth(String text, boolean scale) {
78-
if (text.equals("")) { return 0; }
101+
if (text.equals("")) { throw new IllegalArgumentException(); }
79102
int total = 0;
80-
for (char character : text.toCharArray()) { total += getWidth(character, scale); }
103+
for (Character character : text.toCharArray()) { total += getWidth(character, scale); }
81104
return total;
82105
}
83106

src/main/java/com/sentropic/guiapi/gui/GUI.java

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import com.comphenix.protocol.wrappers.WrappedChatComponent;
55
import com.sentropic.guiapi.GUIAPI;
66
import com.sentropic.guiapi.packet.WrapperPlayServerTitle;
7-
import org.apache.commons.lang.ObjectUtils;
87
import org.bukkit.configuration.ConfigurationSection;
98
import org.bukkit.entity.Player;
109
import org.jetbrains.annotations.NotNull;
@@ -104,9 +103,9 @@ public boolean removeIf(Predicate<GUIComponent> predicate) {
104103
public boolean isDebugging() { return debug; }
105104

106105
private static final String ID_DEBUG = "debug:";
106+
107107
public void setDebug(boolean debug) {
108-
if (this.debug == debug) { return; }
109-
else { this.debug = debug; }
108+
if (this.debug == debug) { return; } else { this.debug = debug; }
110109
if (debug) {
111110
List<GUIComponent> debugComponents = new ArrayList<>();
112111
ConfigurationSection debugSection = GUIAPI.getPlugin().getConfig().getConfigurationSection("debug");
@@ -119,38 +118,43 @@ public void setDebug(boolean debug) {
119118
String id = ID_DEBUG+componentKey;
120119
int offset = componentSection.getInt("offset");
121120
String text = Objects.requireNonNull(componentSection.getString("text"));
121+
int width = componentSection.getInt("width", -1);
122+
122123
Font font = new Font(Objects.requireNonNull(fontSection.getString("id")),
123124
fontSection.getInt("height"));
124125
Alignment alignment = Alignment.valueOf(Objects.requireNonNull(componentSection.getString("alignment")).toUpperCase());
125126
boolean scale = componentSection.getBoolean("scale", true);
126127

127-
debugComponents.add(new GUIComponent(id, offset, text, font, alignment, scale));
128+
GUIComponent component;
129+
if (width == -1) { component = new GUIComponent(id, offset, text, font, alignment, scale); } else {
130+
component = new GUIComponent(id, offset, text, width, font, alignment);
131+
}
132+
debugComponents.add(component);
128133
} catch (NullPointerException | IllegalArgumentException ignored) { }
129134
}
130135
for (GUIComponent component : debugComponents) { putOnTop(component); }
131136
} else { removeIf(component -> component.getID().startsWith(ID_DEBUG)); }
132137
}
133138

134-
private void build() {
139+
private void build() { //TODO see if can optimize
135140
StringBuilder builder = new StringBuilder("[{\"text\":\"");
136141
int offset = 0;
137142
Font font = Font.DEFAULT;
138-
139143
for (GUIComponent component : guiComponents) {
140-
for (GUIComponent word : component.byWord()) {
141-
if (!font.equals(Font.DEFAULT)) {
142-
builder.append("\",\"font\":\"")
143-
.append(font)
144-
.append("\"},{\"text\":\"");
145-
}
146-
builder.append(spacesOf(offset+word.getLeftOffset()));
147-
font = word.getFont();
148-
if (!font.equals(Font.DEFAULT)) {
149-
builder.append("\",\"font\":\"minecraft:default\"},{\"text\":\"");
150-
}
151-
builder.append(word.getText());
152-
offset = word.getRightOffset();
144+
if (debug && !component.getID().startsWith(ID_DEBUG)) { continue; }
145+
if (!font.equals(Font.DEFAULT)) {
146+
builder.append("\",\"font\":\"")
147+
.append(font)
148+
.append("\"},{\"text\":\"");
149+
}
150+
String text = component.getText();
151+
builder.append(spacesOf(offset+component.getLeftOffset()));
152+
offset = component.getRightOffset();
153+
font = component.getFont();
154+
if (!font.equals(Font.DEFAULT)) {
155+
builder.append("\",\"font\":\"minecraft:default\"},{\"text\":\"");
153156
}
157+
builder.append(text);
154158
}
155159

156160
if (!font.equals(Font.DEFAULT)) {
@@ -180,9 +184,7 @@ public void play() {
180184

181185
public static String spacesOf(int amount) {
182186
Map<Integer,String> spaces;
183-
if (amount == 0) { return ""; } else if (amount > 0) {
184-
spaces = POS_SPACES;
185-
} else {
187+
if (amount == 0) { return ""; } else if (amount > 0) { spaces = POS_SPACES; } else {
186188
amount = -amount;
187189
spaces = NEG_SPACES;
188190
}

src/main/java/com/sentropic/guiapi/gui/GUIComponent.java

Lines changed: 11 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@
22

33
import org.jetbrains.annotations.NotNull;
44

5-
import java.util.ArrayList;
6-
import java.util.List;
7-
85
public class GUIComponent {
96
private String id;
107
private final String text;
@@ -18,20 +15,28 @@ public GUIComponent(@NotNull String id,
1815
Font font,
1916
@NotNull Alignment alignment,
2017
boolean scale) {
18+
this(id, offset, text, font.getWidth(text, scale), font, alignment);
19+
}
20+
21+
GUIComponent(String id,
22+
int offset,
23+
String text,
24+
int width,
25+
Font font,
26+
Alignment alignment) {
2127
this.id = id;
2228
this.text = text;
2329
this.font = font;
2430
switch (alignment) {
2531
case LEFT:
2632
this.leftOffset = offset;
27-
this.rightOffset = -offset-font.getWidth(text, scale);
33+
this.rightOffset = -offset-width;
2834
break;
2935
case RIGHT:
30-
this.leftOffset = offset-font.getWidth(text, scale);
36+
this.leftOffset = offset-width;
3137
this.rightOffset = -offset;
3238
break;
3339
case CENTER:
34-
int width = font.getWidth(text, scale);
3540
this.leftOffset = offset-width/2;
3641
this.rightOffset = -this.leftOffset-width;
3742
break;
@@ -40,29 +45,6 @@ public GUIComponent(@NotNull String id,
4045
}
4146
}
4247

43-
private GUIComponent(int leftOffset, String text, Font font, int rightOffset) {
44-
this.leftOffset = leftOffset;
45-
this.text = text;
46-
this.font = font;
47-
this.rightOffset = rightOffset;
48-
}
49-
50-
public List<GUIComponent> byWord() {
51-
List<GUIComponent> list = new ArrayList<>();
52-
String[] words = text.split(" ");
53-
if (words.length == 1) {
54-
list.add(this);
55-
return list;
56-
}
57-
int spaces = (int) Math.round(4.0*font.getHeight()/8);
58-
list.add(new GUIComponent(leftOffset, words[0], font, 0));
59-
for (int i = 1; i < words.length-1; i++) {
60-
list.add(new GUIComponent(spaces, words[i], font, 0));
61-
}
62-
list.add(new GUIComponent(spaces, words[words.length-1], font, rightOffset));
63-
return list;
64-
}
65-
6648
public String getID() { return id; }
6749

6850
public String getText() { return text; }

0 commit comments

Comments
 (0)