Add type-safe wrapper around Rpc methods

main
copygirl 4 years ago
parent 2c63e07911
commit d66f16c1aa
  1. 7
      src/EscapeMenuAppearance.cs
  2. 1
      src/EscapeMenuWorld.cs
  3. 4
      src/IO/WorldSave.cs
  4. 8
      src/Items/CreativeBuilding.cs
  5. 8
      src/Items/Items.cs
  6. 12
      src/Items/Weapon.cs
  7. 2
      src/Objects/LocalPlayer.cs
  8. 1
      src/Objects/Player.cs
  9. 12
      src/Scenes/Server.cs
  10. 44
      src/Utility/RPC.cs

@ -20,8 +20,8 @@ public class EscapeMenuAppearance : CenterContainer
ColorSlider.Value = GD.Randf(); ColorSlider.Value = GD.Randf();
ColorPreview.Modulate = Color.FromHsv((float)ColorSlider.Value, 1.0F, 1.0F); ColorPreview.Modulate = Color.FromHsv((float)ColorSlider.Value, 1.0F, 1.0F);
this.GetClient().LocalPlayerSpawned += (player) => player.RpcId(1, this.GetClient().LocalPlayerSpawned += (player)
nameof(Player.ChangeAppearance), DisplayName.Text, ColorPreview.Modulate); => RPC.Reliable(1, player.ChangeAppearance, DisplayName.Text, ColorPreview.Modulate);
} }
#pragma warning disable IDE0051 #pragma warning disable IDE0051
@ -49,7 +49,6 @@ public class EscapeMenuAppearance : CenterContainer
if (IsVisibleInTree()) return; if (IsVisibleInTree()) return;
var client = this.GetClient(); var client = this.GetClient();
if (client.Status == NetworkedMultiplayerPeer.ConnectionStatus.Connected) if (client.Status == NetworkedMultiplayerPeer.ConnectionStatus.Connected)
client.LocalPlayer.RpcId(1, nameof(Player.ChangeAppearance), RPC.Reliable(1, client.LocalPlayer.ChangeAppearance, DisplayName.Text, ColorPreview.Modulate);
DisplayName.Text, ColorPreview.Modulate);
} }
} }

@ -105,6 +105,7 @@ public class EscapeMenuWorld : CenterContainer
// Reset players' positions. // Reset players' positions.
foreach (var player in server.GetWorld().Players) foreach (var player in server.GetWorld().Players)
// Can't use RPC helper method here since player is not a LocalPlayer here.
player.RpcId(player.NetworkID, nameof(LocalPlayer.ResetPosition), Vector2.Zero); player.RpcId(player.NetworkID, nameof(LocalPlayer.ResetPosition), Vector2.Zero);
save.ReadDataIntoWorld(server.GetWorld()); save.ReadDataIntoWorld(server.GetWorld());

@ -75,8 +75,8 @@ public class WorldSave
public void ReadDataIntoWorld(World world) public void ReadDataIntoWorld(World world)
{ {
world.Rpc(nameof(World.ClearBlocks)); RPC.Reliable(world.ClearBlocks);
foreach (var (position, color, unbreakable) in Blocks) foreach (var (position, color, unbreakable) in Blocks)
world.Rpc(nameof(World.SpawnBlock), position.X, position.Y, color, unbreakable); RPC.Reliable(world.SpawnBlock, position.X, position.Y, color, unbreakable);
} }
} }

@ -57,14 +57,14 @@ public class CreativeBuilding : Node2D
if (_currentMode == BuildMode.Placing) { if (_currentMode == BuildMode.Placing) {
if (!_canBuild) _currentMode = null; if (!_canBuild) _currentMode = null;
else if (!Input.IsActionPressed("interact_primary")) { else if (!Input.IsActionPressed("interact_primary")) {
RpcId(1, nameof(PlaceLine), _startPos.X, _startPos.Y, _direction, _length); RPC.Reliable(1, PlaceLine, _startPos.X, _startPos.Y, _direction, _length);
_currentMode = null; _currentMode = null;
} }
} }
if (_currentMode == BuildMode.Breaking) { if (_currentMode == BuildMode.Breaking) {
if (!Input.IsActionPressed("interact_secondary")) { if (!Input.IsActionPressed("interact_secondary")) {
RpcId(1, nameof(BreakLine), _startPos.X, _startPos.Y, _direction, _length); RPC.Reliable(1, BreakLine, _startPos.X, _startPos.Y, _direction, _length);
_currentMode = null; _currentMode = null;
} }
} }
@ -121,7 +121,7 @@ public class CreativeBuilding : Node2D
foreach (var pos in GetBlockPositions(start, direction, length)) { foreach (var pos in GetBlockPositions(start, direction, length)) {
if (world.GetBlockAt(pos) != null) continue; if (world.GetBlockAt(pos) != null) continue;
var color = Player.Color.Blend(Color.FromHsv(0.0F, 0.0F, GD.Randf(), 0.2F)); var color = Player.Color.Blend(Color.FromHsv(0.0F, 0.0F, GD.Randf(), 0.2F));
world.Rpc(nameof(World.SpawnBlock), pos.X, pos.Y, color, false); RPC.Reliable(world.SpawnBlock, pos.X, pos.Y, color, false);
} }
} }
@ -137,7 +137,7 @@ public class CreativeBuilding : Node2D
foreach (var pos in GetBlockPositions(start, direction, length)) { foreach (var pos in GetBlockPositions(start, direction, length)) {
var block = world.GetBlockAt(pos); var block = world.GetBlockAt(pos);
if (block?.Unbreakable != false) continue; if (block?.Unbreakable != false) continue;
world.Rpc(nameof(World.Despawn), world.GetPathTo(block)); RPC.Reliable(world.Despawn, world.GetPathTo(block));
} }
} }
} }

@ -39,16 +39,14 @@ public class Items : Node2D, IItems
_current = node; _current = node;
if (sendRpc) { if (sendRpc) {
if (this.GetGame() is Server) Rpc(nameof(DoSetCurrent), _current?.Name); if (this.GetGame() is Server) RPC.Reliable(DoSetCurrent, _current?.Name);
else RpcId(1, nameof(DoSetCurrent), _current?.Name); else RPC.Reliable(1, DoSetCurrent, _current?.Name);
} }
} }
[Remote] [Remote]
public void DoSetCurrent(string name) public void DoSetCurrent(string name)
{ {
if (this.GetGame() is Server) { if ((this.GetGame() is Server) && (Player.NetworkID != GetTree().GetRpcSenderId())) return;
if (GetTree().GetRpcSenderId() != Player.NetworkID) return;
}
var node = (name != null) ? GetNode<Node2D>(name) : null; var node = (name != null) ? GetNode<Node2D>(name) : null;
SetCurrent(node, this.GetGame() is Server); SetCurrent(node, this.GetGame() is Server);
} }

@ -125,7 +125,7 @@ public class Weapon : Sprite
AimDirection = Cursor.Position.AngleToPoint(Player.Position) - angleC; AimDirection = Cursor.Position.AngleToPoint(Player.Position) - angleC;
// FIXME: Angle calculation when cursor is too close to player. // FIXME: Angle calculation when cursor is too close to player.
RpcUnreliableId(1, nameof(SendAimAngle), AimDirection); RPC.Unreliable(1, SendAimAngle, AimDirection);
Update(); Update();
} }
} else { } else {
@ -147,7 +147,7 @@ public class Weapon : Sprite
if (Player.NetworkID != GetTree().GetRpcSenderId()) return; if (Player.NetworkID != GetTree().GetRpcSenderId()) return;
// TODO: Verify input. // TODO: Verify input.
// if ((value < 0) || (value > Mathf.Tau)) return; // if ((value < 0) || (value > Mathf.Tau)) return;
Rpc(nameof(SendAimAngle), value); RPC.Unreliable(SendAimAngle, value);
} else if (!(Player is LocalPlayer)) } else if (!(Player is LocalPlayer))
AimDirection = value; AimDirection = value;
} }
@ -157,7 +157,7 @@ public class Weapon : Sprite
{ {
var seed = unchecked((int)GD.Randi()); var seed = unchecked((int)GD.Randi());
if (!FireInternal(AimDirection, Scale.y > 0, seed)) return; if (!FireInternal(AimDirection, Scale.y > 0, seed)) return;
RpcId(1, nameof(SendFire), AimDirection, Scale.y > 0, seed); RPC.Reliable(1, SendFire, AimDirection, Scale.y > 0, seed);
((LocalPlayer)Player).Velocity -= Mathf.Polar2Cartesian(Knockback, Rotation); ((LocalPlayer)Player).Velocity -= Mathf.Polar2Cartesian(Knockback, Rotation);
} }
@ -198,14 +198,14 @@ public class Weapon : Sprite
if (Player.NetworkID != GetTree().GetRpcSenderId()) return; if (Player.NetworkID != GetTree().GetRpcSenderId()) return;
// TODO: Verify input. // TODO: Verify input.
if (FireInternal(aimDirection, toRight, seed)) if (FireInternal(aimDirection, toRight, seed))
Rpc(nameof(SendFire), aimDirection, toRight, seed); RPC.Reliable(SendFire, aimDirection, toRight, seed);
} else if (!(Player is LocalPlayer)) } else if (!(Player is LocalPlayer))
FireInternal(aimDirection, toRight, seed); FireInternal(aimDirection, toRight, seed);
} }
private void Reload() private void Reload()
{ if (ReloadInternal()) RpcId(1, nameof(SendReload)); } { if (ReloadInternal()) RPC.Reliable(1, SendReload); }
private bool ReloadInternal() private bool ReloadInternal()
{ {
@ -220,7 +220,7 @@ public class Weapon : Sprite
{ {
if (this.GetGame() is Server) { if (this.GetGame() is Server) {
if (Player.NetworkID != GetTree().GetRpcSenderId()) return; if (Player.NetworkID != GetTree().GetRpcSenderId()) return;
if (ReloadInternal()) Rpc(nameof(SendReload)); if (ReloadInternal()) RPC.Reliable(SendReload);
} else if (!(Player is LocalPlayer)) } else if (!(Player is LocalPlayer))
ReloadInternal(); ReloadInternal();
} }

@ -23,7 +23,7 @@ public class LocalPlayer : Player
public override void _Process(float delta) public override void _Process(float delta)
{ {
base._Process(delta); base._Process(delta);
RpcUnreliableId(1, nameof(Player.Move), Position); RPC.Unreliable(1, Move, Position);
} }
public override void _PhysicsProcess(float delta) public override void _PhysicsProcess(float delta)

@ -31,6 +31,7 @@ public class Player : KinematicBody2D, IInitializable
public override void _Process(float delta) public override void _Process(float delta)
{ {
if ((Position.y > 9000) && (this.GetGame() is Server)) if ((Position.y > 9000) && (this.GetGame() is Server))
// Can't use RPC helper method here since player is not a LocalPlayer here.
RpcId(NetworkID, nameof(LocalPlayer.ResetPosition), Vector2.Zero); RpcId(NetworkID, nameof(LocalPlayer.ResetPosition), Vector2.Zero);
} }

@ -83,23 +83,23 @@ public class Server : Game
var world = this.GetWorld(); var world = this.GetWorld();
foreach (var player in world.Players) { foreach (var player in world.Players) {
world.RpcId(networkID, nameof(World.SpawnPlayer), player.NetworkID, player.Position); RPC.Reliable(networkID, world.SpawnPlayer, player.NetworkID, player.Position);
// Send player's appearance. // Send player's appearance.
player.Rset(nameof(Player.DisplayName), player.DisplayName); player.Rset(nameof(Player.DisplayName), player.DisplayName);
player.Rset(nameof(Player.Color), player.Color); player.Rset(nameof(Player.Color), player.Color);
// Send player's currently equipped item. // Send player's currently equipped item.
if (player.Items.Current != null) ((Node2D)player.Items).RpcId( if (player.Items.Current != null) RPC.Reliable(networkID,
networkID, nameof(Items.DoSetCurrent), player.Items.Current.Name); ((Items)player.Items).DoSetCurrent, player.Items.Current.Name);
} }
foreach (var block in world.Blocks) foreach (var block in world.Blocks)
world.RpcId(networkID, nameof(World.SpawnBlock), RPC.Reliable(networkID, world.SpawnBlock,
block.Position.X, block.Position.Y, block.Position.X, block.Position.Y,
block.Color, block.Unbreakable); block.Color, block.Unbreakable);
world.Rpc(nameof(World.SpawnPlayer), networkID, Vector2.Zero); RPC.Reliable(world.SpawnPlayer, networkID, Vector2.Zero);
if (IsSingleplayer) LocalPlayer = world.GetPlayer(networkID); if (IsSingleplayer) LocalPlayer = world.GetPlayer(networkID);
} }
} }
@ -112,6 +112,6 @@ public class Server : Game
// Local player stays around for reconnecting. // Local player stays around for reconnecting.
if (LocalPlayer == player) return; if (LocalPlayer == player) return;
world.Rpc(nameof(World.Despawn), world.GetPathTo(player)); RPC.Reliable(world.Despawn, world.GetPathTo(player));
} }
} }

@ -0,0 +1,44 @@
using System;
using Godot;
public static class RPC
{
public static void Reliable(Action action) => GetNode(action).Rpc(action.Method.Name);
public static void Reliable<T>(Action<T> action, T arg) => GetNode(action).Rpc(action.Method.Name, arg);
public static void Reliable<T0, T1>(Action<T0, T1> action, T0 arg0, T1 arg1) => GetNode(action).Rpc(action.Method.Name, arg0, arg1);
public static void Reliable<T0, T1, T2>(Action<T0, T1, T2> action, T0 arg0, T1 arg1, T2 arg2) => GetNode(action).Rpc(action.Method.Name, arg0, arg1, arg2);
public static void Reliable<T0, T1, T2, T3>(Action<T0, T1, T2, T3> action, T0 arg0, T1 arg1, T2 arg2, T3 arg3) => GetNode(action).Rpc(action.Method.Name, arg0, arg1, arg2, arg3);
public static void Reliable<T0, T1, T2, T3, T4>(Action<T0, T1, T2, T3, T4> action, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4) => GetNode(action).Rpc(action.Method.Name, arg0, arg1, arg2, arg3, arg4);
public static void Reliable<T0, T1, T2, T3, T4, T5>(Action<T0, T1, T2, T3, T4, T5> action, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) => GetNode(action).Rpc(action.Method.Name, arg0, arg1, arg2, arg3, arg4, arg5);
public static void Reliable<T0, T1, T2, T3, T4, T5, T6>(Action<T0, T1, T2, T3, T4, T5, T6> action, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) => GetNode(action).Rpc(action.Method.Name, arg0, arg1, arg2, arg3, arg4, arg5, arg6);
public static void Reliable(int networkID, Action action) => GetNode(action).RpcId(networkID, action.Method.Name);
public static void Reliable<T>(int networkID, Action<T> action, T arg) => GetNode(action).RpcId(networkID, action.Method.Name, arg);
public static void Reliable<T0, T1>(int networkID, Action<T0, T1> action, T0 arg0, T1 arg1) => GetNode(action).RpcId(networkID, action.Method.Name, arg0, arg1);
public static void Reliable<T0, T1, T2>(int networkID, Action<T0, T1, T2> action, T0 arg0, T1 arg1, T2 arg2) => GetNode(action).RpcId(networkID, action.Method.Name, arg0, arg1, arg2);
public static void Reliable<T0, T1, T2, T3>(int networkID, Action<T0, T1, T2, T3> action, T0 arg0, T1 arg1, T2 arg2, T3 arg3) => GetNode(action).RpcId(networkID, action.Method.Name, arg0, arg1, arg2, arg3);
public static void Reliable<T0, T1, T2, T3, T4>(int networkID, Action<T0, T1, T2, T3, T4> action, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4) => GetNode(action).RpcId(networkID, action.Method.Name, arg0, arg1, arg2, arg3, arg4);
public static void Reliable<T0, T1, T2, T3, T4, T5>(int networkID, Action<T0, T1, T2, T3, T4, T5> action, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) => GetNode(action).RpcId(networkID, action.Method.Name, arg0, arg1, arg2, arg3, arg4, arg5);
public static void Reliable<T0, T1, T2, T3, T4, T5, T6>(int networkID, Action<T0, T1, T2, T3, T4, T5, T6> action, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) => GetNode(action).RpcId(networkID, action.Method.Name, arg0, arg1, arg2, arg3, arg4, arg5, arg6);
public static void Unreliable(Action action) => GetNode(action).RpcUnreliable(action.Method.Name);
public static void Unreliable<T>(Action<T> action, T arg) => GetNode(action).RpcUnreliable(action.Method.Name, arg);
public static void Unreliable<T0, T1>(Action<T0, T1> action, T0 arg0, T1 arg1) => GetNode(action).RpcUnreliable(action.Method.Name, arg0, arg1);
public static void Unreliable<T0, T1, T2>(Action<T0, T1, T2> action, T0 arg0, T1 arg1, T2 arg2) => GetNode(action).RpcUnreliable(action.Method.Name, arg0, arg1, arg2);
public static void Unreliable<T0, T1, T2, T3>(Action<T0, T1, T2, T3> action, T0 arg0, T1 arg1, T2 arg2, T3 arg3) => GetNode(action).RpcUnreliable(action.Method.Name, arg0, arg1, arg2, arg3);
public static void Unreliable<T0, T1, T2, T3, T4>(Action<T0, T1, T2, T3, T4> action, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4) => GetNode(action).RpcUnreliable(action.Method.Name, arg0, arg1, arg2, arg3, arg4);
public static void Unreliable<T0, T1, T2, T3, T4, T5>(Action<T0, T1, T2, T3, T4, T5> action, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) => GetNode(action).RpcUnreliable(action.Method.Name, arg0, arg1, arg2, arg3, arg4, arg5);
public static void Unreliable<T0, T1, T2, T3, T4, T5, T6>(Action<T0, T1, T2, T3, T4, T5, T6> action, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) => GetNode(action).RpcUnreliable(action.Method.Name, arg0, arg1, arg2, arg3, arg4, arg5, arg6);
public static void Unreliable(int networkID, Action action) => GetNode(action).RpcUnreliableId(networkID, action.Method.Name);
public static void Unreliable<T>(int networkID, Action<T> action, T arg) => GetNode(action).RpcUnreliableId(networkID, action.Method.Name, arg);
public static void Unreliable<T0, T1>(int networkID, Action<T0, T1> action, T0 arg0, T1 arg1) => GetNode(action).RpcUnreliableId(networkID, action.Method.Name, arg0, arg1);
public static void Unreliable<T0, T1, T2>(int networkID, Action<T0, T1, T2> action, T0 arg0, T1 arg1, T2 arg2) => GetNode(action).RpcUnreliableId(networkID, action.Method.Name, arg0, arg1, arg2);
public static void Unreliable<T0, T1, T2, T3>(int networkID, Action<T0, T1, T2, T3> action, T0 arg0, T1 arg1, T2 arg2, T3 arg3) => GetNode(action).RpcUnreliableId(networkID, action.Method.Name, arg0, arg1, arg2, arg3);
public static void Unreliable<T0, T1, T2, T3, T4>(int networkID, Action<T0, T1, T2, T3, T4> action, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4) => GetNode(action).RpcUnreliableId(networkID, action.Method.Name, arg0, arg1, arg2, arg3, arg4);
public static void Unreliable<T0, T1, T2, T3, T4, T5>(int networkID, Action<T0, T1, T2, T3, T4, T5> action, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) => GetNode(action).RpcUnreliableId(networkID, action.Method.Name, arg0, arg1, arg2, arg3, arg4, arg5);
public static void Unreliable<T0, T1, T2, T3, T4, T5, T6>(int networkID, Action<T0, T1, T2, T3, T4, T5, T6> action, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) => GetNode(action).RpcUnreliableId(networkID, action.Method.Name, arg0, arg1, arg2, arg3, arg4, arg5, arg6);
private static Node GetNode(Delegate action) => (action.Target as Node) ?? throw new ArgumentException(
$"Target ({action.Target?.GetType().ToString() ?? "null"}) must be a Node", nameof(action));
}
Loading…
Cancel
Save