(a410fd46c) Trying to help the merge script through a jungle of merges
This commit is contained in:
@@ -202,6 +202,8 @@
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Screens\SubEditorScreen.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Serialization\SerializableEntityEditor.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Sounds\OggSound.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Sounds\OpenAL\Al.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Sounds\OpenAL\Alc.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Sounds\Sound.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Sounds\SoundChannel.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Sounds\SoundFilters.cs" />
|
||||
@@ -220,7 +222,6 @@
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Sprite\SpriteSheet.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\StatusEffects\StatusEffect.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Utils\LocalizationCSVtoXML.cs">
|
||||
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
|
||||
</Compile>
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Utils\MathUtils.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Utils\OpenFileDialog.cs" />
|
||||
|
||||
@@ -118,9 +118,6 @@
|
||||
<Content Include="MonoGame.Framework.dll.config">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="OpenTK.dll.config">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Shaders\solidcolor_opengl.fx" />
|
||||
<Content Include="SharpFont.dll.config">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
@@ -350,7 +347,7 @@
|
||||
<Import Project="ClientCode.projitems" Label="Shared" />
|
||||
<Import Project="..\BarotraumaShared\SharedCode.projitems" Label="Shared" />
|
||||
<Import Project="..\BarotraumaShared\SharedContent.projitems" Label="Shared" />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="..\..\Libraries\NuGet\GameAnalytics.Mono.SDK.2.1.6\build\net45\GameAnalytics.Mono.SDK.targets" Condition="Exists('..\..\Libraries\NuGet\GameAnalytics.Mono.SDK.2.1.6\build\net45\GameAnalytics.Mono.SDK.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
@@ -368,8 +365,9 @@
|
||||
<Target Name="AfterBuild">
|
||||
<!-- Write version number to a "Version.txt" file in the output folder -->
|
||||
<GetAssemblyIdentity AssemblyFiles="$(TargetPath)">
|
||||
<Output TaskParameter="Assemblies" ItemName="CurrentAssembly" />
|
||||
<Output TaskParameter="Assemblies" ItemName="CurrentAssembly" />
|
||||
</GetAssemblyIdentity>
|
||||
<Exec Command="echo v%(CurrentAssembly.Version) > $(TargetDir)Version.txt"></Exec>
|
||||
<Exec Command="echo v%(CurrentAssembly.Version) > $(TargetDir)Version.txt">
|
||||
</Exec>
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -117,9 +117,6 @@
|
||||
<Content Include="MonoGame.Framework.dll.config">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="OpenTK.dll.config">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Shaders\solidcolor_opengl.fx" />
|
||||
<Content Include="SharpFont.dll.config">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
|
||||
Binary file not shown.
@@ -1,25 +0,0 @@
|
||||
<configuration>
|
||||
<dllmap os="linux" dll="opengl32.dll" target="libGL.so.1"/>
|
||||
<dllmap os="linux" dll="glu32.dll" target="libGLU.so.1"/>
|
||||
<dllmap os="linux" dll="openal32.dll" target="libopenal.so.1"/>
|
||||
<dllmap os="linux" dll="alut.dll" target="libalut.so.0"/>
|
||||
<dllmap os="linux" dll="opencl.dll" target="libOpenCL.so"/>
|
||||
<dllmap os="linux" dll="libX11" target="libX11.so.6"/>
|
||||
<dllmap os="linux" dll="libXi" target="libXi.so.6"/>
|
||||
<!-- <dllmap os="linux" dll="SDL2.dll" target="libSDL2-2.0.so.0"/> -->
|
||||
<dllmap os="osx" dll="opengl32.dll" target="/System/Library/Frameworks/OpenGL.framework/OpenGL"/>
|
||||
<dllmap os="osx" dll="openal32.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
|
||||
<dllmap os="osx" dll="alut.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
|
||||
<dllmap os="osx" dll="libGLES.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
|
||||
<dllmap os="osx" dll="libGLESv1_CM.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
|
||||
<dllmap os="osx" dll="libGLESv2.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
|
||||
<dllmap os="osx" dll="opencl.dll" target="/System/Library/Frameworks/OpenCL.framework/OpenCL"/>
|
||||
<dllmap os="osx" dll="SDL2.dll" target="libSDL2.dylib"/>
|
||||
<!-- XQuartz compatibility (X11 on Mac) -->
|
||||
<dllmap os="osx" dll="libGL.so.1" target="/usr/X11/lib/libGL.dylib"/>
|
||||
<dllmap os="osx" dll="libX11" target="/usr/X11/lib/libX11.dylib"/>
|
||||
<dllmap os="osx" dll="libXcursor.so.1" target="/usr/X11/lib/libXcursor.dylib"/>
|
||||
<dllmap os="osx" dll="libXi" target="/usr/X11/lib/libXi.dylib"/>
|
||||
<dllmap os="osx" dll="libXinerama" target="/usr/X11/lib/libXinerama.dylib"/>
|
||||
<dllmap os="osx" dll="libXrandr.so.2" target="/usr/X11/lib/libXrandr.dylib"/>
|
||||
</configuration>
|
||||
@@ -39,10 +39,14 @@ namespace Barotrauma
|
||||
else if (Entity is Item)
|
||||
{
|
||||
color = Color.CadetBlue;
|
||||
// disable the indicators for items, because they clutter the debug view
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
color = Color.WhiteSmoke;
|
||||
// disable the indicators for structures, because they clutter the debug view
|
||||
return;
|
||||
}
|
||||
ShapeExtensions.DrawCircle(spriteBatch, pos, SightRange, 100, color, thickness: 1 / Screen.Selected.Cam.Zoom);
|
||||
ShapeExtensions.DrawCircle(spriteBatch, pos, 6, 8, color, thickness: 2 / Screen.Selected.Cam.Zoom);
|
||||
|
||||
@@ -219,7 +219,7 @@ namespace Barotrauma
|
||||
{
|
||||
//hull subs don't match => teleport the camera to the other sub
|
||||
character.Submarine = serverHull.Submarine;
|
||||
character.CurrentHull = currentHull = serverHull;
|
||||
character.CurrentHull = CurrentHull = serverHull;
|
||||
SetPosition(serverPos.Position);
|
||||
character.MemLocalState.Clear();
|
||||
}
|
||||
@@ -369,11 +369,11 @@ namespace Barotrauma
|
||||
LimbJoints.ForEach(j => j.UpdateDeformations(deltaTime));
|
||||
foreach (var deformation in SpriteDeformations)
|
||||
{
|
||||
if (character.IsDead && deformation.DeformationParams.StopWhenHostIsDead) { continue; }
|
||||
if (deformation.DeformationParams.UseMovementSine)
|
||||
{
|
||||
if (this is AnimController animator)
|
||||
{
|
||||
//deformation.Phase = MathUtils.WrapAngleTwoPi(animator.WalkPos + MathHelper.Pi);
|
||||
deformation.Phase = MathUtils.WrapAngleTwoPi(animator.WalkPos * deformation.DeformationParams.Frequency + MathHelper.Pi * deformation.DeformationParams.SineOffset);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -538,13 +538,10 @@ namespace Barotrauma
|
||||
if (wearable.InheritLimbDepth)
|
||||
{
|
||||
depth = ActiveSprite.Depth - depthStep;
|
||||
if (wearable.DepthLimb != LimbType.None)
|
||||
Limb depthLimb = (wearable.DepthLimb == LimbType.None) ? this : character.AnimController.GetLimb(wearable.DepthLimb);
|
||||
if (depthLimb != null)
|
||||
{
|
||||
Limb depthLimb = character.AnimController.GetLimb(wearable.DepthLimb);
|
||||
if (depthLimb != null)
|
||||
{
|
||||
depth = depthLimb.ActiveSprite.Depth - depthStep;
|
||||
}
|
||||
depth = depthLimb.ActiveSprite.Depth - depthStep;
|
||||
}
|
||||
}
|
||||
var wearableItemComponent = wearable.WearableComponent;
|
||||
|
||||
@@ -62,9 +62,21 @@ namespace Barotrauma
|
||||
{
|
||||
frame = new GUIFrame(new RectTransform(new Vector2(0.5f, 0.45f), GUI.Canvas) { MinSize = new Point(400, 300), AbsoluteOffset = new Point(10, 10) },
|
||||
color: new Color(0.4f, 0.4f, 0.4f, 0.8f));
|
||||
|
||||
var paddedFrame = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.9f), frame.RectTransform, Anchor.Center), style: null);
|
||||
|
||||
listBox = new GUIListBox(new RectTransform(new Point(paddedFrame.Rect.Width, paddedFrame.Rect.Height - 30), paddedFrame.RectTransform)
|
||||
var toggleText = new GUITextBlock(new RectTransform(new Point(paddedFrame.Rect.Width-30, 20), paddedFrame.RectTransform, Anchor.TopLeft), TextManager.Get("DebugConsoleHelpText"), new Color(150,150,200,255), GUI.SmallFont, Alignment.CenterLeft, style: null);
|
||||
|
||||
var closeButton = new GUIButton(new RectTransform(new Point(20, 20), paddedFrame.RectTransform, Anchor.TopRight), "X", color: Color.Red);
|
||||
closeButton.OnClicked += (btn, userdata) =>
|
||||
{
|
||||
isOpen = false;
|
||||
GUI.ForceMouseOn(null);
|
||||
textBox.Deselect();
|
||||
return true;
|
||||
};
|
||||
|
||||
listBox = new GUIListBox(new RectTransform(new Point(paddedFrame.Rect.Width, paddedFrame.Rect.Height - 50), paddedFrame.RectTransform, Anchor.Center)
|
||||
{
|
||||
IsFixedSize = false
|
||||
}, color: Color.Black * 0.9f);
|
||||
@@ -80,9 +92,6 @@ namespace Barotrauma
|
||||
ResetAutoComplete();
|
||||
}
|
||||
};
|
||||
|
||||
NewMessage("Press F3 to open/close the debug console", Color.Cyan);
|
||||
NewMessage("Enter \"help\" for a list of available console commands", Color.Cyan);
|
||||
}
|
||||
|
||||
public static void AddToGUIUpdateList()
|
||||
@@ -130,6 +139,12 @@ namespace Barotrauma
|
||||
textBox.Deselect();
|
||||
}
|
||||
}
|
||||
else if (isOpen && PlayerInput.KeyHit(Keys.Escape))
|
||||
{
|
||||
isOpen = false;
|
||||
GUI.ForceMouseOn(null);
|
||||
textBox.Deselect();
|
||||
}
|
||||
|
||||
if (isOpen)
|
||||
{
|
||||
|
||||
@@ -230,11 +230,18 @@ namespace Barotrauma
|
||||
if (GameMain.ShowPerf)
|
||||
{
|
||||
int y = 10;
|
||||
DrawString(spriteBatch, new Vector2(300, y), "Draw - Max val: " + GameMain.PerformanceCounter.DrawTimeGraph.LargestValue()+" ms", Color.Green, Color.Black * 0.8f, font: GUI.SmallFont);
|
||||
DrawString(spriteBatch, new Vector2(300, y),
|
||||
"Draw - Avg: " + GameMain.PerformanceCounter.DrawTimeGraph.Average().ToString("0.00") + " ms" +
|
||||
" Max: " + GameMain.PerformanceCounter.DrawTimeGraph.LargestValue().ToString("0.00") + " ms",
|
||||
Color.Green, Color.Black * 0.8f, font: SmallFont);
|
||||
y += 15;
|
||||
GameMain.PerformanceCounter.DrawTimeGraph.Draw(spriteBatch, new Rectangle(300, y, 170, 50), null, 0, Color.Green);
|
||||
y += 50;
|
||||
DrawString(spriteBatch, new Vector2(300, y), "Update - Max val: " + GameMain.PerformanceCounter.UpdateTimeGraph.LargestValue() + " ms", Color.LightBlue, Color.Black * 0.8f, font: GUI.SmallFont);
|
||||
|
||||
DrawString(spriteBatch, new Vector2(300, y),
|
||||
"Update - Avg: " + GameMain.PerformanceCounter.UpdateTimeGraph.Average().ToString("0.00") + " ms" +
|
||||
" Max: " + GameMain.PerformanceCounter.UpdateTimeGraph.LargestValue().ToString("0.00") + " ms",
|
||||
Color.LightBlue, Color.Black * 0.8f, font: SmallFont);
|
||||
y += 15;
|
||||
GameMain.PerformanceCounter.UpdateTimeGraph.Draw(spriteBatch, new Rectangle(300, y, 170, 50), null, 0, Color.LightBlue);
|
||||
GameMain.PerformanceCounter.UpdateIterationsGraph.Draw(spriteBatch, new Rectangle(300, y, 170, 50), 20, 0, Color.Red);
|
||||
@@ -243,7 +250,7 @@ namespace Barotrauma
|
||||
{
|
||||
float elapsedMillisecs = GameMain.PerformanceCounter.GetAverageElapsedMillisecs(key);
|
||||
DrawString(spriteBatch, new Vector2(300, y),
|
||||
key + ": " + elapsedMillisecs,
|
||||
key + ": " + elapsedMillisecs.ToString("0.00"),
|
||||
Color.Lerp(Color.LightGreen, Color.Red, elapsedMillisecs / 10.0f), Color.Black * 0.5f, 0, SmallFont);
|
||||
|
||||
y += 15;
|
||||
|
||||
@@ -85,7 +85,9 @@ namespace Barotrauma
|
||||
{
|
||||
float totalSize = RectTransform.Children
|
||||
.Where(c => !c.GUIComponent.IgnoreLayoutGroups)
|
||||
.Sum(c => isHorizontal ? c.Rect.Width : c.Rect.Height);
|
||||
.Sum(c => isHorizontal ?
|
||||
MathHelper.Clamp(c.Rect.Width, c.MinSize.X, c.MaxSize.X) :
|
||||
MathHelper.Clamp(c.Rect.Height, c.MinSize.Y, c.MaxSize.Y));
|
||||
|
||||
totalSize +=
|
||||
(RectTransform.Children.Count() - 1) *
|
||||
|
||||
@@ -117,7 +117,9 @@ namespace Barotrauma
|
||||
{
|
||||
LayoutGroup = new GUILayoutGroup(new RectTransform(Vector2.One, rectT), isHorizontal: true) { Stretch = true };
|
||||
|
||||
TextBox = new GUITextBox(new RectTransform(Vector2.One, LayoutGroup.RectTransform), textAlignment: textAlignment, style: style)
|
||||
float relativeButtonAreaWidth = MathHelper.Clamp(Rect.Height / (float)Rect.Width, 0.1f, 0.5f);
|
||||
|
||||
TextBox = new GUITextBox(new RectTransform(new Vector2(1.0f - relativeButtonAreaWidth, 1.0f), LayoutGroup.RectTransform), textAlignment: textAlignment, style: style)
|
||||
{
|
||||
ClampText = false,
|
||||
// For some reason the caret in the number inputs is dimmer than it should.
|
||||
@@ -126,7 +128,7 @@ namespace Barotrauma
|
||||
CaretColor = Color.White
|
||||
};
|
||||
TextBox.OnTextChanged += TextChanged;
|
||||
var buttonArea = new GUIFrame(new RectTransform(new Vector2(0.02f, 1.0f), LayoutGroup.RectTransform, Anchor.CenterRight) { MinSize = new Point(Rect.Height, 0) }, style: null);
|
||||
var buttonArea = new GUIFrame(new RectTransform(new Vector2(relativeButtonAreaWidth, 1.0f), LayoutGroup.RectTransform, Anchor.CenterRight) { MinSize = new Point(Rect.Height, 0) }, style: null);
|
||||
PlusButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.5f), buttonArea.RectTransform), "+");
|
||||
PlusButton.OnButtonDown += () =>
|
||||
{
|
||||
@@ -201,6 +203,8 @@ namespace Barotrauma
|
||||
TextBox.textFilterFunction = text => new string(text.Where(c => char.IsDigit(c) || c == '.' || c == '-').ToArray());
|
||||
break;
|
||||
}
|
||||
|
||||
LayoutGroup.Recalculate();
|
||||
}
|
||||
|
||||
private void ReduceValue()
|
||||
|
||||
@@ -35,8 +35,6 @@ namespace Barotrauma
|
||||
this.graphicsDevice = graphicsDevice;
|
||||
componentStyles = new Dictionary<string, GUIComponentStyle>();
|
||||
|
||||
GameMain.Instance.OnResolutionChanged += () => { RescaleFonts(); };
|
||||
|
||||
XDocument doc;
|
||||
try
|
||||
{
|
||||
@@ -89,6 +87,8 @@ namespace Barotrauma
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GameMain.Instance.OnResolutionChanged += () => { RescaleFonts(); };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -20,6 +20,7 @@ namespace Barotrauma
|
||||
protected Color textColor;
|
||||
|
||||
private string wrappedText;
|
||||
private string censoredText;
|
||||
|
||||
public delegate string TextGetterHandler();
|
||||
public TextGetterHandler TextGetter;
|
||||
@@ -175,6 +176,17 @@ namespace Barotrauma
|
||||
SetTextPos();
|
||||
}
|
||||
}
|
||||
|
||||
public bool Censor
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string CensoredText
|
||||
{
|
||||
get { return censoredText; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is the new constructor.
|
||||
@@ -204,6 +216,8 @@ namespace Barotrauma
|
||||
|
||||
RectTransform.ScaleChanged += SetTextPos;
|
||||
RectTransform.SizeChanged += SetTextPos;
|
||||
|
||||
Censor = false;
|
||||
}
|
||||
|
||||
public void CalculateHeightFromText()
|
||||
@@ -225,13 +239,19 @@ namespace Barotrauma
|
||||
{
|
||||
if (text == null) return;
|
||||
|
||||
censoredText = "";
|
||||
for (int i=0;i<text.Length;i++)
|
||||
{
|
||||
censoredText += "\u2022";
|
||||
}
|
||||
|
||||
var rect = Rect;
|
||||
|
||||
overflowClipActive = false;
|
||||
wrappedText = text;
|
||||
|
||||
TextSize = MeasureText(text);
|
||||
|
||||
TextSize = MeasureText(text);
|
||||
|
||||
if (Wrap && rect.Width > 0)
|
||||
{
|
||||
wrappedText = ToolBox.WrapText(text, rect.Width - padding.X - padding.Z, Font, textScale);
|
||||
@@ -338,7 +358,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
Font.DrawString(spriteBatch,
|
||||
Wrap ? wrappedText : text,
|
||||
Censor ? censoredText : (Wrap ? wrappedText : text),
|
||||
pos,
|
||||
textColor * (textColor.A / 255.0f),
|
||||
0.0f, origin, TextScale,
|
||||
|
||||
@@ -142,6 +142,12 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public bool Censor
|
||||
{
|
||||
get { return textBlock.Censor; }
|
||||
set { textBlock.Censor = value; }
|
||||
}
|
||||
|
||||
public override string ToolTip
|
||||
{
|
||||
get
|
||||
@@ -253,9 +259,12 @@ namespace Barotrauma
|
||||
textBlock.Text = textBlock.Text.Substring(0, (int)maxTextLength);
|
||||
}
|
||||
}
|
||||
else if (ClampText && Font.MeasureString(textBlock.Text).X > (int)(textBlock.Rect.Width - textBlock.Padding.X - textBlock.Padding.Z))
|
||||
else
|
||||
{
|
||||
textBlock.Text = textBlock.Text.Substring(0, textBlock.Text.Length - 1);
|
||||
while (ClampText && textBlock.Text.Length>0 && Font.MeasureString(textBlock.Text).X > (int)(textBlock.Rect.Width - textBlock.Padding.X - textBlock.Padding.Z))
|
||||
{
|
||||
textBlock.Text = textBlock.Text.Substring(0, textBlock.Text.Length - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (store)
|
||||
@@ -267,9 +276,10 @@ namespace Barotrauma
|
||||
|
||||
private void CalculateCaretPos()
|
||||
{
|
||||
if (textBlock.WrappedText.Contains("\n"))
|
||||
string textDrawn = Censor ? textBlock.CensoredText : textBlock.WrappedText;
|
||||
if (textDrawn.Contains("\n"))
|
||||
{
|
||||
string[] lines = textBlock.WrappedText.Split('\n');
|
||||
string[] lines = textDrawn.Split('\n');
|
||||
int totalIndex = 0;
|
||||
for (int i = 0; i < lines.Length; i++)
|
||||
{
|
||||
@@ -282,7 +292,7 @@ namespace Barotrauma
|
||||
int index = currentLineLength - diff;
|
||||
Vector2 lineTextSize = Font.MeasureString(lines[i].Substring(0, index));
|
||||
Vector2 lastLineSize = Font.MeasureString(lines[i]);
|
||||
float totalTextHeight = Font.MeasureString(textBlock.WrappedText.Substring(0, totalIndex)).Y;
|
||||
float totalTextHeight = Font.MeasureString(textDrawn.Substring(0, totalIndex)).Y;
|
||||
caretPos = new Vector2(lineTextSize.X, totalTextHeight - lastLineSize.Y) + textBlock.TextPos - textBlock.Origin;
|
||||
break;
|
||||
}
|
||||
@@ -290,7 +300,8 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector2 textSize = Font.MeasureString(textBlock.Text.Substring(0, CaretIndex));
|
||||
textDrawn = Censor ? textBlock.CensoredText : textBlock.Text;
|
||||
Vector2 textSize = Font.MeasureString(textDrawn.Substring(0, CaretIndex));
|
||||
caretPos = new Vector2(textSize.X, 0) + textBlock.TextPos - textBlock.Origin;
|
||||
}
|
||||
caretPosDirty = false;
|
||||
@@ -298,17 +309,18 @@ namespace Barotrauma
|
||||
|
||||
protected List<Tuple<Vector2, int>> GetAllPositions()
|
||||
{
|
||||
string textDrawn = Censor ? textBlock.CensoredText : textBlock.WrappedText;
|
||||
var positions = new List<Tuple<Vector2, int>>();
|
||||
if (textBlock.WrappedText.Contains("\n"))
|
||||
if (textDrawn.Contains("\n"))
|
||||
{
|
||||
string[] lines = textBlock.WrappedText.Split('\n');
|
||||
string[] lines = textDrawn.Split('\n');
|
||||
int index = 0;
|
||||
int totalIndex = 0;
|
||||
for (int i = 0; i < lines.Length; i++)
|
||||
{
|
||||
string line = lines[i];
|
||||
totalIndex += line.Length;
|
||||
float totalTextHeight = Font.MeasureString(textBlock.WrappedText.Substring(0, totalIndex)).Y;
|
||||
float totalTextHeight = Font.MeasureString(textDrawn.Substring(0, totalIndex)).Y;
|
||||
for (int j = 0; j <= line.Length; j++)
|
||||
{
|
||||
Vector2 lineTextSize = Font.MeasureString(line.Substring(0, j));
|
||||
@@ -321,9 +333,10 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
textDrawn = Censor ? textBlock.CensoredText : textBlock.Text;
|
||||
for (int i = 0; i <= textBlock.Text.Length; i++)
|
||||
{
|
||||
Vector2 textSize = Font.MeasureString(textBlock.Text.Substring(0, i));
|
||||
Vector2 textSize = Font.MeasureString(textDrawn.Substring(0, i));
|
||||
Vector2 indexPos = new Vector2(textSize.X + textBlock.Padding.X, textSize.Y + textBlock.Padding.Y) + textBlock.TextPos - textBlock.Origin;
|
||||
//DebugConsole.NewMessage($"index: {i}, pos: {indexPos}", Color.WhiteSmoke);
|
||||
positions.Add(new Tuple<Vector2, int>(textBlock.Rect.Location.ToVector2() + indexPos, i));
|
||||
@@ -822,6 +835,7 @@ namespace Barotrauma
|
||||
|
||||
private void CalculateSelection()
|
||||
{
|
||||
string textDrawn = Censor ? textBlock.CensoredText : textBlock.WrappedText;
|
||||
InitSelectionStart();
|
||||
selectionEndIndex = CaretIndex;
|
||||
selectionEndPos = caretPos;
|
||||
@@ -829,12 +843,12 @@ namespace Barotrauma
|
||||
if (IsLeftToRight)
|
||||
{
|
||||
selectedText = Text.Substring(selectionStartIndex, selectedCharacters);
|
||||
selectionRectSize = Font.MeasureString(textBlock.WrappedText.Substring(selectionStartIndex, selectedCharacters));
|
||||
selectionRectSize = Font.MeasureString(textDrawn.Substring(selectionStartIndex, selectedCharacters));
|
||||
}
|
||||
else
|
||||
{
|
||||
selectedText = Text.Substring(selectionEndIndex, selectedCharacters);
|
||||
selectionRectSize = Font.MeasureString(textBlock.WrappedText.Substring(selectionEndIndex, selectedCharacters));
|
||||
selectionRectSize = Font.MeasureString(textDrawn.Substring(selectionEndIndex, selectedCharacters));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,11 @@ namespace Barotrauma
|
||||
BottomLeft, BottomCenter, BottomRight
|
||||
}
|
||||
|
||||
public enum ScaleBasis
|
||||
{
|
||||
Normal, BothWidth, BothHeight
|
||||
}
|
||||
|
||||
public class RectTransform
|
||||
{
|
||||
#region Fields and Properties
|
||||
@@ -286,6 +291,8 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private ScaleBasis scaleBasis;
|
||||
|
||||
public bool IsLastChild
|
||||
{
|
||||
get
|
||||
@@ -320,9 +327,10 @@ namespace Barotrauma
|
||||
#endregion
|
||||
|
||||
#region Initialization
|
||||
public RectTransform(Vector2 relativeSize, RectTransform parent, Anchor anchor = Anchor.TopLeft, Pivot? pivot = null, Point? minSize = null, Point? maxSize = null)
|
||||
public RectTransform(Vector2 relativeSize, RectTransform parent, Anchor anchor = Anchor.TopLeft, Pivot? pivot = null, Point? minSize = null, Point? maxSize = null, ScaleBasis scaleBasis = ScaleBasis.Normal)
|
||||
{
|
||||
Init(parent, anchor, pivot);
|
||||
this.scaleBasis = scaleBasis;
|
||||
this.relativeSize = relativeSize;
|
||||
this.minSize = minSize;
|
||||
this.maxSize = maxSize;
|
||||
@@ -340,6 +348,7 @@ namespace Barotrauma
|
||||
public RectTransform(Point absoluteSize, RectTransform parent = null, Anchor anchor = Anchor.TopLeft, Pivot? pivot = null)
|
||||
{
|
||||
Init(parent, anchor, pivot);
|
||||
this.scaleBasis = ScaleBasis.Normal;
|
||||
this.nonScaledSize = absoluteSize;
|
||||
RecalculateScale();
|
||||
RecalculateRelativeSize();
|
||||
@@ -416,7 +425,16 @@ namespace Barotrauma
|
||||
|
||||
protected void RecalculateAbsoluteSize()
|
||||
{
|
||||
nonScaledSize = NonScaledParentRect.Size.Multiply(RelativeSize).Clamp(MinSize, MaxSize);
|
||||
Point size = NonScaledParentRect.Size;
|
||||
if (scaleBasis == ScaleBasis.BothWidth)
|
||||
{
|
||||
size.Y = size.X;
|
||||
}
|
||||
else if (scaleBasis == ScaleBasis.BothHeight)
|
||||
{
|
||||
size.X = size.Y;
|
||||
}
|
||||
nonScaledSize = size.Multiply(RelativeSize).Clamp(MinSize, MaxSize);
|
||||
recalculateRect = true;
|
||||
SizeChanged?.Invoke();
|
||||
}
|
||||
|
||||
@@ -159,14 +159,7 @@ namespace Barotrauma
|
||||
|
||||
public GameMain()
|
||||
{
|
||||
/*#if !DEBUG && OSX
|
||||
// Use a separate path for content that's editable due to macOS's .app bundles crashing when edited during runtime
|
||||
string macPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "Library/Barotrauma");
|
||||
Directory.SetCurrentDirectory(macPath);
|
||||
Content.RootDirectory = macPath + "/Content";
|
||||
#else*/
|
||||
Content.RootDirectory = "Content";
|
||||
/*#endif*/
|
||||
|
||||
GraphicsDeviceManager = new GraphicsDeviceManager(this);
|
||||
|
||||
@@ -280,7 +273,7 @@ namespace Barotrauma
|
||||
canLoadInSeparateThread = true;
|
||||
#endif
|
||||
|
||||
loadingCoroutine = CoroutineManager.StartCoroutine(Load(canLoadInSeparateThread), "", canLoadInSeparateThread);
|
||||
loadingCoroutine = CoroutineManager.StartCoroutine(Load(canLoadInSeparateThread), "Load", canLoadInSeparateThread);
|
||||
}
|
||||
|
||||
private void InitUserStats()
|
||||
@@ -541,7 +534,9 @@ namespace Barotrauma
|
||||
/// </summary>
|
||||
protected override void UnloadContent()
|
||||
{
|
||||
CoroutineManager.StopCoroutines("Load");
|
||||
Video.Close();
|
||||
VoipCapture.Instance?.Dispose();
|
||||
SoundManager?.Dispose();
|
||||
}
|
||||
|
||||
|
||||
@@ -114,7 +114,11 @@ namespace Barotrauma
|
||||
Character character = characterInfo.Character;
|
||||
if (character == null || character.IsDead)
|
||||
{
|
||||
if (characterInfo.CauseOfDeath.Type == CauseOfDeathType.Affliction && characterInfo.CauseOfDeath.Affliction == null)
|
||||
if (characterInfo.CauseOfDeath == null)
|
||||
{
|
||||
statusText = TextManager.Get("CauseOfDeathDescription.Unknown");
|
||||
}
|
||||
else if (characterInfo.CauseOfDeath.Type == CauseOfDeathType.Affliction && characterInfo.CauseOfDeath.Affliction == null)
|
||||
{
|
||||
string errorMsg = "Character \"" + character.Name + "\" had an invalid cause of death (the type of the cause of death was Affliction, but affliction was not specified).";
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
@@ -126,7 +130,7 @@ namespace Barotrauma
|
||||
statusText = characterInfo.CauseOfDeath.Type == CauseOfDeathType.Affliction ?
|
||||
characterInfo.CauseOfDeath.Affliction.CauseOfDeathDescription :
|
||||
TextManager.Get("CauseOfDeathDescription." + characterInfo.CauseOfDeath.Type.ToString());
|
||||
}
|
||||
}
|
||||
statusColor = Color.DarkRed;
|
||||
}
|
||||
else
|
||||
|
||||
@@ -3,7 +3,7 @@ using Barotrauma.Networking;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
using OpenTK.Audio.OpenAL;
|
||||
using OpenAL;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
@@ -75,6 +75,8 @@ namespace Barotrauma
|
||||
{
|
||||
settingsFrame = new GUIFrame(new RectTransform(new Vector2(0.8f, 0.8f), GUI.Canvas, Anchor.Center));
|
||||
|
||||
Vector2 tickBoxScale = Vector2.One * 0.05f;
|
||||
|
||||
var settingsFramePadding = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), settingsFrame.RectTransform, Anchor.TopCenter) { RelativeOffset = new Vector2(0.0f, 0.05f) }) { RelativeSpacing = 0.01f, IsHorizontal = true };
|
||||
|
||||
/// General tab --------------------------------------------------------------
|
||||
@@ -96,7 +98,7 @@ namespace Barotrauma
|
||||
|
||||
foreach (ContentPackage contentPackage in ContentPackage.List)
|
||||
{
|
||||
var tickBox = new GUITickBox(new RectTransform(new Point(32, 32), contentPackageList.Content.RectTransform), contentPackage.Name)
|
||||
var tickBox = new GUITickBox(new RectTransform(tickBoxScale, contentPackageList.Content.RectTransform, scaleBasis: ScaleBasis.BothHeight), contentPackage.Name)
|
||||
{
|
||||
UserData = contentPackage,
|
||||
OnSelected = SelectContentPackage,
|
||||
@@ -132,7 +134,7 @@ namespace Barotrauma
|
||||
if (newLanguage == Language) return true;
|
||||
|
||||
Language = newLanguage;
|
||||
ApplySettings();
|
||||
UnsavedSettings = true;
|
||||
|
||||
var msgBox = new GUIMessageBox(TextManager.Get("RestartRequiredLabel"), TextManager.Get("RestartRequiredLanguage"));
|
||||
//change fonts to the default font of the new language to make sure
|
||||
@@ -250,7 +252,7 @@ namespace Barotrauma
|
||||
return true;
|
||||
};
|
||||
|
||||
GUITickBox vsyncTickBox = new GUITickBox(new RectTransform(new Point(32, 32), leftColumn.RectTransform), TextManager.Get("EnableVSync"))
|
||||
GUITickBox vsyncTickBox = new GUITickBox(new RectTransform(tickBoxScale, leftColumn.RectTransform, scaleBasis: ScaleBasis.BothHeight), TextManager.Get("EnableVSync"))
|
||||
{
|
||||
ToolTip = TextManager.Get("EnableVSyncToolTip"),
|
||||
OnSelected = (GUITickBox box) =>
|
||||
@@ -266,7 +268,7 @@ namespace Barotrauma
|
||||
};
|
||||
|
||||
//TODO: remove hardcoded texts after the texts have been added to localization
|
||||
GUITickBox pauseOnFocusLostBox = new GUITickBox(new RectTransform(new Point(32, 32), leftColumn.RectTransform),
|
||||
GUITickBox pauseOnFocusLostBox = new GUITickBox(new RectTransform(tickBoxScale, leftColumn.RectTransform, scaleBasis: ScaleBasis.BothHeight),
|
||||
TextManager.Get("PauseOnFocusLost", returnNull: true) ?? "Pause on focus lost");
|
||||
pauseOnFocusLostBox.Selected = PauseOnFocusLost;
|
||||
pauseOnFocusLostBox.ToolTip = TextManager.Get("PauseOnFocusLostToolTip", returnNull: true) ?? "Pauses the game when its window is not in focus. Note that the game won't be paused when a multiplayer session is active.";
|
||||
@@ -331,7 +333,7 @@ namespace Barotrauma
|
||||
};
|
||||
lightScrollBar.OnMoved(lightScrollBar, lightScrollBar.BarScroll);
|
||||
|
||||
new GUITickBox(new RectTransform(new Point(32, 32), rightColumn.RectTransform), TextManager.Get("SpecularLighting"))
|
||||
new GUITickBox(new RectTransform(tickBoxScale, rightColumn.RectTransform, scaleBasis: ScaleBasis.BothHeight), TextManager.Get("SpecularLighting"))
|
||||
{
|
||||
ToolTip = TextManager.Get("SpecularLightingToolTip"),
|
||||
Selected = SpecularityEnabled,
|
||||
@@ -343,7 +345,7 @@ namespace Barotrauma
|
||||
}
|
||||
};
|
||||
|
||||
new GUITickBox(new RectTransform(new Point(32, 32), rightColumn.RectTransform), TextManager.Get("ChromaticAberration"))
|
||||
new GUITickBox(new RectTransform(tickBoxScale, rightColumn.RectTransform, scaleBasis: ScaleBasis.BothHeight), TextManager.Get("ChromaticAberration"))
|
||||
{
|
||||
ToolTip = TextManager.Get("ChromaticAberrationToolTip"),
|
||||
Selected = ChromaticAberrationEnabled,
|
||||
@@ -443,7 +445,7 @@ namespace Barotrauma
|
||||
};
|
||||
voiceChatScrollBar.OnMoved(voiceChatScrollBar, voiceChatScrollBar.BarScroll);
|
||||
|
||||
GUITickBox muteOnFocusLostBox = new GUITickBox(new RectTransform(new Point(32, 32), audioSliders.RectTransform), TextManager.Get("MuteOnFocusLost"));
|
||||
GUITickBox muteOnFocusLostBox = new GUITickBox(new RectTransform(tickBoxScale, audioSliders.RectTransform, scaleBasis: ScaleBasis.BothHeight), TextManager.Get("MuteOnFocusLost"));
|
||||
muteOnFocusLostBox.Selected = MuteOnFocusLost;
|
||||
muteOnFocusLostBox.ToolTip = TextManager.Get("MuteOnFocusLostToolTip");
|
||||
muteOnFocusLostBox.OnSelected = (tickBox) =>
|
||||
@@ -455,13 +457,13 @@ namespace Barotrauma
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), audioSliders.RectTransform), TextManager.Get("VoiceChat"));
|
||||
|
||||
IList<string> deviceNames = Alc.GetString((IntPtr)null, AlcGetStringList.CaptureDeviceSpecifier);
|
||||
IList<string> deviceNames = Alc.GetStringList((IntPtr)null, Alc.CaptureDeviceSpecifier);
|
||||
foreach (string name in deviceNames)
|
||||
{
|
||||
DebugConsole.NewMessage(name + " " + name.Length.ToString(), Color.Lime);
|
||||
}
|
||||
|
||||
GUITickBox directionalVoiceChat = new GUITickBox(new RectTransform(new Point(32, 32), audioSliders.RectTransform), TextManager.Get("DirectionalVoiceChat"));
|
||||
GUITickBox directionalVoiceChat = new GUITickBox(new RectTransform(tickBoxScale, audioSliders.RectTransform, scaleBasis: ScaleBasis.BothHeight), TextManager.Get("DirectionalVoiceChat"));
|
||||
directionalVoiceChat.Selected = UseDirectionalVoiceChat;
|
||||
directionalVoiceChat.ToolTip = TextManager.Get("DirectionalVoiceChatToolTip");
|
||||
directionalVoiceChat.OnSelected = (tickBox) =>
|
||||
@@ -470,14 +472,13 @@ namespace Barotrauma
|
||||
UnsavedSettings = true;
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
|
||||
if (string.IsNullOrWhiteSpace(VoiceCaptureDevice)) VoiceCaptureDevice = deviceNames[0];
|
||||
#if (!OSX)
|
||||
var deviceList = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.05f), audioSliders.RectTransform), TextManager.EnsureUTF8(VoiceCaptureDevice), deviceNames.Count);
|
||||
var deviceList = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.05f), audioSliders.RectTransform), TrimAudioDeviceName(VoiceCaptureDevice), deviceNames.Count);
|
||||
foreach (string name in deviceNames)
|
||||
{
|
||||
deviceList.AddItem(TextManager.EnsureUTF8(name), name);
|
||||
deviceList.AddItem(TrimAudioDeviceName(name), name);
|
||||
}
|
||||
deviceList.OnSelected = (GUIComponent selected, object obj) =>
|
||||
{
|
||||
@@ -488,28 +489,32 @@ namespace Barotrauma
|
||||
return true;
|
||||
};
|
||||
#else
|
||||
var suavemente = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), audioSliders.RectTransform),
|
||||
var defaultDeviceGroup = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.1f), audioSliders.RectTransform), true, Anchor.CenterLeft);
|
||||
var suavemente = new GUITextBlock(new RectTransform(new Vector2(.7f, 0.75f), null),
|
||||
TextManager.AddPunctuation(':', TextManager.Get("CurrentDevice"), TextManager.EnsureUTF8(VoiceCaptureDevice)))
|
||||
{
|
||||
ToolTip = TextManager.Get("CurrentDeviceToolTip.OSX"),
|
||||
TextAlignment = Alignment.CenterX
|
||||
TextAlignment = Alignment.CenterLeft
|
||||
};
|
||||
|
||||
new GUIButton(new RectTransform(new Vector2(1.0f, 0.15f), audioSliders.RectTransform), TextManager.Get("RefreshDefaultDevice"))
|
||||
string refreshText = ToolBox.WrapText(TextManager.Get("RefreshDefaultDevice"), defaultDeviceGroup.RectTransform.Rect.Width * 0.3f, GUI.Font);
|
||||
new GUIButton(new RectTransform(new Vector2(.3f, 0.75f), defaultDeviceGroup.RectTransform), refreshText)
|
||||
{
|
||||
ToolTip = TextManager.Get("RefreshDefaultDeviceToolTip"),
|
||||
OnClicked = (bt, userdata) =>
|
||||
{
|
||||
deviceNames = Alc.GetString((IntPtr)null, AlcGetStringList.CaptureDeviceSpecifier);
|
||||
deviceNames = Alc.GetStringList((IntPtr)null, Alc.CaptureDeviceSpecifier);
|
||||
if (VoiceCaptureDevice == deviceNames[0]) return true;
|
||||
|
||||
VoipCapture.ChangeCaptureDevice(deviceNames[0]);
|
||||
suavemente.Text = TextManager.AddPunctuation(':', TextManager.Get("CurrentDevice"), TextManager.EnsureUTF8(VoiceCaptureDevice));
|
||||
suavemente.Text = TextManager.AddPunctuation(':', TextManager.Get("CurrentDevice"), TrimAudioDeviceName(VoiceCaptureDevice));
|
||||
suavemente.Flash(Color.Blue);
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
suavemente.RectTransform.Parent = defaultDeviceGroup.RectTransform;
|
||||
#endif
|
||||
//var radioButtonFrame = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.12f), audioSliders.RectTransform));
|
||||
|
||||
@@ -517,7 +522,7 @@ namespace Barotrauma
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
string langStr = "VoiceMode." + ((VoiceMode)i).ToString();
|
||||
var tick = new GUITickBox(new RectTransform(new Point(32, 32), audioSliders.RectTransform), TextManager.Get(langStr))
|
||||
var tick = new GUITickBox(new RectTransform(tickBoxScale, audioSliders.RectTransform, scaleBasis: ScaleBasis.BothHeight), TextManager.Get(langStr))
|
||||
{
|
||||
ToolTip = TextManager.Get(langStr + "ToolTip")
|
||||
};
|
||||
@@ -651,7 +656,7 @@ namespace Barotrauma
|
||||
};
|
||||
aimAssistSlider.OnMoved(aimAssistSlider, aimAssistSlider.BarScroll);
|
||||
|
||||
new GUITickBox(new RectTransform(new Point(32, 32), controlsLayoutGroup.RectTransform), TextManager.Get("EnableMouseLook"))
|
||||
new GUITickBox(new RectTransform(tickBoxScale, controlsLayoutGroup.RectTransform, scaleBasis: ScaleBasis.BothHeight), TextManager.Get("EnableMouseLook"))
|
||||
{
|
||||
ToolTip = TextManager.Get("EnableMouseLookToolTip"),
|
||||
Selected = EnableMouseLook,
|
||||
@@ -776,6 +781,19 @@ namespace Barotrauma
|
||||
SelectTab(selectedTab);
|
||||
}
|
||||
|
||||
private string TrimAudioDeviceName(string name)
|
||||
{
|
||||
string[] prefixes = { "OpenAL Soft on " };
|
||||
foreach (string prefix in prefixes)
|
||||
{
|
||||
if (name.StartsWith(prefix, StringComparison.InvariantCulture))
|
||||
{
|
||||
return name.Remove(0, prefix.Length);
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
private Tab currentTab;
|
||||
private void SelectTab(Tab tab)
|
||||
{
|
||||
|
||||
@@ -423,7 +423,14 @@ namespace Barotrauma
|
||||
columns++;
|
||||
}
|
||||
|
||||
int startX = slot.Rect.Center.X - (int)(subRect.Width * (columns / 2.0f) + spacing.X * ((columns - 1) / 2.0f));
|
||||
int width = (int)(subRect.Width * columns + spacing.X * (columns - 1));
|
||||
int startX = slot.Rect.Center.X - (int)(width / 2.0f);
|
||||
|
||||
//prevent the inventory from extending outside the left side of the screen
|
||||
startX = Math.Max(startX, 10);
|
||||
//same for the right side of the screen
|
||||
startX -= Math.Max((startX + width) - GameMain.GraphicsWidth, 0);
|
||||
|
||||
subRect.X = startX;
|
||||
int startY = dir < 0 ?
|
||||
slot.EquipButtonRect.Y - subRect.Height - (int)(35 * UIScale) :
|
||||
|
||||
@@ -29,6 +29,10 @@ namespace Barotrauma
|
||||
drawPos.Y = -drawPos.Y;
|
||||
|
||||
Color clr = currentHull == null ? Color.Blue : Color.White;
|
||||
if (isObstructed)
|
||||
{
|
||||
clr = Color.Black;
|
||||
}
|
||||
if (IsSelected) clr = Color.Red;
|
||||
if (IsHighlighted) clr = Color.DarkRed;
|
||||
|
||||
@@ -50,7 +54,7 @@ namespace Barotrauma
|
||||
GUI.DrawLine(spriteBatch,
|
||||
drawPos,
|
||||
new Vector2(e.DrawPosition.X, -e.DrawPosition.Y),
|
||||
Color.Green, width: 5);
|
||||
isObstructed ? Color.Gray : Color.Green, width: 5);
|
||||
}
|
||||
|
||||
GUI.SmallFont.DrawString(spriteBatch,
|
||||
|
||||
@@ -194,8 +194,7 @@ namespace Barotrauma.Networking
|
||||
Hull.EditFire = false;
|
||||
Hull.EditWater = false;
|
||||
|
||||
newName = newName.Replace(":", "").Replace(";", "");
|
||||
name = newName;
|
||||
Name = newName;
|
||||
|
||||
entityEventManager = new ClientEntityEventManager(this);
|
||||
|
||||
@@ -473,7 +472,8 @@ namespace Barotrauma.Networking
|
||||
var passwordBox = new GUITextBox(new RectTransform(new Vector2(0.8f, 0.1f), msgBox.InnerFrame.RectTransform, Anchor.Center) { MinSize = new Point(0, 20) })
|
||||
{
|
||||
IgnoreLayoutGroups = true,
|
||||
UserData = "password"
|
||||
UserData = "password",
|
||||
Censor = true
|
||||
};
|
||||
|
||||
var okButton = msgBox.Buttons[0];
|
||||
@@ -1303,6 +1303,11 @@ namespace Barotrauma.Networking
|
||||
if (existingClient.ID == myID)
|
||||
{
|
||||
existingClient.SetPermissions(permissions, permittedConsoleCommands);
|
||||
name = tc.Name;
|
||||
if (GameMain.NetLobbyScreen.CharacterNameBox != null)
|
||||
{
|
||||
GameMain.NetLobbyScreen.CharacterNameBox.Text = name;
|
||||
}
|
||||
}
|
||||
currentClients.Add(existingClient);
|
||||
}
|
||||
@@ -1562,6 +1567,7 @@ namespace Barotrauma.Networking
|
||||
outmsg.Write(GameMain.NetLobbyScreen.LastUpdateID);
|
||||
outmsg.Write(ChatMessage.LastID);
|
||||
outmsg.Write(LastClientListUpdateID);
|
||||
outmsg.Write(name);
|
||||
|
||||
var campaign = GameMain.GameSession?.GameMode as MultiPlayerCampaign;
|
||||
if (campaign == null || campaign.LastSaveID == 0)
|
||||
@@ -1581,8 +1587,8 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (outmsg.LengthBytes + chatMsgQueue[i].EstimateLengthBytesClient() > client.Configuration.MaximumTransmissionUnit - 5)
|
||||
{
|
||||
//not enough room in this packet
|
||||
return;
|
||||
//no more room in this packet
|
||||
break;
|
||||
}
|
||||
chatMsgQueue[i].ClientWrite(outmsg);
|
||||
}
|
||||
@@ -1617,7 +1623,7 @@ namespace Barotrauma.Networking
|
||||
if (outmsg.LengthBytes + chatMsgQueue[i].EstimateLengthBytesClient() > client.Configuration.MaximumTransmissionUnit - 5)
|
||||
{
|
||||
//not enough room in this packet
|
||||
return;
|
||||
break;
|
||||
}
|
||||
chatMsgQueue[i].ClientWrite(outmsg);
|
||||
}
|
||||
|
||||
@@ -11,5 +11,15 @@ namespace Barotrauma.Networking
|
||||
respawnTimer = Math.Max(0.0f, respawnTimer - deltaTime);
|
||||
}
|
||||
}
|
||||
|
||||
partial void UpdateTransportingProjSpecific(float deltaTime)
|
||||
{
|
||||
if (shuttleTransportTimer + deltaTime > 15.0f && shuttleTransportTimer <= 15.0f &&
|
||||
GameMain.Client?.Character != null &&
|
||||
GameMain.Client.Character.Submarine == respawnShuttle)
|
||||
{
|
||||
GameMain.Client.AddChatMessage("ServerMessage.ShuttleLeaving", ChatMessageType.Server);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,15 +71,16 @@ namespace Barotrauma.Networking
|
||||
Stretch = true
|
||||
};
|
||||
|
||||
var titleHolder = new GUILayoutGroup(new RectTransform(new Vector2(0.97f, 0.07f), previewContainer.RectTransform))
|
||||
var titleHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.07f), previewContainer.RectTransform))
|
||||
{
|
||||
IsHorizontal = true,
|
||||
Stretch = true
|
||||
};
|
||||
|
||||
var title = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), titleHolder.RectTransform), ServerName, font: GUI.LargeFont, wrap: true);
|
||||
var title = new GUITextBlock(new RectTransform(new Vector2(0.7f, 1.0f), titleHolder.RectTransform), ServerName, font: GUI.LargeFont, wrap: true);
|
||||
title.Text = ToolBox.LimitString(title.Text, title.Font, title.Rect.Width);
|
||||
|
||||
new GUITextBlock(new RectTransform(Vector2.One, title.RectTransform),
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.3f, 1.0f), titleHolder.RectTransform),
|
||||
TextManager.AddPunctuation(':', TextManager.Get("ServerListVersion"), string.IsNullOrEmpty(GameVersion) ? TextManager.Get("Unknown") : GameVersion),
|
||||
textAlignment: Alignment.Right);
|
||||
|
||||
|
||||
@@ -63,6 +63,15 @@ namespace Barotrauma.Steam
|
||||
return instance.client.SteamId;
|
||||
}
|
||||
|
||||
public static string GetUsername()
|
||||
{
|
||||
if (instance == null || !instance.isInitialized)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
return instance.client.Username;
|
||||
}
|
||||
|
||||
public static ulong GetWorkshopItemIDFromUrl(string url)
|
||||
{
|
||||
try
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using Lidgren.Network;
|
||||
using Microsoft.Xna.Framework;
|
||||
using OpenTK.Audio.OpenAL;
|
||||
using OpenAL;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
@@ -69,7 +69,7 @@ namespace Barotrauma.Networking
|
||||
VoipConfig.SetupEncoding();
|
||||
|
||||
//set up capture device
|
||||
captureDevice = Alc.CaptureOpenDevice(deviceName, VoipConfig.FREQUENCY, ALFormat.Mono16, VoipConfig.BUFFER_SIZE * 5);
|
||||
captureDevice = Alc.CaptureOpenDevice(deviceName, VoipConfig.FREQUENCY, Al.FormatMono16, VoipConfig.BUFFER_SIZE * 5);
|
||||
|
||||
if (captureDevice == IntPtr.Zero)
|
||||
{
|
||||
@@ -88,20 +88,20 @@ namespace Barotrauma.Networking
|
||||
return;
|
||||
}
|
||||
|
||||
ALError alError = AL.GetError();
|
||||
AlcError alcError = Alc.GetError(captureDevice);
|
||||
if (alcError != AlcError.NoError)
|
||||
int alError = Al.GetError();
|
||||
int alcError = Alc.GetError(captureDevice);
|
||||
if (alcError != Alc.NoError)
|
||||
{
|
||||
throw new Exception("Failed to open capture device: " + alcError.ToString() + " (ALC)");
|
||||
}
|
||||
if (alError != ALError.NoError)
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to open capture device: " + alError.ToString() + " (AL)");
|
||||
}
|
||||
|
||||
Alc.CaptureStart(captureDevice);
|
||||
alcError = Alc.GetError(captureDevice);
|
||||
if (alcError != AlcError.NoError)
|
||||
if (alcError != Alc.NoError)
|
||||
{
|
||||
throw new Exception("Failed to start capturing: " + alcError.ToString());
|
||||
}
|
||||
@@ -132,11 +132,11 @@ namespace Barotrauma.Networking
|
||||
short[] uncompressedBuffer = new short[VoipConfig.BUFFER_SIZE];
|
||||
while (capturing)
|
||||
{
|
||||
AlcError alcError;
|
||||
Alc.GetInteger(captureDevice, AlcGetInteger.CaptureSamples, 1, out int sampleCount);
|
||||
int alcError;
|
||||
Alc.GetInteger(captureDevice, Alc.EnumCaptureSamples, out int sampleCount);
|
||||
|
||||
alcError = Alc.GetError(captureDevice);
|
||||
if (alcError != AlcError.NoError)
|
||||
if (alcError != Alc.NoError)
|
||||
{
|
||||
throw new Exception("Failed to determine sample count: " + alcError.ToString());
|
||||
}
|
||||
@@ -160,7 +160,7 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
|
||||
alcError = Alc.GetError(captureDevice);
|
||||
if (alcError != AlcError.NoError)
|
||||
if (alcError != Alc.NoError)
|
||||
{
|
||||
throw new Exception("Failed to capture samples: " + alcError.ToString());
|
||||
}
|
||||
@@ -214,7 +214,7 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
Thread.Sleep(VoipConfig.BUFFER_SIZE * 800 / VoipConfig.FREQUENCY);
|
||||
Thread.Sleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -335,12 +335,6 @@ namespace Barotrauma
|
||||
}
|
||||
subName = doc.Root.GetAttributeString("submarine", "");
|
||||
saveTime = doc.Root.GetAttributeString("savetime", "");
|
||||
|
||||
if (long.TryParse(saveTime, out long unixTime))
|
||||
{
|
||||
DateTime time = ToolBox.Epoch.ToDateTime(unixTime);
|
||||
saveTime = time.ToString();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -350,6 +344,11 @@ namespace Barotrauma
|
||||
if (splitSaveFile.Length > 1) { subName = splitSaveFile[1]; }
|
||||
if (splitSaveFile.Length > 2) { saveTime = splitSaveFile[2]; }
|
||||
}
|
||||
if (!string.IsNullOrEmpty(saveTime) && long.TryParse(saveTime, out long unixTime))
|
||||
{
|
||||
DateTime time = ToolBox.Epoch.ToDateTime(unixTime);
|
||||
saveTime = time.ToString();
|
||||
}
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), saveFrame.RectTransform, Anchor.BottomLeft),
|
||||
text: subName, font: GUI.SmallFont)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Barotrauma.Extensions;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -231,7 +232,16 @@ namespace Barotrauma
|
||||
"", style: "ItemCategory" + category.ToString())
|
||||
{
|
||||
UserData = category,
|
||||
OnClicked = (btn, userdata) => { FilterStoreItems((MapEntityCategory)userdata, searchBox.Text); return true; }
|
||||
OnClicked = (btn, userdata) =>
|
||||
{
|
||||
MapEntityCategory newCategory = (MapEntityCategory)userdata;
|
||||
if (newCategory != selectedItemCategory)
|
||||
{
|
||||
searchBox.Text = "";
|
||||
}
|
||||
FilterStoreItems((MapEntityCategory)userdata, searchBox.Text);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
itemCategoryButtons.Add(categoryButton);
|
||||
|
||||
@@ -487,10 +497,15 @@ namespace Barotrauma
|
||||
{
|
||||
//refresh store view
|
||||
FillStoreItemList();
|
||||
FilterStoreItems(MapEntityCategory.Equipment, searchBox.Text);
|
||||
}
|
||||
|
||||
MapEntityCategory? category = null;
|
||||
//only select a specific category if the search box is empty
|
||||
//(items from all categories are shown when searching)
|
||||
if (string.IsNullOrEmpty(searchBox.Text)) { category = selectedItemCategory; }
|
||||
FilterStoreItems(category, searchBox.Text);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void DrawMap(SpriteBatch spriteBatch, GUICustomComponent mapContainer)
|
||||
{
|
||||
GameMain.GameSession?.Map?.Draw(spriteBatch, mapContainer);
|
||||
@@ -655,7 +670,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateItemFrame(PurchasedItem pi, PriceInfo priceInfo, GUIListBox listBox, int width)
|
||||
private GUIComponent CreateItemFrame(PurchasedItem pi, PriceInfo priceInfo, GUIListBox listBox, int width)
|
||||
{
|
||||
GUIFrame frame = new GUIFrame(new RectTransform(new Point(listBox.Content.Rect.Width, (int)(GUI.Scale * 50)), listBox.Content.RectTransform), style: "ListBoxElement")
|
||||
{
|
||||
@@ -739,6 +754,10 @@ namespace Barotrauma
|
||||
content.RectTransform.RecalculateChildren(true, true);
|
||||
amountInput?.LayoutGroup.Recalculate();
|
||||
textBlock.Text = ToolBox.LimitString(textBlock.Text, textBlock.Font, textBlock.Rect.Width);
|
||||
content.RectTransform.IsFixedSize = true;
|
||||
content.RectTransform.Children.ForEach(c => c.IsFixedSize = true);
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
private bool BuyItem(GUIComponent component, object obj)
|
||||
@@ -776,12 +795,24 @@ namespace Barotrauma
|
||||
|
||||
private void RefreshMyItems()
|
||||
{
|
||||
myItemList.Content.ClearChildren();
|
||||
|
||||
foreach (PurchasedItem ip in Campaign.CargoManager.PurchasedItems)
|
||||
HashSet<GUIComponent> existingItemFrames = new HashSet<GUIComponent>();
|
||||
foreach (PurchasedItem pi in Campaign.CargoManager.PurchasedItems)
|
||||
{
|
||||
CreateItemFrame(ip, ip.ItemPrefab.GetPrice(Campaign.Map.CurrentLocation), myItemList, myItemList.Rect.Width);
|
||||
var itemFrame = myItemList.Content.GetChildByUserData(pi);
|
||||
if (itemFrame == null)
|
||||
{
|
||||
itemFrame = CreateItemFrame(pi, pi.ItemPrefab.GetPrice(Campaign.Map.CurrentLocation), myItemList, myItemList.Rect.Width);
|
||||
}
|
||||
itemFrame.GetChild(0).GetChild<GUINumberInput>().IntValue = pi.Quantity;
|
||||
existingItemFrames.Add(itemFrame);
|
||||
}
|
||||
|
||||
var removedItemFrames = myItemList.Content.Children.Except(existingItemFrames).ToList();
|
||||
foreach (GUIComponent removedItemFrame in removedItemFrames)
|
||||
{
|
||||
myItemList.Content.RemoveChild(removedItemFrame);
|
||||
}
|
||||
|
||||
myItemList.Content.RectTransform.SortChildren((x, y) =>
|
||||
(x.GUIComponent.UserData as PurchasedItem).ItemPrefab.Name.CompareTo((y.GUIComponent.UserData as PurchasedItem).ItemPrefab.Name));
|
||||
myItemList.Content.RectTransform.SortChildren((x, y) =>
|
||||
@@ -821,17 +852,28 @@ namespace Barotrauma
|
||||
|
||||
private void FillStoreItemList()
|
||||
{
|
||||
storeItemList.ClearChildren();
|
||||
|
||||
int width = storeItemList.Rect.Width;
|
||||
HashSet<GUIComponent> existingItemFrames = new HashSet<GUIComponent>();
|
||||
foreach (MapEntityPrefab mapEntityPrefab in MapEntityPrefab.List)
|
||||
{
|
||||
if (!(mapEntityPrefab is ItemPrefab itemPrefab)) { continue; }
|
||||
PriceInfo priceInfo = itemPrefab.GetPrice(Campaign.Map.CurrentLocation);
|
||||
if (priceInfo == null) continue;
|
||||
if (priceInfo == null) { continue; }
|
||||
|
||||
CreateItemFrame(new PurchasedItem(itemPrefab, 0), priceInfo, storeItemList, width);
|
||||
var itemFrame = myItemList.Content.GetChildByUserData(priceInfo);
|
||||
if (itemFrame == null)
|
||||
{
|
||||
itemFrame = CreateItemFrame(new PurchasedItem(itemPrefab, 0), priceInfo, storeItemList, width);
|
||||
}
|
||||
existingItemFrames.Add(itemFrame);
|
||||
}
|
||||
|
||||
var removedItemFrames = storeItemList.Content.Children.Except(existingItemFrames).ToList();
|
||||
foreach (GUIComponent removedItemFrame in removedItemFrames)
|
||||
{
|
||||
storeItemList.Content.RemoveChild(removedItemFrame);
|
||||
}
|
||||
|
||||
storeItemList.Content.RectTransform.SortChildren(
|
||||
(x, y) => (x.GUIComponent.UserData as PurchasedItem).ItemPrefab.Name.CompareTo((y.GUIComponent.UserData as PurchasedItem).ItemPrefab.Name));
|
||||
}
|
||||
|
||||
@@ -968,7 +968,10 @@ namespace Barotrauma
|
||||
};
|
||||
|
||||
label = new GUITextBlock(new RectTransform(textLabelSize, parent.RectTransform), TextManager.Get("Password"), textAlignment: textAlignment);
|
||||
passwordBox = new GUITextBox(new RectTransform(textFieldSize, label.RectTransform, Anchor.CenterRight), textAlignment: textAlignment);
|
||||
passwordBox = new GUITextBox(new RectTransform(textFieldSize, label.RectTransform, Anchor.CenterRight), textAlignment: textAlignment)
|
||||
{
|
||||
Censor = true
|
||||
};
|
||||
|
||||
isPublicBox = new GUITickBox(new RectTransform(tickBoxSize, parent.RectTransform), TextManager.Get("PublicServer"))
|
||||
{
|
||||
|
||||
@@ -147,6 +147,12 @@ namespace Barotrauma
|
||||
get { return playerList; }
|
||||
}
|
||||
|
||||
public GUITextBox CharacterNameBox
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public GUIButton StartButton
|
||||
{
|
||||
get;
|
||||
@@ -920,7 +926,26 @@ namespace Barotrauma
|
||||
UserData = characterInfo
|
||||
};
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.1f), infoContainer.RectTransform), characterInfo.Name, font: GUI.LargeFont, textAlignment: Alignment.Center, wrap: true);
|
||||
CharacterNameBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.1f), infoContainer.RectTransform), characterInfo.Name, font: GUI.LargeFont, textAlignment: Alignment.Center)
|
||||
{
|
||||
MaxTextLength = Client.MaxNameLength,
|
||||
OverflowClip = true
|
||||
};
|
||||
CharacterNameBox.OnEnterPressed += (tb, text) => { CharacterNameBox.Deselect(); return true; };
|
||||
CharacterNameBox.OnDeselected += (tb, key) =>
|
||||
{
|
||||
if (GameMain.Client == null) { return; }
|
||||
string newName = Client.SanitizeName(tb.Text);
|
||||
if (string.IsNullOrWhiteSpace(newName))
|
||||
{
|
||||
tb.Text = GameMain.Client.Name;
|
||||
}
|
||||
else
|
||||
{
|
||||
ReadyToStartBox.Selected = false;
|
||||
GameMain.Client.Name = tb.Text;
|
||||
};
|
||||
};
|
||||
|
||||
GUIComponent headContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.6f, 0.2f), infoContainer.RectTransform, Anchor.TopCenter), isHorizontal: true)
|
||||
{
|
||||
@@ -1309,6 +1334,7 @@ namespace Barotrauma
|
||||
{
|
||||
Selected = true,
|
||||
Enabled = false,
|
||||
Visible = false,
|
||||
ToolTip = TextManager.Get("ReadyToStartTickBox"),
|
||||
UserData = "clientready"
|
||||
};
|
||||
|
||||
@@ -70,8 +70,14 @@ namespace Barotrauma
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoHolder.RectTransform), TextManager.Get("YourName"));
|
||||
clientNameBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.13f), infoHolder.RectTransform), "")
|
||||
{
|
||||
Text = GameMain.Config.DefaultPlayerName
|
||||
Text = GameMain.Config.DefaultPlayerName,
|
||||
MaxTextLength = Client.MaxNameLength,
|
||||
OverflowClip = true
|
||||
};
|
||||
if (string.IsNullOrEmpty(clientNameBox.Text))
|
||||
{
|
||||
clientNameBox.Text = SteamManager.GetUsername();
|
||||
}
|
||||
clientNameBox.OnTextChanged += RefreshJoinButtonState;
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoHolder.RectTransform), TextManager.Get("ServerIP"));
|
||||
@@ -236,7 +242,7 @@ namespace Barotrauma
|
||||
{
|
||||
serverInfo = (ServerInfo)obj;
|
||||
ipBox.UserData = serverInfo;
|
||||
ipBox.Text = serverInfo.ServerName;
|
||||
ipBox.Text = ToolBox.LimitString(serverInfo.ServerName, ipBox.Font, ipBox.Rect.Width);
|
||||
}
|
||||
catch (InvalidCastException)
|
||||
{
|
||||
@@ -411,7 +417,6 @@ namespace Barotrauma
|
||||
};
|
||||
|
||||
var serverName = new GUITextBlock(new RectTransform(new Vector2(columnRelativeWidth[3], 1.0f), serverContent.RectTransform), serverInfo.ServerName, style: "GUIServerListTextBox");
|
||||
|
||||
var gameStartedBox = new GUITickBox(new RectTransform(new Vector2(columnRelativeWidth[4], 0.4f), serverContent.RectTransform, Anchor.Center),
|
||||
label: "", style: "GUIServerListRoundStartedTickBox") {
|
||||
ToolTip = TextManager.Get((serverInfo.GameStarted) ? "ServerListRoundStarted" : "ServerListRoundNotStarted"),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using System;
|
||||
using OpenTK.Audio.OpenAL;
|
||||
using OpenAL;
|
||||
using NVorbis;
|
||||
using System.Collections.Generic;
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace Barotrauma.Sounds
|
||||
|
||||
reader = new VorbisReader(filename);
|
||||
|
||||
ALFormat = reader.Channels == 1 ? ALFormat.Mono16 : ALFormat.Stereo16;
|
||||
ALFormat = reader.Channels == 1 ? Al.FormatMono16 : Al.FormatStereo16;
|
||||
SampleRate = reader.SampleRate;
|
||||
|
||||
if (!stream)
|
||||
@@ -35,26 +35,26 @@ namespace Barotrauma.Sounds
|
||||
|
||||
CastBuffer(floatBuffer, shortBuffer, readSamples);
|
||||
|
||||
AL.BufferData((int)ALBuffer, ALFormat, shortBuffer,
|
||||
Al.BufferData(ALBuffer, ALFormat, shortBuffer,
|
||||
readSamples * sizeof(short), SampleRate);
|
||||
|
||||
ALError alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
int alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to set buffer data for non-streamed audio! "+AL.GetErrorString(alError));
|
||||
throw new Exception("Failed to set buffer data for non-streamed audio! "+Al.GetErrorString(alError));
|
||||
}
|
||||
|
||||
MuffleBuffer(floatBuffer, SampleRate, reader.Channels);
|
||||
|
||||
CastBuffer(floatBuffer, shortBuffer, readSamples);
|
||||
|
||||
AL.BufferData((int)ALMuffledBuffer, ALFormat, shortBuffer,
|
||||
Al.BufferData(ALMuffledBuffer, ALFormat, shortBuffer,
|
||||
readSamples * sizeof(short), SampleRate);
|
||||
|
||||
alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to set buffer data for non-streamed audio! " + AL.GetErrorString(alError));
|
||||
throw new Exception("Failed to set buffer data for non-streamed audio! " + Al.GetErrorString(alError));
|
||||
}
|
||||
|
||||
reader.Dispose();
|
||||
@@ -98,4 +98,4 @@ namespace Barotrauma.Sounds
|
||||
base.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using System;
|
||||
using OpenTK.Audio.OpenAL;
|
||||
using OpenAL;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System.IO;
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace Barotrauma.Sounds
|
||||
get { return !Stream ? alMuffledBuffer : 0; }
|
||||
}
|
||||
|
||||
public ALFormat ALFormat
|
||||
public int ALFormat
|
||||
{
|
||||
get;
|
||||
protected set;
|
||||
@@ -91,26 +91,26 @@ namespace Barotrauma.Sounds
|
||||
|
||||
if (!stream)
|
||||
{
|
||||
AL.GenBuffer(out alBuffer);
|
||||
ALError alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
Al.GenBuffer(out alBuffer);
|
||||
int alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to create OpenAL buffer for non-streamed sound: " + AL.GetErrorString(alError));
|
||||
throw new Exception("Failed to create OpenAL buffer for non-streamed sound: " + Al.GetErrorString(alError));
|
||||
}
|
||||
|
||||
if (!AL.IsBuffer(alBuffer))
|
||||
if (!Al.IsBuffer(alBuffer))
|
||||
{
|
||||
throw new Exception("Generated OpenAL buffer is invalid!");
|
||||
}
|
||||
|
||||
AL.GenBuffer(out alMuffledBuffer);
|
||||
alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
Al.GenBuffer(out alMuffledBuffer);
|
||||
alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to create OpenAL buffer for non-streamed sound: " + AL.GetErrorString(alError));
|
||||
throw new Exception("Failed to create OpenAL buffer for non-streamed sound: " + Al.GetErrorString(alError));
|
||||
}
|
||||
|
||||
if (!AL.IsBuffer(alMuffledBuffer))
|
||||
if (!Al.IsBuffer(alMuffledBuffer))
|
||||
{
|
||||
throw new Exception("Generated OpenAL buffer is invalid!");
|
||||
}
|
||||
@@ -186,32 +186,32 @@ namespace Barotrauma.Sounds
|
||||
Owner.KillChannels(this);
|
||||
if (alBuffer != 0)
|
||||
{
|
||||
if (!AL.IsBuffer(alBuffer))
|
||||
if (!Al.IsBuffer(alBuffer))
|
||||
{
|
||||
throw new Exception("Buffer to delete is invalid!");
|
||||
}
|
||||
|
||||
AL.DeleteBuffer(ref alBuffer); alBuffer = 0;
|
||||
Al.DeleteBuffer(alBuffer); alBuffer = 0;
|
||||
|
||||
ALError alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
int alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to delete OpenAL buffer for non-streamed sound: " + AL.GetErrorString(alError));
|
||||
throw new Exception("Failed to delete OpenAL buffer for non-streamed sound: " + Al.GetErrorString(alError));
|
||||
}
|
||||
}
|
||||
if (alMuffledBuffer != 0)
|
||||
{
|
||||
if (!AL.IsBuffer(alMuffledBuffer))
|
||||
if (!Al.IsBuffer(alMuffledBuffer))
|
||||
{
|
||||
throw new Exception("Buffer to delete is invalid!");
|
||||
}
|
||||
|
||||
AL.DeleteBuffer(ref alMuffledBuffer); alMuffledBuffer = 0;
|
||||
Al.DeleteBuffer(alMuffledBuffer); alMuffledBuffer = 0;
|
||||
|
||||
ALError alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
int alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to delete OpenAL buffer for non-streamed sound: " + AL.GetErrorString(alError));
|
||||
throw new Exception("Failed to delete OpenAL buffer for non-streamed sound: " + Al.GetErrorString(alError));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using System;
|
||||
using OpenTK.Audio.OpenAL;
|
||||
using OpenAL;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System.Collections.Generic;
|
||||
|
||||
@@ -15,49 +15,49 @@ namespace Barotrauma.Sounds
|
||||
|
||||
public SoundSourcePool(int sourceCount = SoundManager.SOURCE_COUNT)
|
||||
{
|
||||
ALError alError = ALError.NoError;
|
||||
int alError = Al.NoError;
|
||||
|
||||
ALSources = new uint[sourceCount];
|
||||
for (int i = 0; i < sourceCount; i++)
|
||||
{
|
||||
AL.GenSource(out ALSources[i]);
|
||||
alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
Al.GenSource(out ALSources[i]);
|
||||
alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Error generating alSource[" + i.ToString() + "]: " + AL.GetErrorString(alError));
|
||||
throw new Exception("Error generating alSource[" + i.ToString() + "]: " + Al.GetErrorString(alError));
|
||||
}
|
||||
|
||||
if (!AL.IsSource(ALSources[i]))
|
||||
if (!Al.IsSource(ALSources[i]))
|
||||
{
|
||||
throw new Exception("Generated alSource[" + i.ToString() + "] is invalid!");
|
||||
}
|
||||
|
||||
AL.SourceStop(ALSources[i]);
|
||||
alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
Al.SourceStop(ALSources[i]);
|
||||
alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Error stopping newly generated alSource[" + i.ToString() + "]: " + AL.GetErrorString(alError));
|
||||
throw new Exception("Error stopping newly generated alSource[" + i.ToString() + "]: " + Al.GetErrorString(alError));
|
||||
}
|
||||
|
||||
AL.Source(ALSources[i], ALSourcef.MinGain, 0.0f);
|
||||
alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
Al.Sourcef(ALSources[i], Al.MinGain, 0.0f);
|
||||
alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Error setting min gain: " + AL.GetErrorString(alError));
|
||||
throw new Exception("Error setting min gain: " + Al.GetErrorString(alError));
|
||||
}
|
||||
|
||||
AL.Source(ALSources[i], ALSourcef.MaxGain, 1.0f);
|
||||
alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
Al.Sourcef(ALSources[i], Al.MaxGain, 1.0f);
|
||||
alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Error setting max gain: " + AL.GetErrorString(alError));
|
||||
throw new Exception("Error setting max gain: " + Al.GetErrorString(alError));
|
||||
}
|
||||
|
||||
AL.Source(ALSources[i], ALSourcef.RolloffFactor, 1.0f);
|
||||
alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
Al.Sourcef(ALSources[i], Al.RolloffFactor, 1.0f);
|
||||
alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Error setting rolloff factor: " + AL.GetErrorString(alError));
|
||||
throw new Exception("Error setting rolloff factor: " + Al.GetErrorString(alError));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -66,11 +66,11 @@ namespace Barotrauma.Sounds
|
||||
{
|
||||
for (int i = 0; i < ALSources.Length; i++)
|
||||
{
|
||||
AL.DeleteSource(ref ALSources[i]);
|
||||
ALError alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
Al.DeleteSource(ALSources[i]);
|
||||
int alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to delete ALSources[" + i.ToString() + "]: " + AL.GetErrorString(alError));
|
||||
throw new Exception("Failed to delete ALSources[" + i.ToString() + "]: " + Al.GetErrorString(alError));
|
||||
}
|
||||
}
|
||||
ALSources = null;
|
||||
@@ -95,35 +95,35 @@ namespace Barotrauma.Sounds
|
||||
if (position != null)
|
||||
{
|
||||
uint alSource = Sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex);
|
||||
AL.Source(alSource, ALSourceb.SourceRelative, false);
|
||||
ALError alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
Al.Sourcei(alSource, Al.SourceRelative, Al.False);
|
||||
int alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to enable source's relative flag: " + AL.GetErrorString(alError));
|
||||
throw new Exception("Failed to enable source's relative flag: " + Al.GetErrorString(alError));
|
||||
}
|
||||
|
||||
AL.Source(alSource, ALSource3f.Position, position.Value.X, position.Value.Y, position.Value.Z);
|
||||
alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
Al.Source3f(alSource, Al.Position, position.Value.X, position.Value.Y, position.Value.Z);
|
||||
alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to set source's position: " + AL.GetErrorString(alError));
|
||||
throw new Exception("Failed to set source's position: " + Al.GetErrorString(alError));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint alSource = Sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex);
|
||||
AL.Source(alSource, ALSourceb.SourceRelative, true);
|
||||
ALError alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
Al.Sourcei(alSource, Al.SourceRelative, Al.True);
|
||||
int alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to disable source's relative flag: " + AL.GetErrorString(alError));
|
||||
throw new Exception("Failed to disable source's relative flag: " + Al.GetErrorString(alError));
|
||||
}
|
||||
|
||||
AL.Source(alSource, ALSource3f.Position, 0.0f, 0.0f, 0.0f);
|
||||
alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
Al.Source3f(alSource, Al.Position, 0.0f, 0.0f, 0.0f);
|
||||
alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to reset source's position: " + AL.GetErrorString(alError));
|
||||
throw new Exception("Failed to reset source's position: " + Al.GetErrorString(alError));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -140,12 +140,12 @@ namespace Barotrauma.Sounds
|
||||
if (ALSourceIndex < 0) return;
|
||||
|
||||
uint alSource = Sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex);
|
||||
AL.Source(alSource, ALSourcef.ReferenceDistance, near);
|
||||
Al.Sourcef(alSource, Al.ReferenceDistance, near);
|
||||
|
||||
ALError alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
int alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to set source's reference distance: " + AL.GetErrorString(alError));
|
||||
throw new Exception("Failed to set source's reference distance: " + Al.GetErrorString(alError));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -161,11 +161,11 @@ namespace Barotrauma.Sounds
|
||||
if (ALSourceIndex < 0) return;
|
||||
|
||||
uint alSource = Sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex);
|
||||
AL.Source(alSource, ALSourcef.MaxDistance, far);
|
||||
ALError alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
Al.Sourcef(alSource, Al.MaxDistance, far);
|
||||
int alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to set source's max distance: " + AL.GetErrorString(alError));
|
||||
throw new Exception("Failed to set source's max distance: " + Al.GetErrorString(alError));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -185,11 +185,11 @@ namespace Barotrauma.Sounds
|
||||
float effectiveGain = gain;
|
||||
if (category != null) effectiveGain *= Sound.Owner.GetCategoryGainMultiplier(category);
|
||||
|
||||
AL.Source(alSource, ALSourcef.Gain, effectiveGain);
|
||||
ALError alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
Al.Sourcef(alSource, Al.Gain, effectiveGain);
|
||||
int alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to set source's gain: " + AL.GetErrorString(alError));
|
||||
throw new Exception("Failed to set source's gain: " + Al.GetErrorString(alError));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -207,11 +207,11 @@ namespace Barotrauma.Sounds
|
||||
if (!IsStream)
|
||||
{
|
||||
uint alSource = Sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex);
|
||||
AL.Source(alSource, ALSourceb.Looping, looping);
|
||||
ALError alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
Al.Sourcei(alSource, Al.Looping, looping ? Al.True : Al.False);
|
||||
int alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to set source's looping state: " + AL.GetErrorString(alError));
|
||||
throw new Exception("Failed to set source's looping state: " + Al.GetErrorString(alError));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -242,41 +242,41 @@ namespace Barotrauma.Sounds
|
||||
if (!IsStream)
|
||||
{
|
||||
uint alSource = Sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex);
|
||||
int playbackPos; AL.GetSource(alSource, ALGetSourcei.SampleOffset, out playbackPos);
|
||||
ALError alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
int playbackPos; Al.GetSourcei(alSource, Al.SampleOffset, out playbackPos);
|
||||
int alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to get source's playback position: " + AL.GetErrorString(alError));
|
||||
throw new Exception("Failed to get source's playback position: " + Al.GetErrorString(alError));
|
||||
}
|
||||
|
||||
AL.SourceStop(alSource);
|
||||
Al.SourceStop(alSource);
|
||||
|
||||
alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to stop source: " + AL.GetErrorString(alError));
|
||||
throw new Exception("Failed to stop source: " + Al.GetErrorString(alError));
|
||||
}
|
||||
|
||||
AL.BindBufferToSource(alSource,(uint)(muffled ? Sound.ALMuffledBuffer : Sound.ALBuffer));
|
||||
Al.Sourcei(alSource, Al.Buffer, muffled ? (int)Sound.ALMuffledBuffer : (int)Sound.ALBuffer);
|
||||
|
||||
alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to bind buffer to source: " + AL.GetErrorString(alError));
|
||||
throw new Exception("Failed to bind buffer to source: " + Al.GetErrorString(alError));
|
||||
}
|
||||
|
||||
AL.SourcePlay(alSource);
|
||||
alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
Al.SourcePlay(alSource);
|
||||
alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to replay source: " + AL.GetErrorString(alError));
|
||||
throw new Exception("Failed to replay source: " + Al.GetErrorString(alError));
|
||||
}
|
||||
|
||||
AL.Source(alSource, ALSourcei.SampleOffset, playbackPos);
|
||||
alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
Al.Sourcei(alSource, Al.SampleOffset, playbackPos);
|
||||
alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to reset playback position: " + AL.GetErrorString(alError));
|
||||
throw new Exception("Failed to reset playback position: " + Al.GetErrorString(alError));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -324,11 +324,13 @@ namespace Barotrauma.Sounds
|
||||
{
|
||||
if (ALSourceIndex < 0) return false;
|
||||
if (IsStream && !reachedEndSample) return true;
|
||||
bool playing = AL.GetSourceState(Sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex)) == ALSourceState.Playing;
|
||||
ALError alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
int state;
|
||||
Al.GetSourcei(Sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex), Al.SourceState, out state);
|
||||
bool playing = state == Al.Playing;
|
||||
int alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to determine playing state from source: " + AL.GetErrorString(alError));
|
||||
throw new Exception("Failed to determine playing state from source: " + Al.GetErrorString(alError));
|
||||
}
|
||||
return playing;
|
||||
}
|
||||
@@ -357,47 +359,47 @@ namespace Barotrauma.Sounds
|
||||
{
|
||||
if (!IsStream)
|
||||
{
|
||||
AL.BindBufferToSource(sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex), 0);
|
||||
ALError alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
Al.Sourcei(sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex), Al.Buffer, 0);
|
||||
int alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to reset source buffer: " + AL.GetErrorString(alError));
|
||||
throw new Exception("Failed to reset source buffer: " + Al.GetErrorString(alError));
|
||||
}
|
||||
|
||||
if (!AL.IsBuffer(sound.ALBuffer))
|
||||
if (!Al.IsBuffer(sound.ALBuffer))
|
||||
{
|
||||
throw new Exception(sound.Filename + " has an invalid buffer!");
|
||||
}
|
||||
|
||||
uint alBuffer = sound.Owner.GetCategoryMuffle(category) || muffle ? sound.ALMuffledBuffer : sound.ALBuffer;
|
||||
AL.BindBufferToSource(sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex), alBuffer);
|
||||
alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
Al.Sourcei(sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex), Al.Buffer, (int)alBuffer);
|
||||
alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to bind buffer to source (" + ALSourceIndex.ToString() + ":" + sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex) + "," + sound.ALBuffer.ToString() + "): " + AL.GetErrorString(alError));
|
||||
throw new Exception("Failed to bind buffer to source (" + ALSourceIndex.ToString() + ":" + sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex) + "," + sound.ALBuffer.ToString() + "): " + Al.GetErrorString(alError));
|
||||
}
|
||||
|
||||
AL.SourcePlay(sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex));
|
||||
alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
Al.SourcePlay(sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex));
|
||||
alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to play source: " + AL.GetErrorString(alError));
|
||||
throw new Exception("Failed to play source: " + Al.GetErrorString(alError));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AL.BindBufferToSource(sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex), (uint)sound.ALBuffer);
|
||||
ALError alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
Al.Sourcei(sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex), Al.Buffer, (int)sound.ALBuffer);
|
||||
int alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to reset source buffer: " + AL.GetErrorString(alError));
|
||||
throw new Exception("Failed to reset source buffer: " + Al.GetErrorString(alError));
|
||||
}
|
||||
|
||||
AL.Source(sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex), ALSourceb.Looping, false);
|
||||
alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
Al.Sourcei(sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex), Al.Looping, Al.False);
|
||||
alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to set stream looping state: " + AL.GetErrorString(alError));
|
||||
throw new Exception("Failed to set stream looping state: " + Al.GetErrorString(alError));
|
||||
}
|
||||
|
||||
streamShortBuffer = new short[STREAM_BUFFER_SIZE];
|
||||
@@ -406,15 +408,15 @@ namespace Barotrauma.Sounds
|
||||
emptyBuffers = new List<uint>();
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
AL.GenBuffer(out streamBuffers[i]);
|
||||
Al.GenBuffer(out streamBuffers[i]);
|
||||
|
||||
alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to generate stream buffers: " + AL.GetErrorString(alError));
|
||||
throw new Exception("Failed to generate stream buffers: " + Al.GetErrorString(alError));
|
||||
}
|
||||
|
||||
if (!AL.IsBuffer(streamBuffers[i]))
|
||||
if (!Al.IsBuffer(streamBuffers[i]))
|
||||
{
|
||||
throw new Exception("Generated streamBuffer[" + i.ToString() + "] is invalid!");
|
||||
}
|
||||
@@ -445,57 +447,57 @@ namespace Barotrauma.Sounds
|
||||
{
|
||||
if (ALSourceIndex >= 0)
|
||||
{
|
||||
AL.SourceStop(Sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex));
|
||||
ALError alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
Al.SourceStop(Sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex));
|
||||
int alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to stop source: " + AL.GetErrorString(alError));
|
||||
throw new Exception("Failed to stop source: " + Al.GetErrorString(alError));
|
||||
}
|
||||
|
||||
if (IsStream)
|
||||
{
|
||||
uint alSource = Sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex);
|
||||
|
||||
AL.SourceStop(alSource);
|
||||
alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
Al.SourceStop(alSource);
|
||||
alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to stop streamed source: " + AL.GetErrorString(alError));
|
||||
throw new Exception("Failed to stop streamed source: " + Al.GetErrorString(alError));
|
||||
}
|
||||
|
||||
int buffersToUnqueue = 0;
|
||||
int[] unqueuedBuffers = null;
|
||||
uint[] unqueuedBuffers = null;
|
||||
|
||||
buffersToUnqueue = 0;
|
||||
AL.GetSource(alSource, ALGetSourcei.BuffersProcessed, out buffersToUnqueue);
|
||||
alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
Al.GetSourcei(alSource, Al.BuffersProcessed, out buffersToUnqueue);
|
||||
alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to determine processed buffers from streamed source: " + AL.GetErrorString(alError));
|
||||
throw new Exception("Failed to determine processed buffers from streamed source: " + Al.GetErrorString(alError));
|
||||
}
|
||||
|
||||
unqueuedBuffers = new int[buffersToUnqueue];
|
||||
AL.SourceUnqueueBuffers((int)alSource, buffersToUnqueue, unqueuedBuffers);
|
||||
alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
unqueuedBuffers = new uint[buffersToUnqueue];
|
||||
Al.SourceUnqueueBuffers(alSource, buffersToUnqueue, unqueuedBuffers);
|
||||
alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to unqueue buffers from streamed source: " + AL.GetErrorString(alError));
|
||||
throw new Exception("Failed to unqueue buffers from streamed source: " + Al.GetErrorString(alError));
|
||||
}
|
||||
|
||||
AL.BindBufferToSource(alSource, 0);
|
||||
alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
|
||||
Al.Sourcei(alSource, Al.Buffer, 0);
|
||||
alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to reset buffer for streamed source: " + AL.GetErrorString(alError));
|
||||
throw new Exception("Failed to reset buffer for streamed source: " + Al.GetErrorString(alError));
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
AL.DeleteBuffer(ref streamBuffers[i]);
|
||||
alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
Al.DeleteBuffer(streamBuffers[i]);
|
||||
alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to delete streamBuffers[" + i.ToString() + "] ("+streamBuffers[i].ToString()+"): " + AL.GetErrorString(alError));
|
||||
throw new Exception("Failed to delete streamBuffers[" + i.ToString() + "] ("+streamBuffers[i].ToString()+"): " + Al.GetErrorString(alError));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -503,11 +505,11 @@ namespace Barotrauma.Sounds
|
||||
}
|
||||
else
|
||||
{
|
||||
AL.BindBufferToSource(Sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex), 0);
|
||||
alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
Al.Sourcei(Sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex), Al.Buffer, 0);
|
||||
alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to unbind buffer to non-streamed source: " + AL.GetErrorString(alError));
|
||||
throw new Exception("Failed to unbind buffer to non-streamed source: " + Al.GetErrorString(alError));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -526,47 +528,49 @@ namespace Barotrauma.Sounds
|
||||
{
|
||||
uint alSource = Sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex);
|
||||
|
||||
bool playing = AL.GetSourceState(alSource) == ALSourceState.Playing;
|
||||
ALError alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
int state;
|
||||
Al.GetSourcei(Sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex), Al.SourceState, out state);
|
||||
bool playing = state == Al.Playing;
|
||||
int alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to determine playing state from streamed source: " + AL.GetErrorString(alError));
|
||||
throw new Exception("Failed to determine playing state from streamed source: " + Al.GetErrorString(alError));
|
||||
}
|
||||
|
||||
int buffersToUnqueue = 0;
|
||||
int[] unqueuedBuffers = null;
|
||||
uint[] unqueuedBuffers = null;
|
||||
if (!startedPlaying)
|
||||
{
|
||||
buffersToUnqueue = 0;
|
||||
AL.GetSource(alSource, ALGetSourcei.BuffersProcessed, out buffersToUnqueue);
|
||||
alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
Al.GetSourcei(alSource, Al.BuffersProcessed, out buffersToUnqueue);
|
||||
alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to determine processed buffers from streamed source: " + AL.GetErrorString(alError));
|
||||
throw new Exception("Failed to determine processed buffers from streamed source: " + Al.GetErrorString(alError));
|
||||
}
|
||||
|
||||
unqueuedBuffers = new int[buffersToUnqueue+emptyBuffers.Count];
|
||||
AL.SourceUnqueueBuffers((int)alSource, buffersToUnqueue, unqueuedBuffers);
|
||||
unqueuedBuffers = new uint[buffersToUnqueue+emptyBuffers.Count];
|
||||
Al.SourceUnqueueBuffers(alSource, buffersToUnqueue, unqueuedBuffers);
|
||||
for (int i = 0; i < emptyBuffers.Count; i++)
|
||||
{
|
||||
unqueuedBuffers[buffersToUnqueue + i] = (int)emptyBuffers[i];
|
||||
unqueuedBuffers[buffersToUnqueue + i] = emptyBuffers[i];
|
||||
}
|
||||
buffersToUnqueue += emptyBuffers.Count;
|
||||
emptyBuffers.Clear();
|
||||
alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to unqueue buffers from streamed source: " + AL.GetErrorString(alError));
|
||||
throw new Exception("Failed to unqueue buffers from streamed source: " + Al.GetErrorString(alError));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
startedPlaying = false;
|
||||
buffersToUnqueue = 4;
|
||||
unqueuedBuffers = new int[4];
|
||||
unqueuedBuffers = new uint[4];
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
unqueuedBuffers[i] = (int)streamBuffers[i];
|
||||
unqueuedBuffers[i] = streamBuffers[i];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -612,20 +616,20 @@ namespace Barotrauma.Sounds
|
||||
|
||||
if (readSamples > 0)
|
||||
{
|
||||
AL.BufferData<short>(unqueuedBuffers[i], Sound.ALFormat, buffer, readSamples, Sound.SampleRate);
|
||||
Al.BufferData<short>(unqueuedBuffers[i], Sound.ALFormat, buffer, readSamples, Sound.SampleRate);
|
||||
|
||||
alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to assign data to stream buffer: " +
|
||||
AL.GetErrorString(alError) + ": " + unqueuedBuffers[i].ToString() + "/" + unqueuedBuffers.Length + ", readSamples: " + readSamples);
|
||||
Al.GetErrorString(alError) + ": " + unqueuedBuffers[i].ToString() + "/" + unqueuedBuffers.Length + ", readSamples: " + readSamples);
|
||||
}
|
||||
|
||||
AL.SourceQueueBuffer((int)alSource, unqueuedBuffers[i]);
|
||||
alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
Al.SourceQueueBuffer(alSource, unqueuedBuffers[i]);
|
||||
alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to queue buffer[" + i.ToString() + "] to stream: " + AL.GetErrorString(alError));
|
||||
throw new Exception("Failed to queue buffer[" + i.ToString() + "] to stream: " + Al.GetErrorString(alError));
|
||||
}
|
||||
}
|
||||
else if (readSamples < 0)
|
||||
@@ -637,10 +641,11 @@ namespace Barotrauma.Sounds
|
||||
emptyBuffers.Add((uint)unqueuedBuffers[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (AL.GetSourceState(alSource) != ALSourceState.Playing)
|
||||
|
||||
Al.GetSourcei(alSource, Al.SourceState, out state);
|
||||
if (state != Al.Playing)
|
||||
{
|
||||
AL.SourcePlay(alSource);
|
||||
Al.SourcePlay(alSource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
using System.Threading;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
using OpenTK.Audio.OpenAL;
|
||||
using OpenAL;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
@@ -20,7 +20,7 @@ namespace Barotrauma.Sounds
|
||||
}
|
||||
|
||||
private IntPtr alcDevice;
|
||||
private OpenTK.ContextHandle alcContext;
|
||||
private IntPtr alcContext;
|
||||
|
||||
public enum SourcePoolIndex
|
||||
{
|
||||
@@ -42,11 +42,11 @@ namespace Barotrauma.Sounds
|
||||
{
|
||||
if (Disabled) { return; }
|
||||
listenerPosition = value;
|
||||
AL.Listener(ALListener3f.Position,value.X,value.Y,value.Z);
|
||||
ALError alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
Al.Listener3f(Al.Position,value.X,value.Y,value.Z);
|
||||
int alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to set listener position: " + AL.GetErrorString(alError));
|
||||
throw new Exception("Failed to set listener position: " + Al.GetErrorString(alError));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -59,11 +59,11 @@ namespace Barotrauma.Sounds
|
||||
{
|
||||
if (Disabled) { return; }
|
||||
listenerOrientation[0] = value.X; listenerOrientation[1] = value.Y; listenerOrientation[2] = value.Z;
|
||||
AL.Listener(ALListenerfv.Orientation, ref listenerOrientation);
|
||||
ALError alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
Al.Listenerfv(Al.Orientation, listenerOrientation);
|
||||
int alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to set listener target vector: " + AL.GetErrorString(alError));
|
||||
throw new Exception("Failed to set listener target vector: " + Al.GetErrorString(alError));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -74,11 +74,11 @@ namespace Barotrauma.Sounds
|
||||
{
|
||||
if (Disabled) { return; }
|
||||
listenerOrientation[3] = value.X; listenerOrientation[4] = value.Y; listenerOrientation[5] = value.Z;
|
||||
AL.Listener(ALListenerfv.Orientation, ref listenerOrientation);
|
||||
ALError alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
Al.Listenerfv(Al.Orientation, listenerOrientation);
|
||||
int alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to set listener up vector: " + AL.GetErrorString(alError));
|
||||
throw new Exception("Failed to set listener up vector: " + Al.GetErrorString(alError));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -92,11 +92,11 @@ namespace Barotrauma.Sounds
|
||||
if (Disabled) { return; }
|
||||
if (Math.Abs(ListenerGain - value) < 0.001f) { return; }
|
||||
listenerGain = value;
|
||||
AL.Listener(ALListenerf.Gain, listenerGain);
|
||||
ALError alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
Al.Listenerf(Al.Gain, listenerGain);
|
||||
int alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to set listener gain: " + AL.GetErrorString(alError));
|
||||
throw new Exception("Failed to set listener gain: " + Al.GetErrorString(alError));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -126,8 +126,8 @@ namespace Barotrauma.Sounds
|
||||
return;
|
||||
}
|
||||
|
||||
AlcError alcError = Alc.GetError(alcDevice);
|
||||
if (alcError != AlcError.NoError)
|
||||
int alcError = Alc.GetError(alcDevice);
|
||||
if (alcError != Alc.NoError)
|
||||
{
|
||||
//The audio device probably wasn't ready, this happens quite often
|
||||
//Just wait a while and try again
|
||||
@@ -136,7 +136,7 @@ namespace Barotrauma.Sounds
|
||||
alcDevice = Alc.OpenDevice(null);
|
||||
|
||||
alcError = Alc.GetError(alcDevice);
|
||||
if (alcError != AlcError.NoError)
|
||||
if (alcError != Alc.NoError)
|
||||
{
|
||||
DebugConsole.ThrowError("Error initializing ALC device: " + alcError.ToString() + ". Disabling audio playback...");
|
||||
Disabled = true;
|
||||
@@ -161,14 +161,14 @@ namespace Barotrauma.Sounds
|
||||
}
|
||||
|
||||
alcError = Alc.GetError(alcDevice);
|
||||
if (alcError != AlcError.NoError)
|
||||
if (alcError != Alc.NoError)
|
||||
{
|
||||
DebugConsole.ThrowError("Error after assigning ALC context: " + alcError.ToString() + ". Disabling audio playback...");
|
||||
Disabled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
ALError alError = ALError.NoError;
|
||||
int alError = Al.NoError;
|
||||
|
||||
sourcePools = new SoundSourcePool[2];
|
||||
sourcePools[(int)SourcePoolIndex.Default] = new SoundSourcePool(SOURCE_COUNT);
|
||||
@@ -177,12 +177,12 @@ namespace Barotrauma.Sounds
|
||||
sourcePools[(int)SourcePoolIndex.Voice] = new SoundSourcePool(8);
|
||||
playingChannels[(int)SourcePoolIndex.Voice] = new SoundChannel[8];
|
||||
|
||||
AL.DistanceModel(ALDistanceModel.LinearDistanceClamped);
|
||||
Al.DistanceModel(Al.LinearDistanceClamped);
|
||||
|
||||
alError = AL.GetError();
|
||||
if (alError != ALError.NoError)
|
||||
alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
DebugConsole.ThrowError("Error setting distance model: " + AL.GetErrorString(alError) + ". Disabling audio playback...");
|
||||
DebugConsole.ThrowError("Error setting distance model: " + Al.GetErrorString(alError) + ". Disabling audio playback...");
|
||||
Disabled = true;
|
||||
return;
|
||||
}
|
||||
@@ -239,7 +239,7 @@ namespace Barotrauma.Sounds
|
||||
{
|
||||
if (Disabled || srcInd < 0 || srcInd >= sourcePools[(int)poolIndex].ALSources.Length) return 0;
|
||||
|
||||
if (!AL.IsSource(sourcePools[(int)poolIndex].ALSources[srcInd]))
|
||||
if (!Al.IsSource(sourcePools[(int)poolIndex].ALSources[srcInd]))
|
||||
{
|
||||
throw new Exception("alSources[" + srcInd.ToString() + "] is invalid!");
|
||||
}
|
||||
@@ -276,8 +276,8 @@ namespace Barotrauma.Sounds
|
||||
{
|
||||
for (int i = 0; i < sourcePools[0].ALSources.Length; i++)
|
||||
{
|
||||
AL.Source(sourcePools[0].ALSources[i], ALSourcef.MaxGain, i == ind ? 1.0f : 0.0f);
|
||||
AL.Source(sourcePools[0].ALSources[i], ALSourcef.MinGain, 0.0f);
|
||||
Al.Sourcef(sourcePools[0].ALSources[i], Al.MaxGain, i == ind ? 1.0f : 0.0f);
|
||||
Al.Sourcef(sourcePools[0].ALSources[i], Al.MinGain, 0.0f);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -503,10 +503,7 @@ namespace Barotrauma.Sounds
|
||||
}
|
||||
}
|
||||
}
|
||||
if (streamingThread != null && !streamingThread.ThreadState.HasFlag(ThreadState.Stopped))
|
||||
{
|
||||
streamingThread.Join();
|
||||
}
|
||||
streamingThread?.Join();
|
||||
for (int i = loadedSounds.Count - 1; i >= 0; i--)
|
||||
{
|
||||
loadedSounds[i].Dispose();
|
||||
@@ -514,7 +511,7 @@ namespace Barotrauma.Sounds
|
||||
sourcePools[(int)SourcePoolIndex.Default]?.Dispose();
|
||||
sourcePools[(int)SourcePoolIndex.Voice]?.Dispose();
|
||||
|
||||
if (!Alc.MakeContextCurrent(OpenTK.ContextHandle.Zero))
|
||||
if (!Alc.MakeContextCurrent(IntPtr.Zero))
|
||||
{
|
||||
throw new Exception("Failed to detach the current ALC context! (error code: " + Alc.GetError(alcDevice).ToString() + ")");
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using OpenTK.Audio.OpenAL;
|
||||
using OpenAL;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
@@ -21,7 +21,7 @@ namespace Barotrauma.Sounds
|
||||
|
||||
public VideoSound(SoundManager owner, string filename, int sampleRate, Video vid) : base(owner, filename, true, false)
|
||||
{
|
||||
ALFormat = ALFormat.Stereo16;
|
||||
ALFormat = Al.FormatStereo16;
|
||||
SampleRate = sampleRate;
|
||||
|
||||
sampleQueue = new Queue<short[]>();
|
||||
@@ -110,4 +110,4 @@ namespace Barotrauma.Sounds
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using Barotrauma.Networking;
|
||||
using Microsoft.Xna.Framework;
|
||||
using OpenTK.Audio.OpenAL;
|
||||
using OpenAL;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace Barotrauma.Sounds
|
||||
{
|
||||
VoipConfig.SetupEncoding();
|
||||
|
||||
ALFormat = ALFormat.Mono16;
|
||||
ALFormat = Al.FormatMono16;
|
||||
SampleRate = VoipConfig.FREQUENCY;
|
||||
|
||||
queue = q;
|
||||
|
||||
@@ -40,6 +40,9 @@ namespace Barotrauma.SpriteDeformations
|
||||
[Serialize(false, true)]
|
||||
public bool UseMovementSine { get; set; }
|
||||
|
||||
[Serialize(false, true)]
|
||||
public bool StopWhenHostIsDead { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Only used if UseMovementSine is enabled. Multiplier for Pi.
|
||||
/// </summary>
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||
<NuGetPackageImportStamp>
|
||||
</NuGetPackageImportStamp>
|
||||
<AllowedReferenceRelatedFileExtensions>.pdb</AllowedReferenceRelatedFileExtensions>
|
||||
<AllowedReferenceRelatedFileExtensions>.pdb</AllowedReferenceRelatedFileExtensions>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationIcon>..\BarotraumaShared\Icon.ico</ApplicationIcon>
|
||||
@@ -39,7 +39,7 @@
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'ReleaseWindows|x64'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>..\bin\ReleaseWindows\</OutputPath>
|
||||
<DefineConstants>TRACE;WINDOWS;CLIENT</DefineConstants>
|
||||
<DefineConstants>TRACE;WINDOWS;CLIENT;X64</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
@@ -49,7 +49,7 @@
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'DebugWindows|x64'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>..\bin\DebugWindows\</OutputPath>
|
||||
<DefineConstants>TRACE;WINDOWS;CLIENT;DEBUG</DefineConstants>
|
||||
<DefineConstants>TRACE;DEBUG;WINDOWS;CLIENT;X64</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
@@ -60,7 +60,7 @@
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'ReleaseWindows|x86'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>..\bin\x86\ReleaseWindows\</OutputPath>
|
||||
<DefineConstants>TRACE;WINDOWS;CLIENT</DefineConstants>
|
||||
<DefineConstants>TRACE;WINDOWS;CLIENT;X86</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
@@ -70,7 +70,7 @@
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'DebugWindows|x86'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>..\bin\x86\DebugWindows\</OutputPath>
|
||||
<DefineConstants>TRACE;WINDOWS;CLIENT;DEBUG</DefineConstants>
|
||||
<DefineConstants>TRACE;DEBUG;WINDOWS;CLIENT;X86</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
@@ -95,9 +95,6 @@
|
||||
<Reference Include="NVorbis, Version=0.8.6.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\Libraries\NuGet\NVorbis.0.8.6\lib\net35\NVorbis.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="OpenTK, Version=3.0.1.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\Libraries\NuGet\OpenTK.3.0.1\lib\net20\OpenTK.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="PresentationCore" />
|
||||
<Reference Include="RestSharp, Version=105.2.3.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\Libraries\NuGet\RestSharp.105.2.3\lib\net45\RestSharp.dll</HintPath>
|
||||
@@ -215,16 +212,16 @@
|
||||
<Content Include="Shaders\losshader.fx" />
|
||||
<Content Include="Shaders\postprocess.fx" />
|
||||
<Content Include="Shaders\watershader.fx" />
|
||||
<Content Include="wrap_oal.dll">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="MonoGame.Framework.dll.config">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="OpenTK.dll.config">
|
||||
<Content Include="SharpFont.dll.config">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="SharpFont.dll.config">
|
||||
<Content Include="soft_oal_x64.dll">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="soft_oal_x86.dll">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
@@ -306,7 +303,7 @@
|
||||
<Import Project="ClientCode.projitems" Label="Shared" />
|
||||
<Import Project="..\BarotraumaShared\SharedCode.projitems" Label="Shared" />
|
||||
<Import Project="..\BarotraumaShared\SharedContent.projitems" Label="Shared" />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="..\..\Libraries\NuGet\GameAnalytics.Mono.SDK.2.1.6\build\net45\GameAnalytics.Mono.SDK.targets" Condition="Exists('..\..\Libraries\NuGet\GameAnalytics.Mono.SDK.2.1.6\build\net45\GameAnalytics.Mono.SDK.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
<package id="NLog" version="4.3.8" targetFramework="net45" />
|
||||
<package id="nVLC" version="3.0.0" targetFramework="net45" />
|
||||
<package id="NVorbis" version="0.8.6" targetFramework="net45" />
|
||||
<package id="OpenTK" version="3.0.1" targetFramework="net45" />
|
||||
<package id="RestSharp" version="105.2.3" targetFramework="net45" />
|
||||
<package id="SharpDX" version="4.2.0" targetFramework="net45" />
|
||||
<package id="SharpDX.Direct2D1" version="4.2.0" targetFramework="net45" />
|
||||
|
||||
@@ -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.9.0.3")]
|
||||
[assembly: AssemblyFileVersion("0.9.0.3")]
|
||||
[assembly: AssemblyVersion("0.9.0.4")]
|
||||
[assembly: AssemblyFileVersion("0.9.0.4")]
|
||||
|
||||
@@ -273,10 +273,7 @@
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="$(Configuration.EndsWith('Linux'))">
|
||||
<None Include="Launch_BarotraumaServer">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<ItemGroup Condition="$(Configuration.EndsWith('Linux')) Or $(Configuration.EndsWith('Mac'))">
|
||||
<None Include="DedicatedServer">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
|
||||
@@ -153,20 +153,5 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
return this.Permissions.HasFlag(permission);
|
||||
}
|
||||
|
||||
public static string SanitizeName(string name)
|
||||
{
|
||||
name = name.Trim();
|
||||
if (name.Length > 20)
|
||||
{
|
||||
name = name.Substring(0, 20);
|
||||
}
|
||||
string rName = "";
|
||||
for (int i = 0; i < name.Length; i++)
|
||||
{
|
||||
rName += name[i] < 32 ? '?' : name[i];
|
||||
}
|
||||
return rName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,12 +30,13 @@ namespace Barotrauma
|
||||
if (entities.Entity is Item)
|
||||
{
|
||||
message.Write((byte)SpawnableType.Item);
|
||||
DebugConsole.Log("Writing item spawn data " + entities.Entity.ToString() + " (ID: " + entities.Entity.ID + ")");
|
||||
((Item)entities.Entity).WriteSpawnData(message);
|
||||
}
|
||||
else if (entities.Entity is Character)
|
||||
{
|
||||
message.Write((byte)SpawnableType.Character);
|
||||
DebugConsole.NewMessage("WRITING CHARACTER DATA: " + (entities.Entity).ToString() + " (ID: " + entities.Entity.ID + ")", Color.Cyan);
|
||||
DebugConsole.Log("Writing character spawn data: " + entities.Entity.ToString() + " (ID: " + entities.Entity.ID + ")");
|
||||
((Character)entities.Entity).WriteSpawnData(message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -576,7 +576,7 @@ namespace Barotrauma.Networking
|
||||
HandleOwnership(msgContent, inc.SenderConnection);
|
||||
}
|
||||
|
||||
DebugConsole.NewMessage(packetHeader.ToString(), Color.Lime);
|
||||
DebugConsole.Log(packetHeader.ToString());
|
||||
if (inc.SenderConnection != OwnerConnection && serverSettings.BanList.IsBanned(inc.SenderEndPoint.Address, 0))
|
||||
{
|
||||
inc.SenderConnection.Deny(DisconnectReason.Banned.ToString());
|
||||
@@ -661,7 +661,13 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (GameMain.Config.UseSteamMatchmaking)
|
||||
{
|
||||
SteamManager.RefreshServerDetails(this);
|
||||
bool refreshSuccessful = SteamManager.RefreshServerDetails(this);
|
||||
if (GameSettings.VerboseLogging)
|
||||
{
|
||||
Log(refreshSuccessful ?
|
||||
"Refreshed server info on the server list." :
|
||||
"Refreshing server info on the server list failed.", ServerLog.MessageType.ServerMessage);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -865,6 +871,8 @@ namespace Barotrauma.Networking
|
||||
c.LastRecvLobbyUpdate = NetIdUtils.Clamp(inc.ReadUInt16(), c.LastRecvLobbyUpdate, GameMain.NetLobbyScreen.LastUpdateID);
|
||||
c.LastRecvChatMsgID = NetIdUtils.Clamp(inc.ReadUInt16(), c.LastRecvChatMsgID, c.LastChatMsgQueueID);
|
||||
c.LastRecvClientListUpdate = NetIdUtils.Clamp(inc.ReadUInt16(), c.LastRecvClientListUpdate, LastClientListUpdateID);
|
||||
|
||||
TryChangeClientName(c, inc.ReadString());
|
||||
|
||||
c.LastRecvCampaignSave = inc.ReadUInt16();
|
||||
if (c.LastRecvCampaignSave > 0)
|
||||
@@ -2066,11 +2074,44 @@ namespace Barotrauma.Networking
|
||||
public override void AddChatMessage(ChatMessage message)
|
||||
{
|
||||
if (string.IsNullOrEmpty(message.Text)) { return; }
|
||||
Log(message.TextWithSender, ServerLog.MessageType.Chat);
|
||||
Log(message.TextWithSender, ServerLog.MessageType.Chat);
|
||||
|
||||
base.AddChatMessage(message);
|
||||
}
|
||||
|
||||
private bool TryChangeClientName(Client c, string newName)
|
||||
{
|
||||
if (c == null || string.IsNullOrEmpty(newName)) { return false; }
|
||||
|
||||
newName = Client.SanitizeName(newName);
|
||||
if (newName == c.Name) { return false; }
|
||||
|
||||
//update client list even if the name cannot be changed to the one sent by the client,
|
||||
//so the client will be informed what their actual name is
|
||||
LastClientListUpdateID++;
|
||||
|
||||
if (!Client.IsValidName(newName, this))
|
||||
{
|
||||
SendDirectChatMessage("Could not change your name to \"" + newName + "\" (the name contains disallowed symbols).", c, ChatMessageType.MessageBox);
|
||||
return false;
|
||||
}
|
||||
if (c.Connection != OwnerConnection && Homoglyphs.Compare(newName.ToLower(), Name.ToLower()))
|
||||
{
|
||||
SendDirectChatMessage("Could not change your name to \"" + newName + "\" (too similar to the server's name).", c, ChatMessageType.MessageBox);
|
||||
return false;
|
||||
}
|
||||
Client nameTaken = ConnectedClients.Find(c2 => c != c2 && Homoglyphs.Compare(c2.Name.ToLower(), newName.ToLower()));
|
||||
if (nameTaken != null)
|
||||
{
|
||||
SendDirectChatMessage("Could not change your name to \"" + newName + "\" (too similar to the name of the client \"" + nameTaken.Name + "\").", c, ChatMessageType.MessageBox);
|
||||
return false;
|
||||
}
|
||||
|
||||
SendChatMessage("Player \"" + c.Name + "\" has changed their name to \"" + newName + "\".", ChatMessageType.Server);
|
||||
c.Name = newName;
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void KickPlayer(string playerName, string reason)
|
||||
{
|
||||
playerName = playerName.ToLowerInvariant();
|
||||
|
||||
@@ -432,7 +432,7 @@ namespace Barotrauma.Networking
|
||||
DebugConsole.NewMessage(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (invalid name)", Color.Red);
|
||||
return;
|
||||
}
|
||||
if (inc.SenderConnection != OwnerConnection && Homoglyphs.Compare(clName.ToLower(),Name.ToLower()))
|
||||
if (inc.SenderConnection != OwnerConnection && Homoglyphs.Compare(clName.ToLower(), Name.ToLower()))
|
||||
{
|
||||
DisconnectUnauthClient(inc, unauthClient, DisconnectReason.NameTaken, "");
|
||||
Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (name taken by the server)", ServerLog.MessageType.Error);
|
||||
|
||||
@@ -48,6 +48,9 @@ namespace Barotrauma.Networking
|
||||
private List<ServerEntityEvent> uniqueEvents;
|
||||
|
||||
private UInt16 lastSentToAll;
|
||||
private UInt16 lastSentToAnyone;
|
||||
private double lastSentToAnyoneTime;
|
||||
private double lastWarningTime;
|
||||
|
||||
public List<ServerEntityEvent> Events
|
||||
{
|
||||
@@ -99,6 +102,8 @@ namespace Barotrauma.Networking
|
||||
bufferedEvents = new List<BufferedEvent>();
|
||||
|
||||
uniqueEvents = new List<ServerEntityEvent>();
|
||||
|
||||
lastWarningTime = -10.0;
|
||||
}
|
||||
|
||||
public void CreateEvent(IServerSerializable entity, object[] extraData = null)
|
||||
@@ -198,6 +203,7 @@ namespace Barotrauma.Networking
|
||||
var inGameClients = clients.FindAll(c => c.InGame && !c.NeedsMidRoundSync);
|
||||
if (inGameClients.Count > 0)
|
||||
{
|
||||
lastSentToAnyone = inGameClients[0].LastRecvEntityEventID;
|
||||
lastSentToAll = inGameClients[0].LastRecvEntityEventID;
|
||||
if (server.OwnerConnection != null)
|
||||
{
|
||||
@@ -207,25 +213,39 @@ namespace Barotrauma.Networking
|
||||
lastSentToAll = owner.LastRecvEntityEventID;
|
||||
}
|
||||
}
|
||||
inGameClients.ForEach(c => { if (NetIdUtils.IdMoreRecent(lastSentToAll, c.LastRecvEntityEventID)) lastSentToAll = c.LastRecvEntityEventID; });
|
||||
inGameClients.ForEach(c =>
|
||||
{
|
||||
if (NetIdUtils.IdMoreRecent(lastSentToAll, c.LastRecvEntityEventID)) { lastSentToAll = c.LastRecvEntityEventID; }
|
||||
if (NetIdUtils.IdMoreRecent(c.LastRecvEntityEventID, lastSentToAnyone)) { lastSentToAnyone = c.LastRecvEntityEventID; }
|
||||
});
|
||||
lastSentToAnyoneTime = events.Find(e => e.ID == lastSentToAnyone)?.CreateTime ?? Timing.TotalTime;
|
||||
|
||||
if ((Timing.TotalTime - lastSentToAnyoneTime) > 10.0 && (Timing.TotalTime - lastWarningTime) > 5.0)
|
||||
{
|
||||
lastWarningTime = Timing.TotalTime;
|
||||
GameServer.Log("WARNING: ServerEntityEventManager is lagging behind! Last sent id: " + lastSentToAnyone.ToString() + ", latest create id: " + ID.ToString(), ServerLog.MessageType.ServerMessage);
|
||||
//TODO: reset clients if this happens, maybe do it if a majority are behind rather than all of them?
|
||||
}
|
||||
|
||||
clients.Where(c => c.NeedsMidRoundSync).ForEach(c => { if (NetIdUtils.IdMoreRecent(lastSentToAll, c.FirstNewEventID)) lastSentToAll = (ushort)(c.FirstNewEventID - 1); });
|
||||
|
||||
ServerEntityEvent firstEventToResend = events.Find(e => e.ID == (ushort)(lastSentToAll + 1));
|
||||
if (firstEventToResend != null && (Timing.TotalTime - firstEventToResend.CreateTime) > 10.0f)
|
||||
if (firstEventToResend != null && ((lastSentToAnyoneTime - firstEventToResend.CreateTime) > 10.0 || (Timing.TotalTime - firstEventToResend.CreateTime) > 30.0))
|
||||
{
|
||||
//it's been 10 seconds since this event was created, kick everyone that hasn't received it yet, this is way too old
|
||||
// UNLESS the event was created when the client was still midround syncing, in which case we'll wait until the timeout
|
||||
// runs out before kicking the client
|
||||
// This event is 10 seconds older than the last one we've successfully sent,
|
||||
// kick everyone that hasn't received it yet, this is way too old
|
||||
// UNLESS the event was created when the client was still midround syncing,
|
||||
// in which case we'll wait until the timeout runs out before kicking the client
|
||||
List<Client> toKick = inGameClients.FindAll(c =>
|
||||
NetIdUtils.IdMoreRecent((UInt16)(lastSentToAll + 1), c.LastRecvEntityEventID) &&
|
||||
(firstEventToResend.CreateTime > c.MidRoundSyncTimeOut || Timing.TotalTime > c.MidRoundSyncTimeOut));
|
||||
(firstEventToResend.CreateTime > c.MidRoundSyncTimeOut || lastSentToAnyoneTime > c.MidRoundSyncTimeOut));
|
||||
toKick.ForEach(c =>
|
||||
{
|
||||
DebugConsole.NewMessage(c.Name + " was kicked due to excessive desync (expected old event " + (c.LastRecvEntityEventID + 1).ToString() + ")", Color.Red);
|
||||
GameServer.Log("Disconnecting client " + c.Name + " due to excessive desync (expected old event "
|
||||
+ (c.LastRecvEntityEventID + 1).ToString() +
|
||||
" (created " + (Timing.TotalTime - firstEventToResend.CreateTime).ToString("0.##") + " s ago)" +
|
||||
" (created " + (Timing.TotalTime - firstEventToResend.CreateTime).ToString("0.##") + " s ago, " +
|
||||
(lastSentToAnyoneTime - firstEventToResend.CreateTime).ToString("0.##") + " s older than last event sent to anyone)" +
|
||||
" Events queued: " + events.Count + ", last sent to all: " + lastSentToAll, ServerLog.MessageType.Error);
|
||||
server.DisconnectClient(c, "", "ServerMessage.ExcessiveDesyncOldEvent");
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Barotrauma.Items.Components;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -9,19 +10,15 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
private List<Client> GetClientsToRespawn()
|
||||
{
|
||||
GameServer server = networkMember as GameServer;
|
||||
|
||||
return networkMember.ConnectedClients.FindAll(c =>
|
||||
c.InGame &&
|
||||
(!c.SpectateOnly || (!server.ServerSettings.AllowSpectating && server.OwnerConnection != c.Connection)) &&
|
||||
(!c.SpectateOnly || (!GameMain.Server.ServerSettings.AllowSpectating && GameMain.Server.OwnerConnection != c.Connection)) &&
|
||||
(c.Character == null || c.Character.IsDead));
|
||||
}
|
||||
|
||||
private List<CharacterInfo> GetBotsToRespawn()
|
||||
{
|
||||
GameServer server = networkMember as GameServer;
|
||||
|
||||
if (server.ServerSettings.BotSpawnMode == BotSpawnMode.Normal)
|
||||
if (GameMain.Server.ServerSettings.BotSpawnMode == BotSpawnMode.Normal)
|
||||
{
|
||||
return Character.CharacterList
|
||||
.FindAll(c => c.TeamID == Character.TeamType.Team1 && c.AIController != null && c.Info != null && c.IsDead)
|
||||
@@ -29,14 +26,14 @@ namespace Barotrauma.Networking
|
||||
.ToList();
|
||||
}
|
||||
|
||||
int currPlayerCount = server.ConnectedClients.Count(c =>
|
||||
int currPlayerCount = GameMain.Server.ConnectedClients.Count(c =>
|
||||
c.InGame &&
|
||||
(!c.SpectateOnly || (!server.ServerSettings.AllowSpectating && server.OwnerConnection != c.Connection)));
|
||||
(!c.SpectateOnly || (!GameMain.Server.ServerSettings.AllowSpectating && GameMain.Server.OwnerConnection != c.Connection)));
|
||||
|
||||
var existingBots = Character.CharacterList
|
||||
.FindAll(c => c.TeamID == Character.TeamType.Team1 && c.AIController != null && c.Info != null);
|
||||
|
||||
int requiredBots = server.ServerSettings.BotCount - currPlayerCount;
|
||||
int requiredBots = GameMain.Server.ServerSettings.BotCount - currPlayerCount;
|
||||
requiredBots -= existingBots.Count(b => !b.IsDead);
|
||||
|
||||
List<CharacterInfo> botsToRespawn = new List<CharacterInfo>();
|
||||
@@ -58,21 +55,19 @@ namespace Barotrauma.Networking
|
||||
|
||||
partial void UpdateWaiting(float deltaTime)
|
||||
{
|
||||
var server = networkMember as GameServer;
|
||||
|
||||
int characterToRespawnCount = GetClientsToRespawn().Count;
|
||||
int totalCharacterCount = server.ConnectedClients.Count;
|
||||
int totalCharacterCount = GameMain.Server.ConnectedClients.Count;
|
||||
/*if (server.Character != null)
|
||||
{
|
||||
totalCharacterCount++;
|
||||
if (server.Character.IsDead) characterToRespawnCount++;
|
||||
}*/
|
||||
bool startCountdown = (float)characterToRespawnCount >= Math.Max((float)totalCharacterCount * server.ServerSettings.MinRespawnRatio, 1.0f);
|
||||
bool startCountdown = (float)characterToRespawnCount >= Math.Max((float)totalCharacterCount * GameMain.Server.ServerSettings.MinRespawnRatio, 1.0f);
|
||||
|
||||
if (startCountdown != CountdownStarted)
|
||||
{
|
||||
CountdownStarted = startCountdown;
|
||||
server.CreateEntityEvent(this);
|
||||
GameMain.Server.CreateEntityEvent(this);
|
||||
}
|
||||
|
||||
if (!CountdownStarted) return;
|
||||
@@ -80,7 +75,7 @@ namespace Barotrauma.Networking
|
||||
respawnTimer -= deltaTime;
|
||||
if (respawnTimer <= 0.0f)
|
||||
{
|
||||
respawnTimer = server.ServerSettings.RespawnInterval;
|
||||
respawnTimer = GameMain.Server.ServerSettings.RespawnInterval;
|
||||
|
||||
DispatchShuttle();
|
||||
}
|
||||
@@ -98,13 +93,10 @@ namespace Barotrauma.Networking
|
||||
|
||||
partial void DispatchShuttle()
|
||||
{
|
||||
var server = networkMember as GameServer;
|
||||
if (server == null) return;
|
||||
|
||||
if (respawnShuttle != null)
|
||||
{
|
||||
state = State.Transporting;
|
||||
server.CreateEntityEvent(this);
|
||||
GameMain.Server.CreateEntityEvent(this);
|
||||
|
||||
ResetShuttle();
|
||||
|
||||
@@ -124,17 +116,78 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
state = State.Waiting;
|
||||
GameServer.Log("Respawning everyone in main sub.", ServerLog.MessageType.Spawning);
|
||||
server.CreateEntityEvent(this);
|
||||
GameMain.Server.CreateEntityEvent(this);
|
||||
|
||||
RespawnCharacters();
|
||||
}
|
||||
}
|
||||
|
||||
partial void UpdateReturningProjSpecific()
|
||||
{
|
||||
foreach (Door door in shuttleDoors)
|
||||
{
|
||||
if (door.IsOpen) door.TrySetState(false, false, true);
|
||||
}
|
||||
|
||||
var shuttleGaps = Gap.GapList.FindAll(g => g.Submarine == respawnShuttle && g.ConnectedWall != null);
|
||||
shuttleGaps.ForEach(g => Spawner.AddToRemoveQueue(g));
|
||||
|
||||
var dockingPorts = Item.ItemList.FindAll(i => i.Submarine == respawnShuttle && i.GetComponent<DockingPort>() != null);
|
||||
dockingPorts.ForEach(d => d.GetComponent<DockingPort>().Undock());
|
||||
|
||||
//shuttle has returned if the path has been traversed or the shuttle is close enough to the exit
|
||||
if (!CoroutineManager.IsCoroutineRunning("forcepos"))
|
||||
{
|
||||
if ((shuttleSteering?.SteeringPath != null && shuttleSteering.SteeringPath.Finished)
|
||||
|| (respawnShuttle.WorldPosition.Y + respawnShuttle.Borders.Y > Level.Loaded.StartPosition.Y - Level.ShaftHeight &&
|
||||
Math.Abs(Level.Loaded.StartPosition.X - respawnShuttle.WorldPosition.X) < 1000.0f))
|
||||
{
|
||||
CoroutineManager.StopCoroutines("forcepos");
|
||||
CoroutineManager.StartCoroutine(
|
||||
ForceShuttleToPos(new Vector2(Level.Loaded.StartPosition.X, Level.Loaded.Size.Y + 1000.0f), 100.0f), "forcepos");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (respawnShuttle.WorldPosition.Y > Level.Loaded.Size.Y || shuttleReturnTimer <= 0.0f)
|
||||
{
|
||||
CoroutineManager.StopCoroutines("forcepos");
|
||||
|
||||
ResetShuttle();
|
||||
|
||||
state = State.Waiting;
|
||||
GameServer.Log("The respawn shuttle has left.", ServerLog.MessageType.Spawning);
|
||||
GameMain.Server.CreateEntityEvent(this);
|
||||
|
||||
respawnTimer = GameMain.Server.ServerSettings.RespawnInterval;
|
||||
CountdownStarted = false;
|
||||
}
|
||||
}
|
||||
|
||||
partial void UpdateTransportingProjSpecific(float deltaTime)
|
||||
{
|
||||
//if there are no living chracters inside, transporting can be stopped immediately
|
||||
if (!Character.CharacterList.Any(c => c.Submarine == respawnShuttle && !c.IsDead))
|
||||
{
|
||||
shuttleTransportTimer = 0.0f;
|
||||
}
|
||||
|
||||
if (shuttleTransportTimer <= 0.0f)
|
||||
{
|
||||
GameServer.Log("The respawn shuttle is leaving.", ServerLog.MessageType.ServerMessage);
|
||||
state = State.Returning;
|
||||
|
||||
GameMain.Server.CreateEntityEvent(this);
|
||||
|
||||
CountdownStarted = false;
|
||||
maxTransportTime = GameMain.Server.ServerSettings.MaxTransportTime;
|
||||
shuttleReturnTimer = maxTransportTime;
|
||||
shuttleTransportTimer = maxTransportTime;
|
||||
}
|
||||
}
|
||||
|
||||
partial void RespawnCharactersProjSpecific()
|
||||
{
|
||||
var server = networkMember as GameServer;
|
||||
if (server == null) return;
|
||||
|
||||
var respawnSub = respawnShuttle ?? Submarine.MainSub;
|
||||
|
||||
var clients = GetClientsToRespawn();
|
||||
@@ -150,7 +203,7 @@ namespace Barotrauma.Networking
|
||||
var botsToSpawn = GetBotsToRespawn();
|
||||
characterInfos.AddRange(botsToSpawn);
|
||||
|
||||
server.AssignJobs(clients);
|
||||
GameMain.Server.AssignJobs(clients);
|
||||
foreach (Client c in clients)
|
||||
{
|
||||
c.CharacterInfo.Job = new Job(c.AssignedJob);
|
||||
@@ -241,7 +294,6 @@ namespace Barotrauma.Networking
|
||||
item.Description = shuttleSpawnPoints[i].IdCardDesc;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -236,8 +236,8 @@ namespace Barotrauma.Networking
|
||||
TraitorsEnabled = traitorsEnabled;
|
||||
GameMain.NetLobbyScreen.SetTraitorsEnabled(traitorsEnabled);
|
||||
|
||||
var botSpawnMode = BotSpawnMode.Fill;
|
||||
Enum.TryParse(doc.Root.GetAttributeString("BotSpawnMode", "Fill"), out botSpawnMode);
|
||||
var botSpawnMode = BotSpawnMode.Normal;
|
||||
Enum.TryParse(doc.Root.GetAttributeString("BotSpawnMode", "Normal"), out botSpawnMode);
|
||||
BotSpawnMode = botSpawnMode;
|
||||
|
||||
//"65-90", "97-122", "48-59" = upper and lower case english alphabet and numbers
|
||||
|
||||
437
Barotrauma/BarotraumaShared/OpenALSoft_LICENSE
Normal file
437
Barotrauma/BarotraumaShared/OpenALSoft_LICENSE
Normal file
@@ -0,0 +1,437 @@
|
||||
GNU LIBRARY GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1991 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the library GPL. It is
|
||||
numbered 2 because it goes with version 2 of the ordinary GPL.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Library General Public License, applies to some
|
||||
specially designated Free Software Foundation software, and to any
|
||||
other libraries whose authors decide to use it. You can use it for
|
||||
your libraries, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if
|
||||
you distribute copies of the library, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link a program with the library, you must provide
|
||||
complete object files to the recipients so that they can relink them
|
||||
with the library, after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
Our method of protecting your rights has two steps: (1) copyright
|
||||
the library, and (2) offer you this license which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
Also, for each distributor's protection, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
library. If the library is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original
|
||||
version, so that any problems introduced by others will not reflect on
|
||||
the original authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that companies distributing free
|
||||
software will individually obtain patent licenses, thus in effect
|
||||
transforming the program into proprietary software. To prevent this,
|
||||
we have made it clear that any patent must be licensed for everyone's
|
||||
free use or not licensed at all.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the ordinary
|
||||
GNU General Public License, which was designed for utility programs. This
|
||||
license, the GNU Library General Public License, applies to certain
|
||||
designated libraries. This license is quite different from the ordinary
|
||||
one; be sure to read it in full, and don't assume that anything in it is
|
||||
the same as in the ordinary license.
|
||||
|
||||
The reason we have a separate public license for some libraries is that
|
||||
they blur the distinction we usually make between modifying or adding to a
|
||||
program and simply using it. Linking a program with a library, without
|
||||
changing the library, is in some sense simply using the library, and is
|
||||
analogous to running a utility program or application program. However, in
|
||||
a textual and legal sense, the linked executable is a combined work, a
|
||||
derivative of the original library, and the ordinary General Public License
|
||||
treats it as such.
|
||||
|
||||
Because of this blurred distinction, using the ordinary General
|
||||
Public License for libraries did not effectively promote software
|
||||
sharing, because most developers did not use the libraries. We
|
||||
concluded that weaker conditions might promote sharing better.
|
||||
|
||||
However, unrestricted linking of non-free programs would deprive the
|
||||
users of those programs of all benefit from the free status of the
|
||||
libraries themselves. This Library General Public License is intended to
|
||||
permit developers of non-free programs to use free libraries, while
|
||||
preserving your freedom as a user of such programs to change the free
|
||||
libraries that are incorporated in them. (We have not seen how to achieve
|
||||
this as regards changes in header files, but we have achieved it as regards
|
||||
changes in the actual functions of the Library.) The hope is that this
|
||||
will lead to faster development of free libraries.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, while the latter only
|
||||
works together with the library.
|
||||
|
||||
Note that it is possible for a library to be covered by the ordinary
|
||||
General Public License rather than by this special one.
|
||||
|
||||
GNU LIBRARY GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library which
|
||||
contains a notice placed by the copyright holder or other authorized
|
||||
party saying it may be distributed under the terms of this Library
|
||||
General Public License (also called "this License"). Each licensee is
|
||||
addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also compile or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
c) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
d) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the source code distributed need not include anything that is normally
|
||||
distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Library General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
@@ -2306,11 +2306,16 @@
|
||||
<None Include="$(MSBuildThisFileDirectory)Content\Tutorials\TutorialOutpost.sub">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)MonoKickstart_LICENSE">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)OpenALSoft_LICENSE">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)Submarines\Berilia.sub">
|
||||
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)Submarines\Dugong_Tutorial.sub">
|
||||
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)Submarines\TutorialOutpost.sub" />
|
||||
</ItemGroup>
|
||||
@@ -3448,7 +3453,6 @@
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)Submarines\Muikku.sub">
|
||||
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)Submarines\Orca.sub">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
|
||||
@@ -22,6 +22,11 @@ namespace Barotrauma
|
||||
|
||||
private float soundRange;
|
||||
private float sightRange;
|
||||
|
||||
/// <summary>
|
||||
/// How long does it take for the ai target to fade out if not kept alive.
|
||||
/// </summary>
|
||||
public float FadeOutTime { get; private set; } = 3;
|
||||
|
||||
public float SoundRange
|
||||
{
|
||||
@@ -121,6 +126,7 @@ namespace Barotrauma
|
||||
MinSoundRange = element.GetAttributeFloat("minsoundrange", SoundRange);
|
||||
MaxSightRange = element.GetAttributeFloat("maxsightrange", SightRange);
|
||||
MaxSoundRange = element.GetAttributeFloat("maxsoundrange", SoundRange);
|
||||
FadeOutTime = element.GetAttributeFloat("fadeouttime", FadeOutTime);
|
||||
SonarLabel = element.GetAttributeString("sonarlabel", "");
|
||||
string typeString = element.GetAttributeString("type", "Any");
|
||||
if (Enum.TryParse(typeString, out TargetType t))
|
||||
|
||||
@@ -435,7 +435,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (gap.Submarine != Character.Submarine) { continue; }
|
||||
if (gap.Open < 1 || gap.IsRoomToRoom) { continue; }
|
||||
var path = indoorSteering.PathFinder.FindPath(Character.SimPosition, gap.SimPosition);
|
||||
var path = indoorSteering.PathFinder.FindPath(Character.SimPosition, gap.SimPosition, Character.Submarine);
|
||||
if (!path.Unreachable)
|
||||
{
|
||||
if (escapePoint != Vector2.Zero)
|
||||
@@ -1182,7 +1182,7 @@ namespace Barotrauma
|
||||
}
|
||||
else if (target.Entity != null)
|
||||
{
|
||||
//skip the target if it's a room and the character is already inside a sub
|
||||
// Ignore the target if it's a room and the character is already inside a sub
|
||||
if (character.CurrentHull != null && target.Entity is Hull) { continue; }
|
||||
|
||||
Door door = null;
|
||||
@@ -1203,6 +1203,12 @@ namespace Barotrauma
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Ignore the target if it's a decoy and the character is already inside a sub
|
||||
if (character.CurrentHull != null && targetingTag == "decoy")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (target.Entity is Structure s)
|
||||
{
|
||||
|
||||
@@ -154,6 +154,7 @@ namespace Barotrauma
|
||||
|
||||
currentTarget = target;
|
||||
Vector2 pos = host.SimPosition;
|
||||
// TODO: remove this and handle differently?
|
||||
if (character != null && character.Submarine == null)
|
||||
{
|
||||
var targetHull = Hull.FindHull(FarseerPhysics.ConvertUnits.ToDisplayUnits(target), null, false);
|
||||
@@ -163,7 +164,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
var newPath = pathFinder.FindPath(pos, target, "(Character: " + character.Name + ")");
|
||||
var newPath = pathFinder.FindPath(pos, target, character.Submarine, "(Character: " + character.Name + ")");
|
||||
bool useNewPath = currentPath == null || needsNewPath;
|
||||
if (!useNewPath && currentPath != null && currentPath.CurrentNode != null && newPath.Nodes.Any() && !newPath.Unreachable)
|
||||
{
|
||||
@@ -448,7 +449,8 @@ namespace Barotrauma
|
||||
|
||||
private float? GetNodePenalty(PathNode node, PathNode nextNode)
|
||||
{
|
||||
if (character == null) { return 0.0f; }
|
||||
if (character == null) { return 0.0f; }
|
||||
if (nextNode.Waypoint.isObstructed) { return null; }
|
||||
float penalty = 0.0f;
|
||||
if (nextNode.Waypoint.ConnectedGap != null && nextNode.Waypoint.ConnectedGap.Open < 0.9f)
|
||||
{
|
||||
|
||||
@@ -215,11 +215,12 @@ namespace Barotrauma
|
||||
|
||||
protected virtual void OnCompleted()
|
||||
{
|
||||
if (Completed != null)
|
||||
{
|
||||
Completed();
|
||||
Completed = null;
|
||||
}
|
||||
Completed?.Invoke();
|
||||
//if (Completed != null)
|
||||
//{
|
||||
// Completed();
|
||||
// Completed = null;
|
||||
//}
|
||||
}
|
||||
|
||||
public virtual void Reset() { }
|
||||
|
||||
@@ -181,8 +181,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (closeEnough)
|
||||
{
|
||||
character.AIController.SteeringManager.Reset();
|
||||
character.AnimController.TargetDir = Target.WorldPosition.X > character.WorldPosition.X ? Direction.Right : Direction.Left;
|
||||
OnCompleted();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -204,11 +203,6 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isCompleted)
|
||||
{
|
||||
character.AIController.SteeringManager.Reset();
|
||||
character.AnimController.TargetDir = Target.WorldPosition.X > character.WorldPosition.X ? Direction.Right : Direction.Left;
|
||||
}
|
||||
return isCompleted;
|
||||
}
|
||||
|
||||
@@ -223,5 +217,15 @@ namespace Barotrauma
|
||||
float interactionDistance = Target is Item i ? i.InteractDistance * 0.9f : 0;
|
||||
CloseEnough = Math.Max(interactionDistance, CloseEnough);
|
||||
}
|
||||
|
||||
protected override void OnCompleted()
|
||||
{
|
||||
character.AIController.SteeringManager.Reset();
|
||||
if (Target != null)
|
||||
{
|
||||
character.AnimController.TargetDir = Target.WorldPosition.X > character.WorldPosition.X ? Direction.Right : Direction.Left;
|
||||
}
|
||||
base.OnCompleted();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,7 +156,7 @@ namespace Barotrauma
|
||||
bool isRoomNameFound = currentTarget.DisplayName != null;
|
||||
errorMsg = "(Character " + character.Name + " idling, target " + (isRoomNameFound ? currentTarget.DisplayName : currentTarget.ToString()) + ")";
|
||||
#endif
|
||||
var path = PathSteering.PathFinder.FindPath(character.SimPosition, currentTarget.SimPosition, errorMsg);
|
||||
var path = PathSteering.PathFinder.FindPath(character.SimPosition, currentTarget.SimPosition, errorMsgStr: errorMsg);
|
||||
PathSteering.SetPath(path);
|
||||
}
|
||||
|
||||
|
||||
@@ -173,7 +173,7 @@ namespace Barotrauma
|
||||
|
||||
if (targetCharacterName == null) targetCharacterName = "";
|
||||
if (targetRoomName == null) targetRoomName = "";
|
||||
string msg = TextManager.GetWithVariables(messageTag, new string[2] { "[name]", "[roomname]" }, new string[2] { targetCharacterName, targetRoomName }, new bool[2] { false, true });
|
||||
string msg = TextManager.GetWithVariables(messageTag, new string[2] { "[name]", "[roomname]" }, new string[2] { targetCharacterName, targetRoomName }, new bool[2] { false, true }, true);
|
||||
if (msg == null) return "";
|
||||
|
||||
return msg;
|
||||
|
||||
@@ -157,13 +157,18 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public SteeringPath FindPath(Vector2 start, Vector2 end, string errorMsgStr = null)
|
||||
public SteeringPath FindPath(Vector2 start, Vector2 end, Submarine hostSub = null, string errorMsgStr = null)
|
||||
{
|
||||
float closestDist = 0.0f;
|
||||
PathNode startNode = null;
|
||||
foreach (PathNode node in nodes)
|
||||
{
|
||||
Vector2 nodePos = node.Position;
|
||||
if (hostSub != null)
|
||||
{
|
||||
Vector2 diff = hostSub.SimPosition - node.Waypoint.Submarine.SimPosition;
|
||||
nodePos -= diff;
|
||||
}
|
||||
|
||||
float xDiff = Math.Abs(start.X - nodePos.X);
|
||||
float yDiff = Math.Abs(start.Y - nodePos.Y);
|
||||
@@ -185,7 +190,7 @@ namespace Barotrauma
|
||||
if (insideSubmarine)
|
||||
{
|
||||
var body = Submarine.PickBody(
|
||||
start, node.Waypoint.SimPosition, null,
|
||||
start, nodePos, null,
|
||||
Physics.CollisionWall | Physics.CollisionLevel | Physics.CollisionStairs);
|
||||
|
||||
if (body != null)
|
||||
@@ -215,7 +220,11 @@ namespace Barotrauma
|
||||
foreach (PathNode node in nodes)
|
||||
{
|
||||
Vector2 nodePos = node.Position;
|
||||
|
||||
if (hostSub != null)
|
||||
{
|
||||
Vector2 diff = hostSub.SimPosition - node.Waypoint.Submarine.SimPosition;
|
||||
nodePos -= diff;
|
||||
}
|
||||
float dist = Vector2.DistanceSquared(end, nodePos);
|
||||
if (insideSubmarine)
|
||||
{
|
||||
@@ -229,7 +238,7 @@ namespace Barotrauma
|
||||
//if searching for a path inside the sub, make sure the waypoint is visible
|
||||
if (insideSubmarine)
|
||||
{
|
||||
var body = Submarine.PickBody(end, node.Waypoint.SimPosition, null,
|
||||
var body = Submarine.PickBody(end, nodePos, null,
|
||||
Physics.CollisionWall | Physics.CollisionLevel | Physics.CollisionStairs );
|
||||
|
||||
if (body != null)
|
||||
@@ -237,7 +246,6 @@ namespace Barotrauma
|
||||
//if (body.UserData is Submarine) continue;
|
||||
if (body.UserData is Structure && !((Structure)body.UserData).IsPlatform) continue;
|
||||
if (body.UserData is Item && body.FixtureList[0].CollisionCategories.HasFlag(Physics.CollisionWall)) continue;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2030,6 +2030,11 @@ namespace Barotrauma
|
||||
|
||||
//Do ragdoll shenanigans before Stun because it's still technically a stun, innit? Less network updates for us!
|
||||
bool allowRagdoll = GameMain.NetworkMember != null ? GameMain.NetworkMember.ServerSettings.AllowRagdollButton : true;
|
||||
bool tooFastToUnragdoll = AnimController.Collider.LinearVelocity.LengthSquared() > 1f;
|
||||
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient)
|
||||
{
|
||||
tooFastToUnragdoll = false;
|
||||
}
|
||||
if (IsForceRagdolled)
|
||||
{
|
||||
IsRagdolled = IsForceRagdolled;
|
||||
@@ -2039,7 +2044,7 @@ namespace Barotrauma
|
||||
IsRagdolled = IsKeyDown(InputType.Ragdoll);
|
||||
}
|
||||
//Keep us ragdolled if we were forced or we're too speedy to unragdoll
|
||||
else if (allowRagdoll && (!IsRagdolled || AnimController.Collider.LinearVelocity.LengthSquared() < 1f))
|
||||
else if (allowRagdoll && (!IsRagdolled || !tooFastToUnragdoll))
|
||||
{
|
||||
if (ragdollingLockTimer > 0.0f)
|
||||
{
|
||||
@@ -2589,7 +2594,7 @@ namespace Barotrauma
|
||||
if (info != null) { info.Remove(); }
|
||||
|
||||
#if CLIENT
|
||||
GameMain.GameSession?.CrewManager?.RemoveCharacter(this);
|
||||
GameMain.GameSession?.CrewManager?.KillCharacter(this);
|
||||
#endif
|
||||
|
||||
CharacterList.Remove(this);
|
||||
|
||||
@@ -89,6 +89,14 @@ namespace Barotrauma
|
||||
|
||||
public static void StopCoroutines(string name)
|
||||
{
|
||||
Coroutines.ForEach(c =>
|
||||
{
|
||||
if (c.Name == name)
|
||||
{
|
||||
c.Thread?.Abort();
|
||||
c.Thread?.Join();
|
||||
}
|
||||
});
|
||||
Coroutines.RemoveAll(c => c.Name == name);
|
||||
}
|
||||
|
||||
@@ -99,31 +107,42 @@ namespace Barotrauma
|
||||
|
||||
public static void ExecuteCoroutineThread(CoroutineHandle handle)
|
||||
{
|
||||
while (true)
|
||||
try
|
||||
{
|
||||
if (handle.Coroutine.Current != null)
|
||||
while (true)
|
||||
{
|
||||
WaitForSeconds wfs = handle.Coroutine.Current as WaitForSeconds;
|
||||
if (wfs != null)
|
||||
if (handle.Coroutine.Current != null)
|
||||
{
|
||||
Thread.Sleep((int)(wfs.TotalTime * 1000));
|
||||
}
|
||||
else
|
||||
{
|
||||
switch ((CoroutineStatus)handle.Coroutine.Current)
|
||||
WaitForSeconds wfs = handle.Coroutine.Current as WaitForSeconds;
|
||||
if (wfs != null)
|
||||
{
|
||||
case CoroutineStatus.Success:
|
||||
return;
|
||||
Thread.Sleep((int)(wfs.TotalTime * 1000));
|
||||
}
|
||||
else
|
||||
{
|
||||
switch ((CoroutineStatus)handle.Coroutine.Current)
|
||||
{
|
||||
case CoroutineStatus.Success:
|
||||
return;
|
||||
|
||||
case CoroutineStatus.Failure:
|
||||
DebugConsole.ThrowError("Coroutine \"" + handle.Name + "\" has failed");
|
||||
return;
|
||||
case CoroutineStatus.Failure:
|
||||
DebugConsole.ThrowError("Coroutine \"" + handle.Name + "\" has failed");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Thread.Yield();
|
||||
if (!handle.Coroutine.MoveNext()) return;
|
||||
Thread.Yield();
|
||||
if (!handle.Coroutine.MoveNext()) return;
|
||||
}
|
||||
}
|
||||
catch (ThreadAbortException tae)
|
||||
{
|
||||
//not an error, don't worry about it
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DebugConsole.ThrowError("Coroutine \"" + handle.Name + "\" has thrown an exception", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -112,6 +112,7 @@ namespace Barotrauma
|
||||
List<Vector2> positions = new List<Vector2>();
|
||||
foreach (var allowedPosition in availablePositions)
|
||||
{
|
||||
if (Level.Loaded.ExtraWalls.Any(w => w.Cells.Any(c => c.IsPointInside(allowedPosition.Position.ToVector2())))) { continue; }
|
||||
positions.Add(allowedPosition.Position.ToVector2());
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace Barotrauma
|
||||
public float GetAverageElapsedMillisecs(string identifier)
|
||||
{
|
||||
if (!avgTicksPerFrame.ContainsKey(identifier)) return 0.0f;
|
||||
return avgTicksPerFrame[identifier] / TimeSpan.TicksPerMillisecond;
|
||||
return avgTicksPerFrame[identifier] / (float)TimeSpan.TicksPerMillisecond;
|
||||
}
|
||||
|
||||
public bool Update(double deltaTime)
|
||||
|
||||
@@ -98,7 +98,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (item.GetComponent<Items.Components.Repairable>() != null)
|
||||
{
|
||||
item.Condition = item.Health;
|
||||
item.Condition = item.Prefab.Health;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -176,7 +176,16 @@ namespace Barotrauma
|
||||
Level.Loaded.Seed + (outpost == Level.Loaded.StartOutpost ? "start" : "end"));
|
||||
InitializeWatchman(spawnedCharacter);
|
||||
var objectiveManager = (spawnedCharacter.AIController as HumanAIController)?.ObjectiveManager;
|
||||
objectiveManager?.SetOrder(new AIObjectiveGoTo(watchmanSpawnpoint, spawnedCharacter, objectiveManager, repeat: true, getDivingGearIfNeeded: false));
|
||||
if (objectiveManager != null)
|
||||
{
|
||||
var moveOrder = new AIObjectiveGoTo(watchmanSpawnpoint, spawnedCharacter, objectiveManager, repeat: true, getDivingGearIfNeeded: false);
|
||||
moveOrder.Completed += () =>
|
||||
{
|
||||
// Turn towards the center of the sub. Doesn't work in all possible cases, but this is the simplest solution for now.
|
||||
spawnedCharacter.AnimController.TargetDir = spawnedCharacter.Submarine.WorldPosition.X > spawnedCharacter.WorldPosition.X ? Direction.Right : Direction.Left;
|
||||
};
|
||||
objectiveManager.SetOrder(moveOrder);
|
||||
}
|
||||
if (watchmanJob != null)
|
||||
{
|
||||
spawnedCharacter.GiveJobItems();
|
||||
|
||||
@@ -241,6 +241,14 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var sub in Submarine.Loaded)
|
||||
{
|
||||
if (sub.IsOutpost)
|
||||
{
|
||||
sub.DisableObstructedWayPoints();
|
||||
}
|
||||
}
|
||||
|
||||
Entity.Spawner = new EntitySpawner();
|
||||
|
||||
if (GameMode.Mission != null) Mission = GameMode.Mission;
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
public partial class GameSettings
|
||||
{
|
||||
{
|
||||
const string savePath = "config.xml";
|
||||
const string playerSavePath = "config_player.xml";
|
||||
const string vanillaContentPackagePath = "Data/ContentPackages/Vanilla";
|
||||
@@ -43,9 +43,9 @@ namespace Barotrauma
|
||||
public bool SpecularityEnabled { get; set; }
|
||||
public bool ChromaticAberrationEnabled { get; set; }
|
||||
|
||||
public bool PauseOnFocusLost { get; set; } = true;
|
||||
public bool PauseOnFocusLost { get; set; }
|
||||
public bool MuteOnFocusLost { get; set; }
|
||||
public bool UseDirectionalVoiceChat { get; set; } = true;
|
||||
public bool UseDirectionalVoiceChat { get; set; }
|
||||
|
||||
public enum VoiceMode
|
||||
{
|
||||
@@ -57,7 +57,7 @@ namespace Barotrauma
|
||||
public VoiceMode VoiceSetting { get; set; }
|
||||
public string VoiceCaptureDevice { get; set; }
|
||||
|
||||
public float NoiseGateThreshold { get; set; } = -45;
|
||||
public float NoiseGateThreshold { get; set; }
|
||||
|
||||
private KeyOrMouse[] keyMapping;
|
||||
|
||||
@@ -69,12 +69,7 @@ namespace Barotrauma
|
||||
|
||||
private bool useSteamMatchmaking;
|
||||
private bool requireSteamAuthentication;
|
||||
|
||||
public string QuickStartSubmarineName
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public string QuickStartSubmarineName;
|
||||
|
||||
#if DEBUG
|
||||
//steam functionality can be enabled/disabled in debug builds
|
||||
@@ -126,7 +121,7 @@ namespace Barotrauma
|
||||
set { jobPreferences = value; }
|
||||
}
|
||||
|
||||
public int CharacterHeadIndex { get; set; } = 1;
|
||||
public int CharacterHeadIndex { get; set; }
|
||||
public int CharacterHairIndex { get; set; }
|
||||
public int CharacterBeardIndex { get; set; }
|
||||
public int CharacterMoustacheIndex { get; set; }
|
||||
@@ -160,7 +155,6 @@ namespace Barotrauma
|
||||
#if CLIENT
|
||||
if (applyButton != null)
|
||||
{
|
||||
//applyButton.Selected = unsavedSettings;
|
||||
applyButton.Enabled = unsavedSettings;
|
||||
applyButton.Text = TextManager.Get(unsavedSettings ? "ApplySettingsButtonUnsavedChanges" : "ApplySettingsButton");
|
||||
}
|
||||
@@ -168,7 +162,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private float soundVolume = 0.5f, musicVolume = 0.3f, voiceChatVolume = 0.5f, microphoneVolume = 1.0f;
|
||||
private float soundVolume, musicVolume, voiceChatVolume, microphoneVolume;
|
||||
|
||||
public float SoundVolume
|
||||
{
|
||||
@@ -229,9 +223,9 @@ namespace Barotrauma
|
||||
|
||||
private HashSet<string> selectedContentPackagePaths = new HashSet<string>();
|
||||
|
||||
public string MasterServerUrl { get; set; }
|
||||
public bool AutoCheckUpdates { get; set; }
|
||||
public bool WasGameUpdated { get; set; }
|
||||
public string MasterServerUrl { get; set; }
|
||||
public bool AutoCheckUpdates { get; set; }
|
||||
public bool WasGameUpdated { get; set; }
|
||||
|
||||
private string defaultPlayerName;
|
||||
public string DefaultPlayerName
|
||||
@@ -256,9 +250,9 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
private const float MinHUDScale = 0.75f, MaxHUDScale = 1.25f;
|
||||
public static float HUDScale { get; set; } = 1.0f;
|
||||
public static float HUDScale { get; set; }
|
||||
private const float MinInventoryScale = 0.75f, MaxInventoryScale = 1.25f;
|
||||
public static float InventoryScale { get; set; } = 1.0f;
|
||||
public static float InventoryScale { get; set; }
|
||||
|
||||
public List<string> CompletedTutorialNames { get; private set; }
|
||||
|
||||
@@ -267,7 +261,7 @@ namespace Barotrauma
|
||||
|
||||
public bool CampaignDisclaimerShown, EditorDisclaimerShown;
|
||||
|
||||
private static bool sendUserStatistics;
|
||||
private static bool sendUserStatistics = true;
|
||||
public static bool SendUserStatistics
|
||||
{
|
||||
get { return sendUserStatistics; }
|
||||
@@ -353,13 +347,7 @@ namespace Barotrauma
|
||||
}
|
||||
if (doc != null)
|
||||
{
|
||||
foreach (XElement subElement in doc.Root.Elements())
|
||||
{
|
||||
if (subElement.Name.ToString().ToLowerInvariant() == "keymapping")
|
||||
{
|
||||
LoadKeyBinds(subElement);
|
||||
}
|
||||
}
|
||||
LoadControls(doc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -415,35 +403,15 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
#region Load DefaultConfig
|
||||
private void LoadDefaultConfig(bool setLanguage = true)
|
||||
{
|
||||
XDocument doc = XMLExtensions.TryLoadXml(savePath);
|
||||
|
||||
if (setLanguage || string.IsNullOrEmpty(Language))
|
||||
{
|
||||
Language = doc.Root.GetAttributeString("language", "English");
|
||||
}
|
||||
|
||||
MasterServerUrl = doc.Root.GetAttributeString("masterserverurl", "");
|
||||
|
||||
AutoCheckUpdates = doc.Root.GetAttributeBool("autocheckupdates", true);
|
||||
WasGameUpdated = doc.Root.GetAttributeBool("wasgameupdated", false);
|
||||
|
||||
VerboseLogging = doc.Root.GetAttributeBool("verboselogging", false);
|
||||
SaveDebugConsoleLogs = doc.Root.GetAttributeBool("savedebugconsolelogs", false);
|
||||
|
||||
QuickStartSubmarineName = doc.Root.GetAttributeString("quickstartsub", "");
|
||||
|
||||
if (doc == null)
|
||||
{
|
||||
GraphicsWidth = 1024;
|
||||
GraphicsHeight = 678;
|
||||
|
||||
GraphicsHeight = 768;
|
||||
MasterServerUrl = "";
|
||||
|
||||
SelectedContentPackages.Add(ContentPackage.List.Any() ? ContentPackage.List[0] : new ContentPackage(""));
|
||||
|
||||
jobPreferences = new List<string>();
|
||||
foreach (JobPrefab job in JobPrefab.List)
|
||||
{
|
||||
@@ -452,158 +420,24 @@ namespace Barotrauma
|
||||
return;
|
||||
}
|
||||
|
||||
XElement graphicsMode = doc.Root.Element("graphicsmode");
|
||||
GraphicsWidth = 0;
|
||||
GraphicsHeight = 0;
|
||||
VSyncEnabled = graphicsMode.GetAttributeBool("vsync", true);
|
||||
|
||||
XElement graphicsSettings = doc.Root.Element("graphicssettings");
|
||||
ParticleLimit = graphicsSettings.GetAttributeInt("particlelimit", 1500);
|
||||
LightMapScale = MathHelper.Clamp(graphicsSettings.GetAttributeFloat("lightmapscale", 0.5f), 0.1f, 1.0f);
|
||||
SpecularityEnabled = graphicsSettings.GetAttributeBool("specularity", true);
|
||||
ChromaticAberrationEnabled = graphicsSettings.GetAttributeBool("chromaticaberration", true);
|
||||
HUDScale = graphicsSettings.GetAttributeFloat("hudscale", 1.0f);
|
||||
InventoryScale = graphicsSettings.GetAttributeFloat("inventoryscale", 1.0f);
|
||||
var losModeStr = graphicsSettings.GetAttributeString("losmode", "Transparent");
|
||||
if (!Enum.TryParse(losModeStr, out losMode))
|
||||
{
|
||||
losMode = LosMode.Transparent;
|
||||
}
|
||||
|
||||
#if CLIENT
|
||||
if (GraphicsWidth == 0 || GraphicsHeight == 0)
|
||||
{
|
||||
GraphicsWidth = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width;
|
||||
GraphicsHeight = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height;
|
||||
}
|
||||
#endif
|
||||
|
||||
var windowModeStr = graphicsMode.GetAttributeString("displaymode", "Fullscreen");
|
||||
if (!Enum.TryParse(windowModeStr, out WindowMode wm))
|
||||
{
|
||||
wm = WindowMode.Fullscreen;
|
||||
}
|
||||
WindowMode = wm;
|
||||
|
||||
useSteamMatchmaking = doc.Root.GetAttributeBool("usesteammatchmaking", true);
|
||||
requireSteamAuthentication = doc.Root.GetAttributeBool("requiresteamauthentication", true);
|
||||
AutoUpdateWorkshopItems = doc.Root.GetAttributeBool("autoupdateworkshopitems", true);
|
||||
|
||||
#if DEBUG
|
||||
EnableSplashScreen = false;
|
||||
#else
|
||||
EnableSplashScreen = doc.Root.GetAttributeBool("enablesplashscreen", true);
|
||||
#endif
|
||||
|
||||
AimAssistAmount = doc.Root.GetAttributeFloat("aimassistamount", 0.5f);
|
||||
|
||||
bool resetLanguage = setLanguage || string.IsNullOrEmpty(Language);
|
||||
SetDefaultValues(resetLanguage);
|
||||
SetDefaultBindings(doc, legacy: false);
|
||||
|
||||
foreach (XElement subElement in doc.Root.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
case "keymapping":
|
||||
LoadKeyBinds(subElement);
|
||||
break;
|
||||
case "gameplay":
|
||||
jobPreferences = new List<string>();
|
||||
foreach (XElement ele in subElement.Element("jobpreferences").Elements("job"))
|
||||
{
|
||||
string jobIdentifier = ele.GetAttributeString("identifier", "");
|
||||
if (string.IsNullOrEmpty(jobIdentifier)) continue;
|
||||
jobPreferences.Add(jobIdentifier);
|
||||
}
|
||||
break;
|
||||
case "player":
|
||||
defaultPlayerName = subElement.GetAttributeString("name", "");
|
||||
CharacterHeadIndex = subElement.GetAttributeInt("headindex", CharacterHeadIndex);
|
||||
if (Enum.TryParse(subElement.GetAttributeString("gender", "none"), true, out Gender g))
|
||||
{
|
||||
CharacterGender = g;
|
||||
}
|
||||
if (Enum.TryParse(subElement.GetAttributeString("race", "white"), true, out Race r))
|
||||
{
|
||||
CharacterRace = r;
|
||||
}
|
||||
else
|
||||
{
|
||||
CharacterRace = Race.White;
|
||||
}
|
||||
CharacterHairIndex = subElement.GetAttributeInt("hairindex", -1);
|
||||
CharacterBeardIndex = subElement.GetAttributeInt("beardindex", -1);
|
||||
CharacterMoustacheIndex = subElement.GetAttributeInt("moustacheindex", -1);
|
||||
CharacterFaceAttachmentIndex = subElement.GetAttributeInt("faceattachmentindex", -1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
MasterServerUrl = doc.Root.GetAttributeString("masterserverurl", MasterServerUrl);
|
||||
WasGameUpdated = doc.Root.GetAttributeBool("wasgameupdated", WasGameUpdated);
|
||||
VerboseLogging = doc.Root.GetAttributeBool("verboselogging", VerboseLogging);
|
||||
SaveDebugConsoleLogs = doc.Root.GetAttributeBool("savedebugconsolelogs", SaveDebugConsoleLogs);
|
||||
AutoUpdateWorkshopItems = doc.Root.GetAttributeBool("autoupdateworkshopitems", AutoUpdateWorkshopItems);
|
||||
|
||||
List<string> missingPackagePaths = new List<string>();
|
||||
List<ContentPackage> incompatiblePackages = new List<ContentPackage>();
|
||||
foreach (XElement subElement in doc.Root.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
case "contentpackage":
|
||||
string path = System.IO.Path.GetFullPath(subElement.GetAttributeString("path", ""));
|
||||
var matchingContentPackage = ContentPackage.List.Find(cp => System.IO.Path.GetFullPath(cp.Path) == path);
|
||||
if (matchingContentPackage == null)
|
||||
{
|
||||
missingPackagePaths.Add(path);
|
||||
}
|
||||
else if (!matchingContentPackage.IsCompatible())
|
||||
{
|
||||
incompatiblePackages.Add(matchingContentPackage);
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectedContentPackages.Add(matchingContentPackage);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TextManager.LoadTextPacks(SelectedContentPackages);
|
||||
|
||||
//display error messages after all content packages have been loaded
|
||||
//to make sure the package that contains text files has been loaded before we attempt to use TextManager
|
||||
foreach (string missingPackagePath in missingPackagePaths)
|
||||
{
|
||||
DebugConsole.ThrowError(TextManager.GetWithVariable("ContentPackageNotFound", "[packagepath]", missingPackagePath));
|
||||
}
|
||||
foreach (ContentPackage incompatiblePackage in incompatiblePackages)
|
||||
{
|
||||
DebugConsole.ThrowError(TextManager.GetWithVariables(incompatiblePackage.GameVersion <= new Version(0, 0, 0, 0) ? "IncompatibleContentPackageUnknownVersion" : "IncompatibleContentPackage",
|
||||
new string[3] { "[packagename]", "[packageversion]", "[gameversion]" }, new string[3] { incompatiblePackage.Name, incompatiblePackage.GameVersion.ToString(), GameMain.Version.ToString() }));
|
||||
}
|
||||
foreach (ContentPackage contentPackage in SelectedContentPackages)
|
||||
{
|
||||
bool packageOk = contentPackage.VerifyFiles(out List<string> errorMessages);
|
||||
if (!packageOk)
|
||||
{
|
||||
DebugConsole.ThrowError("Error in content package \"" + contentPackage.Name + "\":\n" + string.Join("\n", errorMessages));
|
||||
continue;
|
||||
}
|
||||
foreach (ContentFile file in contentPackage.Files)
|
||||
{
|
||||
ToolBox.IsProperFilenameCase(file.Path);
|
||||
}
|
||||
}
|
||||
if (!SelectedContentPackages.Any())
|
||||
{
|
||||
var availablePackage = ContentPackage.List.FirstOrDefault(cp => cp.IsCompatible() && cp.CorePackage);
|
||||
if (availablePackage != null)
|
||||
{
|
||||
SelectedContentPackages.Add(availablePackage);
|
||||
}
|
||||
}
|
||||
|
||||
//save to get rid of the invalid selected packages in the config file
|
||||
if (missingPackagePaths.Count > 0 || incompatiblePackages.Count > 0) { SaveNewPlayerConfig(); }
|
||||
LoadGeneralSettings(doc, resetLanguage);
|
||||
LoadGraphicSettings(doc);
|
||||
LoadAudioSettings(doc);
|
||||
LoadControls(doc);
|
||||
LoadContentPackages(doc);
|
||||
UnsavedSettings = false;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Save DefaultConfig
|
||||
private void SaveNewDefaultConfig()
|
||||
{
|
||||
XDocument doc = new XDocument();
|
||||
@@ -619,6 +453,7 @@ namespace Barotrauma
|
||||
new XAttribute("autocheckupdates", AutoCheckUpdates),
|
||||
new XAttribute("musicvolume", musicVolume),
|
||||
new XAttribute("soundvolume", soundVolume),
|
||||
new XAttribute("microphonevolume", microphoneVolume),
|
||||
new XAttribute("voicechatvolume", voiceChatVolume),
|
||||
new XAttribute("verboselogging", VerboseLogging),
|
||||
new XAttribute("savedebugconsolelogs", SaveDebugConsoleLogs),
|
||||
@@ -637,7 +472,7 @@ namespace Barotrauma
|
||||
{
|
||||
doc.Root.Add(new XAttribute("wasgameupdated", true));
|
||||
}
|
||||
|
||||
|
||||
XElement gMode = doc.Root.Element("graphicsmode");
|
||||
if (gMode == null)
|
||||
{
|
||||
@@ -738,7 +573,6 @@ namespace Barotrauma
|
||||
"Saving game settings failed.\n" + e.Message + "\n" + e.StackTrace);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Load PlayerConfig
|
||||
public void LoadPlayerConfig()
|
||||
@@ -760,143 +594,27 @@ namespace Barotrauma
|
||||
private bool LoadPlayerConfigInternal()
|
||||
{
|
||||
XDocument doc = XMLExtensions.LoadXml(playerSavePath);
|
||||
|
||||
if (doc == null || doc.Root == null)
|
||||
{
|
||||
ShowUserStatisticsPrompt = true;
|
||||
return false;
|
||||
}
|
||||
LoadGeneralSettings(doc);
|
||||
LoadGraphicSettings(doc);
|
||||
LoadAudioSettings(doc);
|
||||
LoadControls(doc);
|
||||
LoadContentPackages(doc);
|
||||
|
||||
Language = doc.Root.GetAttributeString("language", Language);
|
||||
AutoCheckUpdates = doc.Root.GetAttributeBool("autocheckupdates", AutoCheckUpdates);
|
||||
sendUserStatistics = doc.Root.GetAttributeBool("senduserstatistics", true);
|
||||
|
||||
XElement graphicsMode = doc.Root.Element("graphicsmode");
|
||||
GraphicsWidth = graphicsMode.GetAttributeInt("width", GraphicsWidth);
|
||||
GraphicsHeight = graphicsMode.GetAttributeInt("height", GraphicsHeight);
|
||||
VSyncEnabled = graphicsMode.GetAttributeBool("vsync", VSyncEnabled);
|
||||
|
||||
XElement graphicsSettings = doc.Root.Element("graphicssettings");
|
||||
ParticleLimit = graphicsSettings.GetAttributeInt("particlelimit", ParticleLimit);
|
||||
LightMapScale = MathHelper.Clamp(graphicsSettings.GetAttributeFloat("lightmapscale", LightMapScale), 0.1f, 1.0f);
|
||||
SpecularityEnabled = graphicsSettings.GetAttributeBool("specularity", SpecularityEnabled);
|
||||
ChromaticAberrationEnabled = graphicsSettings.GetAttributeBool("chromaticaberration", ChromaticAberrationEnabled);
|
||||
HUDScale = graphicsSettings.GetAttributeFloat("hudscale", HUDScale);
|
||||
InventoryScale = graphicsSettings.GetAttributeFloat("inventoryscale", InventoryScale);
|
||||
var losModeStr = graphicsSettings.GetAttributeString("losmode", "Transparent");
|
||||
if (!Enum.TryParse(losModeStr, out losMode))
|
||||
XElement tutorialsElement = doc.Root.Element("tutorials");
|
||||
if (tutorialsElement != null)
|
||||
{
|
||||
losMode = LosMode.Transparent;
|
||||
}
|
||||
|
||||
#if CLIENT
|
||||
if (GraphicsWidth == 0 || GraphicsHeight == 0)
|
||||
{
|
||||
GraphicsWidth = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width;
|
||||
GraphicsHeight = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height;
|
||||
}
|
||||
#endif
|
||||
|
||||
var windowModeStr = graphicsMode.GetAttributeString("displaymode", "Fullscreen");
|
||||
if (!Enum.TryParse(windowModeStr, out windowMode))
|
||||
{
|
||||
windowMode = WindowMode.Fullscreen;
|
||||
}
|
||||
|
||||
XElement audioSettings = doc.Root.Element("audio");
|
||||
if (audioSettings != null)
|
||||
{
|
||||
SoundVolume = audioSettings.GetAttributeFloat("soundvolume", SoundVolume);
|
||||
MusicVolume = audioSettings.GetAttributeFloat("musicvolume", MusicVolume);
|
||||
VoiceChatVolume = audioSettings.GetAttributeFloat("voicechatvolume", VoiceChatVolume);
|
||||
MuteOnFocusLost = audioSettings.GetAttributeBool("muteonfocuslost", false);
|
||||
UseDirectionalVoiceChat = audioSettings.GetAttributeBool("usedirectionalvoicechat", true);
|
||||
string voiceSettingStr = audioSettings.GetAttributeString("voicesetting", "Disabled");
|
||||
VoiceCaptureDevice = audioSettings.GetAttributeString("voicecapturedevice", "");
|
||||
NoiseGateThreshold = audioSettings.GetAttributeFloat("noisegatethreshold", -45);
|
||||
var voiceSetting = VoiceMode.Disabled;
|
||||
if (Enum.TryParse(voiceSettingStr, out voiceSetting))
|
||||
foreach (XElement element in tutorialsElement.Elements())
|
||||
{
|
||||
VoiceSetting = voiceSetting;
|
||||
}
|
||||
}
|
||||
|
||||
useSteamMatchmaking = doc.Root.GetAttributeBool("usesteammatchmaking", useSteamMatchmaking);
|
||||
requireSteamAuthentication = doc.Root.GetAttributeBool("requiresteamauthentication", requireSteamAuthentication);
|
||||
|
||||
EnableSplashScreen = doc.Root.GetAttributeBool("enablesplashscreen", EnableSplashScreen);
|
||||
|
||||
PauseOnFocusLost = doc.Root.GetAttributeBool("pauseonfocuslost", PauseOnFocusLost);
|
||||
AimAssistAmount = doc.Root.GetAttributeFloat("aimassistamount", AimAssistAmount);
|
||||
EnableMouseLook = doc.Root.GetAttributeBool("enablemouselook", EnableMouseLook);
|
||||
|
||||
CrewMenuOpen = doc.Root.GetAttributeBool("crewmenuopen", CrewMenuOpen);
|
||||
ChatOpen = doc.Root.GetAttributeBool("chatopen", ChatOpen);
|
||||
|
||||
CampaignDisclaimerShown = doc.Root.GetAttributeBool("campaigndisclaimershown", false);
|
||||
EditorDisclaimerShown = doc.Root.GetAttributeBool("editordisclaimershown", false);
|
||||
|
||||
foreach (XElement subElement in doc.Root.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
case "keymapping":
|
||||
LoadKeyBinds(subElement);
|
||||
break;
|
||||
case "gameplay":
|
||||
jobPreferences = new List<string>();
|
||||
foreach (XElement ele in subElement.Element("jobpreferences").Elements("job"))
|
||||
{
|
||||
string jobIdentifier = ele.GetAttributeString("identifier", "");
|
||||
if (string.IsNullOrEmpty(jobIdentifier)) continue;
|
||||
jobPreferences.Add(jobIdentifier);
|
||||
}
|
||||
break;
|
||||
case "player":
|
||||
defaultPlayerName = subElement.GetAttributeString("name", defaultPlayerName);
|
||||
CharacterHeadIndex = subElement.GetAttributeInt("headindex", CharacterHeadIndex);
|
||||
if (Enum.TryParse(subElement.GetAttributeString("gender", "none"), true, out Gender g))
|
||||
{
|
||||
CharacterGender = g;
|
||||
}
|
||||
if (Enum.TryParse(subElement.GetAttributeString("race", "white"), true, out Race r))
|
||||
{
|
||||
CharacterRace = r;
|
||||
}
|
||||
else
|
||||
{
|
||||
CharacterRace = Race.White;
|
||||
}
|
||||
CharacterHairIndex = subElement.GetAttributeInt("hairindex", CharacterHairIndex);
|
||||
CharacterBeardIndex = subElement.GetAttributeInt("beardindex", CharacterBeardIndex);
|
||||
CharacterMoustacheIndex = subElement.GetAttributeInt("moustacheindex", CharacterMoustacheIndex);
|
||||
CharacterFaceAttachmentIndex = subElement.GetAttributeInt("faceattachmentindex", CharacterFaceAttachmentIndex);
|
||||
break;
|
||||
case "tutorials":
|
||||
foreach (XElement tutorialElement in subElement.Elements())
|
||||
{
|
||||
CompletedTutorialNames.Add(tutorialElement.GetAttributeString("name", ""));
|
||||
}
|
||||
break;
|
||||
CompletedTutorialNames.Add(element.GetAttributeString("name", ""));
|
||||
}
|
||||
}
|
||||
|
||||
UnsavedSettings = false;
|
||||
|
||||
selectedContentPackagePaths = new HashSet<string>();
|
||||
|
||||
foreach (XElement subElement in doc.Root.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
case "contentpackage":
|
||||
string path = System.IO.Path.GetFullPath(subElement.GetAttributeString("path", ""));
|
||||
selectedContentPackagePaths.Add(path);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
LoadContentPackages(selectedContentPackagePaths);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -957,7 +675,7 @@ namespace Barotrauma
|
||||
}
|
||||
foreach (ContentPackage incompatiblePackage in incompatiblePackages)
|
||||
{
|
||||
DebugConsole.ThrowError(TextManager.GetWithVariables(incompatiblePackage.GameVersion <= new Version(0, 0, 0, 0) ? "IncompatibleContentPackageUnknownVersion" : "IncompatibleContentPackage",
|
||||
DebugConsole.ThrowError(TextManager.GetWithVariables(incompatiblePackage.GameVersion <= new Version(0, 0, 0, 0) ? "IncompatibleContentPackageUnknownVersion" : "IncompatibleContentPackage",
|
||||
new string[3] { "[packagename]", "[packageversion]", "[gameversion]" }, new string[3] { incompatiblePackage.Name, incompatiblePackage.GameVersion.ToString(), GameMain.Version.ToString() }));
|
||||
}
|
||||
}
|
||||
@@ -1038,7 +756,7 @@ namespace Barotrauma
|
||||
new XAttribute("vsync", VSyncEnabled),
|
||||
new XAttribute("displaymode", windowMode));
|
||||
}
|
||||
|
||||
|
||||
XElement audio = doc.Root.Element("audio");
|
||||
if (audio == null)
|
||||
{
|
||||
@@ -1048,6 +766,8 @@ namespace Barotrauma
|
||||
audio.ReplaceAttributes(
|
||||
new XAttribute("musicvolume", musicVolume),
|
||||
new XAttribute("soundvolume", soundVolume),
|
||||
new XAttribute("voicechatvolume", voiceChatVolume),
|
||||
new XAttribute("microphonevolume", microphoneVolume),
|
||||
new XAttribute("muteonfocuslost", MuteOnFocusLost),
|
||||
new XAttribute("usedirectionalvoicechat", UseDirectionalVoiceChat),
|
||||
new XAttribute("voicesetting", VoiceSetting),
|
||||
@@ -1153,12 +873,149 @@ namespace Barotrauma
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Loading Configs
|
||||
private void LoadGeneralSettings(XDocument doc, bool setLanguage = true)
|
||||
{
|
||||
if (setLanguage)
|
||||
{
|
||||
Language = doc.Root.GetAttributeString("language", Language);
|
||||
}
|
||||
AutoCheckUpdates = doc.Root.GetAttributeBool("autocheckupdates", AutoCheckUpdates);
|
||||
sendUserStatistics = doc.Root.GetAttributeBool("senduserstatistics", sendUserStatistics);
|
||||
QuickStartSubmarineName = doc.Root.GetAttributeString("quickstartsubmarine", "");
|
||||
useSteamMatchmaking = doc.Root.GetAttributeBool("usesteammatchmaking", useSteamMatchmaking);
|
||||
requireSteamAuthentication = doc.Root.GetAttributeBool("requiresteamauthentication", requireSteamAuthentication);
|
||||
EnableSplashScreen = doc.Root.GetAttributeBool("enablesplashscreen", EnableSplashScreen);
|
||||
PauseOnFocusLost = doc.Root.GetAttributeBool("pauseonfocuslost", PauseOnFocusLost);
|
||||
AimAssistAmount = doc.Root.GetAttributeFloat("aimassistamount", AimAssistAmount);
|
||||
EnableMouseLook = doc.Root.GetAttributeBool("enablemouselook", EnableMouseLook);
|
||||
CrewMenuOpen = doc.Root.GetAttributeBool("crewmenuopen", CrewMenuOpen);
|
||||
ChatOpen = doc.Root.GetAttributeBool("chatopen", ChatOpen);
|
||||
CampaignDisclaimerShown = doc.Root.GetAttributeBool("campaigndisclaimershown", CampaignDisclaimerShown);
|
||||
EditorDisclaimerShown = doc.Root.GetAttributeBool("editordisclaimershown", EditorDisclaimerShown);
|
||||
XElement gameplayElement = doc.Root.Element("gameplay");
|
||||
if (gameplayElement != null)
|
||||
{
|
||||
jobPreferences = new List<string>();
|
||||
foreach (XElement ele in gameplayElement.Element("jobpreferences").Elements("job"))
|
||||
{
|
||||
string jobIdentifier = ele.GetAttributeString("identifier", "");
|
||||
if (string.IsNullOrEmpty(jobIdentifier)) continue;
|
||||
jobPreferences.Add(jobIdentifier);
|
||||
}
|
||||
}
|
||||
|
||||
XElement playerElement = doc.Root.Element("player");
|
||||
if (playerElement != null)
|
||||
{
|
||||
defaultPlayerName = playerElement.GetAttributeString("name", defaultPlayerName);
|
||||
CharacterHeadIndex = playerElement.GetAttributeInt("headindex", CharacterHeadIndex);
|
||||
if (Enum.TryParse(playerElement.GetAttributeString("gender", "none"), true, out Gender g))
|
||||
{
|
||||
CharacterGender = g;
|
||||
}
|
||||
if (Enum.TryParse(playerElement.GetAttributeString("race", "white"), true, out Race r))
|
||||
{
|
||||
CharacterRace = r;
|
||||
}
|
||||
else
|
||||
{
|
||||
CharacterRace = Race.White;
|
||||
}
|
||||
CharacterHairIndex = playerElement.GetAttributeInt("hairindex", CharacterHairIndex);
|
||||
CharacterBeardIndex = playerElement.GetAttributeInt("beardindex", CharacterBeardIndex);
|
||||
CharacterMoustacheIndex = playerElement.GetAttributeInt("moustacheindex", CharacterMoustacheIndex);
|
||||
CharacterFaceAttachmentIndex = playerElement.GetAttributeInt("faceattachmentindex", CharacterFaceAttachmentIndex);
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadGraphicSettings(XDocument doc)
|
||||
{
|
||||
XElement graphicsMode = doc.Root.Element("graphicsmode");
|
||||
GraphicsWidth = graphicsMode.GetAttributeInt("width", GraphicsWidth);
|
||||
GraphicsHeight = graphicsMode.GetAttributeInt("height", GraphicsHeight);
|
||||
VSyncEnabled = graphicsMode.GetAttributeBool("vsync", VSyncEnabled);
|
||||
|
||||
XElement graphicsSettings = doc.Root.Element("graphicssettings");
|
||||
ParticleLimit = graphicsSettings.GetAttributeInt("particlelimit", ParticleLimit);
|
||||
LightMapScale = MathHelper.Clamp(graphicsSettings.GetAttributeFloat("lightmapscale", LightMapScale), 0.1f, 1.0f);
|
||||
SpecularityEnabled = graphicsSettings.GetAttributeBool("specularity", SpecularityEnabled);
|
||||
ChromaticAberrationEnabled = graphicsSettings.GetAttributeBool("chromaticaberration", ChromaticAberrationEnabled);
|
||||
HUDScale = graphicsSettings.GetAttributeFloat("hudscale", HUDScale);
|
||||
InventoryScale = graphicsSettings.GetAttributeFloat("inventoryscale", InventoryScale);
|
||||
var losModeStr = graphicsSettings.GetAttributeString("losmode", "Transparent");
|
||||
if (!Enum.TryParse(losModeStr, out losMode))
|
||||
{
|
||||
losMode = LosMode.Transparent;
|
||||
}
|
||||
#if CLIENT
|
||||
if (GraphicsWidth == 0 || GraphicsHeight == 0)
|
||||
{
|
||||
GraphicsWidth = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width;
|
||||
GraphicsHeight = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height;
|
||||
}
|
||||
#endif
|
||||
var windowModeStr = graphicsMode.GetAttributeString("displaymode", "Fullscreen");
|
||||
if (!Enum.TryParse(windowModeStr, out windowMode))
|
||||
{
|
||||
windowMode = WindowMode.Fullscreen;
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadAudioSettings(XDocument doc)
|
||||
{
|
||||
XElement audioSettings = doc.Root.Element("audio");
|
||||
if (audioSettings != null)
|
||||
{
|
||||
SoundVolume = audioSettings.GetAttributeFloat("soundvolume", SoundVolume);
|
||||
MusicVolume = audioSettings.GetAttributeFloat("musicvolume", MusicVolume);
|
||||
VoiceChatVolume = audioSettings.GetAttributeFloat("voicechatvolume", VoiceChatVolume);
|
||||
MuteOnFocusLost = audioSettings.GetAttributeBool("muteonfocuslost", MuteOnFocusLost);
|
||||
UseDirectionalVoiceChat = audioSettings.GetAttributeBool("usedirectionalvoicechat", UseDirectionalVoiceChat);
|
||||
VoiceCaptureDevice = audioSettings.GetAttributeString("voicecapturedevice", VoiceCaptureDevice);
|
||||
NoiseGateThreshold = audioSettings.GetAttributeFloat("noisegatethreshold", NoiseGateThreshold);
|
||||
MicrophoneVolume = audioSettings.GetAttributeFloat("microphonevolume", MicrophoneVolume);
|
||||
var voiceSetting = VoiceMode.Disabled;
|
||||
string voiceSettingStr = audioSettings.GetAttributeString("voicesetting", "");
|
||||
if (Enum.TryParse(voiceSettingStr, out voiceSetting))
|
||||
{
|
||||
VoiceSetting = voiceSetting;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadControls(XDocument doc)
|
||||
{
|
||||
XElement keyMapping = doc.Root.Element("keymapping");
|
||||
if (keyMapping != null)
|
||||
{
|
||||
LoadKeyBinds(keyMapping);
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadContentPackages(XDocument doc)
|
||||
{
|
||||
selectedContentPackagePaths = new HashSet<string>();
|
||||
foreach (XElement subElement in doc.Root.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
case "contentpackage":
|
||||
string path = System.IO.Path.GetFullPath(subElement.GetAttributeString("path", ""));
|
||||
selectedContentPackagePaths.Add(path);
|
||||
break;
|
||||
}
|
||||
}
|
||||
LoadContentPackages(selectedContentPackagePaths);
|
||||
}
|
||||
#endregion
|
||||
|
||||
private void LoadKeyBinds(XElement element)
|
||||
{
|
||||
foreach (XAttribute attribute in element.Attributes())
|
||||
{
|
||||
if (!Enum.TryParse(attribute.Name.ToString(), true, out InputType inputType)) { continue; }
|
||||
|
||||
|
||||
if (int.TryParse(attribute.Value.ToString(), out int mouseButton))
|
||||
{
|
||||
keyMapping[(int)inputType] = new KeyOrMouse(mouseButton);
|
||||
@@ -1169,7 +1026,7 @@ namespace Barotrauma
|
||||
{
|
||||
keyMapping[(int)inputType] = new KeyOrMouse(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1184,5 +1041,62 @@ namespace Barotrauma
|
||||
{
|
||||
return keyMapping[(int)inputType];
|
||||
}
|
||||
|
||||
private void SetDefaultValues(bool resetLanguage = true)
|
||||
{
|
||||
GraphicsWidth = 0;
|
||||
GraphicsHeight = 0;
|
||||
VSyncEnabled = true;
|
||||
#if DEBUG
|
||||
EnableSplashScreen = false;
|
||||
#else
|
||||
EnableSplashScreen = true;
|
||||
#endif
|
||||
ParticleLimit = 1500;
|
||||
LightMapScale = 0.5f;
|
||||
SpecularityEnabled = false;
|
||||
ChromaticAberrationEnabled = true;
|
||||
PauseOnFocusLost = true;
|
||||
MuteOnFocusLost = false;
|
||||
UseDirectionalVoiceChat = true;
|
||||
VoiceSetting = VoiceMode.Disabled;
|
||||
VoiceCaptureDevice = null;
|
||||
NoiseGateThreshold = -45;
|
||||
windowMode = WindowMode.Fullscreen;
|
||||
losMode = LosMode.Transparent;
|
||||
useSteamMatchmaking = true;
|
||||
requireSteamAuthentication = true;
|
||||
QuickStartSubmarineName = string.Empty;
|
||||
CharacterHeadIndex = 1;
|
||||
CharacterHairIndex = -1;
|
||||
CharacterBeardIndex = -1;
|
||||
CharacterMoustacheIndex = -1;
|
||||
CharacterFaceAttachmentIndex = -1;
|
||||
CharacterGender = Gender.None;
|
||||
CharacterRace = Race.White;
|
||||
aimAssistAmount = 0.5f;
|
||||
EnableMouseLook = true;
|
||||
CrewMenuOpen = true;
|
||||
ChatOpen = true;
|
||||
soundVolume = 0.5f;
|
||||
musicVolume = 0.3f;
|
||||
voiceChatVolume = 0.5f;
|
||||
microphoneVolume = 1.0f;
|
||||
AutoCheckUpdates = true;
|
||||
defaultPlayerName = string.Empty;
|
||||
HUDScale = 1;
|
||||
InventoryScale = 1;
|
||||
AutoUpdateWorkshopItems = true;
|
||||
CampaignDisclaimerShown = false;
|
||||
if (resetLanguage)
|
||||
{
|
||||
Language = "English";
|
||||
}
|
||||
MasterServerUrl = "http://www.undertowgames.com/baromaster";
|
||||
WasGameUpdated = false;
|
||||
VerboseLogging = false;
|
||||
SaveDebugConsoleLogs = false;
|
||||
AutoUpdateWorkshopItems = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ namespace Barotrauma.Items.Components
|
||||
private Body doorBody;
|
||||
|
||||
private bool docked;
|
||||
private bool obstructedWayPointsDisabled;
|
||||
|
||||
private float forceLockTimer;
|
||||
//if the submarine isn't in the correct position to lock within this time after docking has been activated,
|
||||
@@ -732,6 +733,9 @@ namespace Barotrauma.Items.Components
|
||||
bodies = null;
|
||||
}
|
||||
|
||||
Item.Submarine.EnableObstructedWaypoints();
|
||||
obstructedWayPointsDisabled = false;
|
||||
|
||||
#if SERVER
|
||||
if (GameMain.Server != null)
|
||||
{
|
||||
@@ -813,6 +817,11 @@ namespace Barotrauma.Items.Components
|
||||
dockingState = MathHelper.Lerp(dockingState, 1.0f, deltaTime * 10.0f);
|
||||
}
|
||||
}
|
||||
if (!obstructedWayPointsDisabled && dockingState >= 0.99f)
|
||||
{
|
||||
Item.Submarine.DisableObstructedWayPoints(DockingTarget?.Item.Submarine);
|
||||
obstructedWayPointsDisabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void RemoveComponentSpecific()
|
||||
@@ -983,6 +992,5 @@ namespace Barotrauma.Items.Components
|
||||
Undock();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -413,7 +413,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
target = ConvertUnits.ToSimUnits(Level.Loaded.StartPosition);
|
||||
}
|
||||
steeringPath = pathFinder.FindPath(ConvertUnits.ToSimUnits(controlledSub == null ? item.WorldPosition : controlledSub.WorldPosition), target, "(Autopilot, target: " + target + ")");
|
||||
steeringPath = pathFinder.FindPath(ConvertUnits.ToSimUnits(controlledSub == null ? item.WorldPosition : controlledSub.WorldPosition), target, errorMsgStr: "(Autopilot, target: " + target + ")");
|
||||
}
|
||||
|
||||
public void SetDestinationLevelStart()
|
||||
|
||||
@@ -174,6 +174,12 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private void Launch(Vector2 impulse)
|
||||
{
|
||||
if (item.AiTarget != null)
|
||||
{
|
||||
item.AiTarget.SightRange = item.AiTarget.MaxSightRange;
|
||||
item.AiTarget.SoundRange = item.AiTarget.MaxSoundRange;
|
||||
}
|
||||
|
||||
item.Drop(null);
|
||||
|
||||
item.body.Enabled = true;
|
||||
|
||||
@@ -122,6 +122,16 @@ namespace Barotrauma.Items.Components
|
||||
Update(deltaTime, cam);
|
||||
}
|
||||
|
||||
public void ResetDeterioration()
|
||||
{
|
||||
deteriorationTimer = Rand.Range(MinDeteriorationDelay, MaxDeteriorationDelay);
|
||||
item.Condition = item.Prefab.Health;
|
||||
#if SERVER
|
||||
//let the clients know the initial deterioration delay
|
||||
item.CreateServerEvent(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
UpdateProjSpecific(deltaTime);
|
||||
|
||||
@@ -338,9 +338,15 @@ namespace Barotrauma.Items.Components
|
||||
canPlaceNode = true;
|
||||
}
|
||||
|
||||
Vector2 relativeNodePos = newNodePos - item.Position;
|
||||
if (sub != null)
|
||||
{
|
||||
relativeNodePos += sub.HiddenSubPosition;
|
||||
}
|
||||
|
||||
sectionExtents = new Vector2(
|
||||
Math.Max(Math.Abs((newNodePos.X + sub.HiddenSubPosition.X) - item.Position.X), sectionExtents.X),
|
||||
Math.Max(Math.Abs((newNodePos.Y + sub.HiddenSubPosition.Y) - item.Position.Y), sectionExtents.Y));
|
||||
Math.Max(Math.Abs(relativeNodePos.X), sectionExtents.X),
|
||||
Math.Max(Math.Abs(relativeNodePos.Y), sectionExtents.Y));
|
||||
}
|
||||
|
||||
public override bool Use(float deltaTime, Character character = null)
|
||||
|
||||
@@ -286,6 +286,23 @@ namespace Barotrauma.Items.Components
|
||||
if (!equipLimb.WearingItems.Contains(wearableSprite))
|
||||
{
|
||||
equipLimb.WearingItems.Add(wearableSprite);
|
||||
equipLimb.WearingItems.Sort((i1, i2) => { return i2.Sprite.Depth.CompareTo(i1.Sprite.Depth); });
|
||||
equipLimb.WearingItems.Sort((i1, i2) =>
|
||||
{
|
||||
if (i1?.WearableComponent == null && i2?.WearableComponent == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (i1?.WearableComponent == null)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if (i2?.WearableComponent == null)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return i1.WearableComponent.AllowedSlots.Contains(InvSlotType.OuterClothes).CompareTo(i2.WearableComponent.AllowedSlots.Contains(InvSlotType.OuterClothes));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1042,8 +1042,8 @@ namespace Barotrauma
|
||||
//aitarget goes silent/invisible if the components don't keep it active
|
||||
if (aiTarget != null)
|
||||
{
|
||||
aiTarget.SightRange -= deltaTime * 1000.0f;
|
||||
aiTarget.SoundRange -= deltaTime * 1000.0f;
|
||||
aiTarget.SightRange -= deltaTime * (aiTarget.MaxSightRange / aiTarget.FadeOutTime);
|
||||
aiTarget.SoundRange -= deltaTime * (aiTarget.MaxSoundRange / aiTarget.FadeOutTime);
|
||||
}
|
||||
|
||||
bool broken = condition <= 0.0f;
|
||||
@@ -2017,6 +2017,8 @@ namespace Barotrauma
|
||||
if (element.GetAttributeBool("flippedy", false)) item.FlipY(false);
|
||||
|
||||
item.condition = element.GetAttributeFloat("condition", item.Prefab.Health);
|
||||
item.lastSentCondition = item.condition;
|
||||
|
||||
item.SetActiveSprite();
|
||||
|
||||
foreach (ItemComponent component in item.components)
|
||||
|
||||
@@ -1366,6 +1366,11 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
List<InterestingPosition> suitablePositions = positionsOfInterest.FindAll(p => positionType.HasFlag(p.PositionType));
|
||||
//avoid floating ice chunks on the main path
|
||||
if (positionType == PositionType.MainPath)
|
||||
{
|
||||
suitablePositions.RemoveAll(p => extraWalls.Any(w => w.Cells.Any(c => c.IsPointInside(p.Position.ToVector2()))));
|
||||
}
|
||||
if (!suitablePositions.Any())
|
||||
{
|
||||
string errorMsg = "Could not find a suitable position of interest. (PositionType: " + positionType + ", minDistFromSubs: " + minDistFromSubs + ")\n" + Environment.StackTrace;
|
||||
|
||||
@@ -1433,7 +1433,7 @@ namespace Barotrauma
|
||||
|
||||
Submarine sub = new Submarine(path);
|
||||
sub.Load(unloadPrevious);
|
||||
|
||||
|
||||
return sub;
|
||||
}
|
||||
|
||||
@@ -1564,6 +1564,94 @@ namespace Barotrauma
|
||||
PreviewImage = null;
|
||||
#endif
|
||||
}
|
||||
|
||||
private List<PathNode> outdoorNodes;
|
||||
private List<PathNode> OutdoorNodes
|
||||
{
|
||||
get
|
||||
{
|
||||
if (outdoorNodes == null)
|
||||
{
|
||||
outdoorNodes = PathNode.GenerateNodes(WayPoint.WayPointList.FindAll(wp => wp.SpawnType == SpawnType.Path && wp.Submarine == this && wp.CurrentHull == null));
|
||||
}
|
||||
return outdoorNodes;
|
||||
}
|
||||
}
|
||||
private HashSet<PathNode> obstructedNodes = new HashSet<PathNode>();
|
||||
|
||||
/// <summary>
|
||||
/// Permanently disables obstructed waypoints obstructed by the level.
|
||||
/// </summary>
|
||||
public void DisableObstructedWayPoints()
|
||||
{
|
||||
// Check collisions to level
|
||||
foreach (var node in OutdoorNodes)
|
||||
{
|
||||
if (node == null || node.Waypoint == null) { continue; }
|
||||
var wp = node.Waypoint;
|
||||
if (wp.isObstructed) { continue; }
|
||||
foreach (var connection in node.connections)
|
||||
{
|
||||
bool isObstructed = false;
|
||||
var connectedWp = connection.Waypoint;
|
||||
if (connectedWp.isObstructed) { continue; }
|
||||
Vector2 start = ConvertUnits.ToSimUnits(wp.WorldPosition);
|
||||
Vector2 end = ConvertUnits.ToSimUnits(connectedWp.WorldPosition);
|
||||
var body = Submarine.PickBody(start, end, null, Physics.CollisionLevel, allowInsideFixture: false);
|
||||
if (body != null)
|
||||
{
|
||||
connectedWp.isObstructed = true;
|
||||
wp.isObstructed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Temporarily disables waypoints obstructed by the other sub.
|
||||
/// </summary>
|
||||
public void DisableObstructedWayPoints(Submarine otherSub)
|
||||
{
|
||||
if (otherSub == null) { return; }
|
||||
if (otherSub == this) { return; }
|
||||
// Check collisions to other subs. Currently only walls are taken into account.
|
||||
foreach (var node in OutdoorNodes)
|
||||
{
|
||||
if (node == null || node.Waypoint == null) { continue; }
|
||||
var wp = node.Waypoint;
|
||||
if (wp.isObstructed) { continue; }
|
||||
foreach (var connection in node.connections)
|
||||
{
|
||||
bool isObstructed = false;
|
||||
var connectedWp = connection.Waypoint;
|
||||
if (connectedWp.isObstructed) { continue; }
|
||||
Vector2 start = ConvertUnits.ToSimUnits(wp.WorldPosition) - otherSub.SimPosition;
|
||||
Vector2 end = ConvertUnits.ToSimUnits(connectedWp.WorldPosition) - otherSub.SimPosition;
|
||||
var body = Submarine.PickBody(start, end, null, Physics.CollisionWall, allowInsideFixture: false);
|
||||
if (body != null && body.UserData is Structure && !((Structure)body.UserData).IsPlatform)
|
||||
{
|
||||
connectedWp.isObstructed = true;
|
||||
wp.isObstructed = true;
|
||||
obstructedNodes.Add(node);
|
||||
obstructedNodes.Add(connection);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Only affects temporarily disabled waypoints.
|
||||
/// </summary>
|
||||
public void EnableObstructedWaypoints()
|
||||
{
|
||||
foreach (var node in obstructedNodes)
|
||||
{
|
||||
node.Waypoint.isObstructed = false;
|
||||
}
|
||||
obstructedNodes.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -32,6 +32,8 @@ namespace Barotrauma
|
||||
public Ladder Ladders;
|
||||
public Structure Stairs;
|
||||
|
||||
public bool isObstructed;
|
||||
|
||||
private ushort gapId;
|
||||
public Gap ConnectedGap
|
||||
{
|
||||
|
||||
@@ -7,6 +7,8 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
partial class Client : IDisposable
|
||||
{
|
||||
public const int MaxNameLength = 20;
|
||||
|
||||
public string Name;
|
||||
public byte ID;
|
||||
|
||||
@@ -205,6 +207,21 @@ namespace Barotrauma.Networking
|
||||
SetPermissions(permissions, permittedCommands);
|
||||
}
|
||||
|
||||
public static string SanitizeName(string name)
|
||||
{
|
||||
name = name.Trim();
|
||||
if (name.Length > MaxNameLength)
|
||||
{
|
||||
name = name.Substring(0, MaxNameLength);
|
||||
}
|
||||
string rName = "";
|
||||
for (int i = 0; i < name.Length; i++)
|
||||
{
|
||||
rName += name[i] < 32 ? '?' : name[i];
|
||||
}
|
||||
return rName;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
DisposeProjSpecific();
|
||||
|
||||
@@ -174,8 +174,8 @@ namespace Barotrauma.Networking
|
||||
get { return name; }
|
||||
set
|
||||
{
|
||||
if (string.IsNullOrEmpty(value)) return;
|
||||
name = value;
|
||||
if (string.IsNullOrEmpty(value)) { return; }
|
||||
name = value.Replace(":", "").Replace(";", "");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -158,41 +158,11 @@ namespace Barotrauma.Networking
|
||||
|
||||
shuttleTransportTimer -= deltaTime;
|
||||
|
||||
#if CLIENT
|
||||
GameClient nClient = networkMember as GameClient;
|
||||
if (shuttleTransportTimer + deltaTime > 15.0f && shuttleTransportTimer <= 15.0f &&
|
||||
nClient.Character != null &&
|
||||
nClient.Character.Submarine == respawnShuttle)
|
||||
{
|
||||
nClient.AddChatMessage("ServerMessage.ShuttleLeaving", ChatMessageType.Server);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if SERVER
|
||||
var server = networkMember as GameServer;
|
||||
if (server == null) return;
|
||||
|
||||
//if there are no living chracters inside, transporting can be stopped immediately
|
||||
if (!Character.CharacterList.Any(c => c.Submarine == respawnShuttle && !c.IsDead))
|
||||
{
|
||||
shuttleTransportTimer = 0.0f;
|
||||
}
|
||||
|
||||
if (shuttleTransportTimer <= 0.0f)
|
||||
{
|
||||
GameServer.Log("The respawn shuttle is leaving.", ServerLog.MessageType.ServerMessage);
|
||||
state = State.Returning;
|
||||
|
||||
server.CreateEntityEvent(this);
|
||||
|
||||
CountdownStarted = false;
|
||||
maxTransportTime = server.ServerSettings.MaxTransportTime;
|
||||
shuttleReturnTimer = maxTransportTime;
|
||||
shuttleTransportTimer = maxTransportTime;
|
||||
}
|
||||
#endif
|
||||
UpdateTransportingProjSpecific(deltaTime);
|
||||
}
|
||||
|
||||
partial void UpdateTransportingProjSpecific(float deltaTime);
|
||||
|
||||
private void UpdateReturning(float deltaTime)
|
||||
{
|
||||
//if (shuttleReturnTimer == maxTransportTime &&
|
||||
@@ -216,56 +186,13 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
shuttleSteering.SetDestinationLevelStart();
|
||||
}
|
||||
|
||||
|
||||
#if SERVER
|
||||
var server = networkMember as GameServer;
|
||||
if (server == null) return;
|
||||
|
||||
foreach (Door door in shuttleDoors)
|
||||
{
|
||||
if (door.IsOpen) door.TrySetState(false, false, true);
|
||||
}
|
||||
|
||||
var shuttleGaps = Gap.GapList.FindAll(g => g.Submarine == respawnShuttle && g.ConnectedWall != null);
|
||||
shuttleGaps.ForEach(g => Spawner.AddToRemoveQueue(g));
|
||||
|
||||
var dockingPorts = Item.ItemList.FindAll(i => i.Submarine == respawnShuttle && i.GetComponent<DockingPort>() != null);
|
||||
dockingPorts.ForEach(d => d.GetComponent<DockingPort>().Undock());
|
||||
|
||||
//shuttle has returned if the path has been traversed or the shuttle is close enough to the exit
|
||||
|
||||
if (!CoroutineManager.IsCoroutineRunning("forcepos"))
|
||||
{
|
||||
if ((shuttleSteering?.SteeringPath != null && shuttleSteering.SteeringPath.Finished)
|
||||
|| (respawnShuttle.WorldPosition.Y + respawnShuttle.Borders.Y > Level.Loaded.StartPosition.Y - Level.ShaftHeight &&
|
||||
Math.Abs(Level.Loaded.StartPosition.X - respawnShuttle.WorldPosition.X) < 1000.0f))
|
||||
{
|
||||
CoroutineManager.StopCoroutines("forcepos");
|
||||
CoroutineManager.StartCoroutine(
|
||||
ForceShuttleToPos(new Vector2(Level.Loaded.StartPosition.X, Level.Loaded.Size.Y + 1000.0f), 100.0f), "forcepos");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (respawnShuttle.WorldPosition.Y > Level.Loaded.Size.Y || shuttleReturnTimer <= 0.0f)
|
||||
{
|
||||
CoroutineManager.StopCoroutines("forcepos");
|
||||
|
||||
ResetShuttle();
|
||||
|
||||
state = State.Waiting;
|
||||
GameServer.Log("The respawn shuttle has left.", ServerLog.MessageType.Spawning);
|
||||
server.CreateEntityEvent(this);
|
||||
|
||||
respawnTimer = server.ServerSettings.RespawnInterval;
|
||||
CountdownStarted = false;
|
||||
}
|
||||
#endif
|
||||
UpdateReturningProjSpecific();
|
||||
}
|
||||
}
|
||||
|
||||
partial void DispatchShuttle();
|
||||
|
||||
partial void UpdateReturningProjSpecific();
|
||||
|
||||
private IEnumerable<object> ForceShuttleToPos(Vector2 position, float speed)
|
||||
{
|
||||
@@ -314,6 +241,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
//restore other items to full condition and recharge batteries
|
||||
item.Condition = item.Prefab.Health;
|
||||
item.GetComponent<Repairable>()?.ResetDeterioration();
|
||||
var powerContainer = item.GetComponent<PowerContainer>();
|
||||
if (powerContainer != null)
|
||||
{
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user