Merge remote-tracking branch 'Regalis11/master' into vanillawork

This commit is contained in:
Nilanth Animosus
2018-07-20 15:38:07 +01:00
58 changed files with 675 additions and 310 deletions

View File

@@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.8.1.5")]
[assembly: AssemblyFileVersion("0.8.1.5")]
[assembly: AssemblyVersion("0.8.1.7")]
[assembly: AssemblyFileVersion("0.8.1.7")]

View File

@@ -99,7 +99,7 @@ namespace Barotrauma
public Camera()
{
zoom = 1.0f;
zoom = prevZoom = 1.0f;
rotation = 0.0f;
position = Vector2.Zero;
@@ -112,7 +112,7 @@ namespace Barotrauma
viewMatrix =
Matrix.CreateTranslation(new Vector3(GameMain.GraphicsWidth / 2.0f, GameMain.GraphicsHeight / 2.0f, 0));
UpdateTransform();
UpdateTransform(false);
}
public Vector2 TargetPos

View File

@@ -81,6 +81,9 @@ namespace Barotrauma
if (Limbs == null)
{
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;
}

View File

@@ -206,8 +206,8 @@ namespace Barotrauma
{
GameMain.GameSession.CrewManager.RemoveCharacter(this);
}
if (GameMain.Client != null && GameMain.Client.Character == this) GameMain.Client.Character = null;
if (GameMain.NetworkMember?.Character == this) GameMain.NetworkMember.Character = null;
if (Lights.LightManager.ViewTarget == this) Lights.LightManager.ViewTarget = null;
}

View File

@@ -32,7 +32,7 @@ namespace Barotrauma
public static void TakeDamage(float amount)
{
healthBar.Flash();
healthBar?.Flash();
damageOverlayTimer = MathHelper.Clamp(amount * 0.1f, 0.2f, 1.0f);
}

View File

@@ -188,6 +188,7 @@ namespace Barotrauma
controlled = this;
IsRemotePlayer = false;
GameMain.Client.HasSpawned = true;
GameMain.Client.Character = this;
GameMain.LightManager.LosEnabled = true;
}
@@ -286,6 +287,7 @@ namespace Barotrauma
if (GameMain.Client.ID == ownerId)
{
GameMain.Client.HasSpawned = true;
GameMain.Client.Character = character;
Controlled = character;

View File

@@ -438,6 +438,8 @@ namespace Barotrauma
NewMessage("Resolution set to 0 x 0 (screen resolution will be used)", Color.Green);
NewMessage("Fullscreen enabled", Color.Green);
GameSettings.ShowUserStatisticsPrompt = true;
GameSettings.VerboseLogging = false;
if (GameMain.Config.MasterServerUrl != "http://www.undertowgames.com/baromaster")

View File

@@ -214,12 +214,9 @@ namespace Barotrauma
if (GameMain.GameSession != null)
{
if (GameSettings.SendUserStatistics)
{
Mission mission = GameMain.GameSession.Mission;
GameAnalyticsSDK.Net.GameAnalytics.AddDesignEvent("QuitRound:" + (save ? "Save" : "NoSave"));
GameAnalyticsSDK.Net.GameAnalytics.AddDesignEvent("EndRound:" + (mission == null ? "NoMission" : (mission.Completed ? "MissionCompleted" : "MissionFailed")));
}
Mission mission = GameMain.GameSession.Mission;
GameAnalyticsManager.AddDesignEvent("QuitRound:" + (save ? "Save" : "NoSave"));
GameAnalyticsManager.AddDesignEvent("EndRound:" + (mission == null ? "NoMission" : (mission.Completed ? "MissionCompleted" : "MissionFailed")));
GameMain.GameSession = null;
}

View File

@@ -134,7 +134,7 @@ namespace Barotrauma
Config.WasGameUpdated = false;
Config.Save("config.xml");
}
ApplyGraphicsSettings();
Content.RootDirectory = "Content";
@@ -244,12 +244,18 @@ namespace Barotrauma
new string[] { "Yes", "No" });
userStatsPrompt.Buttons[0].OnClicked += (btn, userdata) =>
{
GameSettings.ShowUserStatisticsPrompt = false;
GameSettings.SendUserStatistics = true;
GameAnalyticsManager.Init();
return true;
};
userStatsPrompt.Buttons[0].OnClicked += userStatsPrompt.Close;
userStatsPrompt.Buttons[1].OnClicked += (btn, userdata) => { GameSettings.SendUserStatistics = false; return true; };
userStatsPrompt.Buttons[1].OnClicked += (btn, userdata) =>
{
GameSettings.ShowUserStatisticsPrompt = false;
GameSettings.SendUserStatistics = false;
return true;
};
userStatsPrompt.Buttons[1].OnClicked += userStatsPrompt.Close;
}
else if (GameSettings.SendUserStatistics)

View File

@@ -27,7 +27,7 @@ namespace Barotrauma
return verticeList;
}
public static VertexPositionTexture[] GenerateWallShapes(List<VoronoiCell> cells)
public static VertexPositionTexture[] GenerateWallShapes(List<VoronoiCell> cells, Level level)
{
float inwardThickness = 500.0f, outWardThickness = 30.0f;
@@ -80,6 +80,10 @@ namespace Barotrauma
#if DEBUG
DebugConsole.ThrowError("Invalid left normal");
#endif
GameAnalyticsManager.AddErrorEventOnce("CaveGenerator.GenerateWallShapes:InvalidLeftNormal:" + level.Seed,
GameAnalyticsSDK.Net.EGAErrorSeverity.Warning,
"Invalid left normal (leftedge: " + leftEdge + ", rightedge: " + rightEdge + ", normal: " + leftNormal + ", seed: " + level.Seed + ")");
if (cell.body != null)
{
GameMain.World.RemoveBody(cell.body);
@@ -106,6 +110,10 @@ namespace Barotrauma
#if DEBUG
DebugConsole.ThrowError("Invalid right normal");
#endif
GameAnalyticsManager.AddErrorEventOnce("CaveGenerator.GenerateWallShapes:InvalidRightNormal:" + level.Seed,
GameAnalyticsSDK.Net.EGAErrorSeverity.Warning,
"Invalid right normal (leftedge: " + leftEdge + ", rightedge: " + rightEdge + ", normal: " + rightNormal + ", seed: " + level.Seed + ")");
if (cell.body != null)
{
GameMain.World.RemoveBody(cell.body);

View File

@@ -44,6 +44,9 @@ namespace Barotrauma.Networking
private FileReceiver fileReceiver;
//has the client been given a character to control this round
public bool HasSpawned;
public byte ID
{
get { return myID; }
@@ -480,7 +483,7 @@ namespace Barotrauma.Networking
if (gameStarted && Screen.Selected == GameMain.GameScreen)
{
endVoteTickBox.Visible = Voting.AllowEndVoting && myCharacter != null;
endVoteTickBox.Visible = Voting.AllowEndVoting && HasSpawned;
if (respawnManager != null)
{
@@ -666,6 +669,7 @@ namespace Barotrauma.Networking
private IEnumerable<object> StartGame(NetIncomingMessage inc)
{
if (Character != null) Character.Remove();
HasSpawned = false;
GameMain.LightManager.LightingEnabled = true;
@@ -815,7 +819,7 @@ namespace Barotrauma.Networking
string subName = inc.ReadString();
string subHash = inc.ReadString();
var matchingSub = Submarine.SavedSubmarines.Find(s => s.Name == subName && s.MD5Hash.Hash == subHash);
var matchingSub = Submarine.SavedSubmarines.FirstOrDefault(s => s.Name == subName && s.MD5Hash.Hash == subHash);
if (matchingSub != null)
{
submarines.Add(matchingSub);
@@ -1016,29 +1020,32 @@ namespace Barotrauma.Networking
ChatMessage.ClientRead(inc);
break;
default:
DebugConsole.ThrowError("Error while reading update from server (unknown object header \""+objHeader+"\"!)");
if (prevObjHeader != null)
List<string> errorLines = new List<string>
{
DebugConsole.ThrowError("Previous object type: " + prevObjHeader.ToString());
}
else
{
DebugConsole.ThrowError("Error occurred on the very first object!");
}
DebugConsole.ThrowError("Previous object was " + (inc.Position - prevBitPos) + " bits long (" + (inc.PositionInBytes - prevBytePos) + " bytes)");
"Error while reading update from server (unknown object header \"" + objHeader + "\"!)",
prevObjHeader != null ? "Previous object type: " + prevObjHeader.ToString() : "Error occurred on the very first object!",
"Previous object was " + (inc.Position - prevBitPos) + " bits long (" + (inc.PositionInBytes - prevBytePos) + " bytes)"
};
if (prevObjHeader == ServerNetObject.ENTITY_EVENT || prevObjHeader == ServerNetObject.ENTITY_EVENT_INITIAL)
{
foreach (IServerSerializable ent in entities)
{
if (ent == null)
{
DebugConsole.ThrowError(" - NULL");
errorLines.Add(" - NULL");
continue;
}
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");
FileStream fl = File.Open("crashreport_object.bin", FileMode.Create);
@@ -1181,8 +1188,12 @@ namespace Barotrauma.Networking
case FileTransferType.Submarine:
new GUIMessageBox("Download finished", "File \"" + transfer.FileName + "\" was downloaded succesfully.");
var newSub = new Submarine(transfer.FilePath);
Submarine.SavedSubmarines.RemoveAll(s => s.Name == newSub.Name && s.MD5Hash.Hash == newSub.MD5Hash.Hash);
Submarine.SavedSubmarines.Add(newSub);
var existingSubs = Submarine.SavedSubmarines.Where(s => s.Name == newSub.Name && s.MD5Hash.Hash == newSub.MD5Hash.Hash).ToList();
foreach (Submarine existingSub in existingSubs)
{
existingSub.Dispose();
}
Submarine.AddToSavedSubs(newSub);
for (int i = 0; i < 2; i++)
{
@@ -1277,6 +1288,23 @@ namespace Barotrauma.Networking
{
base.Draw(spriteBatch);
if (Screen.Selected == GameMain.GameScreen && !GUI.DisableHUD)
{
if (EndVoteCount > 0)
{
if (!HasSpawned)
{
GUI.DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - 180.0f, 40),
"Votes to end the round (y/n): " + EndVoteCount + "/" + (EndVoteMax - EndVoteCount), Color.White, null, 0, GUI.SmallFont);
}
else
{
GUI.DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - 140.0f, 40),
"Votes (y/n): " + EndVoteCount + "/" + (EndVoteMax - EndVoteCount), Color.White, null, 0, GUI.SmallFont);
}
}
}
if (fileReceiver != null && fileReceiver.ActiveTransfers.Count > 0)
{
Vector2 pos = new Vector2(GameMain.NetLobbyScreen.InfoFrame.Rect.X, GameMain.GraphicsHeight - 35);
@@ -1560,14 +1588,13 @@ namespace Barotrauma.Networking
{
if (!gameStarted) return false;
if (!Voting.AllowEndVoting || myCharacter==null)
if (!Voting.AllowEndVoting || !HasSpawned)
{
tickBox.Visible = false;
return false;
}
Vote(VoteType.EndRound, tickBox.Selected);
return false;
}
}

View File

@@ -63,6 +63,15 @@ namespace Barotrauma.Networking
log.LogFrame.Draw(spriteBatch);
}
if (Screen.Selected == GameMain.GameScreen && !GUI.DisableHUD)
{
if (EndVoteCount > 0)
{
GUI.DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - 180.0f, 40),
"Votes to end the round (y/n): " + EndVoteCount + "/" + (EndVoteMax - EndVoteCount), Color.White, null, 0, GUI.SmallFont);
}
}
if (!ShowNetStats) return;
GUI.Font.DrawString(spriteBatch, "Unique Events: " + entityEventManager.UniqueEvents.Count, new Vector2(10, 50), Color.White);

View File

@@ -191,6 +191,9 @@ namespace Barotrauma.Networking
if (GameSettings.VerboseLogging)
{
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;
}

View File

@@ -119,20 +119,6 @@ namespace Barotrauma.Networking
inGameHUD.Draw(spriteBatch);
if (EndVoteCount > 0)
{
if (GameMain.NetworkMember.myCharacter == null)
{
GUI.DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - 180.0f, 40),
"Votes to end the round (y/n): " + EndVoteCount + "/" + (EndVoteMax - EndVoteCount), Color.White, null, 0, GUI.SmallFont);
}
else
{
GUI.DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - 140.0f, 40),
"Votes (y/n): " + EndVoteCount + "/" + (EndVoteMax - EndVoteCount), Color.White, null, 0, GUI.SmallFont);
}
}
if (respawnManager != null)
{
string respawnInfo = "";

View File

@@ -2,6 +2,7 @@
using Lidgren.Network;
using Microsoft.Xna.Framework;
using System.Collections.Generic;
using System.Linq;
namespace Barotrauma
{
@@ -151,7 +152,7 @@ namespace Barotrauma
{
int votes = inc.ReadByte();
string subName = inc.ReadString();
Submarine sub = Submarine.SavedSubmarines.Find(sm => sm.Name == subName);
Submarine sub = Submarine.SavedSubmarines.FirstOrDefault(sm => sm.Name == subName);
SetVoteText(GameMain.NetLobbyScreen.SubList, sub, votes);
}
}

View File

@@ -203,7 +203,7 @@ namespace Barotrauma
if (GameSettings.SendUserStatistics)
{
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();
}
else

View File

@@ -144,7 +144,7 @@ namespace Barotrauma
return true;
};
}
if (Submarine.SavedSubmarines.Count > 0) subList.Select(Submarine.SavedSubmarines[0]);
if (Submarine.SavedSubmarines.Any()) subList.Select(Submarine.SavedSubmarines.First());
}
public void UpdateLoadMenu()

View File

@@ -149,6 +149,8 @@ namespace Barotrauma
null, null,
Alignment.TopRight, "", frame);
}
RefreshItemTab();
}
public void Update(float deltaTime)
@@ -293,6 +295,7 @@ namespace Barotrauma
{
CreateItemFrame(ip, selectedItemList, selectedItemList.Rect.Width);
}
selectedItemList.UpdateScrollBarSize();
}
public void SelectTab(Tab tab)

View File

@@ -88,7 +88,7 @@ namespace Barotrauma
campaignUI.OnLocationSelected = SelectLocation;
campaignUI.UpdateCharacterLists();
if (GameSettings.SendUserStatistics) GameAnalyticsSDK.Net.GameAnalytics.SetCustomDimension01("singleplayer");
GameAnalyticsManager.SetCustomDimension01("singleplayer");
}
public override void AddToGUIUpdateList()

View File

@@ -143,7 +143,7 @@ namespace Barotrauma
SelectTab(null, 0);
if (GameSettings.SendUserStatistics) GameAnalyticsSDK.Net.GameAnalytics.SetCustomDimension01("");
GameAnalyticsManager.SetCustomDimension01("");
}
public bool SelectTab(GUIButton button, object obj)

View File

@@ -501,7 +501,7 @@ namespace Barotrauma
}
}
if (GameSettings.SendUserStatistics) GameAnalyticsSDK.Net.GameAnalytics.SetCustomDimension01("multiplayer");
GameAnalyticsManager.SetCustomDimension01("multiplayer");
if (GameModePreset.list.Count > 0 && modeList.Selected == null) modeList.Select(0);
@@ -737,8 +737,20 @@ namespace Barotrauma
//hash will be null if opening the sub file failed -> don't select the sub
if (string.IsNullOrWhiteSpace(hash))
{
(component as GUITextBlock).TextColor = Color.DarkRed * 0.8f;
component.CanBeFocused = false;
if (component is GUITextBlock textBlock)
{
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;
@@ -782,8 +794,8 @@ namespace Barotrauma
CanBeFocused = false
};
var matchingSub = Submarine.SavedSubmarines.Find(s => s.Name == sub.Name && s.MD5Hash.Hash == sub.MD5Hash.Hash);
if (matchingSub == null) matchingSub = Submarine.SavedSubmarines.Find(s => s.Name == sub.Name);
var matchingSub = Submarine.SavedSubmarines.FirstOrDefault(s => s.Name == sub.Name && s.MD5Hash.Hash == sub.MD5Hash.Hash);
if (matchingSub == null) matchingSub = Submarine.SavedSubmarines.FirstOrDefault(s => s.Name == sub.Name);
if (matchingSub == null)
{
@@ -1467,8 +1479,8 @@ namespace Barotrauma
return false;
}
Submarine sub = Submarine.SavedSubmarines.Find(m => m.Name == subName && m.MD5Hash.Hash == md5Hash);
if (sub == null) sub = Submarine.SavedSubmarines.Find(m => m.Name == subName);
Submarine sub = Submarine.SavedSubmarines.FirstOrDefault(m => m.Name == subName && m.MD5Hash.Hash == md5Hash);
if (sub == null) sub = Submarine.SavedSubmarines.FirstOrDefault(m => m.Name == subName);
var matchingListSub = subList.children.Find(c => c.UserData == sub);
if (matchingListSub != null)

View File

@@ -349,7 +349,7 @@ namespace Barotrauma
cam.UpdateTransform();
if (GameSettings.SendUserStatistics) GameAnalyticsSDK.Net.GameAnalytics.SetCustomDimension01("editor");
GameAnalyticsManager.SetCustomDimension01("editor");
}
public override void Deselect()

View File

@@ -56,7 +56,7 @@ namespace Barotrauma.Sounds
AL.BufferData(sound.alBufferId, reader.Channels == 1 ? ALFormat.Mono16 : ALFormat.Stereo16, sound.castBuffer,
readSamples * sizeof(short), reader.SampleRate);
ALHelper.Check();
ALHelper.Check(oggFile);
}
//AL.Source(alSourceId, ALSourcei.Buffer, alBufferId);
@@ -100,12 +100,12 @@ namespace Barotrauma.Sounds
public void Dispose()
{
//var state = AL.GetSourceState(alSourceId);
//if (state == ALSourceState.Playing || state == ALSourceState.Paused)
// Stop();
System.Diagnostics.Debug.WriteLine(alBufferId);
//AL.DeleteSource(alSourceId);
AL.DeleteBuffer(alBufferId);
if (alBufferId > 0)
{
AL.DeleteBuffer(alBufferId);
alBufferId = 0;
}
//if (ALHelper.Efx.IsInitialized)
// ALHelper.Efx.DeleteFilter(alFilterId);

View File

@@ -45,16 +45,24 @@ namespace Barotrauma.Sounds
//logHandler(String.Format("Total memory : {0:0.###} {1} ", usedHeap, sizes[order]), 0, 6);
}
public static void Check()
public static void Check(string extraErrorMsg = "")
{
ALError error;
if ((error = AL.GetError()) != ALError.NoError)
{
string errorMsg = "OpenAL error: " + AL.GetErrorString(error);
if (!string.IsNullOrEmpty(extraErrorMsg)) errorMsg += " {" + extraErrorMsg + "} ";
errorMsg += "\n" + Environment.StackTrace;
#if DEBUG
DebugConsole.ThrowError("OpenAL error: " + AL.GetErrorString(error) + "\n" + Environment.StackTrace);
DebugConsole.ThrowError(errorMsg);
#else
DebugConsole.NewMessage("OpenAL error: " + AL.GetErrorString(error) + "\n" + Environment.StackTrace, Microsoft.Xna.Framework.Color.Red);
DebugConsole.NewMessage(errorMsg, Microsoft.Xna.Framework.Color.Red);
#endif
GameAnalyticsManager.AddErrorEventOnce(
"OggStream.Check:" + AL.GetErrorString(error) + extraErrorMsg,
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
errorMsg);
}
}
}
@@ -83,9 +91,17 @@ namespace Barotrauma.Sounds
public Action<string, int, int> LogHandler;
#endif
public OggStream(string filename, int bufferCount = DefaultBufferCount) : this(File.OpenRead(filename), bufferCount) { }
public OggStream(Stream stream, int bufferCount = DefaultBufferCount)
public string FileName
{
get;
private set;
}
public OggStream(string filename, int bufferCount = DefaultBufferCount) : this(File.OpenRead(filename), filename, bufferCount) { }
public OggStream(Stream stream, string fileName, int bufferCount = DefaultBufferCount)
{
this.FileName = fileName;
BufferCount = bufferCount;
alBufferIds = AL.GenBuffers(bufferCount);
@@ -94,7 +110,7 @@ namespace Barotrauma.Sounds
if (ALHelper.XRam.IsInitialized)
{
ALHelper.XRam.SetBufferMode(BufferCount, ref alBufferIds[0], XRamExtension.XRamStorage.Hardware);
ALHelper.Check();
ALHelper.Check(fileName);
}
if (ALHelper.Efx.IsInitialized)
@@ -163,7 +179,7 @@ namespace Barotrauma.Sounds
AL.SourcePlay(alSourceId);
this.Volume = volume;
ALHelper.Check();
ALHelper.Check(FileName);
Preparing = false;
@@ -177,7 +193,7 @@ namespace Barotrauma.Sounds
OggStreamer.Instance.RemoveStream(this);
AL.SourcePause(alSourceId);
ALHelper.Check();
ALHelper.Check(FileName);
}
public void Resume()
@@ -187,7 +203,7 @@ namespace Barotrauma.Sounds
OggStreamer.Instance.AddStream(this);
AL.SourcePlay(alSourceId);
ALHelper.Check();
ALHelper.Check(FileName);
}
public void Stop()
@@ -226,7 +242,7 @@ namespace Barotrauma.Sounds
set
{
AL.Source(alSourceId, ALSourcef.Gain, volume = value);
ALHelper.Check();
ALHelper.Check(FileName);
}
}
@@ -256,20 +272,20 @@ namespace Barotrauma.Sounds
/*if (ALHelper.Efx.IsInitialized)
ALHelper.Efx.DeleteFilter(alFilterId);*/
ALHelper.Check();
ALHelper.Check(FileName);
}
void StopPlayback()
{
AL.SourceStop(alSourceId);
ALHelper.Check();
ALHelper.Check(FileName);
}
void Empty()
{
int queued;
AL.GetSource(alSourceId, ALGetSourcei.BuffersQueued, out queued);
ALHelper.Check();
ALHelper.Check(FileName);
if (queued > 0)
{
@@ -292,12 +308,12 @@ namespace Barotrauma.Sounds
if (processed > 0)
{
AL.SourceUnqueueBuffers(alSourceId, processed, salvaged);
ALHelper.Check();
ALHelper.Check(FileName);
}
// Try turning it off again?
AL.SourceStop(alSourceId);
ALHelper.Check();
ALHelper.Check(FileName);
Empty();
}
@@ -314,7 +330,7 @@ namespace Barotrauma.Sounds
// Fill first buffer synchronously
OggStreamer.Instance.FillBuffer(this, alBufferIds[0]);
AL.SourceQueueBuffer(alSourceId, alBufferIds[0]);
ALHelper.Check();
ALHelper.Check(FileName);
// Schedule the others asynchronously
OggStreamer.Instance.AddStream(this);
@@ -429,7 +445,7 @@ namespace Barotrauma.Sounds
}
AL.BufferData(bufferId, stream.Reader.Channels == 1 ? ALFormat.Mono16 : ALFormat.Stereo16, castBuffer,
readSamples * sizeof(short), stream.Reader.SampleRate);
ALHelper.Check();
ALHelper.Check(stream.FileName);
return readSamples != BufferSize;
}
@@ -466,10 +482,10 @@ namespace Barotrauma.Sounds
int queued;
AL.GetSource(stream.alSourceId, ALGetSourcei.BuffersQueued, out queued);
ALHelper.Check();
ALHelper.Check(stream.FileName);
int processed;
AL.GetSource(stream.alSourceId, ALGetSourcei.BuffersProcessed, out processed);
ALHelper.Check();
ALHelper.Check(stream.FileName);
if (processed == 0 && queued == stream.BufferCount) continue;
@@ -496,7 +512,7 @@ namespace Barotrauma.Sounds
}
AL.SourceQueueBuffers(stream.alSourceId, tempBuffers.Length, tempBuffers);
ALHelper.Check();
ALHelper.Check(stream.FileName);
if (finished && !stream.IsLooped)
continue;
@@ -514,7 +530,7 @@ namespace Barotrauma.Sounds
if (state == ALSourceState.Stopped)
{
AL.SourcePlay(stream.alSourceId);
ALHelper.Check();
ALHelper.Check(stream.FileName);
}
}
}

View File

@@ -54,7 +54,7 @@ namespace Barotrauma
{
DebugConsole.ThrowError("Failed to load sound "+file+"!", e);
}
ALHelper.Check();
ALHelper.Check(file);
}
baseVolume = 1.0f;
@@ -219,7 +219,7 @@ namespace Barotrauma
(SoundManager.IsPlaying(alSourceId) || SoundManager.IsPaused(alSourceId)))
{
SoundManager.Stop(alSourceId);
ALHelper.Check();
ALHelper.Check(filePath);
}
foreach (Sound s in loadedSounds)
@@ -228,7 +228,7 @@ namespace Barotrauma
}
SoundManager.ClearAlSource(AlBufferId);
ALHelper.Check();
ALHelper.Check(filePath);
if (oggSound != null)
{

View File

@@ -143,7 +143,7 @@ namespace Barotrauma.Sounds
volume = 0.0f;
}
if (sourceIndex<1 || soundsPlaying[sourceIndex] != sound)
if (sourceIndex < 1 || soundsPlaying[sourceIndex] != sound)
{
sourceIndex = Play(sound, position, volume, 0.0f, true);
}
@@ -153,7 +153,7 @@ namespace Barotrauma.Sounds
AL.Source(alSources[sourceIndex], ALSourceb.Looping, true);
}
ALHelper.Check();
ALHelper.Check(sound?.FilePath);
return sourceIndex;
}
@@ -165,7 +165,7 @@ namespace Barotrauma.Sounds
return;
AL.SourcePause(alSources[sourceIndex]);
ALHelper.Check();
ALHelper.Check(soundsPlaying[sourceIndex]?.FilePath);
}
public static void Resume(int sourceIndex)
@@ -176,7 +176,7 @@ namespace Barotrauma.Sounds
return;
AL.SourcePlay(alSources[sourceIndex]);
ALHelper.Check();
ALHelper.Check(soundsPlaying[sourceIndex]?.FilePath);
}
public static void Stop(int sourceIndex)
@@ -291,7 +291,7 @@ namespace Barotrauma.Sounds
ALHelper.Efx.Filter(lowpassFilterId, OpenTK.Audio.OpenAL.EfxFilterf.LowpassGainHF, lowPassHfGain = value);
ALHelper.Efx.BindFilterToSource(alSources[i], lowpassFilterId);
ALHelper.Check();
ALHelper.Check(soundsPlaying[i]?.FilePath);
}
}
}
@@ -316,7 +316,7 @@ namespace Barotrauma.Sounds
ALHelper.Efx.Filter(lowpassFilterId, OpenTK.Audio.OpenAL.EfxFilterf.LowpassGainHF, lowPassGain);
ALHelper.Efx.BindFilterToSource(alSources[sourceIndex], lowpassFilterId);
ALHelper.Check();
ALHelper.Check(soundsPlaying[sourceIndex]?.FilePath);
}
public static OggStream StartStream(string file, float volume = 1.0f)
@@ -331,7 +331,7 @@ namespace Barotrauma.Sounds
oggStream.Play(volume);
ALHelper.Check();
ALHelper.Check(file);
return oggStream;
}
@@ -361,15 +361,15 @@ namespace Barotrauma.Sounds
for (int i = 0; i < DefaultSourceCount; i++)
{
string soundPath = soundsPlaying[i]?.FilePath;
var state = OpenTK.Audio.OpenAL.AL.GetSourceState(alSources[i]);
if (state == OpenTK.Audio.OpenAL.ALSourceState.Playing || state == OpenTK.Audio.OpenAL.ALSourceState.Paused)
{
Stop(i);
}
OpenTK.Audio.OpenAL.AL.DeleteSource(alSources[i]);
ALHelper.Check();
OpenTK.Audio.OpenAL.AL.DeleteSource(alSources[i]);
ALHelper.Check(soundPath);
}
if (oggStream != null)

View File

@@ -254,11 +254,14 @@ namespace Barotrauma
partial void DisposeTexture()
{
//check if another sprite is using the same texture
foreach (Sprite s in list)
if (!string.IsNullOrEmpty(file)) //file can be empty if the sprite is created directly from a Texture2D instance
{
if (s.file == file) return;
foreach (Sprite s in list)
{
if (s.file == file) return;
}
}
//if not, free the texture
if (texture != null)
{
@@ -267,6 +270,5 @@ namespace Barotrauma
}
}
}
}

View File

@@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.8.1.5")]
[assembly: AssemblyFileVersion("0.8.1.5")]
[assembly: AssemblyVersion("0.8.1.7")]
[assembly: AssemblyFileVersion("0.8.1.7")]

View File

@@ -119,7 +119,7 @@ namespace Barotrauma
subs = Submarine.SavedSubmarines.Where(s => !s.HasTag(SubmarineTag.HideInMenus)).ToList();
if (subs == null || subs.Count()==0)
if (subs == null || subs.Count() == 0)
{
throw new Exception("No submarines are available.");
}
@@ -187,7 +187,7 @@ namespace Barotrauma
if (GameMain.Server.SubSelectionMode == SelectionMode.Random)
{
var nonShuttles = Submarine.SavedSubmarines.FindAll(c => !c.HasTag(SubmarineTag.Shuttle) && !c.HasTag(SubmarineTag.HideInMenus));
var nonShuttles = Submarine.SavedSubmarines.Where(c => !c.HasTag(SubmarineTag.Shuttle) && !c.HasTag(SubmarineTag.HideInMenus)).ToList();
SelectedSub = nonShuttles[Rand.Range(0, nonShuttles.Count)];
}
if (GameMain.Server.ModeSelectionMode == SelectionMode.Random)

View File

@@ -261,7 +261,7 @@
<Sprite texture="signalcomp.png" depth="0.8" sourcerect="48,16,16,16"/>
<RelayComponent canbeselected = "true">
<RelayComponent canbeselected="true" vulnerabletoemp="false">
<GuiFrame rect="0,0,200,160" alignment="Center" style="ItemUI"/>
</RelayComponent>

View File

@@ -21,7 +21,7 @@
<Sprite texture = "reactor.png" sourcerect="0,0,321,192" depth="0.8"/>
<Reactor canbeselected = "true">
<Reactor canbeselected="true" vulnerabletoemp="false">
<GuiFrame rect="0,0,760,460" alignment="Center" style="ItemUI"/>
<RequiredSkill name="Construction" level="30"/>
<StatusEffect type="InWater" target="This" Temperature="-500.0"/>

View File

@@ -38,6 +38,9 @@ namespace Barotrauma
#if DEBUG
DebugConsole.ThrowError("Attempted to access a removed AITarget\n" + Environment.StackTrace);
#endif
GameAnalyticsManager.AddErrorEventOnce("AITarget.WorldPosition:EntityRemoved",
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
"Attempted to access a removed AITarget\n" + Environment.StackTrace);
return Vector2.Zero;
}
@@ -54,6 +57,9 @@ namespace Barotrauma
#if DEBUG
DebugConsole.ThrowError("Attempted to access a removed AITarget\n" + Environment.StackTrace);
#endif
GameAnalyticsManager.AddErrorEventOnce("AITarget.WorldPosition:EntityRemoved",
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
"Attempted to access a removed AITarget\n" + Environment.StackTrace);
return Vector2.Zero;
}

View File

@@ -274,6 +274,12 @@ namespace Barotrauma
private void UpdateEscape(float deltaTime)
{
if (selectedAiTarget == null || selectedAiTarget.Entity == null || selectedAiTarget.Entity.Removed)
{
state = AIState.None;
return;
}
SteeringManager.SteeringManual(deltaTime, Vector2.Normalize(SimPosition - selectedAiTarget.SimPosition) * 5);
SteeringManager.SteeringWander(1.0f);
SteeringManager.SteeringAvoid(deltaTime, 2f);

View File

@@ -25,6 +25,11 @@ namespace Barotrauma
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));
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) + "\n" + Environment.StackTrace);
return new Limb[0];
}
return limbs;
@@ -87,7 +92,9 @@ namespace Barotrauma
protected List<PhysicsBody> collider;
protected int colliderIndex = 0;
private Category prevCollisionCategory = Category.None;
public PhysicsBody Collider
{
get
@@ -269,11 +276,7 @@ namespace Barotrauma
get { return ignorePlatforms; }
set
{
if (ignorePlatforms == value) return;
ignorePlatforms = value;
UpdateCollisionCategories();
}
}
@@ -365,8 +368,8 @@ namespace Barotrauma
foreach (var joint in LimbJoints)
{
joint.BodyB.SetTransform(
joint.BodyA.Position + (joint.LocalAnchorA - joint.LocalAnchorB)*0.1f,
joint.LimbB?.body?.SetTransform(
joint.BodyA.Position + (joint.LocalAnchorA - joint.LocalAnchorB) * 0.1f,
(joint.LowerLimit + joint.UpperLimit) / 2.0f);
}
@@ -391,7 +394,7 @@ namespace Barotrauma
Limb torso = GetLimb(LimbType.Torso);
Limb head = GetLimb(LimbType.Head);
MainLimb = torso == null ? head : torso;
MainLimb = torso ?? head;
}
public void AddJoint(XElement subElement, float scale = 1.0f)
@@ -739,7 +742,15 @@ namespace Barotrauma
public void FindHull(Vector2? worldPosition = null, bool setSubmarine = true)
{
Vector2 findPos = worldPosition==null ? this.WorldPosition : (Vector2)worldPosition;
Vector2 findPos = worldPosition == null ? this.WorldPosition : (Vector2)worldPosition;
if (!MathUtils.IsValid(findPos))
{
GameAnalyticsManager.AddErrorEventOnce(
"Ragdoll.FindHull:InvalidPosition",
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
"Attempted to find a hull at an invalid position (" + findPos + ")\n" + Environment.StackTrace);
return;
}
Hull newHull = Hull.FindHull(findPos, currentHull);
@@ -799,10 +810,7 @@ namespace Barotrauma
}
CurrentHull = newHull;
character.Submarine = currentHull == null ? null : currentHull.Submarine;
UpdateCollisionCategories();
character.Submarine = currentHull?.Submarine;
}
public void Teleport(Vector2 moveAmount, Vector2 velocityChange)
@@ -842,7 +850,10 @@ namespace Barotrauma
Category collisionCategory = (ignorePlatforms) ?
wall | Physics.CollisionProjectile | Physics.CollisionStairs
: wall | Physics.CollisionProjectile | Physics.CollisionPlatform | Physics.CollisionStairs;
if (collisionCategory == prevCollisionCategory) return;
prevCollisionCategory = collisionCategory;
Collider.CollidesWith = collisionCategory;
foreach (Limb limb in Limbs)
@@ -868,6 +879,7 @@ namespace Barotrauma
UpdateNetPlayerPosition(deltaTime);
CheckDistFromCollider();
UpdateCollisionCategories();
Vector2 flowForce = Vector2.Zero;
@@ -1089,22 +1101,19 @@ namespace Barotrauma
float tfloorY = rayStart.Y + (rayEnd.Y - rayStart.Y) * closestFraction;
float targetY = tfloorY + Collider.height * 0.5f + Collider.radius + colliderHeightFromFloor;
if (Math.Abs(Collider.SimPosition.Y - targetY) > 0.01f && Collider.SimPosition.Y<targetY && !forceImmediate)
if (Math.Abs(Collider.SimPosition.Y - targetY) > 0.01f)
{
Vector2 newSpeed = Collider.LinearVelocity;
newSpeed.Y = (targetY - Collider.SimPosition.Y)*5.0f;
Collider.LinearVelocity = newSpeed;
}
else
{
Vector2 newSpeed = Collider.LinearVelocity;
newSpeed.Y = 0.0f;
Collider.LinearVelocity = newSpeed;
Vector2 newPos = Collider.SimPosition;
newPos.Y = targetY;
Collider.SetTransform(newPos, Collider.Rotation);
}
if (forceImmediate)
{
Collider.LinearVelocity = new Vector2(Collider.LinearVelocity.X, 0);
Collider.SetTransform(new Vector2(Collider.SimPosition.X, targetY), Collider.Rotation);
}
else
{
Collider.LinearVelocity = new Vector2(Collider.LinearVelocity.X, (targetY - Collider.SimPosition.Y) * 5.0f);
}
}
}
}
}
@@ -1165,6 +1174,16 @@ namespace Barotrauma
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;
Collider.SetTransform(simPosition, Collider.Rotation);
@@ -1245,8 +1264,6 @@ namespace Barotrauma
{
//set the position of the ragdoll to make sure limbs don't get stuck inside walls when re-enabling collisions
SetPosition(Collider.SimPosition, true);
UpdateCollisionCategories();
collisionsDisabled = false;
}
}
@@ -1445,22 +1462,17 @@ namespace Barotrauma
private Vector2 GetFlowForce()
{
Vector2 limbPos = ConvertUnits.ToDisplayUnits(Limbs[0].SimPosition);
Vector2 limbPos = Limbs[0].Position;
Vector2 force = Vector2.Zero;
foreach (MapEntity e in MapEntity.mapEntityList)
foreach (Gap gap in Gap.GapList)
{
Gap gap = e as Gap;
if (gap == null || gap.FlowTargetHull != currentHull || gap.LerpedFlowForce == Vector2.Zero) continue;
if (gap.Open <= 0.0f || gap.FlowTargetHull != currentHull || gap.LerpedFlowForce == Vector2.Zero) continue;
Vector2 gapPos = gap.SimPosition;
float dist = Vector2.Distance(limbPos, gapPos);
force += Vector2.Normalize(gap.LerpedFlowForce) * (Math.Max(gap.LerpedFlowForce.Length() - dist, 0.0f) / 500.0f);
}
if (force.Length() > 20.0f) return force;
return force;
}

View File

@@ -1960,7 +1960,7 @@ namespace Barotrauma
characterType = "Enemy";
else if (AIController is HumanAIController)
characterType = "AICrew";
GameAnalyticsSDK.Net.GameAnalytics.AddDesignEvent("Kill:" + characterType + ":" + SpeciesName + ":" + causeOfDeath);
GameAnalyticsManager.AddDesignEvent("Kill:" + characterType + ":" + SpeciesName + ":" + causeOfDeath);
}
if (OnDeath != null) OnDeath(this, causeOfDeath);

View File

@@ -1898,7 +1898,16 @@ namespace Barotrauma
if (string.IsNullOrWhiteSpace(command)) return;
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"))
{
NewMessage(command, Color.White, true);
@@ -1974,6 +1983,13 @@ namespace Barotrauma
{
GameMain.Server.SendConsoleMessage("Command \"" + splitCommand[0] + "\" not found.", client);
return;
}
if (!MathUtils.IsValid(cursorWorldPos))
{
GameMain.Server.SendConsoleMessage("Could not execute command \"" + command + "\" - invalid cursor position.", client);
NewMessage(client.Name + " attempted to execute the console command \"" + command + "\" with invalid cursor position.", Color.White);
return;
}
try

View File

@@ -1,19 +1,51 @@
using GameAnalyticsSDK.Net;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Security.Cryptography;
namespace Barotrauma
{
public static class GameAnalyticsManager
{
private static HashSet<string> sentEventIdentifiers = new HashSet<string>();
public static void Init()
{
#if DEBUG
GameAnalytics.SetEnabledInfoLog(true);
#endif
GameAnalytics.ConfigureBuild(GameMain.Version.ToString());
string exePath = Assembly.GetEntryAssembly().Location;
string exeName = null;
Md5Hash exeHash = null;
exeName = Path.GetFileNameWithoutExtension(exePath).Replace(":", "");
var md5 = MD5.Create();
try
{
using (var stream = File.OpenRead(exePath))
{
exeHash = new Md5Hash(stream);
}
}
catch (Exception e)
{
DebugConsole.ThrowError("Error while calculating MD5 hash for the executable \"" + exePath + "\"", e);
}
GameAnalytics.ConfigureBuild(GameMain.Version.ToString()
+ (string.IsNullOrEmpty(exeName) ? "Unknown" : exeName) + ":"
+ ((exeHash?.ShortHash == null) ? "Unknown" : exeHash.ShortHash));
GameAnalytics.AddDesignEvent("Executable:"
+ (string.IsNullOrEmpty(exeName) ? "Unknown" : exeName) + ":"
+ ((exeHash?.ShortHash == null) ? "Unknown" : exeHash.ShortHash));
GameAnalytics.ConfigureAvailableCustomDimensions01("singleplayer", "multiplayer", "editor");
GameAnalytics.Initialize("a3a073c20982de7c15d21e840e149122", "9010ad9a671233b8d9610d76cec8c897d9ff3ba7");
string contentPackageName = GameMain.Config?.SelectedContentPackage?.Name;
if (!string.IsNullOrEmpty(contentPackageName))
{
@@ -21,5 +53,47 @@ namespace Barotrauma
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);
}
public static void AddDesignEvent(string eventID)
{
if (!GameSettings.SendUserStatistics) return;
GameAnalytics.AddDesignEvent(eventID);
}
public static void AddDesignEvent(string eventID, double value)
{
if (!GameSettings.SendUserStatistics) return;
GameAnalytics.AddDesignEvent(eventID, value);
}
public static void AddProgressionEvent(EGAProgressionStatus progressionStatus, string progression01)
{
if (!GameSettings.SendUserStatistics) return;
GameAnalytics.AddProgressionEvent(progressionStatus, progression01);
}
public static void AddProgressionEvent(EGAProgressionStatus progressionStatus, string progression01, string progression02)
{
if (!GameSettings.SendUserStatistics) return;
GameAnalytics.AddProgressionEvent(progressionStatus, progression01, progression02);
}
public static void SetCustomDimension01(string dimension)
{
if (!GameSettings.SendUserStatistics) return;
GameAnalytics.SetCustomDimension01(dimension);
}
}
}

View File

@@ -57,6 +57,7 @@ namespace Barotrauma
public void CreateItems()
{
CreateItems(purchasedItems);
OnItemsChanged?.Invoke();
}
public static void CreateItems(List<ItemPrefab> itemsToSpawn)

View File

@@ -234,13 +234,12 @@ namespace Barotrauma
campaign.CargoManager.CreateItems();
}
}
if (GameSettings.SendUserStatistics)
{
GameAnalyticsSDK.Net.GameAnalytics.AddDesignEvent("Submarine:" + submarine.Name);
GameAnalyticsSDK.Net.GameAnalytics.AddProgressionEvent(GameAnalyticsSDK.Net.EGAProgressionStatus.Start,
GameAnalyticsManager.AddDesignEvent("Submarine:" + submarine.Name);
GameAnalyticsManager.AddDesignEvent("Level", ToolBox.StringToInt(level.Seed));
GameAnalyticsManager.AddProgressionEvent(GameAnalyticsSDK.Net.EGAProgressionStatus.Start,
GameMode.Name, (Mission == null ? "None" : Mission.GetType().ToString()));
}
#if CLIENT
roundSummary = new RoundSummary(this);
@@ -253,11 +252,10 @@ namespace Barotrauma
public void EndRound(string endMessage)
{
if (Mission != null) Mission.End();
if (GameSettings.SendUserStatistics)
{
GameAnalyticsSDK.Net.GameAnalytics.AddProgressionEvent((Mission == null || Mission.Completed) ? GameAnalyticsSDK.Net.EGAProgressionStatus.Complete : GameAnalyticsSDK.Net.EGAProgressionStatus.Fail,
GameMode.Name, (Mission == null ? "None" : Mission.GetType().ToString()));
}
GameAnalyticsManager.AddProgressionEvent(
(Mission == null || Mission.Completed) ? GameAnalyticsSDK.Net.EGAProgressionStatus.Complete : GameAnalyticsSDK.Net.EGAProgressionStatus.Fail,
GameMode.Name,
(Mission == null ? "None" : Mission.GetType().ToString()));
#if CLIENT
if (roundSummary != null)

View File

@@ -164,7 +164,7 @@ namespace Barotrauma
GameMain.Config.Save("config.xml");
}
}
public static bool ShowUserStatisticsPrompt { get; private set; }
public static bool ShowUserStatisticsPrompt { get; set; }
public GameSettings(string filePath)
{
@@ -334,8 +334,12 @@ namespace Barotrauma
new XAttribute("soundvolume", soundVolume),
new XAttribute("verboselogging", VerboseLogging),
new XAttribute("savedebugconsolelogs", SaveDebugConsoleLogs),
new XAttribute("enablesplashscreen", EnableSplashScreen),
new XAttribute("senduserstatistics", sendUserStatistics));
new XAttribute("enablesplashscreen", EnableSplashScreen));
if (!ShowUserStatisticsPrompt)
{
doc.Root.Add(new XAttribute("senduserstatistics", sendUserStatistics));
}
if (WasGameUpdated)
{
@@ -398,7 +402,16 @@ namespace Barotrauma
new XAttribute("gender", characterGender));
doc.Root.Add(playerElement);
doc.Save(filePath);
try
{
doc.Save(filePath);
}
catch (Exception e)
{
DebugConsole.ThrowError("Saving game settings failed.", e);
GameAnalyticsManager.AddErrorEventOnce("GameSettings.Save:SaveFailed", GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
"Saving game settings failed.\n" + e.Message + "\n" + e.StackTrace);
}
}
private IEnumerable<object> ApplyUnsavedChanges()

View File

@@ -345,17 +345,31 @@ namespace Barotrauma.Items.Components
private void CreateDoorBody()
{
Vector2 position = ConvertUnits.ToSimUnits(item.Position + (dockingTarget.door.Item.WorldPosition - item.WorldPosition));
if (!MathUtils.IsValid(position))
{
string errorMsg =
"Attempted to create a door body at an invalid position (item pos: " + item.Position
+ ", item world pos: " + item.WorldPosition
+ ", docking target world pos: " + DockingTarget.door.Item.WorldPosition + ")\n" + Environment.StackTrace;
DebugConsole.ThrowError(errorMsg);
GameAnalyticsManager.AddErrorEventOnce(
"DockingPort.CreateDoorBody:InvalidPosition",
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
errorMsg);
position = Vector2.Zero;
}
doorBody = BodyFactory.CreateRectangle(GameMain.World,
dockingTarget.door.Body.width,
dockingTarget.door.Body.height,
1.0f,
position,
dockingTarget.door);
doorBody.CollisionCategories = Physics.CollisionWall;
doorBody.BodyType = BodyType.Static;
doorBody.SetTransform(
ConvertUnits.ToSimUnits(item.Position + (dockingTarget.door.Item.WorldPosition - item.WorldPosition)),
0.0f);
}
private void CreateHull()

View File

@@ -349,6 +349,14 @@ namespace Barotrauma.Items.Components
private void PushCharactersAway()
{
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 + ")");
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;
}
//push characters out of the doorway when the door is closing/opening
Vector2 simPos = ConvertUnits.ToSimUnits(new Vector2(item.Rect.X, item.Rect.Y));
@@ -360,6 +368,16 @@ namespace Barotrauma.Items.Components
foreach (Character c in Character.CharacterList)
{
if (!c.Enabled) continue;
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 + ")");
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;
}
int dir = isHorizontal ? Math.Sign(c.SimPosition.Y - item.SimPosition.Y) : Math.Sign(c.SimPosition.X - item.SimPosition.X);
List<PhysicsBody> bodies = c.AnimController.Limbs.Select(l => l.body).ToList();
@@ -368,17 +386,24 @@ namespace Barotrauma.Items.Components
foreach (PhysicsBody body in bodies)
{
float diff = 0.0f;
if (!MathUtils.IsValid(body.SimPosition))
{
DebugConsole.ThrowError("Failed to push a limb out of a doorway - position of the body (character \"" + c.Name + "\") is not valid (" + body.SimPosition + ")");
GameAnalyticsManager.AddErrorEventOnce("PushCharactersAway:LimbPosInvalid", GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
"Failed to push a character out of a doorway - position of the character \"" + c.Name + "\" is not valid (" + body.SimPosition + ")." +
" Removed: " + c.Removed +
" Remoteplayer: " + c.IsRemotePlayer);
continue;
}
if (isHorizontal)
{
if (body.SimPosition.X < simPos.X || body.SimPosition.X > simPos.X + simSize.X) continue;
diff = body.SimPosition.Y - item.SimPosition.Y;
}
else
{
if (body.SimPosition.Y > simPos.Y || body.SimPosition.Y < simPos.Y - simSize.Y) continue;
diff = body.SimPosition.X - item.SimPosition.X;
}

View File

@@ -33,8 +33,7 @@ namespace Barotrauma.Items.Components
get { return powerConsumption; }
set { powerConsumption = value; }
}
[Serialize(false, true)]
public override bool IsActive
{
@@ -60,6 +59,13 @@ namespace Barotrauma.Items.Components
set { voltage = Math.Max(0.0f, value); }
}
[Editable(ToolTip = "Can the item be damaged by electomagnetic pulses."), Serialize(true, true)]
public bool VulnerableToEMP
{
get;
set;
}
public Powered(Item item, XElement element)
: base(item, element)
{

View File

@@ -783,12 +783,6 @@ namespace Barotrauma
public override void Update(float deltaTime, Camera cam)
{
if (Level.Loaded != null && WorldPosition.Y < Level.MaxEntityDepth)
{
Spawner.AddToRemoveQueue(this);
return;
}
ApplyStatusEffects(ActionType.Always, deltaTime, null);
foreach (ItemComponent ic in components)
@@ -851,6 +845,12 @@ namespace Barotrauma
MathHelper.Clamp(body.LinearVelocity.X, -MaxVel, MaxVel),
MathHelper.Clamp(body.LinearVelocity.Y, -MaxVel, MaxVel));
}
if (CurrentHull == null && body.SimPosition.Y < ConvertUnits.ToSimUnits(Level.MaxEntityDepth))
{
Spawner.AddToRemoveQueue(this);
return;
}
}
UpdateNetPosition();
@@ -1430,6 +1430,10 @@ namespace Barotrauma
msg.Write(((Rectangle)value).Width);
msg.Write(((Rectangle)value).Height);
}
else if (value is Enum)
{
msg.Write((int)value);
}
else
{
throw new System.NotImplementedException("Serializing item properties of the type \"" + value.GetType() + "\" not supported");
@@ -1487,6 +1491,24 @@ namespace Barotrauma
{
property.TrySetValue(new Vector4(msg.ReadInt32(), msg.ReadInt32(), msg.ReadInt32(), msg.ReadInt32()));
}
else if (typeof(Enum).IsAssignableFrom(type))
{
int intVal = msg.ReadInt32();
try
{
property.TrySetValue(Enum.ToObject(type, intVal));
}
catch (Exception e)
{
#if DEBUG
DebugConsole.ThrowError("Failed to convert the int value \"" + intVal + "\" to " + type, e);
#endif
GameAnalyticsManager.AddErrorEventOnce(
"Item.ReadPropertyChange:" + Name + ":" + type,
GameAnalyticsSDK.Net.EGAErrorSeverity.Warning,
"Failed to convert the int value \"" + intVal + "\" to " + type + " (item " + Name + ")");
}
}
else
{
return;

View File

@@ -78,15 +78,13 @@ namespace Barotrauma
{
float distSqr = Vector2.DistanceSquared(item.WorldPosition, worldPosition);
if (distSqr > displayRangeSqr) continue;
//ignore reactors (don't want to blow them up)
if (item.GetComponent<Reactor>() != null) continue;
float distFactor = 1.0f - (float)Math.Sqrt(distSqr) / displayRange;
//damage repairable power-consuming items
var powerTransfer = item.GetComponent<Powered>();
if (powerTransfer != null && item.FixRequirements.Count > 0)
var powered = item.GetComponent<Powered>();
if (powered == null || !powered.VulnerableToEMP) continue;
if (item.FixRequirements.Count > 0)
{
item.Condition -= 100 * empStrength * distFactor;
}

View File

@@ -323,18 +323,9 @@ namespace Barotrauma
//choose random edge (ignoring ones where the adjacent cell is outside limits)
else
{
//if (allowedEdges.Count==0)
//{
// edgeIndex = Rand.Int(currentCell.edges.Count, false);
//}
//else
//{
edgeIndex = Rand.Int(allowedEdges.Count, Rand.RandSync.Server);
if (mirror && edgeIndex > 0) edgeIndex = allowedEdges.Count - edgeIndex;
edgeIndex = currentCell.edges.IndexOf(allowedEdges[edgeIndex]);
//}
}
currentCell = currentCell.edges[edgeIndex].AdjacentCell(currentCell);
@@ -357,8 +348,8 @@ namespace Barotrauma
return pathCells;
}
public static List<Body> GeneratePolygons(List<VoronoiCell> cells, out List<Vector2[]> renderTriangles, bool setSolid=true)
public static List<Body> GeneratePolygons(List<VoronoiCell> cells, Level level, out List<Vector2[]> renderTriangles, bool setSolid = true)
{
renderTriangles = new List<Vector2[]>();
var bodies = new List<Body>();
@@ -366,6 +357,14 @@ namespace Barotrauma
List<Vector2> tempVertices = new List<Vector2>();
List<Vector2> bodyPoints = new List<Vector2>();
Body cellBody = new Body(GameMain.World)
{
SleepingAllowed = false,
BodyType = BodyType.Static,
CollisionCategories = Physics.CollisionLevel
};
bodies.Add(cellBody);
for (int n = cells.Count - 1; n >= 0; n-- )
{
VoronoiCell cell = cells[n];
@@ -412,14 +411,12 @@ namespace Barotrauma
cell.bodyVertices.Add(bodyPoints[i]);
bodyPoints[i] = ConvertUnits.ToSimUnits(bodyPoints[i]);
}
if (cell.CellType == CellType.Empty) continue;
cellBody.UserData = cell;
var triangles = MathUtils.TriangulateConvexHull(bodyPoints, ConvertUnits.ToSimUnits(cell.Center));
Body cellBody = new Body(GameMain.World);
for (int i = 0; i < triangles.Count; i++)
{
//don't create a triangle if any of the vertices are too close to each other
@@ -429,16 +426,20 @@ namespace Barotrauma
Vector2.Distance(triangles[i][1], triangles[i][2]) < 0.05f) continue;
Vertices bodyVertices = new Vertices(triangles[i]);
FixtureFactory.AttachPolygon(bodyVertices, 5.0f, cellBody);
var newFixture = FixtureFactory.AttachPolygon(bodyVertices, 5.0f, cellBody);
newFixture.UserData = cell;
if (newFixture.Shape.MassData.Area < FarseerPhysics.Settings.Epsilon)
{
DebugConsole.ThrowError("Invalid triangle created by CaveGenerator (" + triangles[i][0] + ", " + triangles[i][1] + ", " + triangles[i][2] + ")");
GameAnalyticsManager.AddErrorEventOnce(
"CaveGenerator.GeneratePolygons:InvalidTriangle",
GameAnalyticsSDK.Net.EGAErrorSeverity.Warning,
"Invalid triangle created by CaveGenerator (" + triangles[i][0] + ", " + triangles[i][1] + ", " + triangles[i][2] + "). Seed: " + level.Seed);
}
}
cellBody.UserData = cell;
cellBody.SleepingAllowed = false;
cellBody.BodyType = BodyType.Kinematic;
cellBody.CollisionCategories = Physics.CollisionLevel;
cell.body = cellBody;
bodies.Add(cellBody);
}
return bodies;

View File

@@ -449,11 +449,11 @@ namespace Barotrauma
List<VoronoiCell> cellsWithBody = new List<VoronoiCell>(cells);
List<Vector2[]> triangles;
bodies = CaveGenerator.GeneratePolygons(cellsWithBody, out triangles);
bodies = CaveGenerator.GeneratePolygons(cellsWithBody, this, out triangles);
#if CLIENT
renderer.SetBodyVertices(CaveGenerator.GenerateRenderVerticeList(triangles).ToArray(), generationParams.WallColor);
renderer.SetWallVertices(CaveGenerator.GenerateWallShapes(cells), generationParams.WallColor);
renderer.SetWallVertices(CaveGenerator.GenerateWallShapes(cells, this), generationParams.WallColor);
#endif
TopBarrier = BodyFactory.CreateEdge(GameMain.World,
@@ -700,7 +700,7 @@ namespace Barotrauma
SeaFloorTopPos = bottomPositions.Max(p => p.Y);
extraWalls = new LevelWall[] { new LevelWall(bottomPositions, new Vector2(0.0f, -2000.0f), backgroundColor) };
extraWalls = new LevelWall[] { new LevelWall(bottomPositions, new Vector2(0.0f, -2000.0f), backgroundColor, this) };
BottomBarrier = BodyFactory.CreateEdge(GameMain.World,
ConvertUnits.ToSimUnits(new Vector2(borders.X, 0)),

View File

@@ -18,10 +18,9 @@ namespace Barotrauma
private List<Body> bodies;
public LevelWall(List<Vector2> edgePositions, Vector2 extendAmount, Color color)
public LevelWall(List<Vector2> edgePositions, Vector2 extendAmount, Color color, Level level)
{
cells = new List<VoronoiCell>();
for (int i = 0; i < edgePositions.Count - 1; i++)
{
Vector2[] vertices = new Vector2[4];
@@ -47,14 +46,13 @@ namespace Barotrauma
cells.Add(wallCell);
}
List<Vector2[]> triangles;
bodies = CaveGenerator.GeneratePolygons(cells, out triangles, false);
bodies = CaveGenerator.GeneratePolygons(cells, level, out List<Vector2[]> triangles, false);
#if CLIENT
List<VertexPositionTexture> bodyVertices = CaveGenerator.GenerateRenderVerticeList(triangles);
SetBodyVertices(bodyVertices.ToArray(), color);
SetWallVertices(CaveGenerator.GenerateWallShapes(cells), color);
SetWallVertices(CaveGenerator.GenerateWallShapes(cells, level), color);
#endif
}

View File

@@ -423,6 +423,7 @@ namespace Barotrauma.RuinGeneration
Alignment[] alignments = new Alignment[] { Alignment.Top, Alignment.Bottom, Alignment.Right, Alignment.Left, Alignment.Center };
var prop = RuinStructure.GetRandom(RuinStructureType.Prop, alignments[Rand.Int(alignments.Length, Rand.RandSync.Server)]);
if (prop == null) continue;
Vector2 size = (prop.Prefab is StructurePrefab) ? ((StructurePrefab)prop.Prefab).Size : Vector2.Zero;

View File

@@ -51,8 +51,12 @@ namespace Barotrauma
public static bool LockX, LockY;
public static List<Submarine> SavedSubmarines = new List<Submarine>();
private static List<Submarine> savedSubmarines = new List<Submarine>();
public static IEnumerable<Submarine> SavedSubmarines
{
get { return savedSubmarines; }
}
public static readonly Vector2 GridSize = new Vector2(16.0f, 16.0f);
public static Submarine[] MainSubs = new Submarine[2];
@@ -214,10 +218,10 @@ namespace Barotrauma
return ConvertUnits.ToSimUnits(Position);
}
}
public Vector2 Velocity
{
get { return subBody==null ? Vector2.Zero : subBody.Velocity; }
get { return subBody == null ? Vector2.Zero : subBody.Velocity; }
set
{
if (subBody == null) return;
@@ -244,7 +248,7 @@ namespace Barotrauma
public override string ToString()
{
return "Barotrauma.Submarine ("+name+")";
return "Barotrauma.Submarine (" + name + ")";
}
public override bool Removed
@@ -296,9 +300,19 @@ namespace Barotrauma
string previewImageData = doc.Root.GetAttributeString("previewimage", "");
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
@@ -344,7 +358,7 @@ namespace Barotrauma
{
if (dockedSub == this) continue;
Vector2 diff = dockedSub.Submarine == this ? dockedSub.WorldPosition : dockedSub.WorldPosition - WorldPosition;
Vector2 diff = dockedSub.Submarine == this ? dockedSub.WorldPosition : dockedSub.WorldPosition - WorldPosition;
Rectangle dockedSubBorders = dockedSub.Borders;
dockedSubBorders.Y -= dockedSubBorders.Height;
@@ -383,15 +397,15 @@ namespace Barotrauma
public Vector2 FindSpawnPos(Vector2 spawnPos)
{
Rectangle dockedBorders = GetDockedBorders();
int iterations = 0;
bool wallTooClose = false;
do
{
Rectangle worldBorders = new Rectangle(
dockedBorders.X + (int)spawnPos.X,
dockedBorders.Y + (int)spawnPos.Y,
dockedBorders.Width,
dockedBorders.Y + (int)spawnPos.Y,
dockedBorders.Width,
dockedBorders.Height);
wallTooClose = false;
@@ -507,8 +521,8 @@ namespace Barotrauma
public Rectangle CalculateDimensions(bool onlyHulls = true)
{
List<MapEntity> entities = onlyHulls ?
Hull.hullList.FindAll(h => h.Submarine == this).Cast<MapEntity>().ToList() :
List<MapEntity> entities = onlyHulls ?
Hull.hullList.FindAll(h => h.Submarine == this).Cast<MapEntity>().ToList() :
MapEntity.mapEntityList.FindAll(me => me.Submarine == this);
if (entities.Count == 0) return Rectangle.Empty;
@@ -557,7 +571,7 @@ namespace Barotrauma
}
}
public static bool RectsOverlap(Rectangle rect1, Rectangle rect2, bool inclusive=true)
public static bool RectsOverlap(Rectangle rect1, Rectangle rect2, bool inclusive = true)
{
if (inclusive)
{
@@ -584,25 +598,25 @@ namespace Barotrauma
{
if (fixture == null ||
(ignoreSensors && fixture.IsSensor) ||
fixture.CollisionCategories == Category.None ||
fixture.CollisionCategories == Category.None ||
fixture.CollisionCategories == Physics.CollisionItem) return -1;
if (collisionCategory != null &&
if (collisionCategory != null &&
!fixture.CollisionCategories.HasFlag((Category)collisionCategory) &&
!((Category)collisionCategory).HasFlag(fixture.CollisionCategories)) return -1;
if (ignoredBodies != null && ignoredBodies.Contains(fixture.Body)) return -1;
Structure structure = fixture.Body.UserData as Structure;
Structure structure = fixture.Body.UserData as Structure;
if (structure != null)
{
if (structure.IsPlatform && collisionCategory != null && !((Category)collisionCategory).HasFlag(Physics.CollisionPlatform)) return -1;
}
}
if (fraction < closestFraction)
{
closestFraction = fraction;
if (fixture.Body!=null) closestBody = fixture.Body;
if (fixture.Body != null) closestBody = fixture.Body;
}
return fraction;
}
@@ -669,7 +683,7 @@ namespace Barotrauma
get { return flippedX; }
}
public void FlipX(List<Submarine> parents=null)
public void FlipX(List<Submarine> parents = null)
{
if (parents == null) parents = new List<Submarine>();
parents.Add(this);
@@ -729,7 +743,7 @@ namespace Barotrauma
{
if (bodyItems.Contains(item))
{
item.Submarine = this;
item.Submarine = this;
if (Position == Vector2.Zero) item.Move(-HiddenSubPosition);
}
else if (item.Submarine != this)
@@ -751,7 +765,7 @@ namespace Barotrauma
if (Level.Loaded == null || subBody == null) return;
if (WorldPosition.Y < Level.MaxEntityDepth &&
subBody.Body.Enabled &&
subBody.Body.Enabled &&
(GameMain.NetworkMember?.RespawnManager == null || this != GameMain.NetworkMember.RespawnManager.RespawnShuttle))
{
subBody.Body.ResetDynamics();
@@ -778,26 +792,26 @@ namespace Barotrauma
}
subBody.Body.LinearVelocity = new Vector2(
LockX ? 0.0f : subBody.Body.LinearVelocity.X,
LockX ? 0.0f : subBody.Body.LinearVelocity.X,
LockY ? 0.0f : subBody.Body.LinearVelocity.Y);
subBody.Update(deltaTime);
for (int i = 0; i < 2; i++ )
for (int i = 0; i < 2; i++)
{
if (MainSubs[i] == null) continue;
if (this != MainSubs[i] && MainSubs[i].DockedTo.Contains(this)) return;
}
//send updates more frequently if moving fast
networkUpdateTimer -= MathHelper.Clamp(Velocity.Length()*10.0f, 0.1f, 5.0f) * deltaTime;
networkUpdateTimer -= MathHelper.Clamp(Velocity.Length() * 10.0f, 0.1f, 5.0f) * deltaTime;
if (networkUpdateTimer < 0.0f)
{
networkUpdateTimer = 1.0f;
}
}
public void ApplyForce(Vector2 force)
@@ -867,7 +881,7 @@ namespace Barotrauma
subBorders.Inflate(500.0f, 500.0f);
if (subBorders.Contains(position)) return sub;
if (subBorders.Contains(position)) return sub;
}
return null;
@@ -875,9 +889,18 @@ namespace Barotrauma
//saving/loading ----------------------------------------------------
public static void AddToSavedSubs(Submarine sub)
{
savedSubmarines.Add(sub);
}
public static void RefreshSavedSubs()
{
SavedSubmarines.Clear();
for (int i = savedSubmarines.Count - 1; i>= 0; i--)
{
savedSubmarines[i].Dispose();
}
System.Diagnostics.Debug.Assert(savedSubmarines.Count == 0);
if (!Directory.Exists(SavePath))
{
@@ -921,7 +944,7 @@ namespace Barotrauma
foreach (string path in filePaths)
{
SavedSubmarines.Add(new Submarine(path));
savedSubmarines.Add(new Submarine(path));
}
}
@@ -971,7 +994,7 @@ namespace Barotrauma
catch (Exception e)
{
DebugConsole.ThrowError("Loading submarine \"" + file + "\" failed! ("+e.Message+")");
DebugConsole.ThrowError("Loading submarine \"" + file + "\" failed! (" + e.Message + ")");
return null;
}
}
@@ -1147,12 +1170,12 @@ namespace Barotrauma
Submarine sub = new Submarine(element.GetAttributeString("name", ""), "", false);
sub.Load(unloadPrevious, element);
return sub;
return sub;
}
public static Submarine Load(string fileName, bool unloadPrevious)
{
return Load(fileName, SavePath, unloadPrevious);
return Load(fileName, SavePath, unloadPrevious);
}
public static Submarine Load(string fileName, string folder, bool unloadPrevious)
@@ -1285,6 +1308,15 @@ namespace Barotrauma
DockedTo.Clear();
}
public void Dispose()
{
savedSubmarines.Remove(this);
#if CLIENT
PreviewImage?.Remove();
PreviewImage = null;
#endif
}
public void ServerWrite(NetBuffer msg, Client c, object[] extraData = null)
{
msg.Write(ID);

View File

@@ -370,27 +370,22 @@ namespace Barotrauma
public bool OnCollision(Fixture f1, Fixture f2, Contact contact)
{
Limb limb = f2.Body.UserData as Limb;
if (limb != null)
if (f2.Body.UserData is Limb limb)
{
bool collision = CheckLimbCollision(contact, limb);
if (collision) HandleLimbCollision(contact, limb);
return collision;
}
VoronoiCell cell = f2.Body.UserData as VoronoiCell;
if (cell != null)
if (f2.UserData is VoronoiCell cell)
{
HandleLevelCollision(contact, Vector2.Normalize(ConvertUnits.ToDisplayUnits(Body.SimPosition) - cell.Center));
return true;
}
Structure structure = f2.Body.UserData as Structure;
if (structure != null)
if (f2.Body.UserData is Structure structure)
{
Vector2 normal;
FixedArray2<Vector2> points;
contact.GetWorldManifold(out normal, out points);
contact.GetWorldManifold(out Vector2 normal, out FixedArray2<Vector2> points);
if (contact.FixtureA.Body == f1.Body)
{
normal = -normal;
@@ -400,8 +395,7 @@ namespace Barotrauma
return true;
}
Submarine otherSub = f2.Body.UserData as Submarine;
if (otherSub != null)
if (f2.Body.UserData is Submarine otherSub)
{
HandleSubCollision(contact, otherSub);
return true;
@@ -486,8 +480,8 @@ namespace Barotrauma
levelContact.GetWorldManifold(out contactNormal, out temp);
//if the contact normal is pointing from the limb towards the level cell it's touching, flip the normal
VoronoiCell cell = levelContact.FixtureB.Body.UserData is VoronoiCell ?
((VoronoiCell)levelContact.FixtureB.Body.UserData) : ((VoronoiCell)levelContact.FixtureA.Body.UserData);
VoronoiCell cell = levelContact.FixtureB.UserData is VoronoiCell ?
((VoronoiCell)levelContact.FixtureB.UserData) : ((VoronoiCell)levelContact.FixtureA.UserData);
var cellDiff = ConvertUnits.ToDisplayUnits(limb.body.SimPosition) - cell.Center;
if (Vector2.Dot(contactNormal, cellDiff) < 0)
@@ -603,8 +597,8 @@ namespace Barotrauma
levelContact.GetWorldManifold(out contactNormal, out temp);
//if the contact normal is pointing from the sub towards the level cell we collided with, flip the normal
VoronoiCell cell = levelContact.FixtureB.Body.UserData is VoronoiCell ?
((VoronoiCell)levelContact.FixtureB.Body.UserData) : ((VoronoiCell)levelContact.FixtureA.Body.UserData);
VoronoiCell cell = levelContact.FixtureB.UserData is VoronoiCell ?
((VoronoiCell)levelContact.FixtureB.UserData) : ((VoronoiCell)levelContact.FixtureA.UserData);
var cellDiff = ConvertUnits.ToDisplayUnits(Body.SimPosition) - cell.Center;
if (Vector2.Dot(contactNormal, cellDiff) < 0)

View File

@@ -271,7 +271,7 @@ namespace Barotrauma.Networking
case (byte)FileTransferType.Submarine:
string fileName = inc.ReadString();
string fileHash = inc.ReadString();
var requestedSubmarine = Submarine.SavedSubmarines.Find(s => s.Name == fileName && s.MD5Hash.Hash == fileHash);
var requestedSubmarine = Submarine.SavedSubmarines.FirstOrDefault(s => s.Name == fileName && s.MD5Hash.Hash == fileHash);
if (requestedSubmarine != null)
{

View File

@@ -209,7 +209,7 @@ namespace Barotrauma.Networking
GameMain.NetLobbyScreen.RandomizeSettings();
started = true;
if (GameSettings.SendUserStatistics) GameAnalyticsSDK.Net.GameAnalytics.AddDesignEvent("GameServer:Start");
GameAnalyticsManager.AddDesignEvent("GameServer:Start");
yield return CoroutineStatus.Success;
}
@@ -1370,7 +1370,7 @@ namespace Barotrauma.Networking
}
}
if (GameSettings.SendUserStatistics) GameAnalyticsSDK.Net.GameAnalytics.AddDesignEvent("Traitors:" + (TraitorManager == null ? "Disabled" : "Enabled"));
GameAnalyticsManager.AddDesignEvent("Traitors:" + (TraitorManager == null ? "Disabled" : "Enabled"));
SendStartMessage(roundStartSeed, Submarine.MainSub, GameMain.GameSession.GameMode.Preset, connectedClients);
@@ -1583,24 +1583,7 @@ namespace Barotrauma.Networking
BanClient(client, reason, range, duration);
}
public void BanClient(NetConnection conn, string reason, bool range = false, TimeSpan? duration = null)
{
Client client = connectedClients.Find(c => c.Connection == conn);
if (client == null)
{
conn.Disconnect("You have been banned from the server");
if (!banList.IsBanned(conn.RemoteEndPoint.Address.ToString()))
{
banList.BanPlayer("Unnamed", conn.RemoteEndPoint.Address.ToString(), reason, duration);
}
}
else
{
BanClient(client, reason, range);
}
}
public void BanClient(Client client, string reason, bool range = false, TimeSpan? duration = null)
{
if (client == null) return;
@@ -2266,11 +2249,8 @@ namespace Barotrauma.Networking
Log("Shutting down the server...", ServerLog.MessageType.ServerMessage);
log.Save();
}
if (GameSettings.SendUserStatistics)
{
GameAnalyticsSDK.Net.GameAnalytics.AddDesignEvent("GameServer:ShutDown");
}
GameAnalyticsManager.AddDesignEvent("GameServer:ShutDown");
server.Shutdown("The server has been shut down");
}
}

View File

@@ -30,6 +30,9 @@ namespace Barotrauma.Networking
catch (Exception 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
//(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)
{
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

View File

@@ -93,7 +93,7 @@ namespace Barotrauma
{
case VoteType.Sub:
string subName = inc.ReadString();
Submarine sub = Submarine.SavedSubmarines.Find(s => s.Name == subName);
Submarine sub = Submarine.SavedSubmarines.FirstOrDefault(s => s.Name == subName);
sender.SetVote(voteType, sub);
#if CLIENT
UpdateVoteTexts(GameMain.Server.ConnectedClients, voteType);

View File

@@ -360,6 +360,44 @@ namespace Barotrauma
this.radius = radius;
}
private bool IsValidValue(float value, string valueName)
{
if (!MathUtils.IsValid(value))
{
string errorMsg =
"Attempted to apply invalid " + valueName +
" to a physics body (userdata: " + UserData == null ? "null" : UserData.ToString() +
"), value: " + value + "\n" + Environment.StackTrace;
DebugConsole.ThrowError(errorMsg);
GameAnalyticsManager.AddErrorEventOnce(
"PhysicsBody.SetPosition:InvalidPosition",
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
errorMsg);
return false;
}
return true;
}
private bool IsValidValue(Vector2 value, string valueName)
{
if (!MathUtils.IsValid(value))
{
string errorMsg =
"Attempted to apply invalid " + valueName +
" to a physics body (userdata: " + UserData == null ? "null" : UserData.ToString() +
"), value: " + value + "\n" + Environment.StackTrace;
DebugConsole.ThrowError(errorMsg);
GameAnalyticsManager.AddErrorEventOnce(
"PhysicsBody.SetPosition:InvalidPosition",
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
errorMsg);
return false;
}
return true;
}
public void ResetDynamics()
{
body.ResetDynamics();
@@ -367,6 +405,7 @@ namespace Barotrauma
public void ApplyLinearImpulse(Vector2 impulse)
{
if (!IsValidValue(impulse, "impulse")) return;
body.ApplyLinearImpulse(impulse);
}
@@ -375,6 +414,9 @@ namespace Barotrauma
/// </summary>
public void ApplyLinearImpulse(Vector2 impulse, float maxVelocity)
{
if (!IsValidValue(impulse, "impulse")) return;
if (!IsValidValue(maxVelocity, "max velocity")) return;
float currSpeed = body.LinearVelocity.Length();
Vector2 velocityAddition = impulse / Mass;
Vector2 newVelocity = body.LinearVelocity + velocityAddition;
@@ -385,21 +427,26 @@ namespace Barotrauma
public void ApplyLinearImpulse(Vector2 impulse, Vector2 point)
{
if (!IsValidValue(impulse, "impulse")) return;
body.ApplyLinearImpulse(impulse, point);
}
public void ApplyForce(Vector2 force)
{
if (!IsValidValue(force, "force")) return;
body.ApplyForce(force);
}
public void ApplyForce(Vector2 force, Vector2 point)
{
if (!IsValidValue(force, "force")) return;
if (!IsValidValue(point, "point")) return;
body.ApplyForce(force, point);
}
public void ApplyTorque(float torque)
{
if (!IsValidValue(torque, "torque")) return;
body.ApplyTorque(torque);
}
@@ -408,7 +455,10 @@ namespace Barotrauma
System.Diagnostics.Debug.Assert(MathUtils.IsValid(simPosition));
System.Diagnostics.Debug.Assert(Math.Abs(simPosition.X) < 1000000.0f);
System.Diagnostics.Debug.Assert(Math.Abs(simPosition.Y) < 1000000.0f);
if (!IsValidValue(simPosition, "position")) return;
if (!IsValidValue(rotation, "rotation")) return;
body.SetTransform(simPosition, rotation);
SetPrevTransform(simPosition, rotation);
}
@@ -418,14 +468,20 @@ namespace Barotrauma
System.Diagnostics.Debug.Assert(MathUtils.IsValid(simPosition));
System.Diagnostics.Debug.Assert(Math.Abs(simPosition.X) < 1000000.0f);
System.Diagnostics.Debug.Assert(Math.Abs(simPosition.Y) < 1000000.0f);
if (!IsValidValue(simPosition, "position")) return;
if (!IsValidValue(rotation, "rotation")) return;
body.SetTransformIgnoreContacts(ref simPosition, rotation);
SetPrevTransform(simPosition, rotation);
}
public void SetPrevTransform(Vector2 position, float rotation)
public void SetPrevTransform(Vector2 simPosition, float rotation)
{
prevPosition = position;
if (!IsValidValue(simPosition, "position")) return;
if (!IsValidValue(rotation, "rotation")) return;
prevPosition = simPosition;
prevRotation = rotation;
}
@@ -440,16 +496,19 @@ namespace Barotrauma
prevPosition = (Vector2)targetPosition;
}
body.SetTransform((Vector2)targetPosition, targetRotation == null ? body.Rotation : (float)targetRotation);
SetTransform((Vector2)targetPosition, targetRotation == null ? body.Rotation : (float)targetRotation);
targetPosition = null;
}
public void MoveToPos(Vector2 pos, float force, Vector2? pullPos = null)
public void MoveToPos(Vector2 simPosition, float force, Vector2? pullPos = null)
{
if (pullPos == null) pullPos = body.Position;
if (!IsValidValue(simPosition, "position")) return;
if (!IsValidValue(force, "force")) return;
Vector2 vel = body.LinearVelocity;
Vector2 deltaPos = pos - (Vector2)pullPos;
Vector2 deltaPos = simPosition - (Vector2)pullPos;
deltaPos *= force;
body.ApplyLinearImpulse((deltaPos - vel * 0.5f) * body.Mass, (Vector2)pullPos);
}
@@ -474,8 +533,8 @@ namespace Barotrauma
dragForce = Math.Min(drag, Mass * 500.0f) * -velDir;
}
body.ApplyForce(dragForce + buoyancy);
body.ApplyTorque(body.AngularVelocity * body.Mass * -0.08f);
ApplyForce(dragForce + buoyancy);
ApplyTorque(body.AngularVelocity * body.Mass * -0.08f);
}
@@ -559,18 +618,17 @@ namespace Barotrauma
public void SmoothRotate(float targetRotation, float force = 10.0f)
{
float nextAngle = body.Rotation + body.AngularVelocity * (float)Timing.Step;
float angle = MathUtils.GetShortestAngle(nextAngle, targetRotation);
float torque = angle * 60.0f * (force/100.0f);
float torque = angle * 60.0f * (force / 100.0f);
if (body.IsKinematic)
{
if (!IsValidValue(torque, "torque")) return;
body.AngularVelocity = torque;
}
else
{
body.ApplyTorque(body.Mass * torque);
ApplyTorque(body.Mass * torque);
}
}

View File

@@ -223,6 +223,7 @@ namespace Barotrauma
return false;
}
propertyInfo.SetValue(obj, enumVal);
return true;
}
else
{

View File

@@ -1,3 +1,29 @@
---------------------------------------------------------------------------------------------------------
v0.8.1.7
---------------------------------------------------------------------------------------------------------
- Fixed crashes when trying to load submarines in the sub editor.
---------------------------------------------------------------------------------------------------------
v0.8.1.6
---------------------------------------------------------------------------------------------------------
- Fixed a memory leak in submarine preview images which caused crashes in the server lobby screen and
submarine editor.
- Fixed clients not seeing the "vote to end the round" tickbox if they don't have a character assigned to
them (despite the server allowing voting if the client has had a character earlier during the round).
- Fixed clients being able to crash servers if they had the permission to use console commands that
use the position of the client's cursor.
- Fixed crashing if a wire is used by a statuseffect (for example if a detonator tries to trigger a wire
contained inside it).
- Fixed GameAnalytics being stopped if the dedicated server is restarted with the "restart" console command.-
- Fixed wiring items outside the submarine.
- Fixed chatbox discarding the second chat message instead of the first one when the maximum number of
chat messages is reached.
- Some error checking and debug logging to diagnose and prevent a crash caused by doors pushing characters away.
- The spawnitem command doesn't require multi-word item names to be surrounded with quotes anymore.
- Added the option to make powered items immune to electromagnetic pulses.
---------------------------------------------------------------------------------------------------------
v0.8.1.5
---------------------------------------------------------------------------------------------------------