Gradle.................

This commit is contained in:
Logan Gorence
2021-12-21 08:58:44 +00:00
parent 7259de6c17
commit aed37ae013
11 changed files with 85 additions and 47 deletions

View File

@ -0,0 +1,2 @@
dependencies {
}

View File

@ -0,0 +1,57 @@
package cloud.kubelet.foundation.core
import cloud.kubelet.foundation.core.command.BackupCommand
import io.papermc.paper.event.player.ChatEvent
import net.kyori.adventure.text.Component
import org.bukkit.command.CommandExecutor
import org.bukkit.event.EventHandler
import org.bukkit.event.Listener
import org.bukkit.plugin.java.JavaPlugin
class FoundationCorePlugin : JavaPlugin(), Listener {
override fun onEnable() {
val dataPath = dataFolder.toPath()
val backupPath = dataPath.resolve(BACKUPS_DIRECTORY)
// Create Foundation plugin directories.
dataPath.toFile().mkdir()
backupPath.toFile().mkdir()
// Register this as an event listener.
server.pluginManager.registerEvents(this, this)
// Register commands.
registerCommandExecutor("fbackup", BackupCommand(this, backupPath))
val log = slF4JLogger
log.info("Features:")
Util.printFeatureStatus(log, "Backup: ", BACKUP_ENABLED)
}
private fun registerCommandExecutor(name: String, executor: CommandExecutor) {
val command = getCommand(name) ?: throw Exception("Failed to get $name command")
command.setExecutor(executor)
}
@EventHandler
private fun onChatMessage(e: ChatEvent) {
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)
}
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
}
}

View File

@ -0,0 +1,7 @@
package cloud.kubelet.foundation.core
import net.kyori.adventure.text.format.TextColor
object TextColors {
val AMARANTH_PINK = TextColor.fromHexString("#F7A8B8")
}

View File

@ -0,0 +1,28 @@
package cloud.kubelet.foundation.core
import net.kyori.adventure.text.Component
import net.kyori.adventure.text.format.TextColor
import org.slf4j.Logger
object Util {
private val leftBracket: Component = Component.text('[')
private val rightBracket: Component = Component.text(']')
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)
}
fun formatSystemMessage(prefixColor: TextColor?, message: String?): Component {
return leftBracket
.append(foundationName.color(prefixColor))
.append(rightBracket)
.append(whitespace)
.append(Component.text(message!!))
}
}

View File

@ -0,0 +1,143 @@
package cloud.kubelet.foundation.core.command
import cloud.kubelet.foundation.core.FoundationCorePlugin
import cloud.kubelet.foundation.core.Util
import net.kyori.adventure.text.Component
import net.kyori.adventure.text.format.TextColor
import org.bukkit.Server
import org.bukkit.command.Command
import org.bukkit.command.CommandExecutor
import org.bukkit.command.CommandSender
import java.io.BufferedOutputStream
import java.io.FileInputStream
import java.io.FileOutputStream
import java.io.IOException
import java.nio.file.Files
import java.nio.file.Path
import java.time.Instant
import java.util.concurrent.atomic.AtomicBoolean
import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream
class BackupCommand(
private val plugin: FoundationCorePlugin,
private val backupPath: Path
) : CommandExecutor {
override fun onCommand(
sender: CommandSender, command: Command, label: String, args: Array<String>
): 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
.text("Backup is already running.")
.color(TextColor.fromHexString("#FF0000"))
)
return true
}
try {
val server = sender.server
server.scheduler.runTaskAsynchronously(plugin, Runnable {
runBackup(server)
})
} catch (e: Exception) {
sender.sendMessage(String.format("Failed to backup: %s", e.message))
}
return true
}
private fun runBackup(server: Server) {
RUNNING.set(true)
server.sendMessage(Util.formatSystemMessage("Backup started."))
val backupFile =
backupPath.resolve(String.format("backup-%s.zip", Instant.now().toString())).toFile()
try {
FileOutputStream(backupFile).use { zipFileStream ->
ZipOutputStream(BufferedOutputStream(zipFileStream)).use { zipStream ->
backupPlugins(server, zipStream)
backupWorlds(server, zipStream)
}
}
} finally {
RUNNING.set(false)
server.sendMessage(Util.formatSystemMessage("Backup finished."))
}
}
private fun backupPlugins(server: Server, zipStream: ZipOutputStream) {
try {
addDirectoryToZip(zipStream, server.pluginsFolder.toPath())
} catch (e: IOException) {
// TODO: Add error handling.
e.printStackTrace()
}
}
private fun backupWorlds(server: Server, zipStream: ZipOutputStream) {
val worlds = server.worlds
for (world in worlds) {
val worldPath = world.worldFolder.toPath()
// Save the world.
server.scheduler.runTask(plugin, Runnable {
world.save()
})
// Disable auto saving to prevent any world corruption while creating a ZIP.
world.isAutoSave = false
try {
addDirectoryToZip(zipStream, worldPath)
} catch (e: IOException) {
// TODO: Add error handling.
e.printStackTrace()
}
// Re-enable auto saving for this world.
world.isAutoSave = true
}
}
private fun addDirectoryToZip(zipStream: ZipOutputStream, directoryPath: Path) {
val paths = Files.walk(directoryPath)
.filter { path: Path? -> Files.isRegularFile(path) }
.toList()
val buffer = ByteArray(1024)
val backupsPath = backupPath.toRealPath()
for (path in paths) {
val realPath = path.toRealPath()
if (realPath.startsWith(backupsPath)) {
plugin.slF4JLogger.info("Skipping file for backup: {}", realPath)
continue
}
FileInputStream(path.toFile()).use { fileStream ->
val entry = ZipEntry(path.toString())
zipStream.putNextEntry(entry)
var n: Int
while (fileStream.read(buffer).also { n = it } > -1) {
zipStream.write(buffer, 0, n)
}
}
}
}
companion object {
private val RUNNING = AtomicBoolean()
}
}

View File

@ -0,0 +1,13 @@
name: Foundation
version: '${version}'
main: cloud.kubelet.foundation.core.FoundationCorePlugin
api-version: 1.18
prefix: Foundation
load: STARTUP
authors:
- kubelet
commands:
fbackup:
description: Foundation Backup
usage: /fbackup
permission: foundation.backup