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. 4
      src/Objects/Player.cs
  5. 4
      src/Scenes/Client.cs
  6. 24
      src/Scenes/Server.cs
  7. 23
      src/World.cs

@ -20,10 +20,8 @@ public class EscapeMenuAppearance : CenterContainer
ColorSlider.Value = GD.Randf();
ColorPreview.Modulate = Color.FromHsv((float)ColorSlider.Value, 1.0F, 1.0F);
// FIXME: LocalPlayer hasn't spawned yet on connection.
// var client = this.GetClient();
// client.Connected += () => client.LocalPlayer.RpcId(1,
// nameof(Player.ChangeAppearance), DisplayName.Text, ColorPreview.Modulate);
this.GetClient().LocalPlayerSpawned += (player) => player.RpcId(1,
nameof(Player.ChangeAppearance), DisplayName.Text, ColorPreview.Modulate);
}
#pragma warning disable IDE0051

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

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

@ -7,6 +7,7 @@ public class Player : KinematicBody2D, IInitializable
public Label DisplayNameLabel { 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(); }
@ -16,7 +17,8 @@ public class Player : KinematicBody2D, IInitializable
public void Initialize()
{
DisplayNameLabel = GetNode<Label>(DisplayNamePath);
Sprite = GetNode<Sprite>(SpritePath);
Sprite = GetNode<Sprite>(SpritePath);
Items = GetNode<IItems>("Items");
RsetConfig("position", MultiplayerAPI.RPCMode.Puppetsync);
RsetConfig(nameof(NetworkID), MultiplayerAPI.RPCMode.Puppetsync);

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

@ -61,6 +61,10 @@ public class Server : Game
IsSingleplayer = false;
_isLocalPlayerConnected = false;
foreach (var player in this.GetWorld().Players)
if (player != _localPlayer)
player.RemoveFromParent();
}
@ -80,16 +84,24 @@ public class Server : Game
} else {
var world = this.GetWorld();
foreach (var player in world.Players)
world.RpcId(networkID, nameof(World.SpawnPlayer),
player.NetworkID, player.Position, player.DisplayName, player.Color);
foreach (var player in world.Players) {
world.RpcId(networkID, nameof(World.SpawnPlayer), player.NetworkID, player.Position);
// 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>())
world.RpcId(networkID, nameof(World.SendBlock),
foreach (var block in world.Blocks)
world.RpcId(networkID, nameof(World.SpawnBlock),
block.Position.X, block.Position.Y,
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);
}
}

@ -41,12 +41,6 @@ public class World : Node
[PuppetSync]
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 block = BlockScene.Init<Block>();
@ -58,21 +52,16 @@ public class World : Node
}
[PuppetSync]
public void SpawnPlayer(int networkID, Vector2 position, string displayName, Color color)
=> 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)
public void SpawnPlayer(int networkID, Vector2 position)
{
var isLocal = networkID == GetTree().GetNetworkUniqueId();
var player = (isLocal ? LocalPlayerScene : PlayerScene).Init<Player>();
player.NetworkID = networkID;
player.Position = position;
player.DisplayName = displayName;
player.Color = color;
player.NetworkID = networkID;
player.Position = position;
PlayerContainer.AddChild(player);
if (player is LocalPlayer localPlayer)
this.GetClient().FireLocalPlayerSpawned(localPlayer);
}
[PuppetSync]

Loading…
Cancel
Save