-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsetup
executable file
·362 lines (316 loc) · 16.6 KB
/
setup
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
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
#!/usr/bin/env -S python3 -B
from tqdm import tqdm
from hashlib import md5
from os import system, unlink, symlink, makedirs, geteuid, getcwd, chmod, rename
from os.path import isfile, isdir
from time import time
from shutil import copyfile, rmtree
from glob import iglob
from pwd import getpwnam as getuser
from t2support import *
if geteuid() != 0:
bail(f"This script must be run with sudo or as root.\n")
pwd = getcwd()
installer_mirror_list = [
"https://www.the-construct.net/downloads/tribes2/tribes2gsi.exe",
"http://spinfusor.ch/tribes2/setup/tribes2_gsi.exe",
"https://adamantis.keybase.pub/Abandonware/Tribes2/tribes2gsi.exe?dl=1",
"http://xfer1.the-construct.net/tribes2/tribes2gsi.exe",
"http://dl.rawr32.net/tribes2gsi.exe",
"https://files.playt2.com/Install/tribes2gsi.exe",
"https://gamestand.net/dl/tribes-2/?ind=1527034109041&filename=tribes2_gsi.exe&wpdmdl=165&refresh=5fb884009d78b1605927936",
"http://www.tribes2stats.com/files/tribes2_gsi.exe"
]
tnpatch_mirror_list = [
"http://www.tribesnext.com/files/TribesNext_rc2a.exe",
"https://keybase.pub/adamantis/Abandonware/Tribes2/TribesNext_rc2a.exe",
"https://files.playt2.com/Install/TribesNext_rc2a.exe",
"https://gamestand.net/dl/tribes-2/?ind=1527034087554&filename=TribesNext_rc2a.exe&wpdmdl=165&refresh=5fb884009d73d1605927936",
"http://www.tribes2stats.com/files/patches/TribesNext_rc2a.exe",
"http://files.nastyhobbit.org/t2-installer/TribesNext_rc2a.exe",
"http://www.the-flet.com/dynamix/t2/TribesNext_rc2a.exe",
"http://cdn.net-load.com/TribesNext_rc2a.exe",
"https://starsiege.pw/_tribes2/TribesNext_rc2a.exe"
]
installer_checksum = "93460541ddd3bdff9b30829ba04f2186"
tnpatch_checksum = "3bec757215cd29b37d85b567edf8d693"
def md5sum(filename):
""" Return the md5 checksum of the given file """
with open(filename, "rb") as file:
file_hash = md5()
chunk = file.read(8192)
while chunk:
file_hash.update(chunk)
chunk = file.read(8192)
return file_hash.hexdigest()
def download_file(url, filename):
""" Download url with progress meter and save to filename """
req = get(url, stream=True)
with open(filename, 'wb') as outfile:
pbar = tqdm(total=int(req.headers['Content-Length']), unit="B", unit_scale=True, unit_divisor=1024, position=0, desc=filename.split("/")[-1])
for chunk in req.iter_content(chunk_size=1024*1024):
if chunk:
pbar.update(len(chunk))
outfile.write(chunk)
pbar.close()
return filename
def version_compare(installed_version, package_version):
if installed_version == package_version: return 0
installed = installed_version.split(".")
packaged = package_version.split(".")
if installed[0] < packaged[0]:
return 1
elif installed[0] > packaged[0]:
return -1
if installed[1] < packaged[1]:
return 1
elif installed[1] > packaged[1]:
return -1
if installed[2] < packaged[2]:
return 1
elif installed[2] > packaged[2]:
return -1
if __name__ == "__main__":
# Check for an existing install. Read version from the release file if it exists, otherwise assume 0.7.3
if isfile(release_file):
with open(release_file, 'r') as rf:
installed_version = rf.read().rstrip()
elif isfile(f"{install_dir}/GameData/Tribes2.exe"):
installed_version = "0.7.3"
else:
installed_version = None
# Get the version in this install package
if isfile(f"{pwd}/etc/t2server/release"):
with open(f"{pwd}/etc/t2server/release", 'r') as rf:
package_version = rf.read().rstrip()
else:
package_version = None
# Compare versions to see if the install package is newer than the installed version and quit if not
if installed_version and package_version: upgrade = version_compare(installed_version, package_version)
else: upgrade = None
# Exit if trying to update to an older version or the same version, otherwise display the initial menu and determine the setup mode
if upgrade == -1:
bail(f"This would install t2server {package_version} which is older than what's already installed, version {installed_version}.")
elif upgrade == 0:
bail(f"The existing t2server install is the same version as this install package, {package_version}.")
elif upgrade == 1:
setup_mode=menu([f"[U]pgrade to {package_version}","[Q]uit"],header=f"An existing t2server {installed_version} install was detected. 'Upgrade' will only update the scripts and files that come with t2server and won't reinstall Tribes 2.")
if setup_mode == "Q": bail()
else:
action=menu(["~~[C]ontinue","[Q]uit"],header="This script will install Tribes 2 for use as a dedicated server.")
if action == "Q": bail()
setup_mode="I"
if setup_mode == "R":
system(f"{pwd}/usr/local/bin/t2remove -Y")
# Check if user exists
try:
user_info = getuser(user)
except KeyError:
user_info = False
if setup_mode == "I" or setup_mode == "R":
# Create or repurpose user if installing or reinstalling
if user_info:
if user_info.pw_dir == install_dir:
pwarn(f"User '{user}' exists and will be reused.")
else:
bail(f"ERROR: User '{user}' already exists and may belong to another person or process.")
else:
print(f"Creating {user} user and {install_dir}.")
system(f"useradd -md {install_dir} {user}")
if not user_info: user_info = getuser(user)
# Create log_dir
print(f"Creating {log_dir}.")
makedirs(log_dir, mode=0o777, exist_ok=True)
chmod(log_dir, 0o777)
# Create .wine dir
print(f"Creating {install_dir}/.wine defaults.")
system(f"su - {user} -c'wineboot -i > /dev/null 2>&1'")
# Map wine I: drive to pwd T: drive to install_dir and L: to log_dir
print(f"Mapping I: in wine for {user}.")
try:
symlink(f"{pwd}/winbin", f"{install_dir}/.wine/dosdevices/i:")
except FileExistsError:
pass
print(f"Mapping L: in wine for {user}.")
try:
symlink(log_dir, f"{install_dir}/.wine/dosdevices/l:")
except FileExistsError:
pass
print(f"Mapping T: in wine for {user}.")
try:
symlink(install_parent, f"{install_dir}/.wine/dosdevices/t:")
except FileExistsError:
pass
# Check for needed exe/zip/dll files in winbin dir
needed_files=[]
if isfile(f"{pwd}/winbin/tribes2gsi.exe"):
pinfo("tribes2gsi.exe found.")
rename(f"{pwd}/winbin/tribes2gsi.exe",f"{pwd}/winbin/tribes2_gsi.exe")
installer_exe = f"{pwd}/winbin/tribes2_gsi.exe"
elif isfile(f"{pwd}/winbin/tribes2_gsi.exe"):
pinfo("tribes2_gsi.exe found.")
installer_exe = f"{pwd}/winbin/tribes2_gsi.exe"
else:
pwarn("Tribes 2 installer not found.")
needed_files.append("tribes2_gsi.exe")
installer_exe = False
if isfile(f"{pwd}/winbin/TribesNext_rc2a.exe"):
pinfo("TribesNext_rc2a.exe found.")
tnpatch_exe = f"{pwd}/winbin/TribesNext_rc2a.exe"
else:
pwarn("Tribes Next patch not found.")
needed_files.append("TribesNext_rc2a.exe")
tnpatch_exe = False
ruby_dll = f"{pwd}/winbin/msvcrt-ruby191.dll"
instwrap_exe = f"{pwd}/winbin/install_wrapper.exe"
# Download files if needed
if not installer_exe or not tnpatch_exe:
action=menu(["~~[D]ownload automatically","[Q]uit"],header="One or more needed files were not found. Download automatically or quit so they can be manually placed in the 'winbin' subdirectory?")
if needed_files == 2:
needed_files=f"{needed_files[0]} and {needed_files[1]}"
if action=="Q": bail(f"Manually place {needed_files} in the 'winbin' subdirectory then rerun setup.")
if not installer_exe:
for url in installer_mirror_list:
try:
pinfo(f"\nDownloading from {url.split('/')[2]}...")
installer_exe = download_file(url, f"{pwd}/winbin/tribes2_gsi.exe")
if md5sum(installer_exe) == installer_checksum:
print("Checksum validation passed.")
break
else:
perror("Checksum validation failed. Trying next mirror.")
except KeyError:
perror("Download error. Trying next mirror.")
continue
if not installer_exe:
bail("ERROR: Tribes 2 installer could not be downloaded.")
if not tnpatch_exe:
for url in tnpatch_mirror_list:
try:
pinfo(f"\nDownloading from {url.split('/')[2]}...")
tnpatch_exe = download_file(url, f"{pwd}/winbin/TribesNext_rc2a.exe")
if md5sum(tnpatch_exe) == tnpatch_checksum:
print("Checksum validation passed.")
break
else:
perror("Checksum validation failed. Trying next mirror." )
except KeyError:
perror("Download error. Trying next mirror.")
continue
if not tnpatch_exe:
bail("ERROR: Tribes Next patch could not be downloaded.")
# Present SLAs before beginning install
sla = None
while not sla:
sla=menu(["[V]iew Tribes 2 and TribesNext License Agreements", "[A]ccept License Agreements", "[Q]uit"], header="Please take a moment to review and accept the Tribes 2 and TribeNext License Agreements before beginning automated install.")
if sla == "V":
print(color.DY)
system(f"/usr/bin/less {pwd}/sla/tribes2.txt")
print(color.DP)
system(f"/usr/bin/less {pwd}/sla/tribesnext.txt")
sla = None
elif sla == "A":
break
elif sla == "Q":
bail("You must accept the License Agreements to install.")
# Ensure sufficient permissions on winbin and its contents
chmod(f"{pwd}/winbin", 0o777)
chmod(installer_exe, 0o777)
chmod(tnpatch_exe, 0o777)
chmod(instwrap_exe, 0o777)
chmod(ruby_dll, 0o777)
# Execute install wrapper
pinfo(f"\nInstalling Tribes 2 and the TribesNext patch in wine. Please wait...")
chowner(install_dir, user)
system(f"su - {user} -c'xvfb-run -as " + '"-fbdir /var/tmp"' + " wine I:/install_wrapper.exe > /dev/null 2>&1'")
# Rudamentary check to see if T2 install succeeded
if not isfile(f"{install_dir}/Tribes 2 Solo & LAN.lnk"): bail(f"ERROR: Tribes 2 installation appears to have failed. Check {log_dir}/install_wrapper.log")
# Rudamentary check to see if TN install succeeded
if not isfile(f"{install_dir}/GameData/TN_Uninstall.exe"): bail(f"ERROR: Tribes Next installation appears to have failed. Check {log_dir}/install_wrapper.log")
# Replace msvcrt-ruby190.dll with msvcrt-ruby191.dll
print("Updating msvcrt-ruby190.dll to msvcrt-ruby191.dll.\n")
copyfile(ruby_dll,f"{install_dir}/GameData/msvcrt-ruby191.dll")
unlink(f"{install_dir}/GameData/msvcrt-ruby190.dll")
symlink(f"{install_dir}/GameData/msvcrt-ruby191.dll", f"{install_dir}/GameData/msvcrt-ruby190.dll")
# Install addons
for addon in iglob(f"{pwd}/addons/*"):
if addon.endswith(".zip"):
pinfo(f"Unpacking {addon} into {install_dir}/GameData.")
system(f"unzip -qqd {install_dir}/GameData {addon}")
elif addon.endswith((".tar",".tgz",".tar.gz",".txz",".tar.xz",".tbz",".tar.bz")):
pinfo(f"Unpacking {addon} into {install_dir}/GameData.")
system(f"tar -C {install_dir}/GameData -xf {addon}")
elif addon.endswith(".vl2"):
pinfo(f"Copying {addon} to {install_dir}/GameData/base.")
copyfile(addon,f"{install_dir}/GameData/base/{addon.split('/')[-1]}")
elif addon.endswith("readme.txt"):
pass
else:
pwarn(f"Ignoring {addon}.")
# Copy t2server and t2bouncer to /usr/local/bin/
if setup_mode == "U": print("Updating t2server script.")
else: print("Installing t2server script.")
copyfile(f"{pwd}/usr/local/bin/t2server",f"{bin_dir}/t2server")
if setup_mode == "U": print("Updating t2bouncer script.")
else: print("Installing t2bouncer script.")
copyfile(f"{pwd}/usr/local/bin/t2bouncer",f"{bin_dir}/t2bouncer")
# Set owner/group on install_dir
chowner(install_dir, user)
if setup_mode == "I" or setup_mode == "R":
# Clean up temp dir and some unneeded files
print("A little housekeeping...")
if isfile(f"{install_dir}/Tribes 2 Online.lnk"): unlink(f"{install_dir}/Tribes 2 Online.lnk")
if isfile(f"{install_dir}/Tribes 2 Solo & LAN.lnk"): unlink(f"{install_dir}/Tribes 2 Solo & LAN.lnk")
if isfile(f"{install_dir}/UNWISE.EXE"): unlink(f"{install_dir}/UNWISE.EXE")
if isfile(f"{install_dir}/Readme.txt"): unlink(f"{install_dir}/Readme.txt")
if isfile(f"{install_dir}/GameData/Classic_LAN.bat"): unlink(f"{install_dir}/GameData/Classic_LAN.bat")
if isfile(f"{install_dir}/GameData/Classic_dedicated_server.bat"): unlink(f"{install_dir}/GameData/Classic_dedicated_server.bat")
if isfile(f"{install_dir}/GameData/Classic_online.bat"): unlink(f"{install_dir}/GameData/Classic_online.bat")
if isfile(f"{install_dir}/GameData/base/EULA.txt"): unlink(f"{install_dir}/GameData/base/EULA.txt")
if isfile(f"{install_dir}/GameData/base/UKEULA.txt"): unlink(f"{install_dir}/GameData/base/UKEULA.txt")
if isdir(f"{install_dir}/Manual"): rmtree(f"{install_dir}/Manual")
if isdir(f"{install_dir}/.wine/drive_c/users/t2server/Temp"): rmtree(f"{install_dir}/.wine/drive_c/users/t2server/Temp")
if isfile(f"{install_dir}/t2csri_eula.txt"): unlink(f"{install_dir}/t2csri_eula.txt")
if isfile(f"{install_dir}/Inside\ Team\ Rabbit\ 2.txt"): unlink(f"{install_dir}/Inside\ Team\ Rabbit\ 2.txt")
if isfile(f"{install_dir}/UpdatePatch.txt"): unlink(f"{install_dir}/UpdatePatch.txt")
if isfile(f"{install_dir}/Classic/Classic_readme.txt"): unlink(f"{install_dir}/Classic/Classic_readme.txt")
if isfile(f"{install_dir}/Classic_technical.txt"): unlink(f"{install_dir}/Classic_technical.txt")
# Create config directory and files
print(f"\nCreating {etc_dir}, default config, and installing prefs files.")
makedirs(f"{etc_dir}/serverprefs", mode=0o775, exist_ok=True)
if isfile(f"{etc_dir}/config.yaml"):
timestamp = int(time())
rename(f"{etc_dir}/config.yaml",f"{etc_dir}/config.yaml.{timestamp}")
pwarn(f"Existing {etc_dir}/config.yaml renamed to {etc_dir}/config.yaml.{timestamp}. Be sure to compare with and update the new config.yaml file.")
print(f"Writing default {etc_dir}/config.yaml.")
copyfile(f"{pwd}/etc/t2server/config.yaml", f"{etc_dir}/config.yaml")
print(f"Writing {etc_dir}/release")
copyfile(f"{pwd}/etc/t2server/release", f"{etc_dir}/release")
for pfile in iglob(f"{pwd}/etc/t2server/serverprefs/*"):
pinfo(f"Copying {pfile} to {etc_dir}/serverprefs.")
copyfile(pfile,f"{etc_dir}/serverprefs/{pfile.split('/')[-1]}")
# Create systemd units
print("\nCreating systemd units:")
print("- t2server service")
copyfile(f"{pwd}/etc/systemd/system/t2server.service",f"{unit_dir}/t2server.service")
print("- t2bouncer service")
copyfile(f"{pwd}/etc/systemd/system/t2bouncer.service",f"{unit_dir}/t2bouncer.service")
print("- t2bouncer timer")
copyfile(f"{pwd}/etc/systemd/system/t2bouncer.timer",f"{unit_dir}/t2bouncer.timer")
system("systemctl daemon-reload")
# Install utility scripts
print("\nInstalling utilities:")
print("- t2bouncer")
copyfile(f"{pwd}/usr/local/bin/t2fixer",f"{bin_dir}/t2fixer")
print("- t2remove")
copyfile(f"{pwd}/usr/local/bin/t2remove",f"{bin_dir}/t2remove")
print("- t2help")
copyfile(f"{pwd}/usr/local/bin/t2help",f"{bin_dir}/t2help")
# Install python module
copyfile(f"{pwd}/usr/local/bin/t2support.py",f"{bin_dir}/t2support.py")
chmod(f"{bin_dir}/t2fixer",0o777)
system(f"{bin_dir}/t2fixer")
# Show help
system(f"{bin_dir}/t2help")
pinfo("You can run 't2help' at any time to view the info above again.")
print(f"{color.X}\n")