From ac87d42c48dfa51798b310af2fa4e5eb8b2c7cee Mon Sep 17 00:00:00 2001 From: Bixilon Date: Sun, 22 Nov 2020 18:53:48 +0100 Subject: [PATCH] fix some bugs in TranslatableComponent (allow parent mapping), other fixes and improvements --- .../minosoft/data/assets/AssetsManager.java | 3 +- .../entities/block/BedEntityMetaData.java | 5 ++ .../data/entities/entities/Entity.java | 2 - .../minosoft/data/text/BaseComponent.java | 13 ++-- .../minosoft/data/text/ChatColors.java | 6 +- .../minosoft/data/text/ChatComponent.java | 8 ++- .../minosoft/data/text/TextComponent.java | 7 +- .../data/text/TranslatableComponent.java | 72 ++++++++++++++----- .../protocol/protocol/PacketHandler.java | 8 +-- .../protocol/protocol/ProtocolDefinition.java | 1 + 10 files changed, 90 insertions(+), 35 deletions(-) diff --git a/src/main/java/de/bixilon/minosoft/data/assets/AssetsManager.java b/src/main/java/de/bixilon/minosoft/data/assets/AssetsManager.java index d472f058e..dbed68dd5 100644 --- a/src/main/java/de/bixilon/minosoft/data/assets/AssetsManager.java +++ b/src/main/java/de/bixilon/minosoft/data/assets/AssetsManager.java @@ -13,6 +13,7 @@ package de.bixilon.minosoft.data.assets; +import com.google.common.base.StandardSystemProperty; import com.google.errorprone.annotations.DoNotCall; import com.google.gson.GsonBuilder; import com.google.gson.JsonElement; @@ -254,7 +255,7 @@ public class AssetsManager { private static String saveAsset(InputStream data) throws IOException { File tempDestinationFile = null; while (tempDestinationFile == null || tempDestinationFile.exists()) { // file exist? lol - tempDestinationFile = new File(System.getProperty("java.io.tmpdir") + "/minosoft/" + Util.generateRandomString(32)); + tempDestinationFile = new File(System.getProperty(StandardSystemProperty.JAVA_IO_TMPDIR.value()) + "/minosoft/" + Util.generateRandomString(32)); } Util.createParentFolderIfNotExist(tempDestinationFile); diff --git a/src/main/java/de/bixilon/minosoft/data/entities/block/BedEntityMetaData.java b/src/main/java/de/bixilon/minosoft/data/entities/block/BedEntityMetaData.java index 348e60f9b..9ed2700f4 100644 --- a/src/main/java/de/bixilon/minosoft/data/entities/block/BedEntityMetaData.java +++ b/src/main/java/de/bixilon/minosoft/data/entities/block/BedEntityMetaData.java @@ -13,6 +13,7 @@ package de.bixilon.minosoft.data.entities.block; +import de.bixilon.minosoft.data.text.ChatColors; import de.bixilon.minosoft.data.text.RGBColor; import de.bixilon.minosoft.util.nbt.tag.IntTag; import de.bixilon.minosoft.util.nbt.tag.NBTTag; @@ -26,6 +27,10 @@ public class BedEntityMetaData extends BlockEntityMetaData { } public BedEntityMetaData(NBTTag nbt) { + if (nbt == null) { + color = ChatColors.RED; + return; + } if (nbt instanceof StringTag stringTag) { // yes, we support bed rgb colors :D color = new RGBColor(stringTag.getValue()); diff --git a/src/main/java/de/bixilon/minosoft/data/entities/entities/Entity.java b/src/main/java/de/bixilon/minosoft/data/entities/entities/Entity.java index a72b9a821..9b3e22c66 100644 --- a/src/main/java/de/bixilon/minosoft/data/entities/entities/Entity.java +++ b/src/main/java/de/bixilon/minosoft/data/entities/entities/Entity.java @@ -212,11 +212,9 @@ public abstract class Entity { @EntityMetaDataFunction(identifier = "pose") public Poses getPose() { if (isCrouching()) { - // crouching return Poses.SNEAKING; } if (isSwimming()) { - // crouching return Poses.SWIMMING; } if (isFlyingWithElytra()) { 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 98d75aed9..f0f1d9a8b 100644 --- a/src/main/java/de/bixilon/minosoft/data/text/BaseComponent.java +++ b/src/main/java/de/bixilon/minosoft/data/text/BaseComponent.java @@ -16,6 +16,7 @@ package de.bixilon.minosoft.data.text; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import de.bixilon.minosoft.modding.event.events.annotations.Unsafe; +import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition; import de.bixilon.minosoft.util.hash.BetterHashSet; import javafx.collections.ObservableList; import javafx.scene.Node; @@ -40,7 +41,7 @@ public class BaseComponent extends ChatComponent { while (iterator.current() != CharacterIterator.DONE) { char c = iterator.current(); iterator.next(); - if (c != '§') { + if (c != ProtocolDefinition.TEXT_COMPONENT_SPECIAL_PREFIX_CHAR) { currentText.append(c); continue; } @@ -92,7 +93,7 @@ public class BaseComponent extends ChatComponent { TextComponent thisTextComponent = null; if (json.has("text")) { String text = json.get("text").getAsString(); - if (text.contains("§")) { + if (text.contains(String.valueOf(ProtocolDefinition.TEXT_COMPONENT_SPECIAL_PREFIX_CHAR))) { // legacy text component parts.add(new BaseComponent(text)); return; @@ -140,20 +141,20 @@ public class BaseComponent extends ChatComponent { parts.add(thisTextComponent); } + final TextComponent parentParameter = thisTextComponent == null ? parent : thisTextComponent; if (json.has("extra")) { JsonArray extras = json.getAsJsonArray("extra"); - TextComponent finalThisChatPart = thisTextComponent; - extras.forEach((extra -> parts.add(new BaseComponent(finalThisChatPart, extra.getAsJsonObject())))); + extras.forEach((extra -> parts.add(new BaseComponent(parentParameter, extra.getAsJsonObject())))); } if (json.has("translate")) { - parts.add(new TranslatableComponent(json.get("translate").getAsString(), json.getAsJsonArray("with"))); + parts.add(new TranslatableComponent(parentParameter, json.get("translate").getAsString(), json.getAsJsonArray("with"))); } } @Override public String toString() { - return getANSIColoredMessage(); + return PostChatFormattingCodes.RESET.getANSI() + getANSIColoredMessage(); } public String getANSIColoredMessage() { diff --git a/src/main/java/de/bixilon/minosoft/data/text/ChatColors.java b/src/main/java/de/bixilon/minosoft/data/text/ChatColors.java index 5d6cb505d..7d6a5eb8f 100644 --- a/src/main/java/de/bixilon/minosoft/data/text/ChatColors.java +++ b/src/main/java/de/bixilon/minosoft/data/text/ChatColors.java @@ -83,6 +83,10 @@ public final class ChatColors { return colorIntMap.get(color); } + public static String getColorChar(RGBColor color) { + return String.format("%x", colorIntMap.get(color)); + } + public static RGBColor getColorByName(String name) { return switch (name.toLowerCase()) { case "black" -> BLACK; @@ -100,7 +104,7 @@ public final class ChatColors { case "red" -> RED; case "light_purple" -> LIGHT_PURPLE; case "yellow" -> YELLOW; - case "white" -> WHITE; + case "white", "reset" -> WHITE; default -> throw new IllegalStateException("Unexpected value: " + name); }; } 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 a8faac6fd..4b37240c7 100644 --- a/src/main/java/de/bixilon/minosoft/data/text/ChatComponent.java +++ b/src/main/java/de/bixilon/minosoft/data/text/ChatComponent.java @@ -19,13 +19,19 @@ import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.scene.Node; +import javax.annotation.Nullable; + public abstract class ChatComponent { public static ChatComponent fromString(String raw) { + return fromString(null, raw); + } + + public static ChatComponent fromString(@Nullable TextComponent parent, String raw) { if (raw == null) { return new BaseComponent(); } try { - return new BaseComponent(JsonParser.parseString(raw).getAsJsonObject()); + return new BaseComponent(parent, JsonParser.parseString(raw).getAsJsonObject()); } catch (JsonParseException | IllegalStateException ignored) { } return new BaseComponent(raw); diff --git a/src/main/java/de/bixilon/minosoft/data/text/TextComponent.java b/src/main/java/de/bixilon/minosoft/data/text/TextComponent.java index 286e1df80..b56235c73 100644 --- a/src/main/java/de/bixilon/minosoft/data/text/TextComponent.java +++ b/src/main/java/de/bixilon/minosoft/data/text/TextComponent.java @@ -13,6 +13,7 @@ package de.bixilon.minosoft.data.text; +import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition; import de.bixilon.minosoft.util.hash.BetterHashSet; import javafx.animation.Animation; import javafx.animation.KeyFrame; @@ -140,11 +141,11 @@ public class TextComponent extends ChatComponent { StringBuilder output = new StringBuilder(); Integer colorChar = ChatColors.getColorId(color); if (colorChar != null) { - output.append('§').append(Integer.toHexString(colorChar)); + output.append(ProtocolDefinition.TEXT_COMPONENT_SPECIAL_PREFIX_CHAR).append(Integer.toHexString(colorChar)); } - formatting.forEach((chatFormattingCode -> output.append('§').append(chatFormattingCode.getChar()))); + formatting.forEach((chatFormattingCode -> output.append(ProtocolDefinition.TEXT_COMPONENT_SPECIAL_PREFIX_CHAR).append(chatFormattingCode.getChar()))); output.append(text); - output.append('§').append(PostChatFormattingCodes.RESET.getChar()); + output.append(ProtocolDefinition.TEXT_COMPONENT_SPECIAL_PREFIX_CHAR).append(PostChatFormattingCodes.RESET.getChar()); return output.toString(); } diff --git a/src/main/java/de/bixilon/minosoft/data/text/TranslatableComponent.java b/src/main/java/de/bixilon/minosoft/data/text/TranslatableComponent.java index 1ee34f56e..ceb0e3893 100644 --- a/src/main/java/de/bixilon/minosoft/data/text/TranslatableComponent.java +++ b/src/main/java/de/bixilon/minosoft/data/text/TranslatableComponent.java @@ -15,54 +15,50 @@ package de.bixilon.minosoft.data.text; import com.google.gson.JsonArray; import de.bixilon.minosoft.data.locale.minecraft.MinecraftLocaleManager; +import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition; import javafx.collections.ObservableList; import javafx.scene.Node; +import javax.annotation.Nullable; import java.util.ArrayList; public class TranslatableComponent extends ChatComponent { private final ArrayList data = new ArrayList<>(); private final String key; + private final TextComponent parent; public TranslatableComponent(String key, JsonArray data) { + this(null, key, data); + } + + public TranslatableComponent(@Nullable TextComponent parent, String key, JsonArray data) { + this.parent = parent; this.key = key; if (data == null) { return; } data.forEach((jsonElement -> { if (jsonElement.isJsonPrimitive()) { - this.data.add(ChatComponent.fromString(jsonElement.getAsString())); + this.data.add(ChatComponent.fromString(parent, jsonElement.getAsString())); } else { - this.data.add(new BaseComponent(jsonElement.getAsJsonObject())); + this.data.add(new BaseComponent(parent, jsonElement.getAsJsonObject())); } })); } @Override public String getANSIColoredMessage() { - Object[] data = new String[this.data.size()]; - for (int i = 0; i < this.data.size(); i++) { - data[i] = this.data.get(i).getANSIColoredMessage(); - } - return MinecraftLocaleManager.translate(key, data); + return getList("getANSIColoredMessage"); } @Override public String getLegacyText() { - Object[] data = new String[this.data.size()]; - for (int i = 0; i < this.data.size(); i++) { - data[i] = this.data.get(i).getLegacyText(); - } - return MinecraftLocaleManager.translate(key, data); + return getList("getLegacyText"); } @Override public String getMessage() { - Object[] data = new String[this.data.size()]; - for (int i = 0; i < this.data.size(); i++) { - data[i] = this.data.get(i).getMessage(); - } - return MinecraftLocaleManager.translate(key, data); + return getList("getMessage"); } @Override @@ -72,4 +68,46 @@ public class TranslatableComponent extends ChatComponent { // This is just a dirty workaround to enable formatting and coloring. Still need to do hover, click, ... stuff return new BaseComponent(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 (parent != null) { + StringBuilder builder = new StringBuilder(); + if (methodName.equals("getANSIColoredMessage")) { + builder.append(ChatColors.getANSIColorByRGBColor(parent.getColor())); + } else if (methodName.equals("getLegacyText")) { + builder.append(ChatColors.getColorChar(parent.getColor())); + + } + for (ChatFormattingCode code : 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(MinecraftLocaleManager.translate(key, data)); + for (ChatFormattingCode code : 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(); + } + return MinecraftLocaleManager.translate(key, data); + } catch (Exception e) { + throw new RuntimeException(e); + } + } } diff --git a/src/main/java/de/bixilon/minosoft/protocol/protocol/PacketHandler.java b/src/main/java/de/bixilon/minosoft/protocol/protocol/PacketHandler.java index 6a28e99ea..69504defa 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/protocol/PacketHandler.java +++ b/src/main/java/de/bixilon/minosoft/protocol/protocol/PacketHandler.java @@ -276,15 +276,15 @@ public class PacketHandler { } Log.game(switch (pkg.getReason()) { - case STOP_RAINING -> "Received weather packet: Starting rain..."; - case START_RAINING -> "Received weather packet: Stopping rain..."; + case START_RAINING -> "Received weather packet: Starting rain..."; + case STOP_RAINING -> "Received weather packet: Stopping rain..."; case CHANGE_GAMEMODE -> String.format("Received game mode change: Now in %s", GameModes.byId(pkg.getValue().intValue())); default -> ""; }); switch (pkg.getReason()) { - case STOP_RAINING -> connection.getPlayer().getWorld().setRaining(true); - case START_RAINING -> connection.getPlayer().getWorld().setRaining(false); + case STOP_RAINING -> connection.getPlayer().getWorld().setRaining(false); + case START_RAINING -> connection.getPlayer().getWorld().setRaining(true); case CHANGE_GAMEMODE -> connection.getPlayer().setGameMode(GameModes.byId(pkg.getValue().intValue())); } } diff --git a/src/main/java/de/bixilon/minosoft/protocol/protocol/ProtocolDefinition.java b/src/main/java/de/bixilon/minosoft/protocol/protocol/ProtocolDefinition.java index c31beea0d..b85278517 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/protocol/ProtocolDefinition.java +++ b/src/main/java/de/bixilon/minosoft/protocol/protocol/ProtocolDefinition.java @@ -36,6 +36,7 @@ public final class ProtocolDefinition { public static final int LAN_SERVER_MAXIMUM_SERVERS = 100; // maximum number of lan servers, set because otherwise dos attacks would be easy public static final String DEFAULT_MOD = "minecraft"; + public static final char TEXT_COMPONENT_SPECIAL_PREFIX_CHAR = '§'; public static final int DEFAULT_BUFFER_SIZE = 4096;