From c514c6100c23506fab04b90f89d0e840cf61aac4 Mon Sep 17 00:00:00 2001 From: Padi Date: Sun, 20 Oct 2024 21:34:34 +0200 Subject: [PATCH] Support Satisfactory 1.0 with tests --- opengsq/protocols/satisfactory.py | 119 ++++++++++++++++++++++----- tests/protocols/test_satisfactory.py | 6 +- 2 files changed, 104 insertions(+), 21 deletions(-) diff --git a/opengsq/protocols/satisfactory.py b/opengsq/protocols/satisfactory.py index d096a38..f2a5858 100644 --- a/opengsq/protocols/satisfactory.py +++ b/opengsq/protocols/satisfactory.py @@ -1,4 +1,6 @@ import struct +import time +import aiohttp from opengsq.responses.satisfactory import Status from opengsq.binary_reader import BinaryReader @@ -9,41 +11,113 @@ class Satisfactory(ProtocolBase): """ - This class represents the Satisfactory Protocol. It provides methods to interact with the Satisfactory API. + This class represents the Satisfactory Protocol. It provides methods to interact with the Satisfactory Lightweight Query API. """ full_name = "Satisfactory Protocol" + def __init__(self, host: str, port: int, app_token: str, timeout: float = 5): + """ + Initializes the Satisfactory object with the given parameters. + + :param host: The host of the server. + :param port: The port of the server. + :param access_token: The application token for the Satisfactory dedicated server. + :param timeout: The timeout for the server connection. + """ + + super().__init__(host, port, timeout) + + if app_token is None: + raise ValueError("app_token must not be None") + + self.api_url = f"https://{self._host}:{self._port}/api/v1/" + self.app_token = app_token + self.protocol_magic = 0xF6D5 + self.protocol_version = 1 + async def get_status(self) -> Status: """ - Asynchronously retrieves the status of the game server. The status includes the server state, version, and beacon port. + Asynchronously retrieves the status of the game server. The status includes the server state, name, player count and max player count. The server state can be one of the following: - 1 - Idle (no game loaded) - 2 - Currently loading or creating a game - 3 - Currently in game + 0 - Offline (The server is offline. Servers will never send this as a response) + 1 - Idle (The server is running, but no save is currently loaded) + 2 - Loading (The server is currently loading a map. In this state, HTTPS API is unavailable) + 3 - Playing (The server is running, and a save is loaded. Server is joinable by players) :return: A Status object containing the status of the game server. """ - # Credit: https://github.com/dopeghoti/SF-Tools/blob/main/Protocol.md - # Send message id, protocol version - request = struct.pack("2b", 0, 0) + "opengsq".encode() + # Generate a unique cookie using the current time (in ticks) + cookie = int(time.time() * 1000) + + # Construct the request packet + request = struct.pack( + " Status: import asyncio async def main_async(): - satisfactory = Satisfactory(host="79.136.0.124", port=15777, timeout=5.0) + satisfactory = Satisfactory( + host="79.136.0.124", + port=7777, + timeout=5.0, + app_token="ewoJInBsIjogIkFQSVRva2VuIgp9.EE80F05DAFE991AE8850CD4CFA55840D9F41705952A96AF054561ABA3676BE4D4893B162271D3BC0A0CC50797219D2C8E627F0737FC8776F3468EA44B3700EF7", + ) status = await satisfactory.get_status() print(status) diff --git a/tests/protocols/test_satisfactory.py b/tests/protocols/test_satisfactory.py index ad6ffc0..188c4dc 100644 --- a/tests/protocols/test_satisfactory.py +++ b/tests/protocols/test_satisfactory.py @@ -7,7 +7,11 @@ # handler.enable_save = True # Satisfactory -test = Satisfactory(host="79.136.0.124", port=15777) +test = Satisfactory( + host="79.136.0.124", + port=7777, + app_token="ewoJInBsIjogIkFQSVRva2VuIgp9.EE80F05DAFE991AE8850CD4CFA55840D9F41705952A96AF054561ABA3676BE4D4893B162271D3BC0A0CC50797219D2C8E627F0737FC8776F3468EA44B3700EF7", +) @pytest.mark.asyncio