From 62e7d1af67c0b953c8a950e418a262c88d8ae903 Mon Sep 17 00:00:00 2001 From: InvalidArgument3 Date: Mon, 17 Jun 2024 17:12:36 -0500 Subject: [PATCH 1/5] "latch on" to vanilla asteroids for spawning, default zone size to 0 Revert ""latch on" to vanilla asteroids for spawning, default zone size to 0" This reverts commit bc9cb47a0f58425dfdaf7b5536462b4331bdebcb. Reapply ""latch on" to vanilla asteroids for spawning, default zone size to 0" This reverts commit ed38072913bb6a49bdefb38ae1cabc117cbae96f. Update AsteroidSpawner.cs Revert "attempt at queueing asteroid updates" This reverts commit d330e341863816d30868f4dce8b7cb14a2783ebf. latching functional fix godawful lag when not near vanilla asteroid for latching do NOT write temp spawn areas to config config to add custom spawnable areas. issue with infinite spawnin Revert "config to add custom spawnable areas. issue with infinite spawnin" This reverts commit a87192018d74e8f7f2b0e1d556ee3ada50d19488. Update AsteroidSpawner.cs --- .../AsteroidEntities/AsteroidSpawner.cs | 228 +++++++++++------- .../DynamicAsteroids/AsteroidSettings.cs | 34 ++- 2 files changed, 158 insertions(+), 104 deletions(-) diff --git a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs index 7517f4b7..97d9f74b 100644 --- a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs +++ b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs @@ -9,6 +9,7 @@ using DynamicAsteroids; using Invalid.DynamicRoids; using Sandbox.Game.Entities; +using VRage.Game.Entity; public class AsteroidZone { @@ -40,11 +41,12 @@ public class AsteroidSpawner private Dictionary playerZones = new Dictionary(); private Dictionary playerMovementData = new Dictionary(); private Queue gravityCheckQueue = new Queue(); - private const int GravityChecksPerTick = 1; + private const int GravityChecksPerTick = 10; 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; } @@ -62,12 +64,6 @@ 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() @@ -90,13 +86,6 @@ 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() @@ -131,62 +120,10 @@ public void LoadAsteroidState() // Add to gravity check queue gravityCheckQueue.Enqueue(asteroid); - - // Add to update queue - _updateQueue.Enqueue(asteroid); } } } - private void LoadAsteroidsInRange(Vector3D playerPosition, AsteroidZone zone) - { - int skippedCount = 0; - int respawnedCount = 0; - List skippedPositions = new List(); - List respawnedPositions = new List(); - - foreach (var state in _despawnedAsteroids.ToArray()) - { - if (zone.IsPointInZone(state.Position)) - { - bool tooClose = _asteroids.Any(a => Vector3D.DistanceSquared(a.PositionComp.GetPosition(), state.Position) < AsteroidSettings.MinDistanceFromPlayer * AsteroidSettings.MinDistanceFromPlayer); - - if (tooClose) - { - skippedCount++; - skippedPositions.Add(state.Position); - continue; - } - - respawnedCount++; - respawnedPositions.Add(state.Position); - - var asteroid = AsteroidEntity.CreateAsteroid(state.Position, state.Size, Vector3D.Zero, state.Type); - 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); - var messageBytes = MyAPIGateway.Utilities.SerializeToBinary(message); - MyAPIGateway.Multiplayer.SendMessageToOthers(32000, messageBytes); - - _despawnedAsteroids.Remove(state); - - // Add to gravity check queue - gravityCheckQueue.Enqueue(asteroid); - } - } - - if (skippedCount > 0) - { - Log.Info($"Skipped respawn of {skippedCount} asteroids due to proximity to other asteroids or duplicate ID."); - } - - if (respawnedCount > 0) - { - Log.Info($"Respawned {respawnedCount} asteroids at positions: {string.Join(", ", respawnedPositions.Select(p => p.ToString()))}"); - } - } - public void Close() { if (!MyAPIGateway.Session.IsServer) @@ -341,6 +278,70 @@ public void UpdateZones() private int _spawnIntervalTimer = 0; private int _updateIntervalTimer = 0; + private List _activeDespawnedAsteroids = new List(); + private List _processingDespawnedAsteroids = new List(); + + private void LoadAsteroidsInRange(Vector3D playerPosition, AsteroidZone zone) + { + int skippedCount = 0; + int respawnedCount = 0; + List skippedPositions = new List(); + List respawnedPositions = new List(); + + // Use a bounding sphere for spatial partitioning + BoundingSphereD sphere = new BoundingSphereD(zone.Center, zone.Radius); + List entitiesInRange = new List(); + MyGamePruningStructure.GetAllEntitiesInSphere(ref sphere, entitiesInRange); + + foreach (var state in _activeDespawnedAsteroids) + { + if (zone.IsPointInZone(state.Position)) + { + bool tooClose = entitiesInRange.Any(e => e is MyVoxelBase && Vector3D.DistanceSquared(e.PositionComp.GetPosition(), state.Position) < AsteroidSettings.MinDistanceFromPlayer * AsteroidSettings.MinDistanceFromPlayer); + + if (tooClose) + { + skippedCount++; + skippedPositions.Add(state.Position); + continue; + } + + respawnedCount++; + respawnedPositions.Add(state.Position); + + var asteroid = AsteroidEntity.CreateAsteroid(state.Position, state.Size, Vector3D.Zero, state.Type); + 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); + var messageBytes = MyAPIGateway.Utilities.SerializeToBinary(message); + MyAPIGateway.Multiplayer.SendMessageToOthers(32000, messageBytes); + + _activeDespawnedAsteroids.Remove(state); + + // Add to gravity check queue + gravityCheckQueue.Enqueue(asteroid); + } + } + + if (skippedCount > 0) + { + Log.Info($"Skipped respawn of {skippedCount} asteroids due to proximity to other asteroids or duplicate ID."); + } + + if (respawnedCount > 0) + { + Log.Info($"Respawned {respawnedCount} asteroids at positions: {string.Join(", ", respawnedPositions.Select(p => p.ToString()))}"); + } + } + + private void SwapDespawnedAsteroids() + { + var temp = _activeDespawnedAsteroids; + _activeDespawnedAsteroids = _processingDespawnedAsteroids; + _processingDespawnedAsteroids = temp; + _processingDespawnedAsteroids.Clear(); + } public void UpdateTick() { if (!MyAPIGateway.Session.IsServer) return; @@ -349,18 +350,41 @@ public void UpdateTick() MergeZones(); UpdateZones(); + // Clear previous temporary areas before creating new ones + ClearTemporarySpawnableAreas(); + CreateTemporarySpawnableAreasAroundVanillaAsteroids(); + try { List players = new List(); MyAPIGateway.Players.GetPlayers(players); + bool anyPlayerNearVanillaAsteroid = false; + Vector3D unusedNearestPoint; + + foreach (var player in players) + { + Vector3D playerPosition = player.GetPosition(); + if (IsNearVanillaAsteroid(playerPosition, out unusedNearestPoint)) + { + anyPlayerNearVanillaAsteroid = true; + break; + } + } + + if (!anyPlayerNearVanillaAsteroid) + { + // Skip the costly logic if no players are near vanilla asteroids + return; + } + if (_updateIntervalTimer > 0) { _updateIntervalTimer--; } else { - ProcessAsteroidUpdates(); + UpdateAsteroids(playerZones.Values.ToList()); _updateIntervalTimer = AsteroidSettings.UpdateInterval; } @@ -393,29 +417,35 @@ public void UpdateTick() { Log.Exception(ex, typeof(AsteroidSpawner)); } + + // Swap the lists + SwapDespawnedAsteroids(); } - private void ProcessAsteroidUpdates() + private void ClearTemporarySpawnableAreas() { - int updatesProcessed = 0; - - while (updatesProcessed < UpdatesPerTick && _updateQueue.Count > 0) - { - var asteroid = _updateQueue.Dequeue(); + AsteroidSettings.ValidSpawnLocations.RemoveAll(area => area.Name.StartsWith("TempArea_")); + } - // Perform the update logic for the asteroid here - UpdateAsteroid(asteroid); + private bool IsNearVanillaAsteroid(Vector3D position, out Vector3D nearestPoint) + { + List voxelMaps = new List(); + MyAPIGateway.Session.VoxelMaps.GetInstances(voxelMaps, v => v is IMyVoxelMap && !v.StorageName.StartsWith("mod_")); - // Re-enqueue the asteroid for future updates - _updateQueue.Enqueue(asteroid); + double minDistance = double.MaxValue; + nearestPoint = Vector3D.Zero; - updatesProcessed++; + foreach (var voxelMap in voxelMaps) + { + double distanceSquared = Vector3D.DistanceSquared(position, voxelMap.GetPosition()); + if (distanceSquared < minDistance) + { + minDistance = distanceSquared; + nearestPoint = voxelMap.GetPosition(); + } } - } - private void UpdateAsteroid(AsteroidEntity asteroid) - { - // Implement the actual update logic for an individual asteroid here + return minDistance < AsteroidSettings.VanillaAsteroidSpawnLatchingRadius * AsteroidSettings.VanillaAsteroidSpawnLatchingRadius; } private void ProcessGravityCheckQueue() @@ -537,6 +567,7 @@ public void SpawnAsteroids(List zones) zoneSpawnAttempts < AsteroidSettings.MaxZoneAttempts && totalSpawnAttempts < AsteroidSettings.MaxTotalAttempts) { Vector3D newPosition; + Vector3D nearestPoint; do { newPosition = zone.Center + RandVector() * AsteroidSettings.ZoneRadius; @@ -551,10 +582,20 @@ public void SpawnAsteroids(List zones) Vector3D newVelocity; if (!AsteroidSettings.CanSpawnAsteroidAtPoint(newPosition, out newVelocity)) continue; - if (IsNearVanillaAsteroid(newPosition)) + if (AsteroidSettings.EnableVanillaAsteroidSpawnLatching && IsNearVanillaAsteroid(newPosition, out nearestPoint)) { - skippedPositions.Add(newPosition); - continue; + double distance = Vector3D.Distance(newPosition, nearestPoint); + if (distance < AsteroidSettings.MinDistanceFromVanillaAsteroids) + { + newPosition = nearestPoint + (newPosition - nearestPoint).Normalized() * AsteroidSettings.MinDistanceFromVanillaAsteroids; + } + + // Ensure the new position is valid + if (!IsValidSpawnPosition(newPosition, zones)) + { + skippedPositions.Add(newPosition); + continue; + } } if (AsteroidSettings.MaxAsteroidCount != -1 && _asteroids.Count >= AsteroidSettings.MaxAsteroidCount) @@ -710,21 +751,22 @@ private void RemoveAsteroid(AsteroidEntity asteroid) } } - private bool IsNearVanillaAsteroid(Vector3D position) + public void CreateTemporarySpawnableAreasAroundVanillaAsteroids() { List voxelMaps = new List(); MyAPIGateway.Session.VoxelMaps.GetInstances(voxelMaps, v => v is IMyVoxelMap && !v.StorageName.StartsWith("mod_")); foreach (var voxelMap in voxelMaps) { - if (Vector3D.DistanceSquared(position, voxelMap.GetPosition()) < AsteroidSettings.MinDistanceFromVanillaAsteroids * AsteroidSettings.MinDistanceFromVanillaAsteroids) - { - Log.Info($"Position {position} is near vanilla asteroid {voxelMap.StorageName}"); - return true; - } + Vector3D asteroidPosition = voxelMap.GetPosition(); + SpawnableArea tempArea = new SpawnableArea + { + Name = "TempArea_" + voxelMap.StorageName, + CenterPosition = asteroidPosition, + Radius = AsteroidSettings.VanillaAsteroidSpawnLatchingRadius + }; + AsteroidSettings.ValidSpawnLocations.Add(tempArea); } - - return false; } private Vector3D RandVector() diff --git a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs index 506eb9e5..57a1b918 100644 --- a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs +++ b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs @@ -13,6 +13,8 @@ public static class AsteroidSettings public static bool EnableLogging = false; public static bool EnablePersistence = false; public static bool EnableMiddleMouseAsteroidSpawn = false; + public static bool EnableVanillaAsteroidSpawnLatching = true; + public static double VanillaAsteroidSpawnLatchingRadius = 10000; public static bool DisableZoneWhileMovingFast = true; public static double ZoneSpeedThreshold = 2000.0; public static int SaveStateInterval = 600; @@ -137,6 +139,8 @@ public static void SaveSettings() writer.WriteLine($"EnableLogging={EnableLogging}"); writer.WriteLine($"EnablePersistence={EnablePersistence}"); writer.WriteLine($"EnableMiddleMouseAsteroidSpawn={EnableMiddleMouseAsteroidSpawn}"); + writer.WriteLine($"EnableVanillaAsteroidSpawnLatching={EnableVanillaAsteroidSpawnLatching}"); + writer.WriteLine($"VanillaAsteroidSpawnLatchingRadius={VanillaAsteroidSpawnLatchingRadius}"); writer.WriteLine($"DisableZoneWhileMovingFast={DisableZoneWhileMovingFast}"); writer.WriteLine($"ZoneSpeedThreshold={ZoneSpeedThreshold}"); writer.WriteLine($"SaveStateInterval={SaveStateInterval}"); @@ -155,7 +159,6 @@ public static void SaveSettings() writer.WriteLine($"MinDistanceFromPlayer={MinDistanceFromPlayer}"); writer.WriteLine($"Seed={Seed}"); writer.WriteLine($"IgnorePlanets={IgnorePlanets}"); - writer.WriteLine("[Weights]"); writer.WriteLine($"IceWeight={IceWeight}"); writer.WriteLine($"StoneWeight={StoneWeight}"); @@ -168,19 +171,16 @@ public static void SaveSettings() writer.WriteLine($"GoldWeight={GoldWeight}"); writer.WriteLine($"PlatinumWeight={PlatinumWeight}"); writer.WriteLine($"UraniniteWeight={UraniniteWeight}"); - writer.WriteLine("[AsteroidSize]"); writer.WriteLine($"BaseIntegrity={BaseIntegrity}"); writer.WriteLine($"MinAsteroidSize={MinAsteroidSize}"); writer.WriteLine($"MaxAsteroidSize={MaxAsteroidSize}"); writer.WriteLine($"MinSubChunkSize={MinSubChunkSize}"); - writer.WriteLine("[SubChunkVelocity]"); writer.WriteLine($"SubChunkVelocityMin={SubChunkVelocityMin}"); writer.WriteLine($"SubChunkVelocityMax={SubChunkVelocityMax}"); writer.WriteLine($"SubChunkAngularVelocityMin={SubChunkAngularVelocityMin}"); writer.WriteLine($"SubChunkAngularVelocityMax={SubChunkAngularVelocityMax}"); - writer.WriteLine("[DropRanges]"); WriteIntArray(writer, "IceDropRange", IceDropRange); WriteIntArray(writer, "StoneDropRange", StoneDropRange); @@ -193,13 +193,15 @@ public static void SaveSettings() WriteIntArray(writer, "GoldDropRange", GoldDropRange); WriteIntArray(writer, "PlatinumDropRange", PlatinumDropRange); WriteIntArray(writer, "UraniniteDropRange", UraniniteDropRange); - writer.WriteLine("[SpawnableAreas]"); foreach (var area in ValidSpawnLocations) { - writer.WriteLine($"Name={area.Name}"); - writer.WriteLine($"CenterPosition={area.CenterPosition.X},{area.CenterPosition.Y},{area.CenterPosition.Z}"); - writer.WriteLine($"Radius={area.Radius}"); + if (!area.Name.StartsWith("TempArea_")) // Skip temporary areas + { + writer.WriteLine($"Name={area.Name}"); + writer.WriteLine($"CenterPosition={area.CenterPosition.X},{area.CenterPosition.Y},{area.CenterPosition.Z}"); + writer.WriteLine($"Radius={area.Radius}"); + } } } } @@ -242,6 +244,12 @@ public static void LoadSettings() case "EnableMiddleMouseAsteroidSpawn": EnableMiddleMouseAsteroidSpawn = bool.Parse(value); break; + case "EnableVanillaAsteroidSpawnLatching": + EnableVanillaAsteroidSpawnLatching = bool.Parse(value); + break; + case "VanillaAsteroidSpawnLatchingRadius": + VanillaAsteroidSpawnLatchingRadius = double.Parse(value); + break; case "DisableZoneWhileMovingFast": DisableZoneWhileMovingFast = bool.Parse(value); break; @@ -409,7 +417,7 @@ public static void LoadSettings() { Name = "DefaultArea", CenterPosition = new Vector3D(0.0, 0.0, 0.0), - Radius = 10000 + Radius = 0 }); SaveSettings(); } @@ -445,8 +453,12 @@ public class SpawnableArea public bool ContainsPoint(Vector3D point) { - double distanceSquared = (point - CenterPosition).LengthSquared(); - return distanceSquared <= Radius * Radius; + // Calculate the squared distance to avoid expensive square root operations + double distanceSquared = Vector3D.DistanceSquared(CenterPosition, point); + double radiusSquared = Radius * Radius; + + // Return whether the point is within the spawnable area + return distanceSquared <= radiusSquared; } public Vector3D VelocityAtPoint(Vector3D point) From 4134121fca0898beaa3ed1bbbf3d9bdb2729d12a Mon Sep 17 00:00:00 2001 From: InvalidArgument3 Date: Mon, 17 Jun 2024 21:46:22 -0500 Subject: [PATCH 2/5] Revert ""latch on" to vanilla asteroids for spawning, default zone size to 0" This reverts commit 62e7d1af67c0b953c8a950e418a262c88d8ae903. --- .../AsteroidEntities/AsteroidSpawner.cs | 228 +++++++----------- .../DynamicAsteroids/AsteroidSettings.cs | 34 +-- 2 files changed, 104 insertions(+), 158 deletions(-) diff --git a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs index 97d9f74b..7517f4b7 100644 --- a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs +++ b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs @@ -9,7 +9,6 @@ using DynamicAsteroids; using Invalid.DynamicRoids; using Sandbox.Game.Entities; -using VRage.Game.Entity; public class AsteroidZone { @@ -41,12 +40,11 @@ public class AsteroidSpawner private Dictionary playerZones = new Dictionary(); private Dictionary playerMovementData = new Dictionary(); private Queue gravityCheckQueue = new Queue(); - private const int GravityChecksPerTick = 10; + 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; } @@ -64,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() @@ -86,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() @@ -120,10 +131,62 @@ public void LoadAsteroidState() // Add to gravity check queue gravityCheckQueue.Enqueue(asteroid); + + // Add to update queue + _updateQueue.Enqueue(asteroid); } } } + private void LoadAsteroidsInRange(Vector3D playerPosition, AsteroidZone zone) + { + int skippedCount = 0; + int respawnedCount = 0; + List skippedPositions = new List(); + List respawnedPositions = new List(); + + foreach (var state in _despawnedAsteroids.ToArray()) + { + if (zone.IsPointInZone(state.Position)) + { + bool tooClose = _asteroids.Any(a => Vector3D.DistanceSquared(a.PositionComp.GetPosition(), state.Position) < AsteroidSettings.MinDistanceFromPlayer * AsteroidSettings.MinDistanceFromPlayer); + + if (tooClose) + { + skippedCount++; + skippedPositions.Add(state.Position); + continue; + } + + respawnedCount++; + respawnedPositions.Add(state.Position); + + var asteroid = AsteroidEntity.CreateAsteroid(state.Position, state.Size, Vector3D.Zero, state.Type); + 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); + var messageBytes = MyAPIGateway.Utilities.SerializeToBinary(message); + MyAPIGateway.Multiplayer.SendMessageToOthers(32000, messageBytes); + + _despawnedAsteroids.Remove(state); + + // Add to gravity check queue + gravityCheckQueue.Enqueue(asteroid); + } + } + + if (skippedCount > 0) + { + Log.Info($"Skipped respawn of {skippedCount} asteroids due to proximity to other asteroids or duplicate ID."); + } + + if (respawnedCount > 0) + { + Log.Info($"Respawned {respawnedCount} asteroids at positions: {string.Join(", ", respawnedPositions.Select(p => p.ToString()))}"); + } + } + public void Close() { if (!MyAPIGateway.Session.IsServer) @@ -278,70 +341,6 @@ public void UpdateZones() private int _spawnIntervalTimer = 0; private int _updateIntervalTimer = 0; - private List _activeDespawnedAsteroids = new List(); - private List _processingDespawnedAsteroids = new List(); - - private void LoadAsteroidsInRange(Vector3D playerPosition, AsteroidZone zone) - { - int skippedCount = 0; - int respawnedCount = 0; - List skippedPositions = new List(); - List respawnedPositions = new List(); - - // Use a bounding sphere for spatial partitioning - BoundingSphereD sphere = new BoundingSphereD(zone.Center, zone.Radius); - List entitiesInRange = new List(); - MyGamePruningStructure.GetAllEntitiesInSphere(ref sphere, entitiesInRange); - - foreach (var state in _activeDespawnedAsteroids) - { - if (zone.IsPointInZone(state.Position)) - { - bool tooClose = entitiesInRange.Any(e => e is MyVoxelBase && Vector3D.DistanceSquared(e.PositionComp.GetPosition(), state.Position) < AsteroidSettings.MinDistanceFromPlayer * AsteroidSettings.MinDistanceFromPlayer); - - if (tooClose) - { - skippedCount++; - skippedPositions.Add(state.Position); - continue; - } - - respawnedCount++; - respawnedPositions.Add(state.Position); - - var asteroid = AsteroidEntity.CreateAsteroid(state.Position, state.Size, Vector3D.Zero, state.Type); - 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); - var messageBytes = MyAPIGateway.Utilities.SerializeToBinary(message); - MyAPIGateway.Multiplayer.SendMessageToOthers(32000, messageBytes); - - _activeDespawnedAsteroids.Remove(state); - - // Add to gravity check queue - gravityCheckQueue.Enqueue(asteroid); - } - } - - if (skippedCount > 0) - { - Log.Info($"Skipped respawn of {skippedCount} asteroids due to proximity to other asteroids or duplicate ID."); - } - - if (respawnedCount > 0) - { - Log.Info($"Respawned {respawnedCount} asteroids at positions: {string.Join(", ", respawnedPositions.Select(p => p.ToString()))}"); - } - } - - private void SwapDespawnedAsteroids() - { - var temp = _activeDespawnedAsteroids; - _activeDespawnedAsteroids = _processingDespawnedAsteroids; - _processingDespawnedAsteroids = temp; - _processingDespawnedAsteroids.Clear(); - } public void UpdateTick() { if (!MyAPIGateway.Session.IsServer) return; @@ -350,41 +349,18 @@ public void UpdateTick() MergeZones(); UpdateZones(); - // Clear previous temporary areas before creating new ones - ClearTemporarySpawnableAreas(); - CreateTemporarySpawnableAreasAroundVanillaAsteroids(); - try { List players = new List(); MyAPIGateway.Players.GetPlayers(players); - bool anyPlayerNearVanillaAsteroid = false; - Vector3D unusedNearestPoint; - - foreach (var player in players) - { - Vector3D playerPosition = player.GetPosition(); - if (IsNearVanillaAsteroid(playerPosition, out unusedNearestPoint)) - { - anyPlayerNearVanillaAsteroid = true; - break; - } - } - - if (!anyPlayerNearVanillaAsteroid) - { - // Skip the costly logic if no players are near vanilla asteroids - return; - } - if (_updateIntervalTimer > 0) { _updateIntervalTimer--; } else { - UpdateAsteroids(playerZones.Values.ToList()); + ProcessAsteroidUpdates(); _updateIntervalTimer = AsteroidSettings.UpdateInterval; } @@ -417,35 +393,29 @@ public void UpdateTick() { Log.Exception(ex, typeof(AsteroidSpawner)); } - - // Swap the lists - SwapDespawnedAsteroids(); } - private void ClearTemporarySpawnableAreas() + private void ProcessAsteroidUpdates() { - AsteroidSettings.ValidSpawnLocations.RemoveAll(area => area.Name.StartsWith("TempArea_")); - } + int updatesProcessed = 0; - private bool IsNearVanillaAsteroid(Vector3D position, out Vector3D nearestPoint) - { - List voxelMaps = new List(); - MyAPIGateway.Session.VoxelMaps.GetInstances(voxelMaps, v => v is IMyVoxelMap && !v.StorageName.StartsWith("mod_")); + while (updatesProcessed < UpdatesPerTick && _updateQueue.Count > 0) + { + var asteroid = _updateQueue.Dequeue(); - double minDistance = double.MaxValue; - nearestPoint = Vector3D.Zero; + // Perform the update logic for the asteroid here + UpdateAsteroid(asteroid); - foreach (var voxelMap in voxelMaps) - { - double distanceSquared = Vector3D.DistanceSquared(position, voxelMap.GetPosition()); - if (distanceSquared < minDistance) - { - minDistance = distanceSquared; - nearestPoint = voxelMap.GetPosition(); - } + // Re-enqueue the asteroid for future updates + _updateQueue.Enqueue(asteroid); + + updatesProcessed++; } + } - return minDistance < AsteroidSettings.VanillaAsteroidSpawnLatchingRadius * AsteroidSettings.VanillaAsteroidSpawnLatchingRadius; + private void UpdateAsteroid(AsteroidEntity asteroid) + { + // Implement the actual update logic for an individual asteroid here } private void ProcessGravityCheckQueue() @@ -567,7 +537,6 @@ public void SpawnAsteroids(List zones) zoneSpawnAttempts < AsteroidSettings.MaxZoneAttempts && totalSpawnAttempts < AsteroidSettings.MaxTotalAttempts) { Vector3D newPosition; - Vector3D nearestPoint; do { newPosition = zone.Center + RandVector() * AsteroidSettings.ZoneRadius; @@ -582,20 +551,10 @@ public void SpawnAsteroids(List zones) Vector3D newVelocity; if (!AsteroidSettings.CanSpawnAsteroidAtPoint(newPosition, out newVelocity)) continue; - if (AsteroidSettings.EnableVanillaAsteroidSpawnLatching && IsNearVanillaAsteroid(newPosition, out nearestPoint)) + if (IsNearVanillaAsteroid(newPosition)) { - double distance = Vector3D.Distance(newPosition, nearestPoint); - if (distance < AsteroidSettings.MinDistanceFromVanillaAsteroids) - { - newPosition = nearestPoint + (newPosition - nearestPoint).Normalized() * AsteroidSettings.MinDistanceFromVanillaAsteroids; - } - - // Ensure the new position is valid - if (!IsValidSpawnPosition(newPosition, zones)) - { - skippedPositions.Add(newPosition); - continue; - } + skippedPositions.Add(newPosition); + continue; } if (AsteroidSettings.MaxAsteroidCount != -1 && _asteroids.Count >= AsteroidSettings.MaxAsteroidCount) @@ -751,22 +710,21 @@ private void RemoveAsteroid(AsteroidEntity asteroid) } } - public void CreateTemporarySpawnableAreasAroundVanillaAsteroids() + private bool IsNearVanillaAsteroid(Vector3D position) { List voxelMaps = new List(); MyAPIGateway.Session.VoxelMaps.GetInstances(voxelMaps, v => v is IMyVoxelMap && !v.StorageName.StartsWith("mod_")); foreach (var voxelMap in voxelMaps) { - Vector3D asteroidPosition = voxelMap.GetPosition(); - SpawnableArea tempArea = new SpawnableArea - { - Name = "TempArea_" + voxelMap.StorageName, - CenterPosition = asteroidPosition, - Radius = AsteroidSettings.VanillaAsteroidSpawnLatchingRadius - }; - AsteroidSettings.ValidSpawnLocations.Add(tempArea); + if (Vector3D.DistanceSquared(position, voxelMap.GetPosition()) < AsteroidSettings.MinDistanceFromVanillaAsteroids * AsteroidSettings.MinDistanceFromVanillaAsteroids) + { + Log.Info($"Position {position} is near vanilla asteroid {voxelMap.StorageName}"); + return true; + } } + + return false; } private Vector3D RandVector() diff --git a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs index 57a1b918..506eb9e5 100644 --- a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs +++ b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs @@ -13,8 +13,6 @@ public static class AsteroidSettings public static bool EnableLogging = false; public static bool EnablePersistence = false; public static bool EnableMiddleMouseAsteroidSpawn = false; - public static bool EnableVanillaAsteroidSpawnLatching = true; - public static double VanillaAsteroidSpawnLatchingRadius = 10000; public static bool DisableZoneWhileMovingFast = true; public static double ZoneSpeedThreshold = 2000.0; public static int SaveStateInterval = 600; @@ -139,8 +137,6 @@ public static void SaveSettings() writer.WriteLine($"EnableLogging={EnableLogging}"); writer.WriteLine($"EnablePersistence={EnablePersistence}"); writer.WriteLine($"EnableMiddleMouseAsteroidSpawn={EnableMiddleMouseAsteroidSpawn}"); - writer.WriteLine($"EnableVanillaAsteroidSpawnLatching={EnableVanillaAsteroidSpawnLatching}"); - writer.WriteLine($"VanillaAsteroidSpawnLatchingRadius={VanillaAsteroidSpawnLatchingRadius}"); writer.WriteLine($"DisableZoneWhileMovingFast={DisableZoneWhileMovingFast}"); writer.WriteLine($"ZoneSpeedThreshold={ZoneSpeedThreshold}"); writer.WriteLine($"SaveStateInterval={SaveStateInterval}"); @@ -159,6 +155,7 @@ public static void SaveSettings() writer.WriteLine($"MinDistanceFromPlayer={MinDistanceFromPlayer}"); writer.WriteLine($"Seed={Seed}"); writer.WriteLine($"IgnorePlanets={IgnorePlanets}"); + writer.WriteLine("[Weights]"); writer.WriteLine($"IceWeight={IceWeight}"); writer.WriteLine($"StoneWeight={StoneWeight}"); @@ -171,16 +168,19 @@ public static void SaveSettings() writer.WriteLine($"GoldWeight={GoldWeight}"); writer.WriteLine($"PlatinumWeight={PlatinumWeight}"); writer.WriteLine($"UraniniteWeight={UraniniteWeight}"); + writer.WriteLine("[AsteroidSize]"); writer.WriteLine($"BaseIntegrity={BaseIntegrity}"); writer.WriteLine($"MinAsteroidSize={MinAsteroidSize}"); writer.WriteLine($"MaxAsteroidSize={MaxAsteroidSize}"); writer.WriteLine($"MinSubChunkSize={MinSubChunkSize}"); + writer.WriteLine("[SubChunkVelocity]"); writer.WriteLine($"SubChunkVelocityMin={SubChunkVelocityMin}"); writer.WriteLine($"SubChunkVelocityMax={SubChunkVelocityMax}"); writer.WriteLine($"SubChunkAngularVelocityMin={SubChunkAngularVelocityMin}"); writer.WriteLine($"SubChunkAngularVelocityMax={SubChunkAngularVelocityMax}"); + writer.WriteLine("[DropRanges]"); WriteIntArray(writer, "IceDropRange", IceDropRange); WriteIntArray(writer, "StoneDropRange", StoneDropRange); @@ -193,15 +193,13 @@ public static void SaveSettings() WriteIntArray(writer, "GoldDropRange", GoldDropRange); WriteIntArray(writer, "PlatinumDropRange", PlatinumDropRange); WriteIntArray(writer, "UraniniteDropRange", UraniniteDropRange); + writer.WriteLine("[SpawnableAreas]"); foreach (var area in ValidSpawnLocations) { - if (!area.Name.StartsWith("TempArea_")) // Skip temporary areas - { - writer.WriteLine($"Name={area.Name}"); - writer.WriteLine($"CenterPosition={area.CenterPosition.X},{area.CenterPosition.Y},{area.CenterPosition.Z}"); - writer.WriteLine($"Radius={area.Radius}"); - } + writer.WriteLine($"Name={area.Name}"); + writer.WriteLine($"CenterPosition={area.CenterPosition.X},{area.CenterPosition.Y},{area.CenterPosition.Z}"); + writer.WriteLine($"Radius={area.Radius}"); } } } @@ -244,12 +242,6 @@ public static void LoadSettings() case "EnableMiddleMouseAsteroidSpawn": EnableMiddleMouseAsteroidSpawn = bool.Parse(value); break; - case "EnableVanillaAsteroidSpawnLatching": - EnableVanillaAsteroidSpawnLatching = bool.Parse(value); - break; - case "VanillaAsteroidSpawnLatchingRadius": - VanillaAsteroidSpawnLatchingRadius = double.Parse(value); - break; case "DisableZoneWhileMovingFast": DisableZoneWhileMovingFast = bool.Parse(value); break; @@ -417,7 +409,7 @@ public static void LoadSettings() { Name = "DefaultArea", CenterPosition = new Vector3D(0.0, 0.0, 0.0), - Radius = 0 + Radius = 10000 }); SaveSettings(); } @@ -453,12 +445,8 @@ public class SpawnableArea public bool ContainsPoint(Vector3D point) { - // Calculate the squared distance to avoid expensive square root operations - double distanceSquared = Vector3D.DistanceSquared(CenterPosition, point); - double radiusSquared = Radius * Radius; - - // Return whether the point is within the spawnable area - return distanceSquared <= radiusSquared; + double distanceSquared = (point - CenterPosition).LengthSquared(); + return distanceSquared <= Radius * Radius; } public Vector3D VelocityAtPoint(Vector3D point) From 02f69aff7d110c2a0fb5a3aba11b250e58d029c6 Mon Sep 17 00:00:00 2001 From: InvalidArgument3 Date: Mon, 17 Jun 2024 22:16:44 -0500 Subject: [PATCH 3/5] Update AsteroidSpawner.cs --- .../AsteroidEntities/AsteroidSpawner.cs | 37 ++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs index 7517f4b7..d97d4de5 100644 --- a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs +++ b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs @@ -416,6 +416,29 @@ private void ProcessAsteroidUpdates() private void UpdateAsteroid(AsteroidEntity asteroid) { // Implement the actual update logic for an individual asteroid here + Vector3D currentPosition = asteroid.PositionComp.GetPosition(); + bool inAnyZone = false; + AsteroidZone currentZone = null; + + foreach (var zone in playerZones.Values) + { + if (zone.IsPointInZone(currentPosition)) + { + inAnyZone = true; + currentZone = zone; + break; + } + } + + if (!inAnyZone) + { + Log.Info($"Removing asteroid at {currentPosition} due to being out of any player zone"); + RemoveAsteroid(asteroid); + } + else if (currentZone != null) + { + currentZone.AsteroidCount++; + } } private void ProcessGravityCheckQueue() @@ -542,6 +565,7 @@ public void SpawnAsteroids(List zones) newPosition = zone.Center + RandVector() * AsteroidSettings.ZoneRadius; zoneSpawnAttempts++; totalSpawnAttempts++; + Log.Info($"Attempting to spawn asteroid at {newPosition} (attempt {totalSpawnAttempts})"); } while (!IsValidSpawnPosition(newPosition, zones) && zoneSpawnAttempts < AsteroidSettings.MaxZoneAttempts && totalSpawnAttempts < AsteroidSettings.MaxTotalAttempts); @@ -549,10 +573,15 @@ public void SpawnAsteroids(List zones) break; Vector3D newVelocity; - if (!AsteroidSettings.CanSpawnAsteroidAtPoint(newPosition, out newVelocity)) continue; + if (!AsteroidSettings.CanSpawnAsteroidAtPoint(newPosition, out newVelocity)) + { + Log.Info($"Cannot spawn asteroid at {newPosition}, skipping."); + continue; + } if (IsNearVanillaAsteroid(newPosition)) { + Log.Info($"Position {newPosition} is near a vanilla asteroid, skipping."); skippedPositions.Add(newPosition); continue; } @@ -563,6 +592,12 @@ public void SpawnAsteroids(List zones) return; } + if (zone.AsteroidCount >= AsteroidSettings.MaxAsteroidsPerZone) + { + Log.Info($"Zone at {zone.Center} has reached its maximum asteroid count ({AsteroidSettings.MaxAsteroidsPerZone}). Skipping further spawning in this zone."); + break; + } + AsteroidType type = AsteroidSettings.GetAsteroidType(newPosition); float size = AsteroidSettings.GetAsteroidSize(newPosition); Quaternion rotation = Quaternion.CreateFromYawPitchRoll((float)rand.NextDouble() * MathHelper.TwoPi, From 759cd2053789fd4b29e8087bcd240cf7ee2f266d Mon Sep 17 00:00:00 2001 From: InvalidArgument3 Date: Mon, 17 Jun 2024 22:26:45 -0500 Subject: [PATCH 4/5] Update AsteroidSpawner.cs --- .../DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs index d97d4de5..42b8f54f 100644 --- a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs +++ b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs @@ -529,6 +529,12 @@ public void SpawnAsteroids(List zones) int asteroidsSpawned = 0; int zoneSpawnAttempts = 0; + if (zone.AsteroidCount >= AsteroidSettings.MaxAsteroidsPerZone) + { + Log.Info($"Zone at {zone.Center} has reached its maximum asteroid count ({AsteroidSettings.MaxAsteroidsPerZone}). Skipping further spawning in this zone."); + continue; + } + bool skipSpawning = false; List players = new List(); MyAPIGateway.Players.GetPlayers(players); From 5e5eec1bc306d3ee6f0c3d9e81c8366a0f32e9b9 Mon Sep 17 00:00:00 2001 From: InvalidArgument3 Date: Mon, 17 Jun 2024 22:28:19 -0500 Subject: [PATCH 5/5] ensure updateasteroids is working, shit --- .../AsteroidEntities/AsteroidSpawner.cs | 99 ++++++++++--------- 1 file changed, 50 insertions(+), 49 deletions(-) diff --git a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs index 42b8f54f..9ae8cff6 100644 --- a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs +++ b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs @@ -360,6 +360,7 @@ public void UpdateTick() } else { + UpdateAsteroids(playerZones.Values.ToList()); ProcessAsteroidUpdates(); _updateIntervalTimer = AsteroidSettings.UpdateInterval; } @@ -395,6 +396,55 @@ public void UpdateTick() } } + private void UpdateAsteroids(List zones) + { + Log.Info($"Updating asteroids. Total asteroids: {_asteroids.Count}, Total zones: {zones.Count}"); + int removedCount = 0; + + foreach (var asteroid in _asteroids.ToArray()) + { + bool inAnyZone = false; + AsteroidZone currentZone = null; + + foreach (var zone in zones) + { + if (zone.IsPointInZone(asteroid.PositionComp.GetPosition())) + { + inAnyZone = true; + currentZone = zone; + break; + } + } + + if (!inAnyZone) + { + Log.Info($"Removing asteroid at {asteroid.PositionComp.GetPosition()} due to distance from all player zones"); + RemoveAsteroid(asteroid); + removedCount++; + } + else if (currentZone != null) + { + foreach (var zone in zones) + { + if (zone != currentZone && zone.IsPointInZone(asteroid.PositionComp.GetPosition())) + { + zone.AsteroidCount--; + } + } + currentZone.AsteroidCount++; + } + + // Add to gravity check queue + gravityCheckQueue.Enqueue(asteroid); + } + + Log.Info($"Update complete. Removed asteroids: {removedCount}, Remaining asteroids: {_asteroids.Count}"); + foreach (var zone in zones) + { + Log.Info($"Zone center: {zone.Center}, Radius: {zone.Radius}, Asteroid count: {zone.AsteroidCount}"); + } + } + private void ProcessAsteroidUpdates() { int updatesProcessed = 0; @@ -458,55 +508,6 @@ private void ProcessGravityCheckQueue() } } - private void UpdateAsteroids(List zones) - { - Log.Info($"Updating asteroids. Total asteroids: {_asteroids.Count}, Total zones: {zones.Count}"); - int removedCount = 0; - - foreach (var asteroid in _asteroids.ToArray()) - { - bool inAnyZone = false; - AsteroidZone currentZone = null; - - foreach (var zone in zones) - { - if (zone.IsPointInZone(asteroid.PositionComp.GetPosition())) - { - inAnyZone = true; - currentZone = zone; - break; - } - } - - if (!inAnyZone) - { - Log.Info($"Removing asteroid at {asteroid.PositionComp.GetPosition()} due to distance from all player zones"); - RemoveAsteroid(asteroid); - removedCount++; - } - else if (currentZone != null) - { - foreach (var zone in zones) - { - if (zone != currentZone && zone.IsPointInZone(asteroid.PositionComp.GetPosition())) - { - zone.AsteroidCount--; - } - } - currentZone.AsteroidCount++; - } - - // Add to gravity check queue - gravityCheckQueue.Enqueue(asteroid); - } - - Log.Info($"Update complete. Removed asteroids: {removedCount}, Remaining asteroids: {_asteroids.Count}"); - foreach (var zone in zones) - { - Log.Info($"Zone center: {zone.Center}, Radius: {zone.Radius}, Asteroid count: {zone.AsteroidCount}"); - } - } - public void SpawnAsteroids(List zones) { int totalSpawnAttempts = 0;