mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-01-20 02:54:46 +00:00
started doors
This commit is contained in:
parent
c85d7a65a2
commit
fa633aa79d
77
common/src/main/scala/net/psforever/objects/doors/Door.scala
Normal file
77
common/src/main/scala/net/psforever/objects/doors/Door.scala
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package net.psforever.objects.doors
|
||||
|
||||
import akka.actor.{ActorContext, ActorRef, Props}
|
||||
import net.psforever.objects.{PlanetSideGameObject, Player}
|
||||
import net.psforever.packet.game.UseItemMessage
|
||||
import net.psforever.types.PlanetSideEmpire
|
||||
|
||||
/**
|
||||
* na
|
||||
* @param ddef the `ObjectDefinition` that constructs this object and maintains some of its immutable fields
|
||||
*/
|
||||
class Door(ddef : DoorDefinition) extends PlanetSideGameObject {
|
||||
/** Internal reference to the `Actor` for this `Door`, sets up by this `Door`. */
|
||||
private var actor = ActorRef.noSender
|
||||
|
||||
def Actor(implicit context : ActorContext) : ActorRef = {
|
||||
if(actor == ActorRef.noSender) {
|
||||
actor = context.actorOf(Props(classOf[DoorControl], this), s"${ddef.Name}_${GUID.guid}")
|
||||
}
|
||||
actor
|
||||
}
|
||||
|
||||
private var openState : Boolean = false
|
||||
private var faction : PlanetSideEmpire.Value = PlanetSideEmpire.NEUTRAL
|
||||
private var hackedBy : Option[PlanetSideEmpire.Value] = None
|
||||
|
||||
def Open : Boolean = openState
|
||||
|
||||
def Faction : PlanetSideEmpire.Value = faction
|
||||
|
||||
def Convert(toFaction : PlanetSideEmpire.Value) : Unit = {
|
||||
hackedBy = None
|
||||
faction = toFaction
|
||||
}
|
||||
|
||||
def Request(player : Player, msg : UseItemMessage) : Door.Exchange = {
|
||||
if(!openState) {
|
||||
if(faction == PlanetSideEmpire.NEUTRAL || player.Faction == faction) {
|
||||
Door.OpenEvent()
|
||||
}
|
||||
else {
|
||||
Door.NoEvent()
|
||||
}
|
||||
}
|
||||
else {
|
||||
Door.NoEvent()
|
||||
}
|
||||
}
|
||||
|
||||
def Definition : DoorDefinition = ddef
|
||||
}
|
||||
|
||||
object Door {
|
||||
final case class Request(player : Player, msg : UseItemMessage)
|
||||
|
||||
sealed trait Exchange
|
||||
|
||||
final case class DoorMessage(player : Player, msg : UseItemMessage, response : Exchange)
|
||||
|
||||
final case class OpenEvent() extends Exchange
|
||||
|
||||
final case class CloseEvent() extends Exchange
|
||||
|
||||
final case class NoEvent() extends Exchange
|
||||
|
||||
def apply(tdef : DoorDefinition) : Door = {
|
||||
new Door(tdef)
|
||||
}
|
||||
|
||||
import net.psforever.packet.game.PlanetSideGUID
|
||||
def apply(guid : PlanetSideGUID, ddef : DoorDefinition) : Door = {
|
||||
val obj = new Door(ddef)
|
||||
obj.GUID = guid
|
||||
obj
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package net.psforever.objects.doors
|
||||
|
||||
import akka.actor.{Actor, ActorRef, Cancellable}
|
||||
import net.psforever.packet.game.PlanetSideGUID
|
||||
|
||||
import scala.collection.mutable.ListBuffer
|
||||
|
||||
class DoorCloseControl(implicit val environment : ActorRef) extends Actor {
|
||||
import DoorCloseControl._
|
||||
private var doorCloser : Cancellable = DefaultCloser
|
||||
private var openDoors : List[DoorEntry] = Nil
|
||||
|
||||
def receive : Receive = {
|
||||
case DoorIsOpen(guid, time) =>
|
||||
if(openDoors.isEmpty) {
|
||||
//doorCloser = context.system.scheduler.scheduleOnce(timeout, environment, Door.DoorMessage())
|
||||
}
|
||||
else {
|
||||
openDoors = openDoors :+ DoorEntry(guid, time)
|
||||
}
|
||||
|
||||
case _ => ;
|
||||
}
|
||||
}
|
||||
|
||||
object DoorCloseControl {
|
||||
private final val timeout : Long = 5000L
|
||||
|
||||
private final val DefaultCloser : Cancellable = new Cancellable() {
|
||||
override def cancel : Boolean = true
|
||||
override def isCancelled : Boolean = true
|
||||
}
|
||||
|
||||
private final case class DoorEntry(door_guid : PlanetSideGUID, opened_at_time : Long)
|
||||
|
||||
final case class DoorIsOpen(door_guid : PlanetSideGUID, opened_at_time : Long = System.nanoTime())
|
||||
|
||||
final case class CloseTheDoor(door_guid : PlanetSideGUID)
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package net.psforever.objects.doors
|
||||
|
||||
import akka.actor.{Actor, Cancellable}
|
||||
|
||||
/**
|
||||
* An `Actor` that handles messages being dispatched to a specific `Door`.
|
||||
* @param door the `Door` object being governed
|
||||
*/
|
||||
class DoorControl(door : Door) extends Actor {
|
||||
private var doorCloser : Cancellable = DoorControl.DefaultCloser
|
||||
|
||||
def receive : Receive = {
|
||||
case Door.Request(player, msg) =>
|
||||
sender ! Door.DoorMessage(player, msg, door.Request(player, msg))
|
||||
//doorCloser = context.system.scheduler.scheduleOnce(5000L, sender, Door.DoorMessage())
|
||||
case _ =>
|
||||
sender ! Door.NoEvent()
|
||||
}
|
||||
}
|
||||
|
||||
object DoorControl {
|
||||
final val DefaultCloser : Cancellable = new Cancellable() {
|
||||
override def cancel : Boolean = true
|
||||
override def isCancelled : Boolean = true
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package net.psforever.objects.doors
|
||||
|
||||
import net.psforever.objects.definition.ObjectDefinition
|
||||
|
||||
/**
|
||||
* The definition for any `door`.
|
||||
* @param objectId the object's identifier number
|
||||
*/
|
||||
abstract class DoorDefinition(objectId : Int) extends ObjectDefinition(objectId) {
|
||||
Name = "door"
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package net.psforever.objects.zones
|
||||
|
||||
import net.psforever.objects.doors.{Door, DoorDefinition}
|
||||
|
||||
/**
|
||||
* Wrapper `Class` designed to instantiate a `Door` server object.
|
||||
* @param ddef a `DoorDefinition` object, indicating the specific functionality of the resulting `Door`
|
||||
* @param id the globally unique identifier to which this `Door` will be registered
|
||||
*/
|
||||
class DoorObjectBuilder(private val ddef : DoorDefinition, private val id : Int) extends ServerObjectBuilder[Door] {
|
||||
import akka.actor.ActorContext
|
||||
import net.psforever.objects.guid.NumberPoolHub
|
||||
|
||||
def Build(implicit context : ActorContext, guid : NumberPoolHub) : Door = {
|
||||
val obj = Door(ddef)
|
||||
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 DoorObjectBuilder {
|
||||
/**
|
||||
* Overloaded constructor for a `DoorObjectBuilder`.
|
||||
* @param ddef a `DoorDefinition` object
|
||||
* @param id a globally unique identifier
|
||||
* @return a `DoorObjectBuilder` object
|
||||
*/
|
||||
def apply(ddef : DoorDefinition, id : Int) : DoorObjectBuilder = {
|
||||
new DoorObjectBuilder(ddef, id)
|
||||
}
|
||||
}
|
||||
|
|
@ -9,7 +9,7 @@ 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 {
|
||||
trait ServerObjectBuilder[A <: PlanetSideGameObject] {
|
||||
/**
|
||||
* Instantiate and configure the given server object
|
||||
* (at a later time compared to the construction of the builder class).<br>
|
||||
|
|
@ -23,5 +23,5 @@ trait ServerObjectBuilder {
|
|||
* defaults to `null`
|
||||
* @return the object that was created and integrated into the `Zone`
|
||||
*/
|
||||
def Build(implicit context : ActorContext = null, guid : NumberPoolHub = null) : PlanetSideGameObject
|
||||
def Build(implicit context : ActorContext = null, guid : NumberPoolHub = null) : A
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import net.psforever.objects.terminals.{Terminal, TerminalDefinition}
|
|||
* @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 {
|
||||
class TerminalObjectBuilder(private val tdef : TerminalDefinition, private val id : Int) extends ServerObjectBuilder[Terminal] {
|
||||
import akka.actor.ActorContext
|
||||
import net.psforever.objects.guid.NumberPoolHub
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ package net.psforever.objects.zones
|
|||
* `LoadMapMessage`
|
||||
*/
|
||||
class ZoneMap(private val name : String) {
|
||||
private var localObjects : List[ServerObjectBuilder] = List()
|
||||
private var localObjects : List[ServerObjectBuilder[_]] = List()
|
||||
|
||||
def Name : String = name
|
||||
|
||||
|
|
@ -29,7 +29,7 @@ class ZoneMap(private val name : String) {
|
|||
* 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 = {
|
||||
def LocalObject(obj : ServerObjectBuilder[_]) : Unit = {
|
||||
localObjects = localObjects :+ obj
|
||||
}
|
||||
|
||||
|
|
@ -37,7 +37,7 @@ class ZoneMap(private val name : String) {
|
|||
* 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] = {
|
||||
def LocalObjects : List[ServerObjectBuilder[_]] = {
|
||||
localObjects
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import ch.qos.logback.core.status._
|
|||
import ch.qos.logback.core.util.StatusPrinter
|
||||
import com.typesafe.config.ConfigFactory
|
||||
import net.psforever.crypto.CryptoInterface
|
||||
import net.psforever.objects.zones.{InterstellarCluster, TerminalObjectBuilder, Zone, ZoneMap}
|
||||
import net.psforever.objects.zones._
|
||||
import net.psforever.objects.guid.TaskResolver
|
||||
import org.slf4j
|
||||
import org.fusesource.jansi.Ansi._
|
||||
|
|
@ -222,6 +222,12 @@ object PsLogin {
|
|||
def createContinents() : List[Zone] = {
|
||||
val map13 = new ZoneMap("map13") {
|
||||
import net.psforever.objects.GlobalDefinitions._
|
||||
val ddef = new net.psforever.objects.doors.DoorDefinition(242) {} //generic door
|
||||
|
||||
LocalObject(DoorObjectBuilder(ddef, 330))
|
||||
LocalObject(DoorObjectBuilder(ddef, 332))
|
||||
LocalObject(DoorObjectBuilder(ddef, 372))
|
||||
LocalObject(DoorObjectBuilder(ddef, 373))
|
||||
LocalObject(TerminalObjectBuilder(cert_terminal, 186))
|
||||
LocalObject(TerminalObjectBuilder(cert_terminal, 187))
|
||||
LocalObject(TerminalObjectBuilder(cert_terminal, 188))
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import org.log4s.MDC
|
|||
import MDCContextAware.Implicits._
|
||||
import ServiceManager.Lookup
|
||||
import net.psforever.objects._
|
||||
import net.psforever.objects.doors.Door
|
||||
import net.psforever.objects.zones.{InterstellarCluster, Zone}
|
||||
import net.psforever.objects.entity.IdentifiableEntity
|
||||
import net.psforever.objects.equipment._
|
||||
|
|
@ -206,6 +207,17 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
case _ => ;
|
||||
}
|
||||
|
||||
case Door.DoorMessage(_, msg, order) =>
|
||||
order match {
|
||||
case Door.OpenEvent() =>
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, GenericObjectStateMsg(msg.object_guid, 16)))
|
||||
|
||||
case Door.CloseEvent() =>
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, GenericObjectStateMsg(msg.object_guid, 17)))
|
||||
|
||||
case Door.NoEvent() => ;
|
||||
}
|
||||
|
||||
case Terminal.TerminalMessage(tplayer, msg, order) =>
|
||||
order match {
|
||||
case Terminal.BuyExosuit(exosuit, subtype) =>
|
||||
|
|
@ -943,15 +955,24 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
log.info("UseItem: " + msg)
|
||||
// TODO: Not all fields in the response are identical to source in real packet logs (but seems to be ok)
|
||||
// TODO: Not all incoming UseItemMessage's respond with another UseItemMessage (i.e. doors only send out GenericObjectStateMsg)
|
||||
if (itemType != 121) sendResponse(PacketCoding.CreateGamePacket(0, UseItemMessage(avatar_guid, unk1, object_guid, unk2, unk3, unk4, unk5, unk6, unk7, unk8, itemType)))
|
||||
if (itemType == 121 && !unk3){ // TODO : medkit use ?!
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, UseItemMessage(avatar_guid, unk1, object_guid, 0, unk3, unk4, unk5, unk6, unk7, unk8, itemType)))
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, PlanetsideAttributeMessage(avatar_guid, 0, 100))) // avatar with 100 hp
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, ObjectDeleteMessage(PlanetSideGUID(unk1), 2)))
|
||||
}
|
||||
if (unk1 == 0 && !unk3 && unk7 == 25) {
|
||||
// TODO: This should only actually be sent to doors upon opening; may break non-door items upon use
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, GenericObjectStateMsg(object_guid, 16)))
|
||||
continent.GUID(object_guid) match {
|
||||
case Some(door : Door) =>
|
||||
log.info("Door action!")
|
||||
door.Actor ! Door.Request(player, msg)
|
||||
case Some(obj : PlanetSideGameObject) =>
|
||||
if(itemType != 121) {
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, UseItemMessage(avatar_guid, unk1, object_guid, unk2, unk3, unk4, unk5, unk6, unk7, unk8, itemType)))
|
||||
}
|
||||
else if(itemType == 121 && !unk3) { // TODO : medkit use ?!
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, UseItemMessage(avatar_guid, unk1, object_guid, 0, unk3, unk4, unk5, unk6, unk7, unk8, itemType)))
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, PlanetsideAttributeMessage(avatar_guid, 0, 100))) // avatar with 100 hp
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, ObjectDeleteMessage(PlanetSideGUID(unk1), 2)))
|
||||
}
|
||||
// if(unk1 == 0 && !unk3 && unk7 == 25) {
|
||||
// // TODO: This should only actually be sent to doors upon opening; may break non-door items upon use
|
||||
// sendResponse(PacketCoding.CreateGamePacket(0, GenericObjectStateMsg(object_guid, 16)))
|
||||
// }
|
||||
case None => ;
|
||||
}
|
||||
|
||||
case msg @ UnuseItemMessage(player_guid, item) =>
|
||||
|
|
|
|||
Loading…
Reference in a new issue