From 307b7aee4af34e47139259db7049a85c682b7be2 Mon Sep 17 00:00:00 2001 From: Dico Date: Thu, 27 Sep 2018 04:41:58 +0100 Subject: Tweaks --- src/main/kotlin/io/dico/parcels2/PlayerProfile.kt | 141 ++------------------- .../dico/parcels2/blockvisitor/WorkDispatcher.kt | 8 +- .../parcels2/command/AbstractParcelCommands.kt | 13 +- .../io/dico/parcels2/command/CommandsAdmin.kt | 15 ++- .../command/CommandsAdminPrivilegesGlobal.kt | 4 +- .../io/dico/parcels2/command/CommandsDebug.kt | 69 ++++++---- .../io/dico/parcels2/command/CommandsGeneral.kt | 19 +-- .../parcels2/command/CommandsPrivilegesLocal.kt | 6 + .../dico/parcels2/command/ParcelCommandBuilder.kt | 2 +- .../command/ParcelOptionsInteractCommand.kt | 9 +- .../dico/parcels2/command/ParcelParameterTypes.kt | 26 +++- .../io/dico/parcels2/command/ParcelTarget.kt | 49 +++---- .../parcels2/defaultimpl/DefaultParcelGenerator.kt | 2 +- .../io/dico/parcels2/listener/ListenerHelper.kt | 16 --- .../io/dico/parcels2/listener/ParcelListeners.kt | 2 +- .../kotlin/io/dico/parcels2/util/BukkitUtil.kt | 12 ++ src/main/kotlin/io/dico/parcels2/util/UUIDUtil.kt | 14 -- src/main/kotlin/io/dico/parcels2/util/ext/Misc.kt | 3 + .../kotlin/io/dico/parcels2/util/ext/Player.kt | 4 +- 19 files changed, 162 insertions(+), 252 deletions(-) delete mode 100644 src/main/kotlin/io/dico/parcels2/listener/ListenerHelper.kt create mode 100644 src/main/kotlin/io/dico/parcels2/util/BukkitUtil.kt delete mode 100644 src/main/kotlin/io/dico/parcels2/util/UUIDUtil.kt diff --git a/src/main/kotlin/io/dico/parcels2/PlayerProfile.kt b/src/main/kotlin/io/dico/parcels2/PlayerProfile.kt index ae73639..99b2b5f 100644 --- a/src/main/kotlin/io/dico/parcels2/PlayerProfile.kt +++ b/src/main/kotlin/io/dico/parcels2/PlayerProfile.kt @@ -3,13 +3,11 @@ package io.dico.parcels2 import io.dico.parcels2.storage.Storage -import io.dico.parcels2.util.PLAYER_NAME_PLACEHOLDER -import io.dico.parcels2.util.getPlayerName +import io.dico.parcels2.util.ext.PLAYER_NAME_PLACEHOLDER import io.dico.parcels2.util.ext.isValid import io.dico.parcels2.util.ext.uuid -import kotlinx.coroutines.Deferred -import kotlinx.coroutines.Unconfined -import kotlinx.coroutines.async +import io.dico.parcels2.util.getOfflinePlayer +import io.dico.parcels2.util.getPlayerName import org.bukkit.Bukkit import org.bukkit.OfflinePlayer import java.util.UUID @@ -70,8 +68,7 @@ interface PlayerProfile { if (input == Star.name) return Star - return Bukkit.getOfflinePlayer(input).takeIf { it.isValid }?.let { PlayerProfile(it) } - ?: Unresolved(input) + return getOfflinePlayer(input)?.let { PlayerProfile(it) } ?: Unresolved(input) } } @@ -83,8 +80,7 @@ interface PlayerProfile { override val notNullName: String get() = nameOrBukkitName ?: PLAYER_NAME_PLACEHOLDER - val player: OfflinePlayer? get() = Bukkit.getOfflinePlayer(uuid).takeIf { it.isValid } - val playerUnchecked: OfflinePlayer get() = Bukkit.getOfflinePlayer(uuid) + val player: OfflinePlayer? get() = getOfflinePlayer(uuid) override fun matches(player: OfflinePlayer, allowNameMatch: Boolean): Boolean { return uuid == player.uuid || (allowNameMatch && name?.let { it == player.name } == true) @@ -147,10 +143,6 @@ interface PlayerProfile { return other is Unresolved && name == other.name } - fun tryResolve(storage: Storage): Deferred { - return async(Unconfined) { tryResolveSuspendedly(storage) } - } - suspend fun tryResolveSuspendedly(storage: Storage): Real? { return storage.getPlayerUuidForName(name).await()?.let { resolve(it) } } @@ -178,120 +170,9 @@ interface PlayerProfile { } - -/* - - -/** - * This class can represent: - * - * An existing player - * A fake player (with only a name) - * An existing player who must have its uuid resolved from the database (after checking against Bukkit OfflinePlayer) - * STAR profile, which matches everyone. This profile is considered a REAL player, because it can have a privilege. - */ -class PlayerProfile2 private constructor(uuid: UUID?, - val name: String?, - val isReal: Boolean = uuid != null) { - private var _uuid: UUID? = uuid - val notNullName: String get() = name ?: getPlayerNameOrDefault(uuid!!) - - val uuid: UUID? get() = _uuid ?: if (isReal) throw IllegalStateException("This PlayerProfile must be resolved first") else null - - companion object { - // below uuid is just a randomly generated one (version 4). Hopefully no minecraft player will ever have it :) - val star = PlayerProfile(UUID.fromString("7d09c4c6-117d-4f36-9778-c4d24618cee1"), "*", true) - - fun nameless(player: OfflinePlayer): PlayerProfile { - if (!player.isValid) throw IllegalArgumentException("The given OfflinePlayer is not valid") - return PlayerProfile(player.uuid) - } - - fun fromNameAndUuid(name: String?, uuid: UUID?): PlayerProfile? { - if (name == null && uuid == null) return null - if (star.name == name && star._uuid == uuid) return star - return PlayerProfile(uuid, name) - } - - fun realPlayerByName(name: String): PlayerProfile { - return fromString(name, allowReal = true, allowFake = false) - } - - fun fromString(input: String, allowReal: Boolean = true, allowFake: Boolean = false): PlayerProfile { - if (!allowReal) { - if (!allowFake) throw IllegalArgumentException("at least one of allowReal and allowFake must be true") - return PlayerProfile(input) - } - - if (input == star.name) return star - - return Bukkit.getOfflinePlayer(input).takeIf { it.isValid }?.let { PlayerProfile(it) } - ?: PlayerProfile(null, input, !allowFake) - } - - operator fun createWith(name: String): PlayerProfile { - if (name == star.name) return star - return PlayerProfile(null, name) - } - - operator fun createWith(uuid: UUID): PlayerProfile { - if (uuid == star.uuid) return star - return PlayerProfile(uuid, null) - } - - operator fun createWith(player: OfflinePlayer): PlayerProfile { - // avoid UUID comparison against STAR - return if (player.isValid) PlayerProfile(player.uuid, player.name) else createWith(player.name) - } - } - - val isStar: Boolean get() = this === star || (name == star.name && _uuid == star._uuid) - val hasUUID: Boolean get() = _uuid != null - val mustBeResolved: Boolean get() = isReal && _uuid == null - - val onlinePlayer: Player? get() = uuid?.let { Bukkit.getPlayer(uuid) } - - val onlinePlayerAllowingNameMatch: Player? get() = onlinePlayer ?: name?.let { Bukkit.getPlayerExact(name) } - val offlinePlayer: OfflinePlayer? get() = uuid?.let { Bukkit.getOfflinePlayer(it).takeIf { it.isValid } } - val offlinePlayerAllowingNameMatch: OfflinePlayer? - get() = offlinePlayer ?: Bukkit.getOfflinePlayer(name).takeIf { it.isValid } - - fun matches(player: OfflinePlayer, allowNameMatch: Boolean = false): Boolean { - if (isStar) return true - return uuid?.let { it == player.uniqueId } ?: false - || (allowNameMatch && name?.let { it == player.name } ?: false) - } - - fun equals(other: PlayerProfile): Boolean { - return if (_uuid != null) _uuid == other._uuid - else other._uuid == null && isReal == other.isReal && name == other.name - } - - override fun equals(other: Any?): Boolean { - return other is PlayerProfile && equals(other) - } - - override fun hashCode(): Int { - return _uuid?.hashCode() ?: name!!.hashCode() - } - - /** - * resolve the uuid of this player profile if [mustBeResolved], using specified [storage]. - * returns true if the PlayerProfile has a uuid after this call. - */ - suspend fun resolve(storage: Storage): Boolean { - if (mustBeResolved) { - val uuid = storage.getPlayerUuidForName(name!!).await() - _uuid = uuid - return uuid != null - } - return _uuid != null - } - - fun resolve(uuid: UUID) { - if (isReal && _uuid == null) { - _uuid = uuid - } - } -} -*/ +suspend fun PlayerProfile.resolved(storage: Storage, resolveToFake: Boolean = false): PlayerProfile? = + when (this) { + is PlayerProfile.Unresolved -> tryResolveSuspendedly(storage) + ?: if (resolveToFake) PlayerProfile.Fake(name) else null + else -> this + } \ No newline at end of file diff --git a/src/main/kotlin/io/dico/parcels2/blockvisitor/WorkDispatcher.kt b/src/main/kotlin/io/dico/parcels2/blockvisitor/WorkDispatcher.kt index 7201a06..7162561 100644 --- a/src/main/kotlin/io/dico/parcels2/blockvisitor/WorkDispatcher.kt +++ b/src/main/kotlin/io/dico/parcels2/blockvisitor/WorkDispatcher.kt @@ -24,7 +24,6 @@ data class TickWorktimeOptions(var workTime: Int, var tickInterval: Int) interface WorkDispatcher { /** * Submit a [task] that should be run synchronously, but limited such that it does not stall the server - * a bunch */ fun dispatch(task: WorkerTask): Worker @@ -89,11 +88,6 @@ interface Worker : WorkerAndScopeMembersUnion { * Await completion of this worker */ suspend fun awaitCompletion() - - /** - * An object attached to this worker - */ - //val attachment: Any? } interface WorkerScope : WorkerAndScopeMembersUnion { @@ -114,7 +108,7 @@ interface WorkerScope : WorkerAndScopeMembersUnion { /** * Get a [WorkerScope] that is responsible for [portion] part of the progress - * If [portion] is negative, the remainder of the progress is used + * If [portion] is negative, the remaining progress is used */ fun delegateWork(portion: Double = -1.0): WorkerScope } diff --git a/src/main/kotlin/io/dico/parcels2/command/AbstractParcelCommands.kt b/src/main/kotlin/io/dico/parcels2/command/AbstractParcelCommands.kt index a660fc0..79faf36 100644 --- a/src/main/kotlin/io/dico/parcels2/command/AbstractParcelCommands.kt +++ b/src/main/kotlin/io/dico/parcels2/command/AbstractParcelCommands.kt @@ -20,12 +20,8 @@ abstract class AbstractParcelCommands(val plugin: ParcelsPlugin) : ICommandRecei return getParcelCommandReceiver(plugin.parcelProvider, context, target, cmdName) } - protected fun error(message: String): Nothing { - throw CommandException(message) - } - protected fun checkConnected(action: String) { - if (!plugin.storage.isConnected) error("Parcels cannot $action right now because of a database error") + if (!plugin.storage.isConnected) err("Parcels cannot $action right now because of a database error") } protected suspend fun checkParcelLimit(player: Player, world: ParcelWorld) { @@ -35,7 +31,7 @@ abstract class AbstractParcelCommands(val plugin: ParcelsPlugin) : ICommandRecei val limit = player.parcelLimit if (numOwnedParcels >= limit) { - error("You have enough plots for now") + err("You have enough plots for now") } } @@ -65,10 +61,7 @@ abstract class AbstractParcelCommands(val plugin: ParcelsPlugin) : ICommandRecei } } - protected fun err(message: String): Nothing = throw CommandException(message) - override fun getCoroutineContext() = plugin.coroutineContext - - } +fun err(message: String): Nothing = throw CommandException(message) \ No newline at end of file diff --git a/src/main/kotlin/io/dico/parcels2/command/CommandsAdmin.kt b/src/main/kotlin/io/dico/parcels2/command/CommandsAdmin.kt index 9c3ca4f..79028a2 100644 --- a/src/main/kotlin/io/dico/parcels2/command/CommandsAdmin.kt +++ b/src/main/kotlin/io/dico/parcels2/command/CommandsAdmin.kt @@ -8,18 +8,19 @@ import io.dico.dicore.command.annotation.Flag import io.dico.parcels2.ParcelsPlugin import io.dico.parcels2.PlayerProfile import io.dico.parcels2.Privilege -import io.dico.parcels2.command.ParcelTarget.Companion.ID -import io.dico.parcels2.command.ParcelTarget.Kind +import io.dico.parcels2.command.ParcelTarget.TargetKind +import io.dico.parcels2.resolved class CommandsAdmin(plugin: ParcelsPlugin) : AbstractParcelCommands(plugin) { @Cmd("setowner") @RequireParcelPrivilege(Privilege.ADMIN) - fun ParcelScope.cmdSetowner(target: PlayerProfile): Any? { - parcel.owner = target + suspend fun ParcelScope.cmdSetowner(@ProfileKind(ProfileKind.ANY) target: PlayerProfile): Any? { + val profile = target.resolved(plugin.storage, resolveToFake = true)!! + parcel.owner = profile - val fakeString = if (target.isFake) " (fake)" else "" - return "${target.notNullName}$fakeString is the new owner of (${parcel.id.idString})" + val fakeString = if (profile.isFake) " (fake)" else "" + return "${profile.notNullName}$fakeString is the new owner of (${parcel.id.idString})" } @Cmd("dispose") @@ -43,7 +44,7 @@ class CommandsAdmin(plugin: ParcelsPlugin) : AbstractParcelCommands(plugin) { @Cmd("swap") @RequireParcelPrivilege(Privilege.ADMIN) fun ParcelScope.cmdSwap(context: ExecutionContext, - @Kind(ID) target: ParcelTarget, + @TargetKind(TargetKind.ID) target: ParcelTarget, @Flag sure: Boolean): Any? { Validate.isTrue(!parcel.hasBlockVisitors, "A process is already running in this parcel") if (!sure) return areYouSureMessage(context) diff --git a/src/main/kotlin/io/dico/parcels2/command/CommandsAdminPrivilegesGlobal.kt b/src/main/kotlin/io/dico/parcels2/command/CommandsAdminPrivilegesGlobal.kt index 1bd42e8..541ea87 100644 --- a/src/main/kotlin/io/dico/parcels2/command/CommandsAdminPrivilegesGlobal.kt +++ b/src/main/kotlin/io/dico/parcels2/command/CommandsAdminPrivilegesGlobal.kt @@ -9,16 +9,14 @@ import io.dico.dicore.command.annotation.Desc import io.dico.parcels2.* import io.dico.parcels2.PrivilegeChangeResult.* import io.dico.parcels2.util.ext.PERM_ADMIN_MANAGE -import io.dico.parcels2.util.ext.hasPermAdminManage import org.bukkit.OfflinePlayer -import org.bukkit.command.CommandSender -import org.bukkit.entity.Player class CommandsAdminPrivilegesGlobal(plugin: ParcelsPlugin) : AbstractParcelCommands(plugin) { private val data inline get() = plugin.globalPrivileges private fun checkContext(context: ExecutionContext, owner: OfflinePlayer): OfflinePlayer { + checkConnected("have privileges changed") val sender = context.sender if (sender !== owner) { Validate.isAuthorized(sender, PERM_ADMIN_MANAGE) diff --git a/src/main/kotlin/io/dico/parcels2/command/CommandsDebug.kt b/src/main/kotlin/io/dico/parcels2/command/CommandsDebug.kt index b3b632f..6331b4c 100644 --- a/src/main/kotlin/io/dico/parcels2/command/CommandsDebug.kt +++ b/src/main/kotlin/io/dico/parcels2/command/CommandsDebug.kt @@ -1,14 +1,17 @@ package io.dico.parcels2.command import io.dico.dicore.command.* -import io.dico.dicore.command.IContextFilter.Priority.* +import io.dico.dicore.command.IContextFilter.Priority.PERMISSION import io.dico.dicore.command.annotation.Cmd import io.dico.dicore.command.annotation.PreprocessArgs +import io.dico.dicore.command.annotation.RequireParameters import io.dico.dicore.command.parameter.ArgumentBuffer -import io.dico.parcels2.ParcelsPlugin -import io.dico.parcels2.Privilege +import io.dico.parcels2.* import io.dico.parcels2.blockvisitor.RegionTraverser -import io.dico.parcels2.doBlockOperation +import io.dico.parcels2.util.ext.PERM_ADMIN_MANAGE +import io.dico.parcels2.util.ext.PERM_BAN_BYPASS +import io.dico.parcels2.util.ext.PERM_BUILD_ANYWHERE +import kotlinx.coroutines.launch import org.bukkit.Bukkit import org.bukkit.Material import org.bukkit.block.BlockFace @@ -29,7 +32,7 @@ class CommandsDebug(plugin: ParcelsPlugin) : AbstractParcelCommands(plugin) { if (worldName == "list") { return Bukkit.getWorlds().joinToString("\n- ", "- ", "") } - val world = Bukkit.getWorld(worldName) ?: throw CommandException("World $worldName is not loaded") + val world = Bukkit.getWorld(worldName) ?: err("World $worldName is not loaded") sender.teleport(world.spawnLocation) return "Teleported you to $worldName spawn" } @@ -76,44 +79,64 @@ class CommandsDebug(plugin: ParcelsPlugin) : AbstractParcelCommands(plugin) { blockData.javaClass.interfaces!!.contentToString() } - @Cmd("visitors") - fun cmdVisitors(): Any? { + @Cmd("jobs") + fun cmdJobs(): Any? { val workers = plugin.workDispatcher.workers println(workers.map { it.job }.joinToString(separator = "\n")) return "Task count: ${workers.size}" } - @Cmd("force_visitors") - fun cmdForceVisitors(): Any? { - val workers = plugin.workDispatcher.workers - plugin.workDispatcher.completeAllTasks() - return "Completed task count: ${workers.size}" - } - - @Cmd("hasperm") - fun cmdHasperm(sender: CommandSender, target: Player, permission: String): Any? { - return target.hasPermission(permission).toString() + @Cmd("complete_jobs") + fun cmdCompleteJobs(): Any? = cmdJobs().also { + plugin.launch { plugin.workDispatcher.completeAllTasks() } } @Cmd("message") @PreprocessArgs fun cmdMessage(sender: CommandSender, message: String): Any? { + // testing @PreprocessArgs which merges "hello there" into a single argument sender.sendMessage(message) return null } + @Cmd("hasperm") + fun cmdHasperm(target: Player, permission: String): Any? { + return target.hasPermission(permission).toString() + } + @Cmd("permissions") - fun cmdPermissions(context: ExecutionContext, vararg address: String): Any? { + fun cmdPermissions(context: ExecutionContext, of: Player, vararg address: String): Any? { val target = context.address.dispatcherForTree.getDeepChild(ArgumentBuffer(address)) Validate.isTrue(target.depth == address.size && target.hasCommand(), "Not found: /${address.joinToString(separator = " ")}") + return getPermissionsOf(target).joinToString(separator = "\n") { "$it: ${of.hasPermission(it)}" } + } + + @Cmd("privilege") + @RequireParameters(1) + suspend fun ParcelScope.cmdPrivilege(target: PlayerProfile, adminPerm: String?): Any? { + val key = toPrivilegeKey(target) + + val perm = when (adminPerm) { + "none" -> null + "build" -> PERM_BUILD_ANYWHERE + "manage", null -> PERM_ADMIN_MANAGE + "enter" -> PERM_BAN_BYPASS + else -> err("adminPerm should be build, manager or enter") + } - val permissions = getPermissionsOf(target) - return permissions.joinToString(separator = "\n") + val privilege = if (perm == null) { + parcel.getStoredPrivilege(key) + } else { + if (key is PlayerProfile.Star) err("* can't have permissions") + parcel.getEffectivePrivilege(key.player!!, perm) + } + + return privilege.toString() } - private fun getPermissionsOf(address: ICommandAddress, - path: Array = emptyArray(), - result: MutableList = mutableListOf()): List { + private fun getPermissionsOf(address: ICommandAddress) = getPermissionsOf(address, emptyArray(), mutableListOf()) + + private fun getPermissionsOf(address: ICommandAddress, path: Array, result: MutableList): List { val command = address.command ?: return result var inherited = false diff --git a/src/main/kotlin/io/dico/parcels2/command/CommandsGeneral.kt b/src/main/kotlin/io/dico/parcels2/command/CommandsGeneral.kt index 67b873b..7f791cf 100644 --- a/src/main/kotlin/io/dico/parcels2/command/CommandsGeneral.kt +++ b/src/main/kotlin/io/dico/parcels2/command/CommandsGeneral.kt @@ -9,7 +9,7 @@ import io.dico.dicore.command.annotation.RequireParameters import io.dico.parcels2.ParcelsPlugin import io.dico.parcels2.PlayerProfile import io.dico.parcels2.Privilege -import io.dico.parcels2.command.ParcelTarget.Kind +import io.dico.parcels2.command.ParcelTarget.TargetKind import io.dico.parcels2.util.ext.hasParcelHomeOthers import io.dico.parcels2.util.ext.hasPermAdminManage import io.dico.parcels2.util.ext.uuid @@ -29,7 +29,7 @@ class CommandsGeneral(plugin: ParcelsPlugin, parent: SpecialCommandAddress) : Ab checkParcelLimit(player, world) val parcel = world.nextEmptyParcel() - ?: error("This world is full, please ask an admin to upsize it") + ?: err("This world is full, please ask an admin to upsize it") parcel.owner = PlayerProfile(uuid = player.uuid) player.teleport(parcel.homeLocation) return "Enjoy your new parcel!" @@ -58,7 +58,7 @@ class CommandsGeneral(plugin: ParcelsPlugin, parent: SpecialCommandAddress) : Ab @RequireParameters(0) suspend fun cmdHome( player: Player, - @Kind(ParcelTarget.OWNER_REAL) target: ParcelTarget + @TargetKind(TargetKind.OWNER_REAL) target: ParcelTarget ): Any? { return cmdGoto(player, target) } @@ -66,7 +66,7 @@ class CommandsGeneral(plugin: ParcelsPlugin, parent: SpecialCommandAddress) : Ab @Cmd("tp", aliases = ["teleport"]) suspend fun cmdTp( player: Player, - @Kind(ParcelTarget.ID) target: ParcelTarget + @TargetKind(TargetKind.ID) target: ParcelTarget ): Any? { return cmdGoto(player, target) } @@ -74,17 +74,17 @@ class CommandsGeneral(plugin: ParcelsPlugin, parent: SpecialCommandAddress) : Ab @Cmd("goto") suspend fun cmdGoto( player: Player, - @Kind(ParcelTarget.ANY) target: ParcelTarget + @TargetKind(TargetKind.ANY) target: ParcelTarget ): Any? { if (target is ParcelTarget.ByOwner) { target.resolveOwner(plugin.storage) if (!target.owner.matches(player) && !player.hasParcelHomeOthers) { - error("You do not have permission to teleport to other people's parcels") + err("You do not have permission to teleport to other people's parcels") } } val match = target.getParcelSuspend(plugin.storage) - ?: error("The specified parcel could not be matched") + ?: err("The specified parcel could not be matched") player.teleport(match.homeLocation) return null } @@ -92,7 +92,7 @@ class CommandsGeneral(plugin: ParcelsPlugin, parent: SpecialCommandAddress) : Ab @Cmd("goto_fake") suspend fun cmdGotoFake( player: Player, - @Kind(ParcelTarget.OWNER_FAKE) target: ParcelTarget + @TargetKind(TargetKind.OWNER_FAKE) target: ParcelTarget ): Any? { return cmdGoto(player, target) } @@ -105,7 +105,7 @@ class CommandsGeneral(plugin: ParcelsPlugin, parent: SpecialCommandAddress) : Ab suspend fun ParcelScope.cmdClaim(player: Player): Any? { checkConnected("be claimed") parcel.owner.takeIf { !player.hasPermAdminManage }?.let { - error(if (it.matches(player)) "You already own this parcel" else "This parcel is not available") + err(if (it.matches(player)) "You already own this parcel" else "This parcel is not available") } checkParcelLimit(player, world) @@ -117,6 +117,7 @@ class CommandsGeneral(plugin: ParcelsPlugin, parent: SpecialCommandAddress) : Ab @Desc("Unclaims this parcel") @RequireParcelPrivilege(Privilege.OWNER) fun ParcelScope.cmdUnclaim(player: Player): Any? { + checkConnected("be unclaimed") parcel.dispose() return "Your parcel has been disposed" } diff --git a/src/main/kotlin/io/dico/parcels2/command/CommandsPrivilegesLocal.kt b/src/main/kotlin/io/dico/parcels2/command/CommandsPrivilegesLocal.kt index f347f06..21910b1 100644 --- a/src/main/kotlin/io/dico/parcels2/command/CommandsPrivilegesLocal.kt +++ b/src/main/kotlin/io/dico/parcels2/command/CommandsPrivilegesLocal.kt @@ -28,6 +28,7 @@ class CommandsPrivilegesLocal(plugin: ParcelsPlugin) : AbstractParcelCommands(pl ) @RequireParcelPrivilege(Privilege.OWNER) suspend fun ParcelScope.cmdEntrust(sender: Player, player: PlayerProfile): Any? { + checkConnected("have privileges changed") checkOwned(sender) val key = toPrivilegeKey(player) @@ -46,6 +47,7 @@ class CommandsPrivilegesLocal(plugin: ParcelsPlugin) : AbstractParcelCommands(pl ) @RequireParcelPrivilege(Privilege.OWNER) suspend fun ParcelScope.cmdDistrust(sender: Player, player: PlayerProfile): Any? { + checkConnected("have privileges changed") checkOwned(sender) val key = toPrivilegeKey(player) @@ -63,6 +65,7 @@ class CommandsPrivilegesLocal(plugin: ParcelsPlugin) : AbstractParcelCommands(pl ) @RequireParcelPrivilege(Privilege.CAN_MANAGE) suspend fun ParcelScope.cmdAllow(sender: Player, player: PlayerProfile): Any? { + checkConnected("have privileges changed") checkOwned(sender) val key = toPrivilegeKey(player) @@ -83,6 +86,7 @@ class CommandsPrivilegesLocal(plugin: ParcelsPlugin) : AbstractParcelCommands(pl ) @RequireParcelPrivilege(Privilege.CAN_MANAGE) suspend fun ParcelScope.cmdDisallow(sender: Player, player: PlayerProfile): Any? { + checkConnected("have privileges changed") checkOwned(sender) val key = toPrivilegeKey(player) @@ -103,6 +107,7 @@ class CommandsPrivilegesLocal(plugin: ParcelsPlugin) : AbstractParcelCommands(pl ) @RequireParcelPrivilege(Privilege.CAN_MANAGE) suspend fun ParcelScope.cmdBan(sender: Player, player: PlayerProfile): Any? { + checkConnected("have privileges changed") checkOwned(sender) val key = toPrivilegeKey(player) @@ -123,6 +128,7 @@ class CommandsPrivilegesLocal(plugin: ParcelsPlugin) : AbstractParcelCommands(pl ) @RequireParcelPrivilege(Privilege.CAN_MANAGE) suspend fun ParcelScope.cmdUnban(sender: Player, player: PlayerProfile): Any? { + checkConnected("have privileges changed") checkOwned(sender) val key = toPrivilegeKey(player) diff --git a/src/main/kotlin/io/dico/parcels2/command/ParcelCommandBuilder.kt b/src/main/kotlin/io/dico/parcels2/command/ParcelCommandBuilder.kt index 40e5253..891988c 100644 --- a/src/main/kotlin/io/dico/parcels2/command/ParcelCommandBuilder.kt +++ b/src/main/kotlin/io/dico/parcels2/command/ParcelCommandBuilder.kt @@ -33,7 +33,7 @@ fun getParcelCommands(plugin: ParcelsPlugin): ICommandDispatcher = CommandBuilde ) group("interact", "i") { - val command = ParcelOptionsInteractCommand(plugin.parcelProvider) + val command = ParcelOptionsInteractCommand(plugin) Interactables.classesById.forEach { addSubCommand(it.name, command) } diff --git a/src/main/kotlin/io/dico/parcels2/command/ParcelOptionsInteractCommand.kt b/src/main/kotlin/io/dico/parcels2/command/ParcelOptionsInteractCommand.kt index 5c38b06..1b61660 100644 --- a/src/main/kotlin/io/dico/parcels2/command/ParcelOptionsInteractCommand.kt +++ b/src/main/kotlin/io/dico/parcels2/command/ParcelOptionsInteractCommand.kt @@ -4,11 +4,12 @@ import io.dico.dicore.command.* import io.dico.dicore.command.parameter.type.ParameterTypes import io.dico.parcels2.Interactables import io.dico.parcels2.ParcelProvider +import io.dico.parcels2.ParcelsPlugin import io.dico.parcels2.Privilege import org.bukkit.command.CommandSender import org.bukkit.entity.Player -class ParcelOptionsInteractCommand(val parcelProvider: ParcelProvider) : Command() { +class ParcelOptionsInteractCommand(val plugin: ParcelsPlugin) : Command() { init { setShortDescription("View and/or change the setting") @@ -20,10 +21,12 @@ class ParcelOptionsInteractCommand(val parcelProvider: ParcelProvider) : Command } override fun execute(sender: CommandSender, context: ExecutionContext): String? { + if (!plugin.storage.isConnected) err("Parcels cannot have their options changed right now because of a database error") + val interactableClass = Interactables[context.address.mainKey] val allowed: Boolean? = context.get("allowed") - val parcel = parcelProvider.getParcelRequired(sender as Player, + val parcel = plugin.parcelProvider.getParcelRequired(sender as Player, if (allowed == null) Privilege.DEFAULT else Privilege.CAN_MANAGE) if (allowed == null) { @@ -52,5 +55,3 @@ class ParcelOptionsInteractCommand(val parcelProvider: ParcelProvider) : Command } } - -private fun err(message: String): Nothing = throw CommandException(message) \ No newline at end of file diff --git a/src/main/kotlin/io/dico/parcels2/command/ParcelParameterTypes.kt b/src/main/kotlin/io/dico/parcels2/command/ParcelParameterTypes.kt index 8beef7f..ae58f94 100644 --- a/src/main/kotlin/io/dico/parcels2/command/ParcelParameterTypes.kt +++ b/src/main/kotlin/io/dico/parcels2/command/ParcelParameterTypes.kt @@ -3,8 +3,12 @@ package io.dico.parcels2.command import io.dico.dicore.command.CommandException import io.dico.dicore.command.parameter.ArgumentBuffer import io.dico.dicore.command.parameter.Parameter +import io.dico.dicore.command.parameter.type.ParameterConfig import io.dico.dicore.command.parameter.type.ParameterType import io.dico.parcels2.* +import io.dico.parcels2.command.ProfileKind.Companion.ANY +import io.dico.parcels2.command.ProfileKind.Companion.FAKE +import io.dico.parcels2.command.ProfileKind.Companion.REAL import org.bukkit.command.CommandSender import org.bukkit.entity.Player @@ -43,11 +47,27 @@ class ParcelParameterType(val parcelProvider: ParcelProvider) : ParameterType(PlayerProfile::class.java) { +annotation class ProfileKind(val kind: Int) { + companion object : ParameterConfig(ProfileKind::class.java) { + const val REAL = 1 + const val FAKE = 2 + const val ANY = 4 + + override fun toParameterInfo(annotation: ProfileKind): Int { + return annotation.kind + } + } +} + +class ProfileParameterType : ParameterType(PlayerProfile::class.java, ProfileKind) { + + override fun parse(parameter: Parameter, sender: CommandSender, buffer: ArgumentBuffer): PlayerProfile { + val info = parameter.paramInfo ?: REAL + val allowReal = info and REAL != 0 + val allowFake = info and FAKE != 0 - override fun parse(parameter: Parameter, sender: CommandSender, buffer: ArgumentBuffer): PlayerProfile { val input = buffer.next() - return PlayerProfile.byName(input, allowReal = true, allowFake = true) + return PlayerProfile.byName(input, allowReal, allowFake) } } diff --git a/src/main/kotlin/io/dico/parcels2/command/ParcelTarget.kt b/src/main/kotlin/io/dico/parcels2/command/ParcelTarget.kt index 8c0d718..2852ff0 100644 --- a/src/main/kotlin/io/dico/parcels2/command/ParcelTarget.kt +++ b/src/main/kotlin/io/dico/parcels2/command/ParcelTarget.kt @@ -4,13 +4,20 @@ import io.dico.dicore.command.parameter.ArgumentBuffer import io.dico.dicore.command.parameter.Parameter import io.dico.dicore.command.parameter.type.ParameterConfig import io.dico.dicore.command.parameter.type.ParameterType -import io.dico.parcels2.* +import io.dico.parcels2.Parcel +import io.dico.parcels2.ParcelProvider +import io.dico.parcels2.ParcelWorld +import io.dico.parcels2.PlayerProfile +import io.dico.parcels2.command.ParcelTarget.TargetKind.Companion.DEFAULT_KIND +import io.dico.parcels2.command.ParcelTarget.TargetKind.Companion.ID +import io.dico.parcels2.command.ParcelTarget.TargetKind.Companion.OWNER +import io.dico.parcels2.command.ParcelTarget.TargetKind.Companion.OWNER_FAKE +import io.dico.parcels2.command.ParcelTarget.TargetKind.Companion.OWNER_REAL +import io.dico.parcels2.command.ParcelTarget.TargetKind.Companion.PREFER_OWNED_FOR_DEFAULT +import io.dico.parcels2.command.ParcelTarget.TargetKind.Companion.REAL import io.dico.parcels2.storage.Storage import io.dico.parcels2.util.Vec2i import io.dico.parcels2.util.ext.floor -import kotlinx.coroutines.CoroutineStart.UNDISPATCHED -import kotlinx.coroutines.Deferred -import kotlinx.coroutines.async import org.bukkit.command.CommandSender import org.bukkit.entity.Player @@ -18,8 +25,6 @@ sealed class ParcelTarget(val world: ParcelWorld, val parsedKind: Int, val isDef abstract suspend fun getParcelSuspend(storage: Storage): Parcel? - fun ParcelsPlugin.getParcelDeferred(): Deferred = async(start = UNDISPATCHED) { getParcelSuspend(storage) } - class ByID(world: ParcelWorld, val id: Vec2i?, parsedKind: Int, isDefault: Boolean) : ParcelTarget(world, parsedKind, isDefault) { override suspend fun getParcelSuspend(storage: Storage): Parcel? = getParcel() fun getParcel() = id?.let { world.getParcelById(it) } @@ -61,29 +66,29 @@ sealed class ParcelTarget(val world: ParcelWorld, val parsedKind: Int, val isDef } } - companion object { - const val ID = 1 // ID - const val OWNER_REAL = 2 // an owner backed by a UUID - const val OWNER_FAKE = 4 // an owner not backed by a UUID + annotation class TargetKind(val kind: Int) { + companion object : ParameterConfig(TargetKind::class.java) { + const val ID = 1 // ID + const val OWNER_REAL = 2 // an owner backed by a UUID + const val OWNER_FAKE = 4 // an owner not backed by a UUID - const val OWNER = OWNER_REAL or OWNER_FAKE // any owner - const val ANY = ID or OWNER_REAL or OWNER_FAKE // any - const val REAL = ID or OWNER_REAL // no owner not backed by a UUID + const val OWNER = OWNER_REAL or OWNER_FAKE // any owner + const val ANY = ID or OWNER_REAL or OWNER_FAKE // any + const val REAL = ID or OWNER_REAL // no owner not backed by a UUID - const val DEFAULT_KIND = REAL + const val DEFAULT_KIND = REAL - const val PREFER_OWNED_FOR_DEFAULT = 8 // if the kind can be ID and OWNER_REAL, prefer OWNER_REAL for default - // instead of parcel that the player is in - } + const val PREFER_OWNED_FOR_DEFAULT = 8 // if the kind can be ID and OWNER_REAL, prefer OWNER_REAL for default + // instead of parcel that the player is in - annotation class Kind(val kind: Int) - private object Config : ParameterConfig(Kind::class.java) { - override fun toParameterInfo(annotation: Kind): Int { - return annotation.kind + override fun toParameterInfo(annotation: TargetKind): Int { + return annotation.kind + } } } - class PType(val parcelProvider: ParcelProvider, val parcelAddress: SpecialCommandAddress? = null) : ParameterType(ParcelTarget::class.java, Config) { + class PType(val parcelProvider: ParcelProvider, val parcelAddress: SpecialCommandAddress? = null) : + ParameterType(ParcelTarget::class.java, TargetKind) { override fun parse(parameter: Parameter, sender: CommandSender, buffer: ArgumentBuffer): ParcelTarget { var input = buffer.next() diff --git a/src/main/kotlin/io/dico/parcels2/defaultimpl/DefaultParcelGenerator.kt b/src/main/kotlin/io/dico/parcels2/defaultimpl/DefaultParcelGenerator.kt index 1c513f8..7ccb458 100644 --- a/src/main/kotlin/io/dico/parcels2/defaultimpl/DefaultParcelGenerator.kt +++ b/src/main/kotlin/io/dico/parcels2/defaultimpl/DefaultParcelGenerator.kt @@ -219,7 +219,7 @@ class DefaultParcelGenerator( skullBlock.type = Material.PLAYER_HEAD val skull = skullBlock.state as Skull if (owner is PlayerProfile.Real) { - skull.owningPlayer = owner.playerUnchecked + skull.owningPlayer = Bukkit.getOfflinePlayer(owner.uuid) } else { skull.owner = owner.name } diff --git a/src/main/kotlin/io/dico/parcels2/listener/ListenerHelper.kt b/src/main/kotlin/io/dico/parcels2/listener/ListenerHelper.kt deleted file mode 100644 index e8617fd..0000000 --- a/src/main/kotlin/io/dico/parcels2/listener/ListenerHelper.kt +++ /dev/null @@ -1,16 +0,0 @@ -package io.dico.parcels2.listener - -import io.dico.dicore.RegistratorListener -import io.dico.parcels2.ParcelsPlugin -import org.bukkit.event.Event - -interface HasPlugin { - val plugin: ParcelsPlugin -} - -inline fun HasPlugin.listener(crossinline block: suspend (T) -> Unit) = RegistratorListener { event -> - - -} - - diff --git a/src/main/kotlin/io/dico/parcels2/listener/ParcelListeners.kt b/src/main/kotlin/io/dico/parcels2/listener/ParcelListeners.kt index f838950..a62f569 100644 --- a/src/main/kotlin/io/dico/parcels2/listener/ParcelListeners.kt +++ b/src/main/kotlin/io/dico/parcels2/listener/ParcelListeners.kt @@ -60,7 +60,7 @@ class ParcelListeners( val user = event.player if (user.hasPermBanBypass) return@l val parcel = parcelProvider.getParcelAt(event.to) ?: return@l - if (!parcel.canEnter(user)) { + if (!parcel.canEnterFast(user)) { parcelProvider.getParcelAt(event.from)?.also { user.teleport(it.homeLocation) user.sendParcelMessage(nopermit = true, message = "You are banned from this parcel") diff --git a/src/main/kotlin/io/dico/parcels2/util/BukkitUtil.kt b/src/main/kotlin/io/dico/parcels2/util/BukkitUtil.kt new file mode 100644 index 0000000..d6837bd --- /dev/null +++ b/src/main/kotlin/io/dico/parcels2/util/BukkitUtil.kt @@ -0,0 +1,12 @@ +package io.dico.parcels2.util + +import io.dico.parcels2.util.ext.isValid +import org.bukkit.Bukkit +import org.bukkit.OfflinePlayer +import java.util.UUID + +fun getPlayerName(uuid: UUID): String? = getOfflinePlayer(uuid)?.name + +fun getOfflinePlayer(uuid: UUID): OfflinePlayer? = Bukkit.getOfflinePlayer(uuid).takeIf { it.isValid } + +fun getOfflinePlayer(name: String): OfflinePlayer? = Bukkit.getOfflinePlayer(name).takeIf { it.isValid } diff --git a/src/main/kotlin/io/dico/parcels2/util/UUIDUtil.kt b/src/main/kotlin/io/dico/parcels2/util/UUIDUtil.kt deleted file mode 100644 index 1398037..0000000 --- a/src/main/kotlin/io/dico/parcels2/util/UUIDUtil.kt +++ /dev/null @@ -1,14 +0,0 @@ -package io.dico.parcels2.util - -import io.dico.parcels2.util.ext.isValid -import org.bukkit.Bukkit -import java.nio.ByteBuffer -import java.util.UUID - -const val PLAYER_NAME_PLACEHOLDER = ":unknown_name:" - -fun getPlayerName(uuid: UUID): String? { - return Bukkit.getOfflinePlayer(uuid)?.takeIf { it.isValid }?.name -} - - diff --git a/src/main/kotlin/io/dico/parcels2/util/ext/Misc.kt b/src/main/kotlin/io/dico/parcels2/util/ext/Misc.kt index e4c2b4c..4df4d52 100644 --- a/src/main/kotlin/io/dico/parcels2/util/ext/Misc.kt +++ b/src/main/kotlin/io/dico/parcels2/util/ext/Misc.kt @@ -2,7 +2,10 @@ package io.dico.parcels2.util.ext import io.dico.dicore.Formatting import io.dico.parcels2.logger +import org.bukkit.Bukkit +import org.bukkit.OfflinePlayer import java.io.File +import java.util.UUID fun File.tryCreate(): Boolean { if (exists()) { diff --git a/src/main/kotlin/io/dico/parcels2/util/ext/Player.kt b/src/main/kotlin/io/dico/parcels2/util/ext/Player.kt index 1875ff8..a7f21c5 100644 --- a/src/main/kotlin/io/dico/parcels2/util/ext/Player.kt +++ b/src/main/kotlin/io/dico/parcels2/util/ext/Player.kt @@ -52,4 +52,6 @@ fun Player.sendParcelMessage(except: Boolean = false, nopermit: Boolean = false, } else { sendMessage(prefix + Formatting.translateChars('&', message)) } -} \ No newline at end of file +} + +const val PLAYER_NAME_PLACEHOLDER = ":unknown_name:" -- cgit v1.2.3