(2402e736e) Tester's build, January 25th 2020

This commit is contained in:
Joonas Rikkonen
2020-01-25 12:48:13 +02:00
parent 4a58987eae
commit eaa18a20a3
57 changed files with 710 additions and 139 deletions

3
.gitignore vendored
View File

@@ -13,9 +13,6 @@ bld/
[Rr]elease*/
*.o
# Barotrauma content folder
BarotraumaShared/Content/
# Misc vs crap
*.v12.suo
*.suo

View File

@@ -176,6 +176,8 @@ namespace Barotrauma
healthBar = new GUIProgressBar(HUDLayoutSettings.ToRectTransform(HUDLayoutSettings.HealthBarAreaLeft, GUI.Canvas),
barSize: 1.0f, color: Color.Green, style: horizontal ? "GUIProgressBar" : "GUIProgressBarVertical")
{
Enabled = true,
HoverCursor = CursorState.Hand,
IsHorizontal = horizontal
};
healthBarShadow = new GUIProgressBar(HUDLayoutSettings.ToRectTransform(HUDLayoutSettings.HealthBarAreaLeft, GUI.Canvas),

View File

@@ -26,17 +26,14 @@ namespace Barotrauma
/// <seealso cref="NetLobbyScreen.Select"/> where I'm utilizing this
private readonly List<GUITextBox> registers = new List<GUITextBox>();
private readonly bool skipDuplicate;
// Selector index
private int index;
// Local changes we've made into previously stored messages
private string[] localChanges;
public ChatManager(bool skipDuplicate, bool loop, short maxCount)
public ChatManager(bool loop, short maxCount)
{
this.skipDuplicate = skipDuplicate;
this.loop = loop;
this.maxCount = maxCount;
localChanges = new string[maxCount];
@@ -87,13 +84,10 @@ namespace Barotrauma
public void Store(string message)
{
Clear();
string strip = StripMessage(message);
var strip = StripMessage(message);
if (string.IsNullOrWhiteSpace(strip)) { return; }
if (skipDuplicate && messageList.Any(p => message == p))
{
return;
}
if (messageList.Count > 1 && messageList[1] == message) { return; }
// insert to the second position as the first position is reserved for the original message if any
messageList.Insert(1, message);
@@ -104,7 +98,7 @@ namespace Barotrauma
}
// [It's also possible to lambdas too in short methods, if you like: string StripMessage(string text) => ChatMessage.GetChatMessageCommand(text, out string msg);]
string StripMessage(string text)
static string StripMessage(string text)
{
ChatMessage.GetChatMessageCommand(text, out string msg);
return msg;
@@ -129,40 +123,61 @@ namespace Barotrauma
/// <returns>A message or null</returns>
private string SelectMessage(Direction direction, string original)
{
if (direction == Direction.Other) { return null; }
// temporarily save our changes in case we fat-finger and want to go back
localChanges[index] = original;
int dir = (int) direction;
int nextIndex = (index + dir);
if (loop && messageList.Count > 1)
var originalIndex = index;
while (true)
{
nextIndex = LoopAround(nextIndex);
}
else
{
if (nextIndex > messageList.Count - 1)
if (direction == Direction.Other)
{
return null;
}
}
return nextIndex < 0 ? localChanges.FirstOrDefault() : EntryAt(index = nextIndex);
string EntryAt(int i)
{
// if we've previously edited the entry then give us that, else give us the original message
return localChanges[i] ?? messageList[i];
}
int LoopAround(int next)
{
if (next > (messageList.Count - 1)) { return 1; }
if (next < 1) { return messageList.Count - 1; }
return next;
// temporarily save our changes in case we fat-finger and want to go back
localChanges[index] = original;
var dir = (int) direction;
var nextIndex = (index + dir);
if (loop && messageList.Count > 1)
{
nextIndex = LoopAround(nextIndex);
}
else
{
if (nextIndex > messageList.Count - 1)
{
return null;
}
}
if (nextIndex >= 0 && EntryAt(nextIndex) == original && nextIndex != originalIndex && originalIndex != 0)
{
index = nextIndex;
continue;
}
return nextIndex < 0 ? localChanges.FirstOrDefault() : EntryAt(index = nextIndex);
string EntryAt(int i)
{
// if we've previously edited the entry then give us that, else give us the original message
return localChanges[i] ?? messageList[i];
}
int LoopAround(int next)
{
if (next > (messageList.Count - 1))
{
return 1;
}
if (next < 1)
{
return messageList.Count - 1;
}
return next;
}
}
}

View File

@@ -61,7 +61,7 @@ namespace Barotrauma
public static GUITextBox TextBox => textBox;
private static readonly ChatManager chatManager = new ChatManager(true, true, 64);
private static readonly ChatManager chatManager = new ChatManager(true, 64);
public static void Init()
{

View File

@@ -1,17 +1,19 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using Barotrauma.CharacterEditor;
using Barotrauma.Extensions;
using Barotrauma.Items.Components;
using Barotrauma.Networking;
using Barotrauma.Sounds;
using Barotrauma.Tutorials;
using EventInput;
using FarseerPhysics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
namespace Barotrauma
{
@@ -26,11 +28,23 @@ namespace Barotrauma
PickItemFail,
DropItem
}
public enum CursorState
{
Default, // Cursor
Hand, // Hand with a finger
Move, // arrows pointing to all directions
IBeam, // Text
Dragging,// Closed hand
Waiting, // Hourglass
WaitingBackground // Cursor + Hourglass
}
public static class GUI
{
public static GUICanvas Canvas => GUICanvas.Instance;
public static CursorState MouseCursor = CursorState.Default;
public static readonly SamplerState SamplerState = new SamplerState()
{
Filter = TextureFilter.Linear,
@@ -82,8 +96,7 @@ namespace Barotrauma
public static GUIStyle Style;
private static Texture2D t;
private static Sprite Cursor => Style.CursorSprite;
private static Sprite[] MouseCursorSprites => Style.CursorSprite;
private static bool debugDrawSounds, debugDrawEvents;
@@ -184,7 +197,7 @@ namespace Barotrauma
public static void Init(GameWindow window, IEnumerable<ContentPackage> selectedContentPackages, GraphicsDevice graphicsDevice)
{
GUI.GraphicsDevice = graphicsDevice;
GraphicsDevice = graphicsDevice;
var files = ContentPackage.GetFilesOfType(selectedContentPackages, ContentType.UIStyle);
XElement selectedStyle = null;
@@ -306,7 +319,7 @@ namespace Barotrauma
if (GameMain.ShowFPS || GameMain.DebugDraw)
{
DrawString(spriteBatch, new Vector2(10, 10),
"FPS: " + (int)GameMain.PerformanceCounter.AverageFramesPerSecond,
"FPS: " + Math.Round(GameMain.PerformanceCounter.AverageFramesPerSecond),
Color.White, Color.Black * 0.5f, 0, SmallFont);
}
@@ -339,7 +352,7 @@ namespace Barotrauma
y += 15;
}
if (FarseerPhysics.Settings.EnableDiagnostics)
if (Settings.EnableDiagnostics)
{
DrawString(spriteBatch, new Vector2(320, y), "ContinuousPhysicsTime: " + GameMain.World.ContinuousPhysicsTime.TotalMilliseconds, Color.Lerp(Color.LightGreen, Color.Red, (float)GameMain.World.ContinuousPhysicsTime.TotalMilliseconds / 10.0f), Color.Black * 0.5f, 0, SmallFont);
DrawString(spriteBatch, new Vector2(320, y + 15), "ControllersUpdateTime: " + GameMain.World.ControllersUpdateTime.TotalMilliseconds, Color.Lerp(Color.LightGreen, Color.Red, (float)GameMain.World.ControllersUpdateTime.TotalMilliseconds / 10.0f), Color.Black * 0.5f, 0, SmallFont);
@@ -415,10 +428,10 @@ namespace Barotrauma
}
else
{
soundStr += System.IO.Path.GetFileNameWithoutExtension(playingSoundChannel.Sound.Filename);
soundStr += Path.GetFileNameWithoutExtension(playingSoundChannel.Sound.Filename);
#if DEBUG
if (PlayerInput.GetKeyboardState.IsKeyDown(Microsoft.Xna.Framework.Input.Keys.G))
if (PlayerInput.GetKeyboardState.IsKeyDown(Keys.G))
{
if (PlayerInput.MousePosition.Y >= y && PlayerInput.MousePosition.Y <= y + 12)
{
@@ -507,10 +520,13 @@ namespace Barotrauma
if (GameMain.WindowActive && !HideCursor)
{
spriteBatch.End();
spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: GUI.SamplerStateClamp, rasterizerState: GameMain.ScissorTestEnable);
Cursor.Draw(spriteBatch, PlayerInput.LatestMousePosition, 0, Scale / 2f);
spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: SamplerStateClamp, rasterizerState: GameMain.ScissorTestEnable);
var sprite = MouseCursorSprites[(int) MouseCursor];
sprite.Draw(spriteBatch, PlayerInput.LatestMousePosition, Color.White, sprite.Origin, 0f, Scale / 1.5f);
spriteBatch.End();
spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: GUI.SamplerState, rasterizerState: GameMain.ScissorTestEnable);
spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: SamplerState, rasterizerState: GameMain.ScissorTestEnable);
}
HideCursor = false;
}
@@ -723,13 +739,14 @@ namespace Barotrauma
GUIComponent prevMouseOn = MouseOn;
MouseOn = null;
int inventoryIndex = -1;
if (Inventory.IsMouseOnInventory())
{
inventoryIndex = updateList.IndexOf(CharacterHUD.HUDFrame);
}
for (int i = updateList.Count - 1; i > inventoryIndex; i--)
for (var i = updateList.Count - 1; i > inventoryIndex; i--)
{
GUIComponent c = updateList[i];
var c = updateList[i];
if (!c.CanBeFocused) { continue; }
if (c.MouseRect.Contains(PlayerInput.MousePosition))
{
@@ -740,8 +757,198 @@ namespace Barotrauma
break;
}
}
MouseCursor = UpdateMouseCursorState(MouseOn);
return MouseOn;
}
private static CursorState UpdateMouseCursorState(GUIComponent c)
{
// Waiting and drag cursor override everything else
if (MouseCursor == CursorState.Waiting) { return CursorState.Waiting; }
if (GUIScrollBar.DraggingBar != null) { return GUIScrollBar.DraggingBar.Bar.HoverCursor; }
// Wire cursors
if (ConnectionPanel.HighlightedWire != null) { return CursorState.Hand; }
if (Wire.DraggingWire != null) { return CursorState.Dragging; }
if (Connection.DraggingConnected != null) { return CursorState.Dragging; }
if (c == null || c is GUICustomComponent)
{
switch (Screen.Selected)
{
// Character editor limbs
case CharacterEditorScreen editor:
return editor.GetMouseCursorState();
// Portrait area during gameplay
case GameScreen _ when HUDLayoutSettings.PortraitArea.Contains(PlayerInput.MousePosition):
return CursorState.Hand;
// Sub editor drag and highlight
case SubEditorScreen editor:
{
// Portrait area
if ((editor.CharacterMode || editor.WiringMode) &&
HUDLayoutSettings.PortraitArea.Contains(PlayerInput.MousePosition))
{
return CursorState.Hand;
}
foreach (var mapEntity in MapEntity.mapEntityList)
{
if (MapEntity.StartMovingPos != Vector2.Zero)
{
return CursorState.Dragging;
}
if (mapEntity.IsHighlighted)
{
return CursorState.Hand;
}
}
break;
}
// Campaign map highlighted location
case LobbyScreen lobby:
{
if (lobby.CampaignUI?.Campaign.Map.HighlightedLocation != null) { return CursorState.Hand; }
break;
}
case NetLobbyScreen lobby:
{
if (lobby.CampaignUI?.Campaign.Map.HighlightedLocation != null) { return CursorState.Hand; }
break;
}
}
}
if (c != null && c.Visible)
{
// When a button opens a submenu, it increases to the size of the entire screen.
// And this is of course picked up as clickable area.
// There has to be a better way of checking this but for now this works.
var monitorRect = new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight);
var parent = FindInteractParent(c);
if (c.Enabled)
{
// Some parent elements take priority
// but not when the child is a GUIButton or GUITickBox
if (!(parent is GUIButton) && !(parent is GUIListBox) ||
(c is GUIButton) || (c is GUITickBox))
{
if (!c.Rect.Equals(monitorRect)) { return c.HoverCursor; }
}
}
// Children in list boxes can be interacted with despite not having
// a GUIButton inside of them so instead of hard coding we check if
// the children can be interacted with by checking their hover state
if (parent is GUIListBox)
{
var hoverParent = c;
while (true)
{
if (hoverParent == parent || hoverParent == null) { break; }
if (hoverParent.State == GUIComponent.ComponentState.Hover) { return CursorState.Hand; }
hoverParent = hoverParent.Parent;
}
}
if (parent != null)
{
if (!parent.Rect.Equals(monitorRect)) { return parent.HoverCursor; }
}
}
if (Inventory.IsMouseOnInventory()) { return Inventory.GetInventoryMouseCursor(); }
var character = Character.Controlled;
// ReSharper disable once InvertIf
if (character != null)
{
// Health menus
if (character.CharacterHealth.MouseOnElement) { return CursorState.Hand; }
if (character.SelectedCharacter != null)
{
if (character.SelectedCharacter.CharacterHealth.MouseOnElement)
{
return CursorState.Hand;
}
}
// Character is hovering over an item placed in the world
if (character.FocusedItem != null) { return CursorState.Hand; }
}
return CursorState.Default;
static GUIComponent FindInteractParent(GUIComponent component)
{
while (true)
{
var parent = component.Parent;
if (parent == null) { return null; }
if (ContainsMouse(parent))
{
if (parent.Enabled)
{
switch (parent)
{
case GUIButton button:
return button;
case GUITextBox box:
return box;
case GUIListBox list:
return list;
case GUIScrollBar bar:
return bar;
}
}
component = parent;
}
else
{
return null;
}
}
}
static bool ContainsMouse(GUIComponent component)
{
// If component has a mouse rectangle then use that, if not use it's physical rect
return !component.MouseRect.Equals(Rectangle.Empty) ?
component.MouseRect.Contains(PlayerInput.MousePosition) :
component.Rect.Contains(PlayerInput.MousePosition);
}
}
/// <summary>
/// Set the cursor to an hourglass.
/// Will automatically revert after 10 seconds or when <see cref="ClearCursorWait"/> is called.
/// </summary>
public static void SetCursorWaiting()
{
CoroutineManager.StartCoroutine(WaitCursorCoroutine(), "WaitCursorTimeout");
static IEnumerable<object> WaitCursorCoroutine()
{
MouseCursor = CursorState.Waiting;
var timeOut = DateTime.Now + new TimeSpan(0, 0, 10);
while (DateTime.Now < timeOut) { yield return CoroutineStatus.Running; }
if (MouseCursor == CursorState.Waiting) { MouseCursor = CursorState.Default; }
yield return CoroutineStatus.Success;
}
}
public static void ClearCursorWait()
{
CoroutineManager.StopCoroutines("WaitCursorTimeout");
MouseCursor = CursorState.Default;
}
public static bool HasSizeChanged(Point referenceResolution, float referenceUIScale, float referenceHUDScale)
{
@@ -754,7 +961,7 @@ namespace Barotrauma
HandlePersistingElements(deltaTime);
RefreshUpdateList();
UpdateMouseOn();
System.Diagnostics.Debug.Assert(updateList.Count == updateListSet.Count);
Debug.Assert(updateList.Count == updateListSet.Count);
updateList.ForEach(c => c.UpdateAuto(deltaTime));
UpdateMessages(deltaTime);
}

View File

@@ -154,6 +154,7 @@ namespace Barotrauma
public GUIButton(RectTransform rectT, string text = "", Alignment textAlignment = Alignment.Center, string style = "", Color? color = null, ScalableFont font = null) : base(style, rectT)
{
CanBeFocused = true;
HoverCursor = CursorState.Hand;
if (color.HasValue)
{

View File

@@ -16,6 +16,8 @@ namespace Barotrauma
#region Hierarchy
public GUIComponent Parent => RectTransform.Parent?.GUIComponent;
public CursorState HoverCursor = CursorState.Default;
public IEnumerable<GUIComponent> Children => RectTransform.Children.Select(c => c.GUIComponent);
public T GetChild<T>() where T : GUIComponent

View File

@@ -147,6 +147,7 @@ namespace Barotrauma
public GUIDropDown(RectTransform rectT, string text = "", int elementCount = 4, string style = "", bool selectMultiple = false, bool dropAbove = false) : base(style, rectT)
{
HoverCursor = CursorState.Hand;
CanBeFocused = true;
this.selectMultiple = selectMultiple;

View File

@@ -192,12 +192,28 @@ namespace Barotrauma
public GUIScrollBar(RectTransform rectT, float barSize = 1, Color? color = null, string style = "", bool? isHorizontal = null) : base(style, rectT)
{
CanBeFocused = true;
this.isHorizontal = isHorizontal ?? (Rect.Width > Rect.Height);
Frame = new GUIFrame(new RectTransform(Vector2.One, rectT));
GUI.Style.Apply(Frame, IsHorizontal ? "GUIFrameHorizontal" : "GUIFrameVertical", this);
this.barSize = barSize;
Bar = new GUIButton(new RectTransform(Vector2.One, rectT, IsHorizontal ? Anchor.CenterLeft : Anchor.TopCenter), color: color);
switch (style)
{
case "":
HoverCursor = CursorState.Default;
Bar.HoverCursor = CursorState.Default;
break;
case "GUISlider":
HoverCursor = CursorState.Default;
Bar.HoverCursor = CursorState.Hand;
break;
default:
HoverCursor = CursorState.Hand;
Bar.HoverCursor = CursorState.Hand;
break;
}
GUI.Style.Apply(Bar, IsHorizontal ? "GUIButtonHorizontal" : "GUIButtonVertical", this);
Bar.OnPressed = SelectBar;
enabled = true;
@@ -222,8 +238,6 @@ namespace Barotrauma
{
if (!Visible) { return; }
base.Update(deltaTime);
if (!enabled) { return; }
Frame.State = GUI.MouseOn == Frame ? ComponentState.Hover : ComponentState.None;

View File

@@ -25,7 +25,7 @@ namespace Barotrauma
public ScalableFont ObjectiveTitleFont { get; private set; }
public ScalableFont ObjectiveNameFont { get; private set; }
public Sprite CursorSprite { get; private set; }
public readonly Sprite[] CursorSprite = new Sprite[7];
public UISprite UIGlow { get; private set; }
@@ -38,10 +38,15 @@ namespace Barotrauma
configElement = element;
foreach (XElement subElement in configElement.Elements())
{
switch (subElement.Name.ToString().ToLowerInvariant())
var name = subElement.Name.ToString().ToLowerInvariant();
switch (name)
{
case "cursor":
CursorSprite = new Sprite(subElement);
foreach (var children in subElement.Descendants())
{
var index = children.GetAttributeInt("state", (int) CursorState.Default);
CursorSprite[index] = new Sprite(children);
}
break;
case "uiglow":
UIGlow = new UISprite(subElement);

View File

@@ -231,6 +231,7 @@ namespace Barotrauma
Alignment textAlignment = Alignment.Left, bool wrap = false, string style = "", Color? color = null)
: base(style, rectT)
{
HoverCursor = CursorState.IBeam;
CanBeFocused = true;
Enabled = true;

View File

@@ -134,6 +134,7 @@ namespace Barotrauma
public GUITickBox(RectTransform rectT, string label, ScalableFont font = null, string style = "") : base(null, rectT)
{
CanBeFocused = true;
HoverCursor = CursorState.Hand;
layoutGroup = new GUILayoutGroup(new RectTransform(Vector2.One, rectT), true);
@@ -176,6 +177,7 @@ namespace Barotrauma
protected override void Update(float deltaTime)
{
if (!Visible) return;
base.Update(deltaTime);
if (GUI.MouseOn == this && Enabled)
{

View File

@@ -891,7 +891,13 @@ namespace Barotrauma
double deltaTime = gameTime.ElapsedGameTime.TotalSeconds;
PerformanceCounter.Update(deltaTime);
double step = 1.0 / Timing.FrameLimit;
while (!Config.VSyncEnabled && sw.Elapsed.TotalSeconds + deltaTime < step)
{
Thread.Sleep(1);
}
PerformanceCounter.Update(sw.Elapsed.TotalSeconds + deltaTime);
if (loadingScreenOpen)
{

View File

@@ -97,7 +97,10 @@ namespace Barotrauma.Tutorials
stunbaton.Unequip(officer);
officer.Inventory.RemoveItem(stunbaton);
var ballistichelmet = FindOrGiveItem(officer, "ballistichelmet");
var ballistichelmet =
officer.Inventory.FindItemByIdentifier("ballistichelmet1") ??
officer.Inventory.FindItemByIdentifier("ballistichelmet2") ??
FindOrGiveItem(officer, "ballistichelmet3");
ballistichelmet.Unequip(officer);
officer.Inventory.RemoveItem(ballistichelmet);

View File

@@ -24,6 +24,12 @@ namespace Barotrauma.Items.Components
{
get { return flashTimer; }
}
public static Wire DraggingConnected
{
get => draggingConnected;
}
private float flashTimer;
public static void DrawConnections(SpriteBatch spriteBatch, ConnectionPanel panel, Character character)

View File

@@ -51,6 +51,11 @@ namespace Barotrauma.Items.Components
get { return sectionExtents; }
}
public static Wire DraggingWire
{
get => draggingWire;
}
partial void InitProjSpecific(XElement element)
{
if (defaultWireSprite == null)

View File

@@ -653,10 +653,19 @@ namespace Barotrauma
if (Character.Controlled.Inventory != null)
{
foreach (InventorySlot slot in Character.Controlled.Inventory.slots)
var inv = Character.Controlled.Inventory;
for (var i = 0; i < inv.slots.Length; i++)
{
if (slot.InteractRect.Contains(PlayerInput.MousePosition) ||
slot.EquipButtonRect.Contains(PlayerInput.MousePosition))
var slot = inv.slots[i];
if (slot.InteractRect.Contains(PlayerInput.MousePosition))
{
return true;
}
// check if the equip button actually exists
if (slot.EquipButtonRect.Contains(PlayerInput.MousePosition) &&
i >= 0 && inv.Items.Length > i &&
inv.Items[i] != null)
{
return true;
}
@@ -664,10 +673,19 @@ namespace Barotrauma
}
if (Character.Controlled.SelectedCharacter?.Inventory != null)
{
foreach (InventorySlot slot in Character.Controlled.SelectedCharacter.Inventory.slots)
var inv = Character.Controlled.SelectedCharacter.Inventory;
for (var i = 0; i < inv.slots.Length; i++)
{
if (slot.InteractRect.Contains(PlayerInput.MousePosition) ||
slot.EquipButtonRect.Contains(PlayerInput.MousePosition))
var slot = inv.slots[i];
if (slot.InteractRect.Contains(PlayerInput.MousePosition))
{
return true;
}
// check if the equip button actually exists
if (slot.EquipButtonRect.Contains(PlayerInput.MousePosition) &&
i >= 0 && inv.Items.Length > i &&
inv.Items[i] != null)
{
return true;
}
@@ -676,7 +694,7 @@ namespace Barotrauma
if (Character.Controlled.SelectedConstruction != null)
{
foreach (ItemComponent ic in Character.Controlled.SelectedConstruction.Components)
foreach (var ic in Character.Controlled.SelectedConstruction.ActiveHUDs)
{
var itemContainer = ic as ItemContainer;
if (itemContainer?.Inventory?.slots == null) continue;
@@ -699,6 +717,88 @@ namespace Barotrauma
return false;
}
public static CursorState GetInventoryMouseCursor()
{
var character = Character.Controlled;
if (character == null) { return CursorState.Default; }
if (draggingItem != null || DraggingInventory != null) { return CursorState.Dragging; }
var inv = character.Inventory;
var selInv = character.SelectedCharacter?.Inventory;
if (inv == null) { return CursorState.Default; }
foreach (var item in inv.Items)
{
var container = item?.GetComponent<ItemContainer>();
if (container == null) { continue; }
if (container.Inventory.slots != null)
{
if (container.Inventory.slots.Any(slot => slot.IsHighlighted))
{
return CursorState.Hand;
}
}
if (container.Inventory.movableFrameRect.Contains(PlayerInput.MousePosition))
{
return CursorState.Move;
}
}
if (selInv != null)
{
foreach (var slot in selInv.slots)
{
if (slot.InteractRect.Contains(PlayerInput.MousePosition) ||
slot.EquipButtonRect.Contains(PlayerInput.MousePosition))
{
return CursorState.Hand;
}
}
}
if (character.SelectedConstruction != null)
{
foreach (var ic in character.SelectedConstruction.ActiveHUDs)
{
var itemContainer = ic as ItemContainer;
if (itemContainer?.Inventory?.slots == null) continue;
foreach (var slot in itemContainer.Inventory.slots)
{
if (slot.InteractRect.Contains(PlayerInput.MousePosition) ||
slot.EquipButtonRect.Contains(PlayerInput.MousePosition))
{
return CursorState.Hand;
}
}
}
}
foreach (var slot in inv.slots)
{
if (slot.EquipButtonRect.Contains(PlayerInput.MousePosition))
{
return CursorState.Hand;
}
// This is the only place we double check this because if we have a inventory container
// highlighting any area within that container registers as highlighting the
// original slot the item is in thus giving us a false hand cursor.
if (slot.InteractRect.Contains(PlayerInput.MousePosition))
{
if (slot.IsHighlighted)
{
return CursorState.Hand;
}
}
}
return CursorState.Default;
}
protected static void DrawToolTip(SpriteBatch spriteBatch, string toolTip, Rectangle highlightedSlot, List<ColorData> colorData = null)
{

View File

@@ -88,8 +88,15 @@ namespace Barotrauma
float arrowWidth = 32.0f;
float arrowSize = 15.0f;
bool invalidDir = false;
if (dir == Vector2.Zero)
{
invalidDir = true;
dir = IsHorizontal ? Vector2.UnitX : Vector2.UnitY;
}
GUI.Arrow.Draw(sb,
arrowPos, clr * 0.8f,
arrowPos, invalidDir ? Color.Red : clr * 0.8f,
GUI.Arrow.Origin, MathUtils.VectorToAngle(dir) + MathHelper.PiOver2,
IsHorizontal ?
new Vector2(Math.Min(rect.Height, arrowWidth) / GUI.Arrow.size.X, arrowSize / GUI.Arrow.size.Y) :

View File

@@ -44,6 +44,8 @@ namespace Barotrauma
private Location highlightedLocation;
public Location HighlightedLocation => highlightedLocation;
private Vector2 drawOffset;
private Vector2 drawOffsetNoise;

View File

@@ -13,7 +13,9 @@ namespace Barotrauma
protected static Vector2 selectionPos = Vector2.Zero;
protected static Vector2 selectionSize = Vector2.Zero;
protected static Vector2 startMovingPos = Vector2.Zero;
private static Vector2 startMovingPos = Vector2.Zero;
public static Vector2 StartMovingPos => startMovingPos;
private static bool resizing;
private int resizeDirX, resizeDirY;

View File

@@ -66,7 +66,7 @@ namespace Barotrauma.Networking
}
txt = order.GetChatMessage(targetCharacter?.Name, senderCharacter?.CurrentHull?.DisplayName, givingOrderToSelf: targetCharacter == senderCharacter, orderOption: orderOption);
if (GameMain.Client.GameStarted)
if (GameMain.Client.GameStarted && Screen.Selected == GameMain.GameScreen)
{
if (order.TargetAllCharacters)
{

View File

@@ -401,6 +401,7 @@ namespace Barotrauma.Networking
// Before main looping starts, we loop here and wait for approval message
private IEnumerable<object> WaitForStartingInfo()
{
GUI.SetCursorWaiting();
requiresPw = false;
pwRetries = -1;
@@ -503,6 +504,7 @@ namespace Barotrauma.Networking
reconnectBox?.Close(); reconnectBox = null;
GUI.ClearCursorWait();
if (connectCancelled) { yield return CoroutineStatus.Success; }
yield return CoroutineStatus.Success;
@@ -1435,6 +1437,11 @@ namespace Barotrauma.Networking
if (clientPeer is SteamP2POwnerPeer)
{
TaskPool.Add(Steamworks.SteamNetworkingUtils.WaitForPingDataAsync(), (task) =>
{
Steam.SteamManager.UpdateLobby(serverSettings);
});
Steam.SteamManager.UpdateLobby(serverSettings);
}
}
@@ -1978,7 +1985,7 @@ namespace Barotrauma.Networking
if (ChildServerRelay.Process != null)
{
int checks = 0;
while (!ChildServerRelay.Process.HasExited)
while (ChildServerRelay.Process != null && !ChildServerRelay.Process.HasExited)
{
if (checks > 10)
{

View File

@@ -509,11 +509,6 @@ namespace Barotrauma.Networking
IP = "";
Port = "";
QueryPort = "";
string pingLocation = lobby.GetData("pinglocation");
if (!string.IsNullOrEmpty(pingLocation))
{
PingLocation = Steamworks.Data.PingLocation.TryParseFromString(pingLocation);
}
PlayerCount = currPlayers;
MaxPlayers = maxPlayers;
HasPassword = hasPassword;

View File

@@ -118,6 +118,8 @@ namespace Barotrauma.Steam
TaskPool.Add(Steamworks.SteamMatchmaking.CreateLobbyAsync(serverSettings.MaxPlayers + 10),
(lobby) =>
{
currentLobby = lobby.Result;
if (currentLobby == null)
{
DebugConsole.ThrowError("Failed to create Steam lobby");
@@ -125,8 +127,6 @@ namespace Barotrauma.Steam
return;
}
currentLobby = lobby.Result;
DebugConsole.NewMessage("Lobby created!", Microsoft.Xna.Framework.Color.Lime);
lobbyState = LobbyState.Owner;
@@ -169,7 +169,8 @@ namespace Barotrauma.Steam
currentLobby?.SetData("playercount", (GameMain.Client?.ConnectedClients?.Count ?? 0).ToString());
currentLobby?.SetData("maxplayernum", serverSettings.MaxPlayers.ToString());
//currentLobby?.SetData("hostipaddress", lobbyIP);
currentLobby?.SetData("pinglocation", Steamworks.SteamNetworkingUtils.LocalPingLocation.ToString() ?? "");
string pingLocation = Steamworks.SteamNetworkingUtils.LocalPingLocation.ToString();
currentLobby?.SetData("pinglocation", pingLocation ?? "");
currentLobby?.SetData("lobbyowner", SteamIDUInt64ToString(GetSteamID()));
currentLobby?.SetData("haspassword", serverSettings.HasPassword.ToString());
@@ -254,6 +255,7 @@ namespace Barotrauma.Steam
ServerInfo serverInfo = new ServerInfo();
serverInfo.ServerName = lobby.GetData("name");
serverInfo.OwnerID = SteamIDStringToUInt64(lobby.GetData("lobbyowner"));
serverInfo.LobbyID = lobby.Id;
serverInfo.PlayerCount = int.TryParse(lobby.GetData("playercount"), out int playerCount) ? playerCount : 0;
serverInfo.MaxPlayers = int.TryParse(lobby.GetData("maxplayernum"), out int maxPlayers) ? maxPlayers : 1;
@@ -371,6 +373,12 @@ namespace Barotrauma.Steam
serverInfo.ContentPackageHashes.Clear();
}
string pingLocation = lobby.GetData("pinglocation");
if (!string.IsNullOrEmpty(pingLocation))
{
serverInfo.PingLocation = Steamworks.Data.PingLocation.TryParseFromString(pingLocation);
}
bool? getLobbyBool(string key)
{
string data = lobby.GetData(key);

View File

@@ -112,6 +112,7 @@ namespace Barotrauma
if (GameMain.Config != null)
{
sb.AppendLine("Graphics mode: " + GameMain.Config.GraphicsWidth + "x" + GameMain.Config.GraphicsHeight + " (" + GameMain.Config.WindowMode.ToString() + ")");
sb.AppendLine("VSync "+ (GameMain.Config.VSyncEnabled ? "ON" : "OFF"));
}
if (GameMain.SelectedPackages != null)
{

View File

@@ -244,6 +244,7 @@ namespace Barotrauma
private IEnumerable<object> WaitForCampaignSetup()
{
GUI.SetCursorWaiting();
string headerText = TextManager.Get("CampaignStartingPleaseWait");
var msgBox = new GUIMessageBox(headerText, TextManager.Get("CampaignStarting"), new string[] { TextManager.Get("Cancel") });
@@ -251,6 +252,7 @@ namespace Barotrauma
{
GameMain.NetLobbyScreen.HighlightMode(GameMain.NetLobbyScreen.SelectedModeIndex);
GameMain.NetLobbyScreen.SelectMode(GameMain.NetLobbyScreen.SelectedModeIndex);
GUI.ClearCursorWait();
CoroutineManager.StopCoroutines("WaitForCampaignSetup");
return true;
};
@@ -263,6 +265,7 @@ namespace Barotrauma
yield return CoroutineStatus.Running;
}
msgBox.Close();
GUI.ClearCursorWait();
yield return CoroutineStatus.Success;
}

View File

@@ -746,6 +746,21 @@ namespace Barotrauma.CharacterEditor
buttonsPanelToggle?.UpdateOpenState((float)deltaTime, new Vector2(-buttonsPanel.Rect.Width - leftArea.RectTransform.AbsoluteOffset.X, 0), buttonsPanel.RectTransform);
}
public CursorState GetMouseCursorState()
{
foreach (var limb in character.AnimController.Limbs)
{
if (limb?.ActiveSprite == null) { continue; }
if (selectedJoints.Any(j => j.LimbA == limb || j.LimbB == limb)) { continue; }
// character limbs
if (editLimbs && !spriteSheetRect.Contains(PlayerInput.MousePosition) &&
MathUtils.RectangleContainsPoint(GetLimbPhysicRect(limb), PlayerInput.MousePosition)) { return CursorState.Hand; }
// spritesheet
if (GetLimbSpritesheetRect(limb).Contains(PlayerInput.MousePosition)) { return CursorState.Hand; }
}
return CursorState.Default;
}
/// <summary>
/// Fps independent mouse input. The draw method is called multiple times per frame.
/// </summary>

View File

@@ -18,6 +18,11 @@ namespace Barotrauma
get { return GameMain.GameSession.CrewManager; }
}
public CampaignUI CampaignUI
{
get { return campaignUI; }
}
public string GetMoney()
{
return campaignUI == null ? "" : campaignUI.GetMoney();

View File

@@ -545,10 +545,10 @@ namespace Barotrauma
break;
case Tab.CharacterEditor:
Submarine.MainSub = null;
GameMain.CharacterEditorScreen.Select();
CoroutineManager.StartCoroutine(SelectScreenWithWaitCursor(GameMain.CharacterEditorScreen));
break;
case Tab.SubmarineEditor:
GameMain.SubEditorScreen.Select();
CoroutineManager.StartCoroutine(SelectScreenWithWaitCursor(GameMain.SubEditorScreen));
break;
case Tab.QuickStartDev:
QuickStart();
@@ -560,7 +560,7 @@ namespace Barotrauma
break;
case Tab.SteamWorkshop:
if (!Steam.SteamManager.IsInitialized) return false;
GameMain.SteamWorkshopScreen.Select();
CoroutineManager.StartCoroutine(SelectScreenWithWaitCursor(GameMain.SteamWorkshopScreen));
break;
case Tab.Credits:
titleText.Visible = false;
@@ -577,6 +577,16 @@ namespace Barotrauma
return true;
}
private IEnumerable<object> SelectScreenWithWaitCursor(Screen screen)
{
GUI.SetCursorWaiting();
//tiny delay to get the cursor to render
yield return new WaitForSeconds(0.02f);
GUI.ClearCursorWait();
screen.Select();
yield return CoroutineStatus.Success;
}
public bool ReturnToMainMenu(GUIButton button, object obj)
{
GUI.PreventPauseMenuToggle = false;
@@ -1165,7 +1175,8 @@ namespace Barotrauma
maxPlayersBox = new GUITextBox(new RectTransform(new Vector2(0.6f, 1.0f), buttonContainer.RectTransform), textAlignment: Alignment.Center)
{
Text = maxPlayers.ToString(),
Enabled = false
// ?
// Enabled = false
};
new GUIButton(new RectTransform(new Vector2(0.2f, 1.0f), buttonContainer.RectTransform), "+", textAlignment: Alignment.Center)
{

View File

@@ -1080,6 +1080,7 @@ namespace Barotrauma
public IEnumerable<object> WaitForStartRound(GUIButton startButton, bool allowCancel)
{
GUI.SetCursorWaiting();
string headerText = TextManager.Get("RoundStartingPleaseWait");
var msgBox = new GUIMessageBox(headerText, TextManager.Get("RoundStarting"),
allowCancel ? new string[] { TextManager.Get("Cancel") } : new string[0]);
@@ -1091,6 +1092,7 @@ namespace Barotrauma
startButton.Enabled = true;
GameMain.Client.RequestRoundEnd();
CoroutineManager.StopCoroutines("WaitForStartRound");
GUI.ClearCursorWait();
return true;
};
msgBox.Buttons[0].OnClicked += msgBox.Close;
@@ -1113,7 +1115,7 @@ namespace Barotrauma
{
startButton.Enabled = true;
}
GUI.ClearCursorWait();
yield return CoroutineStatus.Success;
}

View File

@@ -147,6 +147,8 @@ namespace Barotrauma
private DateTime refreshDisableTimer;
private bool waitingForRefresh;
private bool steamPingInfoReady;
private const float sidebarWidth = 0.2f;
public ServerListScreen()
{
@@ -1423,6 +1425,15 @@ namespace Barotrauma
{
if (waitingForRefresh) { return; }
steamPingInfoReady = false;
CoroutineManager.StopCoroutines("EstimateLobbyPing");
TaskPool.Add(Steamworks.SteamNetworkingUtils.WaitForPingDataAsync(), (task) =>
{
steamPingInfoReady = true;
});
friendsListUpdateTime = Timing.TotalTime - 1.0;
UpdateFriendsList();
@@ -1684,11 +1695,7 @@ namespace Barotrauma
}
else if (serverInfo.PingLocation != null)
{
Steamworks.Data.PingLocation pingLocation = serverInfo.PingLocation.Value;
serverInfo.Ping = Steamworks.SteamNetworkingUtils.LocalPingLocation?.EstimatePingTo(pingLocation) ?? -1;
serverInfo.PingChecked = true;
serverPingText.TextColor = GetPingTextColor(serverInfo.Ping);
serverPingText.Text = serverInfo.Ping > -1 ? serverInfo.Ping.ToString() : "?";
CoroutineManager.StartCoroutine(EstimateLobbyPing(serverInfo, serverPingText), "EstimateLobbyPing");
}
if (serverInfo.LobbyID == 0 && (string.IsNullOrWhiteSpace(serverInfo.IP) || string.IsNullOrWhiteSpace(serverInfo.Port)))
@@ -1749,6 +1756,22 @@ namespace Barotrauma
FilterServers();
}
private IEnumerable<object> EstimateLobbyPing(ServerInfo serverInfo, GUITextBlock serverPingText)
{
while (!steamPingInfoReady)
{
yield return CoroutineStatus.Running;
}
Steamworks.Data.PingLocation pingLocation = serverInfo.PingLocation.Value;
serverInfo.Ping = Steamworks.SteamNetworkingUtils.LocalPingLocation?.EstimatePingTo(pingLocation) ?? -1;
serverInfo.PingChecked = true;
serverPingText.TextColor = GetPingTextColor(serverInfo.Ping);
serverPingText.Text = serverInfo.Ping > -1 ? serverInfo.Ping.ToString() : "?";
yield return CoroutineStatus.Success;
}
private void ServerQueryFinished()
{
if (!serverList.Content.Children.Any())

View File

@@ -1435,7 +1435,7 @@ namespace Barotrauma
#if DEBUG
deleteBtn.Enabled = true;
#else
deleteBtn.Enabled = userData is Submarine sub && sub.IsVanillaSubmarine();
deleteBtn.Enabled = userData is Submarine sub && !sub.IsVanillaSubmarine();
#endif
}
return true;

View File

@@ -6,7 +6,7 @@
<RootNamespace>Barotrauma</RootNamespace>
<Authors>FakeFish, Undertow Games</Authors>
<Product>Barotrauma</Product>
<Version>0.9.700.0</Version>
<Version>0.9.701.0</Version>
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
<Platforms>AnyCPU;x64</Platforms>
<AssemblyName>Barotrauma</AssemblyName>

View File

@@ -6,7 +6,7 @@
<RootNamespace>Barotrauma</RootNamespace>
<Authors>FakeFish, Undertow Games</Authors>
<Product>Barotrauma</Product>
<Version>0.9.700.0</Version>
<Version>0.9.701.0</Version>
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
<Platforms>AnyCPU;x64</Platforms>
<AssemblyName>Barotrauma</AssemblyName>

View File

@@ -6,7 +6,7 @@
<RootNamespace>Barotrauma</RootNamespace>
<Authors>FakeFish, Undertow Games</Authors>
<Product>Barotrauma</Product>
<Version>0.9.700.0</Version>
<Version>0.9.701.0</Version>
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
<Platforms>AnyCPU;x64</Platforms>
<AssemblyName>Barotrauma</AssemblyName>

View File

@@ -6,7 +6,7 @@
<RootNamespace>Barotrauma</RootNamespace>
<Authors>FakeFish, Undertow Games</Authors>
<Product>Barotrauma Dedicated Server</Product>
<Version>0.9.700.0</Version>
<Version>0.9.701.0</Version>
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
<Platforms>AnyCPU;x64</Platforms>
<AssemblyName>DedicatedServer</AssemblyName>

View File

@@ -6,7 +6,7 @@
<RootNamespace>Barotrauma</RootNamespace>
<Authors>FakeFish, Undertow Games</Authors>
<Product>Barotrauma Dedicated Server</Product>
<Version>0.9.700.0</Version>
<Version>0.9.701.0</Version>
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
<Platforms>AnyCPU;x64</Platforms>
<AssemblyName>DedicatedServer</AssemblyName>

View File

@@ -313,11 +313,11 @@ namespace Barotrauma.Networking
List<NetEntityEvent> eventsToSync = null;
if (client.NeedsMidRoundSync)
{
eventsToSync = GetEventsToSync(client, uniqueEvents);
eventsToSync = GetEventsToSync(client);
}
else
{
eventsToSync = GetEventsToSync(client, events);
eventsToSync = GetEventsToSync(client);
}
if (eventsToSync.Count == 0)
@@ -380,13 +380,13 @@ namespace Barotrauma.Networking
/// <summary>
/// Returns a list of events that should be sent to the client from the eventList
/// </summary>
/// <param name="client"></param>
/// <param name="eventList"></param>
/// <returns></returns>
private List<NetEntityEvent> GetEventsToSync(Client client, List<ServerEntityEvent> eventList)
private List<NetEntityEvent> GetEventsToSync(Client client)
{
List<NetEntityEvent> eventsToSync = new List<NetEntityEvent>();
if (eventList.Count == 0) return eventsToSync;
var eventList = client.NeedsMidRoundSync ? uniqueEvents : events;
if (eventList.Count == 0) { return eventsToSync; }
//find the index of the first event the client hasn't received
int startIndex = eventList.Count;
@@ -409,7 +409,18 @@ namespace Barotrauma.Networking
continue;
}
eventsToSync.AddRange(eventList.GetRange(i, eventList.Count - i));
if (client.NeedsMidRoundSync)
{
if (i <= client.UnreceivedEntityEventCount)
{
eventsToSync.AddRange(eventList.GetRange(i, client.UnreceivedEntityEventCount - i));
}
}
else
{
eventsToSync.AddRange(eventList.GetRange(i, eventList.Count - i));
}
break;
}

View File

@@ -6,7 +6,7 @@
<RootNamespace>Barotrauma</RootNamespace>
<Authors>FakeFish, Undertow Games</Authors>
<Product>Barotrauma Dedicated Server</Product>
<Version>0.9.700.0</Version>
<Version>0.9.701.0</Version>
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
<Platforms>AnyCPU;x64</Platforms>
<AssemblyName>DedicatedServer</AssemblyName>

View File

@@ -980,8 +980,7 @@ namespace Barotrauma
public void GiveJobItems(WayPoint spawnPoint = null)
{
if (info == null || info.Job == null) return;
if (info == null || info.Job == null) { return; }
info.Job.GiveJobItems(this, spawnPoint);
}

View File

@@ -420,7 +420,7 @@ namespace Barotrauma
if (logging)
{
var fileMd5 = new Md5Hash(hash);
DebugConsole.NewMessage(" " + file.Path + ": " + fileMd5.ShortHash);
DebugConsole.NewMessage(" " + file.Path + ": " + fileMd5.Hash);
}
hashes.Add(hash);
}
@@ -440,7 +440,7 @@ namespace Barotrauma
md5Hash = new Md5Hash(bytes);
if (logging)
{
DebugConsole.NewMessage("****************************** Package hash: " + md5Hash.ShortHash);
DebugConsole.NewMessage("****************************** Package hash: " + md5Hash.Hash);
}
}
@@ -470,6 +470,14 @@ namespace Barotrauma
break;
}
if (filePaths.Count > 1)
{
using (MD5 tempMd5 = MD5.Create())
{
filePaths = filePaths.OrderBy(f => ToolBox.StringToUInt32Hash(f.CleanUpPathCrossPlatform(true), tempMd5)).ToList();
}
}
foreach (string filePath in filePaths)
{
if (!File.Exists(filePath)) continue;

View File

@@ -489,6 +489,14 @@ namespace Barotrauma
}
}));
commands.Add(new Command("dumptofile", "", (string[] args) =>
{
string filename = "consoleOutput.txt";
if (args.Length > 0) { filename = string.Join(" ", args); }
File.WriteAllLines(filename, Messages.Select(m => m.Text).ToArray());
}));
commands.Add(new Command("findentityids", "findentityids [entityname]", (string[] args) =>
{
if (args.Length == 0) return;
@@ -924,6 +932,12 @@ namespace Barotrauma
}));
commands.Add(new Command("difficulty|leveldifficulty", "difficulty [0-100]: Change the level difficulty setting in the server lobby.", null));
commands.Add(new Command("autoitemplacerdebug|outfitdebug", "autoitemplacerdebug: Toggle automatic item placer debug info on/off. The automatically placed items are listed in the debug console at the start of a round.", (string[] args) =>
{
AutoItemPlacer.OutputDebugInfo = !AutoItemPlacer.OutputDebugInfo;
NewMessage((AutoItemPlacer.OutputDebugInfo ? "Enabled" : "Disabled") + " automatic item placer logging.", Color.White);
}, isCheat: false));
commands.Add(new Command("verboselogging", "verboselogging: Toggle verbose console logging on/off. When on, additional debug information is written to the debug console.", (string[] args) =>
{
@@ -1373,10 +1387,7 @@ namespace Barotrauma
var variant = job != null ? Rand.Range(0, job.Variants, Rand.RandSync.Server) : 0;
CharacterInfo characterInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobPrefab: job, variant: variant);
spawnedCharacter = Character.Create(characterInfo, spawnPosition, ToolBox.RandomSeed(8));
if (job != null)
{
spawnedCharacter.GiveJobItems(spawnPoint);
}
spawnedCharacter.GiveJobItems(spawnPoint);
if (GameMain.GameSession != null)
{

View File

@@ -10,6 +10,8 @@ namespace Barotrauma
{
private static readonly List<Item> spawnedItems = new List<Item>();
public static bool OutputDebugInfo = false;
public static void PlaceIfNeeded(GameMode gameMode)
{
if (GameMain.NetworkMember != null && !GameMain.NetworkMember.IsServer) { return; }
@@ -82,14 +84,24 @@ namespace Barotrauma
// Spawn items that don't have containers last
prefabsWithoutContainer.Randomize().ForEach(i => SpawnItems(i));
DebugConsole.NewMessage("Automatically placed items: ");
foreach (string itemName in spawnedItems.Select(it => it.Name).Distinct())
if (OutputDebugInfo)
{
DebugConsole.NewMessage(" - " + itemName + " x" + spawnedItems.Count(it => it.Name == itemName));
DebugConsole.NewMessage("Automatically placed items: ");
foreach (string itemName in spawnedItems.Select(it => it.Name).Distinct())
{
DebugConsole.NewMessage(" - " + itemName + " x" + spawnedItems.Count(it => it.Name == itemName));
}
}
bool SpawnItems(ItemPrefab itemPrefab)
{
if (itemPrefab == null)
{
string errorMsg = "Error in AutoItemPlacer.SpawnItems - itemPrefab was null.\n"+Environment.StackTrace;
DebugConsole.ThrowError(errorMsg);
GameAnalyticsManager.AddErrorEventOnce("AutoItemPlacer.SpawnItems:ItemNull", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
return false;
}
bool success = false;
foreach (PreferredContainer preferredContainer in itemPrefab.PreferredContainers)
{

View File

@@ -907,6 +907,7 @@ namespace Barotrauma
new XAttribute("width", GraphicsWidth),
new XAttribute("height", GraphicsHeight),
new XAttribute("vsync", VSyncEnabled),
new XAttribute("framelimit", Timing.FrameLimit),
new XAttribute("displaymode", windowMode));
}
@@ -1228,6 +1229,7 @@ namespace Barotrauma
new XAttribute("width", GraphicsWidth),
new XAttribute("height", GraphicsHeight),
new XAttribute("vsync", VSyncEnabled),
new XAttribute("framelimit", Timing.FrameLimit),
new XAttribute("displaymode", windowMode));
}
@@ -1423,6 +1425,7 @@ namespace Barotrauma
GraphicsWidth = graphicsMode.GetAttributeInt("width", GraphicsWidth);
GraphicsHeight = graphicsMode.GetAttributeInt("height", GraphicsHeight);
VSyncEnabled = graphicsMode.GetAttributeBool("vsync", VSyncEnabled);
Timing.FrameLimit = graphicsMode.GetAttributeInt("framelimit", 200);
XElement graphicsSettings = doc.Root.Element("graphicssettings");
ParticleLimit = graphicsSettings.GetAttributeInt("particlelimit", ParticleLimit);
@@ -1504,6 +1507,7 @@ namespace Barotrauma
GraphicsWidth = 0;
GraphicsHeight = 0;
VSyncEnabled = true;
Timing.FrameLimit = 200;
#if DEBUG
EnableSplashScreen = false;
#else

View File

@@ -1283,7 +1283,7 @@ namespace Barotrauma
}
}
ApplyStatusEffects(ActionType.Always, deltaTime, null);
ApplyStatusEffects(ActionType.Always, deltaTime, character: (parentInventory as CharacterInventory)?.Owner as Character);
for (int i = 0; i < updateableComponents.Count; i++)
{
@@ -1306,7 +1306,7 @@ namespace Barotrauma
#endif
ic.WasUsed = false;
ic.ApplyStatusEffects(parentInventory == null ? ActionType.OnNotContained : ActionType.OnContained, deltaTime);
ic.ApplyStatusEffects(parentInventory == null ? ActionType.OnNotContained : ActionType.OnContained, deltaTime, character: (parentInventory as CharacterInventory)?.Owner as Character);
if (ic.IsActive)
{

View File

@@ -228,7 +228,9 @@ namespace Barotrauma
if (hulls[i] == null) hulls[i] = Hull.FindHullOld(searchPos[i], null, false, true);
}
if (hulls[0] == null && hulls[1] == null) return;
if (hulls[1] == hulls[0]) { hulls[1] = null; }
if (hulls[0] == null && hulls[1] == null) { return; }
if (hulls[0] == null && hulls[1] != null)
{

View File

@@ -619,7 +619,10 @@ namespace Barotrauma
if (Bodies != null)
{
foreach (Body b in Bodies)
{
GameMain.World.Remove(b);
}
Bodies.Clear();
}
if (Sections != null)
@@ -648,7 +651,10 @@ namespace Barotrauma
if (Bodies != null)
{
foreach (Body b in Bodies)
{
GameMain.World.Remove(b);
}
Bodies.Clear();
}
if (Sections != null)

View File

@@ -14,6 +14,7 @@ namespace Barotrauma.Networking
private static Stream writeStream;
private static Stream readStream;
private static volatile bool shutDown;
private static ManualResetEvent writeManualResetEvent;
private static byte[] tempBytes;
private enum ReadState
@@ -49,6 +50,8 @@ namespace Barotrauma.Networking
readCancellationToken = new CancellationTokenSource();
writeManualResetEvent = new ManualResetEvent(false);
readThread = new Thread(UpdateRead);
writeThread = new Thread(UpdateWrite);
readThread.Start();
@@ -58,6 +61,7 @@ namespace Barotrauma.Networking
private static void PrivateShutDown()
{
shutDown = true;
writeManualResetEvent.Set();
readCancellationToken?.Cancel();
readThread?.Join(); readThread = null;
writeThread?.Join(); writeThread = null;
@@ -152,7 +156,11 @@ namespace Barotrauma.Networking
msgAvailable = msgsToWrite.TryDequeue(out msg);
}
}
Thread.Yield();
if (!shutDown)
{
writeManualResetEvent.Reset();
writeManualResetEvent.WaitOne();
}
}
}
@@ -163,6 +171,7 @@ namespace Barotrauma.Networking
lock (msgsToWrite)
{
msgsToWrite.Enqueue(msg);
writeManualResetEvent.Set();
}
}

View File

@@ -154,10 +154,16 @@ namespace Barotrauma.Networking
}
}
string fileName = ServerName + "_" + DateTime.Now.ToString("yyyy-MM-dd_HH:mm") + ".txt";
string fileName = ServerName + "_" + DateTime.Now.ToString("yyyy-MM-dd_HH:mm");
fileName = ToolBox.RemoveInvalidFileNameChars(fileName);
string filePath = Path.Combine(SavePath, fileName);
string filePath = Path.Combine(SavePath, fileName + ".txt");
int i = 2;
while (File.Exists(filePath))
{
filePath = Path.Combine(SavePath, fileName + " (" + i + ").txt");
i++;
}
try
{

View File

@@ -20,10 +20,12 @@
public virtual void Select()
{
if (selected != null && selected != this)
{
selected.Deselect();
#if CLIENT
GUI.ClearCursorWait();
//make sure any textbox in the previously selected screen doesn't stay selected
if (GUI.KeyboardDispatcher.Subscriber != DebugConsole.TextBox)
{

View File

@@ -10,7 +10,28 @@ namespace Barotrauma
public static double TotalTime;
public static double Accumulator;
public static double Step = 1.0 / 60.0;
public const int FixedUpdateRate = 60;
public static double Step = 1.0 / FixedUpdateRate;
private static int frameLimit;
/// <summary>
/// Maximum FPS (0 = unlimited).
/// </summary>
public static int FrameLimit
{
get { return frameLimit; }
set
{
if (value <= 0)
{
frameLimit = 0;
}
else
{
frameLimit = Math.Max(value, FixedUpdateRate);
}
}
}
public static double Alpha
{

View File

@@ -1,5 +1,25 @@
---------------------------------------------------------------------------------------------------------
v0.9.7000 (Unstable)
v0.9.701 (Unstable)
---------------------------------------------------------------------------------------------------------
- Fixed SteamP2P server hosting.
- Fixed a bug that caused "missing entity" errors when joining mid-round. Occurred if entities were created or removed while the client was in the process of getting in sync with the server, for example if the other players were firing turrets while the client was joining. However, there may still other bugs left that can cause the same "missing entity" error message.
- Cap the framerate to 200 FPS when VSync is off to prevent overloading the GPU. The cap can be adjusted by changing the "framelimit" attribute in config_player.xml.
- Rebalanced random events.
- Numerous fixes and improvements to Berilia.
- Give job items to humans spawned with the "spawn" command.
- Fixed content package hash mismatches between Windows and Linux.
- Fixed client crashing when disconnecting from the server as a host.
- Fixed clients crashing when an order message is received while in the server lobby.
- New sprites (that actually match the worn sprite) for dropped outfits.
- Slightly increased the view range of the coilguns and railguns.
- Cursor changes according to what it's hovered on (hand icon when on a button, caret icon when on a textbox, etc).
- The automatically placed items are not listed in the debug console by default anymore. Listing them can be re-enabled with the command "outfitdebug".
- Fixed crashing when saving structures into item assemblies.
- Fixed sub editor allowing vanilla subs to be deleted.
---------------------------------------------------------------------------------------------------------
v0.9.700 (Unstable)
---------------------------------------------------------------------------------------------------------
- Additional logging to diagnose event/entity ID errors: server and clients write a log file with a bunch of debug information the error happens. The files can be found in the ServerLogs folder after the error has occurred. If you get log files, please send them to us to help us diagnose these bugs!
@@ -24,10 +44,12 @@ v0.9.7.0
---------------------------------------------------------------------------------------------------------
UI/UX improvements:
- Graphical and functional overhaul of all user interfaces.
- Better feedback on shooting.
- Double clicking on an item moves it to the equipped inventory (e.g. ammo to the equipped weapon).
- Periscopes can be deselected by pressing esc.
- Fabricators can pull ingredients directly from the user's inventory without having to place them in the fabricator's input slots.
- Lock the on/off slider in the pump interface when the state is controlled by signals, same with the engine slider.
- Lock the on/off switch in the pump interface when the state is controlled by signals, same with the engine slider.
- 1 second cooldown before doors can be opened/closed after someone else has opened/closed them. Makes it less likely for doors to be opened/closed accidentally when multiple people are trying to use them at the same time.
- Show a warning if trying to start a campaign for the first time without playing the tutorials.
- Diving suits and fire extinguishers are not automatically picked up from the lockers/brackets when clicking on them to make it less likely to accidentally pick them up. Instead, clicking on them opens the inventory of the container, the same way when interacting with e.g. a steel cabinet.
@@ -58,7 +80,7 @@ Additions and changes:
- The job gear variants are not just visually different versions of the same item, but completely separate items. The job variants now allow the players to choose what kind of gear they want to spawn with, not just the look of the uniform.
- Attachable items and wire nodes can now be freely placed around the character instead of always being placed at the position of the character. When attaching items/wires, there's a placement grid that makes it much easier to neatly attach/wire things mid-round.
- The submarines now get automatically outfitted with a semi-random selection of supplies when starting a campaign. The items that have been manually placed in the submarine editor are kept as-is.
- Split internal damage into multiple subtypes: blunt force trauma, lacerations and bite wounds. The new afflictions are functionally identical to the default internal damage affliction, but can be used to identify the source of the injuries.
- Splitted internal damage into multiple subtypes: blunt force trauma, lacerations and bite wounds. The new afflictions are functionally identical to the default internal damage affliction, but can be used to identify the source of the injuries.
- Humans are more resistant to gunshot wounds, lacerations and blunt force trauma than monsters. The intention is to allow making weapons more effective towards monsters without making killing your crewmates with them too easy.
- Added a "terminal" item that can be used to send and display textual signals. Could be used for things such as terminals that send commands to devices or display some data received from devices.
- Added muzzle flashes to small firearms.

View File

@@ -82,8 +82,8 @@ namespace FarseerPhysics.Dynamics
BodyType = BodyType.Static;
}
public World World { get {return _world; } }
public World World { get { return _world; } }
public int IslandIndex { get; set; }
/// <summary>
@@ -350,7 +350,17 @@ namespace FarseerPhysics.Dynamics
/// Create all proxies.
/// </summary>
internal void CreateProxies()
{
{
for (int i = 0; i < FixtureList.Count; i++)
{
Debug.Assert(FixtureList[i].ProxyCount == 0, "Proxies already created for a Fixture.");
if (FixtureList[i].ProxyCount > 0)
{
DestroyProxies();
break;
}
}
IBroadPhase broadPhase = World.ContactManager.BroadPhase;
for (int i = 0; i < FixtureList.Count; i++)
FixtureList[i].CreateProxies(broadPhase, ref _xf);

View File

@@ -307,7 +307,7 @@ namespace FarseerPhysics.Dynamics
internal void CreateProxies(IBroadPhase broadPhase, ref Transform xf)
{
if (ProxyCount != 0)
throw new InvalidOperationException("Proxies allready created for this Fixture.");
throw new InvalidOperationException("Proxies already created for this Fixture.");
// Create proxies in the broad-phase.
ProxyCount = Shape.ChildCount;