mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-03-08 06:50:31 +00:00
changing continent id and building id to normal data types in BroadcastWarpgateUpdate and BuildingInfoUpdate; implementing warp gates and branched logic for warp gate initialization in WSA; updating tests
This commit is contained in:
parent
f0bec9cf3a
commit
33a7636f5e
9 changed files with 176 additions and 83 deletions
|
|
@ -0,0 +1,22 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package net.psforever.objects.serverobject.structures
|
||||
|
||||
import akka.actor.ActorContext
|
||||
import net.psforever.objects.zones.Zone
|
||||
|
||||
class WarpGate(id : Int, zone : Zone) extends Building(id, zone) {
|
||||
//TODO stuff later
|
||||
}
|
||||
|
||||
object WarpGate {
|
||||
def apply(id : Int, zone : Zone) : WarpGate = {
|
||||
new WarpGate(id, zone)
|
||||
}
|
||||
|
||||
def Structure(id : Int, zone : Zone, context : ActorContext) : WarpGate = {
|
||||
import akka.actor.Props
|
||||
val obj = new WarpGate(id, zone)
|
||||
obj.Actor = context.actorOf(Props(classOf[BuildingControl], obj), s"$id-gate")
|
||||
obj
|
||||
}
|
||||
}
|
||||
|
|
@ -17,17 +17,17 @@ import scodec.codecs._
|
|||
* I believe these `Boolean` values actually indicate some measure of warpgate operation.
|
||||
* Geowarps, for example, though their appearance does not change, recieve this packet.
|
||||
* Moreover, they can operate as a receiving-end broadcast gate.
|
||||
* @param continent_guid identifies the zone (continent)
|
||||
* @param building_guid identifies the warpgate (see `BuildingInfoUpdateMessage`)
|
||||
* @param continent_id the zone
|
||||
* @param building_id the warp gate (see `BuildingInfoUpdateMessage`)
|
||||
* @param unk1 na
|
||||
* @param unk2 na
|
||||
* @param is_broadcast if true, the gate replaces its destination text with "Broadcast"
|
||||
* @param broadcast if true, the gate replaces its destination text with "Broadcast"
|
||||
*/
|
||||
final case class BroadcastWarpgateUpdateMessage(continent_guid : PlanetSideGUID,
|
||||
building_guid : PlanetSideGUID,
|
||||
final case class BroadcastWarpgateUpdateMessage(continent_id : Int,
|
||||
building_id : Int,
|
||||
unk1 : Boolean,
|
||||
unk2 : Boolean,
|
||||
is_broadcast : Boolean)
|
||||
broadcast : Boolean)
|
||||
extends PlanetSideGamePacket {
|
||||
type Packet = BroadcastWarpgateUpdateMessage
|
||||
def opcode = GamePacketOpcode.BroadcastWarpgateUpdateMessage
|
||||
|
|
@ -36,10 +36,10 @@ final case class BroadcastWarpgateUpdateMessage(continent_guid : PlanetSideGUID,
|
|||
|
||||
object BroadcastWarpgateUpdateMessage extends Marshallable[BroadcastWarpgateUpdateMessage] {
|
||||
implicit val codec : Codec[BroadcastWarpgateUpdateMessage] = (
|
||||
("continent_guid" | PlanetSideGUID.codec) ::
|
||||
("building_guid" | PlanetSideGUID.codec) ::
|
||||
("continent_id" | uint16L) ::
|
||||
("building_id" | uint16L) ::
|
||||
("unk1" | bool) ::
|
||||
("unk2" | bool) ::
|
||||
("is_broadcast" | bool)
|
||||
("broadcast" | bool)
|
||||
).as[BroadcastWarpgateUpdateMessage]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,8 +87,8 @@ final case class Additional3(unk1 : Boolean,
|
|||
* 064 - Health Module<br>
|
||||
* 128 - Pain Module<br>
|
||||
* `
|
||||
* @param continent_guid the continent (zone)
|
||||
* @param building_guid the building
|
||||
* @param continent_id the continent (zone)
|
||||
* @param building_id the building
|
||||
* @param ntu_level if the building has a silo, the amount of NTU in that silo;
|
||||
* NTU is reported in multiples of 10%;
|
||||
* valid for 0 (0%) to 10 (100%)
|
||||
|
|
@ -117,8 +117,8 @@ final case class Additional3(unk1 : Boolean,
|
|||
* @param boost_spawn_pain if the building has spawn tubes, the (boosted) strength of its enemy pain field
|
||||
* @param boost_generator_pain if the building has a generator, the (boosted) strength of its enemy pain field
|
||||
*/
|
||||
final case class BuildingInfoUpdateMessage(continent_guid : PlanetSideGUID,
|
||||
building_guid : PlanetSideGUID,
|
||||
final case class BuildingInfoUpdateMessage(continent_id : Int,
|
||||
building_id : Int,
|
||||
ntu_level : Int,
|
||||
is_hacked : Boolean,
|
||||
empire_hack : PlanetSideEmpire.Value,
|
||||
|
|
@ -171,8 +171,8 @@ object BuildingInfoUpdateMessage extends Marshallable[BuildingInfoUpdateMessage]
|
|||
).as[Additional3]
|
||||
|
||||
implicit val codec : Codec[BuildingInfoUpdateMessage] = (
|
||||
("continent_guid" | PlanetSideGUID.codec) ::
|
||||
("building_guid" | PlanetSideGUID.codec) ::
|
||||
("continent_id" | uint16L) ::
|
||||
("building_id" | uint16L) ::
|
||||
("ntu_level" | uint4L) ::
|
||||
("is_hacked" | bool ) ::
|
||||
("empire_hack" | PlanetSideEmpire.codec) ::
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@ class BroadcastWarpgateUpdateMessageTest extends Specification {
|
|||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case BroadcastWarpgateUpdateMessage(continent_guid, building_guid, state1, state2, state3) =>
|
||||
continent_guid mustEqual PlanetSideGUID(13)
|
||||
building_guid mustEqual PlanetSideGUID(1)
|
||||
continent_guid mustEqual 13
|
||||
building_guid mustEqual 1
|
||||
state1 mustEqual false
|
||||
state2 mustEqual false
|
||||
state3 mustEqual true
|
||||
|
|
@ -23,7 +23,7 @@ class BroadcastWarpgateUpdateMessageTest extends Specification {
|
|||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = BroadcastWarpgateUpdateMessage(PlanetSideGUID(13), PlanetSideGUID(1), false, false, true)
|
||||
val msg = BroadcastWarpgateUpdateMessage(13, 1, false, false, true)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
|
|
|
|||
|
|
@ -12,29 +12,29 @@ class BuildingInfoUpdateMessageTest extends Specification {
|
|||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case BuildingInfoUpdateMessage(continent_guid : PlanetSideGUID,
|
||||
building_guid : PlanetSideGUID,
|
||||
ntu_level : Int,
|
||||
is_hacked : Boolean,
|
||||
empire_hack : PlanetSideEmpire.Value,
|
||||
hack_time_remaining : Long,
|
||||
empire_own : PlanetSideEmpire.Value,
|
||||
unk1 : Long,
|
||||
unk1x : Option[Additional1],
|
||||
generator_state : PlanetSideGeneratorState.Value,
|
||||
spawn_tubes_normal : Boolean,
|
||||
force_dome_active : Boolean,
|
||||
lattice_benefit : Int,
|
||||
unk3 : Int,
|
||||
unk4 : List[Additional2],
|
||||
unk5 : Long,
|
||||
unk6 : Boolean,
|
||||
unk7 : Int,
|
||||
unk7x : Option[Additional3],
|
||||
boost_spawn_pain : Boolean,
|
||||
boost_generator_pain : Boolean) =>
|
||||
continent_guid mustEqual PlanetSideGUID(4)
|
||||
building_guid mustEqual PlanetSideGUID(9)
|
||||
case BuildingInfoUpdateMessage(continent_guid,
|
||||
building_guid,
|
||||
ntu_level,
|
||||
is_hacked,
|
||||
empire_hack,
|
||||
hack_time_remaining,
|
||||
empire_own,
|
||||
unk1,
|
||||
unk1x,
|
||||
generator_state,
|
||||
spawn_tubes_normal,
|
||||
force_dome_active,
|
||||
lattice_benefit,
|
||||
unk3,
|
||||
unk4,
|
||||
unk5,
|
||||
unk6,
|
||||
unk7,
|
||||
unk7x,
|
||||
boost_spawn_pain,
|
||||
boost_generator_pain) =>
|
||||
continent_guid mustEqual 4
|
||||
building_guid mustEqual 9
|
||||
ntu_level mustEqual 1
|
||||
is_hacked mustEqual false
|
||||
empire_hack mustEqual PlanetSideEmpire.NEUTRAL
|
||||
|
|
@ -61,8 +61,8 @@ class BuildingInfoUpdateMessageTest extends Specification {
|
|||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = BuildingInfoUpdateMessage(PlanetSideGUID(4),
|
||||
PlanetSideGUID(9),
|
||||
val msg = BuildingInfoUpdateMessage(4,
|
||||
9,
|
||||
1,
|
||||
false,
|
||||
PlanetSideEmpire.NEUTRAL,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import net.psforever.objects.GlobalDefinitions
|
|||
import net.psforever.objects.definition.ObjectDefinition
|
||||
import net.psforever.objects.serverobject.affinity.FactionAffinity
|
||||
import net.psforever.objects.serverobject.doors.{Door, DoorControl}
|
||||
import net.psforever.objects.serverobject.structures.{Amenity, Building, BuildingControl}
|
||||
import net.psforever.objects.serverobject.structures.{Amenity, Building, BuildingControl, WarpGate}
|
||||
import net.psforever.objects.zones.Zone
|
||||
import net.psforever.packet.game.PlanetSideGUID
|
||||
import net.psforever.types.PlanetSideEmpire
|
||||
|
|
@ -98,6 +98,19 @@ class BuildingTest extends Specification {
|
|||
}
|
||||
}
|
||||
|
||||
class WarpGateTest extends Specification {
|
||||
"WarpGate" should {
|
||||
"construct" in {
|
||||
val bldg = WarpGate(10, Zone.Nowhere)
|
||||
bldg.Id mustEqual 10
|
||||
bldg.Actor mustEqual ActorRef.noSender
|
||||
bldg.Amenities mustEqual Nil
|
||||
bldg.Zone mustEqual Zone.Nowhere
|
||||
bldg.Faction mustEqual PlanetSideEmpire.NEUTRAL
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class BuildingControl1Test extends ActorTest {
|
||||
"Building Control" should {
|
||||
"construct" in {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import akka.actor.{Actor, Props}
|
||||
import akka.actor.{Actor, ActorContext, Props}
|
||||
import net.psforever.objects.guid.NumberPoolHub
|
||||
import net.psforever.packet.game.PlanetSideGUID
|
||||
import net.psforever.objects.serverobject.ServerObjectBuilder
|
||||
import net.psforever.objects.serverobject.structures.{Building, FoundationBuilder}
|
||||
import net.psforever.objects.serverobject.structures.{Building, FoundationBuilder, WarpGate}
|
||||
import net.psforever.objects.zones.Zone
|
||||
import net.psforever.types.Vector3
|
||||
|
||||
|
|
@ -14,7 +14,23 @@ import scala.concurrent.duration.Duration
|
|||
class BuildingBuilderTest extends ActorTest {
|
||||
"Building object" should {
|
||||
"build" in {
|
||||
val actor = system.actorOf(Props(classOf[ServerObjectBuilderTest.BuildingTestActor], 10, Zone.Nowhere), "building")
|
||||
val structure : (Int,Zone,ActorContext)=>Building = Building.Structure
|
||||
val actor = system.actorOf(Props(classOf[ServerObjectBuilderTest.BuildingTestActor], structure, 10, Zone.Nowhere), "building")
|
||||
actor ! "!"
|
||||
|
||||
val reply = receiveOne(Duration.create(1000, "ms"))
|
||||
assert(reply.isInstanceOf[Building])
|
||||
assert(reply.asInstanceOf[Building].Id == 10)
|
||||
assert(reply.asInstanceOf[Building].Zone == Zone.Nowhere)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class WarpGateBuilderTest extends ActorTest {
|
||||
"WarpGate object" should {
|
||||
"build" in {
|
||||
val structure : (Int,Zone,ActorContext)=>Building = WarpGate.Structure
|
||||
val actor = system.actorOf(Props(classOf[ServerObjectBuilderTest.BuildingTestActor], structure, 10, Zone.Nowhere), "wgate")
|
||||
actor ! "!"
|
||||
|
||||
val reply = receiveOne(Duration.create(1000, "ms"))
|
||||
|
|
@ -167,10 +183,10 @@ object ServerObjectBuilderTest {
|
|||
}
|
||||
}
|
||||
|
||||
class BuildingTestActor(building_id : Int, zone : Zone) extends Actor {
|
||||
class BuildingTestActor(structure_con : (Int,Zone,ActorContext)=>Building, building_id : Int, zone : Zone) extends Actor {
|
||||
def receive : Receive = {
|
||||
case _ =>
|
||||
sender ! FoundationBuilder(Building.Structure).Build(building_id, zone)(context)
|
||||
sender ! FoundationBuilder(structure_con).Build(building_id, zone)(context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import net.psforever.objects.serverobject.implantmech.ImplantTerminalMech
|
|||
import net.psforever.objects.serverobject.locks.IFFLock
|
||||
import net.psforever.objects.serverobject.mblocker.Locker
|
||||
import net.psforever.objects.serverobject.pad.VehicleSpawnPad
|
||||
import net.psforever.objects.serverobject.structures.{Building, FoundationBuilder}
|
||||
import net.psforever.objects.serverobject.structures.{Building, FoundationBuilder, WarpGate}
|
||||
import net.psforever.objects.serverobject.terminals.Terminal
|
||||
import net.psforever.types.Vector3
|
||||
|
||||
|
|
@ -48,6 +48,10 @@ object Maps {
|
|||
val map12 = new ZoneMap("map12")
|
||||
|
||||
val map13 = new ZoneMap("map13") {
|
||||
LocalBuilding(1, FoundationBuilder(WarpGate.Structure))
|
||||
LocalBuilding(2, FoundationBuilder(WarpGate.Structure))
|
||||
LocalBuilding(3, FoundationBuilder(WarpGate.Structure))
|
||||
|
||||
LocalObject(ServerObjectBuilder(372, Door.Constructor))
|
||||
LocalObject(ServerObjectBuilder(373, Door.Constructor))
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ import net.psforever.objects.serverobject.pad.VehicleSpawnPad
|
|||
import net.psforever.objects.serverobject.terminals.{MatrixTerminalDefinition, Terminal}
|
||||
import net.psforever.objects.serverobject.terminals.Terminal.TerminalMessage
|
||||
import net.psforever.objects.vehicles.{AccessPermissionGroup, Utility, VehicleLockState}
|
||||
import net.psforever.objects.serverobject.structures.Building
|
||||
import net.psforever.objects.serverobject.structures.{Building, WarpGate}
|
||||
import net.psforever.objects.serverobject.terminals.Terminal
|
||||
import net.psforever.objects.vehicles.{AccessPermissionGroup, VehicleLockState}
|
||||
import net.psforever.objects.zones.{InterstellarCluster, Zone}
|
||||
|
|
@ -1000,7 +1000,6 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
case InterstellarCluster.ClientInitializationComplete(tplayer)=>
|
||||
//custom
|
||||
sendResponse(ContinentalLockUpdateMessage(13, PlanetSideEmpire.VS)) // "The VS have captured the VS Sanctuary."
|
||||
sendResponse(BroadcastWarpgateUpdateMessage(PlanetSideGUID(13), PlanetSideGUID(1), false, false, true)) // VS Sanctuary: Inactive Warpgate -> Broadcast Warpgate
|
||||
|
||||
//this will cause the client to send back a BeginZoningMessage packet (see below)
|
||||
sendResponse(LoadMapMessage(continent.Map.Name, continent.Id, 40100,25,true,3770441820L)) //VS Sanctuary
|
||||
|
|
@ -1241,10 +1240,10 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
sendResponse(TimeOfDayMessage(1191182336))
|
||||
sendResponse(ReplicationStreamMessage(5, Some(6), Vector(SquadListing()))) //clear squad list
|
||||
|
||||
sendResponse(ZonePopulationUpdateMessage(PlanetSideGUID(6), 414, 138, 0, 138, 0, 138, 0, 138, 0))
|
||||
sendResponse(ZonePopulationUpdateMessage(6, 414, 138, 0, 138, 0, 138, 0, 138, 0))
|
||||
(1 to 255).foreach(i => { sendResponse(SetEmpireMessage(PlanetSideGUID(i), PlanetSideEmpire.VS)) })
|
||||
|
||||
//render Equipment that was dropped into zone before the player arrived
|
||||
//render Equipment that was dropped into zone before the player arrived
|
||||
continent.EquipmentOnGround.foreach(item => {
|
||||
val definition = item.Definition
|
||||
sendResponse(
|
||||
|
|
@ -3041,11 +3040,75 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
log.error(s"DeployRequest: $obj can not transition to $state - $reason$mobileShift")
|
||||
}
|
||||
|
||||
/**
|
||||
* For a given continental structure, determine the method of generating server-join client configuration packets.
|
||||
* @param continentNumber the zone id
|
||||
* @param buildingNumber the building id
|
||||
* @param building the building object
|
||||
*/
|
||||
def initBuilding(continentNumber : Int, buildingNumber : Int, building : Building) : Unit = {
|
||||
building match {
|
||||
case _ : WarpGate =>
|
||||
initGate(continentNumber, buildingNumber, building)
|
||||
case _ : Building =>
|
||||
initFacility(continentNumber, buildingNumber, building)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For a given facility structure, configure a client by dispatching the appropriate packets.
|
||||
* Pay special attention to the details of `BuildingInfoUpdateMessage` when preparing this packet.
|
||||
* @see `BuildingInfoUpdateMessage`
|
||||
* @see `DensityLevelUpdateMessage`
|
||||
* @param continentNumber the zone id
|
||||
* @param buildingNumber the building id
|
||||
* @param building the building object
|
||||
*/
|
||||
def initFacility(continentNumber : Int, buildingNumber : Int, building : Building) : Unit = {
|
||||
sendResponse(
|
||||
BuildingInfoUpdateMessage(
|
||||
PlanetSideGUID(continentNumber), PlanetSideGUID(buildingNumber),
|
||||
10,
|
||||
continentNumber, //Zone
|
||||
buildingNumber, //Facility
|
||||
8, //NTU%
|
||||
false, //Hacked
|
||||
PlanetSideEmpire.NEUTRAL, //Base hacked by
|
||||
0, //Time remaining for hack (ms)
|
||||
building.Faction, //Base owned by
|
||||
0, //!! Field != 0 will cause malformed packet. See class def.
|
||||
None,
|
||||
PlanetSideGeneratorState.Normal, //Generator state
|
||||
true, //Respawn tubes operating state
|
||||
false, //Force dome state
|
||||
0, //Lattice benefits
|
||||
0, //!! Field > 0 will cause malformed packet. See class def.
|
||||
Nil,
|
||||
0,
|
||||
false,
|
||||
8, //!! Field != 8 will cause malformed packet. See class def.
|
||||
None,
|
||||
false, //Boosted spawn room pain field
|
||||
false //Boosted generator room pain field
|
||||
)
|
||||
)
|
||||
sendResponse(DensityLevelUpdateMessage(continentNumber, buildingNumber, List(0,0, 0,0, 0,0, 0,0)))
|
||||
}
|
||||
|
||||
/**
|
||||
* For a given lattice warp gate structure, configure a client by dispatching the appropriate packets.
|
||||
* Unlike other facilities, gates do not have complicated `BuildingInfoUpdateMessage` packets.
|
||||
* Also unlike facilities, gates have an additional packet.
|
||||
* @see `BuildingInfoUpdateMessage`
|
||||
* @see `DensityLevelUpdateMessage`
|
||||
* @see `BroadcastWarpgateUpdateMessage`
|
||||
* @param continentNumber the zone id
|
||||
* @param buildingNumber the building id
|
||||
* @param building the building object
|
||||
*/
|
||||
def initGate(continentNumber : Int, buildingNumber : Int, building : Building) : Unit = {
|
||||
sendResponse(
|
||||
BuildingInfoUpdateMessage(
|
||||
continentNumber, buildingNumber,
|
||||
0,
|
||||
false,
|
||||
PlanetSideEmpire.NEUTRAL,
|
||||
0,
|
||||
|
|
@ -3066,33 +3129,8 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
false
|
||||
)
|
||||
)
|
||||
sendResponse(DensityLevelUpdateMessage(continentNumber, buildingNumber, List(0,0, 0,0, 0,0, 0,0))) //TODO what is density?
|
||||
//TODO BroadcastWarpgateUpdateMessage() for warp gates
|
||||
// sendResponse(
|
||||
// BuildingInfoUpdateMessage(
|
||||
// PlanetSideGUID(6), //Ceryshen
|
||||
// PlanetSideGUID(2), //Anguta
|
||||
// 8, //80% NTU
|
||||
// true, //Base hacked
|
||||
// PlanetSideEmpire.NC, //Base hacked by NC
|
||||
// 600000, //10 minutes remaining for hack
|
||||
// PlanetSideEmpire.VS, //Base owned by VS
|
||||
// 0, //!! Field != 0 will cause malformed packet. See class def.
|
||||
// None,
|
||||
// PlanetSideGeneratorState.Critical, //Generator critical
|
||||
// true, //Respawn tubes destroyed
|
||||
// true, //Force dome active
|
||||
// 16, //Tech plant lattice benefit
|
||||
// 0,
|
||||
// Nil, //!! Field > 0 will cause malformed packet. See class def.
|
||||
// 0,
|
||||
// false,
|
||||
// 8, //!! Field != 8 will cause malformed packet. See class def.
|
||||
// None,
|
||||
// true, //Boosted spawn room pain field
|
||||
// true //Boosted generator room pain field
|
||||
// )
|
||||
// )
|
||||
sendResponse(DensityLevelUpdateMessage(continentNumber, buildingNumber, List(0,0, 0,0, 0,0, 0,0)))
|
||||
sendResponse(BroadcastWarpgateUpdateMessage(continentNumber, buildingNumber, false, false, true))
|
||||
}
|
||||
|
||||
def configZone(zone : Zone) : Unit = {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue