VolatileEntities

VolatileEntities

VolatileEntities 是一个基于 ECS 的 Hytale 框架,它允许你创建和管理非持久性或时间控制的实体,而不会在世界中留下“垃圾”。

图书馆

VolatileEntities

VolatileEntities 是一个基于 ECS 的 Hytale 框架,允许你创建和管理非持久化时间控制实体,且不会在世界中留下“垃圾”。

它旨在:

  • 提供对实体生命周期的精细控制(距离、超时、所有者断开连接等),
  • 在服务器重启时自动清理实体,
  • 并在你的插件卸载后确保清理。

核心功能

重启时的自动非持久化

任何带有 VolatileComponent 的实体都会在服务器重启后的第一个游戏刻自动移除,这得益于:

  • 组件编解码器 (VolatileComponent.CODEC) 处理的 expiredOnLoad 标志,
  • 以及 VolatileTickSystem 系统会销毁“从磁盘加载”的易失实体。

这保证了易失实体永远不会在重启后存活,即使它们曾被保存到磁盘。


运行时灵活 TTL(插件运行时)

使用 VolatileConfigVolatilePolicy,你可以精确控制实体在运行时的存活时间:

  • IDLE_TIMEOUT – 在 X 个游戏刻或秒无活动后消失,
  • MAX_DISTANCE – 当与链接实体距离过远时消失,
  • LINKED_ENTITY_INVALID – 当链接实体变得无效时消失,
  • CUSTOM – 通过 VolatileContext 上的谓词实现完全自定义的消失逻辑。

所有这些都在你的插件加载时由 VolatileTickSystem 评估。


策略组合

策略不是排他性的

单个易失实体可以同时组合多个策略。实体将在任何策略条件满足时立即被移除。

例如,一个实体可以:

  • 在 10 秒不活动后消失(IDLE_TIMEOUT),
  • 或者在与目标距离过远时消失(MAX_DISTANCE),
  • 或者在其所有者断开连接时被移除(OWNER_DISCONNECT)。

这让你无需编写自定义代码即可表达复杂的生命周期。

VolatileEntities.builder()
    .withinDistance(targetRef, 30f)
    .idleTimeoutSeconds(10f)
    .ownedBy(playerUuid)
    .spawn(commandBuffer);

组合易失策略(示例)

此示例演示如何将多个 VolatilePolicy 规则组合到一个 VolatileConfig 中。

策略不是排他性的:一个实体可以同时应用多个生命周期规则。

实体将在任何策略条件满足时被移除。


示例:与另一个实体绑定的区块边界实体

VolatileConfig.VolatileConfigBuilder configBuilder = VolatileConfig.builder()
        // 区块卸载时自动移除实体
        .policy(VolatilePolicy.CHUNK_UNLOAD)

        // 一旦策略条件变为无效,立即移除
        .removeOnInvalid(true);

// 可选地将此易失实体链接到另一个实体(例如,一个怪物或 NPC)
if (linkedEntity != null) {
        configBuilder
        .policy(VolatilePolicy.LINKED_ENTITY_INVALID)
        .linkedEntity(linkedEntity);
}

VolatileConfig config = configBuilder.build();
return new VolatileComponent(config);

使用 Hytale 的 DespawnComponent 实现绝对 TTL(区块卸载/重载安全)

VolatileEntities 与 Hytale 原版系统干净地集成:

  • DespawnComponent + DespawnSystem 处理绝对、实时 TTL,
  • USE_DESPAWN_TTL 策略告诉 VolatileEntities 将 TTL 处理完全委托DespawnComponent

这意味着:

  • TTL 基于实时(TimeResource),而非游戏刻,
  • 区块卸载/重载是安全的,
  • 如果区块重载时消失时间已过,实体立即被移除。

因此,你可以选择:

  • 运行时、仅联机 TTLIDLE_TIMEOUT),或
  • 绝对 TTL,即使在卸载时也继续计时(USE_DESPAWN_TTL + DespawnComponent)。

插件卸载后的清理

为了解决经典的“移除模组后实体残留”问题,VolatileEntities 使用了一种保活模式:

  • VolatileDespawnKeepAliveSystem 持续刷新易失实体上的原版 DespawnComponent(使用 USE_DESPAWN_TTL 的除外),
  • 当你的插件安装时,消失截止时间被不断向前推,
  • 一旦你的插件被移除,最后的消失截止时间最终会到达。

此时,Hytale 的核心 DespawnSystem 会自动清理所有剩余的易失实体,即使你的插件已不存在。

无需手动扫描世界。没有孤儿实体。


高级策略

除了核心 TTL 策略外,该框架还支持:

  • CHUNK_UNLOAD – 当区块卸载时自动移除易失实体(由 VolatileChunkUnloadSystem 处理,这是一个 EntityEventSystem<ChunkUnloadEvent>)。
  • OWNER_DISCONNECT – 当玩家断开连接时,标记或移除属于该玩家的易失实体(由 VolatileOwnerDisconnectListener 处理,监听 PlayerDisconnectEvent)。

将这些策略组合在一起,为临时实体提供了强大的生命周期工具集。


典型用例

使用 VolatileEntities 将以下实体标记为易失:

  • 全息投影,
  • 弹射物,
  • 视觉效果,
  • 临时 NPC,
  • 辅助或标记实体

使它们:

  • 在重启时消失,
  • 可选地遵循运行时规则(超时、距离、所有权、自定义逻辑),
  • 并且仍保证在插件卸载后被清理。

使用示例

1) 将现有实体标记为易失(仅重启)

如果你已经手动生成了一个实体(例如全息投影),你可以简单地附加一个 VolatileComponent 使其非持久化。

holder.addComponent(
    VolatileComponent.getComponentType(),
    VolatileComponent.restartOnly()
);

结果:

  • 实体在服务器运行期间存在,
  • 在重启后的第一个游戏刻被移除,
  • 卸载安全清理仍然适用。

2) 绝对 TTL(10 秒实时)

要在固定实时时间后消失实体(即使跨越区块卸载),结合使用 DespawnComponentUSE_DESPAWN_TTL

holder.addComponent(
    DespawnComponent.getComponentType(),
    DespawnComponent.despawnInSeconds(time, 10f)
);

VolatileConfig cfg = VolatileConfig.builder()
    .policy(VolatilePolicy.USE_DESPAWN_TTL)
    .build();

holder.addComponent(
    VolatileComponent.getComponentType(),
    new VolatileComponent(cfg)
);

这里:

  • Hytale 自行处理 TTL,
  • VolatileEntities 不会刷新消失时间,
  • 重启和卸载清理仍然得到保证。

3) 标记一个已存在的实体为易失

你可以在实体已经存在后将其标记为易失:

store.putComponent(
    ref,
    VolatileComponent.getComponentType(),
    VolatileComponent.restartOnly()
);

无需重新生成或手动消失逻辑。


API 参考(快速概览)

VolatileComponent – 工厂方法

  • restartOnly() – 仅运行时有效,重启时移除
  • withTimeout(int ticks) / withTimeoutSeconds(float seconds, int tickRate)
  • withinDistance(Ref<EntityStore> target, float distance)
  • linkedTo(Ref<EntityStore> target)
  • ownedBy(UUID playerUuid)
  • useDespawnTtl()

VolatileConfig

用于高级控制的预设和构建器:

  • chunkBound()
  • linkedTo(ref)
  • withinDistance(ref, distance)
  • ownedBy(playerUuid)
  • withTimeout(ticks)
  • useDespawnTtl()
  • custom(ctx -> { ... })

VolatileEntities.builder()

为了方便,构建器 API 提供了流畅的方式来生成易失实体:

VolatileEntities.builder()
    .at(new Vector3d(x, y, z))
    .with(MyComponent.TYPE, new MyComponent(...))
    .withinDistance(targetRef, 50f)
    .idleTimeoutSeconds(10f)
    .spawn(commandBuffer);

安装

  1. VolatileEntities JAR 文件放入你的服务器的插件文件夹。

  2. 在你的插件清单中声明依赖:

{
  "Group": "Ender_Griefeur99",
  "Name": "MyPlugin",
  "Version": "1.0.0",
  "Main": "fr.ender_griefeur99.myplugin.MyPlugin",
  "ServerVersion": "*",
  "IncludesAssetPack": false,
  "Dependencies": {
    "Ender_Griefeur99:VolatileEntities": "*"
  }
}