diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..a96db8c --- /dev/null +++ b/.editorconfig @@ -0,0 +1,45 @@ +# The source skeleton for this configuration can be found at +# https://github.com/BesLogic/shared-configs/blob/main/.editorconfig +# Modifications to this file that are not project-specific should also be done upstream. + +# Editor configuration, see https://editorconfig.org +root = true + +[*] +#### Widely Supported by Editors #### +#### https://github.com/editorconfig/editorconfig/wiki/EditorConfig-Properties#widely-supported-by-editors + +indent_style = space +indent_size = 2 +# tab_width defaults indent_size when indent_size is a number, but VS will add it back +tab_width = 2 +# TODO: Change back in a formatting pass +end_of_line = crlf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +#### Supported By A Limited Number of Editors #### +#### https://github.com/editorconfig/editorconfig/wiki/EditorConfig-Properties#supported-by-a-limited-number-of-editors + +max_line_length = 100 + +#### Ideas for Domain-Specific Properties #### +#### https://github.com/editorconfig/editorconfig/wiki/EditorConfig-Properties#ideas-for-domain-specific-properties + +quote_type = auto + +#### EditorGuidelines #### +#### https://marketplace.visualstudio.com/items?itemName=PaulHarrington.EditorGuidelinesPreview#editorconfig-support-vs-2017-and-above +guidelines = 80, 100 + +#### Language-specific overrides #### + +[*.cs] +indent_size = 4 +# tab_width defaults indent_size when indent_size is a number, but VS will add it back +tab_width = 4 + +[*.{md,patch,diff}] +max_line_length = off +trim_trailing_whitespace = false diff --git a/.gitattributes b/.gitattributes index 412eeda..dfe0770 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,22 +1,2 @@ # Auto detect text files and perform LF normalization * text=auto - -# Custom for Visual Studio -*.cs diff=csharp -*.sln merge=union -*.csproj merge=union -*.vbproj merge=union -*.fsproj merge=union -*.dbproj merge=union - -# Standard to msysgit -*.doc diff=astextplain -*.DOC diff=astextplain -*.docx diff=astextplain -*.DOCX diff=astextplain -*.dot diff=astextplain -*.DOT diff=astextplain -*.pdf diff=astextplain -*.PDF diff=astextplain -*.rtf diff=astextplain -*.RTF diff=astextplain diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..7d571e4 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,43 @@ +name: CI + +# PR / branch validation only. Publishing (and its validation) lives in release.yml. +on: + push: + branches: + - main + pull_request: + +permissions: + contents: read + +concurrency: + # Cancel previous runs for the same PR + # Don't cancel successive pushes to main + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + build: + # Pinned (not windows-latest) so a runner image bump can't silently drop the + # .NET Framework 4.8.1 targeting pack this build needs. + runs-on: windows-2022 + + steps: + - uses: actions/checkout@v7 + + - uses: actions/setup-dotnet@v5 + with: + dotnet-version: "10.0.x" + + # Debug + implicit restore. -o collects the output in a known, flat path for the upload step. + - run: dotnet build --configuration Debug -o artifacts + + - run: dotnet format --verify-no-changes + + - uses: actions/upload-artifact@v4 + with: + name: LiveSplit.AutoSplitIntegration + path: | + artifacts/LiveSplit.AutoSplitIntegration.dll + artifacts/LiveSplit.AutoSplitIntegration.pdb + if-no-files-found: error diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..02de93c --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,127 @@ +name: Release + +# The `validate` job runs on every PR/push/dispatch (so a manifest that would break the updater +# is caught before merge). The `release` job depends on it and only publishes on a push to main +# that changes the manifest, or a manual workflow_dispatch. The tag is created as part of +# publishing, so a failed run leaves nothing to clean up (just re-run via "Run workflow"). +on: + push: + branches: + - main + paths: + - update.LiveSplit.AutoSplitIntegration.xml + pull_request: + branches: + - main + paths: + - update.LiveSplit.AutoSplitIntegration.xml + workflow_dispatch: + inputs: + version: + description: "Version (X.Y.Z) to (re)publish. Leave blank for release entry in the manifest" + required: false + default: "" + +permissions: + contents: read + +concurrency: + # Cancel previous runs for the same PR + # Don't cancel successive pushes to main + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + validate: + # Only bash + pwsh needed, so the cheaper Linux runner (with real coreutils) is fine. + runs-on: ubuntu-latest + outputs: + version: ${{ steps.ver.outputs.version }} + steps: + - uses: actions/checkout@v7 + + # Target version = the workflow_dispatch input if given, else the highest non-0.0.0 + # in the manifest (0.0.0 is the unreleased staging block). + - name: Determine target version + id: ver + shell: bash + run: | + xml=update.LiveSplit.AutoSplitIntegration.xml + version="${{ github.event.inputs.version }}" + version="${version#v}" # tolerate a stray leading v; the manifest/build use bare X.Y.Z + if [ -z "$version" ]; then + version=$(grep -oE '> "$GITHUB_OUTPUT" + echo "Target release version: ${version:-}" + + # Fails on any manifest shape that would break the updater's parse, and (with a target + # version) that its release entry is complete. Also fails a manifest with no releasable + # entry, so an empty version can never reach the release job. + - name: Validate manifest + shell: pwsh + run: ./scripts/validate-manifest.ps1 -ReleaseVersion "${{ steps.ver.outputs.version }}" + + release: + needs: validate + # PRs validate only; publishing happens on push-to-main and manual dispatch. + if: github.event_name != 'pull_request' + # Pinned windows runner for the .NET Framework 4.8.1 targeting pack (see ci.yml). + runs-on: windows-2022 + permissions: + contents: write + env: + VERSION: ${{ needs.validate.outputs.version }} + steps: + - uses: actions/checkout@v7 + + # On a push, skip if the release already exists (unrelated manifest edits, e.g. adding to + # the 0.0.0 block, must not republish). workflow_dispatch skips this check and always + # (re)publishes, so a failed release can be retried. + - name: Check existing release + id: exists + if: github.event_name == 'push' + shell: bash + env: + GH_TOKEN: ${{ github.token }} + run: | + if gh release view "v$VERSION" >/dev/null 2>&1; then + echo "already=true" >> "$GITHUB_OUTPUT" + echo "Release v$VERSION already exists; nothing to publish." + else + echo "already=false" >> "$GITHUB_OUTPUT" + fi + + - uses: actions/setup-dotnet@v5 + if: steps.exists.outputs.already != 'true' + with: + dotnet-version: "10.0.x" + + # Release build with implicit restore. + - run: dotnet build --configuration Release -o artifacts -p:Version=$env:VERSION + if: steps.exists.outputs.already != 'true' + + - name: Release notes from manifest + if: steps.exists.outputs.already != 'true' + shell: pwsh + run: | + [xml]$doc = Get-Content -Raw -LiteralPath 'update.LiveSplit.AutoSplitIntegration.xml' + $u = $doc.SelectSingleNode("/updates/update[@version='$env:VERSION']") + $lines = @($u.SelectNodes('changelog/change') | ForEach-Object { '- ' + $_.InnerText.Trim() }) + Set-Content -Path release-notes.md -Value $lines -Encoding utf8 + Get-Content release-notes.md + + # Creates the tag v at this commit and the release together, so nothing is left + # dangling on failure. make_latest (default) promotes it to the "latest" release. + - uses: softprops/action-gh-release@v3 + if: steps.exists.outputs.already != 'true' + with: + tag_name: v${{ needs.validate.outputs.version }} + target_commitish: ${{ github.sha }} + name: v${{ needs.validate.outputs.version }} + body_path: release-notes.md + files: | + artifacts/LiveSplit.AutoSplitIntegration.dll + artifacts/LiveSplit.AutoSplitIntegration.pdb + fail_on_unmatched_files: true diff --git a/.gitignore b/.gitignore index c5bc0c2..7ef383e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,248 +1,15 @@ -## Ignore Visual Studio temporary files, build results, and -## files generated by popular Visual Studio add-ons. - -# User-specific files -*.suo -*.user -*.sln.docstates -*.userprefs - # Build results -[Dd]ebug/ -[Dd]ebugPublic/ -[Rr]elease/ -[Rr]eleases/ -# x64/ -# x86/ -build/ -bld/ [Bb]in/ [Oo]bj/ -Builds/ - -#SVN Stuff -.svn/ - -#API -API/ - -#Website -Website/ - -# Roslyn cache directories -*.ide/ - -# MSTest test Results -[Tt]est[Rr]esult*/ -[Bb]uild[Ll]og.* - -#NUNIT -*.VisualState.xml -TestResult.xml - -# Build Results of an ATL Project -[Dd]ebugPS/ -[Rr]eleasePS/ -dlldata.c - -*_i.c -*_p.c -*_i.h -*.ilk -*.meta -*.obj -*.pch -*.pdb -*.pgc -*.pgd -*.rsp -*.sbr -*.tlb -*.tli -*.tlh -*.tmp -*.tmp_proj -*.log -*.vspscc -*.vssscc -.builds -*.pidb -*.svclog -*.scc - -# Chutzpah Test files -_Chutzpah* - -# Visual C++ cache files -ipch/ -*.aps -*.ncb -*.opensdf -*.sdf -*.cachefile - -# Visual Studio profiler -*.psess -*.vsp -*.vspx - -# TFS 2012 Local Workspace -$tf/ - -# Guidance Automation Toolkit -*.gpState - -# ReSharper is a .NET coding add-in -_ReSharper*/ -*.[Rr]e[Ss]harper -*.DotSettings.user - -# JustCode is a .NET coding addin-in -.JustCode - -# TeamCity is a build add-in -_TeamCity* - -# DotCover is a Code Coverage Tool -*.dotCover - -# NCrunch -_NCrunch_* -.*crunch*.local.xml - -# MightyMoose -*.mm.* -AutoTest.Net/ - -# Web workbench (sass) -.sass-cache/ - -# Installshield output folder -[Ee]xpress/ -# DocProject is a documentation generator add-in -DocProject/buildhelp/ -DocProject/Help/*.HxT -DocProject/Help/*.HxC -DocProject/Help/*.hhc -DocProject/Help/*.hhk -DocProject/Help/*.hhp -DocProject/Help/Html2 -DocProject/Help/html +# CI build output (dotnet build -o artifacts) +artifacts/ -# Click-Once directory -publish/ - -# Publish Web Output -*.[Pp]ublish.xml -*.azurePubxml -# TODO: Comment the next line if you want to checkin your web deploy settings -# but database connection strings (with potential passwords) will be unencrypted -*.pubxml -*.publishproj - -# NuGet Packages -*.nupkg -# The packages folder can be ignored because of Package Restore -**/packages/* -# except build/, which is used as an MSBuild target. -!**/packages/build/ -# If using the old MSBuild-Integrated Package Restore, uncomment this: -#!**/packages/repositories.config - -# Windows Azure Build Output -csx/ -*.build.csdef - -# Windows Store app package directory -AppPackages/ - -# Others -sql/ -*.Cache -ClientBin/ -[Ss]tyle[Cc]op.* -~$* -*~ -*.dbmdl -*.dbproj.schemaview -*.pfx -*.publishsettings -node_modules/ - -# RIA/Silverlight projects -Generated_Code/ - -# Backup & report files from converting an old project file -# to a newer Visual Studio version. Backup files are not needed, -# because we have git ;-) -_UpgradeReport_Files/ -Backup*/ -UpgradeLog*.XML -UpgradeLog*.htm - -# SQL Server files -*.mdf -*.ldf - -# Business Intelligence projects -*.rdl.data -*.bim.layout -*.bim_*.settings - -# Microsoft Fakes -FakesAssemblies/ - -# ========================= -# Operating System Files -# ========================= - -# OSX -# ========================= +# Visual Studio +.vs/ +*.user +*.suo +# OS .DS_Store -.AppleDouble -.LSOverride - -# Icon must end with two \r -Icon - - -# Thumbnails -._* - -# Files that might appear on external disk -.Spotlight-V100 -.Trashes - -# Directories potentially created on remote AFP share -.AppleDB -.AppleDesktop -Network Trash Folder -Temporary Items -.apdisk - -# Windows -# ========================= - -# Windows image file caches Thumbs.db -ehthumbs.db - -# Folder config file -Desktop.ini - -# Recycle Bin used on file shares -$RECYCLE.BIN/ - -# Windows Installer files -*.cab -*.msi -*.msm -*.msp -*.dropbox -.dropbox.attr -LiveSplit/LiveSplit.Core/Updates/GitInfo/branch.txt -LiveSplit/LiveSplit.Core/Updates/GitInfo/version.txt -LiveSplit/LiveSplit.Core/Updates/GitInfo/revision.txt -.vs diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..1038ab5 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: MIT +// Copyright 2026 Beslogic Inc. +// +// The source skeleton for this configuration can be found at +// https://github.com/BesLogic/shared-configs/blob/main/.vscode/extensions.json +// Modifications to this file that are not project-specific should also be done upstream. +{ + // See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations. + // List of extensions which should be recommended for users of this workspace. + // Only keep those used by your specific project + "recommendations": [ + // General + "eamodio.gitlens", + "editorconfig.editorconfig", + "pkief.material-icon-theme", + // GitHub + "bierner.github-markdown-preview", + "github.vscode-github-actions", + // C# + "ms-dotnettools.csharp", + // "ms-dotnettools.csdevkit", + // Markdown + "bierner.github-markdown-preview", + "davidanson.vscode-markdownlint", + // XML + "redhat.vscode-xml", + // YAML + "redhat.vscode-yaml", + // + // Add your project's framework-specific and project-specific extensions under here + ], +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..e162952 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,115 @@ +// SPDX-License-Identifier: MIT +// Copyright 2026 Beslogic Inc. +// +// The source skeleton for this configuration can be found at +// https://github.com/BesLogic/shared-configs/blob/main/.vscode/settings.json +// Modifications to this file that are not project-specific should also be done upstream. +{ + /* + * General + */ + "files.associations": { + "*.json": "jsonc", + }, + "editor.rulers": [ + 80, + 100 + ], + "editor.detectIndentation": false, + "editor.tabSize": 2, + "editor.insertSpaces": true, + "editor.comments.insertSpace": true, + "files.eol": "\n", + "files.insertFinalNewline": true, + "files.trimFinalNewlines": true, + "files.trimTrailingWhitespace": true, + "editor.bracketPairColorization.enabled": true, + "editor.formatOnSave": true, + "editor.formatOnSaveMode": "file", + "editor.codeActionsOnSave": { + "source.fixAll": "explicit", + // Clearing unreachable code when doing a quick temporary change is annoying + "source.fixAll.ts": "never", + // "source.*Imports": https://github.com/microsoft/TypeScript/pull/50931#issuecomment-1416288712 + // Let dedicated imports tool deal with it + "source.organizeImports": "never", + "source.sortImports": "never", + // IDEM, but also it's annoying to remove imports because of commented code while testing + "source.removeUnusedImports": "never", + }, + /* + * Git + */ + "[git-commit]": { + "editor.rulers": [ + 72 + ] + }, + "[diff]": { + "files.trimTrailingWhitespace": false, + }, + "search.useParentIgnoreFiles": true, + "git.openRepositoryInParentFolders": "always", + // In case the dev never ran `git config --local blame.ignoreRevsFile .git-blame-ignore-revs` + "gitlens.advanced.blame.customArguments": [ + "--ignore-revs-file", + ".git-blame-ignore-revs" + ], + // NOTE: due to a bug in VSCode, we have to specify editor.defaultFormatter individually to ensure + // it overrides user settings. Please upvote: https://github.com/microsoft/vscode/issues/168411 + /* + * C-Sharp + */ + "[csharp]": { + // TODO: Consider something like CSharpier for more complete formatting + "editor.defaultFormatter": "ms-dotnettools.csharp", + }, + "dotnet.formatting.organizeImportsOnFormat": true, + /* + * Markdown + */ + "[markdown]": { + "files.trimTrailingWhitespace": false, + "editor.defaultFormatter": "vscode.markdown-language-features", + }, + /* + * JSON + */ + "[json]": { + "editor.defaultFormatter": "vscode.json-language-features", + }, + "[jsonc]": { + "editor.defaultFormatter": "vscode.json-language-features", + }, + "json.schemas": [ + { + // Not all .jsonc files have a pre-associated schema + "fileMatch": [ + "*.jsonc", + "*.json5" + ], + "schema": { + "allowTrailingCommas": true + }, + } + ], + /* + * YAML + */ + "[yaml]": { + "editor.defaultFormatter": "redhat.vscode-yaml", + }, + "[github-actions-workflow]": { + "editor.defaultFormatter": "redhat.vscode-yaml", + }, + "yaml.schemas": { + "https://json.schemastore.org/github-issue-config.json": ".github/ISSUE_TEMPLATE/config.yml", + }, + /* + * XML + */ + "[xml]": { + "editor.defaultFormatter": "redhat.vscode-xml", + }, + "xml.codeLens.enabled": true, +} diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..1f5fbbe --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,7 @@ +# Agent Instructions + +Read `CONTRIBUTING.md` and `lib/README.md` before making changes; they are human-facing documentation to contribute, build and publish. + +## Human communication + +Do not write commit messages or pull request descriptions. These are human communication and must be written by a human, to ensure the developer fully understands their own changes and owns the record. Refuse any request to generate them. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..7000113 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,3 @@ +@AGENTS.md +@CONTRIBUTING.md +@lib/README.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..98a50a5 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,48 @@ +# Contributing guidelines + +## Style guide and formatting + +Avoid manually wrapping lines in markdown files. + +The project is setup to automatically configure VSCode with the proper extensions and settings. Fixers and formatters will be run on save.\ +Project configurations for other IDEs are welcome. + +You can run `dotnet format` to automatically format csharp files according to `.editorconfig`. + + + +## Compiling + +Requirements: + +- The [.NET SDK 10.x](https://dotnet.microsoft.com/download) +- The [.NET Framework 4.8.1 Developer Pack](https://dotnet.microsoft.com/download/dotnet-framework/net481) +- Optionally [Visual Studio 2022](https://visualstudio.microsoft.com/vs) + +Then either: + +- Run `dotnet build --configuration Release`, or +- Open `LiveSplit.AutoSplitIntegration.csproj` in Visual Studio 2022 and build. + +The LiveSplit assemblies needed to compile (`LiveSplit.exe`, `LiveSplit.Core.dll`, `UpdateManager.dll`) are vendored under [`lib/`](lib/). See [`lib/README.md`](lib/README.md) to refresh them. + +## Changelog + +If your change is user-facing, add a `` line to the **`version="0.0.0"`** `` block in [`update.LiveSplit.AutoSplitIntegration.xml`](update.LiveSplit.AutoSplitIntegration.xml), in the same PR. Entries there reach users only once promoted into a real version at release. + +Do not modify `version="0.0.0"` or the `` in [`LiveSplit.AutoSplitIntegration.csproj`](LiveSplit.AutoSplitIntegration.csproj) (fallback for local builds). The real release version comes from the **manifest**: the newest non-`0.0.0` `` is what gets released automatically by [.github/release.yml](.github/release.yml). + +## Releasing a new version + +We use LiveSplit's built-in component auto-updater: LiveSplit polls the factory's `XMLURL`, and offers an update when a listed `` is newer than the installed component's `Version`. + +To publish a release, edit [`update.LiveSplit.AutoSplitIntegration.xml`](update.LiveSplit.AutoSplitIntegration.xml): + +1. Rename the `version="0.0.0"` block to `version="X.Y.Z"` (its staged ``s become this release's changelog) +1. Move the last release's `` to it and update the version there. Move the previous release back to an empty ``. (only the newest release lists files; see the note in that XML) +1. Add a fresh empty `version="0.0.0"` block on top for the next cycle +1. Commit and merge to `main` + +The **Release** workflow then validates the manifest, builds with the manifest's version, and publishes a `vX.Y.Z` GitHub release+tag with the `.dll` + `.pdb` attached. + +If a release fails partway, just re-run it from [`Actions > Release`](https://github.com/Toufool/LiveSplit.AutoSplitIntegration/actions/workflows/build.yml)`> Run workflow` after fixing the issue. The tag is only created on a successful publish, so there is nothing to delete or clean up first. diff --git a/LiveSplit.AutoSplitIntegration.csproj b/LiveSplit.AutoSplitIntegration.csproj index 73cd121..04bd226 100644 --- a/LiveSplit.AutoSplitIntegration.csproj +++ b/LiveSplit.AutoSplitIntegration.csproj @@ -1,105 +1,77 @@ - - - + + - Debug - AnyCPU - {8DEB033B-6D0F-4301-9CB4-ABDC3DEFD397} + latest + enable + + + true + + + true + + + true + moderate + + $(WarningsAsErrors);NU1903;NU1904 + + all + + + + + net481 + true Library LiveSplit LiveSplit.AutoSplitIntegration - v4.8.1 - 512 - false true - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true - - - AnyCPU + + + false + + true + full - false - update\Components\ - DEBUG;TRACE - prompt - 4 - - - - - AnyCPU - pdbonly - true - ..\..\bin\Release\Components\ - TRACE - prompt - 4 + + + LiveSplit.AutoSplitIntegration + Directly connects AutoSplit with LiveSplit. + Toufool + Copyright © 2026 + + 0.0.0-dev - - - - - - - - UserControl - - - AutoSplitIntegrationComponentSettings.cs - - - - - - + + + - ..\..\..\Documents\LiveSplit\LiveSplit.exe + lib\LiveSplit.exe + false - ..\..\..\Documents\LiveSplit\LiveSplit.Core.dll + lib\LiveSplit.Core.dll + false - - - - - ..\..\..\Documents\LiveSplit\UpdateManager.dll + lib\UpdateManager.dll + false + + - - - False - Microsoft .NET Framework 4.6.1 %28x86 and x64%29 - true - - - False - .NET Framework 3.5 SP1 - false - - - - - AutoSplitIntegrationComponentSettings.cs - - - - - - - \ No newline at end of file + diff --git a/LiveSplit.AutoSplitIntegration.sln b/LiveSplit.AutoSplitIntegration.sln deleted file mode 100644 index fddc302..0000000 --- a/LiveSplit.AutoSplitIntegration.sln +++ /dev/null @@ -1,25 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.30011.22 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LiveSplit.AutoSplitIntegration", "LiveSplit.AutoSplitIntegration.csproj", "{8DEB033B-6D0F-4301-9CB4-ABDC3DEFD397}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {8DEB033B-6D0F-4301-9CB4-ABDC3DEFD397}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8DEB033B-6D0F-4301-9CB4-ABDC3DEFD397}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8DEB033B-6D0F-4301-9CB4-ABDC3DEFD397}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8DEB033B-6D0F-4301-9CB4-ABDC3DEFD397}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {CBC1EDDD-B566-4239-95C4-F15AFA594D0A} - EndGlobalSection -EndGlobal diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs deleted file mode 100644 index 7bf8d4f..0000000 --- a/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System.Reflection; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly -[assembly: AssemblyTitle("LiveSplit.AutoSplitIntegration")] -[assembly: AssemblyDescription("Directly connects AutoSplit with LiveSplit.")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("LiveSplit.AutoSplitIntegration")] -[assembly: AssemblyCopyright("Copyright © 2020")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("a007166e-78ab-468a-bc1f-64f88bb9407f")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/README.md b/README.md index b965bde..ef2ca9f 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,12 @@ -# AutoSplit Integration +# AutoSplit Integration [![CI](/../../actions/workflows/ci.yml/badge.svg)](/../../actions/workflows/build.yml) [![SemVer](https://badgen.net/badge/_/SemVer%20compliant/grey?label)](https://semver.org/) Directly connects [AutoSplit](https://github.com/Toufool/Auto-Split) with [LiveSplit](https://github.com/LiveSplit/LiveSplit). ## Installation - Close AutoSplit if it’s currently open -- Download [the `.dll` file](/update/Components/LiveSplit.AutoSplitIntegration.dll?raw=true) and place it into your `[...]\LiveSplit\Components` folder. +- Download [the `.dll` file](../../releases/latest/download/LiveSplit.AutoSplitIntegration.dll) and place it into your `[...]\LiveSplit\Components` folder. + - Optionally also download the matching [`.pdb` file](../../releases/latest/download/LiveSplit.AutoSplitIntegration.pdb) into the same folder. It adds source line numbers to crash reports, which helps when reporting bugs. - Open LiveSplit -> Right Click -> Edit Layout -> Plus Button -> Control -> AutoSplit Integration. - Click Layout Settings -> AutoSplit Integration - Click the Browse buttons to locate your AutoSplit Path (path to `AutoSplit.exe`) and Profile Path (path to your AutoSplit `.toml` profile file) respectively. @@ -18,10 +19,9 @@ Directly connects [AutoSplit](https://github.com/Toufool/Auto-Split) with [LiveS - If you want to close AutoSplit, just close its window. Alternatively, if AutoSplit is for some reason not responding, you can kill it in the same menu where you can reopen it. This way your settings won’t be saved though. - You can also find the options to reopen/kill AutoSplit in the component’s settings. -## Compiling +## Contributing -- Clone/download LiveSplit and this repository -- Open it in [Visual Studio 2019](https://visualstudio.microsoft.com/vs) +Building from source and contributing guidelines are documented in [`CONTRIBUTING.md`](CONTRIBUTING.md). ## Resources diff --git a/UI/Components/AutoSplitIntegrationComponent.cs b/UI/Components/AutoSplitIntegrationComponent.cs index 9d836a7..ea2b959 100644 --- a/UI/Components/AutoSplitIntegrationComponent.cs +++ b/UI/Components/AutoSplitIntegrationComponent.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Drawing; using System.IO; @@ -157,4 +157,4 @@ private void State_OnReset(object sender, TimerPhase e) private void State_OnUndoSplit(object sender, EventArgs e) => AutoSplit.Send("undo"); } -} \ No newline at end of file +} diff --git a/UI/Components/AutoSplitIntegrationComponentSettings.cs b/UI/Components/AutoSplitIntegrationComponentSettings.cs index 57ceb3f..3d03174 100644 --- a/UI/Components/AutoSplitIntegrationComponentSettings.cs +++ b/UI/Components/AutoSplitIntegrationComponentSettings.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.IO; using System.Reflection; using System.Windows.Forms; @@ -145,4 +145,4 @@ private void ButtonSettingsPathBrowse_Click(object sender, EventArgs e) private void TextBoxSettingsPath_TextChanged(object sender, EventArgs e) => component.SettingsPath = textBoxSettingsPath.Text; } -} \ No newline at end of file +} diff --git a/UI/Components/AutoSplitIntegrationFactory.cs b/UI/Components/AutoSplitIntegrationFactory.cs index ffe1849..a65343f 100644 --- a/UI/Components/AutoSplitIntegrationFactory.cs +++ b/UI/Components/AutoSplitIntegrationFactory.cs @@ -1,4 +1,4 @@ -using System; +using System; using LiveSplit.Model; using LiveSplit.UI.Components; @@ -14,13 +14,13 @@ public class AutoSplitIntegrationFactory : IComponentFactory public ComponentCategory Category => ComponentCategory.Control; - public Version Version => Version.Parse("1.8.2"); + public Version Version => GetType().Assembly.GetName().Version; public string UpdateName => ComponentName; - public string UpdateURL => "https://raw.githubusercontent.com/Toufool/LiveSplit.AutoSplitIntegration/main/update/Components/"; + public string UpdateURL => "https://github.com/Toufool/LiveSplit.AutoSplitIntegration/releases/"; - public string XMLURL => "https://raw.githubusercontent.com/Toufool/LiveSplit.AutoSplitIntegration/main/update/Components/update.LiveSplit.AutoSplitIntegration.xml"; + public string XMLURL => "https://raw.githubusercontent.com/Toufool/LiveSplit.AutoSplitIntegration/main/update.LiveSplit.AutoSplitIntegration.xml"; public IComponent Create(LiveSplitState state) => new AutoSplitIntegrationComponent(state); } diff --git a/UI/Components/AutoSplitProcess.cs b/UI/Components/AutoSplitProcess.cs index 88c6f5e..8f98c55 100644 --- a/UI/Components/AutoSplitProcess.cs +++ b/UI/Components/AutoSplitProcess.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Diagnostics; using System.IO; using LiveSplit.Model; diff --git a/lib/LiveSplit.Core.dll b/lib/LiveSplit.Core.dll new file mode 100644 index 0000000..f31ab4b Binary files /dev/null and b/lib/LiveSplit.Core.dll differ diff --git a/lib/LiveSplit.exe b/lib/LiveSplit.exe new file mode 100644 index 0000000..562c851 Binary files /dev/null and b/lib/LiveSplit.exe differ diff --git a/lib/README.md b/lib/README.md new file mode 100644 index 0000000..37e6bad --- /dev/null +++ b/lib/README.md @@ -0,0 +1,23 @@ +# Vendored LiveSplit reference assemblies + +These are **third-party build-time reference assemblies from LiveSplit**, required to +compile this plugin. They are **not** redistributed with the plugin: at runtime the +LiveSplit host process provides them, so the project references them with +`false` (they are not copied into the build output). + +| File | Purpose | +| -------------------- | --------------------------------------------------- | +| `LiveSplit.exe` | Host app assembly (`LiveSplit.UI.Components`, etc.) | +| `LiveSplit.Core.dll` | Core model/timer types (`LiveSplitState`, etc.) | +| `UpdateManager.dll` | Component auto-update interfaces | + +## Pinned version + +Currently pinned to **LiveSplit 1.8.37**. + +## How to refresh + +1. Download the latest release zip from (e.g. `LiveSplit_x.y.z.zip`). +2. Extract it and copy `LiveSplit.exe`, `LiveSplit.Core.dll`, and `UpdateManager.dll` from the archive root into this `lib/` folder, overwriting the existing files. +3. Update the **Pinned version** above. +4. Rebuild and commit. diff --git a/lib/UpdateManager.dll b/lib/UpdateManager.dll new file mode 100644 index 0000000..9869026 Binary files /dev/null and b/lib/UpdateManager.dll differ diff --git a/scripts/validate-manifest.ps1 b/scripts/validate-manifest.ps1 new file mode 100644 index 0000000..4791a28 --- /dev/null +++ b/scripts/validate-manifest.ps1 @@ -0,0 +1,93 @@ +#!/usr/bin/env pwsh +<# +.SYNOPSIS + Validate the auto-update manifest the way LiveSplit's UpdateManager parses it. + +.DESCRIPTION + UpdateManager parses the manifest with no null checks inside a silent catch-all, so any + malformed node aborts parsing and offers zero updates with no error. This script fails loudly + (GitHub `::error::` annotations) on any shape that would break that parse. + + With -ReleaseVersion, also asserts that version's entry is release-ready: it exists, has a + download/v/ asset path, and a non-empty changelog. +#> +param( + [string]$Path = 'update.LiveSplit.AutoSplitIntegration.xml', + [string]$ReleaseVersion = '' +) +$ErrorActionPreference = 'Stop' +$errs = @() +$versions = @() + +[xml]$doc = Get-Content -Raw -LiteralPath $Path +$root = $doc.DocumentElement +if ($root.Name -ne 'updates') { $errs += "root is <$($root.Name)>, expected " } + +foreach ($node in $root.ChildNodes) { + if ($node.NodeType -ne [System.Xml.XmlNodeType]::Element -or $node.Name -ne 'update') { + $errs += "non- node inside ($($node.NodeType) '$($node.Name)'). The updater aborts on it. Keep comments above the root" + continue + } + $v = $node.GetAttribute('version') + if ([string]::IsNullOrEmpty($v)) { + $errs += ' without a version attribute' + $v = '?' + } + $versions += $v + + # The updater iterates ALL children of (FileChange.Parse each) and of + # (InnerText each). A comment in NREs and aborts parsing. A comment in + # leaks its text in as a visible change line. So every child must be the expected element. + $files = $node.SelectSingleNode('files') + if ($null -eq $files) { $errs += " is missing (use if it has none)" } + else { + foreach ($c in $files.ChildNodes) { + if ($c.NodeType -ne [System.Xml.XmlNodeType]::Element -or $c.Name -ne 'file') { + $errs += " contains a non- node ($($c.NodeType) '$($c.Name)'). Aborts the updater's parse" + continue + } + if ([string]::IsNullOrEmpty($c.GetAttribute('path'))) { $errs += " has a without a path attribute" } + if ([string]::IsNullOrEmpty($c.GetAttribute('status'))) { $errs += " has a without a status attribute" } + } + } + + $changelog = $node.SelectSingleNode('changelog') + if ($null -eq $changelog) { $errs += " is missing " } + else { + foreach ($c in $changelog.ChildNodes) { + if ($c.NodeType -ne [System.Xml.XmlNodeType]::Element -or $c.Name -ne 'change') { + $errs += " contains a non- node ($($c.NodeType) '$($c.Name)'). Its text would leak into the shown changelog" + } + } + } +} + +# A manifest with only the 0.0.0 staging block has nothing to release. +if (@($versions | Where-Object { $_ -ne '0.0.0' }).Count -eq 0) { + $errs += 'no releasable entry (only the 0.0.0 staging block). Promote it to a real version' +} + +if ($ReleaseVersion) { + $u = $root.SelectSingleNode("update[@version='$ReleaseVersion']") + if ($null -eq $u) { + $errs += "no to release (promote the 0.0.0 staging block to this version)" + } + else { + if ($u.SelectNodes("files/file[contains(@path,'download/v$ReleaseVersion/')]").Count -eq 0) { + $errs += " has no download/v$ReleaseVersion/ asset path" + } + $hasChange = $false + foreach ($c in $u.SelectNodes('changelog/change')) { if ($c.InnerText.Trim()) { $hasChange = $true } } + if (-not $hasChange) { $errs += " has no non-empty changelog entry" } + } +} + +if ($errs.Count) { + # file= attaches each as a GitHub annotation on the manifest (no line numbers tracked). + $errs | ForEach-Object { Write-Host "::error file=$($Path)::$_" } + exit 1 +} + +$n = @($doc.updates.update).Count +$suffix = if ($ReleaseVersion) { "; release entry $ReleaseVersion is ready" } else { '' } +Write-Host "Manifest OK: $n entries parse cleanly$suffix." diff --git a/update.LiveSplit.AutoSplitIntegration.xml b/update.LiveSplit.AutoSplitIntegration.xml new file mode 100644 index 0000000..acdf1f9 --- /dev/null +++ b/update.LiveSplit.AutoSplitIntegration.xml @@ -0,0 +1,58 @@ + + + + + + + Rebuilt on .NET Framework 4.8.1. + Fixed a `System.NullReferenceException` when setting a "Settings Path" without first starting AutoSplit. + Fixed the auto-update source. + + + + + + + + + Fixes AutoSplit being reopened on clicking “Cancel”. + + + + + + Fixes AutoSplit not being opened correctly. + + + diff --git a/update/Components/LiveSplit.AutoSplitIntegration.dll b/update/Components/LiveSplit.AutoSplitIntegration.dll deleted file mode 100644 index 0f549a1..0000000 Binary files a/update/Components/LiveSplit.AutoSplitIntegration.dll and /dev/null differ diff --git a/update/Components/update.LiveSplit.AutoSplitIntegration.xml b/update/Components/update.LiveSplit.AutoSplitIntegration.xml deleted file mode 100644 index 5de8017..0000000 --- a/update/Components/update.LiveSplit.AutoSplitIntegration.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - Fixes AutoSplit being reopened on clicking “Cancel”. - - - - - - - - Fixes AutoSplit not being opened correctly. - - -