Merge remote-tracking branch 'upstream/master' into develop
This commit is contained in:
@@ -519,10 +519,12 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
string errorMsg = "Error while reading a message from server. ";
|
||||
if (GameMain.Client == null) { errorMsg += "Client disposed."; }
|
||||
AppendExceptionInfo(ref errorMsg, e);
|
||||
GameAnalyticsManager.AddErrorEventOnce("GameClient.Update:CheckServerMessagesException" + e.TargetSite.ToString(), GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
new GUIMessageBox(TextManager.Get("Error"), TextManager.GetWithVariables("MessageReadError", ("[message]", e.Message), ("[targetsite]", e.TargetSite.ToString())))
|
||||
AppendExceptionInfo(ref errorMsg, out Entity causingEntity, e);
|
||||
|
||||
string targetSite = e.TargetSite?.ToString() ?? "unknown";
|
||||
GameAnalyticsManager.AddErrorEventOnce("GameClient.Update:CheckServerMessagesException" + targetSite, GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||
DebugConsole.ThrowError(errorMsg, contentPackage: causingEntity?.ContentPackage);
|
||||
new GUIMessageBox(TextManager.Get("Error"), TextManager.GetWithVariables("MessageReadError", ("[message]", e.Message), ("[targetsite]", targetSite)))
|
||||
{
|
||||
DisplayInLoadingScreens = true
|
||||
};
|
||||
@@ -664,7 +666,7 @@ namespace Barotrauma.Networking
|
||||
catch (Exception e)
|
||||
{
|
||||
string errorMsg = "Error while reading an ingame update message from server.";
|
||||
AppendExceptionInfo(ref errorMsg, e);
|
||||
AppendExceptionInfo(ref errorMsg, out Entity causingEntity, e);
|
||||
GameAnalyticsManager.AddErrorEventOnce("GameClient.ReadDataMessage:ReadIngameUpdate", GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||
throw;
|
||||
}
|
||||
@@ -988,13 +990,15 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (Level.Loaded.EqualityCheckValues[stage] != levelEqualityCheckValues[stage])
|
||||
{
|
||||
string errorMsg = "Level equality check failed. The level generated at your end doesn't match the level generated by the server" +
|
||||
" (client value " + stage + ": " + Level.Loaded.EqualityCheckValues[stage].ToString("X") +
|
||||
", server value " + stage + ": " + levelEqualityCheckValues[stage].ToString("X") +
|
||||
", level value count: " + levelEqualityCheckValues.Count +
|
||||
", seed: " + Level.Loaded.Seed +
|
||||
", sub: " + (Submarine.MainSub == null ? "null" : (Submarine.MainSub.Info.Name + " (" + Submarine.MainSub.Info.MD5Hash.ShortRepresentation + ")")) +
|
||||
", mirrored: " + Level.Loaded.Mirrored + "). Round init status: " + roundInitStatus + "." + campaignErrorInfo;
|
||||
string errorMsg = "Level equality check failed. The level generated at your end doesn't match the level generated by the server, " +
|
||||
$"(client value {stage}:{Level.Loaded.EqualityCheckValues[stage].ToString("X")}, " +
|
||||
$"server value {stage}: {levelEqualityCheckValues[stage].ToString("X")}, " +
|
||||
$"level value count: {levelEqualityCheckValues.Count}, " +
|
||||
$"seed: {Level.Loaded.Seed}, " +
|
||||
$"missions: {string.Join(", ", GameMain.GameSession.GameMode.Missions.Select(m => m.Prefab.Identifier))}, " +
|
||||
$"sub: {(Submarine.MainSub == null ? "null" : (Submarine.MainSub.Info.Name + " (" + Submarine.MainSub.Info.MD5Hash.ShortRepresentation))}, " +
|
||||
$"mirrored: {Level.Loaded.Mirrored}). Round init status: {roundInitStatus}." +
|
||||
campaignErrorInfo;
|
||||
GameAnalyticsManager.AddErrorEventOnce("GameClient.StartGame:LevelsDontMatch" + Level.Loaded.Seed, GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||
throw new Exception(errorMsg);
|
||||
}
|
||||
@@ -1472,6 +1476,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
string levelSeed = inc.ReadString();
|
||||
float levelDifficulty = inc.ReadSingle();
|
||||
Identifier biomeId = inc.ReadIdentifier();
|
||||
string subName = inc.ReadString();
|
||||
string subHash = inc.ReadString();
|
||||
string shuttleName = inc.ReadString();
|
||||
@@ -1559,7 +1564,7 @@ namespace Barotrauma.Networking
|
||||
var selectedEnemySub = hasEnemySub && GameMain.NetLobbyScreen.SelectedEnemySub is { } enemySub ? Option.Some(enemySub) : Option.None;
|
||||
|
||||
GameMain.GameSession = new GameSession(GameMain.NetLobbyScreen.SelectedSub, selectedEnemySub, gameMode, missionPrefabs: selectedMissions);
|
||||
GameMain.GameSession.StartRound(levelSeed, levelDifficulty, levelGenerationParams: null, forceBiome: ServerSettings.Biome);
|
||||
GameMain.GameSession.StartRound(levelSeed, levelDifficulty, levelGenerationParams: null, forceBiome: biomeId);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2077,16 +2082,15 @@ namespace Barotrauma.Networking
|
||||
|
||||
UInt16 updateID = inc.ReadUInt16();
|
||||
|
||||
|
||||
UInt16 settingsLen = inc.ReadUInt16();
|
||||
byte[] settingsData = inc.ReadBytes(settingsLen);
|
||||
|
||||
bool isInitialUpdate = inc.ReadBoolean();
|
||||
DebugConsole.Log($"Received {(isInitialUpdate ? "initial" : string.Empty)} lobby update ID: {updateID}, last ID: {GameMain.NetLobbyScreen.LastUpdateID}.");
|
||||
|
||||
if (isInitialUpdate)
|
||||
{
|
||||
if (GameSettings.CurrentConfig.VerboseLogging)
|
||||
{
|
||||
DebugConsole.NewMessage("Received initial lobby update, ID: " + updateID + ", last ID: " + GameMain.NetLobbyScreen.LastUpdateID, Color.Gray);
|
||||
}
|
||||
{
|
||||
ReadInitialUpdate(inc);
|
||||
initialUpdateReceived = true;
|
||||
}
|
||||
@@ -2365,7 +2369,7 @@ namespace Barotrauma.Networking
|
||||
GameAnalyticsManager.AddErrorEventOnce("GameClient.ReadInGameUpdate", GameAnalyticsManager.ErrorSeverity.Critical, string.Join("\n", errorLines));
|
||||
|
||||
throw new Exception(
|
||||
$"Exception thrown while reading segment {segment.Identifier} at position {segment.Pointer}." +
|
||||
$"Exception thrown while reading a message of the type \"{segment.Identifier}\" at position {segment.Pointer}." +
|
||||
(prevSegments.Any() ? $" Previous segments: {string.Join(", ", prevSegments)}" : ""),
|
||||
ex);
|
||||
});
|
||||
@@ -3767,16 +3771,24 @@ namespace Barotrauma.Networking
|
||||
eventErrorWritten = true;
|
||||
}
|
||||
|
||||
private static void AppendExceptionInfo(ref string errorMsg, Exception e)
|
||||
private static void AppendExceptionInfo(ref string errorMsg, out Entity causingEntity, Exception e)
|
||||
{
|
||||
if (!errorMsg.EndsWith("\n")) { errorMsg += "\n"; }
|
||||
|
||||
Exception innerMostException = e.GetInnermost();
|
||||
causingEntity = GetCausingEntity(e);
|
||||
|
||||
if (causingEntity != null)
|
||||
{
|
||||
errorMsg += "Entity: " + causingEntity + "\n";
|
||||
}
|
||||
errorMsg += e.Message + "\n";
|
||||
var innermostException = e.GetInnermost();
|
||||
if (innermostException != e)
|
||||
|
||||
if (innerMostException != e)
|
||||
{
|
||||
// If available, only append the stacktrace of the innermost exception,
|
||||
// because that's the most important one to fix
|
||||
errorMsg += "Inner exception: " + innermostException.Message + "\n" + innermostException.StackTrace.CleanupStackTrace();
|
||||
errorMsg += "Inner exception: " + innerMostException.Message + "\n" + innerMostException.StackTrace.CleanupStackTrace();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3784,6 +3796,24 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the exception or any of its inner exceptions are EntityEventExceptions, and returns the entity that caused the innermost EntityEventException.
|
||||
/// </summary>
|
||||
private static Entity GetCausingEntity(Exception e)
|
||||
{
|
||||
Entity causingEntity = null;
|
||||
Exception currentException = e;
|
||||
while (currentException != null)
|
||||
{
|
||||
if (currentException is EntityEventException entityEventException)
|
||||
{
|
||||
causingEntity = entityEventException.Entity;
|
||||
}
|
||||
currentException = currentException.InnerException;
|
||||
}
|
||||
return causingEntity;
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
public void ForceTimeOut()
|
||||
{
|
||||
|
||||
+28
-10
@@ -154,13 +154,25 @@ namespace Barotrauma.Networking
|
||||
//16 = entity ID, 8 = msg length
|
||||
if (msg.BitPosition + 16 + 8 > msg.LengthBits)
|
||||
{
|
||||
string errorMsg = $"Error while reading a message from the server. Entity event data exceeds the size of the buffer (current position: {msg.BitPosition}, length: {msg.LengthBits}).";
|
||||
UInt16 potentialEntityId = Entity.NullEntityID;
|
||||
try
|
||||
{
|
||||
potentialEntityId = msg.ReadUInt16();
|
||||
}
|
||||
catch
|
||||
{
|
||||
//failed to read the ID, do nothing (we would've just used it for the error message)
|
||||
}
|
||||
Entity targetEntity = Entity.FindEntityByID(potentialEntityId);
|
||||
|
||||
string errorMsg = $"Error while reading a message from the server (entity: {targetEntity?.ToString() ?? "unknown"}).";
|
||||
errorMsg += $" Entity event data exceeds the size of the buffer (current position: {msg.BitPosition}, length: {msg.LengthBits}).";
|
||||
errorMsg += "\nPrevious entities:";
|
||||
for (int j = tempEntityList.Count - 1; j >= 0; j--)
|
||||
{
|
||||
errorMsg += "\n" + (tempEntityList[j] == null ? "NULL" : tempEntityList[j].ToString());
|
||||
}
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
DebugConsole.ThrowError(errorMsg, contentPackage: targetEntity?.ContentPackage);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -172,7 +184,7 @@ namespace Barotrauma.Networking
|
||||
if (GameSettings.CurrentConfig.VerboseLogging)
|
||||
{
|
||||
DebugConsole.NewMessage("received msg " + thisEventID + " (null entity)",
|
||||
Microsoft.Xna.Framework.Color.Orange);
|
||||
Color.Orange);
|
||||
}
|
||||
tempEntityList.Add(null);
|
||||
if (thisEventID == (UInt16)(lastReceivedID + 1)) { lastReceivedID++; }
|
||||
@@ -187,7 +199,7 @@ namespace Barotrauma.Networking
|
||||
//skip the event if we've already received it or if the entity isn't found
|
||||
if (thisEventID != (UInt16)(lastReceivedID + 1) || entity == null)
|
||||
{
|
||||
if (thisEventID != (UInt16) (lastReceivedID + 1))
|
||||
if (thisEventID != (UInt16)(lastReceivedID + 1))
|
||||
{
|
||||
if (GameSettings.CurrentConfig.VerboseLogging)
|
||||
{
|
||||
@@ -195,7 +207,7 @@ namespace Barotrauma.Networking
|
||||
"Received msg " + thisEventID + " (waiting for " + (lastReceivedID + 1) + ")",
|
||||
NetIdUtils.IdMoreRecent(thisEventID, (UInt16)(lastReceivedID + 1))
|
||||
? GUIStyle.Red
|
||||
: Microsoft.Xna.Framework.Color.Yellow);
|
||||
: Color.Yellow);
|
||||
}
|
||||
}
|
||||
else if (entity == null)
|
||||
@@ -215,12 +227,18 @@ namespace Barotrauma.Networking
|
||||
if (GameSettings.CurrentConfig.VerboseLogging)
|
||||
{
|
||||
DebugConsole.NewMessage("received msg " + thisEventID + " (" + entity.ToString() + ")",
|
||||
Microsoft.Xna.Framework.Color.Green);
|
||||
Color.Green);
|
||||
}
|
||||
lastReceivedID++;
|
||||
ReadEvent(msg, entity, sendingTime);
|
||||
msg.ReadPadBits();
|
||||
|
||||
try
|
||||
{
|
||||
ReadEvent(msg, entity, sendingTime);
|
||||
msg.ReadPadBits();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
throw new EntityEventException("Failed to read event." , entity as Entity, exception);
|
||||
}
|
||||
if (msg.BitPosition != msgPosition + msgLength * 8)
|
||||
{
|
||||
var prevEntity = tempEntityList.Count >= 2 ? tempEntityList[tempEntityList.Count - 2] : null;
|
||||
@@ -231,7 +249,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
GameAnalyticsManager.AddErrorEventOnce("ClientEntityEventManager.Read:BitPosMismatch", GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||
|
||||
throw new Exception(errorMsg);
|
||||
throw new EntityEventException(errorMsg, entity as Entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+10
-1
@@ -74,7 +74,16 @@ sealed class SteamConnectSocket : P2PSocket
|
||||
{
|
||||
if (!SteamManager.IsInitialized) { return Result.Failure(new Error(ErrorCode.SteamNotInitialized)); }
|
||||
|
||||
var connectionManager = Steamworks.SteamNetworkingSockets.ConnectRelay<ConnectionManager>(endpoint.SteamId.Value);
|
||||
ConnectionManager connectionManager;
|
||||
try
|
||||
{
|
||||
connectionManager = Steamworks.SteamNetworkingSockets.ConnectRelay<ConnectionManager>(endpoint.SteamId.Value);
|
||||
}
|
||||
catch (ArgumentException e)
|
||||
{
|
||||
DebugConsole.ThrowError("Failed to connect via SteamP2P. Are you logged in to Steam, is the same Steam account already connected to the server?", e);
|
||||
return Result.Failure(new Error(ErrorCode.FailedToCreateSteamP2PSocket));
|
||||
}
|
||||
if (connectionManager is null) { return Result.Failure(new Error(ErrorCode.FailedToCreateSteamP2PSocket)); }
|
||||
connectionManager.SetEndpointAndCallbacks(endpoint, callbacks);
|
||||
|
||||
|
||||
@@ -202,6 +202,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
DebugConsole.ThrowError("Capture device has been disconnected. You can select another available device in the settings.");
|
||||
Disconnected = true;
|
||||
TryRefreshDevice();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -401,5 +402,65 @@ namespace Barotrauma.Networking
|
||||
captureThread = null;
|
||||
if (captureDevice != IntPtr.Zero) { Alc.CaptureCloseDevice(captureDevice); }
|
||||
}
|
||||
|
||||
public static void TryRefreshDevice()
|
||||
{
|
||||
DebugConsole.NewMessage("Refreshing audio capture device");
|
||||
|
||||
List<string> deviceList = Alc.GetStringList(IntPtr.Zero, Alc.CaptureDeviceSpecifier).ToList();
|
||||
int alcError = Alc.GetError(IntPtr.Zero);
|
||||
if (alcError != Alc.NoError)
|
||||
{
|
||||
DebugConsole.ThrowError("Failed to list available audio input devices: " + alcError.ToString());
|
||||
return;
|
||||
}
|
||||
|
||||
if (deviceList.Any())
|
||||
{
|
||||
string device;
|
||||
|
||||
if (deviceList.Find(n => n.Equals(GameSettings.CurrentConfig.Audio.VoiceCaptureDevice, StringComparison.OrdinalIgnoreCase))
|
||||
is string availablePreviousDevice)
|
||||
{
|
||||
DebugConsole.NewMessage($" Previous device choice available: {availablePreviousDevice}");
|
||||
device = availablePreviousDevice;
|
||||
}
|
||||
else
|
||||
{
|
||||
device = Alc.GetString(IntPtr.Zero, Alc.CaptureDefaultDeviceSpecifier);
|
||||
DebugConsole.NewMessage($" Reverting to default device: {device}");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(device))
|
||||
{
|
||||
device = deviceList[0];
|
||||
DebugConsole.NewMessage($" No default device found, resorting to first available device: {device}");
|
||||
}
|
||||
|
||||
// Save the new device choice and generate a new voice capture instance with it
|
||||
var currentConfig = GameSettings.CurrentConfig;
|
||||
currentConfig.Audio.VoiceCaptureDevice = device;
|
||||
GameSettings.SetCurrentConfig(currentConfig);
|
||||
if (Instance is VoipCapture currentCaptureInstance)
|
||||
{
|
||||
currentCaptureInstance.Dispose();
|
||||
}
|
||||
Create(GameSettings.CurrentConfig.Audio.VoiceCaptureDevice);
|
||||
}
|
||||
|
||||
// Didn't end up with any capture device, so let's disable voice capture for now
|
||||
if (Instance == null)
|
||||
{
|
||||
DebugConsole.NewMessage($" No devices found, disabling");
|
||||
var currentConfig = GameSettings.CurrentConfig;
|
||||
currentConfig.Audio.VoiceSetting = VoiceMode.Disabled;
|
||||
GameSettings.SetCurrentConfig(currentConfig);
|
||||
}
|
||||
|
||||
if (GUI.SettingsMenuOpen)
|
||||
{
|
||||
SettingsMenu.Instance?.CreateAudioAndVCTab(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user