mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-16 02:45:13 -04:00
fixes and improvements, ChatComponent: ClickEvent and HoverEvent
This commit is contained in:
parent
bf238f5ddd
commit
f0e922cdf5
@ -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.
|
Check out [wiki.vg](https://wiki.vg/Main_Page) for more information.
|
||||||
|
|
||||||
### Supported versions
|
### 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
|
### 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.
|
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.
|
||||||
|
@ -229,7 +229,7 @@ public class EntityMetaData {
|
|||||||
public ChatComponent getChatComponent(EntityMetaDataFields field) {
|
public ChatComponent getChatComponent(EntityMetaDataFields field) {
|
||||||
Object object = get(field);
|
Object object = get(field);
|
||||||
if (object instanceof String string) {
|
if (object instanceof String string) {
|
||||||
return ChatComponent.fromString(string);
|
return ChatComponent.valueOf(string);
|
||||||
}
|
}
|
||||||
return (ChatComponent) object;
|
return (ChatComponent) object;
|
||||||
}
|
}
|
||||||
|
@ -259,7 +259,7 @@ public enum EntityMetaDataFields {
|
|||||||
MINECART_FURNACE_HAS_FUEL(false),
|
MINECART_FURNACE_HAS_FUEL(false),
|
||||||
|
|
||||||
MINECART_COMMAND_BLOCK_COMMAND(""),
|
MINECART_COMMAND_BLOCK_COMMAND(""),
|
||||||
MINECART_COMMAND_BLOCK_LAST_OUTPUT(ChatComponent.fromString("")),
|
MINECART_COMMAND_BLOCK_LAST_OUTPUT(ChatComponent.valueOf("")),
|
||||||
|
|
||||||
PRIMED_TNT_FUSE_TIME(80),
|
PRIMED_TNT_FUSE_TIME(80),
|
||||||
|
|
||||||
|
@ -70,11 +70,11 @@ public class Slot {
|
|||||||
if (nbt.containsKey("display")) {
|
if (nbt.containsKey("display")) {
|
||||||
CompoundTag display = nbt.getCompoundTag("display");
|
CompoundTag display = nbt.getCompoundTag("display");
|
||||||
if (display.containsKey("Name")) {
|
if (display.containsKey("Name")) {
|
||||||
this.customDisplayName = ChatComponent.fromString(display.getStringTag("Name").getValue());
|
this.customDisplayName = ChatComponent.valueOf(display.getStringTag("Name").getValue());
|
||||||
}
|
}
|
||||||
if (display.containsKey("Lore")) {
|
if (display.containsKey("Lore")) {
|
||||||
for (StringTag lore : display.getListTag("Lore").<StringTag>getValue()) {
|
for (StringTag lore : display.getListTag("Lore").<StringTag>getValue()) {
|
||||||
this.lore.add(ChatComponent.fromString(lore.getValue()));
|
this.lore.add(ChatComponent.valueOf(lore.getValue()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,7 +79,7 @@ public class PlayerListItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public ChatComponent getDisplayName() {
|
public ChatComponent getDisplayName() {
|
||||||
return (hasDisplayName() ? displayName : ChatComponent.fromString(name));
|
return (hasDisplayName() ? displayName : ChatComponent.valueOf(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDisplayName(ChatComponent displayName) {
|
public void setDisplayName(ChatComponent displayName) {
|
||||||
|
@ -72,7 +72,7 @@ public class PlayerListItemBulk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public ChatComponent getDisplayName() {
|
public ChatComponent getDisplayName() {
|
||||||
return (hasDisplayName() ? displayName : ChatComponent.fromString(name));
|
return (hasDisplayName() ? displayName : ChatComponent.valueOf(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasDisplayName() {
|
public boolean hasDisplayName() {
|
||||||
|
@ -98,7 +98,7 @@ public class BaseComponent extends ChatComponent {
|
|||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public BaseComponent(@Nullable TextComponent parent, JsonElement data) {
|
public BaseComponent(@Nullable TextComponent parent, JsonElement data) {
|
||||||
TextComponent thisTextComponent = null;
|
MultiChatComponent thisTextComponent = null;
|
||||||
if (data instanceof JsonObject json) {
|
if (data instanceof JsonObject json) {
|
||||||
if (json.has("text")) {
|
if (json.has("text")) {
|
||||||
String text = json.get("text").getAsString();
|
String text = json.get("text").getAsString();
|
||||||
@ -143,7 +143,14 @@ public class BaseComponent extends ChatComponent {
|
|||||||
if (json.has("obfuscated")) {
|
if (json.has("obfuscated")) {
|
||||||
formattingCodes.addOrRemove(PreChatFormattingCodes.OBFUSCATED, json.get("obfuscated").getAsBoolean());
|
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) {
|
if (thisTextComponent != null) {
|
||||||
|
@ -16,6 +16,7 @@ package de.bixilon.minosoft.data.text;
|
|||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import com.google.gson.JsonParseException;
|
import com.google.gson.JsonParseException;
|
||||||
import com.google.gson.JsonParser;
|
import com.google.gson.JsonParser;
|
||||||
|
import com.google.gson.JsonPrimitive;
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
@ -23,19 +24,29 @@ import javafx.scene.Node;
|
|||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
public abstract class ChatComponent {
|
public abstract class ChatComponent {
|
||||||
public static ChatComponent fromString(String raw) {
|
public static ChatComponent valueOf(Object raw) {
|
||||||
return fromString(null, 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) {
|
if (raw == null) {
|
||||||
return new BaseComponent();
|
return new BaseComponent();
|
||||||
}
|
}
|
||||||
|
if (raw instanceof JsonPrimitive primitive) {
|
||||||
|
raw = primitive.getAsString();
|
||||||
|
}
|
||||||
|
|
||||||
JsonObject json;
|
JsonObject json;
|
||||||
try {
|
if (raw instanceof JsonObject) {
|
||||||
json = JsonParser.parseString(raw).getAsJsonObject();
|
json = (JsonObject) raw;
|
||||||
} catch (JsonParseException | IllegalStateException ignored) {
|
} else if (raw instanceof String) {
|
||||||
return new BaseComponent(raw);
|
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);
|
return new BaseComponent(parent, json);
|
||||||
}
|
}
|
||||||
|
52
src/main/java/de/bixilon/minosoft/data/text/ClickEvent.java
Normal file
52
src/main/java/de/bixilon/minosoft/data/text/ClickEvent.java
Normal 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
|
||||||
|
}
|
||||||
|
}
|
63
src/main/java/de/bixilon/minosoft/data/text/HoverEvent.java
Normal file
63
src/main/java/de/bixilon/minosoft/data/text/HoverEvent.java
Normal 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()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -39,7 +39,7 @@ public class TranslatableComponent extends ChatComponent {
|
|||||||
}
|
}
|
||||||
data.forEach((jsonElement -> {
|
data.forEach((jsonElement -> {
|
||||||
if (jsonElement.isJsonPrimitive()) {
|
if (jsonElement.isJsonPrimitive()) {
|
||||||
this.data.add(ChatComponent.fromString(parent, jsonElement.getAsString()));
|
this.data.add(ChatComponent.valueOf(parent, jsonElement.getAsString()));
|
||||||
} else {
|
} else {
|
||||||
this.data.add(new BaseComponent(parent, jsonElement.getAsJsonObject()));
|
this.data.add(new BaseComponent(parent, jsonElement.getAsJsonObject()));
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ public class ServerListPing {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (json.get("description").isJsonPrimitive()) {
|
if (json.get("description").isJsonPrimitive()) {
|
||||||
motd = ChatComponent.fromString(json.get("description").getAsString());
|
motd = ChatComponent.valueOf(json.get("description").getAsString());
|
||||||
} else {
|
} else {
|
||||||
motd = new BaseComponent(json.getAsJsonObject("description"));
|
motd = new BaseComponent(json.getAsJsonObject("description"));
|
||||||
}
|
}
|
||||||
|
@ -200,7 +200,7 @@ public class InByteBuffer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public ChatComponent readTextComponent() {
|
public ChatComponent readTextComponent() {
|
||||||
return ChatComponent.fromString(readString());
|
return ChatComponent.valueOf(readString());
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getLength() {
|
public int getLength() {
|
||||||
|
@ -38,6 +38,7 @@ import java.util.zip.*;
|
|||||||
public final class Util {
|
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 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 RANDOM_STRING_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||||
|
public static final String LINE_SEPARATOR = System.getProperty("line.separator");
|
||||||
private static final Random random = ThreadLocalRandom.current();
|
private static final Random random = ThreadLocalRandom.current();
|
||||||
|
|
||||||
public static UUID getUUIDFromString(String uuid) {
|
public static UUID getUUIDFromString(String uuid) {
|
||||||
@ -167,11 +168,10 @@ public final class Util {
|
|||||||
|
|
||||||
public static String readFile(BufferedReader reader, boolean closeStream) throws IOException {
|
public static String readFile(BufferedReader reader, boolean closeStream) throws IOException {
|
||||||
StringBuilder stringBuilder = new StringBuilder();
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
String ls = System.getProperty("line.separator");
|
|
||||||
String line;
|
String line;
|
||||||
while ((line = reader.readLine()) != null) {
|
while ((line = reader.readLine()) != null) {
|
||||||
stringBuilder.append(line);
|
stringBuilder.append(line);
|
||||||
stringBuilder.append(ls);
|
stringBuilder.append(LINE_SEPARATOR);
|
||||||
}
|
}
|
||||||
stringBuilder.deleteCharAt(stringBuilder.length() - 1);
|
stringBuilder.deleteCharAt(stringBuilder.length() - 1);
|
||||||
if (closeStream) {
|
if (closeStream) {
|
||||||
|
@ -79,11 +79,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.list-cell:selected {
|
.list-cell:selected {
|
||||||
-fx-background-color: -primary-color;
|
-fx-background-color: -primary-dark-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
.list-cell:filled:hover {
|
.list-cell:filled:hover {
|
||||||
-fx-background-color: -primary-dark-color;
|
-fx-background-color: -primary-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu-bar {
|
.menu-bar {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user