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",