1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
package scalevalapokalypsi.UI
import scalevalapokalypsi.Client.{newClient, Client, GameEvent}
import scalevalapokalypsi.Server.Server
import scalevalapokalypsi.constants.*
import scalevalapokalypsi.utils.*
import java.lang.Thread.sleep
import scala.util.{Try,Success,Failure}
import scala.collection.immutable.LazyList
import java.lang.Thread
import scala.io.StdIn.readLine
@main def main(): Unit =
val option = getValidInput[Int](
"Miten tahdot pelata?\n" +
s"1) Liity viralliselle palvelimelle ($DEFAULT_SERVER)\n" +
"2) Käynnistä palvelin laitteellasi ja liity sille\n" +
"3) Liity mielivaltaiselle palvelimelle",
s => s.toIntOption match
case None =>
Left("Syötä kokonaisluku.")
case Some(i) =>
if i < 1 || i > 3 then
Left("Syötä kokonaisluku väliltä [1,3].")
else
Right(i)
)
val serverName =
if option == 3 then
readLine("Syötä palvelimen verkkotunnus.\n> ")
else if option == 2 then
"127.0.0.1"
else
DEFAULT_SERVER
val serverPort =
if option == 1 then
DEFAULT_PORT
else
getValidInput[Int](
s"Valitse portti palvelimelle. (Jätä tyhjäksi oletusta $DEFAULT_PORT varten)",
s =>
if s == "" then
Right(DEFAULT_PORT)
else
s.toIntOption match
case None =>
Left("Syötä kokonaisluku.")
case Some(i) =>
if i > 0 && i <= 65535 then
Right(i)
else
Left("Syötä portti lailliselta väliltä.")
)
val maxClients = if option == 2 then
getValidInput[Int](
"Kuinka monta pelaajaa pelissä saa olla samanaikaisesti?",
s => s.toIntOption match
case None =>
Left("Syötä kokonaisluku.")
case Some(i) =>
if i > 1000 then
println(
"Aika ison määrän valitsit, mutta olkoon menneeksi."
)
if i > 0 then
Right(i)
else
Left("Syötä positiivinen kokonaisluku.")
)
else
0
val timeLimit = if option == 2 then
getValidInput[Int](
s"Syötä vuorojen aikaraja yksiköttömänä sekunneissa odottelun vähentämiseksi. Syötä 0 aikarajan poistamiseksi. (Jätä tyhjäksi oletusta $DEFAULT_TURN_TIME_LIMIT varten)",
s => if s == "" then
Right(DEFAULT_TURN_TIME_LIMIT)
else
s.toIntOption
.toRight("Syötä kokonaisluku")
.filterOrElse(
_ >= 0,
"Syötä epänegatiivinen kokonaisluku."
)
)
else
0
if option == 2 then
Thread(() => new Server(serverPort, maxClients, timeLimit, true).startServer()).start()
println("Palvelin käynnistetty taustalla.")
val name = readLine("Valitse itsellesi pelin sisäinen alter ego.\n> ")
Try(newClient(name, serverName, serverPort))
.toOption
.flatten match
case Some(client) =>
startClient(client)
case None =>
println(
"Serverille liittyminen epäonnistui. Tarkista internet-yhteytesi. Jos yhteytesi on kunnossa ja liittyminen ei pian onnistu, ota yhteyttä Joel Kronqvistiin <joel.kronqvist@iki.fi> olettaen, ettei vuodesta 2024 ole kulunut kohtuuttomasti aikaa."
)
/** Client game loop. Handles output to and from the client in the eyes of the
* terminal.
*/
def startClient(client: Client): Unit =
var hasQuit = false
val stdinReader = StdinLineReader()
stdinReader.startReading()
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)
|