From 13479b1ae31505db3d04418bb57a8ef57acbe193 Mon Sep 17 00:00:00 2001 From: Logan Gorence Date: Thu, 23 Dec 2021 22:44:02 +0000 Subject: [PATCH] Major refactoring to use Koin. --- build.gradle.kts | 3 + foundation-core/build.gradle.kts | 2 + .../foundation/core/FoundationCorePlugin.kt | 137 +++--------------- .../cloud/kubelet/foundation/core/Util.kt | 4 - .../foundation/core/abstraction/Feature.kt | 31 ++++ .../core/abstraction/FoundationPlugin.kt | 54 +++++++ .../backup}/BackupCommand.kt | 11 +- .../core/features/backup/BackupFeature.kt | 21 +++ .../core/features/dev/DevFeature.kt | 20 +++ .../core/features/player/PlayerFeature.kt | 14 ++ .../stats}/LeaderboardCommand.kt | 2 +- .../stats}/PersistentStoreCommand.kt | 20 ++- .../core/features/stats/StatsFeature.kt | 56 +++++++ .../{ => features}/update/ModuleManifest.kt | 2 +- .../update}/UpdateCommand.kt | 5 +- .../core/features/update/UpdateFeature.kt | 9 ++ .../update}/UpdateService.kt | 5 +- .../core/{ => features}/update/UpdateUtil.kt | 2 +- .../core/features/world/WorldFeature.kt | 14 ++ 19 files changed, 269 insertions(+), 143 deletions(-) create mode 100644 foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/abstraction/Feature.kt create mode 100644 foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/abstraction/FoundationPlugin.kt rename foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/{command => features/backup}/BackupCommand.kt (93%) create mode 100644 foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/features/backup/BackupFeature.kt create mode 100644 foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/features/dev/DevFeature.kt create mode 100644 foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/features/player/PlayerFeature.kt rename foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/{command => features/stats}/LeaderboardCommand.kt (97%) rename foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/{command => features/stats}/PersistentStoreCommand.kt (80%) create mode 100644 foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/features/stats/StatsFeature.kt rename foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/{ => features}/update/ModuleManifest.kt (72%) rename foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/{command => features/update}/UpdateCommand.kt (77%) create mode 100644 foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/features/update/UpdateFeature.kt rename foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/{service => features/update}/UpdateService.kt (90%) rename foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/{ => features}/update/UpdateUtil.kt (96%) create mode 100644 foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/features/world/WorldFeature.kt diff --git a/build.gradle.kts b/build.gradle.kts index ef7a872..f452d1e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -82,6 +82,9 @@ subprojects { implementation(platform("org.jetbrains.kotlin:kotlin-bom")) implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") + implementation("io.insert-koin:koin-core:3.1.4") + testImplementation("io.insert-koin:koin-test:3.1.4") + // Serialization implementation("com.charleskorn.kaml:kaml:0.38.0") implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.1") diff --git a/foundation-core/build.gradle.kts b/foundation-core/build.gradle.kts index 2ae636d..b1b3fb9 100644 --- a/foundation-core/build.gradle.kts +++ b/foundation-core/build.gradle.kts @@ -1,3 +1,5 @@ dependencies { // TODO: might be able to ship all dependencies in core? are we duplicating classes in JARs? + + implementation("software.amazon.awssdk:s3:2.17.102") } diff --git a/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/FoundationCorePlugin.kt b/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/FoundationCorePlugin.kt index 51e2301..488df17 100644 --- a/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/FoundationCorePlugin.kt +++ b/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/FoundationCorePlugin.kt @@ -1,27 +1,27 @@ package cloud.kubelet.foundation.core -import cloud.kubelet.foundation.core.command.* -import cloud.kubelet.foundation.core.devupdate.DevUpdateServer -import cloud.kubelet.foundation.core.persist.PersistentStore -import cloud.kubelet.foundation.core.persist.setAllProperties -import io.papermc.paper.event.player.AsyncChatEvent -import net.kyori.adventure.text.Component -import net.kyori.adventure.text.TextComponent -import org.bukkit.GameMode -import org.bukkit.command.CommandExecutor -import org.bukkit.command.TabCompleter -import org.bukkit.event.EventHandler -import org.bukkit.event.Listener -import org.bukkit.plugin.java.JavaPlugin +import cloud.kubelet.foundation.core.abstraction.Feature +import cloud.kubelet.foundation.core.abstraction.FoundationPlugin +import cloud.kubelet.foundation.core.features.backup.BackupFeature +import cloud.kubelet.foundation.core.features.dev.DevFeature +import cloud.kubelet.foundation.core.features.player.PlayerFeature +import cloud.kubelet.foundation.core.features.stats.StatsFeature +import cloud.kubelet.foundation.core.features.update.UpdateFeature +import cloud.kubelet.foundation.core.features.world.WorldFeature +import org.koin.dsl.module import java.nio.file.Path -import java.time.Instant -import java.util.concurrent.ConcurrentHashMap -class FoundationCorePlugin : JavaPlugin(), Listener { - internal val persistentStores = ConcurrentHashMap() +class FoundationCorePlugin : FoundationPlugin() { private lateinit var _pluginDataPath: Path - private lateinit var chatLogStore: PersistentStore - private lateinit var devUpdateServer: DevUpdateServer + override val features: List + get() = listOf( + BackupFeature(), + DevFeature(), + PlayerFeature(), + StatsFeature(), + UpdateFeature(), + WorldFeature(), + ) var pluginDataPath: Path /** @@ -38,104 +38,15 @@ class FoundationCorePlugin : JavaPlugin(), Listener { _pluginDataPath = value } - /** - * Fetch a persistent store by name. Make sure the name is path-safe, descriptive and consistent across server runs. - */ - fun getPersistentStore(name: String) = persistentStores.getOrPut(name) { PersistentStore(this, name) } + override fun module() = module { + single { this@FoundationCorePlugin } + } override fun onEnable() { + // Create core plugin directory. pluginDataPath = dataFolder.toPath() - val backupPath = pluginDataPath.resolve(BACKUPS_DIRECTORY) - - // Create Foundation plugin directories. pluginDataPath.toFile().mkdir() - backupPath.toFile().mkdir() - // Register this as an event listener. - server.pluginManager.registerEvents(this, this) - - // Register commands. - registerCommandExecutor("fbackup", BackupCommand(this, backupPath)) - registerCommandExecutor("fupdate", UpdateCommand()) - registerCommandExecutor(listOf("survival", "s"), GamemodeCommand(GameMode.SURVIVAL)) - registerCommandExecutor(listOf("creative", "c"), GamemodeCommand(GameMode.CREATIVE)) - registerCommandExecutor(listOf("adventure", "a"), GamemodeCommand(GameMode.ADVENTURE)) - registerCommandExecutor(listOf("spectator", "sp"), GamemodeCommand(GameMode.SPECTATOR)) - registerCommandExecutor(listOf("leaderboard", "lb"), LeaderboardCommand()) - registerCommandExecutor("pstore", PersistentStoreCommand(this)) - registerCommandExecutor("setspawn", SetSpawnCommand()) - registerCommandExecutor("spawn", SpawnCommand()) - - val log = slF4JLogger - log.info("Features:") - Util.printFeatureStatus(log, "Backup", BACKUP_ENABLED) - chatLogStore = getPersistentStore("chat-logs") - devUpdateServer = DevUpdateServer(this) - devUpdateServer.enable() - } - - override fun onDisable() { - persistentStores.values.forEach { store -> store.close() } - persistentStores.clear() - devUpdateServer.disable() - } - - private fun registerCommandExecutor(name: String, executor: CommandExecutor) { - registerCommandExecutor(listOf(name), executor) - } - - private fun registerCommandExecutor(names: List, executor: CommandExecutor) { - for (name in names) { - val command = getCommand(name) ?: throw Exception("Failed to get $name command") - command.setExecutor(executor) - if (executor is TabCompleter) { - command.tabCompleter = executor - } - } - } - - // TODO: Disabling chat reformatting until I do something with it and figure out how to make it - // be less disruptive. - /*@EventHandler - private fun onChatMessage(e: ChatEvent) { - return - e.isCancelled = true - val name = e.player.displayName() - val component = Component.empty() - .append(leftBracket) - .append(name) - .append(rightBracket) - .append(Component.text(' ')) - .append(e.message()) - server.sendMessage(component) - }*/ - - @EventHandler - private fun logOnChatMessage(e: AsyncChatEvent) { - val player = e.player - val message = e.message() - - if (message !is TextComponent) { - return - } - - val content = message.content() - chatLogStore.create("ChatMessageEvent") { - setAllProperties( - "timestamp" to Instant.now().toEpochMilli(), - "player.id" to player.identity().uuid().toString(), - "player.name" to player.name, - "message.content" to content - ) - } - } - - companion object { - private const val BACKUPS_DIRECTORY = "backups" - - private val leftBracket: Component = Component.text('[') - private val rightBracket: Component = Component.text(']') - - const val BACKUP_ENABLED = true + super.onEnable() } } diff --git a/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/Util.kt b/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/Util.kt index 8349712..177f88d 100644 --- a/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/Util.kt +++ b/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/Util.kt @@ -11,10 +11,6 @@ object Util { private val whitespace: Component = Component.text(' ') private val foundationName: Component = Component.text("Foundation") - fun printFeatureStatus(logger: Logger, feature: String?, state: Boolean) { - logger.info("{}: {}", feature, if (state) "Enabled" else "Disabled") - } - fun formatSystemMessage(message: String): Component { return formatSystemMessage(TextColors.AMARANTH_PINK, message) } diff --git a/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/abstraction/Feature.kt b/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/abstraction/Feature.kt new file mode 100644 index 0000000..61b9a31 --- /dev/null +++ b/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/abstraction/Feature.kt @@ -0,0 +1,31 @@ +package cloud.kubelet.foundation.core.abstraction + +import cloud.kubelet.foundation.core.FoundationCorePlugin +import org.bukkit.command.CommandExecutor +import org.bukkit.command.TabCompleter +import org.bukkit.event.Listener +import org.koin.core.component.KoinComponent +import org.koin.core.component.inject +import org.koin.dsl.module + +abstract class Feature : KoinComponent, Listener { + private val plugin by inject() + + open fun enable() {} + open fun disable() {} + open fun module() = module {} + + protected fun registerCommandExecutor(name: String, executor: CommandExecutor) { + registerCommandExecutor(listOf(name), executor) + } + + protected fun registerCommandExecutor(names: List, executor: CommandExecutor) { + for (name in names) { + val command = plugin.getCommand(name) ?: throw Exception("Failed to get $name command") + command.setExecutor(executor) + if (executor is TabCompleter) { + command.tabCompleter = executor + } + } + } +} diff --git a/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/abstraction/FoundationPlugin.kt b/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/abstraction/FoundationPlugin.kt new file mode 100644 index 0000000..78241d2 --- /dev/null +++ b/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/abstraction/FoundationPlugin.kt @@ -0,0 +1,54 @@ +package cloud.kubelet.foundation.core.abstraction + +import org.bukkit.plugin.java.JavaPlugin +import org.koin.core.KoinApplication +import org.koin.core.context.startKoin +import org.koin.core.context.stopKoin +import org.koin.core.module.Module +import org.koin.dsl.module + +abstract class FoundationPlugin : JavaPlugin() { + private lateinit var pluginModule: Module + private lateinit var pluginApplication: KoinApplication + protected abstract val features: List + + override fun onEnable() { + pluginModule = module { + single { this@FoundationPlugin } + single { server } + single { config } + single { slF4JLogger } + } + + // TODO: If we have another plugin using this class, we may need to use context isolation. + // https://insert-koin.io/docs/reference/koin-core/context-isolation + pluginApplication = startKoin { + modules(pluginModule) + modules(module()) + } + + features.forEach { + pluginApplication.modules(it.module()) + } + + features.forEach { + try { + slF4JLogger.info("Enabling feature: ${it.javaClass.simpleName}") + it.enable() + server.pluginManager.registerEvents(it, this) + } catch (e: Exception) { + slF4JLogger.error("Failed to enable feature: ${it.javaClass.simpleName}", e) + } + } + } + + override fun onDisable() { + features.forEach { + it.disable() + } + + stopKoin() + } + + protected open fun module() = module {} +} diff --git a/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/command/BackupCommand.kt b/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/features/backup/BackupCommand.kt similarity index 93% rename from foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/command/BackupCommand.kt rename to foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/features/backup/BackupCommand.kt index 4420b96..5d88e37 100644 --- a/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/command/BackupCommand.kt +++ b/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/features/backup/BackupCommand.kt @@ -1,4 +1,4 @@ -package cloud.kubelet.foundation.core.command +package cloud.kubelet.foundation.core.features.backup import cloud.kubelet.foundation.core.FoundationCorePlugin import cloud.kubelet.foundation.core.Util @@ -26,15 +26,6 @@ class BackupCommand( override fun onCommand( sender: CommandSender, command: Command, label: String, args: Array ): Boolean { - if (!FoundationCorePlugin.BACKUP_ENABLED) { - sender.sendMessage( - Component - .text("Backup is not enabled.") - .color(TextColor.fromHexString("#FF0000")) - ) - return true - } - if (RUNNING.get()) { sender.sendMessage( Component diff --git a/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/features/backup/BackupFeature.kt b/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/features/backup/BackupFeature.kt new file mode 100644 index 0000000..e9bd42e --- /dev/null +++ b/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/features/backup/BackupFeature.kt @@ -0,0 +1,21 @@ +package cloud.kubelet.foundation.core.features.backup + +import cloud.kubelet.foundation.core.FoundationCorePlugin +import cloud.kubelet.foundation.core.abstraction.Feature +import org.koin.core.component.inject + +class BackupFeature : Feature() { + private val plugin by inject() + + override fun enable() { + // Create backup directory. + val backupPath = plugin.pluginDataPath.resolve(BACKUPS_DIRECTORY) + backupPath.toFile().mkdir() + + registerCommandExecutor("fbackup", BackupCommand(plugin, backupPath)) + } + + companion object { + private const val BACKUPS_DIRECTORY = "backups" + } +} diff --git a/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/features/dev/DevFeature.kt b/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/features/dev/DevFeature.kt new file mode 100644 index 0000000..17d8499 --- /dev/null +++ b/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/features/dev/DevFeature.kt @@ -0,0 +1,20 @@ +package cloud.kubelet.foundation.core.features.dev + +import cloud.kubelet.foundation.core.FoundationCorePlugin +import cloud.kubelet.foundation.core.abstraction.Feature +import cloud.kubelet.foundation.core.devupdate.DevUpdateServer +import org.koin.core.component.inject + +class DevFeature : Feature() { + private val plugin = inject() + private lateinit var devUpdateServer: DevUpdateServer + + override fun enable() { + devUpdateServer = DevUpdateServer(plugin.value) + devUpdateServer.enable() + } + + override fun disable() { + devUpdateServer.disable() + } +} diff --git a/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/features/player/PlayerFeature.kt b/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/features/player/PlayerFeature.kt new file mode 100644 index 0000000..4191627 --- /dev/null +++ b/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/features/player/PlayerFeature.kt @@ -0,0 +1,14 @@ +package cloud.kubelet.foundation.core.features.player + +import cloud.kubelet.foundation.core.abstraction.Feature +import cloud.kubelet.foundation.core.command.GamemodeCommand +import org.bukkit.GameMode + +class PlayerFeature : Feature() { + override fun enable() { + registerCommandExecutor(listOf("survival", "s"), GamemodeCommand(GameMode.SURVIVAL)) + registerCommandExecutor(listOf("creative", "c"), GamemodeCommand(GameMode.CREATIVE)) + registerCommandExecutor(listOf("adventure", "a"), GamemodeCommand(GameMode.ADVENTURE)) + registerCommandExecutor(listOf("spectator", "sp"), GamemodeCommand(GameMode.SPECTATOR)) + } +} diff --git a/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/command/LeaderboardCommand.kt b/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/features/stats/LeaderboardCommand.kt similarity index 97% rename from foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/command/LeaderboardCommand.kt rename to foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/features/stats/LeaderboardCommand.kt index a92b2f1..0b84e72 100644 --- a/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/command/LeaderboardCommand.kt +++ b/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/features/stats/LeaderboardCommand.kt @@ -1,4 +1,4 @@ -package cloud.kubelet.foundation.core.command +package cloud.kubelet.foundation.core.features.stats import cloud.kubelet.foundation.core.SortOrder import cloud.kubelet.foundation.core.allPlayerStatisticsOf diff --git a/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/command/PersistentStoreCommand.kt b/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/features/stats/PersistentStoreCommand.kt similarity index 80% rename from foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/command/PersistentStoreCommand.kt rename to foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/features/stats/PersistentStoreCommand.kt index 56387a5..41d7a7f 100644 --- a/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/command/PersistentStoreCommand.kt +++ b/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/features/stats/PersistentStoreCommand.kt @@ -1,15 +1,21 @@ -package cloud.kubelet.foundation.core.command +package cloud.kubelet.foundation.core.features.stats -import cloud.kubelet.foundation.core.FoundationCorePlugin import org.bukkit.command.Command import org.bukkit.command.CommandExecutor import org.bukkit.command.CommandSender import org.bukkit.command.TabCompleter -class PersistentStoreCommand(private val plugin: FoundationCorePlugin) : CommandExecutor, TabCompleter { +class PersistentStoreCommand( + private val statsFeature: StatsFeature +) : CommandExecutor, TabCompleter { private val allSubCommands = mutableListOf("stats", "sample", "delete-all-entities") - override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array): Boolean { + override fun onCommand( + sender: CommandSender, + command: Command, + label: String, + args: Array + ): Boolean { if (args.isEmpty()) { sender.sendMessage("Invalid Command Usage.") return true @@ -17,7 +23,7 @@ class PersistentStoreCommand(private val plugin: FoundationCorePlugin) : Command when (args[0]) { "stats" -> { - plugin.persistentStores.forEach { (name, store) -> + statsFeature.persistentStores.forEach { (name, store) -> val counts = store.transact { entityTypes.associateWith { type -> getAll(type).size() }.toSortedMap() } @@ -36,7 +42,7 @@ class PersistentStoreCommand(private val plugin: FoundationCorePlugin) : Command val storeName = args[1] val entityTypeName = args[2] - val store = plugin.getPersistentStore(storeName) + val store = statsFeature.getPersistentStore(storeName) store.transact { val entities = getAll(entityTypeName).take(3) for (entity in entities) { @@ -55,7 +61,7 @@ class PersistentStoreCommand(private val plugin: FoundationCorePlugin) : Command val storeName = args[1] val entityTypeName = args[2] - val store = plugin.getPersistentStore(storeName) + val store = statsFeature.getPersistentStore(storeName) store.transact { store.deleteAllEntities(entityTypeName) } diff --git a/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/features/stats/StatsFeature.kt b/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/features/stats/StatsFeature.kt new file mode 100644 index 0000000..9c1a1cc --- /dev/null +++ b/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/features/stats/StatsFeature.kt @@ -0,0 +1,56 @@ +package cloud.kubelet.foundation.core.features.stats + +import cloud.kubelet.foundation.core.FoundationCorePlugin +import cloud.kubelet.foundation.core.abstraction.Feature +import cloud.kubelet.foundation.core.persist.PersistentStore +import cloud.kubelet.foundation.core.persist.setAllProperties +import io.papermc.paper.event.player.AsyncChatEvent +import net.kyori.adventure.text.TextComponent +import org.bukkit.event.EventHandler +import org.koin.core.component.inject +import java.time.Instant +import java.util.concurrent.ConcurrentHashMap + +class StatsFeature : Feature() { + private val plugin = inject() + private lateinit var chatLogStore: PersistentStore + // TODO: Move persistence stuff to its own module. + internal val persistentStores = ConcurrentHashMap() + + override fun enable() { + chatLogStore = getPersistentStore("chat-logs") + + registerCommandExecutor("pstore", PersistentStoreCommand(this)) + } + + override fun disable() { + persistentStores.values.forEach { store -> store.close() } + persistentStores.clear() + } + + /** + * Fetch a persistent store by name. Make sure the name is path-safe, descriptive and consistent across server runs. + */ + fun getPersistentStore(name: String) = + persistentStores.getOrPut(name) { PersistentStore(plugin.value, name) } + + @EventHandler + private fun logOnChatMessage(e: AsyncChatEvent) { + val player = e.player + val message = e.message() + + if (message !is TextComponent) { + return + } + + val content = message.content() + chatLogStore.create("ChatMessageEvent") { + setAllProperties( + "timestamp" to Instant.now().toEpochMilli(), + "player.id" to player.identity().uuid().toString(), + "player.name" to player.name, + "message.content" to content + ) + } + } +} diff --git a/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/update/ModuleManifest.kt b/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/features/update/ModuleManifest.kt similarity index 72% rename from foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/update/ModuleManifest.kt rename to foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/features/update/ModuleManifest.kt index 1cd9743..dd9da54 100644 --- a/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/update/ModuleManifest.kt +++ b/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/features/update/ModuleManifest.kt @@ -1,4 +1,4 @@ -package cloud.kubelet.foundation.core.update +package cloud.kubelet.foundation.core.features.update import kotlinx.serialization.Serializable diff --git a/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/command/UpdateCommand.kt b/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/features/update/UpdateCommand.kt similarity index 77% rename from foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/command/UpdateCommand.kt rename to foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/features/update/UpdateCommand.kt index 5c07129..ebebe28 100644 --- a/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/command/UpdateCommand.kt +++ b/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/features/update/UpdateCommand.kt @@ -1,6 +1,5 @@ -package cloud.kubelet.foundation.core.command +package cloud.kubelet.foundation.core.features.update -import cloud.kubelet.foundation.core.service.UpdateService import org.bukkit.command.Command import org.bukkit.command.CommandExecutor import org.bukkit.command.CommandSender @@ -15,4 +14,4 @@ class UpdateCommand : CommandExecutor { UpdateService.updatePlugins(sender) return true } -} \ No newline at end of file +} diff --git a/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/features/update/UpdateFeature.kt b/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/features/update/UpdateFeature.kt new file mode 100644 index 0000000..a965f63 --- /dev/null +++ b/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/features/update/UpdateFeature.kt @@ -0,0 +1,9 @@ +package cloud.kubelet.foundation.core.features.update + +import cloud.kubelet.foundation.core.abstraction.Feature + +class UpdateFeature : Feature() { + override fun enable() { + registerCommandExecutor("fupdate", UpdateCommand()) + } +} diff --git a/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/service/UpdateService.kt b/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/features/update/UpdateService.kt similarity index 90% rename from foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/service/UpdateService.kt rename to foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/features/update/UpdateService.kt index a8f6106..a3d20ff 100644 --- a/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/service/UpdateService.kt +++ b/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/features/update/UpdateService.kt @@ -1,11 +1,10 @@ -package cloud.kubelet.foundation.core.service +package cloud.kubelet.foundation.core.features.update -import cloud.kubelet.foundation.core.update.UpdateUtil import org.bukkit.command.CommandSender import kotlin.io.path.name import kotlin.io.path.toPath -// TODO: Switch to classes and use dependency injection with koin. +// TODO: Switch to a class and use dependency injection with koin. object UpdateService { fun updatePlugins(sender: CommandSender, onFinish: (() -> Unit)? = null) { val updateDir = sender.server.pluginsFolder.resolve("update") diff --git a/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/update/UpdateUtil.kt b/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/features/update/UpdateUtil.kt similarity index 96% rename from foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/update/UpdateUtil.kt rename to foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/features/update/UpdateUtil.kt index 118cf43..8920a68 100644 --- a/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/update/UpdateUtil.kt +++ b/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/features/update/UpdateUtil.kt @@ -1,4 +1,4 @@ -package cloud.kubelet.foundation.core.update +package cloud.kubelet.foundation.core.features.update import kotlinx.serialization.DeserializationStrategy import kotlinx.serialization.builtins.MapSerializer diff --git a/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/features/world/WorldFeature.kt b/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/features/world/WorldFeature.kt new file mode 100644 index 0000000..2edf88b --- /dev/null +++ b/foundation-core/src/main/kotlin/cloud/kubelet/foundation/core/features/world/WorldFeature.kt @@ -0,0 +1,14 @@ +package cloud.kubelet.foundation.core.features.world + +import cloud.kubelet.foundation.core.abstraction.Feature +import cloud.kubelet.foundation.core.command.GamemodeCommand +import cloud.kubelet.foundation.core.command.SetSpawnCommand +import cloud.kubelet.foundation.core.command.SpawnCommand +import org.bukkit.GameMode + +class WorldFeature : Feature() { + override fun enable() { + registerCommandExecutor("setspawn", SetSpawnCommand()) + registerCommandExecutor("spawn", SpawnCommand()) + } +}