@@ -215,9 +215,86 @@ dotnet publish -c Release -r win-x64 -p:SelfContained=false -p UseAppHost=true -
215215 - 具体的原理,请详见` parser/simai/SimaiParser.cs` 中,对` MuConvert.antlr` 下的各个类的引用。
216216- MA2的话,由于其天生就是为了机读设计的、格式相对简单,没有必要上ANTLR;而是直接逐行读取、一行内` Split(' \t' )` ,就足以解析MA2的所有内容了。
217217
218+ # ## 目录与命名空间约定(贡献代码必读)
219+ - 在目录上,本项目按** 功能类型** 划分一级子目录,如` parser` 、` generator` 、` chart` 、` collection` 等。
220+ - 在各个一级子目录中,如有必要的情况下,可再以** 游戏名** 创建二级子目录加以整理,如` parser/mai` 、` generator/mai` 、` chart/mai` 等。
221+ - 这样可以使相同功能类型的代码相对集中,减少了重构时可能需要的工作量、防止重构漏掉东西等。
222+ - 在命名空间上,本项目采用** 按游戏划分** 的逻辑命名空间,这样可以方便用户的使用。
223+ - ** 同一游戏下的谱面 IR、各语法格式的 Parser/Generator、以及其他直接相关的类型等** ,一律放在统一的命名空间` MuConvert.< 游戏简写> ` 下。
224+ - 例如,对maimai来说,尽管相关文件分散在` parser/mai` 、` generator/mai` 、` chart/mai` 、` collection` 等多个子目录中,但命名空间均为` MuConvert.mai` 。
225+ - 多个游戏会共用的、** 与具体游戏无关的基础设施** (例如谱面基类 ` BaseChart< TNote> ` 、` IBaseChart` 、` BPMList` 、` IParser` 等),则保留在 ` MuConvert.chart` 、` MuConvert.parser` 等目录级公共命名空间中。
226+ - 将来若接入其他游戏,应为其单独使用一个顶层命名空间(例如` MuConvert.chu` 、` MuConvert.ogk` )。
227+
218228# ## 多语言(i18n)相关
219229- 本项目中支持基于` System.Globalization` 的多语言,语言文件位于` i18n` 目录中。
220230- 其中,一级支持语言为三个(即[MaiChartManager](https://github.com/MuNET-OSS/MaiChartManager)支持的语言):简体中文(` Locale.zh.resx` )、英语(` Locale.resx` )、繁体中文(` Locale.zh-hant.resx` )。
221231 - 一般的开发过程,包括有意提交PR的人在实现代码时需要新增/修改i18n key的,只需处理这三种语言文件即可。
222232- 其他的为二级支持语言,一般的开发过程可以不必处理和新增这些语言的翻译key;Maintainers会定期的将一级支持语言的翻译内容(通过LLM机器翻译)同步到这些语言中。
223- - 当然,如果你发现翻译有错误,也可以直接提PR修改。
233+ - 当然,如果你发现翻译有错误,也可以直接提PR修改。
234+
235+ # ## 如何在已支持的游戏中新增一种语法格式
236+ 对于已经支持了的游戏,想要增加一种支持的源语法格式或目标语法格式时:
237+ ** 只需要编写Parser和Generator即可** 。注意应当实现对应的接口(` IParser` / ` IGenerator` ),详见下文。
238+
239+ 1. ** 文件放置位置** :仿照现有的目录结构即可。以 maimai 为例,在 ` parser/mai` 下新增 ` FooParser` ,在 ` generator/mai` 下新增 ` FooGenerator` 。但是,如[目录与命名空间约定](# 目录与命名空间约定贡献代码必读)部分所述,文件的命名空间应统一为`MuConvert.mai`。
240+ 2. ** 实现的接口** :应实现泛型参数为该游戏谱面类型的接口。继续以 maimai 为例,应实现的接口为 ` IParser< MaiChart> ` 、` IGenerator< MaiChart> ` 。详见下方代码段的示例。
241+ 3. ** Alerts** :所有的Parser和Generator,应当使用` utils/Error.cs` 中定义的` Alert` 类来实现转谱的信息的log,而不要往控制台上输出信息。
242+ - IParser和IGenerator的定义中都要求函数要返回List< Alert> ,因此在你的解析/生成过程中,应当根据情况生成不同等级的Alert对象,并返回出来。而不是打印到控制台。
243+ - 如果遇到无法修复的错误、希望中止转谱过程的话,则应当(在记录好最后引发错误的Alert后),抛出` ConversionException` 。
244+ - 具体写法,请参照现有的maimai的Parser和Generator等。
245+
246+ ` ` ` csharp
247+ using MuConvert.parser;
248+ using MuConvert.utils;
249+
250+ namespace MuConvert.mai; // 注意命名空间应该是MuConvert.< 游戏名> ,不要使用默认的基于目录的命名空间
251+
252+ public sealed class FooParser : IParser< MaiChart>
253+ {
254+ public (MaiChart, List< Alert> ) Parse(string text)
255+ {
256+ var chart = new MaiChart ();
257+ var alerts = new List<Alert> ();
258+ if (text == " " )
259+ { // 这是一个抛异常中止转谱的示例
260+ alerts.Add(new Alert(Alert.Level.Error, " 输入的文本为空!" )); // 要把最后的错误记录成Alert
261+ throw new ConversionException(alerts); // 然后抛出ConversionException,把alerts作为参数传入。
262+ }
263+ // TODO: 填充 chart,记录 Alert,必要时抛出 ConversionException
264+ return (chart, alerts);
265+ }
266+ }
267+ ` ` `
268+
269+ ` ` ` csharp
270+ using MuConvert.generator;
271+ using MuConvert.utils;
272+
273+ namespace MuConvert.mai;
274+
275+ public sealed class FooGenerator : IGenerator< MaiChart>
276+ {
277+ public (string, List< Alert> ) Generate(MaiChart chart)
278+ {
279+ var alerts = new List<Alert> ();
280+ // TODO: 由 chart 生成目标文本,记录 Alert
281+ return (" " , alerts);
282+ }
283+ }
284+ ` ` `
285+
286+ # ## 如何新增对另一种游戏的支持(注意事项)
287+ 1. ** 命名空间** :命名空间使用 ` MuConvert.< 游戏简写> ` (如中二可用` MuConvert.chu` 、音击可用` MuConvert.ogk` ),
288+ 2. ** 代码目录** :模仿现有maimai的写法,在各个功能分类的一级子目录中新建二级子目录,例如 ` chart/ogk` 、` parser/ogk` 、` generator/ogk` 等,把代码放到这些目录下。
289+ - 特殊地,如果该游戏的某个功能类型非常简单,如只有一个文件,那么也可以不单独创建二级子目录,而是直接放在一级子目录下。例子见现有的` collection/maidata.cs` ,因为与maimai相关的collection只有这一个文件(MuConvert本身不对Sinmai的` Music.xml` 做处理,这太复杂了、而且是MCM该干的事),所以` maidata.cs` 直接放在了` collection` 一级目录下,没有区分二级子目录。
290+ 3. ** 中间表示(IR)** :为该游戏定义音符类型与谱面类型。
291+ - 音符类型无需继承任何类,自己定义即可。
292+ - 谱面类型,应继承` BaseChart` ,并实现其中的相关getter,同时添加上自己特定于自己这个游戏的属性。
293+ 4. ** Parser & Generator** :详见上文[如何在已支持的游戏中新增一种语法格式](# 如何在已支持的游戏中新增一种语法格式)部分的说明,编写Parser和Generator,并实现对应的接口。
294+ 5. ** 测试** :在` test` 中新建你游戏的子目录如` ogk` ,在其中放置测试文件。直接放置即可,xUnit会自动找到,无需修改csproj等。
295+ - 如需放置测试数据,测试数据放在如`test/ogk/testset`中;读取测试数据时,可参见`test/mai/TestUtils.cs`中`FindTestsetRoot ()` 函数的写法。
296+ 6. ** 多语言(i18n)** (可选):如果有i18n的必要的话,直接在` i18n` 目录中的对应的语言文件` .resx` 中,新增对应的key即可。
297+ - 无需创建单独文件,也不用管命名空间之类的问题,但建议key在命名的时候遵循一定的规律以防冲突。
298+ - 详见上文[多语言(i18n)相关](# 多语言i18n相关)部分的说明。
299+ 7. ** CLI** (可选):如需实现CLI,可在` Program.cs` 中增加相应的功能。
300+
0 commit comments