我正在为 Spigot 1.20.4 (Java) 开发一个雕像插件,用于创建 NPC 雕像。目前,当您创建雕像时,您可以使用消费者来定义右键单击该 NPC 时会发生什么。
Statue.StatueBuilder builder = new Statue.StatueBuilder(entityType)
.setName("Test")
.setOnClick(connectionPlayer -> System.out.println("TEST " + new Random().nextInt()));
Statue statue = builder.build();
#setOnClick 接受 StatueAction,其定义为:
public interface StatueAction {
void perform(ConnectionPlayer player);
}
我需要保存这些数据(yml、json 等),这样当服务器重新启动时,雕像将再次生成。但是,我无法序列化消费者。尝试使用 YML 和 JSON。我明白为什么,但不知道如何解决它。
关于如何将 onClick 操作保存到文件有什么想法吗?或者,如果这不是一个好方法,我可能会采取其他方法来实现类似的目标,有什么想法吗? 我确实研究了如何序列化 lambda?,但是似乎这些都不能正常工作(对我来说),这意味着我一定做错了一些事情。
这是我目前正在尝试序列化它的方式
StatueAction<ConnectionPlayer> r = (connectionPlayer) -> System.out.println("Hello");
Statue.StatueBuilder builder = new Statue.StatueBuilder(entityType).setName("Test").setOnClick(r);
Statue statue = builder.build();
statue.spawn(player.getLocation());
statue.createDefaultAttribs();
System.out.println(statue.serialize());
输出是
{"name":"Test","entityType":"ARMOR_STAND","entityUUID":"6c2a484c-3168-4fb8-a3ee-8c2d93bddf1d","textDisplaysID":[],"onClick":{}}
Statue序列化方法定义为
public static class StatueSerializer implements JsonSerializer<Statue> {
@Override
public JsonElement serialize(Statue statue, Type type, JsonSerializationContext jsonSerializationContext) {
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("name", statue.name);
jsonObject.addProperty("entityType", statue.entityType.name());
jsonObject.addProperty("entityUUID", statue.getEntityUUID().toString());
jsonObject.add("textDisplaysID", jsonSerializationContext.serialize(statue.getTextDisplaysID()));
// Serialize the CustomAction using its own serialization logic
jsonObject.add("onClick", jsonSerializationContext.serialize(statue.getOnClick()));
return jsonObject;
}
}
public String serialize() {
Gson gson = new GsonBuilder()
.registerTypeAdapter(Statue.class, new Statue.StatueSerializer())
.create();
return gson.toJson(this);
}
如果您只有静态数量的可能操作,那么您可以使用一个枚举,其常量代表这些操作,而不是使用接口,然后仅序列化操作的名称/常量名称。
这类似于 Minecraft 本身如何序列化文本组件的
clickEvent
和 hoverEvent
操作。
另一种选择可能是向您的
serialize
接口添加 StatueAction
方法,以便实现可以序列化所有必要的数据。但是,您还必须包含一些标识符,并拥有一些“注册表”,在反序列化时,根据 JSON 数据中的标识符查找操作类。查看有关 Gson 和多态性的其他问题。Class.forName
进行反序列化,即使它看起来很方便,因为如果 JSON 数据可能以某种方式受到不受信任的用户的影响,那么他们将允许他们创建可能被利用的任意类的实例。