diff --git a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs index 17dba020..7517f4b7 100644 --- a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs +++ b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs @@ -10,8 +10,6 @@ using Invalid.DynamicRoids; using Sandbox.Game.Entities; - - public class AsteroidZone { public Vector3D Center { get; set; } @@ -31,9 +29,6 @@ public bool IsPointInZone(Vector3D point) } } - - - public class AsteroidSpawner { public List _asteroids; @@ -43,14 +38,18 @@ public class AsteroidSpawner private List _despawnedAsteroids = new List(); private List _networkMessages = new List(); private Dictionary playerZones = new Dictionary(); - private Dictionary playerMovementData = new Dictionary(); + private Queue gravityCheckQueue = new Queue(); + private const int GravityChecksPerTick = 1; + + private Queue _updateQueue = new Queue(); + private const int UpdatesPerTick = 50; // Adjust this number based on performance needs private class PlayerMovementData { public Vector3D LastPosition { get; set; } public DateTime LastUpdateTime { get; set; } - public double Speed { get; set; } // Added to store the calculated speed + public double Speed { get; set; } } public void Init(int seed) @@ -63,6 +62,12 @@ public void Init(int seed) _worldLoadTime = DateTime.UtcNow; rand = new Random(seed); AsteroidSettings.Seed = seed; + + // Add all asteroids to the update queue + foreach (var asteroid in _asteroids) + { + _updateQueue.Enqueue(asteroid); + } } public void SaveAsteroidState() @@ -75,7 +80,7 @@ public void SaveAsteroidState() Position = asteroid.PositionComp.GetPosition(), Size = asteroid.Size, Type = asteroid.Type, - EntityId = asteroid.EntityId // Save unique ID + EntityId = asteroid.EntityId }).ToList(); asteroidStates.AddRange(_despawnedAsteroids); @@ -85,6 +90,13 @@ public void SaveAsteroidState() { writer.Write(stateBytes, 0, stateBytes.Length); } + + // Ensure the update queue is saved as well + _updateQueue.Clear(); + foreach (var asteroid in _asteroids) + { + _updateQueue.Enqueue(asteroid); + } } public void LoadAsteroidState() @@ -109,13 +121,19 @@ public void LoadAsteroidState() if (_asteroids.Any(a => a.EntityId == state.EntityId)) { Log.Info($"Skipping duplicate asteroid with ID {state.EntityId}"); - continue; // Skip duplicates + continue; } var asteroid = AsteroidEntity.CreateAsteroid(state.Position, state.Size, Vector3D.Zero, state.Type); - asteroid.EntityId = state.EntityId; // Assign the saved ID + asteroid.EntityId = state.EntityId; _asteroids.Add(asteroid); MyEntities.Add(asteroid); + + // Add to gravity check queue + gravityCheckQueue.Enqueue(asteroid); + + // Add to update queue + _updateQueue.Enqueue(asteroid); } } } @@ -144,7 +162,7 @@ private void LoadAsteroidsInRange(Vector3D playerPosition, AsteroidZone zone) respawnedPositions.Add(state.Position); var asteroid = AsteroidEntity.CreateAsteroid(state.Position, state.Size, Vector3D.Zero, state.Type); - asteroid.EntityId = state.EntityId; // Assign the saved ID + asteroid.EntityId = state.EntityId; _asteroids.Add(asteroid); var message = new AsteroidNetworkMessage(state.Position, state.Size, Vector3D.Zero, Vector3D.Zero, state.Type, false, asteroid.EntityId, false, true, Quaternion.Identity); @@ -152,6 +170,9 @@ private void LoadAsteroidsInRange(Vector3D playerPosition, AsteroidZone zone) MyAPIGateway.Multiplayer.SendMessageToOthers(32000, messageBytes); _despawnedAsteroids.Remove(state); + + // Add to gravity check queue + gravityCheckQueue.Enqueue(asteroid); } } @@ -219,6 +240,7 @@ public void AssignZonesToPlayers() playerZones = updatedZones; } + public void MergeZones() { List mergedZones = new List(); @@ -234,7 +256,6 @@ public void MergeZones() if (distance <= combinedRadius) { - // Merge the zones by updating the center and radius of the merged zone Vector3D newCenter = (zone.Center + mergedZone.Center) / 2; double newRadius = Math.Max(zone.Radius, mergedZone.Radius) + distance / 2; mergedZone.Center = newCenter; @@ -247,12 +268,10 @@ public void MergeZones() if (!merged) { - // If the zone couldn't be merged with any existing merged zones, add it as a new merged zone mergedZones.Add(new AsteroidZone(zone.Center, zone.Radius) { AsteroidCount = zone.AsteroidCount }); } } - // Update the playerZones dictionary with the merged zones playerZones.Clear(); List players = new List(); MyAPIGateway.Players.GetPlayers(players); @@ -318,6 +337,7 @@ public void UpdateZones() playerZones = updatedZones; } + private int _spawnIntervalTimer = 0; private int _updateIntervalTimer = 0; @@ -340,7 +360,7 @@ public void UpdateTick() } else { - UpdateAsteroids(playerZones.Values.ToList()); + ProcessAsteroidUpdates(); _updateIntervalTimer = AsteroidSettings.UpdateInterval; } @@ -364,6 +384,8 @@ public void UpdateTick() } } + ProcessGravityCheckQueue(); + if (AsteroidSettings.EnableLogging) MyAPIGateway.Utilities.ShowNotification($"Active Asteroids: {_asteroids.Count}", 1000 / 60); } @@ -373,6 +395,46 @@ public void UpdateTick() } } + private void ProcessAsteroidUpdates() + { + int updatesProcessed = 0; + + while (updatesProcessed < UpdatesPerTick && _updateQueue.Count > 0) + { + var asteroid = _updateQueue.Dequeue(); + + // Perform the update logic for the asteroid here + UpdateAsteroid(asteroid); + + // Re-enqueue the asteroid for future updates + _updateQueue.Enqueue(asteroid); + + updatesProcessed++; + } + } + + private void UpdateAsteroid(AsteroidEntity asteroid) + { + // Implement the actual update logic for an individual asteroid here + } + + private void ProcessGravityCheckQueue() + { + for (int i = 0; i < GravityChecksPerTick && gravityCheckQueue.Count > 0; i++) + { + var asteroid = gravityCheckQueue.Dequeue(); + if (IsInNaturalGravity(asteroid.PositionComp.GetPosition())) + { + RemoveAsteroid(asteroid); + } + else + { + // Re-enqueue if still valid + gravityCheckQueue.Enqueue(asteroid); + } + } + } + private void UpdateAsteroids(List zones) { Log.Info($"Updating asteroids. Total asteroids: {_asteroids.Count}, Total zones: {zones.Count}"); @@ -401,7 +463,6 @@ private void UpdateAsteroids(List zones) } else if (currentZone != null) { - // Ensure the asteroid is counted in the correct zone foreach (var zone in zones) { if (zone != currentZone && zone.IsPointInZone(asteroid.PositionComp.GetPosition())) @@ -411,6 +472,9 @@ private void UpdateAsteroids(List zones) } currentZone.AsteroidCount++; } + + // Add to gravity check queue + gravityCheckQueue.Enqueue(asteroid); } Log.Info($"Update complete. Removed asteroids: {removedCount}, Remaining asteroids: {_asteroids.Count}"); @@ -435,14 +499,13 @@ public void SpawnAsteroids(List zones) List skippedPositions = new List(); List spawnedPositions = new List(); - UpdatePlayerMovementData(); // Update player movement data + UpdatePlayerMovementData(); foreach (var zone in zones) { int asteroidsSpawned = 0; int zoneSpawnAttempts = 0; - // Check if any player in the zone is moving too fast bool skipSpawning = false; List players = new List(); MyAPIGateway.Players.GetPlayers(players); @@ -494,7 +557,6 @@ public void SpawnAsteroids(List zones) continue; } - // Check max asteroid count before actually adding a new asteroid if (AsteroidSettings.MaxAsteroidCount != -1 && _asteroids.Count >= AsteroidSettings.MaxAsteroidCount) { Log.Warning($"Maximum asteroid count of {AsteroidSettings.MaxAsteroidCount} reached. No more asteroids will be spawned until existing ones are removed."); @@ -518,6 +580,9 @@ public void SpawnAsteroids(List zones) var message = new AsteroidNetworkMessage(newPosition, size, newVelocity, Vector3D.Zero, type, false, asteroid.EntityId, false, true, rotation); _networkMessages.Add(message); asteroidsSpawned++; + + // Add to gravity check queue + gravityCheckQueue.Enqueue(asteroid); } } @@ -576,6 +641,11 @@ private void UpdatePlayerMovementData() private bool IsValidSpawnPosition(Vector3D position, List zones) { + if (AsteroidSettings.IgnorePlanets && IsInNaturalGravity(position)) + { + return false; + } + foreach (var zone in zones) { if (zone.IsPointInZone(position) && @@ -587,6 +657,13 @@ private bool IsValidSpawnPosition(Vector3D position, List zones) return false; } + private bool IsInNaturalGravity(Vector3D position) + { + float naturalGravityInterference; + Vector3 gravity = MyAPIGateway.Physics.CalculateNaturalGravityAt(position, out naturalGravityInterference); + return gravity.LengthSquared() > 0; + } + public void SendNetworkMessages() { if (_networkMessages.Count == 0) return; diff --git a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs index 5f4ab973..05b9e4b3 100644 --- a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs +++ b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs @@ -30,6 +30,7 @@ public static class AsteroidSettings public static double MinDistanceFromVanillaAsteroids = 1000; public static double MinDistanceFromPlayer = 3000; public static int Seed = 69420; + public static bool IgnorePlanets = true; public static double IceWeight = 99; public static double StoneWeight = 0.5; public static double IronWeight = 0.25; @@ -153,6 +154,7 @@ public static void SaveSettings() writer.WriteLine($"MinDistanceFromVanillaAsteroids={MinDistanceFromVanillaAsteroids}"); writer.WriteLine($"MinDistanceFromPlayer={MinDistanceFromPlayer}"); writer.WriteLine($"Seed={Seed}"); + writer.WriteLine($"IgnorePlanets={IgnorePlanets}"); writer.WriteLine("[Weights]"); writer.WriteLine($"IceWeight={IceWeight}"); @@ -291,6 +293,9 @@ public static void LoadSettings() case "Seed": Seed = int.Parse(value); break; + case "IgnorePlanets": + IgnorePlanets = bool.Parse(value); + break; case "IceWeight": IceWeight = double.Parse(value); break;