Initial support for server REPL (#68)

* Initial support for server console

* Expand README

* Fix unmanagedClasspath for `sbt pslogin/console`
This commit is contained in:
L-11 2016-08-26 22:46:57 -05:00 committed by pschord
parent 2ee4d27a9d
commit 88b6974edc
3 changed files with 57 additions and 9 deletions

View file

@ -51,6 +51,40 @@ sbt pslogin/run
```
This will clone the repository and SBT will compile and run the login server. Note: SBT is quite slow at starting up. It's recommended you have an open SBT console in order to avoid this startup time.
## Running the Server
To run a headless, non-interactive server, run
```
sbt pslogin/run
```
PlanetSide can now connect to your server.
To run your custom server with an interactive `scala>` REPL, run
```
sbt pslogin/console
```
![image](https://cloud.githubusercontent.com/assets/16912082/18024110/7b48dba8-6bc8-11e6-81d8-4692bc9d48a8.png)
To start the server and begin listening for connections, enter the following expression into the REPL:
```
PsLogin.run
```
![image](https://cloud.githubusercontent.com/assets/16912082/18024137/1167452a-6bc9-11e6-8765-a86fb465de61.png)
This process is identical to running the headless, non-interactive server: PlanetSide clients can connect, logging output will be printed to the screen, etc. The advantage is that you now have an interactive REPL that will evaluate any Scala expression you type into it.
![image](https://cloud.githubusercontent.com/assets/16912082/18024339/62197f66-6bcd-11e6-90f7-5569d33472a7.png)
The REPL supports various useful commands. For example, to see the type of an arbitrary expression `foo`, run `:type foo`. To print all members of a type, run `:javap -p some-type`. You can run `:help` to see a full list of commands.
![image](https://cloud.githubusercontent.com/assets/16912082/18024371/e0b72f9e-6bcd-11e6-9de5-421ec3eff994.png)
## Connecting to the Server through the Client
To get PlanetSide to connect to your custom server, you will have to navigate to the `client.ini` file (located within the PlanetSide game directory) and modify the IP addresses.

View file

@ -22,7 +22,8 @@ lazy val commonSettings = Seq(
lazy val pscryptoSettings = Seq(
unmanagedClasspath in Test += (baseDirectory in ThisBuild).value / "pscrypto-lib",
unmanagedClasspath in Runtime += (baseDirectory in ThisBuild).value / "pscrypto-lib"
unmanagedClasspath in Runtime += (baseDirectory in ThisBuild).value / "pscrypto-lib",
unmanagedClasspath in Compile += (baseDirectory in ThisBuild).value / "pscrypto-lib"
)
lazy val psloginPackSettings = packAutoSettings ++ Seq(

View file

@ -21,6 +21,14 @@ import scala.concurrent.duration._
object PsLogin {
private val logger = org.log4s.getLogger
var args : Array[String] = Array()
var config : java.util.Map[String,Object] = null
var system : akka.actor.ActorSystem = null
var loginRouter : akka.actor.Props = null
var worldRouter : akka.actor.Props = null
var loginListener : akka.actor.ActorRef = null
var worldListener : akka.actor.ActorRef = null
def banner() : Unit = {
println(ansi().fgBright(BLUE).a(""" ___ ________"""))
println(ansi().fgBright(BLUE).a(""" / _ \/ __/ __/__ _______ _ _____ ____"""))
@ -94,7 +102,7 @@ object PsLogin {
}
}
def main(args : Array[String]) : Unit = {
def run() : Unit = {
// Early start up
banner()
println(systemInformation)
@ -109,7 +117,7 @@ object PsLogin {
}
initializeLogging(configDirectory + File.separator + "logback.xml")
parseArgs(args)
parseArgs(this.args)
/** Initialize the PSCrypto native library
*
@ -143,14 +151,14 @@ object PsLogin {
* This same config can be specified in a configuration file, but that's more work at this point.
* In the future we will have a unified configuration file specific to this server
*/
val config = Map(
config = Map(
"akka.loggers" -> List("akka.event.slf4j.Slf4jLogger").asJava,
"akka.loglevel" -> "INFO",
"akka.logging-filter" -> "akka.event.slf4j.Slf4jLoggingFilter"
).asJava
/** Start up the main actor system. This "system" is the home for all actors running on this server */
val system = ActorSystem("PsLogin", ConfigFactory.parseMap(config))
system = ActorSystem("PsLogin", ConfigFactory.parseMap(config))
/** Create pipelines for the login and world servers
*
@ -186,10 +194,10 @@ object PsLogin {
*/
/** Create two actors for handling the login and world server endpoints */
val listener = system.actorOf(Props(new UdpListener(Props(new SessionRouter("Login", loginTemplate)), "login-session-router",
LoginConfig.serverIpAddress, loginServerPort, None)), "login-udp-endpoint")
val worldListener = system.actorOf(Props(new UdpListener(Props(new SessionRouter("World", worldTemplate)), "world-session-router",
LoginConfig.serverIpAddress, worldServerPort, None)), "world-udp-endpoint")
loginRouter = Props(new SessionRouter("Login", loginTemplate))
worldRouter = Props(new SessionRouter("World", worldTemplate))
loginListener = system.actorOf(Props(new UdpListener(loginRouter, "login-session-router", LoginConfig.serverIpAddress, loginServerPort, None)), "login-udp-endpoint")
worldListener = system.actorOf(Props(new UdpListener(worldRouter, "world-session-router", LoginConfig.serverIpAddress, worldServerPort, None)), "world-udp-endpoint")
logger.info(s"NOTE: Set client.ini to point to ${LoginConfig.serverIpAddress.getHostAddress}:$loginServerPort")
@ -198,6 +206,11 @@ object PsLogin {
// TODO: clean up active sessions and close resources safely
logger.info("Login server now shutting down...")
}
}
def main(args : Array[String]) : Unit = {
this.args = args
run()
// Wait forever until the actor system shuts down
Await.result(system.whenTerminated, Duration.Inf)