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/index.md b/docs/index.md index 95cfadf..23fd351 100644 --- a/docs/index.md +++ b/docs/index.md @@ -6,6 +6,9 @@ 大部分文章可能会写的不明不白以至于需要频繁修改, 如果你有更好的修改建议的话欢迎来提 issue. +实战部分附带一张测试地图供读者下载下来乱弄研究与测试, +你可以在[这里](resources/CelesteModTutorial.zip)进行下载. + 那么一切就绪, 可以开始阅读 入门-第一节 了: [开始 - Celeste Everest MonoMod](basics/celeste_everest_monomod.md) diff --git a/docs/loenn/basic_configurations.md b/docs/loenn/basic_configurations.md new file mode 100644 index 0000000..921acee --- /dev/null +++ b/docs/loenn/basic_configurations.md @@ -0,0 +1,19 @@ +# Loenn 基础配置 + +## Lua + +## EntityData + +## 基础结构 + +### placements + +### fieldInformation + +### fieldOrder + +## 基础函数 + +### selection + +### sprite 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/to_do_list.md b/docs/misc/to_do_list.md index eeddd79..6350dab 100644 --- a/docs/misc/to_do_list.md +++ b/docs/misc/to_do_list.md @@ -12,6 +12,7 @@ | ----------------------------- | ------ | | 完善跨 mod 交互 | 进行中 | | 添加测试地图 | 进行中 | +| 分离 Loenn 节及补充 | 准备中 | | 更新基础环境配置-模板使用 | 准备中 | | everest 自带事件 | 计划中 | | publicizer 的使用 | 计划中 | @@ -20,6 +21,6 @@ | 重构 hook 节 | 计划中 | | 分离 DynamicData 相关 | 计划中 | | 完善 StateMachine | 计划中 | -| 添加 Effext 相关 | 计划中 | +| 添加 Effect 相关 | 计划中 | | 添加 Collider 相关 | 计划中 | diff --git a/docs/resources/CelesteModTutorial.zip b/docs/resources/CelesteModTutorial.zip new file mode 100644 index 0000000..1fa9ec0 Binary files /dev/null and b/docs/resources/CelesteModTutorial.zip differ diff --git a/mkdocs.yml b/mkdocs.yml index 9062e6f..a6daec4 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -70,6 +70,14 @@ 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" + # - Loenn 节点: "loenn/nodes.md" + # - Loenn 绘制: "loenn/rendering.md" + # - Entity 结构: "loenn/entity_structs.md" + # - Trigger 结构: "loenn/trigger_structs.md" + # - Effect 结构: "loenn/effect_structs.md" - 实战: - 简单自定义实体: "coding_challenges/simple_entity.md" - 简单自定义Trigger: "coding_challenges/simple_trigger.md" diff --git a/src/CelesteModTutorial/CelesteModTutorial.dll b/src/CelesteModTutorial/CelesteModTutorial.dll new file mode 100644 index 0000000..31b1356 Binary files /dev/null and b/src/CelesteModTutorial/CelesteModTutorial.dll differ diff --git a/src/CelesteModTutorial/Code/CelesteMod.props b/src/CelesteModTutorial/Code/CelesteMod.props new file mode 100644 index 0000000..792e275 --- /dev/null +++ b/src/CelesteModTutorial/Code/CelesteMod.props @@ -0,0 +1,80 @@ + + + Library + + false + false + ModFolder + copy + false + + + + + + + net452 + x86 + + + net7.0 + + + + true + $(CelesteRootPath) + $(CelesteRootPath)/legacyRef + + + + + + + + + + + + + + + + + + + + + + $(CelesteAssemblyPath)/Celeste.exe + False + + + $(CelesteAssemblyPath)/Celeste.dll + False + + + $(CelesteAssemblyPath)/FNA.dll + False + + + $(CelesteAssemblyPath)/MMHOOK_Celeste.dll + False + + + $(CelesteAssemblyPath)/YamlDotNet.dll + False + + + $(CelesteAssemblyPath)/MonoMod.Utils.dll + False + + + $(CelesteAssemblyPath)/Mono.Cecil.dll + False + + + $(CelesteAssemblyPath)/MonoMod.RuntimeDetour.dll + False + + + \ No newline at end of file diff --git a/src/CelesteModTutorial/Code/CelesteMod.targets b/src/CelesteModTutorial/Code/CelesteMod.targets new file mode 100644 index 0000000..40377d7 --- /dev/null +++ b/src/CelesteModTutorial/Code/CelesteMod.targets @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/CelesteModTutorial/Code/CelesteModTutorial.csproj b/src/CelesteModTutorial/Code/CelesteModTutorial.csproj new file mode 100644 index 0000000..666d231 --- /dev/null +++ b/src/CelesteModTutorial/Code/CelesteModTutorial.csproj @@ -0,0 +1,19 @@ + + + + + $(AssemblyName) + preview + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/CelesteModTutorial/Code/CelesteModTutorialModule.cs b/src/CelesteModTutorial/Code/CelesteModTutorialModule.cs new file mode 100644 index 0000000..b82a686 --- /dev/null +++ b/src/CelesteModTutorial/Code/CelesteModTutorialModule.cs @@ -0,0 +1,35 @@ +using MonoMod.ModInterop; +using System.Reflection; + +namespace 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 LoadContent(bool firstLoad) + { + base.LoadContent(firstLoad); + } + + public override void Load() + { + Instance = this; + } + + public override void Unload() + { + + } +} \ No newline at end of file diff --git a/src/CelesteModTutorial/Code/CelesteModTutorialSaveData.cs b/src/CelesteModTutorial/Code/CelesteModTutorialSaveData.cs new file mode 100644 index 0000000..60fa5cd --- /dev/null +++ b/src/CelesteModTutorial/Code/CelesteModTutorialSaveData.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CelesteModTutorial; + +public class CelesteModTutorialSaveData : EverestModuleSaveData +{ +} diff --git a/src/CelesteModTutorial/Code/CelesteModTutorialSession.cs b/src/CelesteModTutorial/Code/CelesteModTutorialSession.cs new file mode 100644 index 0000000..02d2781 --- /dev/null +++ b/src/CelesteModTutorial/Code/CelesteModTutorialSession.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CelesteModTutorial; + +public class CelesteModTutorialSession : EverestModuleSession +{ +} diff --git a/src/CelesteModTutorial/Code/CelesteModTutorialSettings.cs b/src/CelesteModTutorial/Code/CelesteModTutorialSettings.cs new file mode 100644 index 0000000..f4c0d17 --- /dev/null +++ b/src/CelesteModTutorial/Code/CelesteModTutorialSettings.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CelesteModTutorial; + +public class CelesteModTutorialSettings : EverestModuleSettings +{ +} diff --git a/src/CelesteModTutorial/Code/Common.props b/src/CelesteModTutorial/Code/Common.props new file mode 100644 index 0000000..6da7abf --- /dev/null +++ b/src/CelesteModTutorial/Code/Common.props @@ -0,0 +1,11 @@ + + + D:\Steam\steamapps\common\Celeste + true + true + ModFolder + + copy + False + + \ No newline at end of file diff --git a/src/CelesteModTutorial/Code/Entities/PassByRefill.cs b/src/CelesteModTutorial/Code/Entities/PassByRefill.cs new file mode 100644 index 0000000..84cda12 --- /dev/null +++ b/src/CelesteModTutorial/Code/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 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/Code/Entities/PassByRefillWithTexture.cs b/src/CelesteModTutorial/Code/Entities/PassByRefillWithTexture.cs new file mode 100644 index 0000000..72c60ed --- /dev/null +++ b/src/CelesteModTutorial/Code/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 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/Code/ModFolder/CelesteModTutorial.dll b/src/CelesteModTutorial/Code/ModFolder/CelesteModTutorial.dll new file mode 100644 index 0000000..31b1356 Binary files /dev/null and b/src/CelesteModTutorial/Code/ModFolder/CelesteModTutorial.dll differ diff --git a/src/CelesteModTutorial/Code/ModFolder/CelesteModTutorial.pdb b/src/CelesteModTutorial/Code/ModFolder/CelesteModTutorial.pdb new file mode 100644 index 0000000..791d325 Binary files /dev/null and b/src/CelesteModTutorial/Code/ModFolder/CelesteModTutorial.pdb differ diff --git a/src/CelesteModTutorial/Code/Triggers/SetPassByRefillDashesTrigger.cs b/src/CelesteModTutorial/Code/Triggers/SetPassByRefillDashesTrigger.cs new file mode 100644 index 0000000..c105db9 --- /dev/null +++ b/src/CelesteModTutorial/Code/Triggers/SetPassByRefillDashesTrigger.cs @@ -0,0 +1,40 @@ +using Celeste.Mod.Entities; +using CelesteModTutorial.Entities; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace 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/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..8d4d121 Binary files /dev/null and b/src/CelesteModTutorial/Maps/CelesteModTutorial/Test.bin differ diff --git a/src/CelesteModTutorial/everest.yaml b/src/CelesteModTutorial/everest.yaml new file mode 100644 index 0000000..a98aa18 --- /dev/null +++ b/src/CelesteModTutorial/everest.yaml @@ -0,0 +1,7 @@ +- Name: CelesteModTutorial + Version: 0.0.1 + DLL: CelesteModTutorial.dll + Dependencies: + - Name: Everest + Version: 1.4000.0 +