Skip to content

feat(WeatherControl): 让外部模组能通过 Mod.Call 注册自己的气候控制项#174

Open
hocha113 wants to merge 4 commits into
487666123:1.4.4from
hocha113:1.4.4
Open

feat(WeatherControl): 让外部模组能通过 Mod.Call 注册自己的气候控制项#174
hocha113 wants to merge 4 commits into
487666123:1.4.4from
hocha113:1.4.4

Conversation

@hocha113

@hocha113 hocha113 commented May 26, 2026

Copy link
Copy Markdown
Contributor

概要

把气候控制面板从只支持内置 5 项扩展成一个统一的注册中心,外部模组可以通过 Mod.Call 注册自己的控制项,也可以挂自己的 UI 视图自成一栏。原版 5 项的存档、网络协议、公共字段都保留不变。

顺手修一处 SandstormLocked 存档键名不一致的小 bug。

动机

现状是 WeatherAmbientElement 把 5 个内置控制项(时间 / 月相 / 降雨 / 沙暴 / 风向)和它们的命中区、网络包、UI 逻辑硬编码在一起,没有给外部模组留入口。如果联动作者想加个自己的天气(比如"火烧日"),既不能在面板上加图标,也不能复用现有的派发与同步机制。

这次把控制项抽出来做成接口和注册中心,让所有项走同一条路,本地状态由回调读写,跨客户端同步由统一的派发层负责,UI 由 Registry 列出。内置 5 项也用同一套接口落地,外部读写它们和读写自己注册的项写法一致。

主要改动

新增抽象层

  • 路径: Content/Functions/WeatherControl/
  • IWeatherControl 单个控制项的抽象,描述 Id、图标、档位、是否支持锁定、本地读写回调等
  • IWeatherControlGroup 一栏内容的抽象,让模组可以挂自己的 UI 视图进面板
  • WeatherControlInfo 普通项的具体实现,内置项和 Mod.Call 注册的项都用这个
  • WeatherControlRegistry 注册中心,是 ModSystem,提供 Register / Unregister / TryGet / DispatchStage / DispatchLocked
  • WeatherBuiltinControls 把内置 5 项注册进 Registry,对接现有的 WeatherController 静态字段
  • WeatherControlCrossModMod.Call 收到的弱引用参数转成 WeatherControlInfo 走 Registry

通用同步包

  • 路径: Packets/Weather/
  • WeatherStageSyncPacket 通用档位同步,包内只带 id 与目标 stage
  • WeatherLockSyncPacket 通用锁定同步,结构同上
  • 内置 5 项的旧 NetModule 保留未删,原版 UI 调用路径不变;外部模组与新 Registry 派发统一走这两个新包

UI

  • 路径: UI/WeatherControl/
  • 新增 ModdedWeatherItemsView 浮在艺术画面左上角,横向排列所有未指定栏目的模组项
  • 新增 WeatherControlSlot 单个槽位,32x32 半透明小框,左键循环档位,右键切锁定,悬停 tooltip 用 displayName + tooltip + 锁定提示
  • WeatherGUI 增加 BuildCustomGroupViews() 把外部注册的 IWeatherControlGroup 视图按优先级倒序挂进 MainPanel
  • 槽位图标超过 28 像素时按比例缩到 28,避免别的模组传大图标把场景撑变形

Mod.Call API(Common/ModSystems/ModIntegrationsSystem.cs

新增 8 个分支,命名对齐已有约定:

  • RegisterWeatherControl / UnregisterWeatherControl
  • RegisterWeatherControlGroup / UnregisterWeatherControlGroup
  • QueryWeatherControlStage / SetWeatherControlStage
  • IsWeatherControlLocked / SetWeatherControlLocked

每条都把参数解析交给 WeatherControlCrossMod,返回值约定与项目现有 Mod.Call一致(查询类返回结果,操作类返回 bool)。

实际效果

DI6{BKZF4}(6G@I _A6Z EA

如图,我编写了一个“火烧日”模组,简单实现了一个烧灼大地风格的天气事件,通过 Mod.Call 将这个天气的控制注册进了 ImproveGame

该模组我已经同步上传至github: hocha113/FireoftheSun

Helper 文件

新增 ImproveGame_WeatherControlCrossModHelper.cs 在项目根目录,跟现有的 ImproveGame_ModernConfigCrossModHelper.cs 同套路:提供强类型封装与内置项 Id 速查常量,建议外部开发者复制到自己模组里直接调用。

顺带修的 bug

Content/Functions/WeatherController.csSandstormLocked 写入键名是 sandstorm、读取键名是 sandstormLocked,老版本写入的存档读不回锁定状态。统一改成 sandstormLocked,同时兼容读取旧的 sandstorm 键。

兼容性

  • 公共字段 WeatherController.RainLocked / SandstormLocked / MoonPhaseLocked / WindLocked 保留不变
  • 内置 5 项的旧 NetModule(SetTimePacket / SetMoonPhasePacket / SetRainPacket / SetSandstormPacket / SetWindPacket)未动,原版艺术画面 UI 还是走它们
  • 存档结构未变,老存档加载后含义不变,旧的 sandstorm 键名也能读
  • 没有引入新依赖

测试

  • 单人 / 多人 host / 多人客户端都测过:在面板上点击内置 5 项,左右键交互、tooltip、锁定提示、跨客户端同步都正常
  • 配套写了一个示例模组 FireoftheSun("火烧日"),通过 Helper 接入新的 Mod.Call API,在面板艺术画面里看到自己的图标 + 悬停 tooltip + 左右键交互;该模组还实现了 CustomSky + ModSceneEffect + Filters.Scene 来演示一个完整的天气效果接入是什么样子
  • 旧存档(含 Unlocked / RainLocked 等键)加载后状态恢复正常
  • 用一个旧版本写入的 sandstorm 键存档验证向后兼容读取

文档

  • CrossModSupport.md 追加了 8 个新条目 + 内置项 Id 速查表 + 使用例
  • README-en.md 的 Cross-mod 区段同步追加了英文版

Checklist

  • 改动通过本地构建(0 错误 0 警告)
  • 不破坏现有存档与多人同步
  • 文档已同步更新
  • Changelog 条目待维护者决定写在哪一版(建议挂到 v1.8.1.15 的"新增内容"段下)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant