Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
Bruce0203 committed Aug 2, 2023
1 parent accdfe8 commit bbe4c43
Show file tree
Hide file tree
Showing 15 changed files with 276 additions and 127 deletions.
50 changes: 0 additions & 50 deletions client/src/commonMain/kotlin/scene/GameScene.kt

This file was deleted.

53 changes: 40 additions & 13 deletions client/src/commonMain/kotlin/ui/MainMenu.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package ui

import io.ktor.http.*
import korlibs.datastructure.get
import korlibs.datastructure.getExtra
import korlibs.datastructure.set
Expand All @@ -24,6 +25,7 @@ import korlibs.time.milliseconds
import network.ViewedRoom
import network.createRoom
import network.getViewedRooms
import network.joinRoom
import org.koin.core.qualifier.named
import org.koin.mp.KoinPlatform.getKoin
import scene.styler
Expand All @@ -41,6 +43,7 @@ class MainMenuState {
lateinit var buttonCursor: View
val buttonSize = Size(sceneContainer.width * 0.7, sceneContainer.height * 0.165)
var clickElapsed = DateTime.now()
lateinit var loading: View
}

suspend fun MainMenuState.mainMenu() {
Expand Down Expand Up @@ -79,7 +82,9 @@ suspend fun MainMenuState.mainMenu() {
uiHorizontalStack(height = top.height*0.75f, padding = padding*2) {
val bottomButtonSize = Size(top.heightD * PI, .0)
customUiButton(size = bottomButtonSize).bottomButton("방 생성").onClick {
room(createRoom())
val room = createRoom()
serverList.removeFromParent()
waitingRoom(room.uuid)
}
customUiButton(size = bottomButtonSize).bottomButton("새로고침").onClick {
rooms.removeChildrenIf { index, child -> child.isRoom }
Expand Down Expand Up @@ -135,22 +140,44 @@ fun MainMenuState.room(room: ViewedRoom) {
val now = DateTime.now()
if (buttonCursor.visible && now - clickElapsed < 250.milliseconds) {
serverList.visible = false
lateinit var loading: View
loading = sceneContainer.uiContainer {
uiText("서버에 연결 중...") { styles(styler) }
.centerOnStage()
.alignY(containerRoot, 0.4, true)

customUiButton(size = Size(sceneContainer.width*0.471f, sceneContainer.width/25)) {
sceneContainer.uiContainer {
loading = this
val text = uiText("서버에 연결 중...") {
styles(styler)
bottomButton("취소")
centerOnStage()
alignY(containerRoot, 0.4, true)
}
.centerXOnStage()
.alignY(containerRoot, 0.6, true)
.onClick {
serverList.visible = true
lateinit var cancelText: View
val button =
customUiButton(size = Size(sceneContainer.width * 0.471f, sceneContainer.width / 25)) {
styles(styler)
cancelText = bottomButton("취소").centerOn(this)
centerXOnStage()
alignY(containerRoot, 0.6, true)
onClick {
loading.removeFromParent()
serverList.visible = true
}
}
when (joinRoom(room.uuid)) {
HttpStatusCode.OK -> {
loading.removeFromParent()
serverList.removeFromParent()
waitingRoom(room.uuid)
}

HttpStatusCode.NotFound -> {
text.text = "서버에 연결할 수 없습니다"
cancelText.removeFromParent()
button.uiText("서버 목록으로 돌아가기").centerOn(this)
}

else -> {
text.text = "서버에 인원이 꽉 찼습니다!"
cancelText.removeFromParent()
button.uiText("서버 목록으로 돌아가기").centerOn(this)
}
}
}
return@onDown
} else clickElapsed = now
Expand Down
23 changes: 23 additions & 0 deletions client/src/commonMain/kotlin/ui/waitingRoom.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package ui

import korlibs.korge.style.styles
import korlibs.korge.ui.uiContainer
import korlibs.korge.ui.uiText
import korlibs.korge.view.align.alignX
import korlibs.korge.view.align.alignY
import kotlinx.uuid.UUID
import network.ViewedRoom
import network.getRoomName
import scene.styler
import sceneContainer

suspend fun waitingRoom(room: UUID) {
sceneContainer.uiContainer {
styles(styler)
uiText(getRoomName(room)) {

}
.alignY(root, 0.5, true)
.alignX(root, 0.5, true)
}
}
3 changes: 1 addition & 2 deletions client/src/jsMain/kotlin/main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ import org.koin.dsl.module
import org.koin.mp.KoinPlatform

suspend fun main() {
val url = resourcesVfs["client.properties"].readProperties()
.get("server")?: "http://localhost:8080"
val url = resourcesVfs["client.properties"].readProperties()["server"]!!
startKoin {}
KoinPlatform.getKoin().loadModules(listOf(module {
factory {
Expand Down
5 changes: 1 addition & 4 deletions server/src/main/kotlin/application/main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,10 @@ import io.ktor.server.routing.*

val server = embeddedServer(Netty, environment)

fun main() {
server.start(wait = true)
}
fun main() { server.start(wait = true) }

fun startTestServer() = server.start()


fun Application.module() {
install(CORS) {
anyHost()
Expand Down
14 changes: 11 additions & 3 deletions server/src/main/kotlin/application/rooms.kt
Original file line number Diff line number Diff line change
@@ -1,23 +1,31 @@
package application

import application.configuration.getPlayer
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.auth.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import kotlinx.uuid.UUID
import model.createRoom
import model.listRoom
import model.nameRoom

fun Application.configureRooms() {
routing {
authenticate {
route("rooms") {
post { call.respond(listRoom()) }
post("create") {
call.respond(createRoom(call.getPlayer()))
post("create") { call.respond(createRoom(call.getPlayer())) }
post("join/{uuid}") {
call.parameters["uuid"]
//todo
call.respond(HttpStatusCode.OK)
}
post("{uuid}/name") {
call.respond(nameRoom(UUID(call.parameters["uuid"]!!)))
}
}
}
}

}
60 changes: 60 additions & 0 deletions server/src/main/kotlin/application/websocket.kt
Original file line number Diff line number Diff line change
@@ -1,13 +1,73 @@
package application

import io.ktor.serialization.kotlinx.*
import io.ktor.server.application.*
import io.ktor.server.routing.*
import io.ktor.server.websocket.*
import io.ktor.util.reflect.*
import io.ktor.websocket.*
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.InternalSerializationApi
import kotlinx.serialization.KSerializer
import kotlinx.serialization.json.Json
import kotlinx.uuid.UUID
import model.Room
import model.Rooms
import network.PacketController
import network.PacketFrame
import network.ServerPacket
import network.ServerPacket.GET_ROOM_NUMBER
import network.packet
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.jetbrains.exposed.sql.transactions.transaction
import java.time.Duration
import kotlin.reflect.KClass
import kotlin.reflect.KTypeProjection
import kotlin.reflect.full.allSupertypes
import kotlin.reflect.full.createType
import kotlin.reflect.javaType

val serialFormat = Json

fun Application.configureWebsocket() {
install(WebSockets) {
val _15sec = Duration.ofSeconds(15)
pingPeriod = _15sec
timeout = _15sec
contentConverter = KotlinxWebsocketSerializationConverter(serialFormat)
}
routing {
webSocket {
for (frame in incoming) {
frame.readBytes()
val packet = receiveDeserialized<PacketFrame>()
val serverPacketCT = serverPacket(ServerPacket.values()[packet.type])
serverPacketCT.invoke(serverPacketCT.decode(packet.data)!!)
}
}
}
}

@OptIn(InternalSerializationApi::class, ExperimentalStdlibApi::class, ExperimentalSerializationApi::class)
private fun PacketController<*>.decode(data: String): Any? {
val type = clazz.createType(clazz.allSupertypes.map { KTypeProjection(null, it) })
val typeInfo = typeInfoImpl(type.javaType, clazz, type)
val serializer = serialFormat.serializersModule.serializerForTypeInfo(typeInfo)
@Suppress("UNCHECKED_CAST")
return serialFormat.decodeFromString(serializer as KSerializer<Any?>, data)
}

@Suppress("UNCHECKED_CAST")
fun serverPacket(serverPacket: ServerPacket): PacketController<Any> = when(serverPacket) {
GET_ROOM_NUMBER -> packet<UUID> {
transaction { Room.find(Rooms.id eq it).first().name }
}
ServerPacket.LEAVE_ROOM -> packet {

}
} as PacketController<Any>

inline fun <reified T : Any> transactionPacket(crossinline code: (T) -> Any) = object : PacketController<T> {
override fun invoke(t: T) = transaction { code(t) }
override val clazz: KClass<T> = T::class
}
23 changes: 23 additions & 0 deletions server/src/main/kotlin/model/JoinSession.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package model

import kotlinx.uuid.UUID
import kotlinx.uuid.exposed.KotlinxUUIDEntity
import kotlinx.uuid.exposed.KotlinxUUIDEntityClass
import kotlinx.uuid.exposed.KotlinxUUIDTable
import org.jetbrains.exposed.dao.id.EntityID
import org.jetbrains.exposed.sql.SchemaUtils
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.jetbrains.exposed.sql.transactions.transaction

object JoinSessions : KotlinxUUIDTable() {
val room = reference("room", Rooms)
val player = reference("player", Players)
init { let { transaction { SchemaUtils.create(it) } } }
}

class JoinSession(id: EntityID<UUID>) : KotlinxUUIDEntity(id) {
companion object : KotlinxUUIDEntityClass<JoinSession>(JoinSessions)
var room by JoinSessions.room
var player by JoinSessions.player
}

7 changes: 6 additions & 1 deletion server/src/main/kotlin/model/Rooms.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class Room(id: EntityID<UUID>) : KotlinxUUIDEntity(id) {
fun listRoom() = transaction {
Room.all().map {
ViewedRoom(
it.id.value,
it.name,
it.maxPlayers,
Player.count(Players.room eq it.id).toInt()
Expand All @@ -40,5 +41,9 @@ fun createRoom(creator: UUID) = transaction {
val player = Player.find(Players.id eq creator).first()
name = "${player.name}의 방"
maxPlayers = 6
}.run { ViewedRoom(name, maxPlayers, 0) }
}.run { ViewedRoom(id.value, name, maxPlayers, 0) }
}

fun nameRoom(room: UUID) = transaction {
Room.find(Rooms.id eq room).first().name
}
Loading

0 comments on commit bbe4c43

Please sign in to comment.