Release 1.11.4.1 (Winter Update)

This commit is contained in:
Markus Isberg
2025-12-08 14:56:47 +00:00
parent 21e34e5cd8
commit 598966f200
121 changed files with 1614 additions and 819 deletions
@@ -103,7 +103,7 @@ namespace Barotrauma.Items.Components
var inputBuilder = ImmutableArray.CreateBuilder<CircuitBoxInputConnection>();
var outputBuilder = ImmutableArray.CreateBuilder<CircuitBoxOutputConnection>();
foreach (Connection conn in Item.Connections)
foreach (Connection conn in Item.Connections.OrderBy(static c => c.DisplayOrder))
{
if (conn.IsOutput)
{
@@ -236,9 +236,7 @@ namespace Barotrauma.Items.Components
cloneNode.ReplaceAllConnectionLabelOverrides(origNode.ConnectionLabelOverrides);
}
if (!clonedContainedItems.Any()) { return; }
foreach (var origComp in original.Components)
foreach (CircuitBoxComponent origComp in original.Components)
{
if (!clonedContainedItems.TryGetValue(origComp.Item.ID, out var clonedItem)) { continue; }
var newComponent = new CircuitBoxComponent(origComp.ID, clonedItem, origComp.Position, this, origComp.UsedResource);
@@ -661,6 +659,7 @@ namespace Barotrauma.Items.Components
}
wire.From.Connection.CircuitBoxConnections.Remove(wire.To);
wire.To.Connection.CircuitBoxConnections.Remove(wire.From);
if (wire.From is CircuitBoxInputConnection input)
{
@@ -17,6 +17,8 @@ namespace Barotrauma.Items.Components
//how many wires can be linked to this connection in total
public readonly int MaxWires = 5;
public readonly int DisplayOrder;
public readonly string Name;
private readonly LocalizedString _displayName;
public LocalizedString DisplayName
@@ -92,7 +94,7 @@ namespace Barotrauma.Items.Components
return "Connection (" + item.Name + ", " + Name + ")";
}
public Connection(ContentXElement element, ConnectionPanel connectionPanel, IdRemap idRemap)
public Connection(ContentXElement element, int connectionIndex, ConnectionPanel connectionPanel, IdRemap idRemap, bool isItemSwap)
{
#if CLIENT
@@ -117,25 +119,44 @@ namespace Barotrauma.Items.Components
IsOutput = element.Name.ToString() == "output";
Name = element.GetAttributeString("name", IsOutput ? "output" : "input");
int displayOrder;
if (element.GetAttribute("displayorderoverride") is not { } displayOrderAttr)
{
var sameElements = connectionPanel.Connections.Where(c => c.IsOutput == IsOutput);
displayOrder = !sameElements.Any() ? 0 : sameElements.Max(static c => c.DisplayOrder) + 1;
}
else
{
displayOrder = displayOrderAttr.GetAttributeInt(0);
}
DisplayOrder = displayOrder;
string displayNameTag = "", fallbackTag = "";
//if displayname is not present, attempt to find it from the prefab
if (element.GetAttribute("displayname") == null)
{
foreach (var subElement in item.Prefab.ConfigElement.Elements())
{
if (!subElement.Name.ToString().Equals("connectionpanel", StringComparison.OrdinalIgnoreCase)) { continue; }
if (!subElement.Name.ToString().Equals("connectionpanel", StringComparison.OrdinalIgnoreCase)) { continue; }
int prefabConnectionIndex = 0;
foreach (XElement connectionElement in subElement.Elements())
{
string prefabConnectionName = connectionElement.GetAttributeString("name", null);
if (prefabConnectionName.IsNullOrEmpty()) { continue; }
string[] aliases = connectionElement.GetAttributeStringArray("aliases", Array.Empty<string>());
if (prefabConnectionName == Name || aliases.Contains(Name))
if (prefabConnectionName == Name || aliases.Contains(Name) ||
//when swapping items, we move wires based on the order of the connections, not the names
//= we should find a connection based on the index if the name doesn't match
(isItemSwap && connectionIndex == prefabConnectionIndex))
{
displayNameTag = connectionElement.GetAttributeString("displayname", "");
fallbackTag = connectionElement.GetAttributeString("fallbackdisplayname", "");
}
prefabConnectionIndex++;
}
}
}
}
else
{
@@ -78,10 +78,10 @@ namespace Barotrauma.Items.Components
switch (subElement.Name.ToString())
{
case "input":
Connections.Add(new Connection(subElement, this, IdRemap.DiscardId));
Connections.Add(new Connection(subElement, connectionIndex: Connections.Count, this, IdRemap.DiscardId, isItemSwap: false));
break;
case "output":
Connections.Add(new Connection(subElement, this, IdRemap.DiscardId));
Connections.Add(new Connection(subElement, connectionIndex: Connections.Count, this, IdRemap.DiscardId, isItemSwap: false));
break;
}
}
@@ -293,10 +293,10 @@ namespace Barotrauma.Items.Components
switch (subElement.Name.ToString())
{
case "input":
loadedConnections.Add(new Connection(subElement, this, idRemap));
loadedConnections.Add(new Connection(subElement, connectionIndex: loadedConnections.Count, this, idRemap, isItemSwap));
break;
case "output":
loadedConnections.Add(new Connection(subElement, this, idRemap));
loadedConnections.Add(new Connection(subElement, connectionIndex: loadedConnections.Count, this, idRemap, isItemSwap));
break;
}
}
@@ -1,4 +1,5 @@
using System;
using Barotrauma.Networking;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -7,7 +8,7 @@ namespace Barotrauma.Items.Components;
/// <summary>
/// Base class for signal components that can select between input/output connections (e.g. multiplexer and demultiplexer components)
/// </summary>
abstract class ConnectionSelectorComponent : ItemComponent
abstract partial class ConnectionSelectorComponent : ItemComponent, IServerSerializable
{
protected int selectedConnectionIndex;
protected string selectedConnectionIndexStr;
@@ -22,6 +23,8 @@ abstract class ConnectionSelectorComponent : ItemComponent
get { return selectedConnectionIndex; }
set
{
int prevIndex = selectedConnectionIndex; // store original, so we know if the state has changed and can sync it in MP
selectedConnectionIndex = Math.Max(0, value);
//don't clamp until we've determined how many connections the item has
//(can't be done until the connection panel component has been loaded too)
@@ -31,6 +34,11 @@ abstract class ConnectionSelectorComponent : ItemComponent
}
selectedConnectionName = GetConnectionName(selectedConnectionIndex);
selectedConnectionIndexStr = selectedConnectionIndex.ToString();
if (prevIndex != selectedConnectionIndex)
{
OnStateChanged();
}
}
}
@@ -55,6 +63,8 @@ abstract class ConnectionSelectorComponent : ItemComponent
{
}
partial void OnStateChanged();
protected abstract string GetConnectionName(int connectionIndex);
/// <summary>
@@ -63,10 +63,7 @@ namespace Barotrauma.Items.Components
/// This can be used to make them additionally work the other way around, periodically getting the current value of the property from the item and refreshing the UI.
/// </summary>
public float GetValueInterval { get; set; } = -1.0f;
#if CLIENT
public float GetValueTimer;
#endif
public string Name => "CustomInterfaceElement";
@@ -248,7 +245,7 @@ namespace Barotrauma.Items.Components
ciElement.Label = "Signal out " + customInterfaceElementList.Count(e => e.ContinuousSignal == ciElement.ContinuousSignal);
}
customInterfaceElementList.Add(ciElement);
IsActive |= ciElement.ContinuousSignal;
IsActive |= ciElement.ContinuousSignal || ciElement.GetValueInterval > 0.0f;
}
InitProjSpecific();
@@ -348,13 +345,10 @@ namespace Barotrauma.Items.Components
//make sure the clients know about the states of the checkboxes and text fields
if (customInterfaceElementList.Any())
{
if (item.FullyInitialized)
CoroutineManager.Invoke(() =>
{
CoroutineManager.Invoke(() =>
{
if (!item.Removed) { item.CreateServerEvent(this); }
}, delay: 0.1f);
}
if (item.FullyInitialized && !item.Removed) { item.CreateServerEvent(this); }
}, delay: 0.1f);
}
#endif
}
@@ -418,6 +412,16 @@ namespace Barotrauma.Items.Components
{
foreach (CustomInterfaceElement ciElement in customInterfaceElementList)
{
if (ciElement.GetValueInterval > 0.0f)
{
ciElement.GetValueTimer -= deltaTime;
if (ciElement.GetValueTimer <= 0.0f)
{
SetSignalToPropertyValue(ciElement);
ciElement.GetValueTimer = ciElement.GetValueInterval;
}
}
if (!ciElement.ContinuousSignal && ciElement.PropertyName != "Voltage") { continue; }
//TODO: allow changing output when a tickbox is not selected
if (!string.IsNullOrEmpty(ciElement.Signal) && ciElement.Connection != null)
@@ -140,7 +140,7 @@ namespace Barotrauma.Items.Components
}
}
[Editable(MinValueFloat = 0.0f, MaxValueFloat = 1.0f, DecimalCount = 2), Serialize(0.0f, IsPropertySaveable.Yes, description: "How much light pulsates (in Hz). 0 = not at all, 1 = alternates between full brightness and off.")]
[Editable(MinValueFloat = 0.0f, MaxValueFloat = 1.0f, DecimalCount = 2), Serialize(0.0f, IsPropertySaveable.Yes, description: "How much light pulsates. 0 = not at all, 1 = alternates between full brightness and off.")]
public float PulseAmount
{
get { return pulseAmount; }