148 lines
4.4 KiB
C#
148 lines
4.4 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|