动态浮动数字库

动态浮动数字库

独立的、可配置的浮动伤害数字API,适用于Hytale模组。

图书馆

DynamicFloatingDamageFormatter

独立、可配置的浮动伤害数字 API,适用于 Hytale 模组。

此包可作为插件(带适配器)分发,或作为纯 API(核心)供其他模组直接调用。

包含内容

  1. DynamicFloatingDamageFormatter-core.jar 仅 API。其他模组自行调用 DamageNumbers.emit(...)

  2. DynamicFloatingDamageFormatter-with-adapter.jar API + 适配器(DamageNumberEST),自动挂钩伤害事件并生成战斗文本。

快速安装(无需代码)

  1. DynamicFloatingDamageFormatter-with-adapter.jar 放入服务器的 mods/ 文件夹。
  2. examples/Server/Entity/UI/ 中的 UI JSON 文件复制到你的资源包中。
  3. examples/Server/Config/DamageNumberConfig.json 复制到你的资源包中。

这将立即根据配置的类型替换/增强战斗文本。

API 用法(代码集成)

将核心 jar 添加为依赖项,并在你自己的伤害代码运行时生成伤害数字。

注册一种类型(可选但推荐)

import irai.mod.DynamicFloatingDamageFormatter.DamageNumbers;

DamageNumbers.kind("POISON")
    .label("Poison")
    .ui("SocketReforge_CombatText_Poison")
    .dot(true)
    .register();

直接生成数字

DamageNumbers.emit(store, targetRef, amount, "POISON");

如果你已有 Damage 对象

DamageNumbers.attachTarget(damage, targetRef);
DamageNumbers.emit(damage);

抑制基础战斗文本(可选)

DamageNumbers.markSkipCombatText(damage);

DynamicFloatingDamageFormatter 教程

这是一个实用的端到端指南,介绍如何在你自己的模组中使用格式化器。内容包括:

  • 即插即用(无需代码)。
  • 核心 API 用法(在你自己的伤害事件中调用)。
  • 配置和 UI 资源自定义。

快速安装(无需代码)

如果你希望自动挂钩伤害事件,请使用带适配器的构建。

  1. DynamicFloatingDamageFormatter-with-adapter.jar 放入服务器的 mods/ 文件夹。
  2. examples/Server/Entity/UI/*.json 复制到你的资源包中。
  3. examples/Server/Config/DamageNumberConfig.json 复制到你的资源包中。

就这样。适配器将为符合你配置的任何伤害生成战斗文本。


挂钩与注册(插件设置)

如果你希望格式化器自动挂钩伤害,你的插件需要:

  1. 加载并应用 DamageNumberConfig.json
  2. 注册一个生成数字的 DamageEventSystem(适配器系统)。

示例插件设置:

import javax.annotation.Nonnull;

import com.hypixel.hytale.server.core.plugin.JavaPlugin;
import com.hypixel.hytale.server.core.plugin.JavaPluginInit;
import com.hypixel.hytale.server.core.util.Config;
import com.hypixel.hytale.server.core.modules.entity.damage.DamageEventSystem;

import irai.mod.DynamicFloatingDamageFormatter.DamageNumberConfig;
import irai.mod.DynamicFloatingDamageFormatter.DamageNumbers;

public final class MyPlugin extends JavaPlugin {
    private final Config<DamageNumberConfig> damageConfig;

    public MyPlugin(@Nonnull JavaPluginInit init) {
        super(init);
        this.damageConfig = this.withConfig("DamageNumberConfig", DamageNumberConfig.CODEC);
    }

    @Override
    protected void setup() {
        // 加载配置并应用它。
        damageConfig.save().join();
        DamageNumbers.applyConfig(damageConfig.get());

        // 注册你的适配器系统(继承 DamageEventSystem)。
        this.getEntityStoreRegistry().registerSystem(new MyDamageNumberEST());
    }
}

如果你没有适配器系统,你仍然可以使用核心 API 手动生成数字。

核心 API 用法(代码集成)

如果你想要完全控制,依赖核心 jar 并自行生成数字。

示例:在你自己的伤害代码运行时生成一个自定义类型。

import irai.mod.DynamicFloatingDamageFormatter.DamageNumbers;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;

public void onMyDamage(Store<EntityStore> store, Ref<EntityStore> target, float amount) {
    DamageNumbers.emit(store, target, amount, "POISON");
}

如果你已有 Damage 对象并希望格式化器选择类型:

import irai.mod.DynamicFloatingDamageFormatter.DamageNumbers;
import com.hypixel.hytale.server.core.modules.entity.damage.Damage;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;

public void onDamage(Damage damage, Ref<EntityStore> target) {
    DamageNumbers.attachTarget(damage, target);
    DamageNumbers.emit(damage);
}

标记伤害元数据

你可以通过向 Damage 对象附加元数据来指导格式化器。

DamageNumbers.markKind(damage, "BLEED");      // 强制使用类型
DamageNumbers.markCritical(damage);           // 强制使用 CRITICAL 类型
DamageNumbers.markSkipCombatText(damage);     // 抑制基础战斗文本

如果你已经使用了 DamageCause 但想要自定义样式,这会特别有用。


配置基础

配置文件位于:

Server/Config/DamageNumberConfig.json

它使用三个数组:

  • DEFAULTS – 全局格式化规则
  • KINDS – 每种类型的样式
  • ALIASES – 将伤害原因 ID 映射到类型

示例:

{
  "DEFAULTS": [
    "format={label} {amount}",
    "rounding=ROUND",
    "min=1",
    "precision=2",
    "style=PLAIN",
    "labelByDefault=true"
  ],
  "KINDS": [
    "POISON|label=Poison|icon=<item is=\"Ingredient_Poison\"/>|format={icon}{label} {amount}|color=#008700|ui=SocketReforge_CombatText_Poison|dot=true"
  ],
  "ALIASES": [
    "poison=POISON",
    "toxic=POISON"
  ]
}

支持的 KINDS 键:

  • label
  • icon(原始标记,插入到 {icon}
  • iconBg(背景标记,插入到 {iconBg}
  • iconOverlay(覆盖层标记,插入到 {iconOverlay}
  • format(支持 {iconBg}{icon}{iconOverlay}{label}{amount}{kind}
  • color
  • ui(主要 UI 组件 ID)
  • uiAlt(备用 UI ID,每次命中切换)
  • dot(视为 DoT,用于角度/随机化)
  • roundingROUNDFLOORCEILNONE
  • precision
  • min
  • stylePLAINMESSAGETOOLTIP
  • labelByDefault

别名通过子字符串匹配 DamageCause.getId()


UI 资源基础

每个 ui=... 指向一个包含 "Type": "CombatText"Server/Entity/UI/*.json 资源。

你可以调整的关键字段:

  • RandomPositionOffsetRange – 每次命中的随机 X/Y 偏移量
  • HitboxOffset – 基础偏移量
  • AnimationEvents – 缩放、淡出和计时
  • HitAngleModifierStrength – 命中角度对运动的影响程度

如果你设置了 uiAlt,格式化器会在主要和备用组件之间交替以减少重叠。

图标字符串会原样注入到战斗文本中。如果你的客户端支持,你可以使用:

  • <item is="Item_Id"/> 用于物品图标
  • <img src="texture.png" width="16" height="16"/> 用于图像标签

要将背景/覆盖层与图标分层,请在你的格式字符串中包含 {iconBg}{iconOverlay},例如:

format={iconBg}{icon}{iconOverlay}{label} {amount}


DoT 示例

在 DoT 的每次跳动时,直接生成数字:

DamageNumbers.emit(store, targetRef, perTickDamage, "BURN");

在配置中设置 dot=true 以允许 DoT 跳动有更广泛的角度随机化。


仅格式化(无战斗文本)

如果你只想要格式化的字符串:

String text = DamageNumbers.format(amount, "POISON");

粒子用法(可选)

如果你希望使用基于粒子的数字和图标而不是 UI CombatText,请将粒子键添加到你的 KINDS 条目中:

  • particleFont=FloatingDamage_<KIND>(数字)
  • particleIcon=FloatingDamage_Icon_<Kind>(图标)
  • particleBackground=FloatingDamage_Background(可选)

示例(粒子数字 + 图标):

POISON|label=|color=#008700|ui=SocketReforge_CombatText_Poison|dot=true|particleFont=FloatingDamage_POISON|particleIcon=FloatingDamage_Icon_Poison

示例(仅 UI,无粒子):

POISON|label=|color=#008700|ui=SocketReforge_CombatText_Poison|dot=true

注意:

  • 粒子资源位于 Common/Particles/FloatingDamage/Server/Particles/FloatingDamage/ 下。
  • 如果没有设置 particleFont,格式化器将回退到 CombatText UI。

故障排除

  • 基础白色伤害数字仍然显示: 调用 DamageNumbers.markSkipCombatText(damage) 或禁用基础战斗文本。
  • 没有随机化: 确保你的 UI JSON 包含 RandomPositionOffsetRange,并且你的 dot=true 类型确实被标记为 DoT。

由 iRaiden 制作