-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathServerRpcSender.cs
More file actions
100 lines (83 loc) · 3.64 KB
/
Copy pathServerRpcSender.cs
File metadata and controls
100 lines (83 loc) · 3.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
using System;
using Cysharp.Threading.Tasks;
using Mirage.Serialization;
namespace Mirage.RemoteCalls
{
/// <summary>
/// Methods used by weaver to send RPCs
/// </summary>
public static class ServerRpcSender
{
public static void Send(NetworkBehaviour behaviour, int relativeIndex, NetworkWriter writer, Channel channelId, bool requireAuthority)
{
var index = behaviour.Identity.RemoteCallCollection.GetIndexOffset(behaviour) + relativeIndex;
Validate(behaviour, index, requireAuthority);
var message = new RpcMessage
{
NetId = behaviour.NetId,
FunctionIndex = index,
Payload = writer.ToArraySegment()
};
behaviour.Client.Send(message, channelId);
}
public static UniTask<T> SendWithReturn<T>(NetworkBehaviour behaviour, int relativeIndex, NetworkWriter writer, bool requireAuthority)
{
var index = behaviour.Identity.RemoteCallCollection.GetIndexOffset(behaviour) + relativeIndex;
Validate(behaviour, index, requireAuthority);
var message = new RpcWithReplyMessage
{
NetId = behaviour.NetId,
FunctionIndex = index,
Payload = writer.ToArraySegment()
};
(var task, var id) = behaviour.ClientObjectManager._rpcHandler.CreateReplyTask<T>();
message.ReplyId = id;
// reply rpcs are always reliable
behaviour.Client.Send(message, Channel.Reliable);
return task;
}
private static void Validate(NetworkBehaviour behaviour, int index, bool requireAuthority)
{
var client = behaviour.Client;
if (client == null || !client.Active)
{
var rpc = behaviour.Identity.RemoteCallCollection.GetRelative(behaviour, index);
throw new InvalidOperationException($"ServerRpc Function {rpc} called on server without an active client.");
}
// if authority is required, then client must have authority to send
if (requireAuthority && !behaviour.HasAuthority)
{
var rpc = behaviour.Identity.RemoteCallCollection.GetRelative(behaviour, index);
throw new InvalidOperationException($"Trying to send ServerRpc for object without authority. {rpc}");
}
if (client.Player == null)
{
throw new InvalidOperationException("Send ServerRpc attempted with no client connection.");
}
}
/// <summary>
/// Used by weaver to check if ClientRPC should be invoked locally in host mode
/// </summary>
/// <param name="behaviour"></param>
/// <param name="target"></param>
/// <param name="player">player used for RpcTarget.Player</param>
/// <returns></returns>
public static bool ShouldInvokeLocally(NetworkBehaviour behaviour, bool requireAuthority)
{
// not client? error
if (!behaviour.IsClient)
{
throw new InvalidOperationException("Server RPC can only be called when client is active");
}
// not host? never invoke locally
if (!behaviour.IsServer)
return false;
// check if auth is required and that host has auth over the object
if (requireAuthority && !behaviour.HasAuthority)
{
throw new InvalidOperationException($"Trying to send ServerRpc for object without authority.");
}
return true;
}
}
}