using System.Threading; using System.Threading.Tasks; using Godot; public partial class GameManager : Node { [Export] Player player; [Export] double closeTickInterval = 1; [Export] double farTickInterval = 10; [Export] int maxFarThreads = 16; public static GameManager Singleton { get; private set; } public IGenerator Generator { get; private set; } public Universe GameUniverse { get; private set; } public Sector CurrentSector { get; private set; } private double closeTickTimer = 0; private double farTickTimer = 0; public override void _Ready() { Singleton = this; Generator = new TestGenerator(); Generator.GenerateUniverse((universe) => { GameUniverse = universe; CurrentSector = universe.Sectors[1, 1, 1]; }); } public override void _Process(double delta) { closeTickTimer += delta; farTickTimer += delta; if (closeTickTimer >= closeTickInterval) { SimulateClose(closeTickTimer); closeTickTimer = 0; } if (farTickTimer >= farTickInterval) { SimulateFar(farTickTimer); farTickTimer = 0; } } private void SimulateClose(double delta) { Vector3I currentCoordinates = CurrentSector.Coordinates; Sector[,,] sectors = GameUniverse.Sectors; int sizeX = sectors.GetLength(0); int sizeY = sectors.GetLength(1); int sizeZ = sectors.GetLength(2); int startX = Mathf.Clamp(currentCoordinates.X - 1, 0, sizeX); int startY = Mathf.Clamp(currentCoordinates.Y - 1, 0, sizeY); int startZ = Mathf.Clamp(currentCoordinates.Z - 1, 0, sizeZ); int endX = Mathf.Clamp(currentCoordinates.X + 1, 0, sizeX); int endY = Mathf.Clamp(currentCoordinates.Y + 1, 0, sizeY); int endZ = Mathf.Clamp(currentCoordinates.Z + 1, 0, sizeZ); for (int x = startX; x <= endX; x++) { for (int y = startY; y <= endY; y++) { for (int z = startZ; z <= endZ; z++) { int taskX = x; int taskY = y; int taskZ = z; Task.Run(() => { sectors[taskX, taskY, taskZ].Simulate(delta); }); } } } } private void SimulateFar(double delta) { Sector[,,] sectors = GameUniverse.Sectors; int sizeX = sectors.GetLength(0); int countX = Mathf.Clamp(sizeX / maxFarThreads, 1, int.MaxValue); for (int x = 0; x < sizeX; x += countX) { double taskDelta = delta; int taskStartX = x; int taskCountX = countX; _ = SimulateFarThreaded(taskDelta, taskStartX, taskCountX); } } private async Task SimulateFarThreaded(double delta, int startX, int countX) { Vector3I currentCoordinates = CurrentSector.Coordinates; Sector[,,] sectors = GameUniverse.Sectors; int sizeX = sectors.GetLength(0); int sizeY = sectors.GetLength(1); int sizeZ = sectors.GetLength(2); int startSkipX = Mathf.Clamp(currentCoordinates.X - 1, 0, sizeX); int startSkipY = Mathf.Clamp(currentCoordinates.Y - 1, 0, sizeY); int startSkipZ = Mathf.Clamp(currentCoordinates.Z - 1, 0, sizeZ); int endSkipX = Mathf.Clamp(currentCoordinates.X + 1, 0, sizeX); int endSkipY = Mathf.Clamp(currentCoordinates.Y + 1, 0, sizeY); int endSkipZ = Mathf.Clamp(currentCoordinates.Z + 1, 0, sizeZ); int endX = Mathf.Clamp(startX + countX, 0, sizeX); for (int x = startX; x < endX; x++) { for (int y = 0; y < sizeY; y++) { for (int z = 0; z < sizeZ; z++) { if (Helpers.IsBetweenInclusive(x, startSkipX, endSkipX)) { if (Helpers.IsBetweenInclusive(y, startSkipY, endSkipY)) { if (Helpers.IsBetweenInclusive(z, startSkipZ, endSkipZ)) { continue; } } } sectors[x, y, z].Simulate(delta); } } } } }