mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-07-13 07:24:53 +00:00
moved files from /continent/ to /zones/; separated Actor for managing items on the ground; added comments
This commit is contained in:
parent
186c4ccba9
commit
61535bc232
14 changed files with 526 additions and 243 deletions
|
|
@ -1,64 +0,0 @@
|
||||||
// Copyright (c) 2017 PSForever
|
|
||||||
package net.psforever.objects.continent
|
|
||||||
|
|
||||||
import akka.actor.{Actor, Props}
|
|
||||||
import net.psforever.objects.Player
|
|
||||||
|
|
||||||
import scala.annotation.tailrec
|
|
||||||
|
|
||||||
class IntergalacticCluster(zones : List[Zone]) extends Actor {
|
|
||||||
private[this] val log = org.log4s.getLogger
|
|
||||||
log.info("Starting interplanetary cluster ...")
|
|
||||||
|
|
||||||
override def preStart() : Unit = {
|
|
||||||
super.preStart()
|
|
||||||
for(zone <- zones) {
|
|
||||||
log.info(s"Built continent ${zone.ZoneId}")
|
|
||||||
zone.Actor = context.actorOf(Props(classOf[ZoneActor], zone), s"${zone.ZoneId}-actor")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def receive : Receive = {
|
|
||||||
case IntergalacticCluster.GetWorld(zoneId) =>
|
|
||||||
log.info(s"Asked to find $zoneId")
|
|
||||||
findWorldInCluster(zones.iterator, zoneId) match {
|
|
||||||
case Some(continent) =>
|
|
||||||
sender ! IntergalacticCluster.GiveWorld(zoneId, continent)
|
|
||||||
case None =>
|
|
||||||
log.error(s"Requested zone with id $zoneId could not be found")
|
|
||||||
}
|
|
||||||
|
|
||||||
case IntergalacticCluster.RequestZoneInitialization(tplayer) =>
|
|
||||||
zones.foreach(zone => {
|
|
||||||
sender ! Zone.ClientInitialization(zone.ClientInitialization())
|
|
||||||
})
|
|
||||||
sender ! IntergalacticCluster.ClientInitializationComplete(tplayer)
|
|
||||||
|
|
||||||
case _ => ;
|
|
||||||
}
|
|
||||||
|
|
||||||
@tailrec private def findWorldInCluster(iter : Iterator[Zone], zoneId : String) : Option[Zone] = {
|
|
||||||
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 : Zone)
|
|
||||||
|
|
||||||
final case class RequestZoneInitialization(tplayer : Player)
|
|
||||||
|
|
||||||
final case class ClientInitializationComplete(tplayer : Player)
|
|
||||||
}
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
// Copyright (c) 2017 PSForever
|
|
||||||
package net.psforever.objects.continent
|
|
||||||
|
|
||||||
import akka.actor.ActorContext
|
|
||||||
import net.psforever.objects.PlanetSideGameObject
|
|
||||||
import net.psforever.objects.guid.NumberPoolHub
|
|
||||||
|
|
||||||
trait ServerObjectBuilder {
|
|
||||||
def Build(implicit context : ActorContext, guid : NumberPoolHub) : PlanetSideGameObject
|
|
||||||
}
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
// Copyright (c) 2017 PSForever
|
|
||||||
package net.psforever.objects.continent
|
|
||||||
|
|
||||||
import net.psforever.objects.terminals.{Terminal, TerminalDefinition}
|
|
||||||
|
|
||||||
class TerminalObjectBuilder(tdef : TerminalDefinition, id : Int) extends ServerObjectBuilder {
|
|
||||||
import akka.actor.ActorContext
|
|
||||||
import net.psforever.objects.guid.NumberPoolHub
|
|
||||||
|
|
||||||
def Build(implicit context : ActorContext, guid : NumberPoolHub) : Terminal = {
|
|
||||||
val obj = Terminal(tdef)
|
|
||||||
guid.register(obj, id)
|
|
||||||
obj.Actor
|
|
||||||
obj
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
object TerminalObjectBuilder {
|
|
||||||
def apply(tdef : TerminalDefinition, id : Int) : TerminalObjectBuilder = {
|
|
||||||
new TerminalObjectBuilder(tdef, id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,104 +0,0 @@
|
||||||
// Copyright (c) 2017 PSForever
|
|
||||||
package net.psforever.objects.continent
|
|
||||||
|
|
||||||
import akka.actor.{ActorContext, ActorRef, Props}
|
|
||||||
import net.psforever.objects.{PlanetSideGameObject, Player}
|
|
||||||
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.GamePacket
|
|
||||||
import net.psforever.packet.game.PlanetSideGUID
|
|
||||||
import net.psforever.types.Vector3
|
|
||||||
|
|
||||||
import scala.collection.mutable.ListBuffer
|
|
||||||
|
|
||||||
class Zone(id : String, map : ZoneMap, zoneNumber : Int) {
|
|
||||||
private var actor = ActorRef.noSender
|
|
||||||
private var accessor : ActorRef = ActorRef.noSender
|
|
||||||
//private var startupUtilities : List[ServerObjectBuilder] = List()
|
|
||||||
private var guid : NumberPoolHub = new NumberPoolHub(new LimitedNumberSource(65536))
|
|
||||||
|
|
||||||
def Actor : ActorRef = actor
|
|
||||||
|
|
||||||
def Init(implicit context : ActorContext) : Unit = {
|
|
||||||
//TODO wrong initialization
|
|
||||||
implicit val guid = this.guid
|
|
||||||
val pool = guid.AddPool("pool", (200 to 1000).toList)
|
|
||||||
pool.Selector = new RandomSelector
|
|
||||||
val poolActor = context.actorOf(Props(classOf[NumberPoolActor], pool), name = s"$ZoneId-poolActor")
|
|
||||||
accessor = context.actorOf(Props(classOf[NumberPoolAccessorActor], guid, pool, poolActor), s"$ZoneId-accessor")
|
|
||||||
|
|
||||||
map.LocalObjects.foreach({builderObject =>
|
|
||||||
builderObject.Build
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
def Actor_=(zoneActor : ActorRef) : ActorRef = {
|
|
||||||
if(actor == ActorRef.noSender) {
|
|
||||||
actor = zoneActor
|
|
||||||
}
|
|
||||||
Actor
|
|
||||||
}
|
|
||||||
|
|
||||||
private val equipmentOnGround : ListBuffer[Equipment] = ListBuffer[Equipment]()
|
|
||||||
|
|
||||||
def ZoneId : String = id
|
|
||||||
|
|
||||||
def ZoneNumber : Int = zoneNumber
|
|
||||||
|
|
||||||
def Map : ZoneMap = map
|
|
||||||
|
|
||||||
def GUID : ActorRef = accessor
|
|
||||||
|
|
||||||
def GUID(hub : NumberPoolHub) : ActorRef = {
|
|
||||||
if(actor == ActorRef.noSender) {
|
|
||||||
guid = hub
|
|
||||||
}
|
|
||||||
Actor
|
|
||||||
}
|
|
||||||
|
|
||||||
def GUID(object_guid : PlanetSideGUID) : Option[PlanetSideGameObject] = GUID(object_guid.guid)
|
|
||||||
|
|
||||||
def GUID(object_guid : Int) : Option[PlanetSideGameObject] = guid(object_guid) match {
|
|
||||||
case Some(obj) =>
|
|
||||||
Some(obj.asInstanceOf[PlanetSideGameObject]) //potential casting error
|
|
||||||
case None =>
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
def EquipmentOnGround : ListBuffer[Equipment] = equipmentOnGround
|
|
||||||
|
|
||||||
// def AddUtility(obj : ServerObjectBuilder) : Unit = {
|
|
||||||
// startupUtilities = startupUtilities :+ obj
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// def StartupUtilities : List[ServerObjectBuilder] = {
|
|
||||||
// val utilities = startupUtilities
|
|
||||||
// startupUtilities = Nil
|
|
||||||
// utilities
|
|
||||||
// }
|
|
||||||
|
|
||||||
def ClientInitialization() : List[GamePacket] = {
|
|
||||||
List.empty[GamePacket]
|
|
||||||
}
|
|
||||||
|
|
||||||
def ClientConfiguration() : List[GamePacket] = {
|
|
||||||
List.empty[GamePacket]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
object Zone {
|
|
||||||
final case class DropItemOnGround(item : Equipment, pos : Vector3, orient : Vector3)
|
|
||||||
|
|
||||||
final case class GetItemOnGround(player : Player, item_guid : PlanetSideGUID)
|
|
||||||
|
|
||||||
final case class ItemFromGround(player : Player, item : Equipment)
|
|
||||||
|
|
||||||
final case class ClientInitialization(list : List[GamePacket])
|
|
||||||
|
|
||||||
def apply(id : String, map : ZoneMap, number : Int) : Zone = {
|
|
||||||
new Zone(id, map, number)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
// Copyright (c) 2017 PSForever
|
|
||||||
package net.psforever.objects.continent
|
|
||||||
|
|
||||||
class ZoneMap(private val name : String) {
|
|
||||||
private var localObjects : List[ServerObjectBuilder] = List()
|
|
||||||
|
|
||||||
def Name : String = name
|
|
||||||
|
|
||||||
def LocalObject(obj : ServerObjectBuilder) : Unit = {
|
|
||||||
localObjects = localObjects :+ obj
|
|
||||||
}
|
|
||||||
|
|
||||||
def LocalObjects : List[ServerObjectBuilder] = {
|
|
||||||
val utilities = localObjects
|
|
||||||
localObjects = Nil
|
|
||||||
utilities
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,113 @@
|
||||||
|
// Copyright (c) 2017 PSForever
|
||||||
|
package net.psforever.objects.zones
|
||||||
|
|
||||||
|
import akka.actor.{Actor, Props}
|
||||||
|
import net.psforever.objects.Player
|
||||||
|
|
||||||
|
import scala.annotation.tailrec
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The root of the universe of one-continent planets, codified by the game's "Interstellar Map."
|
||||||
|
* Constructs each zone and thus instigates the construction of every server object in the game world.
|
||||||
|
* The nanite flow connecting all of these `Zone`s is called the "Intercontinental Lattice."<br>
|
||||||
|
* <br>
|
||||||
|
* The process of "construction" and "initialization" and "configuration" are referenced at this level.
|
||||||
|
* These concepts are not the same thing;
|
||||||
|
* the distinction is important.
|
||||||
|
* "Construction" and "instantiation" of the cluster merely produces the "facade" of the different `Zone` entities.
|
||||||
|
* In such a `List`, every built `Zone` is capable of being a destination on the "Intercontinental lattice."
|
||||||
|
* "Initialization" and "configuration" of the cluster refers to the act of completing the "Intercontinental Lattice"
|
||||||
|
* by connecting different terminus warp gates together.
|
||||||
|
* Other activities involve event management and managing wide-reaching and factional attributes.
|
||||||
|
* @param zones a `List` of continental `Zone` arenas
|
||||||
|
*/
|
||||||
|
class InterstellarCluster(zones : List[Zone]) extends Actor {
|
||||||
|
private[this] val log = org.log4s.getLogger
|
||||||
|
log.info("Starting interplanetary cluster ...")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a `ZoneActor` for each `Zone`.
|
||||||
|
* That `Actor` is sent a packet that would start the construction of the `Zone`'s server objects.
|
||||||
|
* The process is maintained this way to allow every planet to be created and configured in separate stages.
|
||||||
|
*/
|
||||||
|
override def preStart() : Unit = {
|
||||||
|
super.preStart()
|
||||||
|
for(zone <- zones) {
|
||||||
|
log.info(s"Built continent ${zone.Id}")
|
||||||
|
zone.Actor = context.actorOf(Props(classOf[ZoneActor], zone), s"${zone.Id}-actor")
|
||||||
|
zone.Actor ! Zone.Init()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def receive : Receive = {
|
||||||
|
case InterstellarCluster.GetWorld(zoneId) =>
|
||||||
|
log.info(s"Asked to find $zoneId")
|
||||||
|
findWorldInCluster(zones.iterator, zoneId) match {
|
||||||
|
case Some(continent) =>
|
||||||
|
sender ! InterstellarCluster.GiveWorld(zoneId, continent)
|
||||||
|
case None =>
|
||||||
|
log.error(s"Requested zone $zoneId could not be found")
|
||||||
|
}
|
||||||
|
|
||||||
|
case InterstellarCluster.RequestClientInitialization(tplayer) =>
|
||||||
|
zones.foreach(zone => {
|
||||||
|
sender ! Zone.ClientInitialization(zone.ClientInitialization()) //do this for each Zone
|
||||||
|
})
|
||||||
|
sender ! InterstellarCluster.ClientInitializationComplete(tplayer) //will be processed after all Zones
|
||||||
|
|
||||||
|
case _ => ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search through the `List` of `Zone` entities and find the one with the matching designation.
|
||||||
|
* @param iter an `Iterator` of `Zone` entities
|
||||||
|
* @param zoneId the name of the `Zone`
|
||||||
|
* @return the discovered `Zone`
|
||||||
|
*/
|
||||||
|
@tailrec private def findWorldInCluster(iter : Iterator[Zone], zoneId : String) : Option[Zone] = {
|
||||||
|
if(!iter.hasNext) {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
val cont = iter.next
|
||||||
|
if(cont.Id == zoneId) {
|
||||||
|
Some(cont)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
findWorldInCluster(iter, zoneId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object InterstellarCluster {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request a hard reference to a `Zone`.
|
||||||
|
* @param zoneId the name of the `Zone`
|
||||||
|
*/
|
||||||
|
final case class GetWorld(zoneId : String)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide a hard reference to a `Zone`.
|
||||||
|
* @param zoneId the name of the `Zone`
|
||||||
|
* @param zone the `Zone`
|
||||||
|
*/
|
||||||
|
final case class GiveWorld(zoneId : String, zone : Zone)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signal to the cluster that a new client needs to be initialized for all listed `Zone` destinations.
|
||||||
|
* @param tplayer the `Player` belonging to the client;
|
||||||
|
* may be superfluous
|
||||||
|
* @see `Zone`
|
||||||
|
*/
|
||||||
|
final case class RequestClientInitialization(tplayer : Player)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return signal intended to inform the original sender that all `Zone`s have finished being initialized.
|
||||||
|
* @param tplayer the `Player` belonging to the client;
|
||||||
|
* may be superfluous
|
||||||
|
* @see `WorldSessionActor`
|
||||||
|
*/
|
||||||
|
final case class ClientInitializationComplete(tplayer : Player)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
// Copyright (c) 2017 PSForever
|
||||||
|
package net.psforever.objects.zones
|
||||||
|
|
||||||
|
import akka.actor.ActorContext
|
||||||
|
import net.psforever.objects.PlanetSideGameObject
|
||||||
|
import net.psforever.objects.guid.NumberPoolHub
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper `Trait` designed to be extended to implement custom object instantiation logic at the `ZoneMap` level.
|
||||||
|
* @see `Zone.Init`
|
||||||
|
*/
|
||||||
|
trait ServerObjectBuilder {
|
||||||
|
/**
|
||||||
|
* Instantiate and configure the given server object
|
||||||
|
* (at a later time compared to the construction of the builder class).<br>
|
||||||
|
* <br>
|
||||||
|
* Externally, it expects a `context` to properly integrate within an `ActorSystem`
|
||||||
|
* and is provided with a source for globally unique identifiers to integrate into the `Zone`.
|
||||||
|
* Neither is required of the `return` type, however.
|
||||||
|
* @param context a context to allow the object to properly set up `ActorSystem` functionality;
|
||||||
|
* defaults to `null`
|
||||||
|
* @param guid the local globally unique identifier system to complete the process of object introduction;
|
||||||
|
* defaults to `null`
|
||||||
|
* @return the object that was created and integrated into the `Zone`
|
||||||
|
*/
|
||||||
|
def Build(implicit context : ActorContext = null, guid : NumberPoolHub = null) : PlanetSideGameObject
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
// Copyright (c) 2017 PSForever
|
||||||
|
package net.psforever.objects.zones
|
||||||
|
|
||||||
|
import net.psforever.objects.terminals.{Terminal, TerminalDefinition}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper `Class` designed to instantiate a `Terminal` server object.
|
||||||
|
* @param tdef a `TerminalDefinition` object, indicating the specific functionality of the resulting `Terminal`
|
||||||
|
* @param id the globally unique identifier to which this `Terminal` will be registered
|
||||||
|
*/
|
||||||
|
class TerminalObjectBuilder(private val tdef : TerminalDefinition, private val id : Int) extends ServerObjectBuilder {
|
||||||
|
import akka.actor.ActorContext
|
||||||
|
import net.psforever.objects.guid.NumberPoolHub
|
||||||
|
|
||||||
|
def Build(implicit context : ActorContext, guid : NumberPoolHub) : Terminal = {
|
||||||
|
val obj = Terminal(tdef)
|
||||||
|
guid.register(obj, id) //non-Actor GUID registration
|
||||||
|
obj.Actor //it's necessary to register beforehand because the Actor name utilizes the GUID
|
||||||
|
obj
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object TerminalObjectBuilder {
|
||||||
|
/**
|
||||||
|
* Overloaded constructor for a `TerminalObjectBuilder`.
|
||||||
|
* @param tdef a `TerminalDefinition` object
|
||||||
|
* @param id a globally unique identifier
|
||||||
|
* @return a `TerminalObjectBuilder` object
|
||||||
|
*/
|
||||||
|
def apply(tdef : TerminalDefinition, id : Int) : TerminalObjectBuilder = {
|
||||||
|
new TerminalObjectBuilder(tdef, id)
|
||||||
|
}
|
||||||
|
}
|
||||||
259
common/src/main/scala/net/psforever/objects/zones/Zone.scala
Normal file
259
common/src/main/scala/net/psforever/objects/zones/Zone.scala
Normal file
|
|
@ -0,0 +1,259 @@
|
||||||
|
// Copyright (c) 2017 PSForever
|
||||||
|
package net.psforever.objects.zones
|
||||||
|
|
||||||
|
import akka.actor.{ActorContext, ActorRef, Props}
|
||||||
|
import net.psforever.objects.{PlanetSideGameObject, Player}
|
||||||
|
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.GamePacket
|
||||||
|
import net.psforever.packet.game.PlanetSideGUID
|
||||||
|
import net.psforever.types.Vector3
|
||||||
|
|
||||||
|
import scala.collection.mutable.ListBuffer
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A server object representing the one-landmass planets as well as the individual subterranean caverns.<br>
|
||||||
|
* <br>
|
||||||
|
* The concept of a "zone" is synonymous to the common vernacular "continent,"
|
||||||
|
* commonly referred by names such as Hossin or Ishundar and internally identified as c2 and c7, respectively.
|
||||||
|
* A `Zone` is composed of the abstracted concept of all the information pertinent for the simulation of the environment.
|
||||||
|
* That is, "everything about the continent."
|
||||||
|
* Physically, server objects and dynamic game objects are maintained through a local unique identifier system.
|
||||||
|
* Static server objects originate from the `ZoneMap`.
|
||||||
|
* Dynamic game objects originate from player characters.
|
||||||
|
* (Write more later.)
|
||||||
|
* @param zoneId the privileged name that can be used as the second parameter in the packet `LoadMapMessage`
|
||||||
|
* @param zoneMap the map of server objects upon which this `Zone` is based
|
||||||
|
* @param zoneNumber the numerical index of the `Zone` as it is recognized in a variety of packets;
|
||||||
|
* also used by `LivePlayerList` to indicate a specific `Zone`
|
||||||
|
* @see `ZoneMap`<br>
|
||||||
|
* `LoadMapMessage`<br>
|
||||||
|
* `LivePlayerList`
|
||||||
|
*/
|
||||||
|
class Zone(private val zoneId : String, zoneMap : ZoneMap, zoneNumber : Int) {
|
||||||
|
/** Governs general synchronized external requests. */
|
||||||
|
private var actor = ActorRef.noSender
|
||||||
|
|
||||||
|
/** Used by the globally unique identifier system to coordinate requests. */
|
||||||
|
private var accessor : ActorRef = ActorRef.noSender
|
||||||
|
/** The basic support structure for the globally unique number system used by this `Zone`. */
|
||||||
|
private var guid : NumberPoolHub = new NumberPoolHub(new LimitedNumberSource(65536))
|
||||||
|
/** A synchronized `List` of items (`Equipment`) dropped by players on the ground and can be collected again. */
|
||||||
|
private val equipmentOnGround : ListBuffer[Equipment] = ListBuffer[Equipment]()
|
||||||
|
/** Used by the `Zone` to coordinate `Equipment` dropping and collection requests. */
|
||||||
|
private var ground : ActorRef = ActorRef.noSender
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Establish the basic accessible conditions necessary for a functional `Zone`.<br>
|
||||||
|
* <br>
|
||||||
|
* Called from the `Actor` that governs this `Zone` when it is passed a constructor reference to the `Zone`.
|
||||||
|
* Specifically, the order of calling follows: `InterstellarCluster.preStart -> ZoneActor.receive(Zone.Init()) -> Zone.Init`.
|
||||||
|
* The basic method performs three main operations.
|
||||||
|
* First, the `Actor`-driven aspect of the globally unique identifier system for this `Zone` is finalized.
|
||||||
|
* Second, all supporting `Actor` agents are created, e.g., `ground`.
|
||||||
|
* Third, the `ZoneMap` server objects are loaded and constructed within that aforementioned system.
|
||||||
|
* To avoid being called more than once, there is a test whether the `accessor` for the globally unique identifier system has been changed.
|
||||||
|
* @param context a reference to an `ActorContext` necessary for `Props`
|
||||||
|
*/
|
||||||
|
def Init(implicit context : ActorContext) : Unit = {
|
||||||
|
if(accessor == ActorRef.noSender) {
|
||||||
|
//TODO wrong initialization for GUID
|
||||||
|
implicit val guid = this.guid
|
||||||
|
//passed into builderObject.Build implicitly
|
||||||
|
val pool = guid.AddPool("pool", (200 to 1000).toList)
|
||||||
|
pool.Selector = new RandomSelector
|
||||||
|
val poolActor = context.actorOf(Props(classOf[NumberPoolActor], pool), name = s"$Id-poolActor")
|
||||||
|
accessor = context.actorOf(Props(classOf[NumberPoolAccessorActor], guid, pool, poolActor), s"$Id-accessor")
|
||||||
|
ground = context.actorOf(Props(classOf[ZoneGroundActor], equipmentOnGround), s"$Id-ground")
|
||||||
|
|
||||||
|
Map.LocalObjects.foreach({ builderObject =>
|
||||||
|
builderObject.Build
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A reference to the primary `Actor` that governs this `Zone`.
|
||||||
|
* @return an `ActorRef`
|
||||||
|
* @see `ZoneActor`<br>
|
||||||
|
* `Zone.Init`
|
||||||
|
*/
|
||||||
|
def Actor : ActorRef = actor
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Give this `Zone` an `Actor` that will govern its interactions sequentially.
|
||||||
|
* @param zoneActor an `ActorRef` for this `Zone`;
|
||||||
|
* will not overwrite any existing governance unless `noSender`
|
||||||
|
* @return an `ActorRef`
|
||||||
|
* @see `ZoneActor`
|
||||||
|
*/
|
||||||
|
def Actor_=(zoneActor : ActorRef) : ActorRef = {
|
||||||
|
if(actor == ActorRef.noSender) {
|
||||||
|
actor = zoneActor
|
||||||
|
}
|
||||||
|
Actor
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The privileged name that can be used as the second parameter in the packet `LoadMapMessage`.
|
||||||
|
* @return the name
|
||||||
|
*/
|
||||||
|
def Id : String = zoneId
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The map of server objects upon which this `Zone` is based
|
||||||
|
* @return the map
|
||||||
|
*/
|
||||||
|
def Map : ZoneMap = zoneMap
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The numerical index of the `Zone` as it is recognized in a variety of packets.
|
||||||
|
* @return the abstract index position of this `Zone`
|
||||||
|
*/
|
||||||
|
def Number : Int = zoneNumber
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The globally unique identifier system is synchronized via an `Actor` to ensure that concurrent requests do not clash.
|
||||||
|
* A clash is merely when the same number is produced more than once by the same system due to concurrent requests.
|
||||||
|
* @return synchronized reference to the globally unique identifier system
|
||||||
|
*/
|
||||||
|
def GUID : ActorRef = accessor
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replace the current globally unique identifier system with a new one.
|
||||||
|
* The replacement will not occur if the current system is populated or if its synchronized reference has been created.
|
||||||
|
* @return synchronized reference to the globally unique identifier system
|
||||||
|
*/
|
||||||
|
def GUID(hub : NumberPoolHub) : ActorRef = {
|
||||||
|
if(actor == ActorRef.noSender && guid.Pools.map({case ((_, pool)) => pool.Count}).sum == 0) {
|
||||||
|
guid = hub
|
||||||
|
}
|
||||||
|
Actor
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recover an object from the globally unique identifier system by the number that was assigned previously.
|
||||||
|
* @param object_guid the globally unique identifier requested
|
||||||
|
* @return the associated object, if it exists
|
||||||
|
* @see `GUID(Int)`
|
||||||
|
*/
|
||||||
|
def GUID(object_guid : PlanetSideGUID) : Option[PlanetSideGameObject] = GUID(object_guid.guid)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recover an object from the globally unique identifier system by the number that was assigned previously.
|
||||||
|
* The object must be upcast into due to the differtence between the storage type and the return type.
|
||||||
|
* @param object_guid the globally unique identifier requested
|
||||||
|
* @return the associated object, if it exists
|
||||||
|
* @see `NumberPoolHub(Int)`
|
||||||
|
*/
|
||||||
|
def GUID(object_guid : Int) : Option[PlanetSideGameObject] = guid(object_guid) match {
|
||||||
|
case Some(obj) =>
|
||||||
|
Some(obj.asInstanceOf[PlanetSideGameObject])
|
||||||
|
case None =>
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The `List` of items (`Equipment`) dropped by players on the ground and can be collected again.
|
||||||
|
* @return the `List` of `Equipment`
|
||||||
|
*/
|
||||||
|
def EquipmentOnGround : List[Equipment] = equipmentOnGround.toList
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Coordinate `Equipment` that has been dropped on the ground or to-be-dropped on the ground.
|
||||||
|
* @return synchronized reference to the ground
|
||||||
|
* @see `ZoneGroundActor`<br>
|
||||||
|
* `Zone.DropItemOnGround`<br>
|
||||||
|
* `Zone.GetItemOnGround`<br>
|
||||||
|
* `Zone.ItemFromGround`
|
||||||
|
*/
|
||||||
|
def Ground : ActorRef = ground
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide bulk correspondence on all map entities that can be composed into packet messages and reported to a client.
|
||||||
|
* These messages are sent in this fashion at the time of joining the server:<br>
|
||||||
|
* - `BroadcastWarpgateUpdateMessage`<br>
|
||||||
|
* - `BuildingInfoUpdateMessage`<br>
|
||||||
|
* - `CaptureFlagUpdateMessage`<br>
|
||||||
|
* - `ContinentalLockUpdateMessage`<br>
|
||||||
|
* - `DensityLevelUpdateMessage`<br>
|
||||||
|
* - `ModuleLimitsMessage`<br>
|
||||||
|
* - `VanuModuleUpdateMessage`<br>
|
||||||
|
* - `ZoneForcedCavernConnectionMessage`<br>
|
||||||
|
* - `ZoneInfoMessage`<br>
|
||||||
|
* - `ZoneLockInfoMessage`<br>
|
||||||
|
* - `ZonePopulationUpdateMessage`
|
||||||
|
* @return a `List` of `GamePacket` messages
|
||||||
|
*/
|
||||||
|
def ClientInitialization() : List[GamePacket] = {
|
||||||
|
//TODO unimplemented
|
||||||
|
List.empty[GamePacket]
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide bulk correspondence on all server objects that can be composed into packet messages and reported to a client.
|
||||||
|
* These messages are sent in this fashion at the time of joining a specific `Zone`:<br>
|
||||||
|
* - `HackMessage`<br>
|
||||||
|
* - `PlanetsideAttributeMessage`<br>
|
||||||
|
* - `SetEmpireMessage`<br>
|
||||||
|
* - `TimeOfDayMessage`<br>
|
||||||
|
* - `WeatherMessage`
|
||||||
|
* @return a `List` of `GamePacket` messages
|
||||||
|
*/
|
||||||
|
def ClientConfiguration() : List[GamePacket] = {
|
||||||
|
//TODO unimplemented
|
||||||
|
List.empty[GamePacket]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object Zone {
|
||||||
|
/**
|
||||||
|
* Message to initialize the `Zone`.
|
||||||
|
* @see `Zone.Init(implicit ActorContext)`
|
||||||
|
*/
|
||||||
|
final case class Init()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Message to relinguish an item and place in on the ground.
|
||||||
|
* @param item the piece of `Equipment`
|
||||||
|
* @param pos where it is dropped
|
||||||
|
* @param orient in which direction it is facing when dropped
|
||||||
|
*/
|
||||||
|
final case class DropItemOnGround(item : Equipment, pos : Vector3, orient : Vector3)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Message to attempt to acquire an item from the ground (before somoene else?).
|
||||||
|
* @param player who wants the piece of `Equipment`
|
||||||
|
* @param item_guid the unique identifier of the piece of `Equipment`
|
||||||
|
*/
|
||||||
|
final case class GetItemOnGround(player : Player, item_guid : PlanetSideGUID)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Message to give an item from the ground to a specific user.
|
||||||
|
* @param player who wants the piece of `Equipment`
|
||||||
|
* @param item the piece of `Equipment`
|
||||||
|
*/
|
||||||
|
final case class ItemFromGround(player : Player, item : Equipment)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Message to report the packet messages that initialize the client.
|
||||||
|
* @param list a `List` of `GamePacket` messages
|
||||||
|
* @see `Zone.ClientInitialization()`<br>
|
||||||
|
* `InterstallarCluster`
|
||||||
|
*/
|
||||||
|
final case class ClientInitialization(list : List[GamePacket])
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overloaded constructor.
|
||||||
|
* @param id the privileged name that can be used as the second parameter in the packet `LoadMapMessage`
|
||||||
|
* @param map the map of server objects upon which this `Zone` is based
|
||||||
|
* @param number the numerical index of the `Zone` as it is recognized in a variety of packets
|
||||||
|
* @return a `Zone` object
|
||||||
|
*/
|
||||||
|
def apply(id : String, map : ZoneMap, number : Int) : Zone = {
|
||||||
|
new Zone(id, map, number)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
// Copyright (c) 2017 PSForever
|
||||||
|
package net.psforever.objects.zones
|
||||||
|
|
||||||
|
import akka.actor.Actor
|
||||||
|
|
||||||
|
/**
|
||||||
|
* na
|
||||||
|
* @param zone the `Zone` governed by this `Actor`
|
||||||
|
*/
|
||||||
|
class ZoneActor(zone : Zone) extends Actor {
|
||||||
|
private[this] val log = org.log4s.getLogger
|
||||||
|
|
||||||
|
def receive : Receive = {
|
||||||
|
case Zone.Init() =>
|
||||||
|
zone.Init
|
||||||
|
|
||||||
|
case msg =>
|
||||||
|
log.warn(s"Received unexpected message - $msg")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,41 +1,47 @@
|
||||||
// Copyright (c) 2017 PSForever
|
// Copyright (c) 2017 PSForever
|
||||||
package net.psforever.objects.continent
|
package net.psforever.objects.zones
|
||||||
|
|
||||||
import akka.actor.Actor
|
import akka.actor.Actor
|
||||||
import net.psforever.objects.equipment.Equipment
|
import net.psforever.objects.equipment.Equipment
|
||||||
import net.psforever.packet.game.PlanetSideGUID
|
import net.psforever.packet.game.PlanetSideGUID
|
||||||
|
|
||||||
import scala.annotation.tailrec
|
import scala.annotation.tailrec
|
||||||
|
import scala.collection.mutable.ListBuffer
|
||||||
|
|
||||||
class ZoneActor(zone : Zone) extends Actor {
|
/**
|
||||||
private[this] val log = org.log4s.getLogger
|
* na
|
||||||
|
* @param equipmentOnGround a `List` of items (`Equipment`) dropped by players on the ground and can be collected again
|
||||||
override def preStart() : Unit = {
|
*/
|
||||||
super.preStart()
|
class ZoneGroundActor(equipmentOnGround : ListBuffer[Equipment]) extends Actor {
|
||||||
zone.Init
|
//private[this] val log = org.log4s.getLogger
|
||||||
}
|
|
||||||
|
|
||||||
def receive : Receive = {
|
def receive : Receive = {
|
||||||
case Zone.DropItemOnGround(item, pos, orient) =>
|
case Zone.DropItemOnGround(item, pos, orient) =>
|
||||||
item.Position = pos
|
item.Position = pos
|
||||||
item.Orientation = orient
|
item.Orientation = orient
|
||||||
zone.EquipmentOnGround += item
|
equipmentOnGround += item
|
||||||
|
|
||||||
case Zone.GetItemOnGround(player, item_guid) =>
|
case Zone.GetItemOnGround(player, item_guid) =>
|
||||||
FindItemOnGround(item_guid) match {
|
FindItemOnGround(item_guid) match {
|
||||||
case Some(item) =>
|
case Some(item) =>
|
||||||
sender ! Zone.ItemFromGround(player, item)
|
sender ! Zone.ItemFromGround(player, item)
|
||||||
case None =>
|
case None =>
|
||||||
log.warn(s"item on ground $item_guid was requested by $player for pickup but was not found")
|
org.log4s.getLogger.warn(s"item on ground $item_guid was requested by $player for pickup but was not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
case _ => ;
|
case _ => ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shift through objects on the ground to find the location of a specific item.
|
||||||
|
* @param item_guid the global unique identifier of the piece of `Equipment` being sought
|
||||||
|
* @return the index of the object matching `item_guid`, if found;
|
||||||
|
* `None`, otherwise
|
||||||
|
*/
|
||||||
private def FindItemOnGround(item_guid : PlanetSideGUID) : Option[Equipment] = {
|
private def FindItemOnGround(item_guid : PlanetSideGUID) : Option[Equipment] = {
|
||||||
recursiveFindItemOnGround(zone.EquipmentOnGround.iterator, item_guid) match {
|
recursiveFindItemOnGround(equipmentOnGround.iterator, item_guid) match {
|
||||||
case Some(index) =>
|
case Some(index) =>
|
||||||
Some(zone.EquipmentOnGround.remove(index))
|
Some(equipmentOnGround.remove(index))
|
||||||
case None =>
|
case None =>
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
// Copyright (c) 2017 PSForever
|
||||||
|
package net.psforever.objects.zones
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The fixed instantiation and relation of a series of server objects.<br>
|
||||||
|
* <br>
|
||||||
|
* Asides from a `List` of server objects to be built, the operation between any server objects
|
||||||
|
* and the connected functionality emerging from more complex data structures is codified by this object.
|
||||||
|
* In the former case, all `Terminal` server objects for a `Zone` are to be defined herein.
|
||||||
|
* In the latter case, the arrangement of server objects into groups called facilities is also to be defined herein.
|
||||||
|
* Much like a `BasicDefinition` to an object, `ZoneMap` should not maintain mutable information for the companion `Zone`.
|
||||||
|
* Use it as a blueprint.<br>
|
||||||
|
* <br>
|
||||||
|
* The "training zones" are the best example of the difference between a `ZoneMap` and a `Zone.`
|
||||||
|
* `tzdrtr` is the Terran Republic driving course.
|
||||||
|
* `tzdrvs` is the Vanu Sovereignty driving course.
|
||||||
|
* While each course can have different objects and object states (`Zone`),
|
||||||
|
* both courses have the same basic server objects because they are built from the same blueprint (`ZoneMap`).
|
||||||
|
* @param name the privileged name that can be used as the first parameter in the packet `LoadMapMessage`
|
||||||
|
* @see `ServerObjectBuilder`<br>
|
||||||
|
* `LoadMapMessage`
|
||||||
|
*/
|
||||||
|
class ZoneMap(private val name : String) {
|
||||||
|
private var localObjects : List[ServerObjectBuilder] = List()
|
||||||
|
|
||||||
|
def Name : String = name
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append the builder for a server object to the list of builders known to this `ZoneMap`.
|
||||||
|
* @param obj the builder for a server object
|
||||||
|
*/
|
||||||
|
def LocalObject(obj : ServerObjectBuilder) : Unit = {
|
||||||
|
localObjects = localObjects :+ obj
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The list of all server object builder wrappers that have been assigned to this `ZoneMap`.
|
||||||
|
* @return the `List` of all `ServerObjectBuilders` known to this `ZoneMap`
|
||||||
|
*/
|
||||||
|
def LocalObjects : List[ServerObjectBuilder] = {
|
||||||
|
localObjects
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,7 +3,7 @@ import java.net.InetAddress
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
import akka.actor.{ActorContext, ActorRef, ActorSystem, Props}
|
import akka.actor.{ActorRef, ActorSystem, Props}
|
||||||
import akka.routing.RandomPool
|
import akka.routing.RandomPool
|
||||||
import ch.qos.logback.classic.LoggerContext
|
import ch.qos.logback.classic.LoggerContext
|
||||||
import ch.qos.logback.classic.joran.JoranConfigurator
|
import ch.qos.logback.classic.joran.JoranConfigurator
|
||||||
|
|
@ -12,7 +12,7 @@ import ch.qos.logback.core.status._
|
||||||
import ch.qos.logback.core.util.StatusPrinter
|
import ch.qos.logback.core.util.StatusPrinter
|
||||||
import com.typesafe.config.ConfigFactory
|
import com.typesafe.config.ConfigFactory
|
||||||
import net.psforever.crypto.CryptoInterface
|
import net.psforever.crypto.CryptoInterface
|
||||||
import net.psforever.objects.continent.{IntergalacticCluster, TerminalObjectBuilder, Zone, ZoneMap}
|
import net.psforever.objects.zones.{InterstellarCluster, TerminalObjectBuilder, Zone, ZoneMap}
|
||||||
import net.psforever.objects.guid.TaskResolver
|
import net.psforever.objects.guid.TaskResolver
|
||||||
import org.slf4j
|
import org.slf4j
|
||||||
import org.fusesource.jansi.Ansi._
|
import org.fusesource.jansi.Ansi._
|
||||||
|
|
@ -202,7 +202,7 @@ object PsLogin {
|
||||||
val serviceManager = ServiceManager.boot
|
val serviceManager = ServiceManager.boot
|
||||||
serviceManager ! ServiceManager.Register(RandomPool(50).props(Props[TaskResolver]), "taskResolver")
|
serviceManager ! ServiceManager.Register(RandomPool(50).props(Props[TaskResolver]), "taskResolver")
|
||||||
serviceManager ! ServiceManager.Register(Props[AvatarService], "avatar")
|
serviceManager ! ServiceManager.Register(Props[AvatarService], "avatar")
|
||||||
serviceManager ! ServiceManager.Register(Props(classOf[IntergalacticCluster], createContinents()), "galaxy")
|
serviceManager ! ServiceManager.Register(Props(classOf[InterstellarCluster], createContinents()), "galaxy")
|
||||||
|
|
||||||
/** Create two actors for handling the login and world server endpoints */
|
/** Create two actors for handling the login and world server endpoints */
|
||||||
loginRouter = Props(new SessionRouter("Login", loginTemplate))
|
loginRouter = Props(new SessionRouter("Login", loginTemplate))
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import org.log4s.MDC
|
||||||
import MDCContextAware.Implicits._
|
import MDCContextAware.Implicits._
|
||||||
import ServiceManager.Lookup
|
import ServiceManager.Lookup
|
||||||
import net.psforever.objects._
|
import net.psforever.objects._
|
||||||
import net.psforever.objects.continent.{Zone, IntergalacticCluster}
|
import net.psforever.objects.zones.{InterstellarCluster, Zone}
|
||||||
import net.psforever.objects.entity.IdentifiableEntity
|
import net.psforever.objects.entity.IdentifiableEntity
|
||||||
import net.psforever.objects.equipment._
|
import net.psforever.objects.equipment._
|
||||||
import net.psforever.objects.guid.{Task, TaskResolver}
|
import net.psforever.objects.guid.{Task, TaskResolver}
|
||||||
|
|
@ -410,7 +410,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
|
|
||||||
sendResponse(PacketCoding.CreateGamePacket(0, CharacterInfoMessage(0, PlanetSideZoneID(1), 0, PlanetSideGUID(0), true, 0)))
|
sendResponse(PacketCoding.CreateGamePacket(0, CharacterInfoMessage(0, PlanetSideZoneID(1), 0, PlanetSideGUID(0), true, 0)))
|
||||||
|
|
||||||
case IntergalacticCluster.GiveWorld(zoneId, zone) =>
|
case InterstellarCluster.GiveWorld(zoneId, zone) =>
|
||||||
log.info(s"Zone $zoneId has been loaded")
|
log.info(s"Zone $zoneId has been loaded")
|
||||||
player.Continent = zoneId
|
player.Continent = zoneId
|
||||||
continent = zone
|
continent = zone
|
||||||
|
|
@ -419,7 +419,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
case PlayerLoaded(tplayer) =>
|
case PlayerLoaded(tplayer) =>
|
||||||
log.info(s"Player $tplayer has been loaded")
|
log.info(s"Player $tplayer has been loaded")
|
||||||
//init for whole server
|
//init for whole server
|
||||||
galaxy ! IntergalacticCluster.RequestZoneInitialization(tplayer)
|
galaxy ! InterstellarCluster.RequestClientInitialization(tplayer)
|
||||||
|
|
||||||
case PlayerFailedToLoad(tplayer) =>
|
case PlayerFailedToLoad(tplayer) =>
|
||||||
player.Continent match {
|
player.Continent match {
|
||||||
|
|
@ -460,9 +460,9 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
sendResponse(PacketCoding.CreateGamePacket(0, BroadcastWarpgateUpdateMessage(PlanetSideGUID(13), PlanetSideGUID(1), false, false, true))) // VS Sanctuary: Inactive Warpgate -> Broadcast Warpgate
|
sendResponse(PacketCoding.CreateGamePacket(0, BroadcastWarpgateUpdateMessage(PlanetSideGUID(13), PlanetSideGUID(1), false, false, true))) // VS Sanctuary: Inactive Warpgate -> Broadcast Warpgate
|
||||||
sendResponse(PacketCoding.CreateGamePacket(0, ZonePopulationUpdateMessage(PlanetSideGUID(13), 414, 138, 0, 138, 0, 138, 0, 138, 0)))
|
sendResponse(PacketCoding.CreateGamePacket(0, ZonePopulationUpdateMessage(PlanetSideGUID(13), 414, 138, 0, 138, 0, 138, 0, 138, 0)))
|
||||||
|
|
||||||
case IntergalacticCluster.ClientInitializationComplete(tplayer)=>
|
case InterstellarCluster.ClientInitializationComplete(tplayer)=>
|
||||||
//this will cause the client to send back a BeginZoningMessage packet (see below)
|
//this will cause the client to send back a BeginZoningMessage packet (see below)
|
||||||
sendResponse(PacketCoding.CreateGamePacket(0, LoadMapMessage(continent.Map.Name, continent.ZoneId, 40100,25,true,3770441820L))) //VS Sanctuary
|
sendResponse(PacketCoding.CreateGamePacket(0, LoadMapMessage(continent.Map.Name, continent.Id, 40100,25,true,3770441820L))) //VS Sanctuary
|
||||||
log.info("Load the now-registered player")
|
log.info("Load the now-registered player")
|
||||||
//load the now-registered player
|
//load the now-registered player
|
||||||
tplayer.Spawn
|
tplayer.Spawn
|
||||||
|
|
@ -474,7 +474,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
|
|
||||||
case SetCurrentAvatar(tplayer) =>
|
case SetCurrentAvatar(tplayer) =>
|
||||||
val guid = tplayer.GUID
|
val guid = tplayer.GUID
|
||||||
LivePlayerList.Assign(continent.ZoneNumber, sessionId, guid)
|
LivePlayerList.Assign(continent.Number, sessionId, guid)
|
||||||
sendResponse(PacketCoding.CreateGamePacket(0, SetCurrentAvatarMessage(guid,0,0)))
|
sendResponse(PacketCoding.CreateGamePacket(0, SetCurrentAvatarMessage(guid,0,0)))
|
||||||
sendResponse(PacketCoding.CreateGamePacket(0, CreateShortcutMessage(guid, 1, 0, true, Shortcut.MEDKIT)))
|
sendResponse(PacketCoding.CreateGamePacket(0, CreateShortcutMessage(guid, 1, 0, true, Shortcut.MEDKIT)))
|
||||||
|
|
||||||
|
|
@ -633,7 +633,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
//TODO check if can spawn on last continent/location from player?
|
//TODO check if can spawn on last continent/location from player?
|
||||||
//TODO if yes, get continent guid accessors
|
//TODO if yes, get continent guid accessors
|
||||||
//TODO if no, get sanctuary guid accessors and reset the player's expectations
|
//TODO if no, get sanctuary guid accessors and reset the player's expectations
|
||||||
galaxy ! IntergalacticCluster.GetWorld("home3")
|
galaxy ! InterstellarCluster.GetWorld("home3")
|
||||||
|
|
||||||
import scala.concurrent.duration._
|
import scala.concurrent.duration._
|
||||||
import scala.concurrent.ExecutionContext.Implicits.global
|
import scala.concurrent.ExecutionContext.Implicits.global
|
||||||
|
|
@ -657,7 +657,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
sendResponse(PacketCoding.CreateGamePacket(0, ReplicationStreamMessage(5, Some(6), Vector(SquadListing())))) //clear squad list
|
sendResponse(PacketCoding.CreateGamePacket(0, ReplicationStreamMessage(5, Some(6), Vector(SquadListing())))) //clear squad list
|
||||||
|
|
||||||
//load active players in zone
|
//load active players in zone
|
||||||
LivePlayerList.ZonePopulation(continent.ZoneNumber, _ => true).foreach(char => {
|
LivePlayerList.ZonePopulation(continent.Number, _ => true).foreach(char => {
|
||||||
sendResponse(
|
sendResponse(
|
||||||
PacketCoding.CreateGamePacket(0,
|
PacketCoding.CreateGamePacket(0,
|
||||||
ObjectCreateMessage(ObjectClass.avatar, char.GUID, char.Definition.Packet.ConstructorData(char).get)
|
ObjectCreateMessage(ObjectClass.avatar, char.GUID, char.Definition.Packet.ConstructorData(char).get)
|
||||||
|
|
@ -752,7 +752,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
if(item.GUID == item_guid) {
|
if(item.GUID == item_guid) {
|
||||||
val orient : Vector3 = Vector3(0f, 0f, player.Orientation.z)
|
val orient : Vector3 = Vector3(0f, 0f, player.Orientation.z)
|
||||||
player.FreeHand.Equipment = None
|
player.FreeHand.Equipment = None
|
||||||
continent.Actor ! Zone.DropItemOnGround(item, player.Position, orient) //TODO do I need to wait for callback?
|
continent.Ground ! Zone.DropItemOnGround(item, player.Position, orient)
|
||||||
sendResponse(PacketCoding.CreateGamePacket(0, ObjectDetachMessage(player.GUID, item.GUID, player.Position, 0f, 0f, player.Orientation.z)))
|
sendResponse(PacketCoding.CreateGamePacket(0, ObjectDetachMessage(player.GUID, item.GUID, player.Position, 0f, 0f, player.Orientation.z)))
|
||||||
avatarService ! AvatarServiceMessage(player.Continent, AvatarAction.EquipmentOnGround(player.GUID, player.Position, orient, item))
|
avatarService ! AvatarServiceMessage(player.Continent, AvatarAction.EquipmentOnGround(player.GUID, player.Position, orient, item))
|
||||||
}
|
}
|
||||||
|
|
@ -765,7 +765,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
|
|
||||||
case msg @ PickupItemMessage(item_guid, player_guid, unk1, unk2) =>
|
case msg @ PickupItemMessage(item_guid, player_guid, unk1, unk2) =>
|
||||||
log.info("PickupItem: " + msg)
|
log.info("PickupItem: " + msg)
|
||||||
continent.Actor ! Zone.GetItemOnGround(player, item_guid)
|
continent.Ground ! Zone.GetItemOnGround(player, item_guid)
|
||||||
|
|
||||||
case msg @ ReloadMessage(item_guid, ammo_clip, unk1) =>
|
case msg @ ReloadMessage(item_guid, ammo_clip, unk1) =>
|
||||||
log.info("Reload: " + msg)
|
log.info("Reload: " + msg)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue