mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-01-19 18:14:44 +00:00
Packet: BindPlayerMessage and tests (#104)
This commit is contained in:
parent
b6c1fcc29d
commit
a6a51009fa
|
|
@ -344,7 +344,7 @@ object GamePacketOpcode extends Enumeration {
|
|||
case 0x13 => game.CharacterNoRecordMessage.decode
|
||||
case 0x14 => game.CharacterInfoMessage.decode
|
||||
case 0x15 => noDecoder(UnknownMessage21)
|
||||
case 0x16 => noDecoder(BindPlayerMessage)
|
||||
case 0x16 => game.BindPlayerMessage.decode
|
||||
case 0x17 => noDecoder(ObjectCreateMessage_Duplicate)
|
||||
// 0x18
|
||||
case 0x18 => game.ObjectCreateMessage.decode
|
||||
|
|
|
|||
|
|
@ -0,0 +1,88 @@
|
|||
// Copyright (c) 2016 PSForever.net to present
|
||||
package net.psforever.packet.game
|
||||
|
||||
import net.psforever.packet.{GamePacketOpcode, Marshallable, PacketHelpers, PlanetSideGamePacket}
|
||||
import net.psforever.types.Vector3
|
||||
import scodec.Codec
|
||||
import scodec.codecs._
|
||||
|
||||
/**
|
||||
* A packet dispatched to maintain a manually-set respawn location.<br>
|
||||
* <br>
|
||||
* The packet establishes the player's ability to spawn in an arbitrary location that is not a normal local option.
|
||||
* This process is called "binding."
|
||||
* In addition to player establishing the binding, the packet updates as conditions of the respawn location changes.<br>
|
||||
* <br>
|
||||
* If `logging` is turned on, packets will display different messages depending on context.
|
||||
* As long as the event is marked to be logged, when the packet is received, a message is displayed in the events window.
|
||||
* If the logged action is applicable, the matrixing sound effect will be played too.
|
||||
* Not displaying events is occasionally warranted for aesthetics.
|
||||
* The game will always note if this is your first time binding.<br>
|
||||
* <br>
|
||||
* One common occurrence of this packet is during zone transport.
|
||||
* Specifically, a packet is dispatched after unloading the current zone but before beginning loading in the new zone.
|
||||
* It is preceded by all of the `ObjectDeleteMessage` packets and itself precedes the `LoadMapMessage` packet.<br>
|
||||
* <br>
|
||||
* Actions:<br>
|
||||
* `1` - bound to respawn point<br>
|
||||
* `2` - general unbound / unbinding from respawn point<br>
|
||||
* `3` - respawn point lost<br>
|
||||
* `4` - bound spawn point became available<br>
|
||||
* `5` - bound spawn point became unavailable (different from 3)<br>
|
||||
* <br>
|
||||
* Bind Descriptors:<br>
|
||||
* `@amp_station`<br>
|
||||
* `@ams`<br>
|
||||
* `@comm_station` (interlink facility?)<br>
|
||||
* `@comm_station_dsp` (dropship center?)<br>
|
||||
* `@cryo_facility` (biolab?)<br>
|
||||
* `@tech_plant`<br>
|
||||
* <br>
|
||||
* Exploration:<br>
|
||||
* Find other bind descriptors.
|
||||
* @param action the purpose of the packet
|
||||
* @param bindDesc a description of the respawn binding point
|
||||
* @param unk1 na; usually set `true` if there is more data in the packet ...
|
||||
* @param logging true, to report on bind point change visible in the events window;
|
||||
* false, to render spawn change silent;
|
||||
* a first time event notification will always show
|
||||
* @param unk2 na; if a value, it is usually 40 (hex`28`)
|
||||
* @param unk3 na
|
||||
* @param unk4 na
|
||||
* @param pos a position associated with the binding
|
||||
*/
|
||||
final case class BindPlayerMessage(action : Int,
|
||||
bindDesc : String,
|
||||
unk1 : Boolean,
|
||||
logging : Boolean,
|
||||
unk2 : Int,
|
||||
unk3 : Long,
|
||||
unk4 : Long,
|
||||
pos : Vector3)
|
||||
extends PlanetSideGamePacket {
|
||||
type Packet = BindPlayerMessage
|
||||
def opcode = GamePacketOpcode.BindPlayerMessage
|
||||
def encode = BindPlayerMessage.encode(this)
|
||||
}
|
||||
|
||||
object BindPlayerMessage extends Marshallable[BindPlayerMessage] {
|
||||
/**
|
||||
* A common variant of this packet.
|
||||
* `16028004000000000000000000000000000000`
|
||||
*/
|
||||
val STANDARD = BindPlayerMessage(2, "", false, false, 2, 0, 0, Vector3(0, 0, 0))
|
||||
|
||||
//TODO: there are two ignore(1) in this packet; are they in a good position?
|
||||
implicit val codec : Codec[BindPlayerMessage] = (
|
||||
("action" | uint8L) ::
|
||||
("bindDesc" | PacketHelpers.encodedString) ::
|
||||
("unk1" | bool) ::
|
||||
("logging" | bool) ::
|
||||
ignore(1) ::
|
||||
("unk2" | uint4L) ::
|
||||
ignore(1) ::
|
||||
("unk3" | uint32L) ::
|
||||
("unk4" | uint32L) ::
|
||||
("pos" | Vector3.codec_pos)
|
||||
).as[BindPlayerMessage]
|
||||
}
|
||||
72
common/src/test/scala/game/BindPlayerMessageTest.scala
Normal file
72
common/src/test/scala/game/BindPlayerMessageTest.scala
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
// Copyright (c) 2016 PSForever.net to present
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.Vector3
|
||||
import scodec.bits._
|
||||
|
||||
class BindPlayerMessageTest extends Specification {
|
||||
val string_ams = hex"16 05 8440616D73 08 28000000 00000000 00000 00000 0000"
|
||||
val string_tech = hex"16 01 8b40746563685f706c616e74 d4 28000000 38000000 00064 012b1 a044"
|
||||
|
||||
"decode (ams)" in {
|
||||
PacketCoding.DecodePacket(string_ams).require match {
|
||||
case BindPlayerMessage(action, bindDesc, unk1, logging, unk2, unk3, unk4, pos) =>
|
||||
action mustEqual 5
|
||||
bindDesc.length mustEqual 4
|
||||
bindDesc mustEqual "@ams"
|
||||
unk1 mustEqual false
|
||||
logging mustEqual false
|
||||
unk2 mustEqual 4
|
||||
unk3 mustEqual 40
|
||||
unk4 mustEqual 0
|
||||
pos.x mustEqual 0f
|
||||
pos.y mustEqual 0f
|
||||
pos.z mustEqual 0f
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (tech)" in {
|
||||
PacketCoding.DecodePacket(string_tech).require match {
|
||||
case BindPlayerMessage(action, bindDesc, unk1, logging, unk2, unk3, unk4, pos) =>
|
||||
action mustEqual 1
|
||||
bindDesc.length mustEqual 11
|
||||
bindDesc mustEqual "@tech_plant"
|
||||
unk1 mustEqual true
|
||||
logging mustEqual true
|
||||
unk2 mustEqual 10
|
||||
unk3 mustEqual 40
|
||||
unk4 mustEqual 56
|
||||
pos.x mustEqual 2060.0f
|
||||
pos.y mustEqual 598.0078f
|
||||
pos.z mustEqual 274.5f
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode (ams)" in {
|
||||
val msg = BindPlayerMessage(5, "@ams", false, false, 4, 40, 0, Vector3(0, 0, 0))
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_ams
|
||||
}
|
||||
|
||||
"encode (tech)" in {
|
||||
val msg = BindPlayerMessage(1, "@tech_plant", true, true, 10, 40, 56, Vector3(2060.0f, 598.0078f, 274.5f))
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_tech
|
||||
}
|
||||
|
||||
"standard" in {
|
||||
val msg = BindPlayerMessage.STANDARD
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual hex"16028004000000000000000000000000000000"
|
||||
}
|
||||
}
|
||||
|
|
@ -373,6 +373,9 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
case msg @ BugReportMessage(version_major,version_minor,version_date,bug_type,repeatable,location,zone,pos,summary,desc) =>
|
||||
log.info("BugReportMessage: " + msg)
|
||||
|
||||
case msg @ BindPlayerMessage(action, bindDesc, unk1, logging, unk2, unk3, unk4, pos) =>
|
||||
log.info("BindPlayerMessage: " + msg)
|
||||
|
||||
case default => log.error(s"Unhandled GamePacket ${pkt}")
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue