From 129b49a3876ceb68f271c311d5e45efb2e205300 Mon Sep 17 00:00:00 2001 From: Joel Kronqvist Date: Sat, 9 Nov 2024 16:32:09 +0200 Subject: Made & implemented clearer protocol, added client functionality --- src/main/scala/Server/Server.scala | 56 ++++++++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 20 deletions(-) (limited to 'src/main/scala/Server/Server.scala') diff --git a/src/main/scala/Server/Server.scala b/src/main/scala/Server/Server.scala index faf82e1..a03bc53 100644 --- a/src/main/scala/Server/Server.scala +++ b/src/main/scala/Server/Server.scala @@ -4,21 +4,16 @@ package o1game.Server // TODO: TLS/SSL / import javax.net.ssl.SSLServerSocketFactory import java.lang.Thread.{currentThread, sleep} +import java.io.IOException import java.net.{ServerSocket, Socket} import o1game.constants.* import o1game.Model.Adventure import o1game.Model.Entity +import o1game.utils.stringToByteArray import java.lang.System.currentTimeMillis import scala.util.Try -/** Converts this string to an array of bytes (probably for transmission). - * - * @param str the string to convert - * @return an array of bytes representing the string in UTF8. - */ -def stringToByteArray(str: String): Array[Byte] = - str.toVector.map(_.toByte).toArray /** `Server` exists to initialize a server for the game * and run it with its method `startServer`. @@ -52,17 +47,19 @@ class Server( sleep(POLL_INTERVAL) private def serverStep(): Unit = + this.clients.removeNonCompliant() if this.adventure.isEmpty || this.joinAfterStart then this.receiveNewClient() this.readFromAll() - this.writeClientDataToClients() - this.clients.removeNonCompliant() this.clients.foreach(_.interpretData()) + this.writeClientDataToClients() if this.canExecuteTurns then - println("taking turns") - this.clients.inRandomOrder(_.act()) - this.writeToAll("next turn!") - this.previousTurn = currentTimeMillis() / 1000 + this.clients.inRandomOrder(_.act()) + this.writeClientDataToClients() + this.clients.foreach(c => + this.writeToClient(this.turnStartInfo(c), c) + ) + this.previousTurn = currentTimeMillis() / 1000 if this.adventure.isDefined && this.joinAfterStart then this.clients.foreach( c => if c.isReadyForGameStart then this.adventure.foreach(a => @@ -91,7 +88,7 @@ class Server( case None => None case None => None entity.foreach(c.giveEntity(_)) - this.writeToClient(s"$timeLimit", c) + this.writeToClient(s"$timeLimit\r\n", c) /** Helper function to determine if the next turn can be taken */ @@ -119,6 +116,25 @@ class Server( case None => false + private def turnStartInfo(client: Client): String = + val clientArea = client.entity.map(_.location) + val areaDesc = clientArea + .map(_.description) + .getOrElse("You are floating in the middle of a soothing void.") + val directions = clientArea + .map(_.getNeighborNames.mkString(LIST_SEPARATOR)) + .getOrElse("") + val items = clientArea + .map(_.getItemNames.mkString(LIST_SEPARATOR)) + .getOrElse("") + val entities = client.entity.map(c => + c.location + .getEntityNames + .filter(c.name != _) + .mkString(LIST_SEPARATOR) + ).getOrElse("") + s"$TURN_INDICATOR\r\n$areaDesc\r\n$directions\r\n$items\r\n$entities\r\n" + /** Sends `message` to all clients * * @param message the message to send @@ -131,13 +147,13 @@ class Server( ) private def writeToClient(message: String, client: Client): Unit = - val success = Try( () => + try { val output = client.socket.getOutputStream - output.write(stringToByteArray(message)) + output.write(message.toVector.map(_.toByte).toArray) output.flush() - ) - if success.isFailure then - client.failedProtocol() + } catch { + case e: IOException => client.failedProtocol() + } /** Sends every client's `dataToThisClient` to the client */ private def writeClientDataToClients(): Unit = @@ -158,4 +174,4 @@ class Server( c.receiveData(buffer.take(bytesRead).toVector) ) -end Server \ No newline at end of file +end Server -- cgit v1.2.3