Skip to content

Let manifest sources be declared in JSON - #46

Open
cheapmanga wants to merge 32 commits into
madoiscool:mainfrom
cheapmanga:feature/json-manifest-sources
Open

cheapmanga wants to merge 32 commits into
madoiscool:mainfrom
cheapmanga:feature/json-manifest-sources

Conversation

@cheapmanga

Copy link
Copy Markdown

As discussed — the JSON half only. No plugin loader, no dll, nothing loaded.

A .json file under %AppData%\LuaToolsGui\sources\ declares extra manifest sources. They appear as rows on the Add page and install through the existing pipeline.

{
  "schema": 1,
  "name": "Example sources",
  "sources": [{
    "name": "example-zip",
    "displayName": "Example",
    "kind": "manifestZip",
    "url": "https://raw.githubusercontent.com/someone/some-repo/main/{appid}.zip",
    "badge": "Free"
  }]
}

Why: the sources the app can fetch from are fixed at build time, so following a repo that moved means cutting a release. This makes it a line of JSON.

A file can only say where manifests come from. It names one of two shapes the app already consumes — manifestZip (<appid>.zip) or luaFile (<appid>.lua) — and the app does the fetching. There is no way for one to supply code, a binary, or a routine of its own, so installing one from a stranger cannot execute anything.

Three choices worth flagging for review:

  • Rows are appended after the app's own sources rather than ranked among them. That order is yours to decide, not a dropped-in file's.
  • They're exempt from the lua.tools sign-in gate, since they're fetched from the url the file names and never touch lua.tools.
  • The availability probe goes through GithubProxy like the download does — one that skipped it would report "doesn't have the game" whenever GitHub was blocked, while the download would have gone through a mirror. Hosts that refuse HEAD get a one-byte ranged GET.

Refusals (a name already in use, non-https, missing {appid}, unknown kind) are listed in Settings → Manifest sources with the reason; one bad entry doesn't take a file's good ones with it. Files are re-read when that page opens, so no restart.

All 29 languages. Format documented in SOURCES.md. Happy to change any of it, or drop it if you'd rather not have the surface.

madoiscool and others added 28 commits August 13, 2026 21:54
Updated project name and added image to README. Clarified instructions regarding `dotnet watch` and `dotnet build` conflicts.
Clean up punctuation and wording across many files and replace several hard-coded user-facing error/status strings with Resources.Strings localization keys. Minor readability tweaks in comments, logging messages and scripts/check-i18n.py; XAML and VM comments adjusted. These are behavior-neutral edits (no logic changes intended); tests updated to match wording. If any new resource keys were introduced, ensure they exist in Strings.resx and in all language files.
Rename and simplify unlocker modes (Ost/Bst/Custom), add a one‑shot ModeMigration to rewrite legacy SelectedMode values and tests for the migration. Introduce UpdateManifest support and parsing, and update UnlockerService to support manifest-backed modes (BetterSteamTools) alongside release-based OST installs. Add many localized resource keys/messages and update Strings.Designer bindings. Adjust Mode view/model and onboarding flows to use the new mode names and behaviors (BST recommended, OST experimental, Custom = user-managed). Misc: small wording fixes, improved error handling/messages, and new unit tests (ModeMigrationTests).
an updated minimal but better version of the current italian translation
Introduce DepotDownloaderService and plumbing to download raw Steam depot content (tool acquisition, run/watchdog, key handling, manifest fetch). Add depot-download job support in ManifestJobFactory and API client (DownloadDepotManifestAsync). Update DownloadQueue/DownloadItem to support depot-specific states (Paused, Verifying), Pause/Resume, resume-validate, and auto-dismiss completed items; remove the previous concurrency UI setting. Extend LuaFileParser, SteamDepotInfo and DonateKeysService to expose keys/from-app info. Add select-depots UI and flows in BuildsView + DownloadsView, new strings/translations, AppConfig repo constant, and register service in App. Small tests/file tidy.
Introduce AssetHash helper for SHA-256 verification and remove duplicated hashing/parsing code across services. Add tool-version fingerprints and checked timestamps to CacheService with atomic writes to avoid data loss. Change DepotDownloader repo to mendy-tools/DepotDownloaderMod and implement throttled release checks, digest verification, size-aware progress reporting, and fallbacks so a working tool is never disabled by network failures. SteamlessService updated with the same caching/check logic. Rework ManifestJobFactory into phases (fetch tool once, resolve manifests & sizes up-front, free-space check, then download) and improve progress/detail messages. Add GithubAsset.Size and new localized strings (Downloads_Depots_Preparing / Downloads_Depots_GettingTool) across all languages. Misc: replace ad-hoc SHA256 helpers with AssetHash usages in PluginInstallerService, UnlockerService, and others.
This change adds SteamAutoCrack download/launch support with .NET runtime installation, update checks, and queue integration. It also hardens depot downloads by validating cached manifests, tracking created files for cancel/delete flows, and surfacing clearer progress/status phases. The downloads/history UI gains row actions for app-id copy and folder reveal, plus clearer history clearing and remove actions. Related localization strings and app config/cache updates were added to support the new tool and depot behavior.
Adds an icon to each mode badge, swaps Active to green and Recommended to blue, and reorders them so the active mode reads first.

Co-authored-by: gattoooo
Applying a fix now backs up the files it overwrites into .luatools-fix/ and records them in a manifest, so it can be reverted. Adds a My games toggle that filters the listing to appids with a lua in stplug-in.
Add new "Fixes" localization keys (Applied hint, My Games, counts, revert flow texts, and error messages) across all language .resx files. Improve ManifestJobFactory to prevent zip-slip by resolving paths inside the game folder, back up files keyed by full relative path (not filename), and validate manifest backup paths on revert. Revert now preserves backups/manifests on partial failure (so retries are possible) and only deletes them after a full successful revert.
@madoiscool

Copy link
Copy Markdown
Owner

cool, will merge after dealing with conflits

Introduce robust applied-fix tooling and a one-time depotcache migration. Added AppliedFixIndexService (applied-fixes.json), DepotCacheMigrationService (moves manifests from config\depotcache → depotcache), and FileHash (SHA-256 helpers). Reworked Denuvo fix handling: rename "manifest"→"record", four-phase apply (plan/commit/apply/settle), per-file hashes, safer backups, and conflict detection on revert. Updated ManifestJobFactory, DepotDownloaderService, SteamService, SteamLibraryService, FixesViewModel, and resources (new revert/localization keys). Register services and run migration at startup. Added unit tests for migration and file-hash behaviour.

Co-Authored-By: Brandon Hernandez <142270679+Brandher58@users.noreply.github.com>
@cheapmanga
cheapmanga force-pushed the feature/json-manifest-sources branch from 407680c to 0d6898a Compare September 9, 2026 17:42
@cheapmanga

Copy link
Copy Markdown
Author

Gentle nudge on this one 🙂 I've rebased it, so it's conflict-free and GitHub shows it as mergeable now — should be ready whenever you have a moment. Happy to rebase again or adjust anything if it helps it land. Thanks!

madoiscool and others added 3 commits September 25, 2026 17:09
Steam can return appdetails keyed by a child app id instead of the requested app, which previously caused silent cache misses or wrong-game data. This change resolves entries by validating data.steam_appid, refuses ambiguous or malformed payloads rather than guessing, logs once per app when no match can be proven, and adds regression tests covering child-keyed, direct-key, and refusal edge cases.
This adds a per-connection DNS mode option for the app, with Auto/Always/Never behavior backed by a shared AppHttp handler and a Cloudflare DoH resolver. The change centralizes HTTP clients, keeps settings-driven resolution applied across the app, routes GitHub and update downloads through the same policy, and adds localized settings strings and tests covering resolver bypass, caching, and parsing.
The sources the app can fetch from are fixed at build time, so following a
repo that moved, or adding a community one, means cutting a release. A
`.json` file under %AppData%\LuaToolsGui\sources\ now declares extra
sources; they appear as rows on the Add page and install through the
existing pipeline.

Data only, by design. A file says WHERE manifests come from and nothing
else: it names one of the shapes the app already consumes (a zip or a lua
per appid) and the app does the fetching. There is no way for one of these
files to supply code, a binary, or a routine of its own, so installing one
from a stranger cannot execute anything.

Pack rows are appended after the app's own sources rather than ranked among
them - that order is the app's decision, not a dropped-in file's. They are
also exempt from the lua.tools sign-in gate, since they are fetched from
the url the file names and never touch lua.tools.

The availability probe goes through GithubProxy like the download does; one
that skipped it would report "doesn't have the game" whenever GitHub was
blocked while the download would have succeeded through a mirror. A host
that refuses HEAD is probed with a one-byte ranged GET, because these urls
are whatever host the author picked.

Refusals are shown in Settings with their reason - a name the app already
uses, a non-https url, a missing {appid}, an unknown kind - and one bad
entry never takes a file's good ones with it. Files are re-read when the
Settings page opens, so nothing needs a restart. All 29 languages.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BPSigFCgHqiUUbL9RRPZWs
@cheapmanga
cheapmanga force-pushed the feature/json-manifest-sources branch from 0d6898a to 079f6ad Compare September 25, 2026 16:23
@cheapmanga

Copy link
Copy Markdown
Author

Hey @madoiscool 👋 Rebased this onto v1.3.2 (including the new DNS fallback). No conflicts, and GitHub shows it as mergeable again. It's still one self-contained commit. Would be great to get it in before the next round of changes drifts it again. Happy to tweak anything if needed!

@cheapmanga
cheapmanga force-pushed the feature/json-manifest-sources branch from 079f6ad to 0a61d52 Compare October 4, 2026 11:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants