- Some of the non-game-crashing error messages are sent to GameAnalytics.
- Changed crash severity from Error to Critical. - Exception handling when loading submarine preview images. - Checking if position is valid in Ragdoll.SetPosition.
This commit is contained in:
@@ -81,6 +81,9 @@ namespace Barotrauma
|
|||||||
if (Limbs == null)
|
if (Limbs == null)
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("Failed to draw a ragdoll, limbs have been removed. Character: \"" + character.Name + "\", removed: " + character.Removed + "\n" + Environment.StackTrace);
|
DebugConsole.ThrowError("Failed to draw a ragdoll, limbs have been removed. Character: \"" + character.Name + "\", removed: " + character.Removed + "\n" + Environment.StackTrace);
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce("Ragdoll.Draw:LimbsRemoved",
|
||||||
|
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||||
|
"Failed to draw a ragdoll, limbs have been removed. Character: \"" + character.Name + "\", removed: " + character.Removed + "\n" + Environment.StackTrace);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1020,29 +1020,32 @@ namespace Barotrauma.Networking
|
|||||||
ChatMessage.ClientRead(inc);
|
ChatMessage.ClientRead(inc);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
DebugConsole.ThrowError("Error while reading update from server (unknown object header \""+objHeader+"\"!)");
|
List<string> errorLines = new List<string>
|
||||||
if (prevObjHeader != null)
|
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("Previous object type: " + prevObjHeader.ToString());
|
"Error while reading update from server (unknown object header \"" + objHeader + "\"!)",
|
||||||
}
|
prevObjHeader != null ? "Previous object type: " + prevObjHeader.ToString() : "Error occurred on the very first object!",
|
||||||
else
|
"Previous object was " + (inc.Position - prevBitPos) + " bits long (" + (inc.PositionInBytes - prevBytePos) + " bytes)"
|
||||||
{
|
};
|
||||||
DebugConsole.ThrowError("Error occurred on the very first object!");
|
|
||||||
}
|
|
||||||
DebugConsole.ThrowError("Previous object was " + (inc.Position - prevBitPos) + " bits long (" + (inc.PositionInBytes - prevBytePos) + " bytes)");
|
|
||||||
if (prevObjHeader == ServerNetObject.ENTITY_EVENT || prevObjHeader == ServerNetObject.ENTITY_EVENT_INITIAL)
|
if (prevObjHeader == ServerNetObject.ENTITY_EVENT || prevObjHeader == ServerNetObject.ENTITY_EVENT_INITIAL)
|
||||||
{
|
{
|
||||||
foreach (IServerSerializable ent in entities)
|
foreach (IServerSerializable ent in entities)
|
||||||
{
|
{
|
||||||
if (ent == null)
|
if (ent == null)
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError(" - NULL");
|
errorLines.Add(" - NULL");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Entity e = ent as Entity;
|
Entity e = ent as Entity;
|
||||||
DebugConsole.ThrowError(" - "+e.ToString());
|
errorLines.Add(" - " + e.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (string line in errorLines)
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError(line);
|
||||||
|
}
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce("GameClient.ReadInGameUpdate", GameAnalyticsSDK.Net.EGAErrorSeverity.Critical, string.Join("\n", errorLines));
|
||||||
|
|
||||||
DebugConsole.ThrowError("Writing object data to \"crashreport_object.bin\", please send this file to us at http://github.com/Regalis11/Barotrauma/issues");
|
DebugConsole.ThrowError("Writing object data to \"crashreport_object.bin\", please send this file to us at http://github.com/Regalis11/Barotrauma/issues");
|
||||||
|
|
||||||
FileStream fl = File.Open("crashreport_object.bin", FileMode.Create);
|
FileStream fl = File.Open("crashreport_object.bin", FileMode.Create);
|
||||||
|
|||||||
+3
@@ -191,6 +191,9 @@ namespace Barotrauma.Networking
|
|||||||
if (GameSettings.VerboseLogging)
|
if (GameSettings.VerboseLogging)
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("Failed to read event for entity \"" + entity.ToString() + "\"!", e);
|
DebugConsole.ThrowError("Failed to read event for entity \"" + entity.ToString() + "\"!", e);
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce("ClientEntityEventManager.Read:ReadFailed" + entity.ToString(),
|
||||||
|
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||||
|
"Failed to read event for entity \"" + entity.ToString() + "\"!\n" + e.StackTrace);
|
||||||
}
|
}
|
||||||
msg.Position = msgPosition + msgLength * 8;
|
msg.Position = msgPosition + msgLength * 8;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -203,7 +203,7 @@ namespace Barotrauma
|
|||||||
if (GameSettings.SendUserStatistics)
|
if (GameSettings.SendUserStatistics)
|
||||||
{
|
{
|
||||||
CrashMessageBox( "A crash report (\"crashreport.log\") was saved in the root folder of the game and sent to the developers.");
|
CrashMessageBox( "A crash report (\"crashreport.log\") was saved in the root folder of the game and sent to the developers.");
|
||||||
GameAnalytics.AddErrorEvent(EGAErrorSeverity.Error, crashReport);
|
GameAnalytics.AddErrorEvent(EGAErrorSeverity.Critical, crashReport);
|
||||||
GameAnalytics.OnStop();
|
GameAnalytics.OnStop();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -737,8 +737,20 @@ namespace Barotrauma
|
|||||||
//hash will be null if opening the sub file failed -> don't select the sub
|
//hash will be null if opening the sub file failed -> don't select the sub
|
||||||
if (string.IsNullOrWhiteSpace(hash))
|
if (string.IsNullOrWhiteSpace(hash))
|
||||||
{
|
{
|
||||||
(component as GUITextBlock).TextColor = Color.DarkRed * 0.8f;
|
if (component is GUITextBlock textBlock)
|
||||||
component.CanBeFocused = false;
|
{
|
||||||
|
textBlock.TextColor = Color.DarkRed * 0.8f;
|
||||||
|
textBlock.CanBeFocused = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError("Failed to select submarine. Selected GUIComponent was of the type \"" + (component == null ? "null" : component.GetType().ToString()) + "\".");
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce(
|
||||||
|
"NetLobbyScreen.SelectSub:InvalidComponent",
|
||||||
|
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||||
|
"Failed to select submarine. Selected GUIComponent was of the type \"" + (component == null ? "null" : component.GetType().ToString()) + "\".");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
StartButton.Enabled = false;
|
StartButton.Enabled = false;
|
||||||
|
|
||||||
|
|||||||
@@ -55,6 +55,10 @@ namespace Barotrauma.Sounds
|
|||||||
#else
|
#else
|
||||||
DebugConsole.NewMessage("OpenAL error: " + AL.GetErrorString(error) + "\n" + Environment.StackTrace, Microsoft.Xna.Framework.Color.Red);
|
DebugConsole.NewMessage("OpenAL error: " + AL.GetErrorString(error) + "\n" + Environment.StackTrace, Microsoft.Xna.Framework.Color.Red);
|
||||||
#endif
|
#endif
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce(
|
||||||
|
"OggStream.Check:"+ AL.GetErrorString(error),
|
||||||
|
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||||
|
"OpenAL error: " + AL.GetErrorString(error) + "\n" + Environment.StackTrace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,9 @@ namespace Barotrauma
|
|||||||
#if DEBUG
|
#if DEBUG
|
||||||
DebugConsole.ThrowError("Attempted to access a removed AITarget\n" + Environment.StackTrace);
|
DebugConsole.ThrowError("Attempted to access a removed AITarget\n" + Environment.StackTrace);
|
||||||
#endif
|
#endif
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce("AITarget.WorldPosition:EntityRemoved",
|
||||||
|
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||||
|
"Attempted to access a removed AITarget\n" + Environment.StackTrace);
|
||||||
return Vector2.Zero;
|
return Vector2.Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,6 +57,9 @@ namespace Barotrauma
|
|||||||
#if DEBUG
|
#if DEBUG
|
||||||
DebugConsole.ThrowError("Attempted to access a removed AITarget\n" + Environment.StackTrace);
|
DebugConsole.ThrowError("Attempted to access a removed AITarget\n" + Environment.StackTrace);
|
||||||
#endif
|
#endif
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce("AITarget.WorldPosition:EntityRemoved",
|
||||||
|
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||||
|
"Attempted to access a removed AITarget\n" + Environment.StackTrace);
|
||||||
return Vector2.Zero;
|
return Vector2.Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,11 @@ namespace Barotrauma
|
|||||||
if (limbs == null)
|
if (limbs == null)
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("Attempted to access a potentially removed ragdoll. Character: " + character.Name + ", id: " + character.ID + ", removed: " + character.Removed + ", ragdoll removed: " + !list.Contains(this));
|
DebugConsole.ThrowError("Attempted to access a potentially removed ragdoll. Character: " + character.Name + ", id: " + character.ID + ", removed: " + character.Removed + ", ragdoll removed: " + !list.Contains(this));
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce(
|
||||||
|
"Ragdoll.Limbs:AccessRemoved",
|
||||||
|
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||||
|
"Attempted to access a potentially removed ragdoll. Character: " + character.Name + ", id: " + character.ID + ", removed: " + character.Removed + ", ragdoll removed: " + !list.Contains(this));
|
||||||
|
|
||||||
return new Limb[0];
|
return new Limb[0];
|
||||||
}
|
}
|
||||||
return limbs;
|
return limbs;
|
||||||
@@ -1165,6 +1170,16 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public void SetPosition(Vector2 simPosition, bool lerp = false)
|
public void SetPosition(Vector2 simPosition, bool lerp = false)
|
||||||
{
|
{
|
||||||
|
if (!MathUtils.IsValid(simPosition))
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError("Attempted to move a ragdoll (" + character.Name + ") to an invalid position (" + simPosition + "). " + Environment.StackTrace);
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce(
|
||||||
|
"Ragdoll.SetPosition:InvalidPosition",
|
||||||
|
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||||
|
"Attempted to move a ragdoll (" + character.Name + ") to an invalid position (" + simPosition + "). " + Environment.StackTrace);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Vector2 limbMoveAmount = simPosition - MainLimb.SimPosition;
|
Vector2 limbMoveAmount = simPosition - MainLimb.SimPosition;
|
||||||
|
|
||||||
Collider.SetTransform(simPosition, Collider.Rotation);
|
Collider.SetTransform(simPosition, Collider.Rotation);
|
||||||
|
|||||||
@@ -1898,7 +1898,16 @@ namespace Barotrauma
|
|||||||
if (string.IsNullOrWhiteSpace(command)) return;
|
if (string.IsNullOrWhiteSpace(command)) return;
|
||||||
|
|
||||||
string[] splitCommand = SplitCommand(command);
|
string[] splitCommand = SplitCommand(command);
|
||||||
|
if (splitCommand.Length == 0)
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError("Failed to execute command \"" + command + "\"!");
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce(
|
||||||
|
"DebugConsole.ExecuteCommand:LengthZero",
|
||||||
|
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||||
|
"Failed to execute command \"" + command + "\"!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!splitCommand[0].ToLowerInvariant().Equals("admin"))
|
if (!splitCommand[0].ToLowerInvariant().Equals("admin"))
|
||||||
{
|
{
|
||||||
NewMessage(command, Color.White, true);
|
NewMessage(command, Color.White, true);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using GameAnalyticsSDK.Net;
|
using GameAnalyticsSDK.Net;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
@@ -9,6 +10,8 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
public static class GameAnalyticsManager
|
public static class GameAnalyticsManager
|
||||||
{
|
{
|
||||||
|
private static HashSet<string> sentEventIdentifiers = new HashSet<string>();
|
||||||
|
|
||||||
public static void Init()
|
public static void Init()
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
@@ -47,5 +50,17 @@ namespace Barotrauma
|
|||||||
contentPackageName.Replace(":", "").Substring(0, Math.Min(32, contentPackageName.Length)));
|
contentPackageName.Replace(":", "").Substring(0, Math.Min(32, contentPackageName.Length)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds an error event to GameAnalytics if an event with the same identifier has not been added yet.
|
||||||
|
/// </summary>
|
||||||
|
public static void AddErrorEventOnce(string identifier, EGAErrorSeverity errorSeverity, string message)
|
||||||
|
{
|
||||||
|
if (!GameSettings.SendUserStatistics) return;
|
||||||
|
if (sentEventIdentifiers.Contains(identifier)) return;
|
||||||
|
|
||||||
|
GameAnalytics.AddErrorEvent(errorSeverity, message);
|
||||||
|
sentEventIdentifiers.Add(identifier);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -352,6 +352,8 @@ namespace Barotrauma.Items.Components
|
|||||||
if (!MathUtils.IsValid(item.SimPosition))
|
if (!MathUtils.IsValid(item.SimPosition))
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("Failed to push a character out of a doorway - position of the door is not valid (" + item.SimPosition + ")");
|
DebugConsole.ThrowError("Failed to push a character out of a doorway - position of the door is not valid (" + item.SimPosition + ")");
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce("PushCharactersAway:DoorPosInvalid", GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||||
|
"Failed to push a character out of a doorway - position of the door is not valid (" + item.SimPosition + ").");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -370,6 +372,10 @@ namespace Barotrauma.Items.Components
|
|||||||
if (!MathUtils.IsValid(c.SimPosition))
|
if (!MathUtils.IsValid(c.SimPosition))
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("Failed to push a character out of a doorway - position of the character \"" + c.Name + "\" is not valid (" + c.SimPosition + ")");
|
DebugConsole.ThrowError("Failed to push a character out of a doorway - position of the character \"" + c.Name + "\" is not valid (" + c.SimPosition + ")");
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce("PushCharactersAway:CharacterPosInvalid", GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||||
|
"Failed to push a character out of a doorway - position of the character \"" + c.Name + "\" is not valid (" + c.SimPosition + ")." +
|
||||||
|
" Removed: " + c.Removed +
|
||||||
|
" Remoteplayer: " + c.IsRemotePlayer);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
int dir = isHorizontal ? Math.Sign(c.SimPosition.Y - item.SimPosition.Y) : Math.Sign(c.SimPosition.X - item.SimPosition.X);
|
int dir = isHorizontal ? Math.Sign(c.SimPosition.Y - item.SimPosition.Y) : Math.Sign(c.SimPosition.X - item.SimPosition.X);
|
||||||
|
|||||||
@@ -300,9 +300,19 @@ namespace Barotrauma
|
|||||||
string previewImageData = doc.Root.GetAttributeString("previewimage", "");
|
string previewImageData = doc.Root.GetAttributeString("previewimage", "");
|
||||||
if (!string.IsNullOrEmpty(previewImageData))
|
if (!string.IsNullOrEmpty(previewImageData))
|
||||||
{
|
{
|
||||||
using (MemoryStream mem = new MemoryStream(Convert.FromBase64String(previewImageData)))
|
try
|
||||||
{
|
{
|
||||||
PreviewImage = new Sprite(TextureLoader.FromStream(mem), null, null);
|
using (MemoryStream mem = new MemoryStream(Convert.FromBase64String(previewImageData)))
|
||||||
|
{
|
||||||
|
PreviewImage = new Sprite(TextureLoader.FromStream(mem), null, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError("Loading the preview image of the submarine \"" + Name + "\" failed. The file may be corrupted.", e);
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce("Submarine..ctor:PreviewImageLoadingFailed", GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||||
|
"Loading the preview image of the submarine \"" + Name + "\" failed. The file may be corrupted.");
|
||||||
|
PreviewImage = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -30,6 +30,9 @@ namespace Barotrauma.Networking
|
|||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("Failed to write an event for the entity \"" + e.Entity + "\"", exception);
|
DebugConsole.ThrowError("Failed to write an event for the entity \"" + e.Entity + "\"", exception);
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce("NetEntityEventManager.Write:WriteFailed" + e.Entity.ToString(),
|
||||||
|
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||||
|
"Failed to write an event for the entity \"" + e.Entity + "\"\n" + exception.StackTrace);
|
||||||
|
|
||||||
//write an empty event to avoid messing up IDs
|
//write an empty event to avoid messing up IDs
|
||||||
//(otherwise the clients might read the next event in the message and think its ID
|
//(otherwise the clients might read the next event in the message and think its ID
|
||||||
@@ -49,6 +52,9 @@ namespace Barotrauma.Networking
|
|||||||
if (tempEventBuffer.LengthBytes > 255)
|
if (tempEventBuffer.LengthBytes > 255)
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("Too much data in network event for entity \"" + e.Entity.ToString() + "\" (" + tempEventBuffer.LengthBytes + " bytes");
|
DebugConsole.ThrowError("Too much data in network event for entity \"" + e.Entity.ToString() + "\" (" + tempEventBuffer.LengthBytes + " bytes");
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce("NetEntityEventManager.Write:TooLong" + e.Entity.ToString(),
|
||||||
|
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||||
|
"Too much data in network event for entity \"" + e.Entity.ToString() + "\" (" + tempEventBuffer.LengthBytes + " bytes");
|
||||||
}
|
}
|
||||||
|
|
||||||
//the ID has been taken by another entity (the original entity has been removed) -> write an empty event
|
//the ID has been taken by another entity (the original entity has been removed) -> write an empty event
|
||||||
|
|||||||
Reference in New Issue
Block a user