Skip to content

Commit 93dbcdf

Browse files
committed
feat(Networking): add serialization and deserialization patches for managed action messages
- Implemented MessageBusSerialize and MessageBusDeserialize patches to handle RitsuLib-managed action messages. - Enhanced the message serialization process before vanilla action ID lookup and improved deserialization through a managed action reader. - Updated the patch registration in PatcherSetup to include the new serialization methods.
1 parent 1502f6d commit 93dbcdf

3 files changed

Lines changed: 152 additions & 2 deletions

File tree

‎Combat/Ui/ExtraCornerAmountLabels/ExtraCornerAmountLabelsRuntime.cs‎

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,13 @@ private static void SyncAnchoredSlotHosts(
232232
pool.Add(new());
233233

234234
var entry = pool[writeIndex];
235-
var live = GetOrCreateSlotLabel(host, entry, slotNamePrefix, writeIndex, slot.TextMode);
235+
var live = GetOrCreateSlotLabel(
236+
host,
237+
entry,
238+
slotNamePrefix,
239+
writeIndex,
240+
slot.TextMode,
241+
applyHostStyle);
236242
applyHostStyle(live);
237243
ApplySlotColorOverrides(live, in slot);
238244

@@ -253,7 +259,8 @@ private static Control GetOrCreateSlotLabel(
253259
AnchoredSlotHost entry,
254260
string slotNamePrefix,
255261
int slotIndex,
256-
ExtraIconAmountLabelTextMode textMode)
262+
ExtraIconAmountLabelTextMode textMode,
263+
Action<Control> applyHostStyle)
257264
{
258265
if (GodotObject.IsInstanceValid(entry.Label) && entry.TextMode == textMode &&
259266
LabelMatchesTextMode(entry.Label, textMode))
@@ -263,6 +270,7 @@ private static Control GetOrCreateSlotLabel(
263270
entry.Label!.QueueFree();
264271

265272
var label = CreateSlotLabel($"{slotNamePrefix}{slotIndex}", textMode);
273+
applyHostStyle(label);
266274
host.AddChild(label);
267275
host.MoveChild(label, host.GetChildCount() - 1);
268276
entry.Label = label;

‎Networking/ManagedActions/Patches/RitsuLibManagedNetActionMessagePatches.cs‎

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using MegaCrit.Sts2.Core.Entities.Multiplayer;
22
using MegaCrit.Sts2.Core.GameActions.Multiplayer;
3+
using MegaCrit.Sts2.Core.Multiplayer;
34
using MegaCrit.Sts2.Core.Multiplayer.Messages.Game;
45
using MegaCrit.Sts2.Core.Multiplayer.Replay;
56
using 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
}

‎RitsuLibFramework.PatcherSetup.cs‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,8 @@ private static void RegisterLifecyclePatches()
175175
patcher.RegisterPatch<RitsuLibSidecarNativeTrailerSteamSendPatch>();
176176
patcher.RegisterPatch<RitsuLibSidecarSyncNetBufferPatch>();
177177
patcher.RegisterPatch<RitsuLibSidecarSyncLocationChangedPatch>();
178+
patcher.RegisterPatch<RitsuLibManagedNetActionMessagePatches.MessageBusSerialize>();
179+
patcher.RegisterPatch<RitsuLibManagedNetActionMessagePatches.MessageBusDeserialize>();
178180
patcher.RegisterPatch<RitsuLibManagedNetActionMessagePatches.RequestSerialize>();
179181
patcher.RegisterPatch<RitsuLibManagedNetActionMessagePatches.RequestDeserialize>();
180182
patcher.RegisterPatch<RitsuLibManagedNetActionMessagePatches.AnnouncementSerialize>();

0 commit comments

Comments
 (0)