diff --git a/ReadMe.md b/ReadMe.md index 0c9f01bfa..08e39854c 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -2,8 +2,8 @@ # Minosoft Minosoft is an open source minecraft client, written from scratch in java. It aims to bring more functionality and stability. -[![pipeline status](https://gitlab.bixilon.de/bixilon/minosoft/badges/master/pipeline.svg)](https://gitlab.bixilon.de/bixilon/minosoft/-/commits/master) - +[![pipeline status](https://gitlab.bixilon.de/bixilon/minosoft/badges/master/pipeline.svg)](https://gitlab.bixilon.de/bixilon/minosoft/-/commits/master) +[![](https://jitpack.io/v/de.bixilon.gitlab.bixilon/minosoft.svg)](https://jitpack.io/#de.bixilon.gitlab.bixilon/minosoft) ## Feature overview - Rendering (WIP) diff --git a/src/main/java/de/bixilon/minosoft/config/StaticConfiguration.java b/src/main/java/de/bixilon/minosoft/config/StaticConfiguration.java index c23cb8841..7503d4718 100644 --- a/src/main/java/de/bixilon/minosoft/config/StaticConfiguration.java +++ b/src/main/java/de/bixilon/minosoft/config/StaticConfiguration.java @@ -24,7 +24,7 @@ public class StaticConfiguration { public static boolean SKIP_MOJANG_AUTHENTICATION = false; // disables all connections to mojang public static boolean COLORED_LOG = true; // the log should be colored with ANSI (does not affect base components) public static boolean LOG_RELATIVE_TIME = false; // prefix all log messages with the relative start time in milliseconds instead of the formatted time - public static boolean VERBOSE_ENTITY_META_DATA_LOGGING = false; // if true, the entity meta data is getting serial + public static boolean VERBOSE_ENTITY_META_DATA_LOGGING = false; // if true, the entity meta data is getting serialized public static String HOME_DIRECTORY; static { 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 8000b02a9..43bab8e5f 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; @@ -260,7 +261,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 993a6949a..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,8 @@ 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; @@ -23,9 +25,8 @@ import javax.annotation.Nullable; import java.text.CharacterIterator; import java.text.StringCharacterIterator; import java.util.ArrayList; -import java.util.HashSet; -public class BaseComponent implements ChatComponent { +public class BaseComponent extends ChatComponent { private final ArrayList parts = new ArrayList<>(); public BaseComponent() { @@ -35,12 +36,12 @@ public class BaseComponent implements ChatComponent { // legacy String StringBuilder currentText = new StringBuilder(); RGBColor color = null; - HashSet formattingCodes = new HashSet<>(); + BetterHashSet formattingCodes = new BetterHashSet<>(); StringCharacterIterator iterator = new StringCharacterIterator(text); 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; } @@ -55,19 +56,19 @@ public class BaseComponent implements ChatComponent { currentText = new StringBuilder(); } color = nextColor; - formattingCodes = new HashSet<>(); + formattingCodes = new BetterHashSet<>(); continue; } - ChatFormattingCodes nextFormattingCode = ChatFormattingCodes.getChatFormattingCodeByChar(nextFormattingChar); + ChatFormattingCode nextFormattingCode = ChatFormattingCodes.getChatFormattingCodeByChar(nextFormattingChar); if (nextFormattingCode != null) { if (currentText.length() > 0) { parts.add(new TextComponent(currentText.toString(), color, formattingCodes)); currentText = new StringBuilder(); color = null; - formattingCodes = new HashSet<>(); + formattingCodes = new BetterHashSet<>(); } formattingCodes.add(nextFormattingCode); - if (nextFormattingCode == ChatFormattingCodes.RESET) { + if (nextFormattingCode == PostChatFormattingCodes.RESET) { // special rule here if (currentText.length() > 0) { // color change, add text part @@ -75,7 +76,7 @@ public class BaseComponent implements ChatComponent { currentText = new StringBuilder(); } color = null; - formattingCodes = new HashSet<>(); + formattingCodes = new BetterHashSet<>(); } } } @@ -92,7 +93,7 @@ public class BaseComponent implements 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; @@ -112,47 +113,26 @@ public class BaseComponent implements ChatComponent { color = ChatColors.getColorByName(colorString); } } - HashSet formattingCodes; + BetterHashSet formattingCodes; if (parent != null && parent.getFormatting() != null) { - formattingCodes = (HashSet) parent.getFormatting().clone(); + formattingCodes = (BetterHashSet) parent.getFormatting().clone(); } else { - formattingCodes = new HashSet<>(); + formattingCodes = new BetterHashSet<>(); } if (json.has("bold")) { - if (json.get("bold").getAsBoolean()) { - formattingCodes.add(ChatFormattingCodes.BOLD); - } else { - formattingCodes.remove(ChatFormattingCodes.BOLD); - } + formattingCodes.addOrRemove(PreChatFormattingCodes.BOLD, json.get("bold").getAsBoolean()); } if (json.has("italic")) { - if (json.get("italic").getAsBoolean()) { - formattingCodes.add(ChatFormattingCodes.ITALIC); - } else { - formattingCodes.remove(ChatFormattingCodes.ITALIC); - } + formattingCodes.addOrRemove(PreChatFormattingCodes.ITALIC, json.get("italic").getAsBoolean()); } if (json.has("underlined")) { - if (json.get("underlined").getAsBoolean()) { - formattingCodes.add(ChatFormattingCodes.UNDERLINED); - } else { - formattingCodes.remove(ChatFormattingCodes.UNDERLINED); - - } + formattingCodes.addOrRemove(PreChatFormattingCodes.UNDERLINED, json.get("underlined").getAsBoolean()); } if (json.has("strikethrough")) { - if (json.get("strikethrough").getAsBoolean()) { - formattingCodes.add(ChatFormattingCodes.STRIKETHROUGH); - } else { - formattingCodes.remove(ChatFormattingCodes.STRIKETHROUGH); - } + formattingCodes.addOrRemove(PreChatFormattingCodes.STRIKETHROUGH, json.get("strikethrough").getAsBoolean()); } if (json.has("obfuscated")) { - if (json.get("obfuscated").getAsBoolean()) { - formattingCodes.add(ChatFormattingCodes.OBFUSCATED); - } else { - formattingCodes.remove(ChatFormattingCodes.OBFUSCATED); - } + formattingCodes.addOrRemove(PreChatFormattingCodes.OBFUSCATED, json.get("obfuscated").getAsBoolean()); } thisTextComponent = new TextComponent(text, color, formattingCodes); } @@ -161,20 +141,20 @@ public class BaseComponent implements 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/ChatCode.java b/src/main/java/de/bixilon/minosoft/data/text/ChatCode.java new file mode 100644 index 000000000..1c7695d78 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/data/text/ChatCode.java @@ -0,0 +1,17 @@ +/* + * 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; + +public interface ChatCode { +} 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 8482539c0..7d6a5eb8f 100644 --- a/src/main/java/de/bixilon/minosoft/data/text/ChatColors.java +++ b/src/main/java/de/bixilon/minosoft/data/text/ChatColors.java @@ -54,17 +54,17 @@ public final class ChatColors { return getColorById(Character.digit(c, 16)); } - public static ChatFormattingCode getFormattingById(int id) { + public static ChatCode getFormattingById(int id) { if (id <= 15) { return getColorById(id); } return switch (id) { - case 16 -> ChatFormattingCodes.OBFUSCATED; - case 17 -> ChatFormattingCodes.BOLD; - case 18 -> ChatFormattingCodes.STRIKETHROUGH; - case 19 -> ChatFormattingCodes.UNDERLINED; - case 20 -> ChatFormattingCodes.ITALIC; - case 21 -> ChatFormattingCodes.RESET; + case 16 -> PreChatFormattingCodes.OBFUSCATED; + case 17 -> PreChatFormattingCodes.BOLD; + case 18 -> PreChatFormattingCodes.STRIKETHROUGH; + case 19 -> PreChatFormattingCodes.UNDERLINED; + case 20 -> PreChatFormattingCodes.ITALIC; + case 21 -> PostChatFormattingCodes.RESET; default -> null; }; } @@ -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 1267a67de..4b37240c7 100644 --- a/src/main/java/de/bixilon/minosoft/data/text/ChatComponent.java +++ b/src/main/java/de/bixilon/minosoft/data/text/ChatComponent.java @@ -15,16 +15,23 @@ package de.bixilon.minosoft.data.text; import com.google.gson.JsonParseException; import com.google.gson.JsonParser; +import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.scene.Node; -public interface ChatComponent { - static ChatComponent fromString(String raw) { +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); @@ -33,20 +40,27 @@ public interface ChatComponent { /** * @return Returns the message formatted with ANSI Formatting codes */ - String getANSIColoredMessage(); + public abstract String getANSIColoredMessage(); /** * @return Returns the message formatted with minecraft formatting codes (§) */ - String getLegacyText(); + public abstract String getLegacyText(); /** * @return Returns the unformatted message */ - String getMessage(); + public abstract String getMessage(); /** * @return Returns the a list of Nodes, drawable in JavaFX (TextFlow) */ - ObservableList getJavaFXText(ObservableList nodes); + public abstract ObservableList getJavaFXText(ObservableList nodes); + + /** + * @return Returns the a list of Nodes, drawable in JavaFX (TextFlow) + */ + public ObservableList getJavaFXText() { + return getJavaFXText(FXCollections.observableArrayList()); + } } diff --git a/src/main/java/de/bixilon/minosoft/data/text/ChatFormattingCode.java b/src/main/java/de/bixilon/minosoft/data/text/ChatFormattingCode.java index d0910cd4d..39d2a8e19 100644 --- a/src/main/java/de/bixilon/minosoft/data/text/ChatFormattingCode.java +++ b/src/main/java/de/bixilon/minosoft/data/text/ChatFormattingCode.java @@ -13,5 +13,11 @@ package de.bixilon.minosoft.data.text; -public interface ChatFormattingCode { +public interface ChatFormattingCode extends ChatCode { + char getChar(); + + @Override + String toString(); + + String getANSI(); } diff --git a/src/main/java/de/bixilon/minosoft/data/text/ChatFormattingCodes.java b/src/main/java/de/bixilon/minosoft/data/text/ChatFormattingCodes.java index 528ef5268..556bb2e34 100644 --- a/src/main/java/de/bixilon/minosoft/data/text/ChatFormattingCodes.java +++ b/src/main/java/de/bixilon/minosoft/data/text/ChatFormattingCodes.java @@ -17,60 +17,17 @@ import com.google.common.collect.HashBiMap; import java.util.Arrays; -public enum ChatFormattingCodes implements ChatFormattingCode { - OBFUSCATED('k', "\u001b[5m"), - BOLD('l', "\u001b[1m"), - STRIKETHROUGH('m', "\u001b[9m"), - UNDERLINED('n', "\u001b[4m"), - ITALIC('o', "\u001b[3m"), - RESET('r', "\u001b[0m", ChatFormattingCodePosition.POST); +public final class ChatFormattingCodes { - private final static HashBiMap formattingCodes = HashBiMap.create(); + private static final HashBiMap formattingCodes = HashBiMap.create(); static { - Arrays.stream(values()).forEach(chatFormattingCodes -> formattingCodes.put(chatFormattingCodes.getChar(), chatFormattingCodes)); + Arrays.stream(PreChatFormattingCodes.values()).forEach(chatFormattingCodes -> formattingCodes.put(chatFormattingCodes.getChar(), chatFormattingCodes)); + Arrays.stream(PostChatFormattingCodes.values()).forEach(chatFormattingCodes -> formattingCodes.put(chatFormattingCodes.getChar(), chatFormattingCodes)); + } - final char c; - final String ansi; - final ChatFormattingCodePosition position; - - ChatFormattingCodes(char c, String ansi) { - this.c = c; - this.ansi = ansi; - this.position = ChatFormattingCodePosition.PRE; - } - - ChatFormattingCodes(char c, String ansi, ChatFormattingCodePosition position) { - this.c = c; - this.ansi = ansi; - this.position = position; - } - - public static ChatFormattingCodes getChatFormattingCodeByChar(char c) { - return formattingCodes.get(c); - } - - public char getChar() { - return c; - } - - public ChatFormattingCodePosition getPosition() { - return position; - } - - @Override - public String toString() { - return getANSI(); - } - - public String getANSI() { - return ansi; - } - - public enum ChatFormattingCodePosition { - PRE, - POST + public static ChatFormattingCode getChatFormattingCodeByChar(char nextFormattingChar) { + return formattingCodes.get(nextFormattingChar); } } - diff --git a/src/main/java/de/bixilon/minosoft/data/text/PostChatFormattingCodes.java b/src/main/java/de/bixilon/minosoft/data/text/PostChatFormattingCodes.java new file mode 100644 index 000000000..a3452ab77 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/data/text/PostChatFormattingCodes.java @@ -0,0 +1,40 @@ +/* + * 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; + +public enum PostChatFormattingCodes implements ChatFormattingCode { + RESET('r', "\u001b[0m"); + + final char c; + final String ansi; + + PostChatFormattingCodes(char c, String ansi) { + this.c = c; + this.ansi = ansi; + } + + public char getChar() { + return c; + } + + @Override + public String toString() { + return getANSI(); + } + + public String getANSI() { + return ansi; + } +} + diff --git a/src/main/java/de/bixilon/minosoft/data/text/PreChatFormattingCodes.java b/src/main/java/de/bixilon/minosoft/data/text/PreChatFormattingCodes.java new file mode 100644 index 000000000..1860f33bb --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/data/text/PreChatFormattingCodes.java @@ -0,0 +1,46 @@ +/* + * 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; + +public enum PreChatFormattingCodes implements ChatFormattingCode { + OBFUSCATED('k', "\u001b[5m"), + BOLD('l', "\u001b[1m"), + STRIKETHROUGH('m', "\u001b[9m"), + UNDERLINED('n', "\u001b[4m"), + ITALIC('o', "\u001b[3m"); + + + final char c; + final String ansi; + + PreChatFormattingCodes(char c, String ansi) { + this.c = c; + this.ansi = ansi; + } + + public char getChar() { + return c; + } + + + @Override + public String toString() { + return getANSI(); + } + + public String getANSI() { + return ansi; + } +} + diff --git a/src/main/java/de/bixilon/minosoft/data/text/RGBColor.java b/src/main/java/de/bixilon/minosoft/data/text/RGBColor.java index 98252b985..e1e58412e 100644 --- a/src/main/java/de/bixilon/minosoft/data/text/RGBColor.java +++ b/src/main/java/de/bixilon/minosoft/data/text/RGBColor.java @@ -13,7 +13,7 @@ package de.bixilon.minosoft.data.text; -public final class RGBColor implements ChatFormattingCode { +public final class RGBColor implements ChatCode { private final int color; public RGBColor(int color) { 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 781ee9b62..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,8 @@ 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; import javafx.animation.Timeline; @@ -22,15 +24,14 @@ import javafx.scene.paint.Color; import javafx.scene.text.Text; import javafx.util.Duration; -import java.util.HashSet; import java.util.Objects; -public class TextComponent implements ChatComponent { +public class TextComponent extends ChatComponent { private final String text; private RGBColor color; - private HashSet formatting; + private BetterHashSet formatting; - public TextComponent(String text, RGBColor color, HashSet formatting) { + public TextComponent(String text, RGBColor color, BetterHashSet formatting) { this.text = text; this.color = color; this.formatting = formatting; @@ -46,56 +47,32 @@ public class TextComponent implements ChatComponent { } public TextComponent setObfuscated(boolean obfuscated) { - if (obfuscated) { - formatting.add(ChatFormattingCodes.OBFUSCATED); - } else { - formatting.remove(ChatFormattingCodes.OBFUSCATED); - } + formatting.addOrRemove(PreChatFormattingCodes.OBFUSCATED, obfuscated); return this; } public TextComponent setBold(boolean bold) { - if (bold) { - formatting.add(ChatFormattingCodes.BOLD); - } else { - formatting.remove(ChatFormattingCodes.BOLD); - } + formatting.addOrRemove(PreChatFormattingCodes.BOLD, bold); return this; } public TextComponent setStrikethrough(boolean strikethrough) { - if (strikethrough) { - formatting.add(ChatFormattingCodes.STRIKETHROUGH); - } else { - formatting.remove(ChatFormattingCodes.STRIKETHROUGH); - } + formatting.addOrRemove(PreChatFormattingCodes.STRIKETHROUGH, strikethrough); return this; } public TextComponent setUnderlined(boolean underlined) { - if (underlined) { - formatting.add(ChatFormattingCodes.UNDERLINED); - } else { - formatting.remove(ChatFormattingCodes.UNDERLINED); - } + formatting.addOrRemove(PreChatFormattingCodes.UNDERLINED, underlined); return this; } public TextComponent setItalic(boolean italic) { - if (italic) { - formatting.add(ChatFormattingCodes.ITALIC); - } else { - formatting.remove(ChatFormattingCodes.ITALIC); - } + formatting.addOrRemove(PreChatFormattingCodes.ITALIC, italic); return this; } public TextComponent setReset(boolean reset) { - if (reset) { - formatting.add(ChatFormattingCodes.RESET); - } else { - formatting.remove(ChatFormattingCodes.RESET); - } + formatting.addOrRemove(PostChatFormattingCodes.RESET, reset); return this; } @@ -108,11 +85,11 @@ public class TextComponent implements ChatComponent { return this; } - public HashSet getFormatting() { + public BetterHashSet getFormatting() { return formatting; } - public TextComponent setFormatting(HashSet formatting) { + public TextComponent setFormatting(BetterHashSet formatting) { this.formatting = formatting; return this; } @@ -142,20 +119,20 @@ public class TextComponent implements ChatComponent { } if (formatting != null) { formatting.forEach((chatFormattingCodes -> { - if (chatFormattingCodes.getPosition() == ChatFormattingCodes.ChatFormattingCodePosition.PRE) { - builder.append(chatFormattingCodes.getANSI()); + if (chatFormattingCodes instanceof PreChatFormattingCodes code) { + builder.append(code.getANSI()); } })); } builder.append(text); if (formatting != null) { formatting.forEach((chatFormattingCodes -> { - if (chatFormattingCodes.getPosition() == ChatFormattingCodes.ChatFormattingCodePosition.POST) { - builder.append(chatFormattingCodes.getANSI()); + if (chatFormattingCodes instanceof PostChatFormattingCodes code) { + builder.append(code.getANSI()); } })); } - builder.append(ChatFormattingCodes.RESET); + builder.append(PostChatFormattingCodes.RESET); return builder.toString(); } @@ -164,11 +141,11 @@ public class TextComponent implements 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(ChatFormattingCodes.RESET.getChar()); + output.append(ProtocolDefinition.TEXT_COMPONENT_SPECIAL_PREFIX_CHAR).append(PostChatFormattingCodes.RESET.getChar()); return output.toString(); } @@ -184,16 +161,18 @@ public class TextComponent implements ChatComponent { text.setFill(Color.web(color.toString())); } formatting.forEach((chatFormattingCode -> { - switch (chatFormattingCode) { - case OBFUSCATED -> { - Timeline flasher = new Timeline(new KeyFrame(Duration.seconds(1), e -> text.setVisible(false)), new KeyFrame(Duration.seconds(2), e -> text.setVisible(true))); - flasher.setCycleCount(Animation.INDEFINITE); - flasher.play(); + if (chatFormattingCode instanceof PreChatFormattingCodes code) { + switch (code) { + case OBFUSCATED -> { + Timeline flasher = new Timeline(new KeyFrame(Duration.seconds(1), e -> text.setVisible(false)), new KeyFrame(Duration.seconds(2), e -> text.setVisible(true))); + flasher.setCycleCount(Animation.INDEFINITE); + flasher.play(); + } + 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;"); } - 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); 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 7ecff7738..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 implements ChatComponent { +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 implements 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/gui/main/ServerListCell.java b/src/main/java/de/bixilon/minosoft/gui/main/ServerListCell.java index c0b30efc5..f49b2de7e 100644 --- a/src/main/java/de/bixilon/minosoft/gui/main/ServerListCell.java +++ b/src/main/java/de/bixilon/minosoft/gui/main/ServerListCell.java @@ -28,7 +28,6 @@ import de.bixilon.minosoft.protocol.ping.ForgeModInfo; import de.bixilon.minosoft.protocol.ping.ServerListPing; import de.bixilon.minosoft.util.DNSUtil; import javafx.application.Platform; -import javafx.collections.FXCollections; import javafx.fxml.FXMLLoader; import javafx.fxml.Initializable; import javafx.geometry.Insets; @@ -178,7 +177,7 @@ public class ServerListCell extends ListCell implements Initializable { } serverBrand.setText(ping.getServerModInfo().getBrand()); serverBrand.setTooltip(new Tooltip(ping.getServerModInfo().getInfo())); - motd.getChildren().addAll(ping.getMotd().getJavaFXText(FXCollections.observableArrayList())); + motd.getChildren().addAll(ping.getMotd().getJavaFXText()); if (ping.getFavicon() != null) { icon.setImage(GUITools.getImage(ping.getFavicon())); if (!Arrays.equals(ping.getFavicon(), server.getFavicon())) { @@ -416,7 +415,7 @@ public class ServerListCell extends ListCell implements Initializable { Label serverBrandLabel = new Label(lastPing.getServerBrand()); Label playersOnlineMaxLabel = new Label(LocaleManager.translate(Strings.SERVER_INFO_SLOTS_PLAYERS_ONLINE, lastPing.getPlayerOnline(), lastPing.getMaxPlayers())); TextFlow motdLabel = new TextFlow(); - motdLabel.getChildren().addAll(lastPing.getMotd().getJavaFXText(FXCollections.observableArrayList())); + motdLabel.getChildren().addAll(lastPing.getMotd().getJavaFXText()); Label moddedBrandLabel = new Label(lastPing.getServerModInfo().getBrand()); grid.add(new Label(LocaleManager.translate(Strings.SERVER_INFO_REAL_SERVER_ADDRESS) + ":"), 0, ++column); diff --git a/src/main/java/de/bixilon/minosoft/logging/Log.java b/src/main/java/de/bixilon/minosoft/logging/Log.java index 780de9bf4..b46ce14b2 100644 --- a/src/main/java/de/bixilon/minosoft/logging/Log.java +++ b/src/main/java/de/bixilon/minosoft/logging/Log.java @@ -15,7 +15,7 @@ package de.bixilon.minosoft.logging; import de.bixilon.minosoft.config.StaticConfiguration; import de.bixilon.minosoft.data.text.ChatColors; -import de.bixilon.minosoft.data.text.ChatFormattingCodes; +import de.bixilon.minosoft.data.text.PostChatFormattingCodes; import de.bixilon.minosoft.data.text.RGBColor; import java.text.SimpleDateFormat; @@ -45,18 +45,24 @@ public class Log { }, "Log").start(); } - public static void log(LogLevels level, String message, RGBColor color) { - log(level, "", message, color); + public static void log(LogLevels level, RGBColor color, Object message, Object... format) { + log(level, "", color, message, format); } - public static void log(LogLevels level, String prefix, String message, RGBColor color) { - if (message.isBlank()) { - return; - } + public static void log(LogLevels level, String prefix, RGBColor color, Object message, Object... format) { if (level.ordinal() > Log.level.ordinal()) { // log level too low return; } + if (message == null) { + return; + } + if (message instanceof String string) { + if (string.isBlank()) { + return; + } + message = String.format(string, format); + } StringBuilder builder = new StringBuilder(); builder.append("["); if (StaticConfiguration.LOG_RELATIVE_TIME) { @@ -73,11 +79,11 @@ public class Log { if (color != null && StaticConfiguration.COLORED_LOG) { builder.append(ChatColors.getANSIColorByRGBColor(color)); builder.append(message); - builder.append(ChatFormattingCodes.RESET.getANSI()); + builder.append(PostChatFormattingCodes.RESET.getANSI()); } else { builder.append(message); } - builder.append(ChatFormattingCodes.RESET.getANSI()); + builder.append(PostChatFormattingCodes.RESET.getANSI()); queue.add(builder.toString()); } @@ -86,8 +92,8 @@ public class Log { * * @param message Raw message to log */ - public static void game(String message) { - log(LogLevels.GAME, message, ChatColors.GREEN); + public static void game(Object message, Object... format) { + log(LogLevels.GAME, ChatColors.GREEN, message, format); } /** @@ -95,8 +101,8 @@ public class Log { * * @param message Raw message to log */ - public static void fatal(String message) { - log(LogLevels.FATAL, message, ChatColors.DARK_RED); + public static void fatal(Object message, Object... format) { + log(LogLevels.FATAL, ChatColors.DARK_RED, message, format); } /** @@ -104,8 +110,8 @@ public class Log { * * @param message Raw message to log */ - public static void warn(String message) { - log(LogLevels.WARNING, message, ChatColors.RED); + public static void warn(Object message, Object... format) { + log(LogLevels.WARNING, ChatColors.RED, message, format); } /** @@ -113,8 +119,8 @@ public class Log { * * @param message Raw message to log */ - public static void debug(String message) { - log(LogLevels.DEBUG, message, ChatColors.GRAY); + public static void debug(Object message, Object... format) { + log(LogLevels.DEBUG, ChatColors.GRAY, message, format); } /** @@ -122,8 +128,8 @@ public class Log { * * @param message Raw message to log */ - public static void verbose(String message) { - log(LogLevels.VERBOSE, message, ChatColors.YELLOW); + public static void verbose(Object message, Object... format) { + log(LogLevels.VERBOSE, ChatColors.YELLOW, message, format); } /** @@ -131,8 +137,8 @@ public class Log { * * @param message Raw message to log */ - public static void protocol(String message) { - log(LogLevels.PROTOCOL, message, ChatColors.BLUE); + public static void protocol(Object message, Object... format) { + log(LogLevels.PROTOCOL, ChatColors.BLUE, message, format); } /** @@ -140,10 +146,20 @@ public class Log { * * @param message Raw message to log */ - public static void mojang(String message) { - log(LogLevels.MOJANG, message, ChatColors.AQUA); + public static void mojang(Object message, Object... format) { + log(LogLevels.MOJANG, ChatColors.AQUA, message, format); } + /** + * Logs all general infos, that are more or less important to the user (connecting to server, ...) + * + * @param message Raw message to log + */ + public static void info(Object message, Object... format) { + log(LogLevels.INFO, ChatColors.WHITE, message, format); + } + + public static LogLevels getLevel() { return level; } @@ -156,15 +172,6 @@ public class Log { Log.level = level; } - /** - * Logs all general infos, that are more or less important to the user (connecting to server, ...) - * - * @param message Raw message to log - */ - public static void info(String message) { - log(LogLevels.INFO, message, ChatColors.WHITE); - } - public static boolean printException(Exception exception, LogLevels minimumLogLevel) { // ToDo: log to file, print also exceptions that are not printed with this method if (Log.getLevel().ordinal() >= minimumLogLevel.ordinal()) { diff --git a/src/main/java/de/bixilon/minosoft/modding/Logger.java b/src/main/java/de/bixilon/minosoft/modding/Logger.java index d41729e30..3288a2f2f 100644 --- a/src/main/java/de/bixilon/minosoft/modding/Logger.java +++ b/src/main/java/de/bixilon/minosoft/modding/Logger.java @@ -25,31 +25,31 @@ public class Logger { this.modName = modName; } - public void log(LogLevels level, String message, RGBColor color) { - Log.log(level, String.format("[%s] ", modName), message, color); + public void log(LogLevels level, RGBColor color, Object message, Object... format) { + Log.log(level, String.format("[%s] ", modName), color, message, format); } - public void game(String message) { - log(LogLevels.GAME, message, ChatColors.GREEN); + public void game(Object message, Object... format) { + log(LogLevels.GAME, ChatColors.GREEN, message, format); } - public void fatal(String message) { - log(LogLevels.FATAL, message, ChatColors.DARK_RED); + public void fatal(Object message, Object... format) { + log(LogLevels.FATAL, ChatColors.DARK_RED, message, format); } - public void info(String message) { - log(LogLevels.INFO, message, ChatColors.WHITE); + public void info(Object message, Object... format) { + log(LogLevels.INFO, ChatColors.WHITE, message, format); } - public void warn(String message) { - log(LogLevels.WARNING, message, ChatColors.RED); + public void warn(Object message, Object... format) { + log(LogLevels.WARNING, ChatColors.RED, message, format); } - public void debug(String message) { - log(LogLevels.DEBUG, message, ChatColors.GRAY); + public void debug(Object message, Object... format) { + log(LogLevels.DEBUG, ChatColors.GRAY, message, format); } - public void verbose(String message) { - log(LogLevels.VERBOSE, message, ChatColors.YELLOW); + public void verbose(Object message, Object... format) { + log(LogLevels.VERBOSE, ChatColors.YELLOW, message, format); } } diff --git a/src/main/java/de/bixilon/minosoft/modding/loading/ModLoader.java b/src/main/java/de/bixilon/minosoft/modding/loading/ModLoader.java index eb12dd05f..67ee51c6e 100644 --- a/src/main/java/de/bixilon/minosoft/modding/loading/ModLoader.java +++ b/src/main/java/de/bixilon/minosoft/modding/loading/ModLoader.java @@ -23,7 +23,6 @@ import org.xeustechnologies.jcl.JarClassLoader; import org.xeustechnologies.jcl.JclObjectFactory; import java.io.File; -import java.io.IOException; import java.util.LinkedList; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; @@ -87,7 +86,12 @@ public class ModLoader { progress.countDown(); return; } - if (!instance.start(phase)) { + try { + if (!instance.start(phase)) { + throw new ModLoadingException(String.format("Could not load nod %s", instance.getInfo())); + } + } catch (Throwable e) { + e.printStackTrace(); Log.warn(String.format("An error occurred while loading %s", instance.getInfo())); instance.setEnabled(false); } @@ -127,7 +131,7 @@ public class ModLoader { instance.setInfo(modInfo); Log.verbose(String.format("[MOD] Mod file loaded and added to classpath (%s)", modInfo)); zipFile.close(); - } catch (IOException | ModLoadingException | NullPointerException e) { + } catch (Throwable e) { instance = null; e.printStackTrace(); Log.warn(String.format("Could not load mod: %s", file.getAbsolutePath())); diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketTeams.java b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketTeams.java index 9858d3bc4..5098ba183 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketTeams.java +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketTeams.java @@ -13,9 +13,9 @@ package de.bixilon.minosoft.protocol.packets.clientbound.play; +import de.bixilon.minosoft.data.text.ChatCode; import de.bixilon.minosoft.data.text.ChatColors; import de.bixilon.minosoft.data.text.ChatComponent; -import de.bixilon.minosoft.data.text.ChatFormattingCode; import de.bixilon.minosoft.logging.Log; import de.bixilon.minosoft.protocol.packets.ClientboundPacket; import de.bixilon.minosoft.protocol.protocol.InByteBuffer; @@ -32,7 +32,7 @@ public class PacketTeams implements ClientboundPacket { boolean seeFriendlyInvisibles; TeamCollisionRules collisionRule = TeamCollisionRules.NEVER; TeamNameTagVisibilities nameTagVisibility = TeamNameTagVisibilities.ALWAYS; - ChatFormattingCode formattingCode; + ChatCode formattingCode; String[] playerNames; @Override @@ -133,7 +133,7 @@ public class PacketTeams implements ClientboundPacket { return seeFriendlyInvisibles; } - public ChatFormattingCode getFormattingCode() { + public ChatCode getFormattingCode() { return formattingCode; } 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 b065f95bd..cfc9e19c5 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/protocol/PacketHandler.java +++ b/src/main/java/de/bixilon/minosoft/protocol/protocol/PacketHandler.java @@ -278,15 +278,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..122e23ac8 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/protocol/ProtocolDefinition.java +++ b/src/main/java/de/bixilon/minosoft/protocol/protocol/ProtocolDefinition.java @@ -14,7 +14,6 @@ package de.bixilon.minosoft.protocol.protocol; import java.net.InetAddress; -import java.net.UnknownHostException; public final class ProtocolDefinition { public static final int STRING_MAX_LEN = 32767; @@ -36,15 +35,19 @@ 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; static { + // java does (why ever) not allow to directly assign a null + InetAddress temp; try { - LAN_SERVER_BROADCAST_ADDRESS = InetAddress.getByName("224.0.2.60"); - } catch (UnknownHostException e) { + temp = InetAddress.getByName("224.0.2.60"); + } catch (Exception e) { e.printStackTrace(); - throw new RuntimeException(e); + temp = null; } + LAN_SERVER_BROADCAST_ADDRESS = temp; } } diff --git a/src/main/java/de/bixilon/minosoft/util/hash/BetterHashSet.java b/src/main/java/de/bixilon/minosoft/util/hash/BetterHashSet.java new file mode 100644 index 000000000..044d92402 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/util/hash/BetterHashSet.java @@ -0,0 +1,36 @@ +/* + * 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.util.hash; + +import java.util.Collection; +import java.util.HashSet; + +public class BetterHashSet extends HashSet { + + public BetterHashSet() { + super(); + } + + public BetterHashSet(Collection c) { + super(c); + } + + public void addOrRemove(E value, boolean addOrRemove) { + if (addOrRemove) { + super.add(value); + } else { + super.remove(value); + } + } +}