11using MegaCrit . Sts2 . Core . Entities . Multiplayer ;
22using MegaCrit . Sts2 . Core . GameActions . Multiplayer ;
3+ using MegaCrit . Sts2 . Core . Multiplayer ;
34using MegaCrit . Sts2 . Core . Multiplayer . Messages . Game ;
45using MegaCrit . Sts2 . Core . Multiplayer . Replay ;
56using MegaCrit . Sts2 . Core . Multiplayer . Serialization ;
@@ -10,6 +11,68 @@ namespace STS2RitsuLib.Networking.ManagedActions.Patches
1011{
1112 internal static class RitsuLibManagedNetActionMessagePatches
1213 {
14+ internal sealed class MessageBusSerialize : IPatchMethod
15+ {
16+ public static string PatchId => "ritsulib_managed_net_action_message_bus_serialize" ;
17+ public static bool IsCritical => true ;
18+
19+ public static string Description =>
20+ "Serialize RitsuLib-managed action messages before vanilla action id lookup" ;
21+
22+ public static ModPatchTarget [ ] GetTargets ( )
23+ {
24+ return
25+ [
26+ new ( typeof ( NetMessageBus ) , nameof ( NetMessageBus . SerializeMessage ) ) ,
27+ ] ;
28+ }
29+
30+ public static bool Prefix < T > (
31+ ulong senderId ,
32+ T message ,
33+ ref byte [ ] __result ,
34+ ref int length )
35+ where T : INetMessage
36+ {
37+ if ( ! TrySerializeManagedActionMessage ( senderId , message , out var bytes , out var writtenLength ) )
38+ return true ;
39+
40+ __result = bytes ;
41+ length = writtenLength ;
42+ return false ;
43+ }
44+ }
45+
46+ internal sealed class MessageBusDeserialize : IPatchMethod
47+ {
48+ public static string PatchId => "ritsulib_managed_net_action_message_bus_deserialize" ;
49+ public static bool IsCritical => true ;
50+
51+ public static string Description =>
52+ "Deserialize action queue messages through RitsuLib-managed action reader" ;
53+
54+ public static ModPatchTarget [ ] GetTargets ( )
55+ {
56+ return
57+ [
58+ new ( typeof ( NetMessageBus ) , nameof ( NetMessageBus . TryDeserializeMessage ) ) ,
59+ ] ;
60+ }
61+
62+ public static bool Prefix (
63+ byte [ ] packetBytes ,
64+ ref bool __result ,
65+ out INetMessage ? message ,
66+ out ulong ? overrideSenderId )
67+ {
68+ if ( ! TryDeserializeManagedActionMessage ( packetBytes , out message , out overrideSenderId ) )
69+ return true ;
70+
71+ __result = true ;
72+ return false ;
73+ }
74+ }
75+
1376 internal sealed class RequestSerialize : IPatchMethod
1477 {
1578 public static string PatchId => "ritsulib_managed_net_action_request_serialize" ;
@@ -224,5 +287,82 @@ public static bool Prefix(ref CombatReplayEvent __instance, PacketReader reader)
224287 return false ;
225288 }
226289 }
290+
291+ private static bool TrySerializeManagedActionMessage < T > (
292+ ulong senderId ,
293+ T message ,
294+ out byte [ ] bytes ,
295+ out int length )
296+ where T : INetMessage
297+ {
298+ bytes = [ ] ;
299+ length = 0 ;
300+
301+ var writer = new PacketWriter ( ) ;
302+ switch ( message )
303+ {
304+ case RequestEnqueueActionMessage request
305+ when request . action is RitsuLibManagedNetAction :
306+ writer . WriteByte ( ( byte ) request . ToId ( ) ) ;
307+ writer . WriteULong ( senderId ) ;
308+ writer . Write ( request . location ) ;
309+ RitsuLibManagedNetActions . TryWriteNetAction ( writer , request . action ) ;
310+ break ;
311+
312+ case ActionEnqueuedMessage announcement
313+ when announcement . action is RitsuLibManagedNetAction :
314+ writer . WriteByte ( ( byte ) announcement . ToId ( ) ) ;
315+ writer . WriteULong ( senderId ) ;
316+ writer . WriteULong ( announcement . playerId ) ;
317+ writer . Write ( announcement . location ) ;
318+ RitsuLibManagedNetActions . TryWriteNetAction ( writer , announcement . action ) ;
319+ break ;
320+
321+ default :
322+ return false ;
323+ }
324+
325+ length = ( int ) Math . Ceiling ( writer . BitPosition / 8f ) ;
326+ bytes = writer . Buffer ;
327+ return true ;
328+ }
329+
330+ private static bool TryDeserializeManagedActionMessage (
331+ byte [ ] packetBytes ,
332+ out INetMessage ? message ,
333+ out ulong ? overrideSenderId )
334+ {
335+ message = null ;
336+ overrideSenderId = null ;
337+
338+ var reader = new PacketReader ( ) ;
339+ reader . Reset ( packetBytes ) ;
340+ var messageId = reader . ReadByte ( ) ;
341+ if ( ! MessageTypes . TryGetMessageType ( messageId , out var messageType ) )
342+ return false ;
343+
344+ if ( messageType != typeof ( RequestEnqueueActionMessage ) &&
345+ messageType != typeof ( ActionEnqueuedMessage ) )
346+ return false ;
347+
348+ overrideSenderId = reader . ReadULong ( ) ;
349+ if ( messageType == typeof ( RequestEnqueueActionMessage ) )
350+ {
351+ message = new RequestEnqueueActionMessage
352+ {
353+ location = reader . Read < RunLocation > ( ) ,
354+ action = RitsuLibManagedNetActions . ReadNetAction ( reader ) ,
355+ } ;
356+ return true ;
357+ }
358+
359+ message = new ActionEnqueuedMessage
360+ {
361+ playerId = reader . ReadULong ( ) ,
362+ location = reader . Read < RunLocation > ( ) ,
363+ action = RitsuLibManagedNetActions . ReadNetAction ( reader ) ,
364+ } ;
365+ return true ;
366+ }
227367 }
228368}
0 commit comments