Compare commits
8 Commits
main
...
feat/liten
Author | SHA1 | Date |
---|---|---|
Syntriax | 05dfb92bab | |
Syntriax | 7f169fc788 | |
Syntriax | 376f18c43a | |
Syntriax | 150deaa618 | |
Syntriax | d011bf9a7a | |
Syntriax | 19124e733c | |
Syntriax | c28568d0cb | |
Syntriax | 91d301677f |
|
@ -0,0 +1,46 @@
|
||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Start Client",
|
||||||
|
"type": "coreclr",
|
||||||
|
"request": "launch",
|
||||||
|
"preLaunchTask": "build",
|
||||||
|
// If you have changed target frameworks, make sure to update the program path.
|
||||||
|
"program": "${workspaceFolder}/Game/bin/Debug/net8.0/Game.dll",
|
||||||
|
"args": ["127.0.0.1"],
|
||||||
|
"cwd": "${workspaceFolder}",
|
||||||
|
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
|
||||||
|
"console": "internalConsole",
|
||||||
|
"stopAtEntry": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": ".NET Core Attach",
|
||||||
|
"type": "coreclr",
|
||||||
|
"request": "attach",
|
||||||
|
"processId": "${command:pickProcess}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Start Server",
|
||||||
|
"type": "coreclr",
|
||||||
|
"request": "launch",
|
||||||
|
"preLaunchTask": "build",
|
||||||
|
// If you have changed target frameworks, make sure to update the program path.
|
||||||
|
"program": "${workspaceFolder}/Game/bin/Debug/net8.0/Game.dll",
|
||||||
|
"args": ["server"],
|
||||||
|
"cwd": "${workspaceFolder}",
|
||||||
|
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
|
||||||
|
"console": "internalConsole",
|
||||||
|
"stopAtEntry": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": ".NET Core Attach",
|
||||||
|
"type": "coreclr",
|
||||||
|
"request": "attach",
|
||||||
|
"processId": "${command:pickProcess}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -1,27 +0,0 @@
|
||||||
{
|
|
||||||
// Use IntelliSense to learn about possible attributes.
|
|
||||||
// Hover to view descriptions of existing attributes.
|
|
||||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
|
||||||
"version": "0.2.0",
|
|
||||||
"configurations": [
|
|
||||||
{
|
|
||||||
"name": ".NET Core Launch (console)",
|
|
||||||
"type": "coreclr",
|
|
||||||
"request": "launch",
|
|
||||||
"preLaunchTask": "build",
|
|
||||||
// If you have changed target frameworks, make sure to update the program path.
|
|
||||||
"program": "${workspaceFolder}/bin/Debug/net8.0/${workspaceFolderBasename}.dll",
|
|
||||||
"args": [],
|
|
||||||
"cwd": "${workspaceFolder}",
|
|
||||||
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
|
|
||||||
"console": "internalConsole",
|
|
||||||
"stopAtEntry": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": ".NET Core Attach",
|
|
||||||
"type": "coreclr",
|
|
||||||
"request": "attach",
|
|
||||||
"processId": "${command:pickProcess}"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,13 +1,15 @@
|
||||||
using System;
|
using System;
|
||||||
|
using LiteNetLib.Utils;
|
||||||
using Microsoft.Xna.Framework.Input;
|
using Microsoft.Xna.Framework.Input;
|
||||||
|
|
||||||
using Syntriax.Engine.Core;
|
using Syntriax.Engine.Core;
|
||||||
using Syntriax.Engine.Input;
|
using Syntriax.Engine.Input;
|
||||||
|
using Syntriax.Engine.Network;
|
||||||
|
using Syntriax.Engine.Network.Abstract;
|
||||||
|
|
||||||
namespace Pong.Behaviours;
|
namespace Pong.Behaviours;
|
||||||
|
|
||||||
public class PaddleBehaviour(Keys Up, Keys Down, float High, float Low, float Speed) : BehaviourOverride
|
public class PaddleBehaviour(Keys Up, Keys Down, float High, float Low, float Speed) : NetworkBehaviour
|
||||||
{
|
{
|
||||||
private Keys Up { get; } = Up;
|
private Keys Up { get; } = Up;
|
||||||
private Keys Down { get; } = Down;
|
private Keys Down { get; } = Down;
|
||||||
|
@ -26,10 +28,14 @@ public class PaddleBehaviour(Keys Up, Keys Down, float High, float Low, float Sp
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (isUpPressed)
|
if (isUpPressed)
|
||||||
GameObject.Transform.Position = GameObject.Transform.Position + Vector2D.Up * (float)Time.Elapsed.TotalSeconds * Speed;
|
Move(Vector2D.Up);
|
||||||
else if (isDownPressed)
|
else if (isDownPressed)
|
||||||
GameObject.Transform.Position = GameObject.Transform.Position + -Vector2D.Up * (float)Time.Elapsed.TotalSeconds * Speed;
|
Move(-Vector2D.Up);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Move(Vector2D vectorToMove)
|
||||||
|
{
|
||||||
|
GameObject.Transform.Position = GameObject.Transform.Position + vectorToMove * (float)Time.Elapsed.TotalSeconds * Speed;
|
||||||
GameObject.Transform.Position = new Vector2D(GameObject.Transform.Position.X, MathF.Max(MathF.Min(GameObject.Transform.Position.Y, High), Low));
|
GameObject.Transform.Position = new Vector2D(GameObject.Transform.Position.X, MathF.Max(MathF.Min(GameObject.Transform.Position.Y, High), Low));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,8 +60,40 @@ public class PaddleBehaviour(Keys Up, Keys Down, float High, float Low, float Sp
|
||||||
inputs.UnregisterOnRelease(Down, OnDownReleased);
|
inputs.UnregisterOnRelease(Down, OnDownReleased);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnUpPressed(IButtonInputs<Keys> inputs, Keys keys) => isUpPressed = true;
|
private void OnUpPressed(IButtonInputs<Keys> inputs, Keys keys) { isUpPressed = true; SendData(new PaddleInputs() { IsUpPressed = isUpPressed, IsDownPressed = isDownPressed, PositionY = Transform.Position.Y }); }
|
||||||
private void OnUpReleased(IButtonInputs<Keys> inputs, Keys keys) => isUpPressed = false;
|
private void OnUpReleased(IButtonInputs<Keys> inputs, Keys keys) { isUpPressed = false; SendData(new PaddleInputs() { IsUpPressed = isUpPressed, IsDownPressed = isDownPressed, PositionY = Transform.Position.Y }); }
|
||||||
private void OnDownPressed(IButtonInputs<Keys> inputs, Keys keys) => isDownPressed = true;
|
private void OnDownPressed(IButtonInputs<Keys> inputs, Keys keys) { isDownPressed = true; SendData(new PaddleInputs() { IsUpPressed = isUpPressed, IsDownPressed = isDownPressed, PositionY = Transform.Position.Y }); }
|
||||||
private void OnDownReleased(IButtonInputs<Keys> inputs, Keys keys) => isDownPressed = false;
|
private void OnDownReleased(IButtonInputs<Keys> inputs, Keys keys) { isDownPressed = false; SendData(new PaddleInputs() { IsUpPressed = isUpPressed, IsDownPressed = isDownPressed, PositionY = Transform.Position.Y }); }
|
||||||
|
|
||||||
|
public override void ReceiveData<T>(T data)
|
||||||
|
{
|
||||||
|
if (data is not PaddleInputs paddleInputs)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Transform.Position = new(Transform.Position.X, paddleInputs.PositionY);
|
||||||
|
isUpPressed = paddleInputs.IsUpPressed;
|
||||||
|
isDownPressed = paddleInputs.IsDownPressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
[System.Serializable]
|
||||||
|
public struct PaddleInputs : INetworkPacket
|
||||||
|
{
|
||||||
|
public float PositionY { get; set; }
|
||||||
|
public bool IsUpPressed { get; set; }
|
||||||
|
public bool IsDownPressed { get; set; }
|
||||||
|
|
||||||
|
public void Deserialize(NetDataReader reader)
|
||||||
|
{
|
||||||
|
PositionY = reader.GetFloat();
|
||||||
|
IsUpPressed = reader.GetBool();
|
||||||
|
IsDownPressed = reader.GetBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Serialize(NetDataWriter writer)
|
||||||
|
{
|
||||||
|
writer.Put(PositionY);
|
||||||
|
writer.Put(IsUpPressed);
|
||||||
|
writer.Put(IsDownPressed);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Apos.Shapes" Version="0.2.3" />
|
<PackageReference Include="Apos.Shapes" Version="0.2.3" />
|
||||||
|
<PackageReference Include="LiteNetLib" Version="1.2.0" />
|
||||||
<PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.1.303" />
|
<PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.1.303" />
|
||||||
<PackageReference Include="MonoGame.Content.Builder.Task" Version="3.8.1.303" />
|
<PackageReference Include="MonoGame.Content.Builder.Task" Version="3.8.1.303" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
@ -1,16 +1,19 @@
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
using Microsoft.Xna.Framework.Input;
|
using Microsoft.Xna.Framework.Input;
|
||||||
|
|
||||||
using Pong.Behaviours;
|
|
||||||
using Apos.Shapes;
|
using Apos.Shapes;
|
||||||
|
|
||||||
|
using Pong.Behaviours;
|
||||||
|
using Syntriax.Engine.Network;
|
||||||
|
|
||||||
using Syntriax.Engine.Core;
|
using Syntriax.Engine.Core;
|
||||||
using Syntriax.Engine.Core.Abstract;
|
using Syntriax.Engine.Core.Abstract;
|
||||||
using Syntriax.Engine.Physics2D;
|
using Syntriax.Engine.Physics2D;
|
||||||
using Syntriax.Engine.Physics2D.Primitives;
|
|
||||||
using Syntriax.Engine.Physics2D.Abstract;
|
using Syntriax.Engine.Physics2D.Abstract;
|
||||||
|
using Syntriax.Engine.Physics2D.Primitives;
|
||||||
|
|
||||||
namespace Pong;
|
namespace Pong;
|
||||||
|
|
||||||
|
@ -64,58 +67,84 @@ public class GamePong : Game
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
IGameObject gameObjectCamera = gameManager.InstantiateGameObject<GameObject>().SetGameObject("Camera"); ;
|
string[] commandLineArguments = Environment.GetCommandLineArgs();
|
||||||
|
if (commandLineArguments.Length != 1)
|
||||||
|
{
|
||||||
|
if (commandLineArguments[1].Equals("server", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
gameManager.InstantiateGameObject().BehaviourController.AddBehaviour<NetworkServer>().Start(8888, 2);
|
||||||
|
Window.Title = "Pong - Server";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Window.Title = $"Pong - Client -> {commandLineArguments[1]}";
|
||||||
|
gameManager.InstantiateGameObject().BehaviourController.AddBehaviour<NetworkClient>().Connect(commandLineArguments[1], 8888);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gameManager.InstantiateGameObject().BehaviourController.AddBehaviour<NetworkClient>().Connect("127.0.0.1", 8888);
|
||||||
|
Window.Title = $"Pong - Client -> 127.0.0.1";
|
||||||
|
}
|
||||||
|
|
||||||
|
IGameObject gameObjectNetworkManager = gameManager.InstantiateGameObject().SetGameObject("Network Manager"); ;
|
||||||
|
gameObjectNetworkManager.BehaviourController.AddBehaviour<NetworkManager>();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
IGameObject gameObjectCamera = gameManager.InstantiateGameObject().SetGameObject("Camera"); ;
|
||||||
gameObjectCamera.BehaviourController.AddBehaviour<CameraController>();
|
gameObjectCamera.BehaviourController.AddBehaviour<CameraController>();
|
||||||
cameraBehaviour = gameObjectCamera.BehaviourController.AddBehaviour<MonoGameCamera2DBehaviour>(graphics);
|
cameraBehaviour = gameObjectCamera.BehaviourController.AddBehaviour<MonoGameCamera2DBehaviour>(graphics);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
IGameObject gameObjectPongManager = gameManager.InstantiateGameObject<GameObject>().SetGameObject("Pong Game Manager");
|
IGameObject gameObjectPongManager = gameManager.InstantiateGameObject().SetGameObject("Pong Game Manager");
|
||||||
pongManager = gameObjectPongManager.BehaviourController.AddBehaviour<PongManagerBehaviour>(5);
|
pongManager = gameObjectPongManager.BehaviourController.AddBehaviour<PongManagerBehaviour>(5);
|
||||||
|
pongManager.Id = "pongManager";
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
IGameObject gameObjectBall = gameManager.InstantiateGameObject<GameObject>().SetGameObject("Ball");
|
IGameObject gameObjectBall = gameManager.InstantiateGameObject().SetGameObject("Ball");
|
||||||
gameObjectBall.Transform.SetTransform(position: new Vector2D(0, 0f), scale: new Vector2D(10f, 10f));
|
gameObjectBall.Transform.SetTransform(position: new Vector2D(0, 0f), scale: new Vector2D(10f, 10f));
|
||||||
|
|
||||||
gameObjectBall.BehaviourController.AddBehaviour<CircleBehaviour>(new Circle(Vector2D.Zero, 1f));
|
gameObjectBall.BehaviourController.AddBehaviour<CircleBehaviour>(new Circle(Vector2D.Zero, 1f));
|
||||||
gameObjectBall.BehaviourController.AddBehaviour<BallBehaviour>();
|
gameObjectBall.BehaviourController.AddBehaviour<BallBehaviour>().Id = "ball";
|
||||||
gameObjectBall.BehaviourController.AddBehaviour<RigidBody2D>();
|
gameObjectBall.BehaviourController.AddBehaviour<RigidBody2D>();
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
IGameObject gameObjectLeftPaddle = gameManager.InstantiateGameObject<GameObject>().SetGameObject("Left Paddle");
|
IGameObject gameObjectLeftPaddle = gameManager.InstantiateGameObject().SetGameObject("Left Paddle");
|
||||||
gameObjectLeftPaddle.Transform.SetTransform(position: new Vector2D(-468f, 0f), scale: new Vector2D(15f, 60f));
|
gameObjectLeftPaddle.Transform.SetTransform(position: new Vector2D(-468f, 0f), scale: new Vector2D(15f, 60f));
|
||||||
|
|
||||||
gameObjectLeftPaddle.BehaviourController.AddBehaviour<PaddleBehaviour>(Keys.W, Keys.S, 228f, -228f, 400f);
|
gameObjectLeftPaddle.BehaviourController.AddBehaviour<PaddleBehaviour>(Keys.W, Keys.S, 228f, -228f, 400f).Id = "leftPaddle";
|
||||||
gameObjectLeftPaddle.BehaviourController.AddBehaviour<ShapeBehaviour>(Shape.Box);
|
gameObjectLeftPaddle.BehaviourController.AddBehaviour<ShapeBehaviour>(Shape.Box);
|
||||||
gameObjectLeftPaddle.BehaviourController.AddBehaviour<RigidBody2D>().IsStatic = true;
|
gameObjectLeftPaddle.BehaviourController.AddBehaviour<RigidBody2D>().IsStatic = true;
|
||||||
|
|
||||||
IGameObject gameObjectRightPaddle = gameManager.InstantiateGameObject<GameObject>().SetGameObject("Right Paddle");
|
IGameObject gameObjectRightPaddle = gameManager.InstantiateGameObject().SetGameObject("Right Paddle");
|
||||||
gameObjectRightPaddle.Transform.SetTransform(position: new Vector2D(468f, 0f), scale: new Vector2D(15f, 60f));
|
gameObjectRightPaddle.Transform.SetTransform(position: new Vector2D(468f, 0f), scale: new Vector2D(15f, 60f));
|
||||||
gameObjectRightPaddle.BehaviourController.AddBehaviour<PaddleBehaviour>(Keys.Up, Keys.Down, 228f, -228f, 400f);
|
gameObjectRightPaddle.BehaviourController.AddBehaviour<PaddleBehaviour>(Keys.Up, Keys.Down, 228f, -228f, 400f).Id = "rightPaddle";
|
||||||
gameObjectRightPaddle.BehaviourController.AddBehaviour<ShapeBehaviour>(Shape.Box);
|
gameObjectRightPaddle.BehaviourController.AddBehaviour<ShapeBehaviour>(Shape.Box);
|
||||||
gameObjectRightPaddle.BehaviourController.AddBehaviour<RigidBody2D>().IsStatic = true;
|
gameObjectRightPaddle.BehaviourController.AddBehaviour<RigidBody2D>().IsStatic = true;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
IGameObject gameObjectWallTop = gameManager.InstantiateGameObject<GameObject>().SetGameObject("Wall Top");
|
IGameObject gameObjectWallTop = gameManager.InstantiateGameObject().SetGameObject("Wall Top");
|
||||||
gameObjectWallTop.Transform.SetTransform(position: new Vector2D(0f, 308f), scale: new Vector2D(552f, 20f));
|
gameObjectWallTop.Transform.SetTransform(position: new Vector2D(0f, 308f), scale: new Vector2D(552f, 20f));
|
||||||
gameObjectWallTop.BehaviourController.AddBehaviour<ShapeBehaviour>(Shape.Box);
|
gameObjectWallTop.BehaviourController.AddBehaviour<ShapeBehaviour>(Shape.Box);
|
||||||
gameObjectWallTop.BehaviourController.AddBehaviour<RigidBody2D>().IsStatic = true;
|
gameObjectWallTop.BehaviourController.AddBehaviour<RigidBody2D>().IsStatic = true;
|
||||||
|
|
||||||
IGameObject gameObjectWallBottom = gameManager.InstantiateGameObject<GameObject>().SetGameObject("Wall Bottom");
|
IGameObject gameObjectWallBottom = gameManager.InstantiateGameObject().SetGameObject("Wall Bottom");
|
||||||
gameObjectWallBottom.Transform.SetTransform(position: new Vector2D(0f, -308f), scale: new Vector2D(552f, 20f));
|
gameObjectWallBottom.Transform.SetTransform(position: new Vector2D(0f, -308f), scale: new Vector2D(552f, 20f));
|
||||||
gameObjectWallBottom.BehaviourController.AddBehaviour<ShapeBehaviour>(Shape.Box);
|
gameObjectWallBottom.BehaviourController.AddBehaviour<ShapeBehaviour>(Shape.Box);
|
||||||
gameObjectWallBottom.BehaviourController.AddBehaviour<RigidBody2D>().IsStatic = true;
|
gameObjectWallBottom.BehaviourController.AddBehaviour<RigidBody2D>().IsStatic = true;
|
||||||
|
|
||||||
IGameObject gameObjectWallRight = gameManager.InstantiateGameObject<GameObject>().SetGameObject("Wall Right");
|
IGameObject gameObjectWallRight = gameManager.InstantiateGameObject().SetGameObject("Wall Right");
|
||||||
gameObjectWallRight.Transform.SetTransform(position: new Vector2D(532f, 0f), scale: new Vector2D(20f, 328f));
|
gameObjectWallRight.Transform.SetTransform(position: new Vector2D(532f, 0f), scale: new Vector2D(20f, 328f));
|
||||||
gameObjectWallRight.BehaviourController.AddBehaviour<WallScoreBehaviour>((Action)pongManager.ScoreToLeft);
|
gameObjectWallRight.BehaviourController.AddBehaviour<WallScoreBehaviour>((Action)pongManager.ScoreToLeft);
|
||||||
gameObjectWallRight.BehaviourController.AddBehaviour<ShapeBehaviour>(Shape.Box);
|
gameObjectWallRight.BehaviourController.AddBehaviour<ShapeBehaviour>(Shape.Box);
|
||||||
gameObjectWallRight.BehaviourController.AddBehaviour<RigidBody2D>().IsStatic = true;
|
gameObjectWallRight.BehaviourController.AddBehaviour<RigidBody2D>().IsStatic = true;
|
||||||
|
|
||||||
IGameObject gameObjectWallLeft = gameManager.InstantiateGameObject<GameObject>().SetGameObject("Wall Left");
|
IGameObject gameObjectWallLeft = gameManager.InstantiateGameObject().SetGameObject("Wall Left");
|
||||||
gameObjectWallLeft.Transform.SetTransform(position: new Vector2D(-532f, 0f), scale: new Vector2D(20f, 328f));
|
gameObjectWallLeft.Transform.SetTransform(position: new Vector2D(-532f, 0f), scale: new Vector2D(20f, 328f));
|
||||||
gameObjectWallLeft.BehaviourController.AddBehaviour<WallScoreBehaviour>((Action)pongManager.ScoreToRight);
|
gameObjectWallLeft.BehaviourController.AddBehaviour<WallScoreBehaviour>((Action)pongManager.ScoreToRight);
|
||||||
gameObjectWallLeft.BehaviourController.AddBehaviour<ShapeBehaviour>(Shape.Box);
|
gameObjectWallLeft.BehaviourController.AddBehaviour<ShapeBehaviour>(Shape.Box);
|
||||||
|
@ -123,11 +152,11 @@ public class GamePong : Game
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
IGameObject gameObjectLeftScoreText = gameManager.InstantiateGameObject<GameObject>().SetGameObject("Score Left");
|
IGameObject gameObjectLeftScoreText = gameManager.InstantiateGameObject().SetGameObject("Score Left");
|
||||||
gameObjectLeftScoreText.Transform.SetTransform(position: new Vector2D(-250f, 250f), scale: Vector2D.One * .25f);
|
gameObjectLeftScoreText.Transform.SetTransform(position: new Vector2D(-250f, 250f), scale: Vector2D.One * .25f);
|
||||||
gameObjectLeftScoreText.BehaviourController.AddBehaviour<TextScoreBehaviour>(true, spriteFont);
|
gameObjectLeftScoreText.BehaviourController.AddBehaviour<TextScoreBehaviour>(true, spriteFont);
|
||||||
|
|
||||||
IGameObject gameObjectRightScoreText = gameManager.InstantiateGameObject<GameObject>().SetGameObject("Score Right");
|
IGameObject gameObjectRightScoreText = gameManager.InstantiateGameObject().SetGameObject("Score Right");
|
||||||
gameObjectRightScoreText.Transform.SetTransform(position: new Vector2D(250f, 250f), scale: Vector2D.One * .25f);
|
gameObjectRightScoreText.Transform.SetTransform(position: new Vector2D(250f, 250f), scale: Vector2D.One * .25f);
|
||||||
gameObjectRightScoreText.BehaviourController.AddBehaviour<TextScoreBehaviour>(false, spriteFont);
|
gameObjectRightScoreText.BehaviourController.AddBehaviour<TextScoreBehaviour>(false, spriteFont);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
using Syntriax.Engine.Core.Abstract;
|
||||||
|
|
||||||
|
namespace Syntriax.Engine.Network.Abstract;
|
||||||
|
|
||||||
|
public interface INetworkBehaviour : IBehaviour, INetworkEntity
|
||||||
|
{
|
||||||
|
bool IsServer { get; }
|
||||||
|
bool IsClient { get; }
|
||||||
|
|
||||||
|
INetworkCommunicator NetworkCommunicator { get; }
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
using LiteNetLib;
|
||||||
|
|
||||||
|
namespace Syntriax.Engine.Network.Abstract;
|
||||||
|
|
||||||
|
public interface INetworkCommunicator
|
||||||
|
{
|
||||||
|
event OnPacketReceivedDelegate? OnPacketReceived;
|
||||||
|
|
||||||
|
EventBasedNetListener Listener { get; }
|
||||||
|
NetManager Manager { get; }
|
||||||
|
|
||||||
|
void PollEvents();
|
||||||
|
void Stop();
|
||||||
|
|
||||||
|
void Send<T>(NetworkPacket<T> Data);
|
||||||
|
|
||||||
|
delegate void OnPacketReceivedDelegate(INetworkCommunicator sender, object packet);
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
namespace Syntriax.Engine.Network.Abstract;
|
||||||
|
|
||||||
|
public interface INetworkCommunicatorClient : INetworkCommunicator
|
||||||
|
{
|
||||||
|
void Connect(string address, int port, string? password = null);
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
namespace Syntriax.Engine.Network.Abstract;
|
||||||
|
|
||||||
|
public interface INetworkCommunicatorServer : INetworkCommunicator
|
||||||
|
{
|
||||||
|
string Password { get; }
|
||||||
|
int MaxConnectionCount { get; }
|
||||||
|
int Port { get; }
|
||||||
|
|
||||||
|
void Start(int port, int maxConnectionCount, string? password = null);
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
namespace Syntriax.Engine.Network.Abstract;
|
||||||
|
|
||||||
|
public interface INetworkEntity
|
||||||
|
{
|
||||||
|
event OnNetworkIdChangedDelegate? OnNetworkIdChanged;
|
||||||
|
|
||||||
|
uint NetworkId { get; set; }
|
||||||
|
|
||||||
|
void ReceiveData<T>(T data);
|
||||||
|
|
||||||
|
delegate void OnNetworkIdChangedDelegate(INetworkEntity sender, uint previousId);
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
namespace Syntriax.Engine.Network.Abstract;
|
||||||
|
|
||||||
|
public interface INetworkManager
|
||||||
|
{
|
||||||
|
// Action<IGameObject>? OnNetworkGameObjectInstantiated { get; set; }
|
||||||
|
|
||||||
|
INetworkCommunicator NetworkCommunicator { get; }
|
||||||
|
|
||||||
|
// Task<T> Instantiate<T>(params object?[]? args) where T : class, IGameObject;
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
using LiteNetLib.Utils;
|
||||||
|
|
||||||
|
namespace Syntriax.Engine.Network.Abstract;
|
||||||
|
|
||||||
|
public interface INetworkPacket : INetSerializable;
|
|
@ -0,0 +1,7 @@
|
||||||
|
namespace Syntriax.Engine.Network.Abstract;
|
||||||
|
|
||||||
|
public class NetworkPacket<T>
|
||||||
|
{
|
||||||
|
public uint NetworkId { get; set; } = 0;
|
||||||
|
public T Data { get; set; } = default!;
|
||||||
|
}
|
|
@ -0,0 +1,140 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using LiteNetLib;
|
||||||
|
using LiteNetLib.Utils;
|
||||||
|
|
||||||
|
using Syntriax.Engine.Core;
|
||||||
|
using Syntriax.Engine.Network.Abstract;
|
||||||
|
|
||||||
|
namespace Syntriax.Engine.Network;
|
||||||
|
|
||||||
|
public abstract class NetworkBase : BehaviourOverride, INetworkCommunicator
|
||||||
|
{
|
||||||
|
public event INetworkCommunicator.OnPacketReceivedDelegate? OnPacketReceived = null;
|
||||||
|
|
||||||
|
protected readonly NetPacketProcessor netPacketProcessor = new();
|
||||||
|
|
||||||
|
protected readonly Dictionary<uint, INetworkEntity> networkEntities = [];
|
||||||
|
|
||||||
|
protected BehaviourCollector<INetworkEntity> networkEntityCollector = null!;
|
||||||
|
|
||||||
|
public EventBasedNetListener Listener { get; private set; } = null!;
|
||||||
|
public NetManager Manager { get; private set; } = null!;
|
||||||
|
|
||||||
|
public NetworkBase()
|
||||||
|
{
|
||||||
|
Priority = 10;
|
||||||
|
|
||||||
|
Listener = new EventBasedNetListener();
|
||||||
|
Manager = new NetManager(Listener);
|
||||||
|
|
||||||
|
Listener.NetworkReceiveEvent += NetworkReceiveEvent;
|
||||||
|
|
||||||
|
netPacketProcessor.RegisterNestedType<Pong.Behaviours.PaddleBehaviour.PaddleInputs>();
|
||||||
|
RegisterPackets();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RegisterPackets()
|
||||||
|
{
|
||||||
|
var packetTypes = Assembly.GetExecutingAssembly().GetTypes()
|
||||||
|
.Where(t => typeof(INetworkPacket).IsAssignableFrom(t) && !t.IsInterface)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
MethodInfo[] subscribeMethods = netPacketProcessor.GetType()
|
||||||
|
.GetMethods()
|
||||||
|
.Where(m => m.Name == nameof(NetPacketProcessor.SubscribeReusable))
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
MethodInfo subscribeMethod = subscribeMethods
|
||||||
|
.FirstOrDefault(m =>
|
||||||
|
m.GetParameters().Length == 1 &&
|
||||||
|
m.GetParameters()[0].ParameterType.GetGenericTypeDefinition() == typeof(Action<,>)
|
||||||
|
) ?? throw new Exception();
|
||||||
|
|
||||||
|
MethodInfo[] methodInfos = typeof(NetworkBase)
|
||||||
|
.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance);
|
||||||
|
|
||||||
|
MethodInfo method = methodInfos
|
||||||
|
.FirstOrDefault(
|
||||||
|
m => m.Name == nameof(OnPacketArrived) &&
|
||||||
|
m.IsGenericMethodDefinition
|
||||||
|
) ?? throw new Exception();
|
||||||
|
|
||||||
|
foreach (var packetType in packetTypes)
|
||||||
|
{
|
||||||
|
var networkPacketType = typeof(NetworkPacket<>).MakeGenericType(packetType);
|
||||||
|
MethodInfo genericSubscribe = subscribeMethod.MakeGenericMethod(networkPacketType, typeof(NetPeer));
|
||||||
|
|
||||||
|
Action<object, NetPeer> handler = (packet, peer) =>
|
||||||
|
{
|
||||||
|
MethodInfo handlerMethod = method.MakeGenericMethod(packetType);
|
||||||
|
handlerMethod.Invoke(this, [packet, peer]);
|
||||||
|
};
|
||||||
|
genericSubscribe.Invoke(netPacketProcessor, [handler]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnPacketArrived<T>(NetworkPacket<T> packet, NetPeer peer) where T : INetworkPacket
|
||||||
|
{
|
||||||
|
if (networkEntities.TryGetValue(packet.NetworkId, out INetworkEntity? entity))
|
||||||
|
entity.ReceiveData(packet.Data);
|
||||||
|
|
||||||
|
OnPacketReceived?.Invoke(this, packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnInitialize()
|
||||||
|
{
|
||||||
|
base.OnInitialize();
|
||||||
|
|
||||||
|
networkEntityCollector = new(GameObject.GameManager);
|
||||||
|
networkEntityCollector.OnCollected += OnNetworkEntityCollected;
|
||||||
|
networkEntityCollector.OnRemoved += OnNetworkEntityRemoved;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnFinalize()
|
||||||
|
{
|
||||||
|
networkEntityCollector.OnCollected -= OnNetworkEntityCollected;
|
||||||
|
networkEntityCollector.OnRemoved -= OnNetworkEntityRemoved;
|
||||||
|
Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnNetworkEntityCollected(BehaviourCollector<INetworkEntity> sender, INetworkEntity behaviourCollected)
|
||||||
|
{
|
||||||
|
if (behaviourCollected.NetworkId != 0)
|
||||||
|
networkEntities.Add(behaviourCollected.NetworkId, behaviourCollected);
|
||||||
|
|
||||||
|
behaviourCollected.OnNetworkIdChanged += OnNetworkIdChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnNetworkIdChanged(INetworkEntity sender, uint previousId)
|
||||||
|
{
|
||||||
|
if (networkEntities.TryGetValue(previousId, out INetworkEntity? networkEntity) && sender == networkEntity)
|
||||||
|
networkEntities.Remove(previousId);
|
||||||
|
|
||||||
|
networkEntities.Add(sender.NetworkId, sender);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnNetworkEntityRemoved(BehaviourCollector<INetworkEntity> sender, INetworkEntity behaviourRemoved)
|
||||||
|
{
|
||||||
|
networkEntities.Remove(behaviourRemoved.NetworkId);
|
||||||
|
behaviourRemoved.OnNetworkIdChanged -= OnNetworkIdChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void NetworkReceiveEvent(NetPeer peer, NetPacketReader reader, byte channel, DeliveryMethod deliveryMethod)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
netPacketProcessor.ReadAllPackets(reader, peer);
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PollEvents() => Manager.PollEvents();
|
||||||
|
public void Stop() => Manager.Stop();
|
||||||
|
|
||||||
|
protected override void OnUpdate() => PollEvents();
|
||||||
|
|
||||||
|
public abstract void Send<T>(NetworkPacket<T> packet);
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
using Syntriax.Engine.Core;
|
||||||
|
using Syntriax.Engine.Network.Abstract;
|
||||||
|
|
||||||
|
namespace Syntriax.Engine.Network;
|
||||||
|
|
||||||
|
public abstract class NetworkBehaviour : BehaviourOverride, INetworkBehaviour
|
||||||
|
{
|
||||||
|
public event INetworkEntity.OnNetworkIdChangedDelegate? OnNetworkIdChanged = null;
|
||||||
|
|
||||||
|
private uint _networkId = 0;
|
||||||
|
public uint NetworkId
|
||||||
|
{
|
||||||
|
get => _networkId;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == _networkId)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint previousNetworkId = _networkId;
|
||||||
|
_networkId = value;
|
||||||
|
OnNetworkIdChanged?.Invoke(this, previousNetworkId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsServer { get; private set; } = false;
|
||||||
|
public bool IsClient { get; private set; } = false;
|
||||||
|
|
||||||
|
public INetworkCommunicator NetworkCommunicator { get; private set; } = null!;
|
||||||
|
|
||||||
|
|
||||||
|
protected override void OnInitialize()
|
||||||
|
{
|
||||||
|
NetworkCommunicator = BehaviourController.GetBehaviourInParent<INetworkCommunicator>()
|
||||||
|
?? GameObject.GameManager.FindBehaviour<INetworkCommunicator>()
|
||||||
|
?? throw new Exception($"Could not find an {nameof(INetworkCommunicator)}.");
|
||||||
|
|
||||||
|
if (NetworkCommunicator is INetworkCommunicatorClient client)
|
||||||
|
{
|
||||||
|
IsClient = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IsServer = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendData<T>(T data)
|
||||||
|
=> NetworkCommunicator.Send(new NetworkPacket<T>() { NetworkId = _networkId, Data = data });
|
||||||
|
|
||||||
|
public abstract void ReceiveData<T>(T data);
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
using LiteNetLib.Utils;
|
||||||
|
|
||||||
|
using Syntriax.Engine.Network.Abstract;
|
||||||
|
|
||||||
|
namespace Syntriax.Engine.Network;
|
||||||
|
|
||||||
|
public class NetworkClient : NetworkBase, INetworkCommunicatorClient
|
||||||
|
{
|
||||||
|
private readonly NetDataWriter netDataWriter = new();
|
||||||
|
|
||||||
|
public void Connect(string address, int port, string? password = null)
|
||||||
|
{
|
||||||
|
Manager.Start();
|
||||||
|
Manager.Connect(address, port, password ?? string.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Send<T>(NetworkPacket<T> packet)
|
||||||
|
{
|
||||||
|
netDataWriter.Reset();
|
||||||
|
netPacketProcessor.Write(netDataWriter, packet);
|
||||||
|
Manager.FirstPeer.Send(netDataWriter, LiteNetLib.DeliveryMethod.ReliableOrdered);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
using LiteNetLib;
|
||||||
|
using LiteNetLib.Utils;
|
||||||
|
|
||||||
|
using Syntriax.Engine.Core;
|
||||||
|
|
||||||
|
namespace Syntriax.Engine.Network;
|
||||||
|
|
||||||
|
public static class NetworkExtensions
|
||||||
|
{
|
||||||
|
public static Vector2D GetVector2D(this NetPacketReader reader)
|
||||||
|
=> new(reader.GetFloat(), reader.GetFloat());
|
||||||
|
|
||||||
|
public static void GetVector2D(this NetPacketReader reader, out Vector2D vector2D)
|
||||||
|
=> vector2D = new(reader.GetFloat(), reader.GetFloat());
|
||||||
|
|
||||||
|
public static void Put(this NetDataWriter writer, Vector2D vector)
|
||||||
|
{
|
||||||
|
writer.Put(vector.X);
|
||||||
|
writer.Put(vector.Y);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
using Syntriax.Engine.Core;
|
||||||
|
|
||||||
|
using Syntriax.Engine.Network.Abstract;
|
||||||
|
|
||||||
|
namespace Syntriax.Engine.Network;
|
||||||
|
|
||||||
|
public class NetworkManager : NetworkBehaviour, INetworkManager
|
||||||
|
{
|
||||||
|
private BehaviourCollector<INetworkEntity> entities = null!;
|
||||||
|
|
||||||
|
private static uint networkIdIndex = 0;
|
||||||
|
|
||||||
|
protected override void OnInitialize()
|
||||||
|
{
|
||||||
|
base.OnInitialize();
|
||||||
|
|
||||||
|
NetworkId = networkIdIndex++;
|
||||||
|
|
||||||
|
entities = new(GameObject.GameManager);
|
||||||
|
foreach (var entity in entities)
|
||||||
|
entity.NetworkId = networkIdIndex++;
|
||||||
|
|
||||||
|
entities.OnCollected += OnCollected;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnCollected(BehaviourCollector<INetworkEntity> collector, INetworkEntity entity)
|
||||||
|
=> entity.NetworkId = networkIdIndex++;
|
||||||
|
|
||||||
|
public override void ReceiveData<T>(T data) { }
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using LiteNetLib.Utils;
|
||||||
|
|
||||||
|
using Syntriax.Engine.Network.Abstract;
|
||||||
|
|
||||||
|
namespace Syntriax.Engine.Network;
|
||||||
|
|
||||||
|
public class NetworkServer : NetworkBase, INetworkCommunicatorServer
|
||||||
|
{
|
||||||
|
public string Password { get; private set; } = string.Empty;
|
||||||
|
public int MaxConnectionCount { get; private set; } = 2;
|
||||||
|
public int Port { get; private set; } = 8888;
|
||||||
|
|
||||||
|
private readonly NetDataWriter netDataWriter = new();
|
||||||
|
|
||||||
|
public NetworkServer() : this(8888, 2) { }
|
||||||
|
public NetworkServer(int port, int maxConnectionCount) : base()
|
||||||
|
{
|
||||||
|
MaxConnectionCount = maxConnectionCount;
|
||||||
|
Port = port;
|
||||||
|
|
||||||
|
Listener.ConnectionRequestEvent += request =>
|
||||||
|
{
|
||||||
|
if (Manager.ConnectedPeersCount < maxConnectionCount)
|
||||||
|
request.AcceptIfKey(Password);
|
||||||
|
else
|
||||||
|
request.Reject();
|
||||||
|
};
|
||||||
|
|
||||||
|
OnPacketReceived += ServerOnPacketReceived;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Start(int port, int maxConnectionCount, string? password = null)
|
||||||
|
{
|
||||||
|
Password = password ?? string.Empty;
|
||||||
|
MaxConnectionCount = maxConnectionCount;
|
||||||
|
Port = port;
|
||||||
|
|
||||||
|
Manager.Start(port);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Send<T>(NetworkPacket<T> packet)
|
||||||
|
{
|
||||||
|
netDataWriter.Reset();
|
||||||
|
netPacketProcessor.Write(netDataWriter, packet);
|
||||||
|
Manager.SendToAll(netDataWriter, LiteNetLib.DeliveryMethod.ReliableOrdered);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ServerOnPacketReceived(INetworkCommunicator sender, object packet)
|
||||||
|
{
|
||||||
|
MethodInfo[] methodInfos = GetType()
|
||||||
|
.GetMethods(BindingFlags.Public | BindingFlags.Instance);
|
||||||
|
|
||||||
|
MethodInfo method = methodInfos
|
||||||
|
.FirstOrDefault(
|
||||||
|
m => m.Name == nameof(Send) && m.IsGenericMethod
|
||||||
|
) ?? throw new Exception();
|
||||||
|
|
||||||
|
Type typeArguments = packet.GetType().GetGenericArguments()[0];
|
||||||
|
|
||||||
|
MethodInfo methodInfo = method.MakeGenericMethod(typeArguments);
|
||||||
|
|
||||||
|
methodInfo.Invoke(this, [packet]);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue