(ded4a3e0a) v0.9.0.7

This commit is contained in:
Joonas Rikkonen
2019-06-25 16:00:44 +03:00
parent e5ae622c77
commit 4a51db77b5
1777 changed files with 421528 additions and 917 deletions
@@ -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;
}
+26 -10
View File
@@ -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;
+23 -5
View File
@@ -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;
}
}
@@ -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;
}
}
}