diff options
author | Joel Kronqvist <joel.kronqvist@iki.fi> | 2024-11-07 21:00:04 +0200 |
---|---|---|
committer | Joel Kronqvist <joel.kronqvist@iki.fi> | 2024-11-07 21:00:04 +0200 |
commit | 891b6f877ba848a3f78851a757734ebd1f066798 (patch) | |
tree | 849d4f9bac3b3e83f84b6319d7148f93f5a44c06 | |
parent | fdaec6534eb7ee902c75be3e4b732b6970abd859 (diff) | |
download | scalevalapokalypsi-891b6f877ba848a3f78851a757734ebd1f066798.tar.gz scalevalapokalypsi-891b6f877ba848a3f78851a757734ebd1f066798.zip |
Added comments for documentation and reformatted old ones
-rw-r--r-- | src/main/scala/Server/Client.scala | 63 | ||||
-rw-r--r-- | src/main/scala/Server/Clients.scala | 44 | ||||
-rw-r--r-- | src/main/scala/Server/Server.scala | 19 |
3 files changed, 81 insertions, 45 deletions
diff --git a/src/main/scala/Server/Client.scala b/src/main/scala/Server/Client.scala index 1e5dd00..d9bb529 100644 --- a/src/main/scala/Server/Client.scala +++ b/src/main/scala/Server/Client.scala @@ -17,24 +17,53 @@ class Client(val socket: Socket): private var protocolIsIntact = true private var name: Option[String] = None - /** Calculates the amount of bytes available for future incoming messages - */ + /** Calculates the amount of bytes available for future incoming messages */ def spaceAvailable: Int = MAX_MSG_SIZE - incompleteMessageIndex + /** Tests whether the client has behaved according to protocol. + * + * @return false if there has been a protocol violation, true otherwise + */ def isIntactProtocolWise: Boolean = protocolIsIntact + + /** Tests whether this client is initialized and ready to start the game + * + * @return true if the client is ready to join the game + */ def isReadyForGameStart: Boolean = this.protocolState == WaitingForGameStart + + /** Signals this client that it's joining the game. This is important so + * that this object knows to update its protocol state. + */ def gameStart(): Unit = this.protocolState = InGame + + /** Returns the entity this client controls in the model. + * + * @return an option containing the entity + */ def entity: Option[Entity] = this.character + + /** Tells this client object that it controls the specified entity. + * + * @param entity the entity this client is to control + */ def giveEntity(entity: Entity): Unit = println(entity) this.character = Some(entity) + + /** Gets the name of this client, which should match the name of the entity + * that is given to this client. Not very useful if the client hasn't yet + * received the name or if it already has an entity. + * + * @return the name of this client + */ def getName: Option[String] = this.name /** Sets `data` as received for the client. - * - * @return false means there was not enough space to receive the message - */ + * + * @return false means there was not enough space to receive the message + */ def receiveData(data: Vector[Byte]): Boolean = for i <- 0 until min(data.length, spaceAvailable) do this.incompleteMessage(this.incompleteMessageIndex + i) = data(i) @@ -44,8 +73,8 @@ class Client(val socket: Socket): data.length < spaceAvailable /** Returns data that should be sent to this client. - * The data is cleared when calling. - */ + * The data is cleared when calling. + */ def dataToThisClient(): String = val a = this.outData this.outData = "" @@ -61,7 +90,7 @@ class Client(val socket: Socket): /** Returns one line of data if there are any line breaks. - * Removes the parsed data from the message buffering area. + * Removes the parsed data from the message buffering area. */ private def nextLine(): Option[String] = val nextLF = this.incompleteMessage.indexOf(LF) @@ -74,8 +103,7 @@ class Client(val socket: Socket): else None - /** Causes the client to take the actions it has received - */ + /** Causes the client to take the actions it has received */ def interpretData(): Unit = LazyList.continually(this.nextLine()) .takeWhile(_.isDefined) @@ -83,11 +111,11 @@ class Client(val socket: Socket): .foreach(s => takeAction(s)) /** Makes the client execute the action specified by `line`. - * If there is a protocol error, the function changes - * the variable `protocolIsIntact` to false. - * - * @param line the line to interpret - */ + * If there is a protocol error, the function changes + * the variable `protocolIsIntact` to false. + * + * @param line the line to interpret + */ private def takeAction(line: String): Unit = this.protocolIsIntact = this.protocolState match case WaitingForVersion => @@ -109,8 +137,9 @@ class Client(val socket: Socket): this.character.flatMap(action.execute(_)) match case Some(s) => this.addDataToSend(s) case None => this.addDataToSend("You can't do that") - this.character.map(_.location.fullDescription) match - case Some(s) => this.addDataToSend(s) + this.character + .map(_.location.fullDescription) + .foreach(this.addDataToSend(_)) true end Client diff --git a/src/main/scala/Server/Clients.scala b/src/main/scala/Server/Clients.scala index 24a245c..786a09a 100644 --- a/src/main/scala/Server/Clients.scala +++ b/src/main/scala/Server/Clients.scala @@ -6,11 +6,11 @@ class Clients(maxClients: Int): private val clients: Array[Option[Client]] = Array.fill(maxClients)(None) /** Adds `client` to this collection of clients. - * - * @param client the Client to add - * @return true if there was room for the client - * i.e. fewer clients than `maxClients`, false otherwise - */ + * + * @param client the Client to add + * @return true if there was room for the client + * i.e. fewer clients than `maxClients`, false otherwise + */ def addClient(client: Client): Boolean = val i = this.clients.indexOf(None) if i == -1 then @@ -20,9 +20,9 @@ class Clients(maxClients: Int): true /** Returns all the clients. - * - * @return an iterable of all the clients - */ + * + * @return an iterable of all the clients + */ def allClients: Iterable[Client] = clients.toVector.flatten /** Applies the function `f` to all the clients for its side effects. */ @@ -36,17 +36,21 @@ class Clients(maxClients: Int): */ def forall(f: Client => Boolean): Boolean = this.clients.flatten.forall(f) + /** Gets the names of all the clients stored by this object. + * + * @return the names of the clients + */ def names: Vector[String] = this.clients.flatten.flatMap(_.getName).toVector def isEmpty: Boolean = this.clients.flatten.isEmpty /** Applies the function `f` to all the clients for its side effects - * and removes all the clients for which `f([client])` returns false. - * This is useful for doing IO with the client and removing clients - * with stale sockets. - * - * @param f the function to apply to all the clients and filter them with - */ + * and removes all the clients for which `f([client])` returns false. + * This is useful for doing IO with the client and removing clients + * with stale sockets. + * + * @param f the function to apply to all the clients and filter them with + */ def removeNonSatisfying(f: Client => Boolean): Unit = for i <- this.clients.indices do this.clients(i) match @@ -60,11 +64,11 @@ class Clients(maxClients: Int): this.removeNonSatisfying(_.isIntactProtocolWise) /** Applies the function f to all clients for its side effects. - * If the function throws an exception, the client is removed. - * Probably a more concise alternative to `removeNonSatisfying`, - * but might catch exceptions unintentionally. - * - * @param f the function to apply for its side effects to each client - */ + * If the function throws an exception, the client is removed. + * Probably a more concise alternative to `removeNonSatisfying`, + * but might catch exceptions unintentionally. + * + * @param f the function to apply for its side effects to each client + */ def mapAndRemove(f: Client => Unit): Unit = this.removeNonSatisfying(c => Try(f(c)).isSuccess) diff --git a/src/main/scala/Server/Server.scala b/src/main/scala/Server/Server.scala index c0a76ca..6fa284c 100644 --- a/src/main/scala/Server/Server.scala +++ b/src/main/scala/Server/Server.scala @@ -3,14 +3,17 @@ package o1game.Server // TODO: TLS/SSL / import javax.net.ssl.SSLServerSocketFactory -import java.io.IOException import java.lang.Thread.sleep import java.net.{ServerSocket, Socket} import o1game.constants.* import o1game.Model.Adventure import o1game.Model.Entity -import scala.collection.mutable.Map +/** 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 @@ -50,9 +53,9 @@ class Server(port: Int, maxClients: Int, val timeLimit: Int): /** Receives a new client and stores it in `clients`. - * - * @return describes if a client was added - */ + * + * @return describes if a client was added + */ private def receiveNewClient(): Boolean = this.clientGetter.newClient() match case Some(c) => @@ -62,9 +65,9 @@ class Server(port: Int, maxClients: Int, val timeLimit: Int): false /** Sends `message` to all clients - * - * @param message the message to send - */ + * + * @param message the message to send + */ private def writeToAll(message: String): Unit = this.clients.mapAndRemove(c => val output = c.socket.getOutputStream |