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; } }