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
|
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.engine.*
|
||||||
import io.ktor.server.netty.*
|
import io.ktor.server.netty.*
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
embeddedServer(Netty, port = 8888, host = "0.0.0.0") {
|
embeddedServer(Netty, port = 8888, host = "0.0.0.0") {
|
||||||
configureSockets()
|
setupPlugins()
|
||||||
|
configureRoutes()
|
||||||
}.start(wait = true)
|
}.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