From f5920f9c68a98e9a5ed17e9ad61c88eb92acd6a9 Mon Sep 17 00:00:00 2001 From: InvalidArgument3 Date: Wed, 12 Jun 2024 13:32:06 -0500 Subject: [PATCH 01/16] Update AsteroidSettings.cs --- .../Data/Scripts/DynamicAsteroids/AsteroidSettings.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs index 7c3b947c..d72f5963 100644 --- a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs +++ b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs @@ -8,6 +8,8 @@ public static class AsteroidSettings { public static int MaxAsteroidCount = 1000; public static int AsteroidSpawnRadius = 10000; + //TODO: make these velocities only affect a % of asteroids with an option + //note: these are absolutely awful for performance, thousands of moving entities etc. public static int AsteroidVelocityBase = 0; public static double VelocityVariability = 0; public static double AngularVelocityVariability = 0; From 3aa1d79d2423b95f9fe749cb05a33478f9bff636 Mon Sep 17 00:00:00 2001 From: InvalidArgument3 Date: Wed, 12 Jun 2024 16:12:59 -0500 Subject: [PATCH 02/16] persistence toggle --- .../AsteroidEntities/AsteroidSpawner.cs | 4 ++-- .../Data/Scripts/DynamicAsteroids/AsteroidSettings.cs | 2 ++ .../Data/Scripts/DynamicAsteroids/MainSession.cs | 10 ++++++++-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs index d9fc9ad3..68da639b 100644 --- a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs +++ b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs @@ -32,7 +32,7 @@ public void Init(int seed) public void SaveAsteroidState() { - if (!MyAPIGateway.Session.IsServer) + if (!MyAPIGateway.Session.IsServer || !AsteroidSettings.EnablePersistence) // Add check for persistence return; var asteroidStates = _asteroids.Select(asteroid => new AsteroidState @@ -53,7 +53,7 @@ public void SaveAsteroidState() public void LoadAsteroidState() { - if (!MyAPIGateway.Session.IsServer) + if (!MyAPIGateway.Session.IsServer || !AsteroidSettings.EnablePersistence) // Add check for persistence return; _asteroids.Clear(); // Clear existing asteroids to avoid double loading diff --git a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs index d72f5963..9e9bfd29 100644 --- a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs +++ b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs @@ -6,6 +6,8 @@ namespace DynamicAsteroids { public static class AsteroidSettings { + public static bool EnablePersistence = false; // Add this line + public static int MaxAsteroidCount = 1000; public static int AsteroidSpawnRadius = 10000; //TODO: make these velocities only affect a % of asteroids with an option diff --git a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/MainSession.cs b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/MainSession.cs index de0edc10..997f24ea 100644 --- a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/MainSession.cs +++ b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/MainSession.cs @@ -35,7 +35,10 @@ public override void LoadData() AsteroidSettings.Seed = seed; Rand = new Random(seed); _spawner.Init(seed); - _spawner.LoadAsteroidState(); // Load asteroid states + if (AsteroidSettings.EnablePersistence) // Add this line + { + _spawner.LoadAsteroidState(); // Load asteroid states + } } MyAPIGateway.Multiplayer.RegisterMessageHandler(32000, OnMessageReceived); @@ -53,7 +56,10 @@ protected override void UnloadData() Log.Info("Unloading data in MainSession"); if (MyAPIGateway.Session.IsServer) { - _spawner.SaveAsteroidState(); // Save asteroid states + if (AsteroidSettings.EnablePersistence) // Add this line + { + _spawner.SaveAsteroidState(); // Save asteroid states + } _spawner.Close(); } From 07b429e6f37a5815eab8fd2f8c5d337d0f8324e1 Mon Sep 17 00:00:00 2001 From: InvalidArgument3 Date: Wed, 12 Jun 2024 16:50:33 -0500 Subject: [PATCH 03/16] disable the mmb debug spawn asteroid. attempting to make persistence better and entityid based --- .../AsteroidEntities/AsteroidEntity.cs | 1 + .../AsteroidEntities/AsteroidSpawner.cs | 56 ++++++++++++------- .../DynamicAsteroids/AsteroidSettings.cs | 2 +- .../Scripts/DynamicAsteroids/AsteroidState.cs | 23 ++++---- .../Scripts/DynamicAsteroids/MainSession.cs | 16 +++--- 5 files changed, 57 insertions(+), 41 deletions(-) diff --git a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidEntity.cs b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidEntity.cs index d0dbb168..e3086951 100644 --- a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidEntity.cs +++ b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidEntity.cs @@ -84,6 +84,7 @@ public static AsteroidEntity CreateAsteroid(Vector3D position, float size, Vecto { var ent = new AsteroidEntity(); ent.Init(position, size, initialVelocity, type); + ent.EntityId = ent.EntityId; // EntityId is already assigned by the game return ent; } diff --git a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs index 68da639b..9c07a939 100644 --- a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs +++ b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs @@ -32,17 +32,18 @@ public void Init(int seed) public void SaveAsteroidState() { - if (!MyAPIGateway.Session.IsServer || !AsteroidSettings.EnablePersistence) // Add check for persistence + if (!MyAPIGateway.Session.IsServer || !AsteroidSettings.EnablePersistence) return; var asteroidStates = _asteroids.Select(asteroid => new AsteroidState { Position = asteroid.PositionComp.GetPosition(), Size = asteroid.Size, - Type = asteroid.Type + Type = asteroid.Type, + EntityId = asteroid.EntityId // Save unique ID }).ToList(); - asteroidStates.AddRange(_despawnedAsteroids); // Include despawned asteroids + asteroidStates.AddRange(_despawnedAsteroids); var stateBytes = MyAPIGateway.Utilities.SerializeToBinary(asteroidStates); using (var writer = MyAPIGateway.Utilities.WriteBinaryFileInLocalStorage("asteroid_states.dat", typeof(AsteroidSpawner))) @@ -53,10 +54,10 @@ public void SaveAsteroidState() public void LoadAsteroidState() { - if (!MyAPIGateway.Session.IsServer || !AsteroidSettings.EnablePersistence) // Add check for persistence + if (!MyAPIGateway.Session.IsServer || !AsteroidSettings.EnablePersistence) return; - _asteroids.Clear(); // Clear existing asteroids to avoid double loading + _asteroids.Clear(); if (MyAPIGateway.Utilities.FileExistsInLocalStorage("asteroid_states.dat", typeof(AsteroidSpawner))) { @@ -70,9 +71,16 @@ public void LoadAsteroidState() foreach (var state in asteroidStates) { + if (_asteroids.Any(a => a.EntityId == state.EntityId)) + { + Log.Info($"Skipping duplicate asteroid with ID {state.EntityId}"); + continue; // Skip duplicates + } + var asteroid = AsteroidEntity.CreateAsteroid(state.Position, state.Size, Vector3D.Zero, state.Type); + asteroid.EntityId = state.EntityId; // Assign the saved ID _asteroids.Add(asteroid); - MyEntities.Add(asteroid); // Ensure the asteroid is added to the game world + MyEntities.Add(asteroid); } } } @@ -86,15 +94,17 @@ private void LoadAsteroidsInRange(Vector3D playerPosition) if (distanceSquared < AsteroidSettings.AsteroidSpawnRadius * AsteroidSettings.AsteroidSpawnRadius) { bool tooClose = _asteroids.Any(a => Vector3D.DistanceSquared(a.PositionComp.GetPosition(), state.Position) < AsteroidSettings.MinDistanceFromPlayer * AsteroidSettings.MinDistanceFromPlayer); + bool exists = _asteroids.Any(a => a.EntityId == state.EntityId); // Check for existing IDs - if (tooClose) + if (tooClose || exists) { - Log.Info($"Skipping respawn of asteroid at {state.Position} due to proximity to other asteroids"); + Log.Info($"Skipping respawn of asteroid at {state.Position} due to proximity to other asteroids or duplicate ID"); continue; } Log.Info($"Respawning asteroid at {state.Position} due to player re-entering range"); var asteroid = AsteroidEntity.CreateAsteroid(state.Position, state.Size, Vector3D.Zero, state.Type); + asteroid.EntityId = state.EntityId; // Assign the saved ID _asteroids.Add(asteroid); var message = new AsteroidNetworkMessage(state.Position, state.Size, Vector3D.Zero, Vector3D.Zero, state.Type, false, asteroid.EntityId, false, true); @@ -210,20 +220,24 @@ public void UpdateTick() private void RemoveAsteroid(AsteroidEntity asteroid) { - _despawnedAsteroids.Add(new AsteroidState + if (_asteroids.Any(a => a.EntityId == asteroid.EntityId)) { - Position = asteroid.PositionComp.GetPosition(), - Size = asteroid.Size, - Type = asteroid.Type - }); - - var removalMessage = new AsteroidNetworkMessage(asteroid.PositionComp.GetPosition(), asteroid.Size, Vector3D.Zero, Vector3D.Zero, asteroid.Type, false, asteroid.EntityId, true, false); - var removalMessageBytes = MyAPIGateway.Utilities.SerializeToBinary(removalMessage); - MyAPIGateway.Multiplayer.SendMessageToOthers(32000, removalMessageBytes); - - _asteroids.Remove(asteroid); - asteroid.Close(); - MyEntities.Remove(asteroid); + _despawnedAsteroids.Add(new AsteroidState + { + Position = asteroid.PositionComp.GetPosition(), + Size = asteroid.Size, + Type = asteroid.Type, + EntityId = asteroid.EntityId + }); + + var removalMessage = new AsteroidNetworkMessage(asteroid.PositionComp.GetPosition(), asteroid.Size, Vector3D.Zero, Vector3D.Zero, asteroid.Type, false, asteroid.EntityId, true, false); + var removalMessageBytes = MyAPIGateway.Utilities.SerializeToBinary(removalMessage); + MyAPIGateway.Multiplayer.SendMessageToOthers(32000, removalMessageBytes); + + _asteroids.Remove(asteroid); + asteroid.Close(); + MyEntities.Remove(asteroid); + } } private bool IsNearVanillaAsteroid(Vector3D position) diff --git a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs index 9e9bfd29..179045c9 100644 --- a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs +++ b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs @@ -6,7 +6,7 @@ namespace DynamicAsteroids { public static class AsteroidSettings { - public static bool EnablePersistence = false; // Add this line + public static bool EnablePersistence = true; // Add this line public static int MaxAsteroidCount = 1000; public static int AsteroidSpawnRadius = 10000; diff --git a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidState.cs b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidState.cs index 3483a186..5070f3bb 100644 --- a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidState.cs +++ b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidState.cs @@ -7,17 +7,18 @@ using System.Threading.Tasks; using VRageMath; - [ProtoContract] - public class AsteroidState - { - [ProtoMember(1)] - public Vector3D Position { get; set; } +[ProtoContract] +public class AsteroidState +{ + [ProtoMember(1)] + public Vector3D Position { get; set; } - [ProtoMember(2)] - public float Size { get; set; } - - [ProtoMember(3)] - public AsteroidType Type { get; set; } - } + [ProtoMember(2)] + public float Size { get; set; } + [ProtoMember(3)] + public AsteroidType Type { get; set; } + [ProtoMember(4)] + public long EntityId { get; set; } // Unique ID for each asteroid +} \ No newline at end of file diff --git a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/MainSession.cs b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/MainSession.cs index 997f24ea..e57f7641 100644 --- a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/MainSession.cs +++ b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/MainSession.cs @@ -109,14 +109,14 @@ public override void UpdateAfterSimulation() } } - if (MyAPIGateway.Input.IsNewKeyPressed(MyKeys.MiddleButton)) - { - var position = MyAPIGateway.Session.Player?.GetPosition() ?? Vector3D.Zero; - var velocity = MyAPIGateway.Session.Player?.Character?.Physics?.LinearVelocity ?? Vector3D.Zero; - AsteroidType type = DetermineAsteroidType(); // Determine the type of asteroid - AsteroidEntity.CreateAsteroid(position, Rand.Next(50), velocity, type); - Log.Info($"Asteroid created at {position} with velocity {velocity}"); - } + //if (MyAPIGateway.Input.IsNewKeyPressed(MyKeys.MiddleButton)) + //{ + // var position = MyAPIGateway.Session.Player?.GetPosition() ?? Vector3D.Zero; + // var velocity = MyAPIGateway.Session.Player?.Character?.Physics?.LinearVelocity ?? Vector3D.Zero; + // AsteroidType type = DetermineAsteroidType(); // Determine the type of asteroid + // AsteroidEntity.CreateAsteroid(position, Rand.Next(50), velocity, type); + // Log.Info($"Asteroid created at {position} with velocity {velocity}"); + //} } catch (Exception ex) { From f44af7de3ee14f460b6b69b34b5d96780559be60 Mon Sep 17 00:00:00 2001 From: InvalidArgument3 Date: Wed, 12 Jun 2024 17:02:41 -0500 Subject: [PATCH 04/16] remove excess asteroids --- .../AsteroidEntities/AsteroidSpawner.cs | 31 ++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs index 9c07a939..bdbfd4e3 100644 --- a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs +++ b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs @@ -59,6 +59,14 @@ public void LoadAsteroidState() _asteroids.Clear(); + // Clear existing untracked asteroids + var existingAsteroids = MyEntities.GetEntities().OfType().ToList(); + foreach (var existingAsteroid in existingAsteroids) + { + existingAsteroid.Close(); + MyEntities.Remove(existingAsteroid); + } + if (MyAPIGateway.Utilities.FileExistsInLocalStorage("asteroid_states.dat", typeof(AsteroidSpawner))) { byte[] stateBytes; @@ -116,6 +124,24 @@ private void LoadAsteroidsInRange(Vector3D playerPosition) } } + private void RemoveExcessAsteroids(Vector3D playerPosition) + { + if (_asteroids.Count <= AsteroidSettings.MaxAsteroidCount) + return; + + // Sort asteroids by distance from the player + var sortedAsteroids = _asteroids.OrderByDescending(a => Vector3D.DistanceSquared(a.PositionComp.GetPosition(), playerPosition)).ToList(); + + // Remove the furthest asteroids until we are within the limit + while (_asteroids.Count > AsteroidSettings.MaxAsteroidCount) + { + var asteroid = sortedAsteroids.First(); + Log.Info($"Removing excess asteroid at {asteroid.PositionComp.GetPosition()} to maintain the limit"); + RemoveAsteroid(asteroid); + sortedAsteroids.RemoveAt(0); + } + } + public void Close() { if (!MyAPIGateway.Session.IsServer) @@ -209,6 +235,9 @@ public void UpdateTick() MyAPIGateway.Multiplayer.SendMessageToOthers(32000, messageBytes); } + // Ensure the asteroid count does not exceed the maximum limit + RemoveExcessAsteroids(playerPosition); + MyAPIGateway.Utilities.ShowNotification($"Active Asteroids: {_asteroids.Count}", 1000 / 60); } } @@ -220,7 +249,7 @@ public void UpdateTick() private void RemoveAsteroid(AsteroidEntity asteroid) { - if (_asteroids.Any(a => a.EntityId == asteroid.EntityId)) + if (_asteroids.Contains(asteroid)) { _despawnedAsteroids.Add(new AsteroidState { From a8ca0258a850d3b80d36f6955f9d6beb70d2cfd2 Mon Sep 17 00:00:00 2001 From: InvalidArgument3 Date: Wed, 12 Jun 2024 17:02:46 -0500 Subject: [PATCH 05/16] Revert "remove excess asteroids" This reverts commit f44af7de3ee14f460b6b69b34b5d96780559be60. --- .../AsteroidEntities/AsteroidSpawner.cs | 31 +------------------ 1 file changed, 1 insertion(+), 30 deletions(-) diff --git a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs index bdbfd4e3..9c07a939 100644 --- a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs +++ b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs @@ -59,14 +59,6 @@ public void LoadAsteroidState() _asteroids.Clear(); - // Clear existing untracked asteroids - var existingAsteroids = MyEntities.GetEntities().OfType().ToList(); - foreach (var existingAsteroid in existingAsteroids) - { - existingAsteroid.Close(); - MyEntities.Remove(existingAsteroid); - } - if (MyAPIGateway.Utilities.FileExistsInLocalStorage("asteroid_states.dat", typeof(AsteroidSpawner))) { byte[] stateBytes; @@ -124,24 +116,6 @@ private void LoadAsteroidsInRange(Vector3D playerPosition) } } - private void RemoveExcessAsteroids(Vector3D playerPosition) - { - if (_asteroids.Count <= AsteroidSettings.MaxAsteroidCount) - return; - - // Sort asteroids by distance from the player - var sortedAsteroids = _asteroids.OrderByDescending(a => Vector3D.DistanceSquared(a.PositionComp.GetPosition(), playerPosition)).ToList(); - - // Remove the furthest asteroids until we are within the limit - while (_asteroids.Count > AsteroidSettings.MaxAsteroidCount) - { - var asteroid = sortedAsteroids.First(); - Log.Info($"Removing excess asteroid at {asteroid.PositionComp.GetPosition()} to maintain the limit"); - RemoveAsteroid(asteroid); - sortedAsteroids.RemoveAt(0); - } - } - public void Close() { if (!MyAPIGateway.Session.IsServer) @@ -235,9 +209,6 @@ public void UpdateTick() MyAPIGateway.Multiplayer.SendMessageToOthers(32000, messageBytes); } - // Ensure the asteroid count does not exceed the maximum limit - RemoveExcessAsteroids(playerPosition); - MyAPIGateway.Utilities.ShowNotification($"Active Asteroids: {_asteroids.Count}", 1000 / 60); } } @@ -249,7 +220,7 @@ public void UpdateTick() private void RemoveAsteroid(AsteroidEntity asteroid) { - if (_asteroids.Contains(asteroid)) + if (_asteroids.Any(a => a.EntityId == asteroid.EntityId)) { _despawnedAsteroids.Add(new AsteroidState { From 4ec113f27e654f2911076b99cbece2a0d35a31a5 Mon Sep 17 00:00:00 2001 From: InvalidArgument3 Date: Wed, 12 Jun 2024 17:10:45 -0500 Subject: [PATCH 06/16] per-session """persistence""" is good enough honestly --- .../Data/Scripts/DynamicAsteroids/AsteroidSettings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs index 179045c9..6a10178a 100644 --- a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs +++ b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs @@ -6,7 +6,7 @@ namespace DynamicAsteroids { public static class AsteroidSettings { - public static bool EnablePersistence = true; // Add this line + public static bool EnablePersistence = false; //barely works, don't touch this public static int MaxAsteroidCount = 1000; public static int AsteroidSpawnRadius = 10000; From c955ca59743bb9103dab2a6dec07dc737cac2209 Mon Sep 17 00:00:00 2001 From: InvalidArgument3 Date: Wed, 12 Jun 2024 17:30:58 -0500 Subject: [PATCH 07/16] logger toggle, mmb spawn roid toggle --- .../AsteroidEntities/AsteroidEntity.cs | 10 +++++++++ .../AsteroidEntities/AsteroidSpawner.cs | 3 ++- .../DynamicAsteroids/AsteroidSettings.cs | 3 +++ .../Data/Scripts/DynamicAsteroids/Log.cs | 7 ++++-- .../Scripts/DynamicAsteroids/MainSession.cs | 22 +++++++++++-------- 5 files changed, 33 insertions(+), 12 deletions(-) diff --git a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidEntity.cs b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidEntity.cs index e3086951..4fdb825d 100644 --- a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidEntity.cs +++ b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidEntity.cs @@ -294,6 +294,16 @@ public void OnDestroy() public bool DoDamage(float damage, MyStringHash damageSource, bool sync, MyHitInfo? hitInfo = null, long attackerId = 0, long realHitEntityId = 0, bool shouldDetonateAmmo = true, MyStringHash? extraInfo = null) { + //Disabling explosion damage is an awful way to fix this weird rocket bug, but it's okay we'll be using weaponcore :) + var explosionDamageType = MyStringHash.GetOrCompute("Explosion"); + + // Check if the damage source is explosion + if (damageSource == explosionDamageType) + { + Log.Info($"Ignoring explosion damage for asteroid. Damage source: {damageSource.String}"); + return false; // Ignore the damage + } + _integrity -= damage; Log.Info($"DoDamage called with damage: {damage}, damageSource: {damageSource.String}, attackerId: {attackerId}, realHitEntityId: {realHitEntityId}, new integrity: {_integrity}"); diff --git a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs index 9c07a939..8c0539e1 100644 --- a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs +++ b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs @@ -209,7 +209,8 @@ public void UpdateTick() MyAPIGateway.Multiplayer.SendMessageToOthers(32000, messageBytes); } - MyAPIGateway.Utilities.ShowNotification($"Active Asteroids: {_asteroids.Count}", 1000 / 60); + if (AsteroidSettings.EnableLogging) + MyAPIGateway.Utilities.ShowNotification($"Active Asteroids: {_asteroids.Count}", 1000 / 60); } } catch (Exception ex) diff --git a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs index 6a10178a..7c7db7cd 100644 --- a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs +++ b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs @@ -6,7 +6,10 @@ namespace DynamicAsteroids { public static class AsteroidSettings { + public static bool EnableLogging = false; public static bool EnablePersistence = false; //barely works, don't touch this + public static bool EnableMiddleMouseAsteroidSpawn = false; //debug + public static int MaxAsteroidCount = 1000; public static int AsteroidSpawnRadius = 10000; diff --git a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/Log.cs b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/Log.cs index 0c80d6b4..1fbe90fa 100644 --- a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/Log.cs +++ b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/Log.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using DynamicAsteroids; using Sandbox.ModAPI; namespace SC.SUGMA @@ -22,12 +23,14 @@ private Log() public static void Info(string message) { - I._Log(message); + if (AsteroidSettings.EnableLogging) + I._Log(message); } public static void Exception(Exception ex, Type callingType, string prefix = "") { - I._LogException(ex, callingType, prefix); + if (AsteroidSettings.EnableLogging) + I._LogException(ex, callingType, prefix); } public static void Init() diff --git a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/MainSession.cs b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/MainSession.cs index e57f7641..0b0aee8d 100644 --- a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/MainSession.cs +++ b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/MainSession.cs @@ -105,18 +105,22 @@ public override void UpdateAfterSimulation() string rotationString = $"({angularVelocity.X:F2}, {angularVelocity.Y:F2}, {angularVelocity.Z:F2})"; string message = $"Nearest Asteroid: {nearestAsteroid.EntityId} ({nearestAsteroid.Type})\nRotation: {rotationString}"; - MyAPIGateway.Utilities.ShowNotification(message, 1000 / 60); + if (AsteroidSettings.EnableLogging) + MyAPIGateway.Utilities.ShowNotification(message, 1000 / 60); } } - //if (MyAPIGateway.Input.IsNewKeyPressed(MyKeys.MiddleButton)) - //{ - // var position = MyAPIGateway.Session.Player?.GetPosition() ?? Vector3D.Zero; - // var velocity = MyAPIGateway.Session.Player?.Character?.Physics?.LinearVelocity ?? Vector3D.Zero; - // AsteroidType type = DetermineAsteroidType(); // Determine the type of asteroid - // AsteroidEntity.CreateAsteroid(position, Rand.Next(50), velocity, type); - // Log.Info($"Asteroid created at {position} with velocity {velocity}"); - //} + if (AsteroidSettings.EnableMiddleMouseAsteroidSpawn && MyAPIGateway.Input.IsNewKeyPressed(MyKeys.MiddleButton)) + { + if (MyAPIGateway.Session != null) + { + var position = MyAPIGateway.Session.Player?.GetPosition() ?? Vector3D.Zero; + var velocity = MyAPIGateway.Session.Player?.Character?.Physics?.LinearVelocity ?? Vector3D.Zero; + AsteroidType type = DetermineAsteroidType(); // Determine the type of asteroid + AsteroidEntity.CreateAsteroid(position, Rand.Next(50), velocity, type); + Log.Info($"Asteroid created at {position} with velocity {velocity}"); + } + } } catch (Exception ex) { From e5509640e6233b7ff11ef38a4b7259ee63a84d0e Mon Sep 17 00:00:00 2001 From: InvalidArgument3 Date: Wed, 12 Jun 2024 18:06:33 -0500 Subject: [PATCH 08/16] config options for spawning rate, but distribution fucked up somehow?? --- .../AsteroidEntities/AsteroidSpawner.cs | 160 ++++++++++++------ .../DynamicAsteroids/AsteroidSettings.cs | 24 +-- .../Scripts/DynamicAsteroids/MainSession.cs | 67 +++++--- 3 files changed, 163 insertions(+), 88 deletions(-) diff --git a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs index 8c0539e1..1be42edd 100644 --- a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs +++ b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs @@ -17,6 +17,8 @@ public class AsteroidSpawner private DateTime _worldLoadTime; private Random rand; private List _despawnedAsteroids = new List(); + private List _networkMessages = new List(); + public void Init(int seed) { @@ -126,6 +128,9 @@ public void Close() _asteroids?.Clear(); } + private int _spawnIntervalTimer = 0; + private int _updateIntervalTimer = 0; + public void UpdateTick() { if (!MyAPIGateway.Session.IsServer) @@ -150,65 +155,31 @@ public void UpdateTick() { Vector3D playerPosition = player.GetPosition(); - // Load asteroids in range - LoadAsteroidsInRange(playerPosition); - - foreach (var asteroid in _asteroids.ToArray()) + // Update asteroids at a slower interval + if (_updateIntervalTimer > 0) { - double distanceSquared = Vector3D.DistanceSquared(asteroid.PositionComp.GetPosition(), playerPosition); - - // Remove asteroids that are outside the spherical spawn radius - if (distanceSquared > AsteroidSettings.AsteroidSpawnRadius * AsteroidSettings.AsteroidSpawnRadius) - { - Log.Info($"Removing asteroid at {asteroid.PositionComp.GetPosition()} due to distance from player"); - RemoveAsteroid(asteroid); - } + _updateIntervalTimer--; + } + else + { + UpdateAsteroids(playerPosition); + _updateIntervalTimer = AsteroidSettings.UpdateInterval; // Use setting } - int asteroidsSpawned = 0; - int spawnAttempts = 0; - int maxAttempts = 50; // Limit the number of attempts to find valid positions - - while (_asteroids.Count < AsteroidSettings.MaxAsteroidCount && asteroidsSpawned < 10) + // Spawn asteroids at a slower interval + if (_spawnIntervalTimer > 0) + { + _spawnIntervalTimer--; + } + else { - if (spawnAttempts >= maxAttempts) - { - Log.Info("Reached maximum spawn attempts, breaking out of loop to prevent freeze"); - break; - } - - Vector3D newPosition; - do - { - newPosition = playerPosition + RandVector() * AsteroidSettings.AsteroidSpawnRadius; - spawnAttempts++; - } while (Vector3D.DistanceSquared(newPosition, playerPosition) < AsteroidSettings.MinDistanceFromPlayer * AsteroidSettings.MinDistanceFromPlayer && spawnAttempts < maxAttempts); - - if (spawnAttempts >= maxAttempts) - break; - - Vector3D newVelocity; - if (!AsteroidSettings.CanSpawnAsteroidAtPoint(newPosition, out newVelocity)) - continue; - - if (IsNearVanillaAsteroid(newPosition)) - { - Log.Info("Skipped spawning asteroid due to proximity to vanilla asteroid."); - continue; - } - - AsteroidType type = AsteroidSettings.GetAsteroidType(newPosition); - float size = AsteroidSettings.GetAsteroidSize(newPosition); - - Log.Info($"Spawning asteroid at {newPosition} with velocity {newVelocity} of type {type}"); - var asteroid = AsteroidEntity.CreateAsteroid(newPosition, size, newVelocity, type); - _asteroids.Add(asteroid); - - var message = new AsteroidNetworkMessage(newPosition, size, newVelocity, Vector3D.Zero, type, false, asteroid.EntityId, false, true); - var messageBytes = MyAPIGateway.Utilities.SerializeToBinary(message); - MyAPIGateway.Multiplayer.SendMessageToOthers(32000, messageBytes); + SpawnAsteroids(playerPosition); + _spawnIntervalTimer = AsteroidSettings.SpawnInterval; // Use setting } + // Load asteroids in range + LoadAsteroidsInRange(playerPosition); + if (AsteroidSettings.EnableLogging) MyAPIGateway.Utilities.ShowNotification($"Active Asteroids: {_asteroids.Count}", 1000 / 60); } @@ -219,6 +190,89 @@ public void UpdateTick() } } + private void UpdateAsteroids(Vector3D playerPosition) + { + foreach (var asteroid in _asteroids.ToArray()) + { + double distanceSquared = Vector3D.DistanceSquared(asteroid.PositionComp.GetPosition(), playerPosition); + + // Remove asteroids that are outside the spherical spawn radius + if (distanceSquared > AsteroidSettings.AsteroidSpawnRadius * AsteroidSettings.AsteroidSpawnRadius) + { + Log.Info($"Removing asteroid at {asteroid.PositionComp.GetPosition()} due to distance from player"); + RemoveAsteroid(asteroid); + } + } + } + + private void SpawnAsteroids(Vector3D playerPosition) + { + int asteroidsSpawned = 0; + int spawnAttempts = 0; + int maxAttempts = 50; // Limit the number of attempts to find valid positions + + while (_asteroids.Count < AsteroidSettings.MaxAsteroidCount && asteroidsSpawned < 10) + { + if (spawnAttempts >= maxAttempts) + { + Log.Info("Reached maximum spawn attempts, breaking out of loop to prevent freeze"); + break; + } + + Vector3D newPosition; + do + { + newPosition = playerPosition + RandVector() * AsteroidSettings.AsteroidSpawnRadius; + spawnAttempts++; + } while (Vector3D.DistanceSquared(newPosition, playerPosition) < AsteroidSettings.MinDistanceFromPlayer * AsteroidSettings.MinDistanceFromPlayer && spawnAttempts < maxAttempts); + + if (spawnAttempts >= maxAttempts) + break; + + Vector3D newVelocity; + if (!AsteroidSettings.CanSpawnAsteroidAtPoint(newPosition, out newVelocity)) + continue; + + if (IsNearVanillaAsteroid(newPosition)) + { + Log.Info("Skipped spawning asteroid due to proximity to vanilla asteroid."); + continue; + } + + AsteroidType type = AsteroidSettings.GetAsteroidType(newPosition); + float size = AsteroidSettings.GetAsteroidSize(newPosition); + + Log.Info($"Spawning asteroid at {newPosition} with velocity {newVelocity} of type {type}"); + var asteroid = AsteroidEntity.CreateAsteroid(newPosition, size, newVelocity, type); + _asteroids.Add(asteroid); + + var message = new AsteroidNetworkMessage(newPosition, size, newVelocity, Vector3D.Zero, type, false, asteroid.EntityId, false, true); + _networkMessages.Add(message); // Add to the list instead of sending immediately + + asteroidsSpawned++; + } + } + + public void SendNetworkMessages() + { + if (_networkMessages.Count == 0) + return; + + try + { + var messageBytes = MyAPIGateway.Utilities.SerializeToBinary(_networkMessages); + MyAPIGateway.Multiplayer.SendMessageToOthers(32000, messageBytes); + + // Clear the list after sending + _networkMessages.Clear(); + } + catch (Exception ex) + { + Log.Exception(ex, typeof(AsteroidSpawner), "Failed to send network messages"); + } + } + + private void RemoveAsteroid(AsteroidEntity asteroid) { if (_asteroids.Any(a => a.EntityId == asteroid.EntityId)) diff --git a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs index 7c7db7cd..730bbbfa 100644 --- a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs +++ b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs @@ -6,10 +6,14 @@ namespace DynamicAsteroids { public static class AsteroidSettings { - public static bool EnableLogging = false; + public static bool EnableLogging = true; public static bool EnablePersistence = false; //barely works, don't touch this public static bool EnableMiddleMouseAsteroidSpawn = false; //debug + public static int SaveStateInterval = 600; // Default: 600 ticks (10 seconds) + public static int NetworkMessageInterval = 120; // Default: 120 ticks (2 seconds) + public static int SpawnInterval = 1; // Default: 600 ticks (10 seconds) + public static int UpdateInterval = 120; // Default: 120 ticks (2 seconds) public static int MaxAsteroidCount = 1000; public static int AsteroidSpawnRadius = 10000; @@ -59,15 +63,15 @@ public static class AsteroidSettings public static SpawnableArea[] ValidSpawnLocations = { - new SpawnableArea - { - CenterPosition = new Vector3D(148001024.50, 1024.50, 1024.50), - Normal = new Vector3D(1, 10, 0.5).Normalized(), - Radius = 60268000 * 2.5, - InnerRadius = 60268000 * 1.2, - HeightFromCenter = 1000, - } - }; + new SpawnableArea + { + CenterPosition = new Vector3D(148001024.50, 1024.50, 1024.50), + Normal = new Vector3D(1, 10, 0.5).Normalized(), + Radius = 60268000 * 2.5, + InnerRadius = 60268000 * 1.2, + HeightFromCenter = 1000, + } +}; public static bool CanSpawnAsteroidAtPoint(Vector3D point, out Vector3D velocity) { diff --git a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/MainSession.cs b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/MainSession.cs index 0b0aee8d..db735b8b 100644 --- a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/MainSession.cs +++ b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/MainSession.cs @@ -20,6 +20,8 @@ public class MainSession : MySessionComponentBase private int seed; public AsteroidSpawner _spawner = new AsteroidSpawner(); private int _saveStateTimer; + private int _networkMessageTimer; + public override void LoadData() { @@ -90,7 +92,18 @@ public override void UpdateAfterSimulation() else { _spawner.SaveAsteroidState(); - _saveStateTimer = 600; // Set to save every 10 seconds (600 ticks) + _saveStateTimer = AsteroidSettings.SaveStateInterval; // Use setting + } + + // Batch and delay network messages + if (_networkMessageTimer > 0) + { + _networkMessageTimer--; + } + else + { + _spawner.SendNetworkMessages(); + _networkMessageTimer = AsteroidSettings.NetworkMessageInterval; // Use setting } } @@ -132,39 +145,43 @@ private void OnMessageReceived(byte[] message) { try { - var asteroidMessage = MyAPIGateway.Utilities.SerializeFromBinary(message); - Log.Info($"Client: Received message to create/remove asteroid at {asteroidMessage.Position} with velocity {asteroidMessage.InitialVelocity} of type {asteroidMessage.Type}"); + var asteroidMessages = MyAPIGateway.Utilities.SerializeFromBinary>(message); - if (asteroidMessage.IsRemoval) - { - // Find and remove the asteroid with the given EntityId - var asteroid = MyEntities.GetEntityById(asteroidMessage.EntityId) as AsteroidEntity; - if (asteroid != null) - { - asteroid.Close(); - } - } - else if (asteroidMessage.IsInitialCreation) + foreach (var asteroidMessage in asteroidMessages) { - var asteroid = AsteroidEntity.CreateAsteroid(asteroidMessage.Position, asteroidMessage.Size, asteroidMessage.InitialVelocity, asteroidMessage.Type); - asteroid.Physics.AngularVelocity = asteroidMessage.AngularVelocity; - MyEntities.Add(asteroid); - } - else - { - if (asteroidMessage.IsSubChunk) + Log.Info($"Client: Received message to create/remove asteroid at {asteroidMessage.Position} with velocity {asteroidMessage.InitialVelocity} of type {asteroidMessage.Type}"); + + if (asteroidMessage.IsRemoval) { - // Create the sub-chunk asteroid on the client - var subChunk = AsteroidEntity.CreateAsteroid(asteroidMessage.Position, asteroidMessage.Size, asteroidMessage.InitialVelocity, asteroidMessage.Type); - subChunk.Physics.AngularVelocity = asteroidMessage.AngularVelocity; + // Find and remove the asteroid with the given EntityId + var asteroid = MyEntities.GetEntityById(asteroidMessage.EntityId) as AsteroidEntity; + if (asteroid != null) + { + asteroid.Close(); + } } - else + else if (asteroidMessage.IsInitialCreation) { - // Create the regular asteroid on the client var asteroid = AsteroidEntity.CreateAsteroid(asteroidMessage.Position, asteroidMessage.Size, asteroidMessage.InitialVelocity, asteroidMessage.Type); asteroid.Physics.AngularVelocity = asteroidMessage.AngularVelocity; MyEntities.Add(asteroid); } + else + { + if (asteroidMessage.IsSubChunk) + { + // Create the sub-chunk asteroid on the client + var subChunk = AsteroidEntity.CreateAsteroid(asteroidMessage.Position, asteroidMessage.Size, asteroidMessage.InitialVelocity, asteroidMessage.Type); + subChunk.Physics.AngularVelocity = asteroidMessage.AngularVelocity; + } + else + { + // Create the regular asteroid on the client + var asteroid = AsteroidEntity.CreateAsteroid(asteroidMessage.Position, asteroidMessage.Size, asteroidMessage.InitialVelocity, asteroidMessage.Type); + asteroid.Physics.AngularVelocity = asteroidMessage.AngularVelocity; + MyEntities.Add(asteroid); + } + } } } catch (Exception ex) From a4ad70d61850f15033f720a1f3572389acd672b0 Mon Sep 17 00:00:00 2001 From: InvalidArgument3 Date: Wed, 12 Jun 2024 18:26:31 -0500 Subject: [PATCH 09/16] fixed distribution not being diverse --- .../Data/Scripts/DynamicAsteroids/AsteroidSettings.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs index 730bbbfa..7268b5c7 100644 --- a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs +++ b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs @@ -96,14 +96,18 @@ public static bool PlayerCanSeeRings(Vector3D point) return false; } + private static Random rand = new Random(Seed); + public static AsteroidType GetAsteroidType(Vector3D position) { - Random rand = new Random(Seed + position.GetHashCode()); + // Calculate the total weight + double totalWeight = IceWeight + StoneWeight + IronWeight + NickelWeight + CobaltWeight + + MagnesiumWeight + SiliconWeight + SilverWeight + GoldWeight + PlatinumWeight + UraniniteWeight; - double totalWeight = IceWeight + StoneWeight + IronWeight + NickelWeight + CobaltWeight + MagnesiumWeight + - SiliconWeight + SilverWeight + GoldWeight + PlatinumWeight + UraniniteWeight; + // Generate a random value between 0 and totalWeight double randomValue = rand.NextDouble() * totalWeight; + // Determine the asteroid type based on the random value and weights if (randomValue < IceWeight) return AsteroidType.Ice; randomValue -= IceWeight; if (randomValue < StoneWeight) return AsteroidType.Stone; @@ -125,7 +129,6 @@ public static AsteroidType GetAsteroidType(Vector3D position) if (randomValue < PlatinumWeight) return AsteroidType.Platinum; return AsteroidType.Uraninite; } - public static float GetAsteroidSize(Vector3D position) { Random rand = new Random(Seed + position.GetHashCode()); From 13b14f94aa3a631c4e2dbc84e9e807fd514ddb29 Mon Sep 17 00:00:00 2001 From: InvalidArgument3 Date: Wed, 12 Jun 2024 18:28:02 -0500 Subject: [PATCH 10/16] Update AsteroidSettings.cs --- .../Data/Scripts/DynamicAsteroids/AsteroidSettings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs index 7268b5c7..2dbf611c 100644 --- a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs +++ b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs @@ -12,7 +12,7 @@ public static class AsteroidSettings public static int SaveStateInterval = 600; // Default: 600 ticks (10 seconds) public static int NetworkMessageInterval = 120; // Default: 120 ticks (2 seconds) - public static int SpawnInterval = 1; // Default: 600 ticks (10 seconds) + public static int SpawnInterval = 6; // Default: 600 ticks (10 seconds) public static int UpdateInterval = 120; // Default: 120 ticks (2 seconds) public static int MaxAsteroidCount = 1000; From 43dff29fb85a92d1b9a9d4b21746358ad09ecac3 Mon Sep 17 00:00:00 2001 From: InvalidArgument3 Date: Wed, 12 Jun 2024 19:29:51 -0500 Subject: [PATCH 11/16] add "better" logging --- .../AsteroidEntities/AsteroidEntity.cs | 1 + .../AsteroidEntities/AsteroidSpawner.cs | 11 +- .../AsteroidNetworkMessage.cs | 8 + .../Scripts/DynamicAsteroids/MainSession.cs | 11 +- Dynamic Asteroids/Data/newfile.txt | 637 ++++++++++++------ 5 files changed, 472 insertions(+), 196 deletions(-) diff --git a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidEntity.cs b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidEntity.cs index 4fdb825d..3464a09a 100644 --- a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidEntity.cs +++ b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidEntity.cs @@ -153,6 +153,7 @@ private void Init(Vector3D position, float size, Vector3D initialVelocity, Aster WorldMatrix.Orthogonalize(); // Normalize the matrix to prevent rotation spazzing MyEntities.Add(this); + Log.Info($"{(MyAPIGateway.Session.IsServer ? "Server" : "Client")}: Added asteroid entity with ID {EntityId} to MyEntities"); CreatePhysics(); Physics.LinearVelocity = initialVelocity + RandVector() * AsteroidSettings.VelocityVariability; diff --git a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs index 1be42edd..9694f566 100644 --- a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs +++ b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSpawner.cs @@ -245,6 +245,7 @@ private void SpawnAsteroids(Vector3D playerPosition) Log.Info($"Spawning asteroid at {newPosition} with velocity {newVelocity} of type {type}"); var asteroid = AsteroidEntity.CreateAsteroid(newPosition, size, newVelocity, type); _asteroids.Add(asteroid); + Log.Info($"Server: Added new asteroid with ID {asteroid.EntityId} to _asteroids list"); var message = new AsteroidNetworkMessage(newPosition, size, newVelocity, Vector3D.Zero, type, false, asteroid.EntityId, false, true); _networkMessages.Add(message); // Add to the list instead of sending immediately @@ -255,15 +256,14 @@ private void SpawnAsteroids(Vector3D playerPosition) public void SendNetworkMessages() { - if (_networkMessages.Count == 0) - return; - + if (_networkMessages.Count == 0) return; try { + Log.Info($"Server: Preparing to send {_networkMessages.Count} network messages"); var messageBytes = MyAPIGateway.Utilities.SerializeToBinary(_networkMessages); + Log.Info($"Server: Serialized message size: {messageBytes.Length} bytes"); MyAPIGateway.Multiplayer.SendMessageToOthers(32000, messageBytes); - - // Clear the list after sending + Log.Info($"Server: Sent {_networkMessages.Count} network messages"); _networkMessages.Clear(); } catch (Exception ex) @@ -292,6 +292,7 @@ private void RemoveAsteroid(AsteroidEntity asteroid) _asteroids.Remove(asteroid); asteroid.Close(); MyEntities.Remove(asteroid); + Log.Info($"Server: Removed asteroid with ID {asteroid.EntityId} from _asteroids list and MyEntities"); } } diff --git a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidNetworkMessage.cs b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidNetworkMessage.cs index 21ccfb0c..f118fa10 100644 --- a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidNetworkMessage.cs +++ b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidNetworkMessage.cs @@ -1,6 +1,7 @@ using DynamicAsteroids.AsteroidEntities; using VRageMath; using ProtoBuf; +using System.Collections.Generic; namespace DynamicAsteroids { @@ -46,5 +47,12 @@ public AsteroidNetworkMessage(Vector3D position, float size, Vector3D initialVel IsRemoval = isRemoval; IsInitialCreation = isInitialCreation; } + + [ProtoContract] + public class AsteroidNetworkMessageWrapper + { + [ProtoMember(1)] + public List Messages { get; set; } + } } } \ No newline at end of file diff --git a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/MainSession.cs b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/MainSession.cs index db735b8b..15205bc2 100644 --- a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/MainSession.cs +++ b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/MainSession.cs @@ -102,8 +102,9 @@ public override void UpdateAfterSimulation() } else { + Log.Info($"Server: Sending network messages, asteroid count: {_spawner._asteroids.Count}"); _spawner.SendNetworkMessages(); - _networkMessageTimer = AsteroidSettings.NetworkMessageInterval; // Use setting + _networkMessageTimer = AsteroidSettings.NetworkMessageInterval; } } @@ -145,9 +146,9 @@ private void OnMessageReceived(byte[] message) { try { + Log.Info($"Client: Received message of {message.Length} bytes"); var asteroidMessages = MyAPIGateway.Utilities.SerializeFromBinary>(message); - - foreach (var asteroidMessage in asteroidMessages) + Log.Info($"Client: Deserialized {asteroidMessages.Count} asteroid messages"); foreach (var asteroidMessage in asteroidMessages) { Log.Info($"Client: Received message to create/remove asteroid at {asteroidMessage.Position} with velocity {asteroidMessage.InitialVelocity} of type {asteroidMessage.Type}"); @@ -158,6 +159,7 @@ private void OnMessageReceived(byte[] message) if (asteroid != null) { asteroid.Close(); + Log.Info($"Client: Removed asteroid with ID {asteroidMessage.EntityId}"); } } else if (asteroidMessage.IsInitialCreation) @@ -165,6 +167,7 @@ private void OnMessageReceived(byte[] message) var asteroid = AsteroidEntity.CreateAsteroid(asteroidMessage.Position, asteroidMessage.Size, asteroidMessage.InitialVelocity, asteroidMessage.Type); asteroid.Physics.AngularVelocity = asteroidMessage.AngularVelocity; MyEntities.Add(asteroid); + Log.Info($"Client: Created initial asteroid with ID {asteroid.EntityId}"); } else { @@ -173,6 +176,7 @@ private void OnMessageReceived(byte[] message) // Create the sub-chunk asteroid on the client var subChunk = AsteroidEntity.CreateAsteroid(asteroidMessage.Position, asteroidMessage.Size, asteroidMessage.InitialVelocity, asteroidMessage.Type); subChunk.Physics.AngularVelocity = asteroidMessage.AngularVelocity; + Log.Info($"Client: Created sub-chunk asteroid with ID {subChunk.EntityId}"); } else { @@ -180,6 +184,7 @@ private void OnMessageReceived(byte[] message) var asteroid = AsteroidEntity.CreateAsteroid(asteroidMessage.Position, asteroidMessage.Size, asteroidMessage.InitialVelocity, asteroidMessage.Type); asteroid.Physics.AngularVelocity = asteroidMessage.AngularVelocity; MyEntities.Add(asteroid); + Log.Info($"Client: Created asteroid with ID {asteroid.EntityId}"); } } } diff --git a/Dynamic Asteroids/Data/newfile.txt b/Dynamic Asteroids/Data/newfile.txt index b3038e00..a0f87913 100644 --- a/Dynamic Asteroids/Data/newfile.txt +++ b/Dynamic Asteroids/Data/newfile.txt @@ -55,8 +55,19 @@ namespace DynamicAsteroids { public static class AsteroidSettings { + public static bool EnableLogging = true; + public static bool EnablePersistence = false; //barely works, don't touch this + public static bool EnableMiddleMouseAsteroidSpawn = false; //debug + + public static int SaveStateInterval = 600; // Default: 600 ticks (10 seconds) + public static int NetworkMessageInterval = 120; // Default: 120 ticks (2 seconds) + public static int SpawnInterval = 6; // Default: 600 ticks (10 seconds) + public static int UpdateInterval = 120; // Default: 120 ticks (2 seconds) + public static int MaxAsteroidCount = 1000; public static int AsteroidSpawnRadius = 10000; + //TODO: make these velocities only affect a % of asteroids with an option + //note: these are absolutely awful for performance, thousands of moving entities etc. public static int AsteroidVelocityBase = 0; public static double VelocityVariability = 0; public static double AngularVelocityVariability = 0; @@ -101,15 +112,15 @@ namespace DynamicAsteroids public static SpawnableArea[] ValidSpawnLocations = { - new SpawnableArea - { - CenterPosition = new Vector3D(148001024.50, 1024.50, 1024.50), - Normal = new Vector3D(1, 10, 0.5).Normalized(), - Radius = 60268000 * 2.5, - InnerRadius = 60268000 * 1.2, - HeightFromCenter = 1000, - } - }; + new SpawnableArea + { + CenterPosition = new Vector3D(148001024.50, 1024.50, 1024.50), + Normal = new Vector3D(1, 10, 0.5).Normalized(), + Radius = 60268000 * 2.5, + InnerRadius = 60268000 * 1.2, + HeightFromCenter = 1000, + } +}; public static bool CanSpawnAsteroidAtPoint(Vector3D point, out Vector3D velocity) { @@ -134,14 +145,18 @@ namespace DynamicAsteroids return false; } + private static Random rand = new Random(Seed); + public static AsteroidType GetAsteroidType(Vector3D position) { - Random rand = new Random(Seed + position.GetHashCode()); + // Calculate the total weight + double totalWeight = IceWeight + StoneWeight + IronWeight + NickelWeight + CobaltWeight + + MagnesiumWeight + SiliconWeight + SilverWeight + GoldWeight + PlatinumWeight + UraniniteWeight; - double totalWeight = IceWeight + StoneWeight + IronWeight + NickelWeight + CobaltWeight + MagnesiumWeight + - SiliconWeight + SilverWeight + GoldWeight + PlatinumWeight + UraniniteWeight; + // Generate a random value between 0 and totalWeight double randomValue = rand.NextDouble() * totalWeight; + // Determine the asteroid type based on the random value and weights if (randomValue < IceWeight) return AsteroidType.Ice; randomValue -= IceWeight; if (randomValue < StoneWeight) return AsteroidType.Stone; @@ -163,7 +178,6 @@ namespace DynamicAsteroids if (randomValue < PlatinumWeight) return AsteroidType.Platinum; return AsteroidType.Uraninite; } - public static float GetAsteroidSize(Vector3D position) { Random rand = new Random(Seed + position.GetHashCode()); @@ -214,8 +228,32 @@ namespace DynamicAsteroids } } } -using System; +using DynamicAsteroids.AsteroidEntities; +using ProtoBuf; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VRageMath; + +[ProtoContract] +public class AsteroidState +{ + [ProtoMember(1)] + public Vector3D Position { get; set; } + + [ProtoMember(2)] + public float Size { get; set; } + + [ProtoMember(3)] + public AsteroidType Type { get; set; } + + [ProtoMember(4)] + public long EntityId { get; set; } // Unique ID for each asteroid +}using System; using System.IO; +using DynamicAsteroids; using Sandbox.ModAPI; namespace SC.SUGMA @@ -238,12 +276,14 @@ namespace SC.SUGMA public static void Info(string message) { - I._Log(message); + if (AsteroidSettings.EnableLogging) + I._Log(message); } public static void Exception(Exception ex, Type callingType, string prefix = "") { - I._LogException(ex, callingType, prefix); + if (AsteroidSettings.EnableLogging) + I._LogException(ex, callingType, prefix); } public static void Init() @@ -299,11 +339,13 @@ namespace DynamicAsteroids public class MainSession : MySessionComponentBase { public static MainSession I; - public Random Rand; private int seed; - public AsteroidSpawner _spawner = new AsteroidSpawner(); + private int _saveStateTimer; + private int _networkMessageTimer; + + public override void LoadData() { I = this; @@ -314,11 +356,14 @@ namespace DynamicAsteroids Log.Info("Loading data in MainSession"); if (MyAPIGateway.Session.IsServer) { - // Use a fixed seed for testing or a seed based on a consistent source seed = (int)DateTime.UtcNow.Ticks; // Example seed based on current time AsteroidSettings.Seed = seed; Rand = new Random(seed); _spawner.Init(seed); + if (AsteroidSettings.EnablePersistence) // Add this line + { + _spawner.LoadAsteroidState(); // Load asteroid states + } } MyAPIGateway.Multiplayer.RegisterMessageHandler(32000, OnMessageReceived); @@ -336,6 +381,10 @@ namespace DynamicAsteroids Log.Info("Unloading data in MainSession"); if (MyAPIGateway.Session.IsServer) { + if (AsteroidSettings.EnablePersistence) // Add this line + { + _spawner.SaveAsteroidState(); // Save asteroid states + } _spawner.Close(); } @@ -357,6 +406,29 @@ namespace DynamicAsteroids if (MyAPIGateway.Session.IsServer) { _spawner.UpdateTick(); + + // Save asteroid states periodically + if (_saveStateTimer > 0) + { + _saveStateTimer--; + } + else + { + _spawner.SaveAsteroidState(); + _saveStateTimer = AsteroidSettings.SaveStateInterval; // Use setting + } + + // Batch and delay network messages + if (_networkMessageTimer > 0) + { + _networkMessageTimer--; + } + else + { + Log.Info($"Server: Sending network messages, asteroid count: {_spawner._asteroids.Count}"); + _spawner.SendNetworkMessages(); + _networkMessageTimer = AsteroidSettings.NetworkMessageInterval; + } } if (MyAPIGateway.Session?.Player?.Character != null && _spawner._asteroids != null) @@ -370,17 +442,21 @@ namespace DynamicAsteroids string rotationString = $"({angularVelocity.X:F2}, {angularVelocity.Y:F2}, {angularVelocity.Z:F2})"; string message = $"Nearest Asteroid: {nearestAsteroid.EntityId} ({nearestAsteroid.Type})\nRotation: {rotationString}"; - MyAPIGateway.Utilities.ShowNotification(message, 1000 / 60); + if (AsteroidSettings.EnableLogging) + MyAPIGateway.Utilities.ShowNotification(message, 1000 / 60); } } - if (MyAPIGateway.Input.IsNewKeyPressed(MyKeys.MiddleButton)) + if (AsteroidSettings.EnableMiddleMouseAsteroidSpawn && MyAPIGateway.Input.IsNewKeyPressed(MyKeys.MiddleButton)) { - var position = MyAPIGateway.Session.Player?.GetPosition() ?? Vector3D.Zero; - var velocity = MyAPIGateway.Session.Player?.Character?.Physics?.LinearVelocity ?? Vector3D.Zero; - AsteroidType type = DetermineAsteroidType(); // Determine the type of asteroid - AsteroidEntity.CreateAsteroid(position, Rand.Next(50), velocity, type); - Log.Info($"Asteroid created at {position} with velocity {velocity}"); + if (MyAPIGateway.Session != null) + { + var position = MyAPIGateway.Session.Player?.GetPosition() ?? Vector3D.Zero; + var velocity = MyAPIGateway.Session.Player?.Character?.Physics?.LinearVelocity ?? Vector3D.Zero; + AsteroidType type = DetermineAsteroidType(); // Determine the type of asteroid + AsteroidEntity.CreateAsteroid(position, Rand.Next(50), velocity, type); + Log.Info($"Asteroid created at {position} with velocity {velocity}"); + } } } catch (Exception ex) @@ -388,42 +464,51 @@ namespace DynamicAsteroids Log.Exception(ex, typeof(MainSession)); } } + private void OnMessageReceived(byte[] message) { try { - var asteroidMessage = MyAPIGateway.Utilities.SerializeFromBinary(message); - Log.Info($"Client: Received message to create/remove asteroid at {asteroidMessage.Position} with velocity {asteroidMessage.InitialVelocity} of type {asteroidMessage.Type}"); - - if (asteroidMessage.IsRemoval) - { - // Find and remove the asteroid with the given EntityId - var asteroid = MyEntities.GetEntityById(asteroidMessage.EntityId) as AsteroidEntity; - if (asteroid != null) - { - asteroid.Close(); - } - } - else if (asteroidMessage.IsInitialCreation) - { - var asteroid = AsteroidEntity.CreateAsteroid(asteroidMessage.Position, asteroidMessage.Size, asteroidMessage.InitialVelocity, asteroidMessage.Type); - asteroid.Physics.AngularVelocity = asteroidMessage.AngularVelocity; - MyEntities.Add(asteroid); - } - else + Log.Info($"Client: Received message of {message.Length} bytes"); + var asteroidMessages = MyAPIGateway.Utilities.SerializeFromBinary>(message); + Log.Info($"Client: Deserialized {asteroidMessages.Count} asteroid messages"); foreach (var asteroidMessage in asteroidMessages) { - if (asteroidMessage.IsSubChunk) + Log.Info($"Client: Received message to create/remove asteroid at {asteroidMessage.Position} with velocity {asteroidMessage.InitialVelocity} of type {asteroidMessage.Type}"); + + if (asteroidMessage.IsRemoval) { - // Create the sub-chunk asteroid on the client - var subChunk = AsteroidEntity.CreateAsteroid(asteroidMessage.Position, asteroidMessage.Size, asteroidMessage.InitialVelocity, asteroidMessage.Type); - subChunk.Physics.AngularVelocity = asteroidMessage.AngularVelocity; + // Find and remove the asteroid with the given EntityId + var asteroid = MyEntities.GetEntityById(asteroidMessage.EntityId) as AsteroidEntity; + if (asteroid != null) + { + asteroid.Close(); + Log.Info($"Client: Removed asteroid with ID {asteroidMessage.EntityId}"); + } } - else + else if (asteroidMessage.IsInitialCreation) { - // Create the regular asteroid on the client var asteroid = AsteroidEntity.CreateAsteroid(asteroidMessage.Position, asteroidMessage.Size, asteroidMessage.InitialVelocity, asteroidMessage.Type); asteroid.Physics.AngularVelocity = asteroidMessage.AngularVelocity; MyEntities.Add(asteroid); + Log.Info($"Client: Created initial asteroid with ID {asteroid.EntityId}"); + } + else + { + if (asteroidMessage.IsSubChunk) + { + // Create the sub-chunk asteroid on the client + var subChunk = AsteroidEntity.CreateAsteroid(asteroidMessage.Position, asteroidMessage.Size, asteroidMessage.InitialVelocity, asteroidMessage.Type); + subChunk.Physics.AngularVelocity = asteroidMessage.AngularVelocity; + Log.Info($"Client: Created sub-chunk asteroid with ID {subChunk.EntityId}"); + } + else + { + // Create the regular asteroid on the client + var asteroid = AsteroidEntity.CreateAsteroid(asteroidMessage.Position, asteroidMessage.Size, asteroidMessage.InitialVelocity, asteroidMessage.Type); + asteroid.Physics.AngularVelocity = asteroidMessage.AngularVelocity; + MyEntities.Add(asteroid); + Log.Info($"Client: Created asteroid with ID {asteroid.EntityId}"); + } } } } @@ -548,9 +633,95 @@ namespace DynamicAsteroids.AsteroidEntities { var ent = new AsteroidEntity(); ent.Init(position, size, initialVelocity, type); + ent.EntityId = ent.EntityId; // EntityId is already assigned by the game return ent; } + private void Init(Vector3D position, float size, Vector3D initialVelocity, AsteroidType type) + { + try + { + Log.Info("Initializing asteroid entity"); + string modPath = Path.Combine(MainSession.I.ModContext.ModPath, ""); + Type = type; + switch (type) + { + case AsteroidType.Ice: + ModelString = Path.Combine(modPath, IceAsteroidModels[MainSession.I.Rand.Next(IceAsteroidModels.Length)]); + break; + case AsteroidType.Stone: + ModelString = Path.Combine(modPath, StoneAsteroidModels[MainSession.I.Rand.Next(StoneAsteroidModels.Length)]); + break; + case AsteroidType.Iron: + ModelString = Path.Combine(modPath, IronAsteroidModels[MainSession.I.Rand.Next(IronAsteroidModels.Length)]); + break; + case AsteroidType.Nickel: + ModelString = Path.Combine(modPath, NickelAsteroidModels[MainSession.I.Rand.Next(NickelAsteroidModels.Length)]); + break; + case AsteroidType.Cobalt: + ModelString = Path.Combine(modPath, CobaltAsteroidModels[MainSession.I.Rand.Next(CobaltAsteroidModels.Length)]); + break; + case AsteroidType.Magnesium: + ModelString = Path.Combine(modPath, MagnesiumAsteroidModels[MainSession.I.Rand.Next(MagnesiumAsteroidModels.Length)]); + break; + case AsteroidType.Silicon: + ModelString = Path.Combine(modPath, SiliconAsteroidModels[MainSession.I.Rand.Next(SiliconAsteroidModels.Length)]); + break; + case AsteroidType.Silver: + ModelString = Path.Combine(modPath, SilverAsteroidModels[MainSession.I.Rand.Next(SilverAsteroidModels.Length)]); + break; + case AsteroidType.Gold: + ModelString = Path.Combine(modPath, GoldAsteroidModels[MainSession.I.Rand.Next(GoldAsteroidModels.Length)]); + break; + case AsteroidType.Platinum: + ModelString = Path.Combine(modPath, PlatinumAsteroidModels[MainSession.I.Rand.Next(PlatinumAsteroidModels.Length)]); + break; + case AsteroidType.Uraninite: + ModelString = Path.Combine(modPath, UraniniteAsteroidModels[MainSession.I.Rand.Next(UraniniteAsteroidModels.Length)]); + break; + } + + Size = size; + _integrity = AsteroidSettings.BaseIntegrity + Size; + + Log.Info($"Attempting to load model: {ModelString}"); + + Init(null, ModelString, null, Size); + + if (string.IsNullOrEmpty(ModelString)) + Flags &= ~EntityFlags.Visible; + + Save = false; + NeedsWorldMatrix = true; + + PositionComp.LocalAABB = new BoundingBox(-Vector3.Half * Size, Vector3.Half * Size); + + // Apply random rotation + var randomRotation = MatrixD.CreateFromQuaternion(Quaternion.CreateFromYawPitchRoll((float)MainSession.I.Rand.NextDouble() * MathHelper.TwoPi, (float)MainSession.I.Rand.NextDouble() * MathHelper.TwoPi, (float)MainSession.I.Rand.NextDouble() * MathHelper.TwoPi)); + WorldMatrix = randomRotation * MatrixD.CreateWorld(position, Vector3D.Forward, Vector3D.Up); + WorldMatrix.Orthogonalize(); // Normalize the matrix to prevent rotation spazzing + + MyEntities.Add(this); + Log.Info($"{(MyAPIGateway.Session.IsServer ? "Server" : "Client")}: Added asteroid entity with ID {EntityId} to MyEntities"); + + CreatePhysics(); + Physics.LinearVelocity = initialVelocity + RandVector() * AsteroidSettings.VelocityVariability; + Physics.AngularVelocity = RandVector() * AsteroidSettings.GetRandomAngularVelocity(MainSession.I.Rand); // Set initial angular velocity + + Log.Info($"Asteroid model {ModelString} loaded successfully with initial angular velocity: {Physics.AngularVelocity}"); + + if (MyAPIGateway.Session.IsServer) + { + SyncFlag = true; + } + } + catch (Exception ex) + { + Log.Exception(ex, typeof(AsteroidEntity), $"Failed to load model: {ModelString}"); + Flags &= ~EntityFlags.Visible; + } + } + public float Size; public string ModelString = ""; public AsteroidType Type; @@ -673,6 +844,16 @@ namespace DynamicAsteroids.AsteroidEntities public bool DoDamage(float damage, MyStringHash damageSource, bool sync, MyHitInfo? hitInfo = null, long attackerId = 0, long realHitEntityId = 0, bool shouldDetonateAmmo = true, MyStringHash? extraInfo = null) { + //Disabling explosion damage is an awful way to fix this weird rocket bug, but it's okay we'll be using weaponcore :) + var explosionDamageType = MyStringHash.GetOrCompute("Explosion"); + + // Check if the damage source is explosion + if (damageSource == explosionDamageType) + { + Log.Info($"Ignoring explosion damage for asteroid. Damage source: {damageSource.String}"); + return false; // Ignore the damage + } + _integrity -= damage; Log.Info($"DoDamage called with damage: {damage}, damageSource: {damageSource.String}, attackerId: {attackerId}, realHitEntityId: {realHitEntityId}, new integrity: {_integrity}"); @@ -694,90 +875,6 @@ namespace DynamicAsteroids.AsteroidEntities public bool UseDamageSystem => true; - private void Init(Vector3D position, float size, Vector3D initialVelocity, AsteroidType type) - { - try - { - Log.Info("Initializing asteroid entity"); - string modPath = Path.Combine(MainSession.I.ModContext.ModPath, ""); - Type = type; - switch (type) - { - case AsteroidType.Ice: - ModelString = Path.Combine(modPath, IceAsteroidModels[MainSession.I.Rand.Next(IceAsteroidModels.Length)]); - break; - case AsteroidType.Stone: - ModelString = Path.Combine(modPath, StoneAsteroidModels[MainSession.I.Rand.Next(StoneAsteroidModels.Length)]); - break; - case AsteroidType.Iron: - ModelString = Path.Combine(modPath, IronAsteroidModels[MainSession.I.Rand.Next(IronAsteroidModels.Length)]); - break; - case AsteroidType.Nickel: - ModelString = Path.Combine(modPath, NickelAsteroidModels[MainSession.I.Rand.Next(NickelAsteroidModels.Length)]); - break; - case AsteroidType.Cobalt: - ModelString = Path.Combine(modPath, CobaltAsteroidModels[MainSession.I.Rand.Next(CobaltAsteroidModels.Length)]); - break; - case AsteroidType.Magnesium: - ModelString = Path.Combine(modPath, MagnesiumAsteroidModels[MainSession.I.Rand.Next(MagnesiumAsteroidModels.Length)]); - break; - case AsteroidType.Silicon: - ModelString = Path.Combine(modPath, SiliconAsteroidModels[MainSession.I.Rand.Next(SiliconAsteroidModels.Length)]); - break; - case AsteroidType.Silver: - ModelString = Path.Combine(modPath, SilverAsteroidModels[MainSession.I.Rand.Next(SilverAsteroidModels.Length)]); - break; - case AsteroidType.Gold: - ModelString = Path.Combine(modPath, GoldAsteroidModels[MainSession.I.Rand.Next(GoldAsteroidModels.Length)]); - break; - case AsteroidType.Platinum: - ModelString = Path.Combine(modPath, PlatinumAsteroidModels[MainSession.I.Rand.Next(PlatinumAsteroidModels.Length)]); - break; - case AsteroidType.Uraninite: - ModelString = Path.Combine(modPath, UraniniteAsteroidModels[MainSession.I.Rand.Next(UraniniteAsteroidModels.Length)]); - break; - } - - Size = size; - _integrity = AsteroidSettings.BaseIntegrity + Size; - - Log.Info($"Attempting to load model: {ModelString}"); - - Init(null, ModelString, null, Size); - - if (string.IsNullOrEmpty(ModelString)) - Flags &= ~EntityFlags.Visible; - - Save = false; - NeedsWorldMatrix = true; - - PositionComp.LocalAABB = new BoundingBox(-Vector3.Half * Size, Vector3.Half * Size); - - // Apply random rotation - var randomRotation = MatrixD.CreateFromQuaternion(Quaternion.CreateFromYawPitchRoll((float)MainSession.I.Rand.NextDouble() * MathHelper.TwoPi, (float)MainSession.I.Rand.NextDouble() * MathHelper.TwoPi, (float)MainSession.I.Rand.NextDouble() * MathHelper.TwoPi)); - WorldMatrix = randomRotation * MatrixD.CreateWorld(position, Vector3D.Forward, Vector3D.Up); - WorldMatrix.Orthogonalize(); // Normalize the matrix to prevent rotation spazzing - - MyEntities.Add(this); - - CreatePhysics(); - Physics.LinearVelocity = initialVelocity + RandVector() * AsteroidSettings.VelocityVariability; - Physics.AngularVelocity = RandVector() * AsteroidSettings.GetRandomAngularVelocity(MainSession.I.Rand); // Set initial angular velocity - - Log.Info($"Asteroid model {ModelString} loaded successfully with initial angular velocity: {Physics.AngularVelocity}"); - - if (MyAPIGateway.Session.IsServer) - { - SyncFlag = true; - } - } - catch (Exception ex) - { - Log.Exception(ex, typeof(AsteroidEntity), $"Failed to load model: {ModelString}"); - Flags &= ~EntityFlags.Visible; - } - } - private void CreatePhysics() { float mass = 10000 * Size * Size * Size; @@ -807,6 +904,7 @@ namespace DynamicAsteroids.AsteroidEntities var sinPhi = Math.Sin(phi); return Math.Pow(MainSession.I.Rand.NextDouble(), 1 / 3d) * new Vector3D(sinPhi * Math.Cos(theta), sinPhi * Math.Sin(theta), Math.Cos(phi)); } + } } using DynamicAsteroids.AsteroidEntities; @@ -818,6 +916,8 @@ using System; using VRage.Game.ModAPI; using VRage.ModAPI; using VRageMath; +using System.Linq; +using Sandbox.Game.Entities; public class AsteroidSpawner { @@ -825,6 +925,9 @@ public class AsteroidSpawner private bool _canSpawnAsteroids = false; private DateTime _worldLoadTime; private Random rand; + private List _despawnedAsteroids = new List(); + private List _networkMessages = new List(); + public void Init(int seed) { @@ -838,15 +941,105 @@ public class AsteroidSpawner AsteroidSettings.Seed = seed; } + public void SaveAsteroidState() + { + if (!MyAPIGateway.Session.IsServer || !AsteroidSettings.EnablePersistence) + return; + + var asteroidStates = _asteroids.Select(asteroid => new AsteroidState + { + Position = asteroid.PositionComp.GetPosition(), + Size = asteroid.Size, + Type = asteroid.Type, + EntityId = asteroid.EntityId // Save unique ID + }).ToList(); + + asteroidStates.AddRange(_despawnedAsteroids); + + var stateBytes = MyAPIGateway.Utilities.SerializeToBinary(asteroidStates); + using (var writer = MyAPIGateway.Utilities.WriteBinaryFileInLocalStorage("asteroid_states.dat", typeof(AsteroidSpawner))) + { + writer.Write(stateBytes, 0, stateBytes.Length); + } + } + + public void LoadAsteroidState() + { + if (!MyAPIGateway.Session.IsServer || !AsteroidSettings.EnablePersistence) + return; + + _asteroids.Clear(); + + if (MyAPIGateway.Utilities.FileExistsInLocalStorage("asteroid_states.dat", typeof(AsteroidSpawner))) + { + byte[] stateBytes; + using (var reader = MyAPIGateway.Utilities.ReadBinaryFileInLocalStorage("asteroid_states.dat", typeof(AsteroidSpawner))) + { + stateBytes = reader.ReadBytes((int)reader.BaseStream.Length); + } + + var asteroidStates = MyAPIGateway.Utilities.SerializeFromBinary>(stateBytes); + + foreach (var state in asteroidStates) + { + if (_asteroids.Any(a => a.EntityId == state.EntityId)) + { + Log.Info($"Skipping duplicate asteroid with ID {state.EntityId}"); + continue; // Skip duplicates + } + + var asteroid = AsteroidEntity.CreateAsteroid(state.Position, state.Size, Vector3D.Zero, state.Type); + asteroid.EntityId = state.EntityId; // Assign the saved ID + _asteroids.Add(asteroid); + MyEntities.Add(asteroid); + } + } + } + + private void LoadAsteroidsInRange(Vector3D playerPosition) + { + foreach (var state in _despawnedAsteroids.ToArray()) + { + double distanceSquared = Vector3D.DistanceSquared(state.Position, playerPosition); + + if (distanceSquared < AsteroidSettings.AsteroidSpawnRadius * AsteroidSettings.AsteroidSpawnRadius) + { + bool tooClose = _asteroids.Any(a => Vector3D.DistanceSquared(a.PositionComp.GetPosition(), state.Position) < AsteroidSettings.MinDistanceFromPlayer * AsteroidSettings.MinDistanceFromPlayer); + bool exists = _asteroids.Any(a => a.EntityId == state.EntityId); // Check for existing IDs + + if (tooClose || exists) + { + Log.Info($"Skipping respawn of asteroid at {state.Position} due to proximity to other asteroids or duplicate ID"); + continue; + } + + Log.Info($"Respawning asteroid at {state.Position} due to player re-entering range"); + var asteroid = AsteroidEntity.CreateAsteroid(state.Position, state.Size, Vector3D.Zero, state.Type); + asteroid.EntityId = state.EntityId; // Assign the saved ID + _asteroids.Add(asteroid); + + var message = new AsteroidNetworkMessage(state.Position, state.Size, Vector3D.Zero, Vector3D.Zero, state.Type, false, asteroid.EntityId, false, true); + var messageBytes = MyAPIGateway.Utilities.SerializeToBinary(message); + MyAPIGateway.Multiplayer.SendMessageToOthers(32000, messageBytes); + + _despawnedAsteroids.Remove(state); + } + } + } + public void Close() { if (!MyAPIGateway.Session.IsServer) return; + SaveAsteroidState(); Log.Info("Closing AsteroidSpawner"); _asteroids?.Clear(); } + private int _spawnIntervalTimer = 0; + private int _updateIntervalTimer = 0; + public void UpdateTick() { if (!MyAPIGateway.Session.IsServer) @@ -871,75 +1064,144 @@ public class AsteroidSpawner { Vector3D playerPosition = player.GetPosition(); - foreach (var asteroid in _asteroids.ToArray()) + // Update asteroids at a slower interval + if (_updateIntervalTimer > 0) { - double distanceSquared = Vector3D.DistanceSquared(asteroid.PositionComp.GetPosition(), playerPosition); - - // Remove asteroids that are outside the spherical spawn radius - if (distanceSquared > AsteroidSettings.AsteroidSpawnRadius * AsteroidSettings.AsteroidSpawnRadius) - { - Log.Info($"Removing asteroid at {asteroid.PositionComp.GetPosition()} due to distance from player"); - _asteroids.Remove(asteroid); - - var removalMessage = new AsteroidNetworkMessage(asteroid.PositionComp.GetPosition(), asteroid.Size, Vector3D.Zero, Vector3D.Zero, asteroid.Type, false, asteroid.EntityId, true, false); - var removalMessageBytes = MyAPIGateway.Utilities.SerializeToBinary(removalMessage); - MyAPIGateway.Multiplayer.SendMessageToOthers(32000, removalMessageBytes); + _updateIntervalTimer--; + } + else + { + UpdateAsteroids(playerPosition); + _updateIntervalTimer = AsteroidSettings.UpdateInterval; // Use setting + } - asteroid.Close(); - continue; - } + // Spawn asteroids at a slower interval + if (_spawnIntervalTimer > 0) + { + _spawnIntervalTimer--; + } + else + { + SpawnAsteroids(playerPosition); + _spawnIntervalTimer = AsteroidSettings.SpawnInterval; // Use setting } - int asteroidsSpawned = 0; - int spawnAttempts = 0; - int maxAttempts = 50; // Limit the number of attempts to find valid positions + // Load asteroids in range + LoadAsteroidsInRange(playerPosition); - while (_asteroids.Count < AsteroidSettings.MaxAsteroidCount && asteroidsSpawned < 10) - { - if (spawnAttempts >= maxAttempts) - { - Log.Info("Reached maximum spawn attempts, breaking out of loop to prevent freeze"); - break; - } + if (AsteroidSettings.EnableLogging) + MyAPIGateway.Utilities.ShowNotification($"Active Asteroids: {_asteroids.Count}", 1000 / 60); + } + } + catch (Exception ex) + { + Log.Exception(ex, typeof(AsteroidSpawner)); + } + } - Vector3D newPosition; - do - { - newPosition = playerPosition + RandVector() * AsteroidSettings.AsteroidSpawnRadius; - spawnAttempts++; - } while (Vector3D.DistanceSquared(newPosition, playerPosition) < AsteroidSettings.MinDistanceFromPlayer * AsteroidSettings.MinDistanceFromPlayer && spawnAttempts < maxAttempts); + private void UpdateAsteroids(Vector3D playerPosition) + { + foreach (var asteroid in _asteroids.ToArray()) + { + double distanceSquared = Vector3D.DistanceSquared(asteroid.PositionComp.GetPosition(), playerPosition); - if (spawnAttempts >= maxAttempts) - break; + // Remove asteroids that are outside the spherical spawn radius + if (distanceSquared > AsteroidSettings.AsteroidSpawnRadius * AsteroidSettings.AsteroidSpawnRadius) + { + Log.Info($"Removing asteroid at {asteroid.PositionComp.GetPosition()} due to distance from player"); + RemoveAsteroid(asteroid); + } + } + } - Vector3D newVelocity; - if (!AsteroidSettings.CanSpawnAsteroidAtPoint(newPosition, out newVelocity)) - continue; + private void SpawnAsteroids(Vector3D playerPosition) + { + int asteroidsSpawned = 0; + int spawnAttempts = 0; + int maxAttempts = 50; // Limit the number of attempts to find valid positions - if (IsNearVanillaAsteroid(newPosition)) - { - Log.Info("Skipped spawning asteroid due to proximity to vanilla asteroid."); - continue; - } + while (_asteroids.Count < AsteroidSettings.MaxAsteroidCount && asteroidsSpawned < 10) + { + if (spawnAttempts >= maxAttempts) + { + Log.Info("Reached maximum spawn attempts, breaking out of loop to prevent freeze"); + break; + } - AsteroidType type = AsteroidSettings.GetAsteroidType(newPosition); - float size = AsteroidSettings.GetAsteroidSize(newPosition); + Vector3D newPosition; + do + { + newPosition = playerPosition + RandVector() * AsteroidSettings.AsteroidSpawnRadius; + spawnAttempts++; + } while (Vector3D.DistanceSquared(newPosition, playerPosition) < AsteroidSettings.MinDistanceFromPlayer * AsteroidSettings.MinDistanceFromPlayer && spawnAttempts < maxAttempts); - Log.Info($"Spawning asteroid at {newPosition} with velocity {newVelocity} of type {type}"); - var asteroid = AsteroidEntity.CreateAsteroid(newPosition, size, newVelocity, type); - _asteroids.Add(asteroid); + if (spawnAttempts >= maxAttempts) + break; - var message = new AsteroidNetworkMessage(newPosition, size, newVelocity, Vector3D.Zero, type, false, asteroid.EntityId, false, true); - var messageBytes = MyAPIGateway.Utilities.SerializeToBinary(message); - MyAPIGateway.Multiplayer.SendMessageToOthers(32000, messageBytes); - } + Vector3D newVelocity; + if (!AsteroidSettings.CanSpawnAsteroidAtPoint(newPosition, out newVelocity)) + continue; - MyAPIGateway.Utilities.ShowNotification($"Active Asteroids: {_asteroids.Count}", 1000 / 60); + if (IsNearVanillaAsteroid(newPosition)) + { + Log.Info("Skipped spawning asteroid due to proximity to vanilla asteroid."); + continue; } + + AsteroidType type = AsteroidSettings.GetAsteroidType(newPosition); + float size = AsteroidSettings.GetAsteroidSize(newPosition); + + Log.Info($"Spawning asteroid at {newPosition} with velocity {newVelocity} of type {type}"); + var asteroid = AsteroidEntity.CreateAsteroid(newPosition, size, newVelocity, type); + _asteroids.Add(asteroid); + Log.Info($"Server: Added new asteroid with ID {asteroid.EntityId} to _asteroids list"); + + var message = new AsteroidNetworkMessage(newPosition, size, newVelocity, Vector3D.Zero, type, false, asteroid.EntityId, false, true); + _networkMessages.Add(message); // Add to the list instead of sending immediately + + asteroidsSpawned++; + } + } + + public void SendNetworkMessages() + { + if (_networkMessages.Count == 0) return; + try + { + Log.Info($"Server: Preparing to send {_networkMessages.Count} network messages"); + var messageBytes = MyAPIGateway.Utilities.SerializeToBinary(_networkMessages); + Log.Info($"Server: Serialized message size: {messageBytes.Length} bytes"); + MyAPIGateway.Multiplayer.SendMessageToOthers(32000, messageBytes); + Log.Info($"Server: Sent {_networkMessages.Count} network messages"); + _networkMessages.Clear(); } catch (Exception ex) { - Log.Exception(ex, typeof(AsteroidSpawner)); + Log.Exception(ex, typeof(AsteroidSpawner), "Failed to send network messages"); + } + } + + + private void RemoveAsteroid(AsteroidEntity asteroid) + { + if (_asteroids.Any(a => a.EntityId == asteroid.EntityId)) + { + _despawnedAsteroids.Add(new AsteroidState + { + Position = asteroid.PositionComp.GetPosition(), + Size = asteroid.Size, + Type = asteroid.Type, + EntityId = asteroid.EntityId + }); + + var removalMessage = new AsteroidNetworkMessage(asteroid.PositionComp.GetPosition(), asteroid.Size, Vector3D.Zero, Vector3D.Zero, asteroid.Type, false, asteroid.EntityId, true, false); + var removalMessageBytes = MyAPIGateway.Utilities.SerializeToBinary(removalMessage); + MyAPIGateway.Multiplayer.SendMessageToOthers(32000, removalMessageBytes); + + _asteroids.Remove(asteroid); + asteroid.Close(); + MyEntities.Remove(asteroid); + Log.Info($"Server: Removed asteroid with ID {asteroid.EntityId} from _asteroids list and MyEntities"); } } @@ -968,4 +1230,3 @@ public class AsteroidSpawner return Math.Pow(rand.NextDouble(), 1 / 3d) * new Vector3D(sinPhi * Math.Cos(theta), sinPhi * Math.Sin(theta), Math.Cos(phi)); } } - From a8be64879b1c9d3f822d25b3c57b2a1a66e218bc Mon Sep 17 00:00:00 2001 From: InvalidArgument3 Date: Wed, 12 Jun 2024 19:30:01 -0500 Subject: [PATCH 12/16] Update AsteroidNetworkMessage.cs --- .../Scripts/DynamicAsteroids/AsteroidNetworkMessage.cs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidNetworkMessage.cs b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidNetworkMessage.cs index f118fa10..21ccfb0c 100644 --- a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidNetworkMessage.cs +++ b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidNetworkMessage.cs @@ -1,7 +1,6 @@ using DynamicAsteroids.AsteroidEntities; using VRageMath; using ProtoBuf; -using System.Collections.Generic; namespace DynamicAsteroids { @@ -47,12 +46,5 @@ public AsteroidNetworkMessage(Vector3D position, float size, Vector3D initialVel IsRemoval = isRemoval; IsInitialCreation = isInitialCreation; } - - [ProtoContract] - public class AsteroidNetworkMessageWrapper - { - [ProtoMember(1)] - public List Messages { get; set; } - } } } \ No newline at end of file From 15d7662c9b54e793ffc8538569cbee00b045872c Mon Sep 17 00:00:00 2001 From: InvalidArgument3 Date: Wed, 12 Jun 2024 19:35:18 -0500 Subject: [PATCH 13/16] more logging --- .../AsteroidEntities/AsteroidEntity.cs | 26 ++++++++++----- .../Scripts/DynamicAsteroids/MainSession.cs | 32 +++++++------------ 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidEntity.cs b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidEntity.cs index 3464a09a..5cd1ab75 100644 --- a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidEntity.cs +++ b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidEntity.cs @@ -95,6 +95,7 @@ private void Init(Vector3D position, float size, Vector3D initialVelocity, Aster Log.Info("Initializing asteroid entity"); string modPath = Path.Combine(MainSession.I.ModContext.ModPath, ""); Type = type; + switch (type) { case AsteroidType.Ice: @@ -130,6 +131,16 @@ private void Init(Vector3D position, float size, Vector3D initialVelocity, Aster case AsteroidType.Uraninite: ModelString = Path.Combine(modPath, UraniniteAsteroidModels[MainSession.I.Rand.Next(UraniniteAsteroidModels.Length)]); break; + default: + Log.Info("Invalid AsteroidType, setting ModelString to empty."); + ModelString = ""; + break; + } + + if (string.IsNullOrEmpty(ModelString)) + { + Log.Exception(new Exception("ModelString is null or empty"), typeof(AsteroidEntity), "Failed to initialize asteroid entity"); + return; // Early exit if ModelString is not set } Size = size; @@ -139,25 +150,24 @@ private void Init(Vector3D position, float size, Vector3D initialVelocity, Aster Init(null, ModelString, null, Size); - if (string.IsNullOrEmpty(ModelString)) - Flags &= ~EntityFlags.Visible; - Save = false; NeedsWorldMatrix = true; - PositionComp.LocalAABB = new BoundingBox(-Vector3.Half * Size, Vector3.Half * Size); - // Apply random rotation - var randomRotation = MatrixD.CreateFromQuaternion(Quaternion.CreateFromYawPitchRoll((float)MainSession.I.Rand.NextDouble() * MathHelper.TwoPi, (float)MainSession.I.Rand.NextDouble() * MathHelper.TwoPi, (float)MainSession.I.Rand.NextDouble() * MathHelper.TwoPi)); + var randomRotation = MatrixD.CreateFromQuaternion(Quaternion.CreateFromYawPitchRoll( + (float)MainSession.I.Rand.NextDouble() * MathHelper.TwoPi, + (float)MainSession.I.Rand.NextDouble() * MathHelper.TwoPi, + (float)MainSession.I.Rand.NextDouble() * MathHelper.TwoPi)); + WorldMatrix = randomRotation * MatrixD.CreateWorld(position, Vector3D.Forward, Vector3D.Up); - WorldMatrix.Orthogonalize(); // Normalize the matrix to prevent rotation spazzing + WorldMatrix.Orthogonalize(); MyEntities.Add(this); Log.Info($"{(MyAPIGateway.Session.IsServer ? "Server" : "Client")}: Added asteroid entity with ID {EntityId} to MyEntities"); CreatePhysics(); Physics.LinearVelocity = initialVelocity + RandVector() * AsteroidSettings.VelocityVariability; - Physics.AngularVelocity = RandVector() * AsteroidSettings.GetRandomAngularVelocity(MainSession.I.Rand); // Set initial angular velocity + Physics.AngularVelocity = RandVector() * AsteroidSettings.GetRandomAngularVelocity(MainSession.I.Rand); Log.Info($"Asteroid model {ModelString} loaded successfully with initial angular velocity: {Physics.AngularVelocity}"); diff --git a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/MainSession.cs b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/MainSession.cs index 15205bc2..38a3025c 100644 --- a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/MainSession.cs +++ b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/MainSession.cs @@ -22,7 +22,6 @@ public class MainSession : MySessionComponentBase private int _saveStateTimer; private int _networkMessageTimer; - public override void LoadData() { I = this; @@ -33,13 +32,13 @@ public override void LoadData() Log.Info("Loading data in MainSession"); if (MyAPIGateway.Session.IsServer) { - seed = (int)DateTime.UtcNow.Ticks; // Example seed based on current time + seed = (int)DateTime.UtcNow.Ticks; AsteroidSettings.Seed = seed; Rand = new Random(seed); _spawner.Init(seed); - if (AsteroidSettings.EnablePersistence) // Add this line + if (AsteroidSettings.EnablePersistence) { - _spawner.LoadAsteroidState(); // Load asteroid states + _spawner.LoadAsteroidState(); } } @@ -51,6 +50,7 @@ public override void LoadData() } } + protected override void UnloadData() { try @@ -148,13 +148,14 @@ private void OnMessageReceived(byte[] message) { Log.Info($"Client: Received message of {message.Length} bytes"); var asteroidMessages = MyAPIGateway.Utilities.SerializeFromBinary>(message); - Log.Info($"Client: Deserialized {asteroidMessages.Count} asteroid messages"); foreach (var asteroidMessage in asteroidMessages) + Log.Info($"Client: Deserialized {asteroidMessages.Count} asteroid messages"); + + foreach (var asteroidMessage in asteroidMessages) { Log.Info($"Client: Received message to create/remove asteroid at {asteroidMessage.Position} with velocity {asteroidMessage.InitialVelocity} of type {asteroidMessage.Type}"); if (asteroidMessage.IsRemoval) { - // Find and remove the asteroid with the given EntityId var asteroid = MyEntities.GetEntityById(asteroidMessage.EntityId) as AsteroidEntity; if (asteroid != null) { @@ -171,21 +172,10 @@ private void OnMessageReceived(byte[] message) } else { - if (asteroidMessage.IsSubChunk) - { - // Create the sub-chunk asteroid on the client - var subChunk = AsteroidEntity.CreateAsteroid(asteroidMessage.Position, asteroidMessage.Size, asteroidMessage.InitialVelocity, asteroidMessage.Type); - subChunk.Physics.AngularVelocity = asteroidMessage.AngularVelocity; - Log.Info($"Client: Created sub-chunk asteroid with ID {subChunk.EntityId}"); - } - else - { - // Create the regular asteroid on the client - var asteroid = AsteroidEntity.CreateAsteroid(asteroidMessage.Position, asteroidMessage.Size, asteroidMessage.InitialVelocity, asteroidMessage.Type); - asteroid.Physics.AngularVelocity = asteroidMessage.AngularVelocity; - MyEntities.Add(asteroid); - Log.Info($"Client: Created asteroid with ID {asteroid.EntityId}"); - } + var asteroid = AsteroidEntity.CreateAsteroid(asteroidMessage.Position, asteroidMessage.Size, asteroidMessage.InitialVelocity, asteroidMessage.Type); + asteroid.Physics.AngularVelocity = asteroidMessage.AngularVelocity; + MyEntities.Add(asteroid); + Log.Info($"Client: Created asteroid with ID {asteroid.EntityId}"); } } } From 150df3e9d517f1d5e2b48eddf7c0da62ca2f0064 Mon Sep 17 00:00:00 2001 From: InvalidArgument3 Date: Wed, 12 Jun 2024 19:37:55 -0500 Subject: [PATCH 14/16] MORE LOGGING --- .../AsteroidEntities/AsteroidEntity.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidEntity.cs b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidEntity.cs index 5cd1ab75..b5f648a0 100644 --- a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidEntity.cs +++ b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidEntity.cs @@ -93,8 +93,21 @@ private void Init(Vector3D position, float size, Vector3D initialVelocity, Aster try { Log.Info("Initializing asteroid entity"); + if (MainSession.I == null) + { + Log.Exception(new Exception("MainSession.I is null"), typeof(AsteroidEntity), "Failed to initialize asteroid entity"); + return; + } + + if (MainSession.I.ModContext == null) + { + Log.Exception(new Exception("MainSession.I.ModContext is null"), typeof(AsteroidEntity), "Failed to initialize asteroid entity"); + return; + } + string modPath = Path.Combine(MainSession.I.ModContext.ModPath, ""); Type = type; + Log.Info($"Asteroid Type: {type}"); switch (type) { @@ -137,6 +150,8 @@ private void Init(Vector3D position, float size, Vector3D initialVelocity, Aster break; } + Log.Info($"ModelString: {ModelString}"); + if (string.IsNullOrEmpty(ModelString)) { Log.Exception(new Exception("ModelString is null or empty"), typeof(AsteroidEntity), "Failed to initialize asteroid entity"); From ceeb443a6c74a3a4d30e4884ccb42d96356f39aa Mon Sep 17 00:00:00 2001 From: InvalidArgument3 Date: Wed, 12 Jun 2024 19:42:27 -0500 Subject: [PATCH 15/16] Update AsteroidEntity.cs --- .../AsteroidEntities/AsteroidEntity.cs | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidEntity.cs b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidEntity.cs index b5f648a0..fd21892b 100644 --- a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidEntity.cs +++ b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidEntity.cs @@ -93,19 +93,29 @@ private void Init(Vector3D position, float size, Vector3D initialVelocity, Aster try { Log.Info("Initializing asteroid entity"); + + // Check if MainSession.I is null if (MainSession.I == null) { - Log.Exception(new Exception("MainSession.I is null"), typeof(AsteroidEntity), "Failed to initialize asteroid entity"); + Log.Exception(new Exception("MainSession.I is null"), typeof(AsteroidEntity), "MainSession.I is not initialized."); return; } + // Check if ModContext is null if (MainSession.I.ModContext == null) { - Log.Exception(new Exception("MainSession.I.ModContext is null"), typeof(AsteroidEntity), "Failed to initialize asteroid entity"); + Log.Exception(new Exception("MainSession.I.ModContext is null"), typeof(AsteroidEntity), "MainSession.I.ModContext is not initialized."); + return; + } + + // Check if ModPath is null or empty + string modPath = MainSession.I.ModContext.ModPath; + if (string.IsNullOrEmpty(modPath)) + { + Log.Exception(new Exception("MainSession.I.ModContext.ModPath is null or empty"), typeof(AsteroidEntity), "MainSession.I.ModContext.ModPath is not initialized."); return; } - string modPath = Path.Combine(MainSession.I.ModContext.ModPath, ""); Type = type; Log.Info($"Asteroid Type: {type}"); @@ -163,6 +173,13 @@ private void Init(Vector3D position, float size, Vector3D initialVelocity, Aster Log.Info($"Attempting to load model: {ModelString}"); + // Check if Init method parameters are valid + if (string.IsNullOrEmpty(ModelString)) + { + Log.Exception(new Exception("ModelString is null or empty"), typeof(AsteroidEntity), "ModelString is not set."); + return; + } + Init(null, ModelString, null, Size); Save = false; From 49b1e56324c3ff26aeeb995a6e2da939dcc518ac Mon Sep 17 00:00:00 2001 From: InvalidArgument3 Date: Wed, 12 Jun 2024 20:02:01 -0500 Subject: [PATCH 16/16] aaaaaaaaaaaa --- .../Data/Scripts/DynamicAsteroids/AsteroidSettings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs index 2dbf611c..d4814989 100644 --- a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs +++ b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidSettings.cs @@ -8,7 +8,7 @@ public static class AsteroidSettings { public static bool EnableLogging = true; public static bool EnablePersistence = false; //barely works, don't touch this - public static bool EnableMiddleMouseAsteroidSpawn = false; //debug + public static bool EnableMiddleMouseAsteroidSpawn = true; //debug public static int SaveStateInterval = 600; // Default: 600 ticks (10 seconds) public static int NetworkMessageInterval = 120; // Default: 120 ticks (2 seconds)