Files
climperor/gsi_setup.py
T
vosonandCursor f32d24b8f8 Initial commit: 上分帝(Climperor)
从 dota2-draft-vision 迁出并定名,作为天梯选将识别项目起点。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-26 11:47:39 +08:00

143 lines
4.0 KiB
Python

"""Install the Game State Integration config that lets Dota 2 talk to gsi_watch.py.
Usage:
python gsi_setup.py # auto-detect Dota 2 and write the cfg
python gsi_setup.py --path "D:\\Steam\\steamapps\\common\\dota 2 beta"
python gsi_setup.py --remove # uninstall the cfg
python gsi_setup.py --check # only report where things are
After installing, add -gamestateintegration to Dota 2's launch options
(Steam library -> right-click Dota 2 -> Properties) and restart the game.
"""
import re
import sys
from pathlib import Path
from common import load_config
CFG_NAME = "gamestate_integration_climperor.cfg"
CFG_TEMPLATE = """"Climperor"
{{
"uri" "http://127.0.0.1:{port}/"
"timeout" "5.0"
"buffer" "0.1"
"throttle" "0.5"
"heartbeat" "30.0"
"data"
{{
"provider" "1"
"map" "1"
"player" "1"
"hero" "1"
}}
}}
"""
FALLBACK_ROOTS = [
r"C:\Program Files (x86)\Steam",
r"C:\Steam",
r"D:\Steam",
r"D:\SteamLibrary",
r"E:\SteamLibrary",
]
def steam_roots() -> list[Path]:
"""Candidate Steam library roots, from the registry plus libraryfolders.vdf."""
roots: list[Path] = []
try:
import winreg
with winreg.OpenKey(winreg.HKEY_CURRENT_USER, r"Software\Valve\Steam") as key:
roots.append(Path(winreg.QueryValueEx(key, "SteamPath")[0]))
except Exception: # noqa: BLE001 - registry is best-effort
pass
roots += [Path(p) for p in FALLBACK_ROOTS]
# libraryfolders.vdf lists every additional install drive
for root in list(roots):
vdf = root / "steamapps" / "libraryfolders.vdf"
if not vdf.is_file():
continue
try:
text = vdf.read_text(encoding="utf-8", errors="ignore")
except OSError:
continue
for match in re.finditer(r'"path"\s+"([^"]+)"', text):
roots.append(Path(match.group(1).replace("\\\\", "\\")))
seen: set[str] = set()
unique: list[Path] = []
for r in roots:
k = str(r).lower()
if k not in seen:
seen.add(k)
unique.append(r)
return unique
def find_dota() -> Path | None:
"""Locate the 'dota 2 beta' install directory."""
for root in steam_roots():
candidate = root / "steamapps" / "common" / "dota 2 beta"
if (candidate / "game" / "dota").is_dir():
return candidate
return None
def gsi_dir(dota: Path) -> Path:
return dota / "game" / "dota" / "cfg" / "gamestate_integration"
def main() -> None:
args = sys.argv[1:]
if "--path" in args:
dota = Path(args[args.index("--path") + 1])
if not (dota / "game" / "dota").is_dir():
sys.exit(f"not a Dota 2 install directory: {dota}")
else:
dota = find_dota()
if dota is None:
sys.exit(
"could not find Dota 2 automatically.\n"
"Pass it explicitly, e.g.:\n"
' python gsi_setup.py --path "D:\\Steam\\steamapps\\common\\dota 2 beta"'
)
target = gsi_dir(dota) / CFG_NAME
print(f"dota 2 : {dota}")
print(f"gsi cfg : {target}")
if "--check" in args:
print(f"installed: {target.is_file()}")
return
if "--remove" in args:
if target.is_file():
target.unlink()
print("removed.")
else:
print("nothing to remove.")
return
port = load_config().get("gsi", {}).get("port", 3223)
target.parent.mkdir(parents=True, exist_ok=True)
target.write_text(CFG_TEMPLATE.format(port=port), encoding="utf-8")
print(f"installed, endpoint http://127.0.0.1:{port}/")
print()
print("Next steps:")
print(" 1. Steam library -> Dota 2 -> Properties -> Launch Options:")
print(" add -gamestateintegration")
print(" 2. Restart Dota 2.")
print(" 3. Run python gsi_watch.py")
if __name__ == "__main__":
main()