diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..450d76f --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,44 @@ +name: Build + +on: + push: + branches: [master] + +jobs: + compute-version: + name: Compute Version + runs-on: ubuntu-latest + outputs: + version: ${{ steps.version.outputs.version }} + steps: + - uses: actions/checkout@master + with: + ref: ${{ github.head_ref }} + fetch-depth: 0 + + - id: version + uses: paulhatch/semantic-version@v5.3.0 + with: + tag_prefix: '' + major_pattern: 'Add project files' + minor_pattern: 'feature:' + bump_each_commit: true + enable_prerelease_mode: false + + build-nuget: + name: Build Nuget package + runs-on: ubuntu-latest + needs: [compute-version] + steps: + - uses: actions/checkout@master + + - uses: actions/setup-dotnet@v4 + + - run: dotnet restore ./ --locked-mode + name: Restore Project + + - run: dotnet pack -c Release -o ./pub ./ --no-restore -p:Version="${{ needs.compute-version.outputs.version }}" + name: Pack Project + + - name: Push Project + run: dotnet nuget push -s https://ng.zznty.ru/v3/index.json -k ${{ secrets.NUGET_API_KEY }} ./pub/*.nupkg diff --git a/.gitignore b/.gitignore index add57be..4460bfb 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ bin/ obj/ /packages/ riderModule.iml -/_ReSharper.Caches/ \ No newline at end of file +/_ReSharper.Caches/ +.vs/ \ No newline at end of file diff --git a/Plugin.ClientModLoader/ModInjector.cs b/Plugin.ClientModLoader/ModInjector.cs index ea742c1..5ac76ea 100644 --- a/Plugin.ClientModLoader/ModInjector.cs +++ b/Plugin.ClientModLoader/ModInjector.cs @@ -31,7 +31,7 @@ internal static class ModInjector { var index = __state.FindIndex(b => b.PublishedFileId == mod.PublishedFileId && b.PublishedServiceName == mod.PublishedServiceName); - + if (index != -1) { var stateMod = __state[index]; @@ -60,7 +60,7 @@ internal static class ModInjector ) .Instructions(); } - + [HarmonyPatch(typeof(MyDefinitionManager), nameof(MyDefinitionManager.LoadData))] [HarmonyPrefix] private static void LoadDefinitionsPrefix(ref List mods) => AppendToList(ref mods); diff --git a/Plugin.ClientModLoader/ModListComponent.cs b/Plugin.ClientModLoader/ModListComponent.cs index 25dc673..72bf66d 100644 --- a/Plugin.ClientModLoader/ModListComponent.cs +++ b/Plugin.ClientModLoader/ModListComponent.cs @@ -15,14 +15,14 @@ public class ModListComponent : IRenderComponent { private readonly string _configPath; private readonly JsonSerializerOptions _options = new(JsonSerializerDefaults.Web); - + private bool _visible; private string _searchQuery = string.Empty; private Task? _searchTask; private PublishedFileId_t[] _mods = []; private ImmutableDictionary _whitelist = ImmutableDictionary.Empty; - + private List _modList = []; private ModItem? _selected; public HashSet Installed { get; } @@ -57,18 +57,18 @@ public class ModListComponent : IRenderComponent var mods = new List(); var builder = ImmutableDictionary.CreateBuilder(); - + foreach (var item in response.Mods) { if (!ulong.TryParse(item.Id, out var id)) continue; - + mods.Add(new PublishedFileId_t(id)); builder.Add(id, item); } - + _mods = mods.ToArray(); _whitelist = builder.ToImmutable(); - await RefreshAsync(); + await RefreshAsync(); } public void OnFrame() @@ -80,7 +80,7 @@ public class ModListComponent : IRenderComponent try { InputText("##searchbox", ref _searchQuery, 256); - + SameLine(); if (Button("Search")) @@ -88,26 +88,27 @@ public class ModListComponent : IRenderComponent _searchTask = RefreshAsync(); return; } - + Spacing(); - + switch (_searchTask) { case { IsCompleted: false }: TextDisabled("Loading..."); return; case { IsCompletedSuccessfully: false }: - { - TextDisabled("Failed to load plugins list"); - if (_searchTask.Exception is null) return; - - foreach (var exception in _searchTask.Exception.InnerExceptions) { - TextWrapped($"{exception.GetType()}: {exception.Message}"); - } + TextDisabled("Failed to load plugins list"); + if (_searchTask.Exception is null) + return; - return; - } + foreach (var exception in _searchTask.Exception.InnerExceptions) + { + TextWrapped($"{exception.GetType()}: {exception.Message}"); + } + + return; + } } if (_modList.Count == 0) @@ -115,7 +116,7 @@ public class ModListComponent : IRenderComponent TextDisabled("Nothing found"); return; } - + BeginChild("List", new(400, 0), ImGuiChildFlags.Border | ImGuiChildFlags.ResizeX); { if (BeginTable("AvailableModsTable", 3, @@ -155,83 +156,83 @@ public class ModListComponent : IRenderComponent EndChild(); } - + SameLine(); - BeginGroup(); + BeginGroup(); - BeginChild("Mod View", new(0, -GetFrameHeightWithSpacing())); // Leave room for 1 line below us + BeginChild("Mod View", new(0, -GetFrameHeightWithSpacing())); // Leave room for 1 line below us - if (_selected is not null) - { - Text(_selected.Name); - Separator(); - if (BeginTabBar("##ModViewTabs")) + if (_selected is not null) { - if (!string.IsNullOrEmpty(_selected.Description) && BeginTabItem("Description")) + Text(_selected.Name); + Separator(); + if (BeginTabBar("##ModViewTabs")) { - TextWrapped(_selected.Description); - EndTabItem(); + if (!string.IsNullOrEmpty(_selected.Description) && BeginTabItem("Description")) + { + TextWrapped(_selected.Description); + EndTabItem(); + } + + if (BeginTabItem("Mod Description")) + { + TextWrapped(string.IsNullOrEmpty(_selected.ModDescription) ? "Nothing." : _selected.ModDescription); + EndTabItem(); + } + + if (BeginTabItem("Details")) + { + TextLinkOpenURL("Mod URL", _selected.Url); + + Text("Author:"); + SameLine(); + TextWrapped(_selected.Author); + + Text("Created:"); + SameLine(); + TextWrapped(DateTimeOffset.FromUnixTimeSeconds(_selected.Created).ToString("g")); + + Text("Updated:"); + SameLine(); + TextWrapped(DateTimeOffset.FromUnixTimeSeconds(_selected.Updated).ToString("g")); + + EndTabItem(); + } + + EndTabBar(); } - - if (BeginTabItem("Mod Description")) - { - TextWrapped(string.IsNullOrEmpty(_selected.ModDescription) ? "Nothing." : _selected.ModDescription); - EndTabItem(); - } - - if (BeginTabItem("Details")) - { - TextLinkOpenURL("Mod URL", _selected.Url); - - Text("Author:"); - SameLine(); - TextWrapped(_selected.Author); - - Text("Created:"); - SameLine(); - TextWrapped(DateTimeOffset.FromUnixTimeSeconds(_selected.Created).ToString("g")); - - Text("Updated:"); - SameLine(); - TextWrapped(DateTimeOffset.FromUnixTimeSeconds(_selected.Updated).ToString("g")); - - EndTabItem(); - } - - EndTabBar(); } - } - EndChild(); + EndChild(); - if (_selected is not null) - { - var installed = Installed.Contains(_selected.Id); - if (Button(installed ? "Uninstall" : "Install")) + if (_selected is not null) { - if (installed) - Installed.Remove(_selected.Id); - else - Installed.Add(_selected.Id); + var installed = Installed.Contains(_selected.Id); + if (Button(installed ? "Uninstall" : "Install")) + { + if (installed) + Installed.Remove(_selected.Id); + else + Installed.Add(_selected.Id); - Save(); + Save(); + } } - } - EndGroup(); + EndGroup(); } finally { - End(); + End(); } } - + private void Save() { using var stream = File.Create(_configPath); - + JsonSerializer.Serialize(stream, Installed, _options); } @@ -241,14 +242,14 @@ public class ModListComponent : IRenderComponent if (handle.m_UGCQueryHandle == ulong.MaxValue) throw new Exception("Failed to create UGC request"); - + try { SteamUGC.SetSearchText(handle, _searchQuery); SteamUGC.SetReturnLongDescription(handle, true); // TODO font support for other languages // SteamUGC.SetLanguage(handle, MapLanguage(MySandboxGame.Config.Language)); - + var call = SteamUGC.SendQueryUGCRequest(handle); var result = await CallResultAsync.Create(call); @@ -261,9 +262,9 @@ public class ModListComponent : IRenderComponent break; if (details.m_eResult != EResult.k_EResultOK) continue; - + var title = details.m_rgchTitle; - + if (!string.IsNullOrEmpty(_searchQuery) && !title.Contains(_searchQuery, StringComparison.OrdinalIgnoreCase)) continue; @@ -278,7 +279,7 @@ public class ModListComponent : IRenderComponent description, $"https://steamcommunity.com/sharedfiles/filedetails/?id={details.m_nPublishedFileId.m_PublishedFileId}", details.m_rtimeCreated, details.m_rtimeUpdated, item.Author)); } - + _modList = list; } finally diff --git a/Plugin.ClientModLoader/Utils/CallResultAsync.cs b/Plugin.ClientModLoader/Utils/CallResultAsync.cs index a9e20bd..0ab6f14 100644 --- a/Plugin.ClientModLoader/Utils/CallResultAsync.cs +++ b/Plugin.ClientModLoader/Utils/CallResultAsync.cs @@ -22,7 +22,7 @@ public static class CallResultAsync where T : struct return await tcs.Task; } - + [StructLayout(LayoutKind.Sequential, Pack = 8)] private struct GenericCallResult {