1 Commits
Author SHA1 Message Date
DawnsorrowandCursor 69ee41dc91 Document Seamless .co2 paths and fix process-name false positives.
Record Jorg desk compatdata locations for satellite setup; devices list terra; tighten watchers so syncgames argv is not mistaken for Eden.

Co-authored-by: Cursor <[email protected]>
2026-07-15 16:01:59 -05:00
10 changed files with 91 additions and 19 deletions
+1
View File
@@ -61,6 +61,7 @@ syncgames doctor
| [docs/protocol.md](docs/protocol.md) | Shared SSOT protocol (Python ↔ Android) |
| [docs/nas-minio-cloudflare.md](docs/nas-minio-cloudflare.md) | MinIO + NGINX + Cloudflare |
| [docs/add-game.md](docs/add-game.md) | Add / remove games |
| [docs/seamless-save-paths.md](docs/seamless-save-paths.md) | Seamless Coop `.co2` locations (per-device) |
| [docs/fallback-path1.md](docs/fallback-path1.md) | Syncthing fallback |
| [docs/planning/](docs/planning/) | Planning archive |
+11 -7
View File
@@ -1,6 +1,7 @@
from __future__ import annotations
import time
from pathlib import Path
from typing import Callable
from syncgames.config import GameConfig
@@ -26,19 +27,22 @@ def is_game_running(game: GameConfig) -> bool:
pname = _norm(proc.info["name"] or "")
if names and pname in names:
return True
if names and any(pname == _norm(n) for n in names):
return True
cmd = proc.info.get("cmdline") or []
# Match executable basenames only — never substring-search the full
# cmdline (e.g. `syncgames end eden-saves` must not look like Eden).
for part in cmd[:2]:
if not part:
continue
if _norm(Path(part).name) in names:
return True
if appid:
joined = " ".join(cmd).lower()
if appid and (
if (
f"appid={appid}" in joined
or f"steam_appid={appid}" in joined
or f"AppId={appid}" in joined
or f"appid={appid}" in joined
):
return True
for n in game.process_names:
if n.lower() in joined:
return True
except (psutil.Error, TypeError):
continue
return False
+2 -1
View File
@@ -1,6 +1,7 @@
# Copy to ~/.config/syncgames/agent.toml or SyncGames/config/agent.toml
device_id = "pc-desk"
# Unique per machine (this desktop = Jorg, laptop = terra, …)
device_id = "Jorg"
store = "minio" # or "filesystem" for Path 1 fallback
# WAN HTTPS via Cloudflare → NGINX → MinIO (path-style)
+3 -2
View File
@@ -1,12 +1,13 @@
# Registry of known devices (documentation / optional tooling)
# Each machine sets its own device_id in ~/.config/syncgames/agent.toml
[[devices]]
id = "pc-desk"
id = "Jorg"
os = "linux"
role = "desktop"
[[devices]]
id = "laptop"
id = "terra"
os = "linux"
role = "laptop"
+3
View File
@@ -2,6 +2,9 @@ id = "dark-souls-2-sotfs"
name = "Dark Souls II Scholar of the First Sin (Seamless Coop)"
platform = "steam"
versions_to_keep = 5
# Seamless Coop uses a separate extension (.co2). Non-Steam launches use a
# random compatdata id — verify on each device:
# find ~/.steam/steam/steamapps/compatdata -iname '*.co2' | grep -i DarkSoulsII
paths = [
"~/.steam/steam/steamapps/compatdata/335300/pfx/drive_c/users/steamuser/Application Data/DarkSoulsII",
]
+5 -1
View File
@@ -2,8 +2,12 @@ id = "dark-souls-3"
name = "Dark Souls III (Seamless Coop)"
platform = "steam"
versions_to_keep = 5
# Seamless Coop save extension = .co2. Non-Steam / me3 shortcut prefix — NOT
# vanilla 374320. Find with:
# find ~/.steam/steam/steamapps/compatdata -name 'DS30000.co2'
# Note: Roaming\DarkSoulsIII (not Application Data) under Proton for this install.
paths = [
"~/.steam/steam/steamapps/compatdata/374320/pfx/drive_c/users/steamuser/Application Data/DarkSoulsIII",
"~/.steam/steam/steamapps/compatdata/2678480877/pfx/drive_c/users/steamuser/AppData/Roaming/DarkSoulsIII/0110000103f10730",
]
steam_appid = 374320
process_names = [
+3 -1
View File
@@ -2,7 +2,9 @@ id = "dark-souls-remastered"
name = "Dark Souls Remastered (Seamless Coop)"
platform = "steam"
versions_to_keep = 5
# Adjust USERNAME / Steam library path on each device after install.
# Seamless Coop .co2 lives under a non-Steam compatdata prefix when launched via
# me3 / shortcut. Find per device:
# find ~/.steam/steam/steamapps/compatdata -iname '*.co2' | grep -i 'DARK SOULS\|NBGI'
paths = [
"~/.steam/steam/steamapps/compatdata/570940/pfx/drive_c/users/steamuser/Documents/NBGI/DARK SOULS REMASTERED",
]
+6 -3
View File
@@ -2,11 +2,14 @@ id = "elden-ring-seamless"
name = "Elden Ring (Seamless Coop)"
platform = "steam"
versions_to_keep = 5
# Seamless Coop writes alongside vanilla saves under EldenRing/<SteamID>/
# Point at the SeamlessCoop subdirectory once present, or the parent character folder.
# Seamless Coop uses .co2 (not vanilla .sl2). Non-Steam / me3 launches create a
# NEW compatdata id — NOT vanilla 1245620. Find with:
# find ~/.steam/steam/steamapps/compatdata -name 'ER0000.co2'
# Sync the SteamID folder that contains ER0000.co2 (per-device path).
paths = [
"~/.steam/steam/steamapps/compatdata/1245620/pfx/drive_c/users/steamuser/AppData/Roaming/EldenRing",
"~/.steam/steam/steamapps/compatdata/3917582188/pfx/drive_c/users/steamuser/AppData/Roaming/EldenRing/76561198026393392",
]
# Vanilla appid kept for reference; watcher mainly uses process names.
steam_appid = 1245620
process_names = [
"eldenring.exe",
+12
View File
@@ -20,6 +20,18 @@ Effects:
Multiple `--paths` allowed. Globs are expanded at session time.
### Seamless Coop (Souls / Elden Ring)
Modded saves use **`.co2`**, not vanilla `.sl2`. Non-Steam / me3 launchers create a **new** Proton `compatdata/<id>` — not the vanilla Steam AppID folder.
See **[seamless-save-paths.md](seamless-save-paths.md)** for discovery steps and known Jorg desktop paths (reference for satellites — always re-find on each device).
```bash
find ~/.steam/steam/steamapps/compatdata -name '*.co2'
```
Point `paths` at the directory that contains the `.co2` (per machine — the compatdata id can differ on `terra` vs `Jorg`). SteamID subfolders usually match across devices on the same Steam account.
### Platforms
| Value | Meaning |
+41
View File
@@ -0,0 +1,41 @@
# Seamless Coop save locations
Seamless Coop does **not** use the vanilla Steam save slot as the live character file. It uses a separate extension (usually **`.co2`**) so co-op progress cannot corrupt `.sl2`.
When the game is launched via **me3**, a **non-Steam Steam shortcut**, or a copied Proton prefix, Steam creates a **new** `compatdata/<random_id>/`**not** the vanilla AppID (`1245620`, `374320`, …).
## Discover on any device
```bash
find ~/.steam/steam/steamapps/compatdata ~/.local/share/Steam/steamapps/compatdata \
-type f -name '*.co2' 2>/dev/null
```
Point SyncGames `paths` at the **directory that contains** the `.co2` (the SteamID / account subfolder). Do this **per device** — the numeric `compatdata` id often differs between `Jorg` and `terra` even for the same mod launch method. The SteamID folder name is usually stable on one Steam account.
## Known locations (Jorg desktop — reference only)
| Game id | Compatible discovery | Path used on Jorg |
|---------|----------------------|-------------------|
| `elden-ring-seamless` | `ER0000.co2` | `~/.steam/steam/steamapps/compatdata/3917582188/pfx/drive_c/users/steamuser/AppData/Roaming/EldenRing/76561198026393392` |
| `dark-souls-3` | `DS30000.co2` | `~/.steam/steam/steamapps/compatdata/2678480877/pfx/drive_c/users/steamuser/AppData/Roaming/DarkSoulsIII/0110000103f10730` |
| `dark-souls-2-sotfs` | *(no `.co2` on Jorg yet)* | Still template vanilla path — replace after first Seamless launch |
| `dark-souls-remastered` | *(no `.co2` on Jorg yet)* | Still template vanilla path — replace after first Seamless launch |
Older / alternate prefixes may hold conversion leftovers (e.g. `ER0000.cnv.co2` under `3182145933` on Jorg). Prefer the newest live `.co2`, not `.cnv.co2`, unless you intentionally migrate.
## Satellite checklist (`terra`, …)
1. Install AppImage; Setup → same MinIO keys; **`device_id = "terra"`** (or that machines id).
2. Seed/add games; run the `find … '*.co2'` command above.
3. Edit each games path to **this** machines directory (GUI Load → Save, or `syncgames edit`).
4. **Start** → pulls SSOT into the local Seamless folder → play → **End**.
Optional automation after paths are correct:
```bash
./systemd/install-user-units.sh
# ensure syncgames is on PATH, e.g. symlink AppImage CLI or pip install -e
systemctl --user enable --now [email protected]
systemctl --user enable --now [email protected]
```