(ded4a3e0a) v0.9.0.7
This commit is contained in:
@@ -221,6 +221,7 @@
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Sprite\Sprite.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Sprite\SpriteSheet.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\StatusEffects\StatusEffect.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Utils\CrossThread.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Utils\LocalizationCSVtoXML.cs">
|
||||
</Compile>
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Utils\MathUtils.cs" />
|
||||
|
||||
@@ -83,8 +83,9 @@
|
||||
<Reference Include="GameAnalytics.Mono, Version=1.0.7018.15293, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\Libraries\NuGet\GameAnalytics.Mono.SDK.2.1.6\lib\net45\GameAnalytics.Mono.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="MonoGame.Framework, Version=3.7.1.189, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\Libraries\NuGet\MonoGame.Framework.DesktopGL.3.7.1.189\lib\net45\MonoGame.Framework.dll</HintPath>
|
||||
<Reference Include="MonoGame.Framework, Version=3.6.0.1625, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\Libraries\MonoGame.Framework\DesktopGL\MonoGame.Framework.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\Libraries\NuGet\NLog.4.3.8\lib\net45\NLog.dll</HintPath>
|
||||
@@ -354,9 +355,7 @@
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\Libraries\NuGet\GameAnalytics.Mono.SDK.2.1.6\build\net45\GameAnalytics.Mono.SDK.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\Libraries\NuGet\GameAnalytics.Mono.SDK.2.1.6\build\net45\GameAnalytics.Mono.SDK.targets'))" />
|
||||
<Error Condition="!Exists('..\..\Libraries\NuGet\MonoGame.Framework.DesktopGL.3.7.1.189\build\MonoGame.Framework.DesktopGL.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\Libraries\NuGet\MonoGame.Framework.DesktopGL.3.7.1.189\build\MonoGame.Framework.DesktopGL.targets'))" />
|
||||
</Target>
|
||||
<Import Project="..\..\Libraries\NuGet\MonoGame.Framework.DesktopGL.3.7.1.189\build\MonoGame.Framework.DesktopGL.targets" Condition="Exists('..\..\Libraries\NuGet\MonoGame.Framework.DesktopGL.3.7.1.189\build\MonoGame.Framework.DesktopGL.targets')" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
|
||||
@@ -82,8 +82,8 @@
|
||||
<Reference Include="GameAnalytics.Mono, Version=1.0.7018.15293, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\Libraries\NuGet\GameAnalytics.Mono.SDK.2.1.6\lib\net45\GameAnalytics.Mono.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="MonoGame.Framework, Version=3.7.1.189, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\Libraries\NuGet\MonoGame.Framework.DesktopGL.3.7.1.189\lib\net45\MonoGame.Framework.dll</HintPath>
|
||||
<Reference Include="MonoGame.Framework">
|
||||
<HintPath>..\..\Libraries\MonoGame.Framework\DesktopGL\MonoGame.Framework.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\Libraries\NuGet\NLog.4.3.8\lib\net45\NLog.dll</HintPath>
|
||||
@@ -291,10 +291,8 @@
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\Libraries\NuGet\MonoGame.Framework.DesktopGL.3.7.1.189\build\MonoGame.Framework.DesktopGL.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\Libraries\NuGet\MonoGame.Framework.DesktopGL.3.7.1.189\build\MonoGame.Framework.DesktopGL.targets'))" />
|
||||
<Error Condition="!Exists('..\..\Libraries\NuGet\GameAnalytics.Mono.SDK.2.1.6\build\net45\GameAnalytics.Mono.SDK.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\Libraries\NuGet\GameAnalytics.Mono.SDK.2.1.6\build\net45\GameAnalytics.Mono.SDK.targets'))" />
|
||||
</Target>
|
||||
<Import Project="..\..\Libraries\NuGet\MonoGame.Framework.DesktopGL.3.7.1.189\build\MonoGame.Framework.DesktopGL.targets" Condition="Exists('..\..\Libraries\NuGet\MonoGame.Framework.DesktopGL.3.7.1.189\build\MonoGame.Framework.DesktopGL.targets')" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
|
||||
@@ -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.6")]
|
||||
[assembly: AssemblyFileVersion("0.9.0.6")]
|
||||
[assembly: AssemblyVersion("0.9.0.7")]
|
||||
[assembly: AssemblyFileVersion("0.9.0.7")]
|
||||
|
||||
@@ -442,7 +442,8 @@ namespace Barotrauma
|
||||
if (draggingItemToWorld)
|
||||
{
|
||||
if (item.OwnInventory == null ||
|
||||
!item.OwnInventory.CanBePut(CharacterInventory.draggingItem))
|
||||
!item.OwnInventory.CanBePut(CharacterInventory.draggingItem) ||
|
||||
!CanAccessInventory(item.OwnInventory))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@ namespace Barotrauma
|
||||
foreach (Item item in Item.ItemList)
|
||||
{
|
||||
if (!item.Repairables.Any(r => item.Condition < r.ShowRepairUIThreshold)) { continue; }
|
||||
if (!Submarine.VisibleEntities.Contains(item)) { continue; }
|
||||
if (Submarine.VisibleEntities != null && !Submarine.VisibleEntities.Contains(item)) { continue; }
|
||||
|
||||
Vector2 diff = item.WorldPosition - character.WorldPosition;
|
||||
if (Submarine.CheckVisibility(character.SimPosition, character.SimPosition + ConvertUnits.ToSimUnits(diff)) == null)
|
||||
@@ -391,7 +391,7 @@ namespace Barotrauma
|
||||
|
||||
if (!orderIndicatorCount.ContainsKey(target)) { orderIndicatorCount.Add(target, 0); }
|
||||
|
||||
Vector2 drawPos = target.WorldPosition + Vector2.UnitX * order.SymbolSprite.size.X * 1.5f * orderIndicatorCount[target];
|
||||
Vector2 drawPos = target.DrawPosition + Vector2.UnitX * order.SymbolSprite.size.X * 1.5f * orderIndicatorCount[target];
|
||||
GUI.DrawIndicator(spriteBatch, drawPos, cam, 100.0f, order.SymbolSprite, order.Color * iconAlpha);
|
||||
|
||||
orderIndicatorCount[target] = orderIndicatorCount[target] + 1;
|
||||
|
||||
@@ -318,7 +318,7 @@ namespace Barotrauma
|
||||
if (!(mp is ItemPrefab)) continue;
|
||||
sb.AppendLine(mp.Name);
|
||||
}
|
||||
System.Windows.Clipboard.SetText(sb.ToString());
|
||||
Clipboard.SetText(sb.ToString());
|
||||
}));
|
||||
#endif
|
||||
|
||||
@@ -452,6 +452,10 @@ namespace Barotrauma
|
||||
|
||||
commands.Add(new Command("clientlist", "", (string[] args) => { }));
|
||||
AssignRelayToServer("clientlist", true);
|
||||
commands.Add(new Command("setmaxplayers|maxplayers", "", (string[] args) => { }));
|
||||
AssignRelayToServer("setmaxplayers", true);
|
||||
commands.Add(new Command("setpassword|password", "", (string[] args) => { }));
|
||||
AssignRelayToServer("setpassword", true);
|
||||
|
||||
AssignOnExecute("control", (string[] args) =>
|
||||
{
|
||||
|
||||
@@ -6,34 +6,6 @@ using System.Text;
|
||||
|
||||
namespace EventInput
|
||||
{
|
||||
#if WINDOWS
|
||||
public class KeyboardLayout
|
||||
{
|
||||
const uint KLF_ACTIVATE = 1; //activate the layout
|
||||
const int KL_NAMELENGTH = 9; // length of the keyboard buffer
|
||||
const string LANG_EN_US = "00000409";
|
||||
const string LANG_HE_IL = "0001101A";
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern long LoadKeyboardLayout(
|
||||
string pwszKLID, // input locale identifier
|
||||
uint Flags // input locale identifier options
|
||||
);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern long GetKeyboardLayoutName(
|
||||
StringBuilder pwszKLID //[out] string that receives the name of the locale identifier
|
||||
);
|
||||
|
||||
public static string getName()
|
||||
{
|
||||
StringBuilder name = new StringBuilder(KL_NAMELENGTH);
|
||||
GetKeyboardLayoutName(name);
|
||||
return name.ToString();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public class CharacterEventArgs : EventArgs
|
||||
{
|
||||
private readonly char character;
|
||||
@@ -118,50 +90,6 @@ namespace EventInput
|
||||
|
||||
static bool initialized;
|
||||
|
||||
#if WINDOWS
|
||||
delegate IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
|
||||
|
||||
static IntPtr prevWndProc;
|
||||
static WndProc hookProcDelegate;
|
||||
static IntPtr hIMC;
|
||||
|
||||
//various Win32 constants that we need
|
||||
const int GWL_WNDPROC = -4;
|
||||
const int WM_KEYDOWN = 0x100;
|
||||
const int WM_KEYUP = 0x101;
|
||||
const int WM_CHAR = 0x102;
|
||||
const int WM_IME_SETCONTEXT = 0x0281;
|
||||
const int WM_INPUTLANGCHANGE = 0x51;
|
||||
const int WM_GETDLGCODE = 0x87;
|
||||
const int WM_IME_COMPOSITION = 0x10f;
|
||||
const int DLGC_WANTALLKEYS = 4;
|
||||
|
||||
//Win32 functions that we're using
|
||||
[DllImport("Imm32.dll", CharSet = CharSet.Unicode)]
|
||||
static extern IntPtr ImmGetContext(IntPtr hWnd);
|
||||
|
||||
[DllImport("Imm32.dll", CharSet = CharSet.Unicode)]
|
||||
static extern IntPtr ImmAssociateContext(IntPtr hWnd, IntPtr hIMC);
|
||||
|
||||
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
|
||||
static extern IntPtr CallWindowProc(IntPtr lpPrevWndFunc, IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
|
||||
|
||||
public static IntPtr TrySetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong)
|
||||
{
|
||||
if (IntPtr.Size == 4)
|
||||
{
|
||||
return SetWindowLong(hWnd, nIndex, dwNewLong);
|
||||
}
|
||||
return SetWindowLongPtr(hWnd, nIndex, dwNewLong);
|
||||
}
|
||||
|
||||
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
|
||||
static extern IntPtr SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
|
||||
|
||||
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
|
||||
static extern IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the TextInput with the given GameWindow.
|
||||
/// </summary>
|
||||
@@ -172,17 +100,8 @@ namespace EventInput
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#if WINDOWS
|
||||
hookProcDelegate = HookProc;
|
||||
|
||||
prevWndProc = TrySetWindowLong(window.Handle, GWL_WNDPROC,
|
||||
Marshal.GetFunctionPointerForDelegate(hookProcDelegate));
|
||||
|
||||
hIMC = ImmGetContext(window.Handle);
|
||||
#else
|
||||
|
||||
window.TextInput += ReceiveInput;
|
||||
#endif
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
@@ -197,63 +116,5 @@ namespace EventInput
|
||||
{
|
||||
CharEntered?.Invoke(null, new CharacterEventArgs(character, 0));
|
||||
}
|
||||
#if WINDOWS
|
||||
static IntPtr HookProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
IntPtr returnCode = CallWindowProc(prevWndProc, hWnd, msg, wParam, lParam);
|
||||
|
||||
switch (msg)
|
||||
{
|
||||
case WM_GETDLGCODE:
|
||||
returnCode = (IntPtr)(returnCode.ToInt32() | DLGC_WANTALLKEYS);
|
||||
break;
|
||||
|
||||
case WM_KEYDOWN:
|
||||
if (KeyDown != null)
|
||||
KeyDown(null, new KeyEventArgs(HandleKeyInput(wParam)));
|
||||
break;
|
||||
|
||||
case WM_KEYUP:
|
||||
if (KeyUp != null)
|
||||
KeyUp(null, new KeyEventArgs(HandleKeyInput(wParam)));
|
||||
break;
|
||||
|
||||
case WM_CHAR:
|
||||
if (CharEntered != null)
|
||||
CharEntered(null, new CharacterEventArgs((char)wParam, lParam.ToInt64()));
|
||||
break;
|
||||
|
||||
case WM_IME_SETCONTEXT:
|
||||
if (wParam.ToInt32() == 1)
|
||||
ImmAssociateContext(hWnd, hIMC);
|
||||
break;
|
||||
|
||||
case WM_INPUTLANGCHANGE:
|
||||
ImmAssociateContext(hWnd, hIMC);
|
||||
returnCode = (IntPtr)1;
|
||||
break;
|
||||
}
|
||||
|
||||
return returnCode;
|
||||
}
|
||||
|
||||
static Keys HandleKeyInput(IntPtr wParam)
|
||||
{
|
||||
// The conversion does not work for Shift or CTRL. Hence the hack.
|
||||
Keys key = (Keys)wParam;
|
||||
int k = (int)key;
|
||||
if (k == 16)
|
||||
{
|
||||
// Could also be RightShift
|
||||
key = Keys.LeftShift;
|
||||
}
|
||||
else if (k == 17)
|
||||
{
|
||||
// Could also be RightControl
|
||||
key = Keys.LeftControl;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,16 +82,5 @@ namespace EventInput
|
||||
value.Selected = true;
|
||||
}
|
||||
}
|
||||
|
||||
#if WINDOWS
|
||||
//Thread has to be in Single Thread Apartment state in order to receive clipboard
|
||||
string _pasteResult = "";
|
||||
[STAThread]
|
||||
void PasteThread()
|
||||
{
|
||||
_pasteResult = Clipboard.ContainsText() ? Clipboard.GetText() : "";
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ namespace Barotrauma
|
||||
{
|
||||
private static List<ScalableFont> FontList = new List<ScalableFont>();
|
||||
private static Library Lib = null;
|
||||
private static object mutex = new object();
|
||||
|
||||
private string filename;
|
||||
private Face face;
|
||||
@@ -63,33 +64,36 @@ namespace Barotrauma
|
||||
|
||||
public ScalableFont(string filename, uint size, GraphicsDevice gd = null, bool dynamicLoading = false)
|
||||
{
|
||||
if (Lib == null) Lib = new Library();
|
||||
this.filename = filename;
|
||||
this.face = null;
|
||||
foreach (ScalableFont font in FontList)
|
||||
lock (mutex)
|
||||
{
|
||||
if (font.filename == filename)
|
||||
if (Lib == null) Lib = new Library();
|
||||
this.filename = filename;
|
||||
this.face = null;
|
||||
foreach (ScalableFont font in FontList)
|
||||
{
|
||||
this.face = font.face;
|
||||
break;
|
||||
if (font.filename == filename)
|
||||
{
|
||||
this.face = font.face;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.face == null)
|
||||
{
|
||||
this.face = new Face(Lib, filename);
|
||||
}
|
||||
this.size = size;
|
||||
this.textures = new List<Texture2D>();
|
||||
this.texCoords = new Dictionary<uint, GlyphData>();
|
||||
this.DynamicLoading = dynamicLoading;
|
||||
this.graphicsDevice = gd;
|
||||
if (this.face == null)
|
||||
{
|
||||
this.face = new Face(Lib, filename);
|
||||
}
|
||||
this.size = size;
|
||||
this.textures = new List<Texture2D>();
|
||||
this.texCoords = new Dictionary<uint, GlyphData>();
|
||||
this.DynamicLoading = dynamicLoading;
|
||||
this.graphicsDevice = gd;
|
||||
|
||||
if (gd != null && !dynamicLoading)
|
||||
{
|
||||
RenderAtlas(gd);
|
||||
}
|
||||
if (gd != null && !dynamicLoading)
|
||||
{
|
||||
RenderAtlas(gd);
|
||||
}
|
||||
|
||||
FontList.Add(this);
|
||||
FontList.Add(this);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -112,7 +116,10 @@ namespace Barotrauma
|
||||
this.texDims = texDims;
|
||||
this.baseChar = baseChar;
|
||||
|
||||
face.SetPixelSizes(0, size);
|
||||
lock (mutex)
|
||||
{
|
||||
face.SetPixelSizes(0, size);
|
||||
}
|
||||
textures.ForEach(t => t.Dispose());
|
||||
textures.Clear();
|
||||
texCoords.Clear();
|
||||
@@ -123,14 +130,20 @@ namespace Barotrauma
|
||||
pixelBuffer[i] = 0;
|
||||
}
|
||||
|
||||
textures.Add(new Texture2D(gd, texDims, texDims, false, SurfaceFormat.Color));
|
||||
CrossThread.RequestExecutionOnMainThread(() =>
|
||||
{
|
||||
textures.Add(new Texture2D(gd, texDims, texDims, false, SurfaceFormat.Color));
|
||||
});
|
||||
int texIndex = 0;
|
||||
|
||||
Vector2 currentCoords = Vector2.Zero;
|
||||
int nextY = 0;
|
||||
|
||||
face.LoadGlyph(face.GetCharIndex(baseChar), LoadFlags.Default, LoadTarget.Normal);
|
||||
baseHeight = face.Glyph.Metrics.Height.ToInt32();
|
||||
lock (mutex)
|
||||
{
|
||||
face.LoadGlyph(face.GetCharIndex(baseChar), LoadFlags.Default, LoadTarget.Normal);
|
||||
baseHeight = face.Glyph.Metrics.Height.ToInt32();
|
||||
}
|
||||
//lineHeight = baseHeight;
|
||||
for (int i = 0; i < charRanges.Length; i += 2)
|
||||
{
|
||||
@@ -138,76 +151,85 @@ namespace Barotrauma
|
||||
uint end = charRanges[i + 1];
|
||||
for (uint j = start; j <= end; j++)
|
||||
{
|
||||
uint glyphIndex = face.GetCharIndex(j);
|
||||
if (glyphIndex == 0) continue;
|
||||
face.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Normal);
|
||||
if (face.Glyph.Metrics.Width == 0 || face.Glyph.Metrics.Height == 0)
|
||||
lock (mutex)
|
||||
{
|
||||
if (face.Glyph.Metrics.HorizontalAdvance > 0)
|
||||
uint glyphIndex = face.GetCharIndex(j);
|
||||
if (glyphIndex == 0) continue;
|
||||
face.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Normal);
|
||||
if (face.Glyph.Metrics.Width == 0 || face.Glyph.Metrics.Height == 0)
|
||||
{
|
||||
//glyph is empty, but char still applies advance
|
||||
GlyphData blankData = new GlyphData();
|
||||
blankData.advance = (float)face.Glyph.Metrics.HorizontalAdvance;
|
||||
blankData.texIndex = -1; //indicates no texture because the glyph is empty
|
||||
texCoords.Add(j, blankData);
|
||||
if (face.Glyph.Metrics.HorizontalAdvance > 0)
|
||||
{
|
||||
//glyph is empty, but char still applies advance
|
||||
GlyphData blankData = new GlyphData();
|
||||
blankData.advance = (float)face.Glyph.Metrics.HorizontalAdvance;
|
||||
blankData.texIndex = -1; //indicates no texture because the glyph is empty
|
||||
texCoords.Add(j, blankData);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
//stacktrace doesn't really work that well when RenderGlyph throws an exception
|
||||
face.Glyph.RenderGlyph(RenderMode.Normal);
|
||||
byte[] bitmap = face.Glyph.Bitmap.BufferData;
|
||||
int glyphWidth = face.Glyph.Bitmap.Width;
|
||||
int glyphHeight = bitmap.Length / glyphWidth;
|
||||
//stacktrace doesn't really work that well when RenderGlyph throws an exception
|
||||
face.Glyph.RenderGlyph(RenderMode.Normal);
|
||||
byte[] bitmap = face.Glyph.Bitmap.BufferData;
|
||||
int glyphWidth = face.Glyph.Bitmap.Width;
|
||||
int glyphHeight = bitmap.Length / glyphWidth;
|
||||
|
||||
//if (glyphHeight>lineHeight) lineHeight=glyphHeight;
|
||||
//if (glyphHeight>lineHeight) lineHeight=glyphHeight;
|
||||
|
||||
if (glyphWidth > texDims - 1 || glyphHeight > texDims - 1)
|
||||
{
|
||||
throw new Exception(filename + ", " + size.ToString() + ", "+ (char)j + "; Glyph dimensions exceed texture atlas dimensions");
|
||||
}
|
||||
|
||||
nextY = Math.Max(nextY, glyphHeight + 2);
|
||||
|
||||
if (currentCoords.X + glyphWidth + 2 > texDims - 1)
|
||||
{
|
||||
currentCoords.X = 0;
|
||||
currentCoords.Y += nextY;
|
||||
nextY = 0;
|
||||
}
|
||||
if (currentCoords.Y + glyphHeight + 2 > texDims - 1)
|
||||
{
|
||||
currentCoords.X = 0;
|
||||
currentCoords.Y = 0;
|
||||
textures[texIndex].SetData<uint>(pixelBuffer);
|
||||
textures.Add(new Texture2D(gd, texDims, texDims, false, SurfaceFormat.Color));
|
||||
texIndex++;
|
||||
for (int k = 0; k < texDims * texDims; k++)
|
||||
if (glyphWidth > texDims - 1 || glyphHeight > texDims - 1)
|
||||
{
|
||||
pixelBuffer[k] = 0;
|
||||
throw new Exception(filename + ", " + size.ToString() + ", " + (char)j + "; Glyph dimensions exceed texture atlas dimensions");
|
||||
}
|
||||
}
|
||||
|
||||
GlyphData newData = new GlyphData
|
||||
{
|
||||
advance = (float)face.Glyph.Metrics.HorizontalAdvance,
|
||||
texIndex = texIndex,
|
||||
texCoords = new Rectangle((int)currentCoords.X, (int)currentCoords.Y, glyphWidth, glyphHeight),
|
||||
drawOffset = new Vector2(face.Glyph.BitmapLeft, baseHeight * 14 / 10 - face.Glyph.BitmapTop)
|
||||
};
|
||||
texCoords.Add(j, newData);
|
||||
nextY = Math.Max(nextY, glyphHeight + 2);
|
||||
|
||||
for (int y = 0; y < glyphHeight; y++)
|
||||
{
|
||||
for (int x = 0; x < glyphWidth; x++)
|
||||
if (currentCoords.X + glyphWidth + 2 > texDims - 1)
|
||||
{
|
||||
byte byteColor = bitmap[x + y * glyphWidth];
|
||||
pixelBuffer[((int)currentCoords.X + x) + ((int)currentCoords.Y + y) * texDims] = (uint)(byteColor << 24 | byteColor << 16 | byteColor << 8 | byteColor);
|
||||
currentCoords.X = 0;
|
||||
currentCoords.Y += nextY;
|
||||
nextY = 0;
|
||||
}
|
||||
if (currentCoords.Y + glyphHeight + 2 > texDims - 1)
|
||||
{
|
||||
currentCoords.X = 0;
|
||||
currentCoords.Y = 0;
|
||||
CrossThread.RequestExecutionOnMainThread(() =>
|
||||
{
|
||||
textures[texIndex].SetData<uint>(pixelBuffer);
|
||||
textures.Add(new Texture2D(gd, texDims, texDims, false, SurfaceFormat.Color));
|
||||
});
|
||||
texIndex++;
|
||||
for (int k = 0; k < texDims * texDims; k++)
|
||||
{
|
||||
pixelBuffer[k] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
currentCoords.X += glyphWidth + 2;
|
||||
GlyphData newData = new GlyphData
|
||||
{
|
||||
advance = (float)face.Glyph.Metrics.HorizontalAdvance,
|
||||
texIndex = texIndex,
|
||||
texCoords = new Rectangle((int)currentCoords.X, (int)currentCoords.Y, glyphWidth, glyphHeight),
|
||||
drawOffset = new Vector2(face.Glyph.BitmapLeft, baseHeight * 14 / 10 - face.Glyph.BitmapTop)
|
||||
};
|
||||
texCoords.Add(j, newData);
|
||||
|
||||
for (int y = 0; y < glyphHeight; y++)
|
||||
{
|
||||
for (int x = 0; x < glyphWidth; x++)
|
||||
{
|
||||
byte byteColor = bitmap[x + y * glyphWidth];
|
||||
pixelBuffer[((int)currentCoords.X + x) + ((int)currentCoords.Y + y) * texDims] = (uint)(byteColor << 24 | byteColor << 16 | byteColor << 8 | byteColor);
|
||||
}
|
||||
}
|
||||
|
||||
currentCoords.X += glyphWidth + 2;
|
||||
}
|
||||
}
|
||||
textures[texIndex].SetData<uint>(pixelBuffer);
|
||||
CrossThread.RequestExecutionOnMainThread(() =>
|
||||
{
|
||||
textures[texIndex].SetData<uint>(pixelBuffer);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,7 +242,10 @@ namespace Barotrauma
|
||||
face.SetPixelSizes(0, size);
|
||||
face.LoadGlyph(face.GetCharIndex(baseChar), LoadFlags.Default, LoadTarget.Normal);
|
||||
baseHeight = face.Glyph.Metrics.Height.ToInt32();
|
||||
textures.Add(new Texture2D(gd, texDims, texDims, false, SurfaceFormat.Color));
|
||||
CrossThread.RequestExecutionOnMainThread(() =>
|
||||
{
|
||||
textures.Add(new Texture2D(gd, texDims, texDims, false, SurfaceFormat.Color));
|
||||
});
|
||||
}
|
||||
|
||||
uint glyphIndex = face.GetCharIndex(character);
|
||||
@@ -264,7 +289,10 @@ namespace Barotrauma
|
||||
currentDynamicAtlasCoords.X = 0;
|
||||
currentDynamicAtlasCoords.Y = 0;
|
||||
currentDynamicAtlasNextY = 0;
|
||||
textures.Add(new Texture2D(gd, texDims, texDims, false, SurfaceFormat.Color));
|
||||
CrossThread.RequestExecutionOnMainThread(() =>
|
||||
{
|
||||
textures.Add(new Texture2D(gd, texDims, texDims, false, SurfaceFormat.Color));
|
||||
});
|
||||
currentDynamicPixelBuffer = null;
|
||||
}
|
||||
|
||||
@@ -291,7 +319,10 @@ namespace Barotrauma
|
||||
currentDynamicPixelBuffer[((int)currentDynamicAtlasCoords.X + x) + ((int)currentDynamicAtlasCoords.Y + y) * texDims] = (uint)(byteColor << 24 | byteColor << 16 | byteColor << 8 | byteColor);
|
||||
}
|
||||
}
|
||||
textures[newData.texIndex].SetData<uint>(currentDynamicPixelBuffer);
|
||||
CrossThread.RequestExecutionOnMainThread(() =>
|
||||
{
|
||||
textures[newData.texIndex].SetData<uint>(currentDynamicPixelBuffer);
|
||||
});
|
||||
|
||||
currentDynamicAtlasCoords.X += glyphWidth + 2;
|
||||
}
|
||||
|
||||
@@ -184,8 +184,12 @@ namespace Barotrauma
|
||||
sounds[(int)GUISoundType.DropItem] = GameMain.SoundManager.LoadSound("Content/Sounds/DropItem.ogg", false);
|
||||
}
|
||||
// create 1x1 texture for line drawing
|
||||
t = new Texture2D(GraphicsDevice, 1, 1);
|
||||
t.SetData(new Color[] { Color.White });// fill the texture with white
|
||||
CrossThread.RequestExecutionOnMainThread(() =>
|
||||
{
|
||||
t = new Texture2D(GraphicsDevice, 1, 1);
|
||||
t.SetData(new Color[] { Color.White });// fill the texture with white
|
||||
});
|
||||
|
||||
SubmarineIcon = new Sprite("Content/UI/IconAtlas.png", new Rectangle(452, 385, 182, 81), new Vector2(0.5f, 0.5f));
|
||||
arrow = new Sprite("Content/UI/IconAtlas.png", new Rectangle(392, 393, 49, 45), new Vector2(0.5f, 0.5f));
|
||||
SpeechBubbleIcon = new Sprite("Content/UI/IconAtlas.png", new Rectangle(385, 449, 66, 60), new Vector2(0.5f, 0.5f));
|
||||
@@ -948,7 +952,6 @@ namespace Barotrauma
|
||||
public static Texture2D CreateCircle(int radius, bool filled = false)
|
||||
{
|
||||
int outerRadius = radius * 2 + 2; // So circle doesn't go out of bounds
|
||||
Texture2D texture = new Texture2D(GraphicsDevice, outerRadius, outerRadius);
|
||||
|
||||
Color[] data = new Color[outerRadius * outerRadius];
|
||||
|
||||
@@ -986,16 +989,19 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
texture.SetData(data);
|
||||
Texture2D texture = null;
|
||||
CrossThread.RequestExecutionOnMainThread(() =>
|
||||
{
|
||||
texture = new Texture2D(GraphicsDevice, outerRadius, outerRadius);
|
||||
texture.SetData(data);
|
||||
});
|
||||
return texture;
|
||||
}
|
||||
|
||||
public static Texture2D CreateCapsule(int radius, int height)
|
||||
{
|
||||
int textureWidth = radius * 2, textureHeight = height + radius * 2;
|
||||
|
||||
Texture2D texture = new Texture2D(GraphicsDevice, textureWidth, textureHeight);
|
||||
|
||||
Color[] data = new Color[textureWidth * textureHeight];
|
||||
|
||||
// Colour the entire texture transparent first.
|
||||
@@ -1023,13 +1029,17 @@ namespace Barotrauma
|
||||
TrySetArray(data, y * textureWidth + (textureWidth - 1), Color.White);
|
||||
}
|
||||
|
||||
texture.SetData(data);
|
||||
Texture2D texture = null;
|
||||
CrossThread.RequestExecutionOnMainThread(() =>
|
||||
{
|
||||
texture = new Texture2D(GraphicsDevice, textureWidth, textureHeight);
|
||||
texture.SetData(data);
|
||||
});
|
||||
return texture;
|
||||
}
|
||||
|
||||
public static Texture2D CreateRectangle(int width, int height)
|
||||
{
|
||||
Texture2D texture = new Texture2D(GraphicsDevice, width, height);
|
||||
Color[] data = new Color[width * height];
|
||||
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
@@ -1047,7 +1057,13 @@ namespace Barotrauma
|
||||
TrySetArray(data, (height - 1) * width + x, Color.White);
|
||||
}
|
||||
|
||||
texture.SetData(data);
|
||||
|
||||
Texture2D texture = null;
|
||||
CrossThread.RequestExecutionOnMainThread(() =>
|
||||
{
|
||||
texture = new Texture2D(GraphicsDevice, width, height);
|
||||
texture.SetData(data);
|
||||
});
|
||||
return texture;
|
||||
}
|
||||
|
||||
|
||||
@@ -58,7 +58,6 @@ namespace Barotrauma
|
||||
|
||||
private bool isSelecting;
|
||||
private string selectedText = string.Empty;
|
||||
private string clipboard = string.Empty;
|
||||
private int selectedCharacters;
|
||||
private int selectionStartIndex;
|
||||
private int selectionEndIndex;
|
||||
@@ -777,11 +776,7 @@ namespace Barotrauma
|
||||
|
||||
private void CopySelectedText()
|
||||
{
|
||||
#if WINDOWS
|
||||
System.Windows.Clipboard.SetText(selectedText);
|
||||
#else
|
||||
clipboard = selectedText;
|
||||
#endif
|
||||
Clipboard.SetText(selectedText);
|
||||
}
|
||||
|
||||
private void ClearSelection()
|
||||
@@ -795,11 +790,8 @@ namespace Barotrauma
|
||||
private string GetCopiedText()
|
||||
{
|
||||
string t;
|
||||
#if WINDOWS
|
||||
t = System.Windows.Clipboard.GetText();
|
||||
#else
|
||||
t = clipboard;
|
||||
#endif
|
||||
t = Clipboard.GetText();
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,8 +18,11 @@ namespace Barotrauma
|
||||
{
|
||||
if (_whitePixelTexture == null)
|
||||
{
|
||||
_whitePixelTexture = new Texture2D(spriteBatch.GraphicsDevice, 1, 1, false, SurfaceFormat.Color);
|
||||
_whitePixelTexture.SetData(new[] { Color.White });
|
||||
CrossThread.RequestExecutionOnMainThread(() =>
|
||||
{
|
||||
_whitePixelTexture = new Texture2D(spriteBatch.GraphicsDevice, 1, 1, false, SurfaceFormat.Color);
|
||||
_whitePixelTexture.SetData(new[] { Color.White });
|
||||
});
|
||||
}
|
||||
|
||||
return _whitePixelTexture;
|
||||
|
||||
@@ -48,6 +48,8 @@ namespace Barotrauma
|
||||
|
||||
public static Sounds.SoundManager SoundManager;
|
||||
|
||||
public static Thread MainThread { get; private set; }
|
||||
|
||||
public static HashSet<ContentPackage> SelectedPackages
|
||||
{
|
||||
get { return Config?.SelectedContentPackages; }
|
||||
@@ -183,6 +185,8 @@ namespace Barotrauma
|
||||
FarseerPhysics.Settings.ContinuousPhysics = false;
|
||||
FarseerPhysics.Settings.VelocityIterations = 1;
|
||||
FarseerPhysics.Settings.PositionIterations = 1;
|
||||
|
||||
MainThread = Thread.CurrentThread;
|
||||
}
|
||||
|
||||
public void ApplyGraphicsSettings()
|
||||
@@ -220,8 +224,20 @@ namespace Barotrauma
|
||||
|
||||
GraphicsDeviceManager.PreferredBackBufferWidth = GraphicsWidth;
|
||||
GraphicsDeviceManager.PreferredBackBufferHeight = GraphicsHeight;
|
||||
|
||||
|
||||
GraphicsDeviceManager.ApplyChanges();
|
||||
|
||||
if (windowMode == WindowMode.BorderlessWindowed)
|
||||
{
|
||||
GraphicsWidth = GraphicsDevice.PresentationParameters.Bounds.Width;
|
||||
GraphicsHeight = GraphicsDevice.PresentationParameters.Bounds.Height;
|
||||
GraphicsDevice.Viewport = new Viewport(0,0,GraphicsWidth,GraphicsHeight);
|
||||
GraphicsDevice.ScissorRectangle = new Rectangle(0,0,GraphicsWidth,GraphicsHeight);
|
||||
GraphicsDeviceManager.PreferredBackBufferWidth = GraphicsWidth;
|
||||
GraphicsDeviceManager.PreferredBackBufferHeight = GraphicsHeight;
|
||||
|
||||
GraphicsDeviceManager.ApplyChanges();
|
||||
}
|
||||
}
|
||||
|
||||
public void ResetViewPort()
|
||||
@@ -272,10 +288,9 @@ namespace Barotrauma
|
||||
WaitForLanguageSelection = Config.ShowLanguageSelectionPrompt
|
||||
};
|
||||
|
||||
bool canLoadInSeparateThread = false;
|
||||
#if WINDOWS
|
||||
canLoadInSeparateThread = true;
|
||||
#endif
|
||||
bool canLoadInSeparateThread = true;
|
||||
|
||||
ApplyGraphicsSettings();
|
||||
|
||||
loadingCoroutine = CoroutineManager.StartCoroutine(Load(canLoadInSeparateThread), "Load", canLoadInSeparateThread);
|
||||
}
|
||||
@@ -578,6 +593,9 @@ namespace Barotrauma
|
||||
//otherwise it snowballs and becomes unplayable
|
||||
Timing.Accumulator = Timing.Step;
|
||||
}
|
||||
|
||||
CrossThread.ProcessTasks();
|
||||
|
||||
PlayerInput.UpdateVariable();
|
||||
|
||||
bool paused = true;
|
||||
|
||||
@@ -20,8 +20,8 @@ namespace Barotrauma
|
||||
/// </summary>
|
||||
const float CharacterWaitOnSwitch = 10.0f;
|
||||
|
||||
private List<CharacterInfo> characterInfos = new List<CharacterInfo>();
|
||||
private List<Character> characters = new List<Character>();
|
||||
private readonly List<CharacterInfo> characterInfos = new List<CharacterInfo>();
|
||||
private readonly List<Character> characters = new List<Character>();
|
||||
|
||||
private Point screenResolution;
|
||||
|
||||
@@ -1318,7 +1318,7 @@ namespace Barotrauma
|
||||
GUIComponent existingPreview = crewFrame.FindChild("SelectedCharacter");
|
||||
if (existingPreview != null) crewFrame.RemoveChild(existingPreview);
|
||||
|
||||
var previewPlayer = new GUIFrame(new RectTransform(new Vector2(0.4f, 0.8f), crewFrame.RectTransform, Anchor.CenterRight) { RelativeOffset = new Vector2(0.05f, 0.0f) }, style: "InnerFrame")
|
||||
var previewPlayer = new GUIFrame(new RectTransform(new Vector2(0.45f, 0.9f), crewFrame.RectTransform, Anchor.CenterRight) { RelativeOffset = new Vector2(0.05f, 0.0f) }, style: "InnerFrame")
|
||||
{
|
||||
UserData = "SelectedCharacter"
|
||||
};
|
||||
|
||||
@@ -186,46 +186,39 @@ namespace Barotrauma
|
||||
var rightColumn = new GUILayoutGroup(new RectTransform(new Vector2(0.46f, 0.95f), tabs[(int)Tab.Graphics].RectTransform, Anchor.TopRight)
|
||||
{ RelativeOffset = new Vector2(0.025f, 0.02f) })
|
||||
{ RelativeSpacing = 0.01f };
|
||||
|
||||
var supportedDisplayModes = new List<DisplayMode>();
|
||||
foreach (DisplayMode mode in GraphicsAdapter.DefaultAdapter.SupportedDisplayModes)
|
||||
{
|
||||
if (supportedDisplayModes.Any(m => m.Width == mode.Width && m.Height == mode.Height)) { continue; }
|
||||
#if OSX
|
||||
// Monogame currently doesn't support retina displays
|
||||
// so we need to disable resolutions above the viewport size.
|
||||
|
||||
// In a bundled .app you just disable HiDPI in the info.plist
|
||||
// but that's probably not gonna happen.
|
||||
if (mode.Width > GameMain.Instance.GraphicsDevice.DisplayMode.Width || mode.Height > GameMain.Instance.GraphicsDevice.DisplayMode.Height) { continue; }
|
||||
#endif
|
||||
supportedDisplayModes.Add(mode);
|
||||
}
|
||||
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), TextManager.Get("Resolution"));
|
||||
var resolutionDD = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), elementCount: supportedDisplayModes.Count)
|
||||
var resolutionDD = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform))
|
||||
{
|
||||
OnSelected = SelectResolution,
|
||||
#if !LINUX
|
||||
ButtonEnabled = GameMain.Config.WindowMode == WindowMode.Windowed
|
||||
#endif
|
||||
};
|
||||
|
||||
foreach (DisplayMode mode in supportedDisplayModes)
|
||||
{
|
||||
if (mode.Width < MinSupportedResolution.X || mode.Height < MinSupportedResolution.Y) { continue; }
|
||||
resolutionDD.AddItem(mode.Width + "x" + mode.Height, mode);
|
||||
if (GraphicsWidth == mode.Width && GraphicsHeight == mode.Height) resolutionDD.SelectItem(mode);
|
||||
}
|
||||
|
||||
if (resolutionDD.SelectedItemData == null)
|
||||
{
|
||||
resolutionDD.SelectItem(GraphicsAdapter.DefaultAdapter.SupportedDisplayModes.Last());
|
||||
}
|
||||
ButtonEnabled = GameMain.Config.WindowMode != WindowMode.BorderlessWindowed
|
||||
};
|
||||
|
||||
var supportedDisplayModes = UpdateResolutionDD(resolutionDD);
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), TextManager.Get("DisplayMode"));
|
||||
var displayModeDD = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform));
|
||||
|
||||
displayModeDD.OnSelected = (guiComponent, obj) =>
|
||||
{
|
||||
UnsavedSettings = true;
|
||||
GameMain.Config.WindowMode = (WindowMode)guiComponent.UserData;
|
||||
supportedDisplayModes = UpdateResolutionDD(resolutionDD);
|
||||
resolutionDD.ButtonEnabled = GameMain.Config.WindowMode != WindowMode.BorderlessWindowed;
|
||||
GameMain.Instance.ApplyGraphicsSettings();
|
||||
if (GameMain.Config.WindowMode == WindowMode.BorderlessWindowed)
|
||||
{
|
||||
GraphicsWidth = GameMain.GraphicsWidth;
|
||||
GraphicsHeight = GameMain.GraphicsHeight;
|
||||
var displayMode = supportedDisplayModes.Find(m => m.Width == GameMain.GraphicsWidth && m.Height == GameMain.GraphicsHeight);
|
||||
if (displayMode != null)
|
||||
{
|
||||
resolutionDD.SelectItem(displayMode);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
displayModeDD.AddItem(TextManager.Get("Fullscreen"), WindowMode.Fullscreen);
|
||||
displayModeDD.AddItem(TextManager.Get("Windowed"), WindowMode.Windowed);
|
||||
#if (!OSX)
|
||||
@@ -242,15 +235,6 @@ namespace Barotrauma
|
||||
displayModeDD.SelectItem(GameMain.Config.WindowMode);
|
||||
}
|
||||
#endif
|
||||
displayModeDD.OnSelected = (guiComponent, obj) =>
|
||||
{
|
||||
UnsavedSettings = true;
|
||||
GameMain.Config.WindowMode = (WindowMode)guiComponent.UserData;
|
||||
#if !LINUX
|
||||
resolutionDD.ButtonEnabled = GameMain.Config.WindowMode == WindowMode.Windowed;
|
||||
#endif
|
||||
return true;
|
||||
};
|
||||
|
||||
GUITickBox vsyncTickBox = new GUITickBox(new RectTransform(tickBoxScale, leftColumn.RectTransform, scaleBasis: ScaleBasis.BothHeight), TextManager.Get("EnableVSync"))
|
||||
{
|
||||
@@ -811,6 +795,62 @@ namespace Barotrauma
|
||||
SelectTab(selectedTab);
|
||||
}
|
||||
|
||||
private List<DisplayMode> UpdateResolutionDD(GUIDropDown resolutionDD)
|
||||
{
|
||||
var supportedDisplayModes = new List<DisplayMode>();
|
||||
foreach (DisplayMode mode in GraphicsAdapter.DefaultAdapter.SupportedDisplayModes)
|
||||
{
|
||||
if (supportedDisplayModes.Any(m => m.Width == mode.Width && m.Height == mode.Height)) { continue; }
|
||||
#if OSX
|
||||
// Monogame currently doesn't support retina displays
|
||||
// so we need to disable resolutions above the viewport size.
|
||||
|
||||
// In a bundled .app you just disable HiDPI in the info.plist
|
||||
// but that's probably not gonna happen.
|
||||
if (mode.Width > GameMain.Instance.GraphicsDevice.DisplayMode.Width || mode.Height > GameMain.Instance.GraphicsDevice.DisplayMode.Height) { continue; }
|
||||
#endif
|
||||
supportedDisplayModes.Add(mode);
|
||||
}
|
||||
supportedDisplayModes.Sort((a, b) =>
|
||||
{
|
||||
if (a.Width < b.Width)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (a.Width > b.Width)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (a.Height < b.Height)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (a.Height > b.Height)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
resolutionDD.ClearChildren();
|
||||
|
||||
foreach (DisplayMode mode in supportedDisplayModes)
|
||||
{
|
||||
if (mode.Width < MinSupportedResolution.X || mode.Height < MinSupportedResolution.Y) { continue; }
|
||||
resolutionDD.AddItem(mode.Width + "x" + mode.Height, mode);
|
||||
if (GraphicsWidth == mode.Width && GraphicsHeight == mode.Height) resolutionDD.SelectItem(mode);
|
||||
}
|
||||
|
||||
if (resolutionDD.SelectedItemData == null)
|
||||
{
|
||||
resolutionDD.SelectItem(GraphicsAdapter.DefaultAdapter.SupportedDisplayModes.Last());
|
||||
}
|
||||
|
||||
resolutionDD.ListBox.RectTransform.Resize(new Point(resolutionDD.Rect.Width, resolutionDD.Rect.Height * MathHelper.Clamp(supportedDisplayModes.Count, 2, 10)));
|
||||
|
||||
return supportedDisplayModes;
|
||||
}
|
||||
|
||||
private string TrimAudioDeviceName(string name)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(name)) { return string.Empty; }
|
||||
@@ -1024,12 +1064,12 @@ namespace Barotrauma
|
||||
|
||||
SettingsFrame.Flash(Color.Green);
|
||||
|
||||
if (GameMain.WindowMode != GameMain.Config.WindowMode)
|
||||
if (GameMain.WindowMode != GameMain.Config.WindowMode || GameMain.Config.GraphicsWidth != GameMain.GraphicsWidth || GameMain.Config.GraphicsHeight != GameMain.GraphicsHeight)
|
||||
{
|
||||
GameMain.Instance.ApplyGraphicsSettings();
|
||||
}
|
||||
|
||||
if (GameMain.GraphicsWidth != GameMain.Config.GraphicsWidth || GameMain.GraphicsHeight != GameMain.Config.GraphicsHeight)
|
||||
/*if (GameMain.GraphicsWidth != GameMain.Config.GraphicsWidth || GameMain.GraphicsHeight != GameMain.Config.GraphicsHeight)
|
||||
{
|
||||
#if OSX
|
||||
if (GameMain.Config.WindowMode != WindowMode.BorderlessWindowed)
|
||||
@@ -1039,7 +1079,7 @@ namespace Barotrauma
|
||||
#if OSX
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
private bool ApplyClicked(GUIButton button, object userData)
|
||||
|
||||
@@ -290,6 +290,8 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private void DrawGraph(SpriteBatch spriteBatch, GUICustomComponent container)
|
||||
{
|
||||
if (item.Removed) { return; }
|
||||
|
||||
Rectangle graphArea = new Rectangle(container.Rect.X + 30, container.Rect.Y, container.Rect.Width - 30, container.Rect.Height);
|
||||
|
||||
float maxLoad = loadGraph.Max();
|
||||
@@ -359,6 +361,8 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private void DrawFissionRateMeter(SpriteBatch spriteBatch, GUICustomComponent container)
|
||||
{
|
||||
if (item.Removed) { return; }
|
||||
|
||||
Rectangle prevScissorRect = spriteBatch.GraphicsDevice.ScissorRectangle;
|
||||
spriteBatch.End();
|
||||
spriteBatch.GraphicsDevice.ScissorRectangle = container.Rect;
|
||||
@@ -384,6 +388,8 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private void DrawTurbineOutputMeter(SpriteBatch spriteBatch, GUICustomComponent container)
|
||||
{
|
||||
if (item.Removed) { return; }
|
||||
|
||||
DrawMeter(spriteBatch, container.Rect,
|
||||
turbineOutputMeter, TurbineOutput, new Vector2(0.0f, 100.0f), optimalTurbineOutput, allowedTurbineOutput);
|
||||
}
|
||||
@@ -514,7 +520,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
Vector2 newPoint = new Vector2(currX, rect.Bottom - graph[i] * yScale);
|
||||
|
||||
if (graphLine == null)
|
||||
if (graphLine?.Texture == null)
|
||||
{
|
||||
GUI.DrawLine(spriteBatch, prevPoint, newPoint - new Vector2(1.0f, 0), color);
|
||||
}
|
||||
@@ -530,7 +536,7 @@ namespace Barotrauma.Items.Components
|
||||
Vector2 lastPoint = new Vector2(rect.X,
|
||||
rect.Bottom - (graph[graph.Count - 1] + (graph[graph.Count - 2] - graph[graph.Count - 1]) * xOffset) * yScale);
|
||||
|
||||
if (graphLine == null)
|
||||
if (graphLine?.Texture == null)
|
||||
{
|
||||
GUI.DrawLine(spriteBatch, prevPoint, lastPoint, color);
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
ProgressGetter = () =>
|
||||
{
|
||||
return charge / capacity;
|
||||
return capacity <= 0.0f ? 1.0f : charge / capacity;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
base.Update(deltaTime, cam);
|
||||
|
||||
if (equipper == null)
|
||||
if (equipper == null || equipper.Removed)
|
||||
{
|
||||
IsActive = false;
|
||||
return;
|
||||
|
||||
@@ -620,6 +620,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (DraggingItemToWorld &&
|
||||
Character.Controlled.FocusedItem?.OwnInventory != null &&
|
||||
Character.Controlled.FocusedItem.OwnInventory.CanBePut(draggingItem) &&
|
||||
Character.Controlled.FocusedItem.OwnInventory.TryPutItem(draggingItem, Character.Controlled))
|
||||
{
|
||||
GUI.PlayUISound(GUISoundType.PickItem);
|
||||
|
||||
@@ -451,7 +451,7 @@ namespace Barotrauma
|
||||
|
||||
public override void UpdateEditing(Camera cam)
|
||||
{
|
||||
if (editingHUD == null || editingHUD.UserData as Item != this)
|
||||
if (editingHUD == null || editingHUD.UserData == null)
|
||||
{
|
||||
editingHUD = CreateEditingHUD(Screen.Selected != GameMain.SubEditorScreen);
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ namespace Barotrauma
|
||||
center.Y -= center.Y % Submarine.GridSize.Y;
|
||||
|
||||
MapEntity.SelectedList.Clear();
|
||||
MapEntity.SelectedList.AddRange(assemblyEntities);
|
||||
assemblyEntities.ForEach(e => MapEntity.AddSelection(e));
|
||||
|
||||
foreach (MapEntity mapEntity in assemblyEntities)
|
||||
{
|
||||
|
||||
@@ -142,24 +142,27 @@ namespace Barotrauma
|
||||
backgroundPos.Y = -backgroundPos.Y;
|
||||
backgroundPos *= 0.05f;
|
||||
|
||||
|
||||
if (backgroundPos.Y < 1024)
|
||||
if (level.GenerationParams.BackgroundTopSprite != null)
|
||||
{
|
||||
if (backgroundPos.Y < 0 && level.GenerationParams.BackgroundTopSprite != null)
|
||||
int backgroundSize = (int)level.GenerationParams.BackgroundTopSprite.size.Y;
|
||||
if (backgroundPos.Y < backgroundSize)
|
||||
{
|
||||
var backgroundTop = level.GenerationParams.BackgroundTopSprite;
|
||||
backgroundTop.SourceRect = new Rectangle((int)backgroundPos.X, (int)backgroundPos.Y, 1024, (int)Math.Min(-backgroundPos.Y, 1024));
|
||||
backgroundTop.DrawTiled(spriteBatch, Vector2.Zero, new Vector2(GameMain.GraphicsWidth, Math.Min(-backgroundPos.Y, GameMain.GraphicsHeight)),
|
||||
color: level.BackgroundTextureColor);
|
||||
}
|
||||
if (backgroundPos.Y > -1024 && level.GenerationParams.BackgroundSprite != null)
|
||||
{
|
||||
var background = level.GenerationParams.BackgroundSprite;
|
||||
background.SourceRect = new Rectangle((int)backgroundPos.X, (int)Math.Max(backgroundPos.Y, 0), 1024, 1024);
|
||||
background.DrawTiled(spriteBatch,
|
||||
(backgroundPos.Y < 0) ? new Vector2(0.0f, (int)-backgroundPos.Y) : Vector2.Zero,
|
||||
new Vector2(GameMain.GraphicsWidth, (int)Math.Ceiling(1024 - backgroundPos.Y)),
|
||||
color: level.BackgroundTextureColor);
|
||||
if (backgroundPos.Y < 0)
|
||||
{
|
||||
var backgroundTop = level.GenerationParams.BackgroundTopSprite;
|
||||
backgroundTop.SourceRect = new Rectangle((int)backgroundPos.X, (int)backgroundPos.Y, backgroundSize, (int)Math.Min(-backgroundPos.Y, backgroundSize));
|
||||
backgroundTop.DrawTiled(spriteBatch, Vector2.Zero, new Vector2(GameMain.GraphicsWidth, Math.Min(-backgroundPos.Y, GameMain.GraphicsHeight)),
|
||||
color: level.BackgroundTextureColor);
|
||||
}
|
||||
if (-backgroundPos.Y < GameMain.GraphicsHeight && level.GenerationParams.BackgroundSprite != null)
|
||||
{
|
||||
var background = level.GenerationParams.BackgroundSprite;
|
||||
background.SourceRect = new Rectangle((int)backgroundPos.X, (int)Math.Max(backgroundPos.Y, 0), backgroundSize, backgroundSize);
|
||||
background.DrawTiled(spriteBatch,
|
||||
(backgroundPos.Y < 0) ? new Vector2(0.0f, (int)-backgroundPos.Y) : Vector2.Zero,
|
||||
new Vector2(GameMain.GraphicsWidth, (int)Math.Min(Math.Ceiling(backgroundSize - backgroundPos.Y), backgroundSize)),
|
||||
color: level.BackgroundTextureColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -81,29 +81,33 @@ namespace Barotrauma.Lights
|
||||
visionCircle = Sprite.LoadTexture("Content/Lights/visioncircle.png", preMultiplyAlpha: false);
|
||||
highlightRaster = Sprite.LoadTexture("Content/UI/HighlightRaster.png", preMultiplyAlpha: false);
|
||||
|
||||
CreateRenderTargets(graphics);
|
||||
GameMain.Instance.OnResolutionChanged += () =>
|
||||
{
|
||||
CreateRenderTargets(graphics);
|
||||
};
|
||||
|
||||
CrossThread.RequestExecutionOnMainThread(() =>
|
||||
{
|
||||
CreateRenderTargets(graphics);
|
||||
|
||||
#if WINDOWS
|
||||
LosEffect = content.Load<Effect>("Effects/losshader");
|
||||
SolidColorEffect = content.Load<Effect>("Effects/solidcolor");
|
||||
LosEffect = content.Load<Effect>("Effects/losshader");
|
||||
SolidColorEffect = content.Load<Effect>("Effects/solidcolor");
|
||||
#else
|
||||
LosEffect = content.Load<Effect>("Effects/losshader_opengl");
|
||||
SolidColorEffect = content.Load<Effect>("Effects/solidcolor_opengl");
|
||||
LosEffect = content.Load<Effect>("Effects/losshader_opengl");
|
||||
SolidColorEffect = content.Load<Effect>("Effects/solidcolor_opengl");
|
||||
#endif
|
||||
|
||||
if (lightEffect == null)
|
||||
{
|
||||
lightEffect = new BasicEffect(GameMain.Instance.GraphicsDevice)
|
||||
if (lightEffect == null)
|
||||
{
|
||||
VertexColorEnabled = true,
|
||||
TextureEnabled = true,
|
||||
Texture = LightSource.LightTexture
|
||||
};
|
||||
}
|
||||
lightEffect = new BasicEffect(GameMain.Instance.GraphicsDevice)
|
||||
{
|
||||
VertexColorEnabled = true,
|
||||
TextureEnabled = true,
|
||||
Texture = LightSource.LightTexture
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
hullAmbientLights = new Dictionary<Hull, Color>();
|
||||
smoothedHullAmbientLights = new Dictionary<Hull, Color>();
|
||||
|
||||
@@ -137,8 +137,11 @@ namespace Barotrauma
|
||||
{
|
||||
if (noiseTexture == null)
|
||||
{
|
||||
noiseTexture = new Texture2D(GameMain.Instance.GraphicsDevice, generationParams.NoiseResolution, generationParams.NoiseResolution);
|
||||
rawNoiseTexture = new Texture2D(GameMain.Instance.GraphicsDevice, generationParams.NoiseResolution, generationParams.NoiseResolution);
|
||||
CrossThread.RequestExecutionOnMainThread(() =>
|
||||
{
|
||||
noiseTexture = new Texture2D(GameMain.Instance.GraphicsDevice, generationParams.NoiseResolution, generationParams.NoiseResolution);
|
||||
rawNoiseTexture = new Texture2D(GameMain.Instance.GraphicsDevice, generationParams.NoiseResolution, generationParams.NoiseResolution);
|
||||
});
|
||||
rawNoiseSprite = new Sprite(rawNoiseTexture, null, null);
|
||||
}
|
||||
|
||||
@@ -221,8 +224,11 @@ namespace Barotrauma
|
||||
Color.Lerp(noiseTextureData[i], pathColor, crackTextureData[i].A / 255.0f * 0.5f);
|
||||
}
|
||||
|
||||
noiseTexture.SetData(noiseTextureData);
|
||||
rawNoiseTexture.SetData(rawNoiseTextureData);
|
||||
CrossThread.RequestExecutionOnMainThread(() =>
|
||||
{
|
||||
noiseTexture.SetData(noiseTextureData);
|
||||
rawNoiseTexture.SetData(rawNoiseTextureData);
|
||||
});
|
||||
}
|
||||
|
||||
private void LocationChanged(Location prevLocation, Location newLocation)
|
||||
|
||||
@@ -367,14 +367,19 @@ namespace Barotrauma
|
||||
foreach (MapEntity e in newSelection)
|
||||
{
|
||||
if (selectedList.Contains(e))
|
||||
selectedList.Remove(e);
|
||||
{
|
||||
RemoveSelection(e);
|
||||
}
|
||||
else
|
||||
selectedList.Add(e);
|
||||
{
|
||||
AddSelection(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
selectedList = newSelection;
|
||||
selectedList.Clear();
|
||||
newSelection.ForEach(e => AddSelection(e));
|
||||
}
|
||||
|
||||
//select wire if both items it's connected to are selected
|
||||
@@ -457,9 +462,13 @@ namespace Barotrauma
|
||||
PlayerInput.KeyDown(Keys.RightControl))
|
||||
{
|
||||
if (selectedList.Contains(entity))
|
||||
selectedList.Remove(entity);
|
||||
{
|
||||
RemoveSelection(entity);
|
||||
}
|
||||
else
|
||||
selectedList.Add(entity);
|
||||
{
|
||||
AddSelection(entity);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -469,6 +478,60 @@ namespace Barotrauma
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
public static void AddSelection(MapEntity entity)
|
||||
{
|
||||
if (selectedList.Contains(entity)) { return; }
|
||||
selectedList.Add(entity);
|
||||
HandleDoorGapLinks(entity,
|
||||
onGapFound: (door, gap) =>
|
||||
{
|
||||
door.RefreshLinkedGap();
|
||||
if (!selectedList.Contains(gap))
|
||||
{
|
||||
selectedList.Add(gap);
|
||||
}
|
||||
},
|
||||
onDoorFound: (door, gap) =>
|
||||
{
|
||||
if (!selectedList.Contains(door.Item))
|
||||
{
|
||||
selectedList.Add(door.Item);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void HandleDoorGapLinks(MapEntity entity, Action<Door, Gap> onGapFound, Action<Door, Gap> onDoorFound)
|
||||
{
|
||||
if (entity is Item i)
|
||||
{
|
||||
var door = i.GetComponent<Door>();
|
||||
if (door != null)
|
||||
{
|
||||
var gap = door.LinkedGap;
|
||||
if (gap != null)
|
||||
{
|
||||
onGapFound(door, gap);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (entity is Gap gap)
|
||||
{
|
||||
var door = gap.ConnectedDoor;
|
||||
if (door != null)
|
||||
{
|
||||
onDoorFound(door, gap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void RemoveSelection(MapEntity entity)
|
||||
{
|
||||
selectedList.Remove(entity);
|
||||
HandleDoorGapLinks(entity,
|
||||
onGapFound: (door, gap) => selectedList.Remove(gap),
|
||||
onDoorFound: (door, gap) => selectedList.Remove(door.Item));
|
||||
}
|
||||
|
||||
static partial void UpdateAllProjSpecific(float deltaTime)
|
||||
{
|
||||
@@ -533,13 +596,15 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public static List<MapEntity> FilteredSelectedList { get; private set; } = new List<MapEntity>();
|
||||
|
||||
public static void UpdateEditor(Camera cam)
|
||||
{
|
||||
if (highlightedListBox != null) highlightedListBox.UpdateManually((float)Timing.Step);
|
||||
|
||||
if (editingHUD != null)
|
||||
{
|
||||
if (selectedList.Count == 0 || editingHUD.UserData != selectedList[0])
|
||||
if (FilteredSelectedList.Count == 0 || editingHUD.UserData != FilteredSelectedList[0])
|
||||
{
|
||||
foreach (GUIComponent component in editingHUD.Children)
|
||||
{
|
||||
@@ -550,15 +615,20 @@ namespace Barotrauma
|
||||
editingHUD = null;
|
||||
}
|
||||
}
|
||||
|
||||
FilteredSelectedList.Clear();
|
||||
if (selectedList.Count == 0) return;
|
||||
|
||||
if (selectedList.Count == 1)
|
||||
foreach (var e in selectedList)
|
||||
{
|
||||
selectedList[0].UpdateEditing(cam);
|
||||
if (selectedList[0].ResizeHorizontal || selectedList[0].ResizeVertical)
|
||||
if (e is Gap) { continue; }
|
||||
FilteredSelectedList.Add(e);
|
||||
}
|
||||
var first = FilteredSelectedList.FirstOrDefault();
|
||||
if (first != null)
|
||||
{
|
||||
first.UpdateEditing(cam);
|
||||
if (first.ResizeHorizontal || first.ResizeVertical)
|
||||
{
|
||||
selectedList[0].UpdateResizing(cam);
|
||||
first.UpdateResizing(cam);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -622,12 +692,10 @@ namespace Barotrauma
|
||||
selectedList.Clear();
|
||||
}
|
||||
|
||||
|
||||
public static void SelectEntity(MapEntity entity)
|
||||
{
|
||||
DeselectAll();
|
||||
|
||||
selectedList.Add(entity);
|
||||
AddSelection(entity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -30,43 +30,14 @@ namespace Barotrauma
|
||||
return HasBody ? ShowWalls : ShowStructures;;
|
||||
}
|
||||
}
|
||||
|
||||
// Only for testing in the debug build. Not saved.
|
||||
protected Vector2 textureScale = Vector2.One;
|
||||
|
||||
[Editable(DecimalCount = 3, MinValueFloat = 0.01f, MaxValueFloat = 10f, ValueStep = 0.1f), Serialize("1.0, 1.0", false)]
|
||||
public Vector2 TextureScale
|
||||
{
|
||||
get { return textureScale; }
|
||||
set
|
||||
{
|
||||
textureScale = new Vector2(
|
||||
MathHelper.Clamp(value.X, 0.01f, 10),
|
||||
MathHelper.Clamp(value.Y, 0.01f, 10));
|
||||
}
|
||||
}
|
||||
|
||||
private string specialTag;
|
||||
[Editable, Serialize("", true)]
|
||||
public string SpecialTag
|
||||
{
|
||||
get { return specialTag; }
|
||||
set { specialTag = value; }
|
||||
}
|
||||
|
||||
// Only for testing in the debug build. Not saved.
|
||||
#if DEBUG
|
||||
[Editable, Serialize(true, false)]
|
||||
#endif
|
||||
public bool DrawTiled { get; protected set; } = true;
|
||||
|
||||
protected Vector2 textureOffset = Vector2.Zero;
|
||||
[Editable(MinValueFloat = -1000f, MaxValueFloat = 1000f, ValueStep = 10f), Serialize("0.0, 0.0", true)]
|
||||
public Vector2 TextureOffset
|
||||
{
|
||||
get { return textureOffset; }
|
||||
set { textureOffset = value; }
|
||||
}
|
||||
}
|
||||
|
||||
partial void InitProjSpecific()
|
||||
{
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Barotrauma.Items.Components;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -39,7 +42,19 @@ namespace Barotrauma
|
||||
int iconX = iconIndices[(int)spawnType] * IconSize % iconTexture.Width;
|
||||
int iconY = (int)(Math.Floor(iconIndices[(int)spawnType] * IconSize / (float)iconTexture.Width)) * IconSize;
|
||||
|
||||
int iconSize = ConnectedGap == null && Ladders == null ? IconSize : (int)(IconSize * 1.5f);
|
||||
int iconSize = IconSize;
|
||||
if (ConnectedGap != null)
|
||||
{
|
||||
iconSize = (int)(iconSize * 1.5f);
|
||||
}
|
||||
if (Ladders != null)
|
||||
{
|
||||
iconSize = (int)(iconSize * 1.5f);
|
||||
}
|
||||
if (Stairs != null)
|
||||
{
|
||||
iconSize = (int)(iconSize * 1.5f);
|
||||
}
|
||||
|
||||
spriteBatch.Draw(iconTexture,
|
||||
new Rectangle((int)(drawPos.X - iconSize / 2), (int)(drawPos.Y - iconSize / 2), iconSize, iconSize),
|
||||
@@ -82,10 +97,49 @@ namespace Barotrauma
|
||||
editingHUD = CreateEditingHUD();
|
||||
}
|
||||
|
||||
if (PlayerInput.LeftButtonClicked())
|
||||
if (IsSelected && PlayerInput.LeftButtonClicked())
|
||||
{
|
||||
Vector2 position = cam.ScreenToWorld(PlayerInput.MousePosition);
|
||||
|
||||
// Update gaps, ladders, and stairs
|
||||
UpdateLinkedEntity(position, Gap.GapList, gap => ConnectedGap = gap, gap =>
|
||||
{
|
||||
if (ConnectedGap == gap)
|
||||
{
|
||||
ConnectedGap = null;
|
||||
}
|
||||
});
|
||||
UpdateLinkedEntity(position, Item.ItemList, i =>
|
||||
{
|
||||
var ladder = i?.GetComponent<Ladder>();
|
||||
if (ladder != null)
|
||||
{
|
||||
Ladders = ladder;
|
||||
}
|
||||
}, i =>
|
||||
{
|
||||
var ladder = i?.GetComponent<Ladder>();
|
||||
if (ladder != null)
|
||||
{
|
||||
if (Ladders == ladder)
|
||||
{
|
||||
Ladders = null;
|
||||
}
|
||||
}
|
||||
}, inflate: 5);
|
||||
// TODO: Cannot check the rectangle, since the rectangle is not rotated -> Need to use the collider.
|
||||
//var stairList = mapEntityList.Where(me => me is Structure s && s.StairDirection != Direction.None).Select(me => me as Structure);
|
||||
//UpdateLinkedEntity(position, stairList, s =>
|
||||
//{
|
||||
// Stairs = s;
|
||||
//}, s =>
|
||||
//{
|
||||
// if (Stairs == s)
|
||||
// {
|
||||
// Stairs = null;
|
||||
// }
|
||||
//});
|
||||
|
||||
foreach (MapEntity e in mapEntityList)
|
||||
{
|
||||
if (e.GetType() != typeof(WayPoint)) continue;
|
||||
@@ -99,6 +153,23 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateLinkedEntity<T>(Vector2 worldPos, IEnumerable<T> list, Action<T> match, Action<T> noMatch, int inflate = 0) where T : MapEntity
|
||||
{
|
||||
foreach (var entity in list)
|
||||
{
|
||||
var rect = entity.WorldRect;
|
||||
rect.Inflate(inflate, inflate);
|
||||
if (Submarine.RectContains(rect, worldPos))
|
||||
{
|
||||
match(entity);
|
||||
}
|
||||
else
|
||||
{
|
||||
noMatch(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool ChangeSpawnType(GUIButton button, object obj)
|
||||
{
|
||||
GUITextBlock spawnTypeText = button.Parent.GetChildByUserData("spawntypetext") as GUITextBlock;
|
||||
|
||||
@@ -119,7 +119,7 @@ namespace Barotrauma.Media
|
||||
|
||||
/*using (var stream = File.OpenRead(filename))
|
||||
{*/
|
||||
byte[] filenameBytes = Encoding.UTF8.GetBytes(filename);
|
||||
byte[] filenameBytes = Encoding.UTF8.GetBytes(filename + "\0");
|
||||
byte[] filenameBytesNullTerminated = new byte[filenameBytes.Length + 1];
|
||||
filenameBytesNullTerminated[filenameBytes.Length] = 0;
|
||||
Array.Copy(filenameBytes, filenameBytesNullTerminated, filenameBytes.Length);
|
||||
@@ -131,7 +131,10 @@ namespace Barotrauma.Media
|
||||
//LibVlcWrapper.LibVlcMethods.libvlc_media_release(media);
|
||||
|
||||
//LibVlcWrapper.LibVlcMethods.libvlc_video_get_size(mediaPlayer, 0, out width, out height);
|
||||
texture = new Texture2D(graphicsDevice, (int)width, (int)height);
|
||||
CrossThread.RequestExecutionOnMainThread(() =>
|
||||
{
|
||||
texture = new Texture2D(graphicsDevice, (int)width, (int)height);
|
||||
});
|
||||
Width = width; Height = height;
|
||||
|
||||
unmanagedData = Marshal.AllocHGlobal(sizeof(int)*2+(int)(width*height*3));
|
||||
@@ -147,7 +150,7 @@ namespace Barotrauma.Media
|
||||
IntPtr videoUnlockDelegatePtr = Marshal.GetFunctionPointerForDelegate(VideoUnlockDelegate);
|
||||
IntPtr videoDisplayDelegatePtr = Marshal.GetFunctionPointerForDelegate(VideoDisplayDelegate);
|
||||
LibVlcWrapper.LibVlcMethods.libvlc_video_set_callbacks(mediaPlayer, videoLockDelegatePtr, videoUnlockDelegatePtr, videoDisplayDelegatePtr, unmanagedData);
|
||||
LibVlcWrapper.LibVlcMethods.libvlc_video_set_format(mediaPlayer, Encoding.UTF8.GetBytes("RV24"), (int)width, (int)height, (int)width * 3);
|
||||
LibVlcWrapper.LibVlcMethods.libvlc_video_set_format(mediaPlayer, Encoding.UTF8.GetBytes("RV24\0"), (int)width, (int)height, (int)width * 3);
|
||||
|
||||
IntPtr audioPlayDelegatePtr = Marshal.GetFunctionPointerForDelegate(AudioPlayDelegate);
|
||||
IntPtr audioPauseDelegatePtr = Marshal.GetFunctionPointerForDelegate(AudioPauseDelegate);
|
||||
@@ -156,7 +159,7 @@ namespace Barotrauma.Media
|
||||
IntPtr audioDrainDelegatePtr = Marshal.GetFunctionPointerForDelegate(AudioDrainDelegate);
|
||||
|
||||
LibVlcWrapper.LibVlcMethods.libvlc_audio_set_callbacks(mediaPlayer, audioPlayDelegatePtr, audioPauseDelegatePtr, audioResumeDelegatePtr, audioFlushDelegatePtr, audioDrainDelegatePtr, unmanagedData);
|
||||
LibVlcWrapper.LibVlcMethods.libvlc_audio_set_format(mediaPlayer, Encoding.UTF8.GetBytes("S16N"), 44100, 2);
|
||||
LibVlcWrapper.LibVlcMethods.libvlc_audio_set_format(mediaPlayer, Encoding.UTF8.GetBytes("S16N\0"), 44100, 2);
|
||||
|
||||
LibVlcWrapper.LibVlcMethods.libvlc_audio_set_delay(mediaPlayer, 0);
|
||||
|
||||
@@ -216,7 +219,10 @@ namespace Barotrauma.Media
|
||||
(byte)255);
|
||||
}
|
||||
}
|
||||
texture.SetData(colors);
|
||||
CrossThread.RequestExecutionOnMainThread(() =>
|
||||
{
|
||||
texture.SetData(colors);
|
||||
});
|
||||
arr[0] = 0;
|
||||
Marshal.Copy(arr, 0, changedPtr, 1);
|
||||
}
|
||||
|
||||
@@ -154,8 +154,8 @@ namespace Barotrauma.Networking
|
||||
Dispose(true);
|
||||
}
|
||||
}
|
||||
|
||||
const int MaxFileSize = 1000000;
|
||||
|
||||
const int MaxFileSize = 50000000; //50 MB
|
||||
|
||||
public delegate void TransferInDelegate(FileTransferIn fileStreamReceiver);
|
||||
public TransferInDelegate OnFinished;
|
||||
|
||||
@@ -1170,6 +1170,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (respawnAllowed) respawnManager = new RespawnManager(this, GameMain.NetLobbyScreen.UsingShuttle ? GameMain.NetLobbyScreen.SelectedShuttle : null);
|
||||
|
||||
ServerSettings.ServerDetailsChanged = true;
|
||||
gameStarted = true;
|
||||
|
||||
GameMain.GameScreen.Select();
|
||||
@@ -1189,6 +1190,8 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (GameMain.GameSession != null) { GameMain.GameSession.GameMode.End(endMessage); }
|
||||
|
||||
ServerSettings.ServerDetailsChanged = true;
|
||||
|
||||
gameStarted = false;
|
||||
Character.Controlled = null;
|
||||
GameMain.GameScreen.Cam.TargetPos = Vector2.Zero;
|
||||
@@ -1884,17 +1887,11 @@ namespace Barotrauma.Networking
|
||||
client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered);
|
||||
}
|
||||
|
||||
public bool VoteForKick(GUIButton button, object userdata)
|
||||
public void VoteForKick(Client votedClient)
|
||||
{
|
||||
var votedClient = userdata is Client ? (Client)userdata : otherClients.Find(c => c.Character == userdata);
|
||||
if (votedClient == null) return false;
|
||||
|
||||
if (votedClient == null) { return; }
|
||||
votedClient.AddKickVote(ConnectedClients.First(c => c.ID == ID));
|
||||
Vote(VoteType.Kick, votedClient);
|
||||
|
||||
button.Enabled = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void AddChatMessage(ChatMessage message)
|
||||
@@ -2047,13 +2044,15 @@ namespace Barotrauma.Networking
|
||||
client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered);
|
||||
}
|
||||
|
||||
public void SetupNewCampaign(Submarine sub, string savePath, string mapSeed)
|
||||
public void SetupNewCampaign(Submarine sub, string saveName, string mapSeed)
|
||||
{
|
||||
saveName = Path.GetFileNameWithoutExtension(saveName);
|
||||
|
||||
NetOutgoingMessage msg = client.CreateMessage();
|
||||
msg.Write((byte)ClientPacketHeader.CAMPAIGN_SETUP_INFO);
|
||||
|
||||
msg.Write(true); msg.WritePadBits();
|
||||
msg.Write(savePath);
|
||||
msg.Write(saveName);
|
||||
msg.Write(mapSeed);
|
||||
msg.Write(sub.Name);
|
||||
msg.Write(sub.MD5Hash.Hash);
|
||||
@@ -2377,38 +2376,52 @@ namespace Barotrauma.Networking
|
||||
|
||||
public virtual bool SelectCrewCharacter(Character character, GUIComponent characterFrame)
|
||||
{
|
||||
if (character == null) return false;
|
||||
if (character == null) { return false; }
|
||||
|
||||
if (character != myCharacter)
|
||||
{
|
||||
var client = GameMain.NetworkMember.ConnectedClients.Find(c => c.Character == character);
|
||||
if (client == null) return false;
|
||||
if (client == null) { return false; }
|
||||
|
||||
var mute = new GUITickBox(new RectTransform(new Vector2(0.95f, 0.1f), characterFrame.RectTransform, Anchor.BottomCenter) { RelativeOffset = new Vector2(0.0f, 0.1f) },
|
||||
TextManager.Get("Mute"))
|
||||
{
|
||||
Selected = client.MutedLocally,
|
||||
OnSelected = (tickBox) => { client.MutedLocally = tickBox.Selected; return true; }
|
||||
};
|
||||
|
||||
var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.1f), characterFrame.RectTransform, Anchor.BottomCenter), isHorizontal: true)
|
||||
{
|
||||
RelativeSpacing = 0.05f,
|
||||
ChildAnchor = Anchor.CenterLeft,
|
||||
Stretch = true
|
||||
};
|
||||
|
||||
if (HasPermission(ClientPermissions.Ban))
|
||||
{
|
||||
var banButton = new GUIButton(new RectTransform(new Vector2(0.45f, 0.15f), characterFrame.RectTransform, Anchor.BottomRight),
|
||||
var banButton = new GUIButton(new RectTransform(new Vector2(0.45f, 0.9f), buttonContainer.RectTransform),
|
||||
TextManager.Get("Ban"))
|
||||
{
|
||||
UserData = character.Name,
|
||||
OnClicked = GameMain.NetLobbyScreen.BanPlayer
|
||||
UserData = client,
|
||||
OnClicked = (btn, userdata) => { GameMain.NetLobbyScreen.BanPlayer(client); return false; }
|
||||
};
|
||||
}
|
||||
if (HasPermission(ClientPermissions.Kick))
|
||||
{
|
||||
var kickButton = new GUIButton(new RectTransform(new Vector2(0.45f, 0.15f), characterFrame.RectTransform, Anchor.BottomLeft),
|
||||
var kickButton = new GUIButton(new RectTransform(new Vector2(0.45f, 0.9f), buttonContainer.RectTransform),
|
||||
TextManager.Get("Kick"))
|
||||
{
|
||||
UserData = character.Name,
|
||||
OnClicked = GameMain.NetLobbyScreen.KickPlayer
|
||||
UserData = client,
|
||||
OnClicked = (btn, userdata) => { GameMain.NetLobbyScreen.KickPlayer(client); return false; }
|
||||
};
|
||||
}
|
||||
else if (serverSettings.Voting.AllowVoteKick)
|
||||
{
|
||||
var kickVoteButton = new GUIButton(new RectTransform(new Vector2(0.45f, 0.15f), characterFrame.RectTransform, Anchor.BottomRight) { RelativeOffset = new Vector2(0.0f, 0.16f) },
|
||||
var kickVoteButton = new GUIButton(new RectTransform(new Vector2(0.45f, 0.9f), buttonContainer.RectTransform),
|
||||
TextManager.Get("VoteToKick"))
|
||||
{
|
||||
UserData = character,
|
||||
OnClicked = VoteForKick
|
||||
UserData = client,
|
||||
OnClicked = (btn, userdata) => { VoteForKick(client); btn.Enabled = false; return true; }
|
||||
};
|
||||
if (GameMain.NetworkMember.ConnectedClients != null)
|
||||
{
|
||||
|
||||
@@ -214,6 +214,11 @@ namespace Barotrauma.Steam
|
||||
if (s.Rules.ContainsKey("message")) serverInfo.ServerMessage = s.Rules["message"];
|
||||
if (s.Rules.ContainsKey("version")) serverInfo.GameVersion = s.Rules["version"];
|
||||
|
||||
if (s.Rules.ContainsKey("playercount"))
|
||||
{
|
||||
if (int.TryParse(s.Rules["playercount"], out int playerCount)) serverInfo.PlayerCount = playerCount;
|
||||
}
|
||||
|
||||
if (s.Rules.ContainsKey("contentpackage")) serverInfo.ContentPackageNames.AddRange(s.Rules["contentpackage"].Split(','));
|
||||
if (s.Rules.ContainsKey("contentpackagehash")) serverInfo.ContentPackageHashes.AddRange(s.Rules["contentpackagehash"].Split(','));
|
||||
if (s.Rules.ContainsKey("contentpackageurl")) serverInfo.ContentPackageWorkshopUrls.AddRange(s.Rules["contentpackageurl"].Split(','));
|
||||
@@ -235,6 +240,8 @@ namespace Barotrauma.Steam
|
||||
if (Enum.TryParse(s.Rules["traitors"], out YesNoMaybe traitorsEnabled)) serverInfo.TraitorsEnabled = traitorsEnabled;
|
||||
}
|
||||
|
||||
if (s.Rules.ContainsKey("gamestarted")) serverInfo.GameStarted = s.Rules["gamestarted"] == "True";
|
||||
|
||||
if (serverInfo.ContentPackageNames.Count != serverInfo.ContentPackageHashes.Count ||
|
||||
serverInfo.ContentPackageHashes.Count != serverInfo.ContentPackageWorkshopUrls.Count)
|
||||
{
|
||||
@@ -252,7 +259,8 @@ namespace Barotrauma.Steam
|
||||
|
||||
private static bool ValidateServerInfo(ServerList.Server server)
|
||||
{
|
||||
if (string.IsNullOrEmpty(server.Name)) { return false; }
|
||||
if (string.IsNullOrWhiteSpace(server.Name)) { return false; }
|
||||
if (string.IsNullOrWhiteSpace(server.Name.Replace("\0", ""))) { return false; }
|
||||
if (server.Address == null) { return false; }
|
||||
|
||||
return true;
|
||||
@@ -592,8 +600,15 @@ namespace Barotrauma.Steam
|
||||
}
|
||||
|
||||
SaveUtil.ClearFolder(WorkshopItemStagingFolder);
|
||||
Directory.Delete(WorkshopItemStagingFolder);
|
||||
File.Delete(PreviewImageName);
|
||||
try
|
||||
{
|
||||
Directory.Delete(WorkshopItemStagingFolder);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DebugConsole.ThrowError("Failed to delete Workshop item staging folder.", e);
|
||||
}
|
||||
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
@@ -925,28 +940,50 @@ namespace Barotrauma.Steam
|
||||
{
|
||||
if (instance == null || !instance.isInitialized) { return false; }
|
||||
|
||||
bool itemsUpdated = false;
|
||||
foreach (ulong subscribedItemId in instance.client.Workshop.GetSubscribedItemIds())
|
||||
bool? itemsUpdated = null;
|
||||
bool timedOut = false;
|
||||
var query = instance.client.Workshop.CreateQuery();
|
||||
query.FileId = new List<ulong>(instance.client.Workshop.GetSubscribedItemIds());
|
||||
query.UploaderAppId = AppID;
|
||||
query.Run();
|
||||
query.OnResult = (Workshop.Query q) =>
|
||||
{
|
||||
//TODO: fix this, GetItem doesn't query item.Modified
|
||||
var item = instance.client.Workshop.GetItem(subscribedItemId);
|
||||
if (item.Installed && CheckWorkshopItemEnabled(item) && !CheckWorkshopItemUpToDate(item))
|
||||
if (timedOut) { return; }
|
||||
itemsUpdated = false;
|
||||
foreach (var item in q.Items)
|
||||
{
|
||||
if (!UpdateWorkshopItem(item, out string errorMsg))
|
||||
if (item.Installed && CheckWorkshopItemEnabled(item) && !CheckWorkshopItemUpToDate(item))
|
||||
{
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
new GUIMessageBox(
|
||||
TextManager.Get("Error"),
|
||||
TextManager.GetWithVariables("WorkshopItemUpdateFailed", new string[2] { "[itemname]", "[errormessage]" }, new string[2] { item.Title, errorMsg }));
|
||||
}
|
||||
else
|
||||
{
|
||||
new GUIMessageBox("", TextManager.GetWithVariable("WorkshopItemUpdated", "[itemname]", item.Title));
|
||||
itemsUpdated = true;
|
||||
if (!UpdateWorkshopItem(item, out string errorMsg))
|
||||
{
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
new GUIMessageBox(
|
||||
TextManager.Get("Error"),
|
||||
TextManager.GetWithVariables("WorkshopItemUpdateFailed", new string[2] { "[itemname]", "[errormessage]" }, new string[2] { item.Title, errorMsg }));
|
||||
}
|
||||
else
|
||||
{
|
||||
new GUIMessageBox("", TextManager.GetWithVariable("WorkshopItemUpdated", "[itemname]", item.Title));
|
||||
itemsUpdated = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
DateTime timeOut = DateTime.Now + new TimeSpan(0, 0, 10);
|
||||
while (!itemsUpdated.HasValue)
|
||||
{
|
||||
if (DateTime.Now > timeOut)
|
||||
{
|
||||
itemsUpdated = false;
|
||||
timedOut = true;
|
||||
break;
|
||||
}
|
||||
instance.client.Update();
|
||||
System.Threading.Thread.Sleep(10);
|
||||
}
|
||||
return itemsUpdated;
|
||||
|
||||
return itemsUpdated.Value;
|
||||
}
|
||||
|
||||
public static bool UpdateWorkshopItem(Workshop.Item item, out string errorMsg)
|
||||
|
||||
@@ -61,6 +61,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
localEnabled = box.Selected;
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -145,16 +146,12 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (obj is WhiteListedPlayer)
|
||||
{
|
||||
WhiteListedPlayer wlp = obj as WhiteListedPlayer;
|
||||
if (wlp == null) return false;
|
||||
|
||||
if (!(obj is WhiteListedPlayer wlp)) return false;
|
||||
if (!localRemoved.Contains(wlp.UniqueIdentifier)) localRemoved.Add(wlp.UniqueIdentifier);
|
||||
}
|
||||
else if (obj is LocalAdded)
|
||||
{
|
||||
LocalAdded lad = obj as LocalAdded;
|
||||
if (lad == null) return false;
|
||||
|
||||
if (!(obj is LocalAdded lad)) return false;
|
||||
if (localAdded.Contains(lad)) localAdded.Remove(lad);
|
||||
}
|
||||
|
||||
@@ -210,7 +207,6 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
ip = "IP concealed by host";
|
||||
}
|
||||
DebugConsole.NewMessage("nerd: " + name, Color.Lime);
|
||||
whitelistedPlayers.Add(new WhiteListedPlayer(name, uniqueIdentifier, ip));
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,6 @@ namespace Barotrauma
|
||||
{
|
||||
#endif
|
||||
game = new GameMain();
|
||||
//game.GraphicsDevice.PresentationParameters.IsFullScreen = false;
|
||||
#if !DEBUG
|
||||
}
|
||||
catch (Exception e)
|
||||
|
||||
@@ -437,42 +437,48 @@ namespace Barotrauma
|
||||
|
||||
if (characterPreviewFrame != null)
|
||||
{
|
||||
characterPreviewFrame.Parent.RemoveChild(characterPreviewFrame);
|
||||
characterPreviewFrame.Parent?.RemoveChild(characterPreviewFrame);
|
||||
characterPreviewFrame = null;
|
||||
}
|
||||
|
||||
if (Campaign is SinglePlayerCampaign)
|
||||
if (characterList != null)
|
||||
{
|
||||
var hireableCharacters = location.GetHireableCharacters();
|
||||
foreach (GUIComponent child in characterList.Content.Children.ToList())
|
||||
if (Campaign is SinglePlayerCampaign)
|
||||
{
|
||||
if (child.UserData is CharacterInfo character)
|
||||
var hireableCharacters = location.GetHireableCharacters();
|
||||
foreach (GUIComponent child in characterList.Content.Children.ToList())
|
||||
{
|
||||
if (GameMain.GameSession.CrewManager.GetCharacterInfos().Contains(character)) { continue; }
|
||||
if (child.UserData is CharacterInfo character)
|
||||
{
|
||||
if (GameMain.GameSession.CrewManager != null)
|
||||
{
|
||||
if (GameMain.GameSession.CrewManager.GetCharacterInfos().Contains(character)) { continue; }
|
||||
}
|
||||
}
|
||||
else if (child.UserData as string == "mycrew" || child.UserData as string == "hire")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
characterList.RemoveChild(child);
|
||||
}
|
||||
else if (child.UserData as string == "mycrew" || child.UserData as string == "hire")
|
||||
if (!hireableCharacters.Any())
|
||||
{
|
||||
continue;
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.2f), characterList.Content.RectTransform), TextManager.Get("HireUnavailable"), textAlignment: Alignment.Center)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
}
|
||||
characterList.RemoveChild(child);
|
||||
}
|
||||
if (!hireableCharacters.Any())
|
||||
{
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.2f), characterList.Content.RectTransform), TextManager.Get("HireUnavailable"), textAlignment: Alignment.Center)
|
||||
else
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (CharacterInfo c in hireableCharacters)
|
||||
{
|
||||
var frame = c.CreateCharacterFrame(characterList.Content, c.Name + " (" + c.Job.Name + ")", c);
|
||||
new GUITextBlock(new RectTransform(Vector2.One, frame.RectTransform, Anchor.TopRight), c.Salary.ToString(), textAlignment: Alignment.CenterRight);
|
||||
foreach (CharacterInfo c in hireableCharacters)
|
||||
{
|
||||
var frame = c.CreateCharacterFrame(characterList.Content, c.Name + " (" + c.Job.Name + ")", c);
|
||||
new GUITextBlock(new RectTransform(Vector2.One, frame.RectTransform, Anchor.TopRight), c.Salary.ToString(), textAlignment: Alignment.CenterRight);
|
||||
}
|
||||
}
|
||||
}
|
||||
characterList.UpdateScrollBarSize();
|
||||
}
|
||||
characterList.UpdateScrollBarSize();
|
||||
|
||||
RefreshMyItems();
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace Barotrauma
|
||||
{
|
||||
class MainMenuScreen : Screen
|
||||
{
|
||||
public enum Tab { NewGame = 1, LoadGame = 2, HostServer = 3, Settings = 4, Tutorials = 5, JoinServer = 6, CharacterEditor = 7, SubmarineEditor = 8, QuickStartDev = 9, SteamWorkshop = 10, Credits = 11 }
|
||||
public enum Tab { NewGame = 1, LoadGame = 2, HostServer = 3, Settings = 4, Tutorials = 5, JoinServer = 6, CharacterEditor = 7, SubmarineEditor = 8, QuickStartDev = 9, SteamWorkshop = 10, Credits = 11, Empty = 12 }
|
||||
|
||||
private GUIComponent buttonsParent;
|
||||
|
||||
@@ -37,7 +37,11 @@ namespace Barotrauma
|
||||
private GUIComponent titleText;
|
||||
|
||||
private CreditsPlayer creditsPlayer;
|
||||
|
||||
|
||||
#if OSX
|
||||
private bool firstLoadOnMac = true;
|
||||
#endif
|
||||
|
||||
#region Creation
|
||||
public MainMenuScreen(GameMain game)
|
||||
{
|
||||
@@ -360,9 +364,9 @@ namespace Barotrauma
|
||||
OnClicked = SelectTab
|
||||
};
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region Selection
|
||||
#region Selection
|
||||
public override void Select()
|
||||
{
|
||||
base.Select();
|
||||
@@ -378,6 +382,25 @@ namespace Barotrauma
|
||||
ResetButtonStates(null);
|
||||
|
||||
GameAnalyticsManager.SetCustomDimension01("");
|
||||
|
||||
#if OSX
|
||||
// Hack for adjusting the viewport properly after splash screens on older Macs
|
||||
if (firstLoadOnMac)
|
||||
{
|
||||
firstLoadOnMac = false;
|
||||
|
||||
menuTabs[(int)Tab.Empty] = new GUIFrame(new RectTransform(new Vector2(1f, 1f), GUI.Canvas), "", Color.Transparent)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
var emptyList = new GUIListBox(new RectTransform(new Vector2(0.0f, 0.0f), menuTabs[(int)Tab.Empty].RectTransform))
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
SelectTab(null, Tab.Empty);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public override void Deselect()
|
||||
@@ -701,7 +724,14 @@ namespace Barotrauma
|
||||
GameMain.NetLobbyScreen = new NetLobbyScreen();
|
||||
try
|
||||
{
|
||||
int ownerKey = Math.Max(CryptoRandom.Instance.Next(),1);
|
||||
string exeName = ContentPackage.GetFilesOfType(GameMain.Config.SelectedContentPackages, ContentType.ServerExecutable)?.FirstOrDefault();
|
||||
if (string.IsNullOrEmpty(exeName))
|
||||
{
|
||||
DebugConsole.ThrowError("No server executable defined in the selected content packages. Attempting to use the default executable...");
|
||||
exeName = "DedicatedServer.exe";
|
||||
}
|
||||
|
||||
int ownerKey = Math.Max(CryptoRandom.Instance.Next(), 1);
|
||||
|
||||
string arguments = "-name \"" + name.Replace("\\", "\\\\").Replace("\"", "\\\"") + "\"" +
|
||||
" -port " + port.ToString() +
|
||||
@@ -711,16 +741,15 @@ namespace Barotrauma
|
||||
" -maxplayers " + maxPlayersBox.Text +
|
||||
" -ownerkey " + ownerKey.ToString();
|
||||
|
||||
string filename = "DedicatedServer.exe";
|
||||
string filename = exeName;
|
||||
#if LINUX || OSX
|
||||
filename = "./DedicatedServer";
|
||||
filename = "./" + Path.GetFileNameWithoutExtension(exeName);
|
||||
#endif
|
||||
var processInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = filename,
|
||||
Arguments = arguments
|
||||
Arguments = arguments,
|
||||
#if !DEBUG
|
||||
,
|
||||
WindowStyle = ProcessWindowStyle.Hidden
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -1537,7 +1537,7 @@ namespace Barotrauma
|
||||
{
|
||||
UserData = selectedClient
|
||||
};
|
||||
banButton.OnClicked += BanPlayer;
|
||||
banButton.OnClicked = (bt, userdata) => { BanPlayer(selectedClient); return true; };
|
||||
banButton.OnClicked += ClosePlayerFrame;
|
||||
|
||||
var rangebanButton = new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), buttonAreaUpper.RectTransform),
|
||||
@@ -1545,7 +1545,7 @@ namespace Barotrauma
|
||||
{
|
||||
UserData = selectedClient
|
||||
};
|
||||
rangebanButton.OnClicked += BanPlayerRange;
|
||||
rangebanButton.OnClicked = (bt, userdata) => { BanPlayerRange(selectedClient); return true; };
|
||||
rangebanButton.OnClicked += ClosePlayerFrame;
|
||||
}
|
||||
|
||||
@@ -1557,7 +1557,7 @@ namespace Barotrauma
|
||||
TextManager.Get("VoteToKick"))
|
||||
{
|
||||
Enabled = !selectedClient.HasKickVoteFromID(GameMain.Client.ID),
|
||||
OnClicked = GameMain.Client.VoteForKick,
|
||||
OnClicked = (btn, userdata) => { GameMain.Client.VoteForKick(selectedClient); btn.Enabled = false; return true; },
|
||||
UserData = selectedClient
|
||||
};
|
||||
}
|
||||
@@ -1570,7 +1570,7 @@ namespace Barotrauma
|
||||
{
|
||||
UserData = selectedClient
|
||||
};
|
||||
kickButton.OnClicked = KickPlayer;
|
||||
kickButton.OnClicked = (bt, userdata) => { KickPlayer(selectedClient); return true; };
|
||||
kickButton.OnClicked += ClosePlayerFrame;
|
||||
}
|
||||
|
||||
@@ -1599,28 +1599,22 @@ namespace Barotrauma
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool KickPlayer(GUIButton button, object userData)
|
||||
public void KickPlayer(Client client)
|
||||
{
|
||||
Client client = userData as Client;
|
||||
if (client == null || GameMain.NetworkMember == null) return false;
|
||||
GameMain.Client.CreateKickReasonPrompt(client.Name, false);
|
||||
return false;
|
||||
if (GameMain.NetworkMember == null || client == null) { return; }
|
||||
GameMain.Client.CreateKickReasonPrompt(client.Name, false);
|
||||
}
|
||||
|
||||
public bool BanPlayer(GUIButton button, object userData)
|
||||
public void BanPlayer(Client client)
|
||||
{
|
||||
Client client = userData as Client;
|
||||
if (userData == null || GameMain.NetworkMember == null) return false;
|
||||
if (GameMain.NetworkMember == null || client == null) { return; }
|
||||
GameMain.Client.CreateKickReasonPrompt(client.Name, true);
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool BanPlayerRange(GUIButton button, object userData)
|
||||
public void BanPlayerRange(Client client)
|
||||
{
|
||||
Client client = userData as Client;
|
||||
if (userData == null || GameMain.NetworkMember == null) return false;
|
||||
if (GameMain.NetworkMember == null || client == null) { return; }
|
||||
GameMain.Client.CreateKickReasonPrompt(client.Name, true, true);
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void AddToGUIUpdateList()
|
||||
|
||||
@@ -4,7 +4,6 @@ using Barotrauma.Particles;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
using System.Windows;
|
||||
using System.Xml;
|
||||
using System.Text;
|
||||
|
||||
|
||||
@@ -48,6 +48,8 @@ namespace Barotrauma
|
||||
|
||||
public ServerListScreen()
|
||||
{
|
||||
GameMain.Instance.OnResolutionChanged += OnResolutionChanged;
|
||||
|
||||
menu = new GUIFrame(new RectTransform(new Vector2(0.7f, 0.8f), GUI.Canvas, Anchor.Center) { MinSize = new Point(GameMain.GraphicsHeight, 0) });
|
||||
|
||||
var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.97f, 0.95f), menu.RectTransform, Anchor.Center), isHorizontal: true)
|
||||
@@ -170,6 +172,11 @@ namespace Barotrauma
|
||||
refreshDisableTimer = DateTime.Now;
|
||||
}
|
||||
|
||||
private void OnResolutionChanged()
|
||||
{
|
||||
menu.RectTransform.MinSize = new Point(GameMain.GraphicsHeight, 0);
|
||||
}
|
||||
|
||||
public override void Select()
|
||||
{
|
||||
base.Select();
|
||||
@@ -205,6 +212,8 @@ namespace Barotrauma
|
||||
UserData = "noresults"
|
||||
};
|
||||
}
|
||||
|
||||
serverList.UpdateScrollBarSize();
|
||||
}
|
||||
|
||||
private bool RefreshJoinButtonState(GUIComponent component, object obj)
|
||||
|
||||
@@ -47,9 +47,11 @@ namespace Barotrauma
|
||||
|
||||
public SteamWorkshopScreen()
|
||||
{
|
||||
GameMain.Instance.OnResolutionChanged += OnResolutionChanged;
|
||||
|
||||
tabs = new GUIFrame[Enum.GetValues(typeof(Tab)).Length];
|
||||
|
||||
menu = new GUIFrame(new RectTransform(new Vector2(0.6f, 0.8f), GUI.Canvas, Anchor.Center) { MinSize = new Point(GameMain.GraphicsHeight, 0) });
|
||||
menu = new GUIFrame(new RectTransform(new Vector2(0.85f, 0.8f), GUI.Canvas, Anchor.Center) { MinSize = new Point(GameMain.GraphicsHeight, 0) });
|
||||
|
||||
var container = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.85f), menu.RectTransform, Anchor.Center) { RelativeOffset = new Vector2(0.0f, 0.05f) }) { Stretch = true };
|
||||
|
||||
@@ -211,6 +213,11 @@ namespace Barotrauma
|
||||
SelectTab(Tab.Mods);
|
||||
}
|
||||
|
||||
private void OnResolutionChanged()
|
||||
{
|
||||
menu.RectTransform.MinSize = new Point(GameMain.GraphicsHeight, 0);
|
||||
}
|
||||
|
||||
public override void Select()
|
||||
{
|
||||
base.Select();
|
||||
@@ -394,6 +401,7 @@ namespace Barotrauma
|
||||
{
|
||||
IsHorizontal = true,
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.05f,
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
@@ -405,32 +413,6 @@ namespace Barotrauma
|
||||
|
||||
if (item.Installed)
|
||||
{
|
||||
if (listBox != publishedItemList && SteamManager.CheckWorkshopItemEnabled(item) && !SteamManager.CheckWorkshopItemUpToDate(item))
|
||||
{
|
||||
new GUIButton(new RectTransform(new Vector2(0.4f, 0.5f), rightColumn.RectTransform, Anchor.BottomLeft), text: "Update")
|
||||
{
|
||||
UserData = "updatebutton",
|
||||
IgnoreLayoutGroups = true,
|
||||
OnClicked = (btn, userdata) =>
|
||||
{
|
||||
if (SteamManager.UpdateWorkshopItem(item, out string errorMsg))
|
||||
{
|
||||
new GUIMessageBox("", TextManager.GetWithVariable("WorkshopItemUpdated", "[itemname]", TextManager.EnsureUTF8(item.Title)));
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
new GUIMessageBox(
|
||||
TextManager.Get("Error"),
|
||||
TextManager.GetWithVariables("WorkshopItemUpdateFailed", new string[2] { "[itemname]", "[errormessage]" }, new string[2] { TextManager.EnsureUTF8(item.Title), errorMsg }));
|
||||
}
|
||||
btn.Enabled = false;
|
||||
btn.Visible = false;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
GUITickBox enabledTickBox = null;
|
||||
try
|
||||
{
|
||||
@@ -476,6 +458,33 @@ namespace Barotrauma
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (listBox != publishedItemList && SteamManager.CheckWorkshopItemEnabled(item) && !SteamManager.CheckWorkshopItemUpToDate(item))
|
||||
{
|
||||
new GUIButton(new RectTransform(new Vector2(0.4f, 0.5f), rightColumn.RectTransform, Anchor.BottomLeft), text: TextManager.Get("WorkshopItemUpdate"))
|
||||
{
|
||||
UserData = "updatebutton",
|
||||
Font = GUI.SmallFont,
|
||||
OnClicked = (btn, userdata) =>
|
||||
{
|
||||
if (SteamManager.UpdateWorkshopItem(item, out string errorMsg))
|
||||
{
|
||||
new GUIMessageBox("", TextManager.GetWithVariable("WorkshopItemUpdated", "[itemname]", TextManager.EnsureUTF8(item.Title)));
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
new GUIMessageBox(
|
||||
TextManager.Get("Error"),
|
||||
TextManager.GetWithVariables("WorkshopItemUpdateFailed", new string[2] { "[itemname]", "[errormessage]" }, new string[2] { TextManager.EnsureUTF8(item.Title), errorMsg }));
|
||||
}
|
||||
btn.Enabled = false;
|
||||
btn.Visible = false;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
else if (item.Downloading)
|
||||
{
|
||||
@@ -900,7 +909,7 @@ namespace Barotrauma
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), topRightColumn.RectTransform), TextManager.Get("WorkshopItemDescription"));
|
||||
|
||||
var descriptionContainer = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.4f), topRightColumn.RectTransform));
|
||||
var descriptionBox = new GUITextBox(new RectTransform(Vector2.One, descriptionContainer.Content.RectTransform), itemEditor.Description, textAlignment: Alignment.TopLeft, wrap: true);
|
||||
var descriptionBox = new GUITextBox(new RectTransform(Vector2.One, descriptionContainer.Content.RectTransform), itemEditor.Description, textAlignment: Alignment.TopLeft, font: GUI.SmallFont, wrap: true);
|
||||
descriptionBox.OnTextChanged += (textBox, text) =>
|
||||
{
|
||||
Vector2 textSize = textBox.Font.MeasureString(descriptionBox.WrappedText);
|
||||
@@ -1081,6 +1090,7 @@ namespace Barotrauma
|
||||
{
|
||||
InitialDirectory = Path.GetFullPath(SteamManager.WorkshopItemStagingFolder),
|
||||
Title = TextManager.Get("workshopitemaddfiles"),
|
||||
Multiselect = true
|
||||
};
|
||||
if (ofd.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
@@ -1228,7 +1238,7 @@ namespace Barotrauma
|
||||
private void OnAddFilesSelected(string[] fileNames)
|
||||
{
|
||||
if (fileNames == null) { return; }
|
||||
for(int i = 0; i < fileNames.Length; i++)
|
||||
for (int i = 0; i < fileNames.Length; i++)
|
||||
{
|
||||
string file = fileNames[i];
|
||||
if (string.IsNullOrEmpty(file)) { continue; }
|
||||
@@ -1258,6 +1268,7 @@ namespace Barotrauma
|
||||
itemContentPackage.AddFile(filePathRelativeToStagingFolder, ContentType.None);
|
||||
}
|
||||
}
|
||||
itemContentPackage.Save(itemContentPackage.Path);
|
||||
RefreshCreateItemFileList();
|
||||
}
|
||||
|
||||
@@ -1331,6 +1342,7 @@ namespace Barotrauma
|
||||
OnClicked = (btn, userdata) =>
|
||||
{
|
||||
itemContentPackage.RemoveFile(contentFile);
|
||||
itemContentPackage.Save(itemContentPackage.Path);
|
||||
RefreshCreateItemFileList();
|
||||
return true;
|
||||
}
|
||||
@@ -1346,7 +1358,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (itemContentPackage == null || itemEditor == null) return;
|
||||
|
||||
SteamManager.StartPublishItem(itemContentPackage, itemEditor);
|
||||
SteamManager.StartPublishItem(itemContentPackage, itemEditor);
|
||||
CoroutineManager.StartCoroutine(WaitForPublish(itemEditor), "WaitForPublish");
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace Barotrauma
|
||||
"CrewExperienceHigh"
|
||||
};
|
||||
|
||||
private readonly Point defaultPreviewImageSize = new Point(256, 128);
|
||||
private readonly Point defaultPreviewImageSize = new Point(512, 368);
|
||||
|
||||
private Camera cam;
|
||||
|
||||
@@ -2109,10 +2109,7 @@ namespace Barotrauma
|
||||
|
||||
public override void AddToGUIUpdateList()
|
||||
{
|
||||
if (MapEntity.SelectedList.Count == 1)
|
||||
{
|
||||
MapEntity.SelectedList[0].AddToGUIUpdateList();
|
||||
}
|
||||
MapEntity.FilteredSelectedList.FirstOrDefault()?.AddToGUIUpdateList();
|
||||
if (MapEntity.HighlightedListBox != null)
|
||||
{
|
||||
MapEntity.HighlightedListBox.AddToGUIUpdateList();
|
||||
@@ -2293,9 +2290,9 @@ namespace Barotrauma
|
||||
dummyCharacter.SelectedConstruction = null;
|
||||
}*/
|
||||
}
|
||||
else if (MapEntity.SelectedList.Count == 1)
|
||||
else if (MapEntity.FilteredSelectedList.Count == 1)
|
||||
{
|
||||
(MapEntity.SelectedList[0] as Item)?.UpdateHUD(cam, dummyCharacter, (float)deltaTime);
|
||||
(MapEntity.FilteredSelectedList[0] as Item)?.UpdateHUD(cam, dummyCharacter, (float)deltaTime);
|
||||
}
|
||||
|
||||
CharacterHUD.Update((float)deltaTime, dummyCharacter, cam);
|
||||
|
||||
@@ -196,7 +196,7 @@ namespace OpenAL
|
||||
|
||||
public static IntPtr CaptureOpenDevice(string devicename, uint frequency, int format, int buffersize)
|
||||
{
|
||||
byte[] devicenameBytes = Encoding.UTF8.GetBytes(devicename);
|
||||
byte[] devicenameBytes = Encoding.UTF8.GetBytes(devicename + "\0");
|
||||
GCHandle devicenameHandle = GCHandle.Alloc(devicenameBytes, GCHandleType.Pinned);
|
||||
IntPtr retVal = CaptureOpenDevice(devicenameHandle.AddrOfPinnedObject(), frequency, format, buffersize);
|
||||
devicenameHandle.Free();
|
||||
|
||||
@@ -325,7 +325,9 @@ namespace Barotrauma.Sounds
|
||||
if (ALSourceIndex < 0) return false;
|
||||
if (IsStream && !reachedEndSample) return true;
|
||||
int state;
|
||||
Al.GetSourcei(Sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex), Al.SourceState, out state);
|
||||
uint alSource = Sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex);
|
||||
if (!Al.IsSource(alSource)) return false;
|
||||
Al.GetSourcei(alSource, Al.SourceState, out state);
|
||||
bool playing = state == Al.Playing;
|
||||
int alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
|
||||
@@ -174,8 +174,8 @@ namespace Barotrauma.Sounds
|
||||
sourcePools[(int)SourcePoolIndex.Default] = new SoundSourcePool(SOURCE_COUNT);
|
||||
playingChannels[(int)SourcePoolIndex.Default] = new SoundChannel[SOURCE_COUNT];
|
||||
|
||||
sourcePools[(int)SourcePoolIndex.Voice] = new SoundSourcePool(8);
|
||||
playingChannels[(int)SourcePoolIndex.Voice] = new SoundChannel[8];
|
||||
sourcePools[(int)SourcePoolIndex.Voice] = new SoundSourcePool(16);
|
||||
playingChannels[(int)SourcePoolIndex.Voice] = new SoundChannel[16];
|
||||
|
||||
Al.DistanceModel(Al.LinearDistanceClamped);
|
||||
|
||||
@@ -202,7 +202,10 @@ namespace Barotrauma.Sounds
|
||||
}
|
||||
|
||||
Sound newSound = new OggSound(this, filename, stream);
|
||||
loadedSounds.Add(newSound);
|
||||
lock (loadedSounds)
|
||||
{
|
||||
loadedSounds.Add(newSound);
|
||||
}
|
||||
return newSound;
|
||||
}
|
||||
|
||||
@@ -225,7 +228,10 @@ namespace Barotrauma.Sounds
|
||||
newSound.BaseFar = range;
|
||||
}
|
||||
|
||||
loadedSounds.Add(newSound);
|
||||
lock (loadedSounds)
|
||||
{
|
||||
loadedSounds.Add(newSound);
|
||||
}
|
||||
return newSound;
|
||||
}
|
||||
|
||||
@@ -352,12 +358,15 @@ namespace Barotrauma.Sounds
|
||||
|
||||
public void RemoveSound(Sound sound)
|
||||
{
|
||||
for (int i = 0; i < loadedSounds.Count; i++)
|
||||
lock (loadedSounds)
|
||||
{
|
||||
if (loadedSounds[i] == sound)
|
||||
for (int i = 0; i < loadedSounds.Count; i++)
|
||||
{
|
||||
loadedSounds.RemoveAt(i);
|
||||
return;
|
||||
if (loadedSounds[i] == sound)
|
||||
{
|
||||
loadedSounds.RemoveAt(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,7 +97,15 @@ namespace Barotrauma
|
||||
public static Texture2D LoadTexture(string file, bool preMultiplyAlpha = true)
|
||||
{
|
||||
|
||||
if (string.IsNullOrWhiteSpace(file)) { return new Texture2D(GameMain.GraphicsDeviceManager.GraphicsDevice, 1, 1); }
|
||||
if (string.IsNullOrWhiteSpace(file))
|
||||
{
|
||||
Texture2D t = null;
|
||||
CrossThread.RequestExecutionOnMainThread(() =>
|
||||
{
|
||||
t = new Texture2D(GameMain.GraphicsDeviceManager.GraphicsDevice, 1, 1);
|
||||
});
|
||||
return t;
|
||||
}
|
||||
file = Path.GetFullPath(file);
|
||||
foreach (Sprite s in list)
|
||||
{
|
||||
@@ -305,16 +313,22 @@ namespace Barotrauma
|
||||
//check if another sprite is using the same texture
|
||||
if (!string.IsNullOrEmpty(FilePath)) //file can be empty if the sprite is created directly from a Texture2D instance
|
||||
{
|
||||
foreach (Sprite s in list)
|
||||
lock (list)
|
||||
{
|
||||
if (s.FullPath == FullPath) return;
|
||||
foreach (Sprite s in list)
|
||||
{
|
||||
if (s.FullPath == FullPath) return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//if not, free the texture
|
||||
if (texture != null)
|
||||
{
|
||||
texture.Dispose();
|
||||
CrossThread.RequestExecutionOnMainThread(() =>
|
||||
{
|
||||
texture.Dispose();
|
||||
});
|
||||
texture = null;
|
||||
}
|
||||
}
|
||||
|
||||
63
Barotrauma/BarotraumaClient/Source/Utils/CrossThread.cs
Normal file
63
Barotrauma/BarotraumaClient/Source/Utils/CrossThread.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
public static class CrossThread
|
||||
{
|
||||
public delegate void TaskDelegate();
|
||||
|
||||
private class Task
|
||||
{
|
||||
public TaskDelegate Deleg;
|
||||
public ManualResetEvent Mre;
|
||||
public bool Done;
|
||||
|
||||
public Task(TaskDelegate d)
|
||||
{
|
||||
Deleg = d;
|
||||
Mre = new ManualResetEvent(false);
|
||||
Done = false;
|
||||
}
|
||||
|
||||
public void PerformWait()
|
||||
{
|
||||
if (!Done) { Mre.WaitOne(); }
|
||||
}
|
||||
}
|
||||
private static List<Task> enqueuedTasks;
|
||||
|
||||
static CrossThread() { enqueuedTasks = new List<Task>(); }
|
||||
|
||||
public static void ProcessTasks()
|
||||
{
|
||||
lock (enqueuedTasks)
|
||||
{
|
||||
foreach (var task in enqueuedTasks)
|
||||
{
|
||||
task.Deleg();
|
||||
task.Mre.Set();
|
||||
task.Done = true;
|
||||
}
|
||||
enqueuedTasks.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public static void RequestExecutionOnMainThread(TaskDelegate deleg)
|
||||
{
|
||||
if (Thread.CurrentThread == GameMain.MainThread)
|
||||
{
|
||||
deleg();
|
||||
}
|
||||
else
|
||||
{
|
||||
Task newTask = new Task(deleg);
|
||||
lock (enqueuedTasks)
|
||||
{
|
||||
enqueuedTasks.Add(newTask);
|
||||
}
|
||||
newTask.PerformWait();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,34 +18,26 @@ namespace Barotrauma
|
||||
public string FileName { get; private set; }
|
||||
public string[] FileNames { get; private set; }
|
||||
|
||||
public OpenFileDialog()
|
||||
{
|
||||
ofd = new System.Windows.Forms.OpenFileDialog();
|
||||
}
|
||||
public OpenFileDialog() { }
|
||||
|
||||
public System.Windows.Forms.DialogResult ShowDialog()
|
||||
{
|
||||
ofd = new System.Windows.Forms.OpenFileDialog();
|
||||
ofd.Multiselect = Multiselect;
|
||||
ofd.InitialDirectory = InitialDirectory;
|
||||
ofd.Filter = Filter;
|
||||
ofd.Title = Title;
|
||||
|
||||
#if LINUX
|
||||
System.Windows.Forms.DialogResult result;
|
||||
var wrapperForm = new WrapperForm(ofd);
|
||||
System.Windows.Forms.Application.Run(wrapperForm);
|
||||
System.Windows.Forms.Application.Exit();
|
||||
FileName = wrapperForm.FileName;
|
||||
FileNames = wrapperForm.FileNames;
|
||||
return wrapperForm.Result;
|
||||
#else
|
||||
var result = ofd.ShowDialog();
|
||||
FileName = ofd.FileName;
|
||||
FileNames = ofd.FileNames;
|
||||
result = wrapperForm.Result;
|
||||
ofd = null;
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if LINUX
|
||||
private class WrapperForm : System.Windows.Forms.Form
|
||||
{
|
||||
private System.Windows.Forms.OpenFileDialog ofd;
|
||||
@@ -66,9 +58,8 @@ namespace Barotrauma
|
||||
FileName = ofd.FileName;
|
||||
FileNames = ofd.FileNames;
|
||||
System.Threading.Thread.Sleep(100);
|
||||
this.Close();
|
||||
System.Windows.Forms.Application.Exit();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Color = Microsoft.Xna.Framework.Color;
|
||||
|
||||
namespace Barotrauma
|
||||
@@ -43,15 +43,18 @@ namespace Barotrauma
|
||||
_graphicsDevice = graphicsDevice;
|
||||
_needsBmp = needsBmp;
|
||||
_spriteBatch = new SpriteBatch(_graphicsDevice);
|
||||
|
||||
PlaceHolderTexture = new Texture2D(graphicsDevice, 32, 32);
|
||||
|
||||
|
||||
Color[] data = new Color[32 * 32];
|
||||
for (int i = 0; i < 32 * 32; i++)
|
||||
{
|
||||
data[i] = Color.Magenta;
|
||||
}
|
||||
PlaceHolderTexture.SetData(data);
|
||||
|
||||
CrossThread.RequestExecutionOnMainThread(() =>
|
||||
{
|
||||
PlaceHolderTexture = new Texture2D(graphicsDevice, 32, 32);
|
||||
PlaceHolderTexture.SetData(data);
|
||||
});
|
||||
}
|
||||
|
||||
public static Texture2D FromFile(string path, bool preMultiplyAlpha = true)
|
||||
@@ -60,12 +63,7 @@ namespace Barotrauma
|
||||
{
|
||||
using (Stream fileStream = File.OpenRead(path))
|
||||
{
|
||||
var texture = Texture2D.FromStream(_graphicsDevice, fileStream);
|
||||
if (preMultiplyAlpha)
|
||||
{
|
||||
PreMultiplyAlpha(ref texture);
|
||||
}
|
||||
return texture;
|
||||
return FromStream(fileStream, preMultiplyAlpha, path);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -76,16 +74,33 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public static Texture2D FromStream(Stream fileStream, bool preMultiplyAlpha = true)
|
||||
public static Texture2D FromStream(Stream fileStream, bool preMultiplyAlpha = true, string path=null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var texture = Texture2D.FromStream(_graphicsDevice, fileStream);
|
||||
int width = 0; int height = 0; int channels = 0;
|
||||
byte[] textureData = null;
|
||||
Task loadTask = Task.Run(() =>
|
||||
{
|
||||
textureData = Texture2D.TextureDataFromStream(fileStream, out width, out height, out channels);
|
||||
});
|
||||
bool success = loadTask.Wait(10000);
|
||||
if (!success)
|
||||
{
|
||||
DebugConsole.ThrowError("Failed to load texture data from " + (path ?? "stream") + ": timed out");
|
||||
return null;
|
||||
}
|
||||
if (preMultiplyAlpha)
|
||||
{
|
||||
PreMultiplyAlpha(ref texture);
|
||||
PreMultiplyAlpha(ref textureData);
|
||||
}
|
||||
return texture;
|
||||
Texture2D tex = null;
|
||||
CrossThread.RequestExecutionOnMainThread(() =>
|
||||
{
|
||||
tex = new Texture2D(_graphicsDevice, width, height);
|
||||
tex.SetData(textureData);
|
||||
});
|
||||
return tex;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -94,40 +109,35 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private static void PreMultiplyAlpha(ref Texture2D texture)
|
||||
private static void PreMultiplyAlpha(ref byte[] data)
|
||||
{
|
||||
UInt32[] data = new UInt32[texture.Width * texture.Height];
|
||||
texture.GetData(data);
|
||||
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
for (int i = 0; i < data.Length; i+=4)
|
||||
{
|
||||
uint a = (data[i] & 0xff000000) >> 24;
|
||||
uint a = data[i+3];
|
||||
if (a == 0)
|
||||
{
|
||||
data[i] = 0;
|
||||
data[i + 0] = 0;
|
||||
data[i + 1] = 0;
|
||||
data[i + 2] = 0;
|
||||
continue;
|
||||
}
|
||||
else if (a == uint.MaxValue)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
uint r = (data[i] & 0x00ff0000) >> 16;
|
||||
uint g = (data[i] & 0x0000ff00) >> 8;
|
||||
uint b = (data[i] & 0x000000ff);
|
||||
uint r = data[i+0];
|
||||
uint g = data[i+1];
|
||||
uint b = data[i+2];
|
||||
// Monogame 3.7 needs the line below.
|
||||
a *= a; a /= 255;
|
||||
b *= a; b /= 255;
|
||||
g *= a; g /= 255;
|
||||
r *= a; r /= 255;
|
||||
data[i] = (a << 24) | (r << 16) | (g << 8) | b;
|
||||
data[i + 0] = (byte)r;
|
||||
data[i + 1] = (byte)g;
|
||||
data[i + 2] = (byte)b;
|
||||
data[i + 3] = (byte)a;
|
||||
}
|
||||
|
||||
//not sure why this is needed, but it seems to cut the memory usage of the game almost in half
|
||||
//GetData/SetData might be leaking memory?
|
||||
int width = texture.Width; int height = texture.Height;
|
||||
texture.Dispose();
|
||||
texture = new Texture2D(_graphicsDevice, width, height);
|
||||
texture.SetData(data);
|
||||
}
|
||||
|
||||
|
||||
@@ -138,4 +148,4 @@ namespace Barotrauma
|
||||
private static SpriteBatch _spriteBatch;
|
||||
private static bool _needsBmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,8 +83,9 @@
|
||||
<Reference Include="GameAnalytics.Mono, Version=1.0.7018.15293, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\Libraries\NuGet\GameAnalytics.Mono.SDK.2.1.6\lib\net45\GameAnalytics.Mono.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="MonoGame.Framework, Version=3.7.1.189, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\Libraries\NuGet\MonoGame.Framework.WindowsDX.3.7.1.189\lib\net45\MonoGame.Framework.dll</HintPath>
|
||||
<Reference Include="MonoGame.Framework, Version=3.6.0.1625, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\Libraries\MonoGame.Framework\Windows\MonoGame.Framework.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\Libraries\NuGet\NLog.4.3.8\lib\net45\NLog.dll</HintPath>
|
||||
@@ -224,6 +225,9 @@
|
||||
<Content Include="soft_oal_x86.dll">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="x64\SDL2.dll">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BootstrapperPackage Include=".NETFramework,Version=v4.0">
|
||||
@@ -310,9 +314,7 @@
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\Libraries\NuGet\GameAnalytics.Mono.SDK.2.1.6\build\net45\GameAnalytics.Mono.SDK.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\Libraries\NuGet\GameAnalytics.Mono.SDK.2.1.6\build\net45\GameAnalytics.Mono.SDK.targets'))" />
|
||||
<Error Condition="!Exists('..\..\Libraries\NuGet\MonoGame.Framework.WindowsDX.3.7.1.189\build\MonoGame.Framework.WindowsDX.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\Libraries\NuGet\MonoGame.Framework.WindowsDX.3.7.1.189\build\MonoGame.Framework.WindowsDX.targets'))" />
|
||||
</Target>
|
||||
<Import Project="..\..\Libraries\NuGet\MonoGame.Framework.WindowsDX.3.7.1.189\build\MonoGame.Framework.WindowsDX.targets" Condition="Exists('..\..\Libraries\NuGet\MonoGame.Framework.WindowsDX.3.7.1.189\build\MonoGame.Framework.WindowsDX.targets')" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
<packages>
|
||||
<package id="GameAnalytics.Mono.SDK" version="2.1.6" targetFramework="net45" />
|
||||
<package id="Microsoft.NETCore.Platforms" version="3.0.0-preview.19073.11" targetFramework="net45" />
|
||||
<package id="MonoGame.Framework.DesktopGL" version="3.7.1.189" targetFramework="net45" />
|
||||
<package id="MonoGame.Framework.WindowsDX" version="3.7.1.189" targetFramework="net45" />
|
||||
<package id="NETStandard.Library" version="2.0.3" targetFramework="net45" />
|
||||
<package id="NLog" version="4.3.8" targetFramework="net45" />
|
||||
<package id="nVLC" version="3.0.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.6")]
|
||||
[assembly: AssemblyFileVersion("0.9.0.6")]
|
||||
[assembly: AssemblyVersion("0.9.0.7")]
|
||||
[assembly: AssemblyFileVersion("0.9.0.7")]
|
||||
|
||||
@@ -90,7 +90,16 @@ namespace Barotrauma
|
||||
while (queuedMessages.Count > 0)
|
||||
{
|
||||
ColoredText msg = queuedMessages.Dequeue();
|
||||
|
||||
if (GameSettings.SaveDebugConsoleLogs)
|
||||
{
|
||||
unsavedMessages.Add(msg);
|
||||
if (unsavedMessages.Count >= messagesPerFile)
|
||||
{
|
||||
SaveLogs();
|
||||
unsavedMessages.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
string msgTxt = msg.Text;
|
||||
|
||||
if (msg.IsCommand) commandMemory.Add(msgTxt);
|
||||
@@ -167,7 +176,8 @@ namespace Barotrauma
|
||||
RewriteInputToCommandLine(input);
|
||||
}
|
||||
|
||||
Thread.Yield();
|
||||
//TODO: be more clever about it
|
||||
Thread.Sleep(10); //sleep for 10ms to not pin the CPU super hard
|
||||
}
|
||||
}
|
||||
catch (ThreadAbortException)
|
||||
@@ -778,11 +788,47 @@ namespace Barotrauma
|
||||
GameMain.Server.SendConsoleMessage("The code words are: " + traitorManager.codeWords + ", response: " + traitorManager.codeResponse + ".", client);
|
||||
});
|
||||
|
||||
commands.Add(new Command("setpassword|setserverpassword", "setpassword [password]: Changes the password of the server that's being hosted.", (string[] args) =>
|
||||
commands.Add(new Command("setpassword|setserverpassword|password", "setpassword [password]: Changes the password of the server that's being hosted.", (string[] args) =>
|
||||
{
|
||||
if (GameMain.Server == null) { return; }
|
||||
GameMain.Server.ServerSettings.SetPassword(args.Length > 0 ? args[0] : "");
|
||||
NewMessage(GameMain.Server.ServerSettings.HasPassword ? "Changed the server password." : "Removed password protection from the server.");
|
||||
}));
|
||||
AssignOnClientRequestExecute("setpassword", (Client client, Vector2 cursorPos, string[] args) =>
|
||||
{
|
||||
if (GameMain.Server == null) { return; }
|
||||
GameMain.Server.ServerSettings.SetPassword(args.Length > 0 ? args[0] : "");
|
||||
NewMessage(client.Name + " " + (GameMain.Server.ServerSettings.HasPassword ? " changed the server password to \"" + args[0] + "\"." : " removed password protection from the server."));
|
||||
GameMain.Server.SendConsoleMessage(GameMain.Server.ServerSettings.HasPassword ? "Changed the server password." : "Removed password protection from the server.", client);
|
||||
});
|
||||
|
||||
commands.Add(new Command("setmaxplayers|maxplayers", "setmaxplayers [max players]: Sets the maximum player count of the server that's being hosted.", (string[] args) =>
|
||||
{
|
||||
if (GameMain.Server == null || args.Length == 0) return;
|
||||
GameMain.Server.ServerSettings.SetPassword(args[0]);
|
||||
if (!int.TryParse(args[0], out int maxPlayers))
|
||||
{
|
||||
NewMessage(args[0] + " is not a valid player count.");
|
||||
}
|
||||
else
|
||||
{
|
||||
GameMain.Server.ServerSettings.MaxPlayers = maxPlayers;
|
||||
NewMessage("Set the maximum player count to " + maxPlayers + ".");
|
||||
}
|
||||
}));
|
||||
AssignOnClientRequestExecute("setmaxplayers", (Client client, Vector2 cursorPos, string[] args) =>
|
||||
{
|
||||
if (GameMain.Server == null || args.Length == 0) return;
|
||||
if (!int.TryParse(args[0], out int maxPlayers))
|
||||
{
|
||||
GameMain.Server.SendConsoleMessage(args[0] + " is not a valid player count.", client);
|
||||
}
|
||||
else
|
||||
{
|
||||
GameMain.Server.ServerSettings.MaxPlayers = maxPlayers;
|
||||
NewMessage(client.Name + " set the maximum player count to " + maxPlayers + ".");
|
||||
GameMain.Server.SendConsoleMessage("Set the maximum player count to " + maxPlayers + ".", client);
|
||||
}
|
||||
});
|
||||
|
||||
commands.Add(new Command("restart|reset", "restart/reset: Close and restart the server.", (string[] args) =>
|
||||
{
|
||||
@@ -1579,12 +1625,6 @@ namespace Barotrauma
|
||||
}
|
||||
}));
|
||||
|
||||
commands.Add(new Command("setpassword|setserverpassword", "setpassword [password]: Changes the password of the server that's being hosted.", (string[] args) =>
|
||||
{
|
||||
if (GameMain.Server == null || args.Length == 0) return;
|
||||
GameMain.Server.ServerSettings.SetPassword(args[0]);
|
||||
}));
|
||||
|
||||
#if DEBUG
|
||||
commands.Add(new Command("spamevents", "A debug command that creates a ton of entity events.", (string[] args) =>
|
||||
{
|
||||
|
||||
@@ -165,13 +165,27 @@ namespace Barotrauma.Networking
|
||||
expirationTime = DateTime.Now + duration.Value;
|
||||
}
|
||||
|
||||
bannedPlayers.Add(new BannedPlayer(name, ip, reason, expirationTime));
|
||||
if (!string.IsNullOrEmpty(ip))
|
||||
{
|
||||
bannedPlayers.Add(new BannedPlayer(name, ip, reason, expirationTime));
|
||||
}
|
||||
else if (steamID > 0)
|
||||
{
|
||||
bannedPlayers.Add(new BannedPlayer(name, steamID, reason, expirationTime));
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugConsole.ThrowError("Failed to ban a client (no valid IP or Steam ID given)");
|
||||
return;
|
||||
}
|
||||
|
||||
Save();
|
||||
}
|
||||
|
||||
public void UnbanPlayer(string name)
|
||||
{
|
||||
var player = bannedPlayers.Find(bp => bp.Name == name);
|
||||
name = name.ToLower();
|
||||
var player = bannedPlayers.Find(bp => bp.Name.ToLower() == name);
|
||||
if (player == null)
|
||||
{
|
||||
DebugConsole.Log("Could not unban player \"" + name + "\". Matching player not found.");
|
||||
|
||||
@@ -26,6 +26,10 @@ namespace Barotrauma.Networking
|
||||
//for keeping track of disconnected clients in case the reconnect shortly after
|
||||
private List<Client> disconnectedClients = new List<Client>();
|
||||
|
||||
//keeps track of players who've previously been playing on the server
|
||||
//so kick votes persist during the session and the server can let the clients know what name this client used previously
|
||||
private readonly List<PreviousPlayer> previousPlayers = new List<PreviousPlayer>();
|
||||
|
||||
private int roundStartSeed;
|
||||
|
||||
//is the server running
|
||||
@@ -34,7 +38,7 @@ namespace Barotrauma.Networking
|
||||
private NetServer server;
|
||||
|
||||
private DateTime refreshMasterTimer;
|
||||
private TimeSpan refreshMasterInterval = new TimeSpan(0, 0, 30);
|
||||
private TimeSpan refreshMasterInterval = new TimeSpan(0, 0, 60);
|
||||
private bool registeredToMaster;
|
||||
|
||||
private DateTime roundStartTime;
|
||||
@@ -657,23 +661,25 @@ namespace Barotrauma.Networking
|
||||
updateTimer = DateTime.Now + updateInterval;
|
||||
}
|
||||
|
||||
if (!registeredToMaster || refreshMasterTimer >= DateTime.Now) return;
|
||||
|
||||
if (GameMain.Config.UseSteamMatchmaking)
|
||||
if (registeredToMaster && (DateTime.Now > refreshMasterTimer || serverSettings.ServerDetailsChanged))
|
||||
{
|
||||
bool refreshSuccessful = SteamManager.RefreshServerDetails(this);
|
||||
if (GameSettings.VerboseLogging)
|
||||
if (GameMain.Config.UseSteamMatchmaking)
|
||||
{
|
||||
Log(refreshSuccessful ?
|
||||
"Refreshed server info on the server list." :
|
||||
"Refreshing server info on the server list failed.", ServerLog.MessageType.ServerMessage);
|
||||
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
|
||||
{
|
||||
CoroutineManager.StartCoroutine(RefreshMaster());
|
||||
}
|
||||
refreshMasterTimer = DateTime.Now + refreshMasterInterval;
|
||||
serverSettings.ServerDetailsChanged = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
CoroutineManager.StartCoroutine(RefreshMaster());
|
||||
}
|
||||
refreshMasterTimer = DateTime.Now + refreshMasterInterval;
|
||||
}
|
||||
|
||||
private void ReadDataMessage(NetIncomingMessage inc)
|
||||
@@ -724,7 +730,7 @@ namespace Barotrauma.Networking
|
||||
bool isNew = inc.ReadBoolean(); inc.ReadPadBits();
|
||||
if (isNew)
|
||||
{
|
||||
string savePath = inc.ReadString();
|
||||
string saveName = inc.ReadString();
|
||||
string seed = inc.ReadString();
|
||||
string subName = inc.ReadString();
|
||||
string subHash = inc.ReadString();
|
||||
@@ -739,7 +745,11 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
else
|
||||
{
|
||||
if (connectedClient.HasPermission(ClientPermissions.SelectMode)) MultiPlayerCampaign.StartNewCampaign(savePath, matchingSub.FilePath, seed);
|
||||
string localSavePath = SaveUtil.CreateSavePath(SaveUtil.SaveType.Multiplayer, saveName);
|
||||
if (connectedClient.HasPermission(ClientPermissions.SelectMode))
|
||||
{
|
||||
MultiPlayerCampaign.StartNewCampaign(localSavePath, matchingSub.FilePath, seed);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -2182,7 +2192,6 @@ namespace Barotrauma.Networking
|
||||
|
||||
public override void UnbanPlayer(string playerName, string playerIP)
|
||||
{
|
||||
playerName = playerName.ToLowerInvariant();
|
||||
if (!string.IsNullOrEmpty(playerIP))
|
||||
{
|
||||
serverSettings.BanList.UnbanIP(playerIP);
|
||||
@@ -2230,6 +2239,19 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (client.SteamID > 0) { SteamManager.StopAuthSession(client.SteamID); }
|
||||
|
||||
var previousPlayer = previousPlayers.Find(p => p.MatchesClient(client));
|
||||
if (previousPlayer == null)
|
||||
{
|
||||
previousPlayer = new PreviousPlayer(client);
|
||||
previousPlayers.Add(previousPlayer);
|
||||
}
|
||||
previousPlayer.Name = client.Name;
|
||||
previousPlayer.KickVoters.Clear();
|
||||
foreach (Client c in connectedClients)
|
||||
{
|
||||
if (client.HasKickVoteFrom(c)) { previousPlayer.KickVoters.Add(c); }
|
||||
}
|
||||
|
||||
client.Connection.Disconnect(targetmsg);
|
||||
client.Dispose();
|
||||
connectedClients.Remove(client);
|
||||
@@ -2240,6 +2262,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
UpdateCrewFrame();
|
||||
|
||||
serverSettings.ServerDetailsChanged = true;
|
||||
refreshMasterTimer = DateTime.Now;
|
||||
}
|
||||
|
||||
@@ -2558,6 +2581,13 @@ namespace Barotrauma.Networking
|
||||
c.KickVoteCount >= connectedClients.Count * serverSettings.KickVoteRequiredRatio);
|
||||
foreach (Client c in clientsToKick)
|
||||
{
|
||||
var previousPlayer = previousPlayers.Find(p => p.MatchesClient(c));
|
||||
if (previousPlayer != null)
|
||||
{
|
||||
//reset the client's kick votes (they can rejoin after their ban expires)
|
||||
previousPlayer.KickVoters.Clear();
|
||||
}
|
||||
|
||||
SendChatMessage($"ServerMessage.KickedFromServer~[client]={c.Name}", ChatMessageType.Server, null);
|
||||
KickClient(c, "ServerMessage.KickedByVote");
|
||||
BanClient(c, "ServerMessage.KickedByVoteAutoBan", duration: TimeSpan.FromSeconds(serverSettings.AutoBanTime));
|
||||
@@ -3030,4 +3060,25 @@ namespace Barotrauma.Networking
|
||||
//do nothing
|
||||
}
|
||||
}
|
||||
|
||||
partial class PreviousPlayer
|
||||
{
|
||||
public string Name;
|
||||
public string IP;
|
||||
public UInt64 SteamID;
|
||||
public readonly List<Client> KickVoters = new List<Client>();
|
||||
|
||||
public PreviousPlayer(Client c)
|
||||
{
|
||||
Name = c.Name;
|
||||
IP = c.Connection?.RemoteEndPoint?.Address?.ToString() ?? "";
|
||||
SteamID = c.SteamID;
|
||||
}
|
||||
|
||||
public bool MatchesClient(Client c)
|
||||
{
|
||||
if (c.SteamID > 0 && SteamID > 0) { return c.SteamID == SteamID; }
|
||||
return c.IPMatches(IP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -418,7 +418,7 @@ namespace Barotrauma.Networking
|
||||
return "\"" + nameAndHash.First + "\" (hash " + Md5Hash.GetShortHash(nameAndHash.Second) + ")";
|
||||
}
|
||||
|
||||
if (!serverSettings.Whitelist.IsWhiteListed(clName, inc.SenderConnection.RemoteEndPoint.Address))
|
||||
if (inc.SenderConnection != OwnerConnection && !serverSettings.Whitelist.IsWhiteListed(clName, inc.SenderConnection.RemoteEndPoint.Address))
|
||||
{
|
||||
DisconnectUnauthClient(inc, unauthClient, DisconnectReason.NotOnWhitelist, "");
|
||||
Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (not in whitelist)", ServerLog.MessageType.Error);
|
||||
@@ -470,6 +470,17 @@ namespace Barotrauma.Networking
|
||||
unauthenticatedClients.Remove(unauthClient);
|
||||
unauthClient = null;
|
||||
ConnectedClients.Add(newClient);
|
||||
|
||||
var previousPlayer = previousPlayers.Find(p => p.MatchesClient(newClient));
|
||||
if (previousPlayer != null)
|
||||
{
|
||||
foreach (Client c in previousPlayer.KickVoters)
|
||||
{
|
||||
if (!connectedClients.Contains(c)) { continue; }
|
||||
newClient.AddKickVote(c);
|
||||
}
|
||||
}
|
||||
|
||||
LastClientListUpdateID++;
|
||||
|
||||
if (newClient.Connection == OwnerConnection)
|
||||
@@ -482,6 +493,13 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
|
||||
GameMain.Server.SendChatMessage($"ServerMessage.JoinedServer~[client]={clName}", ChatMessageType.Server, null);
|
||||
serverSettings.ServerDetailsChanged = true;
|
||||
|
||||
if (previousPlayer != null && previousPlayer.Name != newClient.Name)
|
||||
{
|
||||
GameMain.Server.SendChatMessage($"ServerMessage.PreviousClientName~[client]={clName}~[previousname]={previousPlayer.Name}", ChatMessageType.Server, null);
|
||||
previousPlayer.Name = newClient.Name;
|
||||
}
|
||||
|
||||
var savedPermissions = serverSettings.ClientPermissions.Find(cp =>
|
||||
cp.SteamID > 0 ?
|
||||
|
||||
@@ -42,6 +42,8 @@ namespace Barotrauma.Steam
|
||||
return false;
|
||||
}
|
||||
|
||||
var contentPackages = GameMain.Config.SelectedContentPackages.Where(cp => cp.HasMultiplayerIncompatibleContent);
|
||||
|
||||
// These server state variables may be changed at any time. Note that there is no longer a mechanism
|
||||
// to send the player count. The player count is maintained by steam and you should use the player
|
||||
// creation/authentication functions to maintain your player count.
|
||||
@@ -51,9 +53,10 @@ namespace Barotrauma.Steam
|
||||
instance.server.MapName = GameMain.NetLobbyScreen?.SelectedSub?.DisplayName ?? "";
|
||||
Instance.server.SetKey("message", GameMain.Server.ServerSettings.ServerMessageText);
|
||||
Instance.server.SetKey("version", GameMain.Version.ToString());
|
||||
Instance.server.SetKey("contentpackage", string.Join(",", GameMain.Config.SelectedContentPackages.Select(cp => cp.Name)));
|
||||
Instance.server.SetKey("contentpackagehash", string.Join(",", GameMain.Config.SelectedContentPackages.Select(cp => cp.MD5hash.Hash)));
|
||||
Instance.server.SetKey("contentpackageurl", string.Join(",", GameMain.Config.SelectedContentPackages.Select(cp => cp.SteamWorkshopUrl ?? "")));
|
||||
Instance.server.SetKey("playercount", GameMain.Server.ConnectedClients.Count.ToString());
|
||||
Instance.server.SetKey("contentpackage", string.Join(",", contentPackages.Select(cp => cp.Name)));
|
||||
Instance.server.SetKey("contentpackagehash", string.Join(",", contentPackages.Select(cp => cp.MD5hash.Hash)));
|
||||
Instance.server.SetKey("contentpackageurl", string.Join(",", contentPackages.Select(cp => cp.SteamWorkshopUrl ?? "")));
|
||||
Instance.server.SetKey("usingwhitelist", (server.ServerSettings.Whitelist != null && server.ServerSettings.Whitelist.Enabled).ToString());
|
||||
Instance.server.SetKey("modeselectionmode", server.ServerSettings.ModeSelectionMode.ToString());
|
||||
Instance.server.SetKey("subselectionmode", server.ServerSettings.SubSelectionMode.ToString());
|
||||
@@ -72,7 +75,7 @@ namespace Barotrauma.Steam
|
||||
public static bool StartAuthSession(byte[] authTicketData, ulong clientSteamID)
|
||||
{
|
||||
if (instance == null || !instance.isInitialized || instance.server == null) return false;
|
||||
|
||||
|
||||
DebugConsole.Log("SteamManager authenticating Steam client " + clientSteamID);
|
||||
if (!instance.server.Auth.StartSession(authTicketData, clientSteamID))
|
||||
{
|
||||
|
||||
@@ -77,9 +77,10 @@ namespace Barotrauma.Networking
|
||||
bool recipientSpectating = recipient.Character == null || recipient.Character.IsDead;
|
||||
bool senderSpectating = sender.Character == null || sender.Character.IsDead;
|
||||
|
||||
//spectators cannot speak with in-game players or vice versa
|
||||
//TODO: allow spectators to hear the voice chat if close enough to the speaker?
|
||||
if (recipientSpectating != senderSpectating) { return false; }
|
||||
//TODO: only allow spectators to hear the voice chat if close enough to the speaker?
|
||||
|
||||
//non-spectators cannot hear spectators
|
||||
if (senderSpectating && !recipientSpectating) { return false; }
|
||||
|
||||
//both spectating, no need to do radio/distance checks
|
||||
if (recipientSpectating && senderSpectating) { return true; }
|
||||
|
||||
@@ -25,47 +25,45 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
partial void InitProjSpecific()
|
||||
{
|
||||
if (File.Exists(SavePath))
|
||||
if (!File.Exists(SavePath)) { return; }
|
||||
|
||||
string[] lines;
|
||||
try
|
||||
{
|
||||
string[] lines;
|
||||
try
|
||||
{
|
||||
lines = File.ReadAllLines(SavePath);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DebugConsole.ThrowError("Failed to open whitelist in " + SavePath, e);
|
||||
return;
|
||||
}
|
||||
lines = File.ReadAllLines(SavePath);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DebugConsole.ThrowError("Failed to open whitelist in " + SavePath, e);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (string line in lines)
|
||||
foreach (string line in lines)
|
||||
{
|
||||
if (line[0] == '#')
|
||||
{
|
||||
if (line[0] == '#')
|
||||
string lineval = line.Substring(1, line.Length - 1);
|
||||
Int32.TryParse(lineval, out int intVal);
|
||||
if (lineval.ToLower() == "true" || intVal != 0)
|
||||
{
|
||||
string lineval = line.Substring(1, line.Length - 1);
|
||||
int intVal = 0;
|
||||
Int32.TryParse(lineval, out intVal);
|
||||
if (lineval.ToLower() == "true" || intVal != 0)
|
||||
{
|
||||
Enabled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Enabled = false;
|
||||
}
|
||||
Enabled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
string[] separatedLine = line.Split(',');
|
||||
if (separatedLine.Length < 2) continue;
|
||||
|
||||
string name = String.Join(",", separatedLine.Take(separatedLine.Length - 1));
|
||||
string ip = separatedLine.Last();
|
||||
|
||||
whitelistedPlayers.Add(new WhiteListedPlayer(name, ip));
|
||||
Enabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string[] separatedLine = line.Split(',');
|
||||
if (separatedLine.Length < 2) continue;
|
||||
|
||||
string name = string.Join(",", separatedLine.Take(separatedLine.Length - 1));
|
||||
string ip = separatedLine.Last();
|
||||
|
||||
whitelistedPlayers.Add(new WhiteListedPlayer(name, ip));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Save()
|
||||
@@ -119,9 +117,7 @@ namespace Barotrauma.Networking
|
||||
private void RemoveFromWhiteList(WhiteListedPlayer wlp)
|
||||
{
|
||||
GameServer.Log("Removing " + wlp.Name + " from whitelist", ServerLog.MessageType.ServerMessage);
|
||||
|
||||
whitelistedPlayers.Remove(wlp);
|
||||
Save();
|
||||
}
|
||||
|
||||
private void AddToWhiteList(string name, string ip)
|
||||
@@ -129,7 +125,6 @@ namespace Barotrauma.Networking
|
||||
if (string.IsNullOrWhiteSpace(name)) return;
|
||||
if (whitelistedPlayers.Any(x => x.Name.ToLower() == name.ToLower() && x.IP == ip)) return;
|
||||
whitelistedPlayers.Add(new WhiteListedPlayer(name, ip));
|
||||
Save();
|
||||
}
|
||||
|
||||
public void ServerAdminWrite(NetBuffer outMsg, Client c)
|
||||
@@ -201,8 +196,10 @@ namespace Barotrauma.Networking
|
||||
GameServer.Log(c.Name + " added " + name + " to whitelist (" + ip + ")", ServerLog.MessageType.ConsoleUsage);
|
||||
AddToWhiteList(name, ip);
|
||||
}
|
||||
|
||||
return removeCount > 0 || addCount > 0 || prevEnabled!=enabled;
|
||||
|
||||
bool changed = removeCount > 0 || addCount > 0 || prevEnabled != enabled;
|
||||
if (changed) { Save(); }
|
||||
return changed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,15 @@ namespace Barotrauma
|
||||
public Submarine SelectedSub
|
||||
{
|
||||
get { return selectedSub; }
|
||||
set { selectedSub = value; lastUpdateID++; }
|
||||
set
|
||||
{
|
||||
selectedSub = value;
|
||||
lastUpdateID++;
|
||||
if (GameMain.NetworkMember?.ServerSettings != null)
|
||||
{
|
||||
GameMain.NetworkMember.ServerSettings.ServerDetailsChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
public Submarine SelectedShuttle
|
||||
{
|
||||
@@ -32,6 +40,11 @@ namespace Barotrauma
|
||||
{
|
||||
lastUpdateID++;
|
||||
selectedModeIndex = MathHelper.Clamp(value, 0, GameModes.Length - 1);
|
||||
if (GameMain.NetworkMember?.ServerSettings != null)
|
||||
{
|
||||
GameMain.NetworkMember.ServerSettings.GameModeIdentifier = SelectedModeIdentifier;
|
||||
GameMain.NetworkMember.ServerSettings.ServerDetailsChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +61,11 @@ namespace Barotrauma
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (GameMain.NetworkMember?.ServerSettings != null)
|
||||
{
|
||||
GameMain.NetworkMember.ServerSettings.GameModeIdentifier = SelectedModeIdentifier;
|
||||
GameMain.NetworkMember.ServerSettings.ServerDetailsChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -196,7 +196,7 @@ namespace Barotrauma
|
||||
if (ignoredHulls != null && ignoredHulls.Contains(hull)) { continue; }
|
||||
if (unreachable.Contains(hull)) { continue; }
|
||||
float hullSafety = 0;
|
||||
if (character.CurrentHull != null)
|
||||
if (character.CurrentHull != null && character.Submarine != null)
|
||||
{
|
||||
// Inside
|
||||
if (!character.Submarine.IsConnectedTo(hull.Submarine)) { continue; }
|
||||
|
||||
@@ -1101,7 +1101,7 @@ namespace Barotrauma
|
||||
//prevent the hands from going above the top of the ladders
|
||||
handPos.Y = Math.Min(-0.5f, handPos.Y);
|
||||
|
||||
if (!PlayerInput.KeyDown(InputType.Aim) || Math.Abs(movement.Y) > 0.01f)
|
||||
if (!character.IsKeyDown(InputType.Aim) || Math.Abs(movement.Y) > 0.01f)
|
||||
{
|
||||
MoveLimb(leftHand,
|
||||
new Vector2(handPos.X,
|
||||
|
||||
@@ -836,13 +836,21 @@ namespace Barotrauma
|
||||
private static string humanConfigFile;
|
||||
public static string HumanConfigFile
|
||||
{
|
||||
get
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(humanConfigFile))
|
||||
{
|
||||
humanConfigFile = GetConfigFile("Human");
|
||||
humanConfigFile = GameMain.Instance.GetFilesOfType(ContentType.Character)?
|
||||
.FirstOrDefault(c => Path.GetFileName(c).ToLowerInvariant() == "human.xml");
|
||||
|
||||
if (humanConfigFile == null)
|
||||
{
|
||||
DebugConsole.ThrowError($"Couldn't find a human config file from the selected content packages!");
|
||||
DebugConsole.ThrowError($"(The config file must end with \"human.xml\")");
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
return humanConfigFile;
|
||||
return humanConfigFile;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -859,12 +867,16 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Searches for a character config file from all currently selected content packages,
|
||||
/// or from a specific package if the contentPackage parameter is given.
|
||||
/// </summary>
|
||||
public static string GetConfigFile(string speciesName, ContentPackage contentPackage = null)
|
||||
{
|
||||
string configFile = null;
|
||||
if (contentPackage == null)
|
||||
{
|
||||
configFile = GameMain.Instance.GetFilesOfType(ContentType.Character, searchAllContentPackages: true)
|
||||
configFile = GameMain.Instance.GetFilesOfType(ContentType.Character)
|
||||
.FirstOrDefault(c => Path.GetFileName(c).ToLowerInvariant() == $"{speciesName.ToLowerInvariant()}.xml");
|
||||
}
|
||||
else
|
||||
@@ -1519,10 +1531,9 @@ namespace Barotrauma
|
||||
if (inventory.Owner is Item)
|
||||
{
|
||||
var owner = (Item)inventory.Owner;
|
||||
if (!CanInteractWith(owner))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!CanInteractWith(owner)) { return false; }
|
||||
ItemContainer container = owner.GetComponents<ItemContainer>().FirstOrDefault(ic => ic.Inventory == inventory);
|
||||
if (container != null && !container.HasRequiredItems(this, addMessage: false)) { return false; }
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -747,7 +747,7 @@ namespace Barotrauma
|
||||
|
||||
public void IncreaseSkillLevel(string skillIdentifier, float increase, Vector2 worldPos)
|
||||
{
|
||||
if (Job == null || (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient)) return;
|
||||
if (Job == null || (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) || Character == null) { return; }
|
||||
|
||||
float prevLevel = Job.GetSkillLevel(skillIdentifier);
|
||||
Job.IncreaseSkillLevel(skillIdentifier, increase);
|
||||
|
||||
@@ -444,6 +444,8 @@ namespace Barotrauma
|
||||
public bool SectorHit(Vector2 armorSector, Vector2 simPosition)
|
||||
{
|
||||
if (armorSector == Vector2.Zero) { return false; }
|
||||
//sector 360 degrees or more -> always hits
|
||||
if (Math.Abs(armorSector.Y - armorSector.X) >= MathHelper.TwoPi) { return true; }
|
||||
float rotation = body.TransformedRotation;
|
||||
float offset = (MathHelper.PiOver2 - GetArmorSectorRotationOffset(armorSector)) * Dir;
|
||||
float hitAngle = VectorExtensions.Angle(VectorExtensions.Forward(rotation + offset), SimPosition - simPosition);
|
||||
@@ -460,9 +462,7 @@ namespace Barotrauma
|
||||
|
||||
protected float GetArmorSectorSize(Vector2 armorSector)
|
||||
{
|
||||
float min = Math.Min(armorSector.X, armorSector.Y);
|
||||
float max = Math.Max(armorSector.X, armorSector.Y);
|
||||
return max - min;
|
||||
return Math.Abs(armorSector.X - armorSector.Y);
|
||||
}
|
||||
|
||||
public void Update(float deltaTime)
|
||||
|
||||
@@ -498,7 +498,7 @@ namespace Barotrauma
|
||||
{
|
||||
Path = path;
|
||||
|
||||
#if OSX
|
||||
#if OSX || LINUX
|
||||
Path = Path.Replace("\\", "/");
|
||||
#endif
|
||||
|
||||
|
||||
@@ -328,7 +328,7 @@ namespace Barotrauma
|
||||
};
|
||||
}));
|
||||
|
||||
commands.Add(new Command("kickid", "kickid [id]: Kick the player with the specified client ID out of the server.", (string[] args) =>
|
||||
commands.Add(new Command("kickid", "kickid [id]: Kick the player with the specified client ID out of the server. You can see the IDs of the clients using the command \"clientlist\".", (string[] args) =>
|
||||
{
|
||||
if (GameMain.NetworkMember == null || args.Length == 0) return;
|
||||
|
||||
@@ -380,7 +380,7 @@ namespace Barotrauma
|
||||
};
|
||||
}));
|
||||
|
||||
commands.Add(new Command("banid", "banid [id]: Kick and ban the player with the specified client ID from the server.", (string[] args) =>
|
||||
commands.Add(new Command("banid", "banid [id]: Kick and ban the player with the specified client ID from the server. You can see the IDs of the clients using the command \"clientlist\".", (string[] args) =>
|
||||
{
|
||||
if (GameMain.NetworkMember == null || args.Length == 0) return;
|
||||
|
||||
|
||||
@@ -66,12 +66,13 @@ namespace Barotrauma
|
||||
|
||||
if (GameMain.Config?.SelectedContentPackages.Count > 0)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder("ContentPackage:");
|
||||
StringBuilder sb = new StringBuilder("ContentPackage: ");
|
||||
int i = 0;
|
||||
foreach (ContentPackage cp in GameMain.Config.SelectedContentPackages)
|
||||
{
|
||||
sb.Append(cp.Name.Replace(":", "").Substring(0, Math.Min(32, cp.Name.Length)));
|
||||
if (i < GameMain.Config.SelectedContentPackages.Count - 1) sb.Append(",");
|
||||
string trimmedName = cp.Name.Replace(":", "").Replace(" ", "");
|
||||
sb.Append(trimmedName.Substring(0, Math.Min(32, trimmedName.Length)));
|
||||
if (i < GameMain.Config.SelectedContentPackages.Count - 1) { sb.Append(" "); }
|
||||
}
|
||||
GameAnalytics.AddDesignEvent(sb.ToString());
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Collections.Generic;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
using System.Xml;
|
||||
using System.IO;
|
||||
#if CLIENT
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using Barotrauma.Tutorials;
|
||||
@@ -142,6 +143,8 @@ namespace Barotrauma
|
||||
public bool CrewMenuOpen { get; set; } = true;
|
||||
public bool ChatOpen { get; set; } = true;
|
||||
|
||||
private string overrideSaveFolder, overrideMultiplayerSaveFolder;
|
||||
|
||||
private bool unsavedSettings;
|
||||
public bool UnsavedSettings
|
||||
{
|
||||
@@ -277,7 +280,6 @@ namespace Barotrauma
|
||||
|
||||
public GameSettings()
|
||||
{
|
||||
SelectedContentPackages = new HashSet<ContentPackage>();
|
||||
ContentPackage.LoadAll(ContentPackage.Folder);
|
||||
CompletedTutorialNames = new List<string>();
|
||||
|
||||
@@ -605,6 +607,17 @@ namespace Barotrauma
|
||||
LoadControls(doc);
|
||||
LoadContentPackages(doc);
|
||||
|
||||
//allow overriding the save paths in the config file
|
||||
if (doc.Root.Attribute("overridesavefolder") != null)
|
||||
{
|
||||
overrideSaveFolder = SaveUtil.SaveFolder = doc.Root.GetAttributeString("overridesavefolder", "");
|
||||
overrideMultiplayerSaveFolder = SaveUtil.MultiplayerSaveFolder = Path.Combine(overrideSaveFolder, "Multiplayer");
|
||||
}
|
||||
if (doc.Root.Attribute("overridemultiplayersavefolder") != null)
|
||||
{
|
||||
overrideMultiplayerSaveFolder = SaveUtil.MultiplayerSaveFolder = doc.Root.GetAttributeString("overridemultiplayersavefolder", "");
|
||||
}
|
||||
|
||||
XElement tutorialsElement = doc.Root.Element("tutorials");
|
||||
if (tutorialsElement != null)
|
||||
{
|
||||
@@ -732,6 +745,15 @@ namespace Barotrauma
|
||||
new XAttribute("campaigndisclaimershown", CampaignDisclaimerShown),
|
||||
new XAttribute("editordisclaimershown", EditorDisclaimerShown));
|
||||
|
||||
if (!string.IsNullOrEmpty(overrideSaveFolder))
|
||||
{
|
||||
doc.Root.Add(new XAttribute("overridesavefolder", overrideSaveFolder));
|
||||
}
|
||||
if (!string.IsNullOrEmpty(overrideMultiplayerSaveFolder))
|
||||
{
|
||||
doc.Root.Add(new XAttribute("overridemultiplayersavefolder", overrideMultiplayerSaveFolder));
|
||||
}
|
||||
|
||||
if (!ShowUserStatisticsPrompt)
|
||||
{
|
||||
doc.Root.Add(new XAttribute("senduserstatistics", sendUserStatistics));
|
||||
|
||||
@@ -22,7 +22,6 @@ namespace Barotrauma.Items.Components
|
||||
private float openState;
|
||||
private Sprite doorSprite, weldedSprite, brokenSprite;
|
||||
private bool scaleBrokenSprite, fadeBrokenSprite;
|
||||
private bool createdNewGap;
|
||||
private bool autoOrientGap;
|
||||
|
||||
private bool isStuck;
|
||||
@@ -87,17 +86,19 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
get
|
||||
{
|
||||
if (linkedGap != null) return linkedGap;
|
||||
|
||||
foreach (MapEntity e in item.linkedTo)
|
||||
if (linkedGap == null)
|
||||
{
|
||||
linkedGap = e as Gap;
|
||||
if (linkedGap != null)
|
||||
{
|
||||
linkedGap.PassAmbientLight = Window != Rectangle.Empty;
|
||||
return linkedGap;
|
||||
}
|
||||
GetLinkedGap();
|
||||
}
|
||||
return linkedGap;
|
||||
}
|
||||
}
|
||||
|
||||
private void GetLinkedGap()
|
||||
{
|
||||
linkedGap = item.linkedTo.FirstOrDefault(e => e is Gap) as Gap;
|
||||
if (linkedGap == null)
|
||||
{
|
||||
Rectangle rect = item.Rect;
|
||||
if (IsHorizontal)
|
||||
{
|
||||
@@ -109,17 +110,13 @@ namespace Barotrauma.Items.Components
|
||||
rect.X -= 5;
|
||||
rect.Width += 10;
|
||||
}
|
||||
|
||||
linkedGap = new Gap(rect, !IsHorizontal, Item.Submarine)
|
||||
{
|
||||
Submarine = item.Submarine,
|
||||
PassAmbientLight = Window != Rectangle.Empty,
|
||||
Open = openState
|
||||
Submarine = item.Submarine
|
||||
};
|
||||
item.linkedTo.Add(linkedGap);
|
||||
createdNewGap = true;
|
||||
return linkedGap;
|
||||
}
|
||||
RefreshLinkedGap();
|
||||
}
|
||||
|
||||
public bool IsHorizontal { get; private set; }
|
||||
@@ -162,14 +159,14 @@ namespace Barotrauma.Items.Components
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
|
||||
public Door(Item item, XElement element)
|
||||
: base(item, element)
|
||||
{
|
||||
IsHorizontal = element.GetAttributeBool("horizontal", false);
|
||||
canBePicked = element.GetAttributeBool("canbepicked", false);
|
||||
autoOrientGap = element.GetAttributeBool("autoorientgap", false);
|
||||
|
||||
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
string texturePath = subElement.GetAttributeString("texture", "");
|
||||
@@ -370,12 +367,20 @@ namespace Barotrauma.Items.Components
|
||||
#endif
|
||||
}
|
||||
|
||||
public override void OnMapLoaded()
|
||||
public void RefreshLinkedGap()
|
||||
{
|
||||
LinkedGap.ConnectedDoor = this;
|
||||
if (autoOrientGap)
|
||||
{
|
||||
LinkedGap.AutoOrient();
|
||||
}
|
||||
LinkedGap.Open = openState;
|
||||
if (createdNewGap && autoOrientGap) linkedGap.AutoOrient();
|
||||
LinkedGap.PassAmbientLight = Window != Rectangle.Empty;
|
||||
}
|
||||
|
||||
public override void OnMapLoaded()
|
||||
{
|
||||
RefreshLinkedGap();
|
||||
#if CLIENT
|
||||
Vector2[] corners = GetConvexHullCorners(Rectangle.Empty);
|
||||
|
||||
@@ -386,6 +391,18 @@ namespace Barotrauma.Items.Components
|
||||
#endif
|
||||
}
|
||||
|
||||
public override void OnScaleChanged()
|
||||
{
|
||||
#if CLIENT
|
||||
UpdateConvexHulls();
|
||||
#endif
|
||||
if (linkedGap != null)
|
||||
{
|
||||
RefreshLinkedGap();
|
||||
linkedGap.Rect = item.Rect;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void RemoveComponentSpecific()
|
||||
{
|
||||
base.RemoveComponentSpecific();
|
||||
|
||||
@@ -53,12 +53,6 @@ namespace Barotrauma.Items.Components
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// How useful the weapon is in combat? Used by AI to sort the used weapon. For the sake of clarity, use a value between 0 and 100 (not enforced).
|
||||
/// </summary>
|
||||
[Serialize(0f, false)]
|
||||
public float CombatPriority { get; private set; }
|
||||
|
||||
public MeleeWeapon(Item item, XElement element)
|
||||
: base(item, element)
|
||||
{
|
||||
|
||||
@@ -43,12 +43,6 @@ namespace Barotrauma.Items.Components
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// How useful the weapon is in combat? Used by AI to sort the used weapon. For the sake of clarity, use a value between 0 and 100 (not enforced).
|
||||
/// </summary>
|
||||
[Serialize(0f, false)]
|
||||
public float CombatPriority { get; private set; }
|
||||
|
||||
public Vector2 TransformedBarrelPos
|
||||
{
|
||||
get
|
||||
@@ -170,6 +164,7 @@ namespace Barotrauma.Items.Components
|
||||
projectile.Item.SetTransform(projectilePos, rotation);
|
||||
|
||||
projectile.Use(deltaTime);
|
||||
if (projectile.Item.Removed) { return true; }
|
||||
projectile.User = character;
|
||||
|
||||
projectile.Item.body.ApplyTorque(projectile.Item.body.Mass * degreeOfFailure * Rand.Range(-10.0f, 10.0f));
|
||||
|
||||
@@ -157,7 +157,8 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
partial void UseProjSpecific(float deltaTime);
|
||||
|
||||
private List<FireSource> fireSourcesInRange = new List<FireSource>();
|
||||
private readonly HashSet<Character> hitCharacters = new HashSet<Character>();
|
||||
private readonly List<FireSource> fireSourcesInRange = new List<FireSource>();
|
||||
private void Repair(Vector2 rayStart, Vector2 rayEnd, float deltaTime, Character user, float degreeOfSuccess, List<Body> ignoredBodies)
|
||||
{
|
||||
var collisionCategories = Physics.CollisionWall | Physics.CollisionCharacter | Physics.CollisionItem | Physics.CollisionLevel | Physics.CollisionRepair;
|
||||
@@ -165,6 +166,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
var bodies = Submarine.PickBodies(rayStart, rayEnd, ignoredBodies, collisionCategories, ignoreSensors: false, allowInsideFixture: true);
|
||||
Type lastHitType = null;
|
||||
hitCharacters.Clear();
|
||||
foreach (Body body in bodies)
|
||||
{
|
||||
Type bodyType = body.UserData?.GetType();
|
||||
@@ -173,6 +175,23 @@ namespace Barotrauma.Items.Components
|
||||
//stop the ray if it already hit a door/wall and is now about to hit some other type of entity
|
||||
if (lastHitType == typeof(Item) || lastHitType == typeof(Structure)) { break; }
|
||||
}
|
||||
|
||||
Character hitCharacter = null;
|
||||
if (body.UserData is Limb limb)
|
||||
{
|
||||
hitCharacter = limb.character;
|
||||
}
|
||||
else if (body.UserData is Character character)
|
||||
{
|
||||
hitCharacter = character;
|
||||
}
|
||||
//only do damage once to each character even if they ray hit multiple limbs
|
||||
if (hitCharacter != null)
|
||||
{
|
||||
if (hitCharacters.Contains(hitCharacter)) { continue; }
|
||||
hitCharacters.Add(hitCharacter);
|
||||
}
|
||||
|
||||
if (FixBody(user, deltaTime, degreeOfSuccess, body))
|
||||
{
|
||||
if (bodyType != null) { lastHitType = bodyType; }
|
||||
|
||||
@@ -545,7 +545,6 @@ namespace Barotrauma.Items.Components
|
||||
GameAnalyticsManager.AddErrorEventOnce("ItemComponent.DegreeOfSuccess:CharacterNull", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
return 0.0f;
|
||||
}
|
||||
float average = skillSuccessSum / requiredSkills.Count;
|
||||
|
||||
float skillSuccessSum = 0.0f;
|
||||
for (int i = 0; i < requiredSkills.Count; i++)
|
||||
@@ -693,6 +692,8 @@ namespace Barotrauma.Items.Components
|
||||
/// </summary>
|
||||
public virtual void OnItemLoaded() { }
|
||||
|
||||
public virtual void OnScaleChanged() { }
|
||||
|
||||
// TODO: Consider using generics, interfaces, or inheritance instead of reflection -> would be easier to debug when something changes/goes wrong.
|
||||
// For example, currently we can edit the constructors but they will fail in runtime because the parameters are not changed here.
|
||||
// It's also painful to find where the constructors are used, because the references exist only at runtime.
|
||||
|
||||
@@ -97,6 +97,7 @@ namespace Barotrauma.Items.Components
|
||||
RelatedItem ri = containableItems.Find(x => x.MatchesItem(containedItem));
|
||||
if (ri != null)
|
||||
{
|
||||
itemsWithStatusEffects.RemoveAll(i => i.First == containedItem);
|
||||
foreach (StatusEffect effect in ri.statusEffects)
|
||||
{
|
||||
itemsWithStatusEffects.Add(new Pair<Item, StatusEffect>(containedItem, effect));
|
||||
@@ -107,12 +108,12 @@ namespace Barotrauma.Items.Components
|
||||
IsActive = itemsWithStatusEffects.Count > 0 || containedItem.body != null;
|
||||
}
|
||||
|
||||
public void OnItemRemoved(Item item)
|
||||
public void OnItemRemoved(Item containedItem)
|
||||
{
|
||||
itemsWithStatusEffects.RemoveAll(i => i.First == item);
|
||||
itemsWithStatusEffects.RemoveAll(i => i.First == containedItem);
|
||||
|
||||
//deactivate if the inventory is empty
|
||||
IsActive = itemsWithStatusEffects.Count > 0 || item.body != null;
|
||||
IsActive = itemsWithStatusEffects.Count > 0 || containedItem.body != null;
|
||||
}
|
||||
|
||||
public bool CanBeContained(Item item)
|
||||
|
||||
@@ -37,6 +37,8 @@ namespace Barotrauma.Items.Components
|
||||
private Item focusTarget;
|
||||
private float targetRotation;
|
||||
|
||||
private bool state;
|
||||
|
||||
public Vector2 UserPos
|
||||
{
|
||||
get { return userPos; }
|
||||
@@ -48,6 +50,13 @@ namespace Barotrauma.Items.Components
|
||||
get { return user; }
|
||||
}
|
||||
|
||||
[Serialize(false, false), Editable(ToolTip = "When enabled, the item will continuously send out a 0/1 signal and interacting with it will flip the signal (making the item behave like a switch). When disabled, the item will simply send out 1 when interacted with.")]
|
||||
public bool IsToggle
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public Controller(Item item, XElement element)
|
||||
: base(item, element)
|
||||
{
|
||||
@@ -55,7 +64,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
userPos = element.GetAttributeVector2("UserPos", Vector2.Zero);
|
||||
|
||||
Enum.TryParse<Direction>(element.GetAttributeString("direction", "None"), out dir);
|
||||
Enum.TryParse(element.GetAttributeString("direction", "None"), out dir);
|
||||
|
||||
foreach (XElement el in element.Elements())
|
||||
{
|
||||
@@ -83,7 +92,12 @@ namespace Barotrauma.Items.Components
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
this.cam = cam;
|
||||
|
||||
|
||||
if (IsToggle)
|
||||
{
|
||||
item.SendSignal(0, state ? "1" : "0", "signal_out", sender: null);
|
||||
}
|
||||
|
||||
if (user == null
|
||||
|| user.Removed
|
||||
|| user.SelectedConstruction != item
|
||||
@@ -94,7 +108,7 @@ namespace Barotrauma.Items.Components
|
||||
CancelUsing(user);
|
||||
user = null;
|
||||
}
|
||||
IsActive = false;
|
||||
if (!IsToggle) { IsActive = false; }
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -169,7 +183,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
item.SendSignal(0, "1", "trigger_out", user);
|
||||
|
||||
|
||||
ApplyStatusEffects(ActionType.OnUse, 1.0f, activator);
|
||||
|
||||
return true;
|
||||
@@ -254,7 +268,14 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public override bool Pick(Character picker)
|
||||
{
|
||||
item.SendSignal(0, "1", "signal_out", picker);
|
||||
if (IsToggle)
|
||||
{
|
||||
state = !state;
|
||||
}
|
||||
else
|
||||
{
|
||||
item.SendSignal(0, "1", "signal_out", picker);
|
||||
}
|
||||
|
||||
#if CLIENT
|
||||
PlaySound(ActionType.OnUse, item.WorldPosition, picker);
|
||||
|
||||
@@ -137,10 +137,10 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public Vector2 AvoidStrength;
|
||||
|
||||
public ObstacleDebugInfo(GraphEdge edge, Vector2? intersection, float dot, Vector2 avoidStrength)
|
||||
public ObstacleDebugInfo(GraphEdge edge, Vector2? intersection, float dot, Vector2 avoidStrength, Vector2 translation)
|
||||
{
|
||||
Point1 = edge.Point1;
|
||||
Point2 = edge.Point2;
|
||||
Point1 = edge.Point1 + translation;
|
||||
Point2 = edge.Point2 + translation;
|
||||
Intersection = intersection;
|
||||
Dot = dot;
|
||||
AvoidStrength = avoidStrength;
|
||||
@@ -210,6 +210,11 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (voltage < minVoltage && currPowerConsumption > 0.0f) { return; }
|
||||
|
||||
if (user != null && user.Removed)
|
||||
{
|
||||
user = null;
|
||||
}
|
||||
|
||||
ApplyStatusEffects(ActionType.OnActive, deltaTime, null);
|
||||
|
||||
if (autoPilot)
|
||||
@@ -333,14 +338,14 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
foreach (GraphEdge edge in cell.Edges)
|
||||
{
|
||||
if (MathUtils.GetLineIntersection(edge.Point1, edge.Point2, controlledSub.WorldPosition, cell.Center, out Vector2 intersection))
|
||||
if (MathUtils.GetLineIntersection(edge.Point1 + cell.Translation, edge.Point2 + cell.Translation, controlledSub.WorldPosition, cell.Center, out Vector2 intersection))
|
||||
{
|
||||
Vector2 diff = controlledSub.WorldPosition - intersection;
|
||||
|
||||
//far enough -> ignore
|
||||
if (Math.Abs(diff.X) > avoidDist.X && Math.Abs(diff.Y) > avoidDist.Y)
|
||||
{
|
||||
debugDrawObstacles.Add(new ObstacleDebugInfo(edge, intersection, 0.0f, Vector2.Zero));
|
||||
debugDrawObstacles.Add(new ObstacleDebugInfo(edge, intersection, 0.0f, Vector2.Zero, Vector2.Zero));
|
||||
continue;
|
||||
}
|
||||
if (diff.LengthSquared() < 1.0f) diff = Vector2.UnitY;
|
||||
@@ -352,13 +357,13 @@ namespace Barotrauma.Items.Components
|
||||
//not heading towards the wall -> ignore
|
||||
if (dot < 0.5)
|
||||
{
|
||||
debugDrawObstacles.Add(new ObstacleDebugInfo(edge, intersection, dot, Vector2.Zero));
|
||||
debugDrawObstacles.Add(new ObstacleDebugInfo(edge, intersection, dot, Vector2.Zero, cell.Translation));
|
||||
continue;
|
||||
}
|
||||
|
||||
Vector2 change = (normalizedDiff * Math.Max((avoidRadius - diff.Length()), 0.0f)) / avoidRadius;
|
||||
newAvoidStrength += change * dot;
|
||||
debugDrawObstacles.Add(new ObstacleDebugInfo(edge, intersection, dot, change * dot));
|
||||
debugDrawObstacles.Add(new ObstacleDebugInfo(edge, intersection, dot, change * dot, cell.Translation));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,7 +275,14 @@ namespace Barotrauma.Items.Components
|
||||
//the raycast didn't hit anything -> the projectile flew somewhere outside the level and is permanently lost
|
||||
if (!hitSomething)
|
||||
{
|
||||
Entity.Spawner.AddToRemoveQueue(item);
|
||||
if (Entity.Spawner == null)
|
||||
{
|
||||
item.Remove();
|
||||
}
|
||||
else
|
||||
{
|
||||
Entity.Spawner.AddToRemoveQueue(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,12 +9,14 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class Repairable : ItemComponent, IServerSerializable, IClientSerializable
|
||||
{
|
||||
public static float SkillIncreaseMultiplier = 0.4f;
|
||||
public static float SkillIncreasePerRepair = 5.0f;
|
||||
|
||||
private string header;
|
||||
|
||||
private float deteriorationTimer;
|
||||
|
||||
bool wasBroken;
|
||||
|
||||
public float LastActiveTime;
|
||||
|
||||
[Serialize(0.0f, true), Editable(MinValueFloat = 0.0f, MaxValueFloat = 100.0f, DecimalCount = 2, ToolTip = "How fast the condition of the item deteriorates per second.")]
|
||||
@@ -173,16 +175,13 @@ namespace Barotrauma.Items.Components
|
||||
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return; }
|
||||
|
||||
float successFactor = requiredSkills.Count == 0 ? 1.0f : 0.0f;
|
||||
foreach (Skill skill in requiredSkills)
|
||||
|
||||
//item must have been below 50% condition for the player to get an achievement or XP for repairing it
|
||||
if (item.Condition < ShowRepairUIThreshold)
|
||||
{
|
||||
float characterSkillLevel = CurrentFixer.GetSkillLevel(skill.Identifier);
|
||||
if (characterSkillLevel >= skill.Level) successFactor += 1.0f / requiredSkills.Count;
|
||||
CurrentFixer.Info.IncreaseSkillLevel(skill.Identifier,
|
||||
SkillIncreaseMultiplier * deltaTime / Math.Max(characterSkillLevel, 1.0f),
|
||||
CurrentFixer.WorldPosition + Vector2.UnitY * 100.0f);
|
||||
wasBroken = true;
|
||||
}
|
||||
|
||||
bool wasBroken = !item.IsFullCondition;
|
||||
float fixDuration = MathHelper.Lerp(FixDurationLowSkill, FixDurationHighSkill, successFactor);
|
||||
if (fixDuration <= 0.0f)
|
||||
{
|
||||
@@ -195,8 +194,16 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (wasBroken && item.IsFullCondition)
|
||||
{
|
||||
foreach (Skill skill in requiredSkills)
|
||||
{
|
||||
float characterSkillLevel = CurrentFixer.GetSkillLevel(skill.Identifier);
|
||||
CurrentFixer.Info.IncreaseSkillLevel(skill.Identifier,
|
||||
SkillIncreasePerRepair / Math.Max(characterSkillLevel, 1.0f),
|
||||
CurrentFixer.WorldPosition + Vector2.UnitY * 100.0f);
|
||||
}
|
||||
SteamAchievementManager.OnItemRepaired(item, currentFixer);
|
||||
deteriorationTimer = Rand.Range(MinDeteriorationDelay, MaxDeteriorationDelay);
|
||||
wasBroken = false;
|
||||
#if SERVER
|
||||
item.CreateServerEvent(this);
|
||||
#endif
|
||||
|
||||
@@ -19,7 +19,8 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private string prevSignal;
|
||||
|
||||
public Character.TeamType TeamID;
|
||||
[Serialize(Character.TeamType.None, false)]
|
||||
public Character.TeamType TeamID { get; set; }
|
||||
|
||||
[Serialize(20000.0f, false)]
|
||||
public float Range
|
||||
@@ -82,8 +83,11 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public bool CanReceive(WifiComponent sender)
|
||||
{
|
||||
if (sender == null || sender.channel != channel || sender.TeamID != TeamID) return false;
|
||||
if (Vector2.DistanceSquared(item.WorldPosition, sender.item.WorldPosition) > sender.range * sender.range) return false;
|
||||
if (sender == null || sender.channel != channel) { return false; }
|
||||
if (sender.TeamID == Character.TeamType.Team1 && TeamID == Character.TeamType.Team2) { return false; }
|
||||
if (sender.TeamID == Character.TeamType.Team2 && TeamID == Character.TeamType.Team1) { return false; }
|
||||
|
||||
if (Vector2.DistanceSquared(item.WorldPosition, sender.item.WorldPosition) > sender.range * sender.range) { return false; }
|
||||
|
||||
return HasRequiredContainedItems(false);
|
||||
}
|
||||
|
||||
@@ -70,7 +70,9 @@ namespace Barotrauma
|
||||
|
||||
private Inventory parentInventory;
|
||||
private Inventory ownInventory;
|
||||
|
||||
|
||||
private Rectangle defaultRect;
|
||||
|
||||
private Dictionary<string, Connection> connections;
|
||||
|
||||
private List<Repairable> repairables;
|
||||
@@ -198,6 +200,34 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private float scale = 1.0f;
|
||||
public override float Scale
|
||||
{
|
||||
get { return scale; }
|
||||
set
|
||||
{
|
||||
if (scale == value) { return; }
|
||||
scale = MathHelper.Clamp(value, 0.1f, 10.0f);
|
||||
|
||||
float relativeScale = scale / prefab.Scale;
|
||||
|
||||
if (!ResizeHorizontal || !ResizeVertical)
|
||||
{
|
||||
int newWidth = ResizeHorizontal ? rect.Width : (int)(defaultRect.Width * relativeScale);
|
||||
int newHeight = ResizeVertical ? rect.Height : (int)(defaultRect.Height * relativeScale);
|
||||
Rect = new Rectangle(rect.X, rect.Y, newWidth, newHeight);
|
||||
}
|
||||
|
||||
if (components != null)
|
||||
{
|
||||
foreach (ItemComponent component in components)
|
||||
{
|
||||
component.OnScaleChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public float PositionUpdateInterval
|
||||
{
|
||||
get;
|
||||
@@ -499,9 +529,10 @@ namespace Barotrauma
|
||||
drawableComponents = new List<IDrawableComponent>();
|
||||
tags = new HashSet<string>();
|
||||
repairables = new List<Repairable>();
|
||||
|
||||
|
||||
defaultRect = newRect;
|
||||
rect = newRect;
|
||||
|
||||
|
||||
condition = itemPrefab.Health;
|
||||
lastSentCondition = condition;
|
||||
|
||||
@@ -626,13 +657,18 @@ namespace Barotrauma
|
||||
ic.OnItemLoaded();
|
||||
}
|
||||
}
|
||||
|
||||
DebugConsole.Log("Created " + Name + " (" + ID + ")");
|
||||
}
|
||||
|
||||
partial void InitProjSpecific();
|
||||
|
||||
public override MapEntity Clone()
|
||||
{
|
||||
Item clone = new Item(rect, Prefab, Submarine, callOnItemLoaded: false);
|
||||
Item clone = new Item(rect, Prefab, Submarine, callOnItemLoaded: false)
|
||||
{
|
||||
defaultRect = defaultRect
|
||||
};
|
||||
foreach (KeyValuePair<string, SerializableProperty> property in SerializableProperties)
|
||||
{
|
||||
if (!property.Value.Attributes.OfType<Editable>().Any()) continue;
|
||||
@@ -1552,7 +1588,7 @@ namespace Barotrauma
|
||||
|
||||
public void Use(float deltaTime, Character character = null, Limb targetLimb = null)
|
||||
{
|
||||
if (RequireAimToUse && !character.IsKeyDown(InputType.Aim))
|
||||
if (RequireAimToUse && (character == null || !character.IsKeyDown(InputType.Aim)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -2050,11 +2086,11 @@ namespace Barotrauma
|
||||
System.Diagnostics.Debug.Assert(Submarine != null || rootContainer.ParentInventory?.Owner is Character);
|
||||
|
||||
Vector2 subPosition = Submarine == null ? Vector2.Zero : Submarine.HiddenSubPosition;
|
||||
|
||||
|
||||
element.Add(new XAttribute("rect",
|
||||
(int)(rect.X - subPosition.X) + "," +
|
||||
(int)(rect.Y - subPosition.Y) + "," +
|
||||
rect.Width + "," + rect.Height));
|
||||
defaultRect.Width + "," + defaultRect.Height));
|
||||
|
||||
if (linkedTo != null && linkedTo.Count > 0)
|
||||
{
|
||||
|
||||
@@ -9,6 +9,7 @@ namespace Barotrauma
|
||||
class Entity : ISpatialEntity
|
||||
{
|
||||
public const ushort NullEntityID = 0;
|
||||
public const ushort EntitySpawnerID = ushort.MaxValue;
|
||||
|
||||
private static Dictionary<ushort, Entity> dictionary = new Dictionary<ushort, Entity>();
|
||||
public static List<Entity> GetEntityList()
|
||||
@@ -43,12 +44,19 @@ namespace Barotrauma
|
||||
}
|
||||
set
|
||||
{
|
||||
if (this is EntitySpawner) { return; }
|
||||
if (value == NullEntityID)
|
||||
{
|
||||
DebugConsole.ThrowError("Cannot set the ID of an entity to " + NullEntityID +
|
||||
"! The value is reserved for entity events referring to a non-existent (e.g. removed) entity.\n" + Environment.StackTrace);
|
||||
return;
|
||||
}
|
||||
if (value == EntitySpawnerID)
|
||||
{
|
||||
DebugConsole.ThrowError("Cannot set the ID of an entity to " + EntitySpawnerID +
|
||||
"! The value is reserved for EntitySpawner.\n" + Environment.StackTrace);
|
||||
return;
|
||||
}
|
||||
|
||||
if (dictionary.TryGetValue(id, out Entity thisEntity) && thisEntity == this)
|
||||
{
|
||||
@@ -107,15 +115,17 @@ namespace Barotrauma
|
||||
this.Submarine = submarine;
|
||||
|
||||
//give a unique ID
|
||||
id = FindFreeID(submarine == null ? (ushort)1 : submarine.IdOffset);
|
||||
|
||||
id = this is EntitySpawner ?
|
||||
EntitySpawnerID :
|
||||
FindFreeID(submarine == null ? (ushort)1 : submarine.IdOffset);
|
||||
|
||||
dictionary.Add(id, this);
|
||||
}
|
||||
|
||||
public static ushort FindFreeID(ushort idOffset = 0)
|
||||
{
|
||||
//ushort.MaxValue - 1 because 0 is a reserved value
|
||||
if (dictionary.Count >= ushort.MaxValue - 1)
|
||||
//ushort.MaxValue - 2 because 0 and ushort.MaxValue are reserved values
|
||||
if (dictionary.Count >= ushort.MaxValue - 2)
|
||||
{
|
||||
throw new Exception("Maximum amount of entities (" + (ushort.MaxValue - 1) + ") reached!");
|
||||
}
|
||||
|
||||
@@ -228,7 +228,11 @@ namespace Barotrauma
|
||||
attacker = item.GetComponent<Projectile>()?.User;
|
||||
if (attacker == null) attacker = item.GetComponent<MeleeWeapon>()?.User;
|
||||
}
|
||||
c.AddDamage(limb.WorldPosition, modifiedAfflictions, attack.Stun * distFactor, false, attacker: attacker);
|
||||
|
||||
//use a position slightly from the limb's position towards the explosion
|
||||
//ensures that the attack hits the correct limb and that the direction of the hit can be determined correctly in the AddDamage methods
|
||||
Vector2 hitPos = limb.WorldPosition + (worldPosition - limb.WorldPosition) / dist * 0.01f;
|
||||
c.AddDamage(hitPos, modifiedAfflictions, attack.Stun * distFactor, false, attacker: attacker);
|
||||
|
||||
if (attack.StatusEffects != null && attack.StatusEffects.Any())
|
||||
{
|
||||
|
||||
@@ -122,6 +122,8 @@ namespace Barotrauma
|
||||
|
||||
GapList.Add(this);
|
||||
InsertToList();
|
||||
|
||||
DebugConsole.Log("Created gap (" + ID + ")");
|
||||
}
|
||||
|
||||
public override MapEntity Clone()
|
||||
|
||||
@@ -242,6 +242,8 @@ namespace Barotrauma
|
||||
WaterVolume = 0.0f;
|
||||
|
||||
InsertToList();
|
||||
|
||||
DebugConsole.Log("Created hull (" + ID + ")");
|
||||
}
|
||||
|
||||
public static Rectangle GetBorders()
|
||||
|
||||
@@ -107,7 +107,7 @@ namespace Barotrauma
|
||||
if (Screen.Selected == GameMain.SubEditorScreen)
|
||||
{
|
||||
MapEntity.SelectedList.Clear();
|
||||
MapEntity.SelectedList.AddRange(entities);
|
||||
entities.ForEach(e => MapEntity.AddSelection(e));
|
||||
}
|
||||
#endif
|
||||
return entities;
|
||||
|
||||
@@ -1274,6 +1274,8 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
DebugConsole.Log("Generating level resources...");
|
||||
|
||||
for (int i = 0; i < generationParams.ItemCount; i++)
|
||||
{
|
||||
var selectedPrefab = ToolBox.SelectWeightedRandom(
|
||||
@@ -1286,6 +1288,7 @@ namespace Barotrauma
|
||||
var selectedEdge = selectedCell.Edges.GetRandom(e => e.IsSolid && !e.OutsideLevel, Rand.RandSync.Server);
|
||||
if (selectedEdge == null) continue;
|
||||
|
||||
|
||||
float edgePos = Rand.Range(0.0f, 1.0f, Rand.RandSync.Server);
|
||||
Vector2 selectedPos = Vector2.Lerp(selectedEdge.Point1, selectedEdge.Point2, edgePos);
|
||||
Vector2 edgeNormal = selectedEdge.GetNormal(selectedCell);
|
||||
@@ -1306,6 +1309,8 @@ namespace Barotrauma
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
DebugConsole.Log("Level resources generated");
|
||||
}
|
||||
|
||||
public Vector2 GetRandomItemPos(PositionType spawnPosType, float randomSpread, float minDistFromSubs, float offsetFromWall = 10.0f)
|
||||
|
||||
@@ -1022,12 +1022,12 @@ namespace Barotrauma.RuinGeneration
|
||||
{
|
||||
targetEntity = ruinEntities.GetRandom(e =>
|
||||
e.Room == targetRoom &&
|
||||
e.Entity.prefab?.Identifier == connection.TargetEntityIdentifier)?.Entity;
|
||||
e.Entity.prefab?.Identifier == connection.TargetEntityIdentifier, Rand.RandSync.Server)?.Entity;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
targetEntity = ruinEntities.GetRandom(e => e.Entity.prefab?.Identifier == connection.TargetEntityIdentifier)?.Entity;
|
||||
targetEntity = ruinEntities.GetRandom(e => e.Entity.prefab?.Identifier == connection.TargetEntityIdentifier, Rand.RandSync.Server)?.Entity;
|
||||
}
|
||||
|
||||
if (targetEntity == null) continue;
|
||||
|
||||
@@ -57,6 +57,8 @@ namespace Barotrauma
|
||||
linkedToID = new List<ushort>();
|
||||
|
||||
InsertToList();
|
||||
|
||||
DebugConsole.Log("Created linked submarine (" + ID + ")");
|
||||
}
|
||||
|
||||
public static LinkedSubmarine CreateDummy(Submarine mainSub, Submarine linkedSub)
|
||||
|
||||
@@ -207,20 +207,22 @@ namespace Barotrauma
|
||||
//clone links between the entities
|
||||
for (int i = 0; i < clones.Count; i++)
|
||||
{
|
||||
if (entitiesToClone[i].linkedTo == null) continue;
|
||||
if (entitiesToClone[i].linkedTo == null) { continue; }
|
||||
foreach (MapEntity linked in entitiesToClone[i].linkedTo)
|
||||
{
|
||||
if (!entitiesToClone.Contains(linked)) continue;
|
||||
|
||||
if (!entitiesToClone.Contains(linked)) { continue; }
|
||||
clones[i].linkedTo.Add(clones[entitiesToClone.IndexOf(linked)]);
|
||||
}
|
||||
}
|
||||
|
||||
//connect clone wires to the clone items
|
||||
//connect clone wires to the clone items and refresh links between doors and gaps
|
||||
for (int i = 0; i < clones.Count; i++)
|
||||
{
|
||||
var cloneItem = clones[i] as Item;
|
||||
if (cloneItem == null) continue;
|
||||
if (cloneItem == null) { continue; }
|
||||
|
||||
var door = cloneItem.GetComponent<Door>();
|
||||
if (door != null) { door.RefreshLinkedGap(); }
|
||||
|
||||
var cloneWire = cloneItem.GetComponent<Wire>();
|
||||
if (cloneWire == null) continue;
|
||||
@@ -231,7 +233,7 @@ namespace Barotrauma
|
||||
|
||||
for (int n = 0; n < 2; n++)
|
||||
{
|
||||
if (originalWire.Connections[n] == null) continue;
|
||||
if (originalWire.Connections[n] == null) { continue; }
|
||||
|
||||
var connectedItem = originalWire.Connections[n].Item;
|
||||
if (connectedItem == null) continue;
|
||||
@@ -555,7 +557,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
[Serialize(1f, false), Editable(0.1f, 10f, DecimalCount = 3, ValueStep = 0.1f)]
|
||||
[Serialize(1f, true), Editable(0.1f, 10f, DecimalCount = 3, ValueStep = 0.1f)]
|
||||
public virtual float Scale { get; set; } = 1;
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -183,6 +183,29 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected Vector2 textureScale = Vector2.One;
|
||||
|
||||
[Editable(DecimalCount = 3, MinValueFloat = 0.01f, MaxValueFloat = 10f, ValueStep = 0.1f), Serialize("1.0, 1.0", false)]
|
||||
public Vector2 TextureScale
|
||||
{
|
||||
get { return textureScale; }
|
||||
set
|
||||
{
|
||||
textureScale = new Vector2(
|
||||
MathHelper.Clamp(value.X, 0.01f, 10),
|
||||
MathHelper.Clamp(value.Y, 0.01f, 10));
|
||||
}
|
||||
}
|
||||
|
||||
protected Vector2 textureOffset = Vector2.Zero;
|
||||
[Editable(MinValueFloat = -1000f, MaxValueFloat = 1000f, ValueStep = 10f), Serialize("0.0, 0.0", true)]
|
||||
public Vector2 TextureOffset
|
||||
{
|
||||
get { return textureOffset; }
|
||||
set { textureOffset = value; }
|
||||
}
|
||||
|
||||
private Rectangle defaultRect;
|
||||
|
||||
public override Rectangle Rect
|
||||
@@ -296,9 +319,8 @@ namespace Barotrauma
|
||||
defaultRect = rectangle;
|
||||
|
||||
rect = rectangle;
|
||||
#if CLIENT
|
||||
TextureScale = sp.TextureScale;
|
||||
#endif
|
||||
|
||||
spriteColor = prefab.SpriteColor;
|
||||
if (sp.IsHorizontal.HasValue)
|
||||
{
|
||||
@@ -355,6 +377,8 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
InsertToList();
|
||||
|
||||
DebugConsole.Log("Created " + Name + " (" + ID + ")");
|
||||
}
|
||||
|
||||
partial void InitProjSpecific();
|
||||
|
||||
@@ -365,7 +365,9 @@ namespace Barotrauma
|
||||
{
|
||||
using (MemoryStream mem = new MemoryStream(Convert.FromBase64String(previewImageData)))
|
||||
{
|
||||
PreviewImage = new Sprite(TextureLoader.FromStream(mem, preMultiplyAlpha: false), null, null);
|
||||
var texture = TextureLoader.FromStream(mem, preMultiplyAlpha: false, path: filePath);
|
||||
if (texture == null) { throw new Exception("PreviewImage texture returned null"); }
|
||||
PreviewImage = new Sprite(texture, null, null);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -382,7 +384,6 @@ namespace Barotrauma
|
||||
|
||||
DockedTo = new List<Submarine>();
|
||||
|
||||
ID = ushort.MaxValue;
|
||||
FreeID();
|
||||
}
|
||||
|
||||
@@ -1405,7 +1406,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
|
||||
ID = (ushort)(ushort.MaxValue - Submarine.loaded.IndexOf(this));
|
||||
ID = (ushort)(ushort.MaxValue - 1 - Submarine.loaded.IndexOf(this));
|
||||
}
|
||||
|
||||
public static Submarine Load(XElement element, bool unloadPrevious)
|
||||
@@ -1553,7 +1554,7 @@ namespace Barotrauma
|
||||
if (MainSub == this) MainSub = null;
|
||||
if (MainSubs[1] == this) MainSubs[1] = null;
|
||||
|
||||
DockedTo.Clear();
|
||||
DockedTo?.Clear();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
||||
@@ -125,6 +125,8 @@ namespace Barotrauma
|
||||
InsertToList();
|
||||
WayPointList.Add(this);
|
||||
|
||||
DebugConsole.Log("Created waypoint (" + ID + ")");
|
||||
|
||||
currentHull = Hull.FindHull(WorldPosition);
|
||||
}
|
||||
|
||||
|
||||
@@ -48,6 +48,11 @@ namespace Barotrauma.Networking
|
||||
get { return "ServerSettings"; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Have some of the properties listed in the server list changed
|
||||
/// </summary>
|
||||
public bool ServerDetailsChanged;
|
||||
|
||||
public class SavedClientPermission
|
||||
{
|
||||
public readonly string IP;
|
||||
@@ -277,7 +282,17 @@ namespace Barotrauma.Networking
|
||||
|
||||
public string ServerName;
|
||||
|
||||
public string ServerMessageText;
|
||||
private string serverMessageText;
|
||||
public string ServerMessageText
|
||||
{
|
||||
get { return serverMessageText; }
|
||||
set
|
||||
{
|
||||
if (serverMessageText == value) { return; }
|
||||
serverMessageText = value;
|
||||
ServerDetailsChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
public int Port;
|
||||
|
||||
@@ -370,19 +385,19 @@ namespace Barotrauma.Networking
|
||||
private set;
|
||||
}
|
||||
|
||||
private bool allowSpectating;
|
||||
[Serialize(true, true)]
|
||||
public bool AllowSpectating
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
get { return allowSpectating; }
|
||||
private set
|
||||
{
|
||||
if (allowSpectating == value) { return; }
|
||||
allowSpectating = value;
|
||||
ServerDetailsChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
[Serialize(true, true)]
|
||||
public bool VoipEnabled {
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
|
||||
[Serialize(true, true)]
|
||||
public bool EndRoundAtLevelEnd
|
||||
{
|
||||
@@ -411,11 +426,17 @@ namespace Barotrauma.Networking
|
||||
private set;
|
||||
}
|
||||
|
||||
private bool voiceChatEnabled;
|
||||
[Serialize(true, true)]
|
||||
public bool VoiceChatEnabled
|
||||
{
|
||||
get;
|
||||
set;
|
||||
get { return voiceChatEnabled; }
|
||||
set
|
||||
{
|
||||
if (voiceChatEnabled == value) { return; }
|
||||
voiceChatEnabled = value;
|
||||
ServerDetailsChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
[Serialize(800, true)]
|
||||
@@ -473,11 +494,17 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
private bool allowRespawn;
|
||||
[Serialize(true, true)]
|
||||
public bool AllowRespawn
|
||||
{
|
||||
get;
|
||||
set;
|
||||
get { return allowRespawn; ; }
|
||||
set
|
||||
{
|
||||
if (allowRespawn == value) { return; }
|
||||
allowRespawn = value;
|
||||
ServerDetailsChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
[Serialize(0, true)]
|
||||
@@ -513,10 +540,16 @@ namespace Barotrauma.Networking
|
||||
set;
|
||||
}
|
||||
|
||||
private YesNoMaybe traitorsEnabled;
|
||||
public YesNoMaybe TraitorsEnabled
|
||||
{
|
||||
get;
|
||||
set;
|
||||
get { return traitorsEnabled; }
|
||||
set
|
||||
{
|
||||
if (traitorsEnabled == value) { return; }
|
||||
traitorsEnabled = value;
|
||||
ServerDetailsChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
private SelectionMode subSelectionMode;
|
||||
@@ -528,6 +561,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
subSelectionMode = value;
|
||||
Voting.AllowSubVoting = subSelectionMode == SelectionMode.Vote;
|
||||
ServerDetailsChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -540,6 +574,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
modeSelectionMode = value;
|
||||
Voting.AllowModeVoting = modeSelectionMode == SelectionMode.Vote;
|
||||
ServerDetailsChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -611,6 +646,7 @@ namespace Barotrauma.Networking
|
||||
public int MaxPlayers
|
||||
{
|
||||
get { return maxPlayers; }
|
||||
set { maxPlayers = MathHelper.Clamp(value, 1, NetConfig.MaxPlayers); }
|
||||
}
|
||||
|
||||
public List<MissionType> AllowedRandomMissionTypes
|
||||
@@ -635,7 +671,14 @@ namespace Barotrauma.Networking
|
||||
|
||||
public void SetPassword(string password)
|
||||
{
|
||||
this.password = Encoding.UTF8.GetString(NetUtility.ComputeSHAHash(Encoding.UTF8.GetBytes(password)));
|
||||
if (string.IsNullOrEmpty(password))
|
||||
{
|
||||
this.password = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
this.password = Encoding.UTF8.GetString(NetUtility.ComputeSHAHash(Encoding.UTF8.GetBytes(password)));
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsPasswordCorrect(string input, int nonce)
|
||||
|
||||
@@ -198,7 +198,7 @@ namespace Voronoi2
|
||||
{
|
||||
foreach (GraphEdge edge in Edges)
|
||||
{
|
||||
if (MathUtils.LinesIntersect(point, Center, edge.Point1, edge.Point2)) return false;
|
||||
if (MathUtils.LinesIntersect(point, Center, edge.Point1 + Translation, edge.Point2 + Translation)) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -102,6 +102,14 @@ namespace Barotrauma
|
||||
partial void LoadTexture(ref Vector4 sourceVector, ref bool shouldReturn, bool premultiplyAlpha = true);
|
||||
partial void CalculateSourceRect();
|
||||
|
||||
private static void AddToList(Sprite elem)
|
||||
{
|
||||
lock (list)
|
||||
{
|
||||
list.Add(elem);
|
||||
}
|
||||
}
|
||||
|
||||
public Sprite(XElement element, string path = "", string file = "", bool? preMultiplyAlpha = null, bool lazyLoad = false)
|
||||
{
|
||||
this.lazyLoad = lazyLoad;
|
||||
@@ -128,7 +136,7 @@ namespace Barotrauma
|
||||
RelativeOrigin = SourceElement.GetAttributeVector2("origin", new Vector2(0.5f, 0.5f));
|
||||
Depth = SourceElement.GetAttributeFloat("depth", 0.001f);
|
||||
ID = GetID(SourceElement);
|
||||
list.Add(this);
|
||||
AddToList(this);
|
||||
}
|
||||
|
||||
internal void LoadParams(SpriteParams spriteParams, bool isFlipped)
|
||||
@@ -147,13 +155,13 @@ namespace Barotrauma
|
||||
public Sprite(string newFile, Vector2 newOrigin, bool preMultiplyAlpha = true)
|
||||
{
|
||||
Init(newFile, newOrigin: newOrigin, preMultiplyAlpha: preMultiplyAlpha);
|
||||
list.Add(this);
|
||||
AddToList(this);
|
||||
}
|
||||
|
||||
public Sprite(string newFile, Rectangle? sourceRectangle, Vector2? origin = null, float rotation = 0, bool preMultiplyAlpha = true)
|
||||
{
|
||||
Init(newFile, sourceRectangle: sourceRectangle, newOrigin: origin, newRotation: rotation, preMultiplyAlpha: preMultiplyAlpha);
|
||||
list.Add(this);
|
||||
AddToList(this);
|
||||
}
|
||||
|
||||
private void Init(string newFile, Rectangle? sourceRectangle = null, Vector2? newOrigin = null, Vector2? newOffset = null, float newRotation = 0,
|
||||
@@ -198,7 +206,10 @@ namespace Barotrauma
|
||||
|
||||
public void Remove()
|
||||
{
|
||||
list.Remove(this);
|
||||
lock (list)
|
||||
{
|
||||
list.Remove(this);
|
||||
}
|
||||
|
||||
DisposeTexture();
|
||||
}
|
||||
|
||||
@@ -640,14 +640,14 @@ namespace Barotrauma
|
||||
character.LastDamageSource = entity;
|
||||
foreach (Limb limb in character.AnimController.Limbs)
|
||||
{
|
||||
limb.character.DamageLimb(entity.WorldPosition, limb, new List<Affliction>() { multipliedAffliction }, stun: 0.0f, playSound: false, attackImpulse: 0.0f);
|
||||
limb.character.DamageLimb(entity.WorldPosition, limb, new List<Affliction>() { multipliedAffliction }, stun: 0.0f, playSound: false, attackImpulse: 0.0f, attacker: affliction.Source);
|
||||
//only apply non-limb-specific afflictions to the first limb
|
||||
if (!affliction.Prefab.LimbSpecific) { break; }
|
||||
}
|
||||
}
|
||||
else if (target is Limb limb)
|
||||
{
|
||||
limb.character.DamageLimb(entity.WorldPosition, limb, new List<Affliction>() { multipliedAffliction }, stun: 0.0f, playSound: false, attackImpulse: 0.0f);
|
||||
limb.character.DamageLimb(entity.WorldPosition, limb, new List<Affliction>() { multipliedAffliction }, stun: 0.0f, playSound: false, attackImpulse: 0.0f, attacker: affliction.Source);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -311,11 +311,9 @@ namespace Barotrauma
|
||||
{
|
||||
if (gameSession.Mission is CombatMission combatMission)
|
||||
{
|
||||
#if CLIENT
|
||||
//all characters that are alive and in the winning team get an achievement
|
||||
UnlockAchievement(gameSession.Mission.Prefab.AchievementIdentifier + (int)GameMain.GameSession.WinningTeam, true,
|
||||
c => c != null && !c.IsDead && !c.IsUnconscious && combatMission.IsInWinningTeam(c));
|
||||
#endif
|
||||
}
|
||||
else if (gameSession.Mission.Completed)
|
||||
{
|
||||
|
||||
@@ -210,8 +210,8 @@ namespace Barotrauma
|
||||
/// </summary>
|
||||
public static float GetMidAngle(float from, float to)
|
||||
{
|
||||
float max = MathHelper.Max(from, to);
|
||||
float min = MathHelper.Min(from, to);
|
||||
float max = Math.Max(from, to);
|
||||
float min = Math.Min(from, to);
|
||||
float diff = max - min;
|
||||
if (from < to)
|
||||
{
|
||||
|
||||
@@ -378,8 +378,6 @@ namespace Barotrauma
|
||||
Thread.Sleep(250);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -470,7 +468,20 @@ namespace Barotrauma
|
||||
foreach (DirectoryInfo di in dir.GetDirectories())
|
||||
{
|
||||
ClearFolder(di.FullName, ignoredFileNames);
|
||||
di.Delete();
|
||||
int maxRetries = 4;
|
||||
for (int i = 0; i <= maxRetries; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
di.Delete();
|
||||
break;
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
if (i >= maxRetries) { throw; }
|
||||
Thread.Sleep(250);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user