Starsector Nihilism Guidance
首页
GitHub 项目
首页
GitHub 项目
  • 首页
  • 基础及舰船相关
    • MOD 骨架和入口文件
    • 制作一艘基本舰船
    • 制作一艘航母与战机
    • 制作一艘相位舰
    • 制作火炮、光束与导弹
    • 为舰船加入内置武器、船插与战机
    • 补充描述文本
  • 无需入门的代码修改
    • 以船插为例初步熟悉代码
    • 制作完整船插
    • 制作最小战术系统
    • 为武器加入命中与光束特效
  • 势力与生涯星系
    • 注册一个势力
    • 配置势力舰队
    • 制作 MOD 入口类的最基础适配
    • 制作一个生涯星系
    • 补完描述文本
  • 战役与无代码对象
    • 制作测试战役装配
    • 为模拟战与标题画面加入装配
    • 为舰船加入外观风格
    • 制作一艘模块船
    • 制作一种星体类型
    • 制作一个自定义实体
  • 音频资源与播放
    • 准备 OGG 音频资源
    • 注册音频资源
    • 为游戏对象加入音频
  • Java 工程化
    • 确认 Java 与编译依赖
    • 迁移代码文件到 src
    • 配置 Gradle 工程
    • 构建 JAR 并声明产物
  • 全局服务
    • 制作 MOD 入口类
    • 使用 Global 访问游戏服务
    • 读取设置
    • 调用声音播放器
    • 记录和定位 MOD 日志
  • 战斗运行时
    • 读取战斗引擎状态
    • 读取战斗对象
    • 制作每帧战斗插件
    • 修改舰船数值
    • 配置武器脚本
    • 配置战斗监听器
    • 制作分层渲染插件
  • 战斗内容扩展
    • 详解舰船插件
    • 详解战术系统
    • 详解武器动画
  • 生涯世界与基础服务
    • 读取生涯世界状态
    • 构建生涯地点
    • 配置生涯势力
    • 放置生涯实体
  • 生涯舰队与舰队成员
    • 生成生涯舰队
    • 管理舰队中的成员
    • 舰队状态的重算过程
    • 维护舰队成员状态
    • 读取并修改舰船装配
  • 市场与商品
    • 创建生涯市场
    • 读写货舱内容
    • 注册市场商品
    • 实现专用子市场
    • 制作专用产业
    • 注册特殊物品
    • 实现市场条件
  • 人物与技能
    • 配置人物基础
    • 让人物承担角色
    • 制作角色技能
  • 生涯脚本与情报事件
    • 编写生涯逐帧脚本
    • 监听生涯事件
    • 选择生涯插件
    • 管理舰队活动情报
  • 酒吧事件与任务
    • 组织生涯交互对话
    • 实现对话插件
    • 接入酒吧事件
    • 构建阶段任务
    • 接入酒吧任务
  • Rules 系统、命令与内存
    • 组织 Rules 规则表
    • 编排 Rules 对话
    • 接入 Rules 生涯场景
    • 编写 Rules 命令
    • 使用 MemoryAPI 保存状态
  • 文件读取与写入
    • 读取 MOD 内文本
    • 读取 MOD 内 JSON 文件
    • 读取 MOD 内 CSV
    • 读写 common 数据
    • 实现本地化机制
  • 常用依赖库
    • 接入常用依赖库
    • 使用 LazyLib 几何工具
    • 使用 LazyLib 查询战场
    • 使用 LazyLib 保存公共 JSON
    • 注册 GraphicsLib 光照数据
    • 创建 GraphicsLib 动态光源
    • 制作 GraphicsLib 纹理映射
    • 配置 MagicLib 自动尾迹
    • 创建 MagicLib 运行时尾迹
    • 配置 MagicLib 数据赏金
    • 使用 MagicLib 辅助生涯开发
    • 使用 MagicLib 战斗小工具
  • 可选依赖与 Nexerelin
    • 接入可选依赖
    • 登记 Nexerelin 势力与外交配置
    • 配置 Nexerelin 的两种星区开局
    • 配置 Nexerelin 战略 AI 与扩张规模
    • 登记 Nexerelin 地面战单位与产业
    • 为 Nexerelin 特遣队添加命名与事件响应
    • 制作即时生效的 LunaLib 设置面板
  • 着色器与渲染
    • 使用 Java OpenGL
    • 使用 GLSL 进阶
    • 使用 VBO 和 VAO 保存顶点
    • 使用 SSBO 传递参数
    • 使用实例化进行绘制
    • 选择 BoxUtil 渲染方案

记录和定位 MOD 日志

日志需要让一次结果能够追溯到实际操作。本节从加载与运行记录出发,说明来源、级别、对象 ID 和异常堆栈怎样配合,再将消息格式整理为工具类。代码能够输出文字之后,还要决定这些文字能否帮助定位问题。

本节预期阅读时间:~12 分钟。

本节预期操作时间:~15 分钟。

学习目标

完成后,您将能够:

  • 取得类对应的日志器;
  • 按事实选择 info、warn 和 error;
  • 用稳定前缀、阶段与对象 ID 组织消息;
  • 保留异常堆栈并定位失败操作;
  • 比较本次启动和运行记录。

前置知识

  • [C6-S4] 的构建与加载;
  • [C7-S1] 的生命周期日志;
  • [C7-S2] 的服务与阶段;
  • Java 字符串、异常对象与 try/catch。

从记录定位本次失败

打开 Starsector/starsector-core/starsector.log,搜索 GearIn 或当前对象 ID。重新构建并启动之后,将记录对应到本次启动:应用阶段涉及类和资源,生涯阶段涉及存档对象,战斗阶段则涉及实体与参数。

本节采用的消息形如:

INFO GearIn load: object=GearIn_artizan_combat variant registered
WARN GearIn combat: object=GearIn_artizan_combat target unavailable
ERROR GearIn variant-load: object=GearIn_artizan_combat variant could not be loaded
java.lang.RuntimeException: ...

前缀与对象 ID 用于找到相关记录,阶段说明当时正在做什么。发生异常时还需要完整堆栈,才能追到失败的调用。定位从首个相关异常开始,后面的错误可能只是前面的失败继续产生的结果。

下面的写法就为这些信息提供对应位置。

为功能类取得日志器

在当前类中创建日志器:

private static final Logger LOG = Global.getLogger(GearInLogWriter.class);

Global.getLogger(...) 按 Class 取得 Log4j 日志器,输出进入前述日志文件。类名提供代码来源,消息中的 ID 提供本次处理的对象。

功能类使用自己的日志来源。 需要统一格式时可以使用工具类,但调用方仍要提供阶段和对象。本节的辅助类会集中输出来源,消息中因此保留这些业务信息。

用级别说明发生了什么

日志级别速查表

级别使用场合
info阶段完成、对象创建和需要观察的结果
warn流程继续,但存在需要核对的状态
error当前操作失败或捕获异常

记录正常加载、需要核对的状态和加载失败时,分别使用:

LOG.info("GearIn load: variant=GearIn_artizan_combat");
LOG.warn("GearIn state: sector not ready");
LOG.error("GearIn load failed: variant=GearIn_artizan_combat", exception);

这里的 error 同时传入消息与异常对象。消息说明加载哪个装配,异常堆栈说明加载在哪个调用中失败。只输出 exception.getMessage(),会丢失这部分调用信息。

编者认为警告也应当有分量。 正常加载阶段缺少 Sector,可以记录为阶段信息;只有操作确实需要它却没有可用对象时,再按失败处理。警告积累过多,真正需要检查的记录反而容易被掩盖。

将消息对应到具体操作

日志以 GearIn 开头,随后写阶段、对象 ID 与结果。局部格式如下:

String prefix = "GearIn " + stage + ": object=" + objectId + " ";
LOG.info(prefix + detail);

固定格式方便搜索,具体字段解释本次操作。 装配日志保留 variantId,舰船日志保留 hullId,生命周期日志保留回调。需要比较数值时,将相关输入与结果写在同一行,就能沿同一个 ID 追踪加载、初始化与运行过程。

消息内容随任务选择。只有一个脱离对象的数字,即使打印得再精确,也无法说明它属于哪次计算。

在异常发生处保留上下文

例如装配加载失败时,捕获位置同时知道本次请求的 ID 与实际异常。把两者交给日志工具,再沿原调用链处理失败:

try {
    Global.getSettings().getVariant("GearIn_artizan_combat");
} catch (RuntimeException exception) {
    GearInLogWriter.error("variant-load", "GearIn_artizan_combat",
            "variant could not be loaded", exception);
    throw exception;
}

这段片段记录后重新抛出原异常,加载失败继续由调用链处理。若某种业务状态允许继续运行,后续动作则由该功能决定。日志保存发生的事实,捕获异常之后是否继续,仍是业务代码的职责。

完整最小例

工具类保存为 src/data/scripts/gearin/GearInLogWriter.java,调用方传入阶段、对象与信息。

完整成品:GearInLogWriter
package data.scripts.gearin;

import org.apache.log4j.Logger;

import com.fs.starfarer.api.Global;

public class GearInLogWriter {

    private static final Logger LOG = Global.getLogger(GearInLogWriter.class);

    private GearInLogWriter() {
    }

    public static void info(String stage, String objectId, String detail) {
        LOG.info(format(stage, objectId, detail));
    }

    public static void warn(String stage, String objectId, String detail) {
        LOG.warn(format(stage, objectId, detail));
    }

    public static void error(String stage, String objectId, String detail, Throwable cause) {
        LOG.error(format(stage, objectId, detail), cause);
    }

    private static String format(String stage, String objectId, String detail) {
        return "GearIn " + stage + ": object=" + objectId + " " + detail;
    }
}

工具统一 info、warn 与 error 的消息格式,调用方提供实际阶段、ID 和结果。直接使用功能类的日志器时,也可以沿用这套字段。回到前面的日志例子,来源、对象与堆栈便都有了明确的写入位置。

验证方案

  1. 保存工具类,构建 JAR 并核对 class 条目。
  2. 在既有入口的当前操作中调用 info,记录阶段、ID 与一个实际结果。
  3. 在业务可继续的异常状态处调用 warn,明确当前条件。
  4. 在可复现的失败操作捕获处用 error 保留异常,再按实际处理逻辑继续或抛出。
  5. 运行对应场景,搜索前缀和对象 ID,比较消息与堆栈来源。

预期结果:

  • 三种级别表达各自实际状态,字段与对象对应。
  • 捕获异常的 error 记录包含原异常和堆栈。
  • 前缀、阶段、ID 和关键参数可以定位实际调用。
  • 本次构建与运行使用当前产物,日志与修改对应。

故障分析

  • 找不到 MOD 消息:前缀、级别过滤或实际调用未对应。

    • 解决方案:核对当前日志器、消息和日志配置,运行实际触发点。
  • 消息无法确定对象:只记录笼统结果,缺少阶段和 ID。

    • 解决方案:补齐当前操作的对象与关键参数。
  • error 消息缺少堆栈:调用只传入文字,异常对象未记录。

    • 解决方案:传入实际 Throwable 作为第二参数。
  • 仍显示旧结果:产物或加载路径采用旧代码。

    • 解决方案:重新构建并核对 JAR 与 mod_info 路径,再启动场景。

总结

从消息定位对象,从级别判断状态,再通过异常堆栈追到失败调用。类日志器与稳定格式帮助检索,实际输入和结果解释发生的过程。

后续验证继续按对象与回调记录。能够把结果对应到输入、调用和文件,日志才提供了排错所需的信息。

建议参考项

  • com.fs.starfarer.api.Global:getLogger 取得类日志器。
  • org.apache.log4j.Logger:info、warn 与 error。
  • Starsector/starsector-core/starsector.log:运行日志与异常堆栈。
在 GitHub 上编辑此页
上次更新: 2026/10/14 12:25
贡献者: 1847905557
上一页
调用声音播放器