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
{
class TimedToken
struct TimedToken
{
public readonly int Token;
public readonly int Expires;
public readonly int Token;
public readonly object Source;
public TimedToken(int token, Actor self, object source, int duration)
@@ -51,7 +51,9 @@ namespace OpenRA.Mods.Common.Traits
public readonly ExternalConditionInfo Info;
readonly ConditionManager conditionManager;
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)
{
@@ -79,20 +81,6 @@ namespace OpenRA.Mods.Common.Traits
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)
{
if (!CanGrantCondition(self, source))
@@ -107,41 +95,44 @@ namespace OpenRA.Mods.Common.Traits
// Check level caps
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)
{
// 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)
{
var expire = timedTokensByExpiration[expireIndex].Value;
Remove(expire);
if (conditionManager.TokenValid(self, expire.Token))
conditionManager.RevokeCondition(self, expire.Token);
var expireToken = timedTokens[expireIndex].Token;
timedTokens.RemoveAt(expireIndex);
if (conditionManager.TokenValid(self, expireToken))
conditionManager.RevokeCondition(self, expireToken);
}
}
}
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)
{
// Prefer tokens from the same source
var expire = timedTokensByExpiration.FirstOrDefault().Value;
if (expire != null)
if (timedTokens.Count > 0)
{
if (conditionManager.TokenValid(self, expire.Token))
conditionManager.RevokeCondition(self, expire.Token);
var expire = timedTokens[0].Token;
if (conditionManager.TokenValid(self, expire))
conditionManager.RevokeCondition(self, expire);
Remove(expire);
timedTokens.RemoveAt(0);
}
}
}
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)
permanentTokens.Add(source, new HashSet<int> { token });
@@ -166,9 +157,9 @@ namespace OpenRA.Mods.Common.Traits
}
else
{
var index = timedTokensByExpiration.FindIndex(p => p.Value.Token == token);
if (index >= 0 && timedTokensByExpiration[index].Value.Source == source)
timedTokensByExpiration.RemoveAt(index);
var index = timedTokens.FindIndex(p => p.Token == token);
if (index >= 0 && timedTokens[index].Source == source)
timedTokens.RemoveAt(index);
else
return false;
}
@@ -184,11 +175,11 @@ namespace OpenRA.Mods.Common.Traits
// Remove expired tokens
var worldTick = self.World.WorldTick;
var count = 0;
while (count < timedTokensByExpiration.Count && timedTokensByExpiration[count].Key < worldTick)
while (count < timedTokens.Count && timedTokens[count].Expires < worldTick)
count++;
if (count > 0)
timedTokensByExpiration.RemoveRange(0, count);
timedTokens.RemoveRange(0, count);
}
}
}