KStarbound/src/main/kotlin/ru/dbotthepony/kstarbound/server/StarboundServer.kt
2024-02-03 20:41:51 +07:00

78 lines
1.9 KiB
Kotlin

package ru.dbotthepony.kstarbound.server
import ru.dbotthepony.kommons.util.MailboxExecutorService
import ru.dbotthepony.kstarbound.client.network.packets.JoinWorldPacket
import ru.dbotthepony.kstarbound.server.network.ServerChannels
import ru.dbotthepony.kstarbound.server.network.ServerConnection
import ru.dbotthepony.kstarbound.server.world.ServerWorld
import java.io.Closeable
import java.io.File
import java.util.Collections
import java.util.concurrent.atomic.AtomicInteger
import java.util.concurrent.locks.LockSupport
import java.util.concurrent.locks.ReentrantLock
import kotlin.concurrent.withLock
abstract class StarboundServer(val root: File) : Closeable {
init {
if (!root.exists()) {
check(root.mkdirs()) { "Unable to create ${root.absolutePath}" }
} else if (!root.isDirectory) {
throw IllegalArgumentException("${root.absolutePath} is not a directory")
}
}
val worlds: MutableList<ServerWorld> = Collections.synchronizedList(ArrayList<ServerWorld>())
val serverID = threadCounter.getAndIncrement()
val thread = Thread(::runThread, "Starbound Server $serverID")
val mailbox = MailboxExecutorService(thread)
val settings = ServerSettings()
val channels = ServerChannels(this)
val lock = ReentrantLock()
@Volatile
var isClosed = false
private set
init {
thread.isDaemon = true
thread.start()
}
fun playerInGame(player: ServerConnection) {
val world = worlds.first()
world.mailbox.execute {
player.world = world
world.players.add(player)
player.send(JoinWorldPacket(world))
}
}
protected abstract fun close0()
private fun runThread() {
while (!isClosed) {
mailbox.executeQueuedTasks()
LockSupport.park()
}
}
final override fun close() {
lock.withLock {
if (isClosed) return
channels.close()
worlds.forEach { it.close() }
close0()
LockSupport.unpark(thread)
}
}
companion object {
private val threadCounter = AtomicInteger()
}
}