mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-13 09:26:11 -04:00
Merge branch 'entity-meta' into render
This commit is contained in:
commit
46671aa1bf
@ -3,7 +3,7 @@
|
|||||||
Minosoft is an open source minecraft client, written from scratch in java. It aims to bring more functionality and stability.
|
Minosoft is an open source minecraft client, written from scratch in java. It aims to bring more functionality and stability.
|
||||||
|
|
||||||
[](https://gitlab.bixilon.de/bixilon/minosoft/-/commits/master)
|
[](https://gitlab.bixilon.de/bixilon/minosoft/-/commits/master)
|
||||||
|
[](https://jitpack.io/#de.bixilon.gitlab.bixilon/minosoft)
|
||||||
|
|
||||||
## Feature overview
|
## Feature overview
|
||||||
- Rendering (WIP)
|
- Rendering (WIP)
|
||||||
|
@ -24,7 +24,7 @@ public class StaticConfiguration {
|
|||||||
public static boolean SKIP_MOJANG_AUTHENTICATION = false; // disables all connections to mojang
|
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 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 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;
|
public static String HOME_DIRECTORY;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
package de.bixilon.minosoft.data.assets;
|
package de.bixilon.minosoft.data.assets;
|
||||||
|
|
||||||
|
import com.google.common.base.StandardSystemProperty;
|
||||||
import com.google.errorprone.annotations.DoNotCall;
|
import com.google.errorprone.annotations.DoNotCall;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
@ -260,7 +261,7 @@ public class AssetsManager {
|
|||||||
private static String saveAsset(InputStream data) throws IOException {
|
private static String saveAsset(InputStream data) throws IOException {
|
||||||
File tempDestinationFile = null;
|
File tempDestinationFile = null;
|
||||||
while (tempDestinationFile == null || tempDestinationFile.exists()) { // file exist? lol
|
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);
|
Util.createParentFolderIfNotExist(tempDestinationFile);
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
package de.bixilon.minosoft.data.entities.block;
|
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.data.text.RGBColor;
|
||||||
import de.bixilon.minosoft.util.nbt.tag.IntTag;
|
import de.bixilon.minosoft.util.nbt.tag.IntTag;
|
||||||
import de.bixilon.minosoft.util.nbt.tag.NBTTag;
|
import de.bixilon.minosoft.util.nbt.tag.NBTTag;
|
||||||
@ -26,6 +27,10 @@ public class BedEntityMetaData extends BlockEntityMetaData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public BedEntityMetaData(NBTTag nbt) {
|
public BedEntityMetaData(NBTTag nbt) {
|
||||||
|
if (nbt == null) {
|
||||||
|
color = ChatColors.RED;
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (nbt instanceof StringTag stringTag) {
|
if (nbt instanceof StringTag stringTag) {
|
||||||
// yes, we support bed rgb colors :D
|
// yes, we support bed rgb colors :D
|
||||||
color = new RGBColor(stringTag.getValue());
|
color = new RGBColor(stringTag.getValue());
|
||||||
|
@ -212,11 +212,9 @@ public abstract class Entity {
|
|||||||
@EntityMetaDataFunction(identifier = "pose")
|
@EntityMetaDataFunction(identifier = "pose")
|
||||||
public Poses getPose() {
|
public Poses getPose() {
|
||||||
if (isCrouching()) {
|
if (isCrouching()) {
|
||||||
// crouching
|
|
||||||
return Poses.SNEAKING;
|
return Poses.SNEAKING;
|
||||||
}
|
}
|
||||||
if (isSwimming()) {
|
if (isSwimming()) {
|
||||||
// crouching
|
|
||||||
return Poses.SWIMMING;
|
return Poses.SWIMMING;
|
||||||
}
|
}
|
||||||
if (isFlyingWithElytra()) {
|
if (isFlyingWithElytra()) {
|
||||||
|
@ -16,6 +16,8 @@ package de.bixilon.minosoft.data.text;
|
|||||||
import com.google.gson.JsonArray;
|
import com.google.gson.JsonArray;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import de.bixilon.minosoft.modding.event.events.annotations.Unsafe;
|
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.collections.ObservableList;
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
|
|
||||||
@ -23,9 +25,8 @@ import javax.annotation.Nullable;
|
|||||||
import java.text.CharacterIterator;
|
import java.text.CharacterIterator;
|
||||||
import java.text.StringCharacterIterator;
|
import java.text.StringCharacterIterator;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashSet;
|
|
||||||
|
|
||||||
public class BaseComponent implements ChatComponent {
|
public class BaseComponent extends ChatComponent {
|
||||||
private final ArrayList<ChatComponent> parts = new ArrayList<>();
|
private final ArrayList<ChatComponent> parts = new ArrayList<>();
|
||||||
|
|
||||||
public BaseComponent() {
|
public BaseComponent() {
|
||||||
@ -35,12 +36,12 @@ public class BaseComponent implements ChatComponent {
|
|||||||
// legacy String
|
// legacy String
|
||||||
StringBuilder currentText = new StringBuilder();
|
StringBuilder currentText = new StringBuilder();
|
||||||
RGBColor color = null;
|
RGBColor color = null;
|
||||||
HashSet<ChatFormattingCodes> formattingCodes = new HashSet<>();
|
BetterHashSet<ChatFormattingCode> formattingCodes = new BetterHashSet<>();
|
||||||
StringCharacterIterator iterator = new StringCharacterIterator(text);
|
StringCharacterIterator iterator = new StringCharacterIterator(text);
|
||||||
while (iterator.current() != CharacterIterator.DONE) {
|
while (iterator.current() != CharacterIterator.DONE) {
|
||||||
char c = iterator.current();
|
char c = iterator.current();
|
||||||
iterator.next();
|
iterator.next();
|
||||||
if (c != '§') {
|
if (c != ProtocolDefinition.TEXT_COMPONENT_SPECIAL_PREFIX_CHAR) {
|
||||||
currentText.append(c);
|
currentText.append(c);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -55,19 +56,19 @@ public class BaseComponent implements ChatComponent {
|
|||||||
currentText = new StringBuilder();
|
currentText = new StringBuilder();
|
||||||
}
|
}
|
||||||
color = nextColor;
|
color = nextColor;
|
||||||
formattingCodes = new HashSet<>();
|
formattingCodes = new BetterHashSet<>();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ChatFormattingCodes nextFormattingCode = ChatFormattingCodes.getChatFormattingCodeByChar(nextFormattingChar);
|
ChatFormattingCode nextFormattingCode = ChatFormattingCodes.getChatFormattingCodeByChar(nextFormattingChar);
|
||||||
if (nextFormattingCode != null) {
|
if (nextFormattingCode != null) {
|
||||||
if (currentText.length() > 0) {
|
if (currentText.length() > 0) {
|
||||||
parts.add(new TextComponent(currentText.toString(), color, formattingCodes));
|
parts.add(new TextComponent(currentText.toString(), color, formattingCodes));
|
||||||
currentText = new StringBuilder();
|
currentText = new StringBuilder();
|
||||||
color = null;
|
color = null;
|
||||||
formattingCodes = new HashSet<>();
|
formattingCodes = new BetterHashSet<>();
|
||||||
}
|
}
|
||||||
formattingCodes.add(nextFormattingCode);
|
formattingCodes.add(nextFormattingCode);
|
||||||
if (nextFormattingCode == ChatFormattingCodes.RESET) {
|
if (nextFormattingCode == PostChatFormattingCodes.RESET) {
|
||||||
// special rule here
|
// special rule here
|
||||||
if (currentText.length() > 0) {
|
if (currentText.length() > 0) {
|
||||||
// color change, add text part
|
// color change, add text part
|
||||||
@ -75,7 +76,7 @@ public class BaseComponent implements ChatComponent {
|
|||||||
currentText = new StringBuilder();
|
currentText = new StringBuilder();
|
||||||
}
|
}
|
||||||
color = null;
|
color = null;
|
||||||
formattingCodes = new HashSet<>();
|
formattingCodes = new BetterHashSet<>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -92,7 +93,7 @@ public class BaseComponent implements ChatComponent {
|
|||||||
TextComponent thisTextComponent = null;
|
TextComponent thisTextComponent = null;
|
||||||
if (json.has("text")) {
|
if (json.has("text")) {
|
||||||
String text = json.get("text").getAsString();
|
String text = json.get("text").getAsString();
|
||||||
if (text.contains("§")) {
|
if (text.contains(String.valueOf(ProtocolDefinition.TEXT_COMPONENT_SPECIAL_PREFIX_CHAR))) {
|
||||||
// legacy text component
|
// legacy text component
|
||||||
parts.add(new BaseComponent(text));
|
parts.add(new BaseComponent(text));
|
||||||
return;
|
return;
|
||||||
@ -112,47 +113,26 @@ public class BaseComponent implements ChatComponent {
|
|||||||
color = ChatColors.getColorByName(colorString);
|
color = ChatColors.getColorByName(colorString);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
HashSet<ChatFormattingCodes> formattingCodes;
|
BetterHashSet<ChatFormattingCode> formattingCodes;
|
||||||
if (parent != null && parent.getFormatting() != null) {
|
if (parent != null && parent.getFormatting() != null) {
|
||||||
formattingCodes = (HashSet<ChatFormattingCodes>) parent.getFormatting().clone();
|
formattingCodes = (BetterHashSet<ChatFormattingCode>) parent.getFormatting().clone();
|
||||||
} else {
|
} else {
|
||||||
formattingCodes = new HashSet<>();
|
formattingCodes = new BetterHashSet<>();
|
||||||
}
|
}
|
||||||
if (json.has("bold")) {
|
if (json.has("bold")) {
|
||||||
if (json.get("bold").getAsBoolean()) {
|
formattingCodes.addOrRemove(PreChatFormattingCodes.BOLD, json.get("bold").getAsBoolean());
|
||||||
formattingCodes.add(ChatFormattingCodes.BOLD);
|
|
||||||
} else {
|
|
||||||
formattingCodes.remove(ChatFormattingCodes.BOLD);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (json.has("italic")) {
|
if (json.has("italic")) {
|
||||||
if (json.get("italic").getAsBoolean()) {
|
formattingCodes.addOrRemove(PreChatFormattingCodes.ITALIC, json.get("italic").getAsBoolean());
|
||||||
formattingCodes.add(ChatFormattingCodes.ITALIC);
|
|
||||||
} else {
|
|
||||||
formattingCodes.remove(ChatFormattingCodes.ITALIC);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (json.has("underlined")) {
|
if (json.has("underlined")) {
|
||||||
if (json.get("underlined").getAsBoolean()) {
|
formattingCodes.addOrRemove(PreChatFormattingCodes.UNDERLINED, json.get("underlined").getAsBoolean());
|
||||||
formattingCodes.add(ChatFormattingCodes.UNDERLINED);
|
|
||||||
} else {
|
|
||||||
formattingCodes.remove(ChatFormattingCodes.UNDERLINED);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (json.has("strikethrough")) {
|
if (json.has("strikethrough")) {
|
||||||
if (json.get("strikethrough").getAsBoolean()) {
|
formattingCodes.addOrRemove(PreChatFormattingCodes.STRIKETHROUGH, json.get("strikethrough").getAsBoolean());
|
||||||
formattingCodes.add(ChatFormattingCodes.STRIKETHROUGH);
|
|
||||||
} else {
|
|
||||||
formattingCodes.remove(ChatFormattingCodes.STRIKETHROUGH);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (json.has("obfuscated")) {
|
if (json.has("obfuscated")) {
|
||||||
if (json.get("obfuscated").getAsBoolean()) {
|
formattingCodes.addOrRemove(PreChatFormattingCodes.OBFUSCATED, json.get("obfuscated").getAsBoolean());
|
||||||
formattingCodes.add(ChatFormattingCodes.OBFUSCATED);
|
|
||||||
} else {
|
|
||||||
formattingCodes.remove(ChatFormattingCodes.OBFUSCATED);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
thisTextComponent = new TextComponent(text, color, formattingCodes);
|
thisTextComponent = new TextComponent(text, color, formattingCodes);
|
||||||
}
|
}
|
||||||
@ -161,20 +141,20 @@ public class BaseComponent implements ChatComponent {
|
|||||||
parts.add(thisTextComponent);
|
parts.add(thisTextComponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final TextComponent parentParameter = thisTextComponent == null ? parent : thisTextComponent;
|
||||||
if (json.has("extra")) {
|
if (json.has("extra")) {
|
||||||
JsonArray extras = json.getAsJsonArray("extra");
|
JsonArray extras = json.getAsJsonArray("extra");
|
||||||
TextComponent finalThisChatPart = thisTextComponent;
|
extras.forEach((extra -> parts.add(new BaseComponent(parentParameter, extra.getAsJsonObject()))));
|
||||||
extras.forEach((extra -> parts.add(new BaseComponent(finalThisChatPart, extra.getAsJsonObject()))));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (json.has("translate")) {
|
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
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return getANSIColoredMessage();
|
return PostChatFormattingCodes.RESET.getANSI() + getANSIColoredMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getANSIColoredMessage() {
|
public String getANSIColoredMessage() {
|
||||||
|
17
src/main/java/de/bixilon/minosoft/data/text/ChatCode.java
Normal file
17
src/main/java/de/bixilon/minosoft/data/text/ChatCode.java
Normal file
@ -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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.bixilon.minosoft.data.text;
|
||||||
|
|
||||||
|
public interface ChatCode {
|
||||||
|
}
|
@ -54,17 +54,17 @@ public final class ChatColors {
|
|||||||
return getColorById(Character.digit(c, 16));
|
return getColorById(Character.digit(c, 16));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ChatFormattingCode getFormattingById(int id) {
|
public static ChatCode getFormattingById(int id) {
|
||||||
if (id <= 15) {
|
if (id <= 15) {
|
||||||
return getColorById(id);
|
return getColorById(id);
|
||||||
}
|
}
|
||||||
return switch (id) {
|
return switch (id) {
|
||||||
case 16 -> ChatFormattingCodes.OBFUSCATED;
|
case 16 -> PreChatFormattingCodes.OBFUSCATED;
|
||||||
case 17 -> ChatFormattingCodes.BOLD;
|
case 17 -> PreChatFormattingCodes.BOLD;
|
||||||
case 18 -> ChatFormattingCodes.STRIKETHROUGH;
|
case 18 -> PreChatFormattingCodes.STRIKETHROUGH;
|
||||||
case 19 -> ChatFormattingCodes.UNDERLINED;
|
case 19 -> PreChatFormattingCodes.UNDERLINED;
|
||||||
case 20 -> ChatFormattingCodes.ITALIC;
|
case 20 -> PreChatFormattingCodes.ITALIC;
|
||||||
case 21 -> ChatFormattingCodes.RESET;
|
case 21 -> PostChatFormattingCodes.RESET;
|
||||||
default -> null;
|
default -> null;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -83,6 +83,10 @@ public final class ChatColors {
|
|||||||
return colorIntMap.get(color);
|
return colorIntMap.get(color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String getColorChar(RGBColor color) {
|
||||||
|
return String.format("%x", colorIntMap.get(color));
|
||||||
|
}
|
||||||
|
|
||||||
public static RGBColor getColorByName(String name) {
|
public static RGBColor getColorByName(String name) {
|
||||||
return switch (name.toLowerCase()) {
|
return switch (name.toLowerCase()) {
|
||||||
case "black" -> BLACK;
|
case "black" -> BLACK;
|
||||||
@ -100,7 +104,7 @@ public final class ChatColors {
|
|||||||
case "red" -> RED;
|
case "red" -> RED;
|
||||||
case "light_purple" -> LIGHT_PURPLE;
|
case "light_purple" -> LIGHT_PURPLE;
|
||||||
case "yellow" -> YELLOW;
|
case "yellow" -> YELLOW;
|
||||||
case "white" -> WHITE;
|
case "white", "reset" -> WHITE;
|
||||||
default -> throw new IllegalStateException("Unexpected value: " + name);
|
default -> throw new IllegalStateException("Unexpected value: " + name);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -15,16 +15,23 @@ package de.bixilon.minosoft.data.text;
|
|||||||
|
|
||||||
import com.google.gson.JsonParseException;
|
import com.google.gson.JsonParseException;
|
||||||
import com.google.gson.JsonParser;
|
import com.google.gson.JsonParser;
|
||||||
|
import javafx.collections.FXCollections;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
|
|
||||||
public interface ChatComponent {
|
import javax.annotation.Nullable;
|
||||||
static ChatComponent fromString(String raw) {
|
|
||||||
|
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) {
|
if (raw == null) {
|
||||||
return new BaseComponent();
|
return new BaseComponent();
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return new BaseComponent(JsonParser.parseString(raw).getAsJsonObject());
|
return new BaseComponent(parent, JsonParser.parseString(raw).getAsJsonObject());
|
||||||
} catch (JsonParseException | IllegalStateException ignored) {
|
} catch (JsonParseException | IllegalStateException ignored) {
|
||||||
}
|
}
|
||||||
return new BaseComponent(raw);
|
return new BaseComponent(raw);
|
||||||
@ -33,20 +40,27 @@ public interface ChatComponent {
|
|||||||
/**
|
/**
|
||||||
* @return Returns the message formatted with ANSI Formatting codes
|
* @return Returns the message formatted with ANSI Formatting codes
|
||||||
*/
|
*/
|
||||||
String getANSIColoredMessage();
|
public abstract String getANSIColoredMessage();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Returns the message formatted with minecraft formatting codes (§)
|
* @return Returns the message formatted with minecraft formatting codes (§)
|
||||||
*/
|
*/
|
||||||
String getLegacyText();
|
public abstract String getLegacyText();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Returns the unformatted message
|
* @return Returns the unformatted message
|
||||||
*/
|
*/
|
||||||
String getMessage();
|
public abstract String getMessage();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Returns the a list of Nodes, drawable in JavaFX (TextFlow)
|
* @return Returns the a list of Nodes, drawable in JavaFX (TextFlow)
|
||||||
*/
|
*/
|
||||||
ObservableList<Node> getJavaFXText(ObservableList<Node> nodes);
|
public abstract ObservableList<Node> getJavaFXText(ObservableList<Node> nodes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Returns the a list of Nodes, drawable in JavaFX (TextFlow)
|
||||||
|
*/
|
||||||
|
public ObservableList<Node> getJavaFXText() {
|
||||||
|
return getJavaFXText(FXCollections.observableArrayList());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,5 +13,11 @@
|
|||||||
|
|
||||||
package de.bixilon.minosoft.data.text;
|
package de.bixilon.minosoft.data.text;
|
||||||
|
|
||||||
public interface ChatFormattingCode {
|
public interface ChatFormattingCode extends ChatCode {
|
||||||
|
char getChar();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
String toString();
|
||||||
|
|
||||||
|
String getANSI();
|
||||||
}
|
}
|
||||||
|
@ -17,60 +17,17 @@ import com.google.common.collect.HashBiMap;
|
|||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
public enum ChatFormattingCodes implements ChatFormattingCode {
|
public final class ChatFormattingCodes {
|
||||||
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);
|
|
||||||
|
|
||||||
private final static HashBiMap<Character, ChatFormattingCodes> formattingCodes = HashBiMap.create();
|
private static final HashBiMap<Character, ChatFormattingCode> formattingCodes = HashBiMap.create();
|
||||||
|
|
||||||
static {
|
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;
|
public static ChatFormattingCode getChatFormattingCodeByChar(char nextFormattingChar) {
|
||||||
final String ansi;
|
return formattingCodes.get(nextFormattingChar);
|
||||||
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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
package de.bixilon.minosoft.data.text;
|
package de.bixilon.minosoft.data.text;
|
||||||
|
|
||||||
public final class RGBColor implements ChatFormattingCode {
|
public final class RGBColor implements ChatCode {
|
||||||
private final int color;
|
private final int color;
|
||||||
|
|
||||||
public RGBColor(int color) {
|
public RGBColor(int color) {
|
||||||
|
@ -13,6 +13,8 @@
|
|||||||
|
|
||||||
package de.bixilon.minosoft.data.text;
|
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.Animation;
|
||||||
import javafx.animation.KeyFrame;
|
import javafx.animation.KeyFrame;
|
||||||
import javafx.animation.Timeline;
|
import javafx.animation.Timeline;
|
||||||
@ -22,15 +24,14 @@ import javafx.scene.paint.Color;
|
|||||||
import javafx.scene.text.Text;
|
import javafx.scene.text.Text;
|
||||||
import javafx.util.Duration;
|
import javafx.util.Duration;
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class TextComponent implements ChatComponent {
|
public class TextComponent extends ChatComponent {
|
||||||
private final String text;
|
private final String text;
|
||||||
private RGBColor color;
|
private RGBColor color;
|
||||||
private HashSet<ChatFormattingCodes> formatting;
|
private BetterHashSet<ChatFormattingCode> formatting;
|
||||||
|
|
||||||
public TextComponent(String text, RGBColor color, HashSet<ChatFormattingCodes> formatting) {
|
public TextComponent(String text, RGBColor color, BetterHashSet<ChatFormattingCode> formatting) {
|
||||||
this.text = text;
|
this.text = text;
|
||||||
this.color = color;
|
this.color = color;
|
||||||
this.formatting = formatting;
|
this.formatting = formatting;
|
||||||
@ -46,56 +47,32 @@ public class TextComponent implements ChatComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public TextComponent setObfuscated(boolean obfuscated) {
|
public TextComponent setObfuscated(boolean obfuscated) {
|
||||||
if (obfuscated) {
|
formatting.addOrRemove(PreChatFormattingCodes.OBFUSCATED, obfuscated);
|
||||||
formatting.add(ChatFormattingCodes.OBFUSCATED);
|
|
||||||
} else {
|
|
||||||
formatting.remove(ChatFormattingCodes.OBFUSCATED);
|
|
||||||
}
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TextComponent setBold(boolean bold) {
|
public TextComponent setBold(boolean bold) {
|
||||||
if (bold) {
|
formatting.addOrRemove(PreChatFormattingCodes.BOLD, bold);
|
||||||
formatting.add(ChatFormattingCodes.BOLD);
|
|
||||||
} else {
|
|
||||||
formatting.remove(ChatFormattingCodes.BOLD);
|
|
||||||
}
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TextComponent setStrikethrough(boolean strikethrough) {
|
public TextComponent setStrikethrough(boolean strikethrough) {
|
||||||
if (strikethrough) {
|
formatting.addOrRemove(PreChatFormattingCodes.STRIKETHROUGH, strikethrough);
|
||||||
formatting.add(ChatFormattingCodes.STRIKETHROUGH);
|
|
||||||
} else {
|
|
||||||
formatting.remove(ChatFormattingCodes.STRIKETHROUGH);
|
|
||||||
}
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TextComponent setUnderlined(boolean underlined) {
|
public TextComponent setUnderlined(boolean underlined) {
|
||||||
if (underlined) {
|
formatting.addOrRemove(PreChatFormattingCodes.UNDERLINED, underlined);
|
||||||
formatting.add(ChatFormattingCodes.UNDERLINED);
|
|
||||||
} else {
|
|
||||||
formatting.remove(ChatFormattingCodes.UNDERLINED);
|
|
||||||
}
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TextComponent setItalic(boolean italic) {
|
public TextComponent setItalic(boolean italic) {
|
||||||
if (italic) {
|
formatting.addOrRemove(PreChatFormattingCodes.ITALIC, italic);
|
||||||
formatting.add(ChatFormattingCodes.ITALIC);
|
|
||||||
} else {
|
|
||||||
formatting.remove(ChatFormattingCodes.ITALIC);
|
|
||||||
}
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TextComponent setReset(boolean reset) {
|
public TextComponent setReset(boolean reset) {
|
||||||
if (reset) {
|
formatting.addOrRemove(PostChatFormattingCodes.RESET, reset);
|
||||||
formatting.add(ChatFormattingCodes.RESET);
|
|
||||||
} else {
|
|
||||||
formatting.remove(ChatFormattingCodes.RESET);
|
|
||||||
}
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,11 +85,11 @@ public class TextComponent implements ChatComponent {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public HashSet<ChatFormattingCodes> getFormatting() {
|
public BetterHashSet<ChatFormattingCode> getFormatting() {
|
||||||
return formatting;
|
return formatting;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TextComponent setFormatting(HashSet<ChatFormattingCodes> formatting) {
|
public TextComponent setFormatting(BetterHashSet<ChatFormattingCode> formatting) {
|
||||||
this.formatting = formatting;
|
this.formatting = formatting;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -142,20 +119,20 @@ public class TextComponent implements ChatComponent {
|
|||||||
}
|
}
|
||||||
if (formatting != null) {
|
if (formatting != null) {
|
||||||
formatting.forEach((chatFormattingCodes -> {
|
formatting.forEach((chatFormattingCodes -> {
|
||||||
if (chatFormattingCodes.getPosition() == ChatFormattingCodes.ChatFormattingCodePosition.PRE) {
|
if (chatFormattingCodes instanceof PreChatFormattingCodes code) {
|
||||||
builder.append(chatFormattingCodes.getANSI());
|
builder.append(code.getANSI());
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
builder.append(text);
|
builder.append(text);
|
||||||
if (formatting != null) {
|
if (formatting != null) {
|
||||||
formatting.forEach((chatFormattingCodes -> {
|
formatting.forEach((chatFormattingCodes -> {
|
||||||
if (chatFormattingCodes.getPosition() == ChatFormattingCodes.ChatFormattingCodePosition.POST) {
|
if (chatFormattingCodes instanceof PostChatFormattingCodes code) {
|
||||||
builder.append(chatFormattingCodes.getANSI());
|
builder.append(code.getANSI());
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
builder.append(ChatFormattingCodes.RESET);
|
builder.append(PostChatFormattingCodes.RESET);
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,11 +141,11 @@ public class TextComponent implements ChatComponent {
|
|||||||
StringBuilder output = new StringBuilder();
|
StringBuilder output = new StringBuilder();
|
||||||
Integer colorChar = ChatColors.getColorId(color);
|
Integer colorChar = ChatColors.getColorId(color);
|
||||||
if (colorChar != null) {
|
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(text);
|
||||||
output.append('§').append(ChatFormattingCodes.RESET.getChar());
|
output.append(ProtocolDefinition.TEXT_COMPONENT_SPECIAL_PREFIX_CHAR).append(PostChatFormattingCodes.RESET.getChar());
|
||||||
return output.toString();
|
return output.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,7 +161,8 @@ public class TextComponent implements ChatComponent {
|
|||||||
text.setFill(Color.web(color.toString()));
|
text.setFill(Color.web(color.toString()));
|
||||||
}
|
}
|
||||||
formatting.forEach((chatFormattingCode -> {
|
formatting.forEach((chatFormattingCode -> {
|
||||||
switch (chatFormattingCode) {
|
if (chatFormattingCode instanceof PreChatFormattingCodes code) {
|
||||||
|
switch (code) {
|
||||||
case OBFUSCATED -> {
|
case OBFUSCATED -> {
|
||||||
Timeline flasher = new Timeline(new KeyFrame(Duration.seconds(1), e -> text.setVisible(false)), new KeyFrame(Duration.seconds(2), e -> text.setVisible(true)));
|
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.setCycleCount(Animation.INDEFINITE);
|
||||||
@ -195,6 +173,7 @@ public class TextComponent implements ChatComponent {
|
|||||||
case UNDERLINED -> text.setStyle("-fx-underline: true;");
|
case UNDERLINED -> text.setStyle("-fx-underline: true;");
|
||||||
case ITALIC -> text.setStyle("-fx-font-weight: italic;");
|
case ITALIC -> text.setStyle("-fx-font-weight: italic;");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}));
|
}));
|
||||||
nodes.add(text);
|
nodes.add(text);
|
||||||
return nodes;
|
return nodes;
|
||||||
|
@ -15,54 +15,50 @@ package de.bixilon.minosoft.data.text;
|
|||||||
|
|
||||||
import com.google.gson.JsonArray;
|
import com.google.gson.JsonArray;
|
||||||
import de.bixilon.minosoft.data.locale.minecraft.MinecraftLocaleManager;
|
import de.bixilon.minosoft.data.locale.minecraft.MinecraftLocaleManager;
|
||||||
|
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
public class TranslatableComponent implements ChatComponent {
|
public class TranslatableComponent extends ChatComponent {
|
||||||
private final ArrayList<ChatComponent> data = new ArrayList<>();
|
private final ArrayList<ChatComponent> data = new ArrayList<>();
|
||||||
private final String key;
|
private final String key;
|
||||||
|
private final TextComponent parent;
|
||||||
|
|
||||||
public TranslatableComponent(String key, JsonArray data) {
|
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;
|
this.key = key;
|
||||||
if (data == null) {
|
if (data == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
data.forEach((jsonElement -> {
|
data.forEach((jsonElement -> {
|
||||||
if (jsonElement.isJsonPrimitive()) {
|
if (jsonElement.isJsonPrimitive()) {
|
||||||
this.data.add(ChatComponent.fromString(jsonElement.getAsString()));
|
this.data.add(ChatComponent.fromString(parent, jsonElement.getAsString()));
|
||||||
} else {
|
} else {
|
||||||
this.data.add(new BaseComponent(jsonElement.getAsJsonObject()));
|
this.data.add(new BaseComponent(parent, jsonElement.getAsJsonObject()));
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getANSIColoredMessage() {
|
public String getANSIColoredMessage() {
|
||||||
Object[] data = new String[this.data.size()];
|
return getList("getANSIColoredMessage");
|
||||||
for (int i = 0; i < this.data.size(); i++) {
|
|
||||||
data[i] = this.data.get(i).getANSIColoredMessage();
|
|
||||||
}
|
|
||||||
return MinecraftLocaleManager.translate(key, data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getLegacyText() {
|
public String getLegacyText() {
|
||||||
Object[] data = new String[this.data.size()];
|
return getList("getLegacyText");
|
||||||
for (int i = 0; i < this.data.size(); i++) {
|
|
||||||
data[i] = this.data.get(i).getLegacyText();
|
|
||||||
}
|
|
||||||
return MinecraftLocaleManager.translate(key, data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getMessage() {
|
public String getMessage() {
|
||||||
Object[] data = new String[this.data.size()];
|
return getList("getMessage");
|
||||||
for (int i = 0; i < this.data.size(); i++) {
|
|
||||||
data[i] = this.data.get(i).getMessage();
|
|
||||||
}
|
|
||||||
return MinecraftLocaleManager.translate(key, data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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
|
// This is just a dirty workaround to enable formatting and coloring. Still need to do hover, click, ... stuff
|
||||||
return new BaseComponent(getLegacyText()).getJavaFXText(nodes);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,6 @@ import de.bixilon.minosoft.protocol.ping.ForgeModInfo;
|
|||||||
import de.bixilon.minosoft.protocol.ping.ServerListPing;
|
import de.bixilon.minosoft.protocol.ping.ServerListPing;
|
||||||
import de.bixilon.minosoft.util.DNSUtil;
|
import de.bixilon.minosoft.util.DNSUtil;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.collections.FXCollections;
|
|
||||||
import javafx.fxml.FXMLLoader;
|
import javafx.fxml.FXMLLoader;
|
||||||
import javafx.fxml.Initializable;
|
import javafx.fxml.Initializable;
|
||||||
import javafx.geometry.Insets;
|
import javafx.geometry.Insets;
|
||||||
@ -178,7 +177,7 @@ public class ServerListCell extends ListCell<Server> implements Initializable {
|
|||||||
}
|
}
|
||||||
serverBrand.setText(ping.getServerModInfo().getBrand());
|
serverBrand.setText(ping.getServerModInfo().getBrand());
|
||||||
serverBrand.setTooltip(new Tooltip(ping.getServerModInfo().getInfo()));
|
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) {
|
if (ping.getFavicon() != null) {
|
||||||
icon.setImage(GUITools.getImage(ping.getFavicon()));
|
icon.setImage(GUITools.getImage(ping.getFavicon()));
|
||||||
if (!Arrays.equals(ping.getFavicon(), server.getFavicon())) {
|
if (!Arrays.equals(ping.getFavicon(), server.getFavicon())) {
|
||||||
@ -416,7 +415,7 @@ public class ServerListCell extends ListCell<Server> implements Initializable {
|
|||||||
Label serverBrandLabel = new Label(lastPing.getServerBrand());
|
Label serverBrandLabel = new Label(lastPing.getServerBrand());
|
||||||
Label playersOnlineMaxLabel = new Label(LocaleManager.translate(Strings.SERVER_INFO_SLOTS_PLAYERS_ONLINE, lastPing.getPlayerOnline(), lastPing.getMaxPlayers()));
|
Label playersOnlineMaxLabel = new Label(LocaleManager.translate(Strings.SERVER_INFO_SLOTS_PLAYERS_ONLINE, lastPing.getPlayerOnline(), lastPing.getMaxPlayers()));
|
||||||
TextFlow motdLabel = new TextFlow();
|
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());
|
Label moddedBrandLabel = new Label(lastPing.getServerModInfo().getBrand());
|
||||||
|
|
||||||
grid.add(new Label(LocaleManager.translate(Strings.SERVER_INFO_REAL_SERVER_ADDRESS) + ":"), 0, ++column);
|
grid.add(new Label(LocaleManager.translate(Strings.SERVER_INFO_REAL_SERVER_ADDRESS) + ":"), 0, ++column);
|
||||||
|
@ -15,7 +15,7 @@ package de.bixilon.minosoft.logging;
|
|||||||
|
|
||||||
import de.bixilon.minosoft.config.StaticConfiguration;
|
import de.bixilon.minosoft.config.StaticConfiguration;
|
||||||
import de.bixilon.minosoft.data.text.ChatColors;
|
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 de.bixilon.minosoft.data.text.RGBColor;
|
||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
@ -45,18 +45,24 @@ public class Log {
|
|||||||
}, "Log").start();
|
}, "Log").start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void log(LogLevels level, String message, RGBColor color) {
|
public static void log(LogLevels level, RGBColor color, Object message, Object... format) {
|
||||||
log(level, "", message, color);
|
log(level, "", color, message, format);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void log(LogLevels level, String prefix, String message, RGBColor color) {
|
public static void log(LogLevels level, String prefix, RGBColor color, Object message, Object... format) {
|
||||||
if (message.isBlank()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (level.ordinal() > Log.level.ordinal()) {
|
if (level.ordinal() > Log.level.ordinal()) {
|
||||||
// log level too low
|
// log level too low
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (message == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (message instanceof String string) {
|
||||||
|
if (string.isBlank()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
message = String.format(string, format);
|
||||||
|
}
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
builder.append("[");
|
builder.append("[");
|
||||||
if (StaticConfiguration.LOG_RELATIVE_TIME) {
|
if (StaticConfiguration.LOG_RELATIVE_TIME) {
|
||||||
@ -73,11 +79,11 @@ public class Log {
|
|||||||
if (color != null && StaticConfiguration.COLORED_LOG) {
|
if (color != null && StaticConfiguration.COLORED_LOG) {
|
||||||
builder.append(ChatColors.getANSIColorByRGBColor(color));
|
builder.append(ChatColors.getANSIColorByRGBColor(color));
|
||||||
builder.append(message);
|
builder.append(message);
|
||||||
builder.append(ChatFormattingCodes.RESET.getANSI());
|
builder.append(PostChatFormattingCodes.RESET.getANSI());
|
||||||
} else {
|
} else {
|
||||||
builder.append(message);
|
builder.append(message);
|
||||||
}
|
}
|
||||||
builder.append(ChatFormattingCodes.RESET.getANSI());
|
builder.append(PostChatFormattingCodes.RESET.getANSI());
|
||||||
queue.add(builder.toString());
|
queue.add(builder.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,8 +92,8 @@ public class Log {
|
|||||||
*
|
*
|
||||||
* @param message Raw message to log
|
* @param message Raw message to log
|
||||||
*/
|
*/
|
||||||
public static void game(String message) {
|
public static void game(Object message, Object... format) {
|
||||||
log(LogLevels.GAME, message, ChatColors.GREEN);
|
log(LogLevels.GAME, ChatColors.GREEN, message, format);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -95,8 +101,8 @@ public class Log {
|
|||||||
*
|
*
|
||||||
* @param message Raw message to log
|
* @param message Raw message to log
|
||||||
*/
|
*/
|
||||||
public static void fatal(String message) {
|
public static void fatal(Object message, Object... format) {
|
||||||
log(LogLevels.FATAL, message, ChatColors.DARK_RED);
|
log(LogLevels.FATAL, ChatColors.DARK_RED, message, format);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -104,8 +110,8 @@ public class Log {
|
|||||||
*
|
*
|
||||||
* @param message Raw message to log
|
* @param message Raw message to log
|
||||||
*/
|
*/
|
||||||
public static void warn(String message) {
|
public static void warn(Object message, Object... format) {
|
||||||
log(LogLevels.WARNING, message, ChatColors.RED);
|
log(LogLevels.WARNING, ChatColors.RED, message, format);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -113,8 +119,8 @@ public class Log {
|
|||||||
*
|
*
|
||||||
* @param message Raw message to log
|
* @param message Raw message to log
|
||||||
*/
|
*/
|
||||||
public static void debug(String message) {
|
public static void debug(Object message, Object... format) {
|
||||||
log(LogLevels.DEBUG, message, ChatColors.GRAY);
|
log(LogLevels.DEBUG, ChatColors.GRAY, message, format);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -122,8 +128,8 @@ public class Log {
|
|||||||
*
|
*
|
||||||
* @param message Raw message to log
|
* @param message Raw message to log
|
||||||
*/
|
*/
|
||||||
public static void verbose(String message) {
|
public static void verbose(Object message, Object... format) {
|
||||||
log(LogLevels.VERBOSE, message, ChatColors.YELLOW);
|
log(LogLevels.VERBOSE, ChatColors.YELLOW, message, format);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -131,8 +137,8 @@ public class Log {
|
|||||||
*
|
*
|
||||||
* @param message Raw message to log
|
* @param message Raw message to log
|
||||||
*/
|
*/
|
||||||
public static void protocol(String message) {
|
public static void protocol(Object message, Object... format) {
|
||||||
log(LogLevels.PROTOCOL, message, ChatColors.BLUE);
|
log(LogLevels.PROTOCOL, ChatColors.BLUE, message, format);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -140,10 +146,20 @@ public class Log {
|
|||||||
*
|
*
|
||||||
* @param message Raw message to log
|
* @param message Raw message to log
|
||||||
*/
|
*/
|
||||||
public static void mojang(String message) {
|
public static void mojang(Object message, Object... format) {
|
||||||
log(LogLevels.MOJANG, message, ChatColors.AQUA);
|
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() {
|
public static LogLevels getLevel() {
|
||||||
return level;
|
return level;
|
||||||
}
|
}
|
||||||
@ -156,15 +172,6 @@ public class Log {
|
|||||||
Log.level = level;
|
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) {
|
public static boolean printException(Exception exception, LogLevels minimumLogLevel) {
|
||||||
// ToDo: log to file, print also exceptions that are not printed with this method
|
// ToDo: log to file, print also exceptions that are not printed with this method
|
||||||
if (Log.getLevel().ordinal() >= minimumLogLevel.ordinal()) {
|
if (Log.getLevel().ordinal() >= minimumLogLevel.ordinal()) {
|
||||||
|
@ -25,31 +25,31 @@ public class Logger {
|
|||||||
this.modName = modName;
|
this.modName = modName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void log(LogLevels level, String message, RGBColor color) {
|
public void log(LogLevels level, RGBColor color, Object message, Object... format) {
|
||||||
Log.log(level, String.format("[%s] ", modName), message, color);
|
Log.log(level, String.format("[%s] ", modName), color, message, format);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void game(String message) {
|
public void game(Object message, Object... format) {
|
||||||
log(LogLevels.GAME, message, ChatColors.GREEN);
|
log(LogLevels.GAME, ChatColors.GREEN, message, format);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void fatal(String message) {
|
public void fatal(Object message, Object... format) {
|
||||||
log(LogLevels.FATAL, message, ChatColors.DARK_RED);
|
log(LogLevels.FATAL, ChatColors.DARK_RED, message, format);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void info(String message) {
|
public void info(Object message, Object... format) {
|
||||||
log(LogLevels.INFO, message, ChatColors.WHITE);
|
log(LogLevels.INFO, ChatColors.WHITE, message, format);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void warn(String message) {
|
public void warn(Object message, Object... format) {
|
||||||
log(LogLevels.WARNING, message, ChatColors.RED);
|
log(LogLevels.WARNING, ChatColors.RED, message, format);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void debug(String message) {
|
public void debug(Object message, Object... format) {
|
||||||
log(LogLevels.DEBUG, message, ChatColors.GRAY);
|
log(LogLevels.DEBUG, ChatColors.GRAY, message, format);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void verbose(String message) {
|
public void verbose(Object message, Object... format) {
|
||||||
log(LogLevels.VERBOSE, message, ChatColors.YELLOW);
|
log(LogLevels.VERBOSE, ChatColors.YELLOW, message, format);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,6 @@ import org.xeustechnologies.jcl.JarClassLoader;
|
|||||||
import org.xeustechnologies.jcl.JclObjectFactory;
|
import org.xeustechnologies.jcl.JclObjectFactory;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
@ -87,7 +86,12 @@ public class ModLoader {
|
|||||||
progress.countDown();
|
progress.countDown();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
if (!instance.start(phase)) {
|
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()));
|
Log.warn(String.format("An error occurred while loading %s", instance.getInfo()));
|
||||||
instance.setEnabled(false);
|
instance.setEnabled(false);
|
||||||
}
|
}
|
||||||
@ -127,7 +131,7 @@ public class ModLoader {
|
|||||||
instance.setInfo(modInfo);
|
instance.setInfo(modInfo);
|
||||||
Log.verbose(String.format("[MOD] Mod file loaded and added to classpath (%s)", modInfo));
|
Log.verbose(String.format("[MOD] Mod file loaded and added to classpath (%s)", modInfo));
|
||||||
zipFile.close();
|
zipFile.close();
|
||||||
} catch (IOException | ModLoadingException | NullPointerException e) {
|
} catch (Throwable e) {
|
||||||
instance = null;
|
instance = null;
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
Log.warn(String.format("Could not load mod: %s", file.getAbsolutePath()));
|
Log.warn(String.format("Could not load mod: %s", file.getAbsolutePath()));
|
||||||
|
@ -13,9 +13,9 @@
|
|||||||
|
|
||||||
package de.bixilon.minosoft.protocol.packets.clientbound.play;
|
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.ChatColors;
|
||||||
import de.bixilon.minosoft.data.text.ChatComponent;
|
import de.bixilon.minosoft.data.text.ChatComponent;
|
||||||
import de.bixilon.minosoft.data.text.ChatFormattingCode;
|
|
||||||
import de.bixilon.minosoft.logging.Log;
|
import de.bixilon.minosoft.logging.Log;
|
||||||
import de.bixilon.minosoft.protocol.packets.ClientboundPacket;
|
import de.bixilon.minosoft.protocol.packets.ClientboundPacket;
|
||||||
import de.bixilon.minosoft.protocol.protocol.InByteBuffer;
|
import de.bixilon.minosoft.protocol.protocol.InByteBuffer;
|
||||||
@ -32,7 +32,7 @@ public class PacketTeams implements ClientboundPacket {
|
|||||||
boolean seeFriendlyInvisibles;
|
boolean seeFriendlyInvisibles;
|
||||||
TeamCollisionRules collisionRule = TeamCollisionRules.NEVER;
|
TeamCollisionRules collisionRule = TeamCollisionRules.NEVER;
|
||||||
TeamNameTagVisibilities nameTagVisibility = TeamNameTagVisibilities.ALWAYS;
|
TeamNameTagVisibilities nameTagVisibility = TeamNameTagVisibilities.ALWAYS;
|
||||||
ChatFormattingCode formattingCode;
|
ChatCode formattingCode;
|
||||||
String[] playerNames;
|
String[] playerNames;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -133,7 +133,7 @@ public class PacketTeams implements ClientboundPacket {
|
|||||||
return seeFriendlyInvisibles;
|
return seeFriendlyInvisibles;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChatFormattingCode getFormattingCode() {
|
public ChatCode getFormattingCode() {
|
||||||
return formattingCode;
|
return formattingCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,15 +278,15 @@ public class PacketHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Log.game(switch (pkg.getReason()) {
|
Log.game(switch (pkg.getReason()) {
|
||||||
case STOP_RAINING -> "Received weather packet: Starting rain...";
|
case START_RAINING -> "Received weather packet: Starting rain...";
|
||||||
case START_RAINING -> "Received weather packet: Stopping 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()));
|
case CHANGE_GAMEMODE -> String.format("Received game mode change: Now in %s", GameModes.byId(pkg.getValue().intValue()));
|
||||||
default -> "";
|
default -> "";
|
||||||
});
|
});
|
||||||
|
|
||||||
switch (pkg.getReason()) {
|
switch (pkg.getReason()) {
|
||||||
case STOP_RAINING -> connection.getPlayer().getWorld().setRaining(true);
|
case STOP_RAINING -> connection.getPlayer().getWorld().setRaining(false);
|
||||||
case START_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()));
|
case CHANGE_GAMEMODE -> connection.getPlayer().setGameMode(GameModes.byId(pkg.getValue().intValue()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
package de.bixilon.minosoft.protocol.protocol;
|
package de.bixilon.minosoft.protocol.protocol;
|
||||||
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.UnknownHostException;
|
|
||||||
|
|
||||||
public final class ProtocolDefinition {
|
public final class ProtocolDefinition {
|
||||||
public static final int STRING_MAX_LEN = 32767;
|
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 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 String DEFAULT_MOD = "minecraft";
|
||||||
|
public static final char TEXT_COMPONENT_SPECIAL_PREFIX_CHAR = '§';
|
||||||
|
|
||||||
public static final int DEFAULT_BUFFER_SIZE = 4096;
|
public static final int DEFAULT_BUFFER_SIZE = 4096;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
|
// java does (why ever) not allow to directly assign a null
|
||||||
|
InetAddress temp;
|
||||||
try {
|
try {
|
||||||
LAN_SERVER_BROADCAST_ADDRESS = InetAddress.getByName("224.0.2.60");
|
temp = InetAddress.getByName("224.0.2.60");
|
||||||
} catch (UnknownHostException e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
throw new RuntimeException(e);
|
temp = null;
|
||||||
}
|
}
|
||||||
|
LAN_SERVER_BROADCAST_ADDRESS = temp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* 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<E> extends HashSet<E> {
|
||||||
|
|
||||||
|
public BetterHashSet() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public BetterHashSet(Collection<? extends E> c) {
|
||||||
|
super(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addOrRemove(E value, boolean addOrRemove) {
|
||||||
|
if (addOrRemove) {
|
||||||
|
super.add(value);
|
||||||
|
} else {
|
||||||
|
super.remove(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user