added basic Continent management system as a service; hooked it into WSA, at least as far as home3 is concerned; transferred GUID test functions to continent-level

This commit is contained in:
FateJH 2017-09-15 22:26:36 -04:00
parent a4b14e5da4
commit 99b019714b
5 changed files with 215 additions and 40 deletions

View file

@ -0,0 +1,59 @@
// Copyright (c) 2017 PSForever
package net.psforever.objects.continent
import akka.actor.{ActorContext, ActorRef, Props}
import net.psforever.objects.Player
import net.psforever.objects.entity.IdentifiableEntity
import net.psforever.objects.equipment.Equipment
import net.psforever.objects.guid.NumberPoolHub
import net.psforever.objects.guid.actor.{NumberPoolAccessorActor, NumberPoolActor}
import net.psforever.objects.guid.selector.RandomSelector
import net.psforever.objects.guid.source.LimitedNumberSource
import net.psforever.packet.game.PlanetSideGUID
import net.psforever.types.Vector3
import scala.collection.mutable.ListBuffer
class Continent(zoneId : String, map : String) {
private var actor = ActorRef.noSender
private val guid : NumberPoolHub = new NumberPoolHub(new LimitedNumberSource(65536))
private var accessor : ActorRef = ActorRef.noSender
def Actor(implicit context : ActorContext) : ActorRef = {
if(actor == ActorRef.noSender) {
actor = context.actorOf(Props(classOf[ContinentActor], this), s"$zoneId-actor")
val pool = guid.AddPool("pool", (400 to 599).toList)
val poolActor = context.actorOf(Props(classOf[NumberPoolActor], pool), name = s"$ZoneId-poolActor")
pool.Selector = new RandomSelector
accessor = context.actorOf(Props(classOf[NumberPoolAccessorActor], guid, pool, poolActor), s"$ZoneId-accessor")
}
actor
}
private val equipmentOnGround : ListBuffer[Equipment] = ListBuffer[Equipment]()
def ZoneId : String = zoneId
def Map : String = map
def GUID : ActorRef = accessor
def GUID(object_guid : PlanetSideGUID) : Option[IdentifiableEntity] = guid(object_guid.guid)
def EquipmentOnGround : ListBuffer[Equipment] = equipmentOnGround
}
object Continent {
final def Nowhere : Continent = { Continent("", "") } //TODO needs overrides
final case class DropItemOnGround(item : Equipment, pos : Vector3, orient : Vector3)
final case class GetItemOnGround(player : Player, item_guid : PlanetSideGUID)
final case class GiveItemFromGround(player : Player, item : Equipment)
def apply(zoneId : String, map : String) : Continent = {
new Continent(zoneId, map)
}
}

View file

@ -0,0 +1,62 @@
// Copyright (c) 2017 PSForever
package net.psforever.objects.continent
import akka.actor.Actor
import net.psforever.objects.equipment.Equipment
import net.psforever.packet.game.PlanetSideGUID
import scala.annotation.tailrec
class ContinentActor(continent : Continent) extends Actor {
private[this] val log = org.log4s.getLogger
import Continent._
def receive : Receive = {
case DropItemOnGround(item, pos, orient) =>
item.Position = pos
item.Orientation = orient
continent.EquipmentOnGround += item
case GetItemOnGround(player, item_guid) =>
FindItemOnGround(item_guid) match {
case Some(item) =>
sender ! GiveItemFromGround(player, item)
case None =>
log.warn(s"item on ground $item_guid was requested by $player for pickup but was not found")
}
case _ => ;
}
private def FindItemOnGround(item_guid : PlanetSideGUID) : Option[Equipment] = {
recursiveFindItemOnGround(continent.EquipmentOnGround.iterator, item_guid) match {
case Some(index) =>
Some(continent.EquipmentOnGround.remove(index))
case None =>
None
}
}
/**
* Shift through objects on the ground to find the location of a specific item.
* @param iter an `Iterator` of `Equipment`
* @param item_guid the global unique identifier of the piece of `Equipment` being sought
* @param index the current position in the array-list structure used to create the `Iterator`
* @return the index of the object matching `item_guid`, if found;
* `None`, otherwise
*/
@tailrec private def recursiveFindItemOnGround(iter : Iterator[Equipment], item_guid : PlanetSideGUID, index : Int = 0) : Option[Int] = {
if(!iter.hasNext) {
None
}
else {
val item : Equipment = iter.next
if(item.GUID == item_guid) {
Some(index)
}
else {
recursiveFindItemOnGround(iter, item_guid, index + 1)
}
}
}
}

View file

@ -0,0 +1,46 @@
// Copyright (c) 2017 PSForever
package net.psforever.objects.continent
import akka.actor.Actor
import scala.annotation.tailrec
class IntergalacticCluster(continents : List[Continent]) extends Actor {
//private[this] val log = org.log4s.getLogger
for(continent <- continents) {
continent.Actor //seed context
}
def receive : Receive = {
case IntergalacticCluster.GetWorld(zoneId) =>
findWorldInCluster(continents.iterator, zoneId) match {
case Some(continent) =>
sender ! IntergalacticCluster.GiveWorld(zoneId, continent)
case None =>
sender ! IntergalacticCluster.GiveWorld(zoneId, Continent.Nowhere)
}
case _ => ;
}
@tailrec private def findWorldInCluster(iter : Iterator[Continent], zoneId : String) : Option[Continent] = {
if(!iter.hasNext) {
None
}
else {
val cont = iter.next
if(cont.ZoneId == zoneId) {
Some(cont)
}
else {
findWorldInCluster(iter, zoneId)
}
}
}
}
object IntergalacticCluster {
final case class GetWorld(zoneId : String)
final case class GiveWorld(zoneId : String, zone : Continent)
}