mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-03-06 05:50:23 +00:00
unified code paths for dropping an item, and reinforced code path for picking an item back up; LocalService will handle some of the work now; ActionResultMessage embraces its simplistic nature (we don't have enough error messages)
This commit is contained in:
parent
fdf05337fd
commit
f6f7ad5617
12 changed files with 192 additions and 126 deletions
|
|
@ -386,27 +386,15 @@ object Zone {
|
|||
final case class NoValidSpawnPoint(zone_number : Int, spawn_group : Option[Int])
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
object Ground {
|
||||
final case class DropItem(item : Equipment, pos : Vector3, orient : Vector3)
|
||||
final case class ItemOnGround(item : Equipment, pos : Vector3, orient : Vector3)
|
||||
final case class CanNotDropItem(item : Equipment)
|
||||
|
||||
/**
|
||||
* 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)
|
||||
final case class PickupItem(item_guid : PlanetSideGUID)
|
||||
final case class ItemInHand(item : Equipment)
|
||||
final case class CanNotPickupItem(item_guid : PlanetSideGUID)
|
||||
}
|
||||
|
||||
object Vehicle {
|
||||
final case class Spawn(vehicle : Vehicle)
|
||||
|
|
|
|||
|
|
@ -50,10 +50,10 @@ class ZoneActor(zone : Zone) extends Actor {
|
|||
zone.Population forward msg
|
||||
|
||||
//frwd to Ground Actor
|
||||
case msg @ Zone.DropItemOnGround =>
|
||||
case msg @ Zone.Ground.DropItem =>
|
||||
zone.Ground forward msg
|
||||
|
||||
case msg @ Zone.GetItemOnGround =>
|
||||
case msg @ Zone.Ground.PickupItem =>
|
||||
zone.Ground forward msg
|
||||
|
||||
//frwd to Vehicle Actor
|
||||
|
|
|
|||
|
|
@ -16,18 +16,22 @@ class ZoneGroundActor(equipmentOnGround : ListBuffer[Equipment]) extends Actor {
|
|||
//private[this] val log = org.log4s.getLogger
|
||||
|
||||
def receive : Receive = {
|
||||
case Zone.DropItemOnGround(item, pos, orient) =>
|
||||
item.Position = pos
|
||||
item.Orientation = orient
|
||||
equipmentOnGround += item
|
||||
|
||||
case Zone.GetItemOnGround(player, item_guid) =>
|
||||
FindItemOnGround(item_guid) match {
|
||||
case Some(item) =>
|
||||
sender ! Zone.ItemFromGround(player, item)
|
||||
case Zone.Ground.DropItem(item, pos, orient) =>
|
||||
sender ! (FindItemOnGround(item.GUID) match {
|
||||
case None =>
|
||||
org.log4s.getLogger.warn(s"item on ground $item_guid was requested by $player for pickup but was not found")
|
||||
}
|
||||
equipmentOnGround += item
|
||||
Zone.Ground.ItemOnGround(item, pos, orient)
|
||||
case Some(_) =>
|
||||
Zone.Ground.CanNotDropItem(item)
|
||||
})
|
||||
|
||||
case Zone.Ground.PickupItem(item_guid) =>
|
||||
sender ! (FindItemOnGround(item_guid) match {
|
||||
case Some(item) =>
|
||||
Zone.Ground.ItemInHand(item)
|
||||
case None =>
|
||||
Zone.Ground.CanNotPickupItem(item_guid)
|
||||
})
|
||||
|
||||
case _ => ;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,13 +19,18 @@ final case class ActionResultMessage(successful : Boolean,
|
|||
}
|
||||
|
||||
object ActionResultMessage extends Marshallable[ActionResultMessage] {
|
||||
def apply() : ActionResultMessage = {
|
||||
ActionResultMessage(true, None)
|
||||
}
|
||||
/**
|
||||
* A message where the result is always a pass.
|
||||
* @return an `ActionResultMessage` object
|
||||
*/
|
||||
def Pass : ActionResultMessage = ActionResultMessage(true, None)
|
||||
|
||||
def apply(error : Long) : ActionResultMessage = {
|
||||
ActionResultMessage(false, Some(error))
|
||||
}
|
||||
/**
|
||||
* A message where the result is always a failure.
|
||||
* @param error the error code
|
||||
* @return an `ActionResultMessage` object
|
||||
*/
|
||||
def Fail(error : Long) : ActionResultMessage = ActionResultMessage(false, Some(error))
|
||||
|
||||
implicit val codec : Codec[ActionResultMessage] = (
|
||||
("successful" | bool) >>:~ { res =>
|
||||
|
|
|
|||
|
|
@ -40,6 +40,14 @@ final case class ObjectDetachMessage(parent_guid : PlanetSideGUID,
|
|||
}
|
||||
|
||||
object ObjectDetachMessage extends Marshallable[ObjectDetachMessage] {
|
||||
def apply(parent_guid : PlanetSideGUID, child_guid : PlanetSideGUID, pos : Vector3, orient : Vector3) : ObjectDetachMessage = {
|
||||
ObjectDetachMessage(parent_guid, child_guid, pos, orient.x, orient.y, orient.z)
|
||||
}
|
||||
|
||||
def apply(parent_guid : PlanetSideGUID, child_guid : PlanetSideGUID, pos : Vector3, orient_z : Float) : ObjectDetachMessage = {
|
||||
ObjectDetachMessage(parent_guid, child_guid, pos, 0, 0, orient_z)
|
||||
}
|
||||
|
||||
implicit val codec : Codec[ObjectDetachMessage] = (
|
||||
("parent_guid" | PlanetSideGUID.codec) ::
|
||||
("child_guid" | PlanetSideGUID.codec) ::
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ class ActionResultMessageTest extends Specification {
|
|||
}
|
||||
|
||||
"encode (pass, minimal)" in {
|
||||
val msg = ActionResultMessage()
|
||||
val msg = ActionResultMessage.Pass
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_pass
|
||||
|
|
@ -52,7 +52,7 @@ class ActionResultMessageTest extends Specification {
|
|||
}
|
||||
|
||||
"encode (fail, minimal)" in {
|
||||
val msg = ActionResultMessage(1)
|
||||
val msg = ActionResultMessage.Fail(1)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_fail
|
||||
|
|
|
|||
|
|
@ -26,10 +26,24 @@ class ObjectDetachMessageTest extends Specification {
|
|||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
"encode (1)" in {
|
||||
val msg = ObjectDetachMessage(PlanetSideGUID(2916), PlanetSideGUID(2502), Vector3(3567.1406f, 2988.0078f, 71.84375f), 0f, 0f, 270f)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
|
||||
"encode (2)" in {
|
||||
val msg = ObjectDetachMessage(PlanetSideGUID(2916), PlanetSideGUID(2502), Vector3(3567.1406f, 2988.0078f, 71.84375f), Vector3(0f, 0f, 270f))
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
|
||||
"encode (3)" in {
|
||||
val msg = ObjectDetachMessage(PlanetSideGUID(2916), PlanetSideGUID(2502), Vector3(3567.1406f, 2988.0078f, 71.84375f), 270f)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -477,7 +477,7 @@ class ZoneGroundTest extends ActorTest {
|
|||
assert(zone.EquipmentOnGround.isEmpty)
|
||||
assert(item.Position == Vector3.Zero)
|
||||
assert(item.Orientation == Vector3.Zero)
|
||||
zone.Ground ! Zone.DropItemOnGround(item, Vector3(1.1f, 2.2f, 3.3f), Vector3(4.4f, 5.5f, 6.6f))
|
||||
zone.Ground ! Zone.Ground.DropItem(item, Vector3(1.1f, 2.2f, 3.3f), Vector3(4.4f, 5.5f, 6.6f))
|
||||
expectNoMsg(Duration.create(100, "ms"))
|
||||
|
||||
assert(zone.EquipmentOnGround == List(item))
|
||||
|
|
@ -490,17 +490,16 @@ class ZoneGroundTest extends ActorTest {
|
|||
val player = Player(Avatar("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, 5))
|
||||
system.actorOf(Props(classOf[ZoneTest.ZoneInitActor], zone), "get-item-test-good") ! "!"
|
||||
receiveOne(Duration.create(200, "ms")) //consume
|
||||
zone.Ground ! Zone.DropItemOnGround(item, Vector3.Zero, Vector3.Zero)
|
||||
zone.Ground ! Zone.Ground.DropItem(item, Vector3.Zero, Vector3.Zero)
|
||||
expectNoMsg(Duration.create(100, "ms"))
|
||||
|
||||
assert(zone.EquipmentOnGround == List(item))
|
||||
zone.Ground ! Zone.GetItemOnGround(player, PlanetSideGUID(10))
|
||||
zone.Ground ! Zone.Ground.PickupItem(PlanetSideGUID(10))
|
||||
val reply = receiveOne(Duration.create(100, "ms"))
|
||||
|
||||
assert(zone.EquipmentOnGround.isEmpty)
|
||||
assert(reply.isInstanceOf[Zone.ItemFromGround])
|
||||
assert(reply.asInstanceOf[Zone.ItemFromGround].player == player)
|
||||
assert(reply.asInstanceOf[Zone.ItemFromGround].item == item)
|
||||
assert(reply.isInstanceOf[Zone.Ground.ItemInHand])
|
||||
assert(reply.asInstanceOf[Zone.Ground.ItemInHand].item == item)
|
||||
}
|
||||
|
||||
"get item from ground (failure)" in {
|
||||
|
|
@ -508,11 +507,11 @@ class ZoneGroundTest extends ActorTest {
|
|||
val player = Player(Avatar("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, 5))
|
||||
system.actorOf(Props(classOf[ZoneTest.ZoneInitActor], zone), "get-item-test-fail") ! "!"
|
||||
receiveOne(Duration.create(200, "ms")) //consume
|
||||
zone.Ground ! Zone.DropItemOnGround(item, Vector3.Zero, Vector3.Zero)
|
||||
zone.Ground ! Zone.Ground.DropItem(item, Vector3.Zero, Vector3.Zero)
|
||||
expectNoMsg(Duration.create(100, "ms"))
|
||||
|
||||
assert(zone.EquipmentOnGround == List(item))
|
||||
zone.Ground ! Zone.GetItemOnGround(player, PlanetSideGUID(11)) //wrong guid
|
||||
zone.Ground ! Zone.Ground.PickupItem(PlanetSideGUID(11)) //wrong guid
|
||||
expectNoMsg(Duration.create(500, "ms"))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -255,7 +255,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
|
||||
case AvatarResponse.ChangeAmmo(weapon_guid, weapon_slot, previous_guid, ammo_id, ammo_guid, ammo_data) =>
|
||||
if(tplayer_guid != guid) {
|
||||
sendResponse(ObjectDetachMessage(weapon_guid, previous_guid, Vector3(0,0,0), 0f, 0f, 0f))
|
||||
sendResponse(ObjectDetachMessage(weapon_guid, previous_guid, Vector3.Zero, 0))
|
||||
sendResponse(
|
||||
ObjectCreateMessage(
|
||||
ammo_id,
|
||||
|
|
@ -405,7 +405,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
}
|
||||
|
||||
case LocalServiceResponse(_, guid, reply) =>
|
||||
val tplayer_guid = if(player.HasGUID) { player.GUID} else { PlanetSideGUID(0) }
|
||||
val tplayer_guid = if(player.HasGUID) { player.GUID} else { PlanetSideGUID(-1) }
|
||||
reply match {
|
||||
case LocalResponse.DoorOpens(door_guid) =>
|
||||
if(tplayer_guid != guid) {
|
||||
|
|
@ -415,16 +415,21 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
case LocalResponse.DoorCloses(door_guid) => //door closes for everyone
|
||||
sendResponse(GenericObjectStateMsg(door_guid, 17))
|
||||
|
||||
case LocalResponse.DropItem(id, item_guid, data) =>
|
||||
if(tplayer_guid != guid) {
|
||||
sendResponse(ObjectCreateMessage(id, item_guid, data))
|
||||
}
|
||||
|
||||
case LocalResponse.HackClear(target_guid, unk1, unk2) =>
|
||||
sendResponse(HackMessage(0, target_guid, guid, 0, unk1, HackState.HackCleared, unk2))
|
||||
|
||||
case LocalResponse.HackObject(target_guid, unk1, unk2) =>
|
||||
if(player.GUID != guid) {
|
||||
if(tplayer_guid != guid) {
|
||||
sendResponse(HackMessage(0, target_guid, guid, 100, unk1, HackState.Hacked, unk2))
|
||||
}
|
||||
|
||||
case LocalResponse.ProximityTerminalEffect(object_guid, effectState) =>
|
||||
if(player.GUID != guid) {
|
||||
if(tplayer_guid != guid) {
|
||||
sendResponse(ProximityTerminalUseMessage(PlanetSideGUID(0), object_guid, effectState))
|
||||
}
|
||||
|
||||
|
|
@ -465,7 +470,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
}
|
||||
|
||||
case VehicleResponse.DetachFromRails(vehicle_guid, pad_guid, pad_position, pad_orientation_z) =>
|
||||
sendResponse(ObjectDetachMessage(pad_guid, vehicle_guid, pad_position + Vector3(0,0,0.5f), 0, 0, pad_orientation_z))
|
||||
sendResponse(ObjectDetachMessage(pad_guid, vehicle_guid, pad_position + Vector3(0,0,0.5f), pad_orientation_z))
|
||||
|
||||
case VehicleResponse.InventoryState(obj, parent_guid, start, con_data) =>
|
||||
if(tplayer_guid != guid) {
|
||||
|
|
@ -844,12 +849,10 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
})
|
||||
//drop items on ground
|
||||
val pos = tplayer.Position
|
||||
val orient = tplayer.Orientation
|
||||
val orient = Vector3(0,0, tplayer.Orientation.z)
|
||||
((dropHolsters ++ dropInventory).map(_.obj) ++ drop).foreach(obj => {
|
||||
continent.Ground ! Zone.DropItemOnGround(obj, pos, Vector3(0f, 0f, orient.z))
|
||||
sendResponse(ObjectDetachMessage(tplayer.GUID, obj.GUID, pos, 0f, 0f, orient.z))
|
||||
val objDef = obj.Definition
|
||||
avatarService ! AvatarServiceMessage(tplayer.Continent, AvatarAction.EquipmentOnGround(tplayer.GUID, pos, orient, objDef.ObjectId, obj.GUID, objDef.Packet.ConstructorData(obj).get))
|
||||
//TODO make a sound when dropping stuff
|
||||
continent.Ground ! Zone.Ground.DropItem(obj, pos, orient)
|
||||
})
|
||||
sendResponse(ItemTransactionResultMessage (msg.terminal_guid, TransactionType.Buy, true))
|
||||
}
|
||||
|
|
@ -938,12 +941,9 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
})
|
||||
//drop stuff on ground
|
||||
val pos = tplayer.Position
|
||||
val orient = tplayer.Orientation
|
||||
val orient = Vector3(0,0, tplayer.Orientation.z)
|
||||
((dropHolsters ++ dropInventory).map(_.obj)).foreach(obj => {
|
||||
continent.Ground ! Zone.DropItemOnGround(obj, pos, Vector3(0f, 0f, orient.z))
|
||||
sendResponse(ObjectDetachMessage(tplayer.GUID, obj.GUID, pos, 0f, 0f, orient.z))
|
||||
val objDef = obj.Definition
|
||||
avatarService ! AvatarServiceMessage(tplayer.Continent, AvatarAction.EquipmentOnGround(tplayer.GUID, pos, orient, objDef.ObjectId, obj.GUID, objDef.Packet.ConstructorData(obj).get))
|
||||
continent.Ground ! Zone.Ground.DropItem(obj, pos, orient)
|
||||
})
|
||||
|
||||
case Terminal.VehicleLoadout(definition, weapons, inventory) =>
|
||||
|
|
@ -1177,7 +1177,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
case VehicleSpawnPad.ServerVehicleOverrideStart(vehicle, pad) =>
|
||||
val vdef = vehicle.Definition
|
||||
if(vehicle.Seats(0).isOccupied) {
|
||||
sendResponse(ObjectDetachMessage(pad.GUID, vehicle.GUID, pad.Position + Vector3(0, 0, 0.5f), 0, 0, pad.Orientation.z))
|
||||
sendResponse(ObjectDetachMessage(pad.GUID, vehicle.GUID, pad.Position + Vector3(0, 0, 0.5f), pad.Orientation.z))
|
||||
}
|
||||
ServerVehicleOverride(vehicle, vdef.AutoPilotSpeed1, GlobalDefinitions.isFlightVehicle(vdef):Int)
|
||||
|
||||
|
|
@ -1375,6 +1375,62 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
RequestSanctuaryZoneSpawn(player, zone_number)
|
||||
}
|
||||
|
||||
case Zone.Ground.ItemOnGround(item, pos, orient) =>
|
||||
item.Position = pos
|
||||
item.Orientation = Vector3(0,0, orient.z) //only one kind of rotation is important
|
||||
val exclusionId = player.Find(item) match {
|
||||
case Some(slotNum) =>
|
||||
player.Slot(slotNum).Equipment = None
|
||||
sendResponse(ObjectDetachMessage(player.GUID, item.GUID, pos, orient.z))
|
||||
sendResponse(ActionResultMessage.Pass)
|
||||
player.GUID //we're dropping it; don't need to see it dropped again
|
||||
case None =>
|
||||
PlanetSideGUID(0) //object is being introduced into the world upon drop
|
||||
}
|
||||
localService ! LocalServiceMessage(continent.Id, LocalAction.DropItem(exclusionId, item))
|
||||
|
||||
case Zone.Ground.CanNotDropItem(item) =>
|
||||
log.warn(s"DropItem: $player tried to drop a $item on the ground, but he missed")
|
||||
player.Find(item) match {
|
||||
case None => //item in limbo
|
||||
taskResolver ! GUIDTask.UnregisterEquipment(item)(continent.GUID)
|
||||
case Some(_) => ;
|
||||
}
|
||||
|
||||
case Zone.Ground.ItemInHand(item) =>
|
||||
player.Fit(item) match {
|
||||
case Some(slotNum) =>
|
||||
val item_guid = item.GUID
|
||||
val player_guid = player.GUID
|
||||
player.Slot(slotNum).Equipment = item
|
||||
val definition = item.Definition
|
||||
sendResponse(
|
||||
ObjectCreateDetailedMessage(
|
||||
definition.ObjectId,
|
||||
item_guid,
|
||||
ObjectCreateMessageParent(player_guid, slotNum),
|
||||
definition.Packet.DetailedConstructorData(item).get
|
||||
)
|
||||
)
|
||||
avatarService ! AvatarServiceMessage(continent.Id, if(player.VisibleSlots.contains(slotNum)) {
|
||||
AvatarAction.EquipmentInHand(player_guid, player_guid, slotNum, item)
|
||||
}
|
||||
else {
|
||||
AvatarAction.ObjectDelete(player_guid, item_guid)
|
||||
})
|
||||
sendResponse(ActionResultMessage.Pass)
|
||||
case None =>
|
||||
continent.Ground ! Zone.Ground.DropItem(item, item.Position, item.Orientation) //restore previous state
|
||||
}
|
||||
|
||||
case Zone.Ground.CanNotPickupItem(item_guid) =>
|
||||
continent.GUID(item_guid) match {
|
||||
case Some(item) =>
|
||||
log.warn(s"DropItem: finding a $item on the ground was suggested, but $player can not reach it")
|
||||
case None =>
|
||||
log.warn(s"DropItem: finding an item ($item_guid) on the ground was suggested, but $player can not see it")
|
||||
}
|
||||
|
||||
case InterstellarCluster.ClientInitializationComplete() =>
|
||||
StopBundlingPackets()
|
||||
LivePlayerList.Add(sessionId, avatar)
|
||||
|
|
@ -1467,31 +1523,6 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
//TacticsMessage
|
||||
StopBundlingPackets()
|
||||
|
||||
|
||||
case Zone.ItemFromGround(tplayer, item) =>
|
||||
val obj_guid = item.GUID
|
||||
val player_guid = tplayer.GUID
|
||||
tplayer.Fit(item) match {
|
||||
case Some(slot) =>
|
||||
tplayer.Slot(slot).Equipment = item
|
||||
avatarService ! AvatarServiceMessage(tplayer.Continent, AvatarAction.ObjectDelete(player_guid, obj_guid))
|
||||
val definition = item.Definition
|
||||
sendResponse(
|
||||
ObjectCreateDetailedMessage(
|
||||
definition.ObjectId,
|
||||
obj_guid,
|
||||
ObjectCreateMessageParent(player_guid, slot),
|
||||
definition.Packet.DetailedConstructorData(item).get
|
||||
)
|
||||
)
|
||||
sendResponse(ActionResultMessage())
|
||||
if(tplayer.VisibleSlots.contains(slot)) {
|
||||
avatarService ! AvatarServiceMessage(tplayer.Continent, AvatarAction.EquipmentInHand(player_guid, player_guid, slot, item))
|
||||
}
|
||||
case None =>
|
||||
continent.Ground ! Zone.DropItemOnGround(item, item.Position, item.Orientation) //restore
|
||||
}
|
||||
|
||||
case ItemHacking(tplayer, target, tool_guid, delta, completeAction, tickAction) =>
|
||||
progressBarUpdate.cancel
|
||||
if(progressBarValue.isDefined) {
|
||||
|
|
@ -1607,18 +1638,17 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
import scala.concurrent.ExecutionContext.Implicits.global
|
||||
clientKeepAlive.cancel
|
||||
clientKeepAlive = context.system.scheduler.schedule(0 seconds, 500 milliseconds, self, PokeClient())
|
||||
log.warn(PacketCoding.DecodePacket(hex"d2327e7b8a972b95113881003710").toString)
|
||||
|
||||
case msg @ CharacterCreateRequestMessage(name, head, voice, gender, empire) =>
|
||||
log.info("Handling " + msg)
|
||||
sendResponse(ActionResultMessage(true, None))
|
||||
sendResponse(ActionResultMessage.Pass)
|
||||
self ! ListAccountCharacters
|
||||
|
||||
case msg @ CharacterRequestMessage(charId, action) =>
|
||||
log.info("Handling " + msg)
|
||||
action match {
|
||||
case CharacterRequestAction.Delete =>
|
||||
sendResponse(ActionResultMessage(false, Some(1)))
|
||||
sendResponse(ActionResultMessage.Fail(1))
|
||||
case CharacterRequestAction.Select =>
|
||||
//TODO check if can spawn on last continent/location from player?
|
||||
//TODO if yes, get continent guid accessors
|
||||
|
|
@ -1828,7 +1858,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
import scala.concurrent.duration._
|
||||
import scala.concurrent.ExecutionContext.Implicits.global
|
||||
context.system.scheduler.scheduleOnce(50 milliseconds, self, UnregisterCorpseOnVehicleDisembark(player))
|
||||
//sendResponse(ObjectDetachMessage(vehicle_guid, player.GUID, Vector3.Zero, 0, 0, 0))
|
||||
//sendResponse(ObjectDetachMessage(vehicle_guid, player.GUID, Vector3.Zero, 0))
|
||||
//sendResponse(PlayerStateShiftMessage(ShiftState(1, Vector3.Zero, 0)))
|
||||
}
|
||||
|
||||
|
|
@ -1989,8 +2019,8 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
val tailReloadValue : Int = if(xs.isEmpty) { 0 } else { xs.map(_.obj.asInstanceOf[AmmoBox].Capacity).reduceLeft(_ + _) }
|
||||
val sumReloadValue : Int = originalBoxCapacity + tailReloadValue
|
||||
val previousBox = tool.AmmoSlot.Box //current magazine in tool
|
||||
sendResponse(ObjectDetachMessage(tool.GUID, previousBox.GUID, Vector3(0f, 0f, 0f), 0f, 0f, 0f))
|
||||
sendResponse(ObjectDetachMessage(player.GUID, box.GUID, Vector3(0f, 0f, 0f), 0f, 0f, 0f))
|
||||
sendResponse(ObjectDetachMessage(tool.GUID, previousBox.GUID, Vector3.Zero, 0f))
|
||||
sendResponse(ObjectDetachMessage(player.GUID, box.GUID, Vector3.Zero, 0f))
|
||||
obj.Inventory -= x.start //remove replacement ammo from inventory
|
||||
val ammoSlotIndex = tool.FireMode.AmmoSlotIndex
|
||||
tool.AmmoSlots(ammoSlotIndex).Box = box //put replacement ammo in tool
|
||||
|
|
@ -2158,27 +2188,37 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
sendResponse(EmoteMsg(avatar_guid, emote))
|
||||
|
||||
case msg @ DropItemMessage(item_guid) =>
|
||||
log.info("DropItem: " + msg)
|
||||
player.FreeHand.Equipment match {
|
||||
case Some(item) =>
|
||||
if(item.GUID == item_guid) {
|
||||
val orient : Vector3 = Vector3(0f, 0f, player.Orientation.z)
|
||||
player.FreeHand.Equipment = None
|
||||
continent.Ground ! Zone.DropItemOnGround(item, player.Position, orient)
|
||||
sendResponse(ObjectDetachMessage(player.GUID, item.GUID, player.Position, 0f, 0f, player.Orientation.z))
|
||||
val objDef = item.Definition
|
||||
avatarService ! AvatarServiceMessage(player.Continent, AvatarAction.EquipmentOnGround(player.GUID, player.Position, orient, objDef.ObjectId, item.GUID, objDef.Packet.ConstructorData(item).get))
|
||||
}
|
||||
else {
|
||||
log.warn(s"item in hand was ${item.GUID} but trying to drop $item_guid; nothing will be dropped")
|
||||
log.info(s"DropItem: $msg")
|
||||
continent.GUID(item_guid) match {
|
||||
case Some(item : Equipment) =>
|
||||
player.FreeHand.Equipment match {
|
||||
case Some(_) =>
|
||||
if(item.GUID == item_guid) {
|
||||
continent.Ground ! Zone.Ground.DropItem(item, player.Position, player.Orientation)
|
||||
}
|
||||
case None =>
|
||||
log.warn(s"DropItem: $player wanted to drop a $item, but it wasn't at hand")
|
||||
}
|
||||
case Some(obj) => //TODO LLU
|
||||
log.warn(s"DropItem: $player wanted to drop a $obj, but that isn't possible")
|
||||
case None =>
|
||||
log.error(s"$player wanted to drop an item, but it was not in hand")
|
||||
log.warn(s"DropItem: $player wanted to drop an item ($item_guid), but it was nowhere to be found")
|
||||
}
|
||||
|
||||
case msg @ PickupItemMessage(item_guid, player_guid, unk1, unk2) =>
|
||||
log.info("PickupItem: " + msg)
|
||||
continent.Ground ! Zone.GetItemOnGround(player, item_guid)
|
||||
log.info(s"PickupItem: $msg")
|
||||
continent.GUID(item_guid) match {
|
||||
case Some(item : Equipment) =>
|
||||
player.Fit(item) match {
|
||||
case Some(_) =>
|
||||
continent.Ground ! Zone.Ground.PickupItem(item_guid)
|
||||
case None => //skip
|
||||
sendResponse(ActionResultMessage.Fail(16)) //error code?
|
||||
}
|
||||
case _ =>
|
||||
log.warn(s"PickupItem: $player requested an item that doesn't exist in this zone; assume client-side garbage data")
|
||||
sendResponse(ObjectDeleteMessage(item_guid, 0))
|
||||
}
|
||||
|
||||
case msg @ ReloadMessage(item_guid, ammo_clip, unk1) =>
|
||||
log.info("Reload: " + msg)
|
||||
|
|
@ -3847,14 +3887,14 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
case Some(InventoryItem(item2, destIndex)) => //yes, swap
|
||||
//cleanly shuffle items around to avoid losing icons
|
||||
//the next ObjectDetachMessage is necessary to avoid icons being lost, but only as part of this swap
|
||||
sendResponse(ObjectDetachMessage(source_guid, item_guid, Vector3.Zero, 0f, 0f, 0f))
|
||||
sendResponse(ObjectDetachMessage(source_guid, item_guid, Vector3.Zero, 0f))
|
||||
val item2_guid = item2.GUID
|
||||
destination.Slot(destIndex).Equipment = None //remove the swap item from destination
|
||||
(indexSlot.Equipment = item2) match {
|
||||
case Some(_) => //item and item2 swapped places successfully
|
||||
log.info(s"MoveItem: $item2 swapped to $source @ $index")
|
||||
//remove item2 from destination
|
||||
sendResponse(ObjectDetachMessage(destination_guid, item2_guid, Vector3.Zero, 0f, 0f, 0f))
|
||||
sendResponse(ObjectDetachMessage(destination_guid, item2_guid, Vector3.Zero, 0f))
|
||||
destination match {
|
||||
case obj : Vehicle =>
|
||||
vehicleService ! VehicleServiceMessage(s"${obj.Actor}", VehicleAction.UnstowEquipment(player_guid, item2_guid))
|
||||
|
|
@ -3897,8 +3937,8 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
val pos = source.Position
|
||||
val sourceOrientZ = source.Orientation.z
|
||||
val orient : Vector3 = Vector3(0f, 0f, sourceOrientZ)
|
||||
continent.Actor ! Zone.DropItemOnGround(item2, pos, orient)
|
||||
sendResponse(ObjectDetachMessage(destination_guid, item2_guid, pos, 0f, 0f, sourceOrientZ)) //ground
|
||||
continent.Ground ! Zone.Ground.DropItem(item2, pos, orient)
|
||||
sendResponse(ObjectDetachMessage(destination_guid, item2_guid, pos, sourceOrientZ)) //ground
|
||||
val objDef = item2.Definition
|
||||
destination match {
|
||||
case obj : Vehicle =>
|
||||
|
|
@ -3956,15 +3996,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
* @param item the item
|
||||
*/
|
||||
def NormalItemDrop(obj : PlanetSideGameObject with Container, zone : Zone, service : ActorRef)(item : Equipment) : Unit = {
|
||||
val itemGUID = item.GUID
|
||||
val ang = obj.Orientation.z
|
||||
val pos = obj.Position
|
||||
val orient = Vector3(0f, 0f, ang)
|
||||
item.Position = pos
|
||||
item.Orientation = orient
|
||||
zone.Ground ! Zone.DropItemOnGround(item, pos, orient)
|
||||
val itemDef = item.Definition
|
||||
service ! AvatarServiceMessage(zone.Id, AvatarAction.EquipmentOnGround(Service.defaultPlayerGUID, pos, orient, itemDef.ObjectId, itemGUID, itemDef.Packet.ConstructorData(item).get))
|
||||
continent.Ground ! Zone.Ground.DropItem(item, obj.Position, Vector3(0f, 0f, obj.Orientation.z))
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package services.local
|
||||
|
||||
import net.psforever.objects.equipment.Equipment
|
||||
import net.psforever.objects.serverobject.PlanetSideServerObject
|
||||
import net.psforever.objects.serverobject.doors.Door
|
||||
import net.psforever.objects.zones.Zone
|
||||
|
|
@ -12,6 +13,7 @@ object LocalAction {
|
|||
|
||||
final case class DoorOpens(player_guid : PlanetSideGUID, continent : Zone, door : Door) extends Action
|
||||
final case class DoorCloses(player_guid : PlanetSideGUID, door_guid : PlanetSideGUID) extends Action
|
||||
final case class DropItem(player_guid : PlanetSideGUID, item : Equipment) extends Action
|
||||
final case class HackClear(player_guid : PlanetSideGUID, target : PlanetSideServerObject, unk1 : Long, unk2 : Long = 8L) extends Action
|
||||
final case class HackTemporarily(player_guid : PlanetSideGUID, continent : Zone, target : PlanetSideServerObject, unk1 : Long, unk2 : Long = 8L) extends Action
|
||||
final case class ProximityTerminalEffect(player_guid : PlanetSideGUID, object_guid : PlanetSideGUID, effectState : Boolean) extends Action
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package services.local
|
||||
|
||||
import net.psforever.packet.game.objectcreate.ConstructorData
|
||||
import net.psforever.packet.game.{PlanetSideGUID, TriggeredSound}
|
||||
import net.psforever.types.Vector3
|
||||
|
||||
|
|
@ -9,6 +10,7 @@ object LocalResponse {
|
|||
|
||||
final case class DoorOpens(door_guid : PlanetSideGUID) extends Response
|
||||
final case class DoorCloses(door_guid : PlanetSideGUID) extends Response
|
||||
final case class DropItem(item_id : Int, item_guid : PlanetSideGUID, item_data : ConstructorData) extends Response
|
||||
final case class HackClear(target_guid : PlanetSideGUID, unk1 : Long, unk2 : Long) extends Response
|
||||
final case class HackObject(target_guid : PlanetSideGUID, unk1 : Long, unk2 : Long) extends Response
|
||||
final case class ProximityTerminalEffect(object_guid : PlanetSideGUID, effectState : Boolean) extends Response
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
package services.local
|
||||
|
||||
import akka.actor.{Actor, Props}
|
||||
import net.psforever.packet.game.objectcreate.{DroppedItemData, PlacementData}
|
||||
import services.local.support.{DoorCloseActor, HackClearActor}
|
||||
import services.{GenericEventBus, Service}
|
||||
|
||||
|
|
@ -46,6 +47,17 @@ class LocalService extends Actor {
|
|||
LocalEvents.publish(
|
||||
LocalServiceResponse(s"/$forChannel/Local", player_guid, LocalResponse.DoorCloses(door_guid))
|
||||
)
|
||||
case LocalAction.DropItem(player_guid, item) =>
|
||||
val definition = item.Definition
|
||||
val objectData = DroppedItemData(
|
||||
PlacementData(item.Position, item.Orientation),
|
||||
definition.Packet.ConstructorData(item).get
|
||||
)
|
||||
LocalEvents.publish(
|
||||
LocalServiceResponse(s"/$forChannel/Local", player_guid,
|
||||
LocalResponse.DropItem(definition.ObjectId, item.GUID, objectData)
|
||||
)
|
||||
)
|
||||
case LocalAction.HackClear(player_guid, target, unk1, unk2) =>
|
||||
LocalEvents.publish(
|
||||
LocalServiceResponse(s"/$forChannel/Local", player_guid, LocalResponse.HackClear(target.GUID, unk1, unk2))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue