Few cleanups
This commit is contained in:
parent
1d35ea2b49
commit
5b13eb5ece
10 changed files with 189 additions and 130 deletions
|
@ -1,11 +1,13 @@
|
|||
package de.pheerai.buzzer
|
||||
|
||||
import de.pheerai.buzzer.plugins.*
|
||||
import de.pheerai.buzzer.routing.configureRoutes
|
||||
import de.pheerai.buzzer.setup.setupPlugins
|
||||
import io.ktor.server.engine.*
|
||||
import io.ktor.server.netty.*
|
||||
|
||||
fun main() {
|
||||
embeddedServer(Netty, port = 8888, host = "0.0.0.0") {
|
||||
configureSockets()
|
||||
setupPlugins()
|
||||
configureRoutes()
|
||||
}.start(wait = true)
|
||||
}
|
||||
|
|
21
src/main/kotlin/de/pheerai/buzzer/clients/adminClient.kt
Normal file
21
src/main/kotlin/de/pheerai/buzzer/clients/adminClient.kt
Normal file
|
@ -0,0 +1,21 @@
|
|||
package de.pheerai.buzzer.clients
|
||||
|
||||
import kotlinx.html.*
|
||||
|
||||
fun HTML.createAdminDocument() {
|
||||
head {
|
||||
meta { charset = "UTF-8" }
|
||||
title { +"JS Client" }
|
||||
script { src = "https://code.jquery.com/jquery-3.6.0.min.js" }
|
||||
script { src = "/assets/adminClient.js" }
|
||||
}
|
||||
body {
|
||||
ol {
|
||||
id = "usernames"
|
||||
}
|
||||
button {
|
||||
onClick = "resetReceived()"
|
||||
+"Reset"
|
||||
}
|
||||
}
|
||||
}
|
34
src/main/kotlin/de/pheerai/buzzer/clients/playerClient.kt
Normal file
34
src/main/kotlin/de/pheerai/buzzer/clients/playerClient.kt
Normal file
|
@ -0,0 +1,34 @@
|
|||
package de.pheerai.buzzer.clients
|
||||
|
||||
import kotlinx.html.*
|
||||
|
||||
fun HTML.createPlayerDocument() {
|
||||
head {
|
||||
meta { charset = "UTF-8" }
|
||||
title { +"JS Client" }
|
||||
link(
|
||||
href = "/assets/player.css",
|
||||
rel = "stylesheet",
|
||||
type = "text/css"
|
||||
)
|
||||
script { src = "https://code.jquery.com/jquery-3.6.0.min.js" }
|
||||
script { src = "/assets/playerClient.js" }
|
||||
}
|
||||
body {
|
||||
div(classes = "parent") {
|
||||
attributes["foo"] = "bar"
|
||||
div(classes = "input") {
|
||||
label { +"Player" }
|
||||
div(classes = "bumper") {}
|
||||
input {
|
||||
id = "username"
|
||||
placeholder = "<name>"
|
||||
}
|
||||
}
|
||||
button(classes = "submit") {
|
||||
onClick = "sendUsername()"
|
||||
+"I know that!"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
14
src/main/kotlin/de/pheerai/buzzer/data/SessionStorage.kt
Normal file
14
src/main/kotlin/de/pheerai/buzzer/data/SessionStorage.kt
Normal file
|
@ -0,0 +1,14 @@
|
|||
package de.pheerai.buzzer.data
|
||||
|
||||
import java.util.*
|
||||
|
||||
object SessionStorage {
|
||||
val playerSessions = synchronisedCollectionOf<PlayerSocket>()
|
||||
val gameMasterSessions = synchronisedCollectionOf<GameMasterSocket>()
|
||||
}
|
||||
|
||||
fun <T : Any> synchronisedCollectionOf(vararg data: T): MutableCollection<T> {
|
||||
val list = LinkedList<T>()
|
||||
list.addAll(data)
|
||||
return Collections.synchronizedCollection(list)
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package de.pheerai.buzzer.handlers
|
||||
|
||||
import de.pheerai.buzzer.data.GameMasterSocket
|
||||
import de.pheerai.buzzer.data.SessionStorage
|
||||
import io.ktor.http.cio.websocket.*
|
||||
import kotlinx.coroutines.isActive
|
||||
|
||||
suspend fun WebSocketSession.handleGameMasterSocket() {
|
||||
SessionStorage.gameMasterSessions.add(GameMasterSocket(this))
|
||||
for (frame in incoming) {
|
||||
when (frame) {
|
||||
is Frame.Text -> {
|
||||
val text = frame.readText()
|
||||
SessionStorage.playerSessions.filter { it.session.isActive }
|
||||
.forEach { it.session.send(text) }
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package de.pheerai.buzzer.handlers
|
||||
|
||||
import de.pheerai.buzzer.data.PlayerSocket
|
||||
import de.pheerai.buzzer.data.SessionStorage
|
||||
import io.ktor.http.cio.websocket.*
|
||||
import kotlinx.coroutines.isActive
|
||||
import org.slf4j.Logger
|
||||
|
||||
suspend fun WebSocketSession.handlePlayerSocket(log: Logger) {
|
||||
SessionStorage.playerSessions.add(PlayerSocket(this))
|
||||
for (frame in incoming) {
|
||||
when (frame) {
|
||||
is Frame.Text -> {
|
||||
val text = frame.readText()
|
||||
log.info("Username: $text")
|
||||
SessionStorage.gameMasterSessions.filter { it.session.isActive }
|
||||
.forEach { it.session.send(text) }
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,128 +0,0 @@
|
|||
package de.pheerai.buzzer.plugins
|
||||
|
||||
import de.pheerai.buzzer.data.GameMasterSocket
|
||||
import de.pheerai.buzzer.data.PlayerSocket
|
||||
import io.ktor.application.*
|
||||
import io.ktor.html.*
|
||||
import io.ktor.http.cio.websocket.*
|
||||
import io.ktor.http.content.*
|
||||
import io.ktor.routing.*
|
||||
import io.ktor.websocket.*
|
||||
import kotlinx.coroutines.isActive
|
||||
import kotlinx.html.*
|
||||
import java.time.Duration
|
||||
import java.util.*
|
||||
|
||||
fun Application.configureSockets() {
|
||||
install(WebSockets) {
|
||||
pingPeriod = Duration.ofSeconds(15)
|
||||
timeout = Duration.ofSeconds(15)
|
||||
maxFrameSize = Long.MAX_VALUE
|
||||
masking = false
|
||||
}
|
||||
|
||||
routing {
|
||||
val playerSessions = Collections.synchronizedCollection(LinkedList<PlayerSocket>())
|
||||
val gameMasterSessions = Collections.synchronizedCollection(LinkedList<GameMasterSocket>())
|
||||
|
||||
static("/assets") {
|
||||
resources("css")
|
||||
resources("js")
|
||||
}
|
||||
|
||||
get("/") {
|
||||
call.respondHtml {
|
||||
createPlayerDocument()
|
||||
}
|
||||
}
|
||||
|
||||
get("/client/player") {
|
||||
call.respondHtml {
|
||||
createPlayerDocument()
|
||||
}
|
||||
}
|
||||
|
||||
get("/client/master") {
|
||||
call.respondHtml {
|
||||
createAdminDocument()
|
||||
}
|
||||
}
|
||||
|
||||
webSocket("/socket/player") {
|
||||
playerSessions.add(PlayerSocket(this))
|
||||
for (frame in incoming) {
|
||||
when (frame) {
|
||||
is Frame.Text -> {
|
||||
val text = frame.readText()
|
||||
log.info("Username: $text")
|
||||
gameMasterSessions.filter { it.session.isActive }
|
||||
.forEach { it.session.send(text) }
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
webSocket("/socket/master") {
|
||||
gameMasterSessions.add(GameMasterSocket(this))
|
||||
for (frame in incoming) {
|
||||
when (frame) {
|
||||
is Frame.Text -> {
|
||||
val text = frame.readText()
|
||||
playerSessions.filter { it.session.isActive }
|
||||
.forEach { it.session.send(text) }
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun HTML.createPlayerDocument() {
|
||||
head {
|
||||
meta { charset = "UTF-8" }
|
||||
title { +"JS Client" }
|
||||
link(
|
||||
href = "/assets/player.css",
|
||||
rel = "stylesheet",
|
||||
type = "text/css"
|
||||
)
|
||||
script { src = "https://code.jquery.com/jquery-3.6.0.min.js" }
|
||||
script { src = "/assets/playerClient.js" }
|
||||
}
|
||||
body {
|
||||
div(classes = "parent") {
|
||||
div(classes = "input") {
|
||||
label { +"Player" }
|
||||
div(classes = "bumper") {}
|
||||
input {
|
||||
id = "username"
|
||||
placeholder = "<name>"
|
||||
}
|
||||
}
|
||||
button(classes = "submit") {
|
||||
onClick = "sendUsername()"
|
||||
+"I know that!"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun HTML.createAdminDocument() {
|
||||
head {
|
||||
meta { charset = "UTF-8" }
|
||||
title { +"JS Client" }
|
||||
script { src = "https://code.jquery.com/jquery-3.6.0.min.js" }
|
||||
script { src = "/assets/adminClient.js" }
|
||||
}
|
||||
body {
|
||||
ol {
|
||||
id = "usernames"
|
||||
}
|
||||
button {
|
||||
onClick = "resetReceived()"
|
||||
+"Reset"
|
||||
}
|
||||
}
|
||||
}
|
52
src/main/kotlin/de/pheerai/buzzer/routing/setupRoutes.kt
Normal file
52
src/main/kotlin/de/pheerai/buzzer/routing/setupRoutes.kt
Normal file
|
@ -0,0 +1,52 @@
|
|||
package de.pheerai.buzzer.routing
|
||||
|
||||
import de.pheerai.buzzer.clients.createAdminDocument
|
||||
import de.pheerai.buzzer.clients.createPlayerDocument
|
||||
import de.pheerai.buzzer.handlers.handleGameMasterSocket
|
||||
import de.pheerai.buzzer.handlers.handlePlayerSocket
|
||||
import io.ktor.application.*
|
||||
import io.ktor.html.*
|
||||
import io.ktor.http.content.*
|
||||
import io.ktor.routing.*
|
||||
import io.ktor.websocket.*
|
||||
import org.slf4j.Logger
|
||||
|
||||
fun Application.configureRoutes() {
|
||||
routing {
|
||||
assetRoutes()
|
||||
clientRoutes()
|
||||
websocketRoutes(log)
|
||||
}
|
||||
}
|
||||
|
||||
private fun Routing.websocketRoutes(log: Logger) {
|
||||
webSocket("/socket/player") { handlePlayerSocket(log) }
|
||||
webSocket("/socket/master") { handleGameMasterSocket() }
|
||||
}
|
||||
|
||||
private fun Routing.clientRoutes() {
|
||||
get("/") {
|
||||
call.respondHtml {
|
||||
createPlayerDocument()
|
||||
}
|
||||
}
|
||||
|
||||
get("/client/player") {
|
||||
call.respondHtml {
|
||||
createPlayerDocument()
|
||||
}
|
||||
}
|
||||
|
||||
get("/client/master") {
|
||||
call.respondHtml {
|
||||
createAdminDocument()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun Routing.assetRoutes() {
|
||||
static("/assets") {
|
||||
resources("css")
|
||||
resources("js")
|
||||
}
|
||||
}
|
7
src/main/kotlin/de/pheerai/buzzer/setup/setupPlugins.kt
Normal file
7
src/main/kotlin/de/pheerai/buzzer/setup/setupPlugins.kt
Normal file
|
@ -0,0 +1,7 @@
|
|||
package de.pheerai.buzzer.setup
|
||||
|
||||
import io.ktor.application.*
|
||||
|
||||
fun Application.setupPlugins() {
|
||||
installWebSockets()
|
||||
}
|
15
src/main/kotlin/de/pheerai/buzzer/setup/webSockets.kt
Normal file
15
src/main/kotlin/de/pheerai/buzzer/setup/webSockets.kt
Normal file
|
@ -0,0 +1,15 @@
|
|||
package de.pheerai.buzzer.setup
|
||||
|
||||
import io.ktor.application.*
|
||||
import io.ktor.http.cio.websocket.*
|
||||
import io.ktor.websocket.*
|
||||
import java.time.Duration
|
||||
|
||||
fun Application.installWebSockets() {
|
||||
install(WebSockets) {
|
||||
pingPeriod = Duration.ofSeconds(15)
|
||||
timeout = Duration.ofSeconds(15)
|
||||
maxFrameSize = Long.MAX_VALUE
|
||||
masking = false
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue