/// <summary> /// Add a StatusInstance to this tracker, updating the value of the status associated with the given instance. /// </summary> public bool AddStatusInstance(StatusInstance <TObject> instance) { if (instance == null) { throw new ArgumentNullException(); } if (instance.tracker != null && instance.tracker != this) { throw new InvalidOperationException("Already added to another tracker"); } TBaseStatus status = instance.Status; InstanceType type = instance.InstanceType; if (type == InstanceType.Feed) { if (currentRaw[InstanceType.Prevent][status] > 0) { return(false); } var preventableStatuses = new List <TBaseStatus> { status }.Concat(rules.statusesExtendedBy[status]); foreach (var preventableStatus in preventableStatuses) { if (rules.extraPreventionConditions.AnyValues(preventableStatus)) { foreach (var condition in rules.extraPreventionConditions[preventableStatus]) { if (condition(obj, preventableStatus)) { return(false); } } } } if (rules.SingleInstance[status]) { foreach (StatusInstance <TObject> removedInstance in statusInstances[InstanceType.Feed][status]) { removedInstance.tracker = null; } statusInstances[InstanceType.Feed].Clear(status); } } if (statusInstances[type].AddUnique(status, instance)) { instance.tracker = this; CheckInstanceChanged(instance); return(true); } else { return(false); } }
/// <summary> /// Create a new StatusInstance and add it to this tracker, updating the value of the given status. /// Returns the newly created instance, if successfully added, or null, if not. /// </summary> /// <param name="status">The status to which the instance will add its value</param> /// <param name="value">The amount by which the instance will increase the given status</param> /// <param name="cancelPriority">An instance with lower cancel priority will be cancelled before an instance with /// higher priority when Cancel() is called on its status.</param> /// <param name="type"> /// The InstanceType determines whether the instance will feed, suppress, or prevent its status. /// (Feed is the default and most common. When a status is cancelled, its "Feed" StatusInstances are removed.) /// </param> public StatusInstance <TObject> Add(TBaseStatus status, int value = 1, int cancelPriority = 0, InstanceType type = InstanceType.Feed, int?overrideSetIndex = null) { var instance = new StatusInstance <TObject>(status, value, cancelPriority, type, overrideSetIndex); if (AddStatusInstance(instance)) { return(instance); } else { return(null); } }
/// <summary> /// Create a new StatusInstance and add it to this tracker, updating the value of the given status. /// Returns the newly created instance, if successfully added, or null, if not. /// </summary> /// <param name="status">The status to which the instance will add its value</param> /// <param name="value">The amount by which the instance will increase the given status</param> /// <param name="cancelPriority">An instance with lower cancel priority will be cancelled before an instance with /// higher priority when Cancel() is called on its status.</param> /// <param name="type"> /// The InstanceType determines whether the instance will feed, suppress, or prevent its status. /// (Feed is the default and most common. When a status is cancelled, its "Feed" StatusInstances are removed.) /// </param> public StatusInstance <TObject> Add <TStatus>(TStatus status, int value = 1, int cancelPriority = 0, InstanceType type = InstanceType.Feed, int?overrideSetIndex = null) where TStatus : struct { var instance = new StatusInstance <TObject>(Convert(status), value, cancelPriority, type, overrideSetIndex); if (AddStatusInstance(instance)) { return(instance); } else { return(null); } }
private void DeserializeStatusInstances(MultiValueDictionary <TBaseStatus, StatusInstance <TObject> > dict, System.IO.BinaryReader reader, Action <System.IO.BinaryReader, StatusInstance <TObject>, TObject> statusInstanceCallback) { int allKeysCount = reader.ReadInt32(); for (int i = 0; i < allKeysCount; ++i) { int key = reader.ReadInt32(); int count = reader.ReadInt32(); for (int j = 0; j < count; ++j) { StatusInstance <TObject> instance = StatusInstance <TObject> .Deserialize(reader); instance.tracker = this; dict.Add(key, instance); statusInstanceCallback?.Invoke(reader, instance, obj); } } }
internal void CheckInstanceChanged(StatusInstance <TObject> instance) { bool stacked = instance.overrideSetIndex != null; if (stacked) { OverrideSet <TObject> overrideSet = rules.overrideSets[instance.overrideSetIndex.Value]; if (overrideSet == null) { throw new InvalidOperationException($"Override set {instance.overrideSetIndex.Value} does not exist"); } changeStack.Add(overrideSet.onChangedOverrides); } CheckRawChanged(instance.Status, instance.InstanceType); if (stacked) { changeStack.RemoveAt(changeStack.Count - 1); } }
/// <summary>Deserialize and return a StatusInstance that was serialized outside of a StatusTracker.</summary> /// <param name="reader">Deserialize from this BinaryReader. The underlying stream will NOT be automatically closed.</param> public static StatusInstance <TObject> Deserialize(System.IO.BinaryReader reader) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } int status = reader.ReadInt32(); int type = reader.ReadInt32(); int value = reader.ReadInt32(); int priority = reader.ReadInt32(); int?overrideIdx = null; if (reader.ReadBoolean()) { overrideIdx = reader.ReadInt32(); } StatusInstance <TObject> instance = new StatusInstance <TObject>(status, value, priority, (InstanceType)type, overrideIdx); return(instance); }
/// <summary> /// Remove a StatusInstance from this tracker, updating the value of the status associated with the given instance. /// Returns true if successful, or false if the instance wasn't in this tracker. /// </summary> public bool RemoveStatusInstance(StatusInstance <TObject> instance) { if (instance == null) { throw new ArgumentNullException(); } TBaseStatus status = instance.Status; InstanceType type = instance.InstanceType; if (statusInstances[type].Remove(status, instance)) { instance.tracker = null; CheckInstanceChanged(instance); return(true); } else { return(false); } }
protected StatusInstance(StatusInstance <TObject> copyFrom, int?value = null, int?cancelPriority = null, InstanceType?type = null, int?overrideSetIndex = null) { if (copyFrom == null) { throw new ArgumentNullException("copyFrom"); } Status = copyFrom.Status; if (value == null) { internalValue = copyFrom.internalValue; } else { internalValue = value.Value; } if (cancelPriority == null) { CancelPriority = copyFrom.CancelPriority; } else { CancelPriority = cancelPriority.Value; } if (type == null) { InstanceType = copyFrom.InstanceType; } else { InstanceType = type.Value; } if (overrideSetIndex == null) { this.overrideSetIndex = copyFrom.overrideSetIndex; } else { this.overrideSetIndex = overrideSetIndex; } }