ExternalCondition: List<struct TimedToken> timedTokens

This commit is contained in:
atlimit8
2017-08-27 11:21:21 +00:00
committed by Paul Chote
parent 62c76b8ae9
commit c61cd37bec

View File

@@ -34,10 +34,10 @@ namespace OpenRA.Mods.Common.Traits
public class ExternalCondition : ITick public class ExternalCondition : ITick
{ {
class TimedToken struct TimedToken
{ {
public readonly int Token;
public readonly int Expires; public readonly int Expires;
public readonly int Token;
public readonly object Source; public readonly object Source;
public TimedToken(int token, Actor self, object source, int duration) public TimedToken(int token, Actor self, object source, int duration)
@@ -51,7 +51,9 @@ namespace OpenRA.Mods.Common.Traits
public readonly ExternalConditionInfo Info; public readonly ExternalConditionInfo Info;
readonly ConditionManager conditionManager; readonly ConditionManager conditionManager;
readonly Dictionary<object, HashSet<int>> permanentTokens = new Dictionary<object, HashSet<int>>(); readonly Dictionary<object, HashSet<int>> permanentTokens = new Dictionary<object, HashSet<int>>();
readonly List<KeyValuePair<int, TimedToken>> timedTokensByExpiration = new List<KeyValuePair<int, TimedToken>>();
// Tokens are sorted on insert/remove by ascending expiry time
readonly List<TimedToken> timedTokens = new List<TimedToken>();
public ExternalCondition(Actor self, ExternalConditionInfo info) public ExternalCondition(Actor self, ExternalConditionInfo info)
{ {
@@ -79,20 +81,6 @@ namespace OpenRA.Mods.Common.Traits
return true; return true;
} }
void Remove(TimedToken timedToken)
{
timedTokensByExpiration.RemoveAt(timedTokensByExpiration.FindIndex(p => p.Value == timedToken));
}
void Add(TimedToken timedToken)
{
var index = timedTokensByExpiration.FindIndex(p => p.Key >= timedToken.Expires);
if (index >= 0)
timedTokensByExpiration.Insert(index, new KeyValuePair<int, TimedToken>(timedToken.Expires, timedToken));
else
timedTokensByExpiration.Add(new KeyValuePair<int, TimedToken>(timedToken.Expires, timedToken));
}
public int GrantCondition(Actor self, object source, int duration = 0) public int GrantCondition(Actor self, object source, int duration = 0)
{ {
if (!CanGrantCondition(self, source)) if (!CanGrantCondition(self, source))
@@ -107,41 +95,44 @@ namespace OpenRA.Mods.Common.Traits
// Check level caps // Check level caps
if (Info.SourceCap > 0) if (Info.SourceCap > 0)
{ {
var timedCount = timedTokensByExpiration.Count(p => p.Value.Source == source); var timedCount = timedTokens.Count(t => t.Source == source);
if ((permanent != null ? permanent.Count + timedCount : timedCount) >= Info.SourceCap) if ((permanent != null ? permanent.Count + timedCount : timedCount) >= Info.SourceCap)
{ {
// Get timed token from the same source with closest expiration. // Get timed token from the same source with closest expiration.
var expireIndex = timedTokensByExpiration.FindIndex(t => t.Value.Source == source); var expireIndex = timedTokens.FindIndex(t => t.Source == source);
if (expireIndex >= 0) if (expireIndex >= 0)
{ {
var expire = timedTokensByExpiration[expireIndex].Value; var expireToken = timedTokens[expireIndex].Token;
Remove(expire); timedTokens.RemoveAt(expireIndex);
if (conditionManager.TokenValid(self, expireToken))
if (conditionManager.TokenValid(self, expire.Token)) conditionManager.RevokeCondition(self, expireToken);
conditionManager.RevokeCondition(self, expire.Token);
} }
} }
} }
if (Info.TotalCap > 0) if (Info.TotalCap > 0)
{ {
var totalCount = permanentTokens.Values.Sum(t => t.Count) + timedTokensByExpiration.Count; var totalCount = permanentTokens.Values.Sum(t => t.Count) + timedTokens.Count;
if (totalCount >= Info.TotalCap) if (totalCount >= Info.TotalCap)
{ {
// Prefer tokens from the same source // Prefer tokens from the same source
var expire = timedTokensByExpiration.FirstOrDefault().Value; if (timedTokens.Count > 0)
if (expire != null)
{ {
if (conditionManager.TokenValid(self, expire.Token)) var expire = timedTokens[0].Token;
conditionManager.RevokeCondition(self, expire.Token); if (conditionManager.TokenValid(self, expire))
conditionManager.RevokeCondition(self, expire);
Remove(expire); timedTokens.RemoveAt(0);
} }
} }
} }
var timedToken = new TimedToken(token, self, source, duration); var timedToken = new TimedToken(token, self, source, duration);
Add(timedToken); var index = timedTokens.FindIndex(t => t.Expires >= timedToken.Expires);
if (index >= 0)
timedTokens.Insert(index, timedToken);
else
timedTokens.Add(timedToken);
} }
else if (permanent == null) else if (permanent == null)
permanentTokens.Add(source, new HashSet<int> { token }); permanentTokens.Add(source, new HashSet<int> { token });
@@ -166,9 +157,9 @@ namespace OpenRA.Mods.Common.Traits
} }
else else
{ {
var index = timedTokensByExpiration.FindIndex(p => p.Value.Token == token); var index = timedTokens.FindIndex(p => p.Token == token);
if (index >= 0 && timedTokensByExpiration[index].Value.Source == source) if (index >= 0 && timedTokens[index].Source == source)
timedTokensByExpiration.RemoveAt(index); timedTokens.RemoveAt(index);
else else
return false; return false;
} }
@@ -184,11 +175,11 @@ namespace OpenRA.Mods.Common.Traits
// Remove expired tokens // Remove expired tokens
var worldTick = self.World.WorldTick; var worldTick = self.World.WorldTick;
var count = 0; var count = 0;
while (count < timedTokensByExpiration.Count && timedTokensByExpiration[count].Key < worldTick) while (count < timedTokens.Count && timedTokens[count].Expires < worldTick)
count++; count++;
if (count > 0) if (count > 0)
timedTokensByExpiration.RemoveRange(0, count); timedTokens.RemoveRange(0, count);
} }
} }
} }