forked from ArchipelagoMW/Archipelago
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathclient_setup.py
164 lines (145 loc) · 7.05 KB
/
client_setup.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
import io
import logging
import os.path
import subprocess
import urllib.request
from shutil import which
from tkinter.messagebox import askyesnocancel
from typing import Any, Optional
from zipfile import ZipFile
from Utils import open_file
import requests
from Utils import is_windows, messagebox, tuplize_version
MOD_URL = "https://api.github.com/repos/alwaysintreble/TheMessengerRandomizerModAP/releases/latest"
def launch_game(url: Optional[str] = None) -> None:
"""Check the game installation, then launch it"""
def courier_installed() -> bool:
"""Check if Courier is installed"""
return os.path.exists(os.path.join(game_folder, "TheMessenger_Data", "Managed", "Assembly-CSharp.Courier.mm.dll"))
def mod_installed() -> bool:
"""Check if the mod is installed"""
return os.path.exists(os.path.join(game_folder, "Mods", "TheMessengerRandomizerAP", "courier.toml"))
def request_data(request_url: str) -> Any:
"""Fetches json response from given url"""
logging.info(f"requesting {request_url}")
response = requests.get(request_url)
if response.status_code == 200: # success
try:
data = response.json()
except requests.exceptions.JSONDecodeError:
raise RuntimeError(f"Unable to fetch data. (status code {response.status_code})")
else:
raise RuntimeError(f"Unable to fetch data. (status code {response.status_code})")
return data
def install_courier() -> None:
"""Installs latest version of Courier"""
# can't use latest since courier uses pre-release tags
courier_url = "https://api.github.com/repos/Brokemia/Courier/releases"
latest_download = request_data(courier_url)[0]["assets"][-1]["browser_download_url"]
with urllib.request.urlopen(latest_download) as download:
with ZipFile(io.BytesIO(download.read()), "r") as zf:
for member in zf.infolist():
zf.extract(member, path=game_folder)
os.chdir(game_folder)
# linux and mac handling
if not is_windows:
mono_exe = which("mono")
if not mono_exe:
# steam deck support but doesn't currently work
messagebox("Failure", "Failed to install Courier", True)
raise RuntimeError("Failed to install Courier")
# # download and use mono kickstart
# # this allows steam deck support
# mono_kick_url = "https://github.com/flibitijibibo/MonoKickstart/archive/refs/heads/master.zip"
# target = os.path.join(folder, "monoKickstart")
# os.makedirs(target, exist_ok=True)
# with urllib.request.urlopen(mono_kick_url) as download:
# with ZipFile(io.BytesIO(download.read()), "r") as zf:
# for member in zf.infolist():
# zf.extract(member, path=target)
# installer = subprocess.Popen([os.path.join(target, "precompiled"),
# os.path.join(folder, "MiniInstaller.exe")], shell=False)
# os.remove(target)
else:
installer = subprocess.Popen([mono_exe, os.path.join(game_folder, "MiniInstaller.exe")], shell=False)
else:
installer = subprocess.Popen(os.path.join(game_folder, "MiniInstaller.exe"), shell=False)
failure = installer.wait()
if failure:
messagebox("Failure", "Failed to install Courier", True)
os.chdir(working_directory)
raise RuntimeError("Failed to install Courier")
os.chdir(working_directory)
if courier_installed():
messagebox("Success!", "Courier successfully installed!")
return
messagebox("Failure", "Failed to install Courier", True)
raise RuntimeError("Failed to install Courier")
def install_mod() -> None:
"""Installs latest version of the mod"""
assets = request_data(MOD_URL)["assets"]
if len(assets) == 1:
release_url = assets[0]["browser_download_url"]
else:
for asset in assets:
if "TheMessengerRandomizerAP" in asset["name"]:
release_url = asset["browser_download_url"]
break
else:
messagebox("Failure", "Failed to find latest mod download", True)
raise RuntimeError("Failed to install Mod")
mod_folder = os.path.join(game_folder, "Mods")
os.makedirs(mod_folder, exist_ok=True)
with urllib.request.urlopen(release_url) as download:
with ZipFile(io.BytesIO(download.read()), "r") as zf:
for member in zf.infolist():
zf.extract(member, path=mod_folder)
messagebox("Success!", "Latest mod successfully installed!")
def available_mod_update(latest_version: str) -> bool:
"""Check if there's an available update"""
latest_version = latest_version.lstrip("v")
toml_path = os.path.join(game_folder, "Mods", "TheMessengerRandomizerAP", "courier.toml")
with open(toml_path, "r") as f:
installed_version = f.read().splitlines()[1].strip("version = \"")
logging.info(f"Installed version: {installed_version}. Latest version: {latest_version}")
# one of the alpha builds
return "alpha" in latest_version or tuplize_version(latest_version) > tuplize_version(installed_version)
from . import MessengerWorld
game_folder = os.path.dirname(MessengerWorld.settings.game_path)
working_directory = os.getcwd()
if not courier_installed():
should_install = askyesnocancel("Install Courier",
"No Courier installation detected. Would you like to install now?")
if not should_install:
return
logging.info("Installing Courier")
install_courier()
if not mod_installed():
should_install = askyesnocancel("Install Mod",
"No randomizer mod detected. Would you like to install now?")
if not should_install:
return
logging.info("Installing Mod")
install_mod()
else:
latest = request_data(MOD_URL)["tag_name"]
if available_mod_update(latest):
should_update = askyesnocancel("Update Mod",
f"New mod version detected. Would you like to update to {latest} now?")
if should_update:
logging.info("Updating mod")
install_mod()
elif should_update is None:
return
if not is_windows:
if url:
open_file(f"steam://rungameid/764790//{url}/")
else:
open_file("steam://rungameid/764790")
else:
os.chdir(game_folder)
if url:
subprocess.Popen([MessengerWorld.settings.game_path, str(url)])
else:
subprocess.Popen(MessengerWorld.settings.game_path)
os.chdir(working_directory)