diff --git a/src/main/java/de/bixilon/minosoft/data/locale/minecraft/MinecraftLanguage.java b/src/main/java/de/bixilon/minosoft/data/locale/minecraft/MinecraftLanguage.java index 9d9f2cc97..15e05df8a 100644 --- a/src/main/java/de/bixilon/minosoft/data/locale/minecraft/MinecraftLanguage.java +++ b/src/main/java/de/bixilon/minosoft/data/locale/minecraft/MinecraftLanguage.java @@ -13,6 +13,7 @@ package de.bixilon.minosoft.data.locale.minecraft; +import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; @@ -52,6 +53,13 @@ public class MinecraftLanguage { } public String translate(String key, Object... data) { + if (data.length == 1 && data[0] instanceof JsonArray jsonArray) { + data = new Object[jsonArray.size()]; + int i = 0; + for (var element : jsonArray) { + data[i++] = element.getAsString(); + } + } String placeholder = this.data.get(key); if (placeholder == null) { return null; diff --git a/src/main/java/de/bixilon/minosoft/data/text/BaseComponent.java b/src/main/java/de/bixilon/minosoft/data/text/BaseComponent.java index fabf9915c..c36c2fe48 100644 --- a/src/main/java/de/bixilon/minosoft/data/text/BaseComponent.java +++ b/src/main/java/de/bixilon/minosoft/data/text/BaseComponent.java @@ -18,9 +18,12 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; import de.bixilon.minosoft.data.mappings.versions.Version; +import de.bixilon.minosoft.gui.rendering.font.Font; +import de.bixilon.minosoft.gui.rendering.hud.HUDScale; import de.bixilon.minosoft.modding.event.events.annotations.Unsafe; import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition; import de.bixilon.minosoft.util.hash.BetterHashSet; +import glm_.vec2.Vec2; import javafx.collections.ObservableList; import javafx.scene.Node; @@ -28,6 +31,7 @@ import javax.annotation.Nullable; import java.text.CharacterIterator; import java.text.StringCharacterIterator; import java.util.ArrayList; +import java.util.List; public class BaseComponent extends ChatComponent { private static final String LEGACY_RESET_SUFFIX = String.valueOf(ProtocolDefinition.TEXT_COMPONENT_SPECIAL_PREFIX_CHAR) + PostChatFormattingCodes.RESET.getChar(); @@ -43,7 +47,7 @@ public class BaseComponent extends ChatComponent { public BaseComponent(Version version, @Nullable ChatComponent parent, String text) { // legacy String StringBuilder currentText = new StringBuilder(); - RGBColor color = null; + RGBColor color = ChatColors.WHITE; BetterHashSet formattingCodes = new BetterHashSet<>(); StringCharacterIterator iterator = new StringCharacterIterator(text); while (iterator.current() != CharacterIterator.DONE) { @@ -165,7 +169,7 @@ public class BaseComponent extends ChatComponent { } if (json.has("translate")) { - this.parts.add(new TranslatableComponent(version, parentParameter, json.get("translate").getAsString(), json.getAsJsonArray("with"))); + this.parts.add(new BaseComponent(version, version.getLocaleManager().translate(json.get("translate").getAsString(), json.getAsJsonArray("with")))); } } else if (data instanceof JsonPrimitive primitive) { this.parts.add(new BaseComponent(version, parent, primitive.getAsString())); @@ -208,6 +212,13 @@ public class BaseComponent extends ChatComponent { return nodes; } + @Override + public void addVerticies(Vec2 startPosition, Vec2 offset, Font font, HUDScale hudScale, List meshData) { + for (var chatPart : this.parts) { + chatPart.addVerticies(startPosition, offset, font, hudScale, meshData); + } + } + @Unsafe public ArrayList getParts() { return this.parts; diff --git a/src/main/java/de/bixilon/minosoft/data/text/ChatComponent.java b/src/main/java/de/bixilon/minosoft/data/text/ChatComponent.java index d6d71b52f..ef8321245 100644 --- a/src/main/java/de/bixilon/minosoft/data/text/ChatComponent.java +++ b/src/main/java/de/bixilon/minosoft/data/text/ChatComponent.java @@ -18,11 +18,15 @@ import com.google.gson.JsonParseException; import com.google.gson.JsonParser; import com.google.gson.JsonPrimitive; import de.bixilon.minosoft.data.mappings.versions.Version; +import de.bixilon.minosoft.gui.rendering.font.Font; +import de.bixilon.minosoft.gui.rendering.hud.HUDScale; +import glm_.vec2.Vec2; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.scene.Node; import javax.annotation.Nullable; +import java.util.List; public abstract class ChatComponent { public static ChatComponent valueOf(Object raw) { @@ -83,4 +87,9 @@ public abstract class ChatComponent { public ObservableList getJavaFXText() { return getJavaFXText(FXCollections.observableArrayList()); } + + /** + * @return Adds all verticies to the array (used in opengl) + */ + public abstract void addVerticies(Vec2 startPosition, Vec2 offset, Font font, HUDScale hudScale, List meshData); } diff --git a/src/main/java/de/bixilon/minosoft/data/text/TextComponent.java b/src/main/java/de/bixilon/minosoft/data/text/TextComponent.java deleted file mode 100644 index 0b33b193e..000000000 --- a/src/main/java/de/bixilon/minosoft/data/text/TextComponent.java +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Minosoft - * Copyright (C) 2020 Moritz Zwerger - * - * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program.If not, see . - * - * This software is not affiliated with Mojang AB, the original developer of Minecraft. - */ - -package de.bixilon.minosoft.data.text; - -import de.bixilon.minosoft.Minosoft; -import de.bixilon.minosoft.config.ConfigurationPaths; -import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition; -import de.bixilon.minosoft.util.Util; -import de.bixilon.minosoft.util.hash.BetterHashSet; -import javafx.animation.Animation; -import javafx.animation.KeyFrame; -import javafx.animation.Timeline; -import javafx.collections.ObservableList; -import javafx.scene.Node; -import javafx.scene.paint.Color; -import javafx.scene.text.Text; -import javafx.util.Duration; - -import java.util.Objects; - -public class TextComponent extends ChatComponent { - private final String text; - private RGBColor color; - private BetterHashSet formatting; - - public TextComponent(String text, RGBColor color, BetterHashSet formatting) { - this.text = text; - this.color = color; - this.formatting = formatting; - } - - public TextComponent(String text, RGBColor color) { - this.text = text; - this.color = color; - } - - public TextComponent(String text) { - this.text = text; - } - - public TextComponent setObfuscated(boolean obfuscated) { - this.formatting.addOrRemove(PreChatFormattingCodes.OBFUSCATED, obfuscated); - return this; - } - - public TextComponent setBold(boolean bold) { - this.formatting.addOrRemove(PreChatFormattingCodes.BOLD, bold); - return this; - } - - public TextComponent setStrikethrough(boolean strikethrough) { - this.formatting.addOrRemove(PreChatFormattingCodes.STRIKETHROUGH, strikethrough); - return this; - } - - public TextComponent setUnderlined(boolean underlined) { - this.formatting.addOrRemove(PreChatFormattingCodes.UNDERLINED, underlined); - return this; - } - - public TextComponent setItalic(boolean italic) { - this.formatting.addOrRemove(PreChatFormattingCodes.ITALIC, italic); - return this; - } - - public TextComponent setReset(boolean reset) { - this.formatting.addOrRemove(PostChatFormattingCodes.RESET, reset); - return this; - } - - public RGBColor getColor() { - return this.color; - } - - public TextComponent setColor(RGBColor color) { - this.color = color; - return this; - } - - public BetterHashSet getFormatting() { - return this.formatting; - } - - public TextComponent setFormatting(BetterHashSet formatting) { - this.formatting = formatting; - return this; - } - - @Override - public int hashCode() { - return Objects.hash(this.text, this.color, this.formatting); - } - - @Override - public boolean equals(Object obj) { - if (super.equals(obj)) { - return true; - } - if (hashCode() != obj.hashCode()) { - return false; - } - TextComponent their = (TextComponent) obj; - return this.text.equals(their.getMessage()) && this.color.equals(their.getColor()) && this.formatting.equals(their.getFormatting()); - } - - @Override - public String toString() { - return getANSIColoredMessage(); - } - - @Override - public String getANSIColoredMessage() { - StringBuilder builder = new StringBuilder(); - if (this.color != null) { - builder.append(ChatColors.getANSIColorByRGBColor(this.color)); - } - if (this.formatting != null) { - this.formatting.forEach((chatFormattingCodes -> { - if (chatFormattingCodes instanceof PreChatFormattingCodes code) { - builder.append(code.getANSI()); - } - })); - } - builder.append(this.text); - if (this.formatting != null) { - this.formatting.forEach((chatFormattingCodes -> { - if (chatFormattingCodes instanceof PostChatFormattingCodes code) { - builder.append(code.getANSI()); - } - })); - } - builder.append(PostChatFormattingCodes.RESET); - return builder.toString(); - } - - @Override - public String getLegacyText() { - StringBuilder output = new StringBuilder(); - Integer colorChar = ChatColors.getColorId(this.color); - if (colorChar != null) { - output.append(ProtocolDefinition.TEXT_COMPONENT_SPECIAL_PREFIX_CHAR).append(Integer.toHexString(colorChar)); - } - this.formatting.forEach((chatFormattingCode -> output.append(ProtocolDefinition.TEXT_COMPONENT_SPECIAL_PREFIX_CHAR).append(chatFormattingCode.getChar()))); - output.append(this.text); - output.append(ProtocolDefinition.TEXT_COMPONENT_SPECIAL_PREFIX_CHAR).append(PostChatFormattingCodes.RESET.getChar()); - return output.toString(); - } - - @Override - public String getMessage() { - return this.text; - } - - @Override - public ObservableList getJavaFXText(ObservableList nodes) { - Text text = new Text(this.text); - text.setFill(Color.WHITE); - if (Minosoft.getConfig().getBoolean(ConfigurationPaths.BooleanPaths.CHAT_COLORED) && this.color != null) { - text.setFill(Color.web(this.color.toString())); - } - this.formatting.forEach((chatFormattingCode -> { - if (chatFormattingCode instanceof PreChatFormattingCodes code) { - switch (code) { - case OBFUSCATED -> { - // ToDo: potential memory leak: Stop timeline, when TextComponent isn't shown anymore - Timeline obfuscatedTimeline; - if (Minosoft.getConfig().getBoolean(ConfigurationPaths.BooleanPaths.CHAT_OBFUSCATED)) { - obfuscatedTimeline = new Timeline(new KeyFrame(Duration.millis(50), e -> { - char[] chars = text.getText().toCharArray(); - for (int i = 0; i < chars.length; i++) { - chars[i] = Util.getRandomChar(ProtocolDefinition.OBFUSCATED_CHARS); - } - text.setText(new String(chars)); - })); - } else { - obfuscatedTimeline = new Timeline(new KeyFrame(Duration.millis(500), e -> text.setVisible(false)), new KeyFrame(Duration.millis(1000), e -> text.setVisible(true))); - } - obfuscatedTimeline.setCycleCount(Animation.INDEFINITE); - obfuscatedTimeline.play(); - text.getStyleClass().add("obfuscated"); - } - case BOLD -> text.setStyle("-fx-font-weight: bold;"); - case STRIKETHROUGH -> text.setStyle("-fx-strikethrough: true;"); - case UNDERLINED -> text.setStyle("-fx-underline: true;"); - case ITALIC -> text.setStyle("-fx-font-weight: italic;"); - } - } - })); - nodes.add(text); - return nodes; - } -} diff --git a/src/main/java/de/bixilon/minosoft/data/text/TextComponent.kt b/src/main/java/de/bixilon/minosoft/data/text/TextComponent.kt new file mode 100644 index 000000000..34e87dbac --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/data/text/TextComponent.kt @@ -0,0 +1,230 @@ +/* + * Minosoft + * Copyright (C) 2020 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program.If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ +package de.bixilon.minosoft.data.text + +import de.bixilon.minosoft.Minosoft +import de.bixilon.minosoft.config.ConfigurationPaths +import de.bixilon.minosoft.gui.rendering.font.Font +import de.bixilon.minosoft.gui.rendering.font.FontChar +import de.bixilon.minosoft.gui.rendering.hud.HUDScale +import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition +import de.bixilon.minosoft.util.Util +import de.bixilon.minosoft.util.hash.BetterHashSet +import glm_.vec2.Vec2 +import javafx.animation.Animation +import javafx.animation.KeyFrame +import javafx.animation.Timeline +import javafx.collections.ObservableList +import javafx.scene.Node +import javafx.scene.paint.Color +import javafx.scene.text.Text +import javafx.util.Duration +import java.util.* +import java.util.function.Consumer + + +open class TextComponent : ChatComponent { + private val text: String + var color: RGBColor = ChatColors.WHITE + var formatting: BetterHashSet = BetterHashSet() + + constructor(text: String, color: RGBColor?, formatting: BetterHashSet) { + this.text = text + if (color != null) { + this.color = color + } + this.formatting = formatting + } + + constructor(text: String, color: RGBColor) { + this.text = text + this.color = color + } + + constructor(text: String) { + this.text = text + } + + fun setObfuscated(obfuscated: Boolean): TextComponent { + formatting.addOrRemove(PreChatFormattingCodes.OBFUSCATED, obfuscated) + return this + } + + fun setBold(bold: Boolean): TextComponent { + formatting.addOrRemove(PreChatFormattingCodes.BOLD, bold) + return this + } + + fun setStrikethrough(strikethrough: Boolean): TextComponent { + formatting.addOrRemove(PreChatFormattingCodes.STRIKETHROUGH, strikethrough) + return this + } + + fun setUnderlined(underlined: Boolean): TextComponent { + formatting.addOrRemove(PreChatFormattingCodes.UNDERLINED, underlined) + return this + } + + fun setItalic(italic: Boolean): TextComponent { + formatting.addOrRemove(PreChatFormattingCodes.ITALIC, italic) + return this + } + + fun setReset(reset: Boolean): TextComponent { + formatting.addOrRemove(PostChatFormattingCodes.RESET, reset) + return this + } + + fun setColor(color: RGBColor): TextComponent { + this.color = color + return this + } + + fun setFormatting(formatting: BetterHashSet): TextComponent { + this.formatting = formatting + return this + } + + override fun hashCode(): Int { + return Objects.hash(text, color, formatting) + } + + override fun equals(other: Any?): Boolean { + if (super.equals(other)) { + return true + } + if (hashCode() != other.hashCode()) { + return false + } + val their = other as TextComponent? + return text == their!!.message && color == their.color && formatting == their.formatting + } + + override fun toString(): String { + return ansiColoredMessage + } + + override fun getANSIColoredMessage(): String { + val builder = StringBuilder() + builder.append(ChatColors.getANSIColorByRGBColor(this.color)) + + for (formattingCode in this.formatting) { + if (formattingCode is PreChatFormattingCodes) { + builder.append(formattingCode.getANSI()) + } + } + builder.append(this.text) + for (formattingCode in this.formatting) { + if (formattingCode is PostChatFormattingCodes) { + builder.append(formattingCode.getANSI()) + } + } + builder.append(PostChatFormattingCodes.RESET) + return builder.toString() + } + + override fun getLegacyText(): String { + val output = StringBuilder() + val colorChar = ChatColors.getColorId(color) + if (colorChar != null) { + output.append(ProtocolDefinition.TEXT_COMPONENT_SPECIAL_PREFIX_CHAR).append(Integer.toHexString(colorChar)) + } + formatting.forEach(Consumer { chatFormattingCode: ChatFormattingCode -> output.append(ProtocolDefinition.TEXT_COMPONENT_SPECIAL_PREFIX_CHAR).append(chatFormattingCode.char) }) + output.append(text) + output.append(ProtocolDefinition.TEXT_COMPONENT_SPECIAL_PREFIX_CHAR).append(PostChatFormattingCodes.RESET.char) + return output.toString() + } + + override fun getMessage(): String { + return text + } + + override fun getJavaFXText(nodes: ObservableList): ObservableList { + val text = Text(text) + text.fill = Color.WHITE + if (Minosoft.getConfig().getBoolean(ConfigurationPaths.BooleanPaths.CHAT_COLORED)) { + text.fill = Color.web(color.toString()) + } + for (chatFormattingCode in formatting) { + if (chatFormattingCode is PreChatFormattingCodes) { + when (chatFormattingCode) { + PreChatFormattingCodes.OBFUSCATED -> { + // ToDo: potential memory leak: Stop timeline, when TextComponent isn't shown anymore + val obfuscatedTimeline = if (Minosoft.getConfig().getBoolean(ConfigurationPaths.BooleanPaths.CHAT_OBFUSCATED)) { + Timeline(KeyFrame(Duration.millis(50.0), { + val chars = text.text.toCharArray() + for (i in chars.indices) { + chars[i] = Util.getRandomChar(ProtocolDefinition.OBFUSCATED_CHARS) + } + text.text = String(chars) + })) + } else { + Timeline(KeyFrame(Duration.millis(500.0), { + text.isVisible = false + }), KeyFrame(Duration.millis(1000.0), { + text.isVisible = true + })) + } + + obfuscatedTimeline.cycleCount = Animation.INDEFINITE + obfuscatedTimeline.play() + text.styleClass.add("obfuscated") + } + PreChatFormattingCodes.BOLD -> { + text.style = "-fx-font-weight: bold;" + } + PreChatFormattingCodes.STRIKETHROUGH -> { + text.style = "-fx-strikethrough: true;" + } + PreChatFormattingCodes.UNDERLINED -> { + text.style = "-fx-underline: true;" + } + PreChatFormattingCodes.ITALIC -> { + text.style = "-fx-font-weight: italic;" + } + } + } + } + nodes.add(text) + return nodes + } + + override fun addVerticies(startPosition: Vec2, offset: Vec2, font: Font, hudScale: HUDScale, meshData: MutableList) { + fun drawLetterVertex(position: Vec2, uv: Vec2, atlasPage: Int, color: RGBColor, meshData: MutableList) { + meshData.add(position.x) + meshData.add(position.y) + meshData.add(uv.x) + meshData.add(uv.y) + meshData.add(atlasPage.toFloat()) + meshData.add(color.red / 256f) + meshData.add(color.green / 256f) + meshData.add(color.blue / 256f) + } + + fun drawLetter(position: Vec2, scaledX: Float, fontChar: FontChar, color: RGBColor, meshData: MutableList) { + val scaledHeight = fontChar.height * hudScale.scale + drawLetterVertex(Vec2(position.x, position.y), fontChar.uvLeftDown, fontChar.atlasTextureIndex, color, meshData) + drawLetterVertex(Vec2(position.x, position.y + scaledHeight), fontChar.uvLeftUp, fontChar.atlasTextureIndex, color, meshData) + drawLetterVertex(Vec2(position.x + scaledX, position.y), fontChar.uvRightDown, fontChar.atlasTextureIndex, color, meshData) + drawLetterVertex(Vec2(position.x + scaledX, position.y), fontChar.uvRightDown, fontChar.atlasTextureIndex, color, meshData) + drawLetterVertex(Vec2(position.x, position.y + scaledHeight), fontChar.uvLeftUp, fontChar.atlasTextureIndex, color, meshData) + drawLetterVertex(Vec2(position.x + scaledX, position.y + scaledHeight), fontChar.uvRightUp, fontChar.atlasTextureIndex, color, meshData) + } + for (c in text.toCharArray()) { + val fontChar = font.getChar(c) + val scaledX = fontChar.endPixel * hudScale.scale + drawLetter(startPosition + offset, scaledX, fontChar, color, meshData) + offset += Vec2(scaledX, 0f) + } + } +} diff --git a/src/main/java/de/bixilon/minosoft/data/text/TranslatableComponent.java b/src/main/java/de/bixilon/minosoft/data/text/TranslatableComponent.java deleted file mode 100644 index ada6b7b7f..000000000 --- a/src/main/java/de/bixilon/minosoft/data/text/TranslatableComponent.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Minosoft - * Copyright (C) 2020 Moritz Zwerger - * - * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program.If not, see . - * - * This software is not affiliated with Mojang AB, the original developer of Minecraft. - */ - -package de.bixilon.minosoft.data.text; - -import com.google.gson.JsonArray; -import de.bixilon.minosoft.data.mappings.versions.Version; -import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition; -import javafx.collections.ObservableList; -import javafx.scene.Node; - -import javax.annotation.Nullable; -import java.util.ArrayList; -import java.util.Arrays; - -public class TranslatableComponent extends ChatComponent { - private final ArrayList data = new ArrayList<>(); - private final String key; - private final TextComponent parent; - private final Version version; - - public TranslatableComponent(Version version, String key, JsonArray data) { - this(version, null, key, data); - } - - public TranslatableComponent(Version version, @Nullable TextComponent parent, String key, JsonArray data) { - this.version = version; - this.parent = parent; - this.key = key; - if (data == null) { - return; - } - data.forEach((jsonElement -> { - if (jsonElement.isJsonPrimitive()) { - this.data.add(ChatComponent.valueOf(version, parent, jsonElement.getAsString())); - } else { - this.data.add(new BaseComponent(version, parent, jsonElement.getAsJsonObject())); - } - })); - } - - @Override - public String getANSIColoredMessage() { - return getList("getANSIColoredMessage"); - } - - @Override - public String getLegacyText() { - return getList("getLegacyText"); - } - - @Override - public String getMessage() { - return getList("getMessage"); - } - - @Override - public ObservableList getJavaFXText(ObservableList nodes) { - // ToDo fix nested base component (formatting), not just a string - - // This is just a dirty workaround to enable formatting and coloring. Still need to do hover, click, ... stuff - return new BaseComponent(this.version, getLegacyText()).getJavaFXText(nodes); - } - - // just used reflections to not write this twice anc only change the method name - private String getList(String methodName) { - try { - Object[] data = new String[this.data.size()]; - for (int i = 0; i < this.data.size(); i++) { - data[i] = this.data.get(i).getClass().getMethod(methodName).invoke(this.data.get(i)); - } - if (this.parent != null) { - StringBuilder builder = new StringBuilder(); - if (methodName.equals("getANSIColoredMessage")) { - builder.append(ChatColors.getANSIColorByRGBColor(this.parent.getColor())); - } else if (methodName.equals("getLegacyText")) { - builder.append(ChatColors.getColorChar(this.parent.getColor())); - - } - for (ChatFormattingCode code : this.parent.getFormatting()) { - if (code instanceof PreChatFormattingCodes preCode) { - builder.append(switch (methodName) { - case "getANSIColoredMessage" -> preCode.getANSI(); - case "getLegacyText" -> ProtocolDefinition.TEXT_COMPONENT_SPECIAL_PREFIX_CHAR + preCode.getChar(); - default -> ""; - }); - } - } - builder.append(this.version.getLocaleManager().translate(this.key, data)); - for (ChatFormattingCode code : this.parent.getFormatting()) { - if (code instanceof PostChatFormattingCodes postCode) { - builder.append(switch (methodName) { - case "getANSIColoredMessage" -> postCode.getANSI(); - case "getLegacyText" -> ProtocolDefinition.TEXT_COMPONENT_SPECIAL_PREFIX_CHAR + postCode.getChar(); - default -> ""; - }); - } - } - return builder.toString(); - } - String text = this.version.getLocaleManager().translate(this.key, data); - if (text == null) { - // Error, can not translate - text = "{invalid=true, key=" + this.key + ", data=" + Arrays.toString(data); - } - return text; - } catch (Exception e) { - throw new RuntimeException(e); - } - } -} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/ChunkRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/ChunkRenderer.kt index 2b4b6e4ad..9b31c5def 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/ChunkRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/ChunkRenderer.kt @@ -128,9 +128,9 @@ class ChunkRenderer(private val world: World, val renderWindow: RenderWindow) : val data = prepareChunk(chunkLocation, sectionHeight, section) val sectionMap = chunkSectionsToDraw[chunkLocation]!! renderWindow.renderQueue.add { + val newMesh = WorldMesh(data, Vec3(chunkLocation.x, sectionHeight, chunkLocation.z)) sectionMap[sectionHeight]?.unload() - sectionMap.remove(sectionHeight) - sectionMap[sectionHeight] = WorldMesh(data, Vec3(chunkLocation.x, sectionHeight, chunkLocation.z)) + sectionMap[sectionHeight] = newMesh } } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/HUDRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/HUDRenderer.kt index e8675365e..667de52ec 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/HUDRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/HUDRenderer.kt @@ -1,10 +1,8 @@ package de.bixilon.minosoft.gui.rendering.hud -import de.bixilon.minosoft.data.text.ChatColors -import de.bixilon.minosoft.data.text.RGBColor +import de.bixilon.minosoft.data.text.ChatComponent import de.bixilon.minosoft.gui.rendering.Renderer import de.bixilon.minosoft.gui.rendering.font.Font -import de.bixilon.minosoft.gui.rendering.font.FontChar import de.bixilon.minosoft.gui.rendering.shader.Shader import de.bixilon.minosoft.gui.rendering.textures.TextureArray import de.bixilon.minosoft.protocol.network.Connection @@ -16,12 +14,12 @@ import org.lwjgl.opengl.GL13.GL_TEXTURE0 class HUDRenderer : Renderer { private val font = Font() - private val hudScale = HUDScale.LARGE + private val hudScale = HUDScale.MEDIUM var fps: Int = 0 var frame = 0 private lateinit var fontShader: Shader private lateinit var fontAtlasTexture: TextureArray - lateinit var hudMeshHUD: HUDFontMesh + private lateinit var hudMeshHUD: HUDFontMesh override fun init(connection: Connection) { @@ -31,49 +29,14 @@ class HUDRenderer : Renderer { fontShader = Shader("font_vertex.glsl", "font_fragment.glsl") fontShader.load() - drawString(Vec2(100, 100), "FPS: $fps") + hudMeshHUD = HUDFontMesh(floatArrayOf()) } - - fun drawLetterVertex(position: Vec2, uv: Vec2, atlasPage: Int, color: RGBColor, meshData: MutableList) { - meshData.add(position.x) - meshData.add(position.y) - meshData.add(uv.x) - meshData.add(uv.y) - meshData.add(atlasPage.toFloat()) - meshData.add(color.red / 256f) - meshData.add(color.green / 256f) - meshData.add(color.blue / 256f) - } - - fun drawLetter(position: Vec2, scaledX: Float, fontChar: FontChar, color: RGBColor, meshData: MutableList) { - val scaledHeight = fontChar.height * hudScale.scale - drawLetterVertex(Vec2(position.x, position.y), fontChar.uvLeftDown, fontChar.atlasTextureIndex, color, meshData) - drawLetterVertex(Vec2(position.x, position.y + scaledHeight), fontChar.uvLeftUp, fontChar.atlasTextureIndex, color, meshData) - drawLetterVertex(Vec2(position.x + scaledX, position.y), fontChar.uvRightDown, fontChar.atlasTextureIndex, color, meshData) - drawLetterVertex(Vec2(position.x + scaledX, position.y), fontChar.uvRightDown, fontChar.atlasTextureIndex, color, meshData) - drawLetterVertex(Vec2(position.x, position.y + scaledHeight), fontChar.uvLeftUp, fontChar.atlasTextureIndex, color, meshData) - drawLetterVertex(Vec2(position.x + scaledX, position.y + scaledHeight), fontChar.uvRightUp, fontChar.atlasTextureIndex, color, meshData) - } - - fun drawString(position: Vec2, text: String) { - if (this::hudMeshHUD.isInitialized) { - hudMeshHUD.unload() - } - + fun drawChatComponent(position: Vec2, text: ChatComponent) { + hudMeshHUD.unload() val data: MutableList = mutableListOf() - val chars = text.toCharArray() - var xOffset = position.x - - for (char in chars) { - val fontChar = font.getChar(char) - val scaledX = fontChar.endPixel * hudScale.scale - drawLetter(Vec2(xOffset, position.y), scaledX, fontChar, ChatColors.getRandomColor(), data) - xOffset += scaledX - } - + text.addVerticies(position, Vec2(0, 0), font, hudScale, data) hudMeshHUD = HUDFontMesh(data.toFloatArray()) - } fun screenChangeResizeCallback(width: Int, height: Int) { @@ -90,7 +53,7 @@ class HUDRenderer : Renderer { frame++ if (frame % 30 == 0) { - drawString(Vec2(100, 100), "FPS: $fps") + drawChatComponent(Vec2(0, 0), ChatComponent.valueOf("§6FPS:§e$fps")) } hudMeshHUD.draw()