package nl.kallestruik.darena.managers import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json import nl.kallestruik.darena.arenas.Arena import nl.kallestruik.darena.arenas.ArenaConfig import nl.kallestruik.darena.exceptions.ArenaCreationException import nl.kallestruik.darena.exceptions.ArenaEndAbortedException import nl.kallestruik.darena.exceptions.ArenaStartAbortedException import nl.kallestruik.darena.types.ArenaFeature import nl.kallestruik.darena.types.Reloadable import nl.kallestruik.darena.util.Logger import nl.kallestruik.dlib.config.ConfigHelper.toConfigSchema import org.bukkit.entity.Player import org.bukkit.plugin.java.JavaPlugin import java.io.File import java.nio.file.Files class ArenaManager( private val teamManager: TeamManager, private val pointsManager: PointsManager, private val configManager: ConfigManager, private val plugin: JavaPlugin, private val arenaFolder: File, schemaFile: File, ): Reloadable { lateinit var editManager: EditManager; private val arenas: MutableMap = mutableMapOf() var currentArena: Arena? = null override fun reload() { arenas.clear() loadArenas() } init { schemaFile.parentFile.mkdirs() schemaFile.writeText(Json.encodeToString(ArenaConfig.serializer().descriptor.toConfigSchema(listOf()))) } fun loadArenas() { Logger.trace(ArenaManager::class, "loadArenas()") arenaFolder.mkdirs() Files.walk(arenaFolder.toPath()).use { walk -> walk.forEach { path -> if (Files.isDirectory(path)) return@forEach if (path.toString().endsWith(".yml")) { Logger.info(ArenaManager::class, "Skipping legacy config at $path") return@forEach } Logger.info(ArenaManager::class, "Loading arena from: $path") val config = ArenaConfig.load(path.toFile()) arenas[config.name] = Arena( config, plugin, configManager, this, teamManager, pointsManager, ) } } } @Throws(ArenaStartAbortedException::class) fun start(arena: Arena, loadingTimeOverride: Int, spectatorTimeOverride: Int, beforeStartTimeOverride: Int) { Logger.trace(ArenaManager::class, "start(arena: ${arena.config.name}, loadingTimeOverride: $loadingTimeOverride, spectatorTimeOverride: $spectatorTimeOverride, beforeStartTimeOverride: $beforeStartTimeOverride)") if (currentArena != null) throw ArenaStartAbortedException("There is currently another arena in progress. Please end that one first.") if (editManager.isEditing()) throw ArenaStartAbortedException("There is currently an arena being edited. Please finish that first.") // Try to start the arena. If something goes wrong clean it up and throw the exception again so the user can be informed. arena.start(loadingTimeOverride, spectatorTimeOverride, beforeStartTimeOverride) currentArena = arena } @Throws(ArenaEndAbortedException::class) fun end() { Logger.trace(ArenaManager::class, "end()") if (currentArena == null) throw ArenaEndAbortedException("There is currently no arena in progress.") currentArena!!.end() currentArena = null } @Throws(ArenaCreationException::class) fun createArena(name: String) { if (arenas.contains(name)) throw ArenaCreationException("Arena with name $name already exists!") val config = ArenaConfig(name = name) config.file = File(arenaFolder, "$name.json") arenas[config.name] = Arena( config, plugin, configManager, this, teamManager, pointsManager, ) config.save(false) } fun saveConfig(arena: Arena) { arena.config.save(false) } fun getArena(name: String): Arena? { Logger.trace(ArenaManager::class, "getArena(name: $name)") return arenas[name] } fun getAllArenaNames(): Collection { Logger.trace(ArenaManager::class, "getAllArenaNames()") return arenas.keys } fun shouldProcessEvent(feature: ArenaFeature, player: Player?): Boolean { if (currentArena == null) return false if (!currentArena!!.session!!.isInProgress) return false if (feature != ArenaFeature.ALWAYS && !currentArena!!.hasFeature(feature)) return false if ((player != null && !currentArena!!.session!!.participants.contains(player))) return false return true } }