mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-01-19 18:14:44 +00:00
Working login to TR Sancuary!
Packet: SetCurrentAvatarMessage Lots of hacks to get here, but wow, what a milestone.
This commit is contained in:
parent
e0db8ec2b7
commit
5fa0610208
|
|
@ -1,4 +1,4 @@
|
|||
# PlanetSide Login Server
|
||||
# PlanetSide Login Server [](https://travis-ci.org/psforever/PSF-LoginServer)
|
||||
This project contains the code to run and manage the login server role for PlanetSide 1.
|
||||
|
||||

|
||||
|
|
|
|||
|
|
@ -347,7 +347,7 @@ object GamePacketOpcode extends Enumeration {
|
|||
case UnknownMessage21 => noDecoder(opcode)
|
||||
case BindPlayerMessage => noDecoder(opcode)
|
||||
case ObjectCreateMessage_Duplicate => noDecoder(opcode)
|
||||
case ObjectCreateMessage => noDecoder(opcode)
|
||||
case ObjectCreateMessage => game.ObjectCreateMessage.decode
|
||||
case ObjectDeleteMessage => noDecoder(opcode)
|
||||
case PingMsg => noDecoder(opcode)
|
||||
case VehicleStateMessage => noDecoder(opcode)
|
||||
|
|
@ -379,7 +379,7 @@ object GamePacketOpcode extends Enumeration {
|
|||
case LoadMapMessage => noDecoder(opcode)
|
||||
|
||||
// OPCODE 50
|
||||
case SetCurrentAvatarMessage => noDecoder(opcode)
|
||||
case SetCurrentAvatarMessage => game.SetCurrentAvatarMessage.decode
|
||||
case ObjectHeldMessage => noDecoder(opcode)
|
||||
case WeaponFireMessage => noDecoder(opcode)
|
||||
case AvatarJumpMessage => noDecoder(opcode)
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ final case class CharacterInfoMessage(zoneId : PlanetSideZoneID,
|
|||
|
||||
object CharacterInfoMessage extends Marshallable[CharacterInfoMessage] {
|
||||
implicit val codec : Codec[CharacterInfoMessage] = (
|
||||
("unknown" | uint32L).unit(0) ::
|
||||
("unknown" | uint32L).unit(0) :: // this type is set to unit as we dont know what it is yet
|
||||
("zoneId" | PlanetSideZoneID.codec) ::
|
||||
("charId" | uint32L) ::
|
||||
("charGUID" | PlanetSideGUID.codec) ::
|
||||
|
|
|
|||
|
|
@ -4,9 +4,6 @@ import net.psforever.packet.{GamePacketOpcode, Marshallable, PacketHelpers, Plan
|
|||
import scodec.Codec
|
||||
import scodec.codecs._
|
||||
|
||||
/**
|
||||
* Created by Root on 5/19/2016.
|
||||
*/
|
||||
final case class KeepAliveMessage(code : Int) extends PlanetSideGamePacket {
|
||||
type Packet = KeepAliveMessage
|
||||
def opcode = GamePacketOpcode.KeepAliveMessage
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@ case class ObjectCreateMessageParent(guid : Int, slot : Int)
|
|||
case class ObjectCreateMessage(streamLength : Long,
|
||||
objectClass : Int,
|
||||
guid : Int,
|
||||
parentInfo : Option[ObjectCreateMessageParent])
|
||||
parentInfo : Option[ObjectCreateMessageParent]
|
||||
)
|
||||
extends PlanetSideGamePacket {
|
||||
|
||||
def opcode = GamePacketOpcode.ObjectCreateMessage
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
// Copyright (c) 2016 PSForever.net to present
|
||||
package net.psforever.packet.game
|
||||
|
||||
import net.psforever.packet.{GamePacketOpcode, Marshallable, PacketHelpers, PlanetSideGamePacket}
|
||||
import scodec.Codec
|
||||
import scodec.codecs._
|
||||
|
||||
final case class SetCurrentAvatarMessage(guid: PlanetSideGUID, unk1 : Int, unk2 : Int) extends PlanetSideGamePacket {
|
||||
type Packet = SetCurrentAvatarMessage
|
||||
def opcode = GamePacketOpcode.SetCurrentAvatarMessage
|
||||
def encode = SetCurrentAvatarMessage.encode(this)
|
||||
}
|
||||
|
||||
object SetCurrentAvatarMessage extends Marshallable[SetCurrentAvatarMessage] {
|
||||
implicit val codec: Codec[SetCurrentAvatarMessage] = (
|
||||
("guid" | PlanetSideGUID.codec) ::
|
||||
("unk1" | uint(3)) ::
|
||||
("unk2" | uint(3))
|
||||
).as[SetCurrentAvatarMessage]
|
||||
}
|
||||
|
|
@ -142,5 +142,26 @@ class GamePacketTest extends Specification {
|
|||
(hex"1f".bits ++ bin"0" ++ hex"01000000".bits).toByteVector
|
||||
}
|
||||
}
|
||||
|
||||
"ObjectCreateMessage" should {
|
||||
val packet = hex"18 CF 13 00 00 BC 87 00 0A F0 16 C3 43 A1 30 90 00 02 C0 40 00 08 70 43 00 68 00 6F 00 72 00 64 00 54 00 52 00 82 65 1F F5 9E 80 80 00 00 00 00 00 3F FF C0 00 00 00 20 00 00 00 20 27 03 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FC CC 10 00 03 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 90 01 90 00 00 00 00 01 00 7E C8 00 C8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 C0 00 42 C5 46 86 C7 00 00 02 A0 00 00 12 60 78 70 65 5F 77 61 72 70 5F 67 61 74 65 5F 75 73 61 67 65 92 78 70 65 5F 69 6E 73 74 61 6E 74 5F 61 63 74 69 6F 6E 92 78 70 65 5F 73 61 6E 63 74 75 61 72 79 5F 68 65 6C 70 91 78 70 65 5F 62 61 74 74 6C 65 5F 72 61 6E 6B 5F 32 8E 78 70 65 5F 66 6F 72 6D 5F 73 71 75 61 64 8E 78 70 65 5F 74 68 5F 6E 6F 6E 73 61 6E 63 8B 78 70 65 5F 74 68 5F 61 6D 6D 6F 90 78 70 65 5F 74 68 5F 66 69 72 65 6D 6F 64 65 73 8F 75 73 65 64 5F 63 68 61 69 6E 62 6C 61 64 65 9A 76 69 73 69 74 65 64 5F 62 72 6F 61 64 63 61 73 74 5F 77 61 72 70 67 61 74 65 8E 76 69 73 69 74 65 64 5F 6C 6F 63 6B 65 72 8D 75 73 65 64 5F 70 75 6E 69 73 68 65 72 88 75 73 65 64 5F 72 65 6B 8D 75 73 65 64 5F 72 65 70 65 61 74 65 72 9F 76 69 73 69 74 65 64 5F 64 65 63 6F 6E 73 74 72 75 63 74 69 6F 6E 5F 74 65 72 6D 69 6E 61 6C 8F 75 73 65 64 5F 73 75 70 70 72 65 73 73 6F 72 96 76 69 73 69 74 65 64 5F 6F 72 64 65 72 5F 74 65 72 6D 69 6E 61 6C 85 6D 61 70 31 35 85 6D 61 70 31 34 85 6D 61 70 31 32 85 6D 61 70 30 31 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 0A 36 13 88 04 00 40 00 00 10 00 04 00 00 4D 6E 40 10 41 00 00 00 40 00 18 08 38 1C C0 20 32 00 00 07 80 15 E1 D0 02 10 20 00 00 08 00 03 01 07 13 A8 04 06 40 00 00 10 03 20 BB 00 42 E4 00 00 01 00 0E 07 70 08 6C 80 00 06 40 01 C0 F0 01 13 90 00 00 C8 00 38 1E 40 23 32 00 00 19 00 07 03 D0 05 0E 40 00 03 20 00 E8 7B 00 A4 C8 00 00 64 00 DA 4F 80 14 E1 00 00 00 40 00 18 08 38 1F 40 20 32 00 00 0A 00 08 "
|
||||
val packet2 = hex"18 17 74 00 00 BC 8C 10 90 3B 45 C6 FA 94 00 9F F0 00 00 40 00 08 C0 44 00 69 00 66 00 66 00 45"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(packet2).require match {
|
||||
case obj @ ObjectCreateMessage(len, cls, guid, parent) =>
|
||||
len === 29719
|
||||
cls === 121
|
||||
guid === 2497
|
||||
parent === None
|
||||
case default =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
ok
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ class CryptoSessionActor extends Actor with MDCContextAware {
|
|||
def NewClient : Receive = {
|
||||
case RawPacket(msg) =>
|
||||
PacketCoding.UnmarshalPacket(msg) match {
|
||||
case Failure(e) => log.error("Could not decode packet: " + e)
|
||||
case Failure(e) => log.error("Could not decode packet: " + e + s", msg ${msg.toString}")
|
||||
case Successful(p) =>
|
||||
//println("RECV: " + p)
|
||||
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ class LoginSessionActor extends Actor with MDCContextAware {
|
|||
}
|
||||
|
||||
val serverName = "PSForever"
|
||||
val serverAddress = new InetSocketAddress(InetAddress.getLocalHost, 51001)
|
||||
val serverAddress = new InetSocketAddress("192.168.0.2", 51001)
|
||||
|
||||
def handleGamePkt(pkt : PlanetSideGamePacket) = pkt match {
|
||||
case LoginMessage(majorVersion, minorVersion, buildDate, username,
|
||||
|
|
@ -112,7 +112,7 @@ class LoginSessionActor extends Actor with MDCContextAware {
|
|||
case ConnectToWorldRequestMessage(name, _, _, _, _, _, _) =>
|
||||
log.info(s"Connect to world request for '${name}'")
|
||||
|
||||
val response = ConnectToWorldMessage(serverName, serverAddress.getHostName, serverAddress.getPort)
|
||||
val response = ConnectToWorldMessage(serverName, serverAddress.getHostString, serverAddress.getPort)
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, response))
|
||||
case default => log.debug(s"Unhandled GamePacket ${pkt}")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import scodec.bits._
|
|||
class WorldSessionActor extends Actor with MDCContextAware {
|
||||
private[this] val log = org.log4s.getLogger
|
||||
|
||||
private case class UpdateServerList()
|
||||
private case class PokeClient()
|
||||
|
||||
var leftRef : ActorRef = ActorRef.noSender
|
||||
var rightRef : ActorRef = ActorRef.noSender
|
||||
|
|
@ -34,6 +34,9 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
handlePktContainer(ctrl)
|
||||
case game @ GamePacket(_, _, _) =>
|
||||
handlePktContainer(game)
|
||||
// temporary hack to keep the client from disconnecting
|
||||
case PokeClient() =>
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, KeepAliveMessage(0)))
|
||||
case default => failWithError(s"Invalid packet class received: $default")
|
||||
}
|
||||
|
||||
|
|
@ -92,6 +95,9 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
}
|
||||
}
|
||||
|
||||
// XXX: hard coded ObjectCreateMessage
|
||||
val objectHex = hex"18 57 0C 00 00 BC 84 B0 06 C2 D7 65 53 5C A1 60 00 01 34 40 00 09 70 49 00 6C 00 6C 00 6C 00 49 00 49 00 49 00 6C 00 6C 00 6C 00 49 00 6C 00 49 00 6C 00 6C 00 49 00 6C 00 6C 00 6C 00 49 00 6C 00 6C 00 49 00 84 52 70 76 1E 80 80 00 00 00 00 00 3F FF C0 00 00 00 20 00 00 0F F6 A7 03 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FD 90 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 90 01 90 00 64 00 00 01 00 7E C8 00 C8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 C0 00 42 C5 46 86 C7 00 00 00 80 00 00 12 40 78 70 65 5F 73 61 6E 63 74 75 61 72 79 5F 68 65 6C 70 90 78 70 65 5F 74 68 5F 66 69 72 65 6D 6F 64 65 73 8B 75 73 65 64 5F 62 65 61 6D 65 72 85 6D 61 70 31 33 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 0A 23 02 60 04 04 40 00 00 10 00 06 02 08 14 D0 08 0C 80 00 02 00 02 6B 4E 00 82 88 00 00 02 00 00 C0 41 C0 9E 01 01 90 00 00 64 00 44 2A 00 10 91 00 00 00 40 00 18 08 38 94 40 20 32 00 00 00 80 19 05 48 02 17 20 00 00 08 00 70 29 80 43 64 00 00 32 00 0E 05 40 08 9C 80 00 06 40 01 C0 AA 01 19 90 00 00 C8 00 3A 15 80 28 72 00 00 19 00 04 0A B8 05 26 40 00 03 20 06 C2 58 00 A7 88 00 00 02 00 00 80 00 00 "
|
||||
|
||||
def handleGamePkt(pkt : PlanetSideGamePacket) = pkt match {
|
||||
case ConnectToWorldRequestMessage(server, token, majorVersion, minorVersion, revision, buildDate, unk) =>
|
||||
|
||||
|
|
@ -99,8 +105,14 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
|
||||
log.info(s"New world login to ${server} with Token:${token}. ${clientVersion}")
|
||||
|
||||
// ObjectCreateMessage
|
||||
sendRawResponse(objectHex)
|
||||
// XXX: hard coded message
|
||||
sendRawResponse(hex"14 0F 00 00 00 10 27 00 00 C1 D8 7A 02 4B 00 26 5C B0 80 00 ")
|
||||
|
||||
// NOTE: PlanetSideZoneID just chooses the background
|
||||
sendResponse(PacketCoding.CreateGamePacket(0,
|
||||
CharacterInfoMessage(PlanetSideZoneID(0), 0, PlanetSideGUID(0), true, 0)))
|
||||
CharacterInfoMessage(PlanetSideZoneID(1), 0, PlanetSideGUID(0), true, 0)))
|
||||
case msg @ CharacterRequestMessage(charId, action) =>
|
||||
log.info("Handling " + msg)
|
||||
|
||||
|
|
@ -108,6 +120,18 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
case CharacterRequestAction.Delete =>
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, ActionResultMessage(false, Some(1))))
|
||||
case CharacterRequestAction.Select =>
|
||||
PacketCoding.DecodeGamePacket(objectHex).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, _) =>
|
||||
// LoadMapMessage 13714 in mossy .gcap
|
||||
// XXX: hardcoded shit
|
||||
sendRawResponse(hex"31 85 6D 61 70 31 32 85 68 6F 6D 65 32 6C 9D 19 00 00 00 5F 40 B2 1C 80 ")
|
||||
sendRawResponse(objectHex)
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, SetCurrentAvatarMessage(PlanetSideGUID(guid),0,0)))
|
||||
|
||||
import scala.concurrent.duration._
|
||||
import scala.concurrent.ExecutionContext.Implicits.global
|
||||
context.system.scheduler.schedule(0 seconds, 1000 milliseconds, self, PokeClient())
|
||||
}
|
||||
case default =>
|
||||
log.error("Unsupported " + default + " in " + msg)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue