Skip to content

Commit f2bc21e

Browse files
committed
integrated GLD deserialization and server fetch; updated default server URL; incremented version to 0.2
1 parent 400797f commit f2bc21e

4 files changed

Lines changed: 166 additions & 16 deletions

File tree

DystopiaPolyScript.csproj

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,15 @@
1919
<Reference Include="PolytopiaBackendBase">
2020
<HintPath>PolytopiaBackendBase.dll</HintPath>
2121
</Reference>
22+
<Reference Include="GameLogicAssembly">
23+
<HintPath>GameLogicAssembly.dll</HintPath>
24+
</Reference>
25+
<Reference Include="PolytopiaAssembly">
26+
<HintPath>PolytopiaAssembly.dll</HintPath>
27+
</Reference>
28+
<Reference Include="Il2Cppmscorlib">
29+
<HintPath>Il2Cppmscorlib.dll</HintPath>
30+
</Reference>
2231
</ItemGroup>
2332

2433
<ItemGroup>

Main.cs

Lines changed: 155 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,198 @@
1-
using BepInEx.Logging;
1+
using System.Collections.Generic;
2+
using System.Net.Http;
23
using System.Text.Json;
4+
using BepInEx.Logging;
5+
using HarmonyLib;
6+
using Polytopia.Data;
7+
using Il2CppSystem.IO;
8+
using BinaryReader = Il2CppSystem.IO.BinaryReader;
9+
using EndOfStreamException = System.IO.EndOfStreamException;
310

411
namespace DystopiaPolyScript;
512

613
public class ServerConfig
714
{
8-
public string ServerUrl { get; init; } = "http://localhost:5051";
15+
public string ServerUrl { get; init; } = "https://dev.polydystopia.xyz";
916
}
1017

1118
public static class Main
1219
{
1320
private const string CONFIG_FILE_NAME = "polydystopia_server_config.json";
14-
private const string DEFAULT_SERVER_URL = "http://localhost:5051";
21+
private const string DEFAULT_SERVER_URL = "https://dev.polydystopia.xyz";
22+
private const string GldMarker = "##GLD:";
23+
24+
private static string _serverUrl = DEFAULT_SERVER_URL;
25+
private static ManualLogSource _logger = null!;
26+
27+
// Cache parsed GLD by game Seed to handle rewinds/reloads
28+
private static readonly Dictionary<int, GameLogicData> _gldCache = new();
29+
private static readonly Dictionary<int, int> _versionCache = new(); // Seed -> modGldVersion
1530

1631
public static void Load(ManualLogSource logger)
1732
{
18-
var serverUrl = LoadServerUrlFromFile(logger);
33+
_logger = logger;
34+
_serverUrl = LoadServerUrlFromFile(logger);
1935

2036
BuildConfigHelper.GetSelectedBuildConfig().buildServerURL = BuildServerURL.Custom;
21-
BuildConfigHelper.GetSelectedBuildConfig().customServerURL = serverUrl;
37+
BuildConfigHelper.GetSelectedBuildConfig().customServerURL = _serverUrl;
2238

23-
logger.LogInfo($"Polydystopia> Server URL set to: {serverUrl}");
39+
// Apply Harmony patches
40+
Harmony.CreateAndPatchAll(typeof(Main));
41+
42+
logger.LogInfo($"Polydystopia> Server URL set to: {_serverUrl}");
43+
logger.LogInfo("Polydystopia> GLD patches applied");
44+
}
45+
46+
/// <summary>
47+
/// After GameState deserialization, check for trailing GLD version ID and set mockedGameLogicData.
48+
/// The server appends "##GLD:" + modGldVersion (int) after the normal serialized data.
49+
/// </summary>
50+
[HarmonyPostfix]
51+
[HarmonyPatch(typeof(GameState), nameof(GameState.Deserialize))]
52+
private static void Deserialize_Postfix(GameState __instance, BinaryReader __0)
53+
{
54+
_logger?.LogDebug("Deserialize_Postfix: Entered");
55+
56+
try
57+
{
58+
var reader = __0;
59+
if (reader == null)
60+
{
61+
_logger?.LogWarning("Deserialize_Postfix: reader is null");
62+
return;
63+
}
64+
65+
var position = reader.BaseStream.Position;
66+
var length = reader.BaseStream.Length;
67+
var remaining = length - position;
68+
69+
_logger?.LogDebug($"Deserialize_Postfix: Stream position={position}, length={length}, remaining={remaining}");
70+
71+
// Check if there's more data after normal deserialization
72+
if (position >= length)
73+
{
74+
_logger?.LogDebug("Deserialize_Postfix: No trailing data (position >= length)");
75+
76+
var sd = __instance.Seed;
77+
if (_gldCache.TryGetValue(sd, out var cachedGld))
78+
{
79+
__instance.mockedGameLogicData = cachedGld;
80+
var cachedVersion = _versionCache.GetValueOrDefault(sd, -1);
81+
_logger?.LogInfo($"Deserialize_Postfix: Applied cached GLD for Seed={sd}, ModGldVersion={cachedVersion}");
82+
}
83+
return;
84+
}
85+
86+
_logger?.LogDebug($"Deserialize_Postfix: Found {remaining} bytes of trailing data, attempting to read marker");
87+
88+
var marker = reader.ReadString();
89+
_logger?.LogDebug($"Deserialize_Postfix: Read marker string: '{marker}'");
90+
91+
if (marker != GldMarker)
92+
{
93+
_logger?.LogDebug($"Deserialize_Postfix: Marker mismatch - expected '{GldMarker}', got '{marker}'");
94+
return;
95+
}
96+
97+
_logger?.LogInfo($"Deserialize_Postfix: Found GLD marker '{GldMarker}'");
98+
99+
var modGldVersion = reader.ReadInt32();
100+
_logger?.LogInfo($"Deserialize_Postfix: Found embedded ModGldVersion: {modGldVersion}");
101+
102+
_logger?.LogDebug($"Deserialize_Postfix: Fetching GLD from server for version {modGldVersion}");
103+
var gldJson = FetchGldById(modGldVersion);
104+
if (string.IsNullOrEmpty(gldJson))
105+
{
106+
_logger?.LogError($"Deserialize_Postfix: Failed to fetch GLD for ModGldVersion: {modGldVersion}");
107+
return;
108+
}
109+
110+
_logger?.LogDebug($"Deserialize_Postfix: Parsing GLD JSON ({gldJson.Length} chars)");
111+
112+
var customGld = new GameLogicData();
113+
customGld.Parse(gldJson);
114+
__instance.mockedGameLogicData = customGld;
115+
116+
// Cache for subsequent deserializations (rewinds, reloads)
117+
var seed = __instance.Seed;
118+
_gldCache[seed] = customGld;
119+
_versionCache[seed] = modGldVersion;
120+
121+
_logger?.LogInfo($"Deserialize_Postfix: Successfully set mockedGameLogicData from ModGldVersion: {modGldVersion}, cached for Seed={seed}");
122+
}
123+
catch (EndOfStreamException)
124+
{
125+
_logger?.LogDebug("Deserialize_Postfix: EndOfStreamException - no trailing data");
126+
}
127+
catch (Exception ex)
128+
{
129+
_logger?.LogError($"Deserialize_Postfix: Exception: {ex.GetType().Name}: {ex.Message}");
130+
_logger?.LogDebug($"Deserialize_Postfix: Stack trace: {ex.StackTrace}");
131+
}
132+
}
133+
134+
/// <summary>
135+
/// Fetch GLD from server using ModGldVersion ID
136+
/// </summary>
137+
private static string? FetchGldById(int modGldVersion)
138+
{
139+
try
140+
{
141+
using var client = new HttpClient();
142+
var url = $"{_serverUrl.TrimEnd('/')}/api/mods/gld/{modGldVersion}";
143+
_logger?.LogDebug($"FetchGldById: Requesting URL: {url}");
144+
145+
var response = client.GetAsync(url).Result;
146+
_logger?.LogDebug($"FetchGldById: Response status: {response.StatusCode}");
147+
148+
if (response.IsSuccessStatusCode)
149+
{
150+
var gld = response.Content.ReadAsStringAsync().Result;
151+
_logger?.LogInfo($"FetchGldById: Successfully fetched mod GLD ({gld.Length} chars)");
152+
return gld;
153+
}
154+
155+
var errorContent = response.Content.ReadAsStringAsync().Result;
156+
_logger?.LogError($"FetchGldById: Failed with status {response.StatusCode}: {errorContent}");
157+
}
158+
catch (Exception ex)
159+
{
160+
_logger?.LogError($"FetchGldById: Exception: {ex.GetType().Name}: {ex.Message}");
161+
if (ex.InnerException != null)
162+
{
163+
_logger?.LogError($"FetchGldById: Inner exception: {ex.InnerException.Message}");
164+
}
165+
}
166+
return null;
24167
}
25168

26169
private static string LoadServerUrlFromFile(ManualLogSource logger)
27170
{
28171
try
29172
{
30-
if (File.Exists(CONFIG_FILE_NAME))
173+
if (System.IO.File.Exists(CONFIG_FILE_NAME))
31174
{
32-
var jsonContent = File.ReadAllText(CONFIG_FILE_NAME);
175+
var jsonContent = System.IO.File.ReadAllText(CONFIG_FILE_NAME);
33176
var config = JsonSerializer.Deserialize<ServerConfig>(jsonContent);
34177

35178
if (config != null && !string.IsNullOrEmpty(config.ServerUrl))
36179
{
37-
logger.LogInfo($"Loaded server URL from {CONFIG_FILE_NAME}: {config.ServerUrl}");
180+
logger.LogInfo($"Polydystopia> Loaded server URL from {CONFIG_FILE_NAME}: {config.ServerUrl}");
38181
return config.ServerUrl;
39182
}
40183
}
41184

42185
var defaultConfig = new ServerConfig { ServerUrl = DEFAULT_SERVER_URL };
43-
var defaultJson =
44-
JsonSerializer.Serialize(defaultConfig, new JsonSerializerOptions { WriteIndented = true });
45-
File.WriteAllText(CONFIG_FILE_NAME, defaultJson);
186+
var defaultJson = JsonSerializer.Serialize(defaultConfig, new JsonSerializerOptions { WriteIndented = true });
187+
System.IO.File.WriteAllText(CONFIG_FILE_NAME, defaultJson);
46188
logger.LogInfo($"Polydystopia> Created default config file {CONFIG_FILE_NAME} with URL: {DEFAULT_SERVER_URL}");
47189

48190
return DEFAULT_SERVER_URL;
49191
}
50192
catch (Exception ex)
51193
{
52194
logger.LogError($"Polydystopia> Error reading config file: {ex.Message}. Using default URL: {DEFAULT_SERVER_URL}");
53-
54195
return DEFAULT_SERVER_URL;
55196
}
56197
}
57-
}
198+
}

manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"id": "dystopia_poly_script",
33
"name": "Polydystopia",
4-
"version": "0.1",
4+
"version": "0.2",
55
"authors": [
66
"Paranoia"
77
],

polydystopia_server_config.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
"ServerUrl": "http://localhost:5051"
2+
"ServerUrl": "https://dev.polydystopia.xyz"
33
}

0 commit comments

Comments
 (0)