aura effects that will run for longer will not get replaced by aura effects that would end sooner

This commit is contained in:
FateJH 2020-08-20 09:22:22 -04:00
parent f627571f0e
commit ac5e26f37a
2 changed files with 73 additions and 11 deletions

View file

@ -23,7 +23,7 @@ trait AuraEffectBehavior {
* key - aura effect; value - the timer for that effect * key - aura effect; value - the timer for that effect
* @see `ApplicableEffect` * @see `ApplicableEffect`
*/ */
private val effectToTimer: mutable.HashMap[Aura, Cancellable] = mutable.HashMap.empty[Aura, Cancellable] private val effectToTimer: mutable.HashMap[Aura, AuraEffectBehavior.Entry] = mutable.HashMap.empty[Aura, AuraEffectBehavior.Entry]
def AuraTargetObject: AuraEffectBehavior.Target def AuraTargetObject: AuraEffectBehavior.Target
@ -44,7 +44,7 @@ trait AuraEffectBehavior {
*/ */
def ApplicableEffect(effect: Aura): Unit = { def ApplicableEffect(effect: Aura): Unit = {
//create entry //create entry
effectToTimer += effect -> Default.Cancellable effectToTimer += effect -> AuraEffectBehavior.Entry()
} }
/** /**
@ -67,27 +67,29 @@ trait AuraEffectBehavior {
/** /**
* As long as the effect has been approved for this target, * As long as the effect has been approved for this target,
* the timer will either start if it is stopped or has never been started, * the timer will either start if it is stopped or has never been started,
* or the timer will stop and be recreated with the new duration if is currently running. * or the timer will stop and be recreated with the new duration if is currently running for a shoreter amount of time.
* @param effect the effect to be emitted * @param effect the effect to be emitted
* @param duration for how long the effect will be emitted * @param duration for how long the effect will be emitted
* @return `true`, if the timer was started or restarted; * @return `true`, if the timer was started or restarted;
* `false`, otherwise * `false`, otherwise
*/ */
private def StartAuraTimer(effect: Aura, duration: Long): Boolean = { private def StartAuraTimer(effect: Aura, duration: Long): Boolean = {
//pair aura effect with id //pair aura effect with entry
(effectToTimer.get(effect) match { (effectToTimer.get(effect) match {
case None => case Some(timer) if timer.start + timer.duration < System.currentTimeMillis() + duration =>
None
case Some(timer) =>
timer.cancel() timer.cancel()
Some(effect) Some(effect)
case _ =>
None
}) match { }) match {
case None => case None =>
false false
case Some(_) => case Some(_) =>
//paired id with timer; retime //retime
effectToTimer(effect) = effectToTimer(effect) = AuraEffectBehavior.Entry(
duration,
context.system.scheduler.scheduleOnce(duration milliseconds, self, AuraEffectBehavior.EndEffect(effect)) context.system.scheduler.scheduleOnce(duration milliseconds, self, AuraEffectBehavior.EndEffect(effect))
)
true true
} }
} }
@ -102,7 +104,7 @@ trait AuraEffectBehavior {
effectToTimer.get(effect) match { effectToTimer.get(effect) match {
case Some(timer) if !timer.isCancelled => case Some(timer) if !timer.isCancelled =>
timer.cancel() timer.cancel()
effectToTimer(effect) = Default.Cancellable //effectToTimer(effect) = Default.Cancellable
AuraTargetObject.RemoveEffectFromAura(effect) AuraTargetObject.RemoveEffectFromAura(effect)
true true
case _ => case _ =>
@ -116,7 +118,7 @@ trait AuraEffectBehavior {
def EndAllEffects() : Unit = { def EndAllEffects() : Unit = {
effectToTimer.keysIterator.foreach { effect => effectToTimer.keysIterator.foreach { effect =>
effectToTimer(effect).cancel() effectToTimer(effect).cancel()
effectToTimer(effect) = Default.Cancellable //effectToTimer(effect) = Default.Cancellable
} }
val obj = AuraTargetObject val obj = AuraTargetObject
obj.Aura.foreach { obj.RemoveEffectFromAura } obj.Aura.foreach { obj.RemoveEffectFromAura }
@ -164,6 +166,18 @@ trait AuraEffectBehavior {
object AuraEffectBehavior { object AuraEffectBehavior {
type Target = PlanetSideServerObject with AuraContainer type Target = PlanetSideServerObject with AuraContainer
case class Entry(duration: Long, timer: Cancellable) extends Cancellable {
val start: Long = System.currentTimeMillis()
override def isCancelled : Boolean = timer.isCancelled
override def cancel: Boolean = timer.cancel
}
object Entry {
def apply(): Entry = Entry(0, Default.Cancellable)
}
final case class StartEffect(effect: Aura, duration: Long) final case class StartEffect(effect: Aura, duration: Long)
final case class EndEffect(aura: Aura) final case class EndEffect(aura: Aura)

View file

@ -116,6 +116,31 @@ class AuraEffectBehaviorStartEffectTest extends ActorTest {
} }
} }
class AuraEffectBehaviorStartLongerEffectTest extends ActorTest {
val obj = new AuraTest.Entity()
val updateProbe = new TestProbe(system)
obj.Actor = system.actorOf(Props(classOf[AuraTest.Agency], obj, updateProbe.ref), "aura-test-actor")
"AuraEffectBehavior" should {
"replace a shorter effect with a longer one" in {
assert(obj.Aura.isEmpty)
obj.Actor ! AuraEffectBehavior.StartEffect(Aura.Plasma, 500)
val msg1 = updateProbe.receiveOne(100 milliseconds)
assert(
msg1 match {
case AuraTest.DoUpdateAuraEffect() => true
case _ => false
}
)
assert(obj.Aura.contains(Aura.Plasma))
obj.Actor ! AuraEffectBehavior.StartEffect(Aura.Plasma, 2500)
updateProbe.expectNoMessage(2000 milliseconds)
//first effect has not ended naturally (yet)
assert(obj.Aura.contains(Aura.Plasma))
}
}
}
class AuraEffectBehaviorNoRedundantStartEffectTest extends ActorTest { class AuraEffectBehaviorNoRedundantStartEffectTest extends ActorTest {
val obj = new AuraTest.Entity() val obj = new AuraTest.Entity()
val updateProbe = new TestProbe(system) val updateProbe = new TestProbe(system)
@ -137,6 +162,29 @@ class AuraEffectBehaviorNoRedundantStartEffectTest extends ActorTest {
assert(obj.Aura.contains(Aura.Plasma)) assert(obj.Aura.contains(Aura.Plasma))
obj.Actor ! AuraEffectBehavior.StartEffect(Aura.Plasma, 2500) obj.Actor ! AuraEffectBehavior.StartEffect(Aura.Plasma, 2500)
updateProbe.expectNoMessage(1500 milliseconds) updateProbe.expectNoMessage(1500 milliseconds)
}
}
}
class AuraEffectBehaviorNoOverrideStartEffectTest extends ActorTest {
val obj = new AuraTest.Entity()
val updateProbe = new TestProbe(system)
obj.Actor = system.actorOf(Props(classOf[AuraTest.Agency], obj, updateProbe.ref), "aura-test-actor")
"AuraEffectBehavior" should {
"not replace a long-running effect with a short-running effect" in {
assert(obj.Aura.isEmpty)
obj.Actor ! AuraEffectBehavior.StartEffect(Aura.Plasma, 2500)
val msg1 = updateProbe.receiveOne(100 milliseconds)
assert(
msg1 match {
case AuraTest.DoUpdateAuraEffect() => true
case _ => false
}
)
assert(obj.Aura.contains(Aura.Plasma))
obj.Actor ! AuraEffectBehavior.StartEffect(Aura.Plasma, 500)
updateProbe.expectNoMessage(1500 milliseconds)
//effect has not ended naturally //effect has not ended naturally
assert(obj.Aura.contains(Aura.Plasma)) assert(obj.Aura.contains(Aura.Plasma))
} }