Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/delete-version.yml
Original file line number Diff line number Diff line change
Expand Up @@ -87,5 +87,5 @@ jobs:
- name: Purge jsDelivr cache for pointer
shell: bash
run: |
curl -s "https://purge.jsdelivr.net/gh/madoiscool/BetterSteamTools@updates/opensteamtool/latest.toml" \
curl -s "https://purge.jsdelivr.net/gh/${GITHUB_REPOSITORY}@updates/opensteamtool/latest.toml" \
>/dev/null || echo "jsDelivr purge failed (non-fatal)."
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ jobs:
run: |
try {
Invoke-WebRequest -UseBasicParsing `
"https://purge.jsdelivr.net/gh/madoiscool/BetterSteamTools@updates/opensteamtool/latest.toml" | Out-Null
"https://purge.jsdelivr.net/gh/${{ github.repository }}@updates/opensteamtool/latest.toml" | Out-Null
} catch { Write-Host "jsDelivr purge failed (non-fatal): $_" }

- name: Build Debug
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ The `extract_tickets` tool dumps the `AppTicket` and `ETicket` hex strings you n
- Uses `setStat(appid, "steamid")` to configure which SteamID's achievement data to pull.
- If no `setStat` is configured for an app, OpenSteamTool queries `https://stats.opensteamtool.com/{appid}` when `[stats] enable_api = true` (default).
- Priority: `setStat` > stats API when enabled and valid > hardcoded preset SteamID `76561198028121353`.
- With `[stats] local_only = true` (default), achievement unlocks for added games stay local: stores are journaled under `<Steam>/opensteamtool/stats/` and answered locally, so toasts and the library page work, CloudRedirect sync still runs, and nothing is written to your online profile. Set `local_only = false` to let stores reach Valve (unlocks will show on your profile).

### Online Fix
- Add `-onlinefix` to the Steam launch parameters to enable 480-based online play in games that use lobby matchmaking. The current limitation is that only one such game can run at a time.To revert, simply remove -onlinefix from the launch parameters — online play returns to normal on the next launch.
Expand Down
6 changes: 6 additions & 0 deletions opensteamtool.example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,12 @@ enabled = true
# SteamID when no Lua setStat(appid, "steamid") override exists.
# Priority: setStat > stats API when enabled and valid > hardcoded preset SteamID.
enable_api = true
# Keep achievement unlocks for Lua-unlocked games local: stat stores are
# journaled under <Steam>/opensteamtool/stats and answered locally (toast +
# library still work, CloudRedirect sync still runs) instead of reaching
# Valve, so nothing lands on the online profile. Set to false to let stores
# flow to Valve as your account (unlocks WILL show on your profile).
local_only = true

[update]
# Check for a newer BetterSteamTools build on startup. When a newer build is
Expand Down
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ add_library(OpenSteamTool SHARED
Utils/SteamMetadata/RemoteToml.cpp
Utils/SteamMetadata/StatsClient.cpp
Utils/SteamMetadata/SteamDiagnostics.cpp
Utils/Stats/LocalStats.cpp
Utils/Tokeer/TokeerBridge.cpp
Utils/Tokeer/TokeerUri.cpp
Utils/Update/AppUpdater.cpp
Expand Down
34 changes: 21 additions & 13 deletions src/Hook/Hooks_Manifest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,20 +187,28 @@ namespace {
const auto& overrides = LuaConfig::GetManifestOverrides();

// Apply manifest overrides in place (only depots a lua explicitly pins).
if (!overrides.empty() && pDepotInfo && pDepotInfo->m_Size) {
for (uint32 i = 0; i < pDepotInfo->m_Size; ++i) {
DepotEntry& e = pDepotInfo->m_Memory.m_pMemory[i];
auto it = overrides.find(e.DepotId);
if (it != overrides.end()) {
// if size=0 in the override, keep the original size(affects download display but not the actual download)
uint64_t newSize = it->second.size ? it->second.size : e.ManifestSize;
LOG_MANIFEST_INFO("BuildDepotDependency: patching depot {} gid={}->{} size={}->{}",
e.DepotId, e.ManifestGid, it->second.gid,
e.ManifestSize, newSize);
e.ManifestGid = it->second.gid;
e.ManifestSize = newSize;
// Both lists: a pinned depot can arrive via pSharedDepotInfo (shared
// installs), and preseeding below runs on both — patching only
// pDepotInfo left shared depots preseeding/requesting the wrong GID.
if (!overrides.empty()) {
auto patchVec = [&](CUtlVector<DepotEntry>* vec) {
if (!vec || !vec->m_Size) return;
for (uint32 i = 0; i < vec->m_Size; ++i) {
DepotEntry& e = vec->m_Memory.m_pMemory[i];
auto it = overrides.find(e.DepotId);
if (it != overrides.end()) {
// if size=0 in the override, keep the original size(affects download display but not the actual download)
uint64_t newSize = it->second.size ? it->second.size : e.ManifestSize;
LOG_MANIFEST_INFO("BuildDepotDependency: patching depot {} gid={}->{} size={}->{}",
e.DepotId, e.ManifestGid, it->second.gid,
e.ManifestSize, newSize);
e.ManifestGid = it->second.gid;
e.ManifestSize = newSize;
}
}
}
};
patchVec(pDepotInfo);
patchVec(pSharedDepotInfo);
}

// Pre-seed <steam>\depotcache SYNCHRONOUSLY for every depot OST is
Expand Down
Loading