Item/statuseffect optimization:

- PowerTransfer components cache power connections instead of rechecking them every frame
- items store connections in a dictionary with the name of the connection as a key (-> finding the correct connection when sending a signal is more efficient)
- storing item tags & StatusEffect targetNames in HashSets
This commit is contained in:
Regalis
2016-11-08 21:14:29 +02:00
parent 1dc08b3019
commit 1617cd8f7a
4 changed files with 120 additions and 69 deletions
+75 -35
View File
@@ -36,7 +36,7 @@ namespace Barotrauma
public static bool ShowLinks = true;
private List<string> tags;
private HashSet<string> tags;
public Hull CurrentHull;
@@ -55,6 +55,9 @@ namespace Barotrauma
private bool inWater;
private Inventory parentInventory;
private Inventory ownInventory;
private Dictionary<string, Connection> connections;
//a dictionary containing lists of the status effects in all the components of the item
private Dictionary<ActionType, List<StatusEffect>> statusEffectLists;
@@ -275,8 +278,7 @@ namespace Barotrauma
{
get
{
ItemContainer c = GetComponent<ItemContainer>();
return (c == null) ? null : Array.FindAll(c.Inventory.Items, i=>i!=null);
return (ownInventory == null) ? null : Array.FindAll(ownInventory.Items, i => i != null);
}
}
@@ -326,7 +328,7 @@ namespace Barotrauma
components = new List<ItemComponent>();
drawableComponents = new List<IDrawableComponent>();
FixRequirements = new List<FixRequirement>();
tags = new List<string>();
tags = new HashSet<string>();
rect = newRect;
@@ -401,6 +403,12 @@ namespace Barotrauma
if (body != null) body.FarseerBody.OnCollision += OnCollision;
}
var itemContainer = GetComponent<ItemContainer>();
if (itemContainer!=null)
{
ownInventory = itemContainer.Inventory;
}
InsertToList();
ItemList.Add(this);
}
@@ -428,15 +436,16 @@ namespace Barotrauma
public void RemoveContained(Item contained)
{
ItemContainer c = GetComponent<ItemContainer>();
if (c == null) return;
c.RemoveContained(contained);
if (ownInventory != null)
{
ownInventory.RemoveItem(contained);
}
contained.Container = null;
}
public void SetTransform(Vector2 simPosition, float rotation)
public void SetTransform(Vector2 simPosition, float rotation, bool findNewHull = true)
{
if (body != null)
{
@@ -457,7 +466,7 @@ namespace Barotrauma
rect.X = (int)(displayPos.X - rect.Width / 2.0f);
rect.Y = (int)(displayPos.Y + rect.Height / 2.0f);
FindHull();
if (findNewHull) FindHull();
}
public override void Move(Vector2 amount)
@@ -544,7 +553,34 @@ namespace Barotrauma
return rootContainer;
}
public void SetContainedItemPositions()
{
if (ownInventory == null) return;
Vector2 simPos = SimPosition;
Vector2 displayPos = Position;
foreach (Item contained in ownInventory.Items)
{
if (contained == null) continue;
if (contained.body != null)
{
contained.body.FarseerBody.SetTransformIgnoreContacts(ref simPos, 0.0f);
}
contained.Rect =
new Rectangle(
(int)(displayPos.X - contained.Rect.Width / 2.0f),
(int)(displayPos.Y + contained.Rect.Height / 2.0f),
contained.Rect.Width, contained.Rect.Height);
contained.Submarine = Submarine;
contained.CurrentHull = CurrentHull;
}
}
public void AddTag(string tag)
{
if (tags.Contains(tag)) return;
@@ -580,16 +616,15 @@ namespace Barotrauma
bool hasTargets = (effect.TargetNames == null);
Item[] containedItems = ContainedItems;
if (effect.OnContainingNames!=null)
if (effect.OnContainingNames != null)
{
foreach (string s in effect.OnContainingNames)
{
if (containedItems.FirstOrDefault(x => x!=null && x.Name==s && x.Condition>0.0f) == null) return;
if (!containedItems.Any(x => x!=null && x.Name==s && x.Condition > 0.0f)) return;
}
}
List<IPropertyObject> targets = new List<IPropertyObject>();
if (containedItems != null)
{
if (effect.Targets.HasFlag(StatusEffect.TargetType.Contained))
@@ -691,8 +726,7 @@ namespace Barotrauma
{
ic.Update(deltaTime, cam);
if (ic.IsActive) ic.PlaySound(ActionType.OnActive, WorldPosition);
//ic.ApplyStatusEffects(ActionType.OnActive, deltaTime, null);
if (ic.IsActive) ic.PlaySound(ActionType.OnActive, WorldPosition);
}
else
{
@@ -1154,25 +1188,23 @@ namespace Barotrauma
public void SendSignal(int stepsTaken, string signal, string connectionName, float power = 0.0f)
{
if (connections == null) return;
stepsTaken++;
ConnectionPanel panel = GetComponent<ConnectionPanel>();
if (panel == null) return;
foreach (Connection c in panel.Connections)
Connection c = null;
if (!connections.TryGetValue(connectionName, out c)) return;
if (stepsTaken > 10)
{
if (c.Name != connectionName) continue;
if (stepsTaken > 10)
{
//use a coroutine to prevent infinite loops by creating a one
//frame delay if the "signal chain" gets too long
CoroutineManager.StartCoroutine(SendSignal(signal, c, power));
}
else
{
c.SendSignal(stepsTaken, signal, this, power);
}
//use a coroutine to prevent infinite loops by creating a one
//frame delay if the "signal chain" gets too long
CoroutineManager.StartCoroutine(SendSignal(signal, c, power));
}
else
{
c.SendSignal(stepsTaken, signal, this, power);
}
}
private IEnumerable<object> SendSignal(string signal, Connection connection, float power = 0.0f)
@@ -1180,9 +1212,6 @@ namespace Barotrauma
//wait one frame
yield return CoroutineStatus.Running;
ConnectionPanel panel = GetComponent<ConnectionPanel>();
if (panel == null) yield return CoroutineStatus.Success;
connection.SendSignal(0, signal, this, power);
yield return CoroutineStatus.Success;
@@ -1654,7 +1683,18 @@ namespace Barotrauma
foreach (ItemComponent ic in components)
{
ic.OnMapLoaded();
}
}
//cache connections into a dictionary for faster lookups
var connectionPanel = GetComponent<ConnectionPanel>();
connections = new Dictionary<string, Connection>();
if (connectionPanel == null) return;
foreach (Connection c in connectionPanel.Connections)
{
if (!connections.ContainsKey(c.Name))
connections.Add(c.Name, c);
}
}