🧵 生命链接#

本示例展示使用Bookshelf的bs.health模块构建的生命链接系统。该系统将多名玩家的生命值相互绑定,使任一玩家的生命值变化自动同步至所有关联玩家。

原生Minecraft缺乏精确治疗玩家的可靠方法,替代方案常导致时序问题。Bookshelf通过确保生命值更新的一致性解决此问题,允许你在游戏刻的任何时刻获取当前生命值(即使存在待处理变更),无需担心刻安全性问题。


🎯 构建目标#

生命链接系统将实现:

  1. 检测玩家生命值变化时刻

  2. 查找所有关联玩家

  3. 将生命值变化同步至所有关联玩家


📦 准备工作#

开始前请确保具备:

  • Minecraft Java版

  • 基础Minecraft数据包知识(函数、标签、记分板)

  • 已安装Bookshelf的bs.health模块(安装指南参见快速入门

    • @require bookshelf.module.health


🛠️ 分步指南#

1. Prepare the Datapack#

首先创建数据包加载时运行的函数lifestring:load,将其注册到minecraft:load标签中。这个函数用于初始化记分板项。


➔ 创建load函数

@function lifestring:load

scoreboard objectives add lifestring.link dummy
scoreboard objectives add lifestring.health dummy
  • lifestring.link:存储玩家链接ID。相同ID的玩家共享生命值。

  • lifestring.health:存储玩家上一游戏刻的生命值,用于检测变化。

➔ 注册到load标签

@function_tag minecraft:load

{
  "values": [
    "lifestring:load"
  ]
}

lifestring:load添加至此标签可确保数据包启用或重载时自动运行。



3. Detect Health Changes#

需创建持续检测玩家生命值变化的函数:- lifestring:tick:每游戏刻自调度执行- lifestring:check:为每个玩家执行

lifestring:check函数比较玩家当前生命值与上一刻存储值(@s lifestring.health)。若存在差异则运行lifestring:change


➔ 更新load函数

@function lifestring:load

scoreboard objectives add lifestring.link dummy
scoreboard objectives add lifestring.health dummy
schedule function lifestring:tick 1t

➔ 创建tick函数

@function lifestring:tick

execute as @a[scores={lifestring.link=1..}] run function lifestring:check
schedule function lifestring:tick 1t

➔ 创建check函数

@function lifestring:check

execute store result score #this lifestring.health run function #bs.health:get_health {scale:1000}
scoreboard players operation #this lifestring.health -= @s lifestring.health
execute unless score #this lifestring.health matches 0 if score @s lifestring.health matches 0.. run function lifestring:change
scoreboard players operation @s lifestring.health += #this lifestring.health

获取当前生命值(按1000倍缩放存储),减去上一刻生命值得出*#this中的变化量。若非零则运行变更函数。第二次条件检查确保玩家存在lifestring.health*分数,随后将变化量添加至玩家生命值分数。

➔ 创建change函数

@function lifestring:change

say Health Changed!

当关联玩家生命值变化时,lifestring:change函数触发,该玩家将在聊天中发送消息。


4. Find Linked Players#

已知玩家生命值变化时机,需查找具有相同*lifestring.link*分数的其他玩家。可通过谓词实现。


➔ 创建is_linked谓词

@predicate lifestring:is_linked

{
  "condition": "minecraft:entity_scores",
  "entity": "this",
  "scores": {
    "lifestring.link": {
      "min": {
        "type": "minecraft:score",
        "target": {
          "type": "minecraft:fixed",
          "name": "#this"
        },
        "score": "lifestring.link"
      },
      "max": {
        "type": "minecraft:score",
        "target": {
          "type": "minecraft:fixed",
          "name": "#this"
        },
        "score": "lifestring.link"
      }
    }
  }
}

此谓词检查被评估实体("this")的*lifestring.link分数是否等于临时分数#this*中存储的值。

➔ 更新change函数

@function lifestring:change

scoreboard players operation #this lifestring.link = @s lifestring.link
execute as @a[predicate=lifestring:is_linked] run say Health Changed!

当玩家生命值变化时,所有关联玩家将发送"生命值变化!"消息。但需仅更新其他关联玩家(排除变化源玩家)。可通过临时交换*#this*分数与变化源玩家的链接ID实现。

➔ 更新change函数

@function lifestring:change

scoreboard players operation #this lifestring.link >< @s lifestring.link
execute as @a[predicate=lifestring:is_linked] run say Health Changed!
scoreboard players operation #this lifestring.link >< @s lifestring.link

*><运算符交换分数值:1. 将#this与玩家链接ID交换2. 查找所有关联玩家(此时原玩家链接ID在#this*中故被排除)3. 发送消息4. 交换回原始分数


5. Update Players Health#

将存储于*#this*的生命值变化量应用于所有关联玩家。通过新建lifestring:update函数调用Bookshelf的#bs.health:add_health实现。


➔ 更新change函数

@function lifestring:change

execute store result storage lifestring:update points double 0.001 run scoreboard players get #this lifestring.health

scoreboard players operation #this lifestring.link >< @s lifestring.link
execute as @a[predicate=lifestring:is_linked] run function lifestring:update
scoreboard players operation #this lifestring.link >< @s lifestring.link

➔ 创建update函数

@function lifestring:update

function #bs.health:add_health with storage lifestring:update
scoreboard players operation @s lifestring.health += #this lifestring.health

此方案存在潜在问题:#bs.health:add_health无法治疗超过玩家最大生命值。由于未限制*lifestring.health*分数,可能超出最大值。需定义分数上限值避免此问题。

➔ 更新update函数

@function lifestring:update

function #bs.health:add_health with storage lifestring:update
scoreboard players operation @s lifestring.health += #this lifestring.health
execute store result score #max lifestring.health run attribute @s minecraft:max_health get 1000
scoreboard players operation @s lifestring.health < #max lifestring.health

<运算符将分数设为最小值,确保@s lifestring.health不超过#max lifestring.health


✔️ 结语#

本系统是Bookshelf简化复杂任务的典范,实现了关联玩家共享伤害与治疗。你可通过以下方向进一步优化:

  1. 差异化初始生命值:若关联玩家初始生命值不同,应同步为相同百分比还是相同具体值?

  2. 最大生命值:是否累加关联玩家的最大生命值?若某玩家最大生命值变化(如药水效果),如何影响其他玩家?

  3. 玩家登录:关联玩家退出后重进时,是否会保存生命值并与组内同步?

尝试实现这些构想,定制属于你的生命链接系统!


💬 这对你有帮助吗?

欢迎在下方留下你的问题与反馈!