(3a5d98b) v0.9.6.0
This commit is contained in:
@@ -85,8 +85,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (character.Inventory != null)
|
||||
{
|
||||
if (!character.LockHands && character.Stun < 0.1f &&
|
||||
(character.SelectedConstruction == null || character.SelectedConstruction?.GetComponent<Controller>()?.User != character))
|
||||
if (!LockInventory(character))
|
||||
{
|
||||
character.Inventory.Update(deltaTime, cam);
|
||||
}
|
||||
@@ -325,7 +324,7 @@ namespace Barotrauma
|
||||
}
|
||||
if (character.Inventory != null && !character.LockHands)
|
||||
{
|
||||
character.Inventory.Locked = (character.SelectedConstruction?.GetComponent<Controller>()?.User == character);
|
||||
character.Inventory.Locked = LockInventory(character);
|
||||
character.Inventory.DrawOwn(spriteBatch);
|
||||
character.Inventory.CurrentLayout = CharacterHealth.OpenHealthWindow == null && character.SelectedCharacter == null ?
|
||||
CharacterInventory.Layout.Default :
|
||||
@@ -368,6 +367,17 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private static bool LockInventory(Character character)
|
||||
{
|
||||
if (character?.Inventory == null || !character.AllowInput || character.LockHands) { return true; }
|
||||
|
||||
//lock if using a controller, except if we're also using a connection panel in the same item
|
||||
return
|
||||
character.SelectedConstruction != null &&
|
||||
character.SelectedConstruction?.GetComponent<Controller>()?.User == character &&
|
||||
character.SelectedConstruction?.GetComponent<ConnectionPanel>()?.User != character;
|
||||
}
|
||||
|
||||
private static void DrawOrderIndicator(SpriteBatch spriteBatch, Camera cam, Character character, Order order, float iconAlpha = 1.0f)
|
||||
{
|
||||
if (order.TargetAllCharacters)
|
||||
|
||||
@@ -2041,6 +2041,16 @@ namespace Barotrauma
|
||||
|
||||
commands.Add(new Command("spawnsub", "spawnsub [subname]: Spawn a submarine at the position of the cursor", (string[] args) =>
|
||||
{
|
||||
if (GameMain.NetworkMember != null)
|
||||
{
|
||||
ThrowError("Cannot spawn additional submarines during a multiplayer session.");
|
||||
return;
|
||||
}
|
||||
if (args.Length == 0)
|
||||
{
|
||||
ThrowError("Please enter the name of the submarine.");
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
Submarine spawnedSub = Submarine.Load(args[0], false);
|
||||
|
||||
@@ -220,6 +220,7 @@ namespace Barotrauma
|
||||
msgHolder.RectTransform.Resize(new Point(msgHolder.Rect.Width, msgHolder.Children.Sum(c => c.Rect.Height) + (int)(10 * GUI.Scale)), resizeChildren: false);
|
||||
msgHolder.RectTransform.SizeChanged += Recalculate;
|
||||
chatBox.RecalculateChildren();
|
||||
chatBox.UpdateScrollBarSize();
|
||||
}
|
||||
|
||||
CoroutineManager.StartCoroutine(UpdateMessageAnimation(msgHolder, 0.5f));
|
||||
|
||||
@@ -435,12 +435,30 @@ namespace Barotrauma
|
||||
|
||||
public void SelectNext(bool force = false, bool autoScroll = true)
|
||||
{
|
||||
Select(Math.Min(Content.CountChildren - 1, SelectedIndex + 1), force, autoScroll);
|
||||
int index = SelectedIndex + 1;
|
||||
while (index < Content.CountChildren)
|
||||
{
|
||||
if (Content.GetChild(index).Visible)
|
||||
{
|
||||
Select(index, force, autoScroll);
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
public void SelectPrevious(bool force = false, bool autoScroll = true)
|
||||
{
|
||||
Select(Math.Max(0, SelectedIndex - 1), force, autoScroll);
|
||||
int index = SelectedIndex - 1;
|
||||
while (index >= 0)
|
||||
{
|
||||
if (Content.GetChild(index).Visible)
|
||||
{
|
||||
Select(index, force, autoScroll);
|
||||
break;
|
||||
}
|
||||
index--;
|
||||
}
|
||||
}
|
||||
|
||||
public void Select(int childIndex, bool force = false, bool autoScroll = true)
|
||||
|
||||
@@ -233,7 +233,7 @@ namespace Barotrauma
|
||||
switch (InputType)
|
||||
{
|
||||
case NumberType.Int:
|
||||
TextBox.textFilterFunction = text => new string(text.Where(c => char.IsNumber(c)).ToArray());
|
||||
TextBox.textFilterFunction = text => new string(text.Where(c => char.IsNumber(c) || c == '-').ToArray());
|
||||
break;
|
||||
case NumberType.Float:
|
||||
TextBox.textFilterFunction = text => new string(text.Where(c => char.IsDigit(c) || c == '.' || c == '-').ToArray());
|
||||
|
||||
@@ -126,6 +126,11 @@ namespace Barotrauma
|
||||
set { text.Text = value; }
|
||||
}
|
||||
|
||||
public Color? DefaultTextColor
|
||||
{
|
||||
get { return defaultTextColor; }
|
||||
}
|
||||
|
||||
public GUITickBox(RectTransform rectT, string label, ScalableFont font = null, string style = "") : base(null, rectT)
|
||||
{
|
||||
CanBeFocused = true;
|
||||
|
||||
@@ -318,6 +318,8 @@ namespace Barotrauma
|
||||
|
||||
private void InitUserStats()
|
||||
{
|
||||
return;
|
||||
|
||||
if (GameSettings.ShowUserStatisticsPrompt)
|
||||
{
|
||||
if (TextManager.ContainsTag("statisticspromptheader") && TextManager.ContainsTag("statisticsprompttext"))
|
||||
@@ -404,14 +406,18 @@ namespace Barotrauma
|
||||
GUI.Init(Window, Config.SelectedContentPackages, GraphicsDevice);
|
||||
DebugConsole.Init();
|
||||
|
||||
if (Config.AutoUpdateWorkshopItems)
|
||||
CrossThread.RequestExecutionOnMainThread(() =>
|
||||
{
|
||||
if (SteamManager.AutoUpdateWorkshopItems())
|
||||
if (Config.AutoUpdateWorkshopItems)
|
||||
{
|
||||
ContentPackage.LoadAll();
|
||||
Config.ReloadContentPackages();
|
||||
if (SteamManager.AutoUpdateWorkshopItems())
|
||||
{
|
||||
ContentPackage.LoadAll();
|
||||
Config.ReloadContentPackages();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if (SelectedPackages.None())
|
||||
{
|
||||
@@ -844,6 +850,8 @@ namespace Barotrauma
|
||||
|
||||
SteamManager.Update((float)Timing.Step);
|
||||
|
||||
TaskPool.Update();
|
||||
|
||||
SoundManager?.Update();
|
||||
|
||||
Timing.Accumulator -= Timing.Step;
|
||||
|
||||
@@ -431,7 +431,6 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
characterArea.CanBeFocused = false;
|
||||
characterArea.CanBeSelected = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -204,9 +204,14 @@ namespace Barotrauma
|
||||
{
|
||||
campaign.SuppressStateSending = true;
|
||||
|
||||
campaign.Map.SetLocation(currentLocIndex == UInt16.MaxValue ? -1 : currentLocIndex);
|
||||
campaign.Map.SelectLocation(selectedLocIndex == UInt16.MaxValue ? -1 : selectedLocIndex);
|
||||
campaign.Map.SelectMission(selectedMissionIndex);
|
||||
//we need to have the latest save file to display location/mission/store
|
||||
if (campaign.LastSaveID == saveID)
|
||||
{
|
||||
campaign.Map.SetLocation(currentLocIndex == UInt16.MaxValue ? -1 : currentLocIndex);
|
||||
campaign.Map.SelectLocation(selectedLocIndex == UInt16.MaxValue ? -1 : selectedLocIndex);
|
||||
campaign.Map.SelectMission(selectedMissionIndex);
|
||||
campaign.CargoManager.SetPurchasedItems(purchasedItems);
|
||||
}
|
||||
|
||||
campaign.startWatchmanID = startWatchmanID;
|
||||
campaign.endWatchmanID = endWatchmanID;
|
||||
@@ -215,7 +220,6 @@ namespace Barotrauma
|
||||
campaign.PurchasedHullRepairs = purchasedHullRepairs;
|
||||
campaign.PurchasedItemRepairs = purchasedItemRepairs;
|
||||
campaign.PurchasedLostShuttles = purchasedLostShuttles;
|
||||
campaign.CargoManager.SetPurchasedItems(purchasedItems);
|
||||
|
||||
if (myCharacterInfo != null)
|
||||
{
|
||||
|
||||
@@ -108,7 +108,7 @@ namespace Barotrauma.Items.Components
|
||||
if (brokenSprite == null)
|
||||
{
|
||||
//broken doors turn black if no broken sprite has been configured
|
||||
color = color * (item.Condition / item.Prefab.Health);
|
||||
color *= (item.Condition / item.Prefab.Health);
|
||||
color.A = 255;
|
||||
}
|
||||
|
||||
@@ -184,7 +184,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
partial void SetState(bool open, bool isNetworkMessage, bool sendNetworkMessage, bool forcedOpen)
|
||||
{
|
||||
if (isStuck ||
|
||||
if ((IsStuck && !isNetworkMessage) ||
|
||||
(PredictedState == null && isOpen == open) ||
|
||||
(PredictedState != null && isOpen == PredictedState.Value && isOpen == open))
|
||||
{
|
||||
@@ -210,11 +210,7 @@ namespace Barotrauma.Items.Components
|
||||
StopPicking(null);
|
||||
PlaySound(forcedOpen ? ActionType.OnPicked : ActionType.OnUse, item.WorldPosition);
|
||||
}
|
||||
}
|
||||
|
||||
//opening a partially stuck door makes it less stuck
|
||||
if (isOpen) stuck = MathHelper.Clamp(stuck - 30.0f, 0.0f, 100.0f);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public override void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
||||
@@ -225,7 +221,7 @@ namespace Barotrauma.Items.Components
|
||||
bool forcedOpen = msg.ReadBoolean();
|
||||
SetState(open, isNetworkMessage: true, sendNetworkMessage: false, forcedOpen: forcedOpen);
|
||||
Stuck = msg.ReadRangedSingle(0.0f, 100.0f, 8);
|
||||
|
||||
if (isStuck) { OpenState = 0.0f; }
|
||||
PredictedState = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,20 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
get { return light; }
|
||||
}
|
||||
|
||||
|
||||
public override void OnScaleChanged()
|
||||
{
|
||||
light.SpriteScale = Vector2.One * item.Scale;
|
||||
light.Position = ParentBody != null ? ParentBody.Position : item.Position;
|
||||
}
|
||||
|
||||
partial void SetLightSourceState(bool enabled, float brightness)
|
||||
{
|
||||
if (light == null) { return; }
|
||||
light.Enabled = enabled;
|
||||
light.Color = LightColor * brightness;
|
||||
}
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing = false, float itemDepth = -1)
|
||||
{
|
||||
if (light.LightSprite != null && (item.body == null || item.body.Enabled) && lightBrightness > 0.0f)
|
||||
@@ -28,7 +41,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public override void FlipX(bool relativeToSub)
|
||||
{
|
||||
if (light?.LightSprite != null && item.Prefab.CanSpriteFlipX)
|
||||
if (light?.LightSprite != null && item.Prefab.CanSpriteFlipX && item.body == null)
|
||||
{
|
||||
light.LightSpriteEffect = light.LightSpriteEffect == SpriteEffects.None ?
|
||||
SpriteEffects.FlipHorizontally : SpriteEffects.None;
|
||||
@@ -39,5 +52,11 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
IsOn = msg.ReadBoolean();
|
||||
}
|
||||
|
||||
protected override void RemoveComponentSpecific()
|
||||
{
|
||||
base.RemoveComponentSpecific();
|
||||
light.Remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,6 +77,26 @@ namespace Barotrauma.Items.Components
|
||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
||||
{
|
||||
state = msg.ReadBoolean();
|
||||
ushort userID = msg.ReadUInt16();
|
||||
if (userID == 0)
|
||||
{
|
||||
if (user != null)
|
||||
{
|
||||
IsActive = false;
|
||||
CancelUsing(user);
|
||||
user = null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Character newUser = Entity.FindEntityByID(userID) as Character;
|
||||
if (newUser != user)
|
||||
{
|
||||
CancelUsing(user);
|
||||
}
|
||||
user = newUser;
|
||||
IsActive = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,18 +23,23 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
Enabled = false
|
||||
};
|
||||
powerIndicator.TextColor = powerIndicator.DefaultTextColor.Value;
|
||||
|
||||
highVoltageIndicator = new GUITickBox(new RectTransform(indicatorSize, paddedFrame.RectTransform) { AbsoluteOffset = new Point(0, (int)(40 * GUI.yScale)) },
|
||||
TextManager.Get("PowerTransferHighVoltage"), style: "IndicatorLightRed")
|
||||
{
|
||||
ToolTip = TextManager.Get("PowerTransferTipOvervoltage"),
|
||||
Enabled = false
|
||||
};
|
||||
highVoltageIndicator.TextColor = highVoltageIndicator.DefaultTextColor.Value;
|
||||
|
||||
lowVoltageIndicator = new GUITickBox(new RectTransform(indicatorSize, paddedFrame.RectTransform) { AbsoluteOffset = new Point(0, (int)(80 * GUI.yScale)) },
|
||||
TextManager.Get("PowerTransferLowVoltage"), style: "IndicatorLightRed")
|
||||
{
|
||||
ToolTip = TextManager.Get("PowerTransferTipLowvoltage"),
|
||||
Enabled = false
|
||||
};
|
||||
lowVoltageIndicator.TextColor = lowVoltageIndicator.DefaultTextColor.Value;
|
||||
|
||||
var textContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1.0f), paddedFrame.RectTransform, Anchor.TopRight));
|
||||
|
||||
|
||||
@@ -142,7 +142,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (repairSoundChannel == null || !repairSoundChannel.IsPlaying)
|
||||
{
|
||||
repairSoundChannel = SoundPlayer.PlaySound("repair", item.WorldPosition, hullGuess: item.CurrentHull);
|
||||
repairSoundChannel = SoundPlayer.PlaySound("repair", item.WorldPosition, hullGuess: item.CurrentHull);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -221,8 +221,17 @@ namespace Barotrauma.Items.Components
|
||||
deteriorationTimer = msg.ReadSingle();
|
||||
deteriorateAlwaysResetTimer = msg.ReadSingle();
|
||||
DeteriorateAlways = msg.ReadBoolean();
|
||||
CurrentFixer = msg.ReadBoolean() ? Character.Controlled : null;
|
||||
ushort currentFixerID = msg.ReadUInt16();
|
||||
currentFixerAction = (FixActions)msg.ReadRangedInteger(0, 2);
|
||||
|
||||
if (currentFixerID == 0)
|
||||
{
|
||||
CurrentFixer = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
CurrentFixer = Entity.FindEntityByID(currentFixerID) as Character;
|
||||
}
|
||||
}
|
||||
|
||||
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
||||
|
||||
@@ -119,6 +119,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
DrawWire(spriteBatch, draggingConnected, PlayerInput.MousePosition, new Vector2(x + width / 2, y + height - 10), null, panel, "");
|
||||
}
|
||||
panel.TriggerRewiringSound();
|
||||
|
||||
if (!PlayerInput.LeftButtonHeld())
|
||||
{
|
||||
@@ -129,7 +130,11 @@ namespace Barotrauma.Items.Components
|
||||
panel.DisconnectedWires.Add(draggingConnected);
|
||||
}
|
||||
|
||||
if (GameMain.Client != null) { panel.Item.CreateClientEvent(panel); }
|
||||
if (GameMain.Client != null)
|
||||
{
|
||||
panel.Item.CreateClientEvent(panel);
|
||||
}
|
||||
|
||||
draggingConnected = null;
|
||||
}
|
||||
}
|
||||
@@ -205,7 +210,10 @@ namespace Barotrauma.Items.Components
|
||||
SetWire(index, draggingConnected);
|
||||
}
|
||||
}
|
||||
if (GameMain.Client != null) { panel.Item.CreateClientEvent(panel); }
|
||||
if (GameMain.Client != null)
|
||||
{
|
||||
panel.Item.CreateClientEvent(panel);
|
||||
}
|
||||
draggingConnected = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,19 +11,28 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class ConnectionPanel : ItemComponent, IServerSerializable, IClientSerializable
|
||||
{
|
||||
//how long the rewiring sound plays after doing changes to the wiring
|
||||
const float RewireSoundDuration = 5.0f;
|
||||
|
||||
public static Wire HighlightedWire;
|
||||
|
||||
private SoundChannel rewireSoundChannel;
|
||||
private float rewireSoundTimer;
|
||||
|
||||
partial void InitProjSpecific(XElement element)
|
||||
{
|
||||
if (GuiFrame == null) return;
|
||||
if (GuiFrame == null) { return; }
|
||||
new GUICustomComponent(new RectTransform(Vector2.One, GuiFrame.RectTransform), DrawConnections, null)
|
||||
{
|
||||
UserData = this
|
||||
};
|
||||
}
|
||||
|
||||
public void TriggerRewiringSound()
|
||||
{
|
||||
rewireSoundTimer = RewireSoundDuration;
|
||||
}
|
||||
|
||||
partial void UpdateProjSpecific(float deltaTime)
|
||||
{
|
||||
foreach (Wire wire in DisconnectedWires)
|
||||
@@ -40,7 +49,9 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
}
|
||||
if (user != null && user.SelectedConstruction == item && HasRequiredItems(user, addMessage: false))
|
||||
|
||||
rewireSoundTimer -= deltaTime;
|
||||
if (user != null && user.SelectedConstruction == item && rewireSoundTimer > 0.0f)
|
||||
{
|
||||
if (rewireSoundChannel == null || !rewireSoundChannel.IsPlaying)
|
||||
{
|
||||
@@ -51,12 +62,13 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
rewireSoundChannel?.FadeOutAndDispose();
|
||||
rewireSoundChannel = null;
|
||||
rewireSoundTimer = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Move(Vector2 amount)
|
||||
{
|
||||
if (item.Submarine == null || item.Submarine.Loading || Screen.Selected != GameMain.SubEditorScreen) return;
|
||||
if (item.Submarine == null || item.Submarine.Loading || Screen.Selected != GameMain.SubEditorScreen) { return; }
|
||||
MoveConnectedWires(amount);
|
||||
}
|
||||
|
||||
@@ -103,6 +115,7 @@ namespace Barotrauma.Items.Components
|
||||
//delay reading the state until midround syncing is done
|
||||
//because some of the wires connected to the panel may not exist yet
|
||||
long msgStartPos = msg.BitPosition;
|
||||
msg.ReadUInt16(); //user ID
|
||||
foreach (Connection connection in Connections)
|
||||
{
|
||||
for (int i = 0; i < Connection.MaxLinked; i++)
|
||||
@@ -121,6 +134,8 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
else
|
||||
{
|
||||
//don't trigger rewiring sounds if the rewiring is being done by the local user (in that case we'll trigger it locally)
|
||||
if (Character.Controlled == null || user != Character.Controlled) { TriggerRewiringSound(); }
|
||||
ApplyRemoteState(msg);
|
||||
}
|
||||
}
|
||||
@@ -130,6 +145,17 @@ namespace Barotrauma.Items.Components
|
||||
List<Wire> prevWires = Connections.SelectMany(c => c.Wires.Where(w => w != null)).ToList();
|
||||
List<Wire> newWires = new List<Wire>();
|
||||
|
||||
ushort userID = msg.ReadUInt16();
|
||||
|
||||
if (userID == 0)
|
||||
{
|
||||
user = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
user = Entity.FindEntityByID(userID) as Character;
|
||||
}
|
||||
|
||||
foreach (Connection connection in Connections)
|
||||
{
|
||||
connection.ClearConnections();
|
||||
|
||||
@@ -145,6 +145,21 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
Dock(DockingTarget);
|
||||
if (joint == null)
|
||||
{
|
||||
string errorMsg = "Error while reading a docking port network event (Dock method did not create a joint between the ports)." +
|
||||
" Submarine: " + (item.Submarine?.Name ?? "null") +
|
||||
", target submarine: " + (DockingTarget.item.Submarine?.Name ?? "null");
|
||||
if (item.Submarine?.DockedTo.Contains(DockingTarget.item.Submarine) ?? false)
|
||||
{
|
||||
errorMsg += "\nAlready docked.";
|
||||
}
|
||||
if (item.Submarine == DockingTarget.item.Submarine)
|
||||
{
|
||||
errorMsg += "\nTrying to dock the submarine to itself.";
|
||||
}
|
||||
GameAnalyticsManager.AddErrorEventOnce("DockingPort.ClientRead:JointNotCreated", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
}
|
||||
|
||||
if (isLocked)
|
||||
{
|
||||
|
||||
@@ -916,21 +916,30 @@ namespace Barotrauma
|
||||
case NetEntityEvent.Type.ApplyStatusEffect:
|
||||
{
|
||||
ActionType actionType = (ActionType)msg.ReadRangedInteger(0, Enum.GetValues(typeof(ActionType)).Length - 1);
|
||||
byte componentIndex = msg.ReadByte();
|
||||
ushort targetID = msg.ReadUInt16();
|
||||
byte targetLimbID = msg.ReadByte();
|
||||
byte componentIndex = msg.ReadByte();
|
||||
ushort targetCharacterID = msg.ReadUInt16();
|
||||
byte targetLimbID = msg.ReadByte();
|
||||
ushort useTargetID = msg.ReadUInt16();
|
||||
Vector2? worldPosition = null;
|
||||
bool hasPosition = msg.ReadBoolean();
|
||||
if (hasPosition)
|
||||
{
|
||||
worldPosition = new Vector2(msg.ReadSingle(), msg.ReadSingle());
|
||||
}
|
||||
|
||||
ItemComponent targetComponent = componentIndex < components.Count ? components[componentIndex] : null;
|
||||
Character target = FindEntityByID(targetID) as Character;
|
||||
Limb targetLimb = target != null && targetLimbID < target.AnimController.Limbs.Length ? target.AnimController.Limbs[targetLimbID] : null;
|
||||
|
||||
Character targetCharacter = FindEntityByID(targetCharacterID) as Character;
|
||||
Limb targetLimb = targetCharacter != null && targetLimbID < targetCharacter.AnimController.Limbs.Length ?
|
||||
targetCharacter.AnimController.Limbs[targetLimbID] : null;
|
||||
Entity useTarget = FindEntityByID(useTargetID);
|
||||
|
||||
if (targetComponent == null)
|
||||
{
|
||||
ApplyStatusEffects(actionType, 1.0f, target, targetLimb, true);
|
||||
ApplyStatusEffects(actionType, 1.0f, targetCharacter, targetLimb, useTarget, true, worldPosition: worldPosition);
|
||||
}
|
||||
else
|
||||
{
|
||||
targetComponent.ApplyStatusEffects(actionType, 1.0f, target, targetLimb);
|
||||
targetComponent.ApplyStatusEffects(actionType, 1.0f, targetCharacter, targetLimb, useTarget, worldPosition: worldPosition);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -228,12 +228,12 @@ namespace Barotrauma.Lights
|
||||
activeLights.Clear();
|
||||
foreach (LightSource light in lights)
|
||||
{
|
||||
if (light.Color.A < 1 || light.Range < 1.0f || !light.Enabled) continue;
|
||||
if (!MathUtils.CircleIntersectsRectangle(light.WorldPosition, light.Range, viewRect)) continue;
|
||||
if (!light.Enabled) { continue; }
|
||||
if ((light.Color.A < 1 || light.Range < 1.0f) && !light.LightSourceParams.OverrideLightSpriteAlpha.HasValue) { continue; }
|
||||
if (!MathUtils.CircleIntersectsRectangle(light.WorldPosition, light.LightSourceParams.TextureRange, viewRect)) { continue; }
|
||||
activeLights.Add(light);
|
||||
}
|
||||
|
||||
|
||||
//clear the lightmap
|
||||
graphics.Clear(Color.Black);
|
||||
graphics.BlendState = BlendState.Additive;
|
||||
@@ -244,9 +244,9 @@ namespace Barotrauma.Lights
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Additive, transformMatrix: spriteBatchTransform);
|
||||
foreach (LightSource light in activeLights)
|
||||
{
|
||||
if (!light.IsBackground) continue;
|
||||
if (!light.IsBackground) { continue; }
|
||||
light.DrawSprite(spriteBatch, cam);
|
||||
light.DrawLightVolume(spriteBatch, lightEffect, transform);
|
||||
if (light.Color.A > 0 && light.Range > 0.0f) { light.DrawLightVolume(spriteBatch, lightEffect, transform); }
|
||||
backgroundSpritesDrawn = true;
|
||||
}
|
||||
GameMain.ParticleManager.Draw(spriteBatch, true, null, Particles.ParticleBlendState.Additive);
|
||||
@@ -288,7 +288,7 @@ namespace Barotrauma.Lights
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Additive, transformMatrix: spriteBatchTransform);
|
||||
foreach (LightSource light in activeLights)
|
||||
{
|
||||
if (light.IsBackground) continue;
|
||||
if (light.IsBackground) { continue; }
|
||||
light.DrawSprite(spriteBatch, cam);
|
||||
}
|
||||
spriteBatch.End();
|
||||
@@ -303,6 +303,8 @@ namespace Barotrauma.Lights
|
||||
//draw characters to obstruct the highlighted items/characters and light sprites
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
|
||||
SolidColorEffect.CurrentTechnique = SolidColorEffect.Techniques["SolidColor"];
|
||||
SolidColorEffect.Parameters["color"].SetValue(Color.Black.ToVector4());
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, effect: SolidColorEffect, transformMatrix: spriteBatchTransform);
|
||||
foreach (Character character in Character.CharacterList)
|
||||
{
|
||||
@@ -347,8 +349,8 @@ namespace Barotrauma.Lights
|
||||
|
||||
foreach (LightSource light in activeLights)
|
||||
{
|
||||
if (light.IsBackground) continue;
|
||||
light.DrawLightVolume(spriteBatch, lightEffect, transform);
|
||||
if (light.IsBackground) { continue; }
|
||||
if (light.Color.A > 0 && light.Range > 0.0f) { light.DrawLightVolume(spriteBatch, lightEffect, transform); }
|
||||
}
|
||||
Vector3 offset = Vector3.Zero;// new Vector3(Submarine.MainSub.DrawPosition.X, Submarine.MainSub.DrawPosition.Y, 0.0f);
|
||||
lightEffect.World = Matrix.CreateTranslation(Vector3.Zero) * transform;
|
||||
|
||||
@@ -31,10 +31,22 @@ namespace Barotrauma.Lights
|
||||
get { return range; }
|
||||
set
|
||||
{
|
||||
|
||||
range = MathHelper.Clamp(value, 0.0f, 2048.0f);
|
||||
TextureRange = range;
|
||||
if (OverrideLightTexture != null)
|
||||
{
|
||||
TextureRange += Math.Max(
|
||||
Math.Abs(OverrideLightTexture.RelativeOrigin.X - 0.5f) * OverrideLightTexture.size.X,
|
||||
Math.Abs(OverrideLightTexture.RelativeOrigin.Y - 0.5f) * OverrideLightTexture.size.Y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public float TextureRange
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public Sprite OverrideLightTexture
|
||||
{
|
||||
@@ -89,6 +101,8 @@ namespace Barotrauma.Lights
|
||||
break;
|
||||
case "lighttexture":
|
||||
OverrideLightTexture = new Sprite(subElement, preMultiplyAlpha: false);
|
||||
//refresh TextureRange
|
||||
Range = range;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -115,8 +129,16 @@ namespace Barotrauma.Lights
|
||||
|
||||
class LightSource
|
||||
{
|
||||
//how many pixels the position of the light needs to change for the light volume to be recalculated
|
||||
const float MovementRecalculationThreshold = 10.0f;
|
||||
//how many radians the light needs to rotate for the light volume to be recalculated
|
||||
const float RotationRecalculationThreshold = 0.02f;
|
||||
|
||||
private static Texture2D lightTexture;
|
||||
|
||||
private VertexPositionColorTexture[] vertices;
|
||||
private short[] indices;
|
||||
|
||||
private List<ConvexHullList> hullsInRange;
|
||||
|
||||
public Texture2D texture;
|
||||
@@ -167,6 +189,9 @@ namespace Barotrauma.Lights
|
||||
private int vertexCount;
|
||||
private int indexCount;
|
||||
|
||||
private Vector2 translateVertices;
|
||||
private float rotateVertices;
|
||||
|
||||
private readonly LightSourceParams lightSourceParams;
|
||||
|
||||
public LightSourceParams LightSourceParams => lightSourceParams;
|
||||
@@ -177,26 +202,38 @@ namespace Barotrauma.Lights
|
||||
get { return position; }
|
||||
set
|
||||
{
|
||||
if (Math.Abs(position.X - value.X) < 0.1f && Math.Abs(position.Y - value.Y) < 0.1f) return;
|
||||
Vector2 moveAmount = value - position;
|
||||
if (Math.Abs(moveAmount.X) < 0.1f && Math.Abs(moveAmount.Y) < 0.1f) { return; }
|
||||
position = value;
|
||||
|
||||
if (Vector2.DistanceSquared(prevCalculatedPosition, position) < 5.0f * 5.0f) return;
|
||||
//translate light volume manually instead of doing a full recalculation when moving by a small amount
|
||||
if (Vector2.DistanceSquared(prevCalculatedPosition, position) < MovementRecalculationThreshold * MovementRecalculationThreshold && vertices != null)
|
||||
{
|
||||
translateVertices = position - prevCalculatedPosition;
|
||||
return;
|
||||
}
|
||||
|
||||
NeedsHullCheck = true;
|
||||
NeedsRecalculation = true;
|
||||
prevCalculatedPosition = position;
|
||||
}
|
||||
}
|
||||
|
||||
private float prevCalculatedRotation;
|
||||
private float rotation;
|
||||
public float Rotation
|
||||
{
|
||||
get { return rotation; }
|
||||
set
|
||||
{
|
||||
if (Math.Abs(rotation - value) < 0.01f) return;
|
||||
if (Math.Abs(value - rotation) < 0.001f) { return; }
|
||||
rotation = value;
|
||||
|
||||
if (Math.Abs(rotation - prevCalculatedRotation) < RotationRecalculationThreshold && vertices != null)
|
||||
{
|
||||
rotateVertices = rotation - prevCalculatedRotation;
|
||||
return;
|
||||
}
|
||||
|
||||
NeedsHullCheck = true;
|
||||
NeedsRecalculation = true;
|
||||
}
|
||||
@@ -711,16 +748,25 @@ namespace Barotrauma.Lights
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
private void CalculateLightVertices(List<Vector2> rayCastHits)
|
||||
{
|
||||
List<VertexPositionColorTexture> vertices = new List<VertexPositionColorTexture>();
|
||||
vertexCount = rayCastHits.Count * 2 + 1;
|
||||
indexCount = (rayCastHits.Count) * 9;
|
||||
|
||||
//recreate arrays if they're too small or excessively large
|
||||
if (vertices == null || vertices.Length < vertexCount || vertices.Length > vertexCount * 3)
|
||||
{
|
||||
vertices = new VertexPositionColorTexture[vertexCount];
|
||||
indices = new short[indexCount];
|
||||
}
|
||||
|
||||
Vector2 drawPos = position;
|
||||
if (ParentSub != null) drawPos += ParentSub.DrawPosition;
|
||||
if (ParentSub != null) { drawPos += ParentSub.DrawPosition; }
|
||||
|
||||
float cosAngle = (float)Math.Cos(Rotation);
|
||||
float sinAngle = -(float)Math.Sin(Rotation);
|
||||
|
||||
|
||||
Vector2 uvOffset = Vector2.Zero;
|
||||
Vector2 overrideTextureDims = Vector2.One;
|
||||
if (OverrideLightTexture != null)
|
||||
@@ -728,15 +774,15 @@ namespace Barotrauma.Lights
|
||||
overrideTextureDims = new Vector2(OverrideLightTexture.SourceRect.Width, OverrideLightTexture.SourceRect.Height);
|
||||
|
||||
Vector2 origin = OverrideLightTexture.Origin;
|
||||
if (LightSpriteEffect == SpriteEffects.FlipHorizontally) origin.X = OverrideLightTexture.SourceRect.Width - origin.X;
|
||||
if (LightSpriteEffect == SpriteEffects.FlipVertically) origin.Y = (OverrideLightTexture.SourceRect.Height - origin.Y);
|
||||
if (LightSpriteEffect == SpriteEffects.FlipHorizontally) { origin.X = OverrideLightTexture.SourceRect.Width - origin.X; }
|
||||
if (LightSpriteEffect == SpriteEffects.FlipVertically) { origin.Y = OverrideLightTexture.SourceRect.Height - origin.Y; }
|
||||
uvOffset = (origin / overrideTextureDims) - new Vector2(0.5f, 0.5f);
|
||||
}
|
||||
|
||||
// Add a vertex for the center of the mesh
|
||||
vertices.Add(new VertexPositionColorTexture(new Vector3(position.X, position.Y, 0),
|
||||
Color.White, new Vector2(0.5f, 0.5f) + uvOffset));
|
||||
|
||||
vertices[0] = new VertexPositionColorTexture(new Vector3(position.X, position.Y, 0),
|
||||
Color.White, GetUV(new Vector2(0.5f, 0.5f) + uvOffset, LightSpriteEffect));
|
||||
|
||||
//hacky fix to exc excessively large light volumes (they used to be up to 4x the range of the light if there was nothing to block the rays).
|
||||
//might want to tweak the raycast logic in a way that this isn't necessary
|
||||
float boundRadius = Range * 1.1f / (1.0f - Math.Max(Math.Abs(uvOffset.X), Math.Abs(uvOffset.Y)));
|
||||
@@ -800,68 +846,88 @@ namespace Barotrauma.Lights
|
||||
|
||||
//finally, create the vertices
|
||||
VertexPositionColorTexture fullVert = new VertexPositionColorTexture(new Vector3(position.X + rawDiff.X, position.Y + rawDiff.Y, 0),
|
||||
Color.White, new Vector2(0.5f, 0.5f) + diff);
|
||||
Color.White, GetUV(new Vector2(0.5f, 0.5f) + diff, LightSpriteEffect));
|
||||
VertexPositionColorTexture fadeVert = new VertexPositionColorTexture(new Vector3(position.X + rawDiff.X + nDiff.X, position.Y + rawDiff.Y + nDiff.Y, 0),
|
||||
Color.White * 0.0f, new Vector2(0.5f, 0.5f) + diff);
|
||||
Color.White * 0.0f, GetUV(new Vector2(0.5f, 0.5f) + diff, LightSpriteEffect));
|
||||
|
||||
vertices.Add(fullVert);
|
||||
vertices.Add(fadeVert);
|
||||
vertices[1 + i * 2] = fullVert;
|
||||
vertices[1 + i * 2 + 1] = fadeVert;
|
||||
}
|
||||
|
||||
// Compute the indices to form triangles
|
||||
List<short> indices = new List<short>();
|
||||
for (int i = 0; i < rayCastHits.Count-1; i++)
|
||||
for (int i = 0; i < rayCastHits.Count - 1; i++)
|
||||
{
|
||||
//main light body
|
||||
indices.Add(0);
|
||||
indices.Add((short)((i*2 + 3) % vertices.Count));
|
||||
indices.Add((short)((i*2 + 1) % vertices.Count));
|
||||
|
||||
indices[i * 9] = 0;
|
||||
indices[i * 9 + 1] = (short)((i * 2 + 3) % vertexCount);
|
||||
indices[i * 9 + 2] = (short)((i * 2 + 1) % vertexCount);
|
||||
|
||||
//faded light
|
||||
indices.Add((short)((i*2 + 1) % vertices.Count));
|
||||
indices.Add((short)((i*2 + 3) % vertices.Count));
|
||||
indices.Add((short)((i*2 + 4) % vertices.Count));
|
||||
indices[i * 9 + 3] = (short)((i * 2 + 1) % vertexCount);
|
||||
indices[i * 9 + 4] = (short)((i * 2 + 3) % vertexCount);
|
||||
indices[i * 9 + 5] = (short)((i * 2 + 4) % vertexCount);
|
||||
|
||||
indices.Add((short)((i*2 + 2) % vertices.Count));
|
||||
indices.Add((short)((i*2 + 1) % vertices.Count));
|
||||
indices.Add((short)((i*2 + 4) % vertices.Count));
|
||||
indices[i * 9 + 6] = (short)((i * 2 + 2) % vertexCount);
|
||||
indices[i * 9 + 7] = (short)((i * 2 + 1) % vertexCount);
|
||||
indices[i * 9 + 8] = (short)((i * 2 + 4) % vertexCount);
|
||||
}
|
||||
|
||||
|
||||
//main light body
|
||||
indices.Add(0);
|
||||
indices.Add((short)(1));
|
||||
indices.Add((short)(vertices.Count - 2));
|
||||
|
||||
indices[(rayCastHits.Count - 1) * 9] = 0;
|
||||
indices[(rayCastHits.Count - 1) * 9 + 1] = (short)(1);
|
||||
indices[(rayCastHits.Count - 1) * 9 + 2] = (short)(vertexCount - 2);
|
||||
|
||||
//faded light
|
||||
indices.Add((short)(1));
|
||||
indices.Add((short)(vertices.Count-1));
|
||||
indices.Add((short)(vertices.Count-2));
|
||||
indices[(rayCastHits.Count - 1) * 9 + 3] = (short)(1);
|
||||
indices[(rayCastHits.Count - 1) * 9 + 4] = (short)(vertexCount - 1);
|
||||
indices[(rayCastHits.Count - 1) * 9 + 5] = (short)(vertexCount - 2);
|
||||
|
||||
indices.Add((short)(1));
|
||||
indices.Add((short)(2));
|
||||
indices.Add((short)(vertices.Count-1));
|
||||
|
||||
vertexCount = vertices.Count;
|
||||
indexCount = indices.Count;
|
||||
indices[(rayCastHits.Count - 1) * 9 + 6] = (short)(1);
|
||||
indices[(rayCastHits.Count - 1) * 9 + 7] = (short)(2);
|
||||
indices[(rayCastHits.Count - 1) * 9 + 8] = (short)(vertexCount - 1);
|
||||
|
||||
//TODO: a better way to determine the size of the vertex buffer and handle changes in size?
|
||||
//now we just create a buffer for 64 verts and make it larger if needed
|
||||
if (lightVolumeBuffer == null)
|
||||
{
|
||||
lightVolumeBuffer = new DynamicVertexBuffer(GameMain.Instance.GraphicsDevice, VertexPositionColorTexture.VertexDeclaration, Math.Max(64, (int)(vertexCount*1.5)), BufferUsage.None);
|
||||
lightVolumeIndexBuffer = new DynamicIndexBuffer(GameMain.Instance.GraphicsDevice, typeof(short), Math.Max(64*3, (int)(indexCount * 1.5)), BufferUsage.None);
|
||||
lightVolumeBuffer = new DynamicVertexBuffer(GameMain.Instance.GraphicsDevice, VertexPositionColorTexture.VertexDeclaration, Math.Max(64, (int)(vertexCount * 1.5)), BufferUsage.None);
|
||||
lightVolumeIndexBuffer = new DynamicIndexBuffer(GameMain.Instance.GraphicsDevice, typeof(short), Math.Max(64 * 3, (int)(indexCount * 1.5)), BufferUsage.None);
|
||||
}
|
||||
else if (vertexCount > lightVolumeBuffer.VertexCount || indexCount > lightVolumeIndexBuffer.IndexCount)
|
||||
{
|
||||
lightVolumeBuffer.Dispose();
|
||||
lightVolumeIndexBuffer.Dispose();
|
||||
|
||||
lightVolumeBuffer = new DynamicVertexBuffer(GameMain.Instance.GraphicsDevice, VertexPositionColorTexture.VertexDeclaration, (int)(vertexCount*1.5), BufferUsage.None);
|
||||
lightVolumeBuffer = new DynamicVertexBuffer(GameMain.Instance.GraphicsDevice, VertexPositionColorTexture.VertexDeclaration, (int)(vertexCount * 1.5), BufferUsage.None);
|
||||
lightVolumeIndexBuffer = new DynamicIndexBuffer(GameMain.Instance.GraphicsDevice, typeof(short), (int)(indexCount * 1.5), BufferUsage.None);
|
||||
}
|
||||
|
||||
lightVolumeBuffer.SetData<VertexPositionColorTexture>(vertices.ToArray());
|
||||
lightVolumeIndexBuffer.SetData<short>(indices.ToArray());
|
||||
|
||||
lightVolumeBuffer.SetData<VertexPositionColorTexture>(vertices, 0, vertexCount);
|
||||
lightVolumeIndexBuffer.SetData<short>(indices, 0, indexCount);
|
||||
|
||||
Vector2 GetUV(Vector2 vert, SpriteEffects effects)
|
||||
{
|
||||
if (effects == SpriteEffects.FlipHorizontally)
|
||||
{
|
||||
vert.X = 1.0f - vert.X;
|
||||
}
|
||||
else if (effects == SpriteEffects.FlipVertically)
|
||||
{
|
||||
vert.Y = 1.0f - vert.Y;
|
||||
}
|
||||
else if (effects == (SpriteEffects.FlipHorizontally | SpriteEffects.FlipVertically))
|
||||
{
|
||||
vert.X = 1.0f - vert.X;
|
||||
vert.Y = 1.0f - vert.Y;
|
||||
}
|
||||
vert.Y = 1.0f - vert.Y;
|
||||
return vert;
|
||||
}
|
||||
|
||||
translateVertices = Vector2.Zero;
|
||||
rotateVertices = 0.0f;
|
||||
prevCalculatedPosition = position;
|
||||
prevCalculatedRotation = rotation;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -944,15 +1010,12 @@ namespace Barotrauma.Lights
|
||||
|
||||
Vector2 drawPos = position;
|
||||
if (ParentSub != null) drawPos += ParentSub.DrawPosition;
|
||||
drawPos.Y = -drawPos.Y;
|
||||
drawPos.Y = -drawPos.Y;
|
||||
|
||||
spriteBatch.Draw(currentTexture, drawPos, null, Color, -rotation, center, scale, SpriteEffects.None, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
Vector3 offset = ParentSub == null ?
|
||||
Vector3.Zero : new Vector3(ParentSub.DrawPosition.X, ParentSub.DrawPosition.Y, 0.0f);
|
||||
lightEffect.World = Matrix.CreateTranslation(offset) * transform;
|
||||
|
||||
if (NeedsRecalculation)
|
||||
{
|
||||
@@ -962,8 +1025,16 @@ namespace Barotrauma.Lights
|
||||
lastRecalculationTime = (float)Timing.TotalTime;
|
||||
NeedsRecalculation = false;
|
||||
}
|
||||
|
||||
if (vertexCount == 0) return;
|
||||
|
||||
|
||||
Vector2 offset = ParentSub == null ? Vector2.Zero : ParentSub.DrawPosition;
|
||||
lightEffect.World =
|
||||
Matrix.CreateTranslation(-new Vector3(position, 0.0f)) *
|
||||
Matrix.CreateRotationZ(rotateVertices) *
|
||||
Matrix.CreateTranslation(new Vector3(position + offset + translateVertices, 0.0f)) *
|
||||
transform;
|
||||
|
||||
if (vertexCount == 0) { return; }
|
||||
|
||||
lightEffect.DiffuseColor = (new Vector3(Color.R, Color.G, Color.B) * (Color.A / 255.0f)) / 255.0f;
|
||||
if (OverrideLightTexture != null)
|
||||
|
||||
@@ -483,6 +483,8 @@ namespace Barotrauma.Networking
|
||||
if (DateTime.Now > timeOut)
|
||||
{
|
||||
clientPeer?.Close(Lidgren.Network.NetConnection.NoResponseMessage);
|
||||
var msgBox = new GUIMessageBox(TextManager.Get("ConnectionFailed"), TextManager.Get("CouldNotConnectToServer"));
|
||||
msgBox.Buttons[0].OnClicked += ReturnToPreviousMenu;
|
||||
reconnectBox?.Close(); reconnectBox = null;
|
||||
break;
|
||||
}
|
||||
@@ -1232,7 +1234,9 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (Level.Loaded.EqualityCheckVal != levelEqualityCheckVal)
|
||||
{
|
||||
string errorMsg = "Level equality check failed. The level generated at your end doesn't match the level generated by the server (seed " + Level.Loaded.Seed + ").";
|
||||
string errorMsg = "Level equality check failed. The level generated at your end doesn't match the level generated by the server (seed: " + Level.Loaded.Seed +
|
||||
", sub: " + Submarine.MainSub.Name + " (" + Submarine.MainSub.MD5Hash.ShortHash + ")" +
|
||||
", mirrored: " + Level.Loaded.Mirrored + ").";
|
||||
DebugConsole.ThrowError(errorMsg, createMessageBox: true);
|
||||
GameAnalyticsManager.AddErrorEventOnce("GameClient.StartGame:LevelsDontMatch" + levelSeed, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
CoroutineManager.StartCoroutine(EndGame(""));
|
||||
@@ -1274,6 +1278,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
gameStarted = false;
|
||||
Character.Controlled = null;
|
||||
SpawnAsTraitor = false;
|
||||
GameMain.GameScreen.Cam.TargetPos = Vector2.Zero;
|
||||
GameMain.LightManager.LosEnabled = false;
|
||||
respawnManager = null;
|
||||
@@ -1432,6 +1437,8 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
private bool initialUpdateReceived;
|
||||
|
||||
private void ReadLobbyUpdate(IReadMessage inc)
|
||||
{
|
||||
ServerNetObject objHeader;
|
||||
@@ -1452,13 +1459,15 @@ namespace Barotrauma.Networking
|
||||
UInt16 settingsLen = inc.ReadUInt16();
|
||||
byte[] settingsData = inc.ReadBytes(settingsLen);
|
||||
|
||||
if (inc.ReadBoolean())
|
||||
bool isInitialUpdate = inc.ReadBoolean();
|
||||
if (isInitialUpdate)
|
||||
{
|
||||
if (GameSettings.VerboseLogging)
|
||||
{
|
||||
DebugConsole.NewMessage("Received initial lobby update, ID: " + updateID + ", last ID: " + GameMain.NetLobbyScreen.LastUpdateID, Color.Gray);
|
||||
}
|
||||
ReadInitialUpdate(inc);
|
||||
initialUpdateReceived = true;
|
||||
}
|
||||
|
||||
string selectSubName = inc.ReadString();
|
||||
@@ -1489,7 +1498,9 @@ namespace Barotrauma.Networking
|
||||
float autoRestartTimer = autoRestartEnabled ? inc.ReadSingle() : 0.0f;
|
||||
|
||||
//ignore the message if we already a more up-to-date one
|
||||
if (NetIdUtils.IdMoreRecent(updateID, GameMain.NetLobbyScreen.LastUpdateID))
|
||||
//or if we're still waiting for the initial update
|
||||
if (NetIdUtils.IdMoreRecent(updateID, GameMain.NetLobbyScreen.LastUpdateID) &&
|
||||
(isInitialUpdate || initialUpdateReceived))
|
||||
{
|
||||
ReadWriteMessage settingsBuf = new ReadWriteMessage();
|
||||
settingsBuf.Write(settingsData, 0, settingsLen); settingsBuf.BitPosition = 0;
|
||||
@@ -2248,12 +2259,10 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (gameStarted)
|
||||
{
|
||||
tickBox.Visible = false;
|
||||
tickBox.Parent.Visible = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
Vote(VoteType.StartRound, tickBox.Selected);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+16
-1
@@ -200,6 +200,7 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
|
||||
msg.BitPosition += msgLength * 8;
|
||||
msg.ReadPadBits();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -213,6 +214,20 @@ namespace Barotrauma.Networking
|
||||
try
|
||||
{
|
||||
ReadEvent(msg, entity, sendingTime);
|
||||
msg.ReadPadBits();
|
||||
|
||||
if (msg.BitPosition != msgPosition + msgLength * 8)
|
||||
{
|
||||
string errorMsg = "Message byte position incorrect after reading an event for the entity \"" + entity.ToString()
|
||||
+ "\". Read " + (msg.BitPosition - msgPosition) + " bits, expected message length was " + (msgLength * 8) + " bits.";
|
||||
#if DEBUG
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
#endif
|
||||
GameAnalyticsManager.AddErrorEventOnce("ClientEntityEventManager.Read:BitPosMismatch", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
|
||||
//TODO: force the BitPosition to correct place? Having some entity in a potentially incorrect state is not as bad as a desync kick
|
||||
//msg.BitPosition = (int)(msgPosition + msgLength * 8);
|
||||
}
|
||||
}
|
||||
|
||||
catch (Exception e)
|
||||
@@ -231,9 +246,9 @@ namespace Barotrauma.Networking
|
||||
GameAnalyticsManager.AddErrorEventOnce("ClientEntityEventManager.Read:ReadFailed" + entity.ToString(),
|
||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
msg.BitPosition = (int)(msgPosition + msgLength * 8);
|
||||
msg.ReadPadBits();
|
||||
}
|
||||
}
|
||||
msg.ReadPadBits();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -275,6 +275,7 @@ namespace Barotrauma.Networking
|
||||
#if DEBUG
|
||||
CoroutineManager.InvokeAfter(() =>
|
||||
{
|
||||
if (GameMain.Client == null) { return; }
|
||||
if (Rand.Range(0.0f, 1.0f) < GameMain.Client.SimulatedLoss && sendType != Facepunch.Steamworks.Networking.SendType.Reliable) { return; }
|
||||
int count = Rand.Range(0.0f, 1.0f) < GameMain.Client.SimulatedDuplicatesChance ? 2 : 1;
|
||||
for (int i = 0; i < count; i++)
|
||||
|
||||
@@ -18,7 +18,17 @@ namespace Barotrauma.Networking
|
||||
public UInt64 OwnerID;
|
||||
public bool OwnerVerified;
|
||||
|
||||
public string ServerName;
|
||||
private string serverName;
|
||||
public string ServerName
|
||||
{
|
||||
get { return serverName; }
|
||||
set
|
||||
{
|
||||
serverName = value;
|
||||
if (serverName.Length > NetConfig.ServerNameMaxLength) { ServerName = ServerName.Substring(0, NetConfig.ServerNameMaxLength); }
|
||||
}
|
||||
}
|
||||
|
||||
public string ServerMessage;
|
||||
public bool GameStarted;
|
||||
public int PlayerCount;
|
||||
@@ -455,38 +465,7 @@ namespace Barotrauma.Networking
|
||||
if (SteamFriend.IsPlayingThisGame && SteamFriend.ServerLobbyId != 0)
|
||||
{
|
||||
LobbyID = SteamFriend.ServerLobbyId;
|
||||
SteamManager.Instance.LobbyList.SetManualLobbyDataCallback(LobbyID, (lobby) =>
|
||||
{
|
||||
SteamManager.Instance.LobbyList.SetManualLobbyDataCallback(LobbyID, null);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(lobby.GetData("haspassword"))) { return; }
|
||||
bool.TryParse(lobby.GetData("haspassword"), out bool hasPassword);
|
||||
int.TryParse(lobby.GetData("playercount"), out int currPlayers);
|
||||
int.TryParse(lobby.GetData("maxplayernum"), out int maxPlayers);
|
||||
//UInt64.TryParse(lobby.GetData("connectsteamid"), out ulong connectSteamId);
|
||||
string ip = lobby.GetData("hostipaddress");
|
||||
UInt64 ownerId = SteamManager.SteamIDStringToUInt64(lobby.GetData("lobbyowner"));
|
||||
|
||||
if (OwnerID != ownerId) { return; }
|
||||
|
||||
if (string.IsNullOrWhiteSpace(ip)) { ip = ""; }
|
||||
|
||||
ServerName = lobby.Name;
|
||||
Port = "";
|
||||
QueryPort = "";
|
||||
IP = ip;
|
||||
PlayerCount = currPlayers;
|
||||
MaxPlayers = maxPlayers;
|
||||
HasPassword = hasPassword;
|
||||
RespondedToSteamQuery = true;
|
||||
LobbyID = lobby.LobbyID;
|
||||
OwnerID = ownerId;
|
||||
PingChecked = false;
|
||||
OwnerVerified = true;
|
||||
SteamManager.AssignLobbyDataToServerInfo(lobby, this);
|
||||
|
||||
onServerRulesReceived?.Invoke(this);
|
||||
});
|
||||
|
||||
SteamManager.Instance.LobbyList.RequestLobbyData(LobbyID);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -326,8 +326,8 @@ namespace Barotrauma.Steam
|
||||
localQuery.OnFinished = onFinished;
|
||||
#endif
|
||||
|
||||
instance.client.LobbyList.OnLobbiesUpdated = () => { UpdateLobbyQuery(onServerFound, onServerRulesReceived, onFinished); };
|
||||
instance.client.LobbyList.Refresh();
|
||||
|
||||
instance.client.LobbyList.Request();
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -382,42 +382,6 @@ namespace Barotrauma.Steam
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void UpdateLobbyQuery(Action<Networking.ServerInfo> onServerFound, Action<Networking.ServerInfo> onServerRulesReceived, Action onFinished)
|
||||
{
|
||||
foreach (LobbyList.Lobby lobby in instance.client.LobbyList.Lobbies)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(lobby.GetData("haspassword"))) { continue; }
|
||||
bool.TryParse(lobby.GetData("haspassword"), out bool hasPassword);
|
||||
int.TryParse(lobby.GetData("playercount"), out int currPlayers);
|
||||
int.TryParse(lobby.GetData("maxplayernum"), out int maxPlayers);
|
||||
UInt64 ownerId = SteamIDStringToUInt64(lobby.GetData("lobbyowner"));
|
||||
//UInt64.TryParse(lobby.GetData("connectsteamid"), out ulong connectSteamId);
|
||||
string ip = lobby.GetData("hostipaddress");
|
||||
if (string.IsNullOrWhiteSpace(ip)) { ip = ""; }
|
||||
|
||||
var serverInfo = new ServerInfo()
|
||||
{
|
||||
ServerName = lobby.Name,
|
||||
Port = "",
|
||||
QueryPort = "",
|
||||
IP = ip,
|
||||
PlayerCount = currPlayers,
|
||||
MaxPlayers = maxPlayers,
|
||||
HasPassword = hasPassword,
|
||||
RespondedToSteamQuery = true,
|
||||
LobbyID = lobby.LobbyID,
|
||||
OwnerID = ownerId
|
||||
};
|
||||
serverInfo.PingChecked = false;
|
||||
AssignLobbyDataToServerInfo(lobby, serverInfo);
|
||||
|
||||
onServerFound(serverInfo);
|
||||
//onServerRulesReceived(serverInfo);
|
||||
}
|
||||
|
||||
onFinished();
|
||||
}
|
||||
|
||||
public static void AssignLobbyDataToServerInfo(LobbyList.Lobby lobby, ServerInfo serverInfo)
|
||||
{
|
||||
serverInfo.ServerMessage = lobby.GetData("message");
|
||||
@@ -495,6 +459,7 @@ namespace Barotrauma.Steam
|
||||
serverInfo.PingChecked = true;
|
||||
serverInfo.Ping = s.Ping;
|
||||
serverInfo.LobbyID = 0;
|
||||
serverInfo.OwnerVerified = true;
|
||||
if (responded)
|
||||
{
|
||||
s.FetchRules();
|
||||
|
||||
@@ -248,8 +248,10 @@ namespace Barotrauma
|
||||
MapEntityCategory newCategory = (MapEntityCategory)userdata;
|
||||
if (newCategory != selectedItemCategory)
|
||||
{
|
||||
searchBox.Text = "";
|
||||
searchBox.Text = "";
|
||||
storeItemList.ScrollBar.BarScroll = 0f;
|
||||
}
|
||||
|
||||
FilterStoreItems((MapEntityCategory)userdata, searchBox.Text);
|
||||
return true;
|
||||
}
|
||||
@@ -947,7 +949,9 @@ namespace Barotrauma
|
||||
var itemFrame = myItemList.Content.GetChildByUserData(pi);
|
||||
if (itemFrame == null)
|
||||
{
|
||||
itemFrame = CreateItemFrame(pi, pi.ItemPrefab.GetPrice(Campaign.Map.CurrentLocation), myItemList);
|
||||
var priceInfo = pi.ItemPrefab.GetPrice(Campaign.Map.CurrentLocation);
|
||||
if (priceInfo == null) { continue; }
|
||||
itemFrame = CreateItemFrame(pi, priceInfo, myItemList);
|
||||
}
|
||||
itemFrame.GetChild(0).GetChild<GUINumberInput>().IntValue = pi.Quantity;
|
||||
existingItemFrames.Add(itemFrame);
|
||||
|
||||
+15
-11
@@ -99,6 +99,7 @@ namespace Barotrauma.CharacterEditor
|
||||
private Rectangle spriteSheetRect;
|
||||
|
||||
private Rectangle CalculateSpritesheetRectangle() =>
|
||||
Textures == null || Textures.None() ? Rectangle.Empty :
|
||||
new Rectangle(
|
||||
spriteSheetOffsetX,
|
||||
spriteSheetOffsetY,
|
||||
@@ -656,12 +657,6 @@ namespace Barotrauma.CharacterEditor
|
||||
}
|
||||
if (!isFrozen)
|
||||
{
|
||||
if (character.AnimController.Invalid)
|
||||
{
|
||||
Reset(new Character[] { character });
|
||||
SpawnCharacter(currentCharacterConfig);
|
||||
}
|
||||
|
||||
Submarine.MainSub.SetPrevTransform(Submarine.MainSub.Position);
|
||||
Submarine.MainSub.Update((float)deltaTime);
|
||||
|
||||
@@ -722,6 +717,7 @@ namespace Barotrauma.CharacterEditor
|
||||
foreach (Limb limb in character.AnimController.Limbs)
|
||||
{
|
||||
if (limb == null || limb.ActiveSprite == null) { continue; }
|
||||
if (selectedJoints.Any(j => j.LimbA == limb || j.LimbB == limb)) { continue; }
|
||||
// Select limbs on ragdoll
|
||||
if (editLimbs && !spriteSheetRect.Contains(PlayerInput.MousePosition) && MathUtils.RectangleContainsPoint(GetLimbPhysicRect(limb), PlayerInput.MousePosition))
|
||||
{
|
||||
@@ -2727,11 +2723,19 @@ namespace Barotrauma.CharacterEditor
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
character.Params.Save();
|
||||
GUI.AddMessage(GetCharacterEditorTranslation("CharacterSavedTo").Replace("[path]", CharacterParams.FullPath), Color.Green, font: GUI.Font, lifeTime: 5);
|
||||
character.AnimController.SaveRagdoll();
|
||||
GUI.AddMessage(GetCharacterEditorTranslation("RagdollSavedTo").Replace("[path]", RagdollParams.FullPath), Color.Green, font: GUI.Font, lifeTime: 5);
|
||||
AnimParams.ForEach(p => p.Save());
|
||||
if (!string.IsNullOrEmpty(RagdollParams.Texture) && !File.Exists(RagdollParams.Texture))
|
||||
{
|
||||
DebugConsole.ThrowError($"Invalid texture path: {RagdollParams.Texture}");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
character.Params.Save();
|
||||
GUI.AddMessage(GetCharacterEditorTranslation("CharacterSavedTo").Replace("[path]", CharacterParams.FullPath), Color.Green, font: GUI.Font, lifeTime: 5);
|
||||
character.AnimController.SaveRagdoll();
|
||||
GUI.AddMessage(GetCharacterEditorTranslation("RagdollSavedTo").Replace("[path]", RagdollParams.FullPath), Color.Green, font: GUI.Font, lifeTime: 5);
|
||||
AnimParams.ForEach(p => p.Save());
|
||||
}
|
||||
return true;
|
||||
};
|
||||
// Spacing
|
||||
|
||||
@@ -40,6 +40,10 @@ namespace Barotrauma.CharacterEditor
|
||||
canEnterSubmarine = ragdoll.CanEnterSubmarine;
|
||||
canWalk = ragdoll.CanWalk;
|
||||
texturePath = ragdoll.Texture;
|
||||
if (string.IsNullOrEmpty(texturePath) && !name.Equals(Character.HumanSpeciesName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
texturePath = ragdoll.Limbs.FirstOrDefault()?.GetSprite().Texture;
|
||||
}
|
||||
}
|
||||
|
||||
public static Wizard instance;
|
||||
@@ -265,8 +269,30 @@ namespace Barotrauma.CharacterEditor
|
||||
};
|
||||
if (ofd.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
string file = ofd.FileName;
|
||||
string relativePath = UpdaterUtil.GetRelativePath(Path.GetFullPath(file), Environment.CurrentDirectory);
|
||||
string destinationPath = relativePath;
|
||||
|
||||
//copy file to XML path if it's not located relative to the game's files
|
||||
if (relativePath.StartsWith("..") ||
|
||||
Path.GetPathRoot(Environment.CurrentDirectory) != Path.GetPathRoot(file))
|
||||
{
|
||||
destinationPath = Path.Combine(Path.GetDirectoryName(XMLPath), Path.GetFileName(file));
|
||||
|
||||
string destinationDir = Path.GetDirectoryName(destinationPath);
|
||||
if (!Directory.Exists(destinationDir))
|
||||
{
|
||||
Directory.CreateDirectory(destinationDir);
|
||||
}
|
||||
|
||||
if (!File.Exists(destinationPath))
|
||||
{
|
||||
File.Copy(file, Path.GetFullPath(destinationPath), overwrite: true);
|
||||
}
|
||||
}
|
||||
|
||||
isTextureSelected = true;
|
||||
texturePathElement.Text = ToolBox.ConvertAbsoluteToRelativePath(ofd.FileName);
|
||||
texturePathElement.Text = destinationPath;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using RestSharp;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@@ -84,7 +85,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
#else
|
||||
FetchRemoteContent(Frame.RectTransform);
|
||||
FetchRemoteContent();
|
||||
#endif
|
||||
|
||||
|
||||
@@ -753,12 +754,20 @@ namespace Barotrauma
|
||||
exeName = "DedicatedServer.exe";
|
||||
}
|
||||
|
||||
string arguments = "-name \"" + name.Replace("\\", "\\\\").Replace("\"", "\\\"") + "\"" +
|
||||
string arguments = "-name \"" + ToolBox.EscapeCharacters(name) + "\"" +
|
||||
" -public " + isPublicBox.Selected.ToString() +
|
||||
" -playstyle " + ((PlayStyle)playstyleBanner.UserData).ToString() +
|
||||
" -password \"" + passwordBox.Text.Replace("\\", "\\\\").Replace("\"", "\\\"") + "\"" +
|
||||
" -maxplayers " + maxPlayersBox.Text;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(passwordBox.Text))
|
||||
{
|
||||
arguments += " -password \"" + ToolBox.EscapeCharacters(passwordBox.Text) + "\"";
|
||||
}
|
||||
else
|
||||
{
|
||||
arguments += " -nopassword";
|
||||
}
|
||||
|
||||
int ownerKey = 0;
|
||||
|
||||
if (Steam.SteamManager.GetSteamID()!=0)
|
||||
@@ -774,6 +783,7 @@ namespace Barotrauma
|
||||
string filename = exeName;
|
||||
#if LINUX || OSX
|
||||
filename = "./" + Path.GetFileNameWithoutExtension(exeName);
|
||||
arguments = ToolBox.EscapeCharacters(arguments);
|
||||
#endif
|
||||
var processInfo = new ProcessStartInfo
|
||||
{
|
||||
@@ -1149,34 +1159,15 @@ namespace Barotrauma
|
||||
}
|
||||
#endregion
|
||||
|
||||
private void FetchRemoteContent(RectTransform parent)
|
||||
private void FetchRemoteContent()
|
||||
{
|
||||
if (string.IsNullOrEmpty(GameMain.Config.RemoteContentUrl)) { return; }
|
||||
try
|
||||
{
|
||||
var client = new RestClient(GameMain.Config.RemoteContentUrl);
|
||||
var request = new RestRequest("MenuContent.xml", Method.GET);
|
||||
|
||||
IRestResponse response = client.Execute(request);
|
||||
if (response.ResponseStatus != ResponseStatus.Completed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (response.StatusCode != HttpStatusCode.OK)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string xml = response.Content;
|
||||
int index = xml.IndexOf('<');
|
||||
if (index > 0) { xml = xml.Substring(index, xml.Length - index); }
|
||||
if (string.IsNullOrWhiteSpace(xml)) { return; }
|
||||
|
||||
XElement element = XDocument.Parse(xml)?.Root;
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
GUIComponent.FromXML(subElement, parent);
|
||||
}
|
||||
client.ExecuteAsync(request, RemoteContentReceived);
|
||||
CoroutineManager.StartCoroutine(WairForRemoteContentReceived());
|
||||
}
|
||||
|
||||
catch (Exception e)
|
||||
@@ -1189,5 +1180,60 @@ namespace Barotrauma
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<object> WairForRemoteContentReceived()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
lock (remoteContentLock)
|
||||
{
|
||||
if (remoteContentResponse != null) { break; }
|
||||
}
|
||||
yield return new WaitForSeconds(0.1f);
|
||||
}
|
||||
lock (remoteContentLock)
|
||||
{
|
||||
if (remoteContentResponse.ResponseStatus != ResponseStatus.Completed || remoteContentResponse.StatusCode != HttpStatusCode.OK)
|
||||
{
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
string xml = remoteContentResponse.Content;
|
||||
int index = xml.IndexOf('<');
|
||||
if (index > 0) { xml = xml.Substring(index, xml.Length - index); }
|
||||
if (!string.IsNullOrWhiteSpace(xml))
|
||||
{
|
||||
XElement element = XDocument.Parse(xml)?.Root;
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
GUIComponent.FromXML(subElement, Frame.RectTransform);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
catch (Exception e)
|
||||
{
|
||||
#if DEBUG
|
||||
DebugConsole.ThrowError("Reading received remote main menu content failed.", e);
|
||||
#endif
|
||||
GameAnalyticsManager.AddErrorEventOnce("MainMenuScreen.WairForRemoteContentReceived:Exception", GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||
"Reading received remote main menu content failed. " + e.Message);
|
||||
}
|
||||
}
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
private readonly object remoteContentLock = new object();
|
||||
private IRestResponse remoteContentResponse;
|
||||
|
||||
private void RemoteContentReceived(IRestResponse response, RestRequestAsyncHandle handle)
|
||||
{
|
||||
lock (remoteContentLock)
|
||||
{
|
||||
remoteContentResponse = response;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -319,6 +319,14 @@ namespace Barotrauma
|
||||
RelativeSpacing = panelSpacing
|
||||
};
|
||||
|
||||
GameMain.Instance.OnResolutionChanged += () =>
|
||||
{
|
||||
if (innerFrame != null)
|
||||
{
|
||||
innerFrame.RectTransform.MaxSize = new Point(int.MaxValue, GameMain.GraphicsHeight - 50);
|
||||
}
|
||||
};
|
||||
|
||||
var panelContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), innerFrame.RectTransform, Anchor.Center), isHorizontal: true)
|
||||
{
|
||||
Stretch = true,
|
||||
@@ -440,6 +448,14 @@ namespace Barotrauma
|
||||
Stretch = true
|
||||
};
|
||||
|
||||
GameMain.Instance.OnResolutionChanged += () =>
|
||||
{
|
||||
if (panelContainer != null && sideBar != null)
|
||||
{
|
||||
sideBar.RectTransform.MaxSize = new Point(650, panelContainer.RectTransform.Rect.Height);
|
||||
}
|
||||
};
|
||||
|
||||
//player info panel ------------------------------------------------------------
|
||||
|
||||
myCharacterFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.5f), sideBar.RectTransform));
|
||||
@@ -1781,24 +1797,23 @@ namespace Barotrauma
|
||||
RelativeSpacing = 0.03f
|
||||
};
|
||||
|
||||
var headerContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), paddedPlayerFrame.RectTransform), isHorizontal: true)
|
||||
var headerContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), paddedPlayerFrame.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft)
|
||||
{
|
||||
Stretch = true
|
||||
};
|
||||
|
||||
var nameText = new GUITextBlock(new RectTransform(new Vector2(0.75f, 1.0f), headerContainer.RectTransform),
|
||||
var nameText = new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), headerContainer.RectTransform),
|
||||
text: selectedClient.Name, font: GUI.LargeFont);
|
||||
nameText.Text = ToolBox.LimitString(nameText.Text, nameText.Font, nameText.Rect.Width);
|
||||
|
||||
if (selectedClient.SteamID != 0 && Steam.SteamManager.IsInitialized)
|
||||
{
|
||||
var viewSteamProfileButton = new GUIButton(new RectTransform(new Vector2(0.25f, 1.0f), headerContainer.RectTransform, Anchor.TopCenter),
|
||||
var viewSteamProfileButton = new GUIButton(new RectTransform(new Vector2(0.4f, 1.0f), headerContainer.RectTransform, Anchor.TopCenter) { MaxSize = new Point(int.MaxValue, (int)(40 * GUI.Scale)) },
|
||||
TextManager.Get("ViewSteamProfile"))
|
||||
{
|
||||
UserData = selectedClient
|
||||
};
|
||||
|
||||
GUITextBlock.AutoScaleAndNormalize(nameText, viewSteamProfileButton.TextBlock);
|
||||
|
||||
viewSteamProfileButton.TextBlock.AutoScale = true;
|
||||
viewSteamProfileButton.OnClicked = (bt, userdata) =>
|
||||
{
|
||||
Steam.SteamManager.Instance.Overlay.OpenUrl("https://steamcommunity.com/profiles/" + selectedClient.SteamID.ToString());
|
||||
@@ -2054,7 +2069,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
var closeButton = new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), buttonAreaLower.RectTransform, Anchor.BottomRight),
|
||||
TextManager.Get("Close"))
|
||||
TextManager.Get("Close"), style: "GUIButtonLarge")
|
||||
{
|
||||
IgnoreLayoutGroups = true,
|
||||
OnClicked = ClosePlayerFrame
|
||||
@@ -2409,6 +2424,13 @@ namespace Barotrauma
|
||||
AbsoluteOffset = new Point(characterInfoFrame.Rect.Right - characterInfoFrame.Rect.Width, button.Rect.Bottom)
|
||||
});
|
||||
|
||||
characterInfoFrame.RectTransform.SizeChanged += () =>
|
||||
{
|
||||
if (characterInfoFrame == null || HeadSelectionList?.RectTransform == null || button == null) { return; }
|
||||
HeadSelectionList.RectTransform.Resize(new Point(characterInfoFrame.Rect.Width, (characterInfoFrame.Rect.Bottom - button.Rect.Bottom) + characterInfoFrame.Rect.Height * 2));
|
||||
HeadSelectionList.RectTransform.AbsoluteOffset = new Point(characterInfoFrame.Rect.Right - characterInfoFrame.Rect.Width, button.Rect.Bottom);
|
||||
};
|
||||
|
||||
new GUIFrame(new RectTransform(new Vector2(1.25f, 1.25f), HeadSelectionList.RectTransform, Anchor.Center), style: "OuterGlow", color: Color.Black)
|
||||
{
|
||||
UserData = "outerglow",
|
||||
@@ -2446,7 +2468,7 @@ namespace Barotrauma
|
||||
headSprite.SourceRect = new Rectangle(CharacterInfo.CalculateOffset(headSprite, head.Value.ToPoint()), headSprite.SourceRect.Size);
|
||||
characterSprites.Add(headSprite);
|
||||
|
||||
if (row == null || itemsInRow >= 4)
|
||||
if (itemsInRow >= 4 || row == null || gender != (Gender)row.UserData)
|
||||
{
|
||||
row = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.333f), HeadSelectionList.Content.RectTransform), true)
|
||||
{
|
||||
@@ -2536,6 +2558,14 @@ namespace Barotrauma
|
||||
JobSelectionFrame = new GUIFrame(new RectTransform(frameSize, GUI.Canvas, Anchor.TopLeft)
|
||||
{ AbsoluteOffset = new Point(characterInfoFrame.Rect.Right - frameSize.X, characterInfoFrame.Rect.Bottom) }, "GUIFrameListBox");
|
||||
|
||||
characterInfoFrame.RectTransform.SizeChanged += () =>
|
||||
{
|
||||
if (characterInfoFrame == null || JobSelectionFrame?.RectTransform == null) { return; }
|
||||
Point size = new Point(characterInfoFrame.Rect.Width, characterInfoFrame.Rect.Height * 2);
|
||||
JobSelectionFrame.RectTransform.Resize(size);
|
||||
JobSelectionFrame.RectTransform.AbsoluteOffset = new Point(characterInfoFrame.Rect.Right - size.X, characterInfoFrame.Rect.Bottom);
|
||||
};
|
||||
|
||||
new GUIFrame(new RectTransform(new Vector2(1.25f, 1.25f), JobSelectionFrame.RectTransform, Anchor.Center), style: "OuterGlow", color: Color.Black)
|
||||
{
|
||||
UserData = "outerglow",
|
||||
@@ -2600,32 +2630,24 @@ namespace Barotrauma
|
||||
image.Visible = currVisible == (variantIndex + 1);
|
||||
}
|
||||
|
||||
var variantButton = new GUIButton(new RectTransform(new Vector2(0.15f), jobButton.RectTransform, scaleBasis: ScaleBasis.BothWidth) { RelativeOffset = new Vector2(0.05f, 0.05f + 0.2f * variantIndex) }, (variantIndex + 1).ToString(), style: null)
|
||||
var variantButton = CreateJobVariantButton(jobPrefab, variantIndex, images.Length, jobButton);
|
||||
variantButton.OnClicked = (btn, obj) =>
|
||||
{
|
||||
Color = new Color(50, 50, 50, 200),
|
||||
HoverColor = Color.Gray * 0.75f,
|
||||
PressedColor = Color.Black * 0.75f,
|
||||
SelectedColor = new Color(45, 70, 100, 200),
|
||||
UserData = new Pair<JobPrefab, int>(jobPrefab.First, variantIndex+1),
|
||||
OnClicked = (btn, obj) =>
|
||||
currSelected.Selected = false;
|
||||
int k = ((Pair<JobPrefab, int>)obj).Second;
|
||||
btn.Parent.UserData = obj;
|
||||
for (int j = 0; j < images.Length; j++)
|
||||
{
|
||||
currSelected.Selected = false;
|
||||
int k = ((Pair<JobPrefab, int>)obj).Second;
|
||||
btn.Parent.UserData = obj;
|
||||
for (int j = 0; j < images.Length; j++)
|
||||
foreach (GUIImage image in images[j])
|
||||
{
|
||||
foreach (GUIImage image in images[j])
|
||||
{
|
||||
image.Visible = k == (j + 1);
|
||||
}
|
||||
image.Visible = k == (j + 1);
|
||||
}
|
||||
currSelected = btn;
|
||||
currSelected.Selected = true;
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
currSelected = btn;
|
||||
currSelected.Selected = true;
|
||||
|
||||
return false;
|
||||
};
|
||||
if (currVisible == (variantIndex + 1))
|
||||
{
|
||||
currSelected = variantButton;
|
||||
@@ -2818,7 +2840,7 @@ namespace Barotrauma
|
||||
|
||||
subList.Enabled = !enabled && AllowSubSelection;
|
||||
shuttleList.Enabled = !enabled && GameMain.Client.HasPermission(ClientPermissions.SelectSub);
|
||||
StartButton.Visible = GameMain.Client.HasPermission(ClientPermissions.ManageRound) && GameMain.Client.GameStarted && !enabled;
|
||||
StartButton.Visible = GameMain.Client.HasPermission(ClientPermissions.ManageRound) && !GameMain.Client.GameStarted && !enabled;
|
||||
|
||||
if (campaignViewButton != null) { campaignViewButton.Visible = enabled; }
|
||||
|
||||
@@ -2943,34 +2965,28 @@ namespace Barotrauma
|
||||
}
|
||||
if (images.Length > 1)
|
||||
{
|
||||
var variantButton = new GUIButton(new RectTransform(new Vector2(0.15f), slot.RectTransform, scaleBasis: ScaleBasis.BothWidth) { RelativeOffset = new Vector2(0.05f, 0.25f + 0.2f * variantIndex) }, (variantIndex + 1).ToString(), style: null)
|
||||
var variantButton = CreateJobVariantButton(jobPrefab, variantIndex, images.Length, slot);
|
||||
variantButton.OnClicked = (btn, obj) =>
|
||||
{
|
||||
Color = new Color(50, 50, 50, 200),
|
||||
HoverColor = Color.Gray * 0.75f,
|
||||
PressedColor = Color.Black * 0.75f,
|
||||
SelectedColor = new Color(45, 70, 100, 200),
|
||||
Selected = jobPrefab.Second == (variantIndex + 1),
|
||||
UserData = new Pair<JobPrefab, int>(jobPrefab.First, variantIndex + 1),
|
||||
OnClicked = (btn, obj) =>
|
||||
{
|
||||
int k = ((Pair<JobPrefab, int>)obj).Second;
|
||||
btn.Parent.UserData = obj;
|
||||
UpdateJobPreferences(listBox);
|
||||
return false;
|
||||
}
|
||||
int k = ((Pair<JobPrefab, int>)obj).Second;
|
||||
btn.Parent.UserData = obj;
|
||||
UpdateJobPreferences(listBox);
|
||||
return false;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
//info button
|
||||
new GUIButton(new RectTransform(new Vector2(0.15f), slot.RectTransform, Anchor.TopLeft, scaleBasis: ScaleBasis.BothWidth) { RelativeOffset = new Vector2(0.05f) }, style: "GUIButtonInfo")
|
||||
new GUIButton(new RectTransform(new Vector2(0.2f), slot.RectTransform, Anchor.TopLeft, scaleBasis: ScaleBasis.BothHeight)
|
||||
{ RelativeOffset = new Vector2(0.05f) },
|
||||
style: "GUIButtonInfo")
|
||||
{
|
||||
UserData = jobPrefab.First,
|
||||
OnClicked = ViewJobInfo
|
||||
};
|
||||
|
||||
//remove button
|
||||
new GUIButton(new RectTransform(new Vector2(0.15f), slot.RectTransform, Anchor.TopRight, scaleBasis: ScaleBasis.BothWidth) { RelativeOffset = new Vector2(0.05f) }, style: "GUICancelButton")
|
||||
new GUIButton(new RectTransform(new Vector2(0.2f), slot.RectTransform, Anchor.TopRight, scaleBasis: ScaleBasis.BothHeight) { RelativeOffset = new Vector2(0.05f) }, style: "GUICancelButton")
|
||||
{
|
||||
UserData = i,
|
||||
OnClicked = (btn, obj) =>
|
||||
@@ -3013,6 +3029,24 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private GUIButton CreateJobVariantButton(Pair<JobPrefab, int> jobPrefab, int variantIndex, int variantCount, GUIComponent slot)
|
||||
{
|
||||
float relativeHeight = Math.Min(0.7f / variantCount, 0.2f);
|
||||
|
||||
var btn = new GUIButton(new RectTransform(new Vector2(relativeHeight), slot.RectTransform, scaleBasis: ScaleBasis.BothHeight)
|
||||
{ RelativeOffset = new Vector2(0.05f, 0.25f + relativeHeight * 1.05f * variantIndex) },
|
||||
(variantIndex + 1).ToString(), style: null)
|
||||
{
|
||||
Color = new Color(50, 50, 50, 200),
|
||||
HoverColor = Color.Gray * 0.75f,
|
||||
PressedColor = Color.Black * 0.75f,
|
||||
SelectedColor = new Color(45, 70, 100, 200),
|
||||
Selected = jobPrefab.Second == (variantIndex + 1),
|
||||
UserData = new Pair<JobPrefab, int>(jobPrefab.First, variantIndex + 1),
|
||||
};
|
||||
return btn;
|
||||
}
|
||||
|
||||
public Pair<string, string> FailedSelectedSub;
|
||||
public Pair<string, string> FailedSelectedShuttle;
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ using System.Net.NetworkInformation;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
@@ -426,7 +427,7 @@ namespace Barotrauma
|
||||
ToolTip = mode.Name,
|
||||
Selected = true,
|
||||
OnSelected = (tickBox) => { FilterServers(); return true; },
|
||||
UserData = mode.Name
|
||||
UserData = mode.Identifier
|
||||
};
|
||||
gameModeTickBoxes.Add(selectionTick);
|
||||
filterTextList.Add(selectionTick.TextBlock);
|
||||
@@ -736,6 +737,7 @@ namespace Barotrauma
|
||||
info.PlayerCount = GameMain.Client.ConnectedClients.Count;
|
||||
info.PingChecked = false;
|
||||
info.HasPassword = serverSettings.HasPassword;
|
||||
info.OwnerVerified = true;
|
||||
|
||||
if (isInfoNew)
|
||||
{
|
||||
@@ -747,6 +749,12 @@ namespace Barotrauma
|
||||
|
||||
public void AddToRecentServers(ServerInfo info)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(info.IP))
|
||||
{
|
||||
//don't add localhost to recent servers
|
||||
if (IPAddress.TryParse(info.IP, out IPAddress ip) && IPAddress.IsLoopback(ip)) { return; }
|
||||
}
|
||||
|
||||
info.Recent = true;
|
||||
ServerInfo existingInfo = recentServers.Find(serverInfo => info.OwnerID == serverInfo.OwnerID && (info.OwnerID != 0 ? true : (info.IP == serverInfo.IP && info.Port == serverInfo.Port)));
|
||||
if (existingInfo == null)
|
||||
@@ -898,6 +906,11 @@ namespace Barotrauma
|
||||
base.Select();
|
||||
SelectedTab = ServerListTab.All;
|
||||
RefreshServers();
|
||||
|
||||
if (SteamManager.IsInitialized && SteamManager.Instance.LobbyList != null)
|
||||
{
|
||||
SteamManager.Instance.LobbyList.OnLobbyDataReceived = OnLobbyDataReceived;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Deselect()
|
||||
@@ -905,7 +918,7 @@ namespace Barotrauma
|
||||
base.Deselect();
|
||||
if (SteamManager.IsInitialized && SteamManager.Instance.LobbyList != null)
|
||||
{
|
||||
SteamManager.Instance.LobbyList.OnLobbiesUpdated = null;
|
||||
SteamManager.Instance.LobbyList.OnLobbyDataReceived = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -947,6 +960,7 @@ namespace Barotrauma
|
||||
(remoteVersion != null && !NetworkMember.IsCompatible(GameMain.Version, remoteVersion));
|
||||
|
||||
child.Visible =
|
||||
serverInfo.OwnerVerified &&
|
||||
serverInfo.ServerName.ToLowerInvariant().Contains(searchBox.Text.ToLowerInvariant()) &&
|
||||
(!filterSameVersion.Selected || (remoteVersion != null && NetworkMember.IsCompatible(remoteVersion, GameMain.Version))) &&
|
||||
(!filterPassword.Selected || !serverInfo.HasPassword) &&
|
||||
@@ -1405,7 +1419,8 @@ namespace Barotrauma
|
||||
{
|
||||
yield return new WaitForSeconds((float)(refreshDisableTimer - DateTime.Now).TotalSeconds);
|
||||
}
|
||||
|
||||
|
||||
recentServers.Concat(favoriteServers).ForEach(si => si.OwnerVerified = false);
|
||||
if (GameMain.Config.UseSteamMatchmaking)
|
||||
{
|
||||
serverList.ClearChildren();
|
||||
@@ -1479,7 +1494,8 @@ namespace Barotrauma
|
||||
PlayerCount = playerCount,
|
||||
MaxPlayers = maxPlayers,
|
||||
HasPassword = hasPassWord,
|
||||
GameVersion = gameVersion
|
||||
GameVersion = gameVersion,
|
||||
OwnerVerified = true
|
||||
};
|
||||
foreach (string contentPackageName in contentPackageNames.Split(','))
|
||||
{
|
||||
@@ -1511,6 +1527,37 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private void OnLobbyDataReceived(Facepunch.Steamworks.LobbyList.Lobby lobby)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(lobby.GetData("haspassword"))) { return; }
|
||||
bool.TryParse(lobby.GetData("haspassword"), out bool hasPassword);
|
||||
int.TryParse(lobby.GetData("playercount"), out int currPlayers);
|
||||
int.TryParse(lobby.GetData("maxplayernum"), out int maxPlayers);
|
||||
//UInt64.TryParse(lobby.GetData("connectsteamid"), out ulong connectSteamId);
|
||||
string ip = lobby.GetData("hostipaddress");
|
||||
UInt64 ownerId = SteamManager.SteamIDStringToUInt64(lobby.GetData("lobbyowner"));
|
||||
|
||||
ServerInfo newInfo = new ServerInfo();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(ip)) { ip = ""; }
|
||||
|
||||
newInfo.ServerName = lobby.Name;
|
||||
newInfo.Port = "";
|
||||
newInfo.QueryPort = "";
|
||||
newInfo.IP = ip;
|
||||
newInfo.PlayerCount = currPlayers;
|
||||
newInfo.MaxPlayers = maxPlayers;
|
||||
newInfo.HasPassword = hasPassword;
|
||||
newInfo.RespondedToSteamQuery = true;
|
||||
newInfo.LobbyID = lobby.LobbyID;
|
||||
newInfo.OwnerID = ownerId;
|
||||
newInfo.PingChecked = false;
|
||||
newInfo.OwnerVerified = true;
|
||||
SteamManager.AssignLobbyDataToServerInfo(lobby, newInfo);
|
||||
|
||||
AddToServerList(newInfo);
|
||||
}
|
||||
|
||||
private void AddToServerList(ServerInfo serverInfo)
|
||||
{
|
||||
var serverFrame = serverList.Content.FindChild(d => (d.UserData is ServerInfo info) &&
|
||||
@@ -1552,7 +1599,8 @@ namespace Barotrauma
|
||||
if (serverInfo.OwnerVerified)
|
||||
{
|
||||
DebugConsole.NewMessage(serverInfo.OwnerID + " verified!");
|
||||
var childrenToRemove = serverList.Content.FindChildren(c => (c.UserData is ServerInfo info) && info != serverInfo && info.OwnerID == serverInfo.OwnerID).ToList();
|
||||
var childrenToRemove = serverList.Content.FindChildren(c => (c.UserData is ServerInfo info) && info != serverInfo &&
|
||||
(serverInfo.OwnerID != 0 ? info.OwnerID == serverInfo.OwnerID : info.IP == serverInfo.IP)).ToList();
|
||||
foreach (var child in childrenToRemove)
|
||||
{
|
||||
serverList.Content.RemoveChild(child);
|
||||
@@ -1594,7 +1642,13 @@ namespace Barotrauma
|
||||
UserData = "password"
|
||||
};
|
||||
|
||||
var serverName = new GUITextBlock(new RectTransform(new Vector2(columnRelativeWidth[2] * 1.1f, 1.0f), serverContent.RectTransform), serverInfo.ServerName, style: "GUIServerListTextBox");
|
||||
var serverName = new GUITextBlock(new RectTransform(new Vector2(columnRelativeWidth[2] * 1.1f, 1.0f), serverContent.RectTransform),
|
||||
#if !DEBUG
|
||||
serverInfo.ServerName,
|
||||
#else
|
||||
((serverInfo.OwnerID != 0 || serverInfo.LobbyID != 0) ? "[STEAMP2P] " : "[LIDGREN] ") + serverInfo.ServerName,
|
||||
#endif
|
||||
style: "GUIServerListTextBox");
|
||||
|
||||
new GUITickBox(new RectTransform(new Vector2(columnRelativeWidth[3], 0.9f), serverContent.RectTransform, Anchor.Center), label: "")
|
||||
{
|
||||
@@ -1793,7 +1847,7 @@ namespace Barotrauma
|
||||
GameMain.Config.PlayerName = clientNameBox.Text;
|
||||
GameMain.Config.SaveNewPlayerConfig();
|
||||
|
||||
CoroutineManager.StartCoroutine(ConnectToServer(endpoint, serverName));
|
||||
CoroutineManager.StartCoroutine(ConnectToServer(endpoint, serverName), "ConnectToServer");
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1822,40 +1876,31 @@ namespace Barotrauma
|
||||
|
||||
public void GetServerPing(ServerInfo serverInfo, GUITextBlock serverPingText)
|
||||
{
|
||||
if (activePings.Contains(serverInfo.IP)) { return; }
|
||||
activePings.Add(serverInfo.IP);
|
||||
if (CoroutineManager.IsCoroutineRunning("ConnectToServer")) { return; }
|
||||
|
||||
lock (activePings)
|
||||
{
|
||||
if (activePings.Contains(serverInfo.IP)) { return; }
|
||||
activePings.Add(serverInfo.IP);
|
||||
}
|
||||
|
||||
serverInfo.PingChecked = false;
|
||||
serverInfo.Ping = -1;
|
||||
|
||||
var pingThread = new Thread(() => { PingServer(serverInfo, 1000); })
|
||||
{
|
||||
IsBackground = true
|
||||
};
|
||||
pingThread.Start();
|
||||
|
||||
CoroutineManager.StartCoroutine(UpdateServerPingText(serverInfo, serverPingText, 1000));
|
||||
}
|
||||
|
||||
private IEnumerable<object> UpdateServerPingText(ServerInfo serverInfo, GUITextBlock serverPingText, int timeOut)
|
||||
{
|
||||
DateTime timeOutTime = DateTime.Now + new TimeSpan(0, 0, 0, 0, milliseconds: timeOut);
|
||||
while (DateTime.Now < timeOutTime)
|
||||
{
|
||||
if (serverInfo.PingChecked)
|
||||
TaskPool.Add(PingServerAsync(serverInfo?.IP, 1000),
|
||||
new Tuple<ServerInfo, GUITextBlock>(serverInfo, serverPingText),
|
||||
(rtt, obj) =>
|
||||
{
|
||||
if (serverInfo.Ping != -1)
|
||||
var info = obj.Item1;
|
||||
var text = obj.Item2;
|
||||
info.Ping = rtt.Result; info.PingChecked = true;
|
||||
text.TextColor = GetPingTextColor(info.Ping);
|
||||
text.Text = info.Ping > -1 ? info.Ping.ToString() : "?";
|
||||
lock (activePings)
|
||||
{
|
||||
serverPingText.TextColor = GetPingTextColor(serverInfo.Ping);
|
||||
}
|
||||
serverPingText.Text = serverInfo.Ping > -1 ? serverInfo.Ping.ToString() : "?";
|
||||
activePings.Remove(serverInfo.IP);
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
yield return CoroutineStatus.Success;
|
||||
activePings.Remove(serverInfo.IP);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private Color GetPingTextColor(int ping)
|
||||
@@ -1864,18 +1909,27 @@ namespace Barotrauma
|
||||
return ToolBox.GradientLerp(ping / 200.0f, Color.LightGreen, Color.Yellow * 0.8f, Color.Red * 0.75f);
|
||||
}
|
||||
|
||||
public void PingServer(ServerInfo serverInfo, int timeOut)
|
||||
public async Task<int> PingServerAsync(string ip, int timeOut)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(serverInfo?.IP))
|
||||
await Task.Yield();
|
||||
int activePingCount = 100;
|
||||
while (activePingCount > 25)
|
||||
{
|
||||
serverInfo.PingChecked = true;
|
||||
serverInfo.Ping = -1;
|
||||
return;
|
||||
lock (activePings)
|
||||
{
|
||||
activePingCount = activePings.Count;
|
||||
}
|
||||
await Task.Delay(25);
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(ip))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
long rtt = -1;
|
||||
IPAddress address = null;
|
||||
IPAddress.TryParse(serverInfo.IP, out address);
|
||||
IPAddress.TryParse(ip, out address);
|
||||
if (address != null)
|
||||
{
|
||||
//don't attempt to ping if the address is IPv6 and it's not supported
|
||||
@@ -1902,8 +1956,8 @@ namespace Barotrauma
|
||||
}
|
||||
catch (PingException ex)
|
||||
{
|
||||
string errorMsg = "Failed to ping a server (" + serverInfo.ServerName + ", " + serverInfo.IP + ") - " + (ex?.InnerException?.Message ?? ex.Message);
|
||||
GameAnalyticsManager.AddErrorEventOnce("ServerListScreen.PingServer:PingException" + serverInfo.IP, GameAnalyticsSDK.Net.EGAErrorSeverity.Warning, errorMsg);
|
||||
string errorMsg = "Failed to ping a server (" + ip + ") - " + (ex?.InnerException?.Message ?? ex.Message);
|
||||
GameAnalyticsManager.AddErrorEventOnce("ServerListScreen.PingServer:PingException" + ip, GameAnalyticsSDK.Net.EGAErrorSeverity.Warning, errorMsg);
|
||||
#if DEBUG
|
||||
DebugConsole.NewMessage(errorMsg, Color.Red);
|
||||
#endif
|
||||
@@ -1911,10 +1965,9 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
serverInfo.PingChecked = true;
|
||||
serverInfo.Ping = (int)rtt;
|
||||
return (int)rtt;
|
||||
}
|
||||
|
||||
|
||||
public override void Draw(double deltaTime, GraphicsDevice graphics, SpriteBatch spriteBatch)
|
||||
{
|
||||
graphics.Clear(Color.CornflowerBlue);
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace Barotrauma
|
||||
|
||||
private List<GUIButton> tabButtons = new List<GUIButton>();
|
||||
|
||||
private HashSet<string> pendingPreviewImageDownloads = new HashSet<string>();
|
||||
private readonly HashSet<string> pendingPreviewImageDownloads = new HashSet<string>();
|
||||
private Dictionary<string, Sprite> itemPreviewSprites = new Dictionary<string, Sprite>();
|
||||
|
||||
private enum Tab
|
||||
@@ -379,10 +379,16 @@ namespace Barotrauma
|
||||
if (!string.IsNullOrEmpty(item.PreviewImageUrl))
|
||||
{
|
||||
string imagePreviewPath = Path.Combine(SteamManager.WorkshopItemPreviewImageFolder, item.Id + ".png");
|
||||
if (!pendingPreviewImageDownloads.Contains(item.PreviewImageUrl))
|
||||
{
|
||||
pendingPreviewImageDownloads.Add(item.PreviewImageUrl);
|
||||
|
||||
bool isNewImage;
|
||||
lock (pendingPreviewImageDownloads)
|
||||
{
|
||||
isNewImage = !pendingPreviewImageDownloads.Contains(item.PreviewImageUrl);
|
||||
if (isNewImage) { pendingPreviewImageDownloads.Add(item.PreviewImageUrl); }
|
||||
}
|
||||
|
||||
if (isNewImage)
|
||||
{
|
||||
if (File.Exists(imagePreviewPath))
|
||||
{
|
||||
File.Delete(imagePreviewPath);
|
||||
@@ -397,10 +403,13 @@ namespace Barotrauma
|
||||
var request = new RestRequest(fileName, Method.GET);
|
||||
client.ExecuteAsync(request, response =>
|
||||
{
|
||||
pendingPreviewImageDownloads.Remove(item.PreviewImageUrl);
|
||||
lock (pendingPreviewImageDownloads)
|
||||
{
|
||||
pendingPreviewImageDownloads.Remove(item.PreviewImageUrl);
|
||||
}
|
||||
OnPreviewImageDownloaded(response, imagePreviewPath);
|
||||
CoroutineManager.StartCoroutine(WaitForItemPreviewDownloaded(item, listBox, imagePreviewPath));
|
||||
});
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -410,7 +419,10 @@ namespace Barotrauma
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
pendingPreviewImageDownloads.Remove(item.PreviewImageUrl);
|
||||
lock (pendingPreviewImageDownloads)
|
||||
{
|
||||
pendingPreviewImageDownloads.Remove(item.PreviewImageUrl);
|
||||
}
|
||||
DebugConsole.ThrowError("Downloading the preview image of the Workshop item \"" + TextManager.EnsureUTF8(item.Title) + "\" failed.", e);
|
||||
}
|
||||
}
|
||||
@@ -595,8 +607,13 @@ namespace Barotrauma
|
||||
|
||||
private IEnumerable<object> WaitForItemPreviewDownloaded(Facepunch.Steamworks.Workshop.Item item, GUIListBox listBox, string previewImagePath)
|
||||
{
|
||||
while (pendingPreviewImageDownloads.Contains(item.PreviewImageUrl))
|
||||
while (true)
|
||||
{
|
||||
lock (pendingPreviewImageDownloads)
|
||||
{
|
||||
if (!pendingPreviewImageDownloads.Contains(item.PreviewImageUrl)) { break; }
|
||||
}
|
||||
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
|
||||
@@ -522,11 +522,6 @@ namespace Barotrauma
|
||||
OnSelected = (GUITickBox obj) => { Gap.ShowGaps = obj.Selected; return true; },
|
||||
};
|
||||
|
||||
tickBoxHolder.Children.ForEach(c =>
|
||||
{
|
||||
if (c is GUITickBox tb) { tb.RectTransform.MinSize = new Point(0, 32); }
|
||||
});
|
||||
|
||||
GUITextBlock.AutoScaleAndNormalize(tickBoxHolder.Children.Where(c => c is GUITickBox).Select(c => ((GUITickBox)c).TextBlock));
|
||||
|
||||
//spacing
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace Barotrauma.SpriteDeformations
|
||||
/// A positive value means that this deformation is or could be used for multiple sprites.
|
||||
/// This behaviour is not automatic, and has to be implemented for any particular case separately (currently only used in Limbs).
|
||||
/// </summary>
|
||||
[Serialize(-1, true), Editable]
|
||||
[Serialize(-1, true), Editable(minValue: -1, maxValue: 100)]
|
||||
public int Sync
|
||||
{
|
||||
get;
|
||||
|
||||
@@ -64,7 +64,7 @@ namespace Barotrauma
|
||||
{
|
||||
foreach (RoundSound sound in sounds)
|
||||
{
|
||||
if (sound.Sound == null)
|
||||
if (sound?.Sound == null)
|
||||
{
|
||||
string errorMsg = $"Error in StatusEffect.ApplyProjSpecific1 (sound \"{sound.Filename ?? "unknown"}\" was null)\n" + Environment.StackTrace;
|
||||
GameAnalyticsManager.AddErrorEventOnce("StatusEffect.ApplyProjSpecific:SoundNull1" + Environment.StackTrace, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
@@ -90,7 +90,7 @@ namespace Barotrauma
|
||||
selectedSoundIndex = Rand.Int(sounds.Count);
|
||||
}
|
||||
var selectedSound = sounds[selectedSoundIndex];
|
||||
if (selectedSound.Sound == null)
|
||||
if (selectedSound?.Sound == null)
|
||||
{
|
||||
string errorMsg = $"Error in StatusEffect.ApplyProjSpecific2 (sound \"{selectedSound.Filename ?? "unknown"}\" was null)\n" + Environment.StackTrace;
|
||||
GameAnalyticsManager.AddErrorEventOnce("StatusEffect.ApplyProjSpecific:SoundNull2" + Environment.StackTrace, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
|
||||
Reference in New Issue
Block a user