import argparse from logging import exception import os import requests import subprocess import zipfile # Download / extract SteamCMD # Download game server # Download workshop - config for this # Move workshop files to game server folder # Can MAS2 etc be scripted? # Also need to deal with keys # Run server with some basic content (have default car / track to download) # Once the server closes, ServerKeys.bin (or whatever its called) should be there # Optionally copy this somewhere? # Possible args: # Server name # Path to install # Car list # Track list STEAM_CMD_URL = "https://steamcdn-a.akamaihd.net/client/installer/steamcmd.zip" SERVER_APP_ID = 400300 GAME_APP_ID = 365960 # 917387157 - Silverstone 2012 # 1515650133 - McLaren MP4/13 SERVER_SETUP_CONTENT = ["917387157", "1515650133"] def create_server_dir(server_base_path: str, server_path: str) -> bool: if not os.path.exists(server_path): response = input(f"'{server_path}' does not exist. Create? y/N: ") if response.upper == "Y": try: os.makedirs(server_path) except Exception as e: print(f"\nError: Could not create '{server_path}' - {e}") return False else: return False if os.path.exists(server_base_path): print(f"\nError: '{server_base_path}' already exists!") return False try: os.mkdir(server_base_path) except Exception as e: print(f"\nError: Could not create '{server_base_path}' - {e}") return True def download_steamcmd(steamcmd_path: str) -> bool: # Make dir for steamcmd print(f"Creating directory for SteamCMD at '{steamcmd_path}'...") if os.path.exists(steamcmd_path): print(f"\nError: '{steamcmd_path}' already exists!") return False try: os.mkdir(steamcmd_path) except Exception as e: print(f"\nError: Could not create '{steamcmd_path}' - {e}") return False print("Downloading SteamCMD...") print(f"\t{STEAM_CMD_URL}") response = requests.get(STEAM_CMD_URL) print("Writing downloaded file...") with open(f"{steamcmd_path}/steamcmd.zip", "wb") as steamcmd_file: steamcmd_file.write(response.content) return True def extract_steamcmd(steamcmd_path: str) -> bool: print("Extracting SteamCMD zip...") with zipfile.ZipFile(f"{steamcmd_path}/steamcmd.zip", "r") as steamcmd_zip: steamcmd_zip.extractall(steamcmd_path) # Remove steamcmd.zip folder print("Removing downloaded zip...") os.remove(f"{steamcmd_path}/steamcmd.zip") return True def download_server(steamcmd_path: str) -> bool: print("Downloading rFactor 2 server...") subprocess.run( [ f"{steamcmd_path}/steamcmd.exe", "+login", "anonymous", "+app_update", "400300", "validate", "+quit" ] ) return True def read_steam_credentials(credentials_file: str) -> tuple: return (False, {}) def read_workshop(content_file: str) -> tuple: return (False, []) def download_workshop(server_base_path: str, workshop_content: list) -> bool: return False def move_workshop(server_base_path: str, workshop_content: list) -> bool: return False def install_workshop(server_base_path: str, workshop_content: list) -> bool: return False def uninstall_workshop(server_base_path: str, workshop_content: list) -> bool: return False def open_mas2(server_base_path: str) -> bool: # MIGHT be able to create MAS files using the ModMgr it seems return False def start_server(server_base_path: str) -> bool: return False def server_keys(server_base_path: str) -> bool: # download + install basic content here print("Starting server to get server keys file") print("\t1 - Create a server using basic content") print(f"\t2 - Once the server is running, ServerKeys.bin should exist at {server_base_path}/UserData/ServerKeys.bin") print("\t3 - Copy this file to your main rFactor 2 installation which owns the paid DLC you are installing") print("\t\t\\steamapps\\common\\rFactor 2\\UserData\\ServerKeys.bin") print("\t4 - Start a single player race (any content I think)") print("\t5 - There should not be a ServerUnlock.bin file in the folder you copied ServerKeys.bin to") print("\t\t\\steamapps\\common\\rFactor 2\\UserData\\ServerUnlock.bin") print(f"\t6 - Copy ServerUnlock.bin back to {server_base_path}/UserData/ServerUnlock.bin") # start server here - dont think this can be scripted? input("\nPress Enter once you have completed those steps...") return True def setup_server(server_name: str, server_path: str, content_file: str, credentials_file: str) -> bool: server_base_path = f"{server_path}/{server_name}" steamcmd_path = f"{server_base_path}/steamcmd" if not create_server_dir(server_base_path, server_path): return False if not download_steamcmd(steamcmd_path): return False if not extract_steamcmd(steamcmd_path): return False if not download_server(steamcmd_path): return False if not server_keys(server_base_path): return False return True if __name__ == "__main__": parser = argparse.ArgumentParser(description="Set up rFactor 2 server :)") parser.add_argument("name", type=str, help="Friendly name for the server") parser.add_argument("path", type=str, help="Path to download the server to") parser.add_argument("content_file", type=str, help="Path to a list of workshop IDs to download and install onto the server") parser.add_argument("credentials_file", type=str, help="Path to file containing Steam username and password in format username:password") args = parser.parse_args() setup_server(args.name, os.path.abspath(args.path), args.content_file, args.credentials_file)