85 lines
2.7 KiB
Python
85 lines
2.7 KiB
Python
#!/usr/bin/env python3
|
|
# ABOUT ME
|
|
# Locates Cosmoteer's installed Data folder by asking Steam where its libraries
|
|
# are.
|
|
#
|
|
# Why this exists: the mod tests validate against vanilla game data, and the
|
|
# game can be installed to any Steam library on any disk. A fixed list of
|
|
# guessed paths misses real installs, so this reads the library roots out of
|
|
# Steam's own libraryfolders.vdf and looks for the game under each one.
|
|
#
|
|
# install.sh carries the same logic in bash for finding the Mods folder.
|
|
|
|
import os
|
|
import re
|
|
|
|
COSMOTEER_APPID = 799600
|
|
|
|
# One "path" entry per library root; the app data sits in <path>/steamapps.
|
|
_LIBRARY_PATH_RE = re.compile(r'^\s*"path"\s*"(.*)"\s*$')
|
|
|
|
|
|
def steam_roots(home):
|
|
"""The Steam client directories, one per install flavour."""
|
|
return [
|
|
os.path.join(home, ".local/share/Steam"),
|
|
os.path.join(home, ".steam/steam"),
|
|
os.path.join(home, ".steam/root"),
|
|
os.path.join(home, ".var/app/com.valvesoftware.Steam/data/Steam"),
|
|
]
|
|
|
|
|
|
def steam_libraries(home):
|
|
"""Every Steam library root, in search order and without duplicates.
|
|
|
|
Steam's own roots come first so the default library stays searchable even
|
|
when libraryfolders.vdf is missing or unreadable.
|
|
"""
|
|
libraries = list(steam_roots(home))
|
|
for root in steam_roots(home):
|
|
vdf = os.path.join(root, "steamapps", "libraryfolders.vdf")
|
|
try:
|
|
with open(vdf, encoding="utf-8", errors="replace") as handle:
|
|
lines = handle.readlines()
|
|
except OSError:
|
|
continue
|
|
for line in lines:
|
|
match = _LIBRARY_PATH_RE.match(line)
|
|
if match:
|
|
libraries.append(match.group(1).replace("\\\\", "\\"))
|
|
|
|
seen = set()
|
|
unique = []
|
|
for library in libraries:
|
|
if library not in seen:
|
|
seen.add(library)
|
|
unique.append(library)
|
|
return unique
|
|
|
|
|
|
def find_data_dir(home=None, environ=None):
|
|
"""The Cosmoteer Data folder, or None when the game is not installed.
|
|
|
|
COSMOTEER_DATA overrides discovery so an unusual install can be pointed at
|
|
by hand.
|
|
"""
|
|
environ = os.environ if environ is None else environ
|
|
override = environ.get("COSMOTEER_DATA")
|
|
if override:
|
|
return override
|
|
|
|
home = os.path.expanduser("~") if home is None else home
|
|
for library in steam_libraries(home):
|
|
data = os.path.join(library, "steamapps", "common", "Cosmoteer", "Data")
|
|
if os.path.isdir(data):
|
|
return data
|
|
return None
|
|
|
|
|
|
def find_bin_dir(home=None, environ=None):
|
|
"""The Cosmoteer Bin folder, which sits beside Data."""
|
|
data = find_data_dir(home=home, environ=environ)
|
|
if not data:
|
|
return None
|
|
return os.path.join(os.path.dirname(data), "Bin")
|