converted DeployItem from AvatarService to LocalService; attempt at resolving missing overwhip yellow ring is complicated; vehicle ownership packet wqorks on deployables that are mountable, but is less successful on normal simple deployables

This commit is contained in:
Fate-JH 2024-08-06 15:09:34 -04:00
parent 698a5609ab
commit c6860bc718
12 changed files with 109 additions and 92 deletions

View file

@ -130,29 +130,6 @@ class EquipmentInHandTest extends ActorTest {
} }
} }
class DeployItemTest extends ActorTest {
ServiceManager.boot(system)
val service = system.actorOf(Props(classOf[AvatarService], Zone.Nowhere), "deploy-item-test-service")
val objDef = GlobalDefinitions.motionalarmsensor
val obj = new SensorDeployable(objDef)
obj.Position = Vector3(1, 2, 3)
obj.Orientation = Vector3(4, 5, 6)
obj.GUID = PlanetSideGUID(40)
val pkt = ObjectCreateMessage(
objDef.ObjectId,
obj.GUID,
objDef.Packet.ConstructorData(obj).get
)
"AvatarService" should {
"pass DeployItem" in {
service ! Service.Join("test")
service ! AvatarServiceMessage("test", AvatarAction.DeployItem(PlanetSideGUID(10), obj))
expectMsg(AvatarServiceResponse("/test/Avatar", PlanetSideGUID(10), AvatarResponse.DropItem(pkt)))
}
}
}
class DroptItemTest extends ActorTest { class DroptItemTest extends ActorTest {
ServiceManager.boot(system) ServiceManager.boot(system)
val service = system.actorOf(Props(classOf[AvatarService], Zone.Nowhere), "release-test-service") val service = system.actorOf(Props(classOf[AvatarService], Zone.Nowhere), "release-test-service")

View file

@ -563,7 +563,7 @@ class GeneralOperations(
* @param unk2 na * @param unk2 na
*/ */
def hackObject(targetGuid: PlanetSideGUID, unk1: Long, unk2: HackState7): Unit = { def hackObject(targetGuid: PlanetSideGUID, unk1: Long, unk2: HackState7): Unit = {
sendResponse(HackMessage(HackState1.Unk0, targetGuid, player_guid=Service.defaultPlayerGUID, progress=100, unk1, HackState.Hacked, unk2)) sendResponse(HackMessage(HackState1.Unk0, targetGuid, player_guid=Service.defaultPlayerGUID, progress=100, unk1.toFloat, HackState.Hacked, unk2))
} }
/** /**

View file

@ -531,6 +531,7 @@ class PlayerControl(player: Player, avatarActor: typed.ActorRef[AvatarActor.Comm
setupDeployable(obj, tool) setupDeployable(obj, tool)
case Zone.Deployable.IsBuilt(obj: BoomerDeployable) => case Zone.Deployable.IsBuilt(obj: BoomerDeployable) =>
obj.Actor ! Deployable.Ownership(player)
deployablePair match { deployablePair match {
case Some((deployable, tool)) if deployable eq obj => case Some((deployable, tool)) if deployable eq obj =>
val zone = player.Zone val zone = player.Zone
@ -552,11 +553,12 @@ class PlayerControl(player: Player, avatarActor: typed.ActorRef[AvatarActor.Comm
TaskWorkflow.execute(PutNewEquipmentInInventoryOrDrop(player)(trigger)) TaskWorkflow.execute(PutNewEquipmentInInventoryOrDrop(player)(trigger))
} }
Players.buildCooldownReset(zone, player.Name, obj) Players.buildCooldownReset(zone, player.Name, obj)
case _ => ; case _ => ()
} }
deployablePair = None deployablePair = None
case Zone.Deployable.IsBuilt(obj: TelepadDeployable) => case Zone.Deployable.IsBuilt(obj: TelepadDeployable) =>
obj.Actor ! Deployable.Ownership(player)
deployablePair match { deployablePair match {
case Some((deployable, tool: Telepad)) if deployable eq obj => case Some((deployable, tool: Telepad)) if deployable eq obj =>
RemoveOldEquipmentFromInventory(player)(tool) RemoveOldEquipmentFromInventory(player)(tool)
@ -569,11 +571,12 @@ class PlayerControl(player: Player, avatarActor: typed.ActorRef[AvatarActor.Comm
TelepadControl.TelepadError(zone, player.Name, msg = "@Telepad_NoDeploy_RouterLost") TelepadControl.TelepadError(zone, player.Name, msg = "@Telepad_NoDeploy_RouterLost")
} }
Players.buildCooldownReset(zone, player.Name, obj) Players.buildCooldownReset(zone, player.Name, obj)
case _ => ; case _ => ()
} }
deployablePair = None deployablePair = None
case Zone.Deployable.IsBuilt(obj) => case Zone.Deployable.IsBuilt(obj) =>
obj.Actor ! Deployable.Ownership(player)
deployablePair match { deployablePair match {
case Some((deployable, tool)) if deployable eq obj => case Some((deployable, tool)) if deployable eq obj =>
Players.buildCooldownReset(player.Zone, player.Name, obj) Players.buildCooldownReset(player.Zone, player.Name, obj)
@ -584,7 +587,7 @@ class PlayerControl(player: Player, avatarActor: typed.ActorRef[AvatarActor.Comm
case None => case None =>
log.warn(s"${player.Name} should have destroyed a ${tool.Definition.Name} here, but could not find it") log.warn(s"${player.Name} should have destroyed a ${tool.Definition.Name} here, but could not find it")
} }
case _ => ; case _ => ()
} }
deployablePair = None deployablePair = None
@ -701,16 +704,27 @@ class PlayerControl(player: Player, avatarActor: typed.ActorRef[AvatarActor.Comm
if (deployables.Valid(obj) && if (deployables.Valid(obj) &&
!deployables.Contains(obj) && !deployables.Contains(obj) &&
Players.deployableWithinBuildLimits(player, obj)) { Players.deployableWithinBuildLimits(player, obj)) {
//deployables, upon construction, may display an animation effect
tool.Definition match { tool.Definition match {
case GlobalDefinitions.ace | /* animation handled in deployable lifecycle */ case GlobalDefinitions.router_telepad => () /* no special animation */
GlobalDefinitions.router_telepad => ; /* no special animation */ case GlobalDefinitions.ace
if obj.Definition.deployAnimation == DeployAnimation.Standard =>
zone.LocalEvents ! LocalServiceMessage(
zone.id,
LocalAction.TriggerEffectLocation(
obj.OwnerGuid.getOrElse(Service.defaultPlayerGUID),
"spawn_object_effect",
obj.Position,
obj.Orientation
)
)
case GlobalDefinitions.advanced_ace case GlobalDefinitions.advanced_ace
if obj.Definition.deployAnimation == DeployAnimation.Fdu => if obj.Definition.deployAnimation == DeployAnimation.Fdu =>
zone.AvatarEvents ! AvatarServiceMessage(zone.id, AvatarAction.PutDownFDU(player.GUID)) zone.AvatarEvents ! AvatarServiceMessage(zone.id, AvatarAction.PutDownFDU(player.GUID))
case _ => case _ =>
org.log4s.getLogger(name = "Deployables").warn( org.log4s
s"not sure what kind of construction item to animate - ${tool.Definition.Name}" .getLogger(name = "Deployables")
) .warn(s"not sure what kind of construction item to animate - ${tool.Definition.Name}")
} }
deployablePair = Some((obj, tool)) deployablePair = Some((obj, tool))
obj.Faction = player.Faction obj.Faction = player.Faction

View file

@ -4,7 +4,6 @@ package net.psforever.objects.ce
import akka.actor.{Actor, ActorRef, Cancellable} import akka.actor.{Actor, ActorRef, Cancellable}
import net.psforever.objects.guid.{GUIDTask, TaskWorkflow} import net.psforever.objects.guid.{GUIDTask, TaskWorkflow}
import net.psforever.objects._ import net.psforever.objects._
import net.psforever.objects.definition.DeployAnimation
import net.psforever.objects.zones.Zone import net.psforever.objects.zones.Zone
import net.psforever.packet.game._ import net.psforever.packet.game._
import net.psforever.services.Service import net.psforever.services.Service
@ -105,6 +104,7 @@ trait DeployableBehavior {
def loseOwnership(obj: Deployable, toFaction: PlanetSideEmpire.Value): Unit = { def loseOwnership(obj: Deployable, toFaction: PlanetSideEmpire.Value): Unit = {
DeployableBehavior.changeOwnership( DeployableBehavior.changeOwnership(
obj, obj,
toOwner = "",
toFaction, toFaction,
DeployableInfo(obj.GUID, Deployable.Icon.apply(obj.Definition.Item), obj.Position, Service.defaultPlayerGUID) DeployableInfo(obj.GUID, Deployable.Icon.apply(obj.Definition.Item), obj.Position, Service.defaultPlayerGUID)
) )
@ -138,18 +138,18 @@ trait DeployableBehavior {
*/ */
def gainOwnership(player: Player, toFaction: PlanetSideEmpire.Value): Unit = { def gainOwnership(player: Player, toFaction: PlanetSideEmpire.Value): Unit = {
val obj = DeployableObject val obj = DeployableObject
obj.AssignOwnership(player)
decay.cancel() decay.cancel()
DeployableBehavior.changeOwnership( DeployableBehavior.changeOwnership(
obj, obj,
player.Name,
toFaction, toFaction,
DeployableInfo(obj.GUID, Deployable.Icon.apply(obj.Definition.Item), obj.Position, player.GUID) DeployableInfo(obj.GUID, Deployable.Icon.apply(obj.Definition.Item), obj.Position, player.GUID)
) )
obj.AssignOwnership(player)
} }
/** /**
* The first stage of the deployable build process, to put the formal process in motion. * The first stage of the deployable build process, to put the formal process in motion.
* Deployables, upon construction, may display an animation effect.
* Parameters are required to be passed onto the next stage of the build process and are not used here. * Parameters are required to be passed onto the next stage of the build process and are not used here.
* @see `DeployableDefinition.deployAnimation` * @see `DeployableDefinition.deployAnimation`
* @see `DeployableDefinition.DeployTime` * @see `DeployableDefinition.DeployTime`
@ -157,21 +157,9 @@ trait DeployableBehavior {
* @param callback an `ActorRef` used for confirming the deployable's completion of the process * @param callback an `ActorRef` used for confirming the deployable's completion of the process
*/ */
def setupDeployable(callback: ActorRef): Unit = { def setupDeployable(callback: ActorRef): Unit = {
import scala.concurrent.ExecutionContext.Implicits.global
val obj = DeployableObject val obj = DeployableObject
constructed = Some(false) constructed = Some(false)
if (obj.Definition.deployAnimation == DeployAnimation.Standard) {
val zone = obj.Zone
zone.LocalEvents ! LocalServiceMessage(
zone.id,
LocalAction.TriggerEffectLocation(
obj.OwnerGuid.getOrElse(Service.defaultPlayerGUID),
"spawn_object_effect",
obj.Position,
obj.Orientation
)
)
}
import scala.concurrent.ExecutionContext.Implicits.global
setup = context.system.scheduler.scheduleOnce( setup = context.system.scheduler.scheduleOnce(
obj.Definition.DeployTime milliseconds, obj.Definition.DeployTime milliseconds,
self, self,
@ -185,7 +173,7 @@ trait DeployableBehavior {
* Nothing dangerous happens if it does not begin to decay, but, because it is not under a player's management, * Nothing dangerous happens if it does not begin to decay, but, because it is not under a player's management,
* the deployable will not properly transition to a decay state for another reason * the deployable will not properly transition to a decay state for another reason
* and can linger in the zone ownerless for as long as it is not destroyed. * and can linger in the zone ownerless for as long as it is not destroyed.
* @see `AvatarAction.DeployItem` * @see `LocalAction.DeployItem`
* @see `DeploymentAction` * @see `DeploymentAction`
* @see `DeployableInfo` * @see `DeployableInfo`
* @see `LocalAction.DeployableMapIcon` * @see `LocalAction.DeployableMapIcon`
@ -197,27 +185,22 @@ trait DeployableBehavior {
setup = Default.Cancellable setup = Default.Cancellable
constructed = Some(true) constructed = Some(true)
val obj = DeployableObject val obj = DeployableObject
val zone = obj.Zone val zone = obj.Zone
val localEvents = zone.LocalEvents val localEvents = zone.LocalEvents
val owner = obj.OwnerGuid.getOrElse(Service.defaultPlayerGUID) obj.OwnerName.orElse {
obj.OwnerName match { import scala.concurrent.ExecutionContext.Implicits.global
case Some(_) => decay = context.system.scheduler.scheduleOnce(Deployable.decay, self, Deployable.Deconstruct())
case None => None
import scala.concurrent.ExecutionContext.Implicits.global
decay = context.system.scheduler.scheduleOnce(
Deployable.decay,
self,
Deployable.Deconstruct()
)
} }
//zone build //zone build
zone.AvatarEvents ! AvatarServiceMessage(zone.id, AvatarAction.DeployItem(Service.defaultPlayerGUID, obj)) localEvents ! LocalServiceMessage(zone.id, LocalAction.DeployItem(obj))
//zone map icon //zone map icon
localEvents ! LocalServiceMessage( localEvents ! LocalServiceMessage(
obj.Faction.toString, obj.Faction.toString,
LocalAction.DeployableMapIcon( LocalAction.DeployableMapIcon(
Service.defaultPlayerGUID, Service.defaultPlayerGUID,
DeploymentAction.Build, DeployableInfo(obj.GUID, Deployable.Icon(obj.Definition.Item), obj.Position, owner) DeploymentAction.Build,
DeployableInfo(obj.GUID, Deployable.Icon(obj.Definition.Item), obj.Position, obj.OwnerGuid.getOrElse(Service.defaultPlayerGUID))
) )
) )
//local build management //local build management
@ -290,27 +273,44 @@ object DeployableBehavior {
* @param toFaction na * @param toFaction na
* @param info na * @param info na
*/ */
def changeOwnership(obj: Deployable, toFaction: PlanetSideEmpire.Value, info: DeployableInfo): Unit = { def changeOwnership(obj: Deployable, toOwner: String, toFaction: PlanetSideEmpire.Value, info: DeployableInfo): Unit = {
val dGuid = obj.GUID
val originalFaction = obj.Faction val originalFaction = obj.Faction
val zone = obj.Zone val zone = obj.Zone
val localEvents = zone.LocalEvents val localEvents = zone.LocalEvents
val ownershipAction = {
val owner = info.player_guid
LocalAction.SendPlanetsideAttributeMessage(
owner,
owner,
PlanetsideAttributeEnum.OwnershipAssignment,
dGuid.guid.toLong
)
}
if (originalFaction != toFaction) { if (originalFaction != toFaction) {
obj.Faction = toFaction obj.Faction = toFaction
//visual tells in regards to ownership by faction //visual tells in regards to ownership by faction
zone.AvatarEvents ! AvatarServiceMessage( zone.AvatarEvents ! AvatarServiceMessage(
zone.id, zone.id,
AvatarAction.SetEmpire(Service.defaultPlayerGUID, obj.GUID, toFaction) AvatarAction.SetEmpire(Service.defaultPlayerGUID, dGuid, toFaction)
) )
//remove knowledge by the previous owner's faction //remove knowledge by the previous owner's faction
localEvents ! LocalServiceMessage( localEvents ! LocalServiceMessage(
originalFaction.toString, originalFaction.toString,
LocalAction.DeployableMapIcon(Service.defaultPlayerGUID, DeploymentAction.Dismiss, info) LocalAction.DeployableMapIcon(Service.defaultPlayerGUID, DeploymentAction.Dismiss, info)
) )
} else {
//old owner no longer owner
obj.OwnerName.collect { case fromOwner if !fromOwner.equals(toOwner) =>
localEvents ! LocalServiceMessage(fromOwner, ownershipAction)
}
} }
//display to the given faction //display to the given faction
localEvents ! LocalServiceMessage( localEvents ! LocalServiceMessage(
toFaction.toString, toFaction.toString,
LocalAction.DeployableMapIcon(Service.defaultPlayerGUID, DeploymentAction.Build, info) LocalAction.DeployableMapIcon(Service.defaultPlayerGUID, DeploymentAction.Build, info)
) )
//new owner is owner
localEvents ! LocalServiceMessage(toOwner, ownershipAction)
} }
} }

View file

@ -1,10 +1,12 @@
// Copyright (c) 2016 PSForever.net to present // Copyright (c) 2016 PSForever.net to present
package net.psforever.packet.game package net.psforever.packet.game
import net.psforever.packet.GamePacketOpcode.Type
import net.psforever.packet.game.PlanetsideAttributeEnum.PlanetsideAttributeEnum import net.psforever.packet.game.PlanetsideAttributeEnum.PlanetsideAttributeEnum
import net.psforever.packet.{GamePacketOpcode, Marshallable, PlanetSideGamePacket} import net.psforever.packet.{GamePacketOpcode, Marshallable, PlanetSideGamePacket}
import net.psforever.types.PlanetSideGUID import net.psforever.types.PlanetSideGUID
import scodec.Codec import scodec.bits.BitVector
import scodec.{Attempt, Codec}
import scodec.codecs._ import scodec.codecs._
/** /**
@ -68,8 +70,8 @@ import scodec.codecs._
* `17 - BEP. Value seems to be the same as BattleExperienceMessage`<br> * `17 - BEP. Value seems to be the same as BattleExperienceMessage`<br>
* `18 - CEP.`<br> * `18 - CEP.`<br>
* `19 - Anchors. Value is 0 to disengage, 1 to engage.`<br> * `19 - Anchors. Value is 0 to disengage, 1 to engage.`<br>
* `20 - Control console hacking, affects CC timer, yellow base warning lights and message "The FactionName has hacked into BaseName". * `20 - Control console hacking, affects CC timer, yellow base warning lights and message "The FactionName has hacked into BaseName".`
* Format is: Time left - 2 bytes, faction - 1 byte (1-4), isResecured - 1 byte (0-1)`<br> * Format is: Time left - 2 bytes, faction - 1 byte (1-4), isResecured - 1 byte (0-1)<br>
* <ul> * <ul>
* <li>65535 segments per faction in deciseconds (seconds * 10)</li> * <li>65535 segments per faction in deciseconds (seconds * 10)</li>
* <li>0-65535 = Neutral 0 seconds to 1h 49m 14s - 0x0000 to 0xFFFF</li> * <li>0-65535 = Neutral 0 seconds to 1h 49m 14s - 0x0000 to 0xFFFF</li>
@ -134,8 +136,8 @@ import scodec.codecs._
* `31 - Looking for Squad info (marquee and ui):`<br> * `31 - Looking for Squad info (marquee and ui):`<br>
* <ul> * <ul>
* <li>0 - LFS</li> * <li>0 - LFS</li>
* <li>1 is LFSM (Looking for Squad Members)`</li> * <li>1 is LFSM (Looking for Squad Members)</li>
* <li>`n` is the supplemental squad identifier number; same as "LFS;" for the leader, sets "LFSM" after the first manual flagging`</li> * <li>`n` is the supplemental squad identifier number; same as "LFS;" for the leader, sets "LFSM" after the first manual flagging</li>
* </ul> * </ul>
* `32 - Maintain the squad role index, when a member of a squad`<br> * `32 - Maintain the squad role index, when a member of a squad`<br>
* `35 - Battle Rank`<br> * `35 - Battle Rank`<br>
@ -204,8 +206,8 @@ import scodec.codecs._
final case class PlanetsideAttributeMessage(guid: PlanetSideGUID, attribute_type: Int, attribute_value: Long) final case class PlanetsideAttributeMessage(guid: PlanetSideGUID, attribute_type: Int, attribute_value: Long)
extends PlanetSideGamePacket { extends PlanetSideGamePacket {
type Packet = PlanetsideAttributeMessage type Packet = PlanetsideAttributeMessage
def opcode = GamePacketOpcode.PlanetsideAttributeMessage def opcode: Type = GamePacketOpcode.PlanetsideAttributeMessage
def encode = PlanetsideAttributeMessage.encode(this) def encode: Attempt[BitVector] = PlanetsideAttributeMessage.encode(this)
} }
object PlanetsideAttributeMessage extends Marshallable[PlanetsideAttributeMessage] { object PlanetsideAttributeMessage extends Marshallable[PlanetsideAttributeMessage] {
@ -235,5 +237,6 @@ object PlanetsideAttributeMessage extends Marshallable[PlanetsideAttributeMessag
object PlanetsideAttributeEnum extends Enumeration { object PlanetsideAttributeEnum extends Enumeration {
type PlanetsideAttributeEnum = Value type PlanetsideAttributeEnum = Value
val ControlConsoleHackUpdate = Value(20) val ControlConsoleHackUpdate: PlanetsideAttributeEnum.Value = Value(20)
val OwnershipAssignment: PlanetsideAttributeEnum.Value = Value(21)
} }

View file

@ -87,17 +87,6 @@ class AvatarService(zone: Zone) extends Actor {
AvatarResponse.EnvironmentalDamage(player_guid, source_guid, amount) AvatarResponse.EnvironmentalDamage(player_guid, source_guid, amount)
) )
) )
case AvatarAction.DeployItem(player_guid, item) =>
val definition = item.Definition
val objectData = definition.Packet.ConstructorData(item).get
AvatarEvents.publish(
AvatarServiceResponse(
s"/$forChannel/Avatar",
player_guid,
AvatarResponse.DropItem(ObjectCreateMessage(definition.ObjectId, item.GUID, objectData))
)
)
case AvatarAction.Destroy(victim, killer, weapon, pos) => case AvatarAction.Destroy(victim, killer, weapon, pos) =>
AvatarEvents.publish( AvatarEvents.publish(
AvatarServiceResponse(s"/$forChannel/Avatar", victim, AvatarResponse.Destroy(victim, killer, weapon, pos)) AvatarServiceResponse(s"/$forChannel/Avatar", victim, AvatarResponse.Destroy(victim, killer, weapon, pos))

View file

@ -4,7 +4,6 @@ package net.psforever.services.avatar
import net.psforever.objects.Player import net.psforever.objects.Player
import net.psforever.objects.avatar.scoring.KDAStat import net.psforever.objects.avatar.scoring.KDAStat
import net.psforever.objects.ballistics.Projectile import net.psforever.objects.ballistics.Projectile
import net.psforever.objects.ce.Deployable
import net.psforever.objects.equipment.Equipment import net.psforever.objects.equipment.Equipment
import net.psforever.objects.inventory.InventoryItem import net.psforever.objects.inventory.InventoryItem
import net.psforever.objects.serverobject.environment.interaction.common.Watery.OxygenStateTarget import net.psforever.objects.serverobject.environment.interaction.common.Watery.OxygenStateTarget
@ -44,7 +43,6 @@ object AvatarAction {
final case class ConcealPlayer(player_guid: PlanetSideGUID) extends Action final case class ConcealPlayer(player_guid: PlanetSideGUID) extends Action
final case class EnvironmentalDamage(player_guid: PlanetSideGUID, source_guid: PlanetSideGUID, amount: Int) final case class EnvironmentalDamage(player_guid: PlanetSideGUID, source_guid: PlanetSideGUID, amount: Int)
extends Action extends Action
final case class DeployItem(player_guid: PlanetSideGUID, item: Deployable) extends Action
final case class DeactivateImplantSlot(player_guid: PlanetSideGUID, slot: Int) extends Action final case class DeactivateImplantSlot(player_guid: PlanetSideGUID, slot: Int) extends Action
final case class ActivateImplantSlot(player_guid: PlanetSideGUID, slot: Int) extends Action final case class ActivateImplantSlot(player_guid: PlanetSideGUID, slot: Int) extends Action
final case class Destroy(victim: PlanetSideGUID, killer: PlanetSideGUID, weapon: PlanetSideGUID, pos: Vector3) final case class Destroy(victim: PlanetSideGUID, killer: PlanetSideGUID, weapon: PlanetSideGUID, pos: Vector3)

View file

@ -4,7 +4,7 @@ package net.psforever.services.local
import akka.actor.{Actor, Props} import akka.actor.{Actor, Props}
import net.psforever.objects.serverobject.terminals.Terminal import net.psforever.objects.serverobject.terminals.Terminal
import net.psforever.objects.zones.Zone import net.psforever.objects.zones.Zone
import net.psforever.packet.game.{TriggeredEffect, TriggeredEffectLocation} import net.psforever.packet.game.{ObjectCreateMessage, TriggeredEffect, TriggeredEffectLocation}
import net.psforever.services.local.support.CaptureFlagManager import net.psforever.services.local.support.CaptureFlagManager
import net.psforever.types.PlanetSideGUID import net.psforever.types.PlanetSideGUID
import net.psforever.services.local.support._ import net.psforever.services.local.support._
@ -45,6 +45,16 @@ class LocalService(zone: Zone) extends Actor {
case LocalServiceMessage(forChannel, action) => case LocalServiceMessage(forChannel, action) =>
action match { action match {
case LocalAction.DeployItem(item) =>
val definition = item.Definition
val objectData = definition.Packet.ConstructorData(item).get
LocalEvents.publish(
LocalServiceResponse(
s"/$forChannel/Local",
Service.defaultPlayerGUID,
LocalResponse.SendResponse(ObjectCreateMessage(definition.ObjectId, item.GUID, objectData))
)
)
case LocalAction.DeployableMapIcon(player_guid, behavior, deployInfo) => case LocalAction.DeployableMapIcon(player_guid, behavior, deployInfo) =>
LocalEvents.publish( LocalEvents.publish(
LocalServiceResponse( LocalServiceResponse(

View file

@ -27,6 +27,7 @@ object LocalServiceMessage {
object LocalAction { object LocalAction {
trait Action trait Action
final case class DeployItem(item: Deployable) extends Action
final case class DeployableMapIcon( final case class DeployableMapIcon(
player_guid: PlanetSideGUID, player_guid: PlanetSideGUID,
behavior: DeploymentAction.Value, behavior: DeploymentAction.Value,

View file

@ -57,7 +57,7 @@ class DeployableBehaviorSetupTest extends ActorTest {
case _ => assert(false, "self-setup test - no spawn fx") case _ => assert(false, "self-setup test - no spawn fx")
} }
eventsMsgs(1) match { eventsMsgs(1) match {
case AvatarServiceMessage("test", AvatarAction.DeployItem(PlanetSideGUID(0), obj)) => case LocalServiceMessage("test", LocalAction.DeployItem(obj)) =>
assert(obj eq jmine, "self-setup test - not same mine") assert(obj eq jmine, "self-setup test - not same mine")
case _ => case _ =>
assert( false, "self-setup test - wrong deploy message") assert( false, "self-setup test - wrong deploy message")
@ -189,7 +189,7 @@ class DeployableBehaviorSetupOwnedP2Test extends FreedContextActorTest {
case _ => assert(false, "owned setup test, 2 - no spawn fx") case _ => assert(false, "owned setup test, 2 - no spawn fx")
} }
eventsMsgs(3) match { eventsMsgs(3) match {
case AvatarServiceMessage("test", AvatarAction.DeployItem(PlanetSideGUID(0), obj)) => case LocalServiceMessage("test", LocalAction.DeployItem(obj)) =>
assert(obj eq jmine, "owned setup test, 2 - not same mine") assert(obj eq jmine, "owned setup test, 2 - not same mine")
case _ => case _ =>
assert( false, "owned setup test, 2 - wrong deploy message") assert( false, "owned setup test, 2 - wrong deploy message")

View file

@ -48,7 +48,7 @@ class TelepadDeployableNoRouterTest extends ActorTest {
val eventsMsgs = eventsProbe.receiveN(4, 10.seconds) val eventsMsgs = eventsProbe.receiveN(4, 10.seconds)
eventsMsgs.head match { eventsMsgs.head match {
case AvatarServiceMessage("test", AvatarAction.DeployItem(PlanetSideGUID(0), obj)) => case LocalServiceMessage("test", LocalAction.DeployItem(obj)) =>
assert(obj eq telepad, "no-router telepad deployable testt - not same telepad") assert(obj eq telepad, "no-router telepad deployable testt - not same telepad")
case _ => case _ =>
assert( false, "no-router telepad deployable test - wrong deploy message") assert( false, "no-router telepad deployable test - wrong deploy message")
@ -117,7 +117,7 @@ class TelepadDeployableNoActivationTest extends ActorTest {
val eventsMsgs = eventsProbe.receiveN(4, 10.seconds) val eventsMsgs = eventsProbe.receiveN(4, 10.seconds)
eventsMsgs.head match { eventsMsgs.head match {
case AvatarServiceMessage("test", AvatarAction.DeployItem(PlanetSideGUID(0), obj)) => case LocalServiceMessage("test", LocalAction.DeployItem(obj)) =>
assert(obj eq telepad, "no-activate telepad deployable testt - not same telepad") assert(obj eq telepad, "no-activate telepad deployable testt - not same telepad")
case _ => case _ =>
assert( false, "no-activate telepad deployable test - wrong deploy message") assert( false, "no-activate telepad deployable test - wrong deploy message")
@ -190,7 +190,7 @@ class TelepadDeployableAttemptTest extends ActorTest {
val eventsMsgs = eventsProbe.receiveN(2, 10.seconds) val eventsMsgs = eventsProbe.receiveN(2, 10.seconds)
val routerMsgs = routerProbe.receiveN(1, 10.seconds) val routerMsgs = routerProbe.receiveN(1, 10.seconds)
eventsMsgs.head match { eventsMsgs.head match {
case AvatarServiceMessage("test", AvatarAction.DeployItem(PlanetSideGUID(0), obj)) => case LocalServiceMessage("test", LocalAction.DeployItem(obj)) =>
assert(obj eq telepad, "link attempt telepad deployable testt - not same telepad") assert(obj eq telepad, "link attempt telepad deployable testt - not same telepad")
case _ => case _ =>
assert( false, "link attempt telepad deployable test - wrong deploy message") assert( false, "link attempt telepad deployable test - wrong deploy message")
@ -263,7 +263,7 @@ class TelepadDeployableResponseFromRouterTest extends FreedContextActorTest {
val eventsMsgs = eventsProbe.receiveN(9, 10.seconds) val eventsMsgs = eventsProbe.receiveN(9, 10.seconds)
eventsMsgs.head match { eventsMsgs.head match {
case AvatarServiceMessage("test", AvatarAction.DeployItem(PlanetSideGUID(0), obj)) => case LocalServiceMessage("test", LocalAction.DeployItem(obj)) =>
assert(obj eq telepad, "link to router test - not same telepad") assert(obj eq telepad, "link to router test - not same telepad")
case _ => case _ =>
assert( false, "link to router test - wrong deploy message") assert( false, "link to router test - wrong deploy message")

View file

@ -78,6 +78,31 @@ class LocalService5Test extends ActorTest {
} }
} }
class DeployItemTest extends ActorTest {
ServiceManager.boot(system)
val service = system.actorOf(Props(classOf[LocalService], Zone.Nowhere), "deploy-item-test-service")
val objDef = GlobalDefinitions.motionalarmsensor
val obj = new SensorDeployable(objDef)
obj.Position = Vector3(1, 2, 3)
obj.Orientation = Vector3(4, 5, 6)
obj.GUID = PlanetSideGUID(40)
val pkt = ObjectCreateMessage(
objDef.ObjectId,
obj.GUID,
objDef.Packet.ConstructorData(obj).get
)
"AvatarService" should {
"pass DeployItem" in {
service ! Service.Join("test")
service ! LocalServiceMessage("test", LocalAction.DeployItem(obj))
expectMsg(LocalServiceResponse("/test/Local", PlanetSideGUID(0), LocalResponse.SendResponse(pkt)))
}
}
}
class DeployableMapIconTest extends ActorTest { class DeployableMapIconTest extends ActorTest {
ServiceManager.boot(system) ServiceManager.boot(system)