From c3ec0dfa0af0c0bfb9603c9c8d0960572c92fc41 Mon Sep 17 00:00:00 2001 From: Sakimori Date: Thu, 17 Apr 2025 22:55:24 -0400 Subject: [PATCH] thunderstore prep, got rope storage working --- .editorconfig | 7 +++ .github/workflows/build.yml | 55 ++++++++++++++++++++ .gitignore | 6 +++ ExampleMod.sln | 25 +++++++++ GlitchRestore/GlitchRestore.csproj | 28 ---------- GlitchRestore/Plugin.cs | 17 ------ LICENSE.md | 21 ++++++++ NuGet.Config | 6 +++ README.md | 59 +++++++++++++++++++++ Source/ExampleMod.cs | 81 +++++++++++++++++++++++++++++ Source/GlitchRestore.csproj | 70 +++++++++++++++++++++++++ Source/Log.cs | 23 ++++++++ Source/Patches.cs | 19 +++++++ thunderstore/README.md | 4 ++ thunderstore/icon.png | Bin 0 -> 19351 bytes thunderstore/thunderstore.toml | 27 ++++++++++ 16 files changed, 403 insertions(+), 45 deletions(-) create mode 100644 .editorconfig create mode 100644 .github/workflows/build.yml create mode 100644 .gitignore create mode 100644 ExampleMod.sln delete mode 100644 GlitchRestore/GlitchRestore.csproj delete mode 100644 GlitchRestore/Plugin.cs create mode 100644 LICENSE.md create mode 100644 NuGet.Config create mode 100644 README.md create mode 100644 Source/ExampleMod.cs create mode 100644 Source/GlitchRestore.csproj create mode 100644 Source/Log.cs create mode 100644 Source/Patches.cs create mode 100644 thunderstore/README.md create mode 100644 thunderstore/icon.png create mode 100644 thunderstore/thunderstore.toml diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..bdfffd9 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,7 @@ +root = true + +[*.cs] +csharp_new_line_before_open_brace = none +csharp_new_line_before_else = false +csharp_new_line_before_catch = false +csharp_new_line_before_finally = false \ No newline at end of file diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..94a92e0 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,55 @@ +name: build + +on: + push: + branches: [ "main" ] + tags: + - 'v*' + pull_request: + branches: [ "main" ] + workflow_dispatch: + +jobs: + build: + permissions: + contents: write + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Download libs-stripped + uses: actions/checkout@v3 + with: + repository: nine-sols-modding/libs-stripped + path: libs-stripped + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 8.0.x + - name: Restore dependencies + run: dotnet restore + - name: Install tcli + run: dotnet tool install -g tcli + - name: Check against all game versions + run: | + cut -f1 -d' ' libs-stripped/versions.txt | while IFS= read -r version; do + echo "Checking $version" + dotnet build --no-restore -p:DllPath="$PWD/libs-stripped/$version" + done + - name: Publish build + run: | + publish_version=$(cut -f1 -d' ' libs-stripped/versions.txt | tail -n1) + dotnet publish --no-restore -p:DllPath="$PWD/libs-stripped/$publish_version" + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: build + path: | + thunderstore/build/*.zip + thunderstore/build/dll/*.dll + - name: Release + if: startsWith(github.ref, 'refs/tags/') + uses: softprops/action-gh-release@v2 + with: + files: | + thunderstore/build/*.zip + thunderstore/build/dll/*.dll diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6d0bce9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +/.idea +/.vs + +/thunderstore/build +obj +bin diff --git a/ExampleMod.sln b/ExampleMod.sln new file mode 100644 index 0000000..c14ba38 --- /dev/null +++ b/ExampleMod.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.10.34928.147 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GlitchRestore", "Source\GlitchRestore.csproj", "{FC7FF0C4-8F9F-43B9-963F-5C8B3B8920AF}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {FC7FF0C4-8F9F-43B9-963F-5C8B3B8920AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FC7FF0C4-8F9F-43B9-963F-5C8B3B8920AF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FC7FF0C4-8F9F-43B9-963F-5C8B3B8920AF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FC7FF0C4-8F9F-43B9-963F-5C8B3B8920AF}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {2357817E-B903-4DD8-B0FD-64E75AAFD672} + EndGlobalSection +EndGlobal diff --git a/GlitchRestore/GlitchRestore.csproj b/GlitchRestore/GlitchRestore.csproj deleted file mode 100644 index 04a5417..0000000 --- a/GlitchRestore/GlitchRestore.csproj +++ /dev/null @@ -1,28 +0,0 @@ - - - - netstandard2.0 - GlitchRestore - My first plugin - 1.0.0 - true - latest - - https://api.nuget.org/v3/index.json; - https://nuget.bepinex.dev/v3/index.json; - https://nuget.samboy.dev/v3/index.json - - GlitchRestore - - - - - - - - - - - - - diff --git a/GlitchRestore/Plugin.cs b/GlitchRestore/Plugin.cs deleted file mode 100644 index 648dbb6..0000000 --- a/GlitchRestore/Plugin.cs +++ /dev/null @@ -1,17 +0,0 @@ -using BepInEx; -using BepInEx.Logging; - -namespace GlitchRestore; - -[BepInPlugin(MyPluginInfo.PLUGIN_GUID, MyPluginInfo.PLUGIN_NAME, MyPluginInfo.PLUGIN_VERSION)] -public class Plugin : BaseUnityPlugin -{ - internal static new ManualLogSource Logger; - - private void Awake() - { - // Plugin startup logic - Logger = base.Logger; - Logger.LogInfo($"Plugin {MyPluginInfo.PLUGIN_GUID} is loaded!"); - } -} diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..c13f991 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/NuGet.Config b/NuGet.Config new file mode 100644 index 0000000..1864ded --- /dev/null +++ b/NuGet.Config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..9a1020d --- /dev/null +++ b/README.md @@ -0,0 +1,59 @@ +# Nine Sols Example Mod + +## Set up your mod +1. Set up modding with BepInEx and r2modman: [Wiki: Getting Started](https://github.com/nine-sols-modding/Resources/wiki/Getting-started) + 1. download the `NineSolsAPI` mod if you want to use it, +2. clone this repo ([generate from this template](https://github.com/new?template_name=NineSols-ExampleMod&template_owner=jakobhellermann), then update the `.csproj` + 1. Change `` to your mod name + 2. Make sure the `` points to the installed game +3. Install `tcli` tool for building thunderstore mods: `dotnet tool install -g tcli` +4. Follow the **Building** section to make sure everything works as expected. Load into a game and press `Ctrl-H` to toggle your hat wherever you are. + +_Next steps_: +- setup hot reloading for faster iteration times +- use a tool like [ILSpy](https://github.com/icsharpcode/ILSpy) or [dnSpy](https://github.com/dnSpy/dnSpy) to decompile the game code +- check out the [UnityExplorer](https://thunderstore.io/c/nine-sols/p/ninesolsmodding/UnityExplorer/) mod to investigate objects in the game + +## Building + +If you run +```sh +dotnet publish +``` +it will build the DLL of your mod (`Source/bin/Release/netstandard2.1/publish/ExampleMod.dll`), then use `tcli` to +package the mod into a thunderstore-compatible zip in `thunderstore/build/`. + +You can import that mod into your r2modman instance like this: +r2modman config to import local mod + + +## Publishing + +Make sure to fill out all fields in the [thunderstore.toml](./thunderstore/thunderstore.toml). +Then go to https://thunderstore.io/c/nine-sols/create and upload your mod zip, or use tcli with a token created in +[thunderstore.io](thunderstore.io) at `Settings / Teams / Service Accounts`: +```sh +tcli build --config-path ../thunderstore/thunderstore.toml --token $token +``` + +## Hot Reloading + +Building the mod and restarting the game after every minor change becomes cumbersome quickly. Luckily, BepInEx supports hot reloading of DLLs via [ScriptEngine](https://github.com/BepInEx/BepInEx.Debug). + +Download the [ScriptEngine](https://thunderstore.io/c/nine-sols/p/ninesolsmodding/BepinExScriptEngine/) mod in your r2modman instance, and the game will be able to reload DLLs from `r2modmanProfileFolder/BepInEx/scripts/`. + +Go into the `ExampleMod.csproj` file and fill out the `` and uncomment the `` below it. +Now, whenever you hit "Build" in your IDE, the mod DLL will be placed into that `scripts` folder. + +Note: **Disable your mod in r2modman if it is active to prevent it from being loaded twice!** + +By default, ScriptEngine will only reload scripts when you press `F6`, but you can go into r2modman's Config Editor and +edit `BepInEx\config\com.bepis.bepinex.scriptengine.cfg` to have +- `EnableFileSystemWatcher=true` +- `AutoReloadDelay=0` +- `LoadOnStart=true` + +to reload scripts immediately. + +Hot reloading works by first destroying your mod instance game objects and then reinstantiating them, so make sure to clean +up any state you left in the `OnDestroy` callback. \ No newline at end of file diff --git a/Source/ExampleMod.cs b/Source/ExampleMod.cs new file mode 100644 index 0000000..a2a3c64 --- /dev/null +++ b/Source/ExampleMod.cs @@ -0,0 +1,81 @@ +using BepInEx; +using BepInEx.Configuration; +using HarmonyLib; +using NineSolsAPI; +using System; +using UnityEngine; + +namespace GlitchRestore; + +[BepInPlugin(MyPluginInfo.PLUGIN_GUID, MyPluginInfo.PLUGIN_NAME, MyPluginInfo.PLUGIN_VERSION)] +public class ExampleMod : BaseUnityPlugin { + // https://docs.bepinex.dev/articles/dev_guide/plugin_tutorial/4_configuration.html + private ConfigEntry enableSomethingConfig = null!; + private ConfigEntry somethingKeyboardShortcut = null!; + + private Harmony harmony = null!; + + [HarmonyPatch(typeof(PlayerHurtState), nameof(PlayerHurtState.OnStateEnter))] + internal static class RopeRestore { + private static void Prefix(Player ___player, out ClimbableRope __state) { + __state = ___player.touchingRope; + } + + private static void Postfix(ClimbableRope __state, ref Player ___player) { + if (__state != null) { + ___player.touchingRope = __state; + } + } + } + + //[HarmonyPatch(typeof(EffectDealer), nameof(EffectDealer.HitEffectSensorExitCheck))] + //internal static class DamageRespawnRestore { + //I think it's in EffectDealer but I'm not sure + //} + + private void Awake() { + Log.Init(Logger); + RCGLifeCycle.DontDestroyForever(gameObject); + + // Load patches from any class annotated with @HarmonyPatch + harmony = Harmony.CreateAndPatchAll(typeof(ExampleMod).Assembly); + + enableSomethingConfig = Config.Bind("General.Something", "Enable", true, "Enable the thing"); + somethingKeyboardShortcut = Config.Bind("General.Something", "Shortcut", + new KeyboardShortcut(KeyCode.H, KeyCode.LeftControl), "Shortcut to execute"); + + // Usage of the modding API is entirely optional. + // It provides utilities like the KeybindManager, utilities for Instantiating objects including the + // NineSols lifecycle hooks, displaying toast messages and preloading objects from other scenes. + // If you do use the API make sure do have it installed when running your mod, and keep the dependency in the + // thunderstore.toml. + + KeybindManager.Add(this, TestMethod, () => somethingKeyboardShortcut.Value); + + Logger.LogInfo($"Plugin {MyPluginInfo.PLUGIN_GUID} is loaded!"); + } + + // Some fields are private and need to be accessed via reflection. + // You can do this with `typeof(Player).GetField("_hasHat", BindingFlags.Instance|BindingFlags.NonPublic).GetValue(Player.i)` + // or using harmony access tools: + private static readonly AccessTools.FieldRef + PlayerHasHat = AccessTools.FieldRefAccess("_hasHat"); + + private void TestMethod() { + if (!enableSomethingConfig.Value) return; + ToastManager.Toast("Shortcut activated"); + Log.Info("Log messages will only show up in the logging console and LogOutput.txt"); + + // Sometimes variables aren't set in the title screen. Make sure to check for null to prevent crashes. + if (Player.i == null) return; + + var hasHat = PlayerHasHat.Invoke(Player.i); + Player.i.SetHasHat(!hasHat); + } + + private void OnDestroy() { + // Make sure to clean up resources here to support hot reloading + + harmony.UnpatchSelf(); + } +} \ No newline at end of file diff --git a/Source/GlitchRestore.csproj b/Source/GlitchRestore.csproj new file mode 100644 index 0000000..acd7dfb --- /dev/null +++ b/Source/GlitchRestore.csproj @@ -0,0 +1,70 @@ + + + GlitchRestore + Patch speedrun glitches from the speedrun branch back into the main branch game. + netstandard2.1 + 1.0.0 + latest + enable + true + MSB3277 + + + + E:\SteamLibrary\steamapps\common\Nine Sols + $(HOME)/.local/share/Steam/steamapps/common/Nine Sols + $(NineSolsPath)/NineSols_Data/Managed + + + E:\SteamLibrary\steamapps\common\Nine Sols + $(HOME)/.config/r2modmanPlus-local/NineSols/profiles/Default + + $(ProfileDir)/BepInEx/scripts + + + + + $(DllPath)/Assembly-CSharp.dll + + + $(DllPath)/rcg.rcgmakercore.Runtime.dll + + + $(DllPath)/RCG_General.dll + + + $(DllPath)/InControl.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Log.cs b/Source/Log.cs new file mode 100644 index 0000000..afbfd42 --- /dev/null +++ b/Source/Log.cs @@ -0,0 +1,23 @@ +using BepInEx.Logging; + +namespace GlitchRestore; + +internal static class Log { + private static ManualLogSource? logSource; + + internal static void Init(ManualLogSource logSource) { + Log.logSource = logSource; + } + + internal static void Debug(object data) => logSource?.LogDebug(data); + + internal static void Error(object data) => logSource?.LogError(data); + + internal static void Fatal(object data) => logSource?.LogFatal(data); + + internal static void Info(object data) => logSource?.LogInfo(data); + + internal static void Message(object data) => logSource?.LogMessage(data); + + internal static void Warning(object data) => logSource?.LogWarning(data); +} \ No newline at end of file diff --git a/Source/Patches.cs b/Source/Patches.cs new file mode 100644 index 0000000..2284fc2 --- /dev/null +++ b/Source/Patches.cs @@ -0,0 +1,19 @@ +using HarmonyLib; + +namespace ExampleMod; + +[HarmonyPatch] +public class Patches { + + // Patches are powerful. They can hook into other methods, prevent them from runnning, + // change parameters and inject custom code. + // Make sure to use them only when necessary and keep compatibility with other mods in mind. + // Documentation on how to patch can be found in the harmony docs: https://harmony.pardeike.net/articles/patching.html + [HarmonyPatch(typeof(Player), nameof(Player.SetStoryWalk))] + [HarmonyPrefix] + private static bool PatchStoryWalk(ref float walkModifier) { + walkModifier = 1.0f; + + return true; // the original method should be executed + } +} \ No newline at end of file diff --git a/thunderstore/README.md b/thunderstore/README.md new file mode 100644 index 0000000..ad947c6 --- /dev/null +++ b/thunderstore/README.md @@ -0,0 +1,4 @@ +# Nine Sols Example Mod + +Write a description of your mod here, it will be displayed on thunderstore. +Remember to update the icon.png to something representing your mod. \ No newline at end of file diff --git a/thunderstore/icon.png b/thunderstore/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..63cb4997f9f4262f9736b7fa2daf3ab8eea93dcb GIT binary patch literal 19351 zcmd4244T3b%3=Ps!BCT|TbT@*4v~&*LG4udK{0@G; zbzRRt@Vp>=!F`VV-h1t}*IpB;sw|6*Nsb8ufw14pNvnfE2*9rhAaq3F$0VK@7w`kw zT0%(z1gehpg{vh3|E9H&Q&$3k!f`>MFTmG5@JB)7AdsIo2(%Xs0*P#aKxD(NBB7oj z5GJRMl$7dwDJfc27bhzl`wt+HT>p<`Pfg8PlJK#1PjJr2>j^S&BFF2%3l3T;WVPp3 zsLuyMJ-azMGNv_4bBtZNd86 zR~D?HuCRHZta=U*g9;4?CrUCRZ5s0`8dzXbCscO4`W}Sp6^Kv>dabut(jjr&EzZEn zPYP}sz_^QsJVTJX>-ey{r&1L1s4`Km*#QC#nDlPjD+?*~-q0%#66Hr7@z59cF+`EQ zi%jE`SM7B%k2TmV$nqnZR~tUGq&DbX|E@9r$DRuo;pGz+|H8aiwikuWP`NO|DO#83 zed;jrslg|E?(j4mP!vN0mO!}|env!UFD{N7{;3PdIlqZhU>l3XxdwS%syRR3>b&{W zDPjwULY$+m!$`J|3wNRbVo;7)V$#57?H&i~pAto5K2Wsv13TF#hrL{SgLHiZee!g& zG=H_?$Chh;#^WRUcFgM~o`@M(_)+DZ`aZ~XILfy60M}sHA0*U(NbC8Co3Tv?VvzB( z>pcDK{c+tpk`!It;Y$n;4^K=JWpYAOcIQEW&>gnlspyMSkIt0vm)bh+hh#Lb}SVfIvKeM4XM_7DV?NNxO?g0Fl26@jA#94`&9EBm(VE zATGBA$J{eaar`-yt6+Imq0 zO9ySzX~|)62M*JsTH-cKyj7(o!jX~sgojHY**s2CjQ%q8WsZI^{w;|Ricw&NB+|I( zN22s#|4>K|x?*ri6?Zu{MbEQ2jH|GaHC|`R@2ERnHz&$Xh!r7m-A5-V*FwH%)InK2 zwdmpz=-6sf&+t*#gRklE<=B78^3jIM395(J(HhBdx?qt>6ef7GJc|m>&3mTSz@nmw z9u+DteUpBE$StP(mS>s>~X%2oEIlrq$*7Yt&n87&+|6q#04Rzb5b%?Z65^5{u1Z zmLqgS_xNloiD<@?6Fe^2B<&^VCBr~49XZnrqEBgx)RhoXZj+>B?0E4f{^C7HzTDUN zxWmCaSKaF3YXPt=cW|LTm3mS^1ZS zFB#7am`t{-hGo*YFeU$HH>v7=d-V-G$T%oKEH#}2RwFEynQ|(=pCZ#EoBvRgQ=?a- zRby=_`w?9!V_QZcH)&jXJnSPhg@yBz{x7{6i}yocyBS?wqFiEKD4QjlwVQ=qpj&%q zj%Sf)ty{vIG_2V~7sQA}+{8F94b@Y%^ItB!tRcc8R$+nY1Sef2AtueRQfcpNq-$xb zU8yQ-K`MRKy!As1*NeYqs~5Uxe~?egwXGb~dZi&+bo+%v!84cnFWau@1sN|RuL^ID z{!jhRg|?Pha0ECLTz2~cI~Y~!g?64|o`J%cQeSft&BDxT*NX8+2KrgXihFiLs|!DUK6TtM-cVs8VS3MW z$%L!;K~X1lJIy2Q!M4z;kGqV!)j^rhlYiwS#OA>zt($waCS>SXUzOeWRfC?Jfp1-1 z&89(vuCktuzKnsE0X9$Zvw(M88&SLq3-jQ-OPd2vzGObc3_`xnIr0Uj1-^M@j#<4? zJ>yQ_Vddpm8y!1-bCt%p1~E&q_3Z5~w_;bX_2RVw4}0hD&J(Wk&O+N4zvg?>piA2# zJLVfTkgYbh_5C&d-32Jq2Fbei-qoDZvgm00ykB3>FN+`j-YRuPjXREGW}F{5lXdcD zhcU~D4|FcP65B%B*xIwMci|^~Exu+e#2r4qG!;|&e+=f=(C*squC7JTW=~blAK!uq zS7}sL~VKKvHZP8|4YGI|zQSMj1V=wDL<`ZSn&$^}9yYM@?Pq}aY_fcdtJfv5GTG@yu@%1H3-ckyCTyfbK;TWQL%b&eOhx{b6M+Ysj}I$`OtbXiZ4jm<^T!f$Ioydu!?$71sD$mfyBjDP{2KWrmD?Tq#cIvp+#g?H6I zsSPr)7%;C)r|o4Ob{wHAW*rufu_~d5zwBg~WVU2zqV#^xc5vU9u9t=Ws1}AR zuq)sk|2kYhB40SFf`2S=vr*ogqh1j``fyS6t7g_G@5=a=D?K+I7Ty$oJOiF;n6;TrqUoa?6}YQ= zTh{@z>zj?i#>AGvrinX={X&T?vM~8^dTuU%N^{~FKUPLjtPFMQP0RuRk5^%@>VMYF zIf&`rjn6pEulV=uzuQqd$S^`0LL0>qdS=|T z1wJ@)s9c8Gd?Kv{|%8SV|a^Xq8x0v{dBy*5Ka$&U^p-W-mCa zAfUoO2fp5FLK(1^p~uVf@b%GUZFXJftTMLE_^QQcCgAEcW0U{fHPmTqh1##*YZm_Y z@V?h~8|^SWDh^E3`qn!D+!WtdbwUCAd=BSFW~BybCWf<|o+}8%LHG29fM#&_2m*;u zyqA{H^fEsB;TcaU>p917IEN+hS!xs+oxpSyx$C>@ZLnstW!YW0R)tIRW{p;ZJV!G- zvsSa^pO>w7af7#(2k^IlOiV%O@u2sCAOr$h{0M10X;g$IDvq71##aC3dvFol9d=0R zc;!ec+=1ymLWh9mzE*?|K&H0zqkVtvs1mL zrK+ivpA;Q7U%#@bXvFgG;kK#S*jw@<4?QUOibzXcsozp=d(={z#FmIf%4{_jrK9D; z!?2T@#Bxrhvy-_sA5eFu!Qyc57R;g9nBpnx8c7BZI#zBpaDq#zh^twtZ%+N=WiD1|}z zN+t#in9f_s6)?eK+5EJrFr+XVwBn`zIa*z78aO)FyHhceoRFAsU?|`o3X4sdv<)Q5~uSHtpVMvBk)4JxU?{iS++G)n8b&b_5&_wX7 zbR4S*u1l*)iS&%CCzL=kO6IN~a{Hv0kx$Aua}IY;(mHP@PuCE>F?YwbVN~e5Dol3X zZ%jpV5|6=I@8T=^2*?>A`QZ9JY*omC`$u6a|1WcFvpst)3E?CuA(%YvJtovA~+zYdA1&fuQE4glSsQ(OU#UIcDKb!j(QE*+V!# zF5eq-WJs7zECnK{!nO_SRoLP%V1m01oT6)VKX=49vGm)J7h_r;n>-@0U6`IHr-W@{%s*e*%2X6}!p?4=gkRQf> zI3=W&(SP~Xocf0bYkLHHcg_pTj07pgL@EdJWiJ_`Bz^@xrt5n@OM3G5O(GJ7NE~YDlWsIW= zw3!eY!`DNGcVCZ%{lO*xorZ;nM(;u!#+Yd>1-7>G)6Ftk=P+Cp0@+5Tea*u$c~>u#qhN_i$9kBZSe=o*HP?rt4S)t zc_U>5^JECqnv~HrWl6bV{l)2Kh}p!#3_pDpiT>{0V_G5Q$2MG$ZuU+7^x?}>MIL+$ zDuuR{fscfQ3X#1difs~KcK>lMnOBr%RZC3V=SEmk2r$nrIdzQ`SuF>^qKcsB^Hdo9 zkOEr|vg%W+i{{Hwte!ly>G$WTO!^tI>rf7gfJ#gE15Tub3dO4mI#Gp*7A97NTZ18> zBAA8&4G?>_M%{U?g+Tft;qv12-a_T6)ZJn&#>!;s-6Me$j3MHfGn~MwL>0#E5m~x8 zyS++W(NB8UCSK~z#bwpK9q>Y$MK(|Un^H4d^Jm}cCX_6-+NKKMjp2A< zpKv^u>MufIwR>DdQBq`R;<+WPm+M1rx>OJ-u?wQNSoM0i8?TXp>G?}-^GO*)TfRgL z9S$xwSm{?&3=JtQAeZHMGmC9Y1#{wIxb=p+qVDLSxoUj~@!+Ev>6ZoAr*-ze?!1)< z{{e$H>e&Do1eMnfo<7&&Q3O4~fy|WVHz^=LQ?cV?F4|09q}VNAI(FRu&ND=!ZT9uH zy+@sO=Gmm|Y1&?zj>w3iG7Ltyia{1e@?bAQ_Vvexc=R zs$r2k+1qjbCpMegyFe&Y|GN6r@e(%HeY8!tuUk`6F-r+bK$^wogknIPIcZS3mJ1jnS1sx z{C`NgR#GR=wMBh5Qq_$~6(A9t85A{)rpdt29>sZICdm{W42dhw9fA}0frW)}p^`b* z-%LRHnSLBxb~u=U8||6H?R+K3Ddb~`d-!;~D*fIh0POxJ(g-iD!y|}Qi(RgQ|4%yp zL*6(R^F`|nm$XkrQ7UOD;^tT1r+CKlXz3C$Q>7}qdnFYDqA{5M4+t3iycm3?4Vp&y z!UyzNX)VcVyb(B~bPS*P$BDC*Q*KjQgQ0QBm?4dSDBwvGN<<96U&0$}ikK zTlVTvQF`1xZ0C+yAg$rm?Jmpm-Hk4aN^-X!k!6yBXhd3CybhuC_xjyTyW?0goFl1QEGEvEab~C zB@R}nMf?l1K5=32>*NQ*YDC>gGs%C^E&UhW?R#XscNE!t>fNO?-kY`6nI7zEIP$`v zuYYc7?w+6jf4cs6h|1#L#yuv=&%@^q;%bfKqr2)an5#>;5{kXAU)|?e`W8Pfq|liC zd80O=67gR2)bc*gKXHpvA%MF)Y{>X=!esgn4t7kYP(p{7e_NiYun5u6hxefm5rcL* z%R&bz4-&~EaY+P<{?m=*jyYigq`(`Nl$!N%Ga?^xwx*v=_2C+kMRN%krDYO_Ldp z&iBGE#5o?lTo!o4*z7fVMdiS_zBAQFIxNxxEX$0l%R`kIP+7h3;r6{5>JHn|{!M(_ z5Fd|*$D07^w@m?OkSu*awsU`+Qwy2iZ*DR8y>NH#5G144hFrY0LTLbPKYof@ImBk! zrB63_5t{tai!77;8u(xAq=+3Y-W?c%YvOW<--zDOD?Ah9Yqjd$z9)H8uRB`=wU!N2 z{o<^Vi_q0^l_=Nco5Ar*-gg=0Aup-ais$dNE`4x5tlb2MX0G4GOx0&HeIe-(W+!iQ z-7IY!el@yw-(g$*w~Q1X`+4SpB18RIV0!CuMTh&(X}HptgO(9^WaH@*`;ykG+9q3o zkqw3R4l|p4-mgc+v(!k79p;&83ohB#!r5vzgkPDI{UunF`hz0gRvLA`rEuww!VOb~ z&T>uV_nS6*3J42;*l37;WqbVIU&wHjkXY3Pcr*qPugJUUXM{~xJ;ESN{7{x=P_f_s zUjD6!XV)4K3qnI%N5Y($PCqPoHjhZ}e%5t0y}507!*vd1OwBIDU99{;?F+iN4T^ZK zjn(owr$nC{z7VVzH}#|5oo?o=G7I;20T)0A`&f}@NZYuz3U7g1%ya4n`mXmd8p^QawpJ zsO)EbN0H^mEh=L?^6f1Xd@e>KLOiy>QhY)VobLhxcYf8>c`isAFA-E-SCF*$f4+Q5 z9)4m>C5&>fyhs?LF1Xo|6Rojg1gsmk`mEk&_pl=Aoc60S;P zry7Y{7F0jm(F%`^gZZCN(tsibUH3EnNl-r2L`ngZOTTL3rD-!bHKD`J?D|B9iZ)@E3m(+57O&<1l7kD|5|>WG@nVhO!8Wh)#>vtjiD_t z|Kp%jJJ+Yu9nR9uBkJTA(KOx!6TD##rxt1&YvJP7tBaN49Eyv$woafzK~SmAieX0Q zd`6GVo5tkq{-&u2j3{=s>D2{XD2U}Vvhf2I#EC8&MiEVeSG!jo8&`Du@BME>Ql-te zY3?#g3x;%!M;irUVb*AK*Dh*6)|H|jJY0#vRZ^;|1Xi z7*dDrp-jY&)&@7|kHag`OgRqUHGV=~)^8)VNXAGPNG;OVK^8NGr7>|hM)NmA^r9$l z(I?43^%T@LcW9j>E`t&Ar~05np5D zAUMC_K@}mbePAJJ$Z{Yezrg7N>$I2FTfUF=Cpn~v_3padTZ#stsrD0f^S)=vlYI)7 zWQ7Ju0)rj45JeWe`i`H_&Ay(SdY#O)xQ%czW2C7>f;VvzqT1_ri0EbAll^F8-&g1H z20rvv9)WSW>kx3Do@IMmLL6nKEnz6Q9bL7PT^GpWE)RDt{aKcRg7n+F&ynvlNQ1+5 zCEEgk0({Zm`HqXBbbI(`XSC77&x+M_pRh6B31@b??TNkEIH`yAzOJ+lDbmgtF?H*U zq>2a?+kgDEtLK&$`3tQ$#m#KfGC{=wi7SUnvFKD(f|KaNmIk*6Op<`UAQ{4tapWU5 zoYjV&PVIx^k;t+;4iRiy(TQo_{C#{cY>E^p=~d@<>!|$5@k1nU<;btxnHT!Jo?cvq z@Xv3GJ+PN;Y8a^4*wbKy%JcS1#6R%h+IpINRon>i!aHt7mR(SO#}}vb7OfqJ({Av- z&rBH=wTbK1PV;i~EQt{wH-(f5ZD--V`qyPbYVgAL04*&)&E zErfVQzP3xLVb_7GbO>h+vXoM6NyRbt8<2*e$W*839gSl3Pyn}$^2@z+akU-`&5_p# z<1a}Mt~Zwr!HRM@lMgrHX$f=!(e{?;6ehKvg-ND=!e$MjxxXz+k!UY>H~xf1Uz`%? zp&C^?2PR;~6;~l4WDl0zJ{_RS z$QU+e^}{>nMz&ttfG?V*zpk|D16>Vhj?YN{c)m&@gI@1C&=JRF=K0798>q#PTpUCr z>YQIFvayv;2g9?^S6+)9n%hl1-E?5&0roU`^XBPR*HhbHX#d%t%0-)x z`&IO%1S@cJov{Ral)otu;$%GQ4h(f&?Y5hXgn30B-Cs{Wf-lmfwRkblHhtA)lBLKQ zcNR5!I#@P+_}`9Cwli;b8nixd^D2Ej{FG1>v*~s8Exai`r^r0op-k(10qtO$Ln7x| z(FpYBZdLZs%88P@ywJdab@Luw4T-Ah1m=M8m^Wr=G5H0~pG&JE-@?@8f#?XGUCo_n zHQb3+ny-ExP`9eG=-9up5OPyJFFZMjs1w~!sK9SK7Q*&Yg9yayxvbH?t)0M}mv_Ua z{&CNVMq1kzEcW{PrsDL2k@ zH+qkZ6$d6uPW$~}p%xry;nB10et&IDL#4kOQ{Gk`LL{Y<2aLy^(8rnyjA@jQ_#8FoD-T##51P7vv<^e>6Pfd=P#3Dv_D;bnAhY z)$4Km1`uOmBGxm>URDx+_L@iF(yrNjDZE+9H&{( z*tppT?YDg6erKeQycAcnT8f41RJ4~jmY()teeAn>^~QOoArqH=pAMtFtr+RFzR{NPBRc2Q+MRPWNOqvxPJ+d zKQ&gcNW!T};t5CM<%jA*!tJ3W%+)4YUfbYrhQQ8uB&iA!}IY~914 zwlaQA+v(FPBDj|hTErN*DYV@j?C&NhWcukwNU9#gd?!3lXC-2`hQ{C|^PE1`UHucS?{r(YI<2iY z)m3yq{SsTLO^-(8f`0uEed_UT>bL~_>=P+qN6(fKnH!c0aYEGY(c!E+M!)O-Y*^tA zYdtBwK+zz4YG?+|sPEa;v}&(&Qe@trvN(b?f9mSNS9{{=@+>l@FdTi=EF*{D;c?XD z!U3qECvsEMV_w&ve*Q?6w+BYARG$yXl-mELCyG5&iSBS@wTzpwz!`=93@z2muwXLDzh9 zVy^=?>da@p@KS~8+9y5mKaBVAHzDz`0;sfP3ps;4qFE8O?NP{)X6ot&u6MsETkeuo zf&YyU;3E=cuc%EL9+jQ4)9M7^5 z%V$}7Eq;r8!khD&$r1c(HeojDfzadNU~H>vTQKXQgVy?Blc@!dj~YjwgvN=)WX34YWFF z56ng8x|Oxu*YrLlIC2Kn{=2*SbRptXR{W2~hW?Zn4accdG{0&$_Ga2M)Ks(EUA;PW zSkSlc+dK~g-2Enh`DCtrSkw3hk{h;B7QHW@XT*kxQliVe>RPJp-Mg=zoBQqBBa4%b z_mYPi%&s;|dsgSk2MA5W?GwD=#9E1SQ<3Bmz8mmF3-F?A&yF){;&&i<> z0425Fo$n!VvgWzqMVc}P+jm@=Q3N1tr?#Zx3Z~^399WN^Xg@Y1lDhLI>xLlz*#@t0 z4!&4l=dI`A6AAUcuFULqI+jW132II`X?u$pQ681DFeUyu2ATwWRMCZvIGE8yu3Ha2 zJ?_mnK0Iinr0oj`Zf~O25cQek5&``hFiMZu*&a9JqP(Ytk|HI@UVOI(q-mggi_ge z#2LO-kr)dvUNFx{dagqso<6`0Xl#L_<;0$EUKxkDczvbWs#xi-5VxX(Zvtm-c=xrAvn?M36`HydpIayCEK2 z<9a(4a8wpomnhtpMZ6EFz~n(NW$Nvch5D9xtexf3yE~R=zn+0SY8!Qo&-bXsh!*-% zUPI=&nmm~?a|kLc92W-OhOQ8BTRcWkTHpLT|#CwVA02?zsFSb(%4o5DZ#;a-o&@3ZLbn@ zYNck@z&gF%g0Tf=_Yru~cw1IBk zZ8L^iQe30&Vh=VFj!#J^OR+b7yi)$sbyrVen{l{O(TO9871&~(701ReJI<73>V~oA z?Nmh+K~6Pp-_VHO=|%Jg(%Mn_=UTl2C}qkYn!yXgz@~zaPzF1}R-`%&WIFA7H*{PH z%QjT3IQHgDPV#*2To=Cfj37a#DVBY`#0PoKVUuJzGD}t^)7c-Nq_Q&WocR$YfCfFD zjm8d~QxMSMLobm4EHTiobGkV_V2-yaDLqBthg|6>Nb8(^&*zW2^^RBXd};X6x*CEtHg_75E`&i=;G1R6E^}kk$eGPaL%Z>eN2gn_? zKH%;wElvy0z$V?myF(?qXJPL|-tOREA*n6q%M+~7sTI-JM;x-nDPXkF`(0dN=Y~f#Be?9lh*dXj!1ta;B^%b zN`Q6*G2&rviT8{&&T<$EbqB3ua3#>|UQ$1n!cVMOR9>b1U3-AWSZfL~MY{pTNpdMcS)viTqEV%2g)PDH2-d-w|cG;-{ z6Ssat%$?HSLeJY=m;lO77Y`$3)7-!act7&J|LY%oNf3iojS5EO(60c6lqr!e8Q`#) zX4y?TtEA|HMg7mZByY;OI37iue)wQ;)|UhcynW;BJ*grYFf;l2`JTF?&VGkxNjp#b zN|Zx3uyVHB-xQ5zl0ZkmtNe+*d2dd8_TK}PD4REnSa#0JL0d%E{^MU#pdr7Q_R1|~ z-EOwu9<-XfuA#A2da>~$mNi~!L?v1L+&^+&*fm>G@+M99d4?&m0StMxd3KsN-1#Td z5T5RR5y=TNy@48d=fWR_rTJ>FFlT6O<$V42v|V#v&8Mi?rh=X><*^F50++mt{&18Q zODGZ>qwRJe;(jU}?`P1!)nHtf9$a$qTHj0?l4E!o9Gd#df!wj5?Snxu!B^`)t0NGaLMa^A9RHH=DtRWa=+jA z87XhG5B;m_`Im#$ZFqL@w|ZzGCV^xvKPkTP5xuy3UV#k(XZ~RmX@`g694iAWG?N;8;PoCL@Jc+sAYDo ze7Jrlk^#4=t&UPPt4J>BckzOVQ^>%bQx3MuKh~c+3yPZ&e8vX>w4=ImIdM?!92CWl zv3`G>nhV3S61lQxbqb}>u2guXABzYL_R0Q6FNNI;al&zc^jtvBt zLEW7v%Nr$hq6a?72@Q5X=C!w_jjc0syf4-@x#@UI^49dmJ@>613AE9?CCF}rZNO^6 zh_vVCUPAyOo`RfQ@PrYQa$5F7iohJB4@`v3TaHF``<~p;-pkbD@>hvZxxO>G_DWbv z07Tgj8BY)<@~OBw23nY<*u9}1tif+hS011muQbi90DH>wMVWYggi`(f`JSA+=OA=u zP+$(#;}P-+rP`)C^OY{Y1NdM@~fqrG#+U*BbK_E&Z#Gif0-LspgcK`~C( z{I@@zDe!d!d9oxZ6(kmHBgjJE=pfSF-x|>B|aj=@9k4U&RH!L0q!)V*vR*^ z!%_O;bEIUq?+EixRK+|Qdc-8UV@hIORZRjJb=w`p#Jay;wpLMi z`cet&*e7|*QsWOh;0@sN+402Jq_ve=el@FXmsPKr8IMGpJap9wV>`vds9gl@5$uC% zzCUAmkxlMaSm-fRTbcLTZ>nd@q~c*j0$?YY_D{4%!EOVK9ULK6Ch5^Hghg!&CE^`H zV?arM5D7T#D*WCi>aGir&uZP^JFyNcOep<%UPm>?}S9#ccqAAmkx4J1Z zfi0c)?goR(EBvk=Rtuo29Ax`Duk1Ru5Pr^sNxh(!|9hi6axI)x2X@$xo?~lhpx0HG z%c)-FZM@wVj@Nm_p(t)mOp!IF9A<>``?6c z-N>T8ww0)gzB75PLr@#injezmj{7>hkV=H<3kOxXsrN{@X6zY zD^#21^U7GGyub8DHGt6gL1{Dp>~p6n^czRjQ;o)3e@#X_Oq<5-{Oa^F4Fy>AT0s?| zFy}G}Q46VdojB5iSJk=z3Q!z`hvM}g5=g%5?&-Lu+u%^0n&YBlvL60^qnirD!-+UJ za{_mwT#>GHD#608m^1P8oW}qmz$--afZgjvY8zcwDHu@f6~e^^zJxyxNJ&&9f}RVy zI3NCMriE0-mH2EZj8COz+D_N4m6XoQc$cSRdEA)P5G-b2;hgKM0MR(AI&J^BWKo1% zZ1Y|8kz=Qp%NuIR?`0bcT2;ah1nAJz8=bYlY4QGo*z+^BOPTBl1d#H4Cx#fo7JVTy z-x~(7Yv;%!9S!|wbWlEV?#6jk$;_S&CzBaq7Z;7V@rMmRIIo_=_q&Wn{i+~o8EQ>F)e!{5FVd|m4L-qANmu<@;~ zSjzqQukR>tw`(Gb1h7iU_jmydj-Yg#*x2-jaR09+Xo#4`CwI!FR@b(~hd>jWNoT$e z@2Np+(MuP4ttFb#XxxB0)VY>GrKE6i`<2>)H~byqHB9x_5<`pRT|UgM-5L|TLHxWR z;8dL#=w*L{Dw3TF*ZX8O@IlR|ryZ}LCzL5N%#&PA{Nr=?F%WsaGf zXl^TDPf1@`)QdHsJ6VAj53cODe4`Z!yn852)Ih7B+FPz~641}K-Iw?8rC*74lHxl4 zA=zO~`CNhyG6m+LyrNEGZ$I(NQ;;PBnWwwknHQrYTlQX1f9Xz`Gn)h3jnl(sLgFCd zL-3I%IUgp)ibK_@R+N0?LfZNEayNB=bf3mQ`ZfvwDeCSWU~({Dq0q0&!VO57;!t>J z><6AH3527TSXQk(CPfbW-$B2;xaaTg3|PYD?*|R`lPlC!0BcC-;Q-!av{Us%6OVUt zdBCeoIsN`gsiPmch0XQ(f$3kzKGc%p5N&;W)Gp)z^)2e7!V-&`i9T!`-F+1uj zI3?=t*`C$%lyQ)Bs$sD)wl6W2h-{i{T;3^hzQK&O@++D)}G24wGZ?W`;DM#jvSE6iX2$ zXyf{YKUMDbh$e@})^7jaUsk`(wQr~(P+7LyqE>>A4+rgrBSm|p!JjIG`uVu_cze?< zd&SIKV!OG06ME*Pr|KwqV^x<|@D0d1tx~hU_hX5tQ*9>ZSECpHxQ*m9J!Hr2Gq=k- zEQ-V$RG=!{VNLM@9;Itm@t@b3m@{i?C*93xCi>SndD?Ag?i=QG}D+q zfKRm_HyI3j|8r~irmJ`FzbO#U!D}+wSw*>lLB`uCYrK#2%y}(*NGwWY=mNRR%NpLb z1G&#++U~FE8k6tVEHmh6`Lx{5qD*;o#!2uA5dgD6GI*!(#LX5n%eR-c+K|6>mN5(V zWw4BPS8yke+PPI!N@L~%#o#1IMaUioDEo2Jfy|#ma8g2Pzzbn2%GBWQ_2xLg*!ivd z%Dd6lJ*1i8f7LZAF!LAezPKW|5-X1cC^DCo2|?UX)SS1wz{;>_;ssJloYEqS`2r%X zu+RkT)M`JQ(kXCYUDj5=+}??NW)MY-XJ=SHK(sNT%*5Yynfpo=*d;2}yy!{czjya2 z&*$&xx)Y|U{9(3q_-chMbN!@Ll(GFCZzfAPCh8xUY{Li1_W8xnsSO|yD((?YYwqJx z_X%L2mg$4ri=Z?qNphJu)CzfN#ARXhs7D- z82n!Ht$nAcgyK(zxfYCweIiiEvd-d|@9(WWGa)39VZQZHrD%%#O*PKs-|#ux0wrA2 zXMQy;g*PRU%kOY1?oV(6C8>=mv^mCb&C!6_D#QijN$Q?vR?dJp$+T9Sx4CbWjRbR{ zh;un!@zE9Xg3PP`D(r;Co-PiQ5$@?%?d*xXP488#Gv2ci;rQ?x;s6^DmR_^0_!a z^&tjfq2Y&hgEK(=7#)G}v8y^>^`S{`#ss-WR7bQ+*K-\)7vbV&^-d^;^@Y* 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 Fe*xTd7qkEX literal 0 HcmV?d00001 diff --git a/thunderstore/thunderstore.toml b/thunderstore/thunderstore.toml new file mode 100644 index 0000000..8e532f6 --- /dev/null +++ b/thunderstore/thunderstore.toml @@ -0,0 +1,27 @@ +[config] +schemaVersion = "0.0.1" + +[package] +namespace = "yournamespace" +name = "YourModName" +versionNumber = "0.1.0" +description = "your mod description" +websiteUrl = "link to the git repo" +containsNsfwContent = false + +[package.dependencies] +"BepInEx-BepInExPack" = "5.4.2100" +"ninesolsmodding-NineSolsAPI" = "0.0.2" + +[build] +icon = "./icon.png" +readme = "./README.md" +outdir = "./build" + +[[build.copy]] +source = "build/dll" +target = "." + +[publish] +repository = "https://thunderstore.io" +communities = [ "nine-sols" ]