Skip to content

Commit 7b7c77e

Browse files
committed
chore(renaming): 🚚 Align mod/project name with WhileLoopTimeout
1 parent f449c37 commit 7b7c77e

21 files changed

Lines changed: 1350 additions & 0 deletions

.editorconfig

Lines changed: 386 additions & 0 deletions
Large diffs are not rendered by default.

.github/release.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
changelog:
2+
exclude:
3+
labels:
4+
- ignore-release
5+
categories:
6+
- title: Breaking Changes
7+
labels:
8+
- breaking
9+
- title: Features
10+
labels:
11+
- feature
12+
- enhancement
13+
- title: Bug Fixes
14+
labels:
15+
- bug
16+
- fix
17+
- title: Maintenance
18+
labels:
19+
- chore
20+
- dependencies
21+
- docs
22+
- title: Other Changes
23+
labels:
24+
- '*'

.github/workflows/ci.yml

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
tags:
8+
- v*
9+
pull_request:
10+
workflow_dispatch:
11+
12+
permissions:
13+
contents: read
14+
15+
env:
16+
DOTNET_NOLOGO: true
17+
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
18+
DOTNET_CLI_TELEMETRY_OPTOUT: true
19+
RESONITE_INSTALL_DIR: ${{ github.workspace }}/.resonite
20+
21+
jobs:
22+
build:
23+
runs-on: ubuntu-latest
24+
timeout-minutes: 30
25+
steps:
26+
- name: Checkout
27+
uses: actions/checkout@v4
28+
with:
29+
fetch-depth: 0
30+
31+
- name: Verify Steam credentials
32+
shell: bash
33+
run: |
34+
if [ -z "${{ secrets.STEAMUSER }}" ]; then
35+
echo '::error::Missing secrets.STEAMUSER. Add the Steam username used for SteamCMD downloads.'
36+
exit 1
37+
fi
38+
if [ -z "${{ secrets.STEAMPASS }}" ]; then
39+
echo '::error::Missing secrets.STEAMPASS. Add the Steam password used for SteamCMD downloads.'
40+
exit 1
41+
fi
42+
43+
- name: Setup Resonite environment
44+
id: resonite
45+
uses: resonite-modding-group/setup-resonite-env-action@v0.1.0
46+
with:
47+
steam-user: ${{ secrets.STEAMUSER }}
48+
steam-password: ${{ secrets.STEAMPASS }}
49+
resonite-path: ${{ env.RESONITE_INSTALL_DIR }}
50+
51+
- name: Install ResoniteModLoader binaries
52+
env:
53+
RESONITE_PATH: ${{ env.RESONITE_INSTALL_DIR }}
54+
shell: bash
55+
run: |
56+
set -euo pipefail
57+
if [ -z "${RESONITE_PATH:-}" ]; then
58+
echo '::error::Resonite path is empty. Ensure the setup-resonite-env step succeeded and exposed resonite-path.'
59+
exit 1
60+
fi
61+
install -d "$RESONITE_PATH/Libraries" "$RESONITE_PATH/rml_libs"
62+
curl -sSfL -o "$RESONITE_PATH/Libraries/ResoniteModLoader.dll" \
63+
https://github.com/resonite-modding-group/ResoniteModLoader/releases/latest/download/ResoniteModLoader.dll
64+
curl -sSfL -o "$RESONITE_PATH/rml_libs/0Harmony.dll" \
65+
https://github.com/resonite-modding-group/ResoniteModLoader/releases/latest/download/0Harmony.dll
66+
67+
- name: Setup .NET SDK
68+
uses: actions/setup-dotnet@v4
69+
with:
70+
dotnet-version: 9.0.x
71+
72+
- name: Cache NuGet packages
73+
uses: actions/cache@v4
74+
with:
75+
path: ~/.nuget/packages
76+
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json', '**/*.csproj') }}
77+
restore-keys: |
78+
${{ runner.os }}-nuget-
79+
80+
- name: Restore
81+
env:
82+
ResoniteAssembliesDir: ${{ env.RESONITE_INSTALL_DIR }}
83+
shell: bash
84+
run: |
85+
dotnet restore FluxLoopTweaks.sln
86+
87+
- name: Verify formatting
88+
env:
89+
ResoniteAssembliesDir: ${{ env.RESONITE_INSTALL_DIR }}
90+
shell: bash
91+
run: |
92+
dotnet format FluxLoopTweaks.sln --verify-no-changes --no-restore
93+
94+
- name: Build
95+
env:
96+
ResoniteAssembliesDir: ${{ env.RESONITE_INSTALL_DIR }}
97+
shell: bash
98+
run: |
99+
dotnet build FluxLoopTweaks.sln --configuration Release --no-restore
100+
101+
- name: Test
102+
env:
103+
ResoniteAssembliesDir: ${{ env.RESONITE_INSTALL_DIR }}
104+
shell: bash
105+
run: |
106+
dotnet test FluxLoopTweaks.sln --configuration Release --no-build
107+
108+
- name: Prepare release assets
109+
if: startsWith(github.ref, 'refs/tags/v')
110+
shell: bash
111+
run: |
112+
set -euo pipefail
113+
artifacts_dir=release-artifacts
114+
mkdir -p "$artifacts_dir"
115+
cp src/FluxLoopTweaks/bin/Release/net9.0/FluxLoopTweaks.dll "$artifacts_dir/FluxLoopTweaks.dll"
116+
if [ -f src/FluxLoopTweaks/bin/Release/net9.0/FluxLoopTweaks.pdb ]; then
117+
cp src/FluxLoopTweaks/bin/Release/net9.0/FluxLoopTweaks.pdb "$artifacts_dir/FluxLoopTweaks.pdb"
118+
fi
119+
120+
- name: Upload release artifacts
121+
if: startsWith(github.ref, 'refs/tags/v')
122+
uses: actions/upload-artifact@v4
123+
with:
124+
name: flux-loop-tweaks
125+
path: release-artifacts
126+
if-no-files-found: error
127+
128+
release:
129+
runs-on: ubuntu-latest
130+
needs: build
131+
if: startsWith(github.ref, 'refs/tags/v')
132+
permissions:
133+
contents: write
134+
steps:
135+
- name: Download build artifacts
136+
uses: actions/download-artifact@v4
137+
with:
138+
name: flux-loop-tweaks
139+
path: release-artifacts
140+
141+
- name: Publish GitHub release
142+
uses: softprops/action-gh-release@v2
143+
with:
144+
tag_name: ${{ github.ref_name }}
145+
name: Flux Loop Tweaks ${{ github.ref_name }}
146+
generate_release_notes: true
147+
files: |
148+
release-artifacts/FluxLoopTweaks.dll
149+
release-artifacts/FluxLoopTweaks.pdb

.gitignore

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Build outputs
2+
bin/
3+
obj/
4+
**/bin/
5+
**/obj/
6+
7+
# IDE files
8+
.vs/
9+
.idea/
10+
*.user
11+
*.suo
12+
13+
# Local tooling
14+
*.swp
15+
*.DS_Store
16+
17+
# Local Resonite installation (never check in game files)
18+
Resonite/
19+
20+
# Private notes (non-repo disclosure)
21+
local_notes/

AGENTS.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# AGENTS (Repository Root)
2+
3+
This file is **authoritative and persistent** for everything under `/WhileLoopTimeout`. Keep it in version control and treat its directives as mandatory.
4+
5+
## Directives
6+
7+
1. **Golden rule:** Relentlessly minimize complexity, maximize changeability, and enforce strict static checks to suppress runtime bugs. Names, code, and directory structures must be self-explanatory—avoid relying on comments/docs for basic comprehension.
8+
2. **Testing cadence:** Hands-on runtime testing happens later in a live Resonite session; until then, document assumptions and leave TODOs rather than speculative fixes.
9+
3. **Localization:** UI remains English-only until Resonite exposes extensible localization hooks. Do not ship partial translations; revisit only when upstream enables custom locale registration.
10+
4. **Knowledge management:** Split knowledge based on disclosure level.
11+
- Public/committable notes (design decisions, checklists) belong in versioned docs like this AGENTS file or other repo docs.
12+
- Private, potentially sensitive research (e.g., raw assembly dumps, exploratory notes) must live under the git-ignored `local_notes/` directory, each topic in its own markdown file to keep knowledge granular.
13+
5. **Persistence:** Any change to policies/workflow must be reflected here immediately. Subdirectories inherit these rules unless they define their own `AGENTS.md`.
14+
6. **Data model constraints:** This mod must not introduce new FrooxEngine data-model types or `SyncDelegate` definitions. All functionality must be built on existing data-model constructs to avoid sync registration overhead.
15+
7. **Design notes ban:** Do not create standalone design notes or ADR-style docs; instead, keep commits and code self-explanatory and update this AGENTS file if process rules change.
16+
8. **Task completion ritual:** Before declaring any task done, run the following commands in order and address all failures:
17+
- `dotnet format WhileLoopTimeout.sln --verify-no-changes --no-restore`
18+
- `dotnet build WhileLoopTimeout.sln --no-restore`
19+
- `dotnet test WhileLoopTimeout.sln --no-restore`
20+
Capture key failures in the report/PR and rerun after fixes.
21+
9. **WSL / cross-platform NuGet hint:** If `dotnet build`/`test` fails with `Unable to find fallback package folder 'C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages'`, do one of the following before rerunning the commands:
22+
- Export an override to point at a real folder, e.g. `DOTNET_MSBUILD_SDK_RESOLVER_CLI_FALLBACK_FOLDER=$HOME/.nuget/fallback dotnet build ...` (create the folder first).
23+
- Add a symlink/mount so that the Windows path exists from Linux (`sudo mkdir -p /mnt/c/Program\ Files\ \\(x86\\)/Microsoft\ Visual\ Studio/Shared/NuGetPackages`).
24+
- Remove the Windows-only fallback entry from the active `NuGet.Config`.
25+
Tasks stay “in progress” until at least one of these mitigations succeeds.
26+
27+
## Scope / Status
28+
29+
- Repository initialized 2025-11-15 with WhileLoopTimeout for ResoniteModLoader.
30+
- Current deliverable: Guard ProtoFlux `While`/`AsyncWhile` loops with abortable timeouts to keep sessions responsive.
31+
32+
## Localization Policy (Public Summary)
33+
34+
- English-only interface. Reevaluate once Resonite core supports custom localized strings for Dev Tool menus and UIX builders.
35+
36+
## History Tracking Rule
37+
38+
- Detailed work history lives in the git commit log; do not maintain manual work logs in docs. Summaries belong in commit messages and PR descriptions only.

Directory.Build.props

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<Project>
2+
<PropertyGroup>
3+
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
4+
<AnalysisLevel>latest-all</AnalysisLevel>
5+
<Nullable>enable</Nullable>
6+
<EnableNETAnalyzers>true</EnableNETAnalyzers>
7+
</PropertyGroup>
8+
9+
<PropertyGroup Condition="'$(ResoniteAssembliesDir)'==''">
10+
<ResoniteAssembliesDir>$(MSBuildThisFileDirectory)Resonite/</ResoniteAssembliesDir>
11+
<ResoniteAssembliesDir Condition="Exists('/mnt/c/Program Files (x86)/Steam/steamapps/common/Resonite/')">/mnt/c/Program Files (x86)/Steam/steamapps/common/Resonite/</ResoniteAssembliesDir>
12+
<ResoniteAssembliesDir Condition="Exists('C:\\Program Files (x86)\\Steam\\steamapps\\common\\Resonite\\')">C:\\Program Files (x86)\\Steam\\steamapps\\common\\Resonite\\</ResoniteAssembliesDir>
13+
<ResoniteAssembliesDir Condition="Exists('$(HOME)/.steam/steam/steamapps/common/Resonite/')">$(HOME)/.steam/steam/steamapps/common/Resonite/</ResoniteAssembliesDir>
14+
</PropertyGroup>
15+
16+
<PropertyGroup Condition="'$(ResoniteAssembliesDir)'!=''">
17+
<ResolvedResoniteAssembliesDir>$([System.IO.Path]::GetFullPath('$(ResoniteAssembliesDir)'))</ResolvedResoniteAssembliesDir>
18+
</PropertyGroup>
19+
</Project>

Directory.Build.targets

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<Project>
2+
<Target Name="EnsureResoniteAssembliesDir" BeforeTargets="ResolveReferences">
3+
<Error Condition="'$(ResoniteAssembliesDir)'==''" Text="ResoniteAssembliesDir must be set (or install Resonite under ./Resonite, the default Steam Windows path, or ~/.steam/steam/steamapps/common/Resonite/ for auto-detection)." />
4+
<Error Condition="!Exists('$(ResolvedResoniteAssembliesDir)/FrooxEngine.dll')" Text="Cannot find FrooxEngine.dll under $(ResolvedResoniteAssembliesDir)." />
5+
</Target>
6+
</Project>

GitVersion.yml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
mode: Mainline
2+
branches:
3+
master:
4+
regex: ^master$
5+
tag: ''
6+
increment: patch
7+
prevent-increment-of-merged-branch-version: true
8+
feature:
9+
regex: ^(feature|feat|bugfix)/
10+
increment: patch
11+
pull-request:
12+
regex: ^(pull|pr)/
13+
tag: pr
14+
increment: patch
15+
hotfix:
16+
regex: ^hotfix/
17+
increment: patch
18+
release:
19+
regex: ^release/
20+
increment: minor
21+
develop:
22+
regex: ^develop$
23+
increment: minor
24+
ignore:
25+
sha: []
26+
tag-prefix: v
27+
continuous-delivery-fallback-tag: ci
28+
legacy-semver-padding: 3
29+
build-metadata-padding: 5
30+
commits-since-version-source-padding: 4
31+
assembly-versioning-scheme: MajorMinorPatch
32+
assembly-file-versioning-format: '{Major}.{Minor}.{Patch}.0'
33+
assembly-informational-format: '{FullSemVer}+{ShortSha}'
34+
major-version-bump-message: '\+semver:\s?(breaking|major)'
35+
minor-version-bump-message: '\+semver:\s?(feature|minor)'
36+
patch-version-bump-message: '\+semver:\s?(fix|patch)'

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2025 esnya
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# While Loop Timeout
2+
3+
`WhileLoopTimeout` is a [ResoniteModLoader](https://github.com/resonite-modding-group/ResoniteModLoader) mod for [Resonite](https://resonite.com/) that guards ProtoFlux `While`/`AsyncWhile` loops against runaway execution. The mod tracks how long a loop runs during a single engine tick and aborts execution once it exceeds a configurable timeout (default: 30 s), preventing world lockups while still allowing legitimate long-running work.
4+
5+
## Installation
6+
7+
1. Install [ResoniteModLoader](https://github.com/resonite-modding-group/ResoniteModLoader).
8+
2. Download the latest `WhileLoopTimeout.dll` from this repo’s Releases page and place it in the `rml_mods` folder inside your Resonite install (e.g., `C:\Program Files (x86)\Steam\steamapps\common\Resonite\rml_mods`). Create the folder if it does not exist.
9+
3. (Optional) Tweak the **Timeout** config entry if you need a shorter or longer guard window.
10+
4. Launch Resonite and confirm the mod loads via the in-game logs if desired.
11+
12+
## Build & Hot Reload
13+
14+
1. Install the .NET 9 SDK.
15+
2. `dotnet build WhileLoopTimeout.sln` auto-detects `Resonite` next to the repo, the default Steam Windows path, then the default Steam Linux path. If the game lives elsewhere, pass `-p:ResoniteAssembliesDir="/absolute/path/to/Resonite"` so the build can find `FrooxEngine.dll`, `Elements.Core.dll`, `Libraries/ResoniteModLoader.dll`, and `rml_libs/0Harmony.dll`.
16+
3. Set `CopyToMods=true` when invoking `dotnet build` to copy the compiled DLL into `$(ResoniteAssembliesDir)/rml_mods` after each build.
17+
4. Drop `ResoniteHotReloadLib.dll` (and `ResoniteHotReloadLibCore.dll`) into `$(ResoniteAssembliesDir)/rml_libs` and build with `-p:EnableResoniteHotReloadLib=true` if you want the Dev Tool’s **Hot Reload Mods** panel to reload this mod without restarting Resonite. Leave the property unset on machines without the DLL.

0 commit comments

Comments
 (0)