Improve ChatMsg and fix LoginRespMessage

This commit is contained in:
Chord 2016-08-06 11:23:28 -04:00
parent 38715c0d04
commit cb2507360e
4 changed files with 36 additions and 12 deletions

View file

@ -11,18 +11,28 @@ import scodec.codecs._
* Instructs client to display and/or process a chat message/command when sent server to client. * Instructs client to display and/or process a chat message/command when sent server to client.
* Instructs server to route and/or process a chat message/command when sent client to server. * Instructs server to route and/or process a chat message/command when sent client to server.
* *
* @param messagetype the type of the chat message (CMT) * @param messageType the type of the chat message (CMT)
* @param has_wide_contents whether the contents contains wide characters or not * @param wideContents whether the contents contains wide characters or not. This is
* required because Java/Scala have one String type with a charset
* of UTF-16. Therefore, there is no way at runtime to determine the
* charset of String.
* @param recipient identifies the recipient of the message, such as in a tell (occasionally used as "sender" instead i.e. /note) * @param recipient identifies the recipient of the message, such as in a tell (occasionally used as "sender" instead i.e. /note)
* @param contents the textual contents of the message * @param contents the textual contents of the message
* @param note_contents only present when the message is of note type * @param note only used when the message is of note type
*/ */
final case class ChatMsg(messagetype : ChatMessageType.Value, final case class ChatMsg(messageType : ChatMessageType.Value,
has_wide_contents : Boolean, wideContents : Boolean,
recipient : String, recipient : String,
contents : String, contents : String,
note_contents : Option[String]) note : Option[String])
extends PlanetSideGamePacket { extends PlanetSideGamePacket {
// Prevent usage of the Note field unless the message is of type note
if(messageType == ChatMessageType.CMT_NOTE)
assert(note.isDefined, "Note contents required")
else
assert(note.isEmpty, "Note contents found, but message type isnt Note")
type Packet = ChatMsg type Packet = ChatMsg
def opcode = GamePacketOpcode.ChatMsg def opcode = GamePacketOpcode.ChatMsg
def encode = ChatMsg.encode(this) def encode = ChatMsg.encode(this)
@ -31,10 +41,13 @@ final case class ChatMsg(messagetype : 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_value => ("messagetype" | ChatMessageType.codec) >>:~ { messagetype_value =>
(("has_wide_contents" | bool) >>:~ { has_wide_contents_value => (("has_wide_contents" | bool) >>:~ { isWide =>
("recipient" | PacketHelpers.encodedWideStringAligned(7)) :: ("recipient" | PacketHelpers.encodedWideStringAligned(7)) ::
newcodecs.binary_choice(has_wide_contents_value, ("contents" | PacketHelpers.encodedWideString), ("contents" | PacketHelpers.encodedString)) newcodecs.binary_choice(isWide,
"contents" | PacketHelpers.encodedWideString,
"contents" | PacketHelpers.encodedString)
}) :+ }) :+
conditional(messagetype_value == ChatMessageType.CMT_NOTE, ("note_contents" | PacketHelpers.encodedWideString)) conditional(messagetype_value == ChatMessageType.CMT_NOTE,
"note_contents" | PacketHelpers.encodedWideString)
}).as[ChatMsg] }).as[ChatMsg]
} }

View file

@ -26,7 +26,9 @@ object LoginRespMessage extends Marshallable[LoginRespMessage] {
("station_error" | uint32L) :: ("station_error" | uint32L) ::
("subscription_status" | uint32L) :: ("subscription_status" | uint32L) ::
("unknown" | uint32L) :: ("unknown" | uint32L) ::
("username" | PacketHelpers.encodedString) :: ( ("username" | PacketHelpers.encodedString) ::
("privilege" | uint32L) flatZip { priv => bool } xmap[Long]({case (a, _) => a}, priv => (priv, (priv & 1) == 1))) ("privilege" | uint32L)
.flatZip(priv => bool)
.xmap[Long]({case (a, _) => a}, priv => (priv, (priv & 1) == 1))
).as[LoginRespMessage] ).as[LoginRespMessage]
} }

View file

@ -5,7 +5,7 @@ import net.psforever.crypto.CryptoInterface
import net.psforever.crypto.CryptoInterface.CryptoDHState import net.psforever.crypto.CryptoInterface.CryptoDHState
import scodec.bits._ import scodec.bits._
class CryptoInterfaceTest extends Specification { class CryptoInterfaceTest extends Specification { args(stopOnFail = true)
"Crypto interface" should { "Crypto interface" should {
"correctly initialize" in { "correctly initialize" in {
CryptoInterface.initialize() CryptoInterface.initialize()

View file

@ -206,6 +206,15 @@ class GamePacketTest extends Specification {
pkt_tell mustEqual string_tell pkt_tell mustEqual string_tell
} }
"allow and disallow note" in {
ChatMsg(ChatMessageType.CMT_ARMOR,
false,
"DontCare", "DontCare", Some("Should be here")) must throwA[AssertionError]
ChatMsg(ChatMessageType.CMT_NOTE,
false,
"DontCare", "DontCare", None) must throwA[AssertionError]
}
} }
"ChangeFireModeMessage" should { "ChangeFireModeMessage" should {