From 7a5c4719c4ef4496c1d2b6432e1f5b5ba86fd0cb Mon Sep 17 00:00:00 2001 From: Jnick-24 <94058548+Jnick-24@users.noreply.github.com> Date: Fri, 5 Jan 2024 14:19:00 -0600 Subject: [PATCH 1/4] Consolidation of Data (and critical error handling) --- .../ExceptionHandler/CriticalHandle.cs | 61 +++++++++++++++++++ .../HeartModule/ExceptionHandler/HeartLog.cs | 30 +++++++++ .../ExceptionHandler/NetworkedError.cs | 25 ++++++++ .../ExceptionHandler/SoftHandle.cs | 16 +++-- .../Data/Scripts/HeartModule/HeartData.cs | 15 +++++ .../Data/Scripts/HeartModule/HeartLoad.cs | 52 ++++++++++++++++ ...eartNetwork_Session.cs => HeartNetwork.cs} | 24 +++----- .../Scripts/HeartModule/Network/PacketBase.cs | 1 + .../Projectiles/ProjectileManager.cs | 7 ++- 9 files changed, 209 insertions(+), 22 deletions(-) create mode 100644 Heart Module/Data/Scripts/HeartModule/ExceptionHandler/CriticalHandle.cs create mode 100644 Heart Module/Data/Scripts/HeartModule/ExceptionHandler/HeartLog.cs create mode 100644 Heart Module/Data/Scripts/HeartModule/ExceptionHandler/NetworkedError.cs create mode 100644 Heart Module/Data/Scripts/HeartModule/HeartData.cs create mode 100644 Heart Module/Data/Scripts/HeartModule/HeartLoad.cs rename Heart Module/Data/Scripts/HeartModule/Network/{HeartNetwork_Session.cs => HeartNetwork.cs} (73%) diff --git a/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/CriticalHandle.cs b/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/CriticalHandle.cs new file mode 100644 index 00000000..e404ad02 --- /dev/null +++ b/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/CriticalHandle.cs @@ -0,0 +1,61 @@ +using Sandbox.Game; +using Sandbox.ModAPI; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VRage.Game.Components; + +namespace Heart_Module.Data.Scripts.HeartModule.ExceptionHandler +{ + + public class CriticalHandle + { + const int WarnTimeSeconds = 20; + private static CriticalHandle I; + private long CriticalCloseTime = -1; + + public void LoadData() + { + I = this; + } + + int i = 0; + public void Update() + { + if (CriticalCloseTime == -1) + return; + double secondsRemaining = Math.Round((CriticalCloseTime - DateTime.Now.Ticks) / (double)TimeSpan.TicksPerSecond, 1); + + if (secondsRemaining <= 0) + MyVisualScriptLogicProvider.SessionClose(1000, false, true); + + MyAPIGateway.Utilities.ShowNotification($"HeartMod CRITICAL ERROR - Shutting down in {secondsRemaining}s", 1000/60); + i++; + if (i >= 60) + { + i = 0; + MyAPIGateway.Utilities.ShowMessage("HeartMod", $"CRITICAL ERROR - Shutting down in {secondsRemaining} seconds."); + } + } + + public void UnloadData() + { + I = null; + } + + public static void ThrowCriticalException(Exception ex, Type callingType, ulong callerId = ulong.MaxValue) + { + I?.m_ThrowCriticalException(ex, callingType, callerId); + } + + private void m_ThrowCriticalException(Exception ex, Type callingType, ulong callerId = ulong.MaxValue) + { + if (CriticalCloseTime == -1) + return; + HeartLog.LogException(ex, callingType, (callerId != ulong.MaxValue ? $"Shared exception from {callerId}: " : "") + "Critical "); + CriticalCloseTime = DateTime.Now.Ticks + WarnTimeSeconds * TimeSpan.TicksPerSecond; + } + } +} diff --git a/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/HeartLog.cs b/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/HeartLog.cs new file mode 100644 index 00000000..b2fb81c7 --- /dev/null +++ b/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/HeartLog.cs @@ -0,0 +1,30 @@ +using Sandbox.ModAPI; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Heart_Module.Data.Scripts.HeartModule.ExceptionHandler +{ + public class HeartLog + { + TextWriter writer; + + public HeartLog() + { + writer = MyAPIGateway.Utilities.WriteFileInLocalStorage("debug.log", typeof(HeartLog)); + } + + public void Log(string message) + { + writer.WriteLineAsync($"{DateTime.Now:HH:mm:ss}: {message}"); + } + + public void LogException(Exception ex, Type callingType, string prefix = "") + { + Log(prefix + $"Exception in {callingType.FullName}! {ex.Message}\n{ex.StackTrace}"); + } + } +} diff --git a/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/NetworkedError.cs b/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/NetworkedError.cs new file mode 100644 index 00000000..f20a1db1 --- /dev/null +++ b/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/NetworkedError.cs @@ -0,0 +1,25 @@ +using Heart_Module.Data.Scripts.HeartModule.ErrorHandler; +using Heart_Module.Data.Scripts.HeartModule.Network; +using ProtoBuf; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Heart_Module.Data.Scripts.HeartModule.ExceptionHandler +{ + public class NetworkedError : PacketBase + { + [ProtoMember(21)] Exception Exception; + [ProtoMember(22)] bool IsCritical; + + public override void Received(ulong SenderSteamId) + { + if (IsCritical) + CriticalHandle.ThrowCriticalException(Exception, typeof(NetworkedError), SenderSteamId); + else + SoftHandle.RaiseException(Exception, callerId: SenderSteamId); + } + } +} diff --git a/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/SoftHandle.cs b/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/SoftHandle.cs index b7b7fa47..8a906c1f 100644 --- a/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/SoftHandle.cs +++ b/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/SoftHandle.cs @@ -1,24 +1,32 @@ -using Sandbox.ModAPI; +using Heart_Module.Data.Scripts.HeartModule.ExceptionHandler; +using Sandbox.ModAPI; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using VRage.Scripting; using VRage.Utils; namespace Heart_Module.Data.Scripts.HeartModule.ErrorHandler { public class SoftHandle { - public static void RaiseException(string message) + public static void RaiseException(string message, Type callingType = null, ulong callerId = ulong.MaxValue) { MyAPIGateway.Utilities.ShowNotification(message); - MyLog.Default.WriteLineAndConsole(message); + HeartLog.LogException(new Exception(message), callingType ?? typeof(SoftHandle), callerId != ulong.MaxValue ? $"Shared exception from {callerId}: " : ""); + } + + public static void RaiseException(Exception exception, Type callingType = null, ulong callerId = ulong.MaxValue) + { + MyAPIGateway.Utilities.ShowNotification(exception.Message); + HeartLog.LogException(exception, callingType ?? typeof(SoftHandle), callerId != ulong.MaxValue ? $"Shared exception from {callerId}: " : ""); } public static void RaiseSyncException(string message) { - RaiseException("Client is out of sync!\n"+message); + RaiseException("Client is out of sync!\n" + message); } } } diff --git a/Heart Module/Data/Scripts/HeartModule/HeartData.cs b/Heart Module/Data/Scripts/HeartModule/HeartData.cs new file mode 100644 index 00000000..a4e07012 --- /dev/null +++ b/Heart Module/Data/Scripts/HeartModule/HeartData.cs @@ -0,0 +1,15 @@ +using Heart_Module.Data.Scripts.HeartModule.ExceptionHandler; +using Heart_Module.Data.Scripts.HeartModule.Network; + +namespace Heart_Module.Data.Scripts.HeartModule +{ + internal class HeartData + { + public static HeartData I; + public const ushort HeartNetworkId = (ushort)(65198749845 % ushort.MaxValue); + + public bool IsClosing = false; + public HeartNetwork Net = new HeartNetwork(); + public HeartLog Log = new HeartLog(); + } +} diff --git a/Heart Module/Data/Scripts/HeartModule/HeartLoad.cs b/Heart Module/Data/Scripts/HeartModule/HeartLoad.cs new file mode 100644 index 00000000..080054c4 --- /dev/null +++ b/Heart Module/Data/Scripts/HeartModule/HeartLoad.cs @@ -0,0 +1,52 @@ +using Heart_Module.Data.Scripts.HeartModule.ErrorHandler; +using Heart_Module.Data.Scripts.HeartModule.ExceptionHandler; +using System; +using System.Diagnostics; +using System.Text; +using System.Threading.Tasks; +using VRage.Game.Components; + +namespace Heart_Module.Data.Scripts.HeartModule +{ + [MySessionComponentDescriptor(MyUpdateOrder.AfterSimulation)] + internal class HeartLoad : MySessionComponentBase + { + CriticalHandle handle; + + + public override void LoadData() + { + HeartData.I.Log.Log($"Start loading core..."); + + HeartData.I = new HeartData(); + handle = new CriticalHandle(); + handle.LoadData(); + HeartData.I.Net.LoadData(); + + HeartData.I.Log.Log($"Finished loading core."); + } + + public override void UpdateAfterSimulation() + { + try + { + if (HeartData.I.IsClosing) + return; + + handle.Update(); + } + catch (Exception ex) + { + SoftHandle.RaiseException(ex); + } + } + + protected override void UnloadData() + { + handle.UnloadData(); + HeartData.I.Net.UnloadData(); + HeartData.I.Log.Log($"Closing core, log finishes here."); + HeartData.I = null; + } + } +} diff --git a/Heart Module/Data/Scripts/HeartModule/Network/HeartNetwork_Session.cs b/Heart Module/Data/Scripts/HeartModule/Network/HeartNetwork.cs similarity index 73% rename from Heart Module/Data/Scripts/HeartModule/Network/HeartNetwork_Session.cs rename to Heart Module/Data/Scripts/HeartModule/Network/HeartNetwork.cs index 02968015..3e8f0a5b 100644 --- a/Heart Module/Data/Scripts/HeartModule/Network/HeartNetwork_Session.cs +++ b/Heart Module/Data/Scripts/HeartModule/Network/HeartNetwork.cs @@ -1,4 +1,5 @@ -using Sandbox.ModAPI; +using Heart_Module.Data.Scripts.HeartModule.ErrorHandler; +using Sandbox.ModAPI; using System; using System.Collections.Generic; using System.Linq; @@ -10,23 +11,16 @@ namespace Heart_Module.Data.Scripts.HeartModule.Network { - [MySessionComponentDescriptor(MyUpdateOrder.AfterSimulation)] - public class HeartNetwork_Session : MySessionComponentBase + public class HeartNetwork { - public const ushort HeartNetworkId = (ushort)(65198749845 % ushort.MaxValue); - - public static HeartNetwork_Session Net; - - public override void LoadData() + public void LoadData() { - Net = this; - MyAPIGateway.Multiplayer.RegisterSecureMessageHandler(HeartNetworkId, ReceivedPacket); + MyAPIGateway.Multiplayer.RegisterSecureMessageHandler(HeartData.HeartNetworkId, ReceivedPacket); } - protected override void UnloadData() + public void UnloadData() { - Net = null; - MyAPIGateway.Multiplayer.UnregisterSecureMessageHandler(HeartNetworkId, ReceivedPacket); + MyAPIGateway.Multiplayer.UnregisterSecureMessageHandler(HeartData.HeartNetworkId, ReceivedPacket); } void ReceivedPacket(ushort channelId, byte[] serialized, ulong senderSteamId, bool isSenderServer) @@ -38,7 +32,7 @@ void ReceivedPacket(ushort channelId, byte[] serialized, ulong senderSteamId, bo } catch (Exception ex) { - MyLog.Default.WriteLineAndConsole($"Exception in network deserialize: {ex.Message}\n{ex.StackTrace}"); + SoftHandle.RaiseException(ex, typeof(HeartNetwork)); } } @@ -65,7 +59,7 @@ void RelayToClients(PacketBase packet, ulong senderSteamId = 0, byte[] serialize if (serialized == null) // only serialize if necessary, and only once. serialized = MyAPIGateway.Utilities.SerializeToBinary(packet); - MyAPIGateway.Multiplayer.SendMessageTo(HeartNetworkId, serialized, p.SteamUserId); + MyAPIGateway.Multiplayer.SendMessageTo(HeartData.HeartNetworkId, serialized, p.SteamUserId); } TempPlayers.Clear(); diff --git a/Heart Module/Data/Scripts/HeartModule/Network/PacketBase.cs b/Heart Module/Data/Scripts/HeartModule/Network/PacketBase.cs index 024a6162..655a5ddd 100644 --- a/Heart Module/Data/Scripts/HeartModule/Network/PacketBase.cs +++ b/Heart Module/Data/Scripts/HeartModule/Network/PacketBase.cs @@ -9,6 +9,7 @@ namespace Heart_Module.Data.Scripts.HeartModule.Network { [ProtoInclude(1, typeof(SerializableProjectile))] + [ProtoInclude(2, typeof(ExceptionHandler.NetworkedError))] [ProtoContract(UseProtoMembersOnly = true)] public abstract partial class PacketBase { diff --git a/Heart Module/Data/Scripts/HeartModule/Projectiles/ProjectileManager.cs b/Heart Module/Data/Scripts/HeartModule/Projectiles/ProjectileManager.cs index 4ed0f7db..ea897e20 100644 --- a/Heart Module/Data/Scripts/HeartModule/Projectiles/ProjectileManager.cs +++ b/Heart Module/Data/Scripts/HeartModule/Projectiles/ProjectileManager.cs @@ -1,4 +1,5 @@ -using Heart_Module.Data.Scripts.HeartModule.Network; +using Heart_Module.Data.Scripts.HeartModule.ErrorHandler; +using Heart_Module.Data.Scripts.HeartModule.Network; using Heart_Module.Data.Scripts.HeartModule.Projectiles.StandardClasses; using Sandbox.ModAPI; using System; @@ -78,7 +79,7 @@ public override void UpdateAfterSimulation() } catch (Exception ex) { - MyLog.Default.WriteLineAndConsole(ex.Message + " at \n" + ex.StackTrace); + SoftHandle.RaiseException(ex); } } j++; @@ -175,7 +176,7 @@ public void AddProjectile(Projectile projectile) SyncProjectile(projectile); } - public void SyncProjectile(Projectile projectile) => HeartNetwork_Session.Net.SendToEveryone(projectile.AsSerializable()); + public void SyncProjectile(Projectile projectile) => HeartData.I.Net.SendToEveryone(projectile.AsSerializable()); public Projectile GetProjectile(uint id) => ActiveProjectiles.GetValueOrDefault(id, null); public bool IsIdAvailable(uint id) => !ActiveProjectiles.ContainsKey(id); From a63500d7e4a307ca4276cd39692a44eb2867dd08 Mon Sep 17 00:00:00 2001 From: Aristeas <94058548+Jnick-24@users.noreply.github.com> Date: Fri, 5 Jan 2024 18:44:42 -0600 Subject: [PATCH 2/4] Sync work for errors --- .../ExceptionHandler/CriticalHandle.cs | 30 ++++++++++++------- .../HeartModule/ExceptionHandler/HeartLog.cs | 5 +++- .../ExceptionHandler/NetworkedError.cs | 12 +++++--- .../ExceptionHandler/SoftHandle.cs | 11 ++++--- .../Data/Scripts/HeartModule/HeartData.cs | 2 +- .../Data/Scripts/HeartModule/HeartLoad.cs | 10 ++++--- .../HeartModule/Projectiles/DamageHandler.cs | 5 +++- .../Projectiles/ProjectileManager.cs | 8 +++-- .../Weapons/Setup/Adding/SorterWeaponLogic.cs | 3 -- 9 files changed, 56 insertions(+), 30 deletions(-) diff --git a/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/CriticalHandle.cs b/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/CriticalHandle.cs index e404ad02..5b6454b6 100644 --- a/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/CriticalHandle.cs +++ b/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/CriticalHandle.cs @@ -6,6 +6,7 @@ using System.Text; using System.Threading.Tasks; using VRage.Game.Components; +using VRage.Utils; namespace Heart_Module.Data.Scripts.HeartModule.ExceptionHandler { @@ -15,13 +16,13 @@ public class CriticalHandle const int WarnTimeSeconds = 20; private static CriticalHandle I; private long CriticalCloseTime = -1; + private Exception Exception; public void LoadData() { I = this; } - int i = 0; public void Update() { if (CriticalCloseTime == -1) @@ -29,15 +30,16 @@ public void Update() double secondsRemaining = Math.Round((CriticalCloseTime - DateTime.Now.Ticks) / (double)TimeSpan.TicksPerSecond, 1); if (secondsRemaining <= 0) - MyVisualScriptLogicProvider.SessionClose(1000, false, true); - - MyAPIGateway.Utilities.ShowNotification($"HeartMod CRITICAL ERROR - Shutting down in {secondsRemaining}s", 1000/60); - i++; - if (i >= 60) { - i = 0; - MyAPIGateway.Utilities.ShowMessage("HeartMod", $"CRITICAL ERROR - Shutting down in {secondsRemaining} seconds."); + CriticalCloseTime = -1; + if (!MyAPIGateway.Utilities.IsDedicated) + MyVisualScriptLogicProvider.SessionClose(1000, false, true); + else + throw Exception; } + + if (!MyAPIGateway.Utilities.IsDedicated) + MyAPIGateway.Utilities.ShowNotification($"HeartMod CRITICAL ERROR - Shutting down in {secondsRemaining}s", 1000/60); } public void UnloadData() @@ -52,10 +54,18 @@ public static void ThrowCriticalException(Exception ex, Type callingType, ulong private void m_ThrowCriticalException(Exception ex, Type callingType, ulong callerId = ulong.MaxValue) { - if (CriticalCloseTime == -1) + HeartData.I.IsSuspended = true; + if (CriticalCloseTime != -1) return; - HeartLog.LogException(ex, callingType, (callerId != ulong.MaxValue ? $"Shared exception from {callerId}: " : "") + "Critical "); + + Exception = ex; + HeartData.I.Log.LogException(ex, callingType, (callerId != ulong.MaxValue ? $"Shared exception from {callerId}: " : "") + "Critical "); + MyAPIGateway.Utilities.ShowMessage("HeartMod", $"CRITICAL ERROR - Shutting down in {WarnTimeSeconds} seconds."); + MyLog.Default.WriteLineAndConsole($"HeartMod: CRITICAL ERROR - Shutting down in {WarnTimeSeconds} seconds."); CriticalCloseTime = DateTime.Now.Ticks + WarnTimeSeconds * TimeSpan.TicksPerSecond; + + if (MyAPIGateway.Session.IsServer) + HeartData.I.Net.SendToEveryone(new NetworkedError(ex, true)); } } } diff --git a/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/HeartLog.cs b/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/HeartLog.cs index b2fb81c7..9ce05494 100644 --- a/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/HeartLog.cs +++ b/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/HeartLog.cs @@ -15,11 +15,14 @@ public class HeartLog public HeartLog() { writer = MyAPIGateway.Utilities.WriteFileInLocalStorage("debug.log", typeof(HeartLog)); + writer.WriteLine("LogStart"); + writer.Flush(); } public void Log(string message) { - writer.WriteLineAsync($"{DateTime.Now:HH:mm:ss}: {message}"); + writer.WriteLine($"{DateTime.Now:HH:mm:ss}: {message}"); + writer.Flush(); } public void LogException(Exception ex, Type callingType, string prefix = "") diff --git a/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/NetworkedError.cs b/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/NetworkedError.cs index f20a1db1..079d1adc 100644 --- a/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/NetworkedError.cs +++ b/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/NetworkedError.cs @@ -2,10 +2,7 @@ using Heart_Module.Data.Scripts.HeartModule.Network; using ProtoBuf; using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using VRage.Utils; namespace Heart_Module.Data.Scripts.HeartModule.ExceptionHandler { @@ -14,6 +11,13 @@ public class NetworkedError : PacketBase [ProtoMember(21)] Exception Exception; [ProtoMember(22)] bool IsCritical; + public NetworkedError() { } + public NetworkedError(Exception e, bool IsCritical) + { + Exception = e; + this.IsCritical = IsCritical; + } + public override void Received(ulong SenderSteamId) { if (IsCritical) diff --git a/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/SoftHandle.cs b/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/SoftHandle.cs index 8a906c1f..1fe38433 100644 --- a/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/SoftHandle.cs +++ b/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/SoftHandle.cs @@ -14,14 +14,17 @@ public class SoftHandle { public static void RaiseException(string message, Type callingType = null, ulong callerId = ulong.MaxValue) { - MyAPIGateway.Utilities.ShowNotification(message); - HeartLog.LogException(new Exception(message), callingType ?? typeof(SoftHandle), callerId != ulong.MaxValue ? $"Shared exception from {callerId}: " : ""); + MyAPIGateway.Utilities.ShowNotification("Minor Exception: " + message); + Exception soft = new Exception(message); + HeartData.I.Log.LogException(soft, callingType ?? typeof(SoftHandle), callerId != ulong.MaxValue ? $"Shared exception from {callerId}: " : ""); + if (MyAPIGateway.Session.IsServer) + HeartData.I.Net.SendToEveryone(new NetworkedError(soft, false)); } public static void RaiseException(Exception exception, Type callingType = null, ulong callerId = ulong.MaxValue) { - MyAPIGateway.Utilities.ShowNotification(exception.Message); - HeartLog.LogException(exception, callingType ?? typeof(SoftHandle), callerId != ulong.MaxValue ? $"Shared exception from {callerId}: " : ""); + MyAPIGateway.Utilities.ShowNotification("Minor Exception: " + exception.Message); + HeartData.I.Log.LogException(exception, callingType ?? typeof(SoftHandle), callerId != ulong.MaxValue ? $"Shared exception from {callerId}: " : ""); } public static void RaiseSyncException(string message) diff --git a/Heart Module/Data/Scripts/HeartModule/HeartData.cs b/Heart Module/Data/Scripts/HeartModule/HeartData.cs index a4e07012..0abc1aba 100644 --- a/Heart Module/Data/Scripts/HeartModule/HeartData.cs +++ b/Heart Module/Data/Scripts/HeartModule/HeartData.cs @@ -8,7 +8,7 @@ internal class HeartData public static HeartData I; public const ushort HeartNetworkId = (ushort)(65198749845 % ushort.MaxValue); - public bool IsClosing = false; + public bool IsSuspended = false; public HeartNetwork Net = new HeartNetwork(); public HeartLog Log = new HeartLog(); } diff --git a/Heart Module/Data/Scripts/HeartModule/HeartLoad.cs b/Heart Module/Data/Scripts/HeartModule/HeartLoad.cs index 080054c4..a1130159 100644 --- a/Heart Module/Data/Scripts/HeartModule/HeartLoad.cs +++ b/Heart Module/Data/Scripts/HeartModule/HeartLoad.cs @@ -16,13 +16,14 @@ internal class HeartLoad : MySessionComponentBase public override void LoadData() { + HeartData.I = new HeartData(); HeartData.I.Log.Log($"Start loading core..."); - HeartData.I = new HeartData(); handle = new CriticalHandle(); handle.LoadData(); HeartData.I.Net.LoadData(); + HeartData.I.IsSuspended = false; HeartData.I.Log.Log($"Finished loading core."); } @@ -30,15 +31,16 @@ public override void UpdateAfterSimulation() { try { - if (HeartData.I.IsClosing) + if (HeartData.I.IsSuspended) return; - - handle.Update(); } catch (Exception ex) { SoftHandle.RaiseException(ex); } + + // This has the power to shut down the server. Afaik the only way to do this is throwing an exception. Yeah. + handle.Update(); } protected override void UnloadData() diff --git a/Heart Module/Data/Scripts/HeartModule/Projectiles/DamageHandler.cs b/Heart Module/Data/Scripts/HeartModule/Projectiles/DamageHandler.cs index 40201a46..4fe9dae2 100644 --- a/Heart Module/Data/Scripts/HeartModule/Projectiles/DamageHandler.cs +++ b/Heart Module/Data/Scripts/HeartModule/Projectiles/DamageHandler.cs @@ -1,4 +1,5 @@ -using Sandbox.ModAPI; +using Heart_Module.Data.Scripts.HeartModule.ExceptionHandler; +using Sandbox.ModAPI; using System; using System.Collections.Generic; using System.Linq; @@ -59,6 +60,8 @@ private void m_Update() private void m_QueueEvent(DamageEvent damageEvent) { + if (MyAPIGateway.Session.IsServer) + CriticalHandle.ThrowCriticalException(new Exception("Testing"), typeof(DamageHandler)); DamageEvents.Add(damageEvent); } diff --git a/Heart Module/Data/Scripts/HeartModule/Projectiles/ProjectileManager.cs b/Heart Module/Data/Scripts/HeartModule/Projectiles/ProjectileManager.cs index ea897e20..9b1a2b00 100644 --- a/Heart Module/Data/Scripts/HeartModule/Projectiles/ProjectileManager.cs +++ b/Heart Module/Data/Scripts/HeartModule/Projectiles/ProjectileManager.cs @@ -57,7 +57,9 @@ private void TempChatCommandHandler(ulong sender, string messageText, ref bool s int j = 0; public override void UpdateAfterSimulation() { - if (j >= 1 && MyAPIGateway.Session.IsServer) + if (HeartData.I.IsSuspended) return; + + if (j >= 100 && MyAPIGateway.Session.IsServer) { j = 0; try @@ -79,7 +81,7 @@ public override void UpdateAfterSimulation() } catch (Exception ex) { - SoftHandle.RaiseException(ex); + SoftHandle.RaiseException(ex, typeof(ProjectileManager)); } } j++; @@ -141,6 +143,8 @@ public override void UpdatingStopped() public override void Draw() { + if (HeartData.I.IsSuspended) return; + if (MyAPIGateway.Utilities.IsDedicated) return; diff --git a/Heart Module/Data/Scripts/HeartModule/Weapons/Setup/Adding/SorterWeaponLogic.cs b/Heart Module/Data/Scripts/HeartModule/Weapons/Setup/Adding/SorterWeaponLogic.cs index 692bac47..6ec373a8 100644 --- a/Heart Module/Data/Scripts/HeartModule/Weapons/Setup/Adding/SorterWeaponLogic.cs +++ b/Heart Module/Data/Scripts/HeartModule/Weapons/Setup/Adding/SorterWeaponLogic.cs @@ -73,9 +73,6 @@ public bool Terminal_Heart_Shoot } } - - public float Terminal_ExampleFloat { get; set; } - public override void Close() { base.Close(); From 17386809e8120445d2ba810cef39762758bd08dd Mon Sep 17 00:00:00 2001 From: Aristeas <94058548+Jnick-24@users.noreply.github.com> Date: Fri, 5 Jan 2024 20:41:07 -0600 Subject: [PATCH 3/4] Lowering network load 400kb/s -> 200 kb/s --- .../ExceptionHandler/CriticalHandle.cs | 10 +-- .../HeartModule/ExceptionHandler/HeartLog.cs | 6 +- .../ExceptionHandler/NetworkedError.cs | 1 - .../ExceptionHandler/SoftHandle.cs | 10 +-- .../Data/Scripts/HeartModule/HeartLoad.cs | 5 +- .../HeartModule/Network/HeartNetwork.cs | 5 -- .../Scripts/HeartModule/Network/PacketBase.cs | 5 -- .../HeartModule/Projectiles/DamageHandler.cs | 10 +-- .../HeartModule/Projectiles/Projectile.cs | 88 ++++++++++++------- .../Projectiles/ProjectileManager.cs | 33 +++---- .../StandardClasses/SerializableProjectile.cs | 26 +++--- .../SerializableProjectileDefinition.cs | 6 +- ...art_Logger.cs => Heart_Logger.cs.disabled} | 6 +- .../Weapons/Setup/Adding/SorterWeaponLogic.cs | 5 +- .../Adding/SorterWeaponTerminalControls.cs | 11 +-- .../Setup/Hiding/ConveyorSorterLogic.cs | 1 - .../Setup/Hiding/HideSorterControls.cs | 4 +- .../Setup/Hiding/TerminalChainedDelegate.cs | 4 +- 18 files changed, 108 insertions(+), 128 deletions(-) rename Heart Module/Data/Scripts/HeartModule/Utility/{Heart_Logger.cs => Heart_Logger.cs.disabled} (99%) diff --git a/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/CriticalHandle.cs b/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/CriticalHandle.cs index 5b6454b6..290e26cf 100644 --- a/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/CriticalHandle.cs +++ b/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/CriticalHandle.cs @@ -1,16 +1,11 @@ using Sandbox.Game; using Sandbox.ModAPI; using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using VRage.Game.Components; using VRage.Utils; namespace Heart_Module.Data.Scripts.HeartModule.ExceptionHandler { - + public class CriticalHandle { const int WarnTimeSeconds = 20; @@ -39,7 +34,7 @@ public void Update() } if (!MyAPIGateway.Utilities.IsDedicated) - MyAPIGateway.Utilities.ShowNotification($"HeartMod CRITICAL ERROR - Shutting down in {secondsRemaining}s", 1000/60); + MyAPIGateway.Utilities.ShowNotification($"HeartMod CRITICAL ERROR - Shutting down in {secondsRemaining}s", 1000 / 60); } public void UnloadData() @@ -55,6 +50,7 @@ public static void ThrowCriticalException(Exception ex, Type callingType, ulong private void m_ThrowCriticalException(Exception ex, Type callingType, ulong callerId = ulong.MaxValue) { HeartData.I.IsSuspended = true; + HeartData.I.Log.Log("Start Throw Critical Exception " + CriticalCloseTime); if (CriticalCloseTime != -1) return; diff --git a/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/HeartLog.cs b/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/HeartLog.cs index 9ce05494..607b4994 100644 --- a/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/HeartLog.cs +++ b/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/HeartLog.cs @@ -1,10 +1,6 @@ using Sandbox.ModAPI; using System; -using System.Collections.Generic; using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Heart_Module.Data.Scripts.HeartModule.ExceptionHandler { @@ -27,6 +23,8 @@ public void Log(string message) public void LogException(Exception ex, Type callingType, string prefix = "") { + if (ex == null) + return; Log(prefix + $"Exception in {callingType.FullName}! {ex.Message}\n{ex.StackTrace}"); } } diff --git a/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/NetworkedError.cs b/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/NetworkedError.cs index 079d1adc..a9c34911 100644 --- a/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/NetworkedError.cs +++ b/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/NetworkedError.cs @@ -2,7 +2,6 @@ using Heart_Module.Data.Scripts.HeartModule.Network; using ProtoBuf; using System; -using VRage.Utils; namespace Heart_Module.Data.Scripts.HeartModule.ExceptionHandler { diff --git a/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/SoftHandle.cs b/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/SoftHandle.cs index 1fe38433..83ec6d83 100644 --- a/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/SoftHandle.cs +++ b/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/SoftHandle.cs @@ -1,12 +1,6 @@ using Heart_Module.Data.Scripts.HeartModule.ExceptionHandler; using Sandbox.ModAPI; using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using VRage.Scripting; -using VRage.Utils; namespace Heart_Module.Data.Scripts.HeartModule.ErrorHandler { @@ -14,7 +8,7 @@ public class SoftHandle { public static void RaiseException(string message, Type callingType = null, ulong callerId = ulong.MaxValue) { - MyAPIGateway.Utilities.ShowNotification("Minor Exception: " + message); + //MyAPIGateway.Utilities.ShowNotification("Minor Exception: " + message); Exception soft = new Exception(message); HeartData.I.Log.LogException(soft, callingType ?? typeof(SoftHandle), callerId != ulong.MaxValue ? $"Shared exception from {callerId}: " : ""); if (MyAPIGateway.Session.IsServer) @@ -23,7 +17,7 @@ public static void RaiseException(string message, Type callingType = null, ulong public static void RaiseException(Exception exception, Type callingType = null, ulong callerId = ulong.MaxValue) { - MyAPIGateway.Utilities.ShowNotification("Minor Exception: " + exception.Message); + //MyAPIGateway.Utilities.ShowNotification("Minor Exception: " + exception.Message); HeartData.I.Log.LogException(exception, callingType ?? typeof(SoftHandle), callerId != ulong.MaxValue ? $"Shared exception from {callerId}: " : ""); } diff --git a/Heart Module/Data/Scripts/HeartModule/HeartLoad.cs b/Heart Module/Data/Scripts/HeartModule/HeartLoad.cs index a1130159..2ad14eba 100644 --- a/Heart Module/Data/Scripts/HeartModule/HeartLoad.cs +++ b/Heart Module/Data/Scripts/HeartModule/HeartLoad.cs @@ -1,9 +1,6 @@ using Heart_Module.Data.Scripts.HeartModule.ErrorHandler; using Heart_Module.Data.Scripts.HeartModule.ExceptionHandler; using System; -using System.Diagnostics; -using System.Text; -using System.Threading.Tasks; using VRage.Game.Components; namespace Heart_Module.Data.Scripts.HeartModule @@ -12,7 +9,7 @@ namespace Heart_Module.Data.Scripts.HeartModule internal class HeartLoad : MySessionComponentBase { CriticalHandle handle; - + public override void LoadData() { diff --git a/Heart Module/Data/Scripts/HeartModule/Network/HeartNetwork.cs b/Heart Module/Data/Scripts/HeartModule/Network/HeartNetwork.cs index 3e8f0a5b..251b3ded 100644 --- a/Heart Module/Data/Scripts/HeartModule/Network/HeartNetwork.cs +++ b/Heart Module/Data/Scripts/HeartModule/Network/HeartNetwork.cs @@ -2,12 +2,7 @@ using Sandbox.ModAPI; using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using VRage.Game.Components; using VRage.Game.ModAPI; -using VRage.Utils; namespace Heart_Module.Data.Scripts.HeartModule.Network { diff --git a/Heart Module/Data/Scripts/HeartModule/Network/PacketBase.cs b/Heart Module/Data/Scripts/HeartModule/Network/PacketBase.cs index 655a5ddd..4f965171 100644 --- a/Heart Module/Data/Scripts/HeartModule/Network/PacketBase.cs +++ b/Heart Module/Data/Scripts/HeartModule/Network/PacketBase.cs @@ -1,10 +1,5 @@ using Heart_Module.Data.Scripts.HeartModule.Projectiles.StandardClasses; using ProtoBuf; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Heart_Module.Data.Scripts.HeartModule.Network { diff --git a/Heart Module/Data/Scripts/HeartModule/Projectiles/DamageHandler.cs b/Heart Module/Data/Scripts/HeartModule/Projectiles/DamageHandler.cs index 4fe9dae2..c73d2c2b 100644 --- a/Heart Module/Data/Scripts/HeartModule/Projectiles/DamageHandler.cs +++ b/Heart Module/Data/Scripts/HeartModule/Projectiles/DamageHandler.cs @@ -2,12 +2,8 @@ using Sandbox.ModAPI; using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using VRage.Game; using VRage.Game.ModAPI; -using VRage.Utils; using VRageMath; namespace Heart_Module.Data.Scripts.HeartModule.Projectiles @@ -45,13 +41,13 @@ private void m_Update() switch (damageEvent.Type) { case DamageEvent.DamageEntType.Grid: - m_GridDamageHandler((IMyCubeGrid) damageEvent.Entity, damageEvent); + m_GridDamageHandler((IMyCubeGrid)damageEvent.Entity, damageEvent); break; case DamageEvent.DamageEntType.Character: - m_CharacterDamageHandler((IMyCharacter) damageEvent.Entity, damageEvent); + m_CharacterDamageHandler((IMyCharacter)damageEvent.Entity, damageEvent); break; case DamageEvent.DamageEntType.Projectile: - m_ProjectileDamageHandler((Projectile) damageEvent.Entity, damageEvent); + m_ProjectileDamageHandler((Projectile)damageEvent.Entity, damageEvent); break; } } diff --git a/Heart Module/Data/Scripts/HeartModule/Projectiles/Projectile.cs b/Heart Module/Data/Scripts/HeartModule/Projectiles/Projectile.cs index a96a2548..69a3ad3b 100644 --- a/Heart Module/Data/Scripts/HeartModule/Projectiles/Projectile.cs +++ b/Heart Module/Data/Scripts/HeartModule/Projectiles/Projectile.cs @@ -1,14 +1,12 @@ using Heart_Module.Data.Scripts.HeartModule.Debug; using Heart_Module.Data.Scripts.HeartModule.ErrorHandler; using Heart_Module.Data.Scripts.HeartModule.Projectiles.StandardClasses; -using Sandbox.Game.Entities; using Sandbox.ModAPI; using System; using System.Collections.Generic; -using VRage.Game; -using VRage.Game.Entity; using VRage.Game.ModAPI; using VRage.ModAPI; +using VRage.Utils; using VRageMath; namespace Heart_Module.Data.Scripts.HeartModule.Projectiles @@ -23,12 +21,12 @@ public partial class Projectile public Vector3D InheritedVelocity; #endregion - public long Firer; - public Vector3D Position; - public Vector3D Direction; - public float Velocity; - public int RemainingImpacts; - + public long Firer = -1; + public Vector3D Position = Vector3D.Zero; + public Vector3D Direction = Vector3D.Up; + public float Velocity = 0; + public int RemainingImpacts = 0; + public Action Close = (p) => { }; public long LastUpdate { get; private set; } @@ -39,7 +37,7 @@ public partial class Projectile public Projectile() { } public Projectile(SerializableProjectile projectile) - { + { if (!ProjectileManager.I.IsIdAvailable(projectile.Id)) { SoftHandle.RaiseSyncException("Unable to spawn projectile - duplicate Id!"); @@ -47,16 +45,17 @@ public Projectile(SerializableProjectile projectile) return; } - if (!ProjectileDefinitionManager.HasDefinition(projectile.DefinitionId)) + if (!projectile.DefinitionId.HasValue || !ProjectileDefinitionManager.HasDefinition(projectile.DefinitionId.Value)) { SoftHandle.RaiseSyncException("Unable to spawn projectile - invalid DefinitionId!"); + DefinitionId = -1; return; } Id = projectile.Id; - DefinitionId = projectile.DefinitionId; - Definition = ProjectileDefinitionManager.GetDefinition(projectile.DefinitionId); - Firer = projectile.Firer; + DefinitionId = projectile.DefinitionId.Value; + Definition = ProjectileDefinitionManager.GetDefinition(projectile.DefinitionId.Value); + Firer = projectile.Firer.GetValueOrDefault(0); // TODO fill in from Definition SyncUpdate(projectile); @@ -102,7 +101,7 @@ public void DrawUpdate(float delta) { DebugDraw.AddPoint(Position + (InheritedVelocity + Direction * (Velocity + Definition.PhysicalProjectile.Acceleration * delta)) * delta, Color.Green, 0.000001f); } - + public void CheckHits(float delta) { List intersects = new List(); @@ -137,38 +136,59 @@ public void ProjectileHit(IMyEntity impact) public void SyncUpdate(SerializableProjectile projectile) { - if (DefinitionId != projectile.DefinitionId) - { - SoftHandle.RaiseSyncException("DefinitionId Mismatch!"); - return; - } - QueuedDispose = !projectile.IsActive; LastUpdate = projectile.Timestamp; - float delta = (DateTime.Now.Ticks - LastUpdate) / (float) TimeSpan.TicksPerSecond; + float delta = (DateTime.Now.Ticks - LastUpdate) / (float)TimeSpan.TicksPerSecond; + + // The following values may be null to save network load + if (projectile.Direction.HasValue) + Direction = projectile.Direction.Value; + if (projectile.Position.HasValue) + Position = projectile.Position.Value; + if (projectile.Velocity.HasValue) + Velocity = projectile.Velocity.Value; + if (projectile.InheritedVelocity.HasValue) + InheritedVelocity = projectile.InheritedVelocity.Value; + if (projectile.RemainingImpacts.HasValue) + RemainingImpacts = projectile.RemainingImpacts.Value; - Direction = projectile.Direction; - Position = projectile.Position; - Velocity = projectile.Velocity; - InheritedVelocity = projectile.InheritedVelocity; - RemainingImpacts = projectile.RemainingImpacts; TickUpdate(delta); } - public SerializableProjectile AsSerializable() + /// + /// Returns the projectile as a network-ready projectile info class. 0 = max detail, 2+ = min detail + /// + /// + /// + public SerializableProjectile AsSerializable(int DetailLevel = 1) { - return new SerializableProjectile() + SerializableProjectile projectile = new SerializableProjectile() { IsActive = !QueuedDispose, Id = Id, - DefinitionId = DefinitionId, - Position = Position, - Direction = Direction, - InheritedVelocity = InheritedVelocity, - Velocity = Velocity, Timestamp = DateTime.Now.Ticks, }; + + switch (DetailLevel) + { + case 0: + projectile.DefinitionId = DefinitionId; + projectile.Position = Position; + projectile.Direction = Direction; + projectile.InheritedVelocity = InheritedVelocity; + projectile.Velocity = Velocity; + break; + case 1: + projectile.Position = Position; + if (Definition.Guidance.Length > 0) + projectile.Direction = Direction; + if (Definition.PhysicalProjectile.Acceleration > 0) + projectile.Velocity = Velocity; + break; + } + + return projectile; } public void QueueDispose() diff --git a/Heart Module/Data/Scripts/HeartModule/Projectiles/ProjectileManager.cs b/Heart Module/Data/Scripts/HeartModule/Projectiles/ProjectileManager.cs index 9b1a2b00..651ef4dc 100644 --- a/Heart Module/Data/Scripts/HeartModule/Projectiles/ProjectileManager.cs +++ b/Heart Module/Data/Scripts/HeartModule/Projectiles/ProjectileManager.cs @@ -1,5 +1,4 @@ using Heart_Module.Data.Scripts.HeartModule.ErrorHandler; -using Heart_Module.Data.Scripts.HeartModule.Network; using Heart_Module.Data.Scripts.HeartModule.Projectiles.StandardClasses; using Sandbox.ModAPI; using System; @@ -7,7 +6,6 @@ using System.Diagnostics; using System.Linq; using VRage.Game.Components; -using VRage.Utils; using VRageMath; namespace Heart_Module.Data.Scripts.HeartModule.Projectiles @@ -16,7 +14,7 @@ namespace Heart_Module.Data.Scripts.HeartModule.Projectiles public class ProjectileManager : MySessionComponentBase { public static ProjectileManager I = new ProjectileManager(); - const int MaxProjectilesSynced = 50; // TODO: Sync within range of client & possibly current network load + const int MaxProjectilesSynced = 25; // TODO: Sync within range of client. This value should be ~100kB/s per player private Dictionary ActiveProjectiles = new Dictionary(); private List ProjectileSyncStream = new List(); @@ -59,7 +57,7 @@ public override void UpdateAfterSimulation() { if (HeartData.I.IsSuspended) return; - if (j >= 100 && MyAPIGateway.Session.IsServer) + if (j >= 1 && MyAPIGateway.Session.IsServer) { j = 0; try @@ -77,7 +75,7 @@ public override void UpdateAfterSimulation() Firer = MyAPIGateway.Session.Player?.Controller.ControlledEntity.Entity.EntityId ?? -1, }); AddProjectile(p); - MyLog.Default.WriteLineToConsole($"Projectiles: {ActiveProjectiles.Count}"); + //MyLog.Default.WriteLineToConsole($"Projectiles: {ActiveProjectiles.Count}"); } catch (Exception ex) { @@ -86,7 +84,7 @@ public override void UpdateAfterSimulation() } j++; - delta = clock.ElapsedTicks / (float) TimeSpan.TicksPerSecond; + delta = clock.ElapsedTicks / (float)TimeSpan.TicksPerSecond; // Tick projectiles foreach (var projectile in ActiveProjectiles.Values) @@ -101,7 +99,7 @@ public override void UpdateAfterSimulation() { //MyAPIGateway.Utilities.ShowMessage("Heart", $"Closing projectile {projectile.Id}. Age: {projectile.Age} "); if (MyAPIGateway.Session.IsServer) - SyncProjectile(projectile); + SyncProjectile(projectile, 2); projectile.Close.Invoke(projectile); } QueuedCloseProjectiles.Clear(); @@ -116,7 +114,7 @@ public override void UpdateAfterSimulation() if (ActiveProjectiles.ContainsKey(id)) { - SyncProjectile(ActiveProjectiles[id]); + SyncProjectile(ActiveProjectiles[id], 1); numSyncs++; } } @@ -129,8 +127,11 @@ public override void UpdateAfterSimulation() else ProjectileSyncStream.RemoveRange(0, MaxProjectilesSynced); } - MyAPIGateway.Utilities.ShowNotification("Projectiles: " + ActiveProjectiles.Count, 1000/60); - + else + { + MyAPIGateway.Utilities.ShowNotification("Projectiles: " + ActiveProjectiles.Count, 1000 / 60); + } + DamageHandler.Update(); clock.Restart(); @@ -147,7 +148,7 @@ public override void Draw() if (MyAPIGateway.Utilities.IsDedicated) return; - + delta = clock.ElapsedTicks / (float)TimeSpan.TicksPerSecond; // Triggered every frame, avoids jitter in projectiles foreach (var projectile in ActiveProjectiles.Values) @@ -156,12 +157,12 @@ public override void Draw() } } - public void ClientSyncProjectile(SerializableProjectile projectile) + public void UpdateProjectile(SerializableProjectile projectile) { if (MyAPIGateway.Session.IsServer) return; - if (IsIdAvailable(projectile.Id) && projectile.IsActive) + if (IsIdAvailable(projectile.Id) && projectile.IsActive && projectile.DefinitionId.HasValue) AddProjectile(new Projectile(projectile)); else GetProjectile(projectile.Id)?.SyncUpdate(projectile); @@ -169,7 +170,7 @@ public void ClientSyncProjectile(SerializableProjectile projectile) public void AddProjectile(Projectile projectile) { - if (projectile == null) return; // ??? + if (projectile == null || projectile.DefinitionId == -1) return; // Ensure that invalid projectiles don't get added NextId++; while (!IsIdAvailable(NextId)) @@ -177,10 +178,10 @@ public void AddProjectile(Projectile projectile) projectile.SetId(NextId); projectile.Close += (p) => ActiveProjectiles.Remove(p.Id); ActiveProjectiles.Add(projectile.Id, projectile); - SyncProjectile(projectile); + SyncProjectile(projectile, 0); } - public void SyncProjectile(Projectile projectile) => HeartData.I.Net.SendToEveryone(projectile.AsSerializable()); + public void SyncProjectile(Projectile projectile, int DetailLevel = 1) => HeartData.I.Net.SendToEveryone(projectile.AsSerializable(DetailLevel)); public Projectile GetProjectile(uint id) => ActiveProjectiles.GetValueOrDefault(id, null); public bool IsIdAvailable(uint id) => !ActiveProjectiles.ContainsKey(id); diff --git a/Heart Module/Data/Scripts/HeartModule/Projectiles/StandardClasses/SerializableProjectile.cs b/Heart Module/Data/Scripts/HeartModule/Projectiles/StandardClasses/SerializableProjectile.cs index 740cfdc6..fb38e8e3 100644 --- a/Heart Module/Data/Scripts/HeartModule/Projectiles/StandardClasses/SerializableProjectile.cs +++ b/Heart Module/Data/Scripts/HeartModule/Projectiles/StandardClasses/SerializableProjectile.cs @@ -2,9 +2,7 @@ using ProtoBuf; using Sandbox.ModAPI; using System.Collections.Generic; -using VRage.Utils; using VRageMath; -using YourName.ModName.Data.Scripts.HeartModule.Utility; namespace Heart_Module.Data.Scripts.HeartModule.Projectiles.StandardClasses { @@ -14,26 +12,28 @@ namespace Heart_Module.Data.Scripts.HeartModule.Projectiles.StandardClasses [ProtoContract] public class SerializableProjectile : PacketBase { - // TODO add close projectile bool + // ProtoMember IDs are high to avoid collisions [ProtoMember(22)] public bool IsActive = true; [ProtoMember(23)] public uint Id; - [ProtoMember(24)] public int DefinitionId; - [ProtoMember(25)] public Vector3D Position; - [ProtoMember(26)] public Vector3D Direction; - [ProtoMember(27)] public Vector3D InheritedVelocity; - [ProtoMember(28)] public float Velocity; - [ProtoMember(29)] public int RemainingImpacts; - [ProtoMember(210)] public Dictionary OverridenValues; [ProtoMember(211)] public long Timestamp; - [ProtoMember(212)] public long Firer; - + + // All non-required values are nullable + [ProtoMember(24)] public int? DefinitionId; + [ProtoMember(25)] public Vector3D? Position; + [ProtoMember(26)] public Vector3D? Direction; + [ProtoMember(27)] public Vector3D? InheritedVelocity; + [ProtoMember(28)] public float? Velocity; + [ProtoMember(29)] public int? RemainingImpacts; + [ProtoMember(210)] public Dictionary OverridenValues; + [ProtoMember(212)] public long? Firer; + public override void Received(ulong SenderSteamId) { if (MyAPIGateway.Session.IsServer) return; - ProjectileManager.I.ClientSyncProjectile(this); + ProjectileManager.I.UpdateProjectile(this); } } } diff --git a/Heart Module/Data/Scripts/HeartModule/Projectiles/StandardClasses/SerializableProjectileDefinition.cs b/Heart Module/Data/Scripts/HeartModule/Projectiles/StandardClasses/SerializableProjectileDefinition.cs index 71d20b8f..3507fb24 100644 --- a/Heart Module/Data/Scripts/HeartModule/Projectiles/StandardClasses/SerializableProjectileDefinition.cs +++ b/Heart Module/Data/Scripts/HeartModule/Projectiles/StandardClasses/SerializableProjectileDefinition.cs @@ -73,10 +73,10 @@ public struct Visual { [ProtoMember(1)] public string Model; [ProtoMember(2)] public string TrailTexture; - [ProtoMember(3)] public float TrailFadeTime; + [ProtoMember(3)] public float TrailFadeTime; [ProtoMember(4)] public string AttachedParticle; [ProtoMember(5)] public string ImpactParticle; - [ProtoMember(6)] public float VisibleChance; + [ProtoMember(6)] public float VisibleChance; } [ProtoContract] @@ -84,7 +84,7 @@ public struct Audio { [ProtoMember(1)] public string TravelSound; [ProtoMember(2)] public string ImpactSound; - [ProtoMember(3)] public float ImpactSoundChance; + [ProtoMember(3)] public float ImpactSoundChance; } [ProtoContract] diff --git a/Heart Module/Data/Scripts/HeartModule/Utility/Heart_Logger.cs b/Heart Module/Data/Scripts/HeartModule/Utility/Heart_Logger.cs.disabled similarity index 99% rename from Heart Module/Data/Scripts/HeartModule/Utility/Heart_Logger.cs rename to Heart Module/Data/Scripts/HeartModule/Utility/Heart_Logger.cs.disabled index a4751c55..732340a5 100644 --- a/Heart Module/Data/Scripts/HeartModule/Utility/Heart_Logger.cs +++ b/Heart Module/Data/Scripts/HeartModule/Utility/Heart_Logger.cs.disabled @@ -1,9 +1,9 @@ -using System; +using ParallelTasks; +using Sandbox.ModAPI; +using System; using System.Collections.Generic; using System.IO; using System.Text; -using ParallelTasks; -using Sandbox.ModAPI; using VRage.Game; using VRage.Game.Components; using VRage.Game.ModAPI; diff --git a/Heart Module/Data/Scripts/HeartModule/Weapons/Setup/Adding/SorterWeaponLogic.cs b/Heart Module/Data/Scripts/HeartModule/Weapons/Setup/Adding/SorterWeaponLogic.cs index 6ec373a8..58cbf010 100644 --- a/Heart Module/Data/Scripts/HeartModule/Weapons/Setup/Adding/SorterWeaponLogic.cs +++ b/Heart Module/Data/Scripts/HeartModule/Weapons/Setup/Adding/SorterWeaponLogic.cs @@ -1,5 +1,4 @@ using Sandbox.Common.ObjectBuilders; -using Sandbox.Game.EntityComponents; using Sandbox.ModAPI; using System; using VRage.Game.Components; @@ -7,8 +6,6 @@ using VRage.ModAPI; using VRage.ObjectBuilders; using VRage.Sync; -using VRageMath; -using YourName.ModName.Data.Scripts.HeartModule.Utility; namespace YourName.ModName.Data.Scripts.HeartModule.Weapons.Setup.Adding { @@ -50,7 +47,7 @@ public override void UpdateOnceBeforeFrame() if (SorterWep.CubeGrid?.Physics == null) return; // ignore ghost/projected grids - // LoadSettings(); // artifact from chets meme + // LoadSettings(); // artifact from chets meme } public float Terminal_ExampleFloat { get; set; } diff --git a/Heart Module/Data/Scripts/HeartModule/Weapons/Setup/Adding/SorterWeaponTerminalControls.cs b/Heart Module/Data/Scripts/HeartModule/Weapons/Setup/Adding/SorterWeaponTerminalControls.cs index 2fb8b307..efa6a861 100644 --- a/Heart Module/Data/Scripts/HeartModule/Weapons/Setup/Adding/SorterWeaponTerminalControls.cs +++ b/Heart Module/Data/Scripts/HeartModule/Weapons/Setup/Adding/SorterWeaponTerminalControls.cs @@ -1,15 +1,8 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using System.Text; -using Sandbox.Game.Localization; +using Sandbox.Game.Localization; using Sandbox.ModAPI; using Sandbox.ModAPI.Interfaces.Terminal; -using VRage.Game; -using VRage.Game.Components; +using System.Text; using VRage.Game.ModAPI; -using VRage.ModAPI; using VRage.Utils; using VRageMath; diff --git a/Heart Module/Data/Scripts/HeartModule/Weapons/Setup/Hiding/ConveyorSorterLogic.cs b/Heart Module/Data/Scripts/HeartModule/Weapons/Setup/Hiding/ConveyorSorterLogic.cs index 97ebd7ac..c25d36d6 100644 --- a/Heart Module/Data/Scripts/HeartModule/Weapons/Setup/Hiding/ConveyorSorterLogic.cs +++ b/Heart Module/Data/Scripts/HeartModule/Weapons/Setup/Hiding/ConveyorSorterLogic.cs @@ -1,6 +1,5 @@ using Sandbox.Common.ObjectBuilders; using Sandbox.ModAPI; -using VRage.Game; using VRage.Game.Components; using VRage.ModAPI; using VRage.ObjectBuilders; diff --git a/Heart Module/Data/Scripts/HeartModule/Weapons/Setup/Hiding/HideSorterControls.cs b/Heart Module/Data/Scripts/HeartModule/Weapons/Setup/Hiding/HideSorterControls.cs index d5d93cc5..9da25207 100644 --- a/Heart Module/Data/Scripts/HeartModule/Weapons/Setup/Hiding/HideSorterControls.cs +++ b/Heart Module/Data/Scripts/HeartModule/Weapons/Setup/Hiding/HideSorterControls.cs @@ -1,6 +1,6 @@ -using System.Collections.Generic; -using Sandbox.ModAPI; +using Sandbox.ModAPI; using Sandbox.ModAPI.Interfaces.Terminal; +using System.Collections.Generic; namespace YourName.ModName.Data.Scripts.HeartModule.Weapons.Setup.Hiding { diff --git a/Heart Module/Data/Scripts/HeartModule/Weapons/Setup/Hiding/TerminalChainedDelegate.cs b/Heart Module/Data/Scripts/HeartModule/Weapons/Setup/Hiding/TerminalChainedDelegate.cs index 89f1775b..599e9c22 100644 --- a/Heart Module/Data/Scripts/HeartModule/Weapons/Setup/Hiding/TerminalChainedDelegate.cs +++ b/Heart Module/Data/Scripts/HeartModule/Weapons/Setup/Hiding/TerminalChainedDelegate.cs @@ -1,5 +1,5 @@ -using System; -using Sandbox.ModAPI; +using Sandbox.ModAPI; +using System; namespace YourName.ModName.Data.Scripts.HeartModule.Weapons.Setup.Hiding { From 9324b21189eb6a9c448a91ae7525506f610ff5a4 Mon Sep 17 00:00:00 2001 From: Aristeas <94058548+Jnick-24@users.noreply.github.com> Date: Fri, 5 Jan 2024 21:16:00 -0600 Subject: [PATCH 4/4] You can't serialize Exceptions :clueless: --- .../ExceptionHandler/CriticalHandle.cs | 31 +++++++++++++++++-- .../HeartModule/ExceptionHandler/HeartLog.cs | 15 +++++++++ .../ExceptionHandler/NetworkedError.cs | 13 +++++--- .../ExceptionHandler/SoftHandle.cs | 16 ++++++++-- .../Data/Scripts/HeartModule/HeartLoad.cs | 6 ++-- 5 files changed, 68 insertions(+), 13 deletions(-) diff --git a/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/CriticalHandle.cs b/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/CriticalHandle.cs index 290e26cf..fc97ba5e 100644 --- a/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/CriticalHandle.cs +++ b/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/CriticalHandle.cs @@ -1,4 +1,6 @@ using Sandbox.Game; +using Sandbox.Game.Debugging; +using Sandbox.Game.Entities; using Sandbox.ModAPI; using System; using VRage.Utils; @@ -30,9 +32,10 @@ public void Update() if (!MyAPIGateway.Utilities.IsDedicated) MyVisualScriptLogicProvider.SessionClose(1000, false, true); else - throw Exception; + //throw Exception; + MyAPIGateway.Session.Unload(); } - + if (!MyAPIGateway.Utilities.IsDedicated) MyAPIGateway.Utilities.ShowNotification($"HeartMod CRITICAL ERROR - Shutting down in {secondsRemaining}s", 1000 / 60); } @@ -47,6 +50,11 @@ public static void ThrowCriticalException(Exception ex, Type callingType, ulong I?.m_ThrowCriticalException(ex, callingType, callerId); } + public static void ThrowCriticalException(NetworkedError ex, Type callingType, ulong callerId = ulong.MaxValue) + { + I?.m_ThrowCriticalException(ex, callingType, callerId); + } + private void m_ThrowCriticalException(Exception ex, Type callingType, ulong callerId = ulong.MaxValue) { HeartData.I.IsSuspended = true; @@ -61,7 +69,24 @@ private void m_ThrowCriticalException(Exception ex, Type callingType, ulong call CriticalCloseTime = DateTime.Now.Ticks + WarnTimeSeconds * TimeSpan.TicksPerSecond; if (MyAPIGateway.Session.IsServer) - HeartData.I.Net.SendToEveryone(new NetworkedError(ex, true)); + HeartData.I.Net.SendToEveryone(new NetworkedError(Exception, true)); + } + + private void m_ThrowCriticalException(NetworkedError ex, Type callingType, ulong callerId = ulong.MaxValue) + { + HeartData.I.IsSuspended = true; + HeartData.I.Log.Log("Start Throw Critical Exception " + CriticalCloseTime); + if (CriticalCloseTime != -1) + return; + + Exception = new Exception(ex.ExceptionMessage); + HeartData.I.Log.LogException(ex, callingType, (callerId != ulong.MaxValue ? $"Shared exception from {callerId}: " : "") + "Critical "); + MyAPIGateway.Utilities.ShowMessage("HeartMod", $"CRITICAL ERROR - Shutting down in {WarnTimeSeconds} seconds."); + MyLog.Default.WriteLineAndConsole($"HeartMod: CRITICAL ERROR - Shutting down in {WarnTimeSeconds} seconds."); + CriticalCloseTime = DateTime.Now.Ticks + WarnTimeSeconds * TimeSpan.TicksPerSecond; + + if (MyAPIGateway.Session.IsServer) + HeartData.I.Net.SendToEveryone(new NetworkedError(Exception, true)); } } } diff --git a/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/HeartLog.cs b/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/HeartLog.cs index 607b4994..4b5d112e 100644 --- a/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/HeartLog.cs +++ b/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/HeartLog.cs @@ -24,8 +24,23 @@ public void Log(string message) public void LogException(Exception ex, Type callingType, string prefix = "") { if (ex == null) + { + Log("Null exception! CallingType: " + callingType.FullName); return; + } + Log(prefix + $"Exception in {callingType.FullName}! {ex.Message}\n{ex.StackTrace}"); } + + public void LogException(NetworkedError ex, Type callingType, string prefix = "") + { + if (ex == null) + { + Log("Null exception! CallingType: " + callingType.FullName); + return; + } + + Log(prefix + $"Exception in {callingType.FullName}! {ex.ExceptionMessage}\n{ex.ExceptionStackTrace}"); + } } } diff --git a/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/NetworkedError.cs b/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/NetworkedError.cs index a9c34911..cd3c816c 100644 --- a/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/NetworkedError.cs +++ b/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/NetworkedError.cs @@ -5,24 +5,27 @@ namespace Heart_Module.Data.Scripts.HeartModule.ExceptionHandler { + [ProtoContract] public class NetworkedError : PacketBase { - [ProtoMember(21)] Exception Exception; - [ProtoMember(22)] bool IsCritical; + [ProtoMember(21)] public string ExceptionMessage; + [ProtoMember(22)] public string ExceptionStackTrace; + [ProtoMember(23)] public bool IsCritical; public NetworkedError() { } public NetworkedError(Exception e, bool IsCritical) { - Exception = e; + ExceptionMessage = e.Message; + ExceptionStackTrace = e.StackTrace; this.IsCritical = IsCritical; } public override void Received(ulong SenderSteamId) { if (IsCritical) - CriticalHandle.ThrowCriticalException(Exception, typeof(NetworkedError), SenderSteamId); + CriticalHandle.ThrowCriticalException(this, typeof(NetworkedError), SenderSteamId); else - SoftHandle.RaiseException(Exception, callerId: SenderSteamId); + SoftHandle.RaiseException(this, callerId: SenderSteamId); } } } diff --git a/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/SoftHandle.cs b/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/SoftHandle.cs index 83ec6d83..3d971a17 100644 --- a/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/SoftHandle.cs +++ b/Heart Module/Data/Scripts/HeartModule/ExceptionHandler/SoftHandle.cs @@ -8,7 +8,7 @@ public class SoftHandle { public static void RaiseException(string message, Type callingType = null, ulong callerId = ulong.MaxValue) { - //MyAPIGateway.Utilities.ShowNotification("Minor Exception: " + message); + MyAPIGateway.Utilities.ShowNotification("Minor Exception: " + message); Exception soft = new Exception(message); HeartData.I.Log.LogException(soft, callingType ?? typeof(SoftHandle), callerId != ulong.MaxValue ? $"Shared exception from {callerId}: " : ""); if (MyAPIGateway.Session.IsServer) @@ -17,7 +17,19 @@ public static void RaiseException(string message, Type callingType = null, ulong public static void RaiseException(Exception exception, Type callingType = null, ulong callerId = ulong.MaxValue) { - //MyAPIGateway.Utilities.ShowNotification("Minor Exception: " + exception.Message); + if (exception == null) + return; + + MyAPIGateway.Utilities.ShowNotification("Minor Exception: " + exception.Message); + HeartData.I.Log.LogException(exception, callingType ?? typeof(SoftHandle), callerId != ulong.MaxValue ? $"Shared exception from {callerId}: " : ""); + } + + public static void RaiseException(NetworkedError exception, Type callingType = null, ulong callerId = ulong.MaxValue) + { + if (exception == null) + return; + + MyAPIGateway.Utilities.ShowNotification("Minor Exception: " + exception.ExceptionMessage); HeartData.I.Log.LogException(exception, callingType ?? typeof(SoftHandle), callerId != ulong.MaxValue ? $"Shared exception from {callerId}: " : ""); } diff --git a/Heart Module/Data/Scripts/HeartModule/HeartLoad.cs b/Heart Module/Data/Scripts/HeartModule/HeartLoad.cs index 2ad14eba..78d214c9 100644 --- a/Heart Module/Data/Scripts/HeartModule/HeartLoad.cs +++ b/Heart Module/Data/Scripts/HeartModule/HeartLoad.cs @@ -26,6 +26,9 @@ public override void LoadData() public override void UpdateAfterSimulation() { + // This has the power to shut down the server. Afaik the only way to do this is throwing an exception. Yeah. + handle.Update(); + try { if (HeartData.I.IsSuspended) @@ -35,9 +38,6 @@ public override void UpdateAfterSimulation() { SoftHandle.RaiseException(ex); } - - // This has the power to shut down the server. Afaik the only way to do this is throwing an exception. Yeah. - handle.Update(); } protected override void UnloadData()