mirror of
https://github.com/D1GQ/BetterAmongUs.git
synced 2026-10-20 01:46:19 +00:00
157 lines
5.8 KiB
C#
157 lines
5.8 KiB
C#
using AmongUs.Data;
|
|
using BetterAmongUs.Enums;
|
|
using BetterAmongUs.Helpers;
|
|
using BetterAmongUs.Modules;
|
|
using BetterAmongUs.Mono;
|
|
using Hazel;
|
|
|
|
namespace BetterAmongUs.Network;
|
|
|
|
/// <summary>
|
|
/// Handles custom RPC (Remote Procedure Call) messages for BetterAmongUs.
|
|
/// This class provides methods for sending and receiving custom RPC messages
|
|
/// packed within vanilla RPC calls to maintain compatibility with vanilla servers.
|
|
/// </summary>
|
|
internal static class RPC
|
|
{
|
|
/// <summary>
|
|
/// The flag string used to identify custom RPC messages packed within vanilla RPC calls.
|
|
/// </summary>
|
|
internal const string CUSTOM_RPC_FLAG = "bau:rpc";
|
|
|
|
/// <summary>
|
|
/// Sends a custom RPC message packed within a vanilla SetNamePlateStr RPC call.
|
|
/// This method is used to maintain compatibility with vanilla Among Us servers
|
|
/// while allowing custom RPC communication.
|
|
/// </summary>
|
|
/// <param name="customRPC">The custom RPC type to send.</param>
|
|
/// <param name="action">A delegate that writes the custom RPC payload to the message writer.</param>
|
|
/// <param name="targetClientId">The specific client ID to target, or -1 to broadcast to all clients.</param>
|
|
internal static void SendCustomRpcPacked(CustomRPC customRPC, Action<MessageWriter> action, int targetClientId = -1)
|
|
{
|
|
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(CUSTOM_RPC_FLAG); // Flag to check if its a rpc packed into SetNamePlateStr
|
|
writer.Write((byte)customRPC);
|
|
action(writer);
|
|
}, targetClientId);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Handles incoming custom RPC messages by extracting and processing them
|
|
/// from the packed SetNamePlateStr RPC call.
|
|
/// </summary>
|
|
/// <param name="player">The player who sent the RPC message.</param>
|
|
/// <param name="oldReader">The message reader containing the RPC data.</param>
|
|
internal static void HandleCustomRPCPacked(PlayerControl player, MessageReader oldReader)
|
|
{
|
|
if (player == null || player.IsLocalPlayer() || player.Data == null)
|
|
return;
|
|
|
|
MessageReader reader = MessageReader.Get(oldReader);
|
|
|
|
_ = reader.ReadString();
|
|
_ = reader.ReadByte();
|
|
|
|
if (IsPackedCustomRpc(reader))
|
|
{
|
|
CustomRPC customRPC = (CustomRPC)reader.ReadByte();
|
|
switch (customRPC)
|
|
{
|
|
case CustomRPC.SendSecretToPlayer:
|
|
{
|
|
player.BetterData().HandshakeHandler.HandleSecretFromSender(reader);
|
|
}
|
|
break;
|
|
case CustomRPC.CheckSecretHashFromPlayer:
|
|
{
|
|
player.BetterData().HandshakeHandler.HandleSecretHashFromPlayer(reader);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
reader.Recycle();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Processes custom RPC messages received from other players.
|
|
/// </summary>
|
|
/// <param name="player">The player who sent the RPC.</param>
|
|
/// <param name="callId">The ID of the RPC call.</param>
|
|
/// <param name="oldReader">The message reader containing the RPC data.</param>
|
|
/// <remarks>
|
|
/// Handles both defined custom RPCs and protects against unknown RPCs in modded lobbies.
|
|
/// </remarks>
|
|
internal static void HandleCustomRPCLegacy(PlayerControl player, byte callId, MessageReader oldReader)
|
|
{
|
|
if (player == null || player.IsLocalPlayer() || player.Data == null || Enum.IsDefined(typeof(RpcCalls), callId))
|
|
return;
|
|
|
|
if (Enum.IsDefined(typeof(CustomRPC), (int)unchecked(callId)))
|
|
{
|
|
MessageReader reader = MessageReader.Get(oldReader);
|
|
|
|
switch (callId)
|
|
{
|
|
case (byte)CustomRPC.SendSecretToPlayer:
|
|
{
|
|
player.BetterData().HandshakeHandler.HandleSecretFromSender(reader);
|
|
}
|
|
break;
|
|
case (byte)CustomRPC.CheckSecretHashFromPlayer:
|
|
{
|
|
player.BetterData().HandshakeHandler.HandleSecretHashFromPlayer(reader);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else if (!Enum.IsDefined(typeof(CustomRPC), (int)unchecked(callId)))
|
|
{
|
|
try
|
|
{
|
|
if (!GameState.IsHost)
|
|
{
|
|
if (player.IsHost())
|
|
{
|
|
var Icon = Translator.GetString("BAUMark");
|
|
var BAU = $"<color=#278720>{Icon}</color><color=#0ed400><b>{Translator.GetString("BAU")}</b></color><color=#278720>{Icon}</color>";
|
|
Utils.DisconnectSelf(string.Format(Translator.GetString("ModdedLobbyMsg"), BAU));
|
|
}
|
|
}
|
|
}
|
|
catch { }
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Determines whether a MessageReader contains a packed custom RPC message.
|
|
/// </summary>
|
|
/// <param name="reader">The MessageReader to check for custom RPC content.</param>
|
|
/// <returns>
|
|
/// <c>true</c> if the reader contains a custom RPC flag and custom RPC data;
|
|
/// otherwise, <c>false</c>.
|
|
/// </returns>
|
|
internal static bool IsPackedCustomRpc(MessageReader reader)
|
|
{
|
|
if (reader.BytesRemaining > 0)
|
|
{
|
|
try
|
|
{
|
|
if (reader.ReadString() == CUSTOM_RPC_FLAG)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
} |