using System; using System.Collections.Generic; using Godot; public abstract class GameObject { 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; set; } protected bool reassigning = false; public GameObject(Sector sector, Vector3 localCoordinates) { UUID = Guid.NewGuid(); CurrentSector = sector; LocalCoordinates = localCoordinates; GlobalCoordinates = CalculateGlobalCoordinates(sector.GlobalCenterCoordinates, localCoordinates); } public GameObject(Vector3Dec coordinates) { GlobalCoordinates = coordinates; UpdateSector(); } public GameObject(decimal x, decimal y, decimal z) { GlobalCoordinates = new(x, y, z); UpdateSector(); } public Vector3Dec CalculateGlobalCoordinates(Vector3Dec sectorCenter, Vector3 local) { return new ( sectorCenter.X + (decimal)local.X, sectorCenter.Y + (decimal)local.Y, sectorCenter.Z + (decimal)local.Z ); } public bool IsInCurrentSector() { return Helpers.IsInsideArea(CurrentSector.Size / 2, LocalCoordinates); } public void UpdateSector() { List neighbours = CurrentSector.GetNeighbouringSectors(); foreach (Sector sector in neighbours) { if (sector.IsObjectInSector(this)) { reassigning = true; sector.AssignObject(this); return; } } if (!GameManager.GameUniverse.IsInside(CurrentSector.Coordinates, LocalCoordinates)) { return; } foreach (Sector sector in GameManager.GameUniverse.Sectors) { if (sector.IsObjectInSector(this)) { reassigning = true; sector.AssignObject(this); return; } } } public virtual void AssignSector(Sector sector) { CurrentSector = sector; ResetLocalCoordinates(); UpdateSectorOffsetToMainPlayer(); List neighbours = GameManager.Singleton.GetCurrentSector().GetNeighbouringSectors(); if (neighbours.Contains(sector)) { GameManager.Singleton.Spawn(this); } else { GameManager.Singleton.Despawn(this); } reassigning = false; } public Vector3 GetSectorOffset(Sector sector) { Vector3Dec relative = CurrentSector.GlobalCenterCoordinates - sector.GlobalCenterCoordinates; return relative.ToVector3(); } public void UpdateSectorOffset(Sector sector) { SectorOffset = GetSectorOffset(sector); } public void UpdateSectorOffsetToMainPlayer() { UpdateSectorOffset(GameManager.Singleton.GetCurrentSector()); } public void SetCoordinatesFromGlobal(Vector3Dec globalCoordinates) { GlobalCoordinates = globalCoordinates; LocalCoordinates = (globalCoordinates - CurrentSector.GlobalCenterCoordinates).ToVector3(); UpdateNodePosition(); } public void SetCoordinatesFromLocal(Vector3 localCoordinates) { LocalCoordinates = localCoordinates; GlobalCoordinates = Vector3Dec.FromVector3(localCoordinates) + CurrentSector.GlobalCenterCoordinates; UpdateNodePosition(); } public void ResetLocalCoordinates() { SetCoordinatesFromGlobal(GlobalCoordinates); } public virtual void UpdateNodePosition() { } public virtual void Simulate(double delta) { if (!reassigning && !IsInCurrentSector()) { UpdateSector(); } } public virtual Node3D Instantiate(Sector sector) { PackedScene modulePrefab = ResourceLoader.Load("res://prefabs/gameObjects/node.tscn"); Node3D instance = modulePrefab.Instantiate(); instance.Name = $"GameObject-{UUID}"; return instance; } }