mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-04-28 07:15:21 +00:00
Merge branch 'master' into feature/VehicleDismountImprovements
This commit is contained in:
commit
12443c6aa5
51 changed files with 2281 additions and 384 deletions
|
|
@ -128,7 +128,7 @@ class LoginSessionActor extends Actor with MDCContextAware {
|
|||
if(token.isDefined)
|
||||
log.info(s"New login UN:$username Token:${token.get}. $clientVersion")
|
||||
else
|
||||
log.info(s"New login UN:$username PW:$password. $clientVersion")
|
||||
log.info(s"New login UN:$username. $clientVersion")
|
||||
|
||||
// This is temporary until a schema has been developed
|
||||
//val loginSucceeded = accountLookup(username, password.getOrElse(token.get))
|
||||
|
|
|
|||
|
|
@ -110,9 +110,21 @@ object Maps {
|
|||
LocalObject(1576, Terminal.Constructor(order_terminal))
|
||||
LocalObject(1577, Terminal.Constructor(order_terminal))
|
||||
LocalObject(1578, Terminal.Constructor(order_terminal))
|
||||
LocalObject(1744, ProximityTerminal.Constructor(pad_landing)) //air pad A
|
||||
LocalObject(1745, Terminal.Constructor(pad_landing)) //air pad A
|
||||
LocalObject(1747, ProximityTerminal.Constructor(pad_landing)) //air pad B
|
||||
LocalObject(1748, Terminal.Constructor(pad_landing)) //air pad B
|
||||
LocalObject(1756, ProximityTerminal.Constructor(pad_landing)) //air pad C
|
||||
LocalObject(1757, Terminal.Constructor(pad_landing)) //air pad C
|
||||
LocalObject(1765, ProximityTerminal.Constructor(pad_landing)) //air pad D
|
||||
LocalObject(1766, Terminal.Constructor(pad_landing)) //air pad D
|
||||
LocalObject(2145, SpawnTube.Constructor(Vector3(3980.4062f, 4252.7656f, 257.5625f), Vector3(0, 0, 90)))
|
||||
LocalObject(2146, SpawnTube.Constructor(Vector3(3980.4062f, 4259.992f, 257.5625f), Vector3(0, 0, 90)))
|
||||
LocalObject(2147, SpawnTube.Constructor(Vector3(3980.4062f, 4267.3047f, 257.5625f), Vector3(0, 0, 90)))
|
||||
LocalObject(2049, ProximityTerminal.Constructor(repair_silo)) //repair terminal A
|
||||
LocalObject(2050, Terminal.Constructor(repair_silo)) //rearm terminal A
|
||||
LocalObject(2061, ProximityTerminal.Constructor(repair_silo)) //repair terminal B
|
||||
LocalObject(2062, Terminal.Constructor(repair_silo)) //rearm terminal B
|
||||
LocalObject(2239, Terminal.Constructor(spawn_terminal))
|
||||
LocalObject(2244, Terminal.Constructor(spawn_terminal))
|
||||
LocalObject(2245, Terminal.Constructor(spawn_terminal))
|
||||
|
|
@ -214,6 +226,18 @@ object Maps {
|
|||
ObjectToBuilding(1576, 2)
|
||||
ObjectToBuilding(1577, 2)
|
||||
ObjectToBuilding(1578, 2)
|
||||
ObjectToBuilding(1744, 2)
|
||||
ObjectToBuilding(1745, 2)
|
||||
ObjectToBuilding(1747, 2)
|
||||
ObjectToBuilding(1748, 2)
|
||||
ObjectToBuilding(1756, 2)
|
||||
ObjectToBuilding(1757, 2)
|
||||
ObjectToBuilding(1765, 2)
|
||||
ObjectToBuilding(1766, 2)
|
||||
ObjectToBuilding(2049, 2)
|
||||
ObjectToBuilding(2050, 2)
|
||||
ObjectToBuilding(2061, 2)
|
||||
ObjectToBuilding(2062, 2)
|
||||
ObjectToBuilding(2145, 2)
|
||||
ObjectToBuilding(2146, 2)
|
||||
ObjectToBuilding(2147, 2)
|
||||
|
|
@ -351,6 +375,10 @@ object Maps {
|
|||
LocalObject(1591, Terminal.Constructor(order_terminal))
|
||||
LocalObject(1592, Terminal.Constructor(order_terminal))
|
||||
LocalObject(1593, Terminal.Constructor(order_terminal))
|
||||
LocalObject(1846, ProximityTerminal.Constructor(pad_landing)) //air pad S
|
||||
LocalObject(1847, Terminal.Constructor(pad_landing)) //air pad S
|
||||
LocalObject(1849, ProximityTerminal.Constructor(pad_landing)) //air pad N
|
||||
LocalObject(1850, Terminal.Constructor(pad_landing)) //air pad N
|
||||
LocalObject(2156, SpawnTube.Constructor(respawn_tube_tower, Vector3(4364.633f, 3994.125f, 228.1875f), Vector3(0, 0, 90)))
|
||||
LocalObject(2157, SpawnTube.Constructor(respawn_tube_tower, Vector3(4364.633f, 3977.7266f, 228.1875f), Vector3(0, 0, 90)))
|
||||
LocalObject(2333, Door.Constructor) //spawn tube door
|
||||
|
|
@ -374,6 +402,10 @@ object Maps {
|
|||
ObjectToBuilding(1591, 49)
|
||||
ObjectToBuilding(1592, 49)
|
||||
ObjectToBuilding(1593, 49)
|
||||
ObjectToBuilding(1846, 49)
|
||||
ObjectToBuilding(1847, 49)
|
||||
ObjectToBuilding(1849, 49)
|
||||
ObjectToBuilding(1850, 49)
|
||||
ObjectToBuilding(2156, 49)
|
||||
ObjectToBuilding(2157, 49)
|
||||
ObjectToBuilding(2333, 49)
|
||||
|
|
@ -428,6 +460,8 @@ object Maps {
|
|||
def Building2() : Unit = {
|
||||
//HART building C
|
||||
LocalBuilding(2, FoundationBuilder(Building.Structure(StructureType.Building)))
|
||||
LocalObject(12, ProximityTerminal.Constructor(repair_silo)) //repair terminal A
|
||||
LocalObject(13, Terminal.Constructor(repair_silo)) //rearm terminal A //ItemTransaction: ItemTransactionMessage(PlanetSideGUID(2050),Buy,3,25mmbullet,0,PlanetSideGUID(0))
|
||||
LocalObject(186, Terminal.Constructor(cert_terminal))
|
||||
LocalObject(187, Terminal.Constructor(cert_terminal))
|
||||
LocalObject(188, Terminal.Constructor(cert_terminal))
|
||||
|
|
@ -475,6 +509,8 @@ object Maps {
|
|||
LocalObject(1087, Terminal.Constructor(implant_terminal_interface)) //TODO guid not correct
|
||||
LocalObject(1088, Terminal.Constructor(implant_terminal_interface)) //TODO guid not correct
|
||||
LocalObject(1089, Terminal.Constructor(implant_terminal_interface)) //TODO guid not correct
|
||||
ObjectToBuilding(12, 2)
|
||||
ObjectToBuilding(13, 2)
|
||||
ObjectToBuilding(186, 2)
|
||||
ObjectToBuilding(187, 2)
|
||||
ObjectToBuilding(188, 2)
|
||||
|
|
|
|||
|
|
@ -9,12 +9,14 @@ import scodec.Attempt.{Failure, Successful}
|
|||
import scodec.bits._
|
||||
import org.log4s.MDC
|
||||
import MDCContextAware.Implicits._
|
||||
import csr.{CSRWarp, CSRZone, Traveler}
|
||||
import net.psforever.objects.GlobalDefinitions._
|
||||
import services.ServiceManager.Lookup
|
||||
import net.psforever.objects._
|
||||
import net.psforever.objects.definition.ToolDefinition
|
||||
import net.psforever.objects.definition.converter.CorpseConverter
|
||||
import net.psforever.objects.equipment._
|
||||
import net.psforever.objects.loadouts._
|
||||
import net.psforever.objects.guid.{GUIDTask, Task, TaskResolver}
|
||||
import net.psforever.objects.inventory.{Container, GridInventory, InventoryItem}
|
||||
import net.psforever.objects.serverobject.mount.Mountable
|
||||
|
|
@ -28,8 +30,7 @@ import net.psforever.objects.serverobject.mblocker.Locker
|
|||
import net.psforever.objects.serverobject.pad.{VehicleSpawnControl, VehicleSpawnPad}
|
||||
import net.psforever.objects.serverobject.pad.process.{AutoDriveControls, VehicleSpawnControlGuided}
|
||||
import net.psforever.objects.serverobject.structures.{Building, StructureType, WarpGate}
|
||||
import net.psforever.objects.serverobject.terminals.{MatrixTerminalDefinition, ProximityTerminal, Terminal}
|
||||
import net.psforever.objects.serverobject.terminals.Terminal
|
||||
import net.psforever.objects.serverobject.terminals._
|
||||
import net.psforever.objects.serverobject.terminals.Terminal.TerminalMessage
|
||||
import net.psforever.objects.serverobject.tube.SpawnTube
|
||||
import net.psforever.objects.vehicles.{AccessPermissionGroup, Utility, VehicleLockState}
|
||||
|
|
@ -39,6 +40,7 @@ import net.psforever.types._
|
|||
import services._
|
||||
import services.avatar.{AvatarAction, AvatarResponse, AvatarServiceMessage, AvatarServiceResponse}
|
||||
import services.local.{LocalAction, LocalResponse, LocalServiceMessage, LocalServiceResponse}
|
||||
import services.vehicle.VehicleAction.UnstowEquipment
|
||||
import services.vehicle.{VehicleAction, VehicleResponse, VehicleServiceMessage, VehicleServiceResponse}
|
||||
|
||||
import scala.annotation.tailrec
|
||||
|
|
@ -70,6 +72,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
var usingProximityTerminal : Set[PlanetSideGUID] = Set.empty
|
||||
var delayedProximityTerminalResets : Map[PlanetSideGUID, Cancellable] = Map.empty
|
||||
var controlled : Option[Int] = None //keep track of avatar's ServerVehicleOverride state
|
||||
var traveler : Traveler = null
|
||||
|
||||
var clientKeepAlive : Cancellable = DefaultCancellable.obj
|
||||
var progressBarUpdate : Cancellable = DefaultCancellable.obj
|
||||
|
|
@ -488,6 +491,11 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
}
|
||||
}
|
||||
|
||||
case VehicleResponse.InventoryState2(obj_guid, parent_guid, value) =>
|
||||
if(tplayer_guid != guid) {
|
||||
sendResponse(InventoryStateMessage(obj_guid, 0, parent_guid, value))
|
||||
}
|
||||
|
||||
case VehicleResponse.LoadVehicle(vehicle, vtype, vguid, vdata) =>
|
||||
//this is not be suitable for vehicles with people who are seated in it before it spawns (if that is possible)
|
||||
if(tplayer_guid != guid) {
|
||||
|
|
@ -829,7 +837,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
case Terminal.InfantryLoadout(exosuit, subtype, holsters, inventory) =>
|
||||
//TODO optimizations against replacing Equipment with the exact same Equipment and potentially for recycling existing Equipment
|
||||
log.info(s"$tplayer wants to change equipment loadout to their option #${msg.unk1 + 1}")
|
||||
sendResponse(ItemTransactionResultMessage (msg.terminal_guid, TransactionType.InfantryLoadout, true))
|
||||
sendResponse(ItemTransactionResultMessage(msg.terminal_guid, TransactionType.Loadout, true))
|
||||
val dropPred = DropPredicate(tplayer)
|
||||
val (dropHolsters, beforeHolsters) = clearHolsters(tplayer.Holsters().iterator).partition(dropPred)
|
||||
val (dropInventory, beforeInventory) = tplayer.Inventory.Clear().partition(dropPred)
|
||||
|
|
@ -848,7 +856,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
taskResolver ! GUIDTask.UnregisterEquipment(elem.obj)(continent.GUID)
|
||||
})
|
||||
//report change
|
||||
sendResponse(ArmorChangedMessage(tplayer.GUID, exosuit, 0))
|
||||
sendResponse(ArmorChangedMessage(tplayer.GUID, exosuit, subtype))
|
||||
avatarService ! AvatarServiceMessage(tplayer.Continent, AvatarAction.ArmorChanged(tplayer.GUID, exosuit, subtype))
|
||||
sendResponse(PlanetsideAttributeMessage(tplayer.GUID, 4, tplayer.Armor))
|
||||
avatarService ! AvatarServiceMessage(tplayer.Continent, AvatarAction.PlanetsideAttribute(tplayer.GUID, 4, tplayer.Armor))
|
||||
|
|
@ -892,7 +900,53 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
val objDef = obj.Definition
|
||||
avatarService ! AvatarServiceMessage(tplayer.Continent, AvatarAction.EquipmentOnGround(tplayer.GUID, pos, orient, objDef.ObjectId, obj.GUID, objDef.Packet.ConstructorData(obj).get))
|
||||
})
|
||||
sendResponse(ItemTransactionResultMessage (msg.terminal_guid, TransactionType.InfantryLoadout, true))
|
||||
|
||||
case Terminal.VehicleLoadout(definition, weapons, inventory) =>
|
||||
log.info(s"$tplayer wants to change their vehicle equipment loadout to their option #${msg.unk1 + 1}")
|
||||
FindLocalVehicle match {
|
||||
case Some(vehicle) =>
|
||||
sendResponse(ItemTransactionResultMessage (msg.terminal_guid, TransactionType.Loadout, true))
|
||||
val (_, afterInventory) = inventory.partition( DropPredicate(tplayer) ) //dropped items are lost
|
||||
//remove old inventory
|
||||
val deleteEquipment : (Int,Equipment)=>Unit = DeleteEquipmentFromVehicle(vehicle)
|
||||
vehicle.Inventory.Clear().foreach({ case InventoryItem(obj, index) => deleteEquipment(index, obj) })
|
||||
val stowEquipment : (Int,Equipment)=>TaskResolver.GiveTask = StowNewEquipmentInVehicle(vehicle)
|
||||
(if(vehicle.Definition == definition) {
|
||||
//vehicles are the same type; transfer over weapon ammo
|
||||
//TODO ammo switching? no vehicle weapon does that currently but ...
|
||||
//TODO want to completely swap weapons, but holster icon vanishes temporarily after swap
|
||||
//TODO BFR arms must be swapped properly
|
||||
val channel = s"${vehicle.Actor}"
|
||||
weapons.foreach({ case InventoryItem(obj, index) =>
|
||||
val savedWeapon = obj.asInstanceOf[Tool]
|
||||
val existingWeapon = vehicle.Weapons(index).Equipment.get.asInstanceOf[Tool]
|
||||
(0 until existingWeapon.MaxAmmoSlot).foreach({ index =>
|
||||
val existingBox = existingWeapon.AmmoSlots(index).Box
|
||||
existingBox.Capacity = savedWeapon.AmmoSlots(index).Box.Capacity
|
||||
//use VehicleAction.InventoryState2; VehicleAction.InventoryState temporarily glitches ammo count in ui
|
||||
vehicleService ! VehicleServiceMessage(channel, VehicleAction.InventoryState2(PlanetSideGUID(0), existingBox.GUID, existingWeapon.GUID, existingBox.Capacity))
|
||||
})
|
||||
})
|
||||
afterInventory
|
||||
}
|
||||
else {
|
||||
//do not transfer over weapon ammo
|
||||
if(vehicle.Definition.TrunkSize == definition.TrunkSize && vehicle.Definition.TrunkOffset == definition.TrunkOffset) {
|
||||
afterInventory
|
||||
}
|
||||
else {
|
||||
//accommodate as much of inventory as possible
|
||||
//TODO map x,y -> x,y rather than reorganize items
|
||||
val (stow, _) = GridInventory.recoverInventory(afterInventory, vehicle.Inventory) //dropped items can be forgotten
|
||||
stow
|
||||
}
|
||||
}).foreach({ case InventoryItem(obj, index) =>
|
||||
taskResolver ! stowEquipment(index, obj)
|
||||
})
|
||||
case None =>
|
||||
log.error(s"can not apply the loadout - can not find a vehicle")
|
||||
sendResponse(ItemTransactionResultMessage (msg.terminal_guid, TransactionType.Loadout, false))
|
||||
}
|
||||
|
||||
case Terminal.LearnCertification(cert, cost) =>
|
||||
if(!tplayer.Certifications.contains(cert)) {
|
||||
|
|
@ -1054,6 +1108,12 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
|
||||
case VehicleSpawnPad.StartPlayerSeatedInVehicle(vehicle, pad) =>
|
||||
val vehicle_guid = vehicle.GUID
|
||||
PlayerActionsToCancel()
|
||||
if(player.VisibleSlots.contains(player.DrawnSlot)) {
|
||||
player.DrawnSlot = Player.HandsDownSlot
|
||||
sendResponse(ObjectHeldMessage(player.GUID, Player.HandsDownSlot, true))
|
||||
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.ObjectHeld(player.GUID, player.LastDrawnSlot))
|
||||
}
|
||||
sendResponse(PlanetsideAttributeMessage(vehicle_guid, 22, 1L)) //mount points off?
|
||||
sendResponse(PlanetsideAttributeMessage(vehicle_guid, 21, player.GUID.guid)) //fte and ownership?
|
||||
|
||||
|
|
@ -1063,7 +1123,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
vehicleService ! VehicleServiceMessage.UnscheduleDeconstruction(vehicle_guid)
|
||||
}
|
||||
sendResponse(PlanetsideAttributeMessage(vehicle_guid, 22, 0L)) //mount points on?
|
||||
//sendResponse(PlanetsideAttributeMessage(vehicle_guid, 0, vehicle.Definition.MaxHealth)))
|
||||
//sendResponse(PlanetsideAttributeMessage(vehicle_guid, 0, 10))//vehicle.Definition.MaxHealth))
|
||||
sendResponse(PlanetsideAttributeMessage(vehicle_guid, 68, 0L)) //???
|
||||
sendResponse(PlanetsideAttributeMessage(vehicle_guid, 113, 0L)) //???
|
||||
ReloadVehicleAccessPermissions(vehicle)
|
||||
|
|
@ -1147,6 +1207,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
val popNC = poplist.count(_.faction == PlanetSideEmpire.NC)
|
||||
val popVS = poplist.count(_.faction == PlanetSideEmpire.VS)
|
||||
|
||||
StartBundlingPackets()
|
||||
zone.Buildings.foreach({ case(id, building) => initBuilding(continentNumber, id, building) })
|
||||
sendResponse(ZonePopulationUpdateMessage(continentNumber, 414, 138, popTR, 138, popNC, 138, popVS, 138, popBO))
|
||||
sendResponse(ContinentalLockUpdateMessage(continentNumber, PlanetSideEmpire.NEUTRAL))
|
||||
|
|
@ -1231,7 +1292,9 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
RequestSanctuaryZoneSpawn(player, zone_number)
|
||||
|
||||
case InterstellarCluster.ClientInitializationComplete() =>
|
||||
StopBundlingPackets()
|
||||
LivePlayerList.Add(sessionId, avatar)
|
||||
traveler = new Traveler(self, continent.Id)
|
||||
//PropertyOverrideMessage
|
||||
sendResponse(PlanetsideAttributeMessage(PlanetSideGUID(0), 112, 1))
|
||||
sendResponse(ReplicationStreamMessage(5, Some(6), Vector(SquadListing()))) //clear squad list
|
||||
|
|
@ -1280,6 +1343,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
case SetCurrentAvatar(tplayer) =>
|
||||
player = tplayer
|
||||
val guid = tplayer.GUID
|
||||
StartBundlingPackets()
|
||||
sendResponse(SetCurrentAvatarMessage(guid,0,0))
|
||||
sendResponse(PlayerStateShiftMessage(ShiftState(1, tplayer.Position, tplayer.Orientation.z)))
|
||||
if(spectator) {
|
||||
|
|
@ -1312,6 +1376,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
//SquadDefinitionActionMessage and SquadDetailDefinitionUpdateMessage
|
||||
//MapObjectStateBlockMessage and ObjectCreateMessage
|
||||
//TacticsMessage
|
||||
StopBundlingPackets()
|
||||
|
||||
sendResponse(ChatMsg(ChatMessageType.CMT_EXPANSIONS, true, "", "1 on", None)) //CC on
|
||||
|
||||
|
|
@ -1432,9 +1497,10 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
AwardBattleExperiencePoints(avatar, 1000000L)
|
||||
player = new Player(avatar)
|
||||
//player.Position = Vector3(3561.0f, 2854.0f, 90.859375f) //home3, HART C
|
||||
//player.Orientation = Vector3(0f, 0f, 90f)
|
||||
player.Position = Vector3(4262.211f ,4067.0625f ,262.35938f) //z6, Akna.tower
|
||||
player.Orientation = Vector3(0f, 0f, 132.1875f)
|
||||
player.Position = Vector3(3940.3984f, 4343.625f, 266.45312f)
|
||||
player.Orientation = Vector3(0f, 0f, 90f)
|
||||
//player.Position = Vector3(4262.211f ,4067.0625f ,262.35938f) //z6, Akna.tower
|
||||
//player.Orientation = Vector3(0f, 0f, 132.1875f)
|
||||
// player.ExoSuit = ExoSuitType.MAX //TODO strange issue; divide number above by 10 when uncommenting
|
||||
player.Slot(0).Equipment = SimpleItem(remote_electronics_kit) //Tool(GlobalDefinitions.StandardPistol(player.Faction))
|
||||
player.Slot(2).Equipment = Tool(punisher) //suppressor
|
||||
|
|
@ -1477,6 +1543,8 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
|
||||
case msg @ BeginZoningMessage() =>
|
||||
log.info("Reticulating splines ...")
|
||||
traveler.zone = continent.Id
|
||||
StartBundlingPackets()
|
||||
configZone(continent)
|
||||
sendResponse(TimeOfDayMessage(1191182336))
|
||||
|
||||
|
|
@ -1550,6 +1618,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
case _ => ;
|
||||
}
|
||||
})
|
||||
StopBundlingPackets()
|
||||
avatarService ! Service.Join(player.Continent)
|
||||
localService ! Service.Join(player.Continent)
|
||||
vehicleService ! Service.Join(player.Continent)
|
||||
|
|
@ -1706,6 +1775,33 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
}
|
||||
}
|
||||
|
||||
CSRZone.read(traveler, msg) match {
|
||||
case (true, zone, pos) =>
|
||||
if(player.isAlive) {
|
||||
player.Die //die to suspend client-driven position change updates
|
||||
PlayerActionsToCancel()
|
||||
player.Position = pos
|
||||
traveler.zone = zone
|
||||
continent.Population ! Zone.Population.Release(avatar)
|
||||
continent.Population ! Zone.Population.Leave(avatar)
|
||||
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.ObjectDelete(player.GUID, player.GUID))
|
||||
taskResolver ! TaskBeforeZoneChange(GUIDTask.UnregisterAvatar(player)(continent.GUID), zone)
|
||||
}
|
||||
|
||||
case (false, _, _) => ;
|
||||
}
|
||||
|
||||
CSRWarp.read(traveler, msg) match {
|
||||
case (true, pos) =>
|
||||
if(player.isAlive) {
|
||||
PlayerActionsToCancel()
|
||||
sendResponse(PlayerStateShiftMessage(ShiftState(0, pos, player.Orientation.z, None)))
|
||||
player.Position = pos
|
||||
}
|
||||
|
||||
case (false, _) => ;
|
||||
}
|
||||
|
||||
// TODO: Prevents log spam, but should be handled correctly
|
||||
if (messagetype != ChatMessageType.CMT_TOGGLE_GM) {
|
||||
log.info("Chat: " + msg)
|
||||
|
|
@ -1765,15 +1861,15 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
case x :: xs =>
|
||||
val (deleteFunc, modifyFunc) : ((Int, AmmoBox)=>Unit, (AmmoBox, Int)=>Unit) = obj match {
|
||||
case (veh : Vehicle) =>
|
||||
(DeleteAmmunitionInVehicle(veh), ModifyAmmunitionInVehicle(veh))
|
||||
(DeleteEquipmentFromVehicle(veh), ModifyAmmunitionInVehicle(veh))
|
||||
case _ =>
|
||||
(DeleteAmmunition(obj), ModifyAmmunition(obj))
|
||||
(DeleteEquipment(obj), ModifyAmmunition(obj))
|
||||
}
|
||||
val (stowFuncTask, stowFunc) : ((Int, AmmoBox)=>TaskResolver.GiveTask, (Int, AmmoBox)=>Unit) = obj match {
|
||||
case (veh : Vehicle) =>
|
||||
(StowNewAmmunitionInVehicles(veh), StowAmmunitionInVehicles(veh))
|
||||
(StowNewEquipmentInVehicle(veh), StowEquipmentInVehicles(veh))
|
||||
case _ =>
|
||||
(StowNewAmmunition(obj), StowAmmunition(obj))
|
||||
(StowNewEquipment(obj), StowEquipment(obj))
|
||||
}
|
||||
xs.foreach(item => {
|
||||
obj.Inventory -= x.start
|
||||
|
|
@ -1985,9 +2081,9 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
case x :: xs =>
|
||||
val (deleteFunc, modifyFunc) : ((Int, AmmoBox)=>Unit, (AmmoBox, Int)=>Unit) = obj match {
|
||||
case (veh : Vehicle) =>
|
||||
(DeleteAmmunitionInVehicle(veh), ModifyAmmunitionInVehicle(veh))
|
||||
(DeleteEquipmentFromVehicle(veh), ModifyAmmunitionInVehicle(veh))
|
||||
case _ =>
|
||||
(DeleteAmmunition(obj), ModifyAmmunition(obj))
|
||||
(DeleteEquipment(obj), ModifyAmmunition(obj))
|
||||
}
|
||||
xs.foreach(item => {
|
||||
deleteFunc(item.start, item.obj.asInstanceOf[AmmoBox])
|
||||
|
|
@ -2079,7 +2175,14 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
findFunc(parent)
|
||||
case None =>
|
||||
None
|
||||
}) match {
|
||||
})
|
||||
.orElse(FindLocalVehicle match {
|
||||
case Some(parent) =>
|
||||
findFunc(parent)
|
||||
case None =>
|
||||
None
|
||||
})
|
||||
match {
|
||||
case Some((parent, Some(slot))) =>
|
||||
taskResolver ! RemoveEquipmentFromSlot(parent, obj, slot)
|
||||
log.info(s"RequestDestroy: equipment $object_guid")
|
||||
|
|
@ -2283,6 +2386,15 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
//TODO matrix spawn point; for now, just blindly bind to show work (and hope nothing breaks)
|
||||
sendResponse(BindPlayerMessage(1, "@ams", true, true, 0, 0, 0, obj.Position))
|
||||
}
|
||||
else if(obj.Definition.isInstanceOf[RepairRearmSiloDefinition]) {
|
||||
FindLocalVehicle match {
|
||||
case Some(vehicle) =>
|
||||
sendResponse(UseItemMessage(avatar_guid, unk1, object_guid, unk2, unk3, unk4, unk5, unk6, unk7, unk8, itemType))
|
||||
sendResponse(UseItemMessage(avatar_guid, unk1, vehicle.GUID, unk2, unk3, unk4, unk5, unk6, unk7, unk8, vehicle.Definition.ObjectId))
|
||||
case None =>
|
||||
log.error("UseItem: expected seated vehicle, but found none")
|
||||
}
|
||||
}
|
||||
else {
|
||||
sendResponse(UseItemMessage(avatar_guid, unk1, object_guid, unk2, unk3, unk4, unk5, unk6, unk7, unk8, itemType))
|
||||
}
|
||||
|
|
@ -2305,13 +2417,14 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
sendResponse(ObjectDeleteMessage(PlanetSideGUID(unk1), 2))
|
||||
}
|
||||
|
||||
case None => ;
|
||||
case None =>
|
||||
log.error(s"UseItem: can not find object $object_guid")
|
||||
}
|
||||
|
||||
case msg @ ProximityTerminalUseMessage(player_guid, object_guid, _) =>
|
||||
log.info(s"ProximityTerminal: $msg")
|
||||
log.info(s"ProximityTerminalUse: $msg")
|
||||
continent.GUID(object_guid) match {
|
||||
case Some(obj : ProximityTerminal) =>
|
||||
case Some(obj : Terminal with ProximityUnit) =>
|
||||
if(usingProximityTerminal.contains(object_guid)) {
|
||||
SelectProximityUnit(obj)
|
||||
}
|
||||
|
|
@ -2319,9 +2432,9 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
StartUsingProximityUnit(obj)
|
||||
}
|
||||
case Some(obj) => ;
|
||||
log.warn(s"ProximityTerminal: object is not a terminal - $obj")
|
||||
log.warn(s"ProximityTerminalUse: object does not have proximity effects - $obj")
|
||||
case None =>
|
||||
log.warn(s"ProximityTerminal: no object with guid $object_guid found")
|
||||
log.warn(s"ProximityTerminalUse: no object with guid $object_guid found")
|
||||
}
|
||||
|
||||
case msg @ UnuseItemMessage(player_guid, object_guid) =>
|
||||
|
|
@ -2358,20 +2471,46 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
log.error(s"ItemTransaction: $terminal_guid does not exist")
|
||||
}
|
||||
|
||||
case msg @ FavoritesRequest(player_guid, unk, action, line, label) =>
|
||||
case msg @ FavoritesRequest(player_guid, list, action, line, label) =>
|
||||
log.info(s"FavoritesRequest: $msg")
|
||||
if(player.GUID == player_guid) {
|
||||
val name = label.getOrElse("missing_loadout_name")
|
||||
val lineno = if(list == LoadoutType.Vehicle) { line + 10 } else { line }
|
||||
val name = label.getOrElse(s"missing_loadout_${line+1}")
|
||||
action match {
|
||||
case FavoritesAction.Unknown => ;
|
||||
case FavoritesAction.Save =>
|
||||
avatar.SaveLoadout(player, name, line)
|
||||
sendResponse(FavoritesMessage(0, player_guid, line, name))
|
||||
(if(list == LoadoutType.Infantry) {
|
||||
Some(player)
|
||||
}
|
||||
else if(list == LoadoutType.Vehicle) {
|
||||
player.VehicleSeated match {
|
||||
case Some(vehicle_guid) =>
|
||||
continent.GUID(vehicle_guid)
|
||||
case None =>
|
||||
None
|
||||
}
|
||||
}
|
||||
else {
|
||||
None
|
||||
}) match {
|
||||
case Some(owner : Player) => //InfantryLoadout
|
||||
avatar.SaveLoadout(owner, name, lineno)
|
||||
import InfantryLoadout._
|
||||
sendResponse(FavoritesMessage(list, player_guid, line, name, DetermineSubtypeB(player.ExoSuit, DetermineSubtype(player))))
|
||||
case Some(owner : Vehicle) => //VehicleLoadout
|
||||
avatar.SaveLoadout(owner, name, lineno)
|
||||
sendResponse(FavoritesMessage(list, player_guid, line, name))
|
||||
case Some(_) | None =>
|
||||
log.error("FavoritesRequest: unexpected owner for favorites")
|
||||
}
|
||||
|
||||
case FavoritesAction.Delete =>
|
||||
avatar.DeleteLoadout(line)
|
||||
sendResponse(FavoritesMessage(0, player_guid, line, ""))
|
||||
avatar.DeleteLoadout(lineno)
|
||||
sendResponse(FavoritesMessage(list, player_guid, line, ""))
|
||||
|
||||
case FavoritesAction.Unknown =>
|
||||
log.warn("FavoritesRequest: unknown favorites action")
|
||||
}
|
||||
}
|
||||
log.info("FavoritesRequest: " + msg)
|
||||
|
||||
case msg @ WeaponDelayFireMessage(seq_time, weapon_guid) =>
|
||||
log.info("WeaponDelayFire: " + msg)
|
||||
|
|
@ -2562,6 +2701,9 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
sendResponse(PlanetsideAttributeMessage(object_guid, attribute_type, attribute_value))
|
||||
}
|
||||
|
||||
case msg @ FacilityBenefitShieldChargeRequestMessage(guid) =>
|
||||
//log.info(s"ShieldChargeRequest: $msg")
|
||||
|
||||
case msg @ BattleplanMessage(char_id, player_name, zonr_id, diagrams) =>
|
||||
log.info("Battleplan: "+msg)
|
||||
|
||||
|
|
@ -3303,32 +3445,52 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
}
|
||||
|
||||
/**
|
||||
* Given an object that contains a box of amunition in its `Inventory` at a certain location,
|
||||
* Get the current `Vehicle` object that the player is riding/driving.
|
||||
* The vehicle must be found solely through use of `player.VehicleSeated`.
|
||||
* @return the vehicle
|
||||
*/
|
||||
def FindLocalVehicle : Option[Vehicle] = {
|
||||
player.VehicleSeated match {
|
||||
case Some(vehicle_guid) =>
|
||||
continent.GUID(vehicle_guid) match {
|
||||
case Some(obj : Vehicle) =>
|
||||
Some(obj)
|
||||
case _ =>
|
||||
None
|
||||
}
|
||||
case None =>
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an object that contains an item (`Equipment`) in its `Inventory` at a certain location,
|
||||
* remove it permanently.
|
||||
* @param obj the `Container`
|
||||
* @param start where the ammunition can be found
|
||||
* @param item an object to unregister (should have been the ammunition that was removed);
|
||||
* @param start where the item can be found
|
||||
* @param item an object to unregister;
|
||||
* not explicitly checked
|
||||
*/
|
||||
private def DeleteAmmunition(obj : PlanetSideGameObject with Container)(start : Int, item : AmmoBox) : Unit = {
|
||||
private def DeleteEquipment(obj : PlanetSideGameObject with Container)(start : Int, item : Equipment) : Unit = {
|
||||
val item_guid = item.GUID
|
||||
obj.Inventory -= start
|
||||
obj.Slot(start).Equipment = None
|
||||
//obj.Inventory -= start
|
||||
taskResolver ! GUIDTask.UnregisterEquipment(item)(continent.GUID)
|
||||
sendResponse(ObjectDeleteMessage(item_guid, 0))
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a vehicle that contains a box of amunition in its `Trunk` at a certain location,
|
||||
* Given a vehicle that contains an item (`Equipment`) in its `Trunk` at a certain location,
|
||||
* remove it permanently.
|
||||
* @see `DeleteAmmunition`
|
||||
* @see `DeleteEquipment`
|
||||
* @param obj the `Vehicle`
|
||||
* @param start where the ammunition can be found
|
||||
* @param item an object to unregister (should have been the ammunition that was removed);
|
||||
* @param start where the item can be found
|
||||
* @param item an object to unregister;
|
||||
* not explicitly checked
|
||||
*/
|
||||
private def DeleteAmmunitionInVehicle(obj : Vehicle)(start : Int, item : AmmoBox) : Unit = {
|
||||
private def DeleteEquipmentFromVehicle(obj : Vehicle)(start : Int, item : Equipment) : Unit = {
|
||||
val item_guid = item.GUID
|
||||
DeleteAmmunition(obj)(start, item)
|
||||
DeleteEquipment(obj)(start, item)
|
||||
vehicleService ! VehicleServiceMessage(s"${obj.Actor}", VehicleAction.UnstowEquipment(player.GUID, item_guid))
|
||||
}
|
||||
|
||||
|
|
@ -3361,27 +3523,27 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
|
||||
/**
|
||||
* Announce that an already-registered `AmmoBox` object exists in a given position in some `Container` object's inventory.
|
||||
* @see `StowAmmunitionInVehicles`
|
||||
* @see `StowEquipmentInVehicles`
|
||||
* @see `ChangeAmmoMessage`
|
||||
* @param obj the `Container` object
|
||||
* @param index an index in `obj`'s inventory
|
||||
* @param item an `AmmoBox`
|
||||
*/
|
||||
def StowAmmunition(obj : PlanetSideGameObject with Container)(index : Int, item : AmmoBox) : Unit = {
|
||||
def StowEquipment(obj : PlanetSideGameObject with Container)(index : Int, item : AmmoBox) : Unit = {
|
||||
obj.Inventory += index -> item
|
||||
sendResponse(ObjectAttachMessage(obj.GUID, item.GUID, index))
|
||||
}
|
||||
|
||||
/**
|
||||
* Announce that an already-registered `AmmoBox` object exists in a given position in some vehicle's inventory.
|
||||
* @see `StowAmmunition`
|
||||
* @see `StowEquipment`
|
||||
* @see `ChangeAmmoMessage`
|
||||
* @param obj the `Vehicle` object
|
||||
* @param index an index in `obj`'s inventory
|
||||
* @param item an `AmmoBox`
|
||||
*/
|
||||
def StowAmmunitionInVehicles(obj : Vehicle)(index : Int, item : AmmoBox) : Unit = {
|
||||
StowAmmunition(obj)(index, item)
|
||||
def StowEquipmentInVehicles(obj : Vehicle)(index : Int, item : AmmoBox) : Unit = {
|
||||
StowEquipment(obj)(index, item)
|
||||
vehicleService ! VehicleServiceMessage(s"${obj.Actor}", VehicleAction.StowEquipment(player.GUID, obj.GUID, index, item))
|
||||
}
|
||||
|
||||
|
|
@ -3389,14 +3551,14 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
* Prepare tasking that registers an `AmmoBox` object
|
||||
* and announces that it exists in a given position in some `Container` object's inventory.
|
||||
* `PutEquipmentInSlot` is the fastest way to achieve these goals.
|
||||
* @see `StowNewAmmunitionInVehicles`
|
||||
* @see `StowNewEquipmentInVehicle`
|
||||
* @see `ChangeAmmoMessage`
|
||||
* @param obj the `Container` object
|
||||
* @param index an index in `obj`'s inventory
|
||||
* @param item an `AmmoBox`
|
||||
* @return a `TaskResolver.GiveTask` chain that executes the action
|
||||
*/
|
||||
def StowNewAmmunition(obj : PlanetSideGameObject with Container)(index : Int, item : AmmoBox) : TaskResolver.GiveTask = {
|
||||
def StowNewEquipment(obj : PlanetSideGameObject with Container)(index : Int, item : Equipment) : TaskResolver.GiveTask = {
|
||||
PutEquipmentInSlot(obj, item, index)
|
||||
}
|
||||
|
||||
|
|
@ -3404,14 +3566,14 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
* Prepare tasking that registers an `AmmoBox` object
|
||||
* and announces that it exists in a given position in some vehicle's inventory.
|
||||
* `PutEquipmentInSlot` is the fastest way to achieve these goals.
|
||||
* @see `StowNewAmmunition`
|
||||
* @see `StowNewEquipment`
|
||||
* @see `ChangeAmmoMessage`
|
||||
* @param obj the `Container` object
|
||||
* @param index an index in `obj`'s inventory
|
||||
* @param item an `AmmoBox`
|
||||
* @return a `TaskResolver.GiveTask` chain that executes the action
|
||||
*/
|
||||
def StowNewAmmunitionInVehicles(obj : Vehicle)(index : Int, item : AmmoBox) : TaskResolver.GiveTask = {
|
||||
def StowNewEquipmentInVehicle(obj : Vehicle)(index : Int, item : Equipment) : TaskResolver.GiveTask = {
|
||||
TaskResolver.GiveTask(
|
||||
new Task() {
|
||||
private val localService = vehicleService
|
||||
|
|
@ -3430,7 +3592,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
resolver ! scala.util.Success(this)
|
||||
}
|
||||
},
|
||||
List(StowNewAmmunition(obj)(index, item))
|
||||
List(StowNewEquipment(obj)(index, item))
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -3860,11 +4022,6 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
shooting = None
|
||||
case None => ;
|
||||
}
|
||||
if(player != null && player.isAlive && player.VisibleSlots.contains(player.DrawnSlot)) {
|
||||
player.DrawnSlot = Player.HandsDownSlot
|
||||
sendResponse(ObjectHeldMessage(player.GUID, Player.HandsDownSlot, true))
|
||||
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.ObjectHeld(player.GUID, player.LastDrawnSlot))
|
||||
}
|
||||
if(flying) {
|
||||
sendResponse(ChatMsg(ChatMessageType.CMT_FLY, false, "", "off", None))
|
||||
flying = false
|
||||
|
|
@ -4004,7 +4161,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
* Special note is warranted in the case of a medical terminal or an advanced medical terminal.
|
||||
* @param terminal the proximity-based unit
|
||||
*/
|
||||
def StartUsingProximityUnit(terminal : ProximityTerminal) : Unit = {
|
||||
def StartUsingProximityUnit(terminal : Terminal with ProximityUnit) : Unit = {
|
||||
val term_guid = terminal.GUID
|
||||
if(!usingProximityTerminal.contains(term_guid)) {
|
||||
usingProximityTerminal += term_guid
|
||||
|
|
@ -4025,7 +4182,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
* Other sorts of proximity-based units are put on a timer.
|
||||
* @param terminal the proximity-based unit
|
||||
*/
|
||||
def StopUsingProximityUnit(terminal : ProximityTerminal) : Unit = {
|
||||
def StopUsingProximityUnit(terminal : Terminal with ProximityUnit) : Unit = {
|
||||
val term_guid = terminal.GUID
|
||||
if(usingProximityTerminal.contains(term_guid)) {
|
||||
usingProximityTerminal -= term_guid
|
||||
|
|
@ -4044,7 +4201,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
* If this timer completes, a message will be sent that will attempt to disassociate from the target proximity unit.
|
||||
* @param terminal the proximity-based unit
|
||||
*/
|
||||
def SetDelayedProximityUnitReset(terminal : ProximityTerminal) : Unit = {
|
||||
def SetDelayedProximityUnitReset(terminal : Terminal with ProximityUnit) : Unit = {
|
||||
val terminal_guid = terminal.GUID
|
||||
ClearDelayedProximityUnitReset(terminal_guid)
|
||||
import scala.concurrent.duration._
|
||||
|
|
@ -4089,7 +4246,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
* and determinig which kind of unit is being utilized.
|
||||
* @param terminal the proximity-based unit
|
||||
*/
|
||||
def SelectProximityUnit(terminal : ProximityTerminal) : Unit = {
|
||||
def SelectProximityUnit(terminal : Terminal with ProximityUnit) : Unit = {
|
||||
terminal.Definition match {
|
||||
case GlobalDefinitions.adv_med_terminal | GlobalDefinitions.medical_terminal =>
|
||||
ProximityMedicalTerminal(terminal)
|
||||
|
|
@ -4098,6 +4255,10 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
SetDelayedProximityUnitReset(terminal)
|
||||
ProximityHealCrystal(terminal)
|
||||
|
||||
case GlobalDefinitions.repair_silo =>
|
||||
SetDelayedProximityUnitReset(terminal)
|
||||
//TODO insert vehicle repair here; see ProximityMedicalTerminal for example
|
||||
|
||||
case _ => ;
|
||||
}
|
||||
}
|
||||
|
|
@ -4108,7 +4269,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
* If the player is both fully healed and fully repaired, stop using the terminal.
|
||||
* @param unit the medical terminal
|
||||
*/
|
||||
def ProximityMedicalTerminal(unit : ProximityTerminal) : Unit = {
|
||||
def ProximityMedicalTerminal(unit : Terminal with ProximityUnit) : Unit = {
|
||||
val healthFull : Boolean = if(player.Health < player.MaxHealth) {
|
||||
HealAction(player)
|
||||
}
|
||||
|
|
@ -4132,7 +4293,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
* If the player is fully healed, stop using the crystal.
|
||||
* @param unit the healing crystal
|
||||
*/
|
||||
def ProximityHealCrystal(unit : ProximityTerminal) : Unit = {
|
||||
def ProximityHealCrystal(unit : Terminal with ProximityUnit) : Unit = {
|
||||
val healthFull : Boolean = if(player.Health < player.MaxHealth) {
|
||||
HealAction(player)
|
||||
}
|
||||
|
|
@ -4232,12 +4393,95 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
sendResponse(ConnectionClose())
|
||||
}
|
||||
|
||||
def sendResponse(cont : PlanetSideControlPacket) : Unit = {
|
||||
sendResponse(PacketCoding.CreateControlPacket(cont))
|
||||
/**
|
||||
* Persistent collector that intercepts `GamePacket` and `ControlPacket` messages that are being sent towards the network.
|
||||
*/
|
||||
private val packetBundlingCollector : MultiPacketCollector = new MultiPacketCollector()
|
||||
/**
|
||||
* Re-assigned function used to direct/intercept packets being sent towards the network.
|
||||
* Defaults to directing the packets.
|
||||
*/
|
||||
private var packetBundlingFunc : (PlanetSidePacket)=>Option[PlanetSidePacket] = NoBundlingAction
|
||||
|
||||
/**
|
||||
* Start packet bundling by assigning the appropriate function.
|
||||
* @see `sendResponse(PlanetSidePacket) : Unit`
|
||||
*/
|
||||
def StartBundlingPackets() : Unit = {
|
||||
log.trace("WORLD SEND: STARTED BUNDLING PACKETS")
|
||||
packetBundlingFunc = PerformBundlingAction
|
||||
}
|
||||
|
||||
def sendResponse(cont : PlanetSideGamePacket) : Unit = {
|
||||
/**
|
||||
* Stop packet bundling by assigning the appropriate function.
|
||||
* If any bundles are in the collector's buffer, push that bundle out towards the network.
|
||||
* @see `sendResponse(PlanetSidePacket) : Unit`
|
||||
*/
|
||||
def StopBundlingPackets() : Unit = {
|
||||
log.trace("WORLD SEND: PACKET BUNDLING SUSPENDED")
|
||||
packetBundlingFunc = NoBundlingAction
|
||||
packetBundlingCollector.BundleOption match {
|
||||
case Some(bundle) =>
|
||||
sendResponse(bundle)
|
||||
case None => ;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform the packet into either a `PlanetSideGamePacket` or a `PlanetSideControlPacket` and push it towards the network.
|
||||
* @param cont the packet
|
||||
* @return the same packet, to indicate it was sent
|
||||
*/
|
||||
private def NoBundlingAction(cont : PlanetSidePacket) : Option[PlanetSidePacket] = {
|
||||
cont match {
|
||||
case game : PlanetSideGamePacket =>
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, game))
|
||||
case control : PlanetSideControlPacket =>
|
||||
sendResponse(PacketCoding.CreateControlPacket(control))
|
||||
case _ => ;
|
||||
}
|
||||
Some(cont)
|
||||
}
|
||||
|
||||
/**
|
||||
* Intercept the packet being sent towards the network and
|
||||
* add it to a bundle that will eventually be sent to the network itself.
|
||||
* @param cont the packet
|
||||
* @return always `None`, to indicate the packet was not sent
|
||||
*/
|
||||
private def PerformBundlingAction(cont : PlanetSidePacket) : Option[PlanetSidePacket] = {
|
||||
log.trace("WORLD SEND, BUNDLED: " + cont)
|
||||
packetBundlingCollector.Add(cont)
|
||||
None
|
||||
}
|
||||
|
||||
/**
|
||||
* Common entry point for transmitting packets to the network.
|
||||
* Alternately, catch those packets and retain them to send out a bundled message.
|
||||
* @param cont the packet
|
||||
*/
|
||||
def sendResponse(cont : PlanetSidePacket) : Unit = packetBundlingFunc(cont)
|
||||
|
||||
/**
|
||||
* `KeepAliveMessage` is a special `PlanetSideGamePacket` that is excluded from being bundled when it is sent to the network.<br>
|
||||
* <br>
|
||||
* The risk of the server getting caught in a state where the packets dispatched to the client are alwaysd bundled is posible.
|
||||
* Starting the bundling functionality but forgetting to transition into a state where it is deactivated can lead to this problem.
|
||||
* No packets except for `KeepAliveMessage` will ever be sent until the ever-accumulating packets overflow.
|
||||
* To avoid this state, whenever a `KeepAliveMessage` is sent, the packet collector empties its current contents to the network.
|
||||
* @see `StartBundlingPackets`<br>
|
||||
* `StopBundlingPackets`<br>
|
||||
* `clientKeepAlive`
|
||||
* @param cont a `KeepAliveMessage` packet
|
||||
*/
|
||||
def sendResponse(cont : KeepAliveMessage) : Unit = {
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, cont))
|
||||
packetBundlingCollector.BundleOption match {
|
||||
case Some(bundle) =>
|
||||
log.trace("WORLD SEND: INTERMITTENT PACKET BUNDLE")
|
||||
sendResponse(bundle)
|
||||
case None => ;
|
||||
}
|
||||
}
|
||||
|
||||
def sendResponse(cont : PlanetSidePacketContainer) : Unit = {
|
||||
|
|
@ -4246,7 +4490,6 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
}
|
||||
|
||||
def sendResponse(cont : MultiPacketBundle) : Unit = {
|
||||
log.trace("WORLD SEND: " + cont)
|
||||
sendResponse(cont.asInstanceOf[Any])
|
||||
}
|
||||
|
||||
|
|
@ -4272,7 +4515,7 @@ object WorldSessionActor {
|
|||
private final case class ListAccountCharacters()
|
||||
private final case class SetCurrentAvatar(tplayer : Player)
|
||||
private final case class VehicleLoaded(vehicle : Vehicle)
|
||||
private final case class DelayedProximityUnitStop(unit : ProximityTerminal)
|
||||
private final case class DelayedProximityUnitStop(unit : Terminal with ProximityUnit)
|
||||
private final case class UnregisterCorpseOnVehicleDisembark(corpse : Player)
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -88,13 +88,13 @@ object Zones {
|
|||
|
||||
val c6 = new Zone("c6", Maps.ugd06, 28)
|
||||
|
||||
val i1 = new Zone("i1", Maps.map96, 29)
|
||||
val i1 = new Zone("i1", Maps.map99, 29)
|
||||
|
||||
val i2 = new Zone("i2", Maps.map97, 30)
|
||||
val i2 = new Zone("i2", Maps.map98, 30)
|
||||
|
||||
val i3 = new Zone("i3", Maps.map98, 31)
|
||||
val i3 = new Zone("i3", Maps.map97, 31)
|
||||
|
||||
val i4 = new Zone("i4", Maps.map99, 32)
|
||||
val i4 = new Zone("i4", Maps.map96, 32)
|
||||
|
||||
/**
|
||||
* Get the zone identifier name for the sanctuary continent of a given empire.
|
||||
|
|
|
|||
129
pslogin/src/main/scala/csr/CSRWarp.scala
Normal file
129
pslogin/src/main/scala/csr/CSRWarp.scala
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
package csr
|
||||
|
||||
import net.psforever.packet.PacketCoding
|
||||
import net.psforever.packet.game.ChatMsg
|
||||
import net.psforever.types.{ChatMessageType, Vector3}
|
||||
|
||||
import scala.collection.mutable.ArrayBuffer
|
||||
import scala.util.Try
|
||||
|
||||
/*
|
||||
The following is STILL for development and fun.
|
||||
*/
|
||||
/**
|
||||
* An implementation of the CSR command `/warp`, highly modified to serve the purposes of the testing phases of the server.
|
||||
* See `help()` for details.
|
||||
*/
|
||||
object CSRWarp {
|
||||
/**
|
||||
* Accept and confirm that a message sent to a player is a valid `/warp` invocation.
|
||||
* If so, parse the message and send the player to whichever destination in this zone was requested.
|
||||
* @param traveler the player
|
||||
* @param msg the message the player received
|
||||
* @return true, if the player is being transported to another place; false, otherwise
|
||||
*/
|
||||
def read(traveler : Traveler, msg : ChatMsg) : (Boolean, Vector3) = {
|
||||
if(!isProperRequest(msg))
|
||||
return (false, Vector3.Zero) //we do not handle this message
|
||||
|
||||
val buffer = decomposeMessage(msg.contents)
|
||||
if(buffer.length == 0 || buffer(0).equals("") || buffer(0).equals("-help")) {
|
||||
CSRWarp.help(traveler) //print usage information to chat
|
||||
return (false, Vector3.Zero)
|
||||
}
|
||||
var destId : String = ""
|
||||
var coords : ArrayBuffer[Int] = ArrayBuffer.empty[Int]
|
||||
var list : Boolean = false
|
||||
var failedCoordInput = false
|
||||
for(o <- buffer) {
|
||||
val toInt = Try(o.toInt)
|
||||
if(toInt.isSuccess) {
|
||||
coords += toInt.get
|
||||
}
|
||||
else if(coords.nonEmpty && coords.size < 3)
|
||||
failedCoordInput = true
|
||||
if(o.equals("-list"))
|
||||
list = true
|
||||
else if(destId.equals(""))
|
||||
destId = o
|
||||
}
|
||||
if(failedCoordInput || (coords.nonEmpty && coords.size < 3)) {
|
||||
CSRWarp.error(traveler, "Needs three integer components (<x> <y> <z>)")
|
||||
return (false, Vector3.Zero)
|
||||
}
|
||||
else {
|
||||
coords.slice(0, 3).foreach(x => {
|
||||
if(x < 0 || x > 8191) {
|
||||
CSRWarp.error(traveler, "Out of range - 0 < n < 8191, but n = " + x)
|
||||
return (false, Vector3.Zero)
|
||||
}
|
||||
})
|
||||
}
|
||||
val zone = CSRZoneImpl.get(traveler.zone).get //the traveler is already in the appropriate zone
|
||||
if(list && coords.isEmpty && destId.equals("")) {
|
||||
CSRWarp.reply(traveler, CSRZoneImpl.listLocations(zone) + "; " + CSRZoneImpl.listWarpgates(zone))
|
||||
return (false, Vector3.Zero)
|
||||
}
|
||||
val dest : Option[Vector3] = if(coords.nonEmpty) Some(Vector3(coords(0), coords(1), coords(2)))
|
||||
else CSRZoneImpl.getWarpLocation(zone, destId) //coords before destId
|
||||
if(dest.isEmpty) {
|
||||
CSRWarp.error(traveler, "Invalid location")
|
||||
return (false, Vector3.Zero)
|
||||
}
|
||||
(true, dest.get)
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the incoming message is an appropriate type for this command.
|
||||
* @param msg the message
|
||||
* @return true, if we will handle it; false, otherwise
|
||||
*/
|
||||
def isProperRequest(msg : ChatMsg) : Boolean = {
|
||||
msg.messageType == ChatMessageType.CMT_WARP
|
||||
}
|
||||
|
||||
/**
|
||||
* Break the message in the packet down for parsing.
|
||||
* @param msg the contents portion of the message, a space-separated `String`
|
||||
* @return the contents portion of the message, transformed into an `Array`
|
||||
*/
|
||||
private def decomposeMessage(msg : String) : Array[String] = {
|
||||
msg.trim.toLowerCase.split("\\s+")
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message back to the `Traveler` that will be printed into his chat window.
|
||||
* @param traveler the player
|
||||
* @param msg the message to be sent
|
||||
*/
|
||||
private def reply(traveler : Traveler, msg : String) : Unit = {
|
||||
traveler ! PacketCoding.CreateGamePacket(0, ChatMsg(ChatMessageType.CMT_OPEN, true, "", msg, None))
|
||||
}
|
||||
|
||||
/**
|
||||
* Print usage information to the `Traveler`'s chat window.<br>
|
||||
* <br>
|
||||
* The "official" use information for help dictates the command should follow this format:
|
||||
* `/warp <x><y><z> | to <character> | near <object> | above <object> | waypoint`.
|
||||
* In our case, creating fixed coordinate points of interest is not terribly dissimilar from the "near" and "to" aspect.
|
||||
* We can not currently implement most of the options for now, however.<br>
|
||||
* <br>
|
||||
* The destination prioritizes evaluation of the coordinates before the location string.
|
||||
* When the user provides coordinates, he must provide all three components of the coordinate at once, else none will be accepted.
|
||||
* If the coordinates are invalid, the location string will still be checked.
|
||||
* "-list" is accepted while no serious attempt is made to indicate a destination (no location string or not enough coordinates).
|
||||
* @param traveler the player
|
||||
*/
|
||||
private def help(traveler : Traveler) : Unit = {
|
||||
CSRWarp.reply(traveler, "usage: /warp <location> | <gatename> | <x> <y> <z> | [-list]")
|
||||
}
|
||||
|
||||
/**
|
||||
* Print error information to the `Traveler`'s chat window.<br>
|
||||
* The most common reason for error is the lack of information, or wrong information.
|
||||
* @param traveler the player
|
||||
*/
|
||||
private def error(traveler : Traveler, msg : String) : Unit = {
|
||||
CSRWarp.reply(traveler, "Error! " + msg)
|
||||
}
|
||||
}
|
||||
114
pslogin/src/main/scala/csr/CSRZone.scala
Normal file
114
pslogin/src/main/scala/csr/CSRZone.scala
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
package csr
|
||||
|
||||
import net.psforever.packet.PacketCoding
|
||||
import net.psforever.packet.game.ChatMsg
|
||||
import net.psforever.types.{ChatMessageType, Vector3}
|
||||
|
||||
/*
|
||||
The following is STILL for development and fun.
|
||||
*/
|
||||
/**
|
||||
* An implementation of the CSR command `/zone`, slightly modified to serve the purposes of the testing phases of the server.
|
||||
*/
|
||||
object CSRZone {
|
||||
/**
|
||||
* Accept and confirm that a message sent to a player is a valid `/zone` invocation.
|
||||
* If so, parse the message and send the player to whichever zone was requested.
|
||||
* @param traveler the player
|
||||
* @param msg the message the player received
|
||||
* @return true, if the player is being transported to another zone; false, otherwise
|
||||
*/
|
||||
def read(traveler : Traveler, msg : ChatMsg) : (Boolean, String , Vector3 ) = {
|
||||
if(!isProperRequest(msg))
|
||||
return (false,"", Vector3.Zero) //we do not handle this message
|
||||
|
||||
val buffer = decomposeMessage(msg.contents)
|
||||
if(buffer.length == 0 || buffer(0).equals("-help")) {
|
||||
CSRZone.help(traveler) //print usage information to chat
|
||||
return (false,"", Vector3.Zero)
|
||||
}
|
||||
|
||||
var zoneId = ""
|
||||
var gateId = "" //the user can define which warpgate they may visit (actual keyword protocol missing)
|
||||
var list = false //if the user wants a printed list of destination locations
|
||||
for(o <- buffer) {
|
||||
if(o.equals("-list")) {
|
||||
if(zoneId.equals("") || gateId.equals("")) {
|
||||
list = true
|
||||
}
|
||||
}
|
||||
else if(zoneId.equals(""))
|
||||
zoneId = o
|
||||
else if(gateId.equals(""))
|
||||
gateId = o
|
||||
}
|
||||
|
||||
val zoneOpt = CSRZoneImpl.get(zoneId)
|
||||
if(zoneOpt.isEmpty) {
|
||||
if(list)
|
||||
CSRZone.reply(traveler, CSRZoneImpl.list)
|
||||
else
|
||||
CSRZone.error(traveler, "Give a valid zonename (use '/zone -list')")
|
||||
return (false,"", Vector3.Zero)
|
||||
}
|
||||
val zone = zoneOpt.get
|
||||
var destination : Vector3 = CSRZoneImpl.selectRandom(zone) //the destination in the new zone starts as random
|
||||
|
||||
if(!gateId.equals("")) { //if we've defined a warpgate, and can find that warpgate, we re-assign the destination
|
||||
val gateOpt = CSRZoneImpl.getWarpgate(zone, gateId)
|
||||
if(gateOpt.isDefined)
|
||||
destination = gateOpt.get
|
||||
else
|
||||
CSRZone.error(traveler, "Gate id not defined (use '/zone <zone> -list')")
|
||||
}
|
||||
else if(list) {
|
||||
CSRZone.reply(traveler, CSRZoneImpl.listWarpgates(zone))
|
||||
return (false,"",Vector3.Zero)
|
||||
}
|
||||
(true, zone.zonename, destination)
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the incoming message is an appropriate type for this command.
|
||||
* @param msg the message
|
||||
* @return true, if we will handle it; false, otherwise
|
||||
*/
|
||||
def isProperRequest(msg : ChatMsg) : Boolean ={
|
||||
msg.messageType == ChatMessageType.CMT_ZONE
|
||||
}
|
||||
|
||||
/**
|
||||
* Break the message in the packet down for parsing.
|
||||
* @param msg the contents portion of the message, a space-separated `String`
|
||||
* @return the contents portion of the message, transformed into an `Array`
|
||||
*/
|
||||
private def decomposeMessage(msg : String) : Array[String] = {
|
||||
msg.trim.toLowerCase.split("\\s+")
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message back to the `Traveler` that will be printed into his chat window.
|
||||
* @param traveler the player
|
||||
* @param msg the message to be sent
|
||||
*/
|
||||
private def reply(traveler : Traveler, msg : String) : Unit = {
|
||||
traveler ! PacketCoding.CreateGamePacket(0, ChatMsg(ChatMessageType.CMT_OPEN,true,"", msg, None))
|
||||
}
|
||||
|
||||
/**
|
||||
* Print usage information to the `Traveler`'s chat window.
|
||||
* @param traveler the player
|
||||
*/
|
||||
private def help(traveler : Traveler) : Unit = {
|
||||
CSRZone.reply(traveler, "usage: /zone <zone> [gatename] | [-list]")
|
||||
}
|
||||
|
||||
/**
|
||||
* Print error information to the `Traveler`'s chat window.<br>
|
||||
* The most common reason for error is the lack of information, or wrong information.
|
||||
* @param traveler the player
|
||||
*/
|
||||
private def error(traveler : Traveler, msg : String) : Unit = {
|
||||
CSRZone.reply(traveler, "Error! "+msg)
|
||||
}
|
||||
}
|
||||
578
pslogin/src/main/scala/csr/CSRZoneImpl.scala
Normal file
578
pslogin/src/main/scala/csr/CSRZoneImpl.scala
Normal file
|
|
@ -0,0 +1,578 @@
|
|||
package csr
|
||||
|
||||
// Copyright (c) 2017 PSForever
|
||||
import net.psforever.types.Vector3
|
||||
|
||||
import scala.collection.mutable
|
||||
import scala.util.Random
|
||||
|
||||
/*
|
||||
The following is STILL for development and fun.
|
||||
*/
|
||||
/**
|
||||
* A crude representation of the information needed to describe a continent (hitherto, a "zone").
|
||||
* The information is mainly catered to the simulation of the CSR commands `/zone` and `/warp`.
|
||||
* (The exception is `alias` which is maintained for cosmetic purposes and clarification.)
|
||||
* @param alias the common name of the zone
|
||||
* @param map the map name of the zone (this map is loaded)
|
||||
* @param zonename the zone's internal name
|
||||
*/
|
||||
class CSRZoneImpl(val alias : String, val map : String, val zonename : String) {
|
||||
/**
|
||||
* A listing of warpgates, geowarps, and island warpgates in this zone.
|
||||
* The coordinates specified will only ever drop the user on a specific point within the protective bubble of the warpgate.
|
||||
* This breaks from the expected zoning functionality where the user is placed in a random spot under the bubble.
|
||||
* There is no prior usage details for the searchability format of this field's key values.
|
||||
*/
|
||||
private val gates : mutable.HashMap[String, Vector3] = mutable.HashMap()
|
||||
/**
|
||||
* A listing of special locations in this zone, i.e., major faciities, and some landmarks of interest.
|
||||
* There is no prior usage details for the searchability format of this field's key values.
|
||||
*/
|
||||
private val locations : mutable.HashMap[String, Vector3] = mutable.HashMap()
|
||||
}
|
||||
|
||||
object CSRZoneImpl {
|
||||
/**
|
||||
* A listing of all zones that can be visited by their internal name.
|
||||
* The keys in this map should be directly usable by the `/zone` command.
|
||||
*/
|
||||
private val zones = Map[String, CSRZoneImpl](
|
||||
"z1" -> CSRZoneImpl("Solsar", "map01", "z1"),
|
||||
"z2" -> CSRZoneImpl("Hossin", "map02", "z2"),
|
||||
"z3" -> CSRZoneImpl("Cyssor", "map03", "z3"),
|
||||
"z4" -> CSRZoneImpl("Ishundar", "map04", "z4"),
|
||||
"z5" -> CSRZoneImpl("Forseral", "map05", "z5"),
|
||||
"z6" -> CSRZoneImpl("Ceryshen", "map06", "z6"),
|
||||
"z7" -> CSRZoneImpl("Esamir", "map07", "z7"),
|
||||
"z8" -> CSRZoneImpl("Oshur", "map08", "z8"),
|
||||
"z9" -> CSRZoneImpl("Searhus", "map09", "z9"),
|
||||
"z10" -> CSRZoneImpl("Amerish", "map10", "z10"),
|
||||
"home1" -> CSRZoneImpl("NC Sanctuary", "map11", "home1"),
|
||||
"home2" -> CSRZoneImpl("TR Sanctuary", "map12", "home2"),
|
||||
"home3" -> CSRZoneImpl("VS Sanctuary", "map13", "home3"),
|
||||
"tzshtr" -> CSRZoneImpl("VR Shooting Range TR", "map14", "tzshtr"),
|
||||
"tzdrtr" -> CSRZoneImpl("VR Driving Range TR", "map15", "tzdrtr"),
|
||||
"tzcotr" -> CSRZoneImpl("VR Combat csr.CSRZoneImpl TR", "map16", "tzcotr"),
|
||||
"tzshvs" -> CSRZoneImpl("VR Shooting Range VS", "map14", "tzshvs"),
|
||||
"tzdrvs" -> CSRZoneImpl("VR Driving Range VS", "map15", "tzdrvs"),
|
||||
"tzcovs" -> CSRZoneImpl("VR Combat csr.CSRZoneImpl VS", "map16", "tzcovs"),
|
||||
"tzshnc" -> CSRZoneImpl("VR Shooting Range NC", "map14", "tzshnc"),
|
||||
"tzdrnc" -> CSRZoneImpl("VR Driving Range NC", "map15", "tzdrnc"),
|
||||
"tzconc" -> CSRZoneImpl("VR Combat csr.CSRZoneImpl NC", "map16", "tzconc"),
|
||||
"c1" -> CSRZoneImpl("Supai", "ugd01", "c1"),
|
||||
"c2" -> CSRZoneImpl("Hunhau", "ugd02", "c2"),
|
||||
"c3" -> CSRZoneImpl("Adlivun", "ugd03", "c3"),
|
||||
"c4" -> CSRZoneImpl("Byblos", "ugd04", "c4"),
|
||||
"c5" -> CSRZoneImpl("Annwn", "ugd05", "c5"),
|
||||
"c6" -> CSRZoneImpl("Drugaskan", "ugd06", "c6"),
|
||||
"i4" -> CSRZoneImpl("Nexus", "map96", "i4"),
|
||||
"i3" -> CSRZoneImpl("Desolation", "map97", "i3"),
|
||||
"i2" -> CSRZoneImpl("Ascension", "map98", "i2"),
|
||||
"i1" -> CSRZoneImpl("Extinction", "map99", "i1"),
|
||||
"homebo" -> CSRZoneImpl("Black_ops_hq", "Black_ops_hq", "homebo"),
|
||||
"station1" -> CSRZoneImpl("TR Station", "Station1", "station1"),
|
||||
"station2" -> CSRZoneImpl("NC Station", "Station2", "station2"),
|
||||
"station3" -> CSRZoneImpl("VS Station", "Station3", "station3")
|
||||
)
|
||||
/**
|
||||
* A listing of all zones that can be visited by their common name.
|
||||
* The keys in this map should be directly usable by the `/zone` command.
|
||||
* Though the behavior is undocumented, access to this alias list is for the benefit of the user.
|
||||
*/
|
||||
private val alias = Map[String, String](
|
||||
"solsar" -> "z1",
|
||||
"hossin" -> "z2",
|
||||
"cyssor" -> "z3",
|
||||
"ishundar" -> "z4",
|
||||
"forseral" -> "z5",
|
||||
"ceryshen" -> "z6",
|
||||
"esamir" -> "z7",
|
||||
"oshur" -> "z8",
|
||||
"searhus" -> "z9",
|
||||
"amerish" -> "z10",
|
||||
"nc-sanctuary" -> "home1",
|
||||
"tr-sanctuary" -> "home2",
|
||||
"vs-sanctuary" -> "home3",
|
||||
"tr-shooting" -> "tzshtr",
|
||||
"tr-driving" -> "tzdrtr",
|
||||
"tr-combat" -> "tzcotr",
|
||||
"vs-shooting" -> "tzshvs",
|
||||
"vs-driving" -> "tzdrvs",
|
||||
"vs-combat" -> "tzcovs",
|
||||
"nc-shooting" -> "tzshnc",
|
||||
"nc-driving" -> "tzdrnc",
|
||||
"nc-combat" -> "tzconc",
|
||||
"supai" -> "c1",
|
||||
"hunhau" -> "c2",
|
||||
"adlivun" -> "c3",
|
||||
"byblos" -> "c4",
|
||||
"annwn" -> "c5",
|
||||
"drugaskan" -> "c6",
|
||||
"nexus" -> "i4",
|
||||
"desolation" -> "i3",
|
||||
"ascension" -> "i2",
|
||||
"extinction" -> "i1",
|
||||
"Black_ops_hq" -> "homebo",
|
||||
"TR-Station" -> "station1",
|
||||
"NC-Station" -> "station2",
|
||||
"VS-Station" -> "station3"
|
||||
)
|
||||
/**
|
||||
* A value used for selecting where to appear in a zone from the list of locations when the user has no indicated one.
|
||||
*/
|
||||
private val rand = Random
|
||||
setup()
|
||||
|
||||
/**
|
||||
* An abbreviated constructor for creating `CSRZone`s without invocation of `new`.
|
||||
* @param alias the common name of the zone
|
||||
* @param map the map name of the zone (this map is loaded)
|
||||
* @param zonename the zone's internal name
|
||||
*/
|
||||
def apply(alias : String, map : String, zonename : String) : CSRZoneImpl = new CSRZoneImpl(alias, map, zonename)
|
||||
|
||||
/**
|
||||
* Get a valid `CSRZone`'s information.
|
||||
* @param zoneId a name that describes the zone and should be searchable
|
||||
* @return the `CSRZone`, or `None`
|
||||
*/
|
||||
def get(zoneId : String) : Option[CSRZoneImpl] = {
|
||||
var zId = zoneId.toLowerCase
|
||||
if(alias.get(zId).isDefined)
|
||||
zId = alias(zId)
|
||||
zones.get(zId)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a location within the `CSRZone`.
|
||||
* The location should be a facility or a warpgate or interesting.
|
||||
* @param zone the `CSRZone`
|
||||
* @param locId a name that describes a known location in the provided `CSRZone` and is searchable
|
||||
* @return the coordinates of that location, or None
|
||||
*/
|
||||
def getWarpLocation(zone : CSRZoneImpl, locId : String) : Option[Vector3] = {
|
||||
val low_locId = locId.toLowerCase
|
||||
var location = zone.locations.get(low_locId)
|
||||
if(location.isEmpty)
|
||||
location = zone.gates.get(low_locId)
|
||||
location
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the position of a warpgate within the zone.
|
||||
* @param zone the `CSRZone`
|
||||
* @param gateId a name that describes a known warpgate in the provided `CSRZone` and is searchable
|
||||
* @return the coordinates of that warpgate, or None
|
||||
*/
|
||||
def getWarpgate(zone : CSRZoneImpl, gateId : String) : Option[Vector3] = {
|
||||
zone.gates.get(gateId.toLowerCase)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the names for all of the `CSRZones` that can be visited.
|
||||
* @return all of the zonenames
|
||||
*/
|
||||
def list : String = {
|
||||
"zonenames: z1 - z10, home1 - home3, tzshnc, tzdrnc, tzconc, tzshtr, tzdrtr, tzcotr, tzshvs, tzdrvs, tzcovs, c1 - c6, i1 - i4; zones are also aliased to their continent name"
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name for all of the locations that can be visited in this `CSRZone`, excluding warpgates.
|
||||
* @param zone the `CSRZone`
|
||||
* @return all of the location keys
|
||||
*/
|
||||
def listLocations(zone : CSRZoneImpl) : String = {
|
||||
var out : String = "warps: "
|
||||
if(zone.locations.nonEmpty) {
|
||||
out += zone.locations.keys.toArray.sorted.mkString(", ")
|
||||
}
|
||||
else
|
||||
out = "none"
|
||||
out
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name for all of the warpgates that can be visited in this `CSRZone`.
|
||||
* @param zone the `CSRZone`
|
||||
* @return all of the warpgate keys
|
||||
*/
|
||||
def listWarpgates(zone : CSRZoneImpl) : String = {
|
||||
var out : String = "gatenames: "
|
||||
if(zone.gates.isEmpty)
|
||||
out += "none"
|
||||
else
|
||||
out += zone.gates.keys.toArray.sorted.mkString(", ")
|
||||
out
|
||||
}
|
||||
|
||||
/**
|
||||
* Select, of all the `CSRZone` locations and warpgates, a pseudorandom destination to spawn the player in the zone if none has been specified.
|
||||
* @param zone the `CSRZone`
|
||||
* @return the coordinates of the spawn point
|
||||
*/
|
||||
def selectRandom(zone : CSRZoneImpl) : Vector3 = {
|
||||
var outlets = zone.locations //random location?
|
||||
if(outlets.nonEmpty) {
|
||||
return outlets.values.toArray.apply(rand.nextInt(outlets.size))
|
||||
}
|
||||
outlets = zone.gates //random warpgate?
|
||||
if(outlets.nonEmpty) {
|
||||
return outlets.values.toArray.apply(rand.nextInt(outlets.size))
|
||||
}
|
||||
Vector3.Zero //fallback coordinates (that will always be valid)
|
||||
}
|
||||
|
||||
/**
|
||||
* Load all zones with selected places of interest and the coordinates to place the player nearby that given place of interest.
|
||||
* All of these keys should be searchable under the `/warp` command.
|
||||
* Only the warpgate keys are searchable by the `/zone` command.
|
||||
*/
|
||||
def setup() : Unit = {
|
||||
zones("z1").gates += (
|
||||
"gate1" -> Vector3(4150, 7341, 82),
|
||||
"gate2" -> Vector3(5698, 3404, 129),
|
||||
"gate3" -> Vector3(2650, 5363, 176),
|
||||
"gate4" -> Vector3(3022, 1225, 66),
|
||||
"geowarp1" -> Vector3(3678, 2895, 108),
|
||||
"geowarp2" -> Vector3(5672, 4750, 70)
|
||||
)
|
||||
zones("z1").locations += (
|
||||
"amun" -> Vector3(4337, 2278, 68),
|
||||
"aton" -> Vector3(3772, 5463, 54),
|
||||
"bastet" -> Vector3(5412, 5588, 56),
|
||||
"hapi" -> Vector3(4256, 4436, 59),
|
||||
"horus" -> Vector3(3725, 2114, 73),
|
||||
"mont" -> Vector3(3354, 4205, 83),
|
||||
"seth" -> Vector3(4495, 6026, 58),
|
||||
"sobek" -> Vector3(3094, 3027, 75),
|
||||
"thoth" -> Vector3(4615, 3373, 53),
|
||||
"lake" -> Vector3(4317, 4008, 37),
|
||||
"monolith" -> Vector3(5551, 5047, 64)
|
||||
)
|
||||
zones("z2").gates += (
|
||||
"gate1" -> Vector3(1881, 4873, 19),
|
||||
"gate2" -> Vector3(4648, 4625, 28),
|
||||
"gate3" -> Vector3(3296, 2045, 21),
|
||||
"gate4" -> Vector3(5614, 1781, 32),
|
||||
"geowarp1" -> Vector3(5199, 4869, 39),
|
||||
"geowarp2" -> Vector3(3911, 2407, 15)
|
||||
)
|
||||
zones("z2").locations += (
|
||||
"acan" -> Vector3(3534, 4015, 30),
|
||||
"bitol" -> Vector3(4525, 2632, 30),
|
||||
"chac" -> Vector3(4111, 5950, 39),
|
||||
"ghanon" -> Vector3(2565, 3707, 41),
|
||||
"hurakan" -> Vector3(1840, 2934, 38),
|
||||
"ixtab" -> Vector3(3478, 3143, 40),
|
||||
"kisin" -> Vector3(3356, 5374, 31),
|
||||
"mulac" -> Vector3(5592, 2738, 37),
|
||||
"naum" -> Vector3(5390, 3454, 28),
|
||||
"voltan" -> Vector3(4529, 3414, 28),
|
||||
"zotz" -> Vector3(6677, 2342, 129),
|
||||
"monolith" -> Vector3(2938, 2485, 14)
|
||||
)
|
||||
zones("z3").gates += (
|
||||
"gate1" -> Vector3(2616, 6567, 58),
|
||||
"gate2" -> Vector3(6980, 5336, 57),
|
||||
"gate3" -> Vector3(1199, 1332, 66),
|
||||
"gate4" -> Vector3(5815, 1974, 63),
|
||||
"geowarp1" -> Vector3(2403, 4278, 60),
|
||||
"geowarp2" -> Vector3(4722, 2665, 78)
|
||||
)
|
||||
zones("z3").locations += (
|
||||
"aja" -> Vector3(754, 5435, 48),
|
||||
"chuku" -> Vector3(4208, 7021, 54),
|
||||
"bomazi" -> Vector3(1198, 4492, 58),
|
||||
"ekera" -> Vector3(5719, 6555, 51),
|
||||
"faro" -> Vector3(5030, 5700, 57),
|
||||
"gunuku" -> Vector3(4994, 4286, 54),
|
||||
"honsi" -> Vector3(4042, 4588, 89),
|
||||
"itan" -> Vector3(5175, 3393, 48),
|
||||
"kaang" -> Vector3(5813, 3862, 62),
|
||||
"leza" -> Vector3(2691, 1561, 64),
|
||||
"mukuru" -> Vector3(661, 2380, 54),
|
||||
"nzame" -> Vector3(1670, 2706, 45),
|
||||
"orisha" -> Vector3(7060, 1327, 59),
|
||||
"pamba" -> Vector3(7403, 3123, 63),
|
||||
"shango" -> Vector3(6846, 2319, 63),
|
||||
"tore" -> Vector3(3017, 2272, 58),
|
||||
"wele" -> Vector3(436, 7040, 60),
|
||||
"monolith" -> Vector3(4515, 4105, 38),
|
||||
"peak" -> Vector3(3215, 5063, 579)
|
||||
)
|
||||
zones("z4").gates += (
|
||||
"gate1" -> Vector3(4702, 6768, 30),
|
||||
"gate2" -> Vector3(5515, 3368, 69),
|
||||
"gate3" -> Vector3(1564, 3356, 46),
|
||||
"gate4" -> Vector3(3889, 1118, 56),
|
||||
"geowarp1" -> Vector3(4202, 4325, 68),
|
||||
"geowarp2" -> Vector3(2384, 1925, 37)
|
||||
)
|
||||
zones("z4").locations += (
|
||||
"akkan" -> Vector3(2746, 4260, 39),
|
||||
"baal" -> Vector3(825, 5470, 72),
|
||||
"dagon" -> Vector3(1739, 5681, 40),
|
||||
"enkidu" -> Vector3(3217, 3574, 37),
|
||||
"girru" -> Vector3(4475, 5853, 78),
|
||||
"hanish" -> Vector3(3794, 5540, 89),
|
||||
"irkall" -> Vector3(4742, 5270, 66),
|
||||
"kusag" -> Vector3(6532, 4692, 46),
|
||||
"lahar" -> Vector3(6965, 5306, 38),
|
||||
"marduk" -> Vector3(3059, 2144, 70),
|
||||
"neti" -> Vector3(3966, 2417, 80),
|
||||
"zaqar" -> Vector3(4796, 2177, 75),
|
||||
"monolith" -> Vector3(5165, 4083, 35),
|
||||
"stonehenge" -> Vector3(4992, 3776, 56)
|
||||
)
|
||||
zones("z5").gates += (
|
||||
"gate1" -> Vector3(3432, 6498, 73),
|
||||
"gate2" -> Vector3(7196, 3917, 47),
|
||||
"gate3" -> Vector3(1533, 3540, 56),
|
||||
"gate4" -> Vector3(3197, 1390, 45),
|
||||
"geowarp1" -> Vector3(4899, 5633, 38),
|
||||
"geowarp2" -> Vector3(5326, 2558, 54)
|
||||
)
|
||||
zones("z5").locations += (
|
||||
"anu" -> Vector3(3479, 2556, 56),
|
||||
"bel" -> Vector3(3665, 4626, 58),
|
||||
"caer" -> Vector3(4570, 2601, 56),
|
||||
"dagd" -> Vector3(5825, 4449, 55),
|
||||
"eadon" -> Vector3(2725, 2853, 53),
|
||||
"gwydion" -> Vector3(5566, 3739, 61),
|
||||
"lugh" -> Vector3(6083, 5069, 72),
|
||||
"neit" -> Vector3(4345, 4319, 76),
|
||||
"ogma" -> Vector3(3588, 3227, 114),
|
||||
"pwyll" -> Vector3(4683, 4764, 104),
|
||||
"monolith" -> Vector3(3251, 3245, 160),
|
||||
"islands1" -> Vector3(6680, 6217, 125),
|
||||
"islands2" -> Vector3(1059, 6213, 120)
|
||||
)
|
||||
zones("z6").gates += (
|
||||
"gate1" -> Vector3(5040, 4327, 46),
|
||||
"gate2" -> Vector3(2187, 5338, 30),
|
||||
"gate3" -> Vector3(4960, 1922, 15),
|
||||
"gate4" -> Vector3(2464, 3088, 189),
|
||||
"geowarp1" -> Vector3(3221, 5328, 242),
|
||||
"geowarp2" -> Vector3(2237, 1783, 238)
|
||||
)
|
||||
zones("z6").locations += (
|
||||
"akna" -> Vector3(4509, 3732, 219),
|
||||
"anguta" -> Vector3(3999, 4170, 266),
|
||||
"igaluk" -> Vector3(3241, 5658, 235),
|
||||
"keelut" -> Vector3(3630, 1904, 265),
|
||||
"nerrivik" -> Vector3(3522, 3703, 322),
|
||||
"pinga" -> Vector3(5938, 3545, 96),
|
||||
"sedna" -> Vector3(3932, 5160, 232),
|
||||
"tarqaq" -> Vector3(2980, 2155, 237),
|
||||
"tootega" -> Vector3(5171, 3251, 217),
|
||||
"monolith" -> Vector3(4011, 4851, 32),
|
||||
"bridge" -> Vector3(3729, 4859, 234)
|
||||
)
|
||||
zones("z7").gates += (
|
||||
"gate1" -> Vector3(1516, 6448, 61),
|
||||
"gate2" -> Vector3(5249, 3819, 69),
|
||||
"gate3" -> Vector3(2763, 2961, 86),
|
||||
"gate4" -> Vector3(6224, 1152, 78),
|
||||
"geowarp1" -> Vector3(6345, 4802, 90),
|
||||
"geowarp2" -> Vector3(3800, 2197, 64)
|
||||
)
|
||||
zones("z7").locations += (
|
||||
"andvari" -> Vector3(3233, 7207, 78),
|
||||
"dagur" -> Vector3(4026, 6191, 60),
|
||||
"eisa" -> Vector3(3456, 4513, 75),
|
||||
"freyr" -> Vector3(2853, 3840, 56),
|
||||
"gjallar" -> Vector3(1056, 2656, 74),
|
||||
"helheim" -> Vector3(5542, 2532, 53),
|
||||
"jarl" -> Vector3(1960, 5462, 68),
|
||||
"kvasir" -> Vector3(4096, 1571, 69),
|
||||
"mani" -> Vector3(5057, 4989, 58),
|
||||
"nott" -> Vector3(6783, 4329, 46),
|
||||
"ran" -> Vector3(2378, 1919, 85),
|
||||
"vidar" -> Vector3(3772, 3024, 67),
|
||||
"ymir" -> Vector3(1911, 4008, 69),
|
||||
"monolith" -> Vector3(6390, 1622, 63)
|
||||
)
|
||||
zones("z8").gates += (
|
||||
"gate1" -> Vector3(5437, 5272, 32),
|
||||
"gate2" -> Vector3(3251, 5650, 60),
|
||||
"gate3" -> Vector3(5112, 2616, 40),
|
||||
"gate4" -> Vector3(2666, 1665, 45),
|
||||
"geowarp1" -> Vector3(3979, 5370, 47),
|
||||
"geowarp2" -> Vector3(6018, 3136, 35)
|
||||
)
|
||||
zones("z8").locations += (
|
||||
"atar" -> Vector3(3609, 2730, 47),
|
||||
"dahaka" -> Vector3(4633, 5379, 54),
|
||||
"hvar" -> Vector3(3857, 4764, 49),
|
||||
"izha" -> Vector3(5396, 3852, 51),
|
||||
"jamshid" -> Vector3(2371, 3378, 52),
|
||||
"mithra" -> Vector3(2480, 4456, 44),
|
||||
"rashnu" -> Vector3(3098, 3961, 59),
|
||||
"yazata" -> Vector3(4620, 3983, 62),
|
||||
"zal" -> Vector3(3966, 2164, 61),
|
||||
"arch1" -> Vector3(4152, 3285, 31),
|
||||
"arch2" -> Vector3(4688, 5272, 68),
|
||||
"pride" -> Vector3(2913, 4412, 63)
|
||||
)
|
||||
zones("z9").gates += (
|
||||
"gate1" -> Vector3(1505, 6981, 65),
|
||||
"gate2" -> Vector3(6835, 3517, 56),
|
||||
"gate3" -> Vector3(1393, 1376, 53),
|
||||
"geowarp1" -> Vector3(7081, 5552, 46),
|
||||
"geowarp2" -> Vector3(3776, 1092, 49)
|
||||
)
|
||||
zones("z9").locations += (
|
||||
"akua" -> Vector3(5258, 4041, 346),
|
||||
"drakulu" -> Vector3(3806, 2647, 151),
|
||||
"hiro" -> Vector3(4618, 5761, 190),
|
||||
"iva" -> Vector3(6387, 5199, 55),
|
||||
"karihi" -> Vector3(3879, 5574, 236),
|
||||
"laka" -> Vector3(4720, 6718, 49),
|
||||
"matagi" -> Vector3(5308, 5093, 239),
|
||||
"ngaru" -> Vector3(4103, 4077, 205),
|
||||
"oro" -> Vector3(4849, 4456, 208),
|
||||
"pele" -> Vector3(4549, 3712, 208),
|
||||
"rehua" -> Vector3(3843, 2195, 60),
|
||||
"sina" -> Vector3(5919, 2177, 91),
|
||||
"tara" -> Vector3(1082, 4225, 60),
|
||||
"wakea" -> Vector3(1785, 5241, 63),
|
||||
"monolith" -> Vector3(3246, 6507, 105)
|
||||
)
|
||||
zones("z10").gates += (
|
||||
"gate1" -> Vector3(6140, 6599, 71),
|
||||
"gate2" -> Vector3(4814, 4608, 59),
|
||||
"gate3" -> Vector3(3152, 3480, 54),
|
||||
"gate4" -> Vector3(1605, 1446, 40),
|
||||
"geowarp1" -> Vector3(3612, 6918, 38),
|
||||
"geowarp2" -> Vector3(3668, 3327, 55)
|
||||
)
|
||||
zones("z10").locations += (
|
||||
"azeban" -> Vector3(6316, 5160, 62),
|
||||
"cetan" -> Vector3(3587, 2522, 48),
|
||||
"heyoka" -> Vector3(4395, 2327, 47),
|
||||
"ikanam" -> Vector3(2740, 2412, 57),
|
||||
"kyoi" -> Vector3(5491, 2284, 62),
|
||||
"mekala" -> Vector3(6087, 2925, 59),
|
||||
"onatha" -> Vector3(3397, 5799, 48),
|
||||
"qumu" -> Vector3(3990, 5152, 46),
|
||||
"sungrey" -> Vector3(4609, 5624, 72),
|
||||
"tumas" -> Vector3(4687, 6392, 69),
|
||||
"verica" -> Vector3(4973, 3459, 47),
|
||||
"xelas" -> Vector3(6609, 4479, 56),
|
||||
"monolith" -> Vector3(5651, 6024, 38)
|
||||
)
|
||||
zones("home1").gates += (
|
||||
"gate1" -> Vector3(4158, 6344, 44),
|
||||
"gate2" -> Vector3(2214, 5797, 48),
|
||||
"gate3" -> Vector3(5032, 3241, 53)
|
||||
)
|
||||
zones("home1").locations += "hart_c" -> Vector3(2352, 5523, 66)
|
||||
zones("home2").gates += (
|
||||
"gate1" -> Vector3(5283, 4317, 44),
|
||||
"gate2" -> Vector3(3139, 4809, 40),
|
||||
"gate3" -> Vector3(3659, 2894, 26)
|
||||
)
|
||||
zones("home2").locations += "hart_c" -> Vector3(3125, 2864, 35)
|
||||
zones("home3").gates += (
|
||||
"gate1" -> Vector3(5657, 4681, 98),
|
||||
"gate2" -> Vector3(2639, 5366, 57),
|
||||
"gate3" -> Vector3(4079, 2467, 155)
|
||||
)
|
||||
zones("home3").locations += "hart_c" -> Vector3(3675, 2727, 91)
|
||||
zones("tzshtr").locations += "roof" -> Vector3(499, 1568, 25)
|
||||
zones("tzcotr").locations += "spawn" -> Vector3(960, 1002, 32)
|
||||
zones("tzdrtr").locations += (
|
||||
"start" -> Vector3(2457, 1864, 23),
|
||||
"air_pad" -> Vector3(1700, 1900, 32)
|
||||
)
|
||||
zones("tzshvs").locations += "roof" -> Vector3(499, 1568, 25)
|
||||
zones("tzcovs").locations += "spawn" -> Vector3(960, 1002, 32)
|
||||
zones("tzdrvs").locations += (
|
||||
"start" -> Vector3(2457, 1864, 23),
|
||||
"air_pad" -> Vector3(1700, 1900, 32)
|
||||
)
|
||||
zones("tzshnc").locations += "roof" -> Vector3(499, 1568, 25)
|
||||
zones("tzconc").locations += "spawn" -> Vector3(960, 1002, 32)
|
||||
zones("tzdrnc").locations += (
|
||||
"start" -> Vector3(2457, 1864, 23),
|
||||
"air_pad" -> Vector3(1700, 1900, 32)
|
||||
)
|
||||
zones("c1").gates += (
|
||||
"geowarp1" -> Vector3(998, 2038, 103),
|
||||
"geowarp2" -> Vector3(231, 1026, 82),
|
||||
"geowarp3" -> Vector3(2071, 1405, 102),
|
||||
"geowarp4" -> Vector3(1051, 370, 103)
|
||||
)
|
||||
zones("c2").gates += (
|
||||
"geowarp1" -> Vector3(999, 2386, 243),
|
||||
"geowarp2" -> Vector3(283, 1249, 172),
|
||||
"geowarp3" -> Vector3(1887, 1307, 192),
|
||||
"geowarp4" -> Vector3(1039, 155, 143)
|
||||
)
|
||||
zones("c3").gates += (
|
||||
"geowarp1" -> Vector3(1095, 1725, 25),
|
||||
"geowarp2" -> Vector3(226, 832, 42),
|
||||
"geowarp3" -> Vector3(1832, 1026, 43),
|
||||
"geowarp4" -> Vector3(981, 320, 46)
|
||||
)
|
||||
zones("c4").gates += (
|
||||
"geowarp1" -> Vector3(902, 1811, 93),
|
||||
"geowarp2" -> Vector3(185, 922, 113),
|
||||
"geowarp3" -> Vector3(1696, 1188, 92),
|
||||
"geowarp4" -> Vector3(887, 227, 115)
|
||||
)
|
||||
zones("c5").gates += (
|
||||
"geowarp1" -> Vector3(1195, 1752, 244),
|
||||
"geowarp2" -> Vector3(290, 1104, 235),
|
||||
"geowarp3" -> Vector3(1803, 899, 243),
|
||||
"geowarp4" -> Vector3(1042, 225, 246)
|
||||
)
|
||||
zones("c6").gates += (
|
||||
"geowarp1" -> Vector3(1067, 2044, 95),
|
||||
"geowarp2" -> Vector3(290, 693, 73),
|
||||
"geowarp3" -> Vector3(1922, 928, 33),
|
||||
"geowarp4" -> Vector3(1174, 249, 114)
|
||||
)
|
||||
zones("i3").gates += (
|
||||
"gate1" -> Vector3(1219, 2580, 30),
|
||||
"gate2" -> Vector3(2889, 2919, 33),
|
||||
"gate3" -> Vector3(2886, 1235, 32)
|
||||
)
|
||||
zones("i3").locations += (
|
||||
"dahaka" -> Vector3(1421, 2216, 30),
|
||||
"jamshid" -> Vector3(2500, 2543, 30),
|
||||
"izha" -> Vector3(2569, 1544, 30),
|
||||
"oasis" -> Vector3(2084, 1935, 40)
|
||||
)
|
||||
zones("i2").gates += (
|
||||
"gate1" -> Vector3(1243, 1393, 12),
|
||||
"gate2" -> Vector3(2510, 2544, 12),
|
||||
"gate3" -> Vector3(2634, 1477, 12)
|
||||
)
|
||||
zones("i2").locations += (
|
||||
"rashnu" -> Vector3(1709, 1802, 91),
|
||||
"sraosha" -> Vector3(2729, 2349, 91),
|
||||
"zal" -> Vector3(1888, 2728, 91),
|
||||
"center" -> Vector3(2082, 2192, 160),
|
||||
"vpad" -> Vector3(1770, 2686, 92)
|
||||
)
|
||||
zones("i1").gates += (
|
||||
"gate1" -> Vector3(1225, 2036, 67),
|
||||
"gate2" -> Vector3(2548, 2801, 65),
|
||||
"gate3" -> Vector3(2481, 1194, 89)
|
||||
)
|
||||
zones("i1").locations += (
|
||||
"hvar" -> Vector3(1559, 1268, 88),
|
||||
"mithra" -> Vector3(2855, 2850, 89),
|
||||
"yazata" -> Vector3(1254, 2583, 88),
|
||||
"south_of_volcano" -> Vector3(2068, 1686, 88)
|
||||
)
|
||||
zones("i4").gates += (
|
||||
"gate1" -> Vector3(2359, 2717, 36),
|
||||
"gate2" -> Vector3(2732, 1355, 36),
|
||||
"geowarp" -> Vector3(1424, 1640, 45)
|
||||
)
|
||||
zones("i4").locations += "atar" -> Vector3(1915, 1936, 43)
|
||||
}
|
||||
}
|
||||
37
pslogin/src/main/scala/csr/Traveler.scala
Normal file
37
pslogin/src/main/scala/csr/Traveler.scala
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
package csr
|
||||
|
||||
// Copyright (c) 2017 PSForever
|
||||
import akka.actor.ActorRef
|
||||
import net.psforever.packet.PlanetSidePacketContainer
|
||||
|
||||
/*
|
||||
The following is STILL for development and fun.
|
||||
*/
|
||||
/**
|
||||
* The traveler is synonymous with the player.
|
||||
* The primary purpose of the object is to keep track of but not expose the player's session so that packets may be relayed back to him.
|
||||
* csr.Traveler also keeps track of which zone the player currently occupies.
|
||||
* @param session the player's session
|
||||
*/
|
||||
class Traveler(private val session : ActorRef, var zone : String) {
|
||||
/**
|
||||
* `sendToSelf` is a call that permits the session to gain access to its internal `rightRef` so that it can dispatch a packet.
|
||||
* @param msg the byte-code translation of a packet
|
||||
*/
|
||||
def sendToSelf(msg : PlanetSidePacketContainer) : Unit = {
|
||||
// this.session.sendResponse(msg)
|
||||
}
|
||||
|
||||
def !(msg : Any) : Unit = {
|
||||
session ! msg
|
||||
}
|
||||
}
|
||||
|
||||
object Traveler {
|
||||
/**
|
||||
* An abbreviated constructor for creating `csr.Traveler`s without invocation of `new`.
|
||||
* @param session the player's session
|
||||
* @return a traveler object for this player
|
||||
*/
|
||||
def apply(session : ActorRef, zoneId : String) : Traveler = new Traveler(session, zoneId)
|
||||
}
|
||||
|
|
@ -16,6 +16,7 @@ object VehicleAction {
|
|||
final case class DeployRequest(player_guid : PlanetSideGUID, object_guid : PlanetSideGUID, state : DriveState.Value, unk1 : Int, unk2 : Boolean, pos : Vector3) extends Action
|
||||
final case class DismountVehicle(player_guid : PlanetSideGUID, bailType : BailType.Value, unk2 : Boolean) extends Action
|
||||
final case class InventoryState(player_guid : PlanetSideGUID, obj : PlanetSideGameObject, parent_guid : PlanetSideGUID, start : Int, con_data : ConstructorData) extends Action
|
||||
final case class InventoryState2(player_guid : PlanetSideGUID, obj_guid : PlanetSideGUID, parent_guid : PlanetSideGUID, value : Int) extends Action
|
||||
final case class KickPassenger(player_guid : PlanetSideGUID, unk1 : Int, unk2 : Boolean, vehicle_guid : PlanetSideGUID) extends Action
|
||||
final case class LoadVehicle(player_guid : PlanetSideGUID, vehicle : Vehicle, vtype : Int, vguid : PlanetSideGUID, vdata : ConstructorData) extends Action
|
||||
final case class MountVehicle(player_guid : PlanetSideGUID, object_guid : PlanetSideGUID, seat : Int) extends Action
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ object VehicleResponse {
|
|||
final case class DetachFromRails(vehicle_guid : PlanetSideGUID, rails_guid : PlanetSideGUID, rails_pos : Vector3, rails_rot : Float) extends Response
|
||||
final case class DismountVehicle(bailType : BailType.Value , unk2 : Boolean) extends Response
|
||||
final case class InventoryState(obj : PlanetSideGameObject, parent_guid : PlanetSideGUID, start : Int, con_data : ConstructorData) extends Response
|
||||
final case class InventoryState2(obj_guid : PlanetSideGUID, parent_guid : PlanetSideGUID, value : Int) extends Response
|
||||
final case class KickPassenger(seat_num : Int, kickedByDriver : Boolean, vehicle_guid : PlanetSideGUID) extends Response
|
||||
final case class LoadVehicle(vehicle : Vehicle, vtype : Int, vguid : PlanetSideGUID, vdata : ConstructorData) extends Response
|
||||
final case class MountVehicle(object_guid : PlanetSideGUID, seat : Int) extends Response
|
||||
|
|
|
|||
|
|
@ -60,6 +60,10 @@ class VehicleService extends Actor {
|
|||
VehicleEvents.publish(
|
||||
VehicleServiceResponse(s"/$forChannel/Vehicle", player_guid, VehicleResponse.InventoryState(obj, parent_guid, start, con_data))
|
||||
)
|
||||
case VehicleAction.InventoryState2(player_guid, obj_guid, parent_guid, value) =>
|
||||
VehicleEvents.publish(
|
||||
VehicleServiceResponse(s"/$forChannel/Vehicle", player_guid, VehicleResponse.InventoryState2(obj_guid, parent_guid, value))
|
||||
)
|
||||
case VehicleAction.KickPassenger(player_guid, seat_num, kickedByDriver, vehicle_guid) =>
|
||||
VehicleEvents.publish(
|
||||
VehicleServiceResponse(s"/$forChannel/Vehicle", player_guid, VehicleResponse.KickPassenger(seat_num, kickedByDriver, vehicle_guid))
|
||||
|
|
|
|||
|
|
@ -136,6 +136,22 @@ class InventoryStateTest extends ActorTest {
|
|||
}
|
||||
}
|
||||
|
||||
class InventoryState2Test extends ActorTest {
|
||||
ServiceManager.boot(system)
|
||||
val tool = Tool(GlobalDefinitions.beamer)
|
||||
tool.AmmoSlots.head.Box.GUID = PlanetSideGUID(13)
|
||||
val cdata = tool.Definition.Packet.ConstructorData(tool).get
|
||||
|
||||
"VehicleService" should {
|
||||
"pass InventoryState2" in {
|
||||
val service = system.actorOf(Props[VehicleService], "v-service")
|
||||
service ! Service.Join("test")
|
||||
service ! VehicleServiceMessage("test", VehicleAction.InventoryState2(PlanetSideGUID(10), PlanetSideGUID(11), PlanetSideGUID(12), 13))
|
||||
expectMsg(VehicleServiceResponse("/test/Vehicle", PlanetSideGUID(10), VehicleResponse.InventoryState2(PlanetSideGUID(11), PlanetSideGUID(12), 13)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class KickPassengerTest extends ActorTest {
|
||||
ServiceManager.boot(system)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue