mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-04-29 15:55:23 +00:00
Various fixes to ChatMsg (#43)
* Add BinaryChoiceCodec * Proper ChatMsg structuring
This commit is contained in:
parent
4fb13fdc57
commit
fc2ef50be6
5 changed files with 61 additions and 22 deletions
|
|
@ -0,0 +1,31 @@
|
||||||
|
// Copyright (c) 2016 PSForever.net to present
|
||||||
|
package net.psforever.newcodecs
|
||||||
|
|
||||||
|
import scodec.{ Codec, SizeBound }
|
||||||
|
import scodec.bits.BitVector
|
||||||
|
|
||||||
|
private[newcodecs] final class BinaryChoiceCodec[A](choice: Boolean, codec_true: => Codec[A], codec_false: => Codec[A]) extends Codec[A] {
|
||||||
|
|
||||||
|
private lazy val evaluatedCodec_true = codec_true
|
||||||
|
|
||||||
|
private lazy val evaluatedCodec_false = codec_false
|
||||||
|
|
||||||
|
override def sizeBound = if (choice) evaluatedCodec_true.sizeBound else evaluatedCodec_false.sizeBound
|
||||||
|
|
||||||
|
override def encode(a: A) = {
|
||||||
|
if (choice)
|
||||||
|
evaluatedCodec_true.encode(a)
|
||||||
|
else
|
||||||
|
evaluatedCodec_false.encode(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
override def decode(buffer: BitVector) = {
|
||||||
|
if (choice)
|
||||||
|
evaluatedCodec_true.decode(buffer)
|
||||||
|
else
|
||||||
|
evaluatedCodec_false.decode(buffer)
|
||||||
|
}
|
||||||
|
|
||||||
|
override def toString = if(choice) s"binarychoice(true, $evaluatedCodec_true, ?)" else "binarychoice(false, ?, $evaluatedCodec_false)"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -11,4 +11,6 @@ package object newcodecs {
|
||||||
|
|
||||||
def q_float(min : Double, max : Double, bits : Int): Codec[Float] = q_double(min, max, bits).narrow(v => Attempt.successful(v.toFloat), _.toDouble)
|
def q_float(min : Double, max : Double, bits : Int): Codec[Float] = q_double(min, max, bits).narrow(v => Attempt.successful(v.toFloat), _.toDouble)
|
||||||
|
|
||||||
|
def binary_choice[A](choice: Boolean, codec_true: => Codec[A], codec_false: => Codec[A]): Codec[A] = new BinaryChoiceCodec(choice, codec_true, codec_false)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,17 @@
|
||||||
// Copyright (c) 2016 PSForever.net to present
|
// Copyright (c) 2016 PSForever.net to present
|
||||||
package net.psforever.packet.game
|
package net.psforever.packet.game
|
||||||
|
|
||||||
|
import net.psforever.newcodecs._
|
||||||
import net.psforever.packet.{GamePacketOpcode, Marshallable, PacketHelpers, PlanetSideGamePacket}
|
import net.psforever.packet.{GamePacketOpcode, Marshallable, PacketHelpers, PlanetSideGamePacket}
|
||||||
import net.psforever.types.ChatMessageType
|
import net.psforever.types.ChatMessageType
|
||||||
import scodec.Codec
|
import scodec.Codec
|
||||||
import scodec.codecs._
|
import scodec.codecs._
|
||||||
|
|
||||||
final case class ChatMsg(channel : ChatMessageType.Value,
|
final case class ChatMsg(messagetype : ChatMessageType.Value,
|
||||||
unk1 : Boolean,
|
has_wide_contents : Boolean,
|
||||||
recipient : String,
|
recipient : String,
|
||||||
contents : String)
|
contents : String,
|
||||||
|
note_contents : Option[String])
|
||||||
extends PlanetSideGamePacket {
|
extends PlanetSideGamePacket {
|
||||||
type Packet = ChatMsg
|
type Packet = ChatMsg
|
||||||
def opcode = GamePacketOpcode.ChatMsg
|
def opcode = GamePacketOpcode.ChatMsg
|
||||||
|
|
@ -18,9 +20,11 @@ final case class ChatMsg(channel : ChatMessageType.Value,
|
||||||
|
|
||||||
object ChatMsg extends Marshallable[ChatMsg] {
|
object ChatMsg extends Marshallable[ChatMsg] {
|
||||||
implicit val codec : Codec[ChatMsg] = (
|
implicit val codec : Codec[ChatMsg] = (
|
||||||
("messagetype" | ChatMessageType.codec) ::
|
("messagetype" | ChatMessageType.codec) >>:~ { messagetype_value =>
|
||||||
("unk1" | bool) ::
|
(("has_wide_contents" | bool) >>:~ { has_wide_contents_value =>
|
||||||
("recipient" | PacketHelpers.encodedWideStringAligned(7)) ::
|
("recipient" | PacketHelpers.encodedWideStringAligned(7)) ::
|
||||||
("contents" | PacketHelpers.encodedWideString)
|
newcodecs.binary_choice(has_wide_contents_value, ("contents" | PacketHelpers.encodedWideString), ("contents" | PacketHelpers.encodedString))
|
||||||
).as[ChatMsg]
|
}) :+
|
||||||
|
conditional(messagetype_value == ChatMessageType.Note, ("note_contents" | PacketHelpers.encodedWideString))
|
||||||
|
}).as[ChatMsg]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -164,40 +164,42 @@ class GamePacketTest extends Specification {
|
||||||
ok
|
ok
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"ChatMsg" should {
|
"ChatMsg" should {
|
||||||
val string_local = hex"12 1A C000 83610062006300"
|
val string_local = hex"12 1A C000 83610062006300"
|
||||||
val string_tell = hex"12 20 C180640065006600 83610062006300"
|
val string_tell = hex"12 20 C180640065006600 83610062006300"
|
||||||
|
|
||||||
"decode" in {
|
"decode" in {
|
||||||
PacketCoding.DecodePacket(string_local).require match {
|
PacketCoding.DecodePacket(string_local).require match {
|
||||||
case ChatMsg(messagetype, unk1, recipient, contents) =>
|
case ChatMsg(messagetype, has_wide_contents, recipient, contents, note_contents) =>
|
||||||
messagetype mustEqual ChatMessageType.Local
|
messagetype mustEqual ChatMessageType.Local
|
||||||
unk1 mustEqual true
|
has_wide_contents mustEqual true
|
||||||
recipient mustEqual ""
|
recipient mustEqual ""
|
||||||
contents mustEqual "abc"
|
contents mustEqual "abc"
|
||||||
|
note_contents mustEqual None
|
||||||
case default =>
|
case default =>
|
||||||
ko
|
ko
|
||||||
}
|
}
|
||||||
|
|
||||||
PacketCoding.DecodePacket(string_tell).require match {
|
PacketCoding.DecodePacket(string_tell).require match {
|
||||||
case ChatMsg(messagetype, unk1, recipient, contents) =>
|
case ChatMsg(messagetype, has_wide_contents, recipient, contents, note_contents) =>
|
||||||
messagetype mustEqual ChatMessageType.Tell
|
messagetype mustEqual ChatMessageType.Tell
|
||||||
unk1 mustEqual true
|
has_wide_contents mustEqual true
|
||||||
recipient mustEqual "def"
|
recipient mustEqual "def"
|
||||||
contents mustEqual "abc"
|
contents mustEqual "abc"
|
||||||
|
note_contents mustEqual None
|
||||||
case default =>
|
case default =>
|
||||||
ko
|
ko
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"encode" in {
|
"encode" in {
|
||||||
val msg_local = ChatMsg(ChatMessageType.Local, true, "", "abc")
|
val msg_local = ChatMsg(ChatMessageType.Local, true, "", "abc", None)
|
||||||
val pkt_local = PacketCoding.EncodePacket(msg_local).require.toByteVector
|
val pkt_local = PacketCoding.EncodePacket(msg_local).require.toByteVector
|
||||||
|
|
||||||
pkt_local mustEqual string_local
|
pkt_local mustEqual string_local
|
||||||
|
|
||||||
val msg_tell = ChatMsg(ChatMessageType.Tell, true, "def", "abc")
|
val msg_tell = ChatMsg(ChatMessageType.Tell, true, "def", "abc", None)
|
||||||
val pkt_tell = PacketCoding.EncodePacket(msg_tell).require.toByteVector
|
val pkt_tell = PacketCoding.EncodePacket(msg_tell).require.toByteVector
|
||||||
|
|
||||||
pkt_tell mustEqual string_tell
|
pkt_tell mustEqual string_tell
|
||||||
|
|
|
||||||
|
|
@ -148,13 +148,13 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
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, unk6, unk7, unk8) =>
|
||||||
//log.info("PlayerState: " + msg)
|
//log.info("PlayerState: " + msg)
|
||||||
|
|
||||||
case msg @ ChatMsg(messagetype, unk1, recipient, contents) =>
|
case msg @ ChatMsg(messagetype, has_wide_contents, recipient, contents, note_contents) =>
|
||||||
log.info("Chat: " + msg)
|
log.info("Chat: " + msg)
|
||||||
|
|
||||||
// TODO: Depending on messagetype, may need to prepend sender's name to contents with proper spacing
|
// TODO: Depending on messagetype, may need to prepend sender's name to contents with proper spacing
|
||||||
// TODO: Just replays the packet straight back to sender; actually needs to be routed to recipients!
|
// TODO: Just replays the packet straight back to sender; actually needs to be routed to recipients!
|
||||||
sendResponse(PacketCoding.CreateGamePacket(0, ChatMsg(messagetype, unk1, recipient, contents)))
|
sendResponse(PacketCoding.CreateGamePacket(0, ChatMsg(messagetype, has_wide_contents, recipient, contents, note_contents)))
|
||||||
|
|
||||||
case msg @ ChangeFireModeMessage(item_guid, fire_mode) =>
|
case msg @ ChangeFireModeMessage(item_guid, fire_mode) =>
|
||||||
log.info("ChangeFireMode: " + msg)
|
log.info("ChangeFireMode: " + msg)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue