Inventory management focused game written in Godot / C#
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

55 lines
2.7 KiB

public class RPC
{
readonly IEnumerable<int> _targets; // null for "everyone"
IEnumerable<int> _except = null;
RPC(IEnumerable<int> targets) => _targets = targets;
public static RPC ToAll() => new(null);
public static RPC To(IEnumerable<int> peerIds) => new(peerIds);
public static RPC To(params int[] peerIds) => To((IEnumerable<int>)peerIds);
public static RPC To(int peerId) => To([ peerId ]);
public static RPC To(IEnumerable<Player> players) => To(players.Select(p => p.PeerId));
public static RPC To(params Player[] players) => To((IEnumerable<Player>)players);
public static RPC To(Player player) => To(player.PeerId);
public RPC Except(IEnumerable<int> peerIds) { _except = peerIds; return this; }
public RPC Except(params int[] peerIds) => Except((IEnumerable<int>)peerIds);
public RPC Except(int peerId) => Except([ peerId ]);
public RPC Except(IEnumerable<Player> players) => Except(players.Select(p => p.PeerId));
public RPC Except(params Player[] players) => Except((IEnumerable<Player>)players);
public RPC Except(Player player) => Except(player.PeerId);
public void Send(Action action)
=> SendInternal(GetNode(action), action.Method.Name, []);
public void Send<[MustBeVariant] T>(Action<T> action, T arg)
=> SendInternal(GetNode(action), action.Method.Name, Variant.From(arg));
public void Send<[MustBeVariant] T0, [MustBeVariant] T1>(Action<T0, T1> action, T0 arg0, T1 arg1)
=> SendInternal(GetNode(action), action.Method.Name, Variant.From(arg0), Variant.From(arg1));
public void Send<[MustBeVariant] T0, [MustBeVariant] T1, [MustBeVariant] T2>(Action<T0, T1, T2> action, T0 arg0, T1 arg1, T2 arg2)
=> SendInternal(GetNode(action), action.Method.Name, Variant.From(arg0), Variant.From(arg1), Variant.From(arg2));
public void Send<[MustBeVariant] T0, [MustBeVariant] T1, [MustBeVariant] T2, [MustBeVariant] T3>(Action<T0, T1, T2, T3> action, T0 arg0, T1 arg1, T2 arg2, T3 arg3)
=> SendInternal(GetNode(action), action.Method.Name, Variant.From(arg0), Variant.From(arg1), Variant.From(arg2), Variant.From(arg3));
/// <summary> Returns the target of the instance method <paramref name="action"/> as a <see cref="Node"/>. </summary>
static Node GetNode(Delegate action)
=> (action.Target as Node) ?? throw new ArgumentException(
$"Target ({action.Target?.GetType().ToString() ?? "null"}) must be a Node", nameof(action));
void SendInternal(Node node, StringName method, params Variant[] args)
{
if ((_targets == null) && (_except == null))
node.Rpc(method, args);
else {
var targets = _targets ?? node.Multiplayer.GetPeers();
if (_except != null) targets = targets.Except(_except);
foreach (var target in targets)
node.RpcId(target, method, args);
}
}
}