Code Monkey home page Code Monkey logo

psf-loginserver's People

Contributors

adamlc avatar aphedox avatar fate-jh avatar ivanwick avatar jgillich avatar kingferaligatr avatar lelfjior avatar ltripley36706 avatar mazo avatar mjsmith707 avatar nickpsf avatar pschord avatar renovate-bot avatar resaec avatar scrawnyronnie avatar sounours avatar tfarley avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

psf-loginserver's Issues

Chat - Various Chat Issues

  • /squad is currently global for team, despite Squads being implemented. We use /platoon on Test Live 51200 for Global to Team.

  • /platoon is not implemented for the proper Global to Team.

  • /broadcast is the default message, currently. On live, it was Local. The expected behavior for Master is currently Squad or Platoon, preferably Platoon, as the Global to Team chat.

  • Voice chat text is issued twice clientside.

This is the current setup for 51200 and it's pretty important to move this to Master.

Correctly handle SlottedMetaPacket

The current implementation is a hack. These packets are treated specially in the PS client (they are "slots" for reliable subpackets). The client only has 8 slots and the way it selects between them is strange.

Additionally, the server does not handle this packet type at all. The client will disconnect without this being handled.

Session dropping on world transfer has race condition

When sending the below

 val response = ConnectToWorldMessage(serverName, serverAddress.getHostString, serverAddress.getPort)
sendResponse(PacketCoding.CreateGamePacket(0, response))
sendResponse(DropSession(sessionId, "user transferring to world"))

combined with this

 def removeSessionById(id : Long, reason : String, graceful : Boolean) : Unit = {
    ...
    if(graceful) {
      for(i <- 0 to 5) {
        session.send(closePacket)
      }
    }

    // kill all session specific actors
    session.dropSession(graceful)
    ...
}

Can cause the client to fail when connecting to the world. Either we dont do this gracefully or we add a delay

2016-07-31 18:50:59,704  INFO "" login-session-router - New session ID=45 from /X:54346
2016-07-31 18:51:00,164  INFO "sessionId=45" LoginSessionActor - New login UN:ASDF PW:Some(ASDF). Client Version: 3.15.84, Dec  2 2009
2016-07-31 18:51:00,401  INFO "" world-session-router - New session ID=64 from /X:54345
2016-07-31 18:51:01,482  INFO "sessionId=45" LoginSessionActor - New login UN:ASDF PW:Some(ASDF). Client Version: 3.15.84, Dec  2 2009
2016-07-31 18:51:01,482  INFO "sessionId=45" LoginSessionActor - Connect to world request for 'PSForever'
2016-07-31 18:51:01,482  INFO "sessionId=45" login-session-router - Dropping session ID=45 (reason: user transferring to world)
2016-07-31 18:51:02,181  INFO "sourceThread=PsLogin-akka.actor.default-dispatcher-4, akkaSource=akka://PsLogin/user/login-udp-endpoint/login-session-router/login-session-45, sourceActorSystem=PsLogin, akkaTimestamp=16:51:02.179UTC" akka.actor.LocalActorRef - Message [LoginSessionActor$UpdateServerList] from Actor[akka://PsLogin/user/login-udp-endpoint/login-session-router/login-session-45#-1487728806] to Actor[akka://PsLogin/user/login-udp-endpoint/login-session-router/login-session-45#-1487728806] was not delivered. [1] dead letters encountered. This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.
2016-07-31 18:51:02,765 DEBUG "" login-session-router - Session(45, 954)
2016-07-31 18:51:02,765 DEBUG "" world-session-router - Session(64, 18)
2016-07-31 18:51:02,765 DEBUG "" login-session-router - Reaped session ID=45
2016-07-31 18:51:07,765 DEBUG "" world-session-router - Session(64, 36)
2016-07-31 18:51:10,104  INFO "" login-session-router - New session ID=46 from /X:54346
2016-07-31 18:51:10,105 ERROR "sessionId=46" CryptoSessionActor - Unexpected packet type EncryptedPacket(3,ByteVector(64 bytes, 0xf0603c68661fe8c7fb763576da764333fb763576da7643337d509584c0caadf043a470a8dbda3fbeb9f813e8de63c01d883a6e43af64c87e7d509584c0caadf0)) in state NewClient
2016-07-31 18:51:12,765 DEBUG "" world-session-router - Session(64, 54)
2016-07-31 18:51:12,765 DEBUG "" login-session-router - Session(46, 68)
2016-07-31 18:51:17,765 DEBUG "" login-session-router - Session(46, 68)
2016-07-31 18:51:17,765 DEBUG "" world-session-router - Session(64, 72)
2016-07-31 18:51:17,765  INFO "" login-session-router - Dropping session ID=46 (reason: session timed out (outbound))
2016-07-31 18:51:22,766 DEBUG "" world-session-router - Session(64, 90)
2016-07-31 18:51:22,766 DEBUG "" login-session-router - Session(46, 80)
2016-07-31 18:51:22,766 DEBUG "" login-session-router - Reaped session ID=46
2016-07-31 18:51:27,765 DEBUG "" world-session-router - Session(64, 108)
2016-07-31 18:51:30,135  INFO "" login-session-router - New session ID=47 from /X:54346
2016-07-31 18:51:30,135 ERROR "sessionId=47" CryptoSessionActor - Unexpected packet type EncryptedPacket(5,ByteVector(64 bytes, 0x68b300328436490dfb763576da764333fb763576da7643334cfbe2e844ef1969d6ddee09f3f196a72a05b601e766571e0f32b9dad9b89d9d7d509584c0caadf0)) in state NewClient

PlanetSide Combat Engineering

Currently we have no support for placed or triggered CE. This was a core aspect of planetside gameplay

  • Spitfires (server AI, aimbotting, hit scan)
  • Mines (enemy detection, blast radius)
  • Boomers (blast radius effect needed)
  • Motion Sensor Alarms (detection radius)
  • TRAP
  • AEGIS
    • Shielding (passive)
    • Terminal
  • Faction Turret

LoginSessionActor dies upon bad match

SessionRouter or some session specific parent needs to watch child Actors for death events and appropriately restart them.

2016-05-01 23:28:40,326 ERROR [PsLogin-akka.actor.default-dispatcher-10 sessionId=none] akka.actor.OneForOneStrategy - MultiPacket(Vector(ByteVector(62 bytes, 0x0009000403895053466f72657665720000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000), ByteVector(62 bytes, 0x0009000203895053466f72657665720000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000))) (of class psforever.net.MultiPacket)
scala.MatchError: MultiPacket(Vector(ByteVector(62 bytes, 0x0009000403895053466f72657665720000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000), ByteVector(62 bytes, 0x0009000203895053466f72657665720000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000))) (of class psforever.net.MultiPacket)
        at LoginSessionActor.handleControlPkt(LoginSessionActor.scala:37)
        at LoginSessionActor$$anonfun$Started$1.applyOrElse(LoginSessionActor.scala:30)
        at akka.actor.Actor$class.aroundReceive(Actor.scala:482)
        at LoginSessionActor.akka$actor$MDCContextAware$$super$aroundReceive(LoginSessionActor.scala:9)
        at akka.actor.MDCContextAware$class.aroundReceive(MDCContextAware.scala:25)
        at LoginSessionActor.aroundReceive(LoginSessionActor.scala:9)
        at akka.actor.ActorCell.receiveMessage(ActorCell.scala:526)
        at akka.actor.ActorCell.invoke(ActorCell.scala:495)
        at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:257)
        at akka.dispatch.Mailbox.run(Mailbox.scala:224)
        at akka.dispatch.Mailbox.exec(Mailbox.scala:234)
        at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
        at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
        at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
        at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)
2016-05-01 23:28:41,148 ERROR [PsLogin-akka.actor.default-dispatcher-31 sessionId=2] CryptoSessionActor - Failed to decode encrypted packet: Failed to parse control packet 0x09: unknown: expected constant BitVector(8 bits, 0x00) but got BitVector(8 bits, 0x03)
2016-05-01 23:28:42,041 ERROR [PsLogin-akka.actor.default-dispatcher-30 sessionId=2] CryptoSessionActor - Failed to decode encrypted packet: Failed to parse control packet 0x09: unknown: expected constant BitVector(8 bits, 0x00) but got BitVector(8 bits, 0x01)
2016-05-01 23:28:42,773 ERROR [PsLogin-akka.actor.default-dispatcher-31 sessionId=none] LoginSessionActor - Unknown message
2016-05-01 23:28:43,743 ERROR [PsLogin-akka.actor.default-dispatcher-31 sessionId=2] CryptoSessionActor - Failed to decode encrypted packet: Failed to parse control packet 0x09: unknown: expected constant BitVector(8 bits, 0x00) but got BitVector(8 bits, 0x04)
2016-05-01 23:28:43,885 ERROR [PsLogin-akka.actor.default-dispatcher-33 sessionId=2] CryptoSessionActor - Failed to decode encrypted packet: Failed to parse control packet 0x09: unknown: expected constant BitVector(8 bits, 0x00) but got BitVector(8 bits, 0x02)
2016-05-01 23:28:44,837 ERROR [PsLogin-akka.actor.default-dispatcher-33 sessionId=2] CryptoSessionActor - Failed to decode encrypted packet: Failed to parse control packet 0x09: unknown: expected constant BitVector(8 bits, 0x00) but got BitVector(8 bits, 0x03)
2016-05-01 23:28:45,851 ERROR [PsLogin-akka.actor.default-dispatcher-22 sessionId=2] CryptoSessionActor - Failed to decode encrypted packet: Failed to parse control packet 0x09: unknown: expected constant BitVector(8 bits, 0x00) but got BitVector(8 bits, 0x01)
2016-05-01 23:28:46,715 INFO  [PsLogin-akka.actor.default-dispatcher-33 sessionId=none] akka.actor.LocalActorRef - Message [psforever.net.ControlPacket] from Actor[akka://PsLogin/user/session-router/crypto-session2#1836272772] to Actor[akka://PsLogin/user/session-router/login-session2#-143057463] was not delivered. [1] dead letters encountered. This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.

Generate code documentation and diagrams.

In order for people to actually have a chance at contributing to this project, good documentation will be required. Scala is a hard enough barrier to entry as is. Bad documentation cannot be afforded.

Learn how to generate ScalaDocs: http://alvinalexander.com/scala/how-to-generate-scala-documentation-scaladoc-command-examples

Beyond ScalaDocs, higher level architectural diagrams will be required as this game server is Actor/Service oriented and will not be sharing memory between Actors. This is hard enough for me to figure out. I can't imagine the nightmare it would be for someone else new to this paradigm.

Non-unique actors are trying to be created

Not sure why this happens, but it occurs randomly when zoning. Seems like a race condition when switching zones.

player.Actor = context.actorOf(Props(classOf[PlayerControl], player), s"${player.Name}_${player.GUID.guid}")

2020-01-12 01:27:09,338  INFO "sessionId=10" WorldSessionActor - Load in zone z4 at position Vector3(3059.0,2144.0,70.0) in 0 seconds
2020-01-12 01:27:09,338  INFO "sessionId=10" WorldSessionActor - Chat: ChatMsg(CMT_ZONE,true,,z4,None)
2020-01-12 01:27:09,338  INFO "" WorldSessionActor - Player asdf will respawn
2020-01-12 01:27:09,338  INFO "" WorldSessionActor - Setting up combat engineering UI ...
2020-01-12 01:27:09,339 ERROR "sourceThread=PsLogin-akka.actor.default-dispatcher-12, akkaSource=akka://PsLogin/user/service/cluster/z4-actor/z4-players, sourceActorSystem=PsLogin, akkaTimestamp=01:27:09.339UTC" akka.actor.OneForOneStrategy - actor name [asdf_3317] is not unique!
akka.actor.InvalidActorNameException: actor name [asdf_3317] is not unique!
	at akka.actor.dungeon.ChildrenContainer$NormalChildrenContainer.reserve(ChildrenContainer.scala:129)
	at akka.actor.dungeon.Children$class.reserveChild(Children.scala:130)
	at akka.actor.ActorCell.reserveChild(ActorCell.scala:374)
	at akka.actor.dungeon.Children$class.makeChild(Children.scala:268)
	at akka.actor.dungeon.Children$class.actorOf(Children.scala:42)
	at akka.actor.ActorCell.actorOf(ActorCell.scala:374)
	at net.psforever.objects.zones.ZonePopulationActor$$anonfun$receive$1.applyOrElse(ZonePopulationActor.scala:48)
	at akka.actor.Actor$class.aroundReceive(Actor.scala:482)
	at net.psforever.objects.zones.ZonePopulationActor.aroundReceive(ZonePopulationActor.scala:21)
	at akka.actor.ActorCell.receiveMessage(ActorCell.scala:526)
	at akka.actor.ActorCell.invoke(ActorCell.scala:495)
	at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:257)
	at akka.dispatch.Mailbox.run(Mailbox.scala:224)
	at akka.dispatch.Mailbox.exec(Mailbox.scala:234)
	at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
	at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
	at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
	at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)
2020-01-12 01:27:09,750  INFO "sessionId=10" WorldSessionActor - CreateShortcutMessage: CreateShortcutMessage(ValidPlanetSideGUID(0),1,0,true,Some(Shortcut(0,medkit,,)))
2020-01-12 01:27:09,750  INFO "sessionId=10" WorldSessionActor - AvatarFirstTimeEvent: AvatarFirstTimeEventMessage(ValidPlanetSideGUID(3317),ValidPlanetSideGUID(6864),1,used_pulsar)
``

Change default file logger to rolling logger

Log files can get very big if the server is running for a while. Change config/logback.xml to incorporate rolling files
https://stackify.com/logging-logback/

<appender name="rollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <fileNamePattern>log-%d{yyyy-MM-dd}.log</fileNamePattern>
        <maxHistory>30</maxHistory> 
        <totalSizeCap>3GB</totalSizeCap>
    </rollingPolicy>
    <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
        <maxFileSize>3MB</maxFileSize>
    </triggeringPolicy>
    <encoder>
        <pattern>[%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
</appender>

Unbreak scoverage on WorldSessionActor

Requires #278 to have been partially addressed to lower the JVM bytecode size. There is no fix besides refactoring this file.

[error] /home/travis/build/psforever/PSF-LoginServer/pslogin/src/main/scala/WorldSessionActor.scala:67: Could not write class WorldSessionActor because it exceeds JVM code size limits. Method handleGamePkt's code too large!
[error] class WorldSessionActor extends Actor with MDCContextAware {
[error]       ^
[error] one error found
[error] (pslogin/compile:compileIncremental) Compilation failed
[error] Total time: 434 s, completed Oct 11, 2019 3:38:47 PM

Here is some context: https://github.com/scoverage/sbt-scoverage/issues/92

Crash - Combat Engineering - Damaging a deployable cadaver crashes WSA

2020-01-12 00:12:59,448  INFO "sessionId=7" WorldSessionActor - WeaponFire: WeaponFireMessage(355,ValidPlanetSideGUID(9829),ValidPlanetSideGUID(40113),Vector3(982.21094,1023.71094,100.875),0,446,63536,200,255,0,None)
2020-01-12 00:12:59,448  INFO "sessionId=7" WorldSessionActor - Hit: HitMessage(356,ValidPlanetSideGUID(40113),0,Some(HitInfo(Vector3(982.21094,1023.71094,100.875),Vector3(983.7422,1022.2344,100.515625),Some(ValidPlanetSideGUID(7460)))),true,false,None)
2020-01-12 00:12:59,606  INFO "sessionId=7" WorldSessionActor - WeaponFire: WeaponFireMessage(360,ValidPlanetSideGUID(9829),ValidPlanetSideGUID(40114),Vector3(982.2031,1023.71875,100.890625),0,486,63546,200,255,0,None)
2020-01-12 00:12:59,606  INFO "sessionId=7" WorldSessionActor - Hit: HitMessage(360,ValidPlanetSideGUID(40114),0,Some(HitInfo(Vector3(982.2031,1023.71875,100.890625),Vector3(983.75,1022.2422,100.5),Some(ValidPlanetSideGUID(7460)))),true,false,None)
2020-01-12 00:12:59,777  INFO "sessionId=7" WorldSessionActor - WeaponFire: WeaponFireMessage(365,ValidPlanetSideGUID(9829),ValidPlanetSideGUID(40115),Vector3(982.2031,1023.71875,100.890625),0,462,63549,200,255,0,None)
2020-01-12 00:12:59,777  INFO "sessionId=7" WorldSessionActor - Hit: HitMessage(365,ValidPlanetSideGUID(40115),0,Some(HitInfo(Vector3(982.2031,1023.71875,100.890625),Vector3(983.75,1022.2422,100.515625),Some(ValidPlanetSideGUID(7460)))),true,false,None)
2020-01-12 00:12:59,886  INFO "sessionId=7" WorldSessionActor - WeaponFire: WeaponFireMessage(370,ValidPlanetSideGUID(9829),ValidPlanetSideGUID(40116),Vector3(982.2031,1023.71875,100.890625),0,484,63574,200,255,0,None)
2020-01-12 00:12:59,886  INFO "sessionId=7" WorldSessionActor - Hit: HitMessage(370,ValidPlanetSideGUID(40116),0,Some(HitInfo(Vector3(982.2031,1023.71875,100.890625),Vector3(983.7656,1022.2578,100.5),Some(ValidPlanetSideGUID(7460)))),true,false,None)
2020-01-12 00:13:00,108  INFO "sessionId=7" WorldSessionActor - WeaponFire: WeaponFireMessage(375,ValidPlanetSideGUID(9829),ValidPlanetSideGUID(40117),Vector3(982.2031,1023.71875,100.890625),0,480,63569,200,255,0,None)
2020-01-12 00:13:00,108  INFO "sessionId=7" WorldSessionActor - Hit: HitMessage(375,ValidPlanetSideGUID(40117),0,Some(HitInfo(Vector3(982.2031,1023.71875,100.890625),Vector3(983.7578,1022.2578,100.5),Some(ValidPlanetSideGUID(7460)))),true,false,None)
2020-01-12 00:13:00,262  INFO "sessionId=7" WorldSessionActor - WeaponFire: WeaponFireMessage(380,ValidPlanetSideGUID(9829),ValidPlanetSideGUID(40118),Vector3(982.2031,1023.71875,100.890625),0,495,63594,200,255,0,None)
2020-01-12 00:13:00,262  INFO "sessionId=7" WorldSessionActor - Hit: HitMessage(380,ValidPlanetSideGUID(40118),0,Some(HitInfo(Vector3(982.2031,1023.71875,100.890625),Vector3(983.78125,1022.2656,100.484375),Some(ValidPlanetSideGUID(7460)))),true,false,None)
2020-01-12 00:13:00,404  INFO "sessionId=7" WorldSessionActor - WeaponFire: WeaponFireMessage(384,ValidPlanetSideGUID(9829),ValidPlanetSideGUID(40119),Vector3(982.2031,1023.71875,100.890625),0,495,63574,200,255,0,None)
2020-01-12 00:13:00,404  INFO "sessionId=7" WorldSessionActor - Hit: HitMessage(385,ValidPlanetSideGUID(40119),0,Some(HitInfo(Vector3(982.2031,1023.71875,100.890625),Vector3(983.7656,1022.2578,100.484375),Some(ValidPlanetSideGUID(7460)))),true,false,None)
2020-01-12 00:13:00,581  INFO "sessionId=7" WorldSessionActor - WeaponFire: WeaponFireMessage(389,ValidPlanetSideGUID(9829),ValidPlanetSideGUID(40120),Vector3(982.2031,1023.71875,100.890625),0,489,63583,200,255,0,None)
2020-01-12 00:13:00,581  INFO "sessionId=7" WorldSessionActor - Hit: HitMessage(389,ValidPlanetSideGUID(40120),0,Some(HitInfo(Vector3(982.2031,1023.71875,100.890625),Vector3(983.77344,1022.2578,100.484375),Some(ValidPlanetSideGUID(7460)))),true,false,None)
2020-01-12 00:13:00,756  INFO "sessionId=7" WorldSessionActor - WeaponFire: WeaponFireMessage(394,ValidPlanetSideGUID(9829),ValidPlanetSideGUID(40121),Vector3(982.2031,1023.71875,100.890625),0,497,63567,200,255,0,None)
2020-01-12 00:13:00,757  INFO "sessionId=7" WorldSessionActor - Hit: HitMessage(394,ValidPlanetSideGUID(40121),0,Some(HitInfo(Vector3(982.2031,1023.71875,100.890625),Vector3(983.7578,1022.25,100.484375),Some(ValidPlanetSideGUID(7460)))),true,false,None)
2020-01-12 00:13:00,911  INFO "sessionId=7" WorldSessionActor - WeaponFire: WeaponFireMessage(399,ValidPlanetSideGUID(9829),ValidPlanetSideGUID(40122),Vector3(982.2031,1023.71875,100.890625),0,483,63568,200,255,0,None)
2020-01-12 00:13:00,911  INFO "sessionId=7" WorldSessionActor - Hit: HitMessage(399,ValidPlanetSideGUID(40122),0,Some(HitInfo(Vector3(982.2031,1023.71875,100.890625),Vector3(983.7578,1022.2578,100.5),Some(ValidPlanetSideGUID(7460)))),true,false,None)
2020-01-12 00:13:01,073  INFO "sessionId=7" WorldSessionActor - WeaponFire: WeaponFireMessage(404,ValidPlanetSideGUID(9829),ValidPlanetSideGUID(40123),Vector3(982.2031,1023.71875,100.890625),0,490,63598,200,255,0,None)
2020-01-12 00:13:01,073  INFO "sessionId=7" WorldSessionActor - Hit: HitMessage(404,ValidPlanetSideGUID(40123),0,Some(HitInfo(Vector3(982.2031,1023.71875,100.890625),Vector3(983.78906,1022.2656,100.484375),Some(ValidPlanetSideGUID(7460)))),true,false,None)
2020-01-12 00:13:01,151  INFO "sessionId=7" WorldSessionActor - WeaponFire: WeaponFireMessage(409,ValidPlanetSideGUID(9829),ValidPlanetSideGUID(40124),Vector3(982.2031,1023.71875,100.890625),0,489,63560,200,255,0,None)
2020-01-12 00:13:01,248  INFO "sessionId=7" WorldSessionActor - Hit: HitMessage(409,ValidPlanetSideGUID(40124),0,Some(HitInfo(Vector3(982.2031,1023.71875,100.890625),Vector3(983.7578,1022.25,100.484375),Some(ValidPlanetSideGUID(7460)))),true,false,None)
2020-01-12 00:13:01,249 DEBUG "" services.support.SupportActor - a target submitted: Entry(net.psforever.objects.SensorDeployable@13e8b19d,Zones$$anon$14@12bb4822,0)
2020-01-12 00:13:01,267 DEBUG "" services.support.SupportActor - no tasks matching the targets List(net.psforever.objects.SensorDeployable@13e8b19d) have been cleared
2020-01-12 00:13:01,371  INFO "sessionId=7" WorldSessionActor - WeaponFire: WeaponFireMessage(414,ValidPlanetSideGUID(9829),ValidPlanetSideGUID(40100),Vector3(982.2031,1023.71875,100.890625),0,481,63550,200,255,0,None)
2020-01-12 00:13:01,371  INFO "sessionId=7" WorldSessionActor - Hit: HitMessage(414,ValidPlanetSideGUID(40100),0,Some(HitInfo(Vector3(982.2031,1023.71875,100.890625),Vector3(983.75,1022.2422,100.5),Some(ValidPlanetSideGUID(7460)))),true,false,None)
2020-01-12 00:13:01,376 ERROR "sourceThread=PsLogin-akka.actor.default-dispatcher-14, akkaSource=akka://PsLogin/user/world-udp-endpoint/world-session-router/world-session-7, sourceActorSystem=PsLogin, akkaTimestamp=00:13:01.374UTC" akka.actor.OneForOneStrategy - null
java.lang.NullPointerException: null
	at WorldSessionActor.HandleDealingDamage(WorldSessionActor.scala:8712)
	at WorldSessionActor.handleGamePkt(WorldSessionActor.scala:5661)
	at WorldSessionActor$$anonfun$Started$1.applyOrElse(WorldSessionActor.scala:359)
	at scala.PartialFunction$OrElse.applyOrElse(PartialFunction.scala:171)
	at akka.actor.Actor$class.aroundReceive(Actor.scala:482)
	at WorldSessionActor.akka$actor$MDCContextAware$$super$aroundReceive(WorldSessionActor.scala:80)
	at akka.actor.MDCContextAware$class.aroundReceive(MDCContextAware.scala:23)
	at WorldSessionActor.aroundReceive(WorldSessionActor.scala:80)
	at akka.actor.ActorCell.receiveMessage(ActorCell.scala:526)
	at akka.actor.ActorCell.invoke(ActorCell.scala:495)
	at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:257)
	at akka.dispatch.Mailbox.run(Mailbox.scala:224)
	at akka.dispatch.Mailbox.exec(Mailbox.scala:234)
	at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
	at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
	at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
	```

Handling Strings without Length

Having done some packet diving, I've discovered at least two packets that pass ASCII in a wide character format, but do not have the length prefacing the string directly. We have no prepared encoding or decoding for this kind of data as they all assume the first byte or pair of bytes are string length, and this means we can not build packet handling logic. The straightforward aspect of the packet handling also doesn't leave much room for interjection.

For example, a DestroyDisplayMessage packet looks like this:
81 8741006E00670065006C006C006F0035BC D801 8F 20 19207 0A 048004D00460049004300B18E D901 00
There are two character strings here. For the first string, 87 is the proper length (well, 7 is) so the whole thing can be decoded normally. For the second string, however, the length is actually encoded in the 0A in front of the lone 0 as twice the length of the string (5 x 2 = 10, or 0A; modifying it produces predictable results). The number format is incorrect, and the buffering 0 just throws the whole thing off.

In addition, passing DestroyDisplayMessage with the correct form of the encoded wide character string to the client - 8548004D00460049004300 - causes the client to display illegible pictograms in place of the string.

Here's an example of a DamageFeedbackMessage:
7B 76 1448004D0046004900430086 03 90 50 00 00 00
The wide character string is obvious but, this time, the only suggestions of the size exists as high order bits towards the far end of the data. Whether or not that's what it is, we can't deal with it. (A five letter wide character string also has twenty nibbles and 14 is 20 ... I just made that up on the spot.)

Complete abstraction for PlanetSide message channels

PlanetSide runs on top of UDP. UDP is not reliable.

We want a nice way for the user to send messages to a client with some reliability guarantees without worrying about how to construct a SlottedMetaPacket. We should completely abstract away from fragmentation issues, packet reordering, and packet loss.

Code needs to be written to correctly these cases if we are going to have a reliable server.
This is related to #3

Gating - Warpgates - Various Issues with Warpgates

TR can only get to Solsar from Sanctuary, and capturing Solsar does not grant you additional links.
NC has no functioning Warpgates, they all "one-way" instantly warp you back to Sanctuary Spawn
VS can only get to Ceryshen from Sanctuary

I think the current Test Live (51200) does something special to handle this. @SouNourS would know.

Docker build

It may be nice to have a Dockerfile so people can easily build the server, will probably make it easier for people to test too! I can have a stab at this over the next few days if you think it would be useful? :)

Fix Travis CI build

Travis CI is broken because we don't have a way to get the pscrypto library in to the build environment.

This isn't just a problem for Travis -- no one will be able to develop without this library.

Update README.md with contact informations

It would be nice when the README.md would contain information how to get in contact with the dev team (e.g. Discord or the website).

This issue is also relevant for other repositories like the world server.

LoginMessage packet does not handle token

When attempting to decode this appears

Failed to decode encrypted packet: Failed to parse control packet 0x07: Could not find a marshaller for control packet Unknown7
Failed to decode inner packet Failed to parse game packet 0x01: credential_choice: US-ASCII cannot decode string from '0x484f35366e51706c6c73705046395632000000000000000000b8060390b80603'
Failed to decode inner packet Failed to parse game packet 0x01: credential_choice: US-ASCII cannot decode string from '0x484f35366e51706c6c73705046395632000000000000000000b8060390b80603'

Looks like it could have something to do with the fixedSizedByte combinator in scodec (see

object LoginMessage extends Marshallable[LoginMessage] {
private def username = PacketHelpers.encodedStringAligned(7)
private def password = PacketHelpers.encodedString
private def tokenPath = fixedSizeBytes(32, bytes) :: username
private def passwordPath = username :: password
)

Make packet descriptions more DRY?

Currently there is a lot of boilerplate required to describe a new packet (names used in multiple places) and a lot of cross linking required between decoding and encoding. Maybe there isn't a way to avoid this but at the very least a way to template this would be awesome.

Thoughts below.

HotSpotUpdateMessage: Byte-Aligned Lists

HotSpotUpdateMessage is the packet that creates those explosions on the continental map that indicate where combat took place recently. While I think I understand how the packet is composed, and could otherwise write it, there's a bit of a snag with the decoding/encoding. The packet stores hotspot data as a list preceded by its size - scodec otherwise knows how to handle that - but the size is padded from the actual list by four bits. This makes the contents of the list byte-aligned. Scodec doesn't know how to handle that with its standard function listOfN. While it does come with a stock sizedList function that can handle manually provided sizes, the size has to be a non-negative Integer literal. if I could get there from a variable gotten via >>:~ from the same decoding process, that would be good, but I don't know how to do that. The function is not convinced.

I would like a function that works like listOfN, excepting that it ignores padding, but I can not repurpose the existing methods myself. listOfN handles List extraction by passing the buck off to a function called narrow; narrow does the same to exmap; and, the result of this chain is a Tuple that contains both the size and the already-extracted List data. The whole process is a bit spooky to walk through. The approach as with aligned wide-character Strings (issue #67) also might not be possible here.

Here's a sample: first a packet with no entries, a packet with one entry, then that same packets with the nibbles spaced by field.
9F 05 00 10 00
9F 05 00 10 10 00 2E 90 01 45 80 00 00
9F 0500 1 00 (0)
9F 0500 1 01000 2E9 00 145 80000 (0)
That weird 0 is the four bits of padding, with the size of the list as the byte before it and everything after it a part of the entry. The padding also can not be made a part of the entry to eliminate it because each entry begins right after the previous, with the first byte starting in place of the former trailing nibble.
9F 05 00 10 20 00 D0 70 08 CA 80 00 00 0B EA 00 4C 48 00 00
9F 0500 1 02000D07008CA80000 00BEA004C480000

Choose database solution for the LoginServer

Some candidates:

  • MongoDB
  • CouchDB
  • MySQL
  • Flat file
  • ...

It seems like NoSQL / document based DB would allow me to move fast and use plain ol' JSON. A SQL based DB would probably be overkill unless that's preferred for account records. More transient data, such as game state may benefit more from a NoSQL solution.

Cannot dismount "owned" AMS after mounting

2019-12-15 21:27:01,901  INFO "sessionId=108" WorldSessionActor - DismountVehicleMsg: DismountVehicleMsg(PlanetSideGUID(5113),Normal,false)
2019-12-15 21:27:01,901  WARN "" WorldSessionActor - DismountVehicleMsg: TR awildchord i3-5113 100/100 50/50 attempted to dismount ams, owned by Some(PlanetSideGUID(5113)): (3000/3000)(0/601) (1)'s seat 0, but was not allowed

I was allowed to enter but not leave ๐Ÿ˜ฌ

Refactor WorldSessionActor

It's been said for a while at this point, but WorldSessionActor needs to be broken up into smaller files. It has grown to nearly 10K lines of Scala, which is dense as it is. Maintaining and understanding this file is likely next to impossible for new developers. It's so big that TravisCI fails to compile it with code coverage enabled!

Nearly all of the player business logic for PlanetSide is in this single file. Let's start to logically divide this up into smaller sub-files.

Unhandled Cryptopacket Bitvector

Resulted in an "Unknown Login Error" message during Login Progress.
image

See debug log: pslogin-debug_2019-10-11_20-45-09.log

[ERROR] CryptoSessionActor - Could not decode packet in state CryptoSetupFinishing: unmarshal_crypto_packet/obj_type?: expected constant BitVector(8 bits, 0x10) but got BitVector(8 bits, 0x01) [ERROR] CryptoSessionActor - Could not decode packet in state CryptoSetupFinishing: unmarshal_crypto_packet/obj_type?: expected constant BitVector(8 bits, 0x10) but got BitVector(8 bits, 0x01) [ERROR] CryptoSessionActor - Could not decode packet in state CryptoSetupFinishing: unmarshal_crypto_packet/obj_type?: expected constant BitVector(8 bits, 0x10) but got BitVector(8 bits, 0x01)

VNLWorldStatusMessage cannot handle multiple worlds

PlanetSide packet decoding is so next-gen that string decoding can occur on non-byte aligned boundaries. Scodec doesnt like this (especially since codecs are structural, not dynamic in nature) and is not able to decode a second world:

("worlds" | vectorOfN(uint8L, (
// XXX: this needs to be limited to 0x20 bytes
// XXX: this needs to be byte aligned, but not sure how to do this
("world_name" | PacketHelpers.encodedString) :: (

This reason this occurs is that the end of the world record within the VNLWorldStatusMessage is not byte aligned. On the second go around for a new world record, the bitvector is misaligned. Within the PlanetSide client there is an alignment operation performed right after the length of the following string is read. This is okay, but the VNLWorldStatusMessage isn't written for a misalignment. This leads to the behavior that the first entry decodes fine, but not the second. The only way I see to handle this is to somehow communicate to the encodedString codec that the input stream is misaligned. But of course, scodec is pure functional and PlanetSide decoding is imperative (meaning the decoding class has access to the current position in the overall bitstream).

Scodec may need to be modified or something completely custom may have to be done for this case. I would prefer to have a general solution as this issue is definitely going to come up again in a different way.

Crash - CTD - Zone Transfer - When characters zone, the client often crashes to desktop during the Loading Screen

When characters zone, the client often crashes to desktop during the Loading Screen.

Current Result: The game client will commonly crash to desktop during zone transfer.
Expected Result: The game client should never crash during zone transfer.

Reproduction Steps:

  • Using the /zone command, transfer between different continents repeatedly (you can spam /zone z2 /zone z3 /zone z2 /zone z3 etc)
  • Observe crash to desktop

Integrate MariaDB connector in to the server

We have settled on MariaDB for our database. This is essentially feature equivalent with MySQL but more open source (different philosophy).

Now we need

  • A Scala library that works well with MariaDB / MySQL. We DO NOT want a typesafe super-scala crazyness library as it will probably be much harder to read and our SQL will not be portable
  • An understanding of how JDBC fits in to all of this
  • Some schemas to start building (login session, world session, world list, character table, world state)

Fix GamePacket vs GamePacketContainer naming and datastructures

I cannot for the life of me, even as the author, reliably write code that deals with unwrapping packet containers in to inner packets. The naming scheme must change.

Also, the decision to handle packet sequence numbers in the containers was not well thought out as more reverse engineering had to be done in order to figure out how they were actually being used. Now I know once encryption is enabled that they are used for game and control packets. Control packet containers do not have a field for sequence numbers. This is because the first packets that are sent are control packets, but they are NOT sequences.

This maybe should be rethought as it is just not working as is.

Make Control Packets more Approachable

Comment extracted from PR #152 :

"[In regards to working with SlottedMetaPackets,] after reviewing how packets are handled, I determined the best place to intercept packets as they left the server was CyptoSessionActor. They leave WorldSessionActor to CSA as packets and they leave CSA to SessionRouter as bit/byte vectors. If I were to handle them at the WSA level, I'd be testing the packet length by prematurely encoding them and, if it was a sufficient length for maximum transmission unit restrictions, I'd be stuck. Since I wouldn't be manipulating them any further, either I would have to send out the original packet and have it encoded a second time later or I would send out my encoded data and completely bypass checks that were written into CSA. Hoisting [this logic] out of CSA means that the same complicated procedures would have to be repeated in LoginSessionActor as well as anything else we build on top of CSA.
"...
"SlottedMetaPacket and MultiPacket/MultiPacketEx need to change. That's my opinion. The data that is supposed to be put in them is a 'stream', but that inconveniences our ability to construct them since a 'stream' is further along in our process of encoding than we allow input and control. We lack the ability of feeding multiple packets into Multi, for example, because our normal procedure works one packet at a time. It's unnecessarily restricting and suggests the doubling of work. We extract and decode the data from these Control packets whenever we need it, and just once, because, until we process the packet, it's just a Control packet with a 'stream of data.'"

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.