aboutsummaryrefslogtreecommitdiff
path: root/src/scalevalapokalypsi/Client/Client.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/scalevalapokalypsi/Client/Client.scala')
-rw-r--r--src/scalevalapokalypsi/Client/Client.scala87
1 files changed, 42 insertions, 45 deletions
diff --git a/src/scalevalapokalypsi/Client/Client.scala b/src/scalevalapokalypsi/Client/Client.scala
index aab6bc3..e94fdb0 100644
--- a/src/scalevalapokalypsi/Client/Client.scala
+++ b/src/scalevalapokalypsi/Client/Client.scala
@@ -1,12 +1,11 @@
package scalevalapokalypsi.Client
-import java.lang.Thread.sleep
-import java.net.Socket
+import java.net.{Socket,InetSocketAddress}
import scala.io.Source
import scala.sys.process.stdout
import scalevalapokalypsi.constants.*
import scalevalapokalypsi.utils.{stringToByteArray,getNCharsFromSocket}
-import scalevalapokalypsi.Client.{ReceivedLineParser,StdinLineReader,Turn}
+import scalevalapokalypsi.Client.{ReceivedLineParser,RoomState}
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.{Try, Success, Failure}
@@ -34,7 +33,8 @@ enum ServerLineState:
* @return the client created, if all was successful
*/
def newClient(name: String, ip: String, port: Int): Option[Client] =
- val socket = Socket(ip, port)
+ val socket = Socket()
+ socket.connect(new InetSocketAddress(ip, port), INITIAL_CONN_TIMEOUT)
val output = socket.getOutputStream
val input = socket.getInputStream
val initMsg = s"$GAME_VERSION\r\n$name\r\n"
@@ -61,7 +61,6 @@ class Client(socket: Socket):
private val buffer: Array[Byte] = Array.ofDim(MAX_MSG_SIZE)
private var bufferIndex = 0
private val serverLineParser = ReceivedLineParser()
- private val stdinReader = StdinLineReader()
private var serverLineState = ServerLineState.WaitingForTimeLimit
@@ -70,41 +69,49 @@ class Client(socket: Socket):
private var timeLimit: Long = 0
private var lastTurnStart: Long = 0
private var lastExecutedTurn: Long = 0
- private var isSinging: Boolean = false
+ private var lineToSing: Option[String] = None
private val bufferedActions: Buffer[String] = Buffer.empty
assert(
lastTurnStart <= lastExecutedTurn,
"don't initialize with unexecuted turn"
)
- private val turnInfo = Turn()
+ private val turnInfo = RoomState()
-
- /** Starts the client. This shouldn't terminate. */
- def startClient(): Unit =
-
- stdinReader.startReading()
-
- while true do
-
- sleep(POLL_INTERVAL)
+ /** Takes a client step and optionally returns an in-game event for UI
+ *
+ * @param clientInput one line of client input if any
+ * @return an event describing new changes in the game state
+ */
+ def clientStep(clientInput: Option[String]): GameEvent =
this.readAndParseDataFromServer()
- this.displayActions()
+ val actions = this.getNewActions()
- if
+ val roomState = if
this.lastExecutedTurn < this.lastTurnStart &&
- !this.isSinging
+ this.lineToSing.isEmpty
then
- print(this.giveTurn())
-
- // TODO: we probably want to quit at EOF
- stdinReader.newLine().foreach((s: String) =>
- this.isSinging = false
- output.write(stringToByteArray(s+"\r\n"))
+ this.giveTurn()
+ Some(this.turnInfo)
+ else
+ None
+
+ for line <- clientInput do
+ this.lineToSing = None
+ output.write(stringToByteArray(s"$line\r\n"))
+
+ val timeOfTurnEnd = this.lastTurnStart + this.timeLimit
+ val timeToTurnEnd = -currentTimeMillis()/1000 + timeOfTurnEnd
+ GameEvent(
+ actions,
+ roomState,
+ this.lineToSing,
+ this.canAct,
+ Some(timeToTurnEnd).filter(p => this.lastTurnStart != 0)
)
- end startClient
+ end clientStep
private def readAndParseDataFromServer(): Unit =
@@ -112,37 +119,27 @@ class Client(socket: Socket):
while availableBytes != 0 do
val bytesRead = input.read(buffer, 0, availableBytes)
if bytesRead != -1 then
- // TODO: unsafe conversion
parseDataFromServer(buffer.take(bytesRead))
availableBytes = input.available()
- private def giveTurn(): String =
+ private def giveTurn(): Unit =
this.canAct = true
this.lastExecutedTurn = currentTimeMillis / 1000
- s"\n\n${this.turnInfo}\n${this.actionGetterIndicator}"
private def bufferAction(action: String): Unit =
this.bufferedActions += action
- private def displayActions(): Unit =
+ private def getNewActions(): Option[Vector[String]] =
val somethingToShow = this.bufferedActions.nonEmpty
- if somethingToShow then
- if !this.isSinging then
- this.bufferedActions.foreach(println(_))
- this.bufferedActions.clear()
- if !this.isSinging && this.canAct && somethingToShow then
- print(this.actionGetterIndicator)
+ if somethingToShow && this.lineToSing.isEmpty then
+ val res = this.bufferedActions.toVector
+ this.bufferedActions.clear()
+ Some(res)
+ else
+ None
private def startSong(verse: String): Unit =
- this.isSinging = true
- print(s"\nLaula: “$verse”\n> ")
-
- // TODO: this is sometimes in front of actions, use an indicator to test if newline before actions?
- private def actionGetterIndicator =
- val timeOfTurnEnd = this.lastTurnStart + this.timeLimit
- val timeToTurnEnd = -currentTimeMillis()/1000 + timeOfTurnEnd
- s"[$timeToTurnEnd]> "
-
+ this.lineToSing = Some(verse)
private def parseDataFromServer(data: Array[Byte]): Unit =