mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-01-20 02:24:45 +00:00
registered object retain their GUID after being unregistered
This commit is contained in:
parent
ae7f8bf71d
commit
f9414a6798
|
|
@ -9,25 +9,42 @@ import net.psforever.packet.game.PlanetSideGUID
|
|||
* "Testing" the object refers to the act of acquiring a reference to the GUID the object is using.
|
||||
* This object starts with a container class that represents a unprepared GUID state and raises an `Exception` when tested.
|
||||
* Setting a proper `PlanetSideGUID` replaces that container class with a container class that returns the GUID when tested.
|
||||
* The object can be invalidated, restoring the previous `Exception`-raising condition.
|
||||
* @throws `NoGUIDException` if there is no GUID to give
|
||||
* The object can be invalidated, retaining the previous identifier number, but marking that object as being "stale."
|
||||
* "Staleness" is a property indicating whether or not the number can be used as a valid representation of the object.
|
||||
* @throws `NoGUIDException` if a GUID has not yet been assigned
|
||||
*/
|
||||
abstract class IdentifiableEntity extends Identifiable {
|
||||
/** indicate the validity of the current GUID */
|
||||
private var stale : Boolean = true
|
||||
/** storage for the active GUID */
|
||||
private val container : GUIDContainable = GUIDContainer()
|
||||
/** the handle for the active GUID; starts as exception-throwing */
|
||||
private var current : GUIDContainable = IdentifiableEntity.noGUIDContainer
|
||||
|
||||
def HasGUID : Boolean = current ne IdentifiableEntity.noGUIDContainer
|
||||
/**
|
||||
* The object will not originally having a valid GUID,
|
||||
* so "stale" will be used to expressed "not initialized."
|
||||
* After being set and then properly invalidated, then it will indicate proper staleness.
|
||||
* @return whether the value of the GUID is a valid representation for this object
|
||||
*/
|
||||
def HasGUID : Boolean = !stale
|
||||
|
||||
def GUID : PlanetSideGUID = current.GUID
|
||||
|
||||
def GUID_=(guid : PlanetSideGUID) : PlanetSideGUID = {
|
||||
stale = false
|
||||
current = container
|
||||
current.GUID = guid
|
||||
GUID
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the staleness to indicate whether the GUID has ever been set
|
||||
* or that the set GUID is not a proper representation of the object.
|
||||
* It is always set to `true`.
|
||||
*/
|
||||
def Invalidate() : Unit = {
|
||||
current = IdentifiableEntity.noGUIDContainer
|
||||
stale = true
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -50,7 +67,7 @@ private case class NoGUIDContainer() extends GUIDContainable {
|
|||
* @return never returns
|
||||
*/
|
||||
def GUID : PlanetSideGUID = {
|
||||
throw NoGUIDException("object has not initialized a global identifier")
|
||||
throw NoGUIDException(s"object $this has not initialized a global identifier")
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -106,14 +106,16 @@ class EntityTest extends Specification {
|
|||
ok
|
||||
}
|
||||
|
||||
"error while unset" in {
|
||||
"error while not set" in {
|
||||
val obj : EntityTestClass = new EntityTestClass
|
||||
obj.HasGUID mustEqual false
|
||||
obj.GUID must throwA[NoGUIDException]
|
||||
}
|
||||
|
||||
"work after mutation" in {
|
||||
val obj : EntityTestClass = new EntityTestClass
|
||||
obj.GUID = PlanetSideGUID(1051)
|
||||
obj.HasGUID mustEqual true
|
||||
obj.GUID mustEqual PlanetSideGUID(1051)
|
||||
}
|
||||
|
||||
|
|
@ -127,12 +129,43 @@ class EntityTest extends Specification {
|
|||
obj.GUID mustEqual PlanetSideGUID(62)
|
||||
}
|
||||
|
||||
"invalidate and resume error" in {
|
||||
"invalidate and report as not having a GUID, but continue to work" in {
|
||||
val obj : EntityTestClass = new EntityTestClass
|
||||
obj.GUID = PlanetSideGUID(1051)
|
||||
obj.HasGUID mustEqual true
|
||||
obj.GUID mustEqual PlanetSideGUID(1051)
|
||||
obj.Invalidate()
|
||||
obj.GUID must throwA[NoGUIDException]
|
||||
obj.HasGUID mustEqual false
|
||||
obj.GUID mustEqual PlanetSideGUID(1051)
|
||||
}
|
||||
|
||||
"assign a new GUID after invalidation and continue to work" in {
|
||||
val obj : EntityTestClass = new EntityTestClass
|
||||
obj.GUID = PlanetSideGUID(1051)
|
||||
obj.HasGUID mustEqual true
|
||||
obj.GUID mustEqual PlanetSideGUID(1051)
|
||||
obj.Invalidate()
|
||||
obj.GUID mustEqual PlanetSideGUID(1051)
|
||||
obj.HasGUID mustEqual false
|
||||
|
||||
obj.GUID = PlanetSideGUID(1052)
|
||||
obj.HasGUID mustEqual true
|
||||
obj.GUID mustEqual PlanetSideGUID(1052)
|
||||
}
|
||||
|
||||
"assignthe same GUID after invalidation and continue to work" in {
|
||||
val obj : EntityTestClass = new EntityTestClass
|
||||
val guid = new PlanetSideGUID(1051)
|
||||
obj.GUID = guid
|
||||
obj.HasGUID mustEqual true
|
||||
obj.GUID mustEqual guid
|
||||
obj.Invalidate()
|
||||
obj.GUID mustEqual guid
|
||||
obj.HasGUID mustEqual false
|
||||
|
||||
obj.GUID = guid
|
||||
obj.HasGUID mustEqual true
|
||||
obj.GUID mustEqual guid
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects.number
|
||||
|
||||
import akka.actor.{ActorSystem, Props}
|
||||
import akka.actor.Props
|
||||
import base.ActorTest
|
||||
import net.psforever.objects.guid.actor.NumberPoolActor
|
||||
import net.psforever.objects.guid.pool.ExclusivePool
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ class NumberPoolHubTest extends Specification {
|
|||
obj.Numbers.toSet.equals(numberList.toSet) mustEqual true
|
||||
obj.RemovePool("fibonacci").toSet.equals(numberList.toSet) mustEqual true
|
||||
obj.Numbers.isEmpty mustEqual true
|
||||
obj.GetPool("fibonacci") mustEqual None
|
||||
obj.GetPool("fibonacci").isEmpty mustEqual true
|
||||
}
|
||||
|
||||
"block removing the default 'generic' pool" in {
|
||||
|
|
@ -101,7 +101,7 @@ class NumberPoolHubTest extends Specification {
|
|||
hub.register(obj, "fibonacci") match {
|
||||
case Success(number) =>
|
||||
val objFromNumber = hub(number)
|
||||
objFromNumber mustEqual Some(obj)
|
||||
objFromNumber.contains(obj) mustEqual true
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
|
|
@ -111,7 +111,7 @@ class NumberPoolHubTest extends Specification {
|
|||
val hub = new NumberPoolHub(new LimitedNumberSource(51))
|
||||
hub.AddPool("fibonacci1", numberList1)
|
||||
hub.AddPool("fibonacci2", numberList2)
|
||||
hub.WhichPool(13) mustEqual Some("fibonacci2")
|
||||
hub.WhichPool(13).contains("fibonacci2") mustEqual true
|
||||
}
|
||||
|
||||
"lookup the pool of a registered object" in {
|
||||
|
|
@ -119,7 +119,7 @@ class NumberPoolHubTest extends Specification {
|
|||
hub.AddPool("fibonacci", numberList1)
|
||||
val obj = new EntityTestClass()
|
||||
hub.register(obj, "fibonacci")
|
||||
hub.WhichPool(obj) mustEqual Some("fibonacci")
|
||||
hub.WhichPool(obj).contains("fibonacci") mustEqual true
|
||||
}
|
||||
|
||||
"register an object to a specific, unused number; it is assigned to pool 'generic'" in {
|
||||
|
|
@ -130,7 +130,7 @@ class NumberPoolHubTest extends Specification {
|
|||
hub.register(obj, 44) match {
|
||||
case Success(number) =>
|
||||
obj.GUID mustEqual PlanetSideGUID(number)
|
||||
hub.WhichPool(obj) mustEqual Some("generic")
|
||||
hub.WhichPool(obj).contains("generic") mustEqual true
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
|
|
@ -145,8 +145,8 @@ class NumberPoolHubTest extends Specification {
|
|||
hub.register(obj, 5) match {
|
||||
case Success(number) =>
|
||||
obj.GUID mustEqual PlanetSideGUID(number)
|
||||
hub.WhichPool(obj) mustEqual Some("fibonacci")
|
||||
src.Available(5) mustEqual None
|
||||
hub.WhichPool(obj).contains("fibonacci") mustEqual true
|
||||
src.Available(5).isEmpty mustEqual true
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
|
|
@ -161,8 +161,8 @@ class NumberPoolHubTest extends Specification {
|
|||
hub.register(obj, 13) match {
|
||||
case Success(number) =>
|
||||
obj.GUID mustEqual PlanetSideGUID(number)
|
||||
hub.WhichPool(obj) mustEqual Some("fibonacci")
|
||||
src.Available(13) mustEqual None
|
||||
hub.WhichPool(obj).contains("fibonacci") mustEqual true
|
||||
src.Available(13).isEmpty mustEqual true
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
|
|
@ -172,20 +172,21 @@ class NumberPoolHubTest extends Specification {
|
|||
val hub = new NumberPoolHub(new LimitedNumberSource(51))
|
||||
val obj = new EntityTestClass()
|
||||
hub.register(obj)
|
||||
hub.WhichPool(obj) mustEqual Some("generic")
|
||||
hub.WhichPool(obj).contains("generic") mustEqual true
|
||||
}
|
||||
|
||||
"unregister an object" in {
|
||||
val hub = new NumberPoolHub(new LimitedNumberSource(51))
|
||||
hub.AddPool("fibonacci", numberList)
|
||||
val obj = new EntityTestClass()
|
||||
obj.HasGUID mustEqual false
|
||||
hub.register(obj, "fibonacci")
|
||||
hub.WhichPool(obj) mustEqual Some("fibonacci")
|
||||
try { obj.GUID } catch { case _ : Exception => ko } //passes
|
||||
hub.WhichPool(obj).contains("fibonacci") mustEqual true
|
||||
obj.HasGUID mustEqual true
|
||||
|
||||
hub.unregister(obj)
|
||||
hub.WhichPool(obj) mustEqual None
|
||||
obj.GUID must throwA[Exception] //fails
|
||||
obj.HasGUID mustEqual false
|
||||
hub.WhichPool(obj).isEmpty mustEqual true
|
||||
}
|
||||
|
||||
"not register an object to a different pool" in {
|
||||
|
|
@ -247,14 +248,15 @@ class NumberPoolHubTest extends Specification {
|
|||
hub.register(13) match {
|
||||
case Success(key) =>
|
||||
key.Object = obj
|
||||
obj.HasGUID mustEqual true
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
hub.WhichPool(obj) mustEqual Some("fibonacci")
|
||||
hub.WhichPool(obj).contains("fibonacci") mustEqual true
|
||||
hub.unregister(13) match {
|
||||
case Success(thing) =>
|
||||
thing mustEqual Some(obj)
|
||||
thing.get.GUID must throwA[Exception]
|
||||
thing.contains(obj) mustEqual true
|
||||
thing.get.HasGUID mustEqual false
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
|
|
|
|||
|
|
@ -158,10 +158,10 @@ class NumberPoolTest extends Specification {
|
|||
val obj = new GenericPool(map, 11)
|
||||
obj.Selector.asInstanceOf[SpecificSelector].SelectionIndex = 5
|
||||
obj.Get()
|
||||
map.get(5) mustEqual Some("generic")
|
||||
map.get(5).contains("generic") mustEqual true
|
||||
obj.Numbers.contains(5) mustEqual true
|
||||
obj.Return(5) mustEqual true
|
||||
map.get(5) mustEqual None
|
||||
map.get(5).isEmpty mustEqual true
|
||||
obj.Numbers.isEmpty mustEqual true
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ class NumberSourceTest extends Specification {
|
|||
result.isDefined mustEqual true
|
||||
result.get.GUID mustEqual 5
|
||||
result.get.Policy mustEqual AvailabilityPolicy.Leased
|
||||
result.get.Object mustEqual None
|
||||
result.get.Object.isEmpty mustEqual true
|
||||
obj.Size mustEqual 26
|
||||
obj.CountAvailable mustEqual 25
|
||||
obj.CountUsed mustEqual 1
|
||||
|
|
@ -46,7 +46,7 @@ class NumberSourceTest extends Specification {
|
|||
result.get.GUID mustEqual 5
|
||||
obj.CountUsed mustEqual 1
|
||||
val ret = obj.Return(result.get)
|
||||
ret mustEqual None
|
||||
ret.isEmpty mustEqual true
|
||||
obj.CountUsed mustEqual 0
|
||||
}
|
||||
|
||||
|
|
@ -59,7 +59,7 @@ class NumberSourceTest extends Specification {
|
|||
result.get.Object = test
|
||||
obj.CountUsed mustEqual 1
|
||||
val ret = obj.Return(result.get)
|
||||
ret mustEqual Some(test)
|
||||
ret.contains(test) mustEqual true
|
||||
obj.CountUsed mustEqual 0
|
||||
}
|
||||
|
||||
|
|
@ -69,7 +69,7 @@ class NumberSourceTest extends Specification {
|
|||
result.isDefined mustEqual true
|
||||
result.get.GUID mustEqual 5
|
||||
result.get.Policy mustEqual AvailabilityPolicy.Restricted
|
||||
result.get.Object mustEqual None
|
||||
result.get.Object.isEmpty mustEqual true
|
||||
}
|
||||
|
||||
"restrict a number (assigned + multiple assignments)" in {
|
||||
|
|
@ -79,13 +79,13 @@ class NumberSourceTest extends Specification {
|
|||
val result : Option[LoanedKey] = obj.Restrict(5)
|
||||
result.get.GUID mustEqual 5
|
||||
result.get.Policy mustEqual AvailabilityPolicy.Restricted
|
||||
result.get.Object mustEqual None
|
||||
result.get.Object.isEmpty mustEqual true
|
||||
result.get.Object = None //assignment 1
|
||||
result.get.Object mustEqual None //still unassigned
|
||||
result.get.Object.isEmpty mustEqual true //still unassigned
|
||||
result.get.Object = test1 //assignment 2
|
||||
result.get.Object mustEqual Some(test1)
|
||||
result.get.Object.contains(test1) mustEqual true
|
||||
result.get.Object = test2 //assignment 3
|
||||
result.get.Object mustEqual Some(test1) //same as above
|
||||
result.get.Object.contains(test1) mustEqual true //same as above
|
||||
}
|
||||
|
||||
"return a restricted number (correctly fail)" in {
|
||||
|
|
@ -100,7 +100,7 @@ class NumberSourceTest extends Specification {
|
|||
val result2 : Option[SecureKey] = obj.Get(5)
|
||||
result2.get.GUID mustEqual 5
|
||||
result2.get.Policy mustEqual AvailabilityPolicy.Restricted
|
||||
result2.get.Object mustEqual Some(test)
|
||||
result2.get.Object.contains(test) mustEqual true
|
||||
}
|
||||
|
||||
"return a secure key" in {
|
||||
|
|
@ -111,7 +111,7 @@ class NumberSourceTest extends Specification {
|
|||
test.GUID = PlanetSideGUID(5)
|
||||
val result2 : Option[SecureKey] = obj.Get(5)
|
||||
|
||||
obj.Return(result2.get) mustEqual Some(test)
|
||||
obj.Return(result2.get).contains(test) mustEqual true
|
||||
}
|
||||
|
||||
"restrict a previously-assigned number" in {
|
||||
|
|
@ -124,7 +124,7 @@ class NumberSourceTest extends Specification {
|
|||
val result2 : Option[LoanedKey] = obj.Restrict(5)
|
||||
result2.isDefined mustEqual true
|
||||
result2.get.Policy mustEqual AvailabilityPolicy.Restricted
|
||||
result2.get.Object mustEqual Some(test)
|
||||
result2.get.Object.contains(test) mustEqual true
|
||||
}
|
||||
|
||||
"check a number (not previously gotten)" in {
|
||||
|
|
@ -132,7 +132,7 @@ class NumberSourceTest extends Specification {
|
|||
val result2 : Option[SecureKey] = obj.Get(5)
|
||||
result2.get.GUID mustEqual 5
|
||||
result2.get.Policy mustEqual AvailabilityPolicy.Available
|
||||
result2.get.Object mustEqual None
|
||||
result2.get.Object.isEmpty mustEqual true
|
||||
}
|
||||
|
||||
"check a number (previously gotten)" in {
|
||||
|
|
@ -141,11 +141,11 @@ class NumberSourceTest extends Specification {
|
|||
result.isDefined mustEqual true
|
||||
result.get.GUID mustEqual 5
|
||||
result.get.Policy mustEqual AvailabilityPolicy.Leased
|
||||
result.get.Object mustEqual None
|
||||
result.get.Object.isEmpty mustEqual true
|
||||
val result2 : Option[SecureKey] = obj.Get(5)
|
||||
result2.get.GUID mustEqual 5
|
||||
result2.get.Policy mustEqual AvailabilityPolicy.Leased
|
||||
result2.get.Object mustEqual None
|
||||
result2.get.Object.isEmpty mustEqual true
|
||||
}
|
||||
|
||||
"check a number (assigned)" in {
|
||||
|
|
@ -170,10 +170,10 @@ class NumberSourceTest extends Specification {
|
|||
val result2 : Option[SecureKey] = obj.Get(5)
|
||||
result2.get.Policy mustEqual AvailabilityPolicy.Leased
|
||||
result2.get.Object.get mustEqual test
|
||||
obj.Return(5) mustEqual Some(test)
|
||||
obj.Return(5).contains(test) mustEqual true
|
||||
val result3 : Option[SecureKey] = obj.Get(5)
|
||||
result3.get.Policy mustEqual AvailabilityPolicy.Available
|
||||
result3.get.Object mustEqual None
|
||||
result3.get.Object.isEmpty mustEqual true
|
||||
}
|
||||
|
||||
"clear" in {
|
||||
|
|
|
|||
|
|
@ -12,49 +12,49 @@ class RegisterTest extends Specification {
|
|||
"construct (object)" in {
|
||||
val reg = Register(obj)
|
||||
reg.obj mustEqual obj
|
||||
reg.number mustEqual None
|
||||
reg.name mustEqual None
|
||||
reg.callback mustEqual None
|
||||
reg.number.isEmpty mustEqual true
|
||||
reg.name.isEmpty mustEqual true
|
||||
reg.callback.isEmpty mustEqual true
|
||||
}
|
||||
|
||||
"construct (object, callback)" in {
|
||||
val reg = Register(obj, Actor.noSender)
|
||||
reg.obj mustEqual obj
|
||||
reg.number mustEqual None
|
||||
reg.name mustEqual None
|
||||
reg.callback mustEqual Some(Actor.noSender)
|
||||
reg.number.isEmpty mustEqual true
|
||||
reg.name.isEmpty mustEqual true
|
||||
reg.callback.contains(Actor.noSender) mustEqual true
|
||||
}
|
||||
|
||||
"construct (object, suggested number)" in {
|
||||
val reg = Register(obj, 5)
|
||||
reg.obj mustEqual obj
|
||||
reg.number mustEqual Some(5)
|
||||
reg.name mustEqual None
|
||||
reg.callback mustEqual None
|
||||
reg.number.contains(5) mustEqual true
|
||||
reg.name.isEmpty mustEqual true
|
||||
reg.callback.isEmpty mustEqual true
|
||||
}
|
||||
|
||||
"construct (object, suggested number, callback)" in {
|
||||
val reg = Register(obj, 5, Actor.noSender)
|
||||
reg.obj mustEqual obj
|
||||
reg.number mustEqual Some(5)
|
||||
reg.name mustEqual None
|
||||
reg.callback mustEqual Some(Actor.noSender)
|
||||
reg.number.contains(5) mustEqual true
|
||||
reg.name.isEmpty mustEqual true
|
||||
reg.callback.contains(Actor.noSender) mustEqual true
|
||||
}
|
||||
|
||||
"construct (object, pool name)" in {
|
||||
val reg = Register(obj, "pool")
|
||||
reg.obj mustEqual obj
|
||||
reg.number mustEqual None
|
||||
reg.name mustEqual Some("pool")
|
||||
reg.callback mustEqual None
|
||||
reg.number.isEmpty mustEqual true
|
||||
reg.name.contains("pool") mustEqual true
|
||||
reg.callback.isEmpty mustEqual true
|
||||
}
|
||||
|
||||
"construct (object, pool name, callback)" in {
|
||||
val reg = Register(obj, "pool", Actor.noSender)
|
||||
reg.obj mustEqual obj
|
||||
reg.number mustEqual None
|
||||
reg.name mustEqual Some("pool")
|
||||
reg.callback mustEqual Some(Actor.noSender)
|
||||
reg.number.isEmpty mustEqual true
|
||||
reg.name.contains("pool") mustEqual true
|
||||
reg.callback.contains(Actor.noSender) mustEqual true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -341,7 +341,7 @@ object UniqueNumberSystemTest {
|
|||
* @see `UniqueNumberSystem.AllocateNumberPoolActors(NumberPoolHub)(implicit ActorContext)`
|
||||
*/
|
||||
def AllocateNumberPoolActors(poolSource : NumberPoolHub)(implicit system : ActorSystem) : Map[String, ActorRef] = {
|
||||
poolSource.Pools.map({ case ((pname, pool)) =>
|
||||
poolSource.Pools.map({ case (pname, pool) =>
|
||||
pname -> system.actorOf(Props(classOf[NumberPoolActor], pool), pname)
|
||||
}).toMap
|
||||
}
|
||||
|
|
|
|||
|
|
@ -170,7 +170,6 @@ class WorldSessionActor extends Actor
|
|||
var antChargingTick : Cancellable = DefaultCancellable.obj
|
||||
var antDischargingTick : Cancellable = DefaultCancellable.obj
|
||||
|
||||
|
||||
/**
|
||||
* Convert a boolean value into an integer value.
|
||||
* Use: `true:Int` or `false:Int`
|
||||
|
|
@ -1131,7 +1130,7 @@ class WorldSessionActor extends Actor
|
|||
log.warn(s"Vital target ${target.Definition.Name} damage resolution not supported using this method")
|
||||
|
||||
case ResponseToSelf(pkt) =>
|
||||
log.info(s"Received a direct message: $pkt")
|
||||
//log.info(s"Received a direct message: $pkt")
|
||||
sendResponse(pkt)
|
||||
|
||||
case LoadedRemoteProjectile(projectile_guid, Some(projectile)) =>
|
||||
|
|
|
|||
Loading…
Reference in a new issue