(98ad00fa2) v0.9.1.0

This commit is contained in:
Joonas Rikkonen
2019-07-10 13:52:12 +03:00
parent 2a791887ed
commit afa2137bd2
104 changed files with 3041 additions and 3134 deletions

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectView>ShowAllFiles</ProjectView>
</PropertyGroup>
</Project>

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">ReleaseMac</Configuration>
@@ -265,24 +265,61 @@
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="barotrauma.icns" />
<None Include="osx\libMonoPosixHelper.dylib" />
<None Include="osx\libSDL2-2.0.0.dylib" />
<None Include="osx\libcairo.2.dylib" />
<None Include="osx\libexpat.1.5.2.dylib" />
<None Include="osx\libfontconfig.1.dylib" />
<None Include="osx\libfreetype.6.dylib" />
<None Include="osx\libgdiplus.0.dylib" />
<None Include="osx\libgdiplus.dylib" />
<None Include="osx\libgif.4.1.6.dylib" />
<None Include="osx\libglib-2.0.0.dylib" />
<None Include="osx\libintl.8.dylib" />
<None Include="osx\libjpeg.8.dylib" />
<None Include="osx\libopenal.1.dylib" />
<None Include="osx\libpixman-1.0.dylib" />
<None Include="osx\libpng14.14.dylib" />
<None Include="osx\libtiff.5.dylib" />
<None Include="osx\libMonoPosixHelper.dylib">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="osx\libcairo.2.dylib">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="osx\libexpat.1.5.2.dylib">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="osx\libfontconfig.1.dylib">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="osx\libfreetype.6.dylib">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="osx\libgdiplus.0.dylib">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="osx\libgdiplus.dylib">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="osx\libgif.4.1.6.dylib">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="osx\libglib-2.0.0.dylib">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="osx\libintl.8.dylib">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="osx\libjpeg.8.dylib">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="osx\libopenal.1.dylib">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="osx\libpixman-1.0.dylib">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="osx\libpng14.14.dylib">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="osx\libtiff.5.dylib">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="libSDL2-2.0.0.dylib">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup />
<ItemGroup>
<EmbeddedResource Include="Icon.bmp">
<LogicalName>Icon.bmp</LogicalName>
</EmbeddedResource>
</ItemGroup>
<Import Project="ClientCode.projitems" Label="Shared" />
<Import Project="..\BarotraumaShared\SharedCode.projitems" Label="Shared" />
<Import Project="..\BarotraumaShared\SharedContent.projitems" Label="Shared" />

View File

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

View File

@@ -1,51 +0,0 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace Barotrauma
{
partial class HumanoidAnimParams : ISerializableEntity
{
private static GUIListBox editor;
public static GUIListBox Editor
{
get
{
if (editor == null)
{
editor = new GUIListBox(new RectTransform(new Vector2(0.3f, 1), GUI.Canvas));
//editor.AddChild(new SerializableEntityEditor(editor.RectTransform, WalkInstance, false, true, elementHeight: 20));
//editor.AddChild(new SerializableEntityEditor(editor.RectTransform, RunInstance, false, true, elementHeight: 20));
}
return editor;
}
}
#if FALSE
//TODO: fix
public void Save()
{
XDocument doc = XMLExtensions.TryLoadXml(filePath);
if (doc == null || doc.Root == null) return;
SerializableProperty.SerializeProperties(this, doc.Root, true);
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
settings.OmitXmlDeclaration = true;
settings.NewLineOnAttributes = true;
using (var writer = XmlWriter.Create(filePath, settings))
{
doc.WriteTo(writer);
writer.Flush();
}
}
#endif
}
}

View File

@@ -365,7 +365,7 @@ namespace Barotrauma
{
string chatMessage = CauseOfDeath.Type == CauseOfDeathType.Affliction ?
CauseOfDeath.Affliction.SelfCauseOfDeathDescription :
TextManager.Get("Self_CauseOfDeathDescription." + CauseOfDeath.Type.ToString());
TextManager.Get("Self_CauseOfDeathDescription." + CauseOfDeath.Type.ToString(), fallBackTag: "Self_CauseOfDeathDescription.Damage");
if (GameMain.Client != null) chatMessage += " " + TextManager.Get("DeathChatNotification");

View File

@@ -216,7 +216,7 @@ namespace Barotrauma
Color.LightGreen, Color.Black, 2, GUI.SmallFont);
textPos.Y += offset.Y;
}
if (character.FocusedCharacter.CharacterHealth.UseHealthWindow)
if (character.FocusedCharacter.CharacterHealth.UseHealthWindow && character.CanInteractWith(character.FocusedCharacter, 160f, false))
{
GUI.DrawString(spriteBatch, textPos, GetCachedHudText("HealHint", GameMain.Config.KeyBind(InputType.Health).ToString()),
Color.LightGreen, Color.Black, 2, GUI.SmallFont);

View File

@@ -449,12 +449,11 @@ namespace Barotrauma
{
float depth = ActiveSprite.Depth - 0.0000015f;
// TODO: enable when the damage overlay textures have been remade.
//DamagedSprite.Draw(spriteBatch,
// new Vector2(body.DrawPosition.X, -body.DrawPosition.Y),
// color * Math.Min(damageOverlayStrength, 1.0f), ActiveSprite.Origin,
// -body.DrawRotation,
// 1.0f, spriteEffect, depth);
DamagedSprite.Draw(spriteBatch,
new Vector2(body.DrawPosition.X, -body.DrawPosition.Y),
color * Math.Min(damageOverlayStrength, 1.0f), ActiveSprite.Origin,
-body.DrawRotation,
1.0f, spriteEffect, depth);
}
if (GameMain.DebugDraw)

View File

@@ -206,6 +206,7 @@ namespace Barotrauma
case "togglehud":
case "toggleupperhud":
case "togglecharacternames":
case "fpscounter":
return true;
default:
return client.HasConsoleCommandPermission(command);
@@ -1509,7 +1510,7 @@ namespace Barotrauma
return;
}
RagdollParams ragdollParams = character.AnimController.RagdollParams;
ragdollParams.LimbScale = value;
ragdollParams.LimbScale = MathHelper.Clamp(value, RagdollParams.MIN_SCALE, RagdollParams.MAX_SCALE);
var pos = character.WorldPosition;
character.AnimController.Recreate();
character.TeleportTo(pos);
@@ -1534,7 +1535,7 @@ namespace Barotrauma
return;
}
RagdollParams ragdollParams = character.AnimController.RagdollParams;
ragdollParams.JointScale = value;
ragdollParams.JointScale = MathHelper.Clamp(value, RagdollParams.MIN_SCALE, RagdollParams.MAX_SCALE);
var pos = character.WorldPosition;
character.AnimController.Recreate();
character.TeleportTo(pos);
@@ -1559,8 +1560,8 @@ namespace Barotrauma
return;
}
RagdollParams ragdollParams = character.AnimController.RagdollParams;
ragdollParams.LimbScale = value;
ragdollParams.JointScale = value;
ragdollParams.LimbScale = MathHelper.Clamp(value, RagdollParams.MIN_SCALE, RagdollParams.MAX_SCALE);
ragdollParams.JointScale = MathHelper.Clamp(value, RagdollParams.MIN_SCALE, RagdollParams.MAX_SCALE);
var pos = character.WorldPosition;
character.AnimController.Recreate();
character.TeleportTo(pos);

View File

@@ -1394,8 +1394,8 @@ namespace Barotrauma
Vector2 moveAmount = centerDiff == Point.Zero ? Rand.Vector(1.0f) : Vector2.Normalize(centerDiff.ToVector2());
//make sure we don't move the interfaces out of the screen
Vector2 moveAmount1 = ClampMoveAmount(rect1, area, moveAmount * 10.0f * rect1Area / (rect1Area + rect2Area));
Vector2 moveAmount2 = ClampMoveAmount(rect2, area, -moveAmount * 10.0f * rect1Area / (rect1Area + rect2Area));
Vector2 moveAmount1 = ClampMoveAmount(rect1, area, moveAmount * 20.0f * rect1Area / (rect1Area + rect2Area));
Vector2 moveAmount2 = ClampMoveAmount(rect2, area, -moveAmount * 20.0f * rect1Area / (rect1Area + rect2Area));
//move by 10 units in the desired direction and repeat until nothing overlaps
//(or after 100 iterations, in which case we'll just give up and let them overlap)

View File

@@ -148,7 +148,14 @@ namespace Barotrauma
//find the parent GUIListBox highest in the hierarchy
for (int i = parentHierarchy.Count - 1; i >= 0; i--)
{
if (parentHierarchy[i].GUIComponent is GUIListBox) return parentHierarchy[i];
if (parentHierarchy[i].GUIComponent is GUIListBox)
{
if (parentHierarchy[i].Parent != null && parentHierarchy[i].Parent.GUIComponent != null)
{
return parentHierarchy[i].Parent;
}
return parentHierarchy[i];
}
}
//or just go with the direct parent if there are no listboxes in the hierarchy
parentHierarchy.Clear();

View File

@@ -57,8 +57,8 @@ namespace Barotrauma
}
}
public GUIImage(RectTransform rectT, string style)
: this(rectT, null, null, false, style)
public GUIImage(RectTransform rectT, string style, bool scaleToFit = false)
: this(rectT, null, null, scaleToFit, style)
{
}

View File

@@ -131,13 +131,13 @@ namespace Barotrauma
private float pressedDelay = 0.5f;
private bool IsPressedTimerRunning { get { return pressedTimer > 0; } }
public GUINumberInput(RectTransform rectT, NumberType inputType, string style = "", Alignment textAlignment = Alignment.Center) : base(style, rectT)
public GUINumberInput(RectTransform rectT, NumberType inputType, string style = "", Alignment textAlignment = Alignment.Center, float? relativeButtonAreaWidth = null) : base(style, rectT)
{
LayoutGroup = new GUILayoutGroup(new RectTransform(Vector2.One, rectT), isHorizontal: true) { Stretch = true };
float relativeButtonAreaWidth = MathHelper.Clamp(Rect.Height / (float)Rect.Width, 0.1f, 0.5f);
float _relativeButtonAreaWidth = relativeButtonAreaWidth ?? MathHelper.Clamp(Rect.Height / (float)Rect.Width, 0.1f, 0.5f);
TextBox = new GUITextBox(new RectTransform(new Vector2(1.0f - relativeButtonAreaWidth, 1.0f), LayoutGroup.RectTransform), textAlignment: textAlignment, style: style)
TextBox = new GUITextBox(new RectTransform(new Vector2(1.0f - _relativeButtonAreaWidth, 1.0f), LayoutGroup.RectTransform), textAlignment: textAlignment, style: style)
{
ClampText = false,
// For some reason the caret in the number inputs is dimmer than it should.
@@ -146,7 +146,12 @@ namespace Barotrauma
CaretColor = Color.White
};
TextBox.OnTextChanged += TextChanged;
var buttonArea = new GUIFrame(new RectTransform(new Vector2(relativeButtonAreaWidth, 1.0f), LayoutGroup.RectTransform, Anchor.CenterRight) { MinSize = new Point(Rect.Height, 0) }, style: null);
var buttonArea = new GUIFrame(new RectTransform(new Vector2(_relativeButtonAreaWidth, 1.0f), LayoutGroup.RectTransform, Anchor.CenterRight), style: null);
if (!relativeButtonAreaWidth.HasValue)
{
// Not sure what's the point of this
buttonArea.RectTransform.MinSize = new Point(Rect.Height, 0);
}
PlusButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.5f), buttonArea.RectTransform), "+");
PlusButton.OnButtonDown += () =>
{

View File

@@ -246,14 +246,12 @@ namespace Barotrauma
private bool SelectBar()
{
if (!enabled) return false;
// This doesn't work
if (barSize == 1.0f) return false;
if (!enabled || !PlayerInput.LeftButtonDown()) { return false; }
if (barSize >= 1.0f) { return false; }
draggingBar = this;
return true;
}
public void MoveButton(Vector2 moveAmount)

View File

@@ -40,6 +40,9 @@ namespace Barotrauma
{
ToolBox.IsProperFilenameCase(file);
doc = XDocument.Load(file, LoadOptions.SetBaseUri);
if (doc == null) { throw new Exception("doc is null"); }
if (doc.Root == null) { throw new Exception("doc.Root is null"); }
if (doc.Root.Elements() == null) { throw new Exception("doc.Root.Elements() is null"); }
}
catch (Exception e)
{
@@ -113,26 +116,34 @@ namespace Barotrauma
private void RescaleFonts()
{
if (configElement == null) { return; }
if (configElement.Elements() == null) { return; }
foreach (XElement subElement in configElement.Elements())
{
switch (subElement.Name.ToString().ToLowerInvariant())
{
case "font":
if (Font == null) { continue; }
Font.Size = GetFontSize(subElement);
break;
case "smallfont":
if (SmallFont == null) { continue; }
SmallFont.Size = GetFontSize(subElement);
break;
case "largefont":
if (LargeFont == null) { continue; }
LargeFont.Size = GetFontSize(subElement);
break;
case "objectivetitle":
if (ObjectiveTitleFont == null) { continue; }
ObjectiveTitleFont.Size = GetFontSize(subElement);
break;
case "objectivename":
if (ObjectiveNameFont == null) { continue; }
ObjectiveNameFont.Size = GetFontSize(subElement);
break;
case "videotitle":
if (VideoTitleFont == null) { continue; }
VideoTitleFont.Size = GetFontSize(subElement);
break;
}

View File

@@ -389,7 +389,7 @@ namespace Barotrauma
public static void AutoScaleAndNormalize(IEnumerable<GUITextBlock> textBlocks)
{
if (!textBlocks.Any()) { return; }
float minScale = textBlocks.First().TextScale;
float minScale = Math.Max(textBlocks.First().TextScale, 1.0f);
foreach (GUITextBlock textBlock in textBlocks)
{
textBlock.AutoScale = true;

View File

@@ -41,7 +41,28 @@ namespace Barotrauma
OnSelected?.Invoke(this);
}
}
private Color? defaultTextColor;
public override bool Enabled
{
get
{
return enabled;
}
set
{
if (value == enabled) { return; }
enabled = value;
if (color.A == 0)
{
if (defaultTextColor == null) { defaultTextColor = TextBlock.TextColor; }
TextBlock.TextColor = enabled ? defaultTextColor.Value : defaultTextColor.Value * 0.5f;
}
}
}
public Color TextColor
{
get { return text.TextColor; }

View File

@@ -19,6 +19,7 @@ namespace Barotrauma
}
}
public GUIComponent Parent { get; private set; }
public GUIListBox EditorBox { get; private set; }
/// <summary>
/// Uses Linq queries. Don't use too frequently or reimplement.
@@ -29,13 +30,12 @@ namespace Barotrauma
public GUIListBox CreateEditorBox(RectTransform rectT = null)
{
rectT = rectT ?? new RectTransform(new Vector2(0.25f, 0.95f), GUI.Canvas) { MinSize = new Point(340, GameMain.GraphicsHeight) };
rectT = rectT ?? new RectTransform(new Vector2(0.25f, 1f), GUI.Canvas) { MinSize = new Point(340, GameMain.GraphicsHeight) };
rectT.SetPosition(Anchor.TopRight);
rectT.RelativeOffset = new Vector2(0.16f, 0);
EditorBox = new GUIListBox(rectT)
Parent = new GUIFrame(rectT, null, new Color(20, 20, 20, 255));
EditorBox = new GUIListBox(new RectTransform(Vector2.One * 0.98f, rectT, Anchor.Center), color: Color.Black, style: null)
{
Spacing = 10,
Color = Color.Black
Spacing = 10
};
return EditorBox;
}

View File

@@ -1,274 +0,0 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Xml.Linq;
using System.Collections.Generic;
namespace Barotrauma
{
class SpriteSheetPlayer
{
private SpriteSheet[] playingSheets;
private SpriteSheet currentSheet;
private List<PreloadedContent> preloadedSheets;
private GUIFrame background, videoFrame;
private GUITextBlock title;
private GUICustomComponent sheetView;
private float totalElapsed = 0;
private float animationSpeed = 0.1f;
private float loopTimer = 0.0f;
private float loopDelay = 0.0f;
private int currentSheetIndex = 0;
private int currentFrameIndex = 0;
private Color backgroundColor = new Color(0f, 0f, 0f, 1f);
private Action callbackOnStop;
private bool isPlaying;
public bool IsPlaying
{
get { return isPlaying; }
private set
{
if (isPlaying == value) return;
isPlaying = value;
}
}
private readonly Vector2 defaultResolution = new Vector2(520, 300);
private readonly int borderSize = 20;
private class PreloadedContent
{
public string ContentName;
public string ContentTag;
public SpriteSheet[] Sheets;
public PreloadedContent(string name, string tag, SpriteSheet[] sheets)
{
ContentName = name;
ContentTag = tag;
Sheets = sheets;
}
}
public SpriteSheetPlayer()
{
int width = (int)defaultResolution.X;
int height = (int)defaultResolution.Y;
background = new GUIFrame(new RectTransform(new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight), GUI.Canvas, Anchor.Center), "InnerFrame", backgroundColor);
videoFrame = new GUIFrame(new RectTransform(new Point(width + borderSize, height + borderSize), background.RectTransform, Anchor.Center), "SonarFrame");
sheetView = new GUICustomComponent(new RectTransform(new Point(width, height), videoFrame.RectTransform, Anchor.Center),
(spriteBatch, guiCustomComponent) => { DrawSheetView(spriteBatch, guiCustomComponent.Rect); }, UpdateSheetView);
title = new GUITextBlock(new RectTransform(new Vector2(1f, 0f), videoFrame.RectTransform, Anchor.TopCenter, Pivot.BottomCenter), string.Empty, font: GUI.LargeFont, textAlignment: Alignment.Center);
preloadedSheets = new List<PreloadedContent>();
}
public void PreloadContent(string contentPath, string contentTag, string contentId, XElement contentElement)
{
if (preloadedSheets.Find(s => s.ContentName == contentId) != null) return; // Already loaded
preloadedSheets.Add(new PreloadedContent(contentId, contentTag, CreateSpriteSheets(contentPath, contentElement)));
}
public void RemoveAllPreloaded()
{
if (preloadedSheets == null || preloadedSheets.Count == 0) return;
for (int i = 0; i < preloadedSheets.Count; i++)
{
for (int j = 0; j < preloadedSheets[i].Sheets.Length; j++)
{
preloadedSheets[i].Sheets[j].Remove();
}
}
preloadedSheets.Clear();
}
public void RemovePreloadedByTag(string tag)
{
if (preloadedSheets == null || preloadedSheets.Count == 0) return;
for (int i = 0; i < preloadedSheets.Count; i++)
{
if (preloadedSheets[i].ContentTag != tag) continue;
for (int j = 0; j < preloadedSheets[i].Sheets.Length; j++)
{
preloadedSheets[i].Sheets[j].Remove();
}
preloadedSheets[i] = null;
preloadedSheets.RemoveAt(i);
i--;
}
}
public void Play()
{
isPlaying = true;
}
public void Stop()
{
isPlaying = false;
}
private bool OKButtonClicked(GUIButton button, object userData)
{
Stop();
callbackOnStop?.Invoke();
return true;
}
public void AddToGUIUpdateList()
{
if (!isPlaying) return;
background.AddToGUIUpdateList();
}
public void LoadContent(string contentPath, XElement videoElement, string contentId, bool startPlayback, bool hasButton, Action callback = null)
{
totalElapsed = loopTimer = 0.0f;
animationSpeed = videoElement.GetAttributeFloat("animationspeed", 0.1f);
loopDelay = videoElement.GetAttributeFloat("loopdelay", 0.0f);
if (playingSheets != null)
{
foreach (SpriteSheet existingSheet in playingSheets)
{
existingSheet.Remove();
}
playingSheets = null;
}
playingSheets = preloadedSheets.Find(s => s.ContentName == contentId).Sheets;
if (playingSheets == null) // No preloaded sheets found, create sheets
{
playingSheets = CreateSpriteSheets(contentPath, videoElement);
}
currentSheet = playingSheets[0];
Point resolution = currentSheet.FrameSize;
videoFrame.RectTransform.NonScaledSize = resolution + new Point(borderSize, borderSize);
sheetView.RectTransform.NonScaledSize = resolution;
title.Text = TextManager.Get(contentId);
title.RectTransform.NonScaledSize = new Point(resolution.X, 30);
callbackOnStop = callback;
if (hasButton)
{
var okButton = new GUIButton(new RectTransform(new Point(160, 50), videoFrame.RectTransform, Anchor.BottomCenter, Pivot.TopCenter) { AbsoluteOffset = new Point(0, -10) },
TextManager.Get("OK"))
{
OnClicked = OKButtonClicked
};
}
if (startPlayback) Play();
}
private SpriteSheet[] CreateSpriteSheets(string contentPath, XElement videoElement)
{
SpriteSheet[] sheets = null;
try
{
List<XElement> sheetElements = new List<XElement>();
foreach (var sheetElement in videoElement.Elements("Sheet"))
{
sheetElements.Add(sheetElement);
}
sheets = new SpriteSheet[sheetElements.Count];
for (int i = 0; i < sheetElements.Count; i++)
{
sheets[i] = new SpriteSheet(sheetElements[i], contentPath, sheetElements[i].GetAttributeString("path", ""), sheetElements[i].GetAttributeInt("empty", 0));
}
}
catch (Exception e)
{
DebugConsole.ThrowError("Error loading sprite sheet content " + contentPath + "!", e);
}
return sheets;
}
private void UpdateSheetView(float deltaTime, GUICustomComponent viewContainer)
{
if (!isPlaying) return;
if (loopTimer > 0.0f)
{
loopTimer -= deltaTime;
if (loopTimer <= 0.0f)
{
currentSheetIndex = 0;
currentFrameIndex = 0;
currentSheet = playingSheets[currentSheetIndex];
}
else
{
return;
}
}
totalElapsed += deltaTime;
if (totalElapsed > animationSpeed)
{
totalElapsed -= animationSpeed;
currentFrameIndex++;
if (currentFrameIndex > currentSheet.FrameCount - 1)
{
currentSheetIndex++;
if (currentSheetIndex > playingSheets.Length - 1)
{
if (loopDelay > 0.0f)
{
loopTimer = loopDelay;
return;
}
currentSheetIndex = 0;
}
currentFrameIndex = 0;
currentSheet = playingSheets[currentSheetIndex];
}
}
}
private void DrawSheetView(SpriteBatch spriteBatch, Rectangle rect)
{
if (!isPlaying) return;
currentSheet.Draw(spriteBatch, currentFrameIndex, rect.Center.ToVector2(), Color.White, currentSheet.Origin, 0f, Vector2.One);
}
public void Remove()
{
if (playingSheets != null)
{
foreach (SpriteSheet existingSheet in playingSheets)
{
existingSheet.Remove();
}
playingSheets = null;
}
RemoveAllPreloaded();
}
}
}

View File

@@ -30,6 +30,8 @@ namespace Barotrauma
public static readonly Version Version = Assembly.GetEntryAssembly().GetName().Version;
public static string[] ConsoleArguments;
public static GameScreen GameScreen;
public static MainMenuScreen MainMenuScreen;
public static LobbyScreen LobbyScreen;
@@ -116,7 +118,7 @@ namespace Barotrauma
get;
private set;
}
public static WindowMode WindowMode
{
get;
@@ -159,7 +161,7 @@ namespace Barotrauma
get { return loadingScreenOpen; }
}
public GameMain()
public GameMain(string[] args)
{
Content.RootDirectory = "Content";
@@ -171,6 +173,8 @@ namespace Barotrauma
Config = new GameSettings();
ConsoleArguments = args;
GUI.KeyboardDispatcher = new EventInput.KeyboardDispatcher(Window);
PerformanceCounter = new PerformanceCounter();
@@ -294,7 +298,7 @@ namespace Barotrauma
loadingCoroutine = CoroutineManager.StartCoroutine(Load(canLoadInSeparateThread), "Load", canLoadInSeparateThread);
}
private void InitUserStats()
{
if (GameSettings.ShowUserStatisticsPrompt)
@@ -356,6 +360,11 @@ namespace Barotrauma
SoundManager.SetCategoryGainMultiplier("waterambience", Config.SoundVolume);
SoundManager.SetCategoryGainMultiplier("music", Config.MusicVolume);
SoundManager.SetCategoryGainMultiplier("voip", Config.VoiceChatVolume * 20.0f);
if (ConsoleArguments.Contains("skipintro")) {
Config.EnableSplashScreen = false;
}
if (Config.EnableSplashScreen)
{
var pendingSplashScreens = TitleScreen.PendingSplashScreens;
@@ -403,7 +412,7 @@ namespace Barotrauma
InitUserStats();
yield return CoroutineStatus.Running;
LightManager = new Lights.LightManager(base.GraphicsDevice, Content);
TitleScreen.LoadState = 1.0f;
@@ -664,7 +673,7 @@ namespace Barotrauma
GUI.KeyboardDispatcher.Subscriber = null;
}
//if a verification prompt (are you sure you want to x) is open, close it
else if (GUIMessageBox.VisibleBox as GUIMessageBox != null &&
else if (GUIMessageBox.VisibleBox as GUIMessageBox != null &&
GUIMessageBox.VisibleBox.UserData as string == "verificationprompt")
{
((GUIMessageBox)GUIMessageBox.VisibleBox).Close();
@@ -826,8 +835,8 @@ namespace Barotrauma
}
};
}
msgBox.InnerFrame.RectTransform.MinSize = new Point(0,
msgBox.InnerFrame.RectTransform.MinSize = new Point(0,
msgBox.InnerFrame.Rect.Height + linkHolder.Rect.Height + msgBox.Content.AbsoluteSpacing * 2 + 10);
Config.EditorDisclaimerShown = true;
Config.SaveNewPlayerConfig();
@@ -878,6 +887,7 @@ namespace Barotrauma
if (NetworkMember != null) NetworkMember.Disconnect();
SteamManager.ShutDown();
if (GameSettings.SendUserStatistics) GameAnalytics.OnQuit();
if (GameSettings.SaveDebugConsoleLogs) DebugConsole.SaveLogs();
base.OnExiting(sender, args);
}
}

View File

@@ -941,7 +941,7 @@ namespace Barotrauma
else
{
orderTargetFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.2f + order.Options.Length * 0.1f, 0.18f), GUI.Canvas)
{ AbsoluteOffset = new Point(orderButton.Rect.Center.X, orderButton.Rect.Bottom) },
{ AbsoluteOffset = new Point((int)(200 * GUI.Scale), orderButton.Rect.Bottom) },
isHorizontal: true, childAnchor: Anchor.BottomLeft)
{
UserData = character,
@@ -970,6 +970,12 @@ namespace Barotrauma
return true;
}
};
new GUIFrame(new RectTransform(Vector2.One * 1.5f, optionButton.RectTransform, Anchor.Center), style: "OuterGlow")
{
Color = Color.Black,
HoverColor = Color.CadetBlue,
PressedColor = Color.Black
}.RectTransform.SetAsFirstChild();
OrderOptionButtons.Add(optionButton);
@@ -1238,7 +1244,10 @@ namespace Barotrauma
}
hoverArea.Inflate(100, 100);
if (!hoverArea.Contains(PlayerInput.MousePosition)) orderTargetFrame = null;
if (!hoverArea.Contains(PlayerInput.MousePosition) || PlayerInput.RightButtonClicked())
{
orderTargetFrame = null;
}
}
}

View File

@@ -256,6 +256,18 @@ namespace Barotrauma
{
if (c.Info == null || c.Inventory == null) { continue; }
var inventoryElement = new XElement("inventory");
// Recharge headset batteries
var headset = c.Inventory.FindItemByIdentifier("headset");
if (headset != null)
{
var battery = headset.OwnInventory.FindItemByTag("loadable");
if (battery != null)
{
battery.Condition = battery.MaxCondition;
}
}
c.SaveInventory(c.Inventory, inventoryElement);
c.Info.InventoryData = inventoryElement;
c.Inventory?.DeleteAllItems();
@@ -407,7 +419,8 @@ namespace Barotrauma
public override void Save(XElement element)
{
XElement modeElement = new XElement("SinglePlayerCampaign",
new XAttribute("money", Money),
// Refunds the money when save & quitting from the map if there are items selected in the store
new XAttribute("money", Money + (CargoManager != null ? CargoManager.GetTotalItemCost() : 0)),
new XAttribute("cheatsenabled", CheatsEnabled));
CrewManager.Save(modeElement);
Map.Save(modeElement);

View File

@@ -42,8 +42,14 @@ namespace Barotrauma
RelativeSpacing = 0.03f
};
GUIListBox infoTextBox = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.7f), paddedFrame.RectTransform));
GUIListBox infoTextBox = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.7f), paddedFrame.RectTransform))
{
Spacing = (int)(5 * GUI.Scale)
};
//spacing
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.05f), infoTextBox.Content.RectTransform), style: null);
string summaryText = TextManager.GetWithVariables(gameOver ? "RoundSummaryGameOver" :
(progress ? "RoundSummaryProgress" : "RoundSummaryReturn"), new string[2] { "[sub]", "[location]" },
new string[2] { Submarine.MainSub.Name, progress ? GameMain.GameSession.EndLocation.Name : GameMain.GameSession.StartLocation.Name });

View File

@@ -19,6 +19,8 @@ namespace Barotrauma.Items.Components
private GUIComponent inSufficientPowerWarning;
private bool pendingState;
partial void InitProjSpecific(XElement element)
{
var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.9f), GuiFrame.RectTransform, Anchor.Center), childAnchor: Anchor.TopCenter)
@@ -73,32 +75,34 @@ namespace Barotrauma.Items.Components
public override void UpdateHUD(Character character, float deltaTime, Camera cam)
{
inSufficientPowerWarning.Visible = powerConsumption > 0 && voltage < minVoltage;
//activateButton.Enabled = !inSufficientPowerWarning.Visible;
inSufficientPowerWarning.Visible = CurrPowerConsumption > 0 && !hasPower;
}
private bool ToggleActive(GUIButton button, object obj)
{
SetActive(!IsActive, Character.Controlled);
currPowerConsumption = IsActive ? powerConsumption : 0.0f;
if (GameMain.Client != null)
{
pendingState = !IsActive;
item.CreateClientEvent(this);
}
else
{
SetActive(!IsActive, Character.Controlled);
currPowerConsumption = IsActive ? powerConsumption : 0.0f;
}
return true;
}
public void ClientWrite(NetBuffer msg, object[] extraData = null)
{
msg.Write(IsActive);
msg.Write(pendingState);
}
public void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime)
{
SetActive(msg.ReadBoolean());
progressTimer = msg.ReadSingle();
}
}
}

View File

@@ -34,6 +34,8 @@ namespace Barotrauma.Items.Components
private GUIComponent inSufficientPowerWarning;
private FabricationRecipe pendingFabricatedItem;
private Pair<Rectangle, string> tooltip;
partial void InitProjSpecific()
@@ -403,7 +405,7 @@ namespace Barotrauma.Items.Components
}
}
}
private bool StartButtonClicked(GUIButton button, object obj)
{
if (selectedItem == null) { return false; }
@@ -412,19 +414,22 @@ namespace Barotrauma.Items.Components
outputInventoryHolder.Flash(Color.Red);
return false;
}
if (fabricatedItem == null)
if (GameMain.Client != null)
{
StartFabricating(selectedItem, Character.Controlled);
pendingFabricatedItem = fabricatedItem != null ? null : selectedItem;
item.CreateClientEvent(this);
}
else
{
CancelFabricating(Character.Controlled);
}
if (GameMain.Client != null)
{
item.CreateClientEvent(this);
if (fabricatedItem == null)
{
StartFabricating(selectedItem, Character.Controlled);
}
else
{
CancelFabricating(Character.Controlled);
}
}
return true;
@@ -433,7 +438,7 @@ namespace Barotrauma.Items.Components
public override void UpdateHUD(Character character, float deltaTime, Camera cam)
{
activateButton.Enabled = false;
inSufficientPowerWarning.Visible = powerConsumption > 0 && voltage < minVoltage;
inSufficientPowerWarning.Visible = currPowerConsumption > 0 && !hasPower;
var availableIngredients = GetAvailableIngredients();
if (character != null)
@@ -457,7 +462,7 @@ namespace Barotrauma.Items.Components
public void ClientWrite(NetBuffer msg, object[] extraData = null)
{
int itemIndex = fabricatedItem == null ? -1 : fabricationRecipes.IndexOf(fabricatedItem);
int itemIndex = pendingFabricatedItem == null ? -1 : fabricationRecipes.IndexOf(pendingFabricatedItem);
msg.WriteRangedInteger(-1, fabricationRecipes.Count - 1, itemIndex);
}
@@ -474,8 +479,8 @@ namespace Barotrauma.Items.Components
else
{
//if already fabricating the selected item, return
if (fabricatedItem != null && fabricationRecipes.IndexOf(fabricatedItem) == itemIndex) return;
if (itemIndex < 0 || itemIndex >= fabricationRecipes.Count) return;
if (fabricatedItem != null && fabricationRecipes.IndexOf(fabricatedItem) == itemIndex) { return; }
if (itemIndex < 0 || itemIndex >= fabricationRecipes.Count) { return; }
SelectItem(user, fabricationRecipes[itemIndex]);
StartFabricating(fabricationRecipes[itemIndex], user);

View File

@@ -17,10 +17,14 @@ namespace Barotrauma.Items.Components
private GUITextBlock hullNameText, hullBreachText, hullAirQualityText, hullWaterText;
private string noPowerTip = "";
private List<Submarine> displayedSubs = new List<Submarine>();
partial void InitProjSpecific(XElement element)
{
noPowerTip = TextManager.Get("SteeringNoPowerTip");
GuiFrame.RectTransform.RelativeOffset = new Vector2(0.4f, 0.0f);
new GUICustomComponent(new RectTransform(new Vector2(0.9f, 0.85f), GuiFrame.RectTransform, Anchor.Center),
DrawHUDBack, null);
@@ -105,6 +109,16 @@ namespace Barotrauma.Items.Components
private void DrawHUDFront(SpriteBatch spriteBatch, GUICustomComponent container)
{
if (voltage < minVoltage)
{
Vector2 textSize = GUI.Font.MeasureString(noPowerTip);
Vector2 textPos = GuiFrame.Rect.Center.ToVector2();
GUI.DrawString(spriteBatch, textPos - textSize / 2, noPowerTip,
Color.Orange * (float)Math.Abs(Math.Sin(Timing.TotalTime)), Color.Black * 0.8f);
return;
}
foreach (GUIComponent child in submarineContainer.Children.First().Children)
{
if (child.UserData is Hull hull)
@@ -145,6 +159,11 @@ namespace Barotrauma.Items.Components
}
}
if (voltage < minVoltage)
{
return;
}
float scale = 1.0f;
HashSet<Submarine> subs = new HashSet<Submarine>();
foreach (Hull hull in Hull.hullList)

View File

@@ -34,7 +34,8 @@ namespace Barotrauma.Items.Components
private GUITickBox directionalTickBox;
private GUIScrollBar directionalSlider;
private GUIComponent activeControlsContainer;
private GUILayoutGroup activeControlsContainer;
private GUIFrame controlContainer;
private GUICustomComponent sonarView;
@@ -76,12 +77,11 @@ namespace Barotrauma.Items.Components
{
sonarBlips = new List<SonarBlip>();
int viewSize = (int)Math.Min(GuiFrame.Rect.Width - 150, GuiFrame.Rect.Height * 0.9f);
sonarView = new GUICustomComponent(new RectTransform(new Point(viewSize), GuiFrame.RectTransform, Anchor.CenterLeft),
sonarView = new GUICustomComponent(new RectTransform(Point.Zero, GuiFrame.RectTransform, Anchor.CenterLeft),
(spriteBatch, guiCustomComponent) => { DrawSonar(spriteBatch, guiCustomComponent.Rect); }, null);
var controlContainer = new GUIFrame(new RectTransform(new Vector2(0.3f, 0.35f), GuiFrame.RectTransform, Anchor.TopLeft)
{ MinSize = new Point(150, 0), AbsoluteOffset = new Point((int)(viewSize * 0.9f), 0) }, "SonarFrame");
controlContainer = new GUIFrame(new RectTransform(new Vector2(0.3f, 0.35f), GuiFrame.RectTransform, Anchor.TopLeft)
{ MinSize = new Point(150, 0) }, "SonarFrame");
controlContainer.RectTransform.SetAsFirstChild();
@@ -200,6 +200,18 @@ namespace Barotrauma.Items.Components
break;
}
}
SetUILayout();
GameMain.Instance.OnResolutionChanged += SetUILayout;
GameMain.Config.OnHUDScaleChanged += SetUILayout;
}
private void SetUILayout()
{
int viewSize = (int)Math.Min(GuiFrame.Rect.Width - 150, GuiFrame.Rect.Height * 0.9f);
sonarView.RectTransform.NonScaledSize = new Point(viewSize);
controlContainer.RectTransform.AbsoluteOffset = new Point((int)(viewSize * 0.9f), 0);
}
public override void OnItemLoaded()
@@ -612,6 +624,16 @@ namespace Barotrauma.Items.Components
{
if (Level.Loaded != null && dockingPort.Item.Submarine.WorldPosition.Y > Level.Loaded.Size.Y) { continue; }
//don't show the docking ports of the opposing team on the sonar
if (item.Submarine != null && dockingPort.Item.Submarine != null)
{
if ((dockingPort.Item.Submarine.TeamID == Character.TeamType.Team1 && item.Submarine.TeamID == Character.TeamType.Team2) ||
(dockingPort.Item.Submarine.TeamID == Character.TeamType.Team2 && item.Submarine.TeamID == Character.TeamType.Team1))
{
continue;
}
}
Vector2 offset = (dockingPort.Item.WorldPosition - transducerCenter) * scale;
offset.Y = -offset.Y;
if (offset.LengthSquared() > DisplayRadius * DisplayRadius) { continue; }

View File

@@ -27,7 +27,7 @@ namespace Barotrauma.Items.Components
};
private GUITickBox maintainPosTickBox, levelEndTickBox, levelStartTickBox;
private GUIComponent statusContainer, dockingContainer;
private GUIComponent statusContainer, dockingContainer, controlContainer;
private bool dockingNetworkMessagePending;
@@ -86,9 +86,8 @@ namespace Barotrauma.Items.Components
partial void InitProjSpecific(XElement element)
{
int viewSize = (int)Math.Min(GuiFrame.Rect.Width - 150, GuiFrame.Rect.Height * 0.9f);
var controlContainer = new GUIFrame(new RectTransform(new Vector2(0.3f, 0.35f), GuiFrame.RectTransform, Anchor.CenterLeft)
{ MinSize = new Point(150, 0), AbsoluteOffset = new Point((int)(viewSize * 0.99f), (int)(viewSize * 0.05f)) }, "SonarFrame");
controlContainer = new GUIFrame(new RectTransform(new Vector2(0.3f, 0.35f), GuiFrame.RectTransform, Anchor.CenterLeft)
{ MinSize = new Point(150, 0) }, "SonarFrame");
var paddedControlContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.8f), controlContainer.RectTransform, Anchor.Center))
{
RelativeSpacing = 0.03f,
@@ -96,7 +95,7 @@ namespace Barotrauma.Items.Components
};
statusContainer = new GUIFrame(new RectTransform(new Vector2(0.3f, 0.25f), GuiFrame.RectTransform, Anchor.BottomLeft)
{ MinSize = new Point(150, 0), AbsoluteOffset = new Point((int)(viewSize * 0.9f), 0) }, "SonarFrame");
{ MinSize = new Point(150, 0) }, "SonarFrame");
var paddedStatusContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.9f), statusContainer.RectTransform, Anchor.Center))
{
RelativeSpacing = 0.03f,
@@ -295,12 +294,12 @@ namespace Barotrauma.Items.Components
autoPilotLevelEndTip = TextManager.GetWithVariable("SteeringAutoPilotLocationTip", "[locationname]",
GameMain.GameSession?.EndLocation == null ? "End" : GameMain.GameSession.EndLocation.Name);
steerArea = new GUICustomComponent(new RectTransform(new Point(viewSize), GuiFrame.RectTransform, Anchor.CenterLeft),
steerArea = new GUICustomComponent(new RectTransform(Point.Zero, GuiFrame.RectTransform, Anchor.CenterLeft),
(spriteBatch, guiCustomComponent) => { DrawHUD(spriteBatch, guiCustomComponent.Rect); }, null);
//docking interface ----------------------------------------------------
dockingContainer = new GUIFrame(new RectTransform(new Vector2(0.3f, 0.25f), GuiFrame.RectTransform, Anchor.BottomLeft)
{ MinSize = new Point(150, 0), AbsoluteOffset = new Point((int)(viewSize * 0.9f), 0) }, style: null);
{ MinSize = new Point(150, 0) }, style: null);
var paddedDockingContainer = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.9f), dockingContainer.RectTransform, Anchor.Center), style: null);
//TODO: add new texts for these ("Dock" & "Undock")
@@ -364,6 +363,21 @@ namespace Barotrauma.Items.Components
break;
}
}
SetUILayout();
GameMain.Instance.OnResolutionChanged += SetUILayout;
GameMain.Config.OnHUDScaleChanged += SetUILayout;
}
private void SetUILayout()
{
int viewSize = (int)Math.Min(GuiFrame.Rect.Width - 150, GuiFrame.Rect.Height * 0.9f);
controlContainer.RectTransform.AbsoluteOffset = new Point((int)(viewSize * 0.99f), (int)(viewSize * 0.05f));
statusContainer.RectTransform.AbsoluteOffset = new Point((int)(viewSize * 0.9f), 0);
steerArea.RectTransform.NonScaledSize = new Point(viewSize);
dockingContainer.RectTransform.AbsoluteOffset = new Point((int)(viewSize * 0.9f), 0);
}
private void FindConnectedDockingPort()

View File

@@ -41,8 +41,9 @@ namespace Barotrauma.Items.Components
}
Wire equippedWire = null;
if (!panel.Locked || Screen.Selected == GameMain.SubEditorScreen)
bool allowRewiring = GameMain.NetworkMember?.ServerSettings == null || GameMain.NetworkMember.ServerSettings.AllowRewiring;
if (allowRewiring && (!panel.Locked || Screen.Selected == GameMain.SubEditorScreen))
{
//if the Character using the panel has a wire item equipped
//and the wire hasn't been connected yet, draw it on the panel
@@ -278,7 +279,8 @@ namespace Barotrauma.Items.Components
{
ConnectionPanel.HighlightedWire = wire;
if (!wire.Locked && (!panel.Locked || Screen.Selected == GameMain.SubEditorScreen))
bool allowRewiring = GameMain.NetworkMember?.ServerSettings == null || GameMain.NetworkMember.ServerSettings.AllowRewiring;
if (allowRewiring && !wire.Locked && (!panel.Locked || Screen.Selected == GameMain.SubEditorScreen))
{
//start dragging the wire
if (PlayerInput.LeftButtonHeld()) draggingConnected = wire;

View File

@@ -181,7 +181,7 @@ namespace Barotrauma
public override void Draw(SpriteBatch spriteBatch, bool editing, bool back = true)
{
if (!Visible || (!editing && hiddenInGame)) return;
if (!Visible || (!editing && HiddenInGame)) return;
if (editing && !ShowItems) return;
Color color = IsHighlighted && !GUI.DisableItemHighlights && Screen.Selected != GameMain.GameScreen ? Color.Orange : GetSpriteColor();
@@ -451,7 +451,7 @@ namespace Barotrauma
public override void UpdateEditing(Camera cam)
{
if (editingHUD == null || editingHUD.UserData == null)
if (editingHUD == null || editingHUD.UserData as Item != this)
{
editingHUD = CreateEditingHUD(Screen.Selected != GameMain.SubEditorScreen);
}

View File

@@ -132,96 +132,97 @@ namespace Barotrauma
selectedList.Clear();
return;
}
if (PlayerInput.KeyDown(Keys.Delete))
if (GUI.KeyboardDispatcher.Subscriber == null)
{
selectedList.ForEach(e => e.Remove());
selectedList.Clear();
}
if (PlayerInput.KeyDown(Keys.LeftControl) || PlayerInput.KeyDown(Keys.RightControl))
{
if (PlayerInput.KeyHit(Keys.C))
if (PlayerInput.KeyDown(Keys.Delete))
{
CopyEntities(selectedList);
}
else if (PlayerInput.KeyHit(Keys.X))
{
CopyEntities(selectedList);
selectedList.ForEach(e => e.Remove());
selectedList.Clear();
}
else if (copiedList.Count > 0 && PlayerInput.KeyHit(Keys.V))
if (PlayerInput.KeyDown(Keys.LeftControl) || PlayerInput.KeyDown(Keys.RightControl))
{
List<MapEntity> prevEntities = new List<MapEntity>(mapEntityList);
Clone(copiedList);
var clones = mapEntityList.Except(prevEntities).ToList();
Vector2 center = Vector2.Zero;
clones.ForEach(c => center += c.WorldPosition);
center = Submarine.VectorToWorldGrid(center / clones.Count);
Vector2 moveAmount = Submarine.VectorToWorldGrid(cam.WorldViewCenter - center);
selectedList = new List<MapEntity>(clones);
foreach (MapEntity clone in selectedList)
if (PlayerInput.KeyHit(Keys.C))
{
clone.Move(moveAmount);
clone.Submarine = Submarine.MainSub;
CopyEntities(selectedList);
}
}
else if (PlayerInput.KeyHit(Keys.G))
{
if (selectedList.Any())
else if (PlayerInput.KeyHit(Keys.X))
{
if (SelectionGroups.ContainsKey(selectedList.Last()))
CopyEntities(selectedList);
selectedList.ForEach(e => e.Remove());
selectedList.Clear();
}
else if (copiedList.Count > 0 && PlayerInput.KeyHit(Keys.V))
{
List<MapEntity> prevEntities = new List<MapEntity>(mapEntityList);
Clone(copiedList);
var clones = mapEntityList.Except(prevEntities).ToList();
Vector2 center = Vector2.Zero;
clones.ForEach(c => center += c.WorldPosition);
center = Submarine.VectorToWorldGrid(center / clones.Count);
Vector2 moveAmount = Submarine.VectorToWorldGrid(cam.WorldViewCenter - center);
selectedList = new List<MapEntity>(clones);
foreach (MapEntity clone in selectedList)
{
// Ungroup all selected
selectedList.ForEach(e => SelectionGroups.Remove(e));
clone.Move(moveAmount);
clone.Submarine = Submarine.MainSub;
}
else
}
else if (PlayerInput.KeyHit(Keys.G))
{
if (selectedList.Any())
{
foreach (var entity in selectedList)
if (SelectionGroups.ContainsKey(selectedList.Last()))
{
// Remove the old group, if any
SelectionGroups.Remove(entity);
// Create a group that can be accessed with any member
SelectionGroups.Add(entity, selectedList);
// Ungroup all selected
selectedList.ForEach(e => SelectionGroups.Remove(e));
}
else
{
foreach (var entity in selectedList)
{
// Remove the old group, if any
SelectionGroups.Remove(entity);
// Create a group that can be accessed with any member
SelectionGroups.Add(entity, selectedList);
}
}
}
}
else if (PlayerInput.KeyHit(Keys.Z))
{
SetPreviousRects(e => e.rectMemento.Undo());
}
else if (PlayerInput.KeyHit(Keys.R))
{
SetPreviousRects(e => e.rectMemento.Redo());
}
void SetPreviousRects(Func<MapEntity, Rectangle> memoryMethod)
{
foreach (var e in SelectedList)
{
if (e.rectMemento != null)
{
Point diff = memoryMethod(e).Location - e.Rect.Location;
// We have to call the move method, because there's a lot more than just storing the rect (in some cases)
// We also have to reassign the rect, because the move method does not set the width and height. They might have changed too.
// The Rect property is virtual and it's overridden for structs. Setting the rect via the property should automatically recreate the sections for resizable structures.
e.Move(diff.ToVector2());
e.Rect = e.rectMemento.Current;
}
}
}
}
else if (PlayerInput.KeyHit(Keys.Z))
{
SetPreviousRects(e => e.rectMemento.Undo());
}
else if (PlayerInput.KeyHit(Keys.R))
{
SetPreviousRects(e => e.rectMemento.Redo());
}
void SetPreviousRects(Func<MapEntity, Rectangle> memoryMethod)
{
foreach (var e in SelectedList)
{
if (e.rectMemento != null)
{
Point diff = memoryMethod(e).Location - e.Rect.Location;
// We have to call the move method, because there's a lot more than just storing the rect (in some cases)
// We also have to reassign the rect, because the move method does not set the width and height. They might have changed too.
// The Rect property is virtual and it's overridden for structs. Setting the rect via the property should automatically recreate the sections for resizable structures.
e.Move(diff.ToVector2());
e.Rect = e.rectMemento.Current;
}
}
}
}
}
Vector2 position = cam.ScreenToWorld(PlayerInput.MousePosition);
MapEntity highLightedEntity = null;
if (startMovingPos == Vector2.Zero)
{
List<MapEntity> highlightedEntities = new List<MapEntity>();
@@ -282,16 +283,19 @@ namespace Barotrauma
if (highLightedEntity != null) highLightedEntity.isHighlighted = true;
}
Vector2 nudgeAmount = Vector2.Zero;
if (PlayerInput.KeyHit(Keys.Up)) nudgeAmount.Y = 1f;
if (PlayerInput.KeyHit(Keys.Down)) nudgeAmount.Y = -1f;
if (PlayerInput.KeyHit(Keys.Left)) nudgeAmount.X = -1f;
if (PlayerInput.KeyHit(Keys.Right)) nudgeAmount.X = 1f;
if (nudgeAmount != Vector2.Zero)
if (GUI.KeyboardDispatcher.Subscriber == null)
{
foreach (MapEntity entityToNudge in selectedList)
Vector2 nudgeAmount = Vector2.Zero;
if (PlayerInput.KeyHit(Keys.Up)) nudgeAmount.Y = 1f;
if (PlayerInput.KeyHit(Keys.Down)) nudgeAmount.Y = -1f;
if (PlayerInput.KeyHit(Keys.Left)) nudgeAmount.X = -1f;
if (PlayerInput.KeyHit(Keys.Right)) nudgeAmount.X = 1f;
if (nudgeAmount != Vector2.Zero)
{
entityToNudge.Move(nudgeAmount);
foreach (MapEntity entityToNudge in selectedList)
{
entityToNudge.Move(nudgeAmount);
}
}
}
@@ -619,7 +623,7 @@ namespace Barotrauma
if (selectedList.Count == 0) return;
foreach (var e in selectedList)
{
if (e is Gap) { continue; }
if (e is Gap gap && gap.ConnectedDoor != null) { continue; }
FilteredSelectedList.Add(e);
}
var first = FilteredSelectedList.FirstOrDefault();

View File

@@ -18,11 +18,16 @@ namespace Barotrauma
return Screen.Selected == GameMain.SubEditorScreen || GameMain.DebugDraw;
}
public override bool SelectableInEditor
{
get { return !IsHidden(); }
}
public override void Draw(SpriteBatch spriteBatch, bool editing, bool back = true)
{
if (!editing && !GameMain.DebugDraw) return;
if (!editing && !GameMain.DebugDraw) { return; }
if (IsHidden()) return;
if (IsHidden()) { return; }
//Rectangle drawRect =
// Submarine == null ? rect : new Rectangle((int)(Submarine.DrawPosition.X + rect.X), (int)(Submarine.DrawPosition.Y + rect.Y), rect.Width, rect.Height);

View File

@@ -1093,6 +1093,7 @@ namespace Barotrauma.Networking
bool loadSecondSub = inc.ReadBoolean();
bool disguisesAllowed = inc.ReadBoolean();
bool rewiringAllowed = inc.ReadBoolean();
bool isTraitor = inc.ReadBoolean();
string traitorTargetName = isTraitor ? inc.ReadString() : null;
@@ -1114,6 +1115,7 @@ namespace Barotrauma.Networking
GameMain.LightManager.LosMode = (LosMode)losMode;
serverSettings.AllowDisguises = disguisesAllowed;
serverSettings.AllowRewiring = rewiringAllowed;
serverSettings.AllowRagdollButton = allowRagdollButton;
if (campaign == null)
@@ -1706,6 +1708,8 @@ namespace Barotrauma.Networking
case FileTransferType.Submarine:
new GUIMessageBox(TextManager.Get("ServerDownloadFinished"), TextManager.GetWithVariable("FileDownloadedNotification", "[filename]", transfer.FileName));
var newSub = new Submarine(transfer.FilePath);
if (newSub.IsFileCorrupted) { return; }
var existingSubs = Submarine.SavedSubmarines.Where(s => s.Name == newSub.Name && s.MD5Hash.Hash == newSub.MD5Hash.Hash).ToList();
foreach (Submarine existingSub in existingSubs)
{
@@ -2494,7 +2498,7 @@ namespace Barotrauma.Networking
}
else
{
BanPlayer(clientName, banReasonBox.Text, ban);
BanPlayer(clientName, banReasonBox.Text, range: rangeBan);
}
}
else

View File

@@ -60,54 +60,35 @@ namespace Barotrauma.Networking
return contentPackageHashes.SetEquals(myContentPackageHashes);
}
public void CreatePreviewWindow(GUIListBox listBox)
public void CreatePreviewWindow(GUIFrame frame)
{
listBox.ClearChildren();
frame.ClearChildren();
if (listBox == null) return;
if (frame == null) return;
var previewContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), listBox.Content.RectTransform, Anchor.Center))
var previewContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 1.0f), frame.RectTransform, Anchor.Center))
{
Stretch = true
};
var titleHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.07f), previewContainer.RectTransform))
var columnContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.5f), previewContainer.RectTransform))
{
IsHorizontal = true,
Stretch = true
};
var title = new GUITextBlock(new RectTransform(new Vector2(0.7f, 1.0f), titleHolder.RectTransform), ServerName, font: GUI.LargeFont, wrap: true);
float elementHeight = 0.075f;
var title = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), columnContainer.RectTransform), ServerName, font: GUI.LargeFont);
title.Text = ToolBox.LimitString(title.Text, title.Font, title.Rect.Width);
new GUITextBlock(new RectTransform(new Vector2(0.3f, 1.0f), titleHolder.RectTransform),
TextManager.AddPunctuation(':', TextManager.Get("ServerListVersion"), string.IsNullOrEmpty(GameVersion) ? TextManager.Get("Unknown") : GameVersion),
textAlignment: Alignment.Right);
var columnContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.5f), previewContainer.RectTransform), isHorizontal: true)
{
Stretch = true,
RelativeSpacing = 0.005f
};
var columnLeft = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1.0f), columnContainer.RectTransform))
{
RelativeSpacing = 0.02f,
Stretch = true
};
var columnRight = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1.0f), columnContainer.RectTransform))
{
RelativeSpacing = 0.02f,
Stretch = true
};
float elementHeight = 0.1f;
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), columnContainer.RectTransform),
TextManager.AddPunctuation(':', TextManager.Get("ServerListVersion"), string.IsNullOrEmpty(GameVersion) ? TextManager.Get("Unknown") : GameVersion));
// left column -----------------------------------------------------------------------------
//new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), columnLeft.RectTransform), IP + ":" + Port);
var serverMsg = new GUIListBox(new RectTransform(new Vector2(1.0f, 1.0f), columnLeft.RectTransform)) { ScrollBarVisible = true };
var serverMsg = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.5f), columnContainer.RectTransform)) { ScrollBarVisible = true };
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), serverMsg.Content.RectTransform), ServerMessage, wrap: true) { CanBeFocused = false };
// right column -----------------------------------------------------------------------------
@@ -122,20 +103,22 @@ namespace Barotrauma.Networking
CanBeFocused = false
};*/
var gameMode = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), columnRight.RectTransform), TextManager.Get("GameMode"));
new GUITextBlock(new RectTransform(Vector2.One, gameMode.RectTransform), TextManager.Get(string.IsNullOrEmpty(GameMode) ? "Unknown" : GameMode), textAlignment: Alignment.Right);
var gameMode = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), columnContainer.RectTransform), TextManager.Get("GameMode"));
new GUITextBlock(new RectTransform(Vector2.One, gameMode.RectTransform),
TextManager.Get(string.IsNullOrEmpty(GameMode) ? "Unknown" : "GameMode." + GameMode, returnNull: true) ?? GameMode,
textAlignment: Alignment.Right);
var traitors = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), columnContainer.RectTransform), TextManager.Get("Traitors"));
var traitors = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), columnRight.RectTransform), TextManager.Get("Traitors"));
new GUITextBlock(new RectTransform(Vector2.One, traitors.RectTransform), TextManager.Get(!TraitorsEnabled.HasValue ? "Unknown" : TraitorsEnabled.Value.ToString()), textAlignment: Alignment.Right);
var subSelection = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), columnRight.RectTransform), TextManager.Get("ServerListSubSelection"));
var subSelection = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), columnContainer.RectTransform), TextManager.Get("ServerListSubSelection"));
new GUITextBlock(new RectTransform(Vector2.One, subSelection.RectTransform), TextManager.Get(!SubSelectionMode.HasValue ? "Unknown" : SubSelectionMode.Value.ToString()), textAlignment: Alignment.Right);
var modeSelection = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), columnRight.RectTransform), TextManager.Get("ServerListModeSelection"));
var modeSelection = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), columnContainer.RectTransform), TextManager.Get("ServerListModeSelection"));
new GUITextBlock(new RectTransform(Vector2.One, modeSelection.RectTransform), TextManager.Get(!ModeSelectionMode.HasValue ? "Unknown" : ModeSelectionMode.Value.ToString()), textAlignment: Alignment.Right);
var allowSpectating = new GUITickBox(new RectTransform(new Vector2(1, elementHeight), columnRight.RectTransform), TextManager.Get("ServerListAllowSpectating"))
var allowSpectating = new GUITickBox(new RectTransform(new Vector2(1, elementHeight), columnContainer.RectTransform), TextManager.Get("ServerListAllowSpectating"))
{
CanBeFocused = false
};
@@ -144,7 +127,7 @@ namespace Barotrauma.Networking
else
allowSpectating.Selected = AllowSpectating.Value;
var allowRespawn = new GUITickBox(new RectTransform(new Vector2(1, elementHeight), columnRight.RectTransform), TextManager.Get("ServerSettingsAllowRespawning"))
var allowRespawn = new GUITickBox(new RectTransform(new Vector2(1, elementHeight), columnContainer.RectTransform), TextManager.Get("ServerSettingsAllowRespawning"))
{
CanBeFocused = false
};
@@ -153,7 +136,7 @@ namespace Barotrauma.Networking
else
allowRespawn.Selected = AllowRespawn.Value;
var voipEnabledTickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, elementHeight), columnRight.RectTransform), TextManager.Get("serversettingsvoicechatenabled"))
var voipEnabledTickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, elementHeight), columnContainer.RectTransform), TextManager.Get("serversettingsvoicechatenabled"))
{
CanBeFocused = false
};
@@ -162,7 +145,7 @@ namespace Barotrauma.Networking
else
voipEnabledTickBox.Selected = VoipEnabled.Value;
var usingWhiteList = new GUITickBox(new RectTransform(new Vector2(1, elementHeight), columnRight.RectTransform), TextManager.Get("ServerListUsingWhitelist"))
var usingWhiteList = new GUITickBox(new RectTransform(new Vector2(1, elementHeight), columnContainer.RectTransform), TextManager.Get("ServerListUsingWhitelist"))
{
CanBeFocused = false
};
@@ -171,10 +154,16 @@ namespace Barotrauma.Networking
else
usingWhiteList.Selected = UsingWhiteList.Value;
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), columnRight.RectTransform),
columnContainer.RectTransform.SizeChanged += () =>
{
GUITextBlock.AutoScaleAndNormalize(allowSpectating.TextBlock, allowRespawn.TextBlock, voipEnabledTickBox.TextBlock, usingWhiteList.TextBlock);
};
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), columnContainer.RectTransform),
TextManager.Get("ServerListContentPackages"));
var contentPackageList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.3f), columnRight.RectTransform));
var contentPackageList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.3f), columnContainer.RectTransform)) { ScrollBarVisible = true };
if (ContentPackageNames.Count == 0)
{
new GUITextBlock(new RectTransform(Vector2.One, contentPackageList.Content.RectTransform), TextManager.Get("Unknown"), textAlignment: Alignment.Center)
@@ -223,7 +212,7 @@ namespace Barotrauma.Networking
}
if (availableWorkshopUrls.Count > 0)
{
var workshopBtn = new GUIButton(new RectTransform(new Vector2(1.0f, 0.15f), columnLeft.RectTransform), TextManager.Get("ServerListSubscribeMissingPackages"))
var workshopBtn = new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), columnContainer.RectTransform), TextManager.Get("ServerListSubscribeMissingPackages"))
{
ToolTip = TextManager.Get(SteamManager.IsInitialized ? "ServerListSubscribeMissingPackagesTooltip" : "ServerListSubscribeMissingPackagesTooltipNoSteam"),
Enabled = SteamManager.IsInitialized,
@@ -240,11 +229,7 @@ namespace Barotrauma.Networking
// -----------------------------------------------------------------------------
foreach (GUIComponent c in columnLeft.Children)
{
if (c is GUITextBlock textBlock) textBlock.Padding = Vector4.Zero;
}
foreach (GUIComponent c in columnRight.Children)
foreach (GUIComponent c in columnContainer.Children)
{
if (c is GUITextBlock textBlock) textBlock.Padding = Vector4.Zero;
}

View File

@@ -242,6 +242,10 @@ namespace Barotrauma.Steam
if (s.Rules.ContainsKey("gamestarted")) serverInfo.GameStarted = s.Rules["gamestarted"] == "True";
if (s.Rules.ContainsKey("gamemode"))
{
serverInfo.GameMode = s.Rules["gamemode"];
}
if (serverInfo.ContentPackageNames.Count != serverInfo.ContentPackageHashes.Count ||
serverInfo.ContentPackageHashes.Count != serverInfo.ContentPackageWorkshopUrls.Count)
{
@@ -596,7 +600,7 @@ namespace Barotrauma.Steam
}
else
{
DebugConsole.ThrowError("Publishing workshop item " + item.Title + " failed. " + item.Error);
DebugConsole.NewMessage("Publishing workshop item " + item.Title + " failed. " + item.Error, Microsoft.Xna.Framework.Color.Red);
}
SaveUtil.ClearFolder(WorkshopItemStagingFolder);

View File

@@ -73,15 +73,31 @@ namespace Barotrauma.Networking
if (captureDevice == IntPtr.Zero)
{
DebugConsole.NewMessage("Alc.CaptureOpenDevice attempt 1 failed: error code " + Alc.GetError(IntPtr.Zero).ToString(),Color.Orange);
//attempt using a smaller buffer size
captureDevice = Alc.CaptureOpenDevice(deviceName, VoipConfig.FREQUENCY, Al.FormatMono16, VoipConfig.BUFFER_SIZE * 2);
}
if (captureDevice == IntPtr.Zero)
{
DebugConsole.NewMessage("Alc.CaptureOpenDevice attempt 2 failed: error code " + Alc.GetError(IntPtr.Zero).ToString(), Color.Orange);
//attempt using the default device
captureDevice = Alc.CaptureOpenDevice("", VoipConfig.FREQUENCY, Al.FormatMono16, VoipConfig.BUFFER_SIZE * 2);
}
if (captureDevice == IntPtr.Zero)
{
string errorCode = Alc.GetError(IntPtr.Zero).ToString();
if (!GUIMessageBox.MessageBoxes.Any(mb => mb.UserData as string == "capturedevicenotfound"))
{
GUI.SettingsMenuOpen = false;
new GUIMessageBox(TextManager.Get("Error"),
TextManager.Get("VoipCaptureDeviceNotFound", returnNull: true) ?? "Could not start voice capture, suitable capture device not found.")
new GUIMessageBox(TextManager.Get("Error"),
(TextManager.Get("VoipCaptureDeviceNotFound", returnNull: true) ?? "Could not start voice capture, suitable capture device not found.") + " (" + errorCode + ")")
{
UserData = "capturedevicenotfound"
};
}
GameAnalyticsManager.AddErrorEventOnce("Alc.CaptureDeviceOpen(" + deviceName + ") failed", GameAnalyticsSDK.Net.EGAErrorSeverity.Error,"Error code: "+errorCode);
GameMain.Config.VoiceSetting = GameSettings.VoiceMode.Disabled;
Instance?.Dispose();
Instance = null;

View File

@@ -6,6 +6,7 @@ using System.Linq;
using System.Text;
using GameAnalyticsSDK.Net;
using Barotrauma.Steam;
using System.Diagnostics;
#if WINDOWS
using System.Windows.Forms;
@@ -28,7 +29,7 @@ namespace Barotrauma
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
static void Main(string[] args)
{
SteamManager.Initialize();
GameMain game = null;
@@ -36,7 +37,7 @@ namespace Barotrauma
try
{
#endif
game = new GameMain();
game = new GameMain(args);
#if !DEBUG
}
catch (Exception e)
@@ -151,11 +152,14 @@ namespace Barotrauma
return false;
}
public static void CrashMessageBox(string message)
public static void CrashMessageBox(string message, string filePath)
{
#if WINDOWS
MessageBox.Show(message, "Oops! Barotrauma just crashed.", MessageBoxButtons.OK, MessageBoxIcon.Error);
#endif
// Open the crash log.
Process.Start(filePath);
}
static void CrashDump(GameMain game, string filePath, Exception exception)
@@ -278,14 +282,14 @@ namespace Barotrauma
if (GameSettings.SendUserStatistics)
{
CrashMessageBox("A crash report (\"" + filePath + "\") was saved in the root folder of the game and sent to the developers.");
CrashMessageBox("A crash report (\"" + filePath + "\") was saved in the root folder of the game and sent to the developers.", filePath);
GameAnalytics.AddErrorEvent(EGAErrorSeverity.Critical, crashReport);
GameAnalytics.OnQuit();
}
else
{
CrashMessageBox("A crash report (\"" + filePath + "\") was saved in the root folder of the game. The error was not sent to the developers because user statistics have been disabled, but" +
" if you'd like to help fix this bug, you may post it on Barotrauma's GitHub issue tracker: https://github.com/Regalis11/Barotrauma/issues/");
" if you'd like to help fix this bug, you may post it on Barotrauma's GitHub issue tracker: https://github.com/Regalis11/Barotrauma/issues/", filePath);
}
}
}

View File

@@ -9,6 +9,7 @@ using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
using System.Xml.Linq;
namespace Barotrauma
{
@@ -736,6 +737,7 @@ namespace Barotrauma
string arguments = "-name \"" + name.Replace("\\", "\\\\").Replace("\"", "\\\"") + "\"" +
" -port " + port.ToString() +
" -queryport " + queryPort.ToString() +
" -public " + isPublicBox.Selected.ToString() +
" -password \"" + passwordBox.Text.Replace("\\", "\\\\").Replace("\"", "\\\"") + "\"" +
" -upnp " + useUpnpBox.Selected +
" -maxplayers " + maxPlayersBox.Text +
@@ -940,6 +942,20 @@ namespace Barotrauma
#region UI Methods
private void CreateHostServerFields()
{
int port = NetConfig.DefaultPort;
int queryPort = NetConfig.DefaultQueryPort;
int maxPlayers = 8;
if (File.Exists(ServerSettings.SettingsFile))
{
XDocument settingsDoc = XMLExtensions.TryLoadXml(ServerSettings.SettingsFile);
if (settingsDoc?.Root != null)
{
port = settingsDoc.Root.GetAttributeInt("port", port);
queryPort = settingsDoc.Root.GetAttributeInt("queryport", queryPort);
maxPlayers = settingsDoc.Root.GetAttributeInt("maxplayers", maxPlayers);
}
}
Vector2 textLabelSize = new Vector2(1.0f, 0.1f);
Alignment textAlignment = Alignment.CenterLeft;
Vector2 textFieldSize = new Vector2(0.5f, 1.0f);
@@ -954,12 +970,16 @@ namespace Barotrauma
new GUITextBlock(new RectTransform(textLabelSize, parent.RectTransform), TextManager.Get("HostServerButton"), textAlignment: Alignment.Center, font: GUI.LargeFont) { ForceUpperCase = true };
var label = new GUITextBlock(new RectTransform(textLabelSize, parent.RectTransform), TextManager.Get("ServerName"), textAlignment: textAlignment);
serverNameBox = new GUITextBox(new RectTransform(textFieldSize, label.RectTransform, Anchor.CenterRight), textAlignment: textAlignment);
serverNameBox = new GUITextBox(new RectTransform(textFieldSize, label.RectTransform, Anchor.CenterRight), textAlignment: textAlignment)
{
MaxTextLength = NetConfig.ServerNameMaxLength,
OverflowClip = true
};
label = new GUITextBlock(new RectTransform(textLabelSize, parent.RectTransform), TextManager.Get("ServerPort"), textAlignment: textAlignment);
portBox = new GUITextBox(new RectTransform(textFieldSize, label.RectTransform, Anchor.CenterRight), textAlignment: textAlignment)
{
Text = NetConfig.DefaultPort.ToString(),
Text = port.ToString(),
ToolTip = TextManager.Get("ServerPortToolTip")
};
@@ -968,7 +988,7 @@ namespace Barotrauma
label = new GUITextBlock(new RectTransform(textLabelSize, parent.RectTransform), TextManager.Get("ServerQueryPort"), textAlignment: textAlignment);
queryPortBox = new GUITextBox(new RectTransform(textFieldSize, label.RectTransform, Anchor.CenterRight), textAlignment: textAlignment)
{
Text = NetConfig.DefaultQueryPort.ToString(),
Text = queryPort.ToString(),
ToolTip = TextManager.Get("ServerQueryPortToolTip")
};
}
@@ -987,7 +1007,7 @@ namespace Barotrauma
maxPlayersBox = new GUITextBox(new RectTransform(new Vector2(0.6f, 1.0f), buttonContainer.RectTransform), textAlignment: Alignment.Center)
{
Text = "8",
Text = maxPlayers.ToString(),
Enabled = false
};
new GUIButton(new RectTransform(new Vector2(0.2f, 1.0f), buttonContainer.RectTransform), "+", textAlignment: Alignment.Center)

View File

@@ -335,8 +335,12 @@ namespace Barotrauma
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.03f), rightInfoColumn.RectTransform), style: null);
//server info ------------------------------------------------------------------
ServerName = new GUITextBox(new RectTransform(new Vector2(0.3f, 0.05f), infoFrameContent.RectTransform));
ServerName = new GUITextBox(new RectTransform(new Vector2(infoColumnContainer.RectTransform.RelativeSize.X, 0.05f), infoFrameContent.RectTransform))
{
MaxTextLength = NetConfig.ServerNameMaxLength,
OverflowClip = true
};
ServerName.OnDeselected += (textBox, key) =>
{
GameMain.Client.ServerSettings.ClientAdminWrite(ServerSettings.NetFlags.Name);
@@ -1608,13 +1612,13 @@ namespace Barotrauma
public void BanPlayer(Client client)
{
if (GameMain.NetworkMember == null || client == null) { return; }
GameMain.Client.CreateKickReasonPrompt(client.Name, true);
GameMain.Client.CreateKickReasonPrompt(client.Name, ban: true, rangeBan: false);
}
public void BanPlayerRange(Client client)
{
if (GameMain.NetworkMember == null || client == null) { return; }
GameMain.Client.CreateKickReasonPrompt(client.Name, true, true);
GameMain.Client.CreateKickReasonPrompt(client.Name, ban: true, rangeBan: true);
}
public override void AddToGUIUpdateList()

View File

@@ -1,333 +0,0 @@
using FarseerPhysics;
using FarseerPhysics.Dynamics.Joints;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Barotrauma
{
class OldCharacterEditorScreen : Screen
{
private Camera cam;
private GUIComponent GUIpanel;
private GUIButton physicsButton;
private GUIListBox limbList, jointList;
private GUIFrame limbPanel;
private Character editingCharacter;
private Limb editingLimb;
private List<Texture2D> textures;
private List<string> texturePaths;
private bool physicsEnabled;
public override Camera Cam
{
get { return cam; }
}
public override void Select()
{
base.Select();
GameMain.DebugDraw = true;
cam = new Camera();
/*GUIpanel = new GUIFrame(new Rectangle(0, 0, 300, GameMain.GraphicsHeight), "");
//GUIpanel.Padding = new Vector4(10.0f, 10.0f, 10.0f, 10.0f);
physicsButton = new GUIButton(new Rectangle(0, 50, 200, 25), "Physics", Alignment.Left, "", GUIpanel);
physicsButton.OnClicked += TogglePhysics;
new GUITextBlock(new Rectangle(0, 80, 0, 25), "Limbs:", "", GUIpanel);
limbList = new GUIListBox(new Rectangle(0, 110, 0, 250), Color.White * 0.7f, "", GUIpanel);
limbList.OnSelected = SelectLimb;
new GUITextBlock(new Rectangle(0, 360, 0, 25), "Joints:", "", GUIpanel);
jointList = new GUIListBox(new Rectangle(0, 390, 0, 250), Color.White * 0.7f, "", GUIpanel);*/
while (Character.CharacterList.Count > 1)
{
Character.CharacterList.First().Remove();
}
if (Character.CharacterList.Count == 1)
{
if (editingCharacter != Character.CharacterList[0]) UpdateLimbLists(Character.CharacterList[0]);
editingCharacter = Character.CharacterList[0];
Vector2 camPos = editingCharacter.AnimController.Limbs[0].body.SimPosition;
camPos = ConvertUnits.ToDisplayUnits(camPos);
camPos.Y = -camPos.Y;
cam.TargetPos = camPos;
if (physicsEnabled)
{
editingCharacter.Control(1.0f, cam);
}
else
{
cam.TargetPos = Vector2.Zero;
}
}
textures = new List<Texture2D>();
texturePaths = new List<string>();
foreach (Limb limb in editingCharacter.AnimController.Limbs)
{
if (limb.ActiveSprite==null || texturePaths.Contains(limb.ActiveSprite.FilePath)) continue;
textures.Add(limb.ActiveSprite.Texture);
texturePaths.Add(limb.ActiveSprite.FilePath);
}
}
/// <summary>
/// Allows the game to run logic such as updating the world,
/// checking for collisions, gathering input, and playing audio.
/// </summary>
public override void Update(double deltaTime)
{
cam.MoveCamera((float)deltaTime);
GUIpanel.UpdateManually((float)deltaTime);
if (physicsEnabled)
{
Character.UpdateAnimAll((float)deltaTime);
Ragdoll.UpdateAll((float)deltaTime, cam);
GameMain.World.Step((float)deltaTime);
}
}
public override void AddToGUIUpdateList()
{
GUIpanel.AddToGUIUpdateList();
}
/// <summary>
/// This is called when the game should draw itself.
/// </summary>
public override void Draw(double deltaTime, GraphicsDevice graphics, SpriteBatch spriteBatch)
{
//cam.UpdateTransform();
graphics.Clear(Color.CornflowerBlue);
spriteBatch.Begin(SpriteSortMode.BackToFront,
BlendState.AlphaBlend,
null, null, null, null,
cam.Transform);
Submarine.Draw(spriteBatch, true);
spriteBatch.End();
spriteBatch.Begin(SpriteSortMode.BackToFront,
BlendState.AlphaBlend,
null, null, null, null,
cam.Transform);
//if (EntityPrefab.Selected != null) EntityPrefab.Selected.UpdatePlacing(spriteBatch, cam);
//Entity.DrawSelecting(spriteBatch, cam);
if (editingCharacter!=null)
editingCharacter.Draw(spriteBatch, Cam);
spriteBatch.End();
//-------------------- HUD -----------------------------
spriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, GameMain.ScissorTestEnable);
GUIpanel.DrawManually(spriteBatch);
EditLimb(spriteBatch);
int y = 0;
for (int i = 0; i < textures.Count; i++ )
{
int x = GameMain.GraphicsWidth - textures[i].Width;
spriteBatch.Draw(textures[i], new Vector2(x, y), Color.White);
foreach (Limb limb in editingCharacter.AnimController.Limbs)
{
if (limb.ActiveSprite == null || limb.ActiveSprite.FilePath != texturePaths[i]) continue;
Rectangle rect = limb.ActiveSprite.SourceRect;
rect.X += x;
rect.Y += y;
GUI.DrawRectangle(spriteBatch, rect, Color.Red);
Vector2 limbBodyPos = new Vector2(
rect.X + limb.ActiveSprite.Origin.X,
rect.Y + limb.ActiveSprite.Origin.Y);
DrawJoints(spriteBatch, limb, limbBodyPos);
//if (limb.BodyShapeTexture == null) continue;
//spriteBatch.Draw(limb.BodyShapeTexture, limbBodyPos,
// null, Color.White, 0.0f,
// new Vector2(limb.BodyShapeTexture.Width, limb.BodyShapeTexture.Height) / 2,
// 1.0f, SpriteEffects.None, 0.0f);
GUI.DrawLine(spriteBatch, limbBodyPos + Vector2.UnitY * 5.0f, limbBodyPos - Vector2.UnitY * 5.0f, Color.White);
GUI.DrawLine(spriteBatch, limbBodyPos + Vector2.UnitX * 5.0f, limbBodyPos - Vector2.UnitX * 5.0f, Color.White);
if (Vector2.Distance(PlayerInput.MousePosition, limbBodyPos)<5.0f && PlayerInput.LeftButtonHeld())
{
limb.ActiveSprite.Origin += PlayerInput.MouseSpeed;
}
}
y += textures[i].Height;
}
GUI.Draw(Cam, spriteBatch);
//EntityPrefab.DrawList(spriteBatch, new Vector2(20,50));
//Entity.Edit(spriteBatch, cam);
spriteBatch.End();
}
private void UpdateLimbLists(Character character)
{
limbList.ClearChildren();
/*foreach (Limb limb in character.AnimController.Limbs)
{
GUITextBlock textBlock = new GUITextBlock(
new Rectangle(0,0,0,25),
limb.type.ToString(),
Color.Transparent,
Color.White,
Alignment.Left, null,
limbList);
textBlock.Padding = new Vector4(10.0f, 0.0f, 0.0f, 0.0f);
textBlock.UserData = limb;
}
jointList.ClearChildren();
foreach (RevoluteJoint joint in character.AnimController.LimbJoints)
{
Limb limb1 = (Limb)(joint.BodyA.UserData);
Limb limb2 = (Limb)(joint.BodyB.UserData);
GUITextBlock textBlock = new GUITextBlock(
new Rectangle(0, 0, 0, 25),
limb1.type.ToString() + " - " + limb2.type.ToString(),
Color.Transparent,
Color.White,
Alignment.Left, null,
jointList);
textBlock.Padding = new Vector4(10.0f, 0.0f, 0.0f, 0.0f);
textBlock.UserData = joint;
}*/
}
private void DrawJoints(SpriteBatch spriteBatch, Limb limb, Vector2 limbBodyPos)
{
foreach (var joint in editingCharacter.AnimController.LimbJoints)
{
Vector2 jointPos = Vector2.Zero;
if (joint.BodyA == limb.body.FarseerBody)
{
jointPos = ConvertUnits.ToDisplayUnits(joint.LocalAnchorA);
}
else if (joint.BodyB == limb.body.FarseerBody)
{
jointPos = ConvertUnits.ToDisplayUnits(joint.LocalAnchorB);
}
else
{
continue;
}
Vector2 tformedJointPos = jointPos /= limb.Scale;
tformedJointPos.Y = -tformedJointPos.Y;
tformedJointPos += limbBodyPos;
if (joint.BodyA == limb.body.FarseerBody)
{
float a1 = joint.UpperLimit - MathHelper.PiOver2;
float a2 = joint.LowerLimit - MathHelper.PiOver2;
float a3 = (a1 + a2) / 2.0f;
GUI.DrawLine(spriteBatch, tformedJointPos, tformedJointPos + new Vector2((float)Math.Cos(a1), -(float)Math.Sin(a1)) * 30.0f, Color.Green);
GUI.DrawLine(spriteBatch, tformedJointPos, tformedJointPos + new Vector2((float)Math.Cos(a2), -(float)Math.Sin(a2)) * 30.0f, Color.DarkGreen);
GUI.DrawLine(spriteBatch, tformedJointPos, tformedJointPos + new Vector2((float)Math.Cos(a3), -(float)Math.Sin(a3)) * 30.0f, Color.LightGray);
}
GUI.DrawRectangle(spriteBatch, tformedJointPos, new Vector2(5.0f, 5.0f), Color.Red, true);
if (Vector2.Distance(PlayerInput.MousePosition, tformedJointPos) < 10.0f)
{
GUI.DrawString(spriteBatch, tformedJointPos + Vector2.One*10.0f, jointPos.ToString(), Color.White, Color.Black * 0.5f);
GUI.DrawRectangle(spriteBatch, tformedJointPos - new Vector2(3.0f, 3.0f), new Vector2(11.0f, 11.0f), Color.Red, false);
if (PlayerInput.LeftButtonHeld())
{
Vector2 speed = ConvertUnits.ToSimUnits(PlayerInput.MouseSpeed);
speed.Y = -speed.Y;
if (joint.BodyA == limb.body.FarseerBody)
{
joint.LocalAnchorA += speed;
}
else
{
joint.LocalAnchorB += speed;
}
}
}
}
}
private bool SelectLimb(GUIComponent component, object selection)
{
/*try
{
editingLimb = (Limb)selection;
limbPanel = new GUIFrame(new Rectangle(300, 0, 500, 100), Color.Gray*0.8f);
//limbPanel.Padding = new Vector4(10.0f,10.0f,10.0f,10.0f);
new GUITextBlock(new Rectangle(0, 0, 200, 25), editingLimb.type.ToString(), Color.Transparent, Color.Black, Alignment.Left, null, limbPanel);
//spriteOrigin = new GUITextBlock(new Rectangle(0, 25, 200, 25), "Sprite origin: ", Color.White, Color.Black, Alignment.Left, limbPanel);
}
catch
{
return false;
}*/
return true;
}
private void EditLimb(SpriteBatch spriteBatch)
{
if (editingLimb == null) return;
limbPanel.DrawManually(spriteBatch);
}
private bool TogglePhysics(GUIButton button, object selection)
{
physicsEnabled = !physicsEnabled;
physicsButton.Text = (physicsEnabled) ? "Disable physics" : "Enable physics";
return false;
}
}
}

View File

@@ -19,73 +19,87 @@ namespace Barotrauma
//how often the client is allowed to refresh servers
private TimeSpan AllowedRefreshInterval = new TimeSpan(0, 0, 3);
private GUIFrame menu;
private readonly GUIFrame menu;
private GUIListBox serverList;
private GUIListBox serverPreview;
private readonly GUIListBox serverList;
private readonly GUIFrame serverPreview;
private GUIButton joinButton;
private readonly GUIButton joinButton;
private GUITextBox clientNameBox, ipBox;
private readonly GUITextBox clientNameBox, ipBox;
private bool masterServerResponded;
private IRestResponse masterServerResponse;
private GUIButton refreshButton;
private float[] columnRelativeWidth;
private readonly float[] columnRelativeWidth = new float[] { 0.1f, 0.1f, 0.7f, 0.12f, 0.08f, 0.08f };
private readonly string[] columnLabel = new string[] { "ServerListCompatible", "ServerListHasPassword", "ServerListName", "ServerListRoundStarted", "ServerListPlayers", "ServerListPing" };
private readonly GUILayoutGroup labelHolder;
private readonly List<GUITextBlock> labelTexts = new List<GUITextBlock>();
//filters
private GUITextBox searchBox;
private GUITickBox filterPassword;
private GUITickBox filterIncompatible;
private GUITickBox filterFull;
private GUITickBox filterEmpty;
private readonly GUITextBox searchBox;
private readonly GUITickBox filterPassword;
private readonly GUITickBox filterIncompatible;
private readonly GUITickBox filterFull;
private readonly GUITickBox filterEmpty;
//a timer for
private string sortedBy;
private readonly GUIButton serverPreviewToggleButton;
//a timer for preventing the client from spamming the refresh button faster than AllowedRefreshInterval
private DateTime refreshDisableTimer;
private bool waitingForRefresh;
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) });
menu = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.85f), 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)
{ Stretch = true, RelativeSpacing = 0.02f };
//-------------------------------------------------------------------------------------
//left column
//-------------------------------------------------------------------------------------
var leftColumn = new GUILayoutGroup(new RectTransform(new Vector2(0.25f, 1.0f), paddedFrame.RectTransform, Anchor.CenterLeft)) { Stretch = true, RelativeSpacing = 0.5f };
var infoHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.5f), leftColumn.RectTransform)) { RelativeSpacing = 0.05f };
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), infoHolder.RectTransform, Anchor.Center), TextManager.Get("JoinServer"), font: GUI.LargeFont)
var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.97f, 0.95f), menu.RectTransform, Anchor.Center))
{
RelativeSpacing = 0.02f,
Stretch = true
};
//-------------------------------------------------------------------------------------
//Top row
//-------------------------------------------------------------------------------------
var topRow = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.15f), paddedFrame.RectTransform)) { Stretch = true };
var title = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.33f), topRow.RectTransform), TextManager.Get("JoinServer"), font: GUI.LargeFont)
{
Padding = Vector4.Zero,
ForceUpperCase = true,
AutoScale = true
};
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoHolder.RectTransform), TextManager.Get("YourName"));
clientNameBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.13f), infoHolder.RectTransform), "")
var infoHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.33f), topRow.RectTransform), isHorizontal: true) { RelativeSpacing = 0.05f, Stretch = true };
var clientNameHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), infoHolder.RectTransform)) { RelativeSpacing = 0.05f };
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), clientNameHolder.RectTransform), TextManager.Get("YourName"));
clientNameBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.5f), clientNameHolder.RectTransform), "")
{
Text = GameMain.Config.DefaultPlayerName,
MaxTextLength = Client.MaxNameLength,
OverflowClip = true
};
if (string.IsNullOrEmpty(clientNameBox.Text))
{
clientNameBox.Text = SteamManager.GetUsername();
}
clientNameBox.OnTextChanged += RefreshJoinButtonState;
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoHolder.RectTransform), TextManager.Get("ServerIP"));
ipBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.13f), infoHolder.RectTransform), "");
ipBox.OnTextChanged += RefreshJoinButtonState;
ipBox.OnSelected += (sender, key) =>
var ipBoxHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), infoHolder.RectTransform)) { RelativeSpacing = 0.05f };
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), ipBoxHolder.RectTransform), TextManager.Get("ServerIP"));
ipBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.5f), ipBoxHolder.RectTransform), "");
ipBox.OnTextChanged += (textBox, text) => { joinButton.Enabled = !string.IsNullOrEmpty(text); return true; };
ipBox.OnSelected += (sender, key) =>
{
if (sender.UserData is ServerInfo)
{
@@ -94,93 +108,357 @@ namespace Barotrauma
}
};
var filterHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.5f), leftColumn.RectTransform)) { RelativeSpacing = 0.05f };
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), filterHolder.RectTransform), TextManager.Get("FilterServers"));
searchBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.13f), filterHolder.RectTransform), "");
var tickBoxHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.5f), filterHolder.RectTransform));
searchBox.OnTextChanged += (txtBox, txt) => { FilterServers(); return true; };
filterPassword = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.27f), tickBoxHolder.RectTransform), TextManager.Get("FilterPassword"));
filterPassword.OnSelected += (tickBox) => { FilterServers(); return true; };
filterIncompatible = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.27f), tickBoxHolder.RectTransform), TextManager.Get("FilterIncompatibleServers"));
filterIncompatible.OnSelected += (tickBox) => { FilterServers(); return true; };
filterFull = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.27f), tickBoxHolder.RectTransform), TextManager.Get("FilterFullServers"));
filterFull.OnSelected += (tickBox) => { FilterServers(); return true; };
filterEmpty = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.27f), tickBoxHolder.RectTransform), TextManager.Get("FilterEmptyServers"));
filterEmpty.OnSelected += (tickBox) => { FilterServers(); return true; };
//-------------------------------------------------------------------------------------
//right column
// Bottom row
//-------------------------------------------------------------------------------------
var rightColumn = new GUILayoutGroup(new RectTransform(new Vector2(1.0f - leftColumn.RectTransform.RelativeSize.X - 0.017f, 1.0f),
var bottomRow = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f - topRow.RectTransform.RelativeSize.Y),
paddedFrame.RectTransform, Anchor.CenterRight))
{
RelativeSpacing = 0.02f,
Stretch = true
};
var serverListHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), rightColumn.RectTransform)) { Stretch = true, RelativeSpacing = 0.02f };
serverList = new GUIListBox(new RectTransform(new Vector2(1.0f, 1.0f), serverListHolder.RectTransform, Anchor.Center))
var serverListHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), bottomRow.RectTransform), isHorizontal: true)
{
OnSelected = (btn, obj) => {
if (obj is ServerInfo)
Stretch = true
};
// filters -------------------------------------------
var filters = new GUIFrame(new RectTransform(new Vector2(0.25f, 1.0f), serverListHolder.RectTransform, Anchor.Center), style: null)
{
Color = new Color(12, 14, 15, 255) * 0.5f,
OutlineColor = Color.Black
};
var filterToggle = new GUIButton(new RectTransform(new Vector2(0.02f, 1.0f), serverListHolder.RectTransform, Anchor.CenterRight) { MinSize = new Point(20, 0) }, style: "UIToggleButton")
{
OnClicked = (btn, userdata) =>
{
filters.RectTransform.RelativeSize = new Vector2(0.25f, 1.0f);
filters.Visible = !filters.Visible;
filters.IgnoreLayoutGroups = !filters.Visible;
serverListHolder.Recalculate();
btn.Children.ForEach(c => c.SpriteEffects = !filters.Visible ? SpriteEffects.None : SpriteEffects.FlipHorizontally);
return true;
}
};
filterToggle.Children.ForEach(c => c.SpriteEffects = SpriteEffects.FlipHorizontally);
var filterContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.99f), filters.RectTransform, Anchor.Center))
{
Stretch = true,
RelativeSpacing = 0.015f
};
var filterTitle = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), filterContainer.RectTransform), TextManager.Get("FilterServers"), font: GUI.LargeFont)
{
Padding = Vector4.Zero,
AutoScale = true
};
float elementHeight = 0.05f;
var searchHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, elementHeight), filterContainer.RectTransform), isHorizontal: true) { Stretch = true };
var searchTitle = new GUITextBlock(new RectTransform(new Vector2(0.001f, 1.0f), searchHolder.RectTransform), TextManager.Get("Search") + "...");
searchBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 1.0f), searchHolder.RectTransform), "");
searchBox.OnSelected += (sender, userdata) => { searchTitle.Visible = false; };
searchBox.OnDeselected += (sender, userdata) => { searchTitle.Visible = true; };
searchBox.OnTextChanged += (txtBox, txt) => { FilterServers(); return true; };
var filterHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), filterContainer.RectTransform)) { RelativeSpacing = 0.005f };
List<GUITextBlock> filterTextList = new List<GUITextBlock>();
filterPassword = new GUITickBox(new RectTransform(new Vector2(1.0f, elementHeight), filterHolder.RectTransform), TextManager.Get("FilterPassword"))
{
ToolTip = TextManager.Get("FilterPassword"),
OnSelected = (tickBox) => { FilterServers(); return true; }
};
filterTextList.Add(filterPassword.TextBlock);
filterIncompatible = new GUITickBox(new RectTransform(new Vector2(1.0f, elementHeight), filterHolder.RectTransform), TextManager.Get("FilterIncompatibleServers"))
{
ToolTip = TextManager.Get("FilterIncompatibleServers"),
OnSelected = (tickBox) => { FilterServers(); return true; }
};
filterTextList.Add(filterIncompatible.TextBlock);
filterFull = new GUITickBox(new RectTransform(new Vector2(1.0f, elementHeight), filterHolder.RectTransform), TextManager.Get("FilterFullServers"))
{
ToolTip = TextManager.Get("FilterFullServers"),
OnSelected = (tickBox) => { FilterServers(); return true; }
};
filterTextList.Add(filterFull.TextBlock);
filterEmpty = new GUITickBox(new RectTransform(new Vector2(1.0f, elementHeight), filterHolder.RectTransform), TextManager.Get("FilterEmptyServers"))
{
ToolTip = TextManager.Get("FilterEmptyServers"),
OnSelected = (tickBox) => { FilterServers(); return true; }
};
filterTextList.Add(filterEmpty.TextBlock);
filterContainer.RectTransform.SizeChanged += () =>
{
filterContainer.RectTransform.RecalculateChildren(true, true);
filterTextList.ForEach(t => t.Text = t.ToolTip);
GUITextBlock.AutoScaleAndNormalize(filterTextList);
if (filterTextList[0].TextScale < 0.8f)
{
filterTextList.ForEach(t => t.TextScale = 1.0f);
filterTextList.ForEach(t => t.Text = ToolBox.LimitString(t.Text, t.Font, (int)(filterContainer.Rect.Width * 0.8f)));
}
};
// server list ---------------------------------------------------------------------
var serverListContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), serverListHolder.RectTransform)) { Stretch = true };
labelHolder = new GUILayoutGroup(new RectTransform(new Vector2(0.99f, 0.05f), serverListContainer.RectTransform) { MinSize = new Point(0, 15) },
isHorizontal: true)
{
Stretch = true
};
for (int i = 0; i < columnRelativeWidth.Length; i++)
{
var btn = new GUIButton(new RectTransform(new Vector2(columnRelativeWidth[i], 1.0f), labelHolder.RectTransform),
text: TextManager.Get(columnLabel[i]), textAlignment: Alignment.Center, style: null)
{
Color = new Color(12, 14, 15, 255) * 0.5f,
HoverColor = new Color(12, 14, 15, 255) * 2.5f,
SelectedColor = Color.Gray * 0.7f,
PressedColor = Color.Gray * 0.7f,
OutlineColor = Color.Black,
ToolTip = TextManager.Get(columnLabel[i]),
ForceUpperCase = true,
UserData = columnLabel[i],
OnClicked = SortList
};
labelTexts.Add(btn.TextBlock);
new GUIImage(new RectTransform(new Vector2(0.5f, 0.3f), btn.RectTransform, Anchor.BottomCenter, scaleBasis: ScaleBasis.BothHeight), style: "GUIButtonVerticalArrow", scaleToFit: true)
{
CanBeFocused = false,
UserData = "arrowup",
Visible = false
};
new GUIImage(new RectTransform(new Vector2(0.5f, 0.3f), btn.RectTransform, Anchor.BottomCenter, scaleBasis: ScaleBasis.BothHeight), style: "GUIButtonVerticalArrow", scaleToFit: true)
{
CanBeFocused = false,
UserData = "arrowdown",
SpriteEffects = SpriteEffects.FlipVertically,
Visible = false
};
}
serverList = new GUIListBox(new RectTransform(new Vector2(1.0f, 1.0f), serverListContainer.RectTransform, Anchor.Center))
{
ScrollBarVisible = true,
OnSelected = (btn, obj) =>
{
if (obj is ServerInfo serverInfo)
{
ServerInfo serverInfo = (ServerInfo)obj;
joinButton.Enabled = true;
ipBox.UserData = serverInfo;
ipBox.Text = serverInfo.ServerName;
if (!serverPreview.Visible)
{
serverPreview.RectTransform.RelativeSize = new Vector2(0.3f, 1.0f);
serverPreviewToggleButton.Visible = true;
serverPreviewToggleButton.IgnoreLayoutGroups = false;
serverPreview.Visible = true;
serverPreview.IgnoreLayoutGroups = false;
serverListHolder.Recalculate();
}
serverInfo.CreatePreviewWindow(serverPreview);
btn.Children.ForEach(c => c.SpriteEffects = serverPreview.Visible ? SpriteEffects.None : SpriteEffects.FlipHorizontally);
}
return true;
}
};
serverList.OnSelected += SelectServer;
//server preview panel --------------------------------------------------
serverPreview = new GUIListBox(new RectTransform(new Vector2(1.0f, 1.0f), serverListHolder.RectTransform, Anchor.Center));
serverPreviewToggleButton = new GUIButton(new RectTransform(new Vector2(0.02f, 1.0f), serverListHolder.RectTransform, Anchor.CenterRight) { MinSize = new Point(20, 0) }, style: "UIToggleButton")
{
Visible = false,
OnClicked = (btn, userdata) =>
{
serverPreview.RectTransform.RelativeSize = new Vector2(0.25f, 1.0f);
serverPreview.Visible = !serverPreview.Visible;
serverPreview.IgnoreLayoutGroups = !serverPreview.Visible;
serverListHolder.Recalculate();
btn.Children.ForEach(c => c.SpriteEffects = serverPreview.Visible ? SpriteEffects.None : SpriteEffects.FlipHorizontally);
return true;
}
};
columnRelativeWidth = new float[] { 0.04f, 0.02f, 0.044f, 0.77f, 0.02f, 0.075f, 0.06f };
serverPreview = new GUIFrame(new RectTransform(new Vector2(0.3f, 1.0f), serverListHolder.RectTransform, Anchor.Center), style: null)
{
Color = new Color(12, 14, 15, 255) * 0.5f,
OutlineColor = Color.Black,
IgnoreLayoutGroups = true,
Visible = false
};
var buttonContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.075f), rightColumn.RectTransform), style: null);
// Spacing
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.02f), bottomRow.RectTransform), style: null);
GUIButton button = new GUIButton(new RectTransform(new Vector2(0.25f, 0.9f), buttonContainer.RectTransform, Anchor.TopLeft),
var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.075f), bottomRow.RectTransform, Anchor.Center), isHorizontal: true)
{
RelativeSpacing = 0.02f,
Stretch = true
};
GUIButton button = new GUIButton(new RectTransform(new Vector2(0.25f, 0.9f), buttonContainer.RectTransform),
TextManager.Get("Back"), style: "GUIButtonLarge")
{
OnClicked = GameMain.MainMenuScreen.ReturnToMainMenu
};
refreshButton = new GUIButton(new RectTransform(new Vector2(buttonContainer.Rect.Height / (float)buttonContainer.Rect.Width, 0.9f), buttonContainer.RectTransform, Anchor.Center),
"", style: "GUIButtonRefresh") {
ToolTip = TextManager.Get("ServerListRefresh"),
OnClicked = RefreshServers
new GUIButton(new RectTransform(new Vector2(0.25f, 0.9f), buttonContainer.RectTransform),
TextManager.Get("ServerListRefresh"), style: "GUIButtonLarge")
{
OnClicked = (btn, userdata) => { RefreshServers(); return true; }
};
joinButton = new GUIButton(new RectTransform(new Vector2(0.25f, 0.9f), buttonContainer.RectTransform, Anchor.TopRight),
/*var directJoinButton = new GUIButton(new RectTransform(new Vector2(0.25f, 0.9f), buttonContainer.RectTransform),
TextManager.Get("serverlistdirectjoin"), style: "GUIButtonLarge")
{
OnClicked = (btn, userdata) => { ShowDirectJoinPrompt(); return true; }
};*/
joinButton = new GUIButton(new RectTransform(new Vector2(0.25f, 0.9f), buttonContainer.RectTransform),
TextManager.Get("ServerListJoin"), style: "GUIButtonLarge")
{
OnClicked = JoinServer,
OnClicked = (btn, userdata) =>
{
if (ipBox.UserData is ServerInfo selectedServer)
{
JoinServer(selectedServer.IP + ":" + selectedServer.Port, selectedServer.ServerName);
}
else if (!string.IsNullOrEmpty(ipBox.Text))
{
JoinServer(ipBox.Text, "");
}
return true;
},
Enabled = false
};
//--------------------------------------------------------
button.SelectedColor = button.Color;
bottomRow.Recalculate();
serverListHolder.Recalculate();
serverListContainer.Recalculate();
labelHolder.RectTransform.MaxSize = new Point(serverList.Content.Rect.Width, int.MaxValue);
labelHolder.Recalculate();
serverList.Content.RectTransform.SizeChanged += () =>
{
labelHolder.RectTransform.MaxSize = new Point(serverList.Content.Rect.Width, int.MaxValue);
labelHolder.Recalculate();
foreach (GUITextBlock labelText in labelTexts)
{
labelText.Text = ToolBox.LimitString(labelText.ToolTip, labelText.Font, labelText.Rect.Width);
}
};
button.SelectedColor = button.Color;
refreshDisableTimer = DateTime.Now;
}
private void OnResolutionChanged()
{
menu.RectTransform.MinSize = new Point(GameMain.GraphicsHeight, 0);
labelHolder.RectTransform.MaxSize = new Point(serverList.Content.Rect.Width, int.MaxValue);
foreach (GUITextBlock labelText in labelTexts)
{
labelText.Text = ToolBox.LimitString(labelText.ToolTip, labelText.Font, labelText.Rect.Width);
}
}
private bool SortList(GUIButton button, object obj)
{
if (!(obj is string sortBy)) { return false; }
SortList(sortBy, toggle: true);
return true;
}
private void SortList(string sortBy, bool toggle)
{
GUIButton button = labelHolder.GetChildByUserData(sortBy) as GUIButton;
if (button == null) { return; }
sortedBy = sortBy;
var arrowUp = button.GetChildByUserData("arrowup");
var arrowDown = button.GetChildByUserData("arrowdown");
//disable arrow buttons in other labels
foreach (var child in button.Parent.Children)
{
if (child != button)
{
child.GetChildByUserData("arrowup").Visible = false;
child.GetChildByUserData("arrowdown").Visible = false;
}
}
bool ascending = arrowUp.Visible;
if (toggle)
{
ascending = !ascending;
}
arrowUp.Visible = ascending;
arrowDown.Visible = !ascending;
serverList.Content.RectTransform.SortChildren((c1, c2) =>
{
ServerInfo s1 = c1.GUIComponent.UserData as ServerInfo;
ServerInfo s2 = c2.GUIComponent.UserData as ServerInfo;
switch (sortBy)
{
case "ServerListCompatible":
bool? s1Compatible = NetworkMember.IsCompatible(GameMain.Version.ToString(), s1.GameVersion);
if (!s1.ContentPackageHashes.Any()) { s1Compatible = null; }
if (s1Compatible.HasValue) { s1Compatible = s1Compatible.Value && s1.ContentPackagesMatch(GameMain.SelectedPackages); };
bool? s2Compatible = NetworkMember.IsCompatible(GameMain.Version.ToString(), s2.GameVersion);
if (!s2.ContentPackageHashes.Any()) { s2Compatible = null; }
if (s2Compatible.HasValue) { s2Compatible = s2Compatible.Value && s2.ContentPackagesMatch(GameMain.SelectedPackages); };
//convert to int to make sorting easier
//1 Compatible
//0 Unknown
//-1 Incompatible
int s1CompatibleInt = s1Compatible.HasValue ?
(s1Compatible.Value ? 1 : -1) :
0;
int s2CompatibleInt = s2Compatible.HasValue ?
(s2Compatible.Value ? 1 : -1) :
0;
return s2CompatibleInt.CompareTo(s1CompatibleInt) * (ascending ? 1 : -1);
case "ServerListHasPassword":
if (s1.HasPassword == s2.HasPassword) { return 0; }
return (s1.HasPassword ? 1 : -1) * (ascending ? 1 : -1);
case "ServerListName":
return s1.ServerName.CompareTo(s2.ServerName) * (ascending ? 1 : -1);
case "ServerListRoundStarted":
if (s1.GameStarted == s2.GameStarted) { return 0; }
return (s1.GameStarted ? 1 : -1) * (ascending ? 1 : -1);
case "ServerListPlayers":
return s2.PlayerCount.CompareTo(s1.PlayerCount) * (ascending ? 1 : -1);
case "ServerListPing":
return s2.Ping.CompareTo(s1.Ping) * (ascending ? 1 : -1);
default:
return 0;
}
});
}
public override void Select()
{
base.Select();
RefreshServers(null, null);
RefreshServers();
}
private void FilterServers()
@@ -192,9 +470,15 @@ namespace Barotrauma
if (!(child.UserData is ServerInfo)) continue;
ServerInfo serverInfo = (ServerInfo)child.UserData;
Version remoteVersion = null;
if (!string.IsNullOrEmpty(serverInfo.GameVersion))
{
Version.TryParse(serverInfo.GameVersion, out remoteVersion);
}
bool incompatible =
(!serverInfo.ContentPackageHashes.Any() && serverInfo.ContentPackagesMatch(GameMain.Config.SelectedContentPackages)) ||
(!string.IsNullOrEmpty(serverInfo.GameVersion) && serverInfo.GameVersion != GameMain.Version.ToString());
(remoteVersion != null && !NetworkMember.IsCompatible(GameMain.Version, remoteVersion));
child.Visible =
serverInfo.ServerName.ToLowerInvariant().Contains(searchBox.Text.ToLowerInvariant()) &&
@@ -216,59 +500,48 @@ namespace Barotrauma
serverList.UpdateScrollBarSize();
}
private bool RefreshJoinButtonState(GUIComponent component, object obj)
/*private void ShowDirectJoinPrompt()
{
if (obj == null || waitingForRefresh) { return false; }
var msgBox = new GUIMessageBox(TextManager.Get("ServerListDirectJoin"), "", new string[] { TextManager.Get("OK"), TextManager.Get("Cancel") },
relativeSize: new Vector2(0.25f, 0.2f), minSize: new Point(400, 150));
if (!string.IsNullOrWhiteSpace(clientNameBox.Text) && !string.IsNullOrWhiteSpace(ipBox.Text))
var content = new GUILayoutGroup(new RectTransform(new Vector2(0.8f, 0.3f), msgBox.InnerFrame.RectTransform, Anchor.Center) { MinSize = new Point(0, 50) })
{
joinButton.Enabled = true;
}
else
IgnoreLayoutGroups = true,
Stretch = true,
RelativeSpacing = 0.05f
};
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), content.RectTransform), TextManager.Get("ServerIP"));
var ipBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.5f), content.RectTransform));
var okButton = msgBox.Buttons[0];
okButton.Enabled = false;
okButton.OnClicked = (btn, userdata) =>
{
joinButton.Enabled = false;
}
JoinServer(ipBox.Text, "");
msgBox.Close();
return true;
};
return true;
}
var cancelButton = msgBox.Buttons[1];
cancelButton.OnClicked = msgBox.Close;
private bool SelectServer(GUIComponent component, object obj)
ipBox.OnTextChanged += (textBox, text) =>
{
okButton.Enabled = !string.IsNullOrEmpty(text);
return true;
};
}*/
private void RefreshServers()
{
if (obj == null || waitingForRefresh || (!(obj is ServerInfo))) { return false; }
if (!string.IsNullOrWhiteSpace(clientNameBox.Text))
{
joinButton.Enabled = true;
}
else
{
clientNameBox.Flash();
joinButton.Enabled = false;
}
ServerInfo serverInfo;
try
{
serverInfo = (ServerInfo)obj;
ipBox.UserData = serverInfo;
ipBox.Text = ToolBox.LimitString(serverInfo.ServerName, ipBox.Font, ipBox.Rect.Width);
}
catch (InvalidCastException)
{
return false;
}
return true;
}
private bool RefreshServers(GUIButton button, object obj)
{
if (waitingForRefresh) { return false; }
if (waitingForRefresh) { return; }
serverList.ClearChildren();
serverPreview.ClearChildren();
ipBox.Text = null;
joinButton.Enabled = false;
ipBox.UserData = null;
ipBox.Text = "";
new GUITextBlock(new RectTransform(new Vector2(1.0f, 1.0f), serverList.Content.RectTransform),
TextManager.Get("RefreshingServerList"), textAlignment: Alignment.Center)
@@ -277,8 +550,6 @@ namespace Barotrauma
};
CoroutineManager.StartCoroutine(WaitForRefresh());
return true;
}
private IEnumerable<object> WaitForRefresh()
@@ -392,12 +663,15 @@ namespace Barotrauma
{
UserData = serverInfo
};
var serverContent = new GUILayoutGroup(new RectTransform(new Vector2(0.98f, 1.0f), serverFrame.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft)
new GUILayoutGroup(new RectTransform(new Vector2(0.98f, 1.0f), serverFrame.RectTransform, Anchor.Center), isHorizontal: true, childAnchor: Anchor.CenterLeft)
{
Stretch = true,
RelativeSpacing = 0.02f
//RelativeSpacing = 0.02f
};
UpdateServerInfo(serverInfo);
SortList(sortedBy, toggle: false);
FilterServers();
}
private void UpdateServerInfo(ServerInfo serverInfo)
@@ -405,7 +679,7 @@ namespace Barotrauma
var serverFrame = serverList.Content.FindChild(serverInfo);
if (serverFrame == null) return;
var serverContent = serverFrame.Children.First();
var serverContent = serverFrame.Children.First() as GUILayoutGroup;
serverContent.ClearChildren();
var compatibleBox = new GUITickBox(new RectTransform(new Vector2(columnRelativeWidth[0], 0.9f), serverContent.RectTransform, Anchor.Center), label: "")
@@ -425,21 +699,22 @@ namespace Barotrauma
UserData = "password"
};
var serverName = new GUITextBlock(new RectTransform(new Vector2(columnRelativeWidth[3], 1.0f), serverContent.RectTransform), serverInfo.ServerName, style: "GUIServerListTextBox");
var gameStartedBox = new GUITickBox(new RectTransform(new Vector2(columnRelativeWidth[4], 0.4f), serverContent.RectTransform, Anchor.Center),
label: "", style: "GUIServerListRoundStartedTickBox") {
var serverName = new GUITextBlock(new RectTransform(new Vector2(columnRelativeWidth[2] * 1.1f, 1.0f), serverContent.RectTransform), serverInfo.ServerName, style: "GUIServerListTextBox");
new GUITickBox(new RectTransform(new Vector2(columnRelativeWidth[3], 0.9f), serverContent.RectTransform, Anchor.Center), label: "")
{
ToolTip = TextManager.Get((serverInfo.GameStarted) ? "ServerListRoundStarted" : "ServerListRoundNotStarted"),
Selected = serverInfo.GameStarted,
Enabled = false
};
var serverPlayers = new GUITextBlock(new RectTransform(new Vector2(columnRelativeWidth[5], 1.0f), serverContent.RectTransform),
var serverPlayers = new GUITextBlock(new RectTransform(new Vector2(columnRelativeWidth[4], 1.0f), serverContent.RectTransform),
serverInfo.PlayerCount + "/" + serverInfo.MaxPlayers, style: "GUIServerListTextBox", textAlignment: Alignment.Right)
{
ToolTip = TextManager.Get("ServerListPlayers")
};
var serverPingText = new GUITextBlock(new RectTransform(new Vector2(columnRelativeWidth[6], 1.0f), serverContent.RectTransform), "?",
var serverPingText = new GUITextBlock(new RectTransform(new Vector2(columnRelativeWidth[5], 1.0f), serverContent.RectTransform), "?",
style: "GUIServerListTextBox", textColor: Color.White * 0.5f, textAlignment: Alignment.Right)
{
ToolTip = TextManager.Get("ServerListPing")
@@ -448,6 +723,7 @@ namespace Barotrauma
if (serverInfo.PingChecked)
{
serverPingText.Text = serverInfo.Ping > -1 ? serverInfo.Ping.ToString() : "?";
serverPingText.TextColor = GetPingTextColor(serverInfo.Ping);
}
else if (!string.IsNullOrEmpty(serverInfo.IP))
{
@@ -501,6 +777,8 @@ namespace Barotrauma
serverPlayers.TextColor *= 0.5f;
}
serverContent.Recalculate();
SortList(sortedBy, toggle: false);
FilterServers();
}
@@ -594,37 +872,17 @@ namespace Barotrauma
masterServerResponded = true;
}
private bool JoinServer(GUIButton button, object obj)
private bool JoinServer(string ip, string serverName)
{
if (string.IsNullOrWhiteSpace(clientNameBox.Text))
{
clientNameBox.Flash();
joinButton.Enabled = false;
return false;
}
GameMain.Config.DefaultPlayerName = clientNameBox.Text;
GameMain.Config.SaveNewPlayerConfig();
string ip = null;
string serverName = null;
if (ipBox.UserData is ServerInfo serverInfo)
{
ip = serverInfo.IP + ":" + serverInfo.Port;
serverName = serverInfo.ServerName;
}
else if (!string.IsNullOrWhiteSpace(ipBox.Text))
{
ip = ipBox.Text;
}
if (string.IsNullOrWhiteSpace(ip))
{
ipBox.Flash();
joinButton.Enabled = false;
return false;
}
CoroutineManager.StartCoroutine(ConnectToServer(ip, serverName));
return true;
@@ -671,18 +929,7 @@ namespace Barotrauma
{
if (serverInfo.Ping != -1)
{
if (serverInfo.Ping < 50)
{
serverPingText.TextColor = Color.Green * 1.75f;
}
else if (serverInfo.Ping < 150)
{
serverPingText.TextColor = Color.Yellow * 0.85f;
}
else
{
serverPingText.TextColor = Color.Red * 0.75f;
}
serverPingText.TextColor = GetPingTextColor(serverInfo.Ping);
}
serverPingText.Text = serverInfo.Ping > -1 ? serverInfo.Ping.ToString() : "?";
yield return CoroutineStatus.Success;
@@ -693,6 +940,12 @@ namespace Barotrauma
yield return CoroutineStatus.Success;
}
private Color GetPingTextColor(int ping)
{
if (ping < 0) { return Color.DarkRed; }
return ToolBox.GradientLerp(ping / 200.0f, Color.LightGreen, Color.Yellow * 0.8f, Color.Red * 0.75f);
}
public void PingServer(ServerInfo serverInfo, int timeOut)
{
if (serverInfo?.IP == null)

View File

@@ -755,7 +755,7 @@ namespace Barotrauma
for (int i = 0; i < item.Tags.Length && i < 5; i++)
{
if (string.IsNullOrEmpty(item.Tags[i])) { continue; }
string tag = TextManager.Get("Workshop.ContentTag." + item.Tags[i], true);
string tag = TextManager.Get("Workshop.ContentTag." + item.Tags[i].Replace(" ", ""), true);
if (string.IsNullOrEmpty(tag)) { tag = item.Tags[i].CapitaliseFirstInvariant(); }
tags.Add(tag);
}
@@ -1393,9 +1393,20 @@ namespace Barotrauma
}
else
{
new GUIMessageBox(
TextManager.Get("Error"),
TextManager.GetWithVariable("WorkshopItemPublishFailed", "[itemname]", TextManager.EnsureUTF8(item.Title)) + item.Error);
string errorMsg = item.ErrorCode.HasValue ?
TextManager.Get("WorkshopPublishError." + item.ErrorCode.Value.ToString(), returnNull: true) :
null;
if (errorMsg == null)
{
new GUIMessageBox(
TextManager.Get("Error"),
TextManager.GetWithVariable("WorkshopItemPublishFailed", "[itemname]", TextManager.EnsureUTF8(item.Title)) + item.Error);
}
else
{
new GUIMessageBox(TextManager.Get("Error"), errorMsg);
}
}
createItemFrame.ClearChildren();

View File

@@ -1,3 +0,0 @@
#!/bin/sh
exec mono "./DedicatedServer.exe" "$@"

View File

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

View File

@@ -295,6 +295,8 @@ namespace Barotrauma
CloseServer();
SteamManager.ShutDown();
if (GameSettings.SaveDebugConsoleLogs) DebugConsole.SaveLogs();
if (GameSettings.SendUserStatistics) GameAnalytics.OnQuit();
}

View File

@@ -22,6 +22,7 @@ namespace Barotrauma.Items.Components
public void ServerWrite(NetBuffer msg, Client c, object[] extraData = null)
{
msg.Write(IsActive);
msg.Write(progressTimer);
}
}
}

View File

@@ -23,8 +23,7 @@ namespace Barotrauma.Items.Components
{
ushort wireId = msg.ReadUInt16();
Item wireItem = Entity.FindEntityByID(wireId) as Item;
if (wireItem == null) continue;
if (!(Entity.FindEntityByID(wireId) is Item wireItem)) { continue; }
Wire wireComponent = wireItem.GetComponent<Wire>();
if (wireComponent != null)
@@ -35,13 +34,13 @@ namespace Barotrauma.Items.Components
}
//don't allow rewiring locked panels
if (Locked) return;
if (Locked || !GameMain.NetworkMember.ServerSettings.AllowRewiring) { return; }
item.CreateServerEvent(this);
//check if the character can access this connectionpanel
//and all the wires they're trying to connect
if (!item.CanClientAccess(c)) return;
if (!item.CanClientAccess(c)) { return; }
for (int i = 0; i < Connections.Count; i++)
{
foreach (Wire wire in wires[i])
@@ -50,7 +49,7 @@ namespace Barotrauma.Items.Components
// -> we need to check if the client has access to it
if (!Connections.Any(connection => connection.Wires.Contains(wire)))
{
if (!wire.Item.CanClientAccess(c)) return;
if (!wire.Item.CanClientAccess(c)) { return; }
}
}
}
@@ -62,7 +61,7 @@ namespace Barotrauma.Items.Components
foreach (Wire existingWire in Connections[i].Wires)
{
j++;
if (existingWire == null) continue;
if (existingWire == null) { continue; }
//existing wire not in the list of new wires -> disconnect it
if (!wires[i].Contains(existingWire))
@@ -121,7 +120,7 @@ namespace Barotrauma.Items.Components
foreach (Wire newWire in wires[i])
{
//already connected, no need to do anything
if (Connections[i].Wires.Contains(newWire)) continue;
if (Connections[i].Wires.Contains(newWire)) { continue; }
Connections[i].TryAddLink(newWire);
newWire.Connect(Connections[i], true, true);

View File

@@ -35,7 +35,7 @@ namespace Barotrauma.Networking
public bool CompareTo(string ipCompare)
{
if (string.IsNullOrEmpty(IP)) { return false; }
if (string.IsNullOrEmpty(IP) || string.IsNullOrEmpty(IP)) { return false; }
if (!IsRangeBan)
{
return ipCompare == IP;
@@ -50,7 +50,7 @@ namespace Barotrauma.Networking
public bool CompareTo(IPAddress ipCompare)
{
if (string.IsNullOrEmpty(IP)) { return false; }
if (string.IsNullOrEmpty(IP) || ipCompare == null) { return false; }
if (ipCompare.IsIPv4MappedToIPv6 && CompareTo(ipCompare.MapToIPv4().ToString()))
{
return true;

View File

@@ -97,6 +97,10 @@ namespace Barotrauma.Networking
{
name = name.Replace(":", "");
name = name.Replace(";", "");
if (name.Length > NetConfig.ServerNameMaxLength)
{
name = name.Substring(0, NetConfig.ServerNameMaxLength);
}
this.name = name;
@@ -185,11 +189,7 @@ namespace Barotrauma.Networking
if (SteamManager.USE_STEAM)
{
SteamManager.CreateServer(this, isPublic);
if (isPublic)
{
registeredToMaster = true;
}
registeredToMaster = SteamManager.CreateServer(this, isPublic);
}
if (isPublic && !GameMain.Config.UseSteamMatchmaking)
{
@@ -1084,6 +1084,10 @@ namespace Barotrauma.Networking
Log("Client \"" + sender.Name + "\" kicked \"" + kickedClient.Name + "\".", ServerLog.MessageType.ServerMessage);
KickClient(kickedClient, string.IsNullOrEmpty(kickReason) ? $"ServerMessage.KickedBy~[initiator]={sender.Name}" : kickReason);
}
else
{
SendDirectChatMessage(TextManager.GetServerMessage($"ServerMessage.PlayerNotFound~[player]={kickedName}"), sender, ChatMessageType.Console);
}
break;
case ClientPermissions.Ban:
string bannedName = inc.ReadString().ToLowerInvariant();
@@ -1104,11 +1108,15 @@ namespace Barotrauma.Networking
BanClient(bannedClient, string.IsNullOrEmpty(banReason) ? $"ServerMessage.BannedBy~[initiator]={sender.Name}" : banReason, range);
}
}
else
{
SendDirectChatMessage(TextManager.GetServerMessage($"ServerMessage.PlayerNotFound~[player]={bannedName}"), sender, ChatMessageType.Console);
}
break;
case ClientPermissions.Unban:
string unbannedName = inc.ReadString().ToLowerInvariant();
string unbannedName = inc.ReadString();
string unbannedIP = inc.ReadString();
UnbanPlayer(unbannedIP, unbannedIP);
UnbanPlayer(unbannedName, unbannedIP);
break;
case ClientPermissions.ManageRound:
bool end = inc.ReadBoolean();
@@ -1784,6 +1792,8 @@ namespace Barotrauma.Networking
if (serverSettings.AllowRespawn && missionAllowRespawn) respawnManager = new RespawnManager(this, usingShuttle ? selectedShuttle : null);
entityEventManager.RefreshEntityIDs();
//assign jobs and spawnpoints separately for each team
for (int n = 0; n < teamCount; n++)
{
@@ -1969,6 +1979,7 @@ namespace Barotrauma.Networking
msg.Write(Submarine.MainSubs[1] != null); //loadSecondSub
msg.Write(serverSettings.AllowDisguises);
msg.Write(serverSettings.AllowRewiring);
Traitor traitor = null;
if (TraitorManager != null && TraitorManager.TraitorList.Count > 0)

View File

@@ -339,13 +339,14 @@ namespace Barotrauma.Networking
return;
}
if (clVersion != GameMain.Version.ToString())
bool? isCompatibleVersion = IsCompatible(clVersion, GameMain.Version.ToString());
if (isCompatibleVersion.HasValue && !isCompatibleVersion.Value)
{
DisconnectUnauthClient(inc, unauthClient, DisconnectReason.InvalidVersion,
$"DisconnectMessage.InvalidVersion~[version]={GameMain.Version.ToString()}~[clientversion]={clVersion}");
Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (wrong game version)", ServerLog.MessageType.Error);
DebugConsole.NewMessage(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (wrong game version)", Color.Red);
Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (incompatible game version)", ServerLog.MessageType.Error);
DebugConsole.NewMessage(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (incompatible game version)", Color.Red);
return;
}

View File

@@ -10,7 +10,7 @@ namespace Barotrauma.Networking
class ServerEntityEvent : NetEntityEvent
{
private IServerSerializable serializable;
#if DEBUG
public string StackTrace;
#endif
@@ -21,11 +21,10 @@ namespace Barotrauma.Networking
get { return createTime; }
}
public ServerEntityEvent(IServerSerializable entity, UInt16 id)
: base(entity, id)
public ServerEntityEvent(IServerSerializable serializableEntity, UInt16 id)
: base(serializableEntity, id)
{
serializable = entity;
serializable = serializableEntity;
createTime = Timing.TotalTime;
#if DEBUG
@@ -292,6 +291,11 @@ namespace Barotrauma.Networking
bufferedEvents.Add(bufferedEvent);
}
public void RefreshEntityIDs()
{
events.ForEach(e => e.RefreshEntityID());
uniqueEvents.ForEach(e => e.RefreshEntityID());
}
/// <summary>
/// Writes all the events that the client hasn't received yet into the outgoing message

View File

@@ -12,7 +12,6 @@ namespace Barotrauma.Networking
{
partial class ServerSettings
{
public const string SettingsFile = "serversettings.xml";
public static readonly string ClientPermissionsFile = "Data" + Path.DirectorySeparatorChar + "clientpermissions.xml";
partial void InitProjSpecific()

View File

@@ -1295,15 +1295,6 @@
<Content Include="$(MSBuildThisFileDirectory)Content\Characters\Fractalguardian\fractalguardian.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Characters\Human\damagedhead.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Characters\Human\damagedlegs.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Characters\Human\damagedtorso.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Characters\Human\firstnames_female.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -2174,6 +2165,9 @@
<None Include="$(MSBuildThisFileDirectory)Content\Items\Alien\AlienTurret2.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Items\Command\SonarPingFar.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Items\Misc\GuitarClown.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>

View File

@@ -218,6 +218,35 @@ namespace Barotrauma
if (run || speedMultiplier <= 0.0f) targetMovement *= speedMultiplier;
Character.ResetSpeedMultiplier(); // Reset, items will set the value before the next update
Character.AnimController.TargetMovement = targetMovement;
if (!Character.LockHands)
{
DropUnnecessaryItems();
}
if (Character.IsKeyDown(InputType.Aim))
{
var cursorDiffX = Character.CursorPosition.X - Character.Position.X;
if (cursorDiffX > 10.0f)
{
Character.AnimController.TargetDir = Direction.Right;
}
else if (cursorDiffX < -10.0f)
{
Character.AnimController.TargetDir = Direction.Left;
}
if (Character.SelectedConstruction != null) Character.SelectedConstruction.SecondaryUse(deltaTime, Character);
}
else if (Math.Abs(Character.AnimController.TargetMovement.X) > 0.1f && !Character.AnimController.InWater)
{
Character.AnimController.TargetDir = Character.AnimController.TargetMovement.X > 0.0f ? Direction.Right : Direction.Left;
}
}
private void DropUnnecessaryItems()
{
if (!NeedsDivingGear(Character.CurrentHull))
{
bool oxygenLow = Character.OxygenAvailable < CharacterHealth.LowOxygenThreshold;
@@ -278,26 +307,6 @@ namespace Barotrauma
}
}
}
if (Character.IsKeyDown(InputType.Aim))
{
var cursorDiffX = Character.CursorPosition.X - Character.Position.X;
if (cursorDiffX > 10.0f)
{
Character.AnimController.TargetDir = Direction.Right;
}
else if (cursorDiffX < -10.0f)
{
Character.AnimController.TargetDir = Direction.Left;
}
if (Character.SelectedConstruction != null) Character.SelectedConstruction.SecondaryUse(deltaTime, Character);
}
else if (Math.Abs(Character.AnimController.TargetMovement.X) > 0.1f && !Character.AnimController.InWater)
{
Character.AnimController.TargetDir = Character.AnimController.TargetMovement.X > 0.0f ? Direction.Right : Direction.Left;
}
}
protected void ReportProblems()
@@ -428,16 +437,24 @@ namespace Barotrauma
}
else
{
float currentVitality = Character.CharacterHealth.Vitality;
float dmgPercentage = damage / currentVitality * 100;
if (dmgPercentage < currentVitality / 10)
// If not on the same team, always stay defensive
if (attacker.TeamID != Character.TeamID)
{
// Don't retaliate on minor (accidental) dmg done by friendly characters
AddCombatObjective(AIObjectiveCombat.CombatMode.Retreat, Rand.Range(0.5f, 1f, Rand.RandSync.Unsynced));
AddCombatObjective(AIObjectiveCombat.CombatMode.Defensive, Rand.Range(0.5f, 1f, Rand.RandSync.Unsynced));
}
else
{
AddCombatObjective(AIObjectiveCombat.CombatMode.Defensive, Rand.Range(0.5f, 1f, Rand.RandSync.Unsynced));
float currentVitality = Character.CharacterHealth.Vitality;
float dmgPercentage = damage / currentVitality * 100;
if (dmgPercentage < currentVitality / 10)
{
// Don't retaliate on minor (accidental) dmg done by characters that are in the same team
AddCombatObjective(AIObjectiveCombat.CombatMode.Retreat, Rand.Range(0.5f, 1f, Rand.RandSync.Unsynced));
}
else
{
AddCombatObjective(AIObjectiveCombat.CombatMode.Defensive, Rand.Range(0.5f, 1f, Rand.RandSync.Unsynced));
}
}
}
}
@@ -448,24 +465,25 @@ namespace Barotrauma
void AddCombatObjective(AIObjectiveCombat.CombatMode mode, float delay = 0)
{
bool holdPosition = Character.Info?.Job?.Prefab.Identifier == "watchman";
if (ObjectiveManager.CurrentObjective is AIObjectiveCombat combatObjective)
{
if (combatObjective.Enemy != attacker || (combatObjective.Enemy == null && attacker == null))
{
// Replace the old objective with the new.
ObjectiveManager.Objectives.Remove(combatObjective);
objectiveManager.AddObjective(new AIObjectiveCombat(Character, attacker, mode, objectiveManager));
objectiveManager.AddObjective(new AIObjectiveCombat(Character, attacker, mode, objectiveManager) { HoldPosition = holdPosition});
}
}
else
{
if (delay > 0)
{
objectiveManager.AddObjective(new AIObjectiveCombat(Character, attacker, mode, objectiveManager), delay);
objectiveManager.AddObjective(new AIObjectiveCombat(Character, attacker, mode, objectiveManager) { HoldPosition = holdPosition }, delay);
}
else
{
objectiveManager.AddObjective(new AIObjectiveCombat(Character, attacker, mode, objectiveManager));
objectiveManager.AddObjective(new AIObjectiveCombat(Character, attacker, mode, objectiveManager) { HoldPosition = holdPosition });
}
}
}

View File

@@ -17,7 +17,8 @@ namespace Barotrauma
const float coolDown = 10.0f;
public Character Enemy { get; private set; }
public bool HoldPosition { get; set; }
private Item _weapon;
private Item Weapon
{
@@ -125,7 +126,10 @@ namespace Barotrauma
TryArm();
if (seekAmmunition == null || !subObjectives.Contains(seekAmmunition))
{
Move();
if (!HoldPosition)
{
Move();
}
if (WeaponComponent != null)
{
OperateWeapon(deltaTime);
@@ -151,6 +155,8 @@ namespace Barotrauma
private bool TryArm()
{
if (character.LockHands) { return false; }
if (Weapon != null)
{
if (!character.Inventory.Items.Contains(Weapon) || WeaponComponent == null)
@@ -160,7 +166,7 @@ namespace Barotrauma
else if (!WeaponComponent.HasRequiredContainedItems(false))
{
// Seek ammunition only if cannot find a new weapon
if (!Reload(true, () => GetWeapon(out _) == null))
if (!Reload(!HoldPosition, () => GetWeapon(out _) == null))
{
if (seekAmmunition != null && subObjectives.Contains(seekAmmunition))
{
@@ -266,7 +272,7 @@ namespace Barotrauma
private void Unequip()
{
if (character.SelectedItems.Contains(Weapon))
if (!character.LockHands && character.SelectedItems.Contains(Weapon))
{
if (!Weapon.AllowedSlots.Contains(InvSlotType.Any) || !character.Inventory.TryPutItem(Weapon, character, new List<InvSlotType>() { InvSlotType.Any }))
{
@@ -277,6 +283,7 @@ namespace Barotrauma
private bool Equip()
{
if (character.LockHands) { return false; }
if (!WeaponComponent.HasRequiredContainedItems(false))
{
Mode = CombatMode.Retreat;
@@ -322,6 +329,13 @@ namespace Barotrauma
private void Engage()
{
if (character.LockHands)
{
Mode = CombatMode.Retreat;
SteeringManager.Reset();
return;
}
retreatTarget = null;
RemoveSubObjective(ref retreatObjective);
RemoveSubObjective(ref seekAmmunition);

View File

@@ -186,13 +186,14 @@ namespace Barotrauma
}
}
public Hull FindBestHull(IEnumerable<Hull> ignoredHulls = null)
public Hull FindBestHull(IEnumerable<Hull> ignoredHulls = null, bool allowChangingTheSubmarine = true)
{
Hull bestHull = null;
float bestValue = 0;
foreach (Hull hull in Hull.hullList)
{
if (hull.Submarine == null) { continue; }
if (!allowChangingTheSubmarine && hull.Submarine != character.Submarine) { continue; }
if (ignoredHulls != null && ignoredHulls.Contains(hull)) { continue; }
if (unreachable.Contains(hull)) { continue; }
float hullSafety = 0;

View File

@@ -96,6 +96,12 @@ namespace Barotrauma
protected override void Act(float deltaTime)
{
if (character.LockHands)
{
abandon = true;
return;
}
FindTargetItem();
if (targetItem == null || moveToTarget == null)
{

View File

@@ -37,14 +37,21 @@ namespace Barotrauma
float isSelected = character.SelectedConstruction == Item ? 50 : 0;
float devotion = (Math.Min(Priority, 10) + isSelected) / 100;
float max = MathHelper.Min(AIObjectiveManager.OrderPriority - 1, 90);
bool isCompleted = Item.IsFullCondition;
if (isCompleted && character.SelectedConstruction == Item)
{
character?.Speak(TextManager.GetWithVariable("DialogItemRepaired", "[itemname]", Item.Name, true), null, 0.0f, "itemrepaired", 10.0f);
}
return MathHelper.Lerp(0, max, MathHelper.Clamp(devotion + damagePriority * distanceFactor * successFactor * PriorityModifier, 0, 1));
}
public override bool IsCompleted()
{
bool isCompleted = Item.IsFullCondition;
if (isCompleted)
{
if (isCompleted && character.SelectedConstruction == Item)
{
character?.Speak(TextManager.GetWithVariable("DialogItemRepaired", "[itemname]", Item.Name, true), null, 0.0f, "itemrepaired", 10.0f);
}
return isCompleted;

View File

@@ -97,7 +97,7 @@ namespace Barotrauma
}
else
{
string[] splitOptionNames = translatedOptionNames.Split(',');
string[] splitOptionNames = translatedOptionNames.Split(',', '');
OptionNames = new string[Options.Length];
for (int i = 0; i < Options.Length && i < splitOptionNames.Length; i++)
{

View File

@@ -30,11 +30,13 @@ namespace Barotrauma
[Serialize(0f, true), Editable(-360, 360, ToolTip = "Rotation offset (in degrees) used for animations and widgets. If the sprites in the sheet are in different orientations, use the orientation of the torso for the final version of your character (while editing the character in the editor, you can change the orientation freely).")]
public float SpritesheetOrientation { get; set; }
private float limbScale;
[Serialize(1.0f, true), Editable(MIN_SCALE, MAX_SCALE, DecimalCount = 3)]
public float LimbScale { get; set; }
public float LimbScale { get { return limbScale; } set { limbScale = MathHelper.Clamp(value, MIN_SCALE, MAX_SCALE); } }
private float jointScale;
[Serialize(1.0f, true), Editable(MIN_SCALE, MAX_SCALE, DecimalCount = 3)]
public float JointScale { get; set; }
public float JointScale { get { return jointScale; } set { jointScale = MathHelper.Clamp(value, MIN_SCALE, MAX_SCALE); } }
// Don't show in the editor, because shouldn't be edited in runtime. Requires that the limb scale and the collider sizes are adjusted. TODO: automatize.
[Serialize(1f, false)]
@@ -368,16 +370,18 @@ namespace Barotrauma
#endregion
#if CLIENT
public override void AddToEditor(ParamsEditor editor)
public void AddToEditor(ParamsEditor editor, bool alsoChildren = true)
{
base.AddToEditor(editor);
var subParams = GetAllSubParams();
foreach (var subParam in subParams)
if (alsoChildren)
{
subParam.AddToEditor(editor);
//TODO: divider sprite
new GUIFrame(new RectTransform(new Point(editor.EditorBox.Rect.Width, 10), editor.EditorBox.Content.RectTransform),
style: "ConnectionPanelWire");
var subParams = GetAllSubParams();
foreach (var subParam in subParams)
{
subParam.AddToEditor(editor);
new GUIFrame(new RectTransform(new Point(editor.EditorBox.Rect.Width, 10), editor.EditorBox.Content.RectTransform),
style: null, color: Color.Black);
}
}
}
#endif

View File

@@ -1427,7 +1427,7 @@ namespace Barotrauma
Vector2 rayEnd = rayStart - new Vector2(0.0f, height);
var lowestLimb = FindLowestLimb();
//var lowestLimb = FindLowestLimb();
float closestFraction = 1;
GameMain.World.RayCast((fixture, point, normal, fraction) =>
@@ -1440,7 +1440,7 @@ namespace Barotrauma
break;
case Physics.CollisionPlatform:
Structure platform = fixture.Body.UserData as Structure;
if (IgnorePlatforms || lowestLimb.Position.Y < platform.Rect.Y) return -1;
if (IgnorePlatforms && TargetMovement.Y < -0.5f || Collider.Position.Y < platform.Rect.Y) return -1;
break;
case Physics.CollisionWall:
case Physics.CollisionLevel:

View File

@@ -130,16 +130,20 @@ namespace Barotrauma
{
get
{
if (ViewTarget == null) return AnimController.AimSourcePos;
if (ViewTarget == null) { return AnimController.AimSourcePos; }
Vector2 viewTargetWorldPos = ViewTarget.WorldPosition;
if (ViewTarget is Item targetItem)
{
Turret turret = targetItem.GetComponent<Turret>();
if (turret != null)
{
return new Vector2(targetItem.Rect.X + turret.TransformedBarrelPos.X, targetItem.Rect.Y - turret.TransformedBarrelPos.Y);
viewTargetWorldPos = new Vector2(
targetItem.WorldRect.X + turret.TransformedBarrelPos.X,
targetItem.WorldRect.Y - turret.TransformedBarrelPos.Y);
}
}
return ViewTarget.Position;
return Position + (viewTargetWorldPos - WorldPosition);
}
}
@@ -1517,7 +1521,7 @@ namespace Barotrauma
public bool CanAccessInventory(Inventory inventory)
{
if (!CanInteract) return false;
if (!CanInteract || inventory.Locked) { return false; }
//the inventory belongs to some other character
if (inventory.Owner is Character && inventory.Owner != this)
@@ -1558,7 +1562,11 @@ namespace Barotrauma
{
distanceToItem = -1.0f;
if (!CanInteract || item.HiddenInGame) return false;
bool hidden = item.HiddenInGame;
#if CLIENT
if (Screen.Selected == GameMain.SubEditorScreen) { hidden = false; }
#endif
if (!CanInteract || hidden) return false;
if (item.ParentInventory != null)
{
@@ -1802,7 +1810,7 @@ namespace Barotrauma
{
SelectCharacter(focusedCharacter);
}
else if (focusedCharacter != null && IsKeyHit(InputType.Health) && focusedCharacter.CharacterHealth.UseHealthWindow)
else if (focusedCharacter != null && IsKeyHit(InputType.Health) && focusedCharacter.CharacterHealth.UseHealthWindow && CanInteractWith(focusedCharacter, 160f, false))
{
if (focusedCharacter == SelectedCharacter)
{

View File

@@ -105,7 +105,7 @@ namespace Barotrauma
public static bool CheatsEnabled;
private static List<ColoredText> unsavedMessages = new List<ColoredText>();
private static int messagesPerFile = 800;
private static int messagesPerFile = 5000;
public const string SavePath = "ConsoleLogs";
private static void AssignOnExecute(string names, Action<string[]> onExecute)
@@ -648,6 +648,20 @@ namespace Barotrauma
},null));
#if DEBUG
commands.Add(new Command("teleportsub", "teleportsub [start/end]: Teleport the submarine to the start or end of the level. WARNING: does not take outposts into account, so often leads to physics glitches. Only use for debugging.", (string[] args) =>
{
if (Submarine.MainSub == null || Level.Loaded == null) return;
if (args.Length > 0 && args[0].ToLowerInvariant() == "start")
{
Submarine.MainSub.SetPosition(Level.Loaded.StartPosition);
}
else
{
Submarine.MainSub.SetPosition(Level.Loaded.EndPosition);
}
}, isCheat: true));
commands.Add(new Command("waterphysicsparams", "waterphysicsparams [stiffness] [spread] [damping]: defaults 0.02, 0.05, 0.05", (string[] args) =>
{
Vector2 explosionPos = GameMain.GameScreen.Cam.ScreenToWorld(PlayerInput.MousePosition);
@@ -1582,7 +1596,14 @@ namespace Barotrauma
}
}
string fileName = "DebugConsoleLog_" + DateTime.Now.ToShortDateString() + "_" + DateTime.Now.ToShortTimeString();
string fileName = "DebugConsoleLog_";
#if SERVER
fileName += "Server_";
#else
fileName += "Client_";
#endif
fileName += DateTime.Now.ToShortDateString() + "_" + DateTime.Now.ToShortTimeString();
var invalidChars = Path.GetInvalidFileNameChars();
foreach (char invalidChar in invalidChars)
{

View File

@@ -79,6 +79,7 @@ namespace Barotrauma
public int GetTotalItemCost()
{
if (purchasedItems == null) return 0;
return purchasedItems.Sum(i => i.ItemPrefab.GetPrice(campaign.Map.CurrentLocation).BuyPrice * i.Quantity);
}

View File

@@ -267,7 +267,13 @@ namespace Barotrauma
private static bool sendUserStatistics = true;
public static bool SendUserStatistics
{
get { return sendUserStatistics; }
get
{
#if DEBUG
return false;
#endif
return sendUserStatistics;
}
set
{
sendUserStatistics = value;

View File

@@ -178,29 +178,35 @@ namespace Barotrauma.Items.Components
private void SetUser(Character character)
{
if (user == character) return;
if (user != null && user.Removed) user = null;
if (user == character) { return; }
if (user != null && user.Removed) { user = null; }
user = character;
if (item.body?.FarseerBody == null || item.Removed ||
!GameMain.World.BodyList.Contains(item.body.FarseerBody))
{
return;
}
if (user != null)
{
foreach (Limb limb in user.AnimController.Limbs)
{
if (limb.body.FarseerBody != null)
if (limb.body.FarseerBody != null && GameMain.World.BodyList.Contains(limb.body.FarseerBody))
{
if (GameMain.World.BodyList.Contains(limb.body.FarseerBody))
{
item.body.FarseerBody.RestoreCollisionWith(limb.body.FarseerBody);
}
item.body.FarseerBody.RestoreCollisionWith(limb.body.FarseerBody);
}
}
}
foreach (Limb limb in character.AnimController.Limbs)
{
item.body.FarseerBody.IgnoreCollisionWith(limb.body.FarseerBody);
if (limb.body.FarseerBody != null && GameMain.World.BodyList.Contains(limb.body.FarseerBody))
{
item.body.FarseerBody.IgnoreCollisionWith(limb.body.FarseerBody);
}
}
user = character;
}
private void RestoreCollision()

View File

@@ -21,7 +21,7 @@ namespace Barotrauma.Items.Components
private UsableIn usableIn;
[Serialize(0.0f, false), Editable(MinValueFloat = 0.0f, MaxValueFloat = 1000.0f)]
[Serialize(0.0f, false), Editable(MinValueFloat = -1000.0f, MaxValueFloat = 1000.0f)]
public float Force
{
get { return force; }

View File

@@ -11,6 +11,8 @@ namespace Barotrauma.Items.Components
private float progressTimer;
private float progressState;
private bool hasPower;
private ItemContainer inputContainer, outputContainer;
public ItemContainer InputContainer
@@ -58,7 +60,8 @@ namespace Barotrauma.Items.Components
return;
}
if (voltage < minVoltage) { return; }
hasPower = voltage >= minVoltage;
if (!hasPower) { return; }
var repairable = item.GetComponent<Repairable>();
if (repairable != null)
@@ -68,7 +71,7 @@ namespace Barotrauma.Items.Components
ApplyStatusEffects(ActionType.OnActive, deltaTime, null);
if (powerConsumption == 0.0f) voltage = 1.0f;
if (powerConsumption == 0.0f) { voltage = 1.0f; }
progressTimer += deltaTime * voltage;
Voltage -= deltaTime * 10.0f;
@@ -107,28 +110,41 @@ namespace Barotrauma.Items.Components
}
}
if (targetItem.Prefab.DeconstructItems.Any())
if (GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer)
{
inputContainer.Inventory.RemoveItem(targetItem);
Entity.Spawner.AddToRemoveQueue(targetItem);
MoveInputQueue();
PutItemsToLinkedContainer();
}
else
{
if (outputContainer.Inventory.Items.All(i => i != null))
if (targetItem.Prefab.DeconstructItems.Any())
{
targetItem.Drop(dropper: null);
//drop all items that are inside the deconstructed item
foreach (ItemContainer ic in targetItem.GetComponents<ItemContainer>())
{
if (ic?.Inventory?.Items == null) { continue; }
foreach (Item containedItem in ic.Inventory.Items)
{
containedItem?.Drop(dropper: null, createNetworkEvent: true);
}
}
inputContainer.Inventory.RemoveItem(targetItem);
Entity.Spawner.AddToRemoveQueue(targetItem);
MoveInputQueue();
PutItemsToLinkedContainer();
}
else
{
outputContainer.Inventory.TryPutItem(targetItem, user: null, createNetworkEvent: true);
if (outputContainer.Inventory.Items.All(i => i != null))
{
targetItem.Drop(dropper: null);
}
else
{
outputContainer.Inventory.TryPutItem(targetItem, user: null, createNetworkEvent: true);
}
}
}
if (inputContainer.Inventory.Items.Any(i => i != null))
{
#if SERVER
item.CreateServerEvent(this);
#endif
progressTimer = 0.0f;
progressState = 0.0f;
}
}
@@ -188,21 +204,17 @@ namespace Barotrauma.Items.Components
}
#endif
if (!IsActive) { progressState = 0.0f; }
#if CLIENT
if (!IsActive)
{
progressTimer = 0.0f;
activateButton.Text = TextManager.Get("DeconstructorDeconstruct");
}
else
{
activateButton.Text = TextManager.Get("DeconstructorCancel");
progressState = 0.0f;
}
#if CLIENT
activateButton.Text = TextManager.Get(IsActive ? "DeconstructorCancel" : "DeconstructorDeconstruct");
#endif
inputContainer.Inventory.Locked = IsActive;
inputContainer.Inventory.Locked = IsActive;
}
}
}

View File

@@ -19,6 +19,8 @@ namespace Barotrauma.Items.Components
private float timeUntilReady;
private float requiredTime;
private bool hasPower;
private Character user;
private ItemContainer inputContainer, outputContainer;
@@ -198,8 +200,9 @@ namespace Barotrauma.Items.Components
progressState = fabricatedItem == null ? 0.0f : (requiredTime - timeUntilReady) / requiredTime;
if (voltage < minVoltage) { return; }
hasPower = voltage >= minVoltage;
if (!hasPower) { return; }
var repairable = item.GetComponent<Repairable>();
if (repairable != null)
{
@@ -215,43 +218,50 @@ namespace Barotrauma.Items.Components
if (timeUntilReady > 0.0f) { return; }
var availableIngredients = GetAvailableIngredients();
foreach (FabricationRecipe.RequiredItem ingredient in fabricatedItem.RequiredItems)
if (GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer)
{
for (int i = 0; i < ingredient.Amount; i++)
var availableIngredients = GetAvailableIngredients();
foreach (FabricationRecipe.RequiredItem ingredient in fabricatedItem.RequiredItems)
{
var requiredItem = inputContainer.Inventory.Items.FirstOrDefault(it => it != null && it.Prefab == ingredient.ItemPrefab && it.Condition >= ingredient.ItemPrefab.Health * ingredient.MinCondition);
if (requiredItem == null) continue;
//Item4 = use condition bool
if (ingredient.UseCondition && requiredItem.Condition - ingredient.ItemPrefab.Health * ingredient.MinCondition > 0.0f) //Leave it behind with reduced condition if it has enough to stay above 0
for (int i = 0; i < ingredient.Amount; i++)
{
requiredItem.Condition -= ingredient.ItemPrefab.Health * ingredient.MinCondition;
continue;
var availableItem = availableIngredients.FirstOrDefault(it => it != null && it.Prefab == ingredient.ItemPrefab && it.Condition >= ingredient.ItemPrefab.Health * ingredient.MinCondition);
if (availableItem == null) { continue; }
//Item4 = use condition bool
if (ingredient.UseCondition && availableItem.Condition - ingredient.ItemPrefab.Health * ingredient.MinCondition > 0.0f) //Leave it behind with reduced condition if it has enough to stay above 0
{
availableItem.Condition -= ingredient.ItemPrefab.Health * ingredient.MinCondition;
continue;
}
availableIngredients.Remove(availableItem);
Entity.Spawner.AddToRemoveQueue(availableItem);
inputContainer.Inventory.RemoveItem(availableItem);
}
Entity.Spawner.AddToRemoveQueue(requiredItem);
inputContainer.Inventory.RemoveItem(requiredItem);
}
}
if (outputContainer.Inventory.Items.All(i => i != null))
{
Entity.Spawner.AddToSpawnQueue(fabricatedItem.TargetItem, item.Position, item.Submarine, fabricatedItem.TargetItem.Health * fabricatedItem.OutCondition);
}
else
{
Entity.Spawner.AddToSpawnQueue(fabricatedItem.TargetItem, outputContainer.Inventory, fabricatedItem.TargetItem.Health * fabricatedItem.OutCondition);
}
if ((GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer) && user != null && !user.Removed)
{
foreach (Skill skill in fabricatedItem.RequiredSkills)
if (outputContainer.Inventory.Items.All(i => i != null))
{
user.Info.IncreaseSkillLevel(skill.Identifier, skill.Level / 100.0f * SkillIncreaseMultiplier, user.WorldPosition + Vector2.UnitY * 150.0f);
Entity.Spawner.AddToSpawnQueue(fabricatedItem.TargetItem, item.Position, item.Submarine, fabricatedItem.TargetItem.Health * fabricatedItem.OutCondition);
}
else
{
Entity.Spawner.AddToSpawnQueue(fabricatedItem.TargetItem, outputContainer.Inventory, fabricatedItem.TargetItem.Health * fabricatedItem.OutCondition);
}
if (user != null && !user.Removed)
{
foreach (Skill skill in fabricatedItem.RequiredSkills)
{
user.Info.IncreaseSkillLevel(skill.Identifier, skill.Level / 100.0f * SkillIncreaseMultiplier, user.WorldPosition + Vector2.UnitY * 150.0f);
}
}
}
CancelFabricating(null);
CancelFabricating(null);
#if SERVER
item.CreateServerEvent(this);
#endif
}
}
private bool CanBeFabricated(FabricationRecipe fabricableItem)
@@ -328,6 +338,8 @@ namespace Barotrauma.Items.Components
{
var matchingItem = availableIngredients.Find(it => !usedItems.Contains(it) && IsItemValidIngredient(it, requiredItem));
if (matchingItem == null) { continue; }
availableIngredients.Remove(matchingItem);
if (matchingItem.ParentInventory == inputContainer.Inventory)
{

View File

@@ -254,15 +254,19 @@ namespace Barotrauma.Items.Components
{
foreach (Connection connection in connections)
{
if (!connection.IsPower) continue;
if (!connection.IsPower) { continue; }
foreach (Connection recipient in connection.Recipients)
{
if (!(recipient.Item is Item it)) continue;
if (!(recipient.Item is Item it)) { continue; }
PowerTransfer pt = it.GetComponent<PowerTransfer>();
if (pt == null) continue;
if (pt == null) { continue; }
load = Math.Max(load, pt.PowerLoad);
//calculate how much external power there is in the grid
//(power coming from somewhere else than this reactor, e.g. batteries)
float externalPower = CurrPowerConsumption - pt.CurrPowerConsumption;
//reduce the external power from the load to prevent overloading the grid
load = Math.Max(load, pt.PowerLoad - externalPower);
}
}
}

View File

@@ -176,7 +176,7 @@ namespace Barotrauma.Items.Components
float successFactor = requiredSkills.Count == 0 ? 1.0f : 0.0f;
//item must have been below 50% condition for the player to get an achievement or XP for repairing it
//item must have been below the repair threshold for the player to get an achievement or XP for repairing it
if (item.Condition < ShowRepairUIThreshold)
{
wasBroken = true;

View File

@@ -61,6 +61,7 @@ namespace Barotrauma.Items.Components
{
get
{
if (GameMain.NetworkMember?.ServerSettings != null && !GameMain.NetworkMember.ServerSettings.AllowRewiring) { return false; }
return locked || connections.Any(c => c != null && c.ConnectionPanel.Locked);
}
set { locked = value; }

View File

@@ -152,13 +152,12 @@ namespace Barotrauma
get { return description ?? prefab.Description; }
set { description = value; }
}
private bool hiddenInGame;
[Editable, Serialize(false, true)]
public bool HiddenInGame
{
get { return hiddenInGame; }
set { hiddenInGame = value; }
get;
set;
}
public float ImpactTolerance
@@ -262,7 +261,26 @@ namespace Barotrauma
/// </summary>
public string ContainerIdentifier
{
get { return Container?.prefab.Identifier ?? ""; }
get
{
return
Container?.prefab.Identifier ??
ParentInventory?.Owner?.ToString() ??
"";
}
set { /*do nothing*/ }
}
[Serialize(false, false)]
/// <summary>
/// Can be used by status effects or conditionals to check if the physics body of the item is active
/// </summary>
public bool PhysicsBodyActive
{
get
{
return body != null && body.Enabled;
}
set { /*do nothing*/ }
}
@@ -315,7 +333,7 @@ namespace Barotrauma
get { return spriteColor; }
}
public bool IsFullCondition => Condition >= MaxCondition;
public bool IsFullCondition => MathUtils.NearlyEqual(Condition, MaxCondition);
public float MaxCondition => Prefab.Health;
public float ConditionPercentage => MathUtils.Percentage(Condition, MaxCondition);
@@ -334,6 +352,8 @@ namespace Barotrauma
if (Indestructible) return;
float prev = condition;
bool wasInFullCondition = IsFullCondition;
condition = MathHelper.Clamp(value, 0.0f, Prefab.Health);
if (condition == 0.0f && prev > 0.0f)
{
@@ -349,9 +369,17 @@ namespace Barotrauma
SetActiveSprite();
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer && !MathUtils.NearlyEqual(lastSentCondition, condition))
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer)
{
if (Math.Abs(lastSentCondition - condition) > 1.0f || condition == 0.0f || condition == Prefab.Health)
if (Math.Abs(lastSentCondition - condition) > 1.0f)
{
conditionUpdatePending = true;
}
else if (wasInFullCondition != IsFullCondition)
{
conditionUpdatePending = true;
}
else if (!MathUtils.NearlyEqual(lastSentCondition, condition) && (condition <= 0.0f || condition >= Prefab.Health))
{
conditionUpdatePending = true;
}
@@ -2086,11 +2114,13 @@ namespace Barotrauma
System.Diagnostics.Debug.Assert(Submarine != null || rootContainer.ParentInventory?.Owner is Character);
Vector2 subPosition = Submarine == null ? Vector2.Zero : Submarine.HiddenSubPosition;
int width = ResizeHorizontal ? rect.Width : defaultRect.Width;
int height = ResizeVertical ? rect.Height : defaultRect.Height;
element.Add(new XAttribute("rect",
(int)(rect.X - subPosition.X) + "," +
(int)(rect.Y - subPosition.Y) + "," +
defaultRect.Width + "," + defaultRect.Height));
width + "," + height));
if (linkedTo != null && linkedTo.Count > 0)
{

View File

@@ -17,7 +17,8 @@ namespace Barotrauma
}
public bool IsOptional { get; set; }
public bool MatchOnEmpty { get; set; }
public bool IgnoreInEditor { get; set; }
private string[] excludedIdentifiers;
@@ -99,6 +100,11 @@ namespace Barotrauma
var containedItems = parentItem.ContainedItems;
if (containedItems == null) return false;
if (MatchOnEmpty && !containedItems.Any(ci => ci != null))
{
return true;
}
foreach (Item contained in containedItems)
{
if (contained.Condition > 0.0f && MatchesItem(contained)) return true;
@@ -222,6 +228,7 @@ namespace Barotrauma
ri.IsOptional = element.GetAttributeBool("optional", false);
ri.IgnoreInEditor = element.GetAttributeBool("ignoreineditor", false);
ri.MatchOnEmpty = element.GetAttributeBool("matchonempty", false);
return ri;
}
}

View File

@@ -627,7 +627,8 @@ namespace Barotrauma
if (IsHorizontal)
{
if (Math.Max(hull1.Surface + hull1.WaveY[hull1.WaveY.Length - 1], hull2.Surface + hull2.WaveY[0]) > rect.Y) return;
//if the water level is above the gap, oxygen doesn't circulate
if (Math.Max(hull1.WorldSurface + hull1.WaveY[hull1.WaveY.Length - 1], hull2.WorldSurface + hull2.WaveY[0]) > WorldRect.Y) { return; }
}
float totalOxygen = hull1.Oxygen + hull2.Oxygen;

View File

@@ -1548,13 +1548,13 @@ namespace Barotrauma
Point? minSize = null;
DockingPort subPort = null;
float closestDistance = float.MaxValue;
if (Submarine.MainSub != null)
{
Point subSize = Submarine.MainSub.GetDockedBorders().Size;
Point outpostSize = outpost.GetDockedBorders().Size;
minSize = new Point(Math.Max(subSize.X, outpostSize.X), subSize.Y + outpostSize.Y);
float closestDistance = float.MaxValue;
foreach (DockingPort port in DockingPort.List)
{
if (port.IsHorizontal || port.Docked) { continue; }
@@ -1570,17 +1570,43 @@ namespace Barotrauma
}
}
DockingPort outpostPort = null;
closestDistance = float.MaxValue;
foreach (DockingPort port in DockingPort.List)
{
if (port.IsHorizontal || port.Docked) { continue; }
if (port.Item.Submarine != outpost) { continue; }
//the outpost port has to be at the bottom of the outpost
if (port.Item.WorldPosition.Y > outpost.WorldPosition.Y) { continue; }
float dist = Math.Abs(port.Item.WorldPosition.X - outpost.WorldPosition.X);
if (dist < closestDistance)
{
outpostPort = port;
closestDistance = dist;
}
}
float subDockingPortOffset = subPort == null ? 0.0f : subPort.Item.WorldPosition.X - Submarine.MainSub.WorldPosition.X;
//don't try to compensate if the port is very far from the sub's center of mass
if (Math.Abs(subDockingPortOffset) > 2000.0f)
if (Math.Abs(subDockingPortOffset) > 5000.0f)
{
subDockingPortOffset = MathHelper.Clamp(subDockingPortOffset, -2000.0f, 2000.0f);
subDockingPortOffset = MathHelper.Clamp(subDockingPortOffset, -5000.0f, 5000.0f);
string warningMsg = "Docking port very far from the sub's center of mass (submarine: " + Submarine.MainSub.Name + ", dist: " + subDockingPortOffset + "). The level generator may not be able to place the outpost so that docking is possible.";
DebugConsole.NewMessage(warningMsg, Color.Orange);
GameAnalyticsManager.AddErrorEventOnce("Lever.CreateOutposts:DockingPortVeryFar" + Submarine.MainSub.Name, GameAnalyticsSDK.Net.EGAErrorSeverity.Warning, warningMsg);
}
outpost.SetPosition(outpost.FindSpawnPos(i == 0 ? StartPosition : EndPosition, minSize, subDockingPortOffset));
float outpostDockingPortOffset = subPort == null ? 0.0f : outpostPort.Item.WorldPosition.X - outpost.WorldPosition.X;
//don't try to compensate if the port is very far from the outpost's center of mass
if (Math.Abs(outpostDockingPortOffset) > 5000.0f)
{
outpostDockingPortOffset = MathHelper.Clamp(outpostDockingPortOffset, -5000.0f, 5000.0f);
string warningMsg = "Docking port very far from the outpost's center of mass (outpost: " + outpost.Name + ", dist: " + outpostDockingPortOffset + "). The level generator may not be able to place the outpost so that docking is possible.";
DebugConsole.NewMessage(warningMsg, Color.Orange);
GameAnalyticsManager.AddErrorEventOnce("Lever.CreateOutposts:OutpostDockingPortVeryFar" + outpost.Name, GameAnalyticsSDK.Net.EGAErrorSeverity.Warning, warningMsg);
}
outpost.SetPosition(outpost.FindSpawnPos(i == 0 ? StartPosition : EndPosition, minSize, subDockingPortOffset - outpostDockingPortOffset));
if ((i == 0) == !Mirrored)
{
StartOutpost = outpost;

View File

@@ -308,18 +308,24 @@ namespace Barotrauma
if (ResizeHorizontal) placeSize.X = position.X - placePosition.X;
if (ResizeVertical) placeSize.Y = placePosition.Y - position.Y;
newRect = Submarine.AbsRect(placePosition, placeSize);
if (PlayerInput.LeftButtonReleased())
//don't allow resizing width/height to less than the grid size
if (ResizeHorizontal && Math.Abs(placeSize.X) < Submarine.GridSize.X)
{
//don't allow resizing width/height to zero
if ((!ResizeHorizontal || placeSize.X != 0.0f) && (!ResizeVertical || placeSize.Y != 0.0f))
{
newRect.Location -= MathUtils.ToPoint(Submarine.MainSub.Position);
placeSize.X = Submarine.GridSize.X;
}
if (ResizeVertical && Math.Abs(placeSize.Y) < Submarine.GridSize.Y)
{
placeSize.X = Submarine.GridSize.Y;
}
var structure = new Structure(newRect, this, Submarine.MainSub);
structure.Submarine = Submarine.MainSub;
}
newRect = Submarine.AbsRect(placePosition, placeSize);
if (PlayerInput.LeftButtonReleased())
{
newRect.Location -= MathUtils.ToPoint(Submarine.MainSub.Position);
var structure = new Structure(newRect, this, Submarine.MainSub)
{
Submarine = Submarine.MainSub
};
selected = null;
return;

View File

@@ -297,6 +297,12 @@ namespace Barotrauma
}
}
public bool IsFileCorrupted
{
get;
private set;
}
//constructors & generation ----------------------------------------------------
public Submarine(string filePath, string hash = "", bool tryLoad = true) : base(null)
@@ -322,12 +328,17 @@ namespace Barotrauma
int maxLoadRetries = 4;
for (int i = 0; i <= maxLoadRetries; i++)
{
doc = OpenFile(filePath);
doc = OpenFile(filePath, out Exception e);
if (e != null && !(e is IOException)) { break; }
if (doc != null || i == maxLoadRetries || !File.Exists(filePath)) { break; }
DebugConsole.NewMessage("Opening submarine file \"" + filePath + "\" failed, retrying in 250 ms...");
Thread.Sleep(250);
}
if (doc == null || doc.Root == null) { return; }
if (doc == null || doc.Root == null)
{
IsFileCorrupted = true;
return;
}
if (doc != null && doc.Root != null)
{
@@ -1139,7 +1150,11 @@ namespace Barotrauma
savedSubmarines[i].Dispose();
}
}
savedSubmarines.Add(new Submarine(filePath));
var sub = new Submarine(filePath);
if (!sub.IsFileCorrupted)
{
savedSubmarines.Add(sub);
}
savedSubmarines = savedSubmarines.OrderBy(s => s.filePath ?? "").ToList();
}
@@ -1193,16 +1208,26 @@ namespace Barotrauma
foreach (string path in filePaths)
{
savedSubmarines.Add(new Submarine(path));
var sub = new Submarine(path);
if (!sub.IsFileCorrupted)
{
savedSubmarines.Add(sub);
}
}
}
static readonly string TempFolder = Path.Combine("Submarine", "Temp");
public static XDocument OpenFile(string file)
{
return OpenFile(file, out _);
}
public static XDocument OpenFile(string file, out Exception exception)
{
XDocument doc = null;
string extension = "";
exception = null;
try
{
@@ -1229,6 +1254,7 @@ namespace Barotrauma
}
catch (Exception e)
{
exception = e;
DebugConsole.ThrowError("Loading submarine \"" + file + "\" failed!", e);
return null;
}
@@ -1243,6 +1269,7 @@ namespace Barotrauma
catch (Exception e)
{
exception = e;
DebugConsole.ThrowError("Loading submarine \"" + file + "\" failed! (" + e.Message + ")");
return null;
}
@@ -1257,6 +1284,7 @@ namespace Barotrauma
catch (Exception e)
{
exception = e;
DebugConsole.ThrowError("Loading submarine \"" + file + "\" failed! (" + e.Message + ")");
return null;
}

View File

@@ -10,6 +10,8 @@ namespace Barotrauma.Networking
public const int MaxPlayers = 16;
public const int ServerNameMaxLength = 60;
public static string MasterServerUrl = GameMain.Config.MasterServerUrl;
//if a Character is further than this from the sub and the players, the server will disable it

View File

@@ -21,16 +21,28 @@ namespace Barotrauma.Networking
public readonly Entity Entity;
public readonly UInt16 ID;
public UInt16 EntityID
{
get;
private set;
}
//arbitrary extra data that will be passed to the Write method of the serializable entity
//(the index of an itemcomponent for example)
protected object[] Data;
public bool Sent;
protected NetEntityEvent(INetSerializable entity, UInt16 id)
protected NetEntityEvent(INetSerializable serializableEntity, UInt16 id)
{
this.ID = id;
this.Entity = entity as Entity;
this.Entity = serializableEntity as Entity;
RefreshEntityID();
}
public void RefreshEntityID()
{
this.EntityID = this.Entity is Entity entity ? entity.ID : Entity.NullEntityID;
}
public void SetData(object[] data)

View File

@@ -65,7 +65,7 @@ namespace Barotrauma.Networking
break;
}
tempBuffer.Write((UInt16)e.Entity.ID);
tempBuffer.Write(e.EntityID);
tempBuffer.Write((byte)tempEventBuffer.LengthBytes);
tempBuffer.Write(tempEventBuffer);
tempBuffer.WritePadBits();

View File

@@ -241,6 +241,32 @@ namespace Barotrauma.Networking
public virtual void Update(float deltaTime) { }
public virtual void Disconnect() { }
}
/// <summary>
/// Check if the two version are compatible (= if they can play together in multiplayer).
/// Returns null if compatibility could not be determined (invalid/unknown version number).
/// </summary>
public static bool? IsCompatible(string myVersion, string remoteVersion)
{
if (string.IsNullOrEmpty(myVersion) || string.IsNullOrEmpty(remoteVersion)) { return null; }
if (!Version.TryParse(myVersion, out Version myVersionNumber)) { return null; }
if (!Version.TryParse(remoteVersion, out Version remoteVersionNumber)) { return null; }
return IsCompatible(myVersionNumber, remoteVersionNumber);
}
/// <summary>
/// Check if the two version are compatible (= if they can play together in multiplayer).
/// </summary>
public static bool IsCompatible(Version myVersion, Version remoteVersion)
{
//major.minor.build.revision
//revision number is ignored, other values have to match
return
myVersion.Major == remoteVersion.Major &&
myVersion.Minor == remoteVersion.Minor &&
myVersion.Build == remoteVersion.Build;
}
}
}

View File

@@ -31,6 +31,8 @@ namespace Barotrauma.Networking
partial class ServerSettings : ISerializableEntity
{
public const string SettingsFile = "serversettings.xml";
[Flags]
public enum NetFlags : byte
{
@@ -539,7 +541,14 @@ namespace Barotrauma.Networking
get;
set;
}
[Serialize(true, true)]
public bool AllowRewiring
{
get;
set;
}
private YesNoMaybe traitorsEnabled;
public YesNoMaybe TraitorsEnabled
{

View File

@@ -21,7 +21,11 @@ namespace Barotrauma.Steam
{ "monster", 8 },
{ "art", 8 },
{ "mission", 8 },
{ "environment", 5 }
{ "event set", 8 },
{ "total conversion", 5 },
{ "environment", 5 },
{ "item assembly", 5 },
{ "language", 5 }
};
private List<string> popularTags = new List<string>();

View File

@@ -375,7 +375,7 @@ namespace Barotrauma
//Enum.TryParse(element.GetAttributeString("bodytype", "Dynamic"), out BodyType bodyType);
body.BodyType = BodyType.Dynamic;
body.CollisionCategories = Physics.CollisionItem;
body.CollidesWith = Physics.CollisionWall | Physics.CollisionLevel;
body.CollidesWith = Physics.CollisionWall | Physics.CollisionLevel | Physics.CollisionPlatform;
body.Friction = element.GetAttributeFloat("friction", 0.3f);
body.Restitution = element.GetAttributeFloat("restitution", 0.05f);
body.UserData = this;

View File

@@ -414,9 +414,6 @@ namespace Barotrauma
{
switch (Name)
{
case "Condition":
if (parentObject is Item item) { return item.Condition; }
break;
case "Voltage":
if (parentObject is Powered powered) { return powered.Voltage; }
break;
@@ -460,6 +457,21 @@ namespace Barotrauma
case "IsOn":
{ if (parentObject is LightComponent lightComponent) { return lightComponent.IsOn; } }
break;
case "Condition":
{
if (parentObject is Item item) { return item.Condition; }
}
break;
case "ContainerIdentifier":
{
if (parentObject is Item item) { return item.ContainerIdentifier; }
}
break;
case "PhysicsBodyActive":
{
if (parentObject is Item item) { return item.PhysicsBodyActive; }
}
break;
}
return null;

View File

@@ -114,7 +114,7 @@ namespace Barotrauma
string stringValue = element.Attribute(name).Value;
if (string.IsNullOrEmpty(stringValue)) return defaultValue;
string[] splitValue = stringValue.Split(',');
string[] splitValue = stringValue.Split(',', '');
if (convertToLowerInvariant)
{

View File

@@ -277,7 +277,7 @@ namespace Barotrauma
case OperatorType.Equals:
if (type == typeof(bool))
{
return ((bool)propertyValue) == (AttributeValue == "true");
return ((bool)propertyValue) == (AttributeValue == "true" || AttributeValue == "True");
}
else if (FloatValue == null)
{
@@ -290,7 +290,7 @@ namespace Barotrauma
case OperatorType.NotEquals:
if (type == typeof(bool))
{
return ((bool)propertyValue) != (AttributeValue == "true");
return ((bool)propertyValue) != (AttributeValue == "true" || AttributeValue == "True");
}
else if (FloatValue == null)
{

View File

@@ -424,6 +424,7 @@ namespace Barotrauma
public virtual bool HasRequiredConditions(List<ISerializableEntity> targets)
{
if (!propertyConditionals.Any()) return true;
if (requiredItems.All(ri => ri.MatchOnEmpty) && targets.Count == 0) return true;
switch (conditionalComparison)
{
case PropertyConditional.Comparison.Or:

View File

@@ -145,7 +145,7 @@ namespace Barotrauma
UnlockAchievement(c, "clowncostume");
}
if (Submarine.MainSub != null && c.Submarine == null)
if (Submarine.MainSub != null && c.Submarine == null && c.ConfigPath == Character.HumanConfigFile)
{
float dist = 500 / Physics.DisplayToRealWorldRatio;
if (Vector2.DistanceSquared(c.WorldPosition, Submarine.MainSub.WorldPosition) >

View File

@@ -322,6 +322,8 @@ namespace Barotrauma
string[] messages = serverMessage.Split('/');
bool translationsFound = false;
try
{
for (int i = 0; i < messages.Length; i++)
@@ -333,6 +335,7 @@ namespace Barotrauma
if (msg != null) // If a translation was found, otherwise use the original
{
messages[i] = msg;
translationsFound = true;
}
}
else
@@ -343,6 +346,7 @@ namespace Barotrauma
if (msg != null) // If a translation was found, otherwise use the original
{
messages[i] = msg;
translationsFound = true;
}
else
{
@@ -358,12 +362,19 @@ namespace Barotrauma
}
}
string translatedServerMessage = string.Empty;
for (int i = 0; i < messages.Length; i++)
if (translationsFound)
{
translatedServerMessage += messages[i];
string translatedServerMessage = string.Empty;
for (int i = 0; i < messages.Length; i++)
{
translatedServerMessage += messages[i];
}
return translatedServerMessage;
}
else
{
return serverMessage;
}
return translatedServerMessage;
}
catch (IndexOutOfRangeException exception)

View File

@@ -1,3 +1,110 @@
---------------------------------------------------------------------------------------------------------
v0.9.1.0
---------------------------------------------------------------------------------------------------------
Additions and changes:
- Disabled riot shields for now (too much griefing potential).
- Toolboxes can be fabricated and decontructed.
- Nerfed nitroglycerin's structure damage and increased the impact tolerance from 4 to 6.
- Made alien pistols a little less underwhelming (sounds, recoil, particle effects).
- Deconstructors drop all items that are inside the deconstructed item. Previously they would just get destroyed,
making it a potential exploit to destroy items that should not be possible to deconstruct.
- Modified welding fuel tank and oxygen tank sprites a bit to differentiate them from each other a bit more.
- Modified plasma cutter and welding tool sprites a bit to differentiate them from each other a bit more.
- Diving suits play the warning beep when there's no tank in the suit (not just when the tank is running out).
- Server list can be sorted according to ping, name, compatibility or any of the other property in the list.
- Docking ports of the enemy submarine are not shown on the sonar during combat missions.
- Recharge headset batteries between rounds in single player.
- Disable status monitor displays when out of power.
- Reduce server CPU usage.
- Update ladder and gap references if a waypoint is moved around in the editor.
- More descriptive error messages when publishing a Workshop item fails.
- Allow selecting multiple files at once when adding files to a Workshop item.
- Made the autogenerated submarine preview pictures larger.
- The "Host server" menu remembers the previously used port numbers and the player count.
- Restrict server names to a maximum of 60 characters.
- Items now collide with platforms.
- The game automatically opens the generated crash report when it crashes.
- Added "setmaxplayers" command to the dedicated server.
- Clients can change the server password using the command "setpassword" if they have a permission from the host.
- Reduced the range of the sonar ping sound and added a more subtle ping sound that can be heard further away.
- Watchmen now hold position when attacked.
- Added a subtle glow to alien buttons to make them a bit more noticeable.
- Items that are set to be hidden in-game can still be interacted with in the sub editor.
- EXPERIMENTAL: option to disable rewiring items in multiplayer. At the moment the setting can only be
changed by editing a parameter called "allowrewiring" in serversettings.xml.
Misc bugfixes:
- Fixed the position of an outpost's docking port not being taken into account when determining how to
place it in the level. Caused large submarines sometimes to collide with walls when docked to outposts
where the port is offset from the center.
- Fixed corrupted sub files causing crashes.
- Fixed item editing HUD not appearing on any other item after one item has been selected in-game
(e.g. editing the channel on a wifi component prevented editing other items).
- Fixed ladders and other resizeable items reverting to their original size if they're resized and
the sub is saved and reloaded.
- Fixed inability to resize gaps in the sub editor after they've been placed.
- Reactors take other power sources into account when calculating how much power they need to generate.
Fixes overloads on Humpback when turning on the backup batteries and operating the reactor normally.
- Fixed watchmen not retaliating when a character does very small amounts of damage to them.
- Fixed bots being able to take handcuffs off from themselves.
- Fixed waypoint and spawnpoints being selectable in the sub editor even if they're hidden.
- Fixed deconstructing coilgun ammo boxes giving out more materials than the materials required to fabricate them.
- Scrollbars can only be dragged if the mouse button is pressed down while the cursor is on the scrollbar,
not by holding the button and moving it on the scrollbar. Fixes accidentally switching from slider
to another (often happens in the reactor interface).
- Fixed crashing when setting limb or joint scale to 0 using console commands.
- Fixed dropdowns in the Workshop item publish menu being draw behind the buttons below them.
- Fixes bots being unable to exit ladders if some part of their body is below the platform.
- Ignore keyboard inputs (delete, arrow keys, copy/paste) in the sub editor when a textbox is selected.
Prevents accidentally deleting items/structures when attempting to delete text from a textbox.
- Toolboxes can't be put inside other toolboxes or in the doctor's clothes.
- Fixed items bought from the store during a singleplayer campaign session being deducted from the credits
when save & quitting from the map.
- Flares stop emitting particles when inside an inventory.
- Fixed oxygen not flowing through horizontal gaps between subs (e.g. between Remora and the drone).
- Decreased the size of the mountain in the RidgeBasic level type to prevent it from blocking the main path.
- Fixed too small collider sizes on a bunch of crafting materials.
- Fixed order options ("hold fire"/"fire at will" etc) being displayed in one button instead of
being split into separate buttons when playing the game in Chinese.
- Fixed "Text Self_CauseOfDeathDescription.Unknown not found" console error if a character gets killed
by being inside a respawn shuttle when it despawns.
- Fixed sonar not scaling properly when resolution is changed mid-round.
- Fixed fabricators & deconstructors displaying the "insufficient power" warning when power is low
(but still high enough for the devices to run).
Networking fixes:
- Fixed another ID mismatch problem that occasionally caused clients to get kicked out in multiplayer,
usually with an error message warning about a missing item.
- Fixed players always getting range banned when banned by a client.
- Fixed turrets not being aimed correctly in multiplayer if they're in another sub (e.g. the coilgun in
Remora's drone).
- More reliable fabricator and deconstructor syncing. Should fix items disappearing when multiple players
attempt to use the device at the same time and strange timing inconsistencies when deconstructing
multiple items in succession.
- Fixed all servers showing "unknown" as the game mode in the server list.
- Fixed server not allowing forward slashes in host messages.
- Fixed repair interface sometimes getting stuck close to 100% in multiplayer.
Character editor fixes and improvements:
- Nicer layout, made the panels hideable.
- Added buttons for creating joints, duplicating limbs, and deleting limbs/joints.
- A dropdown for selecting which content package to add the character to.
- Allow creating a new content package during character creation.
- Added hotkeys 1, 2, 3 for limb, joint, and animation modes respectively.
- Change the logic of deciding on which parameters are shown and when. In the ragdoll mode you can now
see the ragdoll, but also scale it and see the main parameters. Source rects are now longer shown on the
sprite sheet if limbs mode is disabled.
- Automatically select edit limbs mode when a new character is created.
- Option to create multiple limbs in the character creation wizard.
- Disallow deleting the main limb because it often causes crashes.
- Only allow selecting PNG files as the texture.
- The spritesheet is shown by default.
- Fixed deleted joints not being saved properly.
- Only lock the axis for torso/head position when alt is down.
- Disable test pose if the character is not a humanoid.
- Clamp camera offset so that the character is always at least partially visible.
---------------------------------------------------------------------------------------------------------
v0.9.0.7
---------------------------------------------------------------------------------------------------------
@@ -52,7 +159,6 @@ the reactor behave as if it had two rods in it.
to working like buttons which send out a pulse when interacted with).
- Fixed an issue that occasionally caused the main menu to look distorted when launching the game on Mac.
- Fixed crash after opening the file browser from the Workshop menu more than once on Linux.
- Fixed deconstructing coilgun ammo boxes giving out more materials than the materials required to fabricate them.
- Fixed combat mission achievements being impossible to unlock.
- Fixed item scales not being saved when the scale is modified in the sub editor.
- Fixed incorrect physicorium shell description.
@@ -61,7 +167,7 @@ to working like buttons which send out a pulse when interacted with).
AI characters to let go of ladders when holding RMB.
- Fixed explosion damage bypassing armor (both creature shells and wearable items).
- Fixed OverrideSaveFolder and OverrideMultiplayerSaveFolder settings not being saved.
- Fixed order/report icons "twitching" when the sub moves.
- Fixed order/rept icons "twitching" when the sub moves. or
- Fixed players being able to repair submerged electrical items indefinitely.
- Fixed a "attempted to access a removed ragdoll" console error when a character wearing the health
scanner HUD is removed.

View File

@@ -10,7 +10,6 @@
startwhenclientsready="False"
startwhenclientsreadyratio="0.8"
allowspectating="True"
voipenabled="True"
endroundatlevelend="True"
saveserverlogs="True"
allowragdollbutton="True"
@@ -22,6 +21,7 @@
botcount="0"
maxbotcount="16"
allowdisguises="True"
allowrewiring="True"
subselectionmode="Manual"
modeselectionmode="Manual"
endvoterequiredratio="0.6"
@@ -48,5 +48,5 @@
TraitorsEnabled="No"
BotSpawnMode="Normal"
AllowedRandomMissionTypes="Random,Salvage,Monster,Cargo,Combat"
AllowedClientNameChars="32-33,38-46,48-57,65-90,91,93,95-122,192-255,384-591,1024-1279"
AllowedClientNameChars="32-33,38-46,48-57,65-90,91-91,93-93,95-122,192-255,384-591,1024-1279"
ServerMessage="" />

Some files were not shown because too many files have changed in this diff Show More