mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-09 15:29:20 -04:00
integrate font in ChatComponent api
This commit is contained in:
parent
96260aab44
commit
c39ad18715
@ -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;
|
||||
|
@ -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<ChatFormattingCode> 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<Float> meshData) {
|
||||
for (var chatPart : this.parts) {
|
||||
chatPart.addVerticies(startPosition, offset, font, hudScale, meshData);
|
||||
}
|
||||
}
|
||||
|
||||
@Unsafe
|
||||
public ArrayList<ChatComponent> getParts() {
|
||||
return this.parts;
|
||||
|
@ -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<Node> 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<Float> meshData);
|
||||
}
|
||||
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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<ChatFormattingCode> formatting;
|
||||
|
||||
public TextComponent(String text, RGBColor color, BetterHashSet<ChatFormattingCode> 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<ChatFormattingCode> getFormatting() {
|
||||
return this.formatting;
|
||||
}
|
||||
|
||||
public TextComponent setFormatting(BetterHashSet<ChatFormattingCode> 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<Node> getJavaFXText(ObservableList<Node> 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;
|
||||
}
|
||||
}
|
230
src/main/java/de/bixilon/minosoft/data/text/TextComponent.kt
Normal file
230
src/main/java/de/bixilon/minosoft/data/text/TextComponent.kt
Normal file
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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<ChatFormattingCode> = BetterHashSet()
|
||||
|
||||
constructor(text: String, color: RGBColor?, formatting: BetterHashSet<ChatFormattingCode>) {
|
||||
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<ChatFormattingCode>): 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<Node>): ObservableList<Node> {
|
||||
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<Float>) {
|
||||
fun drawLetterVertex(position: Vec2, uv: Vec2, atlasPage: Int, color: RGBColor, meshData: MutableList<Float>) {
|
||||
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<Float>) {
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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<ChatComponent> 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<Node> getJavaFXText(ObservableList<Node> 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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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<Float>) {
|
||||
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<Float>) {
|
||||
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<Float> = 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()
|
||||
|
Loading…
x
Reference in New Issue
Block a user