Skip to content

Instantly share code, notes, and snippets.

@NadnerbD
Last active August 9, 2025 06:25
Show Gist options
  • Select an option

  • Save NadnerbD/193484b9ac1a0b9e622feed5c332da48 to your computer and use it in GitHub Desktop.

Select an option

Save NadnerbD/193484b9ac1a0b9e622feed5c332da48 to your computer and use it in GitHub Desktop.
from collections import OrderedDict
import re, json, sys, os
def parseObj(tokens):
if(type(tokens) == str):
tokens = re.split(r'[\t\r\n]+', tokens)
tokens.reverse()
obj = OrderedDict()
while len(tokens):
nt = tokens.pop()
if nt in ["}", ""]:
return obj
elif nt.startswith('"'):
nt = json.loads(nt)
val = tokens.pop()
if val.startswith('"'):
obj[nt] = json.loads(val)
elif val == "{":
obj[nt] = parseObj(tokens)
else:
raise Exception("nt = %r" % nt)
def dumpObj(obj, indent=0):
s = ""
for key in obj:
s += "\t" * indent + json.dumps(key)
if type(obj[key]) == OrderedDict:
s += "\n" + "\t" * indent + "{\n" + dumpObj(obj[key], indent + 1) + "\t" * indent + "}\n"
else:
s += "\t\t%s\n" % json.dumps(obj[key])
return s
with open(sys.argv[1], "r") as f:
manifestpath = os.path.dirname(f.name)
data = f.read()
manifest = parseObj(data)
print(dumpObj(manifest))
if "-username" in sys.argv:
username = sys.argv[sys.argv.index("-username") + 1]
appstate = manifest['AppState']
for depotkey in appstate['StagedDepots']:
cmd = \
"DepotDownloader.exe -app " + appstate['appid'] + \
" -depot " + depotkey + " -manifest " + appstate['StagedDepots'][depotkey]['manifest'] + \
" -username " + username + " -remember-password -dir \"" + \
manifestpath + "\\common\\" + appstate['installdir'] + "\" -validate"
print(cmd)
os.system(cmd)
installed_depot = appstate['StagedDepots'][depotkey]
del installed_depot['dlcappid']
appstate['InstalledDepots'][depotkey] = installed_depot
del appstate['StagedDepots'][depotkey]
appstate['StateFlags'] = "4"
appstate['UpdateResult'] = "0"
appstate['StagingSize'] = "0"
appstate['buildid'] = appstate['TargetBuildID']
appstate['BytesStaged'] = appstate['BytesToStage']
appstate['BytesDownloaded'] = appstate['BytesToDownload']
print(dumpObj(manifest))
with open(sys.argv[1], "w") as f:
f.write(dumpObj(manifest))
@metapea
Copy link

metapea commented Aug 8, 2025

@metapea Found the reason for that error XD This testing and adding onto things with almost no knowledge has been painfully fun lol The .acf file you feed to this script is intended to have been written by Steam, with details inside of what update it's trying (and failing) to install.

If your game is already updated, or if for any reason Steam has not filled out the StagedDepots details inside the game's .acf file while trying to update it, this script can't help you right now I think. You might wanna have Steam try to update the game, so it fills out the details in the game's .acf file with the details of the update first. Pretty sure that should have happened before it started trying to download or update anything tho idk whats up with that.

You can just open .acf files with your preferred text editor too, to make sure it's the right file/game and verify what's in there at what point.

It doesn't change at all before, in the middle of, or after a corrupt download update.
the .acf should say what it's downloading with "TargetBuildID", "InstalledDepots" or maybe "SharedDepots"

@outseeker-
Copy link

Oh, so you didn't need an answer for your question what is KeyError: 'StagedDepots'? cool :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment