diff --git a/mono/multiplayer_pong/Pong Multiplayer with C#.csproj b/mono/multiplayer_pong/Pong Multiplayer with C#.csproj index 18dad044ec..cf8558f4d8 100644 --- a/mono/multiplayer_pong/Pong Multiplayer with C#.csproj +++ b/mono/multiplayer_pong/Pong Multiplayer with C#.csproj @@ -1,6 +1,9 @@ - + - net472 - PongMultiplayer + net6.0 + net7.0 + net8.0 + true + PongMultiplayerwithC \ No newline at end of file diff --git a/mono/multiplayer_pong/Pong Multiplayer with C#.sln b/mono/multiplayer_pong/Pong Multiplayer with C#.sln index 158b131783..9640d48a88 100644 --- a/mono/multiplayer_pong/Pong Multiplayer with C#.sln +++ b/mono/multiplayer_pong/Pong Multiplayer with C#.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2012 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Pong Multiplayer with C#", "Pong Multiplayer with C#.csproj", "{4BB6C2D0-FC11-466E-8C73-8DAD689F135A}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Pong Multiplayer with C#", "Pong Multiplayer with C#.csproj", "{58FECEC2-0618-4042-81F2-4EDD7982C229}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -9,11 +9,11 @@ Global ExportRelease|Any CPU = ExportRelease|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {4BB6C2D0-FC11-466E-8C73-8DAD689F135A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4BB6C2D0-FC11-466E-8C73-8DAD689F135A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4BB6C2D0-FC11-466E-8C73-8DAD689F135A}.ExportDebug|Any CPU.ActiveCfg = ExportDebug|Any CPU - {4BB6C2D0-FC11-466E-8C73-8DAD689F135A}.ExportDebug|Any CPU.Build.0 = ExportDebug|Any CPU - {4BB6C2D0-FC11-466E-8C73-8DAD689F135A}.ExportRelease|Any CPU.ActiveCfg = ExportRelease|Any CPU - {4BB6C2D0-FC11-466E-8C73-8DAD689F135A}.ExportRelease|Any CPU.Build.0 = ExportRelease|Any CPU + {58FECEC2-0618-4042-81F2-4EDD7982C229}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {58FECEC2-0618-4042-81F2-4EDD7982C229}.Debug|Any CPU.Build.0 = Debug|Any CPU + {58FECEC2-0618-4042-81F2-4EDD7982C229}.ExportDebug|Any CPU.ActiveCfg = ExportDebug|Any CPU + {58FECEC2-0618-4042-81F2-4EDD7982C229}.ExportDebug|Any CPU.Build.0 = ExportDebug|Any CPU + {58FECEC2-0618-4042-81F2-4EDD7982C229}.ExportRelease|Any CPU.ActiveCfg = ExportRelease|Any CPU + {58FECEC2-0618-4042-81F2-4EDD7982C229}.ExportRelease|Any CPU.Build.0 = ExportRelease|Any CPU EndGlobalSection EndGlobal diff --git a/mono/multiplayer_pong/lobby.tscn b/mono/multiplayer_pong/lobby.tscn index e9e0aa74cc..75c438af5b 100644 --- a/mono/multiplayer_pong/lobby.tscn +++ b/mono/multiplayer_pong/lobby.tscn @@ -1,8 +1,10 @@ -[gd_scene load_steps=2 format=2] +[gd_scene load_steps=2 format=3 uid="uid://bxj0km4t28u17"] -[ext_resource path="res://logic/Lobby.cs" type="Script" id=1] +[ext_resource type="Script" path="res://logic/Lobby.cs" id="1"] [node name="Lobby" type="Control"] +layout_mode = 3 +anchors_preset = 8 anchor_left = 0.5 anchor_top = 0.5 anchor_right = 0.5 @@ -11,13 +13,13 @@ offset_left = -320.0 offset_top = -200.0 offset_right = 320.0 offset_bottom = 200.0 +grow_horizontal = 2 +grow_vertical = 2 size_flags_horizontal = 2 size_flags_vertical = 2 -__meta__ = { -"_edit_use_anchors_": false -} [node name="Title" type="Label" parent="."] +layout_mode = 0 offset_left = 210.0 offset_top = 40.0 offset_right = 430.0 @@ -25,22 +27,19 @@ offset_bottom = 80.0 size_flags_horizontal = 2 size_flags_vertical = 0 text = "Multiplayer Pong" -align = 1 -valign = 1 [node name="LobbyPanel" type="Panel" parent="."] +layout_mode = 0 offset_left = 210.0 offset_top = 160.0 offset_right = 430.0 offset_bottom = 270.0 size_flags_horizontal = 2 size_flags_vertical = 2 -script = ExtResource( 1 ) -__meta__ = { -"_edit_use_anchors_": false -} +script = ExtResource("1") [node name="AddressLabel" type="Label" parent="LobbyPanel"] +layout_mode = 0 offset_left = 10.0 offset_top = 10.0 offset_right = 62.0 @@ -50,6 +49,7 @@ size_flags_vertical = 0 text = "Address" [node name="Address" type="LineEdit" parent="LobbyPanel"] +layout_mode = 0 offset_left = 10.0 offset_top = 30.0 offset_right = 210.0 @@ -59,6 +59,7 @@ size_flags_vertical = 2 text = "127.0.0.1" [node name="HostButton" type="Button" parent="LobbyPanel"] +layout_mode = 0 offset_left = 10.0 offset_top = 60.0 offset_right = 90.0 @@ -68,6 +69,7 @@ size_flags_vertical = 2 text = "Host" [node name="JoinButton" type="Button" parent="LobbyPanel"] +layout_mode = 0 offset_left = 130.0 offset_top = 60.0 offset_right = 210.0 @@ -75,29 +77,24 @@ offset_bottom = 80.0 size_flags_horizontal = 2 size_flags_vertical = 2 text = "Join" -__meta__ = { -"_edit_use_anchors_": false -} [node name="StatusOk" type="Label" parent="LobbyPanel"] +layout_mode = 0 offset_left = 10.0 offset_top = 90.0 offset_right = 210.0 offset_bottom = 104.0 size_flags_horizontal = 2 size_flags_vertical = 0 -custom_colors/font_color = Color(0, 1, 0.015625, 1) -align = 1 [node name="StatusFail" type="Label" parent="LobbyPanel"] +layout_mode = 0 offset_left = 10.0 offset_top = 90.0 offset_right = 210.0 offset_bottom = 104.0 size_flags_horizontal = 2 size_flags_vertical = 0 -custom_colors/font_color = Color(1, 0, 0, 1) -align = 1 [connection signal="pressed" from="LobbyPanel/HostButton" to="LobbyPanel" method="OnHostPressed"] [connection signal="pressed" from="LobbyPanel/JoinButton" to="LobbyPanel" method="OnJoinPressed"] diff --git a/mono/multiplayer_pong/logic/Ball.cs b/mono/multiplayer_pong/logic/Ball.cs index ee9e779629..7d1e575e67 100644 --- a/mono/multiplayer_pong/logic/Ball.cs +++ b/mono/multiplayer_pong/logic/Ball.cs @@ -7,7 +7,7 @@ public partial class Ball : Area2D private Vector2 _direction = Vector2.Left; private bool _stopped = false; - private float _speed = DefaultSpeed; + private double _speed = DefaultSpeed; private Vector2 _screenSize; // Called when the node enters the scene tree for the first time. @@ -17,7 +17,7 @@ public override void _Ready() } // Called every frame. 'delta' is the elapsed time since the previous frame. - public override void _Process(float delta) + public override void _Process(double delta) { _speed += delta; // Ball will move normally for both players, @@ -25,36 +25,36 @@ public override void _Process(float delta) // so each player sees the motion as smooth and not jerky. if (!_stopped) { - Translate(_speed * delta * _direction); + Translate((float)(_speed * delta) * _direction); } // Check screen bounds to make ball bounce. var ballPosition = Position; - if ((ballPosition.y < 0 && _direction.y < 0) || (ballPosition.y > _screenSize.y && _direction.y > 0)) + if ((ballPosition.Y < 0 && _direction.Y < 0) || (ballPosition.Y > _screenSize.Y && _direction.Y > 0)) { - _direction.y = -_direction.y; + _direction.Y = -_direction.Y; } - if (IsNetworkMaster()) + if (IsMultiplayerAuthority()) { - // Only the master will decide when the ball is out in - // the left side (it's own side). This makes the game - // playable even if latency is high and ball is going - // fast. Otherwise ball might be out in the other + // Only the server (Multiplayer Authority) will decide + // when the ball is out in the left side (it's own side). + // This makes the game playable even if latency is high and + // ball is going fast. Otherwise ball might be out in the other // player's screen but not this one. - if (ballPosition.x < 0) + if (ballPosition.X < 0) { GetParent().Rpc("UpdateScore", false); Rpc("ResetBall", false); } else { - // Only the puppet will decide when the ball is out in + // Only the peer will decide when the ball is out in // the right side, which is it's own side. This makes // the game playable even if latency is high and ball // is going fast. Otherwise ball might be out in the // other player's screen but not this one. - if (ballPosition.x > _screenSize.x) + if (ballPosition.X > _screenSize.X) { GetParent().Rpc("UpdateScore", true); Rpc("ResetBall", true); @@ -63,31 +63,31 @@ public override void _Process(float delta) } } - [Sync] + [Rpc(mode: MultiplayerApi.RpcMode.AnyPeer, CallLocal = true)] private void Bounce(bool left, float random) { // Using sync because both players can make it bounce. if (left) { - _direction.x = Mathf.Abs(_direction.x); + _direction.X = Mathf.Abs(_direction.X); } else { - _direction.x = -Mathf.Abs(_direction.x); + _direction.X = -Mathf.Abs(_direction.X); } _speed *= 1.1f; - _direction.y = random * 2.0f - 1; + _direction.Y = random * 2.0f - 1; _direction = _direction.Normalized(); } - [Sync] + [Rpc(mode: MultiplayerApi.RpcMode.AnyPeer, CallLocal = true)] private void Stop() { _stopped = true; } - [Sync] + [Rpc(mode: MultiplayerApi.RpcMode.AnyPeer, CallLocal = true)] private void ResetBall(bool forLeft) { Position = _screenSize / 2; diff --git a/mono/multiplayer_pong/logic/Lobby.cs b/mono/multiplayer_pong/logic/Lobby.cs index 78ebb8c247..f054fa2553 100644 --- a/mono/multiplayer_pong/logic/Lobby.cs +++ b/mono/multiplayer_pong/logic/Lobby.cs @@ -12,7 +12,7 @@ public partial class Lobby : Control private Button _joinButton; private Label _statusOk; private Label _statusFail; - private NetworkedMultiplayerENet _peer; + private ENetMultiplayerPeer _peer; public override void _Ready() { @@ -25,11 +25,11 @@ public override void _Ready() // Connect all callbacks related to networking. // Note: Use snake_case when talking to engine API. - GetTree().Connect("network_peer_connected", this, nameof(PlayerConnected)); - GetTree().Connect("network_peer_disconnected", this, nameof(PlayerDisconnected)); - GetTree().Connect("connected_to_server", this, nameof(ConnectedOk)); - GetTree().Connect("connection_failed", this, nameof(ConnectedFail)); - GetTree().Connect("server_disconnected", this, nameof(ServerDisconnected)); + GetTree().GetMultiplayer().Connect("peer_connected", new Callable(this, nameof(PlayerConnected))); + GetTree().GetMultiplayer().Connect("peer_disconnected", new Callable(this, nameof(PlayerDisconnected))); + GetTree().GetMultiplayer().Connect("connected_to_server", new Callable(this, nameof(ConnectedOk))); + GetTree().GetMultiplayer().Connect("connection_failed", new Callable(this, nameof(ConnectedFail))); + GetTree().GetMultiplayer().Connect("server_disconnected", new Callable(this, nameof(ServerDisconnected))); } // Network callbacks from SceneTree @@ -41,7 +41,7 @@ private void PlayerConnected(int id) var pong = ResourceLoader.Load("res://pong.tscn").Instantiate(); // Connect deferred so we can safely erase it from the callback. - pong.Connect("GameFinished", this, nameof(EndGame), new Godot.Collections.Array(), (int) ConnectFlags.Deferred); + pong.Connect("GameFinished", new Callable(this, nameof(EndGame)), (int) ConnectFlags.Deferred); GetTree().Root.AddChild(pong); Hide(); @@ -49,7 +49,7 @@ private void PlayerConnected(int id) private void PlayerDisconnected(int id) { - EndGame(GetTree().IsNetworkServer() ? "Client disconnected" : "Server disconnected"); + EndGame(GetTree().GetMultiplayer().IsServer() ? "Client disconnected" : "Server disconnected"); } // Callback from SceneTree, only for clients (not server). @@ -63,7 +63,7 @@ private void ConnectedFail() { SetStatus("Couldn't connect", false); - GetTree().NetworkPeer = null; // Remove peer. + GetTree().GetMultiplayer().MultiplayerPeer = null; // Remove peer. _hostButton.Disabled = false; _joinButton.Disabled = false; } @@ -85,7 +85,7 @@ private void EndGame(string withError = "") Show(); } - GetTree().NetworkPeer = null; // Remove peer. + GetTree().GetMultiplayer().MultiplayerPeer = null; // Remove peer. _hostButton.Disabled = false; _joinButton.Disabled = false; @@ -109,8 +109,7 @@ private void SetStatus(string text, bool isOk) private void OnHostPressed() { - _peer = new NetworkedMultiplayerENet(); - _peer.CompressionMode = NetworkedMultiplayerENet.CompressionModeEnum.RangeCoder; + _peer = new ENetMultiplayerPeer(); Error err = _peer.CreateServer(DefaultPort, MaxNumberOfPeers); if (err != Error.Ok) { @@ -119,7 +118,9 @@ private void OnHostPressed() return; } - GetTree().NetworkPeer = _peer; + _peer.Host.Compress(ENetConnection.CompressionMode.RangeCoder); + + GetTree().GetMultiplayer().MultiplayerPeer = _peer; _hostButton.Disabled = true; _joinButton.Disabled = true; SetStatus("Waiting for player...", true); @@ -134,10 +135,11 @@ private void OnJoinPressed() return; } - _peer = new NetworkedMultiplayerENet(); - _peer.CompressionMode = NetworkedMultiplayerENet.CompressionModeEnum.RangeCoder; + _peer = new ENetMultiplayerPeer(); _peer.CreateClient(ip, DefaultPort); - GetTree().NetworkPeer = _peer; + _peer.Host.Compress(ENetConnection.CompressionMode.RangeCoder); + + GetTree().GetMultiplayer().MultiplayerPeer = _peer; SetStatus("Connecting...", true); } } diff --git a/mono/multiplayer_pong/logic/Paddle.cs b/mono/multiplayer_pong/logic/Paddle.cs index d62bd7da6e..dd3f571cb7 100644 --- a/mono/multiplayer_pong/logic/Paddle.cs +++ b/mono/multiplayer_pong/logic/Paddle.cs @@ -13,16 +13,15 @@ public partial class Paddle : Area2D public override void _Ready() { - _screenSizeY = GetViewportRect().Size.y; + _screenSizeY = GetViewportRect().Size.Y; } - public override void _Process(float delta) + public override void _Process(double delta) { // Is the master of the paddle. - if (IsNetworkMaster()) + if (IsMultiplayerAuthority()) { _motion = Input.GetActionStrength("move_down") - Input.GetActionStrength("move_up"); - if (!_youHidden && _motion != 0) { HideYouLabel(); @@ -32,7 +31,7 @@ public override void _Process(float delta) // Using unreliable to make sure position is updated as fast as possible, // even if one of the calls is dropped - RpcUnreliable(nameof(SetPosAndMotion), Position, _motion); + Rpc(nameof(SetPosAndMotion), Position, _motion); } else { @@ -41,13 +40,13 @@ public override void _Process(float delta) HideYouLabel(); } } - Translate(new Vector2(0, _motion * delta)); + Translate(new Vector2(0, _motion * (float)delta)); // Set screen limits. Can't modify structs directly, so we create a new one. - Position = new Vector2(Position.x, Mathf.Clamp(Position.y, 16, _screenSizeY - 16)); + Position = new Vector2(Position.X, Mathf.Clamp(Position.Y, 16, _screenSizeY - 16)); } - [Puppet] + [Rpc(TransferMode = MultiplayerPeer.TransferModeEnum.Unreliable)] private void SetPosAndMotion(Vector2 pos, float motion) { Position = pos; @@ -62,7 +61,7 @@ private void HideYouLabel() private void OnPaddleAreaEnter(Area2D area) { - if (IsNetworkMaster()) + if (IsMultiplayerAuthority()) { area.Rpc("Bounce", _left, GD.Randf()); } diff --git a/mono/multiplayer_pong/logic/Pong.cs b/mono/multiplayer_pong/logic/Pong.cs index 8812beed33..bad7dbd85d 100644 --- a/mono/multiplayer_pong/logic/Pong.cs +++ b/mono/multiplayer_pong/logic/Pong.cs @@ -4,9 +4,9 @@ public partial class Pong : Node2D { [Signal] - private delegate void GameFinished(string withError); + public delegate void GameFinishedEventHandler(string withError); - private const int ScoreToWin = 10; + private const int ScoreToWin = 3; private int _scoreLeft = 0; private int _scoreRight = 0; @@ -28,19 +28,19 @@ public override void _Ready() // By default, all nodes in server inherit from master, // while all nodes in clients inherit from puppet. // SetNetworkMaster is tree-recursive by default. - if (GetTree().IsNetworkServer()) + if (GetTree().GetMultiplayer().IsServer()) { - _playerTwo.SetNetworkMaster(GetTree().GetNetworkConnectedPeers()[0]); + _playerTwo.SetMultiplayerAuthority(GetTree().GetMultiplayer().GetPeers()[0]); } else { - _playerTwo.SetNetworkMaster(GetTree().GetNetworkUniqueId()); + _playerTwo.SetMultiplayerAuthority(GetTree().GetMultiplayer().GetUniqueId()); } - GD.Print("Unique id: ", GetTree().GetNetworkUniqueId()); + GD.Print("Unique id: ", GetTree().GetMultiplayer().GetUniqueId()); } - [Sync] + [Rpc(CallLocal = true)] private void UpdateScore(bool addToLeft) { if (addToLeft) diff --git a/mono/multiplayer_pong/project.godot b/mono/multiplayer_pong/project.godot index 688f3fd9aa..6bf314db45 100644 --- a/mono/multiplayer_pong/project.godot +++ b/mono/multiplayer_pong/project.godot @@ -16,7 +16,7 @@ One of the players should press 'host', while the other should select the address and press 'join'." config/tags=PackedStringArray("2d", "demo", "network", "official") run/main_scene="res://lobby.tscn" -config/features=PackedStringArray("4.2") +config/features=PackedStringArray("4.2", "C#") config/icon="res://icon.webp" [display] @@ -26,6 +26,10 @@ window/size/viewport_height=400 window/stretch/mode="canvas_items" window/stretch/aspect="expand" +[dotnet] + +project/assembly_name="Pong Multiplayer with C#" + [input] move_down={