package scalevalapokalypsi import scalevalapokalypsi.Client.{newClient, Client, StdinLineReader, GameEvent} import scalevalapokalypsi.Server.Server import scalevalapokalypsi.constants.* import java.lang.Thread.sleep import java.lang.System.currentTimeMillis import scala.util.Try import java.lang.Thread import scala.io.StdIn.readLine // TODO: add proper logic for starting the game @main def main(): Unit = print("How do you want to play?\n1) Host and join local game\n2) Join local game\n> ") readLine().toIntOption match case Some(1) => Thread(() => new Server(2267, 5, 30, true).startServer()).start() println("Server started in background.") print("Choose a name:\n> ") val name = readLine() Try(newClient(name, "127.0.0.1", 2267)) .toOption .flatten match case Some(client) => startClient(client) case None => println("Starting the client failed.") case Some(2) => print("Choose a name:\n> ") val name = readLine() Try(newClient(name, "127.0.0.1", 2267)) .toOption .flatten match case Some(client) => startClient(client) case None => println("Starting the client failed.") case _ => println("Invalid input") def startClient(client: Client): Unit = var hasQuit = false val stdinReader = StdinLineReader() stdinReader.startReading() val printer = Printer() while !hasQuit do sleep(POLL_INTERVAL) val line = stdinReader.newLine() if line.map(_.length).getOrElse(0) > 1024 then printer.printLn("Virhe: Syötteesi oli liian pitkä.") else if line == Some("quit") then hasQuit = true else val gameEvent = client.clientStep(line) printer.printGameEvent(gameEvent) class Printer: var inputIndicatorAtStartOfLine = false var queriedLineToSing = false var singStartTime: Option[Long] = None def printGameEvent(gameEvent: GameEvent): Unit = val actions = gameEvent.actions.map(_.mkString("\n")) val roomState = gameEvent.roomState.map(_.toString) val lineToSing = gameEvent.lineToSing if inputIndicatorAtStartOfLine && (actions.isDefined || roomState.isDefined || lineToSing.isDefined) then this.printLn("") actions.foreach(this.printLn(_)) roomState.foreach(this.printLn(_)) lineToSing match case Some(l) => if this.singStartTime.isEmpty then this.singStartTime = Some(currentTimeMillis() / 1000) print(s"Laula: “$l”\n ") val timeSpent = this.singStartTime.map((t: Long) => (currentTimeMillis / 1000 - t).toString ).getOrElse("?") print(this.timeIndicatorUpdater(timeSpent)) case None => this.singStartTime = None val timeLeft = s"${gameEvent.timeToNextTurn.getOrElse("∞")}" if gameEvent.playerCanAct && lineToSing.isEmpty && !inputIndicatorAtStartOfLine then this.inputIndicatorAtStartOfLine = true print(s"[$timeLeft s]> ") if gameEvent.playerCanAct && lineToSing.isEmpty then print(this.timeIndicatorUpdater(timeLeft)) end printGameEvent def printLn(s: String): Unit = println(s) this.inputIndicatorAtStartOfLine = false private def timeIndicatorUpdater(t: String): String = s"\u001b[s\u001b[0E[$t s]> \u001b[u"