本站为非官方 Pylon 文档站,大量内容均为 AI 生成·前往官方文档站● ● ●This is an unofficial Pylon documentation site, most content is AI-generated·Visit Official Docs● ● ●中文开发者交流·加入 QQ 群● ● ●本站为非官方 Pylon 文档站,大量内容均为 AI 生成·前往官方文档站● ● ●This is an unofficial Pylon documentation site, most content is AI-generated·Visit Official Docs● ● ●中文开发者交流·加入 QQ 群● ● ●
Pylon 中文文档
创建附属

函数

介绍 Rebar 函数系统的基础知识。

最后更新时间

物品构造函数

你可能会以为每次创建物品时(比如每次物品被合成时)都会调构造函数。但事实并非如此

关键的一点是:构造函数可以被任意调用,不只是在物品"被创建"的时候

等等……为什么构造函数可以被任意调用?

(叹气) 说来话长……简单讲:

Rebar 没法时刻跟踪每一个物品。如果能改服务端核心代码的话倒是可以。但事实上,Rebar 只能临时跟踪 Rebar 物品。

比如,当我们用一个实现了 RebarItemEntityInteractor 的物品右键实体时,Rebar 会监听 PlayerInteractEntityEvent,发现有个实体被某个物品右键了。为了搞清楚这是什么物品——以及它到底是不是 Rebar 物品——Rebar 得查看存储在物品里的键。但即使 Rebar 知道了键,它对这个物品的了解也有限。这个物品实现了 RebarItemEntityInteractor 吗?如果实现了,Rebar 就需要调它的 onUsedToRightClickEntity

这时候就要靠构造函数了。我们可以查到该物品对应的类,创建一个新实例,然后调用 onUsedToRightClickEntity 方法。

总结一下:这个类可以在任何时候被创建或销毁。字段里存的数据都是临时的。

但假设我们想存便携电池的电量。既然字段存不了电量,那到底能存哪呢?


持久化数据容器 (PDCs)

PDC 是 Paper 加的,不是 Pylon 的。之所以在这里介绍,是因为 Pylon 里几乎所有持久化数据存储(包括方块和实体)都用到了它。

PersistentDataContainer(PDC)是一种简单直接的持久化数据存储方式。结构上类似 JSON——嵌套的键值对存储。每个值用 NamespacedKey 标识。PDC 可以互相嵌套。物品自带一个 PDC,所以要持久保存数据,就得在修改时写入物品的 PDC。

PDC 更多信息看 Paper 文档

举个例子:记录便携电池的电量。把电量存到物品 PDC 里,键名叫 charge_level。不管物品放进箱子还是服务器重启,数据都还在。

听着有点晕的话别急,看个例子就明白了。


计数法棍

想法

做一个能存数字的"计数法棍"。右键时,法棍把存的数字发到你聊天框,然后数字 +1。

创建物品

先做一个还不能计数的法棍。

MyAddonKeys.java
public class MyAddonKeys {
    public static final NamespacedKey countingBaguetteKey = new NamespacedKey(this, "counting_baguette");
}
MyAddonItems.java
public final class ExampleAddonItems {

    // ...

    public static final ItemStack countingBaguette = ItemStackBuilder.rebar(Material.BREAD, countingBaguetteKey)
            .build();

    // ...

    public static void initialize() {

        // ...

        RebarItem.register(CountingBaguette.class, countingBaguette);
        PylonPages.FOOD.addItem(countingBaguette);
    }
}
CountingBaguette.java
public class CountingBaguette extends RebarItem {
    public CountingBaguette(@NotNull ItemStack stack) {
        super(stack);
    }
}
en.yml
item:
  counting_baguette:
    name: "Counting Baguette"
    lore: |-
      <arrow> Mathematics is improved tenfold when combined with baguettes

添加计数逻辑

先检测玩家右键操作:

CountingBaguette.java
public class CountingBaguette extends RebarItem implements RebarInteractor {
    public CountingBaguette(@NotNull ItemStack stack) {
        super(stack);
    }

    @Override
    public void onUsedToClick(@NotNull PlayerInteractEvent event, @NotNull EventPriority priority) {
        // TODO 发送存储的值给玩家
        // TODO 增加存储的值
    }
}

在方法里,读取存的值,发给玩家,再存回 +1 后的值。

往 PDC 存数据还需要两样东西:标识这条数据的 NamespacedKey,以及数据的类型(PersistentDataType)。

PylonSerializers

方便起见,Pylon 在 PylonSerializers 里提供了很多类型。包括 Paper 默认的所有类型,还额外加了一些(如 UUID、Vector、BlockPosition、ItemStack 等)。

CountingBaguette.java
public class CountingBaguette extends RebarItem implements RebarInteractor {
    public static final NamespacedKey COUNT_KEY = new NamespacedKey(MyAddon.getInstance(), "count");

    public CountingBaguette(@NotNull ItemStack stack) {
        super(stack);
    }

    @Override
    public void onUsedToClick(@NotNull PlayerInteractEvent event, @NotNull EventPriority priority) {
        int count = getStack().getPersistentDataContainer().get(COUNT_KEY, PylonSerializers.INTEGER);
        event.getPlayer().sendMessage(String.valueOf(count));
        getStack().editPersistentDataContainer(pdc -> pdc.set(COUNT_KEY, PylonSerializers.INTEGER, count + 1));
    }
}

设置默认值

你可能注意到还没设初始值。来加上:

CountingBaguette.java
NamespacedKey countingBaguetteKey = new NamespacedKey(this, "counting_baguette");
ItemStack countingBaguette = ItemStackBuilder.rebar(Material.BREAD, countingBaguetteKey)
        .editPdc(pdc -> pdc.set(CountingBaguette.COUNT_KEY, PylonSerializers.INTEGER, 0))
        .build();
RebarItem.register(CountingBaguette.class, countingBaguette);
PylonPages.FOOD.addItem(countingBaguette);

搞定!只要物品还在,存的数据就一直在。

目录