Skip to content

Accept delisted owned games and download any or every version - #23

Open
marshmallow-mia wants to merge 13 commits into
Villagers654:mainfrom
marshmallow-mia:fix/delisted-games-and-versions
Open

marshmallow-mia wants to merge 13 commits into
Villagers654:mainfrom
marshmallow-mia:fix/delisted-games-and-versions

Conversation

@marshmallow-mia

Copy link
Copy Markdown
Contributor

What this fixes

Delisted games couldn't be added. The Add Game link check scraped the public store page, so delisted games such as
Echo VR were reported as not found even when owned ("Meta's store page has no catalog metadata"). When signed in, links
are now checked against the downloadable builds of the signed-in accounts, owners first as for an install, with the
store page as a fallback. Slug-less pcvr links and
old oculus.com Rift links, both refused on main, are accepted too.

Older versions were out of reach. The app installed only the newest build. riftlift add --build could pick an
older one, but only among the newest 20 that Meta's supportedBinaries query returns (for Echo VR: 20 of 147
downloadable builds), and into the installed game's folder, replacing it. The new builds module also reads the app's
full binary history (as OculusDB does) and keeps only builds published to a release channel, since unpublished ones
return HTTP 404 from the CDN.

  • GUI: a version picker in the install dialog, including "All versions".
  • CLI: riftlift builds, riftlift add --build all.
  • A chosen build installs side by side with the others. Installs record their binary ID, so builds with the same
    version number never overwrite each other.
  • Builds that download but can't launch (32-bit) say so and name their folder.

Every version

Downloads stay pausable. The install runs in the existing download worker; the chosen build travels in the worker
request. For "All versions" the worker reports each version as it starts, so Pause works between versions and each
version is finalized on its own. Resuming a paused run doesn't ask about every version again. Failed versions come back
as their label, a kind (failed, or downloaded but not launchable) and a reason from the worker's describe_error,
which strips URLs and tokens. The notice lists each version with its reason, since nothing in the 0.11.1.2 window opens
the Activity log. Versions that failed the same way share a line, and a long list scrolls in its own box.

Which versions failed

This one uses a simulated four-version game so both failure kinds show.

A paused version resumes into its own folder. A version's folder is claimed with its build marker before the
download starts. Without that, a paused download's folder had neither the marker nor a library record, so resuming
downloaded the version again into a second folder and left the partial one on disk for good.

Versions stay apart once store details arrive. Store details used to replace a side-by-side install's name with the
store's, so "Lone Echo (1.0)" became "Lone Echo" and every version of a listed game read the same. The version label now
stays. "All versions" also fetches the store details and artwork once and copies them to the other versions; fetched per
version, Meta answered HTTP 429 on a 31-version run.

A plain install stays on the build Meta offers. The full history also lists builds that are only on an alpha, beta or
other non-public channel. A plain install, the owned list's Install button and the picker's "latest" entry use the
newest build Meta's supportedBinaries query offers, as on main; for Bigscreen Beta and SKYBOX VR Video Player, the
highest version code would otherwise be a PCALPHA or device-channel build. Newer builds on other channels stay listed
and installable when chosen.

Every version gets a folder of its own. A chosen version takes the plain game folder only when it is empty or holds
that very build, so it never mixes with another build's paused download. A version-code fallback name that is taken
(version "1.0" build 2 would become game-1-0-2, version 1.0.2's folder) falls back to the build's binary ID.

"All versions" leaves installed versions alone. They keep their library entry and launch options, environment and
DLL overrides, and a resumed run skips the versions it already finished.

Failures say what happened.

  • An expired Meta sign-in (Meta answers with an OAuthException) asks to sign in again instead of "game not found".
  • A build that downloaded but cannot launch says so instead of "check your connection".
  • The reasons for each failed version show even when none installed.
  • Closing Add Game while a link check or version listing is still running no longer raises "Signal source has been
    deleted" in the background thread.

The Windows command line too. riftlift builds and riftlift add --build all work on Windows as on Linux;
before, --build all reached add() and stopped with "use add_all_versions to download every build".

Testing

On 0.11.1.2

  • With the real account through the CI AppImage: riftlift builds lists Echo VR's 147 downloadable versions with their
    channels, and the install dialog lists the same 147 plus "All versions" (the first two screenshots).
  • New since the last base:
    • Per-version reasons in the notice, grouped when they're the same.
    • The scrolling list.
    • No second question on resume.
    • The Windows command line (tests/test_windows_downloads.py).
    • Each of the three notice and resume tests fails before its commit (tests/test_version_installs.py,
      tests/test_download_versions.py).
  • The full suite on Linux (Python 3.10 + PySide6 6.7, 3.12 + 6.11 and 3.12 + 6.12) for every commit, and on macOS.
  • Fork CI on the ported branch: the CI and Windows workflows pass, Python and native jobs alike, including
    tests/test_windows_native.py on Windows.
  • Not verified on 0.11.1.2: a real build that downloads but can't launch. No owned game has one left: the oldest
    builds of BlazeRush (0.0, 0.1) and Lucky's Tale (0.5) fail with "Manifest request returned HTTP 404" (Meta no
    longer serves them; nothing is installed), and VR Coaster Madness 1 is 64-bit. That kind is covered by the unit
    tests and the simulated picture above.
  • Blocks side by side (Linux, the merge's AppImage): 3.0.1O installs beside 4.0.1O into its own folder
    (blocks-3-0-1o, its binary ID recorded, the older M3.1_RC0_Oculus/ layout). 4.0.1O's files are unchanged. Each
    entry launches its own Blocks.exe, and both render on Monado.
  • Windows 10, the fork CI's installers (main, then the merge of all branches installed over it, with the real
    account):
    • Main: builds is "invalid choice". add <Sensor Bounds> --build all stops with "Build 'all' was not found".
    • This branch (merged): builds lists 31 versions for Sensor Bounds and 147 for Echo VR.
    • add --build all installs all 31 in 110 s ("Installed 31 version(s); 0 downloaded but not launchable; 0 failed.").
    • A second run downloads nothing.
  • Live on Linux with a real account: the CI AppImages of main and of all branches merged, with Sensor Bounds (31
    versions).
    • Links:
      • Echo VR's link: main says "This Rift store game could not be found.". This branch says "Ready to install Echo
        VR." and shows the picker.
      • Slug-less and oculus.com Rift links: main says "Paste a valid Meta Rift store link"; this branch accepts both.
    • The picker: 31 versions plus "All versions (31)".
    • Upgrade from main:
      • Main installs 1.31; this branch installs 1.28 beside it.
      • Main's list reads the versioned records.
      • Once the versions are removed, main's install is byte-identical.
    • Pause and resume (command line):
      • Interrupted after 3 s, the version's folder is already claimed with its build marker.
      • Resumed, it continues in that folder (35 of 38 segments cached), with one library record.
    • add --build all: skips main's install and the versions already there. Ctrl+C ends it. A second run continues
      the interrupted version in its folder.
    • "All versions" in the window:
      • Paused, and the app ended.
      • In a new process, the run skipped the installed versions (files unchanged) and finished the paused version in
        its own folder.
      • Resuming no longer asks again.
    • Failures: 30 versions failing at once (games folder made read-only) show their reasons in the scrolling notice.
      Before the last two commits, a failed version only read "download failed".

Earlier, on 7289ef6

  • New tests: tests/test_builds.py, tests/test_download_versions.py, and additions to tests/test_gui.py,
    tests/test_library.py (paused version resumes in place, store details fetched once) and tests/test_metadata.py
    (version label kept). The new library and metadata tests fail without their fix.
  • Live on Linux with a real account:
    • Echo VR (delisted, owned) lists all 147 downloadable builds in the dialog and on the CLI. Its link is accepted when
      signed in and refused with a hint to sign in when not.
    • Links with a slug, without one, with a locale, and old oculus.com Rift links are accepted; Quest and other sites'
      links are not.
    • Sensor Bounds (31 versions): newest build with pause and resume, an older build side by side, both in the library,
      then both uninstalled cleanly.
    • "All versions" through the download worker, paused in version 2 and resumed: 31 library entries, nothing failed,
      no folder left after uninstalling. Same with riftlift add --build all.
    • A versioned name keeps its label when Meta's store details arrive.
    • The same checks on main: Echo VR's link is refused as not found, slug-less and oculus.com links are refused, and
      supportedBinaries returns Echo VR's newest 20 builds.
    • Default build for all 29 owned games: the same as main's for every game after the fix (two differed before).
    • Upgrade from main: a game installed by main stays byte-identical while an older version installs beside it, the
      plain install runs again and the older version is uninstalled; only the build marker is added.
    • An older version paused, the app quit, and resumed in a new process: same folder, one library entry.
    • Blocks 4.0.0O beside 4.0.1O: starts from its own folder and renders on Monado and on the Quest 3 (WiVRn).
    • Steam shortcuts, on a copy of the Steam data: one per version, named with its label, removed on uninstall.
    • No network: the owned list, link check, build list and download each fail with a clear message.
  • tests/test_version_installs.py: default build, folder collisions, installed versions in "All versions", failure
    messages, expired sign-in, Add Game threads after close. Each test fails before its fix.
  • pytest, ruff and the installer step on Linux: same results as main, plus the new tests.

The Add Game link check scraped the public store page for catalog data, so
delisted games such as Echo VR were reported as not found even when owned.
When signed in, links are now verified against the downloadable builds of
the signed-in accounts, with the store page as a fallback.

Meta's supportedBinaries query is fixed at the newest 20 builds. The new
builds module also reads the app's full binary history (as OculusDB does)
and keeps only builds published to a release channel, since unpublished
binaries return HTTP 404 from the CDN. Like a plain install, listing tries
each signed-in account, owners first, until one can download the app.

- GUI: version picker in the install dialog, including "All versions"
- CLI: `riftlift builds`, `riftlift add --build all`
- Explicitly chosen builds install side by side; installs record their
  binary ID so same-version builds never overwrite each other
- Builds that download but cannot launch (32-bit) report their folder
- Accept slug-less pcvr links and legacy oculus.com Rift links

The install runs in the pausable download worker process: the chosen build
travels in the worker request. For "All versions" the worker reports each
version as it starts, so Pause works again between versions and each
version is finalized on its own; failed versions come back as their label
and a kind (failed, or downloaded but not launchable), never error text.
A versioned install wrote the marker naming its build only after the
download. A paused download's folder had neither that marker nor a library
record, so resuming counted it as taken: the version downloaded again into
a second folder (name-1-29-41), and the partial one stayed on disk for good,
since uninstalling only removes folders with a record.

The folder is now claimed with the marker before the download starts, so a
resume continues in it.
Store details replaced a side-by-side install's name with the store's, so
"Lone Echo (1.0)" became "Lone Echo" and every version of a listed game
read the same in the library. The version label now stays. Echo VR and
other delisted games have no store details, which hid this.

"All versions" fetched the same store details and artwork once per version.
On a 31-version run Meta answered HTTP 429 and later versions got none.
They are now fetched for the first version and copied to the others.
The full build history also lists builds that are only on an alpha, beta
or other non-public channel. Sorted by version code, such a build could
become the newest entry, so a plain install, the owned list's Install
button and the picker's "latest" entry picked it: for Bigscreen Beta a
PCALPHA build, for SKYBOX VR Video Player a build only on a device
channel. Builds from Meta's supportedBinaries query are now marked as
offered, and the default is the newest of those, as on main. Newer
builds on other channels stay listed and installable when chosen.
Two ways a chosen version could land in a folder that holds another one:
- With nothing installed yet, the first chosen version took the plain
  game folder even when a paused download of another build was there,
  mixing the two builds' files.
- The version-code fallback name was never checked. Version "1.0" with
  build code 2 falls back to game-1-0-2, which is version 1.0.2's folder.
The plain folder is now used only when it is empty or holds this build,
and when the version-code name is taken as well, the build's binary ID
makes the folder name unique. Plain installs still update in place.
"All versions" called add() for every build, including the ones already
installed. add() writes a fresh library record, so those versions lost
their launch options, environment and DLL overrides, and each was checked
against Meta's CDN again; resuming a paused run did the same for every
version it had already finished. Builds that already have a library
record and folder are now skipped and returned as installed.
- An expired or revoked Meta sign-in made a delisted game's link read
  "game not found": the build list failed with an OAuthException, and the
  store page has no entry for it. It now asks to sign in again.
- A single build that downloaded but cannot launch said "Download failed.
  Check your connection and retry." The worker now reports it as such.
- When no version of "All versions" installed, the per-version reasons
  were dropped; they are shown whenever a version failed.

The French sign-in hint now uses "vous" like the rest of the dialog.
The link check and the version listing run in threads that report
through the dialog's event object. Quitting while one of them was still
waiting for Meta deleted that object, so emit raised "Signal source has
been deleted", the except branch emitted again, and the error escaped the
thread. Their results are now dropped when the dialog is gone, as the
library window's workers already do.
A failed version came back as its label and a kind only, because raw error
text can hold signed URLs or tokens. The worker now sends each one's reason
through describe_error, as a failed single install already does, so it no
longer has to be withheld. The notice stays a short list of versions; the
reasons go to the Activity log.
The Windows command line passed --build straight to add(), so
`riftlift add <app> --build all` stopped with "use add_all_versions to
download every build", and `riftlift builds` didn't exist there. Both now
work as on Linux. The build table and the every-version summary live next
to the code that produces them, so both command lines print the same.
The reasons only went to the library window's Activity log, and since the
0.11.1.2 sidebar nothing opens that log any more: a failed version showed
up as "download failed" and nothing else. The notice now gives each
version's reason, the way a failed single install shows its detail.
Versions that failed for the same reason share a line, so a run that lost
the network stays one line instead of thirty.
Resume runs the same button handler as Install, so a paused "All
versions" run asked "Download all 31 versions?" a second time, as if it
were starting over. While paused the link and the version can't change,
so resuming now continues without the question.
With a reason on every line, a run where 30 versions failed made the
notice 1052 px tall: the dialog reserves the whole text's height, so the
list ran under the OK button and its last versions were cut off. The
versions now go in a read-only box below the summary that scrolls past
twelve lines, and their reasons can be copied from it.
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.

1 participant