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