aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/Server/Server.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/scala/Server/Server.scala')
-rw-r--r--src/main/scala/Server/Server.scala90
1 files changed, 90 insertions, 0 deletions
diff --git a/src/main/scala/Server/Server.scala b/src/main/scala/Server/Server.scala
new file mode 100644
index 0000000..829010c
--- /dev/null
+++ b/src/main/scala/Server/Server.scala
@@ -0,0 +1,90 @@
+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 scala.concurrent.ExecutionContext.Implicits.global
+import scala.concurrent.Future
+import scala.util.{Failure, Success, Try}
+import o1game.constants.*
+
+/** `Server` exists to initialize a server for the game
+ * and run it with its method `startServer`.
+ */
+class Server(port: Int, maxClients: Int):
+ private val socket = ServerSocket(port)
+ private val clientGetter = ConnectionGetter(socket)
+ private val clients: Clients = Clients(maxClients)
+ private val buffer: Array[Byte] = Array.ofDim(1024)
+ private var bufferIndex = 0
+
+ /** Starts the server. Won't terminate under normal circumstances. */
+ def startServer(): Unit =
+ while true do
+ sleep(POLL_INTERVAL)
+ this.receiveNewClient()
+ this.writeToAll("Test message.")
+ this.readFromAll()
+ clients.foreach(_.executeActions())
+
+ /** Receives a new client and stores it in `clients`.
+ *
+ * @return describes if a client was added
+ */
+ private def receiveNewClient(): Boolean =
+ clientGetter.newClient() match
+ case Some(c) =>
+ clients.addClient(Client(c, None))
+ true
+ case None =>
+ false
+
+ /** Sends `message` to all clients
+ *
+ * @param message the message to send
+ */
+ private def writeToAll(message: String): Unit =
+ clients.removeNonSatisfying((c: Client) =>
+ try
+ val output = c.socket.getOutputStream
+ output.write(message.toVector.map(_.toByte).toArray)
+ output.flush()
+ true
+ catch
+ case e: IOException => false
+ )
+
+ /** Reads data sent by clients and stores it in the `Client`s of `clients` */
+ private def readFromAll(): Unit =
+ clients.removeNonSatisfying((c: Client) =>
+ try
+ val input = c.socket.getInputStream
+ while input.available() != 0 do
+ val bytesRead = input.read(buffer)
+ if bytesRead != -1 then
+ c.receiveData(buffer.take(bytesRead).toVector)
+ true
+ catch
+ case e: IOException => false
+ )
+
+end Server
+
+class ConnectionGetter(val socket: ServerSocket):
+
+ private var nextClient: Future[Socket] = Future.failed(IOException())
+
+ def newClient(): Option[Socket] =
+ this.nextClient.value match
+ case Some(Success(s)) =>
+ nextClient = Future(socket.accept())
+ Some(s)
+ case Some(Failure(e)) =>
+ nextClient = Future(socket.accept())
+ None
+ case None => None
+
+end ConnectionGetter