diff --git a/common/src/main/scala/net/psforever/packet/game/BuildingInfoUpdateMessage.scala b/common/src/main/scala/net/psforever/packet/game/BuildingInfoUpdateMessage.scala index 205adf29..28ffc71a 100644 --- a/common/src/main/scala/net/psforever/packet/game/BuildingInfoUpdateMessage.scala +++ b/common/src/main/scala/net/psforever/packet/game/BuildingInfoUpdateMessage.scala @@ -2,6 +2,7 @@ package net.psforever.packet.game import net.psforever.packet.{GamePacketOpcode, Marshallable, PacketHelpers, PlanetSideGamePacket} +import net.psforever.types.PlanetSideEmpire import scodec.{Attempt, Codec, Err} import scodec.codecs._ import shapeless.{::, HNil} diff --git a/common/src/main/scala/net/psforever/packet/game/CharacterCreateRequestMessage.scala b/common/src/main/scala/net/psforever/packet/game/CharacterCreateRequestMessage.scala index b616493d..ed5b4528 100644 --- a/common/src/main/scala/net/psforever/packet/game/CharacterCreateRequestMessage.scala +++ b/common/src/main/scala/net/psforever/packet/game/CharacterCreateRequestMessage.scala @@ -2,8 +2,10 @@ package net.psforever.packet.game import net.psforever.packet.{GamePacketOpcode, Marshallable, PacketHelpers, PlanetSideGamePacket} -import scodec.Codec +import net.psforever.types.PlanetSideEmpire +import scodec.{Attempt, Codec, Err} import scodec.codecs._ +import shapeless.{::, HNil} object CharacterGender extends Enumeration(1) { type Type = Value @@ -34,5 +36,17 @@ object CharacterCreateRequestMessage extends Marshallable[CharacterCreateRequest ("voiceId" | uint8L) :: ("gender" | CharacterGender.codec) :: ("empire" | PlanetSideEmpire.codec) - ).as[CharacterCreateRequestMessage] + ).exmap[CharacterCreateRequestMessage] ( + { + case name :: headId :: voiceId :: gender :: empire :: HNil => + Attempt.successful(CharacterCreateRequestMessage(name, headId, voiceId, gender, empire)) + }, + { + case CharacterCreateRequestMessage(name, _, _, _, PlanetSideEmpire.NEUTRAL) => + Attempt.failure(Err(s"character $name's faction can not declare as neutral")) + + case CharacterCreateRequestMessage(name, headId, voiceId, gender, empire) => + Attempt.successful(name :: headId :: voiceId :: gender :: empire :: HNil) + } + ) } \ No newline at end of file diff --git a/common/src/main/scala/net/psforever/packet/game/ContinentalLockUpdateMessage.scala b/common/src/main/scala/net/psforever/packet/game/ContinentalLockUpdateMessage.scala index 0b119347..24b0f319 100644 --- a/common/src/main/scala/net/psforever/packet/game/ContinentalLockUpdateMessage.scala +++ b/common/src/main/scala/net/psforever/packet/game/ContinentalLockUpdateMessage.scala @@ -2,21 +2,21 @@ package net.psforever.packet.game import net.psforever.packet.{GamePacketOpcode, Marshallable, PacketHelpers, PlanetSideGamePacket} +import net.psforever.types.PlanetSideEmpire import scodec.Codec import scodec.codecs._ /** - * Create a dispatched game packet that instructs the client to update the user about continents that are conquered. - * + * Create a dispatched game packet that instructs the client to update the user about continents that are conquered.
+ *
* This generates the event message "The [empire] have captured [continent]." * If the continent_guid is not a valid zone, no message is displayed. - * If empire is not a valid empire, no message is displayed. - * + * If empire is not a valid empire, or refers to the neutral or Black Ops forces, no message is displayed. * @param continent_guid identifies the zone (continent) - * @param empire identifies the empire; this value is matchable against PlanetSideEmpire + * @param empire identifies the empire */ final case class ContinentalLockUpdateMessage(continent_guid : PlanetSideGUID, - empire : PlanetSideEmpire.Value) // 00 for TR, 40 for NC, 80 for VS; C0 generates no message + empire : PlanetSideEmpire.Value) extends PlanetSideGamePacket { type Packet = ContinentalLockUpdateMessage def opcode = GamePacketOpcode.ContinentalLockUpdateMessage diff --git a/common/src/main/scala/net/psforever/packet/game/DestroyDisplayMessage.scala b/common/src/main/scala/net/psforever/packet/game/DestroyDisplayMessage.scala index bbd14756..5adfa168 100644 --- a/common/src/main/scala/net/psforever/packet/game/DestroyDisplayMessage.scala +++ b/common/src/main/scala/net/psforever/packet/game/DestroyDisplayMessage.scala @@ -2,6 +2,7 @@ package net.psforever.packet.game import net.psforever.packet.{GamePacketOpcode, Marshallable, PacketHelpers, PlanetSideGamePacket} +import net.psforever.types.PlanetSideEmpire import scodec.Codec import scodec.codecs._ @@ -24,8 +25,8 @@ import scodec.codecs._ * In the case of absentee kills, for example, where there is no killer listed, this field has been zero'd (`00000000`).
*
* The faction affiliation is different from the normal way `PlanetSideEmpire` values are recorded. - * The higher nibble will reflect the first part of the `PlanetSideEmpire` value - `0` for TR, `4` for NC `8` for TR, `C` for Neutral/BOPs. - * An extra `20` will be added if the player is in a vehicle or turret at the time - `2` for TR, `6` for NC, `A` for VS, `E` for Neutral/BOPs. + * The higher nibble will reflect the first part of the `PlanetSideEmpire` value. + * An extra `20` will be added if the player is in a vehicle or turret at the time. * When marked as being in a vehicle or turret, the player's name will be enclosed within square brackets. * The length of the player's name found at the start of the wide character string does not reflect whether or not there will be square brackets (fortunately).
*
@@ -36,26 +37,24 @@ import scodec.codecs._ * It is also unknown what the two bytes preceding `method` specify, as changing them does nothing to the displayed message. * @param killer the name of the player who did the killing * @param killer_unk See above - * @param killer_empire the empire affiliation of the killer: - * 0 - TR, 1 - NC, 2 - VS, 3 - Neutral/BOPs + * @param killer_empire the empire affiliation of the killer * @param killer_inVehicle true, if the killer was in a vehicle at the time of the kill; false, otherwise * @param unk na; but does not like being set to 0 * @param method modifies the icon in the message, related to the way the victim was killed * @param victim the name of the player who was killed * @param victim_unk See above - * @param victim_empire the empire affiliation of the victim: - * 0 - TR, 1 - NC, 2 - VS, 3 - Neutral/BOPs + * @param victim_empire the empire affiliation of the victim * @param victim_inVehicle true, if the victim was in a vehicle when he was killed; false, otherwise */ final case class DestroyDisplayMessage(killer : String, killer_unk : Long, - killer_empire : Int, + killer_empire : PlanetSideEmpire.Value, killer_inVehicle : Boolean, - unk : PlanetSideGUID, - method : PlanetSideGUID, + unk : Int, + method : Int, victim : String, victim_unk : Long, - victim_empire : Int, + victim_empire : PlanetSideEmpire.Value, victim_inVehicle : Boolean ) extends PlanetSideGamePacket { @@ -68,13 +67,13 @@ object DestroyDisplayMessage extends Marshallable[DestroyDisplayMessage] { implicit val codec : Codec[DestroyDisplayMessage] = ( ("killer" | PacketHelpers.encodedWideString) :: ("killer_unk" | ulongL(32)) :: - ("killer_empire" | uintL(2)) :: + ("killer_empire" | PlanetSideEmpire.codec) :: ("killer_inVehicle" | bool) :: - ("unk" | PlanetSideGUID.codec) :: - ("method" | PlanetSideGUID.codec) :: + ("unk" | uint16L) :: + ("method" | uint16L) :: ("victim" | PacketHelpers.encodedWideStringAligned(5)) :: ("victim_unk" | ulongL(32)) :: - ("victim_empire" | uintL(2)) :: + ("victim_empire" | PlanetSideEmpire.codec) :: ("victim_inVehicle" | bool) ).as[DestroyDisplayMessage] } diff --git a/common/src/main/scala/net/psforever/packet/game/SetEmpireMessage.scala b/common/src/main/scala/net/psforever/packet/game/SetEmpireMessage.scala index 0dcc7428..bb05ef05 100644 --- a/common/src/main/scala/net/psforever/packet/game/SetEmpireMessage.scala +++ b/common/src/main/scala/net/psforever/packet/game/SetEmpireMessage.scala @@ -2,6 +2,7 @@ package net.psforever.packet.game import net.psforever.packet.{GamePacketOpcode, Marshallable, PacketHelpers, PlanetSideGamePacket} +import net.psforever.types.PlanetSideEmpire import scodec.Codec import scodec.codecs._ diff --git a/common/src/main/scala/net/psforever/packet/game/VNLWorldStatusMessage.scala b/common/src/main/scala/net/psforever/packet/game/VNLWorldStatusMessage.scala index 32d5fc60..b3933422 100644 --- a/common/src/main/scala/net/psforever/packet/game/VNLWorldStatusMessage.scala +++ b/common/src/main/scala/net/psforever/packet/game/VNLWorldStatusMessage.scala @@ -4,6 +4,7 @@ package net.psforever.packet.game import java.net.{InetAddress, InetSocketAddress} import net.psforever.packet.{GamePacketOpcode, Marshallable, PacketHelpers, PlanetSideGamePacket} +import net.psforever.types.PlanetSideEmpire import scodec._ import scodec.bits._ import scodec.codecs._ @@ -22,13 +23,6 @@ object ServerType extends Enumeration(1) { implicit val codec = PacketHelpers.createEnumerationCodec(this, uint8L) } -object PlanetSideEmpire extends Enumeration { - type Type = Value - val TR, NC, VS, NEUTRAL = Value - - implicit val codec = PacketHelpers.createEnumerationCodec(this, uint2L) -} - final case class WorldConnectionInfo(address : InetSocketAddress) final case class WorldInformation(name : String, status : WorldStatus.Value, diff --git a/common/src/main/scala/net/psforever/packet/game/objectcreate/CharacterData.scala b/common/src/main/scala/net/psforever/packet/game/objectcreate/CharacterData.scala index b614fc70..7b252414 100644 --- a/common/src/main/scala/net/psforever/packet/game/objectcreate/CharacterData.scala +++ b/common/src/main/scala/net/psforever/packet/game/objectcreate/CharacterData.scala @@ -2,7 +2,7 @@ package net.psforever.packet.game.objectcreate import net.psforever.packet.{Marshallable, PacketHelpers} -import net.psforever.types.Vector3 +import net.psforever.types.{PlanetSideEmpire, Vector3} import scodec.{Attempt, Codec, Err} import scodec.codecs._ import shapeless.{::, HNil} @@ -18,11 +18,6 @@ import shapeless.{::, HNil} * This base length of this stream is __430__ known bits, excluding the length of the name and the padding on that name. * Of that, __203__ bits are perfectly unknown in significance. *
- * Faction:
- * `0 - Terran Republic`
- * `1 - New Conglomerate`
- * `2 - Vanu Sovereignty`
- *
* Exo-suit:
* `0 - Agile`
* `1 - Refinforced`
@@ -91,7 +86,7 @@ import shapeless.{::, HNil} */ final case class CharacterAppearanceData(pos : Vector3, objYaw : Int, - faction : Int, + faction : PlanetSideEmpire.Value, bops : Boolean, unk1 : Int, name : String, @@ -138,7 +133,7 @@ object CharacterAppearanceData extends Marshallable[CharacterAppearanceData] { ignore(16) :: ("objYaw" | uint8L) :: ignore(1) :: - ("faction" | uint2L) :: + ("faction" | PlanetSideEmpire.codec) :: ("bops" | bool) :: ("unk1" | uint4L) :: ignore(16) :: @@ -164,7 +159,23 @@ object CharacterAppearanceData extends Marshallable[CharacterAppearanceData] { ("unk8" | uint4L) :: ignore(6) :: ("ribbons" | RibbonBars.codec) - ).as[CharacterAppearanceData] + ).exmap[CharacterAppearanceData] ( + { + case a :: _ :: b :: _ :: c :: d :: e :: _ :: f :: g :: _ :: h :: i :: j :: k :: l :: _ :: m :: n :: o :: _ :: p :: _ :: q :: _ :: r :: s :: t :: _ :: u :: HNil => + Attempt.successful( + CharacterAppearanceData(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) + ) + }, + { + case CharacterAppearanceData(_, _, PlanetSideEmpire.NEUTRAL, _, _, name, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) => + Attempt.failure(Err(s"character $name's faction can not declare as neutral")) + + case CharacterAppearanceData(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) => + Attempt.successful( + a :: () :: b :: () :: c :: d :: e :: () :: f :: g :: () :: h :: i :: j :: k :: l :: () :: m :: n :: o :: () :: p :: () :: q :: () :: r :: s :: t :: () :: u :: HNil + ) + } + ) } /** diff --git a/common/src/main/scala/net/psforever/packet/game/objectcreate/ObjectClass.scala b/common/src/main/scala/net/psforever/packet/game/objectcreate/ObjectClass.scala index 7e44ff7a..2daf870d 100644 --- a/common/src/main/scala/net/psforever/packet/game/objectcreate/ObjectClass.scala +++ b/common/src/main/scala/net/psforever/packet/game/objectcreate/ObjectClass.scala @@ -421,7 +421,6 @@ object ObjectClass { case ObjectClass.battlewagon_weapon_systemb => WeaponData.genericCodec case ObjectClass.battlewagon_weapon_systemc => WeaponData.genericCodec case ObjectClass.battlewagon_weapon_systemd => WeaponData.genericCodec - case ObjectClass.beamer => WeaponData.genericCodec case ObjectClass.bolt_driver => WeaponData.genericCodec case ObjectClass.chainblade => WeaponData.genericCodec case ObjectClass.chaingun_p => WeaponData.genericCodec diff --git a/common/src/main/scala/net/psforever/types/PlanetSideEmpire.scala b/common/src/main/scala/net/psforever/types/PlanetSideEmpire.scala new file mode 100644 index 00000000..9f4481c1 --- /dev/null +++ b/common/src/main/scala/net/psforever/types/PlanetSideEmpire.scala @@ -0,0 +1,15 @@ +// Copyright (c) 2016 PSForever.net to present +package net.psforever.types + +import net.psforever.packet.PacketHelpers +import scodec.codecs.uint2L + +/** + * Values for the three empires and the neutral/Black Ops group. + */ +object PlanetSideEmpire extends Enumeration { + type Type = Value + val TR, NC, VS, NEUTRAL = Value + + implicit val codec = PacketHelpers.createEnumerationCodec(this, uint2L) +} diff --git a/common/src/test/scala/GamePacketTest.scala b/common/src/test/scala/GamePacketTest.scala index 4897caba..99c4c07d 100644 --- a/common/src/test/scala/GamePacketTest.scala +++ b/common/src/test/scala/GamePacketTest.scala @@ -374,7 +374,7 @@ class GamePacketTest extends Specification { char.appearance.pos.y mustEqual 2726.789f char.appearance.pos.z mustEqual 91.15625f char.appearance.objYaw mustEqual 19 - char.appearance.faction mustEqual 2 //vs + char.appearance.faction mustEqual PlanetSideEmpire.VS char.appearance.bops mustEqual false char.appearance.unk1 mustEqual 4 char.appearance.name mustEqual "IlllIIIlllIlIllIlllIllI" @@ -529,7 +529,7 @@ class GamePacketTest extends Specification { val app = CharacterAppearanceData( Vector3(3674.8438f, 2726.789f, 91.15625f), 19, - 2, + PlanetSideEmpire.VS, false, 4, "IlllIIIlllIlIllIlllIllI", @@ -1332,13 +1332,13 @@ class GamePacketTest extends Specification { case DestroyDisplayMessage(killer, killer_unk, killer_empire, killer_inVehicle, unk, method, victim, victim_unk, victim_empire, victim_inVehicle) => killer mustEqual "Angello" killer_unk mustEqual 30981173 - killer_empire mustEqual 2 + killer_empire mustEqual PlanetSideEmpire.VS killer_inVehicle mustEqual false - unk mustEqual PlanetSideGUID(121) - method mustEqual PlanetSideGUID(969) + unk mustEqual 121 + method mustEqual 969 victim mustEqual "HMFIC" victim_unk mustEqual 31035057 - victim_empire mustEqual 0 + victim_empire mustEqual PlanetSideEmpire.TR victim_inVehicle mustEqual false case default => ko @@ -1346,7 +1346,7 @@ class GamePacketTest extends Specification { } "encode" in { - val msg = DestroyDisplayMessage("Angello", 30981173, 2, false, PlanetSideGUID(121), PlanetSideGUID(969), "HMFIC", 31035057, 0, false) + val msg = DestroyDisplayMessage("Angello", 30981173, PlanetSideEmpire.VS, false, 121, 969, "HMFIC", 31035057, PlanetSideEmpire.TR, false) val pkt = PacketCoding.EncodePacket(msg).require.toByteVector pkt mustEqual string } diff --git a/pslogin/src/main/scala/LoginSessionActor.scala b/pslogin/src/main/scala/LoginSessionActor.scala index 8131b89c..8fa98af4 100644 --- a/pslogin/src/main/scala/LoginSessionActor.scala +++ b/pslogin/src/main/scala/LoginSessionActor.scala @@ -9,6 +9,7 @@ import org.log4s.MDC import scodec.Attempt.{Failure, Successful} import scodec.bits._ import MDCContextAware.Implicits._ +import net.psforever.types.PlanetSideEmpire import scala.concurrent.duration._ import scala.util.Random diff --git a/pslogin/src/main/scala/WorldSessionActor.scala b/pslogin/src/main/scala/WorldSessionActor.scala index f960132b..f00ea41a 100644 --- a/pslogin/src/main/scala/WorldSessionActor.scala +++ b/pslogin/src/main/scala/WorldSessionActor.scala @@ -10,7 +10,7 @@ import scodec.bits._ import org.log4s.MDC import MDCContextAware.Implicits._ import net.psforever.packet.game.objectcreate._ -import net.psforever.types.{ChatMessageType, Vector3} +import net.psforever.types.{ChatMessageType, PlanetSideEmpire, Vector3} class WorldSessionActor extends Actor with MDCContextAware { private[this] val log = org.log4s.getLogger @@ -113,7 +113,7 @@ class WorldSessionActor extends Actor with MDCContextAware { val app = CharacterAppearanceData( Vector3(3674.8438f, 2726.789f, 91.15625f), 19, - 2, + PlanetSideEmpire.VS, false, 4, "IlllIIIlllIlIllIlllIllI",