diff --git a/prefabs/gameObjects/star.tscn b/prefabs/gameObjects/star.tscn index 1d993b8..abed28f 100644 --- a/prefabs/gameObjects/star.tscn +++ b/prefabs/gameObjects/star.tscn @@ -2,7 +2,7 @@ [ext_resource type="Script" uid="uid://cbt6p1bhh4o8q" path="res://scripts/GameObjects/Nodes/StarNode.cs" id="1_o2f8k"] -[sub_resource type="SphereMesh" id="SphereMesh_2pyv3"] +[sub_resource type="SphereMesh" id="SphereMesh_o2f8k"] radius = 5.0 height = 10.0 @@ -13,7 +13,7 @@ radius = 5.0 script = ExtResource("1_o2f8k") [node name="MeshInstance3D" type="MeshInstance3D" parent="." unique_id=1423841842] -mesh = SubResource("SphereMesh_2pyv3") +mesh = SubResource("SphereMesh_o2f8k") [node name="CollisionShape3D" type="CollisionShape3D" parent="." unique_id=1898956937] shape = SubResource("SphereShape3D_o2f8k") diff --git a/scenes/game.tscn b/scenes/game.tscn index 605adfd..75fb9b1 100644 --- a/scenes/game.tscn +++ b/scenes/game.tscn @@ -55,8 +55,9 @@ GameMenu = NodePath("../GameMenu") [node name="QueueManager" type="Node" parent="." unique_id=355148200] script = ExtResource("4_iywne") -[node name="NetworkManager" type="Node" parent="." unique_id=1765485895] +[node name="NetworkManager" type="Node" parent="." unique_id=1765485895 node_paths=PackedStringArray("RPCNode")] script = ExtResource("5_p57ef") +RPCNode = NodePath("../RPC") [node name="RPC" type="Node" parent="." unique_id=498537245] script = ExtResource("6_u5sy4") diff --git a/scripts/GameManager.cs b/scripts/GameManager.cs index 491646d..a83eaef 100644 --- a/scripts/GameManager.cs +++ b/scripts/GameManager.cs @@ -16,29 +16,25 @@ public partial class GameManager : Node3D [Export] public int maxFarThreads = 16; public static bool Loading { get; private set; } = true; - public static GameManager Instance { get; private set; } + public static GameManager Singleton { get; private set; } public static IGenerator Generator { get; private set; } public static Universe GameUniverse { get; private set; } public Player MainPlayer { get; private set; } - public Dictionary Players { get; private set; } = []; + public List Players { get; private set; } = []; private double closeTickTimer = 0; private double farTickTimer = 0; - public bool simulatingClose = false; - public bool simulatingFar = false; + public bool simulating = false; public bool playerReady = false; private readonly Dictionary spawnedObjects = []; private readonly ConcurrentQueue spawnQueue = []; - public override void _EnterTree() - { - Instance = this; - } - public override void _Ready() { + Singleton = this; + Generator = new TestGenerator(); if (Global.IsGameHost) @@ -57,7 +53,7 @@ public partial class GameManager : Node3D public override void _ExitTree() { Loading = true; - Instance = null; + Singleton = null; } public override void _Process(double delta) @@ -68,14 +64,20 @@ public partial class GameManager : Node3D } closeTickTimer += delta; - if (closeTickTimer >= closeTickInterval && !simulatingClose) + farTickTimer += delta; + + if (closeTickTimer >= closeTickInterval) { SimulateClose(closeTickTimer); closeTickTimer = 0; } - farTickTimer += delta; - if (farTickTimer >= farTickInterval && !simulatingFar) + if (simulating) + { + farTickTimer = 0; + } + + if (farTickTimer >= farTickInterval) { double taskFarTickTimer = farTickTimer; Task.Run(() => @@ -92,48 +94,22 @@ public partial class GameManager : Node3D return MainPlayer.PlayerData.CurrentSector; } - public Player GetPlayer(long id) - { - Players.TryGetValue(id, out Player player); - return player; - } - private void SimulateClose(double delta) { - simulatingClose = true; + List neighbours = GetCurrentSector().GetNeighbouringSectors(); - List sectorsClose = GetCurrentSector().GetNeighbouringSectors(); - - List tasks = []; - sectorsClose.ForEach(sector => + neighbours.ForEach(sector => { - Task simulateTask = Task.Run(() => + Task.Run(() => { sector.Simulate(delta); }); - - tasks.Add(simulateTask); }); - Task.WaitAll([.. tasks]); - - foreach (KeyValuePair player in Players) - { - List playerSectors = player.Value.PlayerData.CurrentSector.GetNeighbouringSectors(); - playerSectors.ForEach(sector => - { - if (player.Key != 1) - { - sector.NetworkSync(player.Key); - } - }); - } - - simulatingClose = false; } private void SimulateFar(double delta) { - simulatingFar = true; + simulating = true; List tasks = []; @@ -158,7 +134,7 @@ public partial class GameManager : Node3D Task.WaitAll([.. tasks]); - simulatingFar = false; + simulating = false; } private void SimulateFarClustered(double delta, int startX, int countX) @@ -219,7 +195,7 @@ public partial class GameManager : Node3D neighbours.ForEach(sector => sector.SpawnObjects()); } - public Player SpawnPlayer(Character character, long networkId, bool isMainPlayer = false) + public Player SpawnPlayer(Character character, bool isMainPlayer = false) { Player player = character.InstantiatePlayer(); player.GameMenu = GameMenu; @@ -230,7 +206,7 @@ public partial class GameManager : Node3D OnPlayerReady(); } - Players.Add(networkId, player); + Players.Add(player); character.UpdateSector(); @@ -286,10 +262,10 @@ public partial class GameManager : Node3D { Sector current = GetCurrentSector(); - foreach (KeyValuePair player in Players) + foreach (Player player in Players) { - player.Value.PlayerData.UpdateSectorOffset(current); - player.Value.PlayerData.UpdateNodePosition(); + player.PlayerData.UpdateSectorOffset(current); + player.PlayerData.UpdateNodePosition(); } List nearby = current.GetNeighbouringSectors(); @@ -305,18 +281,20 @@ public partial class GameManager : Node3D else { gameObject.UpdateSectorOffset(current); - node._Process(0); + node.GlobalPosition = gameObject.LocalCoordinates + gameObject.SectorOffset; } } nearby.ForEach(sector => sector.SpawnObjects()); } + // These should be in RPCNode and should be queued public void SendUniverseToClient(long id) { RpcId(id, nameof(RpcDownloadUniverse), Generator.GetUniverseSize(), Generator.GetSectorSize()); } + // These should be in RPCNode and should be queued [Rpc(MultiplayerApi.RpcMode.Authority)] public void RpcDownloadUniverse(Vector3I universeSize, Vector3 sectorSize) { @@ -324,4 +302,96 @@ public partial class GameManager : Node3D Loading = false; } + + // These should be in RPCNode and should be queued + [Rpc(MultiplayerApi.RpcMode.AnyPeer)] + public void RpcSendNearbySectors(Vector3I coordinates, long id = -1) + { + Sector sector = GameUniverse.GetSector(coordinates); + if (sector == null) + { + return; + } + + List sectors = sector.GetNeighbouringSectors(); + sectors.ForEach(sector => SendSectorToClients(sector, id == -1 ? null : id)); + } + + // These should be in RPCNode and should be queued + public void SendSectorToClients(Sector sector, long? id = null) + { + foreach (GameObject gameObject in sector.GameObjects) + { + if (gameObject is Character) + { + continue; + } + + Godot.Collections.Dictionary gameObjectData = new() { + { "type", gameObject.GetType().Name }, + { "sectorCoordinates", sector.Coordinates }, + { "coordinates", gameObject.LocalCoordinates }, + { "uuid", gameObject.UUID.ToString() }, + }; + + if (id.HasValue) + { + RpcId(id.Value, nameof(RpcDownloadGameObject), gameObjectData); + } + else + { + Rpc(nameof(RpcDownloadGameObject), gameObjectData); + } + } + } + + // These should be in RPCNode and should be queued + [Rpc(MultiplayerApi.RpcMode.Authority)] + public void RpcDownloadGameObject(Godot.Collections.Dictionary gameObjectData) + { + if (!gameObjectData.TryGetValue("type", out var typeData)) + { + return; + } + if (!gameObjectData.TryGetValue("sectorCoordinates", out var sectorCoordinatesData)) + { + return; + } + if (!gameObjectData.TryGetValue("coordinates", out var coordinatesData)) + { + return; + } + if (!gameObjectData.TryGetValue("uuid", out var uuidData)) + { + return; + } + + string type = (string)typeData; + Vector3I sectorCoordinates = (Vector3I)sectorCoordinatesData; + Vector3 coordinates = (Vector3)coordinatesData; + Guid uuid = Guid.Parse((string)uuidData); + + Sector sector = GameUniverse.GetSector(sectorCoordinates); + if (sector == null) + { + return; + } + + GameObject gameObject; + switch (type) + { + case "Star": + gameObject = new Star(sector, coordinates); + break; + + default: + return; + } + + gameObject.UUID = uuid; + + Spawn(gameObject); + + sector.AssignObject(gameObject); + } } diff --git a/scripts/GameObject.cs b/scripts/GameObject.cs index 8ad4333..a689a96 100644 --- a/scripts/GameObject.cs +++ b/scripts/GameObject.cs @@ -4,107 +4,13 @@ using Godot; public abstract class GameObject { - [Flags] - public enum DirtyFlags : ulong - { - None = 0, - UUID = 1UL << 0, - Sector = 1UL << 1, - LocalCoordinates = 1UL << 2, - Rotation = 1UL << 3, - Velocity = 1UL << 4, - AngularVelocity = 1UL << 5 - } - public DirtyFlags DirtyBits { get; protected set; } = DirtyFlags.None; - - protected Guid _uuid; - public Guid UUID - { - get => _uuid; - set - { - if (_uuid != value) - { - _uuid = value; - DirtyBits |= DirtyFlags.UUID; - } - } - } - - protected Vector3I _currentSectorCoordinates; - protected Sector _currentSector; - public Sector CurrentSector - { - get => _currentSector; - protected set - { - if (_currentSector != value) - { - _currentSector = value; - _currentSectorCoordinates = value.Coordinates; - DirtyBits |= DirtyFlags.Sector; - } - } - } - - protected Vector3 _localCoordinates; - public Vector3 LocalCoordinates - { - get => _localCoordinates; - protected set - { - if (_localCoordinates != value) - { - _localCoordinates = value; - DirtyBits |= DirtyFlags.LocalCoordinates; - } - } - } - - protected Vector3 _rotation; - public Vector3 Rotation - { - get => _rotation; - protected set - { - if (_rotation != value) - { - _rotation = value; - DirtyBits |= DirtyFlags.Rotation; - } - } - } - - protected Vector3 _velocity; - public Vector3 Velocity - { - get => _velocity; - protected set - { - if (_velocity != value) - { - _velocity = value; - DirtyBits |= DirtyFlags.Velocity; - } - } - } - - protected Vector3 _angularVelocity; - public Vector3 AngularVelocity - { - get => _angularVelocity; - protected set - { - if (_angularVelocity != value) - { - _angularVelocity = value; - DirtyBits |= DirtyFlags.AngularVelocity; - } - } - } + public Guid UUID { get; set; } + public Sector CurrentSector { get; protected set; } + public Vector3 LocalCoordinates { get; protected set; } public Vector3Dec GlobalCoordinates { get; protected set; } - public Vector3 SectorOffset { get; protected set; } + + public Vector3 SectorOffset { get; set; } protected bool reassigning = false; @@ -115,10 +21,6 @@ public abstract class GameObject CurrentSector = sector; LocalCoordinates = localCoordinates; - Velocity = new(0, 0, 1); - AngularVelocity = Vector3.Zero; - Rotation = Vector3.Zero; - GlobalCoordinates = CalculateGlobalCoordinates(sector.GlobalCenterCoordinates, localCoordinates); } @@ -144,12 +46,6 @@ public abstract class GameObject ); } - public void ApplyVelocity(double delta) - { - SetCoordinatesFromLocal(LocalCoordinates + Velocity * delta); - Rotation += AngularVelocity * delta; - } - public bool IsInCurrentSector() { return Helpers.IsInsideArea(CurrentSector.Size / 2, LocalCoordinates); @@ -191,15 +87,15 @@ public abstract class GameObject UpdateSectorOffsetToMainPlayer(); - List neighbours = GameManager.Instance.GetCurrentSector().GetNeighbouringSectors(); + List neighbours = GameManager.Singleton.GetCurrentSector().GetNeighbouringSectors(); if (neighbours.Contains(sector)) { - GameManager.Instance.Spawn(this); + GameManager.Singleton.Spawn(this); } else { - GameManager.Instance.Despawn(this); + GameManager.Singleton.Despawn(this); } reassigning = false; @@ -218,7 +114,7 @@ public abstract class GameObject public void UpdateSectorOffsetToMainPlayer() { - UpdateSectorOffset(GameManager.Instance.GetCurrentSector()); + UpdateSectorOffset(GameManager.Singleton.GetCurrentSector()); } public void SetCoordinatesFromGlobal(Vector3Dec globalCoordinates) @@ -246,8 +142,6 @@ public abstract class GameObject public virtual void Simulate(double delta) { - ApplyVelocity(delta); - if (!reassigning && !IsInCurrentSector()) { UpdateSector(); @@ -263,70 +157,4 @@ public abstract class GameObject return instance; } - - public virtual Godot.Collections.Dictionary NetworkWrite(long id, bool full) - { - Godot.Collections.Dictionary gameObjectData = []; - - if (full) - gameObjectData.Add("type", GetType().ToString()); - - if (DirtyBits.HasFlag(DirtyFlags.Sector) || full) - gameObjectData.Add("sectorCoordinates", _currentSectorCoordinates); - - if (DirtyBits.HasFlag(DirtyFlags.LocalCoordinates) || full) - gameObjectData.Add("localCoordinates", _localCoordinates); - - if (DirtyBits.HasFlag(DirtyFlags.Rotation) || full) - gameObjectData.Add("rotation", _rotation); - - if (DirtyBits.HasFlag(DirtyFlags.Velocity) || full) - gameObjectData.Add("velocity", _velocity); - - if (DirtyBits.HasFlag(DirtyFlags.AngularVelocity) || full) - gameObjectData.Add("angularVelocity", _angularVelocity); - - if (gameObjectData.Count > 0) - { - gameObjectData.Add("uuid", UUID.ToString()); - return gameObjectData; - } - - return null; - } - - public virtual void NetworkRead(Godot.Collections.Dictionary gameObjectData) - { - if (gameObjectData.TryGetValue("sectorCoordinates", out var sectorCoordinatesData)) - { - Sector newSector = GameManager.GameUniverse.GetSector((Vector3I)sectorCoordinatesData); - CurrentSector.GameObjects.Remove(this); - newSector.GameObjects.Add(this); - - AssignSector(newSector); - } - - if (gameObjectData.TryGetValue("localCoordinates", out var localCoordinatesData)) - LocalCoordinates = (Vector3)localCoordinatesData; - - if (gameObjectData.TryGetValue("rotation", out var rotationData)) - Rotation = (Vector3)rotationData; - - if (gameObjectData.TryGetValue("velocity", out var velocityData)) - Velocity = (Vector3)velocityData; - - if (gameObjectData.TryGetValue("angularVelocity", out var angularVelocityData)) - AngularVelocity = (Vector3)angularVelocityData; - } - - public override bool Equals(object obj) - { - GameObject gameObj = (GameObject)obj; - return gameObj.UUID == UUID; - } - - public override int GetHashCode() - { - return UUID.GetHashCode(); - } } diff --git a/scripts/GameObjects/Character.cs b/scripts/GameObjects/Character.cs index 7ed6327..2b7ceef 100644 --- a/scripts/GameObjects/Character.cs +++ b/scripts/GameObjects/Character.cs @@ -16,7 +16,17 @@ public class Character(Sector sector, Vector3 localCoordinates) : GameObject(sec if (IsMainPlayer()) { - GameManager.Instance.ApplyOrigin(); + GameManager.Singleton.ApplyOrigin(); + + if (!Global.IsGameHost) + { + GameManager.Singleton.RpcId( + 1, + nameof(GameManager.Singleton.RpcSendNearbySectors), + CurrentSector.Coordinates, + NetworkManager.Singleton.LocalNetId + ); + } } reassigning = false; @@ -24,7 +34,7 @@ public class Character(Sector sector, Vector3 localCoordinates) : GameObject(sec public bool IsMainPlayer() { - return player == GameManager.Instance.MainPlayer; + return player == GameManager.Singleton.MainPlayer; } public Player InstantiatePlayer() @@ -38,14 +48,6 @@ public class Character(Sector sector, Vector3 localCoordinates) : GameObject(sec return instance; } - public override void Simulate(double delta) - { - if (!reassigning && !IsInCurrentSector()) - { - UpdateSector(); - } - } - public override void UpdateNodePosition() { if (IsMainPlayer()) diff --git a/scripts/GameObjects/Nodes/StarNode.cs b/scripts/GameObjects/Nodes/StarNode.cs index c7e08d3..e48ccf7 100644 --- a/scripts/GameObjects/Nodes/StarNode.cs +++ b/scripts/GameObjects/Nodes/StarNode.cs @@ -4,41 +4,13 @@ public partial class StarNode : StaticBody3D { public Star StarData { get; set; } - private Vector3 lastFrameCoordinates = Vector3.Zero; - private Vector3 lastFrameRotation = Vector3.Zero; - - private Vector3 velocityOffset = Vector3.Zero; - private Vector3 angularVelocityOffset = Vector3.Zero; - public override void _Ready() { GlobalPosition = StarData.LocalCoordinates + StarData.SectorOffset; - GlobalRotation = StarData.Rotation; } public override void _Process(double delta) { - if (StarData.LocalCoordinates == lastFrameCoordinates) - { - velocityOffset += StarData.Velocity * delta; - } - else - { - lastFrameCoordinates = StarData.LocalCoordinates; - velocityOffset = Vector3.Zero; - } - - if (StarData.Rotation == lastFrameRotation) - { - angularVelocityOffset += StarData.AngularVelocity * delta; - } - else - { - lastFrameRotation = StarData.Rotation; - angularVelocityOffset = Vector3.Zero; - } - - GlobalPosition = StarData.LocalCoordinates + StarData.SectorOffset + velocityOffset; - GlobalRotation = StarData.Rotation + angularVelocityOffset; + GlobalPosition = StarData.LocalCoordinates + StarData.SectorOffset; } } diff --git a/scripts/GameObjects/Star.cs b/scripts/GameObjects/Star.cs index 337e436..16a7914 100644 --- a/scripts/GameObjects/Star.cs +++ b/scripts/GameObjects/Star.cs @@ -5,6 +5,8 @@ public class Star(Sector sector, Vector3 localCoordinates) : GameObject(sector, public override void Simulate(double delta) { base.Simulate(delta); + + //SetCoordinatesFromGlobal(new(GlobalCoordinates.X, GlobalCoordinates.Y, GlobalCoordinates.Z + 1 * (decimal)delta)); } public override Node3D Instantiate(Sector sector) @@ -18,22 +20,4 @@ public class Star(Sector sector, Vector3 localCoordinates) : GameObject(sector, return instance; } - - public override Godot.Collections.Dictionary NetworkWrite(long id, bool full) - { - Godot.Collections.Dictionary gameObjectData = base.NetworkWrite(id, full); - - if (gameObjectData != null) - { - QueueManager.NetworkSyncQueue.Enqueue((id, gameObjectData)); - } - DirtyBits = DirtyFlags.None; - - return gameObjectData; - } - - public override void NetworkRead(Godot.Collections.Dictionary gameObjectData) - { - base.NetworkRead(gameObjectData); - } } diff --git a/scripts/Generator/TestGenerator.cs b/scripts/Generator/TestGenerator.cs index 9565a43..8a54986 100644 --- a/scripts/Generator/TestGenerator.cs +++ b/scripts/Generator/TestGenerator.cs @@ -30,9 +30,9 @@ public class TestGenerator : IGenerator public Vector3I GetSectorOffset(Vector3I universeSize) { return new( - (int)Mathf.Floor(universeSize.X / 2), - (int)Mathf.Floor(universeSize.X / 2), - (int)Mathf.Floor(universeSize.X / 2) + (int)Mathf.Floor(UNIVERSE_SIZE.X / 2), + (int)Mathf.Floor(UNIVERSE_SIZE.X / 2), + (int)Mathf.Floor(UNIVERSE_SIZE.X / 2) ); } @@ -118,13 +118,10 @@ public class TestGenerator : IGenerator for (int i = 0; i < starCount; i++) { - if (coordinates.X == 5 && coordinates.Y == 5 && coordinates.Z == 5) - { - Vector3 localCoordinates = GenerateLocalCoordinates(); - Star star = GenerateStar(sector, localCoordinates); + Vector3 localCoordinates = GenerateLocalCoordinates(); + Star star = GenerateStar(sector, localCoordinates); - sector.GameObjects.Add(star); - } + sector.GameObjects.Add(star); } int shipCount = rng.RandiRange( diff --git a/scripts/NetworkManager.cs b/scripts/NetworkManager.cs index 328a324..7ab4303 100644 --- a/scripts/NetworkManager.cs +++ b/scripts/NetworkManager.cs @@ -3,13 +3,15 @@ using Godot; public partial class NetworkManager : Node { - public static NetworkManager Instance { get; private set; } + [Export] public RPCNode RPCNode { get; private set; } + + public static NetworkManager Singleton { get; private set; } public int LocalNetId { get; private set; } = -1; public override void _Ready() { - Instance = this; + Singleton = this; if (Global.IsGameHost) { @@ -64,7 +66,7 @@ public partial class NetworkManager : Node { if (Global.IsGameHost) { - GameManager.Instance.SendUniverseToClient(id); + GameManager.Singleton.SendUniverseToClient(id); } _ = SpawnNetPlayer(id); @@ -73,7 +75,7 @@ public partial class NetworkManager : Node public void OnPlayerDisconnected(long id) { Player player = GetNode($"/root/Game/Space/Player-{id}"); - GameManager.Instance.DespawnPlayer(player); + GameManager.Singleton.DespawnPlayer(player); } private async Task SpawnNetPlayer(long id) @@ -86,9 +88,14 @@ public partial class NetworkManager : Node bool isMainPlayer = LocalNetId == id; Character character = new(GameManager.GameUniverse.Sectors[5, 5, 5], new(0, 0, 0)); - Player player = GameManager.Instance.SpawnPlayer(character, id, isMainPlayer); + Player player = GameManager.Singleton.SpawnPlayer(character, isMainPlayer); player.Name = $"Player-{id}"; player.SetMultiplayerAuthority((int)id); + + if (isMainPlayer && !Global.IsGameHost) + { + GameManager.Singleton.RpcId(1, nameof(GameManager.Singleton.RpcSendNearbySectors), character.CurrentSector.Coordinates, id); + } } } diff --git a/scripts/Player.cs b/scripts/Player.cs index 955046c..121c6c6 100644 --- a/scripts/Player.cs +++ b/scripts/Player.cs @@ -10,11 +10,11 @@ public partial class Player : CharacterBody3D [Export] public double NetworkPhysicsSyncInterval = 0.05; public Control GameMenu { get; set; } + public Character PlayerData { get; set; } - public Vector3 GravityVelocity { get; set; } = Vector3.Zero; - public Vector3 MovementVelocity { get; set; } = Vector3.Zero; - + private Vector3 gravityVelocity = Vector3.Zero; + private Vector3 movementVelocity = Vector3.Zero; private GravityReceiver gravityReceiver; private double cameraPitch = 0; private Camera3D camera; @@ -35,20 +35,18 @@ public partial class Player : CharacterBody3D { if (IsMultiplayerAuthority()) { - RPCNode rpc = RPCNode.Instance; - networkPhysicsSyncCounter += delta; if (networkPhysicsSyncCounter >= NetworkPhysicsSyncInterval) { networkPhysicsSyncCounter = 0; - rpc.Rpc(nameof(rpc.RpcSyncPlayerPhysics), GetMultiplayerAuthority(), MovementVelocity, GravityVelocity, GlobalRotation); + Rpc(nameof(RpcSyncPhysics), movementVelocity, gravityVelocity, GlobalRotation); } networkSyncCounter += delta; if (networkSyncCounter >= NetworkSyncInterval) { networkSyncCounter = 0; - rpc.Rpc(nameof(rpc.RpcSyncPlayer), GetMultiplayerAuthority(), GlobalPosition, PlayerData.CurrentSector.Coordinates); + Rpc(nameof(RpcSync), GlobalPosition, PlayerData.CurrentSector.Coordinates); } PlayerData.SetCoordinatesFromLocal(GlobalPosition); @@ -59,8 +57,8 @@ public partial class Player : CharacterBody3D public override void _PhysicsProcess(double delta) { - Vector3 newGravityVelocity = GravityVelocity; - Vector3 newMovementVelocity = MovementVelocity; + Vector3 newGravityVelocity = gravityVelocity; + Vector3 newMovementVelocity = movementVelocity; if (!GameMenu.Visible && IsMultiplayerAuthority()) { @@ -78,8 +76,8 @@ public partial class Player : CharacterBody3D } } - GravityVelocity = newGravityVelocity; - MovementVelocity = newMovementVelocity; + gravityVelocity = newGravityVelocity; + movementVelocity = newMovementVelocity; Velocity = newGravityVelocity + newMovementVelocity; MoveAndSlide(); @@ -239,4 +237,33 @@ public partial class Player : CharacterBody3D RotateObjectLocal(Vector3.Forward, rotateAmountZ); } + + [Rpc(MultiplayerApi.RpcMode.AnyPeer)] + public void RpcSync(Vector3 position, Vector3I sectorCoordinates) + { + Sector sector = GameManager.GameUniverse.GetSector(sectorCoordinates); + if (sector == null) + { + return; + } + + Vector3Dec newGlobal = PlayerData.CalculateGlobalCoordinates(sector.GlobalCenterCoordinates, position); + PlayerData.SetCoordinatesFromGlobal(newGlobal); + + if (PlayerData.CurrentSector.Coordinates != sectorCoordinates) + { + sector.AssignObject(PlayerData); + } + + GlobalPosition = position + PlayerData.SectorOffset; + } + + [Rpc(MultiplayerApi.RpcMode.AnyPeer)] + public void RpcSyncPhysics(Vector3 _movementVelocity, Vector3 _gravityVelocity, Vector3 rotation) + { + movementVelocity = _movementVelocity; + gravityVelocity = _gravityVelocity; + + GlobalRotation = rotation; + } } diff --git a/scripts/QueueManager.cs b/scripts/QueueManager.cs index 4eb5cec..fdbb2da 100644 --- a/scripts/QueueManager.cs +++ b/scripts/QueueManager.cs @@ -8,18 +8,11 @@ public partial class QueueManager : Node public static ConcurrentQueue ActionQueue = new(); public static ConcurrentQueue<(Sector, GameObject)> SectorReassignQueue = new(); - public static ConcurrentQueue<(long, Godot.Collections.Dictionary)> NetworkSyncQueue = new(); private readonly int sectorReassignQueueRateLimit = 500; - private readonly int networkSyncQueueRateLimit = 10; public override void _Process(double delta) { - if (!GameManager.Instance.playerReady) - { - return; - } - while (LogQueue.TryDequeue(out string text)) { GD.Print(text); @@ -32,7 +25,7 @@ public partial class QueueManager : Node int sectorReassignQueueProcessed = 0; while ( - !GameManager.Instance.simulatingFar + !GameManager.Singleton.simulating && sectorReassignQueueProcessed++ < sectorReassignQueueRateLimit && SectorReassignQueue.TryDequeue(out var item) ) @@ -44,16 +37,5 @@ public partial class QueueManager : Node gameObject.AssignSector(sector); } - - int networkSyncQueueProcessed = 0; - while ( - networkSyncQueueProcessed++ < networkSyncQueueRateLimit - && NetworkSyncQueue.TryDequeue(out var item) - ) - { - var (clientId, gameObjectData) = item; - - RPCNode.Instance.RpcId(clientId, nameof(RPCNode.RpcSyncGameObject), gameObjectData); - } } } diff --git a/scripts/RPCNode.cs b/scripts/RPCNode.cs index 93c659a..5397ef2 100644 --- a/scripts/RPCNode.cs +++ b/scripts/RPCNode.cs @@ -1,171 +1,5 @@ -using System; -using System.Collections.Generic; using Godot; public partial class RPCNode : Node { - public static RPCNode Instance { get; private set; } - - private readonly HashSet requestedFullGameObjects = []; - - public override void _EnterTree() - { - Instance = this; - } - - public override void _ExitTree() - { - Instance = null; - } - - [Rpc(MultiplayerApi.RpcMode.Authority)] - public void RpcSyncGameObject(Godot.Collections.Dictionary gameObjectData) - { - GD.Print("READING: " + gameObjectData); - - if (!GameManager.Instance.playerReady) - { - return; - } - - if (!gameObjectData.TryGetValue("uuid", out var uuidData)) - return; - - Guid uuid = Guid.Parse((string)uuidData); - - List sectors = GameManager.Instance.GetCurrentSector().GetNeighbouringSectors(); - foreach (Sector sector in sectors) - { - GameObject gameObject = sector.GetObjectById(uuid); - if (gameObject != null) - { - gameObject.NetworkRead(gameObjectData); - return; - } - } - - if (!TrySyncFullGameObject(gameObjectData)) - { - if (requestedFullGameObjects.Contains(uuid)) - { - return; - } - requestedFullGameObjects.Add(uuid); - RpcId(1, nameof(RequestFullGameObject), NetworkManager.Instance.LocalNetId, (string)uuidData); - } - } - - public bool TrySyncFullGameObject(Godot.Collections.Dictionary gameObjectData) - { - if (!gameObjectData.TryGetValue("type", out var typeData)) - return false; - if (!gameObjectData.TryGetValue("sectorCoordinates", out var sectorCoordinatesData)) - return false; - if (!gameObjectData.TryGetValue("localCoordinates", out var localCoordinatesData)) - return false; - if (!gameObjectData.TryGetValue("uuid", out var uuidData)) - return false; - - string type = (string)typeData; - Vector3I sectorCoordinates = (Vector3I)sectorCoordinatesData; - Vector3 localCoordinates = (Vector3)localCoordinatesData; - Guid uuid = Guid.Parse((string)uuidData); - - Sector sector = GameManager.GameUniverse.GetSector(sectorCoordinates); - if (sector == null) - return false; - - GameObject gameObject; - switch (type) - { - case "Star": - gameObject = new Star(sector, localCoordinates); - break; - - default: - return false; - } - - gameObject.UUID = uuid; - gameObject.NetworkRead(gameObjectData); - requestedFullGameObjects.Remove(uuid); - - sector.AssignObject(gameObject); - - return true; - } - - [Rpc(MultiplayerApi.RpcMode.AnyPeer)] - public void RequestFullGameObject(long id, string uuidString) - { - if (!Global.IsGameHost) - { - return; - } - - Guid uuid = Guid.Parse(uuidString); - - List sectors = GameManager.Instance.GetPlayer(id).PlayerData.CurrentSector.GetNeighbouringSectors(); - foreach (Sector sector in sectors) - { - GameObject gameObject = sector.GetObjectById(uuid); - if (gameObject != null) - { - gameObject.NetworkWrite(id, true); - return; - } - } - } - - [Rpc(MultiplayerApi.RpcMode.AnyPeer)] - public void RpcSyncPlayer(long id, Vector3 position, Vector3I sectorCoordinates) - { - if (!GameManager.Instance.playerReady) - { - return; - } - - GameManager.Instance.Players.TryGetValue(id, out Player player); - if (player == null || !player.IsInsideTree()) - { - return; - } - Character playerData = player.PlayerData; - - Sector sector = GameManager.GameUniverse.GetSector(sectorCoordinates); - if (sector == null) - { - return; - } - - Vector3Dec newGlobal = playerData.CalculateGlobalCoordinates(sector.GlobalCenterCoordinates, position); - playerData.SetCoordinatesFromGlobal(newGlobal); - - if (playerData.CurrentSector.Coordinates != sectorCoordinates) - { - sector.AssignObject(playerData); - } - - player.GlobalPosition = position + playerData.SectorOffset; - } - - [Rpc(MultiplayerApi.RpcMode.AnyPeer)] - public void RpcSyncPlayerPhysics(long id, Vector3 _movementVelocity, Vector3 _gravityVelocity, Vector3 rotation) - { - if (!GameManager.Instance.playerReady) - { - return; - } - - GameManager.Instance.Players.TryGetValue(id, out Player player); - if (player == null || !player.IsInsideTree()) - { - return; - } - - player.MovementVelocity = _movementVelocity; - player.GravityVelocity = _gravityVelocity; - - player.GlobalRotation = rotation; - } } diff --git a/scripts/Sector.cs b/scripts/Sector.cs index 8c801e0..077d196 100644 --- a/scripts/Sector.cs +++ b/scripts/Sector.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using Godot; @@ -47,14 +46,6 @@ public class Sector }); } - public void NetworkSync(long id) - { - GameObjects.ForEach(gameObject => - { - gameObject.NetworkWrite(id, false); - }); - } - public bool IsObjectInSector(GameObject gameObject) { return Helpers.IsInsideGlobalArea(GlobalStartCoordinates, GlobalEndCoordinates, gameObject.GlobalCoordinates); @@ -67,20 +58,7 @@ public class Sector public void SpawnObjects() { - GameObjects.ForEach(GameManager.Instance.Spawn); - } - - public GameObject GetObjectById(Guid id) - { - foreach (GameObject gameObject in GameObjects) - { - if (gameObject.UUID.Equals(id)) - { - return gameObject; - } - } - - return null; + GameObjects.ForEach(GameManager.Singleton.Spawn); } public List GetNeighbouringSectors()