using System.Collections.Generic; using System.Threading.Tasks; using Godot; public class TestGenerator : IGenerator { public static Vector3I UNIVERSE_SIZE = new(10, 10, 10); public static Vector3 SECTOR_SIZE = new(50, 50, 50); public static int STARS_PER_SECTOR = 1; public static int STARS_PER_SECTOR_VARIANCE = 0; public static int SHIPS_PER_SECTOR = 0; public static int SHIPS_PER_SECTOR_VARIANCE = 0; public static int STATIONS_PER_SECTOR = 0; public static int STATIONS_PER_SECTOR_VARIANCE = 0; private readonly int threads = 16; private RandomNumberGenerator rng; public Vector3I GetUniverseSize() { return UNIVERSE_SIZE; } public Vector3 GetSectorSize() { return SECTOR_SIZE; } 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) ); } public Vector3I GetSectorOffset() { return GetSectorOffset(UNIVERSE_SIZE); } public Universe InitializeEmptyUniverse(Vector3I universeSize, Vector3 sectorSize) { Universe universe = new(universeSize); for (int x = 0; x < universeSize.X; x++) { for (int y = 0; y < universeSize.Y; y++) { for (int z = 0; z < universeSize.Z; z++) { universe.Sectors[x, y, z] = new Sector( new(x, y, z), GetSectorOffset(universeSize), sectorSize ); } } } return universe; } public Universe GenerateUniverse() { rng = new(); List tasks = []; Universe universe = new(UNIVERSE_SIZE); int countX = Mathf.Clamp(UNIVERSE_SIZE.X / threads, 1, int.MaxValue); for (int x = 0; x < UNIVERSE_SIZE.X; x += countX) { int taskStartX = x; int taskCountX = countX; Task clusteredTask = Task.Run(() => { GenerateClustered(universe, taskStartX, taskCountX); }); tasks.Add(clusteredTask); } Task.WaitAll([.. tasks]); return universe; } private void GenerateClustered(Universe universe, int startX, int countX) { int endX = Mathf.Clamp(startX + countX, 0, UNIVERSE_SIZE.X); for (int x = startX; x < endX; x++) { for (int y = 0; y < UNIVERSE_SIZE.Y; y++) { for (int z = 0; z < UNIVERSE_SIZE.Z; z++) { universe.Sectors[x, y, z] = GenerateSector(new(x, y, z)); } } } } public Sector GenerateSector(Vector3I coordinates) { Sector sector = new(coordinates, GetSectorOffset(), SECTOR_SIZE); int starCount = rng.RandiRange( STARS_PER_SECTOR - STARS_PER_SECTOR_VARIANCE, STARS_PER_SECTOR + STARS_PER_SECTOR_VARIANCE ); starCount = Mathf.Clamp(starCount, 0, int.MaxValue); 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); sector.GameObjects.Add(star); } } int shipCount = rng.RandiRange( SHIPS_PER_SECTOR - SHIPS_PER_SECTOR_VARIANCE, SHIPS_PER_SECTOR + SHIPS_PER_SECTOR_VARIANCE ); shipCount = Mathf.Clamp(shipCount, 0, int.MaxValue); for (int i = 0; i < shipCount; i++) { Vector3 localCoordinates = GenerateLocalCoordinates(); Vessel ship = GenerateShip(sector, localCoordinates); sector.GameObjects.Add(ship); } int stationCount = rng.RandiRange( STATIONS_PER_SECTOR - STATIONS_PER_SECTOR_VARIANCE, STATIONS_PER_SECTOR + STATIONS_PER_SECTOR_VARIANCE ); stationCount = Mathf.Clamp(stationCount, 0, int.MaxValue); for (int i = 0; i < stationCount; i++) { Vector3 localCoordinates = GenerateLocalCoordinates(); Vessel station = GenerateStation(sector, localCoordinates); sector.GameObjects.Add(station); } return sector; } public Star GenerateStar(Sector sector, Vector3 localCoordinates) { return new Star(sector, localCoordinates); } public Star GenerateStar(Sector sector) { return GenerateStar(sector, GenerateLocalCoordinates()); } public Vessel GenerateShip(Sector sector, Vector3 localCoordinates) { return new Vessel(sector, localCoordinates); } public Vessel GenerateShip(Sector sector) { return GenerateShip(sector, GenerateLocalCoordinates()); } public Vessel GenerateStation(Sector sector, Vector3 localCoordinates) { return new Vessel(sector, localCoordinates); } public Vessel GenerateStation(Sector sector) { return GenerateStation(sector, GenerateLocalCoordinates()); } public Vector3 GenerateLocalCoordinates() { double x = (rng.Randf() - 0.5) * SECTOR_SIZE.X; double y = (rng.Randf() - 0.5) * SECTOR_SIZE.Y; double z = (rng.Randf() - 0.5) * SECTOR_SIZE.Z; return new(x, y, z); } }