diff --git a/src/Helpers/InnerNetClientHelper.cs b/src/Helpers/InnerNetClientHelper.cs
index 3549cc0..ddfafa1 100644
--- a/src/Helpers/InnerNetClientHelper.cs
+++ b/src/Helpers/InnerNetClientHelper.cs
@@ -178,57 +178,40 @@ internal static class InnerNetClientHelper
}
///
- /// Starts the RPC desynchronization process for the given player, call ID, and send option.
+ /// Sends an RPC message immediately to all clients that match the specified target criteria, bypassing standard
+ /// synchronization mechanisms.
///
- /// The InnerNetClient instance.
- /// The network ID of the player.
- /// The RPC call ID.
- /// The send option for the RPC.
- /// The client ID to ignore. Default is -1, which means no client is ignored.
- /// Optional function to filter which clients receive the RPC.
- /// A list of MessageWriter instances for the RPC calls.
- ///
- ///
- /// List<MessageWriter> messageWriter = AmongUsClient.Instance.StartRpcDesync(PlayerNetId, (byte)RpcCalls, SendOption, ClientId);
- /// messageWriter.ForEach(mW => mW.Write("RPC TEST"));
- /// AmongUsClient.Instance.FinishRpcDesync(messageWriter);
- ///
- ///
- internal static List StartRpcDesync(this InnerNetClient client, uint playerNetId, byte callId, SendOption option, int ignoreClientId = -1, Func? clientCheck = null)
+ /// The InnerNetClient instance used to send the RPC messages.
+ /// The network ID of the player on whose behalf the RPC is sent.
+ /// The identifier for the RPC call to be executed.
+ /// The send option that determines how the message is delivered (e.g., reliability, ordering).
+ /// A function that selects which clients should receive the RPC message. The RPC is sent only to clients for which
+ /// this function returns .
+ /// An action that writes the RPC payload to the provided MessageWriter.
+ internal static void SendRpcImmediatelyDesync(this InnerNetClient client, uint playerNetId, RpcCalls callId, SendOption option, Func targetClients, Action writeTo)
{
- List messageWriters = [];
-
- if (ignoreClientId < 0)
+ foreach (var allClients in AmongUsClient.Instance.allClients)
{
- messageWriters.Add(client.StartRpcImmediately(playerNetId, callId, option, -1));
- }
- else
- {
- foreach (var allClients in AmongUsClient.Instance.allClients.WhereIl2Cpp(c => c.Id != ignoreClientId))
- {
- if (clientCheck == null || clientCheck.Invoke(allClients))
- {
- messageWriters.Add(client.StartRpcImmediately(playerNetId, callId, option, allClients.Id));
- }
- }
- }
+ if (!targetClients(allClients)) continue;
- return messageWriters;
+ client.SendRpcImmediately(playerNetId, callId, option, writeTo, allClients.Id);
+ }
}
///
- /// Completes and sends the RPC desynchronization messages.
+ /// Sends a remote procedure call (RPC) message immediately to the specified player, using the provided message
+ /// writer action and send option.
///
- /// The InnerNetClient instance.
- /// The list of MessageWriters to finish and send.
- internal static void FinishRpcDesync(this InnerNetClient client, List messageWriters)
+ /// The InnerNetClient instance used to send the RPC message.
+ /// The network identifier of the target player to whom the RPC is sent.
+ /// The identifier of the RPC call to invoke.
+ /// The send option that determines how the message is delivered (such as reliability or channel).
+ /// An action that writes the RPC message content to the provided MessageWriter.
+ /// The client identifier of the specific target client. Use -1 to broadcast to all clients.
+ internal static void SendRpcImmediately(this InnerNetClient client, uint playerNetId, RpcCalls callId, SendOption option, Action writeTo, int targetClientId = -1)
{
- foreach (var msg in messageWriters)
- {
- msg.EndMessage();
- msg.EndMessage();
- client.SendOrDisconnect(msg);
- msg.Recycle();
- }
+ var writer = client.StartRpcImmediately(playerNetId, (byte)callId, option, targetClientId);
+ writeTo(writer);
+ client.FinishRpcImmediately(writer);
}
}
\ No newline at end of file
diff --git a/src/Network/RPC.cs b/src/Network/RPC.cs
index 879866f..fc27b30 100644
--- a/src/Network/RPC.cs
+++ b/src/Network/RPC.cs
@@ -29,15 +29,15 @@ internal static class RPC
/// The specific client ID to target, or -1 to broadcast to all clients.
internal static void SendCustomRpcPacked(CustomRPC customRPC, Action action, int targetClientId = -1)
{
- var writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)RpcCalls.SetNamePlateStr, SendOption.Reliable, targetClientId);
+ AmongUsClient.Instance.SendRpcImmediately(PlayerControl.LocalPlayer.NetId, RpcCalls.SetNamePlateStr, SendOption.Reliable, writer =>
+ {
+ writer.Write(DataManager.Player.Customization.NamePlate);
+ writer.Write(PlayerControl.LocalPlayer.GetNextRpcSequenceId(RpcCalls.SetNamePlateStr));
- writer.Write(DataManager.Player.Customization.NamePlate);
- writer.Write(PlayerControl.LocalPlayer.GetNextRpcSequenceId(RpcCalls.SetNamePlateStr));
-
- writer.Write(CUSTOM_RPC_FLAG); // Flag to check if its a rpc packed into SetNamePlateStr
- writer.Write((byte)customRPC);
- action(writer);
- AmongUsClient.Instance.FinishRpcImmediately(writer);
+ writer.Write(CUSTOM_RPC_FLAG); // Flag to check if its a rpc packed into SetNamePlateStr
+ writer.Write((byte)customRPC);
+ action(writer);
+ }, targetClientId);
}
///
diff --git a/src/Patches/Gameplay/Managers/RoleManagerPatch.cs b/src/Patches/Gameplay/Managers/RoleManagerPatch.cs
index 44e6d14..512c2ad 100644
--- a/src/Patches/Gameplay/Managers/RoleManagerPatch.cs
+++ b/src/Patches/Gameplay/Managers/RoleManagerPatch.cs
@@ -15,11 +15,14 @@ internal static class RoleManagerPatch
internal static Dictionary ImpostorMultiplier = []; // HashPuid, Multiplier
private static readonly Random random = new();
- // Check if client is not verified Better Among Us user
- static readonly Func clientCheck = (clientData) =>
+ // Check if client is verified Better Among Us user
+ private static Func SendTo(PlayerControl target)
{
- return clientData?.BetterData()?.IsVerifiedBetterUser != true;
- };
+ return (clientData) =>
+ {
+ return clientData.Id != target.GetClientId() && clientData?.BetterData()?.IsVerifiedBetterUser != true;
+ };
+ }
[HarmonyPatch(typeof(RoleManager), nameof(RoleManager.SetRole))]
[HarmonyPrefix]
@@ -156,10 +159,11 @@ internal static class RoleManagerPatch
{
if (kvp.Key is not (RoleTypes.Phantom or RoleTypes.Viper))
{
- List messageWriter = AmongUsClient.Instance.StartRpcDesync(pc.NetId, (byte)RpcCalls.SetRole, SendOption.None, pc.GetClientId(), clientCheck);
- messageWriter.ForEach(mW => mW.Write((ushort)RoleTypes.Impostor));
- messageWriter.ForEach(mW => mW.Write(false));
- AmongUsClient.Instance.FinishRpcDesync(messageWriter);
+ AmongUsClient.Instance.SendRpcImmediatelyDesync(pc.NetId, RpcCalls.SetRole, SendOption.None, SendTo(pc), writer =>
+ {
+ writer.Write((ushort)RoleTypes.Impostor);
+ writer.Write(false);
+ });
}
}
@@ -195,10 +199,11 @@ internal static class RoleManagerPatch
{
if (kvp.Key is not RoleTypes.Noisemaker)
{
- List messageWriter = AmongUsClient.Instance.StartRpcDesync(pc.NetId, (byte)RpcCalls.SetRole, SendOption.None, pc.GetClientId(), clientCheck);
- messageWriter.ForEach(mW => mW.Write((ushort)RoleTypes.Crewmate));
- messageWriter.ForEach(mW => mW.Write(false));
- AmongUsClient.Instance.FinishRpcDesync(messageWriter);
+ AmongUsClient.Instance.SendRpcImmediatelyDesync(pc.NetId, RpcCalls.SetRole, SendOption.None, SendTo(pc), writer =>
+ {
+ writer.Write((ushort)RoleTypes.Crewmate);
+ writer.Write(false);
+ });
}
}
@@ -352,10 +357,11 @@ internal static class RoleManagerPatch
// Desync ghost role to hide it from non-BAU players
if (BetterGameSettings.DesyncRoles.GetBool())
{
- List messageWriter = AmongUsClient.Instance.StartRpcDesync(player.NetId, (byte)RpcCalls.SetRole, SendOption.None, player.GetClientId(), clientCheck);
- messageWriter.ForEach(mW => mW.Write((ushort)player.Data.Role.DefaultGhostRole));
- messageWriter.ForEach(mW => mW.Write(false));
- AmongUsClient.Instance.FinishRpcDesync(messageWriter);
+ AmongUsClient.Instance.SendRpcImmediatelyDesync(player.NetId, RpcCalls.SetRole, SendOption.None, SendTo(player), writer =>
+ {
+ writer.Write((ushort)player.Data.Role.DefaultGhostRole);
+ writer.Write(false);
+ });
}
return false;