1+ using System . IO . Compression ;
2+ using System . Text ;
13using System . Text . Json ;
24using System . Text . Json . Serialization ;
35using MegaCrit . Sts2 . Core . Debug ;
@@ -31,6 +33,17 @@ internal sealed record JoinDiagnosticsModEntry(
3133 string Source ,
3234 ulong ? WorkshopItemId ) ;
3335
36+ internal sealed record JoinDiagnosticsPayloadV5 (
37+ string GameVersion ,
38+ uint ModelDbHash ,
39+ string GameMode ,
40+ string SessionState ,
41+ IReadOnlyList < JoinDiagnosticsModEntry > GameplayMods ,
42+ IReadOnlyList < ContentModInventoryPayloadCodec . CompactEntry > ContentMods ,
43+ bool ModelDbHashUsesDeterministicCache ,
44+ string ? ModelDbHashModeDetail ,
45+ bool ? SavedPropertyNetIdUsesDeterministicSort ) ;
46+
3447 internal sealed record JoinPeerSnapshot (
3548 string GameVersion ,
3649 uint ModelDbHash ,
@@ -46,7 +59,7 @@ internal sealed record JoinPeerSnapshot(
4659 internal static class JoinDiagnosticsPayloadCodec
4760 {
4861 private const string ExtensionId = "ritsulib.joinDiagnostics" ;
49- private const int PayloadVersion = 4 ;
62+ private const int PayloadVersion = 5 ;
5063 private static int _registered ;
5164
5265 private static readonly JsonSerializerOptions JsonOptions = new ( )
@@ -85,17 +98,17 @@ public static void Read(PacketReader reader)
8598 try
8699 {
87100 var cacheStatus = ModelIdSerializationCacheDynamicContentPatch . GetDeterministicCacheStatus ( ) ;
88- var payload = new JoinDiagnosticsPayload (
101+ var payload = new JoinDiagnosticsPayloadV5 (
89102 message . version ,
90103 message . idDatabaseHash ,
91104 message . gameMode . ToString ( ) ,
92105 message . sessionState . ToString ( ) ,
93106 CreateLocalModEntries ( ) ,
94- ContentModInventoryPayloadCodec . Encode ( CreateLocalContentModEntries ( ) ) ,
107+ ContentModInventoryPayloadCodec . Compact ( CreateLocalContentModEntries ( ) ) ,
95108 cacheStatus . IsActive ,
96109 cacheStatus . Detail ,
97110 SavedPropertiesTypeCacheInjectionPatch . UsesDeterministicNetIdTable ) ;
98- return JsonSerializer . Serialize ( payload , JsonOptions ) ;
111+ return EncodeCompressed ( payload ) ;
99112 }
100113 catch ( Exception ex )
101114 {
@@ -104,32 +117,83 @@ public static void Read(PacketReader reader)
104117 }
105118 }
106119
107- private static void ReadPayload ( int version , string json )
120+ private static void ReadPayload ( int version , string payload )
108121 {
109122 try
110123 {
111124 if ( version == 1 )
112125 {
113126 JoinFailureDiagnosticsService . ObserveHostPayload ( ConvertLegacyPayload (
114- JsonSerializer . Deserialize < JoinDiagnosticsPayloadV1 > ( json , JsonOptions ) ) ) ;
127+ JsonSerializer . Deserialize < JoinDiagnosticsPayloadV1 > ( payload , JsonOptions ) ) ) ;
115128 return ;
116129 }
117130
118- if ( version != 2 && version != 3 && version != PayloadVersion )
131+ if ( version != 2 && version != 3 && version != 4 && version != PayloadVersion )
119132 {
120133 RitsuLibFramework . Logger . Warn ( $ "[JoinDiagnostics] Unsupported payload version: { version } ") ;
121134 return ;
122135 }
123136
124- JoinFailureDiagnosticsService . ObserveHostPayload (
125- JsonSerializer . Deserialize < JoinDiagnosticsPayload > ( json , JsonOptions ) ) ;
137+ var json = version == PayloadVersion ? DecodeCompressed ( payload ) : payload ;
138+ var parsed = version == PayloadVersion
139+ ? FromWirePayload ( JsonSerializer . Deserialize < JoinDiagnosticsPayloadV5 > ( json , JsonOptions ) )
140+ : JsonSerializer . Deserialize < JoinDiagnosticsPayload > ( json , JsonOptions ) ;
141+ JoinFailureDiagnosticsService . ObserveHostPayload ( parsed ) ;
126142 }
127143 catch ( Exception ex )
128144 {
129145 RitsuLibFramework . Logger . Warn ( $ "[JoinDiagnostics] Failed to read payload: { ex . Message } ") ;
130146 }
131147 }
132148
149+ private static string EncodeCompressed ( JoinDiagnosticsPayloadV5 payload )
150+ {
151+ var json = JsonSerializer . Serialize ( payload , JsonOptions ) ;
152+ return Convert . ToBase64String ( Gzip ( Encoding . UTF8 . GetBytes ( json ) ) ) ;
153+ }
154+
155+ private static JoinDiagnosticsPayload ? FromWirePayload ( JoinDiagnosticsPayloadV5 ? payload )
156+ {
157+ if ( payload == null )
158+ return null ;
159+
160+ return new (
161+ payload . GameVersion ,
162+ payload . ModelDbHash ,
163+ payload . GameMode ,
164+ payload . SessionState ,
165+ payload . GameplayMods ,
166+ ContentModInventoryPayloadCodec . Encode ( ContentModInventoryPayloadCodec . Expand ( payload . ContentMods ) ) ,
167+ payload . ModelDbHashUsesDeterministicCache ,
168+ payload . ModelDbHashModeDetail ,
169+ payload . SavedPropertyNetIdUsesDeterministicSort ) ;
170+ }
171+
172+ private static string DecodeCompressed ( string encoded )
173+ {
174+ return Encoding . UTF8 . GetString ( Gunzip ( Convert . FromBase64String ( encoded ) ) ) ;
175+ }
176+
177+ private static byte [ ] Gzip ( byte [ ] data )
178+ {
179+ using var output = new MemoryStream ( ) ;
180+ using ( var gzip = new GZipStream ( output , CompressionLevel . SmallestSize , true ) )
181+ {
182+ gzip . Write ( data , 0 , data . Length ) ;
183+ }
184+
185+ return output . ToArray ( ) ;
186+ }
187+
188+ private static byte [ ] Gunzip ( byte [ ] data )
189+ {
190+ using var input = new MemoryStream ( data , false ) ;
191+ using var gzip = new GZipStream ( input , CompressionMode . Decompress ) ;
192+ using var output = new MemoryStream ( ) ;
193+ gzip . CopyTo ( output ) ;
194+ return output . ToArray ( ) ;
195+ }
196+
133197 public static JoinPeerSnapshot CreateLocalSnapshot ( )
134198 {
135199 var cacheStatus = ModelIdSerializationCacheDynamicContentPatch . GetDeterministicCacheStatus ( ) ;
0 commit comments