Sync appearance / held item

- Send appearance to server on connect
- Server now sends held items
  to newly connected players
- Simplify World.SpawnPlayer/Block
- Add Items property to Player
main
copygirl 4 years ago
parent 2371574766
commit 537cdeb9db
  1. 6
      src/EscapeMenuAppearance.cs
  2. 2
      src/HUD/RadialMenu.cs
  3. 8
      src/Items/Items.cs
  4. 2
      src/Objects/Player.cs
  5. 4
      src/Scenes/Client.cs
  6. 24
      src/Scenes/Server.cs
  7. 19
      src/World.cs

@ -20,10 +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);
// FIXME: LocalPlayer hasn't spawned yet on connection. this.GetClient().LocalPlayerSpawned += (player) => player.RpcId(1,
// var client = this.GetClient(); nameof(Player.ChangeAppearance), DisplayName.Text, ColorPreview.Modulate);
// client.Connected += () => client.LocalPlayer.RpcId(1,
// nameof(Player.ChangeAppearance), DisplayName.Text, ColorPreview.Modulate);
} }
#pragma warning disable IDE0051 #pragma warning disable IDE0051

@ -25,7 +25,7 @@ public class RadialMenu : Node2D
} }
public IItems GetItems() public IItems GetItems()
=> this.GetClient().LocalPlayer?.GetNode<IItems>("Items"); => this.GetClient().LocalPlayer?.Items;
public override void _UnhandledInput(InputEvent ev) public override void _UnhandledInput(InputEvent ev)
{ {

@ -15,6 +15,8 @@ public class Items : Node2D, IItems
{ {
[Export] public NodePath DefaultItemPath { get; set; } [Export] public NodePath DefaultItemPath { get; set; }
public Player Player { get; private set; }
private Node2D _current; private Node2D _current;
public int Count => GetChildCount(); public int Count => GetChildCount();
public Node2D this[int index] => GetChild<Node2D>(index); public Node2D this[int index] => GetChild<Node2D>(index);
@ -22,6 +24,7 @@ public class Items : Node2D, IItems
public override void _Ready() public override void _Ready()
{ {
Player = GetParent<Player>();
foreach (var item in this) SetActive(item, false); foreach (var item in this) SetActive(item, false);
if (DefaultItemPath != null) SetCurrent(GetNode<Node2D>(DefaultItemPath), false); if (DefaultItemPath != null) SetCurrent(GetNode<Node2D>(DefaultItemPath), false);
} }
@ -41,8 +44,11 @@ public class Items : Node2D, IItems
} }
} }
[Remote] [Remote]
private void DoSetCurrent(string name) public void DoSetCurrent(string name)
{ {
if (this.GetGame() is Server) {
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);
} }

@ -7,6 +7,7 @@ public class Player : KinematicBody2D, IInitializable
public Label DisplayNameLabel { get; private set; } public Label DisplayNameLabel { get; private set; }
public Sprite Sprite { get; private set; } public Sprite Sprite { get; private set; }
public IItems Items { get; private set; }
public int NetworkID { get => int.Parse(Name); set => Name = value.ToString(); } public int NetworkID { get => int.Parse(Name); set => Name = value.ToString(); }
@ -17,6 +18,7 @@ public class Player : KinematicBody2D, IInitializable
{ {
DisplayNameLabel = GetNode<Label>(DisplayNamePath); DisplayNameLabel = GetNode<Label>(DisplayNamePath);
Sprite = GetNode<Sprite>(SpritePath); Sprite = GetNode<Sprite>(SpritePath);
Items = GetNode<IItems>("Items");
RsetConfig("position", MultiplayerAPI.RPCMode.Puppetsync); RsetConfig("position", MultiplayerAPI.RPCMode.Puppetsync);
RsetConfig(nameof(NetworkID), MultiplayerAPI.RPCMode.Puppetsync); RsetConfig(nameof(NetworkID), MultiplayerAPI.RPCMode.Puppetsync);

@ -16,8 +16,12 @@ public class Client : Game
public event Action Connected; public event Action Connected;
public event Action Disconnected; public event Action Disconnected;
public event Action<LocalPlayer> LocalPlayerSpawned;
public event Action<ConnectionStatus> StatusChanged; public event Action<ConnectionStatus> StatusChanged;
internal void FireLocalPlayerSpawned(LocalPlayer player)
=> LocalPlayerSpawned?.Invoke(player);
public override void _Ready() public override void _Ready()
{ {

@ -61,6 +61,10 @@ public class Server : Game
IsSingleplayer = false; IsSingleplayer = false;
_isLocalPlayerConnected = false; _isLocalPlayerConnected = false;
foreach (var player in this.GetWorld().Players)
if (player != _localPlayer)
player.RemoveFromParent();
} }
@ -80,16 +84,24 @@ public class Server : Game
} else { } else {
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), world.RpcId(networkID, nameof(World.SpawnPlayer), player.NetworkID, player.Position);
player.NetworkID, player.Position, player.DisplayName, player.Color);
// Send player's appearance.
player.Rset(nameof(Player.DisplayName), player.DisplayName);
player.Rset(nameof(Player.Color), player.Color);
// Send player's currently equipped item.
if (player.Items.Current != null) ((Node2D)player.Items).RpcId(
networkID, nameof(Items.DoSetCurrent), player.Items.Current.Name);
}
foreach (var block in world.BlockContainer.GetChildren().Cast<Block>()) foreach (var block in world.Blocks)
world.RpcId(networkID, nameof(World.SendBlock), world.RpcId(networkID, nameof(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, "", Colors.Red); world.Rpc(nameof(World.SpawnPlayer), networkID, Vector2.Zero);
if (IsSingleplayer) _localPlayer = world.GetPlayer(networkID); if (IsSingleplayer) _localPlayer = world.GetPlayer(networkID);
} }
} }

@ -41,12 +41,6 @@ public class World : Node
[PuppetSync] [PuppetSync]
public void SpawnBlock(int x, int y, Color color, bool unbreakable) public void SpawnBlock(int x, int y, Color color, bool unbreakable)
=> SpawnBlockInternal(x, y, color, unbreakable);
[Puppet]
public void SendBlock(int x, int y, Color color, bool unbreakable)
=> SpawnBlockInternal(x, y, color, unbreakable);
private void SpawnBlockInternal(int x, int y, Color color, bool unbreakable)
{ {
var position = new BlockPos(x, y); var position = new BlockPos(x, y);
var block = BlockScene.Init<Block>(); var block = BlockScene.Init<Block>();
@ -58,21 +52,16 @@ public class World : Node
} }
[PuppetSync] [PuppetSync]
public void SpawnPlayer(int networkID, Vector2 position, string displayName, Color color) public void SpawnPlayer(int networkID, Vector2 position)
=> SpawnPlayerInternal(networkID, position, displayName, color);
[Puppet]
public void SendPlayer(int networkID, Vector2 position, string displayName, Color color)
=> SpawnPlayerInternal(networkID, position, displayName, color);
private void SpawnPlayerInternal(int networkID, Vector2 position, string displayName, Color color)
{ {
var isLocal = networkID == GetTree().GetNetworkUniqueId(); var isLocal = networkID == GetTree().GetNetworkUniqueId();
var player = (isLocal ? LocalPlayerScene : PlayerScene).Init<Player>(); var player = (isLocal ? LocalPlayerScene : PlayerScene).Init<Player>();
player.NetworkID = networkID; player.NetworkID = networkID;
player.Position = position; player.Position = position;
player.DisplayName = displayName;
player.Color = color;
PlayerContainer.AddChild(player); PlayerContainer.AddChild(player);
if (player is LocalPlayer localPlayer)
this.GetClient().FireLocalPlayerSpawned(localPlayer);
} }
[PuppetSync] [PuppetSync]

Loading…
Cancel
Save