ViaVersion/common/src/main/java/com/viaversion/viaversion/rewriter/ComponentRewriter.java

205 lines
6.9 KiB
Java
Raw Normal View History

/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
2023-01-12 12:45:53 +01:00
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* 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 <http://www.gnu.org/licenses/>.
*/
2021-04-26 21:16:10 +02:00
package com.viaversion.viaversion.rewriter;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
2021-04-16 23:05:31 +02:00
import com.google.gson.JsonParser;
import com.google.gson.JsonPrimitive;
2020-07-28 09:59:35 +02:00
import com.google.gson.JsonSyntaxException;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
/**
* Handles json chat components, containing methods to override certain parts of the handling.
* Also contains methods to register a few of the packets using components.
*/
public class ComponentRewriter<C extends ClientboundPacketType> {
protected final Protocol<C, ?, ?, ?> protocol;
public ComponentRewriter(Protocol<C, ?, ?, ?> protocol) {
this.protocol = protocol;
}
/**
* Use empty constructor if no packet registering is needed.
*/
public ComponentRewriter() {
this.protocol = null;
}
2021-04-10 17:03:43 +02:00
/**
* Processes components at the beginning of the packet.
* Used for packets that have components as their very first value, so no special pre-reading is necessary.
*
* @param packetType clientbound packet type
*/
public void registerComponentPacket(C packetType) {
protocol.registerClientbound(packetType, new PacketHandlers() {
@Override
public void register() {
handler(wrapper -> processText(wrapper.passthrough(Type.COMPONENT)));
}
});
}
2021-11-21 11:12:13 +01:00
@Deprecated/*(forRemoval = true)**/
public void registerChatMessage(C packetType) {
2021-04-10 17:03:43 +02:00
registerComponentPacket(packetType);
}
public void registerBossBar(C packetType) {
protocol.registerClientbound(packetType, new PacketHandlers() {
@Override
public void register() {
map(Type.UUID);
map(Type.VAR_INT);
handler(wrapper -> {
int action = wrapper.get(Type.VAR_INT, 0);
if (action == 0 || action == 3) {
processText(wrapper.passthrough(Type.COMPONENT));
}
});
}
});
}
2021-04-10 17:03:43 +02:00
/**
* Handles sub 1.17 combat event components.
*/
public void registerCombatEvent(C packetType) {
protocol.registerClientbound(packetType, new PacketHandlers() {
@Override
public void register() {
handler(wrapper -> {
if (wrapper.passthrough(Type.VAR_INT) == 2) {
wrapper.passthrough(Type.VAR_INT);
wrapper.passthrough(Type.INT);
processText(wrapper.passthrough(Type.COMPONENT));
}
});
}
});
}
2021-04-10 17:03:43 +02:00
/**
* Handles sub 1.17 title components.
*/
public void registerTitle(C packetType) {
protocol.registerClientbound(packetType, new PacketHandlers() {
@Override
public void register() {
handler(wrapper -> {
int action = wrapper.passthrough(Type.VAR_INT);
if (action >= 0 && action <= 2) {
processText(wrapper.passthrough(Type.COMPONENT));
}
});
}
});
}
public JsonElement processText(String value) {
2020-07-28 09:59:35 +02:00
try {
2021-04-16 23:05:31 +02:00
JsonElement root = JsonParser.parseString(value);
2020-07-28 09:59:35 +02:00
processText(root);
return root;
} catch (JsonSyntaxException e) {
if (Via.getManager().isDebug()) {
Via.getPlatform().getLogger().severe("Error when trying to parse json: " + value);
throw e;
}
// Yay to malformed json being accepted
return new JsonPrimitive(value);
2020-07-28 09:59:35 +02:00
}
}
public void processText(JsonElement element) {
if (element == null || element.isJsonNull()) return;
if (element.isJsonArray()) {
processAsArray(element);
return;
}
if (element.isJsonPrimitive()) {
handleText(element.getAsJsonPrimitive());
return;
}
JsonObject object = element.getAsJsonObject();
JsonPrimitive text = object.getAsJsonPrimitive("text");
if (text != null) {
handleText(text);
}
JsonElement translate = object.get("translate");
if (translate != null) {
handleTranslate(object, translate.getAsString());
JsonElement with = object.get("with");
if (with != null) {
processAsArray(with);
}
}
JsonElement extra = object.get("extra");
if (extra != null) {
processAsArray(extra);
}
JsonObject hoverEvent = object.getAsJsonObject("hoverEvent");
if (hoverEvent != null) {
handleHoverEvent(hoverEvent);
}
}
protected void handleText(JsonPrimitive text) {
// To override if needed
}
protected void handleTranslate(JsonObject object, String translate) {
// To override if needed
}
// To override if needed (don't forget to call super if needed)
protected void handleHoverEvent(JsonObject hoverEvent) {
String action = hoverEvent.getAsJsonPrimitive("action").getAsString();
if (action.equals("show_text")) {
JsonElement value = hoverEvent.get("value");
processText(value != null ? value : hoverEvent.get("contents"));
} else if (action.equals("show_entity")) {
JsonObject contents = hoverEvent.getAsJsonObject("contents");
if (contents != null) {
processText(contents.get("name"));
}
}
}
private void processAsArray(JsonElement element) {
for (JsonElement jsonElement : element.getAsJsonArray()) {
processText(jsonElement);
}
}
2020-08-16 16:24:06 +02:00
public <T extends Protocol<C, ?, ?, ?>> T getProtocol() {
2020-08-16 16:24:06 +02:00
return (T) protocol;
}
}