Beispiel #1
0
 def connectSocket(self):
     if not self.connected:
         # print("Connecting...")
         self.socket.connect(
             ("127.0.0.1", int(self.DS.settings.ConsolePort)))
         self.connected = True
         AstroLogging.logPrint("Connected to RCON Console!")
Beispiel #2
0
def heartbeat_server(serverData, headers, dataToChange=None):
    try:
        url = (
            "https://5EA1.playfabapi.com/Client/ExecuteCloudScript?sdk=UE4MKPL-1.19.190610"
        )
        requestObj = {
            "FunctionName": "heartbeatDedicatedServer",
            "FunctionParameter": {
                "serverName": serverData['Tags']['serverName'],
                "buildVersion": serverData['Tags']['gameBuild'],
                "gameMode": serverData['GameMode'],
                "ipAddress": serverData['ServerIPV4Address'],
                "port": serverData['ServerPort'],
                "matchmakerBuild": serverData['BuildVersion'],
                "maxPlayers": serverData['Tags']['maxPlayers'],
                "numPlayers": str(len(serverData['PlayerUserIds'])),
                "lobbyId": serverData['LobbyID'],
                "publicSigningKey": serverData['Tags']['publicSigningKey'],
                "requiresPassword": serverData['Tags']['requiresPassword']
            },
            "GeneratePlayStreamEvent": True
        }
        if dataToChange is not None:
            requestObj['FunctionParameter'].update(dataToChange)

        AstroLogging.logPrint(requestObj, "debug")
        x = (requests.post(url, headers=headers, json=requestObj)).json()
        AstroLogging.logPrint(x, "debug")
        return x
    except:
        return {"status": "Error"}
Beispiel #3
0
 def saveGame(self):
     self.setStatus("saving")
     self.busy = True
     time.sleep(1)
     AstroLogging.logPrint("Saving the current game...")
     AstroRCON.DSSaveGame(self.settings.ConsolePort)
     self.busy = False
Beispiel #4
0
 def kill_server(self, reason, save=False):
     AstroLogging.logPrint(f"Kill Server: {reason}")
     try:
         self.busy = True
         self.setStatus("shutdown")
     except:
         pass
     try:
         if save:
             self.saveGame()
             time.sleep(1)
             self.shutdownServer()
     except:
         pass
     try:
         self.deregister_all_server()
     except:
         pass
     # Kill all child processes
     try:
         for child in psutil.Process(self.process.pid).children():
             child.kill()
     except:
         pass
     try:
         self.setStatus("off")
     except:
         pass
     # Kill current process
     try:
         os.kill(os.getpid(), 9)
     except:
         pass
Beispiel #5
0
 def on_modified(self, event):
     # AstroLogging.logPrint("File in save directory changed")
     path = os.path.join(self.astroPath, self.moveToPath)
     try:
         if not os.path.exists(path):
             os.makedirs(path)
     except Exception as e:
         AstroLogging.logPrint(e, "error")
     now = time.time()
     try:
         for f in os.listdir(path):
             fpath = os.path.join(path, f)
             if os.stat(fpath).st_mtime < (
                     now - (self.retentionPeriodHours * 60 * 60)):
                 os.remove(fpath)
     except Exception as e:
         AstroLogging.logPrint(e, "error")
     AstroLogging.logPrint("Copying backup to retention folder.")
     time.sleep(1)
     try:
         dirName = os.path.dirname(event.src_path)
         newFile = os.path.join(dirName, [
             f for f in os.listdir(dirName)
             if os.path.isfile(os.path.join(dirName, f))
         ][0])
         # AstroLogging.logPrint(newFile, "debug")
         shutil.copy2(newFile, path)
         # AstroLogging.logPrint(copiedFile, "debug")
     except FileNotFoundError as e:
         AstroLogging.logPrint(e, "error")
     except Exception as e:
         AstroLogging.logPrint(e, "error")
     self.launcher.backupObserver.stop()
Beispiel #6
0
    def __init__(self, container_file_path):
        """
        Extracts the saves from an Astroneer save container

        Reads the container file, divides it into chunks and
        regroups the chunks into save objects

        Arguments:
            container_file_path -- Path to the container file

        Returns:
            The AstroSaveContainer object 

        Exception:
            None
        """
        self.path = container_file_path
        self.save_list = []
        AstroLogging.logPrint('\nInitializing Astroneer save container...')
        with open(self.path, "rb") as container:
            # The Astroneer file type is contained in at least the first 2 bytes of the file
            self.header = container.read(2)

            if not self.is_valid_container_header(self.header):
                raise Exception(
                    f'The save container {self.path} is not valid (First two bytes:{self.header})')
            # Skipping 2 bytes that may be part of the header
            container.read(2)

            # Next 4 bytes are the number of saves chunk
            self.chunk_count = int.from_bytes(
                container.read(4), byteorder='little')

            AstroLogging.logPrint(f'Detected chunks: {self.chunk_count}')

            # Parsing saves chunks
            current_save_name = None
            for _ in range(self.chunk_count):
                current_chunk = container.read(CHUNK_METADATA_SIZE)
                current_chunk_name = self.extract_name_from_chunk(
                    current_chunk)

                if current_chunk_name != current_save_name:
                    if current_save_name != None:
                        # Parsing a new save, storing the current save
                        self.save_list.append(AstroSave(current_save_name,
                                                        current_chunks_names))

                    current_chunks_names = []
                    current_save_name = current_chunk_name

                current_chunks_names.append(
                    self.extract_chunk_file_name_from_chunk(current_chunk))

            # Saving the last save of the container file
            self.save_list.append(AstroSave(current_save_name,
                                            current_chunks_names))
Beispiel #7
0
 def on_modified(self, event):
     time.sleep(1)
     dirName = os.path.dirname(event.src_path)
     fileName = [
         f for f in os.listdir(dirName)
         if os.path.isfile(os.path.join(dirName, f))
     ][0]
     AstroLogging.logPrint(f"Server saved. {fileName}")
     self.launcher.saveObserver.stop()
Beispiel #8
0
def get_microsoft_save_folder():
    """
    Retrieves the microsoft save folders from %appdata%

    We know that the saves are stored along with a container.* file.
    We look for that specific container by checking if it contains a
    save date in order to return the whole path

    Arguments:
        None

    Returns:
        Returns the list of the microsoft save folder path found in %appdata%

    Exception:
        FileNotFoundError if no save folder is found
    """
    # glob is used to get the path using the wildcard *
    for result in glob.iglob(
            os.environ['LOCALAPPDATA'] +
            '\\Packages\\SystemEraSoftworks*\\SystemAppData\\wgs'):
        AstroLogging.logPrint(f'SES path found in appadata: {result}', 'debug')
        SES_appdata_path = result

    microsoft_save_folders = []

    for root, _, files in os.walk(SES_appdata_path):
        # Seeking every file in the SES folder
        for file in files:
            if re.search(r'^container\.', file):
                # We matched a container.* file
                container_full_path = os.path.join(root, file)
                AstroLogging.logPrint(
                    f'Container file found:{container_full_path}', 'debug')

                with open(container_full_path, 'rb') as container:
                    # Decoding the container to check for a date string
                    container_binary_content = container.read()
                    container_text = container_binary_content.decode(
                        'utf-16le', errors='ignore')

                    # Save date matches $YYYY.MM.dd
                    if re.search(r'\$\d{4}\.\d{2}\.\d{2}', container_text):
                        AstroLogging.logPrint(f'Matching save folder {root}',
                                              'debug')
                        microsoft_save_folders.append(root)

    if not microsoft_save_folders:
        AstroLogging.logPrint(f'No save folder found.', 'debug')
        raise FileNotFoundError
    elif len(microsoft_save_folders) != 1:
        # We are not supposed to have more than one save folder
        AstroLogging.logPrint(
            f'More than one save folders was found:\n {microsoft_save_folders}',
            'debug')

    return microsoft_save_folders
 def shutdownServer(self):
     if not self.AstroRCON.connected:
         return False
     self.setStatus("shutdown")
     self.busy = True
     # time.sleep(1)
     self.AstroRCON.DSServerShutdown()
     self.DSServerStats = None
     AstroLogging.logPrint("Server shutdown.")
 def saveGame(self):
     if not self.AstroRCON.connected:
         return False
     self.setStatus("saving")
     self.busy = True
     # time.sleep(1)
     AstroLogging.logPrint("Saving the current game...")
     self.AstroRCON.DSSaveGame()
     self.busy = False
Beispiel #11
0
 def saveGame(self, name=None):
     if not self.AstroRCON.connected:
         return False
     self.setStatus("saving")
     self.busy = "Saving"
     # time.sleep(1)
     AstroLogging.logPrint("Saving the current game...")
     self.AstroRCON.DSSaveGame(name)
     self.getSaves()
     self.busy = False
Beispiel #12
0
    def start_server(self):
        """
            Starts the Dedicated Server process and waits for it to be registered
        """
        self.DedicatedServer.status = "starting"
        self.DedicatedServer.busy = False
        oldLobbyIDs = self.DedicatedServer.deregister_all_server()
        AstroLogging.logPrint("Starting Server process...")
        if self.launcherConfig.EnableAutoRestart:
            AstroLogging.logPrint(
                f"Next restart is at {self.DedicatedServer.nextRestartTime}")
        time.sleep(5)
        startTime = time.time()
        self.DedicatedServer.start()
        self.DaemonProcess = AstroDaemon.launch(
            executable=self.isExecutable,
            consolePID=self.DedicatedServer.process.pid)

        # Wait for server to finish registering...
        while not self.DedicatedServer.registered:
            try:
                serverData = (AstroAPI.get_server(
                    self.DedicatedServer.ipPortCombo, self.headers))
                serverData = serverData['data']['Games']
                lobbyIDs = [x['LobbyID'] for x in serverData]
                if len(set(lobbyIDs) - set(oldLobbyIDs)) == 0:
                    time.sleep(self.launcherConfig.PlayfabAPIFrequency)
                else:
                    now = time.time()
                    if now - startTime > 15:
                        self.DedicatedServer.registered = True
                        del oldLobbyIDs
                        self.DedicatedServer.LobbyID = serverData[0]['LobbyID']

                if self.DedicatedServer.process.poll() is not None:
                    AstroLogging.logPrint(
                        "Server was forcefully closed before registration. Exiting...."
                    )
                    return False
            except KeyboardInterrupt:
                self.DedicatedServer.kill_server("Launcher shutting down")
            except:
                AstroLogging.logPrint(
                    "Failed to check server. Probably hit rate limit. Backing off and trying again..."
                )
                self.launcherConfig.PlayfabAPIFrequency += 1
                time.sleep(self.launcherConfig.PlayfabAPIFrequency)

        doneTime = time.time()
        elapsed = doneTime - startTime
        AstroLogging.logPrint(
            f"Server ready with ID {self.DedicatedServer.LobbyID}. Took {round(elapsed,2)} seconds to register."
        )
        self.DedicatedServer.status = "ready"
        self.DedicatedServer.server_loop()
Beispiel #13
0
def generate_XAUTH(serverGUID):
    url = "https://5EA1.playfabapi.com/Client/LoginWithCustomID?sdk=UE4MKPL-1.19.190610"
    requestObj = {
        "CreateAccount": True,
        "CustomId": serverGUID,
        "TitleId": "5EA1"
    }
    AstroLogging.logPrint(requestObj, "debug")
    x = (requests.post(url, headers=base_headers, json=requestObj)).json()
    AstroLogging.logPrint(x, "debug")
    return x['data']['SessionTicket']
Beispiel #14
0
 def newSaveGame(self):
     if not self.AstroRCON.connected:
         return False
     self.setStatus("newsave")
     self.busy = "NewSave"
     # time.sleep(1)
     AstroLogging.logPrint("Starting a new savegame...")
     self.AstroRCON.DSNewGame()
     self.AstroRCON.DSSaveGame()
     self.getSaves()
     self.busy = False
Beispiel #15
0
 def get(self):
     # ip = self.request.headers.get("X-Real-IP") or \
     #    self.request.headers.get("X-Forwarded-For") or \
     #    self.request.remote_ip
     # if ip == "::1":
     evt = self.get_argument('evt')
     msg = self.get_argument('msg')
     name = self.get_argument('name')
     if evt == "chat" or evt == "cmd":
         AstroLogging.logPrint(msg, msgType=evt, playerName=name, dwet="c")
     self.write({"message": "Success"})
Beispiel #16
0
 def validate_playfab_certs(self):
     AstroLogging.logPrint("Attempting to validate Playfab Certs")
     playfabRequestCommand = [
         "powershell", '-executionpolicy', 'bypass', '-command',
         'Invoke-WebRequest -uri https://5ea1.playfabapi.com/ -UseBasicParsing'
     ]
     with open(os.devnull, 'w') as tempf:
         proc = subprocess.Popen(playfabRequestCommand,
                                 stdout=tempf,
                                 stderr=tempf)
         proc.communicate()
Beispiel #17
0
 def connectSocket(self):
     if not self.connected:
         # print("Connecting...")
         self.socket.connect(
             ("127.0.0.1", int(self.DS.settings.ConsolePort)))
         with self.lockRcon() as s:
             # Send console password
             s.socket.sendall(
                 f"{self.DS.settings.ConsolePassword}\n".encode())
             # print(f"{self.DS.settings.ConsolePassword}\n".encode())
         self.connected = True
         AstroLogging.logPrint("Connected to RCON Console!")
Beispiel #18
0
 def loadSaveGame(self, saveData):
     if not self.AstroRCON.connected:
         return False
     self.setStatus("loadsave")
     self.busy = "LoadSave"
     name = saveData['name']
     if pathvalidate.is_valid_filename(name):
         # time.sleep(1)
         AstroLogging.logPrint(f"Loading save: {name}")
         self.AstroRCON.DSLoadGame(name)
     self.getSaves()
     self.busy = False
Beispiel #19
0
def deregister_server(lobbyID, headers):
    url = 'https://5EA1.playfabapi.com/Client/ExecuteCloudScript?sdk=UE4MKPL-1.19.190610'
    requestObj = {
        "FunctionName": "deregisterDedicatedServer",
        "FunctionParameter": {
            "lobbyId": lobbyID
        },
        "GeneratePlayStreamEvent": True
    }

    AstroLogging.logPrint(requestObj, "debug")
    x = (requests.post(url, headers=headers, json=requestObj)).json()
    AstroLogging.logPrint(x, "debug")
    return x
Beispiel #20
0
def get_container_list(path):
    """
    List all containers in a folder
    Arguments:
        path -- path for search containers
    Returns:
        Returns a list of all containers found (only filename of container)
    Exception:
        None
    """
    list_containers = []

    for file in [
            f for f in os.listdir(path)
            if os.path.isfile(os.path.join(path, f))
    ]:
        if file.rfind("container") != -1:
            list_containers.append(file)

    if not list_containers:
        AstroLogging.logPrint('\nNo container found in path: ' + path)
    elif len(list_containers) == 1:
        AstroLogging.logPrint('\nOne container found', 'debug')
    else:
        AstroLogging.logPrint('\nContainers found:')
        for i, container in enumerate(list_containers):
            AstroLogging.logPrint(f'\t {i+1}) {container}')

    return list_containers
Beispiel #21
0
 def check_for_update(self):
     try:
         url = "https://api.github.com/repos/ricky-davis/AstroLauncher/releases/latest"
         data = ((requests.get(url)).json())
         latestVersion = data['tag_name']
         if latestVersion != self.version:
             AstroLogging.logPrint(
                 f"UPDATE: There is a newer version of the launcher out! {latestVersion}"
             )
             AstroLogging.logPrint(f"Download it at {self.latestURL}")
             if self.isExecutable and not self.launcherConfig.DisableAutoUpdate:
                 self.autoupdate(data)
     except:
         pass
Beispiel #22
0
 def deleteSaveGame(self, saveData):
     if not self.AstroRCON.connected:
         return False
     name = saveData['name']
     if pathvalidate.is_valid_filename(name):
         self.setStatus("delsave")
         self.busy = "DelSave"
         saveGamePath = r"Astro\Saved\SaveGames"
         AstroLogging.logPrint(f"Deleting save: {saveData['fileName']}")
         sfPath = os.path.join(self.astroPath, saveGamePath,
                               saveData['fileName'])
         if os.path.exists(sfPath):
             os.remove(sfPath)
     self.getSaves()
     self.busy = False
Beispiel #23
0
 def __post_init__(self):
     # pylint: disable=no-member
     hasError = False
     for field, data in self.__dataclass_fields__.items():
         try:
             self.__dict__[field] = data.type(self.__dict__[field])
         except ValueError:
             hasError = True
             AstroLogging.logPrint(
                 f"INI error: {field} must be of type {data.type.__name__}",
                 "critical")
     if hasError:
         AstroLogging.logPrint("Fix your launcher config file!",
                               "critical")
         sys.exit()
Beispiel #24
0
    def __init__(self, launcher):
        logging.getLogger('tornado.access').disabled = True
        self.launcher = launcher
        self.port = self.launcher.launcherConfig.WebServerPort
        self.ssl = False
        curDir = self.launcher.launcherPath
        if self.launcher.isExecutable:
            curDir = sys._MEIPASS
        self.assetDir = os.path.join(curDir, "assets")
        # temp
        # these will later be saved and loaded from/to an .ini
        self.cookieSecret = secrets.token_hex(16).encode()
        self.passwordHash = self.launcher.launcherConfig.WebServerPasswordHash
        cfgOvr = {}

        if len(self.passwordHash) != 64:
            AstroLogging.logPrint(
                "SECURITY ALERT: You must set your Web Server Password!", "warning")
            cfgOvr["WebServerPasswordHash"] = ""
            self.passwordHash = ""

        if cfgOvr != {}:
            self.launcher.overwrite_launcher_config(cfgOvr)
            self.launcher.refresh_launcher_config()

        settings = {
            'debug': True,
            "static_path": self.assetDir,
            "cookie_secret": self.cookieSecret,
            "login_url": "/login",
            "ui_modules": UIModules
        }

        handlers = [(r'/', MainHandler, dict(path=settings['static_path'], launcher=self.launcher)),
                    (r"/login", LoginHandler,
                     dict(path=settings['static_path'], launcher=self.launcher)),
                    (r'/logout', LogoutHandler, dict(launcher=self.launcher)),
                    (r"/api", APIRequestHandler, dict(launcher=self.launcher)),
                    (r"/api/savegame", SaveRequestHandler,
                     dict(launcher=self.launcher)),
                    (r"/api/reboot", RebootRequestHandler,
                     dict(launcher=self.launcher)),
                    (r"/api/shutdown", ShutdownRequestHandler,
                     dict(launcher=self.launcher)),
                    (r"/api/player", PlayerRequestHandler,
                     dict(launcher=self.launcher)),
                    ]
        super().__init__(handlers, **settings)
Beispiel #25
0
 def save_reporting(self):
     if self.saveObserver:
         if not self.saveObserver.is_alive():
             self.saveObserver = None
             self.save_reporting()
     else:
         self.saveObserver = Observer()
         saveGamePath = r"Astro\Saved\SaveGames"
         watchPath = os.path.join(self.astroPath, saveGamePath)
         try:
             if not os.path.exists(watchPath):
                 os.makedirs(watchPath)
         except Exception as e:
             AstroLogging.logPrint(e)
         self.saveObserver.schedule(self.SaveHandler(self), watchPath)
         self.saveObserver.start()
Beispiel #26
0
    def print_container(self):
        """
        Displays the saves of a container

        Arguments:
            None

        Returns:
            None 

        Exception:
            None
        """
        AstroLogging.logPrint('Extracted save list :')
        for i, save in enumerate(self.save_list):
            AstroLogging.logPrint(f'\t {str(i+1)}) {save.save_name}')
 def getXauth(self):
     if self.lastXAuth is None or (datetime.datetime.now() -
                                   self.lastXAuth).total_seconds() > 3600:
         try:
             gxAuth = None
             while gxAuth is None:
                 try:
                     AstroLogging.logPrint("Generating new xAuth...",
                                           "debug")
                     gxAuth = AstroAPI.generate_XAUTH(
                         self.settings.ServerGuid)
                 except:
                     time.sleep(10)
             self.launcher.headers['X-Authorization'] = gxAuth
             self.lastXAuth = datetime.datetime.now()
         except:
             self.lastXAuth += datetime.timedelta(seconds=20)
Beispiel #28
0
def deregister_server(lobbyID, headers):
    try:
        url = f"https://5EA1.playfabapi.com/Client/ExecuteCloudScript?sdk={base_headers['X-PlayFabSDK']}"
        requestObj = {
            "FunctionName": "deregisterDedicatedServer",
            "FunctionParameter": {
                "lobbyId": lobbyID
            },
            "GeneratePlayStreamEvent": True
        }

        AstroLogging.logPrint(requestObj, "debug")
        x = (AstroRequests.post(url, headers=headers, json=requestObj)).json()
        AstroLogging.logPrint(x, "debug")
        return x
    except:
        return {"status": "Error"}
Beispiel #29
0
def check_container_path(path):
    """
    Defines the container to use

    Find every *container* file in the
    given path and make the user chose one

    Arguments:
        path -- path where to look for the containers

    Returns:
        Returns the chosen container filename

    Exception:
        Raise FileNotFoundError if no container is found
    """
    list_containers = []
    list_containers = get_container_list(path)

    if len(list_containers) == 0:
        raise FileNotFoundError
    if len(list_containers) == 1:
        container_name = list_containers[0]
    else:

        min_container_number = 1
        max_container_number = len(list_containers)
        container_index = 0

        while container_index == 0:
            AstroLogging.logPrint(
                '\nWhich container would you like to convert ?')
            container_index = input()
            try:
                container_index = int(container_index)
                if (container_index < min_container_number
                        or container_index > max_container_number):
                    raise ValueError
            except ValueError:
                container_index = 0
                AstroLogging.logPrint(
                    f'Please use only values between {min_container_number} and {max_container_number}'
                )
        container_name = list_containers[container_index - 1]
    return container_name
Beispiel #30
0
 def on_created(self, event):
     # print(event)
     # time.sleep(1)
     try:
         time.sleep(0.5)
         dirName = os.path.dirname(event.src_path)
         fileNames = [
             os.path.join(dirName, f) for f in os.listdir(dirName)
             if os.path.isfile(os.path.join(dirName, f))
         ]
         # print(fileNames)
         fileName = sorted(fileNames,
                           key=os.path.getmtime,
                           reverse=True)[0]
         AstroLogging.logPrint(
             f"Server saved. {os.path.basename(fileName)}")
     except:
         pass