fixes and improvements, ChatComponent: ClickEvent and HoverEvent

This commit is contained in:
Bixilon 2020-12-07 22:17:19 +01:00
parent bf238f5ddd
commit f0e922cdf5
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
16 changed files with 211 additions and 23 deletions

View File

@ -47,7 +47,7 @@ After pushing it, it is supported. Some versions are more complicated and need a
Check out [wiki.vg](https://wiki.vg/Main_Page) for more information.
### Supported versions
Almost all versions are supported, starting with 13w41b (pre 1.7 snapshot) and ending with the newest (1.16.4 as of writing this). I plan to maintain Minosoft to at least version 1.20, so stay tuned.
Almost all versions are supported, starting with 13w41b (pre 1.7 snapshot) and ending with the newest (1.16.4 as of writing this). I plan to maintain Minosoft to at least version 1.20, so stay tuned. Old versions are supported, but it is highly recommended using the latest stable release.
### Unsupported versions
Sadly, we cannot support all versions. We will add support for all major versions (like 1.8.9, 1.9.4, 1.14.4, etc), but it is simply not possible to support all snapshots.

View File

@ -229,7 +229,7 @@ public class EntityMetaData {
public ChatComponent getChatComponent(EntityMetaDataFields field) {
Object object = get(field);
if (object instanceof String string) {
return ChatComponent.fromString(string);
return ChatComponent.valueOf(string);
}
return (ChatComponent) object;
}

View File

@ -259,7 +259,7 @@ public enum EntityMetaDataFields {
MINECART_FURNACE_HAS_FUEL(false),
MINECART_COMMAND_BLOCK_COMMAND(""),
MINECART_COMMAND_BLOCK_LAST_OUTPUT(ChatComponent.fromString("")),
MINECART_COMMAND_BLOCK_LAST_OUTPUT(ChatComponent.valueOf("")),
PRIMED_TNT_FUSE_TIME(80),

View File

@ -70,11 +70,11 @@ public class Slot {
if (nbt.containsKey("display")) {
CompoundTag display = nbt.getCompoundTag("display");
if (display.containsKey("Name")) {
this.customDisplayName = ChatComponent.fromString(display.getStringTag("Name").getValue());
this.customDisplayName = ChatComponent.valueOf(display.getStringTag("Name").getValue());
}
if (display.containsKey("Lore")) {
for (StringTag lore : display.getListTag("Lore").<StringTag>getValue()) {
this.lore.add(ChatComponent.fromString(lore.getValue()));
this.lore.add(ChatComponent.valueOf(lore.getValue()));
}
}
}

View File

@ -79,7 +79,7 @@ public class PlayerListItem {
}
public ChatComponent getDisplayName() {
return (hasDisplayName() ? displayName : ChatComponent.fromString(name));
return (hasDisplayName() ? displayName : ChatComponent.valueOf(name));
}
public void setDisplayName(ChatComponent displayName) {

View File

@ -72,7 +72,7 @@ public class PlayerListItemBulk {
}
public ChatComponent getDisplayName() {
return (hasDisplayName() ? displayName : ChatComponent.fromString(name));
return (hasDisplayName() ? displayName : ChatComponent.valueOf(name));
}
public boolean hasDisplayName() {

View File

@ -98,7 +98,7 @@ public class BaseComponent extends ChatComponent {
@SuppressWarnings("unchecked")
public BaseComponent(@Nullable TextComponent parent, JsonElement data) {
TextComponent thisTextComponent = null;
MultiChatComponent thisTextComponent = null;
if (data instanceof JsonObject json) {
if (json.has("text")) {
String text = json.get("text").getAsString();
@ -143,7 +143,14 @@ public class BaseComponent extends ChatComponent {
if (json.has("obfuscated")) {
formattingCodes.addOrRemove(PreChatFormattingCodes.OBFUSCATED, json.get("obfuscated").getAsBoolean());
}
thisTextComponent = new TextComponent(text, color, formattingCodes);
thisTextComponent = new MultiChatComponent(text, color, formattingCodes);
if (json.has("clickEvent")) {
thisTextComponent.setClickEvent(new ClickEvent(json.get("clickEvent").getAsJsonObject()));
}
if (json.has("hoverEvent")) {
thisTextComponent.setHoverEvent(new HoverEvent(json.get("hoverEvent").getAsJsonObject()));
}
}
if (thisTextComponent != null) {

View File

@ -16,6 +16,7 @@ package de.bixilon.minosoft.data.text;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonParser;
import com.google.gson.JsonPrimitive;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Node;
@ -23,19 +24,29 @@ import javafx.scene.Node;
import javax.annotation.Nullable;
public abstract class ChatComponent {
public static ChatComponent fromString(String raw) {
return fromString(null, raw);
public static ChatComponent valueOf(Object raw) {
return valueOf(null, raw);
}
public static ChatComponent fromString(@Nullable TextComponent parent, String raw) {
public static ChatComponent valueOf(@Nullable TextComponent parent, Object raw) {
if (raw == null) {
return new BaseComponent();
}
if (raw instanceof JsonPrimitive primitive) {
raw = primitive.getAsString();
}
JsonObject json;
try {
json = JsonParser.parseString(raw).getAsJsonObject();
} catch (JsonParseException | IllegalStateException ignored) {
return new BaseComponent(raw);
if (raw instanceof JsonObject) {
json = (JsonObject) raw;
} else if (raw instanceof String) {
try {
json = JsonParser.parseString((String) raw).getAsJsonObject();
} catch (JsonParseException | IllegalStateException ignored) {
return new BaseComponent((String) raw);
}
} else {
throw new IllegalArgumentException(String.format("%s is not a valid type here!", raw.getClass().getSimpleName()));
}
return new BaseComponent(parent, json);
}

View File

@ -0,0 +1,52 @@
/*
* Minosoft
* Copyright (C) 2020 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program.If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.data.text;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
public class ClickEvent {
private final ClickEventActions action;
private final Object value;
public ClickEvent(JsonObject json) {
this.action = ClickEventActions.valueOf(json.get("action").getAsString().toUpperCase());
JsonPrimitive primitive = json.get("value").getAsJsonPrimitive();
if (primitive.isNumber()) {
this.value = primitive.getAsNumber();
} else {
this.value = primitive.getAsString();
}
}
public ClickEvent(ClickEventActions action, Object value) {
this.action = action;
this.value = value;
}
public ClickEventActions getAction() {
return action;
}
public Object getValue() {
return value;
}
public enum ClickEventActions {
OPEN_URL,
RUN_COMMAND,
SUGGEST_COMMAND,
CHANGE_PAGE
}
}

View File

@ -0,0 +1,63 @@
/*
* Minosoft
* Copyright (C) 2020 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program.If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.data.text;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import de.bixilon.minosoft.data.mappings.ModIdentifier;
import de.bixilon.minosoft.util.Util;
import java.util.UUID;
public class HoverEvent {
private final HoverEventActions action;
private final Object value; // TextComponent, NBT, Entity, Achievement Id
public HoverEvent(JsonObject json) {
this.action = HoverEventActions.valueOf(json.get("action").getAsString().toUpperCase());
JsonElement data = json.get("value");
value = switch (action) { // ToDo
case SHOW_TEXT -> ChatComponent.valueOf(data);
case SHOW_ENTITY -> EntityHoverData.deserialize(JsonParser.parseString(json.get("value").getAsString()).getAsJsonObject());
default -> null;
};
}
public HoverEvent(HoverEventActions action, Object value) {
this.action = action;
if (!(value instanceof ChatComponent) && !(value instanceof EntityHoverData)) {
throw new IllegalArgumentException(String.format("%s is not a valid value hier", value.getClass().getSimpleName()));
}
this.value = value;
}
public Object getValue() {
return value;
}
public enum HoverEventActions {
SHOW_TEXT,
SHOW_ITEM,
SHOW_ENTITY,
SHOW_ACHIEVEMENT
}
public static record EntityHoverData(UUID uuid, ModIdentifier identifier, ChatComponent name) {
public static EntityHoverData deserialize(JsonObject json) {
return new EntityHoverData(Util.getUUIDFromString(json.get("id").getAsString()), new ModIdentifier(json.get("type").getAsString()), ChatComponent.valueOf(json.get("name").getAsString()));
}
}
}

View File

@ -0,0 +1,55 @@
/*
* Minosoft
* Copyright (C) 2020 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program.If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.data.text;
import de.bixilon.minosoft.util.hash.BetterHashSet;
public class MultiChatComponent extends TextComponent {
private ClickEvent clickEvent;
private HoverEvent hoverEvent;
public MultiChatComponent(String text, RGBColor color, BetterHashSet<ChatFormattingCode> formatting, ClickEvent clickEvent, HoverEvent hoverEvent) {
super(text, color, formatting);
this.clickEvent = clickEvent;
this.hoverEvent = hoverEvent;
}
public MultiChatComponent(String text, RGBColor color, BetterHashSet<ChatFormattingCode> formatting) {
super(text, color, formatting);
}
public MultiChatComponent(String text, RGBColor color) {
super(text, color);
}
public MultiChatComponent(String text) {
super(text);
}
public ClickEvent getClickEvent() {
return clickEvent;
}
public void setClickEvent(ClickEvent clickEvent) {
this.clickEvent = clickEvent;
}
public HoverEvent getHoverEvent() {
return hoverEvent;
}
public void setHoverEvent(HoverEvent hoverEvent) {
this.hoverEvent = hoverEvent;
}
}

View File

@ -39,7 +39,7 @@ public class TranslatableComponent extends ChatComponent {
}
data.forEach((jsonElement -> {
if (jsonElement.isJsonPrimitive()) {
this.data.add(ChatComponent.fromString(parent, jsonElement.getAsString()));
this.data.add(ChatComponent.valueOf(parent, jsonElement.getAsString()));
} else {
this.data.add(new BaseComponent(parent, jsonElement.getAsJsonObject()));
}

View File

@ -46,7 +46,7 @@ public class ServerListPing {
}
if (json.get("description").isJsonPrimitive()) {
motd = ChatComponent.fromString(json.get("description").getAsString());
motd = ChatComponent.valueOf(json.get("description").getAsString());
} else {
motd = new BaseComponent(json.getAsJsonObject("description"));
}

View File

@ -200,7 +200,7 @@ public class InByteBuffer {
}
public ChatComponent readTextComponent() {
return ChatComponent.fromString(readString());
return ChatComponent.valueOf(readString());
}
public int getLength() {

View File

@ -38,6 +38,7 @@ import java.util.zip.*;
public final class Util {
public static final Pattern UUID_FIX = Pattern.compile("(\\w{8})(\\w{4})(\\w{4})(\\w{4})(\\w{12})"); // thanks https://www.spigotmc.org/threads/free-code-easily-convert-between-trimmed-and-full-uuids.165615
public static final String RANDOM_STRING_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
public static final String LINE_SEPARATOR = System.getProperty("line.separator");
private static final Random random = ThreadLocalRandom.current();
public static UUID getUUIDFromString(String uuid) {
@ -167,11 +168,10 @@ public final class Util {
public static String readFile(BufferedReader reader, boolean closeStream) throws IOException {
StringBuilder stringBuilder = new StringBuilder();
String ls = System.getProperty("line.separator");
String line;
while ((line = reader.readLine()) != null) {
stringBuilder.append(line);
stringBuilder.append(ls);
stringBuilder.append(LINE_SEPARATOR);
}
stringBuilder.deleteCharAt(stringBuilder.length() - 1);
if (closeStream) {

View File

@ -79,11 +79,11 @@
}
.list-cell:selected {
-fx-background-color: -primary-color;
-fx-background-color: -primary-dark-color;
}
.list-cell:filled:hover {
-fx-background-color: -primary-dark-color;
-fx-background-color: -primary-color;
}
.menu-bar {