v1.7.7.0 (Winter Update 2024)
This commit is contained in:
@@ -184,6 +184,13 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
shakePos = Vector2.Zero;
|
||||
}
|
||||
if (Character.Controlled is Character character && character.FocusedItem == item)
|
||||
{
|
||||
if ((IsFullyOpen || IsFullyClosed) && MathF.Abs(openState - lastOpenState) > 0)
|
||||
{
|
||||
CharacterHUD.RecreateHudTexts = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing, float itemDepth = -1, Color? overrideColor = null)
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public override void AddTooltipInfo(ref LocalizedString name, ref LocalizedString description)
|
||||
{
|
||||
bool mergedMaterialTainted = false;
|
||||
if (!materialName.IsNullOrEmpty() && item.ContainedItems.Count() > 0)
|
||||
{
|
||||
LocalizedString mergedMaterialName = materialName;
|
||||
@@ -22,11 +23,15 @@ namespace Barotrauma.Items.Components
|
||||
var containedMaterial = containedItem.GetComponent<GeneticMaterial>();
|
||||
if (containedMaterial == null) { continue; }
|
||||
mergedMaterialName += ", " + containedMaterial.materialName;
|
||||
if (containedMaterial.Tainted)
|
||||
{
|
||||
mergedMaterialTainted = true;
|
||||
}
|
||||
}
|
||||
name = name.Replace(materialName, mergedMaterialName);
|
||||
}
|
||||
|
||||
if (Tainted)
|
||||
if (Tainted || mergedMaterialTainted)
|
||||
{
|
||||
name = TextManager.GetWithVariable("entityname.taintedgeneticmaterial", "[geneticmaterialname]", name);
|
||||
}
|
||||
|
||||
@@ -71,13 +71,13 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
public override bool ValidateEventData(NetEntityEvent.IData data)
|
||||
=> TryExtractEventData<EventData>(data, out _);
|
||||
=> TryExtractEventData<AttachEventData>(data, out _);
|
||||
|
||||
public void ClientEventWrite(IWriteMessage msg, NetEntityEvent.IData extraData = null)
|
||||
{
|
||||
if (!attachable || body == null) { return; }
|
||||
|
||||
var eventData = ExtractEventData<EventData>(extraData);
|
||||
var eventData = ExtractEventData<AttachEventData>(extraData);
|
||||
|
||||
Vector2 attachPos = eventData.AttachPos;
|
||||
msg.WriteSingle(attachPos.X);
|
||||
@@ -94,7 +94,9 @@ namespace Barotrauma.Items.Components
|
||||
bool shouldBeAttached = msg.ReadBoolean();
|
||||
Vector2 simPosition = new Vector2(msg.ReadSingle(), msg.ReadSingle());
|
||||
UInt16 submarineID = msg.ReadUInt16();
|
||||
UInt16 attacherID = msg.ReadUInt16();
|
||||
Submarine sub = Entity.FindEntityByID(submarineID) as Submarine;
|
||||
Character attacher = Entity.FindEntityByID(attacherID) as Character;
|
||||
|
||||
if (shouldBeAttached)
|
||||
{
|
||||
@@ -104,6 +106,8 @@ namespace Barotrauma.Items.Components
|
||||
item.SetTransform(simPosition, 0.0f);
|
||||
item.Submarine = sub;
|
||||
AttachToWall();
|
||||
PlaySound(ActionType.OnUse, attacher);
|
||||
ApplyStatusEffects(ActionType.OnUse, (float)Timing.Step, character: attacher, user: attacher);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -62,6 +62,10 @@ namespace Barotrauma.Items.Components
|
||||
private readonly Dictionary<ActionType, List<ItemSound>> sounds;
|
||||
private Dictionary<ActionType, SoundSelectionMode> soundSelectionModes;
|
||||
|
||||
/// <summary>
|
||||
/// Starts the timer for delayed client-side corrections (<see cref="StartDelayedCorrection(IReadMessage, float, bool)"/>) - in other words,
|
||||
/// the client will not attempt to read server updates for this component until the timer elapses.
|
||||
/// </summary>
|
||||
protected float correctionTimer;
|
||||
|
||||
public float IsActiveTimer;
|
||||
@@ -760,7 +764,11 @@ namespace Barotrauma.Items.Components
|
||||
/// </summary>
|
||||
protected virtual void CreateGUI() { }
|
||||
|
||||
//Starts a coroutine that will read the correct state of the component from the NetBuffer when correctionTimer reaches zero.
|
||||
/// <summary>
|
||||
/// Starts a coroutine that will read the correct state of the component from the NetBuffer when correctionTimer reaches zero.
|
||||
/// Useful in cases where we a client is constantly adjusting some value, and we don't want state updates from the server to interfere with it
|
||||
/// (e.g. setting the value back to what a client just set it to, when the client has already modified the value further).
|
||||
/// </summary>
|
||||
protected void StartDelayedCorrection(IReadMessage buffer, float sendingTime, bool waitForMidRoundSync = false)
|
||||
{
|
||||
if (delayedCorrectionCoroutine != null) { CoroutineManager.StopCoroutines(delayedCorrectionCoroutine); }
|
||||
|
||||
@@ -372,17 +372,17 @@ namespace Barotrauma.Items.Components
|
||||
outputContainer.Inventory.RectTransform = outputInventoryHolder.RectTransform;
|
||||
}
|
||||
|
||||
private static LocalizedString GetRecipeNameAndAmount(FabricationRecipe fabricationRecipe)
|
||||
private static RichString GetRecipeNameAndAmount(FabricationRecipe fabricationRecipe)
|
||||
{
|
||||
if (fabricationRecipe == null) { return ""; }
|
||||
if (fabricationRecipe.Amount > 1)
|
||||
{
|
||||
return TextManager.GetWithVariables("fabricationrecipenamewithamount",
|
||||
("[name]", fabricationRecipe.DisplayName), ("[amount]", fabricationRecipe.Amount.ToString()));
|
||||
("[name]", RichString.Rich(fabricationRecipe.DisplayName)), ("[amount]", fabricationRecipe.Amount.ToString()));
|
||||
}
|
||||
else
|
||||
{
|
||||
return fabricationRecipe.DisplayName;
|
||||
return RichString.Rich(fabricationRecipe.DisplayName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1978,25 +1978,6 @@ namespace Barotrauma.Items.Components
|
||||
2, GUIStyle.SmallFont);
|
||||
}
|
||||
|
||||
protected override void RemoveComponentSpecific()
|
||||
{
|
||||
base.RemoveComponentSpecific();
|
||||
sonarBlip?.Remove();
|
||||
pingCircle?.Remove();
|
||||
directionalPingCircle?.Remove();
|
||||
screenOverlay?.Remove();
|
||||
screenBackground?.Remove();
|
||||
lineSprite?.Remove();
|
||||
|
||||
foreach (var t in targetIcons.Values)
|
||||
{
|
||||
t.Item1.Remove();
|
||||
}
|
||||
targetIcons.Clear();
|
||||
|
||||
MineralClusters = null;
|
||||
}
|
||||
|
||||
public void ClientEventWrite(IWriteMessage msg, NetEntityEvent.IData extraData = null)
|
||||
{
|
||||
msg.WriteBoolean(currentMode == Mode.Active);
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace Barotrauma.Items.Components
|
||||
Hull hull = Entity.FindEntityByID(hullID) as Hull;
|
||||
item.Submarine = submarine;
|
||||
item.CurrentHull = hull;
|
||||
item.body.SetTransform(simPosition, item.body.Rotation);
|
||||
item.body.SetTransformIgnoreContacts(simPosition, item.body.Rotation);
|
||||
|
||||
switch (targetType)
|
||||
{
|
||||
|
||||
+69
-35
@@ -12,7 +12,7 @@ namespace Barotrauma.Items.Components
|
||||
private readonly List<GUIComponent> uiElements = new List<GUIComponent>();
|
||||
private GUILayoutGroup uiElementContainer;
|
||||
|
||||
private bool readingNetworkEvent;
|
||||
private bool suppressNetworkEvents;
|
||||
|
||||
private GUIComponent insufficientPowerWarning;
|
||||
|
||||
@@ -70,7 +70,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
else
|
||||
{
|
||||
item.CreateClientEvent(this);
|
||||
CreateClientEventWithCorrectionDelay();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -100,13 +100,10 @@ namespace Barotrauma.Items.Components
|
||||
ValueStep = numberInputStep,
|
||||
OnValueChanged = (ni) =>
|
||||
{
|
||||
if (GameMain.Client == null)
|
||||
ValueChanged(ni.UserData as CustomInterfaceElement, ni.FloatValue);
|
||||
if (!suppressNetworkEvents && GameMain.Client != null)
|
||||
{
|
||||
ValueChanged(ni.UserData as CustomInterfaceElement, ni.FloatValue);
|
||||
}
|
||||
else if (!readingNetworkEvent)
|
||||
{
|
||||
item.CreateClientEvent(this);
|
||||
CreateClientEventWithCorrectionDelay();
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -126,13 +123,10 @@ namespace Barotrauma.Items.Components
|
||||
ValueStep = numberInputStep,
|
||||
OnValueChanged = (ni) =>
|
||||
{
|
||||
if (GameMain.Client == null)
|
||||
ValueChanged(ni.UserData as CustomInterfaceElement, ni.IntValue);
|
||||
if (!suppressNetworkEvents && GameMain.Client != null)
|
||||
{
|
||||
ValueChanged(ni.UserData as CustomInterfaceElement, ni.IntValue);
|
||||
}
|
||||
else if (!readingNetworkEvent)
|
||||
{
|
||||
item.CreateClientEvent(this);
|
||||
CreateClientEventWithCorrectionDelay();
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -162,13 +156,10 @@ namespace Barotrauma.Items.Components
|
||||
};
|
||||
tickBox.OnSelected += (tBox) =>
|
||||
{
|
||||
if (GameMain.Client == null)
|
||||
TickBoxToggled(tBox.UserData as CustomInterfaceElement, tBox.Selected);
|
||||
if (!suppressNetworkEvents && GameMain.Client != null)
|
||||
{
|
||||
TickBoxToggled(tBox.UserData as CustomInterfaceElement, tBox.Selected);
|
||||
}
|
||||
else if (!readingNetworkEvent)
|
||||
{
|
||||
item.CreateClientEvent(this);
|
||||
CreateClientEventWithCorrectionDelay();
|
||||
}
|
||||
return true;
|
||||
};
|
||||
@@ -191,8 +182,10 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
ButtonClicked(btnElement);
|
||||
}
|
||||
else if (!readingNetworkEvent)
|
||||
else if (!suppressNetworkEvents && GameMain.Client != null)
|
||||
{
|
||||
//don't use CreateClientEventWithCorrectionDelay here, because buttons have no state,
|
||||
//which means we don't need to worry about server updates interfering with client-side changes to the values in the interface
|
||||
item.CreateClientEvent(this, new EventData(btnElement));
|
||||
}
|
||||
return true;
|
||||
@@ -215,6 +208,12 @@ namespace Barotrauma.Items.Components
|
||||
Visible = false
|
||||
};
|
||||
}
|
||||
|
||||
void CreateClientEventWithCorrectionDelay()
|
||||
{
|
||||
item.CreateClientEvent(this);
|
||||
correctionTimer = CorrectionDelay;
|
||||
}
|
||||
}
|
||||
|
||||
public override void CreateEditingHUD(SerializableEntityEditor editor)
|
||||
@@ -268,7 +267,7 @@ namespace Barotrauma.Items.Components
|
||||
if (visible)
|
||||
{
|
||||
visibleElementCount++;
|
||||
if (element.GetValueInterval > 0.0f)
|
||||
if (element.GetValueInterval > 0.0f && correctionTimer <= 0.0f)
|
||||
{
|
||||
element.GetValueTimer -= deltaTime;
|
||||
if (element.GetValueTimer <= 0.0f)
|
||||
@@ -330,7 +329,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
LocalizedString CreateLabelText(int elementIndex)
|
||||
{
|
||||
var label = customInterfaceElementList[elementIndex].Label;
|
||||
string label = customInterfaceElementList[elementIndex].Label;
|
||||
return string.IsNullOrWhiteSpace(label) ?
|
||||
TextManager.GetWithVariable("connection.signaloutx", "[num]", (elementIndex + 1).ToString()) :
|
||||
TextManager.Get(label).Fallback(label);
|
||||
@@ -373,6 +372,9 @@ namespace Barotrauma.Items.Components
|
||||
private void UpdateSignalProjSpecific(GUIComponent uiElement)
|
||||
{
|
||||
if (uiElement.UserData is not CustomInterfaceElement element) { return; }
|
||||
|
||||
suppressNetworkEvents = true;
|
||||
|
||||
string signal = element.Signal;
|
||||
if (uiElement is GUITextBox tb)
|
||||
{
|
||||
@@ -384,14 +386,22 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (ni.InputType == NumberType.Int)
|
||||
{
|
||||
int.TryParse(signal, out int value);
|
||||
ni.IntValue = value;
|
||||
if (int.TryParse(signal, out int value))
|
||||
{
|
||||
ni.IntValue = value;
|
||||
}
|
||||
else if (float.TryParse(signal, out float floatValue))
|
||||
{
|
||||
ni.IntValue = (int)MathF.Round(floatValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (uiElement is GUITickBox tickBox)
|
||||
{
|
||||
tickBox.Selected = signal.Equals("true", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
suppressNetworkEvents = false;
|
||||
}
|
||||
|
||||
public void ClientEventWrite(IWriteMessage msg, NetEntityEvent.IData extraData = null)
|
||||
@@ -429,38 +439,62 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||
{
|
||||
readingNetworkEvent = true;
|
||||
int msgStartPos = msg.BitPosition;
|
||||
suppressNetworkEvents = true;
|
||||
try
|
||||
{
|
||||
string[] stringValues = new string[customInterfaceElementList.Count];
|
||||
bool[] boolValues = new bool[customInterfaceElementList.Count];
|
||||
for (int i = 0; i < customInterfaceElementList.Count; i++)
|
||||
{
|
||||
var element = customInterfaceElementList[i];
|
||||
switch (element.InputType)
|
||||
{
|
||||
case CustomInterfaceElement.InputTypeOption.Number:
|
||||
case CustomInterfaceElement.InputTypeOption.Text:
|
||||
stringValues[i] = msg.ReadString();
|
||||
break;
|
||||
case CustomInterfaceElement.InputTypeOption.TickBox:
|
||||
case CustomInterfaceElement.InputTypeOption.Button:
|
||||
boolValues[i] = msg.ReadBoolean();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (correctionTimer > 0.0f)
|
||||
{
|
||||
int msgLength = msg.BitPosition - msgStartPos;
|
||||
msg.BitPosition = msgStartPos;
|
||||
StartDelayedCorrection(msg.ExtractBits(msgLength), sendingTime);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < customInterfaceElementList.Count; i++)
|
||||
{
|
||||
var element = customInterfaceElementList[i];
|
||||
switch (element.InputType)
|
||||
{
|
||||
case CustomInterfaceElement.InputTypeOption.Number:
|
||||
string newValue = msg.ReadString();
|
||||
switch (element.NumberType)
|
||||
{
|
||||
case NumberType.Int when int.TryParse(newValue, out int value):
|
||||
case NumberType.Int when int.TryParse(stringValues[i], out int value):
|
||||
ValueChanged(element, value);
|
||||
break;
|
||||
case NumberType.Float when TryParseFloatInvariantCulture(newValue, out float value):
|
||||
case NumberType.Float when TryParseFloatInvariantCulture(stringValues[i], out float value):
|
||||
ValueChanged(element, value);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case CustomInterfaceElement.InputTypeOption.Text:
|
||||
string newTextValue = msg.ReadString();
|
||||
TextChanged(element, newTextValue);
|
||||
TextChanged(element, stringValues[i]);
|
||||
break;
|
||||
case CustomInterfaceElement.InputTypeOption.TickBox:
|
||||
bool tickBoxState = msg.ReadBoolean();
|
||||
bool tickBoxState = boolValues[i];
|
||||
((GUITickBox)uiElements[i]).Selected = tickBoxState;
|
||||
TickBoxToggled(element, tickBoxState);
|
||||
break;
|
||||
case CustomInterfaceElement.InputTypeOption.Button:
|
||||
bool buttonState = msg.ReadBoolean();
|
||||
if (buttonState)
|
||||
if (boolValues[i])
|
||||
{
|
||||
ButtonClicked(element);
|
||||
}
|
||||
@@ -472,7 +506,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
finally
|
||||
{
|
||||
readingNetworkEvent = false;
|
||||
suppressNetworkEvents = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.Networking;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
@@ -21,13 +22,16 @@ namespace Barotrauma.Items.Components
|
||||
private GUIListBox historyBox;
|
||||
private GUITextBlock fillerBlock;
|
||||
private GUITextBox inputBox;
|
||||
private GUILayoutGroup layoutGroup;
|
||||
private bool shouldSelectInputBox;
|
||||
|
||||
private readonly List<GUIComponent> inputElements = new List<GUIComponent>();
|
||||
|
||||
partial void InitProjSpecific(XElement element)
|
||||
{
|
||||
float marginMultiplier = element.GetAttributeFloat("marginmultiplier", 1.0f);
|
||||
|
||||
var layoutGroup = new GUILayoutGroup(new RectTransform(GuiFrame.Rect.Size - GUIStyle.ItemFrameMargin.Multiply(marginMultiplier), GuiFrame.RectTransform, Anchor.Center) { AbsoluteOffset = GUIStyle.ItemFrameOffset.Multiply(marginMultiplier) })
|
||||
layoutGroup = new GUILayoutGroup(new RectTransform(GuiFrame.Rect.Size - GUIStyle.ItemFrameMargin.Multiply(marginMultiplier), GuiFrame.RectTransform, Anchor.Center) { AbsoluteOffset = GUIStyle.ItemFrameOffset.Multiply(marginMultiplier) })
|
||||
{
|
||||
ChildAnchor = Anchor.TopCenter,
|
||||
RelativeSpacing = 0.02f,
|
||||
@@ -39,43 +43,53 @@ namespace Barotrauma.Items.Components
|
||||
AutoHideScrollBar = this.AutoHideScrollbar
|
||||
};
|
||||
|
||||
if (!Readonly)
|
||||
inputElements.Add(CreateFillerBlock());
|
||||
inputElements.Add(new GUIFrame(new RectTransform(new Vector2(0.9f, 0.01f), layoutGroup.RectTransform), style: "HorizontalLine"));
|
||||
|
||||
inputBox = new GUITextBox(new RectTransform(new Vector2(1, .1f), layoutGroup.RectTransform), textColor: TextColor)
|
||||
{
|
||||
CreateFillerBlock();
|
||||
|
||||
new GUIFrame(new RectTransform(new Vector2(0.9f, 0.01f), layoutGroup.RectTransform), style: "HorizontalLine");
|
||||
|
||||
inputBox = new GUITextBox(new RectTransform(new Vector2(1, .1f), layoutGroup.RectTransform), textColor: TextColor)
|
||||
MaxTextLength = MaxMessageLength,
|
||||
OverflowClip = true,
|
||||
OnEnterPressed = (GUITextBox textBox, string text) =>
|
||||
{
|
||||
MaxTextLength = MaxMessageLength,
|
||||
OverflowClip = true,
|
||||
OnEnterPressed = (GUITextBox textBox, string text) =>
|
||||
if (GameMain.NetworkMember == null)
|
||||
{
|
||||
if (GameMain.NetworkMember == null)
|
||||
{
|
||||
SendOutput(text);
|
||||
}
|
||||
else
|
||||
{
|
||||
item.CreateClientEvent(this, new ClientEventData(text));
|
||||
}
|
||||
textBox.Text = string.Empty;
|
||||
return true;
|
||||
SendOutput(text);
|
||||
}
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
item.CreateClientEvent(this, new ClientEventData(text));
|
||||
}
|
||||
textBox.Text = string.Empty;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
inputElements.Add(inputBox);
|
||||
RefreshInputElements();
|
||||
}
|
||||
|
||||
layoutGroup.Recalculate();
|
||||
/// <summary>
|
||||
/// Refreshes the visibility of the input box and the layout of the UI depending on whether the terminal is readonly or not.
|
||||
/// </summary>
|
||||
private void RefreshInputElements()
|
||||
{
|
||||
foreach (var inputElement in inputElements)
|
||||
{
|
||||
inputElement.Visible = !_readonly;
|
||||
inputElement.IgnoreLayoutGroups = !inputElement.Visible;
|
||||
}
|
||||
layoutGroup?.Recalculate();
|
||||
}
|
||||
|
||||
// Create fillerBlock to cover historyBox so new values appear at the bottom of historyBox
|
||||
// This could be removed if GUIListBox supported aligning its children
|
||||
public void CreateFillerBlock()
|
||||
public GUIComponent CreateFillerBlock()
|
||||
{
|
||||
fillerBlock = new GUITextBlock(new RectTransform(new Vector2(1, 1), historyBox.Content.RectTransform, anchor: Anchor.TopCenter), string.Empty)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
return fillerBlock;
|
||||
}
|
||||
|
||||
private void SendOutput(string input)
|
||||
|
||||
@@ -199,6 +199,8 @@ namespace Barotrauma.Items.Components
|
||||
return;
|
||||
}
|
||||
|
||||
if (Width * wireSprite.size.Y * Screen.Selected.Cam.Zoom < 1.0f) { return; }
|
||||
|
||||
Vector2 drawOffset = GetDrawOffset() + offset;
|
||||
|
||||
float baseDepth = UseSpriteDepth ? item.SpriteDepth : wireSprite.Depth;
|
||||
|
||||
@@ -282,7 +282,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!target.CustomInteractHUDText.IsNullOrEmpty() && target.AllowCustomInteract)
|
||||
if (target.ShouldShowCustomInteractText)
|
||||
{
|
||||
texts.Add(target.CustomInteractHUDText);
|
||||
textColors.Add(GUIStyle.Green);
|
||||
|
||||
Reference in New Issue
Block a user