Add radial menu selection

Pressing middle mouse now shows a
radial menu HUD element that allows
selecting active controlled element.

At the moment there only is "Creative
Building" but in the future you may be
able to select weapons and such.

Currently not networked.

- Add IntegratedServer to ClientScene
- Prevent _Draw from being called by
  making Player invisible on server
- Use _UnhandledInput in CreativeBuilding
- Add Cursor.ScreenPosition property
main
copygirl 4 years ago
parent f9339ead77
commit d2559c72de
  1. 5
      project.godot
  2. 41
      scene/ClientScene.tscn
  3. 12
      scene/Player.tscn
  4. 61
      src/CreativeBuilding.cs
  5. 5
      src/Cursor.cs
  6. 4
      src/EscapeMenu.cs
  7. 49
      src/EscapeMenuMultiplayer.cs
  8. 0
      src/IO/WorldSave.cs
  9. 6
      src/Network/IntegratedServer.cs
  10. 1
      src/Objects/LocalPlayer.cs
  11. 3
      src/Objects/Player.cs
  12. 115
      src/RadialMenu.cs
  13. 6
      src/Scenes/Client.cs
  14. 2
      src/World.cs

@ -78,6 +78,11 @@ move_jump={
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":1,"pressure":0.0,"pressed":false,"script":null) , Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":1,"pressure":0.0,"pressed":false,"script":null)
] ]
} }
interact_select={
"deadzone": 0.5,
"events": [ Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"button_mask":0,"position":Vector2( 0, 0 ),"global_position":Vector2( 0, 0 ),"factor":1.0,"button_index":3,"pressed":false,"doubleclick":false,"script":null)
]
}
interact_place={ interact_place={
"deadzone": 0.5, "deadzone": 0.5,
"events": [ Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"button_mask":0,"position":Vector2( 0, 0 ),"global_position":Vector2( 0, 0 ),"factor":1.0,"button_index":1,"pressed":false,"doubleclick":false,"script":null) "events": [ Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"button_mask":0,"position":Vector2( 0, 0 ),"global_position":Vector2( 0, 0 ),"factor":1.0,"button_index":1,"pressed":false,"doubleclick":false,"script":null)

@ -1,4 +1,4 @@
[gd_scene load_steps=9 format=2] [gd_scene load_steps=12 format=2]
[ext_resource path="res://scene/GameScene.tscn" type="PackedScene" id=1] [ext_resource path="res://scene/GameScene.tscn" type="PackedScene" id=1]
[ext_resource path="res://src/Cursor.cs" type="Script" id=2] [ext_resource path="res://src/Cursor.cs" type="Script" id=2]
@ -8,18 +8,26 @@
[ext_resource path="res://src/Viewport.cs" type="Script" id=6] [ext_resource path="res://src/Viewport.cs" type="Script" id=6]
[ext_resource path="res://scene/EscapeMenu.tscn" type="PackedScene" id=7] [ext_resource path="res://scene/EscapeMenu.tscn" type="PackedScene" id=7]
[ext_resource path="res://src/Scenes/Client.cs" type="Script" id=8] [ext_resource path="res://src/Scenes/Client.cs" type="Script" id=8]
[ext_resource path="res://src/Network/IntegratedServer.cs" type="Script" id=9]
[ext_resource path="res://ui_theme.tres" type="Theme" id=10]
[ext_resource path="res://src/RadialMenu.cs" type="Script" id=11]
[node name="Client" instance=ExtResource( 1 )] [node name="Client" instance=ExtResource( 1 )]
script = ExtResource( 8 ) script = ExtResource( 8 )
IntegratedServerPath = NodePath("IntegratedServer")
CursorPath = NodePath("CursorLayer/Cursor") CursorPath = NodePath("CursorLayer/Cursor")
[node name="Viewport" type="Node" parent="." index="0"] [node name="IntegratedServer" type="Node" parent="." index="0"]
script = ExtResource( 9 )
[node name="Viewport" type="Node" parent="." index="1"]
script = ExtResource( 6 ) script = ExtResource( 6 )
[node name="Background" type="TextureRect" parent="." index="1"] [node name="Background" type="TextureRect" parent="." index="2"]
modulate = Color( 0.278431, 0.286275, 0.301961, 1 ) modulate = Color( 0.278431, 0.286275, 0.301961, 1 )
margin_right = 1280.0 margin_right = 1280.0
margin_bottom = 720.0 margin_bottom = 720.0
mouse_filter = 2
texture = ExtResource( 4 ) texture = ExtResource( 4 )
stretch_mode = 2 stretch_mode = 2
script = ExtResource( 5 ) script = ExtResource( 5 )
@ -28,12 +36,33 @@ __meta__ = {
"_edit_use_anchors_": false "_edit_use_anchors_": false
} }
[node name="HUD" type="CanvasLayer" parent="." index="3"] [node name="HUD" type="CanvasLayer" parent="." index="4"]
[node name="RadialMenu" type="Node2D" parent="HUD" index="0"]
visible = false
script = ExtResource( 11 )
[node name="ActiveName" type="Label" parent="HUD/RadialMenu" index="0"]
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
margin_left = -36.0
margin_top = -16.0
margin_right = 36.0
margin_bottom = 16.0
theme = ExtResource( 10 )
align = 1
valign = 1
autowrap = true
__meta__ = {
"_edit_use_anchors_": false
}
[node name="EscapeMenu" parent="HUD" index="0" instance=ExtResource( 7 )] [node name="EscapeMenu" parent="HUD" index="1" instance=ExtResource( 7 )]
visible = false visible = false
[node name="CursorLayer" type="CanvasLayer" parent="." index="4"] [node name="CursorLayer" type="CanvasLayer" parent="." index="5"]
layer = 2 layer = 2
follow_viewport_enable = true follow_viewport_enable = true

@ -1,9 +1,10 @@
[gd_scene load_steps=6 format=2] [gd_scene load_steps=7 format=2]
[ext_resource path="res://ui_theme.tres" type="Theme" id=1] [ext_resource path="res://ui_theme.tres" type="Theme" id=1]
[ext_resource path="res://gfx/player.png" type="Texture" id=2] [ext_resource path="res://gfx/player.png" type="Texture" id=2]
[ext_resource path="res://src/Objects/Player.cs" type="Script" id=3] [ext_resource path="res://src/Objects/Player.cs" type="Script" id=3]
[ext_resource path="res://src/CreativeBuilding.cs" type="Script" id=4] [ext_resource path="res://src/CreativeBuilding.cs" type="Script" id=4]
[ext_resource path="res://gfx/block.png" type="Texture" id=6]
[sub_resource type="CircleShape2D" id=1] [sub_resource type="CircleShape2D" id=1]
radius = 8.0 radius = 8.0
@ -38,5 +39,12 @@ __meta__ = {
z_index = -5 z_index = -5
texture = ExtResource( 2 ) texture = ExtResource( 2 )
[node name="CreativeBuilding" type="Node2D" parent="."] [node name="Items" type="Node2D" parent="."]
[node name="Creative Building" type="Node2D" parent="Items"]
visible = false
script = ExtResource( 4 ) script = ExtResource( 4 )
[node name="Icon" type="Sprite" parent="Items/Creative Building"]
visible = false
texture = ExtResource( 6 )

@ -30,38 +30,43 @@ public class CreativeBuilding : Node2D
_blockTex = GD.Load<Texture>("res://gfx/block.png"); _blockTex = GD.Load<Texture>("res://gfx/block.png");
Cursor = this.GetClient()?.Cursor; Cursor = this.GetClient()?.Cursor;
Player = GetParent<Player>(); Player = GetParent().GetParent<Player>();
}
public override void _UnhandledInput(InputEvent ev)
{
if (!(Player is LocalPlayer) || !Visible) return;
if (ev.IsActionPressed("interact_place")) {
GetTree().SetInputAsHandled();
_currentMode = (((_currentMode == null) && _canBuild) ? BuildMode.Placing : (BuildMode?)null);
}
if (ev.IsActionPressed("interact_break")) {
GetTree().SetInputAsHandled();
_currentMode = ((_currentMode == null) ? BuildMode.Breaking : (BuildMode?)null);
}
// NOTE: These ternary operations require extra brackets for some
// reason or else the syntax highlighting in VS Code breaks?!
} }
public override void _Process(float delta) public override void _Process(float delta)
{ {
if (!(Player is LocalPlayer)) return; if (!(Player is LocalPlayer)) return;
Update(); // Make sure _Draw is being called. if (!Visible) _currentMode = null;
if (_currentMode == BuildMode.Placing) {
if (!_canBuild) _currentMode = null;
else if (!Input.IsActionPressed("interact_place")) {
RpcId(1, nameof(PlaceLine), _startPos.X, _startPos.Y, _direction, _length);
_currentMode = null;
}
}
if (EscapeMenu.Instance.Visible || !Cursor.Visible) if (_currentMode == BuildMode.Breaking) {
{ _currentMode = null; return; } if (!Input.IsActionPressed("interact_break")) {
RpcId(1, nameof(BreakLine), _startPos.X, _startPos.Y, _direction, _length);
switch (_currentMode) { _currentMode = null;
case null: }
if (Input.IsActionJustPressed("interact_place"))
if (_canBuild) _currentMode = BuildMode.Placing;
if (Input.IsActionJustPressed("interact_break"))
_currentMode = BuildMode.Breaking;
break;
case BuildMode.Placing:
if (Input.IsActionJustPressed("interact_break")) _currentMode = null;
else if (!Input.IsActionPressed("interact_place")) {
if (_canBuild) RpcId(1, nameof(PlaceLine), _startPos.X, _startPos.Y, _direction, _length);
_currentMode = null;
}
break;
case BuildMode.Breaking:
if (Input.IsActionJustPressed("interact_place")) _currentMode = null;
else if (!Input.IsActionPressed("interact_break")) {
RpcId(1, nameof(BreakLine), _startPos.X, _startPos.Y, _direction, _length);
_currentMode = null;
}
break;
} }
if (_currentMode != null) { if (_currentMode != null) {
@ -77,11 +82,13 @@ public class CreativeBuilding : Node2D
var world = this.GetWorld(); var world = this.GetWorld();
bool IsBlockAt(BlockPos pos) => world.GetBlockAt(pos) != null; bool IsBlockAt(BlockPos pos) => world.GetBlockAt(pos) != null;
_canBuild = !IsBlockAt(_startPos) && Facings.All.Any(pos => IsBlockAt(_startPos + pos.ToBlockPos())); _canBuild = !IsBlockAt(_startPos) && Facings.All.Any(pos => IsBlockAt(_startPos + pos.ToBlockPos()));
Update(); // Make sure _Draw is being called.
} }
public override void _Draw() public override void _Draw()
{ {
if ((this.GetGame() is Server) || !Cursor.Visible || EscapeMenu.Instance.Visible) return; if (!Cursor.Visible || EscapeMenu.Instance.Visible) return;
var green = Color.FromHsv(1.0F / 3, 1.0F, 1.0F, 0.4F); var green = Color.FromHsv(1.0F / 3, 1.0F, 1.0F, 0.4F);
var red = Color.FromHsv(0.0F, 1.0F, 1.0F, 0.4F); var red = Color.FromHsv(0.0F, 1.0F, 1.0F, 0.4F);

@ -2,6 +2,8 @@ using Godot;
public class Cursor : Node2D public class Cursor : Node2D
{ {
public Vector2 ScreenPosition { get; private set; }
public override void _Ready() public override void _Ready()
{ {
Input.SetMouseMode(Input.MouseMode.Hidden); Input.SetMouseMode(Input.MouseMode.Hidden);
@ -19,6 +21,7 @@ public class Cursor : Node2D
public override void _Process(float delta) public override void _Process(float delta)
{ {
Position = GetGlobalMousePosition() - GetViewport().CanvasTransform.origin; ScreenPosition = GetGlobalMousePosition();
Position = ScreenPosition - GetViewport().CanvasTransform.origin;
} }
} }

@ -15,9 +15,7 @@ public class EscapeMenu : Control
} }
public override void _UnhandledInput(InputEvent @event) public override void _UnhandledInput(InputEvent @event)
{ { if (@event.IsActionPressed("ui_menu")) Toggle(); }
if (@event.IsActionPressed("ui_menu")) Toggle();
}
public void Toggle() public void Toggle()

@ -19,8 +19,6 @@ public class EscapeMenuMultiplayer : Container
public Button ClientDisConnect { get; private set; } public Button ClientDisConnect { get; private set; }
public LineEdit ClientAddress { get; private set; } public LineEdit ClientAddress { get; private set; }
public IntegratedServer IntegratedServer { get; private set; }
public override void _Ready() public override void _Ready()
{ {
Status = GetNode<Label>(StatusPath); Status = GetNode<Label>(StatusPath);
@ -33,22 +31,11 @@ public class EscapeMenuMultiplayer : Container
ClientAddress.PlaceholderText = $"localhost:{DEFAULT_PORT}"; ClientAddress.PlaceholderText = $"localhost:{DEFAULT_PORT}";
this.GetClient().StatusChanged += OnStatusChanged; this.GetClient().StatusChanged += OnStatusChanged;
CallDeferred(nameof(SetupIntegratedServer));
}
private void SetupIntegratedServer()
{
IntegratedServer = new IntegratedServer();
this.GetClient().AddChild(IntegratedServer);
CallDeferred(nameof(StartIntegratedServerAndConnect));
}
private void StartIntegratedServerAndConnect()
{
var port = IntegratedServer.Server.StartSingleplayer();
this.GetClient().Connect("127.0.0.1", port);
} }
private void OnStatusChanged(ConnectionStatus status) private void OnStatusChanged(ConnectionStatus status)
{ {
var server = this.GetClient().IntegratedServer.Server;
switch (status) { switch (status) {
case ConnectionStatus.Disconnected: case ConnectionStatus.Disconnected:
Status.Text = "Disconnected"; Status.Text = "Disconnected";
@ -59,10 +46,10 @@ public class EscapeMenuMultiplayer : Container
Status.Modulate = Colors.Yellow; Status.Modulate = Colors.Yellow;
break; break;
case ConnectionStatus.Connected: case ConnectionStatus.Connected:
if (IntegratedServer == null) { if (!server.IsRunning) {
Status.Text = "Connected!"; Status.Text = "Connected!";
Status.Modulate = Colors.Green; Status.Modulate = Colors.Green;
} else if (IntegratedServer.Server.IsSingleplayer) { } else if (server.IsSingleplayer) {
Status.Text = "Singleplayer"; Status.Text = "Singleplayer";
Status.Modulate = Colors.White; Status.Modulate = Colors.White;
} else { } else {
@ -72,15 +59,16 @@ public class EscapeMenuMultiplayer : Container
break; break;
} }
ServerPort.Editable = IntegratedServer != null;
ServerOpenClose.Disabled = IntegratedServer == null;
ServerOpenClose.Text = (IntegratedServer?.Server.IsSingleplayer == false) ? "Close Server" : "Open Server";
ClientDisConnect.Text = ((IntegratedServer != null) || (status == ConnectionStatus.Disconnected)) ? "Connect" : "Disconnect";
var isSingleplayer = IntegratedServer?.Server.IsSingleplayer == true; ServerPort.Editable = server.IsRunning;
var pauseMode = isSingleplayer ? PauseModeEnum.Stop : PauseModeEnum.Process; ServerOpenClose.Disabled = !server.IsRunning;
this.GetWorld().PauseMode = pauseMode; ServerOpenClose.Text = (server.IsRunning && !server.IsSingleplayer) ? "Close Server" : "Open Server";
if (IntegratedServer != null) IntegratedServer.Server.GetWorld().PauseMode = pauseMode; ClientDisConnect.Text = (server.IsSingleplayer || (status == ConnectionStatus.Disconnected)) ? "Connect" : "Disconnect";
ClientDisConnect.Disabled = server.IsRunning && !server.IsSingleplayer;
var pauseMode = server.IsSingleplayer ? PauseModeEnum.Stop : PauseModeEnum.Process;
this.GetWorld().PauseMode = pauseMode;
server.GetWorld().PauseMode = pauseMode;
// TODO: Allow starting up the integrated server again when disconnected. // TODO: Allow starting up the integrated server again when disconnected.
} }
@ -107,8 +95,8 @@ public class EscapeMenuMultiplayer : Container
private void _on_ServerOpenClose_pressed() private void _on_ServerOpenClose_pressed()
{ {
var server = IntegratedServer?.Server;
var client = this.GetClient(); var client = this.GetClient();
var server = client.IntegratedServer.Server;
if (server?.IsRunning != true) throw new InvalidOperationException(); if (server?.IsRunning != true) throw new InvalidOperationException();
if (server.IsSingleplayer) { if (server.IsSingleplayer) {
@ -133,12 +121,12 @@ public class EscapeMenuMultiplayer : Container
private void _on_ClientDisConnect_pressed() private void _on_ClientDisConnect_pressed()
{ {
var client = this.GetClient(); var client = this.GetClient();
var server = client.IntegratedServer.Server;
if (IntegratedServer != null) { if (server.IsRunning) {
IntegratedServer.Server.Stop(); server.Stop();
client.RemoveChild(IntegratedServer); server.GetWorld().ClearPlayers();
IntegratedServer.QueueFree(); server.GetWorld().ClearBlocks();
IntegratedServer = null;
client.Disconnect(); client.Disconnect();
this.GetWorld().ClearPlayers(); this.GetWorld().ClearPlayers();
@ -156,6 +144,7 @@ public class EscapeMenuMultiplayer : Container
} }
client.Connect(address, port); client.Connect(address, port);
} else { } else {
client.Disconnect();
this.GetWorld().ClearPlayers(); this.GetWorld().ClearPlayers();
this.GetWorld().ClearBlocks(); this.GetWorld().ClearBlocks();
} }

@ -5,9 +5,6 @@ public class IntegratedServer : Node
private SceneTree _sceneTree; private SceneTree _sceneTree;
public Server Server { get; private set; } public Server Server { get; private set; }
public IntegratedServer()
=> Name = "IntegratedServer";
public override void _Ready() public override void _Ready()
{ {
_sceneTree = new SceneTree(); _sceneTree = new SceneTree();
@ -26,6 +23,9 @@ public class IntegratedServer : Node
var color = Color.FromHsv(GD.Randf(), 0.1F, 1.0F); var color = Color.FromHsv(GD.Randf(), 0.1F, 1.0F);
world.SpawnBlock(x, 3, color, true); world.SpawnBlock(x, 3, color, true);
} }
var port = Server.StartSingleplayer();
this.GetClient().Connect("127.0.0.1", port);
} }
public override void _Process(float delta) => _sceneTree.Idle(delta); public override void _Process(float delta) => _sceneTree.Idle(delta);

@ -15,6 +15,7 @@ public class LocalPlayer : Player
public float GroundFriction { get; set; } = 0.2F; public float GroundFriction { get; set; } = 0.2F;
public float AirFriction { get; set; } = 0.05F; public float AirFriction { get; set; } = 0.05F;
public Vector2 Velocity = Vector2.Zero; public Vector2 Velocity = Vector2.Zero;
private DateTime? _jumpPressed = null; private DateTime? _jumpPressed = null;
private DateTime? _lastOnFloor = null; private DateTime? _lastOnFloor = null;

@ -24,6 +24,9 @@ public class Player : KinematicBody2D, IInitializable
RsetConfig(nameof(Color), MultiplayerAPI.RPCMode.Puppetsync); RsetConfig(nameof(Color), MultiplayerAPI.RPCMode.Puppetsync);
} }
public override void _Ready()
=> Visible = this.GetGame() is Client;
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))

@ -0,0 +1,115 @@
using System;
using Godot;
public class RadialMenu : Node2D
{
[Export] public int InnerRadius { get; set; } = 32;
[Export] public int OuterRadius { get; set; } = 64;
[Export] public int MinElements { get; set; } = 8;
[Export] public float Separation { get; set; } = 2F;
public Cursor Cursor { get; private set; }
public Label ActiveName { get; private set; }
private float _startAngle;
public Node2D Selected { get; private set; } = null;
public int? SelectedIndex => (Selected != null) ? Selected.GetIndex() : (int?)null;
public override void _Ready()
{
_startAngle = (-Mathf.Tau / 4) - (Mathf.Tau / MinElements / 2);
Cursor = this.GetClient()?.Cursor;
ActiveName = GetNode<Label>("ActiveName");
}
public Node GetItems()
=> this.GetClient().LocalPlayer?.GetNode<Node2D>("Items");
public void Select(Node2D node)
{
if (node == Selected) return;
if ((node != null) && (node.GetParent() != GetItems())) throw new ArgumentException();
ActiveName.Text = node?.Name ?? "";
if (Visible)
Update();
else {
SetActive(Selected, false);
SetActive(node, true);
}
Selected = node;
}
private static void SetActive(Node2D node, bool value) {
if (node == null) return;
node.SetProcessInput(value);
node.SetProcessUnhandledInput(value);
node.Visible = value;
}
public override void _UnhandledInput(InputEvent ev)
{
if (ev.IsActionPressed("interact_select")) {
Position = this.GetClient().Cursor.ScreenPosition.Round();
Visible = true;
SetActive(Selected, false);
Update();
}
// TODO: Add scrollwheel support.
}
public override void _Process(float delta)
{
if (!Visible) return;
var cursorPos = ToLocal(this.GetClient().Cursor.ScreenPosition);
var angle = cursorPos.Angle() - _startAngle;
var index = (int)((angle / Mathf.Tau + 1) % 1 * MinElements);
var items = GetItems();
if ((cursorPos.Length() > InnerRadius) && (index < items.GetChildCount()))
Select(items.GetChild<Node2D>(index));
if (!Input.IsActionPressed("interact_select")) {
Visible = false;
SetActive(Selected, true);
Update();
}
}
public override void _Draw()
{
var vertices = new Vector2[5];
var colors = new Color[5];
for (var i = 0; i < MinElements; i++) {
var angle1 = _startAngle + Mathf.Tau * ( i / (float)MinElements);
var angle3 = _startAngle + Mathf.Tau * ((i + 1) / (float)MinElements);
var angle2 = (angle1 + angle3) / 2;
var sep1 = new Vector2(Mathf.Cos(angle1 + Mathf.Tau / 4), Mathf.Sin(angle1 + Mathf.Tau / 4)) * Separation;
var sep2 = new Vector2(Mathf.Cos(angle3 - Mathf.Tau / 4), Mathf.Sin(angle3 - Mathf.Tau / 4)) * Separation;
var isSelected = i == SelectedIndex;
var innerRadius = InnerRadius + (isSelected ? 5 : 0);
var outerRadius = OuterRadius + (isSelected ? 5 : 0);
vertices[0] = new Vector2(Mathf.Cos(angle1), Mathf.Sin(angle1)) * innerRadius + sep1;
vertices[1] = new Vector2(Mathf.Cos(angle1), Mathf.Sin(angle1)) * outerRadius + sep1;
vertices[2] = new Vector2(Mathf.Cos(angle2), Mathf.Sin(angle2)) * (outerRadius + Separation);
vertices[3] = new Vector2(Mathf.Cos(angle3), Mathf.Sin(angle3)) * outerRadius + sep2;
vertices[4] = new Vector2(Mathf.Cos(angle3), Mathf.Sin(angle3)) * innerRadius + sep2;
var color = new Color(0.1F, 0.1F, 0.1F, isSelected ? 0.7F : 0.4F);
for (var j = 0; j < colors.Length; j++) colors[j] = color;
DrawPolygon(vertices, colors, antialiased: true);
var items = GetItems();
if ((i < items.GetChildCount()) && (items.GetChild(i)?.GetNodeOrNull("Icon") is Sprite sprite)) {
var pos = new Vector2(Mathf.Cos(angle2), Mathf.Sin(angle2)) * (innerRadius + outerRadius) / 2;
if (sprite.Centered) pos -= sprite.Texture.GetSize() / 2;
DrawTexture(sprite.Texture, sprite.Offset + pos, sprite.Modulate);
}
}
}
}

@ -4,7 +4,10 @@ using static Godot.NetworkedMultiplayerPeer;
public class Client : Game public class Client : Game
{ {
[Export] public NodePath IntegratedServerPath { get; set; }
[Export] public NodePath CursorPath { get; set; } [Export] public NodePath CursorPath { get; set; }
public IntegratedServer IntegratedServer { get; private set; }
public Cursor Cursor { get; private set; } public Cursor Cursor { get; private set; }
public NetworkedMultiplayerENet Peer => (NetworkedMultiplayerENet)Multiplayer.NetworkPeer; public NetworkedMultiplayerENet Peer => (NetworkedMultiplayerENet)Multiplayer.NetworkPeer;
@ -19,7 +22,8 @@ public class Client : Game
public override void _Ready() public override void _Ready()
{ {
base._Ready(); base._Ready();
Cursor = GetNode<Cursor>(CursorPath); Cursor = GetNode<Cursor>(CursorPath);
IntegratedServer = GetNode<IntegratedServer>(IntegratedServerPath);
Multiplayer.Connect("connected_to_server", this, nameof(OnConnectedToServer)); Multiplayer.Connect("connected_to_server", this, nameof(OnConnectedToServer));
Multiplayer.Connect("connection_failed", this, nameof(Disconnect)); Multiplayer.Connect("connection_failed", this, nameof(Disconnect));

@ -27,7 +27,7 @@ public class World : Node
public IEnumerable<Player> Players public IEnumerable<Player> Players
=> PlayerContainer.GetChildren().Cast<Player>(); => PlayerContainer.GetChildren().Cast<Player>();
public Player GetPlayer(int networkID) public Player GetPlayer(int networkID)
=> PlayerContainer.GetNode<Player>(networkID.ToString()); => PlayerContainer.GetNodeOrNull<Player>(networkID.ToString());
public void ClearPlayers() public void ClearPlayers()
{ foreach (var player in Players) player.RemoveFromParent(); } { foreach (var player in Players) player.RemoveFromParent(); }

Loading…
Cancel
Save