Add ResourceSilo definition with basic functionality for charging/discharging

This commit is contained in:
Mazo 2018-05-26 12:52:03 +01:00
parent 2d2788383c
commit 2933811ac6
4 changed files with 181 additions and 0 deletions

View file

@ -13,6 +13,7 @@ import net.psforever.objects.serverobject.mblocker.LockerDefinition
import net.psforever.objects.serverobject.pad.VehicleSpawnPadDefinition
import net.psforever.objects.serverobject.terminals._
import net.psforever.objects.serverobject.tube.SpawnTubeDefinition
import net.psforever.objects.serverobject.resourcesilo.ResourceSiloDefinition
import net.psforever.objects.vehicles.{SeatArmorRestriction, UtilityType}
import net.psforever.types.PlanetSideEmpire
@ -563,6 +564,8 @@ object GlobalDefinitions {
val door = new DoorDefinition
val resource_silo = new ResourceSiloDefinition
/**
* Given a faction, provide the standard assault melee weapon.
* @param faction the faction

View file

@ -0,0 +1,86 @@
// Copyright (c) 2017 PSForever
package net.psforever.objects.serverobject.resourcesilo
import akka.actor.{ActorContext, Props}
import net.psforever.objects.{GlobalDefinitions, Player, Vehicle}
import net.psforever.objects.serverobject.structures.Amenity
import net.psforever.packet.game.UseItemMessage
class ResourceSilo extends Amenity {
private var chargeLevel : Int = 0
private val maximumCharge : Int = 1000
// For the flashing red light on top of the NTU silo on
private var lowNtuWarningOn : Int = 0
// For the NTU display bar
private var capacitorDisplay : Long = 0
def ChargeLevel : Int = chargeLevel
// Do not call directly. Use ResourceSilo.UpdateChargeLevel message to handle logic such as low ntu warnings
def ChargeLevel_=(charge: Int) : Int = {
if(charge < 0 ) {
chargeLevel = 0
} else if (charge > maximumCharge) {
chargeLevel = maximumCharge
} else {
chargeLevel = charge
}
ChargeLevel
}
def MaximumCharge : Int = maximumCharge
def LowNtuWarningOn : Int = lowNtuWarningOn
def LowNtuWarningOn_=(enabled: Int) : Int = {
lowNtuWarningOn = enabled
LowNtuWarningOn
}
def CapacitorDisplay : Long = capacitorDisplay
def CapacitorDisplay_=(value: Long) : Long = {
capacitorDisplay = value
CapacitorDisplay
}
def Definition : ResourceSiloDefinition = GlobalDefinitions.resource_silo
def Use(player: Player, msg : UseItemMessage) : ResourceSilo.Exchange = {
ResourceSilo.ChargeEvent()
}
}
object ResourceSilo {
final case class Use(player: Player, msg : UseItemMessage)
final case class UpdateChargeLevel(amount: Int)
final case class LowNtuWarning(enabled: Int)
final case class SyncStateWithClient()
sealed trait Exchange
final case class ChargeEvent() extends Exchange
final case class ResourceSiloMessage(player: Player, msg : UseItemMessage, response : Exchange)
/**
* Overloaded constructor.
* @return the `Resource Silo` object
*/
def apply() : ResourceSilo = {
new ResourceSilo()
}
/**
* Instantiate an configure a `Resource Silo` object
* @param id the unique id that will be assigned to this entity
* @param context a context to allow the object to properly set up `ActorSystem` functionality;
* not necessary for this object, but required by signature
* @return the `Locker` object
*/
def Constructor(id : Int, context : ActorContext) : ResourceSilo = {
val obj = ResourceSilo()
obj.Actor = context.actorOf(Props(classOf[ResourceSiloControl], obj), s"${obj.Definition.Name}_$id")
obj.Actor ! "startup"
obj
}
}

View file

@ -0,0 +1,80 @@
// Copyright (c) 2017 PSForever
package net.psforever.objects.serverobject.resourcesilo
import akka.actor.{Actor, ActorRef}
import net.psforever.objects.serverobject.affinity.{FactionAffinity, FactionAffinityBehavior}
import net.psforever.objects.serverobject.structures.Building
import net.psforever.packet.game.PlanetSideGUID
import services.ServiceManager.Lookup
import services._
import services.avatar.{AvatarAction, AvatarServiceMessage}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._
/**
* An `Actor` that handles messages being dispatched to a specific `Resource Silo`.
* @param resourceSilo the `Resource Silo` object being governed
*/
class ResourceSiloControl(resourceSilo : ResourceSilo) extends Actor with FactionAffinityBehavior.Check {
def FactionObject : FactionAffinity = resourceSilo
var avatarService : ActorRef = Actor.noSender
private[this] val log = org.log4s.getLogger
def receive : Receive = {
case "startup" =>
ServiceManager.serviceManager ! Lookup("avatar") //ask for a resolver to deal with the GUID system
case ServiceManager.LookupResult("avatar", endpoint) =>
avatarService = endpoint
log.info("ResourceSiloControl: Silo " + resourceSilo.GUID + " Got avatar service " + endpoint)
// todo: This is just a temporary solution to drain NTU over time. When base object destruction is properly implemented NTU should be deducted when base objects repair themselves
context.system.scheduler.schedule(5 second, 5 second, self, ResourceSilo.UpdateChargeLevel(-1))
context.become(Processing)
case _ => ;
}
def Processing : Receive = checkBehavior.orElse {
case ResourceSilo.Use(player, msg) =>
sender ! ResourceSilo.ResourceSiloMessage(player, msg, resourceSilo.Use(player, msg))
case ResourceSilo.LowNtuWarning(enabled: Int) =>
resourceSilo.LowNtuWarningOn = enabled
log.trace(s"LowNtuWarning: Silo ${resourceSilo.GUID} low ntu warning set to ${enabled}")
avatarService ! AvatarServiceMessage(resourceSilo.Owner.asInstanceOf[Building].Zone.Id, AvatarAction.PlanetsideAttribute(PlanetSideGUID(resourceSilo.Owner.asInstanceOf[Building].ModelId), 47, resourceSilo.LowNtuWarningOn))
case ResourceSilo.UpdateChargeLevel(amount: Int) =>
// Increase if positive passed in or decrease charge level if negative number is passed in
resourceSilo.ChargeLevel += amount
if(resourceSilo.ChargeLevel > 0) {
log.trace(s"UpdateChargeLevel: Silo ${resourceSilo.GUID} set to ${resourceSilo.ChargeLevel}")
}
val ntuIsLow = resourceSilo.ChargeLevel.toFloat / resourceSilo.MaximumCharge.toFloat < 0.2f
val ntuBarLevel = scala.math.round((resourceSilo.ChargeLevel.toFloat / resourceSilo.MaximumCharge.toFloat) * 10).toInt
// Only send updated capacitor display value to all clients if it has actually changed
if(resourceSilo.CapacitorDisplay != ntuBarLevel) {
log.trace(s"Silo ${resourceSilo.GUID} NTU bar level has changed from ${resourceSilo.CapacitorDisplay} to ${ntuBarLevel}")
resourceSilo.CapacitorDisplay = ntuBarLevel
avatarService ! AvatarServiceMessage(resourceSilo.Owner.asInstanceOf[Building].Zone.Id, AvatarAction.PlanetsideAttribute(resourceSilo.GUID, 45, resourceSilo.CapacitorDisplay))
}
if(resourceSilo.LowNtuWarningOn == 1 && !ntuIsLow){
self ! ResourceSilo.LowNtuWarning(0)
} else if (resourceSilo.LowNtuWarningOn == 0 && ntuIsLow) {
self ! ResourceSilo.LowNtuWarning(1)
}
//todo: Shut down base power and make base neutral if silo hits zero NTU
case ResourceSilo.SyncStateWithClient() =>
avatarService ! AvatarServiceMessage(resourceSilo.Owner.asInstanceOf[Building].Zone.Id, AvatarAction.PlanetsideAttribute(PlanetSideGUID(resourceSilo.Owner.asInstanceOf[Building].ModelId), 47, resourceSilo.LowNtuWarningOn))
avatarService ! AvatarServiceMessage(resourceSilo.Owner.asInstanceOf[Building].Zone.Id, AvatarAction.PlanetsideAttribute(resourceSilo.GUID, 45, resourceSilo.CapacitorDisplay))
case _ => ;
}
}

View file

@ -0,0 +1,12 @@
// Copyright (c) 2017 PSForever
package net.psforever.objects.serverobject.resourcesilo
import net.psforever.objects.definition.ObjectDefinition
/**
* The definition for any `Resource Silo`.
* Object Id 731.
*/
class ResourceSiloDefinition extends ObjectDefinition(731) {
Name = "resource_silo"
}