mirror of
https://github.com/Facepunch/sbox-public.git
synced 2026-01-02 11:28:19 -05:00
This commit imports the C# engine code and game files, excluding C++ source code. [Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
121 lines
3.3 KiB
C#
121 lines
3.3 KiB
C#
using System.ComponentModel;
|
|
|
|
namespace Sandbox;
|
|
|
|
public static partial class Rpc
|
|
{
|
|
/// <summary>
|
|
/// A static RPC call is incoming from the network. Look up the method and call it.
|
|
/// </summary>
|
|
internal static void IncomingStaticRpcMsg( StaticRpcMsg message, Connection source )
|
|
{
|
|
NetworkDebugSystem.Current?.Record( NetworkDebugSystem.MessageType.Rpc, message );
|
|
|
|
if ( Game.TypeLibrary.GetMemberByIdent( message.MethodIdentity ) is not MethodDescription method )
|
|
{
|
|
throw new( $"Unknown Static RPC type for method with identity '{message.MethodIdentity}'" );
|
|
}
|
|
|
|
if ( !method.HasAttribute<RpcAttribute>() )
|
|
{
|
|
source.Kick( "Unauthorized RPC" );
|
|
return;
|
|
}
|
|
|
|
NetworkDebugSystem.Current?.Track( $"{method.TypeDescription.FullName}.{method.Name}", message );
|
|
|
|
using ( WithCaller( source ) )
|
|
{
|
|
try
|
|
{
|
|
method.Invoke( null, message.Arguments );
|
|
}
|
|
catch ( Exception e )
|
|
{
|
|
Log.Error( e, $"Error calling RPC '{method.TypeDescription.FullName}.{method.Name}' - {e.Message}" );
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when a static RPC is called
|
|
/// </summary>
|
|
[EditorBrowsable( EditorBrowsableState.Never )]
|
|
public static void OnCallRpc( WrappedMethod m, params object[] argumentList )
|
|
{
|
|
var attribute = m.GetAttribute<RpcAttribute>();
|
|
if ( attribute is null ) return;
|
|
|
|
//
|
|
// Send over network
|
|
//
|
|
if ( !Calling && Networking.IsActive )
|
|
{
|
|
SendStaticRpc( m, argumentList, attribute );
|
|
}
|
|
|
|
// Was filtered out
|
|
if ( Filter.HasValue && !Filter.Value.IsRecipient( Connection.Local ) ) return;
|
|
|
|
// Was not included in the filter
|
|
if ( attribute.Mode == RpcMode.Owner && !Networking.IsHost ) return;
|
|
if ( attribute.Mode == RpcMode.Host && !Networking.IsHost ) return;
|
|
|
|
PreCall();
|
|
|
|
// Can they even call this shit
|
|
if ( !HasStaticPermission( Caller ?? Connection.Local, attribute.Flags ) ) return;
|
|
|
|
Resume( m );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Does the current caller have permission to invoke the RPC?
|
|
/// </summary>
|
|
static bool HasStaticPermission( Connection caller, NetFlags permission )
|
|
{
|
|
if ( (permission.Contains( NetFlags.HostOnly ) || permission.Contains( NetFlags.OwnerOnly )) && !caller.IsHost )
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Do the actual send of the static RPC.
|
|
/// </summary>
|
|
private static void SendStaticRpc( WrappedMethod m, object[] argumentList, RpcAttribute attribute )
|
|
{
|
|
var networkSystem = SceneNetworkSystem.Instance;
|
|
if ( networkSystem is null )
|
|
{
|
|
Log.Warning( "SceneNetworkSystem.Instance is null when sending RPC" );
|
|
return;
|
|
}
|
|
|
|
//
|
|
// To everyone
|
|
//
|
|
if ( attribute.Mode == RpcMode.Broadcast )
|
|
{
|
|
var msg = new StaticRpcMsg { MethodIdentity = m.MethodIdentity, Arguments = argumentList };
|
|
networkSystem.Broadcast( msg, Filter, attribute.Flags );
|
|
return;
|
|
}
|
|
|
|
//
|
|
// To the host (statics can't have an owner)
|
|
//
|
|
if ( attribute.Mode is RpcMode.Owner or RpcMode.Host )
|
|
{
|
|
if ( Networking.IsHost ) return; // don't send to ourselves
|
|
|
|
var targetId = Connection.Host?.Id ?? Guid.Empty;
|
|
if ( targetId == Connection.Local.Id ) return; // don't send to ourselves
|
|
if ( targetId == Guid.Empty ) return; // don't send to no-one
|
|
|
|
var msg = new StaticRpcMsg { MethodIdentity = m.MethodIdentity, Arguments = argumentList };
|
|
networkSystem.Send( targetId, msg, attribute.Flags );
|
|
}
|
|
}
|
|
}
|