mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-07-13 07:24:53 +00:00
Merge branch 'packet-updates'
This commit is contained in:
commit
dc008c3e4b
7 changed files with 71 additions and 63 deletions
|
|
@ -6,6 +6,18 @@ import scodec.Codec
|
||||||
import scodec.codecs._
|
import scodec.codecs._
|
||||||
import scodec.bits._
|
import scodec.bits._
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tell the server that the player is is jumping.
|
||||||
|
* This will allow it to coordinate animation with other clients.<br>
|
||||||
|
* <br>
|
||||||
|
* During the jump, the avatar's "height" coordinate does change, as reported in `PlayerStateMessageUpstream`.
|
||||||
|
* `PlayerStateMessage`, however, can depict another player with a proper jumping animation without the explicit coordinate change.
|
||||||
|
* The server must probably account for the distance to the ground when passing along data somehow.<br>
|
||||||
|
* <br>
|
||||||
|
* Exploration:<br>
|
||||||
|
* Is `state` ever not `true`?
|
||||||
|
* @param state true
|
||||||
|
*/
|
||||||
final case class AvatarJumpMessage(state : Boolean)
|
final case class AvatarJumpMessage(state : Boolean)
|
||||||
extends PlanetSideGamePacket {
|
extends PlanetSideGamePacket {
|
||||||
type Packet = AvatarJumpMessage
|
type Packet = AvatarJumpMessage
|
||||||
|
|
@ -14,7 +26,5 @@ final case class AvatarJumpMessage(state : Boolean)
|
||||||
}
|
}
|
||||||
|
|
||||||
object AvatarJumpMessage extends Marshallable[AvatarJumpMessage] {
|
object AvatarJumpMessage extends Marshallable[AvatarJumpMessage] {
|
||||||
implicit val codec : Codec[AvatarJumpMessage] = (
|
implicit val codec : Codec[AvatarJumpMessage] = ("state" | bool).as[AvatarJumpMessage]
|
||||||
("state" | bool)
|
|
||||||
).as[AvatarJumpMessage]
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ package net.psforever.packet.game
|
||||||
import net.psforever.packet.{GamePacketOpcode, Marshallable, PacketHelpers, PlanetSideGamePacket}
|
import net.psforever.packet.{GamePacketOpcode, Marshallable, PacketHelpers, PlanetSideGamePacket}
|
||||||
import scodec.Codec
|
import scodec.Codec
|
||||||
import scodec.codecs._
|
import scodec.codecs._
|
||||||
import scodec.bits._
|
|
||||||
|
|
||||||
object PlanetSideGeneratorState extends Enumeration {
|
object PlanetSideGeneratorState extends Enumeration {
|
||||||
type Type = Value
|
type Type = Value
|
||||||
|
|
@ -66,7 +65,6 @@ object BuildingInfoUpdateMessage extends Marshallable[BuildingInfoUpdateMessage]
|
||||||
("unk5" | uint32L) ::
|
("unk5" | uint32L) ::
|
||||||
("unk6" | bool) ::
|
("unk6" | bool) ::
|
||||||
("unk7" | uint4L) :: //TODO: bool and uintL(2) follow if unk7 != 8
|
("unk7" | uint4L) :: //TODO: bool and uintL(2) follow if unk7 != 8
|
||||||
|
|
||||||
("boost_spawn_pain" | bool) ::
|
("boost_spawn_pain" | bool) ::
|
||||||
("boost_generator_pain" | bool)
|
("boost_generator_pain" | bool)
|
||||||
).as[BuildingInfoUpdateMessage]
|
).as[BuildingInfoUpdateMessage]
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,26 @@ import net.psforever.types.Vector3
|
||||||
import scodec.Codec
|
import scodec.Codec
|
||||||
import scodec.codecs._
|
import scodec.codecs._
|
||||||
|
|
||||||
/** PlayerStateMessageUpstream is constantly sent from the client to the server to update avatar properties.
|
/**
|
||||||
*
|
* Constantly sent from the client to the server to update player avatar properties.<br>
|
||||||
* Note: seq_time appears to be used in other message definitions as well. It
|
* <br>
|
||||||
* seems to represent a timestamp for ordering of e.g. player and weapon events.
|
* Exploration:<br>
|
||||||
|
* `seq_time` appears to be used in other message definitions as well.
|
||||||
|
* It seems to represent a timestamp for ordering, e.g., player and weapon events.
|
||||||
|
* @param avatar_guid the player's GUID
|
||||||
|
* @param pos where the player is in the world
|
||||||
|
* @param vel how the player is moving
|
||||||
|
* @param unk1 na
|
||||||
|
* @param aim_pitch the vertical angle of viewing
|
||||||
|
* @param unk2 na
|
||||||
|
* @param seq_time na
|
||||||
|
* @param unk3 na
|
||||||
|
* @param is_crouching whether the player is crouched
|
||||||
|
* @param unk4 na
|
||||||
|
* @param unk5 na
|
||||||
|
* @param is_cloaking whether the player is cloaked by virtue of an Infiltration Suit
|
||||||
|
* @param unk6 na
|
||||||
|
* @param unk7 na
|
||||||
*/
|
*/
|
||||||
final case class PlayerStateMessageUpstream(avatar_guid : PlanetSideGUID,
|
final case class PlayerStateMessageUpstream(avatar_guid : PlanetSideGUID,
|
||||||
pos : Vector3,
|
pos : Vector3,
|
||||||
|
|
@ -22,9 +38,9 @@ final case class PlayerStateMessageUpstream(avatar_guid : PlanetSideGUID,
|
||||||
is_crouching : Boolean,
|
is_crouching : Boolean,
|
||||||
unk4 : Boolean,
|
unk4 : Boolean,
|
||||||
unk5 : Boolean,
|
unk5 : Boolean,
|
||||||
unk6 : Boolean,
|
is_cloaking : Boolean,
|
||||||
unk7 : Int,
|
unk6 : Int,
|
||||||
unk8 : Int)
|
unk7 : Int)
|
||||||
extends PlanetSideGamePacket {
|
extends PlanetSideGamePacket {
|
||||||
type Packet = PlayerStateMessageUpstream
|
type Packet = PlayerStateMessageUpstream
|
||||||
def opcode = GamePacketOpcode.PlayerStateMessageUpstream
|
def opcode = GamePacketOpcode.PlayerStateMessageUpstream
|
||||||
|
|
@ -44,8 +60,8 @@ object PlayerStateMessageUpstream extends Marshallable[PlayerStateMessageUpstrea
|
||||||
("is_crouching" | bool) ::
|
("is_crouching" | bool) ::
|
||||||
("unk4" | bool) ::
|
("unk4" | bool) ::
|
||||||
("unk5" | bool) ::
|
("unk5" | bool) ::
|
||||||
("unk6" | bool) ::
|
("is_cloaking" | bool) ::
|
||||||
("unk7" | uint8L) ::
|
("unk6" | uint8L) ::
|
||||||
("unk8" | uint16L)
|
("unk7" | uint16L)
|
||||||
).as[PlayerStateMessageUpstream]
|
).as[PlayerStateMessageUpstream]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,8 @@ import scodec.Codec
|
||||||
import scodec.codecs._
|
import scodec.codecs._
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets Auraxis time on the client.
|
* Sets Auraxis time for a continent (zone) on the client.
|
||||||
* Use the slash-command /time to view the current time in the event window.
|
* Use the slash-command `/time` to view the current time in the event window.
|
||||||
* Auraxis time is represented as a standard military twenty-four hour clock, displayed in hours and minutes.<br>
|
* Auraxis time is represented as a standard military twenty-four hour clock, displayed in hours and minutes.<br>
|
||||||
* <br>
|
* <br>
|
||||||
* Time is set per zone on map loading.
|
* Time is set per zone on map loading.
|
||||||
|
|
@ -21,26 +21,18 @@ import scodec.codecs._
|
||||||
* The current time is constrained to a looping twenty-four hour interval.<br>
|
* The current time is constrained to a looping twenty-four hour interval.<br>
|
||||||
* <br>
|
* <br>
|
||||||
* If no time is set, the client starts counting from 10:00 at an initial rate of about one Auraxis minute every four or five real seconds.
|
* If no time is set, the client starts counting from 10:00 at an initial rate of about one Auraxis minute every four or five real seconds.
|
||||||
* Setting the current time to 00 00 42 sets the current time to 00:00 with an indeterminate, but slow, rate.
|
* Setting the current time to 1107296256 sets the current time to 00:00 with an indeterminate, but slow, rate.
|
||||||
* Time is normally initialized somewhere within an interval between 00 00 46 and FF FF 47.
|
* Time is normally initialized somewhere within an interval between 1174405120 and 1207959296.
|
||||||
* Setting the current time extremely high can cause psychedelic rendering as the current time overflows and the rate is too fast.
|
* Setting the current time extremely high (near the numerical maximum) can cause psychedelic rendering.
|
||||||
* (Setting the time to FF FF FF will reduce the rendering system to true gibberish.)<br>
|
* (Setting the time to 4294967040 exactly will reduce the rendering system to gibberish.)<br>
|
||||||
* <br>
|
* <br>
|
||||||
* The interval from 5E 39 46 (4602206, which is ~03:18) to 00 C0 47 (4702208, which is 03:18) is about a full twenty-four hours.
|
* The interval from 1178164736 (~03:18) to 1203765248 (03:18) is about a full twenty-four hours.
|
||||||
* Coincidentally, that is a count of 100002.
|
* That is a count of 25600512.
|
||||||
* @param unk1 consistently 00; does nothing?
|
|
||||||
* @param time Auraxis time
|
* @param time Auraxis time
|
||||||
* @param unk2 consistently 00; does nothing?
|
* @param unk consistently 1092616192; does nothing?
|
||||||
* @param unk3 consistently 00; does nothing?
|
|
||||||
* @param unk4 consistently 20; does nothing?
|
|
||||||
* @param unk5 consistently 41; does nothing?
|
|
||||||
*/
|
*/
|
||||||
final case class TimeOfDayMessage(unk1 : Int,
|
final case class TimeOfDayMessage(time : Long,
|
||||||
time : Int,
|
unk : Long = 1092616192L)
|
||||||
unk2 : Int,
|
|
||||||
unk3 : Int,
|
|
||||||
unk4 : Int,
|
|
||||||
unk5 : Int)
|
|
||||||
extends PlanetSideGamePacket {
|
extends PlanetSideGamePacket {
|
||||||
type Packet = TimeOfDayMessage
|
type Packet = TimeOfDayMessage
|
||||||
def opcode = GamePacketOpcode.TimeOfDayMessage
|
def opcode = GamePacketOpcode.TimeOfDayMessage
|
||||||
|
|
@ -49,12 +41,8 @@ final case class TimeOfDayMessage(unk1 : Int,
|
||||||
|
|
||||||
object TimeOfDayMessage extends Marshallable[TimeOfDayMessage] {
|
object TimeOfDayMessage extends Marshallable[TimeOfDayMessage] {
|
||||||
implicit val codec : Codec[TimeOfDayMessage] = (
|
implicit val codec : Codec[TimeOfDayMessage] = (
|
||||||
("unk1" | uint8L) ::
|
("time" | uint32L) ::
|
||||||
("time" | uintL(24)) ::
|
("unk" | uint32L)
|
||||||
("unk2" | uint8L) ::
|
|
||||||
("unk3" | uint8L) ::
|
|
||||||
("unk4" | uint8L) ::
|
|
||||||
("unk5" | uint8L)
|
|
||||||
).as[TimeOfDayMessage]
|
).as[TimeOfDayMessage]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,12 +15,12 @@ import scodec.codecs._
|
||||||
* This packet also shifts the flavor text for that zone.<br>
|
* This packet also shifts the flavor text for that zone.<br>
|
||||||
* <br>
|
* <br>
|
||||||
* The size of zone's queue is the final upper population limit for that zone.
|
* The size of zone's queue is the final upper population limit for that zone.
|
||||||
* Common values for the zone queue fields are 00 00 00 00 (locked) and 9E 01 00 00 (414 positions).
|
* Common values for the zone queue fields are 0 (locked) and 414 positions.
|
||||||
* When a continent can not accept any players at all, a lock icon will appear over its view pane in the Interstellar View.
|
* When a continent can not accept any players at all, a lock icon will appear over its view pane in the Interstellar View.
|
||||||
* Setting the zone's queue to zero will also render this icon.<br>
|
* Setting the zone's queue to zero will also render this icon.<br>
|
||||||
* <br>
|
* <br>
|
||||||
* The individual queue fields set the maximum empire occupancy for a zone that is represented in the zone Incentives text.
|
* The individual queue fields set the maximum empire occupancy for a zone that is represented in the zone Incentives text.
|
||||||
* Common values for the empire queue fields are 00 00 00 00 (locked population), 8A 00 00 00 (138 positions), and FA 01 00 00 (500 positions).
|
* Common values for the empire queue fields are 0 (locked population), 138 positions, and 500 positions.
|
||||||
* Zone Incentives text, however, will never report more than a "100+" vacancy.
|
* Zone Incentives text, however, will never report more than a "100+" vacancy.
|
||||||
* The actual limits are probably set based on server load.
|
* The actual limits are probably set based on server load.
|
||||||
* The latter queue value is typical for VR area zones.<br>
|
* The latter queue value is typical for VR area zones.<br>
|
||||||
|
|
@ -51,8 +51,8 @@ final case class ZonePopulationUpdateMessage(continent_guid : PlanetSideGUID,
|
||||||
nc_pop : Long,
|
nc_pop : Long,
|
||||||
vs_queue : Long,
|
vs_queue : Long,
|
||||||
vs_pop : Long,
|
vs_pop : Long,
|
||||||
bo_queue : Long,
|
bo_queue : Long = 0L,
|
||||||
bo_pop : Long)
|
bo_pop : Long = 0L)
|
||||||
extends PlanetSideGamePacket {
|
extends PlanetSideGamePacket {
|
||||||
type Packet = ZonePopulationUpdateMessage
|
type Packet = ZonePopulationUpdateMessage
|
||||||
def opcode = GamePacketOpcode.ZonePopulationUpdateMessage
|
def opcode = GamePacketOpcode.ZonePopulationUpdateMessage
|
||||||
|
|
@ -62,10 +62,10 @@ final case class ZonePopulationUpdateMessage(continent_guid : PlanetSideGUID,
|
||||||
object ZonePopulationUpdateMessage extends Marshallable[ZonePopulationUpdateMessage] {
|
object ZonePopulationUpdateMessage extends Marshallable[ZonePopulationUpdateMessage] {
|
||||||
implicit val codec : Codec[ZonePopulationUpdateMessage] = (
|
implicit val codec : Codec[ZonePopulationUpdateMessage] = (
|
||||||
("continent_guid" | PlanetSideGUID.codec) ::
|
("continent_guid" | PlanetSideGUID.codec) ::
|
||||||
("zone_queue" | ulongL(32)) ::
|
("zone_queue" | uint32L) ::
|
||||||
("tr_queue" | ulongL(32)) :: ("tr_pop" | ulongL(32)) ::
|
("tr_queue" | uint32L) :: ("tr_pop" | uint32L) ::
|
||||||
("nc_queue" | ulongL(32)) :: ("nc_pop" | ulongL(32)) ::
|
("nc_queue" | uint32L) :: ("nc_pop" | uint32L) ::
|
||||||
("vs_queue" | ulongL(32)) :: ("vs_pop" | ulongL(32)) ::
|
("vs_queue" | uint32L) :: ("vs_pop" | uint32L) ::
|
||||||
("bo_queue" | ulongL(32)) :: ("bo_pop" | ulongL(32))
|
("bo_queue" | uint32L) :: ("bo_pop" | uint32L)
|
||||||
).as[ZonePopulationUpdateMessage]
|
).as[ZonePopulationUpdateMessage]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -644,20 +644,16 @@ class GamePacketTest extends Specification {
|
||||||
|
|
||||||
"decode" in {
|
"decode" in {
|
||||||
PacketCoding.DecodePacket(string).require match {
|
PacketCoding.DecodePacket(string).require match {
|
||||||
case TimeOfDayMessage(unk1, time, unk2, unk3, unk4, unk5) =>
|
case TimeOfDayMessage(time, unk) =>
|
||||||
unk1 mustEqual 0
|
time mustEqual 1191182336
|
||||||
time mustEqual 4653056
|
unk mustEqual 1092616192
|
||||||
unk2 mustEqual 0
|
|
||||||
unk3 mustEqual 0
|
|
||||||
unk4 mustEqual 32
|
|
||||||
unk5 mustEqual 65
|
|
||||||
case default =>
|
case default =>
|
||||||
ko
|
ko
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"encode" in {
|
"encode" in {
|
||||||
val msg = TimeOfDayMessage(0, 4653056, 0, 0, 32, 65)
|
val msg = TimeOfDayMessage(1191182336)
|
||||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||||
|
|
||||||
pkt mustEqual string
|
pkt mustEqual string
|
||||||
|
|
@ -669,7 +665,7 @@ class GamePacketTest extends Specification {
|
||||||
|
|
||||||
"decode" in {
|
"decode" in {
|
||||||
PacketCoding.DecodePacket(string).require match {
|
PacketCoding.DecodePacket(string).require match {
|
||||||
case PlayerStateMessageUpstream(avatar_guid, pos, vel, unk1, aim_pitch, unk2, seq_time, unk3, is_crouching, unk4, unk5, unk6, unk7, unk8) =>
|
case PlayerStateMessageUpstream(avatar_guid, pos, vel, unk1, aim_pitch, unk2, seq_time, unk3, is_crouching, unk4, unk5, is_cloaking, unk6, unk7) =>
|
||||||
avatar_guid mustEqual PlanetSideGUID(75)
|
avatar_guid mustEqual PlanetSideGUID(75)
|
||||||
pos mustEqual Vector3(3694.1094f, 2735.4531f, 90.84375f)
|
pos mustEqual Vector3(3694.1094f, 2735.4531f, 90.84375f)
|
||||||
vel mustEqual Some(Vector3(4.375f, 2.59375f, 0.0f))
|
vel mustEqual Some(Vector3(4.375f, 2.59375f, 0.0f))
|
||||||
|
|
@ -681,9 +677,9 @@ class GamePacketTest extends Specification {
|
||||||
is_crouching mustEqual false
|
is_crouching mustEqual false
|
||||||
unk4 mustEqual false
|
unk4 mustEqual false
|
||||||
unk5 mustEqual false
|
unk5 mustEqual false
|
||||||
unk6 mustEqual false
|
is_cloaking mustEqual false
|
||||||
unk7 mustEqual 112
|
unk6 mustEqual 112
|
||||||
unk8 mustEqual 0
|
unk7 mustEqual 0
|
||||||
case default =>
|
case default =>
|
||||||
ko
|
ko
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -145,7 +145,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
sendResponse(PacketCoding.CreateGamePacket(0, SetEmpireMessage(PlanetSideGUID(2), PlanetSideEmpire.VS))) //HART building C
|
sendResponse(PacketCoding.CreateGamePacket(0, SetEmpireMessage(PlanetSideGUID(2), PlanetSideEmpire.VS))) //HART building C
|
||||||
sendResponse(PacketCoding.CreateGamePacket(0, SetEmpireMessage(PlanetSideGUID(29), PlanetSideEmpire.NC))) //South Villa Gun Tower
|
sendResponse(PacketCoding.CreateGamePacket(0, SetEmpireMessage(PlanetSideGUID(29), PlanetSideEmpire.NC))) //South Villa Gun Tower
|
||||||
|
|
||||||
sendResponse(PacketCoding.CreateGamePacket(0, TimeOfDayMessage(0, 4653056, 0, 0, 32, 65)))
|
sendResponse(PacketCoding.CreateGamePacket(0, TimeOfDayMessage(1191182336)))
|
||||||
sendResponse(PacketCoding.CreateGamePacket(0, ContinentalLockUpdateMessage(PlanetSideGUID(13), PlanetSideEmpire.VS))) // "The VS have captured the VS Sanctuary."
|
sendResponse(PacketCoding.CreateGamePacket(0, ContinentalLockUpdateMessage(PlanetSideGUID(13), PlanetSideEmpire.VS))) // "The VS have captured the VS Sanctuary."
|
||||||
sendResponse(PacketCoding.CreateGamePacket(0, BroadcastWarpgateUpdateMessage(PlanetSideGUID(13), PlanetSideGUID(1), 32))) // VS Sanctuary: Inactive Warpgate -> Broadcast Warpgate
|
sendResponse(PacketCoding.CreateGamePacket(0, BroadcastWarpgateUpdateMessage(PlanetSideGUID(13), PlanetSideGUID(1), 32))) // VS Sanctuary: Inactive Warpgate -> Broadcast Warpgate
|
||||||
|
|
||||||
|
|
@ -190,7 +190,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
case KeepAliveMessage(code) =>
|
case KeepAliveMessage(code) =>
|
||||||
sendResponse(PacketCoding.CreateGamePacket(0, KeepAliveMessage(0)))
|
sendResponse(PacketCoding.CreateGamePacket(0, KeepAliveMessage(0)))
|
||||||
|
|
||||||
case msg @ PlayerStateMessageUpstream(avatar_guid, pos, vel, unk1, aim_pitch, unk2, seq_time, unk3, is_crouching, unk4, unk5, unk6, unk7, unk8) =>
|
case msg @ PlayerStateMessageUpstream(avatar_guid, pos, vel, unk1, aim_pitch, unk2, seq_time, unk3, is_crouching, unk4, unk5, is_cloaking, unk6, unk7) =>
|
||||||
//log.info("PlayerState: " + msg)
|
//log.info("PlayerState: " + msg)
|
||||||
|
|
||||||
case msg @ ChatMsg(messagetype, has_wide_contents, recipient, contents, note_contents) =>
|
case msg @ ChatMsg(messagetype, has_wide_contents, recipient, contents, note_contents) =>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue