# 生存战争联机版mid播放器模组 **Repository Path**: EmpyrealSynergyStudio/SCnet-midiplayer ## Basic Information - **Project Name**: 生存战争联机版mid播放器模组 - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-10-07 - **Last Updated**: 2026-10-07 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # MIDI 声音发生器(MidiSoundGenerator) 生存战争 2.2 网络版(`sc2.2network`)的 **.netmod 本地模组**:新增一个「MIDI 版声音发生器」方块, 打开菜单即可指定播放玩家数据目录里某个 `.mid` 文件的**某一条轨道**;MIDI 模式下**下方输入**决定播放时机, **正面端口**输出当前 MIDI 音符对应的音级电平。 - 只使用 `sc2.2network` 的既有公开扩展点:不改 `Content/`、不改核心工程源码、不扩内置网络协议枚举。 - 设计取舍、接口定义、位布局、联机同步与已知限制见 [docs/设计文档.md](docs/设计文档.md)。 --- ## 一、安装 1. 取发行包(或自行打包,见第四节):`MidiSoundGenerator.netmod` 2. 放进**游戏数据目录**的 `NetMods/` 下(可放子目录,加载器递归扫描) 3. 启动游戏 → 载入世界 → 创造模式「电子」分类里取出「MIDI 声音发生器」(生存模式可用铜锭、锗晶、铁锭按原版声音发生器同款配方合成) ## 二、使用 ### 2.1 放曲目 把 `.mid` 文件放进**游戏根目录**(与游戏可执行文件同级)的 `Midi/` 子目录;该目录不存在时模组会自动创建, 目录不可读/不可创建时菜单会提示且日志留痕。 - 本仓库自带两首示例:`samples/demo_two_tracks.mid`(双轨:钢琴旋律 + 贝斯,用来验证「选轨道」)与 `samples/demo_chords_drums.mid`(三轨:弦乐和弦 + 鼓通道,用来验证音色族与鼓采样)。 - 也可以直接生成到目标目录:`python3 samples/generate_samples.py <游戏根目录>/Midi` ### 2.2 接线 | 端口 | 普通模式(MIDI 关闭) | MIDI 模式 | | --- | --- | --- | | 下方 Bottom | 音色输入(0.1=Bell … 1.0=Bass) | **播放触发**:0→非 0 上升沿从头播放;回到 0 停止并复位 | | 左方 Left | 音高输入(0~15 半音,15=休止) | 保留 | | 右方 Right | 八度输入(0~15,默认 2) | 保留 | | 上方 Top | 音量输入(0~15,默认 15) | 音量输入(同左) | | 正面 In | 输出口(恒 0V) | **输出口**:当前音符音级 / 15,无音符为 0V | > 与原版声音发生器唯一的接口差异:原版把正面当作**第二音色输入**,本模组把正面改成**输出口**。 ### 2.3 菜单 **点击方块**打开菜单: - 勾选/取消「MIDI 模式」; - 在曲目列表里选 `.mid`(按文件名排序); - 用滑条选轨道(标签实时显示「轨道 k/N」与轨道名); - 「旋转 90°」立即转动方块朝向(其余项在「确定」时一次写回)。 曲目播完自动停止;停止后再次播放需要让触发输入先回到 0 再给上升沿。 改配置(确定/旋转)会让元件按新方块值重建,等效于复位:正在播放的曲目会停下,需要重新给一次触发上升沿。 ### 2.4 联机注意 配置存在方块数据里,服务端校验通过后经原版地形包广播,**所有客户端听到同一条轨道**。 但曲目只按「目录内排序后的第 N 个文件」记录,因此要求: 1. 同一房间各端的 `Midi/` 目录中文件名集合与排序**完全一致**; 2. 增删 `.mid` 会改变既有方块的指向(重新选一次即可)。 ## 三、构建与验证 ```bash # 只验证(解析器 + 音色映射自检 54 项断言、对话框 XML 属性核对 63 项、模组工程编译) Mods/MidiSoundGenerator/verify.sh # 打包成 .netmod(产物在 bin/<配置>/) Mods/MidiSoundGenerator/pack.sh ``` 也可手工执行: ```bash dotnet run --project Mods/MidiSoundGenerator/tests/MidiParserTests/MidiParserTests.csproj -c Debug dotnet run --project Mods/MidiSoundGenerator/tests/DialogXmlCheck/DialogXmlCheck.csproj -c Debug dotnet build Mods/MidiSoundGenerator/MidiSoundGenerator.csproj -c Debug ``` - 模组工程通过 `ProjectReference` 引用 `Survivalcraft` 工程(`Private=false`,不拷贝游戏程序集), 因此**编译器用的就是当前工作区的游戏源码**,游戏接口一改,模组编译立刻暴露。 - `DialogXmlCheck` 用与 `Widget.LoadProperties` 相同的规则核对对话框 XML:属性名写错、字面量类型不对 都会在构建期报出,而不是等到玩家点击方块的那一刻。 - 打包脚本自检包根布局(`modinfo.json` 必须在 zip 根)并拒绝把游戏程序集打进包。 - 两个测试工程与模组工程都不在 `SCNETWORK.slnx` 的既有构建配置内(与 `Plugins/*` 同一登记方式),不会扰动既有编译门禁。 ## 四、已知限制 | 限制 | 说明 | | --- | --- | | 文件按序号寻址 | 见 2.4 联机注意 | | 只处理 Note On | 采样为一次触发型(与原版声音发生器一致),不做包络与延音 | | 单步最多 8 个音符 | 超出的音符本步丢弃,避免音频通道拥塞 | | 输出口为音级电平 | C 音与「无音符」同为 0V(0V 在音高语义里就是 C) | | 外观与原版声音发生器相同 | 复用原版贴图槽与模型(不新增图集资源),靠名称与配方区分 | 后续可选改进见设计文档第十节。