Start working on multi world support
This commit is contained in:
parent
d36250d6ea
commit
98ff252eba
9 changed files with 148 additions and 8 deletions
|
@ -21,6 +21,7 @@ repositories {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(kotlin("stdlib-jdk8"))
|
implementation(kotlin("stdlib-jdk8"))
|
||||||
implementation(kotlin("reflect"))
|
implementation(kotlin("reflect"))
|
||||||
|
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.7")
|
||||||
implementation("commons-codec:commons-codec:1.14")
|
implementation("commons-codec:commons-codec:1.14")
|
||||||
compileOnly("com.comphenix.protocol", "ProtocolLib", "4.5.0")
|
compileOnly("com.comphenix.protocol", "ProtocolLib", "4.5.0")
|
||||||
compileOnly("org.spigotmc", "spigot-api", "1.15.2-R0.1-SNAPSHOT")
|
compileOnly("org.spigotmc", "spigot-api", "1.15.2-R0.1-SNAPSHOT")
|
||||||
|
|
|
@ -5,6 +5,7 @@ import de.moritzruth.spigot_ttt.game.InfoCommand
|
||||||
import de.moritzruth.spigot_ttt.game.ReviveCommand
|
import de.moritzruth.spigot_ttt.game.ReviveCommand
|
||||||
import de.moritzruth.spigot_ttt.game.StartCommand
|
import de.moritzruth.spigot_ttt.game.StartCommand
|
||||||
import de.moritzruth.spigot_ttt.game.items.AddItemSpawnCommand
|
import de.moritzruth.spigot_ttt.game.items.AddItemSpawnCommand
|
||||||
|
import de.moritzruth.spigot_ttt.worlds.WorldCommand
|
||||||
|
|
||||||
object CommandManager {
|
object CommandManager {
|
||||||
fun initializeCommands() {
|
fun initializeCommands() {
|
||||||
|
@ -15,5 +16,6 @@ object CommandManager {
|
||||||
ResourcepackCommand()
|
ResourcepackCommand()
|
||||||
ReloadTTTConfigCommand()
|
ReloadTTTConfigCommand()
|
||||||
InfoCommand()
|
InfoCommand()
|
||||||
|
WorldCommand()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package de.moritzruth.spigot_ttt
|
package de.moritzruth.spigot_ttt
|
||||||
|
|
||||||
import de.moritzruth.spigot_ttt.game.GameManager
|
import de.moritzruth.spigot_ttt.game.GameManager
|
||||||
|
import de.moritzruth.spigot_ttt.worlds.WorldManager
|
||||||
import org.bukkit.ChatColor
|
import org.bukkit.ChatColor
|
||||||
import org.bukkit.plugin.java.JavaPlugin
|
import org.bukkit.plugin.java.JavaPlugin
|
||||||
|
|
||||||
|
@ -12,6 +13,8 @@ class TTTPlugin: JavaPlugin() {
|
||||||
override fun onEnable() {
|
override fun onEnable() {
|
||||||
saveDefaultConfig()
|
saveDefaultConfig()
|
||||||
|
|
||||||
|
WorldManager.removeNeglectedWorlds()
|
||||||
|
|
||||||
CommandManager.initializeCommands()
|
CommandManager.initializeCommands()
|
||||||
GameManager.initialize()
|
GameManager.initialize()
|
||||||
|
|
||||||
|
|
|
@ -2,18 +2,18 @@ package de.moritzruth.spigot_ttt.utils
|
||||||
|
|
||||||
import de.moritzruth.spigot_ttt.plugin
|
import de.moritzruth.spigot_ttt.plugin
|
||||||
import org.bukkit.configuration.file.YamlConfiguration
|
import org.bukkit.configuration.file.YamlConfiguration
|
||||||
import java.nio.file.Paths
|
import java.io.File
|
||||||
|
|
||||||
class ConfigurationFile(name: String): YamlConfiguration() {
|
class ConfigurationFile(private val file: File): YamlConfiguration() {
|
||||||
private val filePath = Paths.get(plugin.dataFolder.absolutePath, "$name.yml").toAbsolutePath().toString()
|
constructor(name: String) : this(plugin.dataFolder.resolve("$name.yml"))
|
||||||
|
|
||||||
init {
|
init {
|
||||||
try {
|
try {
|
||||||
load(filePath)
|
load(file)
|
||||||
} catch (e: Exception) {}
|
} catch (e: Exception) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun save() {
|
fun save() {
|
||||||
save(filePath)
|
save(file)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,12 +4,15 @@ import org.bukkit.command.CommandSender
|
||||||
import org.bukkit.command.TabCompleter
|
import org.bukkit.command.TabCompleter
|
||||||
|
|
||||||
fun createTabCompleter(fn: (sender: CommandSender, index: Int) -> List<String>?) =
|
fun createTabCompleter(fn: (sender: CommandSender, index: Int) -> List<String>?) =
|
||||||
|
createTabCompleter { sender, index, _ -> fn(sender, index) }
|
||||||
|
|
||||||
|
fun createTabCompleter(fn: (sender: CommandSender, index: Int, args: List<String>) -> List<String>?) =
|
||||||
TabCompleter { sender, _, _, args ->
|
TabCompleter { sender, _, _, args ->
|
||||||
val index = args.count()
|
val index = args.count()
|
||||||
|
|
||||||
val completions =
|
val completions =
|
||||||
if (index == 0) emptyList()
|
if (index == 0) emptyList()
|
||||||
else fn(sender, index) ?: emptyList()
|
else fn(sender, index, args.toList()) ?: emptyList()
|
||||||
|
|
||||||
completions.filter { it.startsWith(args.last(), true) }
|
completions.filter { it.startsWith(args.last(), true) }
|
||||||
}
|
}
|
||||||
|
|
73
src/main/kotlin/de/moritzruth/spigot_ttt/worlds/TTTWorld.kt
Normal file
73
src/main/kotlin/de/moritzruth/spigot_ttt/worlds/TTTWorld.kt
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
package de.moritzruth.spigot_ttt.worlds
|
||||||
|
|
||||||
|
import de.moritzruth.spigot_ttt.plugin
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.coroutineScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import org.bukkit.WorldCreator
|
||||||
|
|
||||||
|
class TTTWorld(val sourceWorld: WorldManager.SourceWorld) {
|
||||||
|
var state: State = State.NOT_COPIED; private set
|
||||||
|
enum class State {
|
||||||
|
NOT_COPIED,
|
||||||
|
COPYING,
|
||||||
|
COPIED,
|
||||||
|
LOADED,
|
||||||
|
UNLOADING
|
||||||
|
}
|
||||||
|
|
||||||
|
val id = WorldManager.tttWorlds.count()
|
||||||
|
val actualWorldName = "${WORLD_PREFIX}${id}"
|
||||||
|
private val worldDir = plugin.server.worldContainer.resolve("./$actualWorldName")
|
||||||
|
|
||||||
|
init {
|
||||||
|
WorldManager.tttWorlds.add(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun copy() {
|
||||||
|
if (state != State.NOT_COPIED) throw IllegalStateException("The world was already copied")
|
||||||
|
state = State.COPYING
|
||||||
|
|
||||||
|
coroutineScope {
|
||||||
|
launch(Dispatchers.IO) {
|
||||||
|
sourceWorld.dir.copyRecursively(worldDir)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun load() {
|
||||||
|
if (state != State.COPIED) throw IllegalStateException("The world was not copied yet or already loaded")
|
||||||
|
plugin.server.createWorld(WorldCreator.name(actualWorldName))
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun save() {
|
||||||
|
if (state != State.LOADED) throw IllegalStateException("The world must be loaded")
|
||||||
|
|
||||||
|
coroutineScope {
|
||||||
|
launch(Dispatchers.IO) {
|
||||||
|
val tempWorldDir = WorldManager.worldsDir.resolve("./${sourceWorld.name}_$id")
|
||||||
|
worldDir.copyRecursively(tempWorldDir)
|
||||||
|
sourceWorld.dir.deleteRecursively()
|
||||||
|
tempWorldDir.renameTo(sourceWorld.dir)
|
||||||
|
state = State.NOT_COPIED
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun unloadAndRemove() {
|
||||||
|
if (state != State.LOADED) throw IllegalStateException("The world must be loaded")
|
||||||
|
state = State.UNLOADING
|
||||||
|
plugin.server.unloadWorld(actualWorldName, false)
|
||||||
|
|
||||||
|
coroutineScope {
|
||||||
|
launch(Dispatchers.IO) {
|
||||||
|
worldDir.deleteRecursively()
|
||||||
|
state = State.NOT_COPIED
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val WORLD_PREFIX = "tempworld_"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package de.moritzruth.spigot_ttt.worlds
|
||||||
|
|
||||||
|
import de.moritzruth.spigot_ttt.plugin
|
||||||
|
import de.moritzruth.spigot_ttt.utils.createTabCompleter
|
||||||
|
import org.bukkit.command.Command
|
||||||
|
import org.bukkit.command.CommandExecutor
|
||||||
|
import org.bukkit.command.CommandSender
|
||||||
|
|
||||||
|
class WorldCommand: CommandExecutor {
|
||||||
|
init {
|
||||||
|
val command = plugin.getCommand("world")!!
|
||||||
|
command.setExecutor(this)
|
||||||
|
command.tabCompleter = createTabCompleter { _, index, args ->
|
||||||
|
return@createTabCompleter when(index) {
|
||||||
|
0 -> listOf("load", "save", "join", "list")
|
||||||
|
1 -> when(args[0].toLowerCase()) {
|
||||||
|
"load" -> WorldManager.sourceWorlds.map { it.name }
|
||||||
|
"save", "join" -> WorldManager.tttWorlds.map { it.id.toString() }
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array<out String>): Boolean {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package de.moritzruth.spigot_ttt.worlds
|
||||||
|
|
||||||
|
import de.moritzruth.spigot_ttt.plugin
|
||||||
|
import de.moritzruth.spigot_ttt.utils.ConfigurationFile
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
object WorldManager {
|
||||||
|
data class SourceWorld(val dir: File) {
|
||||||
|
val name: String = dir.name
|
||||||
|
val config = ConfigurationFile(dir.resolve("config.yml"))
|
||||||
|
}
|
||||||
|
|
||||||
|
val worldsDir = plugin.dataFolder.resolve("./worlds").also { it.mkdirs() }
|
||||||
|
val sourceWorlds = worldsDir.listFiles(File::isDirectory)!!.map { SourceWorld(it) }
|
||||||
|
|
||||||
|
val tttWorlds = mutableSetOf<TTTWorld>()
|
||||||
|
|
||||||
|
fun removeNeglectedWorlds() {
|
||||||
|
plugin.server.worldContainer.listFiles { file ->
|
||||||
|
file.isDirectory && file.name.startsWith(TTTWorld.WORLD_PREFIX) &&
|
||||||
|
tttWorlds.find { it.actualWorldName == file.name } != null
|
||||||
|
}!!.forEach { it.deleteRecursively() }
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,12 +23,12 @@ commands:
|
||||||
description: Add an item spawn
|
description: Add an item spawn
|
||||||
|
|
||||||
revive:
|
revive:
|
||||||
usage: /revive [player] ['here']
|
usage: /revive [Player] ['here']
|
||||||
permission: ttt.revive
|
permission: ttt.revive
|
||||||
description: Revive yourself or another player at the world spawn or at your location
|
description: Revive yourself or another player at the world spawn or at your location
|
||||||
|
|
||||||
info:
|
info:
|
||||||
usage: /info [player]
|
usage: /info [Player]
|
||||||
permission: ttt.info
|
permission: ttt.info
|
||||||
description: Show information about all players or a specific player
|
description: Show information about all players or a specific player
|
||||||
|
|
||||||
|
@ -45,3 +45,8 @@ commands:
|
||||||
permission: ttt.reload
|
permission: ttt.reload
|
||||||
aliases:
|
aliases:
|
||||||
- rt
|
- rt
|
||||||
|
|
||||||
|
world:
|
||||||
|
usage: /world load <Name> OR /world <'join'|'save'> <World ID> OR /world list
|
||||||
|
description: Perform world operations
|
||||||
|
permission: ttt.world
|
||||||
|
|
Reference in a new issue