diff --git a/.gitignore b/.gitignore index 0f9f08d..09fe61d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,8 @@ site/** .VSCodeCounter/** .vs/** -.idea/ \ No newline at end of file +.idea/ +**/Source/bin/** +**/Source/obj/** +**/Source/.vs/** +**/Source/CelesteModTutorial.sln \ No newline at end of file diff --git a/docs/advanced/cross_mod_interactions.md b/docs/advanced/cross_mod_interactions.md index 6cd2eb7..3df75d0 100644 --- a/docs/advanced/cross_mod_interactions.md +++ b/docs/advanced/cross_mod_interactions.md @@ -35,14 +35,14 @@ public static bool GravityHelperLoaded; public override void Load() { // 获取 GravityHelperModule 的元数据 - EverestModuleMetadata gravityHelper = new() + EverestModuleMetadata gravityHelperMetadata = new() { Name = "GravityHelper", Version = new Version(1, 2, 20) }; // 判断 GravityHelper 是否成功加载 - GravityHelperLoaded = Everest.Loader.DependencyLoaded(gravityHelper); + GravityHelperLoaded = Everest.Loader.DependencyLoaded(gravityHelperMetadata); } ``` @@ -148,13 +148,61 @@ if (MyCelesteModAPI.MultiplyByTwo(myNumber) > 400) 通过这种方式, 我们可以在自己的 Mod 中访问并调用其他 Mod 提供的功能, 而不需要直接依赖该 Mod 的程序集. - + +`lib-stripped` 是指剥离了所有方法实现的程序集, 仅保留类型和方法签名. +我们可以通过 [`NStrip`](https://github.com/bbepis/NStrip) 或 [`BepInEx.AssemblyPublicizer `](https://github.com/BepInEx/BepInEx.AssemblyPublicizer) 的 `strip-only` 模式等工具对目标程序集进行剥离. +完成后我们可以直接引用被剥离的程序集. @@ -192,7 +240,7 @@ public override void Load() PlayerGravityComponentProperty = gravityHelperModuleType?.GetProperty("PlayerComponent", BindingFlags.NonPublic | BindingFlags.Static); // 反射获取 GravityHelper.Components.SetPlayerGravity 方法 - SetPlayerGravityMethod = playerComponent?.GetValue(null)?.GetType().GetMethod("SetGravity", BindingFlags.Public | BindingFlags.Instance); + SetPlayerGravityMethod = PlayerGravityComponentProperty?.GetValue(null)?.GetType().GetMethod("SetGravity", BindingFlags.Public | BindingFlags.Instance); // 反射获取 GravityHelper.GravityHelperModule.ShouldInvertPlayer 属性 IsPlayerInvertedProperty = gravityHelperModuleType?.GetProperty("ShouldInvertPlayer", BindingFlags.Public | BindingFlags.Static); diff --git a/docs/arc/project_template.md b/docs/arc/project_template.md new file mode 100644 index 0000000..fbab2db --- /dev/null +++ b/docs/arc/project_template.md @@ -0,0 +1,87 @@ +!!! info + 在蔚蓝国外社区流行着另一个 mod 项目模板, 不过我个人不太喜欢它, 不过你需要的话[这是 Github 主页](https://github.com/EverestAPI/CelesteModTemplate) + 所以这里主要使用我个人制作也是个人最常用的一个. + +\_(:з」∠)\_ +根据一些反馈我们发现旧的手动配置环境的方式非常的复杂难操作( +所以呢这里就推荐一种新的配置环境的方式 - **使用模板** +考虑到 nuget 安装模板也需要一定的命令行基础... +所以这里考虑[提供直接的下载链接](https://hongshitieli.lanzouj.com/iJfRz1l0iffg), +或者你也可以选择使用 `dotnet cli` 从 nuget 上的模板安装: + +!!! note + 你可能还需要安装 `.NET 8 SDK` 来使用该模板, 你可以[在这里](https://get.dot.net)找到它 + +??? info "使用 dotnet cli 从模板新建项目" + 首先在一个你喜欢的位置放置你的项目文件夹, 名字即为你的项目名, 例如 `MyCelesteMod`: + ```bat + mkdir MyCelesteMod + cd MyCelesteMod + ``` + 然后在此位置安装 nuget 上我的 mod 模板(如果你没有安装的话): + ```bat + dotnet new install Saladim.CelesteModTemplate + ``` + 然后你就能使用这条指令直接创建项目了: + ```bat + dotnet new sapcelestemode + ``` + 名字即为上层文件夹名, 或者你可以使用 `-n` 参数重写项目名字: + ```bat + dotnet new sapcelestemod -n MySuperCelesteMod + ``` + 模板目前默认不会创建针对 Everest Core 的 Code Mod, 如果你需要的话你可以传入 `--core-only true` 参数: + ```bat + dotnet new sapcelestemod --core-only true + ``` + +完成后使用你喜欢的编辑器打开项目(对于 vs 直接打开 .csproj 文件), 那么按理来说你会看到这几个文件: + +- CelesteMod.props +- CelesteMod.targets +- Common.props +- MyCelesteModModule.cs +- MyCelesteMod.csproj + +以及你的项目, 它的名字是 `MyCelesteMod`, 不同于旧的方法, 在这里你的配置过程很简单: + +- 首先打开 `Common.props`, **将里面的 `CelesteRootPath` 内的内容改成你的蔚蓝安装位置** + +```xml hl_lines="3" + + + C:\Program Files (x86)\Steam\steamapps\common\Celeste + true + true + ModFolder + + +``` + +现在你可以按下 `Ctrl+B` 或者手动点击 `生成->生成解决方案`, +如果你在你的 vs 输出里面看到了类似这两句: + +``` +1>MyCelesteMod -> D:\User\temp\cm\bin\x86\Debug\net452\MyCelesteMod.dll +1>MyCelesteMod -> C:/Program Files (x86)/Steam/steamapps/common/Celeste/Mods/MyCelesteMod_copy/MyCelesteMod.dll +``` + +并且你在你的蔚蓝 Mod 目录下找到了这个被创建的目录, +那么你的环境就算是配完了, 如果你很感兴趣这之中发生了什么, 要引用哪些程序集, 这个模板背后干了什么, 你可以去看那复杂的旧的配置方法. +!!! note + 这个模板使用 `msbuild` 帮助了你很多事! + 比如当你编译完项目之后它会复制编译结果到项目目录的 `ModFolder` 目录下, + 然后将整个 `ModFolder` 复制到蔚蓝的 `Mods\{你的mod名}_copy` 文件夹下! + 所以当我们需要更改一些比如说 loenn 的配置文件, `everest.yaml` 的内容, 你的测试地图等时, + 你只需要简单地重新编译一遍项目, 然后等待模板来帮你做剩下的活! + + +## 更改细节 + +通过模板的话依然有些东西需要自行更改, 比如这个 Mod 的名字. +更改 Mod 的名字很简单, 你只需要简单地在 vs 里重命名项目的名字 +比如我想叫做 `MyAwesomeMod`, 那么你可以通过这样: +![awesome mod!](rename_proj.png) + +顺便别忘了把类似 `MyCelesteModModule.cs` 的文件名也改成类似 `MyAwesomeModModule.cs`, +以及改名后清理一下 ModFolder 下面可能有的一些以过去名字命名的 .dll 和 .pdb 文件! \ No newline at end of file diff --git a/docs/coding_setup/images/base_env/rename_proj.png b/docs/arc/rename_proj.png similarity index 100% rename from docs/coding_setup/images/base_env/rename_proj.png rename to docs/arc/rename_proj.png diff --git a/docs/coding_challenges/simple_texturing.md b/docs/coding_challenges/simple_texturing.md index 3924257..d04952b 100644 --- a/docs/coding_challenges/simple_texturing.md +++ b/docs/coding_challenges/simple_texturing.md @@ -59,11 +59,12 @@ ok 那么现在我们该在代码这边来点贴图了, 这里我们会用到之 - Graphics - Atlases - Gameplay - - `MyCelesteMod` - - pass_by_refill.png + - objects + - PassByRefill + - pass_by_refill.png `pass_by_refill.png` 即我们的贴图, 如果你同时也是一位 mapper 的话你一定很熟悉这个文件夹套套乐! -在代码这边, 我们使用 `GFX.Game["MyCelesteMod/pass_by_refill"]` 来获取这个贴图, 它是一个 `MTexture` 类型的实例, 在获取到这个贴图后, +在代码这边, 我们使用 `GFX.Game["objects/PassByRefill/pass_by_refill"]` 来获取这个贴图, 它是一个 `MTexture` 类型的实例, 在获取到这个贴图后, 我们 `new` 一个 `Monocle.Image`, 然后在构造函数中传入它, 然后使用 `this.Add` 函数挂载到我们的这个实体上, 总的代码应该是这样的: ```cs title="PassByRefill.cs" public PassByRefill(Vector2 position, int dashes) @@ -73,16 +74,17 @@ public PassByRefill(Vector2 position, int dashes) Hitbox hitbox = new(64, 64); Collider = hitbox; - MTexture tex = GFX.Game["MyCelesteMod/pass_by_refill"]; + MTexture tex = GFX.Game["objects/PassByRefill/pass_by_refill"]; Image image = new(tex); this.Add(image); } ``` !!! info - `GFX` 是蔚蓝中的一个管理贴图的类, 我们用它获取到一个贴图组 `Game`, 然后向它检索一个名为 `MyCelesteMod/pass_by_refill` 的贴图, 你可能会疑惑为什么这里的路径只需要后半部分, - 这是因为 `GFX.Game` 只会检索 `Atlases/Graphics/Gameplay` 中的内容. - 同样的, `GFX.Portraits` 只会检索 `Atlases/Graphics/Portraits` 中的内容. + `GFX` 是蔚蓝中的一个管理贴图的类, 我们用它获取到一个贴图组 `Game`, 然后向它检索一个名为 `objects/PassByRefill/pass_by_refill` 的贴图, 你可能会疑惑为什么这里的路径只需要后半部分, + + 这是因为 `GFX.Game` 只会检索 `Graphics/Atlases/Gameplay` 中的内容. + 同样的, `GFX.Portraits` 只会检索 `Graphics/Atlases/Portraits` 中的内容. 顺便记得删掉我们重写的 `Render` 函数, 我们不再需要它了. 总的类应该是这样的: ```cs title="PassByRefill.cs" @@ -99,7 +101,7 @@ public class PassByRefill : Entity Hitbox hitbox = new(64, 64); Collider = hitbox; - MTexture tex = GFX.Game["MyCelesteMod/pass_by_refill"]; + MTexture tex = GFX.Game["objects/PassByRefill/pass_by_refill"]; Image image = new(tex); this.Add(image); } @@ -171,7 +173,7 @@ public class PassByRefill : Entity 然后设置 entity 的 `texture` 属性, 这会让 Loenn 为其设置贴图: ```lua -entity.texture = "MyCelesteMod/pass_by_refill" +entity.texture = "objects/PassByRefill/pass_by_refill" ``` 顺便设置贴图原点为左上角, 否则 Loenn 中的显示可能会与实际游戏中的不同: ```lua @@ -197,7 +199,7 @@ entity.fieldInformation = } } -entity.texture = "MyCelesteMod/pass_by_refill" +entity.texture = "objects/PassByRefill/pass_by_refill" entity.justification = { 0.0, 0.0 } return entity diff --git a/docs/coding_challenges/test_map.md b/docs/coding_challenges/test_map.md new file mode 100644 index 0000000..1f23de0 --- /dev/null +++ b/docs/coding_challenges/test_map.md @@ -0,0 +1,8 @@ +# 测试地图 + +实战部分附带一张测试地图供读者下载下来乱弄研究与测试, +你可以在[这里](../resources/CelesteModTutorial.zip)进行下载. +代码你可以在 `Source` 目录下找到. + +!!! info + 下载并解压后别忘了生成 Mod 的 `dll` 文件! \ No newline at end of file diff --git a/docs/coding_setup/basic_env.md b/docs/coding_setup/basic_env.md index c7b4f8d..01e297b 100644 --- a/docs/coding_setup/basic_env.md +++ b/docs/coding_setup/basic_env.md @@ -52,14 +52,18 @@ Everest 需求我们使用 FNA 版本的蔚蓝, 而 Linux 和 MacOS 上的蔚蓝 ## 通过模板创建项目 !!! info - 在蔚蓝国外社区流行着另一个 mod 项目模板, 不过我个人不太喜欢它, 不过你需要的话[这是 Github 主页](https://github.com/EverestAPI/CelesteModTemplate) - 所以这里主要使用我个人制作也是个人最常用的一个. - -\_(:з」∠)\_ -根据一些反馈我们发现旧的手动配置环境的方式非常的复杂难操作( -所以呢这里就推荐一种新的配置环境的方式 - **使用模板** -考虑到 nuget 安装模板也需要一定的命令行基础... -所以这里考虑[提供直接的下载链接](https://hongshitieli.lanzouj.com/iJfRz1l0iffg), + 在蔚蓝国外社区流行着另一个 mod 项目模板, [这是它的 Github 主页](https://github.com/EverestAPI/CelesteModTemplate) + 不过这里主要介绍使用我个人制作也是个人最常用的一个. + +!!! note + 项目模板在重构的教程中进行了更新, 旧版你可以在[归档-通过模板创建项目](../arc/project_template.md)中找到(不推荐) + +我们在这里提供两种模板: + +- 外部: 在蔚蓝根目录外编写代码. +- 就地: 在 `Celeste/Mods/<你的 Mod 名称>/Source` 中编写代码. + +我们在下面会使用 `Visual Studio` 进行演示. 或者你也可以选择使用 `dotnet cli` 从 nuget 上的模板安装: !!! note @@ -75,43 +79,42 @@ Everest 需求我们使用 FNA 版本的蔚蓝, 而 Linux 和 MacOS 上的蔚蓝 ```bat dotnet new install Saladim.CelesteModTemplate ``` - 然后你就能使用这条指令直接创建项目了: - ```bat - dotnet new sapcelestemod - ``` - 名字即为上层文件夹名, 或者你可以使用 `-n` 参数重写项目名字: + 然后你就能使用这条指令直接创建外部模板了: ```bat - dotnet new sapcelestemod -n MySuperCelesteMod + dotnet new sapcelestemode ``` - 模板目前默认不会创建针对 Everest Core 的 Code Mod, 如果你需要的话你可以传入 `--core-only true` 参数: + 如果需要就地模板使用这条指令: ```bat - dotnet new sapcelestemod --core-only true + dotnet new sapcelestemodi ``` - -完成后使用你喜欢的编辑器打开项目(对于 vs 直接打开 .csproj 文件), 那么按理来说你会看到这几个文件: - -- CelesteMod.props -- CelesteMod.targets -- Common.props -- MyCelesteModModule.cs -- MyCelesteMod.csproj - -以及你的项目, 它的名字是 `MyCelesteMod`, 不同于旧的方法, 在这里你的配置过程很简单: - -- 首先打开 `Common.props`, **将里面的 `CelesteRootPath` 内的内容改成你的蔚蓝安装位置** - -```xml hl_lines="3" - - - C:\Program Files (x86)\Steam\steamapps\common\Celeste - true - true - ModFolder - - + 下面是可选择的一些参数: + + - `-n`: 你的 Mod 名称, 默认为 `MyCelesteMod`, 用于重写项目名字, 例如 `-n YourCelesteMod`. + - `-c`: 指定蔚蓝根目录(只对外部模板生效), 例如 `-c "C:\Program Files\steam\steamapps\Celeste"`. + - `-up`: 是否使用 Publicize 后的 Celeste 程序集, 默认开启, 关闭可以 `-up false`. + - `-ua`: 是否使用 Celeste Mod 分析器, 默认开启, 关闭可以 `-ua false`. + - `-ss`: 向项目中添加 `Session` 类并在 `Module` 中自动配置, 默认关闭. + - `-st`: 向项目中添加 `Settings` 类并在 `Module` 中自动配置, 默认关闭. + - `-sd`: 向项目中添加 `SaveData` 类并在 `Module` 中自动配置, 默认关闭. + - `-ev`: 指定 `everest.yaml` 中的 `EverestCore` 版本, 默认为 `4465`. + - `-mv`: 指定 `everest.yaml` 中的你的 Mod 的初始版本, 默认为 `0.1.0`. + +首先我们打开命令行, 输入以下命令进行安装: +```bat +dotnet new install Saladim.CelesteModTemplate ``` -现在你可以按下 `Ctrl+B` 或者手动点击 `生成->生成解决方案`, +完成后打开 `Visual Studio`, 选择 `创建新项目`, 然后在搜索框中输入 `Celeste`, 你应该能看到以下两个模板: +![vs_template](images/base_env/vs_template.png) + +### 外部模板 + +选择并填写好项目名称之后, 你应该能看到以下内容: +![external_template](images/base_env/external_template.png) + +其中的各选项详细信息可以把鼠标移到旁边的 `info` 图标进行查看. + +完成创建后你可以按下 `Ctrl+B` 或者手动点击 `生成->生成解决方案`, 如果你在你的 vs 输出里面看到了类似这两句: ``` @@ -128,16 +131,16 @@ Everest 需求我们使用 FNA 版本的蔚蓝, 而 Linux 和 MacOS 上的蔚蓝 所以当我们需要更改一些比如说 loenn 的配置文件, `everest.yaml` 的内容, 你的测试地图等时, 你只需要简单地重新编译一遍项目, 然后等待模板来帮你做剩下的活! +### 就地模板 -## 更改细节 +就地模板在进行项目名称填写时你应该会看到以下内容: +![inplace_template](images/base_env/inplace_template.png) -通过模板的话依然有些东西需要自行更改, 比如这个 Mod 的名字. -更改 Mod 的名字很简单, 你只需要简单地在 vs 里重命名项目的名字 -比如我想叫做 `MyAwesomeMod`, 那么你可以通过这样: -![awesome mod!](images/base_env/rename_proj.png) +这里的 `项目名称` 就是你的 Mod 名称. +`位置` 我们需要改到蔚蓝的 `Mods` 目录下, 例如 `C:\Program Files\steam\steamapps\Celeste\Mods`. +填写完成后我们还需要勾选 `将解决方案和项目放在同一目录中`. -顺便别忘了把类似 `MyCelesteModModule.cs` 的文件名也改成类似 `MyAwesomeModModule.cs`, -以及改名后清理一下 ModFolder 下面可能有的一些以过去名字命名的 .dll 和 .pdb 文件! +后面的项目配置基本与外部模板一致, 除了 `Celeste 所在的目录`. 这项已经在上一步的 `位置` 填写过了所以不需要再填写. ## Module 类 @@ -256,12 +259,12 @@ D3D11 Adapter: Intel(R) UHD Graphics 630 - MyCelesteMod (你的根目录) - ModFolder + - Code + - MyCelesteMod.dll + - MyCelesteMod.pdb - everest.yaml - - MyCelesteMod.dll - - MyCelesteMod.pdb - CelesteMod.props - CelesteMod.targets - - Common.props - MyCelesteMod.csproj - MyCelesteModModule.cs @@ -272,4 +275,4 @@ D3D11 Adapter: Intel(R) UHD Graphics 630 - 直接强制重新构建项目 (vs 中 "生成" -> "重新生成项目") - 在项目根目录执行 `msbuild -target:PostModBuild` 命令行 -> 好像是有更好的解决方法, 不过鉴于本人 MSBuild 知识不足只能做成这样了(x \ No newline at end of file +> 好像是有更好的解决方法, 不过鉴于本人 MSBuild 知识不足只能做成这样了(x diff --git a/docs/coding_setup/images/base_env/external_template.png b/docs/coding_setup/images/base_env/external_template.png new file mode 100644 index 0000000..7444b43 Binary files /dev/null and b/docs/coding_setup/images/base_env/external_template.png differ diff --git a/docs/coding_setup/images/base_env/inplace_template.png b/docs/coding_setup/images/base_env/inplace_template.png new file mode 100644 index 0000000..afe26d4 Binary files /dev/null and b/docs/coding_setup/images/base_env/inplace_template.png differ diff --git a/docs/coding_setup/images/base_env/vs_template.png b/docs/coding_setup/images/base_env/vs_template.png new file mode 100644 index 0000000..7d653f2 Binary files /dev/null and b/docs/coding_setup/images/base_env/vs_template.png differ diff --git a/docs/loenn/basic_configurations.md b/docs/loenn/basic_configurations.md new file mode 100644 index 0000000..8cb3c87 --- /dev/null +++ b/docs/loenn/basic_configurations.md @@ -0,0 +1,8 @@ +# Loenn 基础配置 + +## Lua + +## EntityData + +## 基础结构 + diff --git a/docs/loenn/effect_structs.md b/docs/loenn/effect_structs.md new file mode 100644 index 0000000..47a2f7b --- /dev/null +++ b/docs/loenn/effect_structs.md @@ -0,0 +1 @@ +# Effect 结构 \ No newline at end of file diff --git a/docs/loenn/entity_structs.md b/docs/loenn/entity_structs.md new file mode 100644 index 0000000..185ea56 --- /dev/null +++ b/docs/loenn/entity_structs.md @@ -0,0 +1 @@ +# Entity 结构 \ No newline at end of file diff --git a/docs/loenn/folder_structure.md b/docs/loenn/folder_structure.md new file mode 100644 index 0000000..690f718 --- /dev/null +++ b/docs/loenn/folder_structure.md @@ -0,0 +1,2 @@ +# Loenn 目录结构 + diff --git a/docs/loenn/nodes.md b/docs/loenn/nodes.md new file mode 100644 index 0000000..be51292 --- /dev/null +++ b/docs/loenn/nodes.md @@ -0,0 +1 @@ +# Loenn 节点 \ No newline at end of file diff --git a/docs/loenn/rendering.md b/docs/loenn/rendering.md new file mode 100644 index 0000000..f332a58 --- /dev/null +++ b/docs/loenn/rendering.md @@ -0,0 +1,15 @@ +# Loenn 绘制 + +## sprite 函数 + +## Loenn 绘制相关插件 + +### struct.drawable_line + +### struct.drawable_rectangle + +### struct.drawable_sprite + +### struct.drawable_nine_patch + +### struct.drawable_text \ No newline at end of file diff --git a/docs/loenn/trigger_structs.md b/docs/loenn/trigger_structs.md new file mode 100644 index 0000000..7588be9 --- /dev/null +++ b/docs/loenn/trigger_structs.md @@ -0,0 +1 @@ +# Trigger 结构 \ No newline at end of file diff --git a/docs/misc/change_log.md b/docs/misc/change_log.md index c233c54..f09ceaf 100644 --- a/docs/misc/change_log.md +++ b/docs/misc/change_log.md @@ -17,9 +17,14 @@ ### 2024.12.11 * 添加夜间模式 -* 分离阅读代码 -* 分离 StateMachine +* 分离[阅读代码](../coding_setup/code_reading.md) +* 分离 [StateMachine](../components/statemachine.md) -### 2024.12.15 +### 2024.12.16 +* 添加[跨 Mod 交互](../advanced/cross_mod_interactions.md) + +### 2024.12.21 * 更新项目模板 -* 添加跨 Mod 交互 +* 归档并重写[基础环境配置-通过模板创建项目](../coding_setup/basic_env.md) +* 添加[测试地图](../coding_challenges/test_map.md) +* 完善[跨 Mod 交互](../advanced/cross_mod_interactions.md) diff --git a/docs/misc/to_do_list.md b/docs/misc/to_do_list.md index 02119fd..d30de67 100644 --- a/docs/misc/to_do_list.md +++ b/docs/misc/to_do_list.md @@ -10,15 +10,14 @@ | 计划 | 状态 | | ----------------------------- | ------ | -| 完善跨 mod 交互 | 进行中 | -| 添加测试地图 | 进行中 | -| 更新基础环境配置-模板使用 | 准备中 | +| 分离 Loenn 节及补充 | 进行中 | +| 重写 EC 架构相关 | 准备中 | | everest 自带事件 | 计划中 | -| publicizer 的使用 | 计划中 | | 分离已有的组件进行重写 | 计划中 | | 完善 VisualStudio C# 调试 | 计划中 | -| 重构 hook 节 | 计划中 | +| 重构 Hook 节 | 计划中 | | 分离 DynamicData 相关 | 计划中 | | 完善 StateMachine | 计划中 | -| 添加 Effext 相关 | 计划中 | +| 添加 Effect 相关 | 计划中 | | 添加 Collider 相关 | 计划中 | + diff --git a/docs/resources/CelesteModTutorial.zip b/docs/resources/CelesteModTutorial.zip new file mode 100644 index 0000000..08d1e83 Binary files /dev/null and b/docs/resources/CelesteModTutorial.zip differ diff --git a/mkdocs.yml b/mkdocs.yml index 9062e6f..fac76bf 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -70,7 +70,16 @@ nav: - Session, Settings, SaveData: "basics/session_settings_savedata.md" - 进阶: - 跨 Mod 交互: "advanced/cross_mod_interactions.md" + # - Loenn: + # - Loenn 目录结构: "loenn/folder_structure.md" + # - Loenn 基础配置: "loenn/basic_configurations.md" + # - Entity 结构: "loenn/entity_structs.md" + # - Trigger 结构: "loenn/trigger_structs.md" + # - Loenn 绘制: "loenn/rendering.md" + # - Loenn 节点: "loenn/nodes.md" + # - Effect 结构: "loenn/effect_structs.md" - 实战: + - 测试地图: "coding_challenges/test_map.md" - 简单自定义实体: "coding_challenges/simple_entity.md" - 简单自定义Trigger: "coding_challenges/simple_trigger.md" - 简单贴图: "coding_challenges/simple_texturing.md" @@ -97,6 +106,7 @@ nav: - FAQ: "extra_cmcc/cmcc/todo.md" - 历史归档: - 基础环境配置: "arc/basic_env.md" + - 通过模板创建项目: "arc/project_template.md" - 偏好-sdk-styled-proj: "arc/sdk-styled-proj.md" - 杂项: - ChangeLog: "misc/change_log.md" diff --git a/src/CelesteModTutorial/Dialog/English.txt b/src/CelesteModTutorial/Dialog/English.txt new file mode 100644 index 0000000..c1782fc --- /dev/null +++ b/src/CelesteModTutorial/Dialog/English.txt @@ -0,0 +1,9 @@ +# Inline Text Commands: +# {~}wavy text{/~} +# {!}impact text{/!} +# {>> x}changes speed at which characters are displayed{>>} +# {# 000000}this text is black{#} (uses HEX color values) +# {+MENU_BEGIN} inserts the dialog from the MENU_BEGIN value (in English, "CLIMB") +# {n} creates a newline, without a page break +# {0.5} creates a 0.5 second pause +# {big}this text is large{/big} diff --git a/src/CelesteModTutorial/Dialog/Simplified Chinese.txt b/src/CelesteModTutorial/Dialog/Simplified Chinese.txt new file mode 100644 index 0000000..c1782fc --- /dev/null +++ b/src/CelesteModTutorial/Dialog/Simplified Chinese.txt @@ -0,0 +1,9 @@ +# Inline Text Commands: +# {~}wavy text{/~} +# {!}impact text{/!} +# {>> x}changes speed at which characters are displayed{>>} +# {# 000000}this text is black{#} (uses HEX color values) +# {+MENU_BEGIN} inserts the dialog from the MENU_BEGIN value (in English, "CLIMB") +# {n} creates a newline, without a page break +# {0.5} creates a 0.5 second pause +# {big}this text is large{/big} diff --git a/src/CelesteModTutorial/Graphics/Atlases/Gameplay/objects/PassByRefill/pass_by_refill.png b/src/CelesteModTutorial/Graphics/Atlases/Gameplay/objects/PassByRefill/pass_by_refill.png new file mode 100644 index 0000000..5754242 Binary files /dev/null and b/src/CelesteModTutorial/Graphics/Atlases/Gameplay/objects/PassByRefill/pass_by_refill.png differ diff --git a/src/CelesteModTutorial/Loenn/entities/PassByRefill.lua b/src/CelesteModTutorial/Loenn/entities/PassByRefill.lua new file mode 100644 index 0000000..17a48c2 --- /dev/null +++ b/src/CelesteModTutorial/Loenn/entities/PassByRefill.lua @@ -0,0 +1,20 @@ +local entity = {} + +entity.name = "CelesteModTutorial/PassByRefill" +entity.placements = { + name = "normal", + data = { + width = 16, + height = 16, + dashes = 1 + } +} + +entity.fieldInformation = +{ + dashes = { + fieldType = "integer" + } +} + +return entity \ No newline at end of file diff --git a/src/CelesteModTutorial/Loenn/entities/PassByRefillWithTexture.lua b/src/CelesteModTutorial/Loenn/entities/PassByRefillWithTexture.lua new file mode 100644 index 0000000..fd67658 --- /dev/null +++ b/src/CelesteModTutorial/Loenn/entities/PassByRefillWithTexture.lua @@ -0,0 +1,21 @@ +local entity = {} + +entity.name = "CelesteModTutorial/PassByRefillWithTexture" +entity.placements = { + name = "normal", + data = { + dashes = 1 + } +} + +entity.fieldInformation = +{ + dashes = { + fieldType = "integer" + } +} + +entity.texture = "objects/PassByRefill/pass_by_refill" +entity.justification = { 0.0, 0.0 } + +return entity \ No newline at end of file diff --git a/src/CelesteModTutorial/Loenn/lang/en_gb.lang b/src/CelesteModTutorial/Loenn/lang/en_gb.lang new file mode 100644 index 0000000..373971e --- /dev/null +++ b/src/CelesteModTutorial/Loenn/lang/en_gb.lang @@ -0,0 +1,4 @@ +entities.CelesteModTutorial/PassByRefill.placements.name.normal=PassByRefill +entities.CelesteModTutorial/PassByRefillWithTexture.placements.name.normal=PassByRefillWithTexture + +triggers.CelesteModTutorial/SetPassByRefillDashesTrigger.placements.name.normal=SetPassByRefillDashesTrigger \ No newline at end of file diff --git a/src/CelesteModTutorial/Loenn/triggers/SetPassByRefillDashesTrigger.lua b/src/CelesteModTutorial/Loenn/triggers/SetPassByRefillDashesTrigger.lua new file mode 100644 index 0000000..597c758 --- /dev/null +++ b/src/CelesteModTutorial/Loenn/triggers/SetPassByRefillDashesTrigger.lua @@ -0,0 +1,20 @@ +local trigger = {} + +trigger.name = "CelesteModTutorial/SetPassByRefillDashesTrigger" +trigger.placements = { + name = "normal", + data = { + width = 16, + height = 16, + dashes = 2 + } +} + +trigger.fieldInformation = +{ + dashes = { + fieldType = "integer" + } +} + +return trigger \ No newline at end of file diff --git a/src/CelesteModTutorial/Maps/CelesteModTutorial/Test.bin b/src/CelesteModTutorial/Maps/CelesteModTutorial/Test.bin new file mode 100644 index 0000000..6fc2d92 Binary files /dev/null and b/src/CelesteModTutorial/Maps/CelesteModTutorial/Test.bin differ diff --git a/src/CelesteModTutorial/Source/.everestignore b/src/CelesteModTutorial/Source/.everestignore new file mode 100644 index 0000000..e69de29 diff --git a/src/CelesteModTutorial/Source/CelesteMod.props b/src/CelesteModTutorial/Source/CelesteMod.props new file mode 100644 index 0000000..7fc2704 --- /dev/null +++ b/src/CelesteModTutorial/Source/CelesteMod.props @@ -0,0 +1,66 @@ + + + + Library + ../../../ + net7.0 + true + + true + + false + false + true + true + + + + + + + + + + + + + + + + $(CelesteRootPath)/Celeste.dll + False + + + + $(CelesteRootPath)/FNA.dll + False + + + $(CelesteRootPath)/MMHOOK_Celeste.dll + False + + + $(CelesteRootPath)/YamlDotNet.dll + False + + + $(CelesteRootPath)/MonoMod.Utils.dll + False + + + $(CelesteRootPath)/Mono.Cecil.dll + False + + + $(CelesteRootPath)/MonoMod.RuntimeDetour.dll + False + + + + \ No newline at end of file diff --git a/src/CelesteModTutorial/Source/CelesteMod.targets b/src/CelesteModTutorial/Source/CelesteMod.targets new file mode 100644 index 0000000..1e9a245 --- /dev/null +++ b/src/CelesteModTutorial/Source/CelesteMod.targets @@ -0,0 +1,32 @@ + + + + + <_CompileOutput Include="$(OutputPath)/**"/> + + + + + + + + + + + + + + + + + + $(CelesteRootPath)/Mods/Cache/%(Identity).%(Identity).dll + $(CelesteRootPath)/Mods/Cache/%(Identity).%(AssemblyName).dll + false + + + + \ No newline at end of file diff --git a/src/CelesteModTutorial/Source/CelesteModTutorial.csproj b/src/CelesteModTutorial/Source/CelesteModTutorial.csproj new file mode 100644 index 0000000..c1877a4 --- /dev/null +++ b/src/CelesteModTutorial/Source/CelesteModTutorial.csproj @@ -0,0 +1,20 @@ + + + + + Celeste.Mod.CelesteModTutorial + latest + enable + + + + + false + + + false + + + + + \ No newline at end of file diff --git a/src/CelesteModTutorial/Source/CelesteModTutorialModule.cs b/src/CelesteModTutorial/Source/CelesteModTutorialModule.cs new file mode 100644 index 0000000..c49d11a --- /dev/null +++ b/src/CelesteModTutorial/Source/CelesteModTutorialModule.cs @@ -0,0 +1,25 @@ +namespace Celeste.Mod.CelesteModTutorial +{ + public class CelesteModTutorialModule : EverestModule + { + public static CelesteModTutorialModule Instance { get; private set; } + + public override Type SettingsType => typeof(CelesteModTutorialSettings); + public static CelesteModTutorialSettings Settings => (CelesteModTutorialSettings)Instance._Settings; + + public override Type SessionType => typeof(CelesteModTutorialSession); + public static CelesteModTutorialSession Session => (CelesteModTutorialSession)Instance._Session; + + public override Type SaveDataType => typeof(CelesteModTutorialSaveData); + public static CelesteModTutorialSaveData SaveData => (CelesteModTutorialSaveData)Instance._SaveData; + + public override void Load() + { + Instance = this; + } + + public override void Unload() + { + } + } +} \ No newline at end of file diff --git a/src/CelesteModTutorial/Source/CelesteModTutorialSaveData.cs b/src/CelesteModTutorial/Source/CelesteModTutorialSaveData.cs new file mode 100644 index 0000000..6c4985b --- /dev/null +++ b/src/CelesteModTutorial/Source/CelesteModTutorialSaveData.cs @@ -0,0 +1,6 @@ +namespace Celeste.Mod.CelesteModTutorial +{ + public class CelesteModTutorialSaveData : EverestModuleSaveData + { + } +} \ No newline at end of file diff --git a/src/CelesteModTutorial/Source/CelesteModTutorialSession.cs b/src/CelesteModTutorial/Source/CelesteModTutorialSession.cs new file mode 100644 index 0000000..4bbecbf --- /dev/null +++ b/src/CelesteModTutorial/Source/CelesteModTutorialSession.cs @@ -0,0 +1,6 @@ +namespace Celeste.Mod.CelesteModTutorial +{ + public class CelesteModTutorialSession : EverestModuleSession + { + } +} \ No newline at end of file diff --git a/src/CelesteModTutorial/Source/CelesteModTutorialSettings.cs b/src/CelesteModTutorial/Source/CelesteModTutorialSettings.cs new file mode 100644 index 0000000..ee33861 --- /dev/null +++ b/src/CelesteModTutorial/Source/CelesteModTutorialSettings.cs @@ -0,0 +1,6 @@ +namespace Celeste.Mod.CelesteModTutorial +{ + public class CelesteModTutorialSettings : EverestModuleSettings + { + } +} \ No newline at end of file diff --git a/src/CelesteModTutorial/Source/Entities/PassByRefill.cs b/src/CelesteModTutorial/Source/Entities/PassByRefill.cs new file mode 100644 index 0000000..6a03ebb --- /dev/null +++ b/src/CelesteModTutorial/Source/Entities/PassByRefill.cs @@ -0,0 +1,52 @@ +using Celeste.Mod.Entities; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Celeste.Mod.CelesteModTutorial.Entities; + +[Tracked] +[CustomEntity("CelesteModTutorial/PassByRefill")] +public class PassByRefill : Entity +{ + public int Dashes = 0; + + public PassByRefill(Vector2 position, Vector2 size, int dashes) + { + Position = position; + Collider = new Hitbox(64f, 64f); + Dashes = dashes; + } + + public PassByRefill(EntityData data, Vector2 offset) + : this(data.Position + offset, new Vector2(data.Width, data.Height), data.Int("dashes")) + { + + } + + public override void Update() + { + base.Update(); + + // 获取 Player 实例 (别害怕!) + var player = Scene.Tracker.GetEntity(); + + // 检测是否与玩家碰撞 + if (player is not null && CollideCheck(player)) + { + // 如果碰撞了, 那么设置它的冲刺数 + player.Dashes = Dashes; + } + } + + public override void Render() + { + base.Render(); + + Color c = Color.Red; + c.A = 127; + Draw.Rect(Position, Width, Height, c); + } +} diff --git a/src/CelesteModTutorial/Source/Entities/PassByRefillWithTexture.cs b/src/CelesteModTutorial/Source/Entities/PassByRefillWithTexture.cs new file mode 100644 index 0000000..d886b86 --- /dev/null +++ b/src/CelesteModTutorial/Source/Entities/PassByRefillWithTexture.cs @@ -0,0 +1,50 @@ +using Celeste.Mod.Entities; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Celeste.Mod.CelesteModTutorial.Entities; + +[Tracked] +[CustomEntity("CelesteModTutorial/PassByRefillWithTexture")] +public class PassByRefillWithTexture : Entity +{ + public int Dashes = 0; + + public PassByRefillWithTexture(Vector2 position, int dashes) + { + Position = position; + Collider = new Hitbox(64f, 64f); + Dashes = dashes; + + // 获取材质 + MTexture tex = GFX.Game["objects/PassByRefill/pass_by_refill"]; + + // 向实体添加 Image 组件 + Image image = new(tex); + Add(image); + } + + public PassByRefillWithTexture(EntityData data, Vector2 offset) + : this(data.Position + offset, data.Int("dashes")) + { + + } + + public override void Update() + { + base.Update(); + + // 获取 Player 实例 (别害怕!) + var player = Scene.Tracker.GetEntity(); + + // 检测是否与玩家碰撞 + if (player is not null && CollideCheck(player)) + { + // 如果碰撞了, 那么设置它的冲刺数 + player.Dashes = Dashes; + } + } +} diff --git a/src/CelesteModTutorial/Source/Triggers/SetPassByRefillDashesTrigger.cs b/src/CelesteModTutorial/Source/Triggers/SetPassByRefillDashesTrigger.cs new file mode 100644 index 0000000..b575f4c --- /dev/null +++ b/src/CelesteModTutorial/Source/Triggers/SetPassByRefillDashesTrigger.cs @@ -0,0 +1,40 @@ +using Celeste.Mod.CelesteModTutorial.Entities; +using Celeste.Mod.Entities; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Celeste.Mod.CelesteModTutorial.Triggers; + +[CustomEntity("CelesteModTutorial/SetPassByRefillDashesTrigger")] +public class SetPassByRefillDashesTrigger : Trigger +{ + public int Dashes; + + public SetPassByRefillDashesTrigger(EntityData data, Vector2 offset) + : base(data, offset) + { + Dashes = data.Int("dashes"); + } + + public override void OnEnter(Player player) + { + base.OnEnter(player); + + // 获取所有的 PassByRefill + var refills = Scene.Tracker.GetEntities().Cast(); + foreach (var refill in refills) + { + refill.Dashes = Dashes; + } + + // 获取所有的 PassByRefillWithTexture + var refillsWithTexture = Scene.Tracker.GetEntities().Cast(); + foreach (var refillWithTexture in refillsWithTexture) + { + refillWithTexture.Dashes = Dashes; + } + } +} diff --git a/src/CelesteModTutorial/everest.yaml b/src/CelesteModTutorial/everest.yaml new file mode 100644 index 0000000..ff276d4 --- /dev/null +++ b/src/CelesteModTutorial/everest.yaml @@ -0,0 +1,6 @@ +- Name: CelesteModTutorial + Version: 0.1.0 + DLL: Code/CelesteModTutorial.dll + Dependencies: + - Name: EverestCore + Version: 1.4465.0