mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-03-07 22:20:27 +00:00
automated doors, IFF locks, and bases thus that only permissible doors can be opened by players of correct faction alignment; Base is just a prototype example, hastily created for this functionality; LocalService will eventually be used for doors messages (and other things)
This commit is contained in:
parent
fa633aa79d
commit
7fcac7fc25
16 changed files with 366 additions and 93 deletions
|
|
@ -3,11 +3,16 @@ package net.psforever.objects
|
|||
|
||||
import net.psforever.objects.definition._
|
||||
import net.psforever.objects.definition.converter.{CommandDetonaterConverter, LockerContainerConverter, REKConverter}
|
||||
import net.psforever.objects.doors.{DoorDefinition, IFFLockDefinition}
|
||||
import net.psforever.objects.equipment.CItem.DeployedItem
|
||||
import net.psforever.objects.equipment._
|
||||
import net.psforever.objects.inventory.InventoryTile
|
||||
<<<<<<< c5ae9e477ccade5759eac2e9526ba898d0e8f16b
|
||||
import net.psforever.objects.terminals.{CertTerminalDefinition, OrderTerminalDefinition}
|
||||
import net.psforever.packet.game.objectcreate.ObjectClass
|
||||
=======
|
||||
import net.psforever.objects.terminals.OrderTerminalDefinition
|
||||
>>>>>>> automated doors, IFF locks, and bases thus that only permissible doors can be opened by players of correct faction alignment; Base is just a prototype example, hastily created for this functionality; LocalService will eventually be used for doors messages (and other things)
|
||||
import net.psforever.types.PlanetSideEmpire
|
||||
|
||||
object GlobalDefinitions {
|
||||
|
|
@ -1242,4 +1247,9 @@ object GlobalDefinitions {
|
|||
order_terminal = new OrderTerminalDefinition
|
||||
val
|
||||
cert_terminal = new CertTerminalDefinition
|
||||
|
||||
val
|
||||
external_lock = new IFFLockDefinition
|
||||
val
|
||||
door = new DoorDefinition
|
||||
}
|
||||
|
|
|
|||
17
common/src/main/scala/net/psforever/objects/doors/Base.scala
Normal file
17
common/src/main/scala/net/psforever/objects/doors/Base.scala
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package net.psforever.objects.doors
|
||||
|
||||
import net.psforever.types.PlanetSideEmpire
|
||||
|
||||
class Base(private val id : Int) {
|
||||
private var faction : PlanetSideEmpire.Value = PlanetSideEmpire.NEUTRAL
|
||||
|
||||
def Id : Int = id
|
||||
|
||||
def Faction : PlanetSideEmpire.Value = faction
|
||||
|
||||
def Faction_=(emp : PlanetSideEmpire.Value) : PlanetSideEmpire.Value = {
|
||||
faction = emp
|
||||
Faction
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,6 @@ 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
|
||||
|
|
@ -22,26 +21,29 @@ class Door(ddef : DoorDefinition) extends PlanetSideGameObject {
|
|||
}
|
||||
|
||||
private var openState : Boolean = false
|
||||
private var faction : PlanetSideEmpire.Value = PlanetSideEmpire.NEUTRAL
|
||||
private var hackedBy : Option[PlanetSideEmpire.Value] = None
|
||||
private var lockState : Boolean = false
|
||||
|
||||
def Open : Boolean = openState
|
||||
|
||||
def Faction : PlanetSideEmpire.Value = faction
|
||||
|
||||
def Convert(toFaction : PlanetSideEmpire.Value) : Unit = {
|
||||
hackedBy = None
|
||||
faction = toFaction
|
||||
def Open_=(open : Boolean) : Boolean = {
|
||||
openState = open
|
||||
Open
|
||||
}
|
||||
|
||||
def Request(player : Player, msg : UseItemMessage) : Door.Exchange = {
|
||||
if(!openState) {
|
||||
if(faction == PlanetSideEmpire.NEUTRAL || player.Faction == faction) {
|
||||
Door.OpenEvent()
|
||||
}
|
||||
else {
|
||||
Door.NoEvent()
|
||||
}
|
||||
def Locked : Boolean = lockState
|
||||
|
||||
def Locked_=(lock : Boolean) : Boolean = {
|
||||
lockState = lock
|
||||
Locked
|
||||
}
|
||||
|
||||
def Use(player : Player, msg : UseItemMessage) : Door.Exchange = {
|
||||
if(!lockState && !openState) {
|
||||
openState = true
|
||||
Door.OpenEvent()
|
||||
}
|
||||
else if(openState) {
|
||||
Door.CloseEvent()
|
||||
}
|
||||
else {
|
||||
Door.NoEvent()
|
||||
|
|
@ -52,7 +54,7 @@ class Door(ddef : DoorDefinition) extends PlanetSideGameObject {
|
|||
}
|
||||
|
||||
object Door {
|
||||
final case class Request(player : Player, msg : UseItemMessage)
|
||||
final case class Use(player : Player, msg : UseItemMessage)
|
||||
|
||||
sealed trait Exchange
|
||||
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@ 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))
|
||||
case Door.Use(player, msg) =>
|
||||
sender ! Door.DoorMessage(player, msg, door.Use(player, msg))
|
||||
//doorCloser = context.system.scheduler.scheduleOnce(5000L, sender, Door.DoorMessage())
|
||||
case _ =>
|
||||
sender ! Door.NoEvent()
|
||||
|
|
|
|||
|
|
@ -5,9 +5,8 @@ import net.psforever.objects.definition.ObjectDefinition
|
|||
|
||||
/**
|
||||
* The definition for any `door`.
|
||||
* @param objectId the object's identifier number
|
||||
* Object Id 242 is a generic door.
|
||||
*/
|
||||
abstract class DoorDefinition(objectId : Int) extends ObjectDefinition(objectId) {
|
||||
class DoorDefinition extends ObjectDefinition(242) {
|
||||
Name = "door"
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package net.psforever.objects.doors
|
||||
|
||||
import net.psforever.objects.{GlobalDefinitions, PlanetSideGameObject}
|
||||
import net.psforever.types.PlanetSideEmpire
|
||||
|
||||
class IFFLock extends PlanetSideGameObject {
|
||||
private var hackedBy : Option[PlanetSideEmpire.Value] = None
|
||||
|
||||
def Hacker : Option[PlanetSideEmpire.Value] = hackedBy
|
||||
|
||||
def Hacker_=(hacker : PlanetSideEmpire.Value) : Option[PlanetSideEmpire.Value] = {
|
||||
Hacker = Some(hacker)
|
||||
}
|
||||
|
||||
def Hacker_=(hacker : Option[PlanetSideEmpire.Value]) : Option[PlanetSideEmpire.Value] = {
|
||||
hackedBy = hacker
|
||||
Hacker
|
||||
}
|
||||
|
||||
def Definition : IFFLockDefinition = GlobalDefinitions.external_lock
|
||||
}
|
||||
|
||||
object IFFLock {
|
||||
def apply() : IFFLock = {
|
||||
new IFFLock
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package net.psforever.objects.doors
|
||||
|
||||
import net.psforever.objects.definition.ObjectDefinition
|
||||
|
||||
class IFFLockDefinition extends ObjectDefinition(0) {
|
||||
Name = "iff_lock"
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package net.psforever.objects.zones
|
||||
|
||||
import net.psforever.objects.doors.{IFFLock, IFFLockDefinition}
|
||||
|
||||
/**
|
||||
* Wrapper `Class` designed to instantiate a `Door` server object.
|
||||
* @param idef a `IFFLockDefinition` object, indicating the specific functionality of the resulting `Door`
|
||||
* @param id the globally unique identifier to which this `IFFLock` will be registered
|
||||
*/
|
||||
class IFFLockObjectBuilder(private val idef : IFFLockDefinition, private val id : Int) extends ServerObjectBuilder[IFFLock] {
|
||||
import akka.actor.ActorContext
|
||||
import net.psforever.objects.guid.NumberPoolHub
|
||||
|
||||
def Build(implicit context : ActorContext, guid : NumberPoolHub) : IFFLock = {
|
||||
val obj = IFFLock()
|
||||
guid.register(obj, id) //non-Actor GUID registration
|
||||
obj
|
||||
}
|
||||
}
|
||||
|
||||
object IFFLockObjectBuilder {
|
||||
/**
|
||||
* Overloaded constructor for a `IFFLockObjectBuilder`.
|
||||
* @param idef an `IFFLock` object
|
||||
* @param id a globally unique identifier
|
||||
* @return an `IFFLockObjectBuilder` object
|
||||
*/
|
||||
def apply(idef : IFFLockDefinition, id : Int) : IFFLockObjectBuilder = {
|
||||
new IFFLockObjectBuilder(idef, id)
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
package net.psforever.objects.zones
|
||||
|
||||
import akka.actor.{ActorContext, ActorRef, Props}
|
||||
import net.psforever.objects.doors.Base
|
||||
import net.psforever.objects.{PlanetSideGameObject, Player}
|
||||
import net.psforever.objects.equipment.Equipment
|
||||
import net.psforever.objects.guid.NumberPoolHub
|
||||
|
|
@ -48,6 +49,8 @@ class Zone(private val zoneId : String, zoneMap : ZoneMap, zoneNumber : Int) {
|
|||
/** Used by the `Zone` to coordinate `Equipment` dropping and collection requests. */
|
||||
private var ground : ActorRef = ActorRef.noSender
|
||||
|
||||
private var bases : List[Base] = List()
|
||||
|
||||
/**
|
||||
* Establish the basic accessible conditions necessary for a functional `Zone`.<br>
|
||||
* <br>
|
||||
|
|
@ -69,6 +72,8 @@ class Zone(private val zoneId : String, zoneMap : ZoneMap, zoneNumber : Int) {
|
|||
Map.LocalObjects.foreach({ builderObject =>
|
||||
builderObject.Build
|
||||
})
|
||||
|
||||
MakeBases(Map.LocalBases)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -169,6 +174,15 @@ class Zone(private val zoneId : String, zoneMap : ZoneMap, zoneNumber : Int) {
|
|||
*/
|
||||
def Ground : ActorRef = ground
|
||||
|
||||
def MakeBases(num : Int) : List[Base] = {
|
||||
bases = (0 to num).map(id => new Base(id)).toList
|
||||
bases
|
||||
}
|
||||
|
||||
def Base(id : Int) : Option[Base] = {
|
||||
bases.lift(id)
|
||||
}
|
||||
|
||||
/**
|
||||
* 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>
|
||||
|
|
|
|||
|
|
@ -13,8 +13,48 @@ class ZoneActor(zone : Zone) extends Actor {
|
|||
def receive : Receive = {
|
||||
case Zone.Init() =>
|
||||
zone.Init
|
||||
ZoneSetupCheck()
|
||||
|
||||
case msg =>
|
||||
log.warn(s"Received unexpected message - $msg")
|
||||
}
|
||||
|
||||
def ZoneSetupCheck(): Unit = {
|
||||
def guid(id : Int) = zone.GUID(id)
|
||||
val map = zone.Map
|
||||
val slog = org.log4s.getLogger(s"zone/${zone.Id}/sanity")
|
||||
|
||||
//check base to object associations
|
||||
map.ObjectToBase.foreach({ case((object_guid, base_id)) =>
|
||||
if(zone.Base(base_id).isEmpty) {
|
||||
slog.error(s"expected a base #$base_id")
|
||||
}
|
||||
if(guid(object_guid).isEmpty) {
|
||||
slog.error(s"expected object id $object_guid to exist, but it did not")
|
||||
}
|
||||
})
|
||||
|
||||
//check door to lock association
|
||||
import net.psforever.objects.doors.{Door, IFFLock}
|
||||
map.DoorToLock.foreach({ case((door_guid, lock_guid)) =>
|
||||
try {
|
||||
if(!guid(door_guid).get.isInstanceOf[Door]) {
|
||||
slog.error(s"expected id $door_guid to be a door, but it was not")
|
||||
}
|
||||
}
|
||||
catch {
|
||||
case _ : Exception =>
|
||||
slog.error(s"expected a door, but looking for uninitialized object $door_guid")
|
||||
}
|
||||
try {
|
||||
if(!guid(lock_guid).get.isInstanceOf[IFFLock]) {
|
||||
slog.error(s"expected id $lock_guid to be an IFF lock, but it was not")
|
||||
}
|
||||
}
|
||||
catch {
|
||||
case _ : Exception =>
|
||||
slog.error(s"expected an IFF lock, but looking for uninitialized object $lock_guid")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,19 +12,31 @@ package net.psforever.objects.zones
|
|||
* Use it as a blueprint.<br>
|
||||
* <br>
|
||||
* The "training zones" are the best example of the difference between a `ZoneMap` and a `Zone.`
|
||||
* ("Course" will be used as an unofficial location and layout descriptor.)
|
||||
* `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`).
|
||||
* While each course can have different objects and object states, i.e., a `Zone`,
|
||||
* both of these courses utilize the same basic server object layout because they are built from the same blueprint, i.e., a `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()
|
||||
private var linkDoorLock : Map[Int, Int] = Map()
|
||||
private var linkObjectBase : Map[Int, Int] = Map()
|
||||
private var numBases : Int = 0
|
||||
|
||||
def Name : String = name
|
||||
|
||||
/**
|
||||
* 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
|
||||
}
|
||||
|
||||
/**
|
||||
* Append the builder for a server object to the list of builders known to this `ZoneMap`.
|
||||
* @param obj the builder for a server object
|
||||
|
|
@ -33,11 +45,22 @@ class ZoneMap(private val name : String) {
|
|||
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
|
||||
def LocalBases : Int = numBases
|
||||
|
||||
def LocalBases_=(num : Int) : Int = {
|
||||
numBases = math.max(0, num)
|
||||
LocalBases
|
||||
}
|
||||
|
||||
def ObjectToBase : Map[Int, Int] = linkObjectBase
|
||||
|
||||
def ObjectToBase(object_guid : Int, base_id : Int) : Unit = {
|
||||
linkObjectBase = linkObjectBase ++ Map(object_guid -> base_id)
|
||||
}
|
||||
|
||||
def DoorToLock : Map[Int, Int] = linkDoorLock
|
||||
|
||||
def DoorToLock(door_guid : Int, lock_guid : Int) = {
|
||||
linkDoorLock = linkDoorLock ++ Map(door_guid -> lock_guid)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue