From 9b258db1cc709476d95048d32e67d82749a0dd1a Mon Sep 17 00:00:00 2001 From: Test-Account666 <36412486+Test-Account666@users.noreply.github.com> Date: Tue, 3 Feb 2026 17:32:21 +0100 Subject: [PATCH 1/3] refactor(teleportation): centralize and streamline teleportation logic with `TeleportRunnable`, improve localization --- .../executables/spawn/CommandSpawn.kt | 32 ++++-- .../executables/spawn/ListenerSpawn.kt | 2 +- .../teleportask/CommandTeleportAsk.kt | 58 +++------- .../teleportask/ListenerTeleportRequest.kt | 60 ----------- .../waypoints/AbstractCommandWaypoint.kt | 37 ++++--- .../waypoints/home/admin/CommandAdminHome.kt | 3 +- .../waypoints/home/user/CommandHome.kt | 7 ++ .../executables/waypoints/warp/CommandWarp.kt | 5 + .../serversystem/userdata/User.kt | 5 +- .../teleport}/TeleportRequest.kt | 7 +- .../userdata/teleport/TeleportRunnable.kt | 102 ++++++++++++++++++ .../resources/messages/english/messages.yml | 12 ++- .../resources/messages/german/messages.yml | 10 +- .../resources/messages/slovene/messages.yml | 12 ++- src/main/resources/permissions.yml | 13 ++- 15 files changed, 219 insertions(+), 146 deletions(-) delete mode 100644 src/main/kotlin/me/testaccount666/serversystem/commands/executables/teleportask/ListenerTeleportRequest.kt rename src/main/kotlin/me/testaccount666/serversystem/{commands/executables/teleportask => userdata/teleport}/TeleportRequest.kt (60%) create mode 100644 src/main/kotlin/me/testaccount666/serversystem/userdata/teleport/TeleportRunnable.kt diff --git a/src/main/kotlin/me/testaccount666/serversystem/commands/executables/spawn/CommandSpawn.kt b/src/main/kotlin/me/testaccount666/serversystem/commands/executables/spawn/CommandSpawn.kt index 8dd96e9a..a4fa2769 100644 --- a/src/main/kotlin/me/testaccount666/serversystem/commands/executables/spawn/CommandSpawn.kt +++ b/src/main/kotlin/me/testaccount666/serversystem/commands/executables/spawn/CommandSpawn.kt @@ -4,8 +4,11 @@ import me.testaccount666.serversystem.ServerSystem.Companion.instance import me.testaccount666.serversystem.ServerSystem.Companion.log import me.testaccount666.serversystem.commands.ServerSystemCommand import me.testaccount666.serversystem.commands.executables.AbstractServerSystemCommand +import me.testaccount666.serversystem.managers.PermissionManager.hasCommandPermission import me.testaccount666.serversystem.managers.config.ConfigurationManager import me.testaccount666.serversystem.userdata.User +import me.testaccount666.serversystem.userdata.teleport.TeleportRunnable.Companion.teleportLater +import me.testaccount666.serversystem.userdata.teleport.TeleportRunnable.Companion.teleportNow import me.testaccount666.serversystem.utils.MessageBuilder.Companion.command import me.testaccount666.serversystem.utils.MessageBuilder.Companion.general import org.bukkit.Bukkit @@ -53,7 +56,6 @@ open class CommandSpawn : AbstractServerSystemCommand { if (!spawnConfiguration.isSet("Spawn")) return val worldName = spawnConfiguration.getString("Spawn.World") ?: return - val world = Bukkit.getWorld(worldName) ?: return val x = spawnConfiguration.getDouble("Spawn.X") @@ -67,17 +69,17 @@ open class CommandSpawn : AbstractServerSystemCommand { override fun execute(commandSender: User, command: Command, label: String, vararg arguments: String) { if (command.name.equals("spawn", true)) { - handleSpawnCommand(commandSender, label, *arguments) + handleSpawnCommand(commandSender, label, true, *arguments) return } handleSetSpawnCommand(commandSender, label) } - fun handleSpawnCommand(commandSender: User, label: String, vararg arguments: String) { + fun handleSpawnCommand(commandSender: User, label: String, fromCommand: Boolean, vararg arguments: String) { if (isConsoleWithNoTarget(commandSender, getSyntaxPath(null), label, arguments = arguments)) return - if (spawnLocation == null) { + val spawnLocation = spawnLocation ?: run { command("Spawn.NoSpawnSet", commandSender).build() return } @@ -86,16 +88,28 @@ open class CommandSpawn : AbstractServerSystemCommand { general("PlayerNotFound", commandSender) { target(arguments[0]) }.build() return } - - val targetPlayer = targetUser.getPlayer()!! val isSelf = targetUser === commandSender - if (!isSelf && !checkPermission(commandSender, "Spawn.Other", targetPlayer.name)) return + if (!isSelf && !checkPermission(commandSender, "Spawn.Other", targetUser.getNameSafe())) return + + val instantTeleport = !fromCommand || !isSelf || hasCommandPermission(commandSender, "Spawn.InstantTeleport", false) + + if (instantTeleport) { + targetUser.teleportNow(spawnLocation) + sendSuccessMessage(commandSender, targetUser, isSelf) + return + } - targetPlayer.teleport(spawnLocation!!) + command("Spawn.Teleporting", commandSender) { target(targetUser.getNameSafe()) }.build() + targetUser.teleportLater(spawnLocation).apply { + onSuccess = { sendSuccessMessage(commandSender, targetUser, true) } + onFailure = { command("Spawn.Moved", commandSender).build() } + } + } + private fun sendSuccessMessage(commandSender: User, targetUser: User, isSelf: Boolean) { val messagePath = if (isSelf) "Spawn.Success" else "Spawn.SuccessOther" - command(messagePath, commandSender) { target(targetPlayer.name) }.build() + command(messagePath, commandSender) { target(targetUser.getNameSafe()) }.build() if (isSelf) return command("Spawn.Success", targetUser) { sender(commandSender.getNameSafe()) }.build() diff --git a/src/main/kotlin/me/testaccount666/serversystem/commands/executables/spawn/ListenerSpawn.kt b/src/main/kotlin/me/testaccount666/serversystem/commands/executables/spawn/ListenerSpawn.kt index d4995e90..86286668 100644 --- a/src/main/kotlin/me/testaccount666/serversystem/commands/executables/spawn/ListenerSpawn.kt +++ b/src/main/kotlin/me/testaccount666/serversystem/commands/executables/spawn/ListenerSpawn.kt @@ -34,7 +34,7 @@ class ListenerSpawn : Listener { if (cachedUser.isOfflineUser) return@Runnable val user = cachedUser.offlineUser as User - _commandSpawn.handleSpawnCommand(user, "spawn") + _commandSpawn.handleSpawnCommand(user, "spawn", false) }, 20L) } } diff --git a/src/main/kotlin/me/testaccount666/serversystem/commands/executables/teleportask/CommandTeleportAsk.kt b/src/main/kotlin/me/testaccount666/serversystem/commands/executables/teleportask/CommandTeleportAsk.kt index c5ccbfbd..1ef7f9b0 100644 --- a/src/main/kotlin/me/testaccount666/serversystem/commands/executables/teleportask/CommandTeleportAsk.kt +++ b/src/main/kotlin/me/testaccount666/serversystem/commands/executables/teleportask/CommandTeleportAsk.kt @@ -1,22 +1,20 @@ package me.testaccount666.serversystem.commands.executables.teleportask -import me.testaccount666.serversystem.ServerSystem.Companion.instance import me.testaccount666.serversystem.ServerSystem.Companion.log import me.testaccount666.serversystem.commands.ServerSystemCommand import me.testaccount666.serversystem.commands.executables.AbstractServerSystemCommand import me.testaccount666.serversystem.managers.PermissionManager.hasCommandPermission import me.testaccount666.serversystem.managers.messages.MessageManager.applyPlaceholders import me.testaccount666.serversystem.userdata.User +import me.testaccount666.serversystem.userdata.teleport.TeleportRequest +import me.testaccount666.serversystem.userdata.teleport.TeleportRunnable.Companion.teleportLater +import me.testaccount666.serversystem.userdata.teleport.TeleportRunnable.Companion.teleportNow import me.testaccount666.serversystem.utils.ComponentColor.translateToComponent import me.testaccount666.serversystem.utils.MessageBuilder.Companion.command import me.testaccount666.serversystem.utils.MessageBuilder.Companion.general import net.kyori.adventure.text.Component import net.kyori.adventure.text.event.ClickEvent import net.kyori.adventure.text.event.HoverEvent -import org.bukkit.Bukkit -import org.bukkit.Location -import org.bukkit.Particle -import org.bukkit.Sound import org.bukkit.command.Command @ServerSystemCommand("teleportask", ["teleporthereask", "teleportaccept", "teleportdeny", "teleporttoggle"]) @@ -212,6 +210,7 @@ class CommandTeleportAsk : AbstractServerSystemCommand() { private fun handleTeleportAccept(commandSender: User) { val teleportRequest = validateTeleportRequest(commandSender) ?: return + teleportRequest.isCancelled = true val requester = teleportRequest.sender commandSender.teleportRequest = null @@ -221,15 +220,7 @@ class CommandTeleportAsk : AbstractServerSystemCommand() { val teleporter = if (teleportRequest.isTeleportHere) commandSender else requester val target = if (teleportRequest.isTeleportHere) requester else commandSender - val canInstantTeleport = hasCommandPermission(teleporter, "TeleportAsk.InstantTeleport", false) - - if (canInstantTeleport) { - executeTeleport(teleporter, target) - return - } - - command("TeleportAsk.StartingTeleporting", teleporter) { target(target.getNameSafe()) }.build() - startTeleportTimer(teleporter, target, teleportRequest) + executeTeleport(teleporter, target) } private fun handleTeleportDeny(commandSender: User) { @@ -242,20 +233,6 @@ class CommandTeleportAsk : AbstractServerSystemCommand() { command("TeleportDeny.SuccessOther", requester) { target(commandSender.getNameSafe()) }.build() } - private fun startTeleportTimer(teleporter: User, target: User, teleportRequest: TeleportRequest) { - val teleporterPlayer = teleporter.getPlayer() - val targetPlayer = target.getPlayer() - - activeTeleportRequests.add(teleportRequest) - (Bukkit.getScheduler().scheduleSyncDelayedTask(instance, { - if (teleporterPlayer == null || !teleporterPlayer.isOnline) return@scheduleSyncDelayedTask - if (targetPlayer == null || !targetPlayer.isOnline) return@scheduleSyncDelayedTask - - executeTeleport(teleporter, target) - activeTeleportRequests.remove(teleportRequest) - }, 20L * 5)).also { teleportRequest.timerId = it } - } - /** * Executes the teleport with animation and notification * @@ -265,11 +242,16 @@ class CommandTeleportAsk : AbstractServerSystemCommand() { private fun executeTeleport(teleporter: User, target: User) { val targetLocation = target.getPlayer()!!.location - playAnimation(targetLocation) - teleporter.getPlayer()!!.teleport(targetLocation) - playAnimation(targetLocation) - - command("TeleportAsk.TeleportFinished", teleporter) { target(target.getNameSafe()) }.build() + if (!hasCommandPermission(teleporter, "TeleportAsk.InstantTeleport", false)) { + command("TeleportAsk.StartingTeleporting", teleporter) { target(target.getNameSafe()) }.build() + teleporter.teleportLater(targetLocation).apply { + onFailure = { command("TeleportAsk.Moved", user).build() } + onSuccess = { command("TeleportAsk.TeleportFinished", user).build() } + } + } else { + teleporter.teleportNow(targetLocation) + command("TeleportAsk.TeleportFinished", teleporter) { target(target.getNameSafe()) }.build() + } } @@ -290,16 +272,6 @@ class CommandTeleportAsk : AbstractServerSystemCommand() { .asComponent() } - /** - * Plays a teleportation animation effect at the given location - * - * @param location The location to play the animation at - */ - private fun playAnimation(location: Location) { - location.world.playSound(location, Sound.ENTITY_ENDERMAN_TELEPORT, 1.0f, 1.0f) - location.world.spawnParticle(Particle.PORTAL, location, 100, 0.5, 0.5, 0.5, 0.05) - } - private fun handleTeleportToggle(commandSender: User, command: Command, label: String, vararg arguments: String) { if (isConsoleWithNoTarget(commandSender, getSyntaxPath(command), label, arguments = arguments)) return diff --git a/src/main/kotlin/me/testaccount666/serversystem/commands/executables/teleportask/ListenerTeleportRequest.kt b/src/main/kotlin/me/testaccount666/serversystem/commands/executables/teleportask/ListenerTeleportRequest.kt deleted file mode 100644 index b26d5a4b..00000000 --- a/src/main/kotlin/me/testaccount666/serversystem/commands/executables/teleportask/ListenerTeleportRequest.kt +++ /dev/null @@ -1,60 +0,0 @@ -package me.testaccount666.serversystem.commands.executables.teleportask - -import me.testaccount666.serversystem.annotations.RequiredCommands -import me.testaccount666.serversystem.commands.interfaces.ServerSystemCommandExecutor -import me.testaccount666.serversystem.utils.MessageBuilder.Companion.command -import org.bukkit.Bukkit -import org.bukkit.Location -import org.bukkit.event.EventHandler -import org.bukkit.event.Listener -import org.bukkit.event.player.PlayerMoveEvent - -@RequiredCommands([CommandTeleportAsk::class]) -class ListenerTeleportRequest : Listener { - private lateinit var _commandTeleportAsk: CommandTeleportAsk - - fun canRegister(requiredCommands: Set): Boolean { - _commandTeleportAsk = requiredCommands.firstOrNull { it is CommandTeleportAsk } as? CommandTeleportAsk ?: return false - return true - } - - @EventHandler - fun onTeleporterMove(event: PlayerMoveEvent) { - getDistance(event).let { if (it < .1) return } - - _commandTeleportAsk.activeTeleportRequests.toList() - .forEach { teleportRequest -> - val teleporter = if (teleportRequest.isTeleportHere) teleportRequest.receiver else teleportRequest.sender - if (teleporter.getPlayer() == null) return@forEach - val teleporterPlayer = teleporter.getPlayer()!! - - if (event.getPlayer().uniqueId != teleporterPlayer.uniqueId) return@forEach - - Bukkit.getScheduler().cancelTask(teleportRequest.timerId) - teleportRequest.isCancelled = true - _commandTeleportAsk.activeTeleportRequests.remove(teleportRequest) - command("TeleportAsk.Moved", teleporter).build() - } - } - - companion object { - private fun getDistance(event: PlayerMoveEvent): Double { - val fromX = event.from.x - val toX = event.to.x - - val fromY = event.from.y - val toY = event.to.y - - val fromZ = event.from.z - val toZ = event.to.z - - val fromWorld = event.from.world - val toWorld = event.to.world - - val from = Location(fromWorld, fromX, fromY, fromZ) - val to = Location(toWorld, toX, toY, toZ) - - return if (from.world.name.equals(to.world.name, true)) from.distance(to) else Double.MAX_VALUE - } - } -} diff --git a/src/main/kotlin/me/testaccount666/serversystem/commands/executables/waypoints/AbstractCommandWaypoint.kt b/src/main/kotlin/me/testaccount666/serversystem/commands/executables/waypoints/AbstractCommandWaypoint.kt index 5f97844c..eda0fede 100644 --- a/src/main/kotlin/me/testaccount666/serversystem/commands/executables/waypoints/AbstractCommandWaypoint.kt +++ b/src/main/kotlin/me/testaccount666/serversystem/commands/executables/waypoints/AbstractCommandWaypoint.kt @@ -2,12 +2,12 @@ package me.testaccount666.serversystem.commands.executables.waypoints import me.testaccount666.serversystem.commands.executables.AbstractServerSystemCommand import me.testaccount666.serversystem.userdata.User +import me.testaccount666.serversystem.userdata.teleport.TeleportRunnable.Companion.teleportLater +import me.testaccount666.serversystem.userdata.teleport.TeleportRunnable.Companion.teleportNow import me.testaccount666.serversystem.utils.MessageBuilder.Companion.command import me.testaccount666.serversystem.utils.MessageBuilder.Companion.general import me.testaccount666.serversystem.utils.tuples.Tuple import org.bukkit.Location -import org.bukkit.Particle -import org.bukkit.Sound import org.bukkit.command.Command abstract class AbstractCommandWaypoint, P : Waypoint> : AbstractServerSystemCommand() { @@ -75,16 +75,25 @@ abstract class AbstractCommandWaypoint, P : Waypoint> : A } val pointLocation = point.location - val player = commandSender.getPlayer()!! - playAnimation(player.location) - player.teleport(pointLocation) - playAnimation(pointLocation) - - command("${getPrefix(command)}.Success", commandSender) { - target(target.getNameSafe()) - postModifier { it.replace(getPlaceholder(), point.displayName) } - }.build() + if (!canInstantTeleport(command, commandSender)) { + commandSender.teleportLater(pointLocation).apply { + onFailure = { command("${getPrefix(command)}.Moved", commandSender) { target(target.getNameSafe()) }.build() } + onSuccess = { + command("${getPrefix(command)}.Success", user) { + target(target.getNameSafe()) + postModifier { it.replace(getPlaceholder(), point.displayName) } + }.build() + } + } + command("${getPrefix(command)}.Teleporting", commandSender) { target(target.getNameSafe()) }.build() + } else { + commandSender.teleportNow(pointLocation) + command("${getPrefix(command)}.Success", commandSender) { + target(target.getNameSafe()) + postModifier { it.replace(getPlaceholder(), point.displayName) } + }.build() + } } private fun resolveTargetAndPoint(commandSender: User, command: Command, vararg arguments: String): Tuple? { @@ -114,11 +123,6 @@ abstract class AbstractCommandWaypoint, P : Waypoint> : A }.build() } - private fun playAnimation(location: Location) { - location.world.playSound(location, Sound.ENTITY_ENDERMAN_TELEPORT, 1.0f, 1.0f) - location.world.spawnParticle(Particle.PORTAL, location, 100, 0.5, 0.5, 0.5, 0.05) - } - abstract fun argsBeforePoint(command: Command): Int abstract fun getWaypointManager(command: Command, targetUser: User): T abstract fun getCommandType(command: Command): CommandType @@ -127,6 +131,7 @@ abstract class AbstractCommandWaypoint, P : Waypoint> : A abstract fun getPrefix(command: Command): String abstract fun getPlaceholder(): String + abstract fun canInstantTeleport(command: Command, user: User): Boolean } enum class CommandType { CREATE, DELETE, TELEPORT } \ No newline at end of file diff --git a/src/main/kotlin/me/testaccount666/serversystem/commands/executables/waypoints/home/admin/CommandAdminHome.kt b/src/main/kotlin/me/testaccount666/serversystem/commands/executables/waypoints/home/admin/CommandAdminHome.kt index 458b664c..59bfbd63 100644 --- a/src/main/kotlin/me/testaccount666/serversystem/commands/executables/waypoints/home/admin/CommandAdminHome.kt +++ b/src/main/kotlin/me/testaccount666/serversystem/commands/executables/waypoints/home/admin/CommandAdminHome.kt @@ -2,6 +2,7 @@ package me.testaccount666.serversystem.commands.executables.waypoints.home.admin import me.testaccount666.serversystem.commands.executables.waypoints.CommandType import me.testaccount666.serversystem.commands.executables.waypoints.home.AbstractCommandHome +import me.testaccount666.serversystem.userdata.User import me.testaccount666.serversystem.userdata.home.HomeManager import org.bukkit.command.Command @@ -41,6 +42,6 @@ class CommandAdminHome : AbstractCommandHome() { } override fun getSyntaxPath(command: Command?) = "AdminHome" - override fun canAddPoints(pointManager: HomeManager, command: Command) = true + override fun canInstantTeleport(command: Command, user: User) = true } diff --git a/src/main/kotlin/me/testaccount666/serversystem/commands/executables/waypoints/home/user/CommandHome.kt b/src/main/kotlin/me/testaccount666/serversystem/commands/executables/waypoints/home/user/CommandHome.kt index 54869bef..21ba59bf 100644 --- a/src/main/kotlin/me/testaccount666/serversystem/commands/executables/waypoints/home/user/CommandHome.kt +++ b/src/main/kotlin/me/testaccount666/serversystem/commands/executables/waypoints/home/user/CommandHome.kt @@ -4,6 +4,8 @@ import me.testaccount666.serversystem.commands.ServerSystemCommand import me.testaccount666.serversystem.commands.executables.waypoints.CommandType import me.testaccount666.serversystem.commands.executables.waypoints.home.AbstractCommandHome import me.testaccount666.serversystem.commands.executables.waypoints.home.admin.CommandAdminHome +import me.testaccount666.serversystem.managers.PermissionManager.hasCommandPermission +import me.testaccount666.serversystem.userdata.User import me.testaccount666.serversystem.userdata.home.HomeManager import org.bukkit.command.Command @@ -63,5 +65,10 @@ class CommandHome : AbstractCommandHome() { } } + override fun canInstantTeleport(command: Command, user: User): Boolean { + if (isAdminCommand(command)) return _commandAdminHome.canInstantTeleport(command, user) + return hasCommandPermission(user, "Home.InstantTeleport", false) + } + private fun isAdminCommand(command: Command?) = command?.name?.startsWith("admin", true) ?: false } diff --git a/src/main/kotlin/me/testaccount666/serversystem/commands/executables/waypoints/warp/CommandWarp.kt b/src/main/kotlin/me/testaccount666/serversystem/commands/executables/waypoints/warp/CommandWarp.kt index 4ffd3769..72b0830f 100644 --- a/src/main/kotlin/me/testaccount666/serversystem/commands/executables/waypoints/warp/CommandWarp.kt +++ b/src/main/kotlin/me/testaccount666/serversystem/commands/executables/waypoints/warp/CommandWarp.kt @@ -5,6 +5,7 @@ import me.testaccount666.serversystem.commands.executables.waypoints.AbstractCom import me.testaccount666.serversystem.commands.executables.waypoints.CommandType import me.testaccount666.serversystem.commands.executables.waypoints.warp.manager.Warp import me.testaccount666.serversystem.commands.executables.waypoints.warp.manager.WarpManager +import me.testaccount666.serversystem.managers.PermissionManager.hasCommandPermission import me.testaccount666.serversystem.userdata.User import org.bukkit.Location import org.bukkit.command.Command @@ -43,4 +44,8 @@ class CommandWarp : AbstractCommandWaypoint() { CommandType.TELEPORT -> "Warp.Teleport" } } + + override fun canInstantTeleport(command: Command, user: User): Boolean { + return hasCommandPermission(user, "Warp.InstantTeleport", false) + } } diff --git a/src/main/kotlin/me/testaccount666/serversystem/userdata/User.kt b/src/main/kotlin/me/testaccount666/serversystem/userdata/User.kt index 857fdbec..6005d82e 100644 --- a/src/main/kotlin/me/testaccount666/serversystem/userdata/User.kt +++ b/src/main/kotlin/me/testaccount666/serversystem/userdata/User.kt @@ -1,6 +1,7 @@ package me.testaccount666.serversystem.userdata -import me.testaccount666.serversystem.commands.executables.teleportask.TeleportRequest +import me.testaccount666.serversystem.userdata.teleport.TeleportRequest +import me.testaccount666.serversystem.userdata.teleport.TeleportRunnable import net.kyori.adventure.text.Component import org.bukkit.command.CommandSender import org.bukkit.entity.Player @@ -16,7 +17,7 @@ open class User(userFile: File) : OfflineUser(userFile) { protected open var onlinePlayer: Player? = null var teleportRequest: TeleportRequest? = null - + var teleportRunnable: TeleportRunnable? = null var replyUser: User? = null var isAfk = false diff --git a/src/main/kotlin/me/testaccount666/serversystem/commands/executables/teleportask/TeleportRequest.kt b/src/main/kotlin/me/testaccount666/serversystem/userdata/teleport/TeleportRequest.kt similarity index 60% rename from src/main/kotlin/me/testaccount666/serversystem/commands/executables/teleportask/TeleportRequest.kt rename to src/main/kotlin/me/testaccount666/serversystem/userdata/teleport/TeleportRequest.kt index 839f6838..3c3ccb9c 100644 --- a/src/main/kotlin/me/testaccount666/serversystem/commands/executables/teleportask/TeleportRequest.kt +++ b/src/main/kotlin/me/testaccount666/serversystem/userdata/teleport/TeleportRequest.kt @@ -1,11 +1,10 @@ -package me.testaccount666.serversystem.commands.executables.teleportask +package me.testaccount666.serversystem.userdata.teleport import me.testaccount666.serversystem.userdata.User data class TeleportRequest(val sender: User, val receiver: User, private val _timeout: Long, val isTeleportHere: Boolean) { var isCancelled = false - var timerId = 0 val isExpired - get() = System.currentTimeMillis() >= _timeout -} + get() = isCancelled || System.currentTimeMillis() >= _timeout +} \ No newline at end of file diff --git a/src/main/kotlin/me/testaccount666/serversystem/userdata/teleport/TeleportRunnable.kt b/src/main/kotlin/me/testaccount666/serversystem/userdata/teleport/TeleportRunnable.kt new file mode 100644 index 00000000..c3b9e9b4 --- /dev/null +++ b/src/main/kotlin/me/testaccount666/serversystem/userdata/teleport/TeleportRunnable.kt @@ -0,0 +1,102 @@ +package me.testaccount666.serversystem.userdata.teleport + +import me.testaccount666.serversystem.ServerSystem +import me.testaccount666.serversystem.userdata.User +import org.bukkit.Bukkit +import org.bukkit.Location +import org.bukkit.Particle +import org.bukkit.Sound +import org.bukkit.event.player.PlayerTeleportEvent +import org.bukkit.scheduler.BukkitRunnable + +class TeleportRunnable(val user: User, val location: Location, val originLocation: Location, delay: Long) { + private val endTime = System.currentTimeMillis() + delay + private var _running = true + + fun cancel() = let { _running = false } + var onFailure: ((user: User) -> Unit)? = null + var onSuccess: ((user: User) -> Unit)? = null + + init { + user.teleportRunnable?.cancel() + user.teleportRunnable = this + + createTask().runTaskTimer(ServerSystem.instance, 5L, 5L) + } + + private fun createTask(): BukkitRunnable { + return object : BukkitRunnable() { + override fun run() { + runCatching { + if (!_running) { + stopTask() + return + } + + if (calculateDistance() > 0.1) { + stopTask() + return + } + + if (endTime > System.currentTimeMillis()) return + + user.getPlayer()?.let { + playAnimation(originLocation) + it.teleport(location, PlayerTeleportEvent.TeleportCause.PLUGIN) + playAnimation(location) + + onSuccess?.invoke(user) + } + + _running = false + stopTask() + }.onFailure { + it.printStackTrace() + stopTask() + } + } + + fun stopTask() { + if (_running) onFailure?.invoke(user) + + _running = false + user.teleportRunnable = null + Bukkit.getScheduler().cancelTask(taskId) + } + } + } + + private fun calculateDistance(): Double { + val location = user.getPlayer()?.location ?: return Double.MAX_VALUE + if (location.world != originLocation.world) return Double.MAX_VALUE + + return location.distance(originLocation) + } + + companion object { + /** + * Plays a teleportation animation effect at the given location + * + * @param location The location to play the animation at + */ + fun playAnimation(location: Location) { + location.world.playSound(location, Sound.ENTITY_ENDERMAN_TELEPORT, 1.0f, 1.0f) + location.world.spawnParticle(Particle.PORTAL, location, 100, 0.5, 0.5, 0.5, 0.05) + } + + fun User.teleportNow(location: Location) { + val player = getPlayer() ?: error("Player is null!") + + playAnimation(player.location) + player.teleport(location) + playAnimation(location) + } + + fun User.teleportLater(location: Location, delay: Long = 3000): TeleportRunnable { + val originalLocation = getPlayer()?.location ?: error("Player is null!") + + return TeleportRunnable(this, location, originalLocation, delay) + } + } +} + diff --git a/src/main/resources/messages/english/messages.yml b/src/main/resources/messages/english/messages.yml index 88d7567b..6b8025cb 100644 --- a/src/main/resources/messages/english/messages.yml +++ b/src/main/resources/messages/english/messages.yml @@ -67,14 +67,18 @@ Messages: ClearChat: Success: "The chat has been cleared by ." Spawn: + NoSpawnSet: "No spawn was set." + Teleporting: "Starting teleport, please stand still..." Success: "You have been teleported to spawn." SuccessOther: "You have teleported to spawn." - NoSpawnSet: "No spawn was set." + Moved: "Your teleport was cancelled, since you moved." SetSpawn: Success: "You have set spawn to your current location." Home: - Success: "You teleported to the home ." + Success: "You have been teleported to ." DoesNotExist: "The specified home does not exist." + Teleporting: "Starting teleport, please stand still..." + Moved: "Your teleport was cancelled, since you moved." DeleteHome: Success: "You deleted the home ." DoesNotExist: "The specified home does not exist." @@ -287,7 +291,9 @@ Messages: DoesNotExist: "Specified warp doesn't exist." Teleport: DoesNotExist: "Specified warp doesn't exist." - Success: "You teleported to ." + Teleporting: "Starting teleport, please stand still..." + Success: "You have been teleported to ." + Moved: "Your teleport was cancelled, since you moved." Kit: Create: KitAlreadyExists: "The kit already exists." diff --git a/src/main/resources/messages/german/messages.yml b/src/main/resources/messages/german/messages.yml index dfa56858..693206e0 100644 --- a/src/main/resources/messages/german/messages.yml +++ b/src/main/resources/messages/german/messages.yml @@ -67,14 +67,18 @@ Messages: ClearChat: Success: "Der Chat wurde von geleert." Spawn: + NoSpawnSet: "Kein Spawn wurde gesetzt." + Moved: "Deine Teleportation wurde abgebrochen, da du dich bewegt hast." Success: "Du wurdest zum Spawn teleportiert." SuccessOther: "Du hast zum Spawn teleportiert." - NoSpawnSet: "Kein Spawn wurde gesetzt." + StartingTeleporting: "Teleportation wird gestartet, bitte stehen bleiben..." SetSpawn: Success: "Du hast den Spawn auf deine aktuelle Position gesetzt." Home: - Success: "Du wurdest zum Zuhause teleportiert." DoesNotExist: "Das angegebene Zuhause existiert nicht." + Moved: "Deine Teleportation wurde abgebrochen, da du dich bewegt hast." + Success: "Du wurdest zu teleportiert." + StartingTeleporting: "Teleportation wird gestartet, bitte stehen bleiben..." DeleteHome: Success: "Du hast das Zuhause gelöscht." DoesNotExist: "Das angegebene Zuhause existiert nicht." @@ -287,7 +291,9 @@ Messages: DoesNotExist: "Der angegebene Warp existiert nicht." Teleport: DoesNotExist: "Der angegebene Warp existiert nicht." + Moved: "Deine Teleportation wurde abgebrochen, da du dich bewegt hast." Success: "Du wurdest zu teleportiert." + StartingTeleporting: "Teleportation wird gestartet, bitte stehen bleiben..." Kit: Create: KitAlreadyExists: "Das Kit existiert bereits." diff --git a/src/main/resources/messages/slovene/messages.yml b/src/main/resources/messages/slovene/messages.yml index 9577c48c..939f2d84 100644 --- a/src/main/resources/messages/slovene/messages.yml +++ b/src/main/resources/messages/slovene/messages.yml @@ -67,14 +67,18 @@ Messages: ClearChat: Success: "Klepet je počistil ." Spawn: + NoSpawnSet: "Spawn ni nastavljen." + Teleporting: "Teleportacija se zacenja. Stoj pri miru..." Success: "Bil si teleportiran na spawn." SuccessOther: "Teleportiral si na spawn." - NoSpawnSet: "Spawn ni nastavljen." + Moved: "Zaradi premika je bila teleportacija prekinjena." SetSpawn: Success: "Spawn si nastavil na svojo trenutno lokacijo." Home: - Success: "Teleportiral si se v dom ." DoesNotExist: "Navedeni dom ne obstaja." + Teleporting: "Teleportacija se zacenja. Stoj pri miru..." + Success: "Teleportacija k uspešna." + Moved: "Zaradi premika je bila teleportacija prekinjena." DeleteHome: Success: "Izbrisal si dom ." DoesNotExist: "Navedeni dom ne obstaja." @@ -287,7 +291,9 @@ Messages: WarpNotFound: "Navedeni warp ne obstaja." Teleport: WarpNotFound: "Navedeni warp ne obstaja." - Success: "Teleportiral si se na ." + Teleporting: "Teleportacija se zacenja. Stoj pri miru..." + Success: "Teleportacija k uspešna." + Moved: "Zaradi premika je bila teleportacija prekinjena." Kit: Create: KitAlreadyExists: "Komplet že obstaja." diff --git a/src/main/resources/permissions.yml b/src/main/resources/permissions.yml index 7126f14f..37351c9d 100644 --- a/src/main/resources/permissions.yml +++ b/src/main/resources/permissions.yml @@ -176,7 +176,10 @@ Permissions: Spawn: Use: Required: false - Value: "serversystem.command.spawn.use" + Value: "serversystem.command.spawn.teleport" + InstantTeleport: + Required: true + Value: "serversystem.command.warp.teleport.instant" Other: Required: true Value: "serversystem.command.spawn.other" @@ -186,7 +189,10 @@ Permissions: Home: Use: Required: false - Value: "serversystem.command.home.use" + Value: "serversystem.command.home.teleport" + InstantTeleport: + Required: true + Value: "serversystem.command.home.teleport.instant" Set: Required: false Value: "serversystem.command.home.set" @@ -374,6 +380,9 @@ Permissions: Teleport: Required: false Value: "serversystem.command.warp.teleport" + InstantTeleport: + Required: true + Value: "serversystem.command.warp.teleport.instant" Set: Required: true Value: "serversystem.admin.command.warp.set" From 20e6e9928386964311ad1a8d24f817180df4f603 Mon Sep 17 00:00:00 2001 From: Test-Account666 <36412486+Test-Account666@users.noreply.github.com> Date: Tue, 3 Feb 2026 17:32:24 +0100 Subject: [PATCH 2/3] fix(SignType): fix inconsistency with give sign --- .../me/testaccount666/serversystem/clickablesigns/SignType.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/me/testaccount666/serversystem/clickablesigns/SignType.kt b/src/main/kotlin/me/testaccount666/serversystem/clickablesigns/SignType.kt index 5309db90..588d43bc 100644 --- a/src/main/kotlin/me/testaccount666/serversystem/clickablesigns/SignType.kt +++ b/src/main/kotlin/me/testaccount666/serversystem/clickablesigns/SignType.kt @@ -12,7 +12,7 @@ import me.testaccount666.serversystem.clickablesigns.executables.weather.ActionW import me.testaccount666.serversystem.clickablesigns.executables.weather.ConfiguratorWeatherSign enum class SignType(private val _key: String, val signName: String, val clickAction: SignClickAction, val configurator: SignConfigurator) { - GIVE("Give", "F3FD1[Give]", ActionGiveSign(), ConfiguratorGiveSign()), + GIVE("Give", "F3FD1[GIVE]", ActionGiveSign(), ConfiguratorGiveSign()), KIT("Kit", "F3FD1[KIT]", ActionKitSign(), ConfiguratorKitSign()), WARP("Warp", "F3FD1[WARP]", ActionWarpSign(), ConfiguratorWarpSign()), TIME("Time", "F3FD1[TIME]", ActionTimeSign(), ConfiguratorTimeSign()), From bc6b50c36ea00fc17401d5070a478748e612eb57 Mon Sep 17 00:00:00 2001 From: Test-Account666 <36412486+Test-Account666@users.noreply.github.com> Date: Sun, 6 Sep 2026 17:36:44 +0200 Subject: [PATCH 3/3] Switch to Gradle, Reformat tons of stuff, Add new Extension functions --- .gitignore | 11 + .mvn/jvm.config | 2 - TODO | 8 - build.gradle.kts | 131 ++++++ gradle.properties | 6 + gradlew | 251 ++++++++++++ gradlew.bat | 94 +++++ pom.xml | 381 ------------------ settings.gradle.kts | 1 + .../migration/LegacyDataMigrator.kt | 60 +-- .../plugins/essentials/AbstractMigrator.kt | 4 +- .../plugins/essentials/HomeMigrator.kt | 4 +- .../plugins/essentials/MuteMigrator.kt | 17 +- .../plugins/essentials/WarpMigrator.kt | 4 +- .../serversystem/ServerSystem.kt | 41 +- .../clickablesigns/AbstractSignClickAction.kt | 14 +- .../AbstractSignConfigurator.kt | 28 +- .../clickablesigns/SignClickAction.kt | 4 +- .../clickablesigns/SignManager.kt | 6 +- .../clickablesigns/cost/CostHandler.kt | 65 ++- .../executables/give/ActionGiveSign.kt | 20 +- .../executables/give/ConfiguratorGiveSign.kt | 36 +- .../executables/kit/ActionKitSign.kt | 41 +- .../executables/kit/ConfiguratorKitSign.kt | 29 +- .../executables/time/ActionTimeSign.kt | 29 +- .../executables/time/ConfiguratorTimeSign.kt | 28 +- .../executables/warp/ActionWarpSign.kt | 27 +- .../executables/warp/ConfiguratorWarpSign.kt | 24 +- .../executables/weather/ActionWeatherSign.kt | 35 +- .../weather/ConfiguratorWeatherSign.kt | 27 +- .../listener/ListenerSignCreation.kt | 22 +- .../listener/ListenerSignDestroy.kt | 8 +- .../listener/ListenerSignUse.kt | 13 +- .../clickablesigns/util/SignUtils.kt | 8 +- .../commands/ServerSystemCommand.kt | 12 +- .../AbstractServerSystemCommand.kt | 42 +- .../commands/executables/back/CommandBack.kt | 41 +- .../commands/executables/back/ListenerBack.kt | 26 +- .../executables/balance/CommandBalance.kt | 26 +- .../executables/broadcast/CommandBroadcast.kt | 14 +- .../executables/clearchat/CommandClearChat.kt | 8 +- .../clearinventory/CommandClearInventory.kt | 14 +- .../commandspy/CommandCommandSpy.kt | 10 +- .../commandspy/ListenerCommandSpy.kt | 11 +- .../executables/disposal/CommandDisposal.kt | 15 +- .../executables/economy/CommandEconomy.kt | 68 ++-- .../offline/CommandOfflineEnderChest.kt | 11 +- .../enderchest/offline/EnderChestLoader.kt | 9 +- .../offline/ListenerOfflineEnderChest.kt | 15 +- .../offline/TabCompleterOfflineEnderChest.kt | 2 +- .../enderchest/online/CommandEnderChest.kt | 4 +- .../enderchest/online/ListenerEnderChest.kt | 12 +- .../commands/executables/fly/CommandFly.kt | 14 +- .../executables/gamemode/CommandGameMode.kt | 20 +- .../commands/executables/god/CommandGod.kt | 14 +- .../commands/executables/god/ListenerGod.kt | 12 +- .../commands/executables/hat/CommandHat.kt | 26 +- .../commands/executables/heal/CommandHeal.kt | 24 +- .../executables/ignore/CommandIgnore.kt | 16 +- .../executables/ignore/ListenerIgnore.kt | 5 +- .../offline/CommandOfflineInventorySee.kt | 17 +- .../inventorysee/offline/InventoryLoader.kt | 11 +- .../offline/ListenerOfflineInventorySee.kt | 2 +- .../online/CommandInventorySee.kt | 42 +- .../online/ListenerInventorySee.kt | 26 +- .../utils/AbstractInventorySeeListener.kt | 4 +- .../inventorysee/utils/InventorySeeUtils.kt | 44 +- .../commands/executables/ip/CommandIp.kt | 10 +- .../commands/executables/kit/CommandKit.kt | 53 ++- .../executables/kit/TabCompleterKit.kt | 2 +- .../commands/executables/kit/manager/Kit.kt | 11 +- .../executables/kit/manager/KitManager.kt | 20 +- .../executables/language/CommandLanguage.kt | 6 +- .../executables/lightning/CommandLightning.kt | 14 +- .../moderation/AbstractModerationCommand.kt | 33 +- .../executables/moderation/ModerationUtils.kt | 4 +- .../moderation/TabCompleterModeration.kt | 6 +- .../executables/moderation/ban/CommandBan.kt | 29 +- .../executables/moderation/ban/ListenerBan.kt | 8 +- .../moderation/kick/CommandKick.kt | 21 +- .../moderation/mute/CommandMute.kt | 11 +- .../moderation/mute/ListenerMute.kt | 20 +- .../offlineteleport/CommandOfflineTeleport.kt | 17 +- .../commands/executables/pay/CommandPay.kt | 23 +- .../commands/executables/ping/CommandPing.kt | 10 +- .../privatemessage/CommandPrivateMessage.kt | 57 ++- .../privatemessage/ListenerSocialSpy.kt | 17 +- .../executables/rename/CommandRename.kt | 29 +- .../executables/repair/CommandRepair.kt | 48 +-- .../commands/executables/seen/CommandSeen.kt | 15 +- .../serversystem/CommandServerSystem.kt | 53 +-- .../serversystem/TabCompleterServerSystem.kt | 4 +- .../commands/executables/sign/CommandSign.kt | 54 ++- .../executables/signcost/CommandSignCost.kt | 45 +-- .../executables/skull/CommandSkull.kt | 20 +- .../executables/skull/SkullCreator.kt | 22 +- .../executables/smelt/CommandSmelt.kt | 20 +- .../executables/spawn/CommandSpawn.kt | 66 ++- .../executables/spawn/ListenerSpawn.kt | 18 +- .../executables/speed/CommandSpeed.kt | 22 +- .../executables/stack/CommandStack.kt | 13 +- .../commands/executables/sudo/CommandSudo.kt | 27 +- .../executables/sudo/MessageInterceptor.kt | 5 +- .../executables/teamchat/CommandTeamChat.kt | 9 +- .../executables/teleport/CommandTeleport.kt | 322 +++++++-------- .../teleportask/CommandTeleportAsk.kt | 84 ++-- .../commands/executables/time/CommandTime.kt | 24 +- .../executables/unlimited/CommandUnlimited.kt | 24 +- .../unlimited/ListenerUnlimited.kt | 149 +++---- .../executables/vanish/CommandVanish.kt | 24 +- .../executables/vanish/ListenerVanish.kt | 32 +- .../executables/vanish/VanishPacket.kt | 36 +- .../waypoints/AbstractCommandWaypoint.kt | 74 ++-- .../waypoints/AbstractTabCompleterWaypoint.kt | 6 +- .../executables/waypoints/WaypointManager.kt | 28 +- .../home/admin/TabCompleterAdminHome.kt | 4 +- .../waypoints/home/user/CommandHome.kt | 4 +- .../executables/waypoints/warp/CommandWarp.kt | 5 +- .../waypoints/warp/TabCompleterWarp.kt | 2 +- .../executables/weather/CommandWeather.kt | 24 +- .../executables/workbench/MenuUtils.kt | 14 +- .../interfaces/ServerSystemCommandExecutor.kt | 2 +- .../interfaces/ServerSystemTabCompleter.kt | 6 +- .../commands/management/CommandManager.kt | 30 +- .../commands/management/CommandReplacer.kt | 33 +- .../management/CommandSendListener.kt | 12 +- .../wrappers/AbstractCommandWrapper.kt | 6 +- .../wrappers/CommandExecutorWrapper.kt | 12 +- .../commands/wrappers/TabCompleterWrapper.kt | 4 +- .../events/UserPrivateMessageEvent.kt | 21 +- .../extensions/CommandExtensions.kt | 3 + .../extensions/ConfigExtensions.kt | 22 + .../extensions/MessageExtensions.kt | 22 + .../extensions/NumberExtensions.kt | 10 + .../extensions/ServiceExtensions.kt | 6 + .../serversystem/extensions/UserExtensions.kt | 25 ++ .../ListenerAwayFromKeyboard.kt | 64 ++- .../executables/chat/ListenerColorChat.kt | 18 +- .../chat/prefixchat/ListenerPrefixChat.kt | 16 +- .../ListenerClientLanguageChecker.kt | 9 +- .../developerjoin/ListenerDeveloperJoin.kt | 19 +- .../joinquitnotifier/ListenerJoin.kt | 24 +- .../joinquitnotifier/ListenerQuit.kt | 25 +- .../ListenerMinecraftDiscordChat.kt | 20 +- .../operatorspoof/ListenerOperatorSpoof.kt | 59 +-- .../listener/management/ListenerManager.kt | 4 +- .../managers/PermissionManager.kt | 4 +- .../managers/PlaceholderManager.kt | 2 +- .../managers/config/ConfigReader.kt | 3 + .../managers/config/DefaultConfigReader.kt | 23 +- .../database/AbstractDatabaseManager.kt | 2 +- .../database/AbstractSqlDatabaseManager.kt | 8 +- .../managers/database/HikariConfigUtil.kt | 4 +- .../AbstractSqlEconomyDatabaseManager.kt | 2 +- .../economy/MySqlEconomyDatabaseManager.kt | 2 +- .../AbstractSqlModerationDatabaseManager.kt | 2 +- .../moderation/ModerationDatabaseManager.kt | 8 +- .../MySqlModerationDatabaseManager.kt | 6 +- .../SqliteModerationDatabaseManager.kt | 4 +- .../managers/messages/MessageManager.kt | 34 +- .../moderation/AbstractModeration.kt | 4 +- .../moderation/AbstractModerationManager.kt | 4 +- .../serversystem/moderation/BanModeration.kt | 1 + .../serversystem/moderation/MuteModeration.kt | 1 + .../moderation/ban/AbstractSqlBanManager.kt | 14 +- .../moderation/mute/AbstractSqlMuteManager.kt | 16 +- .../executables/BalancePlaceholder.kt | 12 +- .../executables/BaltopPlaceholder.kt | 7 +- .../executables/OnlinePlayersPlaceholder.kt | 4 +- .../PlaceholderExpansionWrapper.kt | 13 +- .../updates/AbstractUpdateChecker.kt | 21 +- .../serversystem/updates/UpdateManager.kt | 19 +- .../serversystem/userdata/CachedUser.kt | 12 +- .../serversystem/userdata/ConsoleUser.kt | 1 - .../serversystem/userdata/OfflineUser.kt | 29 +- .../serversystem/userdata/User.kt | 10 +- .../serversystem/userdata/UserManager.kt | 13 +- .../userdata/listener/UserJoinListener.kt | 18 +- .../userdata/listener/UserQuitListener.kt | 8 +- .../userdata/money/AbstractSqlBankAccount.kt | 19 +- .../userdata/money/ConsoleBankAccount.kt | 5 +- .../userdata/money/EconomyProvider.kt | 5 +- .../money/vault/VaultEconomyProvider.kt | 25 +- .../userdata/persistence/EnumFieldHandler.kt | 2 +- .../persistence/KitMapFieldHandler.kt | 17 +- .../persistence/LocationFieldHandler.kt | 26 +- .../persistence/PersistenceManager.kt | 12 +- .../persistence/PrimitiveFieldHandler.kt | 2 +- .../userdata/persistence/SaveableField.kt | 2 +- .../persistence/UuidSetFieldHandler.kt | 4 +- .../persistence/VanishDataFieldHandler.kt | 17 +- .../userdata/teleport/TeleportRunnable.kt | 89 ++-- .../userdata/vanish/VanishData.kt | 2 +- .../serversystem/utils/ChatColor.kt | 153 ------- .../serversystem/utils/ComponentColor.kt | 313 -------------- .../serversystem/utils/ConstructorAccessor.kt | 2 +- .../serversystem/utils/DurationParser.kt | 38 +- .../serversystem/utils/FieldAccessor.kt | 2 +- .../serversystem/utils/FileUtils.kt | 4 +- .../serversystem/utils/ItemStackExtensions.kt | 9 - .../serversystem/utils/MessageBuilder.kt | 48 +-- .../serversystem/utils/MethodAccessor.kt | 16 +- .../serversystem/utils/ServiceExtensions.kt | 9 - .../serversystem/utils/Version.kt | 4 +- .../serversystem/utils/tuples/BiTuple.kt | 3 - .../serversystem/utils/tuples/Tuple.kt | 3 - src/main/resources/plugin.yml | 6 +- src/main/resources/replacedCommands.yml | 2 +- src/main/resources/templates/VersionInfo.kt | 2 +- .../utils/BiDirectionalHashMapTest.kt | 179 ++++++++ .../utils/ConstructorAccessorTest.kt | 74 ++++ .../serversystem/utils/DurationParserTest.kt | 116 ++++++ .../serversystem/utils/FieldAccessorTest.kt | 122 ++++++ .../serversystem/utils/FileUtilsTest.kt | 137 +++++++ .../serversystem/utils/MethodAccessorTest.kt | 122 ++++++ .../serversystem/utils/VersionTest.kt | 106 +++++ 216 files changed, 3249 insertions(+), 3025 deletions(-) delete mode 100644 .mvn/jvm.config delete mode 100644 TODO create mode 100644 build.gradle.kts create mode 100644 gradle.properties create mode 100755 gradlew create mode 100644 gradlew.bat delete mode 100644 pom.xml create mode 100644 settings.gradle.kts create mode 100644 src/main/kotlin/me/testaccount666/serversystem/extensions/CommandExtensions.kt create mode 100644 src/main/kotlin/me/testaccount666/serversystem/extensions/ConfigExtensions.kt create mode 100644 src/main/kotlin/me/testaccount666/serversystem/extensions/MessageExtensions.kt create mode 100644 src/main/kotlin/me/testaccount666/serversystem/extensions/NumberExtensions.kt create mode 100644 src/main/kotlin/me/testaccount666/serversystem/extensions/ServiceExtensions.kt create mode 100644 src/main/kotlin/me/testaccount666/serversystem/extensions/UserExtensions.kt delete mode 100644 src/main/kotlin/me/testaccount666/serversystem/utils/ChatColor.kt delete mode 100644 src/main/kotlin/me/testaccount666/serversystem/utils/ComponentColor.kt delete mode 100644 src/main/kotlin/me/testaccount666/serversystem/utils/ItemStackExtensions.kt delete mode 100644 src/main/kotlin/me/testaccount666/serversystem/utils/ServiceExtensions.kt delete mode 100644 src/main/kotlin/me/testaccount666/serversystem/utils/tuples/BiTuple.kt delete mode 100644 src/main/kotlin/me/testaccount666/serversystem/utils/tuples/Tuple.kt create mode 100644 src/test/kotlin/me/testaccount666/serversystem/utils/BiDirectionalHashMapTest.kt create mode 100644 src/test/kotlin/me/testaccount666/serversystem/utils/ConstructorAccessorTest.kt create mode 100644 src/test/kotlin/me/testaccount666/serversystem/utils/DurationParserTest.kt create mode 100644 src/test/kotlin/me/testaccount666/serversystem/utils/FieldAccessorTest.kt create mode 100644 src/test/kotlin/me/testaccount666/serversystem/utils/FileUtilsTest.kt create mode 100644 src/test/kotlin/me/testaccount666/serversystem/utils/MethodAccessorTest.kt create mode 100644 src/test/kotlin/me/testaccount666/serversystem/utils/VersionTest.kt diff --git a/.gitignore b/.gitignore index 94fdbf97..b29966b3 100755 --- a/.gitignore +++ b/.gitignore @@ -84,6 +84,7 @@ ehthumbs_vista.db # Dump file *.stackdump +.j* # Folder config file [Dd]esktop.ini @@ -102,6 +103,7 @@ $RECYCLE.BIN/ *.lnk target/ +target pom.xml.tag pom.xml.releaseBackup @@ -124,3 +126,12 @@ qodana.yaml /Changes /Changes.md /SpigotMC.bbcode + +# Gradle +.gradle/** +build/** +gradle/** + +# Markdown files +*.md +!README.md diff --git a/.mvn/jvm.config b/.mvn/jvm.config deleted file mode 100644 index 97c58ccb..00000000 --- a/.mvn/jvm.config +++ /dev/null @@ -1,2 +0,0 @@ ---add-opens=java.base/java.lang=ALL-UNNAMED ---add-opens=java.base/java.io=ALL-UNNAMED \ No newline at end of file diff --git a/TODO b/TODO deleted file mode 100644 index 95890e6f..00000000 --- a/TODO +++ /dev/null @@ -1,8 +0,0 @@ -- /status (Health, GameMode, ...) - -- Command Swapper -- Command Deactivator - -- Essentials to ServerSystem Migrator -- ServerSystem to Essentials Migrator -^ Also CMI? Needs more research \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 00000000..14538b3b --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,131 @@ +import io.papermc.paperweight.userdev.ReobfArtifactConfiguration +import io.papermc.paperweight.util.path +import org.apache.tools.ant.filters.ReplaceTokens +import java.time.LocalDateTime +import java.time.format.DateTimeFormatter + +plugins { + alias(libs.plugins.kotlin.jvm) + alias(libs.plugins.kotlin.spring) + alias(libs.plugins.plugins.maven.shade) + alias(libs.plugins.paperweight.userdev) + alias(libs.plugins.git.version) +} + +group = "me.testaccount666" +val cleanVersion = "4.1.0" + +@Suppress("UNCHECKED_CAST") +val gitVersion = extra["gitVersion"] as groovy.lang.Closure +version = "${cleanVersion}-" + gitVersion().dropWhile { it != '-' }.drop(1).replace("dirty", getFormattedDate()) + +fun getFormattedDate(): String { + return DateTimeFormatter.ofPattern("yyyy-MM-dd.HH-mm").format(LocalDateTime.now()) +} + +java { + toolchain { + languageVersion = JavaLanguageVersion.of(libs.versions.java.get()) + } +} + +val generateVersionInfo = tasks.register("generateVersionInfo") { + val template = file("src/main/resources/templates/VersionInfo.kt") + val outputDir = layout.buildDirectory.dir("generated/kotlin") + + inputs.file(template) + outputs.dir(outputDir) + + doLast { + val outputFile = outputDir.get().file("me/testaccount666/serversystem/utils/VersionInfo.kt").asFile + outputFile.parentFile.mkdirs() + template.copyTo(outputFile, true) + outputFile.writeText(outputFile.readText().replace("@CLEAN_VERSION@", cleanVersion)) + } +} + +kotlin { + compilerOptions { freeCompilerArgs.addAll("-Xjsr305=strict", "-jvm-target=21") } + + sourceSets.main { kotlin.srcDir(generateVersionInfo) } +} + +configurations { + compileOnly { + extendsFrom(configurations.annotationProcessor.get()) + } +} + +repositories { + mavenCentral() + maven("https://repo.essentialsx.net/releases") + maven("https://repo.papermc.io/repository/maven-public") + maven("https://oss.sonatype.org/content/groups/public") + maven("https://repo.extendedclip.com/content/repositories/placeholderapi") + maven("https://jitpack.io") + maven("https://repo.codemc.io/repository/maven-public") + maven("https://gitlab.com/api/v4/projects/80077577/packages/maven") +} + +dependencies { + paperweightDevelopmentBundle(libs.paperdevbundle) + implementation(libs.paperktx) { + exclude(group = "org.jetbrains.kotlin", module = "kotlin-stdlib") + exclude(group = "org.jetbrains.kotlinx", module = "kotlinx-coroutines-core") + } + compileOnly(libs.kotlin.stdlib) + compileOnly(libs.kotlin.reflect) + compileOnly(libs.paperapi) + compileOnly(libs.clip.placeholderapi) + compileOnly(libs.milkbowl.vaultapi) + compileOnly(libs.essentialsx.essentialsx) { exclude("**", "**") } + compileOnly(libs.tr7zw.item.nbt.api.plugin) + compileOnly(libs.classgraph) + compileOnly(libs.bytebuddy.byte.buddy) + compileOnly(libs.zaxxer.hikaricp) + compileOnly(libs.h2) + compileOnly(libs.netty.all) + compileOnly(libs.mojang.authlib) + testImplementation(libs.junit.jupiter.api) + testImplementation(libs.junit.jupiter.engine) + testImplementation(libs.junit.jupiter.params) + testImplementation(libs.mockito.core) + testImplementation(libs.mockito.junit.jupiter) + testImplementation(kotlin("test")) +} + +paperweight { reobfArtifactConfiguration.set(ReobfArtifactConfiguration.MOJANG_PRODUCTION) } + +tasks.build { dependsOn(tasks.shadowJar) } + +tasks.shadowJar { + relocate("me.testaccount666.paperktx", "me.testaccount666.serversystem.libs.paperktx") + archiveFileName.set("ServerSystem.jar") + + val libsDirectory = layout.buildDirectory.path.resolve("libs") + + doFirst { + libsDirectory.toFile().listFiles().filter { it.name.endsWith(".jar") }.forEach(File::delete) + } + + doLast { + archiveFile.get().asFile.copyTo(libsDirectory.resolve("ServerSystem-${version}.jar").toFile(), true) + println(gitVersion()) + } +} + +tasks.processResources { + exclude("templates/**") + filter( + ReplaceTokens::class, + mapOf( + "tokens" to mapOf( + "PROJECT_VERSION" to project.version, + "CLEAN_VERSION" to cleanVersion, + "KOTLIN_VERSION" to libs.versions.kotlin.get() + ) + ) + ) +} + +tasks.withType(Test::useJUnitPlatform) diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 00000000..c9a5e6b3 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,6 @@ +# Generated by Maven-to-Gradle migration +org.gradle.daemon=true +org.gradle.parallel=true +org.gradle.caching=true +# Unsupported +org.gradle.configuration-cache=false diff --git a/gradlew b/gradlew new file mode 100755 index 00000000..ef07e016 --- /dev/null +++ b/gradlew @@ -0,0 +1,251 @@ +#!/bin/sh + +# +# Copyright © 2015 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH="\\\"\\\"" + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 00000000..db3a6ac2 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,94 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH= + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/pom.xml b/pom.xml deleted file mode 100644 index a48f48e8..00000000 --- a/pom.xml +++ /dev/null @@ -1,381 +0,0 @@ - - - 4.0.0 - - me.testaccount666 - ServerSystem - 4.1.0 - jar - - ServerSystem - - - 21 - 21 - 21 - 2.3.20-Beta1 - UTF-8 - ${project.version} - - ${git.commit.id.describe} - yyyy-MM-dd--HH-mm - - - - scm:git:${project.basedir} - scm:git:${project.basedir} - HEAD - - - - - - bytecode.space - https://repo.bytecode.space/repository/maven-public/ - - - - - clean package - - - maven-antrun-plugin - 3.2.0 - - - cleanup-jars - prepare-package - - run - - - - - - - - - - - copy-version - package - - - - - - - run - - - - copy-version-hash - package - - - - - - - run - - - - - - - io.github.git-commit-id - git-commit-id-maven-plugin - 9.0.2 - - - get-the-git-infos - - revision - - initialize - - - - true - ${project.basedir}/git.properties - - full - 8 - - -${build.timestamp} - 8 - true - !* - - - - - - - org.jetbrains.kotlin - kotlin-maven-plugin - ${kotlin.version} - - - compile - compile - - compile - - - - test-compile - test-compile - - test-compile - - - - - ${java.version} - - ${project.basedir}/src/main/kotlin - - true - - - - - ca.bkaw - paper-nms-maven-plugin - 1.4.10 - - - - org.apache.maven.plugins - maven-jar-plugin - 3.5.0 - - - - mojang - - - - - - - maven-resources-plugin - 3.4.0 - - - filter-version-info - generate-sources - - copy-resources - - - - ${project.build.directory}/generated-sources/versioninfo/me/testaccount666/serversystem/utils - - - - src/main/resources/templates - true - - VersionInfo.kt - - - - - - - - - - org.codehaus.mojo - build-helper-maven-plugin - 3.6.1 - - - add-source - generate-sources - - add-source - - - - ${project.build.directory}/generated-sources/versioninfo - - - - - - - - - - src/main/resources - true - - templates/** - - - - - - - - essentials-releases - https://repo.essentialsx.net/releases/ - - - papermc-repo - https://repo.papermc.io/repository/maven-public/ - - - sonatype - https://oss.sonatype.org/content/groups/public/ - - - placeholderapi - https://repo.extendedclip.com/content/repositories/placeholderapi/ - - - - jitpack - https://jitpack.io/ - - - - codemc-repo - https://repo.codemc.io/repository/maven-public/ - default - - - - - - org.jetbrains.kotlin - kotlin-stdlib - ${kotlin.version} - - - org.jetbrains.kotlin - kotlin-reflect - ${kotlin.version} - - - - io.papermc.paper - paper-api - 1.21.8-R0.1-SNAPSHOT - provided - - - ca.bkaw - paper-nms - 1.21.8-SNAPSHOT - provided - - - - me.clip - placeholderapi - 2.11.7 - provided - - - - com.github.MilkBowl - VaultAPI - 1.7.1 - provided - - - net.essentialsx - EssentialsX - 2.21.2 - provided - - - ** - ** - - - - - de.tr7zw - item-nbt-api-plugin - 2.15.5 - provided - - - io.github.classgraph - classgraph - 4.8.184 - - - - net.bytebuddy - byte-buddy - 1.17.7 - provided - - - com.zaxxer - HikariCP - 7.0.2 - provided - - - com.h2database - h2 - 2.4.240 - provided - - - - org.junit.jupiter - junit-jupiter-api - 6.1.0-M1 - test - - - org.junit.jupiter - junit-jupiter-engine - 6.1.0-M1 - test - - - org.junit.jupiter - junit-jupiter-params - 6.1.0-M1 - test - - - org.mockito - mockito-core - 5.21.0 - test - - - org.mockito - mockito-junit-jupiter - 5.21.0 - test - - - io.netty - netty-all - 4.1.130.Final - provided - - - com.mojang - authlib - 3.13.56 - provided - - - diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 00000000..3461d7d7 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1 @@ +rootProject.name = "ServerSystem" diff --git a/src/main/kotlin/me/testaccount666/migration/LegacyDataMigrator.kt b/src/main/kotlin/me/testaccount666/migration/LegacyDataMigrator.kt index 74b1753f..6e7f41e6 100644 --- a/src/main/kotlin/me/testaccount666/migration/LegacyDataMigrator.kt +++ b/src/main/kotlin/me/testaccount666/migration/LegacyDataMigrator.kt @@ -1,31 +1,25 @@ package me.testaccount666.migration +import me.testaccount666.paperktx.extensions.isAir +import me.testaccount666.paperktx.extensions.location import me.testaccount666.serversystem.ServerSystem.Companion.instance import me.testaccount666.serversystem.ServerSystem.Companion.log import me.testaccount666.serversystem.commands.executables.kit.manager.Kit import me.testaccount666.serversystem.commands.executables.kit.manager.KitManager import me.testaccount666.serversystem.commands.executables.waypoints.warp.manager.Warp import me.testaccount666.serversystem.commands.executables.waypoints.warp.manager.WarpManager -import me.testaccount666.serversystem.moderation.AbstractModeration -import me.testaccount666.serversystem.moderation.BanModeration -import me.testaccount666.serversystem.moderation.MuteModeration -import me.testaccount666.serversystem.userdata.ConsoleUser -import me.testaccount666.serversystem.userdata.OfflineUser -import me.testaccount666.serversystem.userdata.UserManager +import me.testaccount666.serversystem.extensions.getService +import me.testaccount666.serversystem.moderation.* +import me.testaccount666.serversystem.userdata.* import me.testaccount666.serversystem.userdata.home.Home -import me.testaccount666.serversystem.utils.ItemStackExtensions.Companion.isAir import me.testaccount666.serversystem.utils.Version import org.bukkit.Bukkit -import org.bukkit.Location import org.bukkit.Material import org.bukkit.configuration.file.FileConfiguration import org.bukkit.configuration.file.YamlConfiguration import org.bukkit.inventory.ItemStack import java.io.File -import java.sql.Connection -import java.sql.DriverManager -import java.sql.ResultSet -import java.sql.SQLException +import java.sql.* import java.util.* import java.util.logging.Level @@ -42,8 +36,7 @@ class LegacyDataMigrator { * @return Optional containing the offline user if found, empty otherwise */ private fun getOfflineUser(uuid: UUID): OfflineUser? { - val userManager = instance.registry.getService() - val user = userManager.getUserOrNull(uuid) ?: run { + val user = getService().getUserOrNull(uuid) ?: run { log.warning("Could not find user with UUID: ${uuid}") return null } @@ -199,7 +192,7 @@ class LegacyDataMigrator { var migratedCount = 0 val defaultItem = ItemStack(Material.AIR) - val kitManager = instance.registry.getService() + val kitManager = getService() for (kitName in kitNames) try { val offhandItem = kitsSection.getItemStack("${kitName}.40", defaultItem) @@ -252,7 +245,7 @@ class LegacyDataMigrator { return } - val warpManager = instance.registry.getService() + val warpManager = getService() val warpSection = legacyWarpsConfig.getConfigurationSection("Warps") val warpNames = warpSection?.getKeys(false) ?: HashSet() var migratedCount = 0 @@ -263,8 +256,8 @@ class LegacyDataMigrator { val x = legacyWarpsConfig.getDouble("${prefix}.X") val y = legacyWarpsConfig.getDouble("${prefix}.Y") val z = legacyWarpsConfig.getDouble("${prefix}.Z") - val yaw = legacyWarpsConfig.getDouble("${prefix}.Yaw").toFloat() - val pitch = legacyWarpsConfig.getDouble("${prefix}.Pitch").toFloat() + val yaw = legacyWarpsConfig.getDouble("${prefix}.Yaw") + val pitch = legacyWarpsConfig.getDouble("${prefix}.Pitch") val worldName = legacyWarpsConfig.getString("${prefix}.World") ?: "" val world = Bukkit.getWorld(worldName) ?: run { @@ -272,7 +265,7 @@ class LegacyDataMigrator { continue } - val location = Location(world, x, y, z, yaw, pitch) + val location = location(x, y, z, world, yaw, pitch) val warp = Warp.of(warpName, location) ?: run { log(Level.WARNING, "Warp name '${warpName}' contains invalid characters, skipping") continue @@ -354,15 +347,15 @@ class LegacyDataMigrator { val legacyConfigFile = File(_legacyDataDirectory, "config.yml") val legacyConfig = YamlConfiguration.loadConfiguration(legacyConfigFile) - if (legacyConfig.getBoolean("mysql.use", false)) { + if (legacyConfig.getBoolean("mysql.use")) { log(Level.INFO, "Legacy MySQL configuration detected. Migrating...") migrateMySqlConfig(legacyConfig) } // Sqlite is handled below - if (legacyConfig.getBoolean("sqlite.use", false)) log(Level.INFO, "Legacy SQLite configuration detected. Migrating...") + if (legacyConfig.getBoolean("sqlite.use")) log(Level.INFO, "Legacy SQLite configuration detected. Migrating...") - if (legacyConfig.getBoolean("h2.use", false)) { + if (legacyConfig.getBoolean("h2.use")) { log(Level.INFO, "Legacy H2 configuration detected. Migrating...") migrateH2Config(legacyConfig) } @@ -406,10 +399,13 @@ class LegacyDataMigrator { // Use current time as issue time since we don't have that in the legacy database val issueTime = System.currentTimeMillis() - val banModeration = BanModeration.builder() - .issueTime(issueTime).expireTime(unbanTime) - .reason(reason).senderUuid(senderUuid) - .targetUuid(bannedUuid).build() + val banModeration = BanModeration.builder { + issueTime(issueTime) + expireTime(unbanTime) + reason(reason) + senderUuid(senderUuid) + targetUuid(bannedUuid) + } applyModeration(bannedUuid, banModeration) } } @@ -459,10 +455,14 @@ class LegacyDataMigrator { // Use current time as issue time since we don't have that in the legacy database val issueTime = System.currentTimeMillis() - val muteModeration = MuteModeration.builder() - .issueTime(issueTime).expireTime(unbanTime) - .reason(reason).senderUuid(senderUuid) - .targetUuid(bannedUuid).isShadowMute(isShadowMute).build() + val muteModeration = MuteModeration.builder { + issueTime(issueTime) + expireTime(unbanTime) + reason(reason) + senderUuid(senderUuid) + targetUuid(bannedUuid) + isShadowMute(isShadowMute) + } applyModeration(bannedUuid, muteModeration) } } diff --git a/src/main/kotlin/me/testaccount666/migration/plugins/essentials/AbstractMigrator.kt b/src/main/kotlin/me/testaccount666/migration/plugins/essentials/AbstractMigrator.kt index 44a59194..fbde7c4e 100644 --- a/src/main/kotlin/me/testaccount666/migration/plugins/essentials/AbstractMigrator.kt +++ b/src/main/kotlin/me/testaccount666/migration/plugins/essentials/AbstractMigrator.kt @@ -1,14 +1,14 @@ package me.testaccount666.migration.plugins.essentials import com.earth2me.essentials.Essentials -import me.testaccount666.serversystem.ServerSystem.Companion.instance +import me.testaccount666.serversystem.extensions.getService import me.testaccount666.serversystem.userdata.UserManager import org.bukkit.Bukkit import java.nio.file.Path import java.util.* abstract class AbstractMigrator { - val userManager by lazy { instance.registry.getService() } + val userManager by lazy { getService() } val essentials by lazy { Essentials.getPlugin(Essentials::class.java) } protected fun offlinePlayers() = Bukkit.getOfflinePlayers() diff --git a/src/main/kotlin/me/testaccount666/migration/plugins/essentials/HomeMigrator.kt b/src/main/kotlin/me/testaccount666/migration/plugins/essentials/HomeMigrator.kt index 6165bb29..66298226 100644 --- a/src/main/kotlin/me/testaccount666/migration/plugins/essentials/HomeMigrator.kt +++ b/src/main/kotlin/me/testaccount666/migration/plugins/essentials/HomeMigrator.kt @@ -27,7 +27,7 @@ class HomeMigrator : AbstractMigrator() { user.homeManager.addPoint(homeName, location) return@runCatching true }.onFailure { - log.log(Level.WARNING, "Couldn't migrate home '${homeName}' for user '${user.uuid}' (${user.getNameSafe()})", it) + log.log(Level.WARNING, "Couldn't migrate home '${homeName}' for user '${user.uuid}' (${user.nameSafe})", it) }.getOrDefault(false) } @@ -62,7 +62,7 @@ class HomeMigrator : AbstractMigrator() { essentialsUser.setHome(homeName, location) return@runCatching true }.onFailure { - log.log(Level.WARNING, "Couldn't migrate home '${home.displayName}' for user '${user.uuid}' (${user.getNameSafe()})", it) + log.log(Level.WARNING, "Couldn't migrate home '${home.displayName}' for user '${user.uuid}' (${user.nameSafe})", it) }.getOrDefault(false) } diff --git a/src/main/kotlin/me/testaccount666/migration/plugins/essentials/MuteMigrator.kt b/src/main/kotlin/me/testaccount666/migration/plugins/essentials/MuteMigrator.kt index bb5c8401..0d47433c 100644 --- a/src/main/kotlin/me/testaccount666/migration/plugins/essentials/MuteMigrator.kt +++ b/src/main/kotlin/me/testaccount666/migration/plugins/essentials/MuteMigrator.kt @@ -1,9 +1,9 @@ package me.testaccount666.migration.plugins.essentials import me.testaccount666.serversystem.ServerSystem.Companion.log +import me.testaccount666.serversystem.extensions.commandMsg import me.testaccount666.serversystem.moderation.MuteModeration import me.testaccount666.serversystem.userdata.UserManager.Companion.consoleUser -import me.testaccount666.serversystem.utils.MessageBuilder.Companion.command import java.util.logging.Level class MuteMigrator : AbstractMigrator() { @@ -20,12 +20,12 @@ class MuteMigrator : AbstractMigrator() { if (!essentialsUser.isMuted) return@count false - val defaultReason = command("Moderation.DefaultReason", consoleUser) { + val defaultReason = consoleUser.commandMsg("Moderation.DefaultReason") { target(essentialsUser.name) prefix(false) send(false) blankError(true) - }.build() + } if (defaultReason.isEmpty()) { log.severe("(MuteMigrator) Default reason is empty! This should not happen!") @@ -42,9 +42,14 @@ class MuteMigrator : AbstractMigrator() { val targetUUID = user.uuid muteManager.addModeration( - MuteModeration.builder().isShadowMute(false) - .targetUuid(targetUUID).issueTime(issueTime).expireTime(expireTime) - .senderUuid(senderUUID).reason(reason).build() + MuteModeration.builder { + isShadowMute(false) + targetUuid(targetUUID) + issueTime(issueTime) + expireTime(expireTime) + senderUuid(senderUUID) + reason(reason) + } ) user.save() diff --git a/src/main/kotlin/me/testaccount666/migration/plugins/essentials/WarpMigrator.kt b/src/main/kotlin/me/testaccount666/migration/plugins/essentials/WarpMigrator.kt index 427a8874..96f6b4c3 100644 --- a/src/main/kotlin/me/testaccount666/migration/plugins/essentials/WarpMigrator.kt +++ b/src/main/kotlin/me/testaccount666/migration/plugins/essentials/WarpMigrator.kt @@ -1,12 +1,12 @@ package me.testaccount666.migration.plugins.essentials -import me.testaccount666.serversystem.ServerSystem.Companion.instance import me.testaccount666.serversystem.ServerSystem.Companion.log import me.testaccount666.serversystem.commands.executables.waypoints.warp.manager.WarpManager +import me.testaccount666.serversystem.extensions.getService import java.util.logging.Level class WarpMigrator : AbstractMigrator() { - val warpManager by lazy { instance.registry.getService() } + val warpManager by lazy { getService() } override fun migrateFrom(): Int { val essentials = essentials diff --git a/src/main/kotlin/me/testaccount666/serversystem/ServerSystem.kt b/src/main/kotlin/me/testaccount666/serversystem/ServerSystem.kt index 031370d1..028b4827 100644 --- a/src/main/kotlin/me/testaccount666/serversystem/ServerSystem.kt +++ b/src/main/kotlin/me/testaccount666/serversystem/ServerSystem.kt @@ -2,6 +2,8 @@ package me.testaccount666.serversystem import me.testaccount666.migration.LegacyDataMigrator import me.testaccount666.migration.plugins.MigratorRegistry +import me.testaccount666.paperktx.PaperKTX +import me.testaccount666.paperktx.scheduler.skedule.okkero.schedule import me.testaccount666.serversystem.clickablesigns.SignManager import me.testaccount666.serversystem.commands.executables.kit.manager.KitManager import me.testaccount666.serversystem.commands.executables.waypoints.warp.manager.WarpManager @@ -9,12 +11,8 @@ import me.testaccount666.serversystem.commands.management.CommandManager import me.testaccount666.serversystem.commands.management.CommandReplacer import me.testaccount666.serversystem.listener.management.ListenerManager import me.testaccount666.serversystem.managers.config.ConfigurationManager -import me.testaccount666.serversystem.managers.database.economy.EconomyDatabaseManager -import me.testaccount666.serversystem.managers.database.economy.MySqlEconomyDatabaseManager -import me.testaccount666.serversystem.managers.database.economy.SqliteEconomyDatabaseManager -import me.testaccount666.serversystem.managers.database.moderation.ModerationDatabaseManager -import me.testaccount666.serversystem.managers.database.moderation.MySqlModerationDatabaseManager -import me.testaccount666.serversystem.managers.database.moderation.SqliteModerationDatabaseManager +import me.testaccount666.serversystem.managers.database.economy.* +import me.testaccount666.serversystem.managers.database.moderation.* import me.testaccount666.serversystem.placeholderapi.PlaceholderApiSupport import me.testaccount666.serversystem.placeholderapi.PlaceholderManager import me.testaccount666.serversystem.updates.UpdateManager @@ -48,6 +46,7 @@ class ServerSystem : JavaPlugin() { } override fun onEnable() { + PaperKTX.plugin = this val migrator = LegacyDataMigrator() if (migrator.isLegacyDataPresent) { log.log(Level.INFO, "Legacy data detected. Attempting to migrate...") @@ -56,7 +55,7 @@ class ServerSystem : JavaPlugin() { val previousVersionFile = File(dataFolder, "previousVersion.yml") val previousVersionConfig = YamlConfiguration.loadConfiguration(previousVersionFile) - previousVersionConfig.set("previousVersion", CURRENT_VERSION.toString()) + previousVersionConfig["previousVersion"] = CURRENT_VERSION.toString() try { previousVersionConfig.save(previousVersionFile) } catch (exception: IOException) { @@ -74,14 +73,18 @@ class ServerSystem : JavaPlugin() { val configManager = registry.getService() registry.registerService(UpdateManager(this, configManager)).start() - Bukkit.getScheduler().runTaskLater(this, Runnable { migrator.migrateLegacyData() }, 1L) + schedule { + waitFor(1) + migrator.migrateLegacyData() + } - Bukkit.getScheduler().runTaskLater(this, Runnable { + schedule { + waitFor(2) registry.getServiceOrNull()?.registerCommands() registry.getServiceOrNull()?.registerListeners() registry.getServiceOrNull()?.registerPlaceholders() registry.getServiceOrNull()?.replaceCommands() - }, 2L) + } } private fun initialize() { @@ -134,27 +137,27 @@ class ServerSystem : JavaPlugin() { if (migratorCount > 0) log.info("Not hooking into Vault since we found data migrators!") - Bukkit.getScheduler().runTask(this, Runnable { + schedule { val warpFile = Path.of(dataFolder.path, "data", "warps.yml").toFile() val warpConfig = YamlConfiguration.loadConfiguration(warpFile) registry.registerService(WarpManager(warpConfig, warpFile)) registry.registerService(SignManager()).loadSignTypes() - }) + } } - override fun onDisable() { - registry.getServiceOrNull()?.run(::saveAllUsers) + override fun onDisable() = with(registry) { + getServiceOrNull()?.run(::saveAllUsers) - registry.getServiceOrNull()?.run(CommandManager::unregisterCommands) - registry.getServiceOrNull()?.run(ListenerManager::unregisterListeners) + getServiceOrNull()?.run(CommandManager::unregisterCommands) + getServiceOrNull()?.run(ListenerManager::unregisterListeners) PlaceholderApiSupport.unregisterPlaceholders() - registry.getServiceOrNull()?.shutdown() - registry.getServiceOrNull()?.shutdown() + getServiceOrNull()?.shutdown() + getServiceOrNull()?.shutdown() - registry.clearServices() + clearServices() } private fun saveAllUsers(userManager: UserManager) = userManager.cachedUsers.forEach { it.offlineUser.save() } diff --git a/src/main/kotlin/me/testaccount666/serversystem/clickablesigns/AbstractSignClickAction.kt b/src/main/kotlin/me/testaccount666/serversystem/clickablesigns/AbstractSignClickAction.kt index c0eb38cf..83c674f6 100644 --- a/src/main/kotlin/me/testaccount666/serversystem/clickablesigns/AbstractSignClickAction.kt +++ b/src/main/kotlin/me/testaccount666/serversystem/clickablesigns/AbstractSignClickAction.kt @@ -2,10 +2,10 @@ package me.testaccount666.serversystem.clickablesigns import me.testaccount666.serversystem.clickablesigns.cost.CostHandler import me.testaccount666.serversystem.clickablesigns.util.SignUtils +import me.testaccount666.serversystem.extensions.generalMsg import me.testaccount666.serversystem.managers.PermissionManager.getPermission import me.testaccount666.serversystem.managers.PermissionManager.hasPermission import me.testaccount666.serversystem.userdata.User -import me.testaccount666.serversystem.utils.MessageBuilder.Companion.general import org.bukkit.block.Sign import org.bukkit.configuration.file.FileConfiguration @@ -23,25 +23,25 @@ abstract class AbstractSignClickAction : SignClickAction { /** * Executes the sign-specific action. * This method is called after permission and cost checks have passed. - * + * * @param user The user who clicked the sign * @param sign The sign that was clicked * @param config The sign configuration * @return true if the action was successful, false otherwise */ - protected abstract fun executeAction(user: User, sign: Sign, config: FileConfiguration): Boolean + protected abstract fun executeAction(user: User, sign: Sign, config: FileConfiguration, onSuccess: () -> Unit): Boolean override fun execute(user: User, sign: Sign) { if (!hasPermission(user, usePermissionNode, false)) { - general("NoPermission", user) { + user.generalMsg("NoPermission") { postModifier { it.replace("", getPermission(usePermissionNode)!!) } - }.build() + } return } val config = SignUtils.loadSignConfig(sign.location) - if (!CostHandler.deductCost(user, config)) return - if (!executeAction(user, sign, config)) CostHandler.refundCost(user, config) + if (!CostHandler.canAfford(user, config)) return + executeAction(user, sign, config) { CostHandler.deductCost(user, config) } } } \ No newline at end of file diff --git a/src/main/kotlin/me/testaccount666/serversystem/clickablesigns/AbstractSignConfigurator.kt b/src/main/kotlin/me/testaccount666/serversystem/clickablesigns/AbstractSignConfigurator.kt index d3826340..401f90b1 100644 --- a/src/main/kotlin/me/testaccount666/serversystem/clickablesigns/AbstractSignConfigurator.kt +++ b/src/main/kotlin/me/testaccount666/serversystem/clickablesigns/AbstractSignConfigurator.kt @@ -1,14 +1,12 @@ package me.testaccount666.serversystem.clickablesigns -import me.testaccount666.serversystem.ServerSystem.Companion.instance import me.testaccount666.serversystem.ServerSystem.Companion.log import me.testaccount666.serversystem.clickablesigns.cost.CostType import me.testaccount666.serversystem.clickablesigns.util.SignUtils +import me.testaccount666.serversystem.extensions.* import me.testaccount666.serversystem.managers.PermissionManager.getPermission import me.testaccount666.serversystem.managers.PermissionManager.hasPermission import me.testaccount666.serversystem.userdata.User -import me.testaccount666.serversystem.utils.MessageBuilder.Companion.general -import me.testaccount666.serversystem.utils.MessageBuilder.Companion.sign import org.bukkit.block.Sign import org.bukkit.configuration.file.FileConfiguration import org.bukkit.configuration.file.YamlConfiguration @@ -22,14 +20,14 @@ import java.util.logging.Level abstract class AbstractSignConfigurator : SignConfigurator { /** * The permission node for the permission required to create this sign. - * + * * @return The permission node */ protected abstract val createPermissionNode: String /** * The sign type for this configurator. - * + * * @return The sign type */ protected abstract val signType: SignType @@ -37,7 +35,7 @@ abstract class AbstractSignConfigurator : SignConfigurator { /** * Validates the sign configuration. * This method is called before saving the configuration. - * + * * @param user The user who is configuring the sign * @param sign The sign being configured * @param config The sign configuration @@ -48,7 +46,7 @@ abstract class AbstractSignConfigurator : SignConfigurator { /** * Adds sign-specific configuration. * This method is called after basic configuration has been set. - * + * * @param user The user who is configuring the sign * @param sign The sign being configured * @param config The sign configuration @@ -57,26 +55,26 @@ abstract class AbstractSignConfigurator : SignConfigurator { /** * Gets the success message key for when the sign is successfully created. - * + * * @return The message key */ protected abstract val successMessageKey: String override fun execute(user: User, sign: Sign) { if (!hasPermission(user, createPermissionNode, false)) { - general("NoPermission", user) { + user.generalMsg("NoPermission") { postModifier { it.replace("", getPermission(createPermissionNode)!!) } - }.build() + } return } val signFile = SignUtils.getSignFile(sign.location) val config = YamlConfiguration.loadConfiguration(signFile) - config.set("Key", signType.name) + config["Key"] = signType.name - config.set("Cost.Type", CostType.NONE.name) - config.set("Cost.Amount", 0) + config["Cost.Type"] = CostType.NONE.name + config["Cost.Amount"] = 0 if (!validateConfiguration(user, sign, config)) return addSignSpecificConfiguration(user, sign, config) @@ -89,7 +87,7 @@ abstract class AbstractSignConfigurator : SignConfigurator { return } - instance.registry.getService().addSignType(sign.location, signType) - sign(successMessageKey, user).build() + getService().addSignType(sign.location, signType) + user.signMsg(successMessageKey) } } \ No newline at end of file diff --git a/src/main/kotlin/me/testaccount666/serversystem/clickablesigns/SignClickAction.kt b/src/main/kotlin/me/testaccount666/serversystem/clickablesigns/SignClickAction.kt index aabb5321..27dab678 100644 --- a/src/main/kotlin/me/testaccount666/serversystem/clickablesigns/SignClickAction.kt +++ b/src/main/kotlin/me/testaccount666/serversystem/clickablesigns/SignClickAction.kt @@ -8,14 +8,14 @@ interface SignClickAction { /** * The permission node for the permission required to use this sign. - * + * * @return The permission node */ val usePermissionNode: String /** * The permission node for the permission required to break this+ sign. - * + * * @return The permission node */ val destroyPermissionNode: String diff --git a/src/main/kotlin/me/testaccount666/serversystem/clickablesigns/SignManager.kt b/src/main/kotlin/me/testaccount666/serversystem/clickablesigns/SignManager.kt index dbc56423..70e4e0ee 100644 --- a/src/main/kotlin/me/testaccount666/serversystem/clickablesigns/SignManager.kt +++ b/src/main/kotlin/me/testaccount666/serversystem/clickablesigns/SignManager.kt @@ -1,5 +1,6 @@ package me.testaccount666.serversystem.clickablesigns +import me.testaccount666.paperktx.extensions.location import me.testaccount666.serversystem.ServerSystem import org.bukkit.Bukkit import org.bukkit.Location @@ -33,10 +34,7 @@ class SignManager { val zString = locationSplit[3] val world = Bukkit.getWorld(worldName) ?: continue - val x = xString.toInt() - val y = yString.toInt() - val z = zString.toInt() - val location = Location(world, x.toDouble(), y.toDouble(), z.toDouble()) + val location = location(xString.toInt(), yString.toInt(), zString.toInt(), world) addSignType(location, signType) } } diff --git a/src/main/kotlin/me/testaccount666/serversystem/clickablesigns/cost/CostHandler.kt b/src/main/kotlin/me/testaccount666/serversystem/clickablesigns/cost/CostHandler.kt index 0ef2e4a9..07f4f722 100644 --- a/src/main/kotlin/me/testaccount666/serversystem/clickablesigns/cost/CostHandler.kt +++ b/src/main/kotlin/me/testaccount666/serversystem/clickablesigns/cost/CostHandler.kt @@ -1,9 +1,8 @@ package me.testaccount666.serversystem.clickablesigns.cost import me.testaccount666.serversystem.ServerSystem.Companion.log +import me.testaccount666.serversystem.extensions.* import me.testaccount666.serversystem.userdata.User -import me.testaccount666.serversystem.utils.MessageBuilder.Companion.general -import me.testaccount666.serversystem.utils.MessageBuilder.Companion.sign import org.bukkit.configuration.file.FileConfiguration import java.util.logging.Level @@ -13,22 +12,33 @@ import java.util.logging.Level object CostHandler { /** * Checks if a user can afford the cost specified in the configuration. - * + * * @param user The user to check * @param config The configuration containing cost information * @return true if the user can afford the cost, false otherwise */ - fun canAfford(user: User, config: FileConfiguration): Boolean { + fun canAfford(user: User, config: FileConfiguration, sendMessage: Boolean = true): Boolean { val costType = getCostType(config) if (costType == CostType.NONE) return true val costAmount = config.getDouble("Cost.Amount") if (costAmount <= 0) return true - if (costType == CostType.EXP) return user.getPlayer()!!.calculateTotalExperiencePoints() >= costAmount - if (costType == CostType.ECONOMY) return user.bankAccount.balance >= costAmount.toBigDecimal() + val canAfford = when (costType) { + CostType.EXP -> user.getPlayer()!!.calculateTotalExperiencePoints() >= costAmount + CostType.ECONOMY -> user.bankAccount.balance >= costAmount.toBigDecimal() + } - return false + if (!canAfford && sendMessage) { + if (costType == CostType.EXP) user.signMsg("Cost.NotEnoughExp") { + postModifier { it.replace("", costAmount.toInt().toString()) } + } + else if (costType == CostType.ECONOMY) user.signMsg("Cost.NotEnoughMoney") { + postModifier { it.replace("", costAmount.toString()) } + } + } + + return canAfford } fun refundCost(user: User, config: FileConfiguration) { @@ -39,8 +49,8 @@ object CostHandler { if (costAmount <= 0) return if (costType == CostType.EXP) { - val player = user.getPlayer() - player!!.setExperienceLevelAndProgress(player.calculateTotalExperiencePoints() + costAmount.toInt()) + val player = user.getPlayer()!! + player.setExperienceLevelAndProgress(player.calculateTotalExperiencePoints() + costAmount.toInt()) return } if (costType == CostType.ECONOMY) { @@ -50,15 +60,15 @@ object CostHandler { bankAccount.balance += costAmount.toBigDecimal() bankAccount.save() } catch (exception: Exception) { - log.log(Level.SEVERE, "Failed to refund cost for '${user.getNameOrNull()}', failed to save bank account", exception) - general("ErrorOccurred", user).build() + log.log(Level.SEVERE, "Failed to refund cost for '${user.nameSafe}', failed to save bank account", exception) + user.generalMsg("ErrorOccurred") } } } /** * Deducts the cost from the user. - * + * * @param user The user to deduct from * @param config The configuration containing cost information * @return true if the cost was successfully deducted, false otherwise @@ -70,22 +80,14 @@ object CostHandler { val costAmount = config.getDouble("Cost.Amount") if (costAmount <= 0) return true - if (!canAfford(user, config)) { - if (costType == CostType.EXP) sign("Cost.NotEnoughExp", user) { - postModifier { it.replace("", costAmount.toInt().toString()) } - }.build() - else if (costType == CostType.ECONOMY) sign("Cost.NotEnoughMoney", user) { - postModifier { it.replace("", costAmount.toString()) } - }.build() - return false - } + if (!canAfford(user, config, false)) return false if (costType == CostType.EXP) { - val player = user.getPlayer() - player!!.setExperienceLevelAndProgress(player.calculateTotalExperiencePoints() - costAmount.toInt()) - sign("Cost.PaidExp", user) { + val player = user.getPlayer()!! + player.setExperienceLevelAndProgress(player.calculateTotalExperiencePoints() - costAmount.toInt()) + user.signMsg("Cost.PaidExp") { postModifier { it.replace("", costAmount.toInt().toString()) } - }.build() + } return true } if (costType == CostType.ECONOMY) { @@ -94,9 +96,9 @@ object CostHandler { try { bankAccount.balance -= costAmount.toBigDecimal() bankAccount.save() - sign("Cost.PaidMoney", user) { + user.signMsg("Cost.PaidMoney") { postModifier { it.replace("", costAmount.toString()) } - }.build() + } return true } catch (_: Exception) { return false @@ -108,16 +110,11 @@ object CostHandler { /** * Gets the cost type from the configuration. - * + * * @param config The configuration * @return The cost type */ fun getCostType(config: FileConfiguration): CostType { - val costTypeStr = config.getString("Cost.Type", "NONE")!! - return try { - CostType.valueOf(costTypeStr.uppercase()) - } catch (_: IllegalArgumentException) { - CostType.NONE - } + return config.getEnum("Cost.Type", CostType.NONE) } } \ No newline at end of file diff --git a/src/main/kotlin/me/testaccount666/serversystem/clickablesigns/executables/give/ActionGiveSign.kt b/src/main/kotlin/me/testaccount666/serversystem/clickablesigns/executables/give/ActionGiveSign.kt index 46fe3bef..457e99e4 100644 --- a/src/main/kotlin/me/testaccount666/serversystem/clickablesigns/executables/give/ActionGiveSign.kt +++ b/src/main/kotlin/me/testaccount666/serversystem/clickablesigns/executables/give/ActionGiveSign.kt @@ -1,9 +1,11 @@ package me.testaccount666.serversystem.clickablesigns.executables.give +import me.testaccount666.paperktx.extensions.ComponentExtensions.asComponent +import me.testaccount666.paperktx.extensions.isAir +import me.testaccount666.paperktx.extensions.set import me.testaccount666.serversystem.clickablesigns.AbstractSignClickAction +import me.testaccount666.serversystem.extensions.signMsg import me.testaccount666.serversystem.userdata.User -import me.testaccount666.serversystem.utils.ItemStackExtensions.Companion.isAir -import me.testaccount666.serversystem.utils.MessageBuilder.Companion.sign import org.bukkit.Bukkit import org.bukkit.block.Sign import org.bukkit.configuration.file.FileConfiguration @@ -11,17 +13,17 @@ import org.bukkit.configuration.file.FileConfiguration class ActionGiveSign : AbstractSignClickAction() { override val basePermissionNode = "ClickableSigns.Give" - override fun executeAction(user: User, sign: Sign, config: FileConfiguration): Boolean { - val item = config.getItemStack("Item") - if (item.isAir()) { - sign("Give.NoItem", user).build() + override fun executeAction(user: User, sign: Sign, config: FileConfiguration, onSuccess: () -> Unit): Boolean { + val item = config.getItemStack("Item").takeUnless { it.isAir() } ?: run { + user.signMsg("Give.NoItem") return false } - val inventory = Bukkit.createInventory(null, 27, "Give Sign") - for (index in 0..().addSignType(sign.location, signType) + getService().addSignType(sign.location, signType) _CONFIGURATORS.removeByValue(sign) val front = sign.getSide(Side.FRONT) - front.line(0, translateToComponent(SignType.GIVE.signName)) - front.line(1, translateToComponent("&2${itemToGive.type.name}")) + front.line(0, SignType.GIVE.signName.asComponent()) + front.line(1, "&2${itemToGive.type.name}".asComponent()) val back = sign.getSide(Side.BACK) for (index in 0..3) back.line(index, front.line(index)) sign.update() @@ -91,17 +87,17 @@ class ConfiguratorGiveSign : AbstractSignConfigurator(), Listener { /** * Validates that the user has permission to create this sign. - * + * * @param user The user to check * @return true if the user has permission, false otherwise */ private fun validatePermission(user: User): Boolean { if (!hasPermission(user, createPermissionNode, false)) { - general("NoPermission", user) { + user.generalMsg("NoPermission") { postModifier { it.replace("", getPermission(createPermissionNode)!!) } - }.build() + } return false } return true diff --git a/src/main/kotlin/me/testaccount666/serversystem/clickablesigns/executables/kit/ActionKitSign.kt b/src/main/kotlin/me/testaccount666/serversystem/clickablesigns/executables/kit/ActionKitSign.kt index 4a6850ca..dd737866 100644 --- a/src/main/kotlin/me/testaccount666/serversystem/clickablesigns/executables/kit/ActionKitSign.kt +++ b/src/main/kotlin/me/testaccount666/serversystem/clickablesigns/executables/kit/ActionKitSign.kt @@ -1,38 +1,51 @@ package me.testaccount666.serversystem.clickablesigns.executables.kit -import me.testaccount666.serversystem.ServerSystem.Companion.instance +import me.testaccount666.paperktx.colors.ChatColor.Companion.stripColor import me.testaccount666.serversystem.clickablesigns.AbstractSignClickAction import me.testaccount666.serversystem.commands.executables.kit.manager.KitManager +import me.testaccount666.serversystem.extensions.* import me.testaccount666.serversystem.userdata.User -import me.testaccount666.serversystem.utils.ChatColor.Companion.stripColor -import me.testaccount666.serversystem.utils.MessageBuilder.Companion.sign +import me.testaccount666.serversystem.utils.DurationParser.parseDate import org.bukkit.block.Sign import org.bukkit.configuration.file.FileConfiguration class ActionKitSign : AbstractSignClickAction() { override val basePermissionNode = "ClickableSigns.Kit" - override fun executeAction(user: User, sign: Sign, config: FileConfiguration): Boolean { - val kitManager = instance.registry.getService() + override fun executeAction(user: User, sign: Sign, config: FileConfiguration, onSuccess: () -> Unit): Boolean { + val kitManager = getService() - var kitName = config.getString("KitName", sign.getLine(1)) - kitName = stripColor(kitName) - if (kitName.isEmpty()) { - sign("Kit.NoKitSpecified", user).build() + val kitName = stripColor(config.getString("KitName", sign.getLine(1))).takeUnless { it.isEmpty() } ?: run { + user.signMsg("Kit.NoKitSpecified") return false } - val kit = kitManager.getKit(kitName.lowercase()) ?: run { - sign("Kit.KitNotFound", user) { + val kit = kitManager.getKit(kitName) ?: run { + user.signMsg("Kit.KitNotFound") { postModifier { it.replace("", kitName) } - }.build() + } return false } + if (user.isOnKitCooldown(kit.name)) { + val cooldown = user.getKitCooldown(kitName) + + user.commandMsg("Kit.OnCooldown") { + postModifier { + it.replace("", kit.displayName) + .replace("", parseDate(cooldown, user)) + } + } + return false + } + + user.setKitCooldown(kit.name, kit.coolDown).also { user.save() } + kit.giveKit(user.getPlayer()!!) - sign("Kit.KitGiven", user) { + user.signMsg("Kit.KitGiven") { postModifier { it.replace("", kit.displayName) } - }.build() + } + onSuccess() return true } } \ No newline at end of file diff --git a/src/main/kotlin/me/testaccount666/serversystem/clickablesigns/executables/kit/ConfiguratorKitSign.kt b/src/main/kotlin/me/testaccount666/serversystem/clickablesigns/executables/kit/ConfiguratorKitSign.kt index dd9a68c4..24848d51 100644 --- a/src/main/kotlin/me/testaccount666/serversystem/clickablesigns/executables/kit/ConfiguratorKitSign.kt +++ b/src/main/kotlin/me/testaccount666/serversystem/clickablesigns/executables/kit/ConfiguratorKitSign.kt @@ -1,14 +1,14 @@ package me.testaccount666.serversystem.clickablesigns.executables.kit -import me.testaccount666.serversystem.ServerSystem.Companion.instance +import me.testaccount666.paperktx.colors.ChatColor.Companion.stripColor +import me.testaccount666.paperktx.extensions.ComponentExtensions.asComponent +import me.testaccount666.paperktx.extensions.ComponentExtensions.asString import me.testaccount666.serversystem.clickablesigns.AbstractSignConfigurator import me.testaccount666.serversystem.clickablesigns.SignType import me.testaccount666.serversystem.commands.executables.kit.manager.KitManager +import me.testaccount666.serversystem.extensions.getService +import me.testaccount666.serversystem.extensions.signMsg import me.testaccount666.serversystem.userdata.User -import me.testaccount666.serversystem.utils.ChatColor.Companion.stripColor -import me.testaccount666.serversystem.utils.ComponentColor.componentToString -import me.testaccount666.serversystem.utils.ComponentColor.translateToComponent -import me.testaccount666.serversystem.utils.MessageBuilder.Companion.sign import org.bukkit.block.Sign import org.bukkit.block.sign.Side import org.bukkit.configuration.file.FileConfiguration @@ -20,24 +20,21 @@ class ConfiguratorKitSign : AbstractSignConfigurator() { override val signType = SignType.KIT override fun validateConfiguration(user: User, sign: Sign, config: YamlConfiguration): Boolean { - val kitManager = instance.registry.getService() - val front = sign.getSide(Side.FRONT) - val kitName = componentToString(front.line(1)) - if (kitName.isEmpty()) { - sign("Kit.NoKitSpecified", user).build() + val kitName = front.line(1).asString().takeUnless { it.isEmpty() } ?: run { + user.signMsg("Kit.NoKitSpecified") return false } - if (!kitManager.kitExists(kitName.lowercase())) { - sign("Kit.KitNotFound", user) { + if (!getService().kitExists(kitName)) { + user.signMsg("Kit.KitNotFound") { postModifier { it.replace("", kitName) } - }.build() + } return false } - front.line(0, translateToComponent(SignType.KIT.signName)) - front.line(1, translateToComponent("&2${kitName}")) + front.line(0, SignType.KIT.signName.asComponent()) + front.line(1, "&2${kitName}".asComponent()) val back = sign.getSide(Side.BACK) for (index in 0..3) back.line(index, front.line(index)) sign.update() @@ -47,6 +44,6 @@ class ConfiguratorKitSign : AbstractSignConfigurator() { override fun addSignSpecificConfiguration(user: User, sign: Sign, config: FileConfiguration) { var kitName = sign.getSide(Side.FRONT).getLine(1) kitName = stripColor(kitName) - config.set("KitName", kitName) + config["KitName"] = kitName } } \ No newline at end of file diff --git a/src/main/kotlin/me/testaccount666/serversystem/clickablesigns/executables/time/ActionTimeSign.kt b/src/main/kotlin/me/testaccount666/serversystem/clickablesigns/executables/time/ActionTimeSign.kt index 1fea8dff..882f48ea 100644 --- a/src/main/kotlin/me/testaccount666/serversystem/clickablesigns/executables/time/ActionTimeSign.kt +++ b/src/main/kotlin/me/testaccount666/serversystem/clickablesigns/executables/time/ActionTimeSign.kt @@ -1,46 +1,47 @@ package me.testaccount666.serversystem.clickablesigns.executables.time +import me.testaccount666.paperktx.colors.ChatColor.Companion.stripColor import me.testaccount666.serversystem.clickablesigns.AbstractSignClickAction +import me.testaccount666.serversystem.extensions.signMsg import me.testaccount666.serversystem.userdata.User -import me.testaccount666.serversystem.utils.ChatColor.Companion.stripColor -import me.testaccount666.serversystem.utils.MessageBuilder.Companion.sign import org.bukkit.block.Sign import org.bukkit.configuration.file.FileConfiguration class ActionTimeSign : AbstractSignClickAction() { override val basePermissionNode = "ClickableSigns.Time" - override fun executeAction(user: User, sign: Sign, config: FileConfiguration): Boolean { - var timeType = config.getString("TimeType", sign.getLine(1))?.lowercase() + override fun executeAction(user: User, sign: Sign, config: FileConfiguration, onSuccess: () -> Unit): Boolean { + var timeType = config.getString("TimeType", sign.getLine(1))!!.lowercase() timeType = stripColor(timeType) if (timeType.isEmpty()) { - sign("Time.NoTimeSpecified", user).build() + user.signMsg("Time.NoTimeSpecified") return false } - val world = user.getPlayer()?.world ?: return false + val world = user.getPlayer()!!.world val time = when (timeType) { - "day" -> 1000 - "noon" -> 6000 - "night" -> 13000 - "midnight" -> 18000 + "day" -> 1000L + "noon" -> 6000L + "night" -> 13000L + "midnight" -> 18000L else -> { try { timeType.toLong() } catch (_: NumberFormatException) { - sign("Time.InvalidTime", user) { + user.signMsg("Time.InvalidTime") { postModifier { it.replace("