From cdaba0ebd5b48d1f2d4579c873d83fdf6ea1a074 Mon Sep 17 00:00:00 2001 From: Dico Date: Thu, 27 Sep 2018 02:58:06 +0100 Subject: Fix privileges of * --- .../dicore/command/predef/DefaultGroupCommand.java | 4 + src/main/kotlin/io/dico/parcels2/Parcel.kt | 8 +- src/main/kotlin/io/dico/parcels2/PlayerProfile.kt | 5 +- src/main/kotlin/io/dico/parcels2/Privilege.kt | 122 ++++++--------------- src/main/kotlin/io/dico/parcels2/Privileges.kt | 64 +++++++++++ .../dico/parcels2/blockvisitor/RegionTraverser.kt | 6 +- .../parcels2/command/AbstractParcelCommands.kt | 9 ++ .../command/CommandsAdminPrivilegesGlobal.kt | 110 +++++++++++++++++++ .../parcels2/command/CommandsPrivilegesGlobal.kt | 65 +++-------- .../parcels2/command/CommandsPrivilegesLocal.kt | 68 +++++++----- .../dico/parcels2/command/ParcelCommandBuilder.kt | 16 ++- .../parcels2/command/ParcelCommandReceivers.kt | 5 +- .../dico/parcels2/command/ParcelParameterTypes.kt | 5 +- .../defaultimpl/GlobalPrivilegesManagerImpl.kt | 23 +--- .../io/dico/parcels2/defaultimpl/ParcelImpl.kt | 110 +++++++++++-------- .../io/dico/parcels2/listener/WorldEditListener.kt | 1 + src/main/kotlin/io/dico/parcels2/util/ext/Misc.kt | 4 + .../kotlin/io/dico/parcels2/util/ext/Player.kt | 13 ++- 18 files changed, 388 insertions(+), 250 deletions(-) create mode 100644 src/main/kotlin/io/dico/parcels2/Privileges.kt create mode 100644 src/main/kotlin/io/dico/parcels2/command/CommandsAdminPrivilegesGlobal.kt diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/predef/DefaultGroupCommand.java b/dicore3/command/src/main/java/io/dico/dicore/command/predef/DefaultGroupCommand.java index 6b389e3..6c03d8e 100644 --- a/dicore3/command/src/main/java/io/dico/dicore/command/predef/DefaultGroupCommand.java +++ b/dicore3/command/src/main/java/io/dico/dicore/command/predef/DefaultGroupCommand.java @@ -17,6 +17,10 @@ public class DefaultGroupCommand extends PredefinedCommand this.modifiable = modifiable; } + public DefaultGroupCommand() { + this(true); + } + @Override protected DefaultGroupCommand newModifiableInstance() { return new DefaultGroupCommand(true); diff --git a/src/main/kotlin/io/dico/parcels2/Parcel.kt b/src/main/kotlin/io/dico/parcels2/Parcel.kt index 75f963f..22ec0df 100644 --- a/src/main/kotlin/io/dico/parcels2/Parcel.kt +++ b/src/main/kotlin/io/dico/parcels2/Parcel.kt @@ -38,7 +38,7 @@ interface Parcel : ParcelData, Privileges { val homeLocation: Location get() = world.blockManager.getHomeLocation(id) } -interface ParcelData : PrivilegesMinimal { +interface ParcelData : RawPrivileges { var owner: PlayerProfile? val lastClaimTime: DateTime? var ownerSignOutdated: Boolean @@ -60,12 +60,6 @@ class ParcelDataHolder(addedMap: MutablePrivilegeMap = mutableMapOf()) override var owner: PlayerProfile? = null override var lastClaimTime: DateTime? = null override var ownerSignOutdated = false - - //override fun canBuild(player: OfflinePlayer, checkAdmin: Boolean, checkGlobal: Boolean) = - // hasPrivilegeToBuild(player) - // || owner.let { it != null && it.matches(player, allowNameMatch = false) } - // || (checkAdmin && player is Player && player.hasPermBuildAnywhere) - override var interactableConfig: InteractableConfiguration = BitmaskInteractableConfiguration() } diff --git a/src/main/kotlin/io/dico/parcels2/PlayerProfile.kt b/src/main/kotlin/io/dico/parcels2/PlayerProfile.kt index 53e2d76..ae73639 100644 --- a/src/main/kotlin/io/dico/parcels2/PlayerProfile.kt +++ b/src/main/kotlin/io/dico/parcels2/PlayerProfile.kt @@ -115,7 +115,10 @@ interface PlayerProfile { } object Star : BaseImpl(), Real { - override val name: String = "*" + override val name get() = "*" + override val nameOrBukkitName get() = name + override val notNullName get() = name + // hopefully nobody will have this random UUID :) override val uuid: UUID = UUID.fromString("7d09c4c6-117d-4f36-9778-c4d24618cee1") diff --git a/src/main/kotlin/io/dico/parcels2/Privilege.kt b/src/main/kotlin/io/dico/parcels2/Privilege.kt index 72878a9..bc16f77 100644 --- a/src/main/kotlin/io/dico/parcels2/Privilege.kt +++ b/src/main/kotlin/io/dico/parcels2/Privilege.kt @@ -1,12 +1,17 @@ package io.dico.parcels2 -import io.dico.parcels2.Privilege.* -import io.dico.parcels2.PrivilegeChangeResult.* -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 org.bukkit.OfflinePlayer -import org.bukkit.entity.Player +import io.dico.parcels2.Privilege.DEFAULT +import java.util.Collections + +typealias PrivilegeKey = PlayerProfile.Real +typealias PrivilegeMap = Map +typealias MutablePrivilegeMap = MutableMap + +@Suppress("FunctionName") +fun MutablePrivilegeMap(): MutablePrivilegeMap = hashMapOf() + +@Suppress("UNCHECKED_CAST") +val EmptyPrivilegeMap = Collections.emptyMap() as MutablePrivilegeMap enum class Privilege( val number: Int, @@ -21,7 +26,7 @@ enum class Privilege( ADMIN(-1, transient = true); fun isDistanceGrEq(other: Privilege): Boolean = - when { // used for example when disallowBuild is called and CAN_MANAGE is the privilege. + when { other > DEFAULT -> this >= other other == DEFAULT -> this == other else -> this <= other @@ -38,12 +43,6 @@ enum class Privilege( return this } - /* - fun canEnter() = this >= BANNED - fun canBuild() = this >= CAN_BUILD - fun canManage() = this >= CAN_MANAGE - */ - companion object { fun getByNumber(id: Int) = when (id) { @@ -56,95 +55,44 @@ enum class Privilege( } } -typealias PrivilegeKey = PlayerProfile.Real -typealias MutablePrivilegeMap = MutableMap -typealias PrivilegeMap = Map - -@Suppress("FunctionName") -fun MutablePrivilegeMap(): MutablePrivilegeMap = hashMapOf() - -interface PrivilegesMinimal { +interface RawPrivileges { val privilegeMap: PrivilegeMap + var privilegeOfStar: Privilege - fun getStoredPrivilege(key: PrivilegeKey): Privilege - fun setStoredPrivilege(key: PrivilegeKey, privilege: Privilege): Boolean -} - -interface Privileges : PrivilegesMinimal { - val keyOfOwner: PlayerProfile.Real? - - fun privilege(player: OfflinePlayer): Privilege { - val key = player.privilegeKey - return if (key == keyOfOwner) OWNER - else getStoredPrivilege(key) - } - - fun privilege(player: OfflinePlayer, adminPerm: String): Privilege = - if (player is Player && player.hasPermission(adminPerm)) ADMIN - else { - val key = player.privilegeKey - if (key == keyOfOwner) OWNER - else getStoredPrivilege(key) - } - - fun changePrivilege(key: PrivilegeKey, positive: Boolean, update: Privilege): PrivilegeChangeResult = - if (key == keyOfOwner) FAIL_OWNER - else if (getStoredPrivilege(key).isChangeInDirection(positive, update) - && setStoredPrivilege(key, update) - ) SUCCESS - else FAIL - - fun canManage(player: OfflinePlayer) = privilege(player, PERM_ADMIN_MANAGE) >= CAN_MANAGE - fun allowManage(player: OfflinePlayer) = changePrivilege(player.privilegeKey, true, CAN_MANAGE) - fun disallowManage(player: OfflinePlayer) = changePrivilege(player.privilegeKey, false, CAN_BUILD) - - fun canBuild(player: OfflinePlayer) = privilege(player, PERM_BUILD_ANYWHERE) >= CAN_BUILD - fun allowBuild(player: OfflinePlayer) = changePrivilege(player.privilegeKey, true, CAN_BUILD) - fun disallowBuild(player: OfflinePlayer) = changePrivilege(player.privilegeKey, false, DEFAULT) - - fun canEnter(player: OfflinePlayer) = privilege(player, PERM_BAN_BYPASS) >= DEFAULT - fun ban(player: OfflinePlayer) = changePrivilege(player.privilegeKey, false, BANNED) - fun unban(player: OfflinePlayer) = changePrivilege(player.privilegeKey, true, DEFAULT) - - /** - * same as [canBuild] but doesn't perform a permission check for admin perms - */ - fun canBuildFast(player: OfflinePlayer) = player.privilegeKey.let { if (it == keyOfOwner) OWNER else getStoredPrivilege(it)} >= CAN_BUILD + fun getRawStoredPrivilege(key: PrivilegeKey): Privilege + fun setRawStoredPrivilege(key: PrivilegeKey, privilege: Privilege): Boolean } -enum class PrivilegeChangeResult { - SUCCESS, FAIL, FAIL_OWNER -} +open class PrivilegesHolder(override var privilegeMap: MutablePrivilegeMap = EmptyPrivilegeMap) : RawPrivileges { + private var _privilegeOfStar: Privilege = DEFAULT -val OfflinePlayer.privilegeKey: PrivilegeKey - inline get() = PlayerProfile.nameless(this) + override var privilegeOfStar: Privilege + get() = _privilegeOfStar + set(value) = run { _privilegeOfStar = value } -open class PrivilegesHolder(override var privilegeMap: MutablePrivilegeMap = MutablePrivilegeMap()) : PrivilegesMinimal { - private var privilegeOfStar: Privilege = DEFAULT + protected val isEmpty + inline get() = privilegeMap === EmptyPrivilegeMap - override fun getStoredPrivilege(key: PrivilegeKey) = - if (key.isStar) privilegeOfStar - else privilegeMap.getOrDefault(key, privilegeOfStar) + override fun getRawStoredPrivilege(key: PrivilegeKey) = + if (key.isStar) _privilegeOfStar + else privilegeMap.getOrDefault(key, _privilegeOfStar) - override fun setStoredPrivilege(key: PrivilegeKey, privilege: Privilege): Boolean { + override fun setRawStoredPrivilege(key: PrivilegeKey, privilege: Privilege): Boolean { privilege.requireNonTransient() if (key.isStar) { - if (privilegeOfStar == privilege) return false - privilegeOfStar = privilege + if (_privilegeOfStar == privilege) return false + _privilegeOfStar = privilege return true } + if (isEmpty) { + if (privilege == DEFAULT) return false + privilegeMap = MutablePrivilegeMap() + } + return if (privilege == DEFAULT) privilegeMap.remove(key) != null else privilegeMap.put(key, privilege) != privilege } } -interface GlobalPrivileges : Privileges { - override val keyOfOwner: PlayerProfile.Real -} - -interface GlobalPrivilegesManager { - operator fun get(owner: PlayerProfile.Real): GlobalPrivileges - operator fun get(owner: OfflinePlayer): GlobalPrivileges = get(owner.privilegeKey) -} diff --git a/src/main/kotlin/io/dico/parcels2/Privileges.kt b/src/main/kotlin/io/dico/parcels2/Privileges.kt new file mode 100644 index 0000000..632f1a4 --- /dev/null +++ b/src/main/kotlin/io/dico/parcels2/Privileges.kt @@ -0,0 +1,64 @@ +package io.dico.parcels2 + +import io.dico.parcels2.PrivilegeChangeResult.* +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 org.bukkit.OfflinePlayer +import org.bukkit.entity.Player + +interface Privileges : RawPrivileges { + val keyOfOwner: PlayerProfile.Real? + + fun getStoredPrivilege(key: PrivilegeKey): Privilege { + return if (key == keyOfOwner) Privilege.OWNER + else getRawStoredPrivilege(key) + } + + override var privilegeOfStar: Privilege + get() = getStoredPrivilege(PlayerProfile.Star) + set(value) { + setRawStoredPrivilege(PlayerProfile.Star, value) + } +} + +val OfflinePlayer.privilegeKey: PrivilegeKey + inline get() = PlayerProfile.nameless(this) + +fun Privileges.getEffectivePrivilege(player: OfflinePlayer, adminPerm: String): Privilege = + if (player is Player && player.hasPermission(adminPerm)) Privilege.ADMIN + else getStoredPrivilege(player.privilegeKey) + +fun Privileges.canManage(player: OfflinePlayer) = getEffectivePrivilege(player, PERM_ADMIN_MANAGE) >= Privilege.CAN_MANAGE +fun Privileges.canManageFast(player: OfflinePlayer) = getStoredPrivilege(player.privilegeKey) >= Privilege.CAN_MANAGE +fun Privileges.canBuild(player: OfflinePlayer) = getEffectivePrivilege(player, PERM_BUILD_ANYWHERE) >= Privilege.CAN_BUILD +fun Privileges.canBuildFast(player: OfflinePlayer) = getStoredPrivilege(player.privilegeKey) >= Privilege.CAN_BUILD +fun Privileges.canEnter(player: OfflinePlayer) = getEffectivePrivilege(player, PERM_BAN_BYPASS) >= Privilege.DEFAULT +fun Privileges.canEnterFast(player: OfflinePlayer) = getStoredPrivilege(player.privilegeKey) >= Privilege.DEFAULT + +enum class PrivilegeChangeResult { + SUCCESS, FAIL, FAIL_OWNER +} + +fun Privileges.changePrivilege(key: PrivilegeKey, positive: Boolean, update: Privilege): PrivilegeChangeResult = + when { + key == keyOfOwner -> FAIL_OWNER + getRawStoredPrivilege(key).isChangeInDirection(positive, update) && setRawStoredPrivilege(key, update) -> SUCCESS + else -> FAIL + } + +fun Privileges.allowManage(key: PrivilegeKey) = changePrivilege(key, true, Privilege.CAN_MANAGE) +fun Privileges.disallowManage(key: PrivilegeKey) = changePrivilege(key, false, Privilege.CAN_BUILD) +fun Privileges.allowBuild(key: PrivilegeKey) = changePrivilege(key, true, Privilege.CAN_BUILD) +fun Privileges.disallowBuild(key: PrivilegeKey) = changePrivilege(key, false, Privilege.DEFAULT) +fun Privileges.allowEnter(key: PrivilegeKey) = changePrivilege(key, true, Privilege.DEFAULT) +fun Privileges.disallowEnter(key: PrivilegeKey) = changePrivilege(key, false, Privilege.BANNED) + +interface GlobalPrivileges : RawPrivileges, Privileges { + override val keyOfOwner: PlayerProfile.Real +} + +interface GlobalPrivilegesManager { + operator fun get(owner: PlayerProfile.Real): GlobalPrivileges + operator fun get(owner: OfflinePlayer): GlobalPrivileges = get(owner.privilegeKey) +} diff --git a/src/main/kotlin/io/dico/parcels2/blockvisitor/RegionTraverser.kt b/src/main/kotlin/io/dico/parcels2/blockvisitor/RegionTraverser.kt index c49faa2..feab318 100644 --- a/src/main/kotlin/io/dico/parcels2/blockvisitor/RegionTraverser.kt +++ b/src/main/kotlin/io/dico/parcels2/blockvisitor/RegionTraverser.kt @@ -83,9 +83,9 @@ sealed class RegionTraverser { private fun slice(region: Region, atY: Int): Pair { if (atY < region.size.y + 1) { - val first = Region(region.origin, region.size.withY(atY + 1)) - val second = Region(region.origin.withY(atY), region.size.addY(-atY - 1)) - return first to second + val bottom = Region(region.origin, region.size.withY(atY + 1)) + val top = Region(region.origin.withY(atY + 1), region.size.addY(-atY - 1)) + return bottom to top } return region to null } diff --git a/src/main/kotlin/io/dico/parcels2/command/AbstractParcelCommands.kt b/src/main/kotlin/io/dico/parcels2/command/AbstractParcelCommands.kt index 6d62729..a660fc0 100644 --- a/src/main/kotlin/io/dico/parcels2/command/AbstractParcelCommands.kt +++ b/src/main/kotlin/io/dico/parcels2/command/AbstractParcelCommands.kt @@ -4,6 +4,8 @@ import io.dico.dicore.command.* import io.dico.parcels2.ParcelWorld import io.dico.parcels2.ParcelsPlugin import io.dico.parcels2.PlayerProfile +import io.dico.parcels2.PlayerProfile.* +import io.dico.parcels2.PrivilegeKey import io.dico.parcels2.blockvisitor.Worker import io.dico.parcels2.util.ext.hasPermAdminManage import io.dico.parcels2.util.ext.parcelLimit @@ -37,6 +39,13 @@ abstract class AbstractParcelCommands(val plugin: ParcelsPlugin) : ICommandRecei } } + protected suspend fun toPrivilegeKey(profile: PlayerProfile): PrivilegeKey = when (profile) { + is Real -> profile + is Unresolved -> profile.tryResolveSuspendedly(plugin.storage) + ?: throw CommandException() + else -> throw CommandException() + } + protected fun areYouSureMessage(context: ExecutionContext) = "Are you sure? You cannot undo this action!\n" + "Run \"/${context.route.joinToString(" ")} -sure\" if you want to go through with this." diff --git a/src/main/kotlin/io/dico/parcels2/command/CommandsAdminPrivilegesGlobal.kt b/src/main/kotlin/io/dico/parcels2/command/CommandsAdminPrivilegesGlobal.kt new file mode 100644 index 0000000..1bd42e8 --- /dev/null +++ b/src/main/kotlin/io/dico/parcels2/command/CommandsAdminPrivilegesGlobal.kt @@ -0,0 +1,110 @@ +@file:Suppress("NON_EXHAUSTIVE_WHEN") + +package io.dico.parcels2.command + +import io.dico.dicore.command.ExecutionContext +import io.dico.dicore.command.Validate +import io.dico.dicore.command.annotation.Cmd +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 { + val sender = context.sender + if (sender !== owner) { + Validate.isAuthorized(sender, PERM_ADMIN_MANAGE) + } + return owner + } + + @Cmd("entrust") + @Desc( + "Allows a player to manage globally", + shortVersion = "allows a player to manage globally" + ) + suspend fun cmdEntrust(context: ExecutionContext, owner: OfflinePlayer, player: PlayerProfile): Any? = + when (data[checkContext(context, owner)].allowManage(toPrivilegeKey(player))) { + FAIL_OWNER -> err("The target cannot be the owner themselves") + FAIL -> err("${player.name} is already allowed to manage globally") + SUCCESS -> "${player.name} is now allowed to manage globally" + } + + @Cmd("distrust") + @Desc( + "Disallows a player to manage globally,", + "they will still be able to build", + shortVersion = "disallows a player to manage globally" + ) + suspend fun cmdDistrust(context: ExecutionContext, owner: OfflinePlayer, player: PlayerProfile): Any? = + when (data[checkContext(context, owner)].disallowManage(toPrivilegeKey(player))) { + FAIL_OWNER -> err("The target cannot be the owner themselves") + FAIL -> err("${player.name} is not currently allowed to manage globally") + SUCCESS -> "${player.name} is not allowed to manage globally anymore" + } + + @Cmd("allow", aliases = ["add", "permit"]) + @Desc( + "Globally allows a player to build on all", + "the parcels that you own.", + shortVersion = "globally allows a player to build on your parcels" + ) + suspend fun cmdAllow(context: ExecutionContext, owner: OfflinePlayer, player: PlayerProfile): Any? = + when (data[checkContext(context, owner)].allowBuild(toPrivilegeKey(player))) { + FAIL_OWNER -> err("The target cannot be the owner themselves") + FAIL -> err("${player.name} is already allowed globally") + SUCCESS -> "${player.name} is now allowed to build globally" + } + + @Cmd("disallow", aliases = ["remove", "forbid"]) + @Desc( + "Globally disallows a player to build on", + "the parcels that you own.", + "If the player is allowed to build on specific", + "parcels, they can still build there.", + shortVersion = "globally disallows a player to build on your parcels" + ) + suspend fun cmdDisallow(context: ExecutionContext, owner: OfflinePlayer, player: PlayerProfile): Any? = + when (data[checkContext(context, owner)].disallowBuild(toPrivilegeKey(player))) { + FAIL_OWNER -> err("The target cannot be the owner themselves") + FAIL -> err("${player.name} is not currently allowed globally") + SUCCESS -> "${player.name} is not allowed to build globally anymore" + } + + @Cmd("ban", aliases = ["deny"]) + @Desc( + "Globally bans a player from all the parcels", + "that you own, making them unable to enter.", + shortVersion = "globally bans a player from your parcels" + ) + suspend fun cmdBan(context: ExecutionContext, owner: OfflinePlayer, player: PlayerProfile): Any? = + when (data[checkContext(context, owner)].disallowEnter(toPrivilegeKey(player))) { + FAIL_OWNER -> err("The target cannot be the owner themselves") + FAIL -> err("${player.name} is already banned globally") + SUCCESS -> "${player.name} is now banned globally" + } + + @Cmd("unban", aliases = ["undeny"]) + @Desc( + "Globally unbans a player from all the parcels", + "that you own, they can enter again.", + "If the player is banned from specific parcels,", + "they will still be banned there.", + shortVersion = "globally unbans a player from your parcels" + ) + suspend fun cmdUnban(context: ExecutionContext, owner: OfflinePlayer, player: PlayerProfile): Any? = + when (data[checkContext(context, owner)].allowEnter(toPrivilegeKey(player))) { + FAIL_OWNER -> err("The target cannot be the owner themselves") + FAIL -> err("${player.name} is not currently banned globally") + SUCCESS -> "${player.name} is not banned globally anymore" + } + +} \ No newline at end of file diff --git a/src/main/kotlin/io/dico/parcels2/command/CommandsPrivilegesGlobal.kt b/src/main/kotlin/io/dico/parcels2/command/CommandsPrivilegesGlobal.kt index e225cb5..9e3ac23 100644 --- a/src/main/kotlin/io/dico/parcels2/command/CommandsPrivilegesGlobal.kt +++ b/src/main/kotlin/io/dico/parcels2/command/CommandsPrivilegesGlobal.kt @@ -1,29 +1,21 @@ -@file:Suppress("NON_EXHAUSTIVE_WHEN") - package io.dico.parcels2.command +import io.dico.dicore.command.ExecutionContext import io.dico.dicore.command.annotation.Cmd import io.dico.dicore.command.annotation.Desc import io.dico.parcels2.ParcelsPlugin -import io.dico.parcels2.PrivilegeChangeResult.* -import org.bukkit.OfflinePlayer +import io.dico.parcels2.PlayerProfile import org.bukkit.entity.Player -class CommandsPrivilegesGlobal(plugin: ParcelsPlugin) : AbstractParcelCommands(plugin) { - private val data - inline get() = plugin.globalPrivileges - +class CommandsPrivilegesGlobal(plugin: ParcelsPlugin, + val adminVersion: CommandsAdminPrivilegesGlobal) : AbstractParcelCommands(plugin) { @Cmd("entrust") @Desc( - "Allows a player to manage this parcel", - shortVersion = "allows a player to manage this parcel" + "Allows a player to manage globally", + shortVersion = "allows a player to manage globally" ) - fun cmdEntrust(sender: Player, player: OfflinePlayer): Any? = - when (data[sender].allowManage(player)) { - FAIL_OWNER -> err("The target cannot be yourself") - FAIL -> err("${player.name} is already allowed to manage globally") - SUCCESS -> "${player.name} is now allowed to manage globally" - } + suspend fun cmdEntrust(sender: Player, context: ExecutionContext, player: PlayerProfile) = + adminVersion.cmdEntrust(context, sender, player) @Cmd("distrust") @Desc( @@ -31,12 +23,8 @@ class CommandsPrivilegesGlobal(plugin: ParcelsPlugin) : AbstractParcelCommands(p "they will still be able to build", shortVersion = "disallows a player to manage globally" ) - fun cmdDistrust(sender: Player, player: OfflinePlayer): Any? = - when (data[sender].disallowManage(player)) { - FAIL_OWNER -> err("The target cannot be yourself") - FAIL -> err("${player.name} is not currently allowed to manage globally") - SUCCESS -> "${player.name} is not allowed to manage globally anymore" - } + suspend fun cmdDistrust(sender: Player, context: ExecutionContext, player: PlayerProfile) = + adminVersion.cmdDistrust(context, sender, player) @Cmd("allow", aliases = ["add", "permit"]) @Desc( @@ -44,12 +32,8 @@ class CommandsPrivilegesGlobal(plugin: ParcelsPlugin) : AbstractParcelCommands(p "the parcels that you own.", shortVersion = "globally allows a player to build on your parcels" ) - fun cmdAllow(sender: Player, player: OfflinePlayer): Any? = - when (data[sender].allowBuild(player)) { - FAIL_OWNER -> err("The target cannot be yourself") - FAIL -> err("${player.name} is already allowed globally") - SUCCESS -> "${player.name} is now allowed to build on all your parcels" - } + suspend fun cmdAllow(sender: Player, context: ExecutionContext, player: PlayerProfile) = + adminVersion.cmdAllow(context, sender, player) @Cmd("disallow", aliases = ["remove", "forbid"]) @Desc( @@ -59,12 +43,8 @@ class CommandsPrivilegesGlobal(plugin: ParcelsPlugin) : AbstractParcelCommands(p "parcels, they can still build there.", shortVersion = "globally disallows a player to build on your parcels" ) - fun cmdDisallow(sender: Player, player: OfflinePlayer): Any? = - when (data[sender].disallowBuild(player)) { - FAIL_OWNER -> err("The target cannot be yourself") - FAIL -> err("${player.name} is not currently allowed globally") - SUCCESS -> "${player.name} is not allowed to build on all your parcels anymore" - } + suspend fun cmdDisallow(sender: Player, context: ExecutionContext, player: PlayerProfile) = + adminVersion.cmdDisallow(context, sender, player) @Cmd("ban", aliases = ["deny"]) @Desc( @@ -72,12 +52,8 @@ class CommandsPrivilegesGlobal(plugin: ParcelsPlugin) : AbstractParcelCommands(p "that you own, making them unable to enter.", shortVersion = "globally bans a player from your parcels" ) - fun cmdBan(sender: Player, player: OfflinePlayer): Any? = - when (data[sender].ban(player)) { - FAIL_OWNER -> err("The target cannot be yourself") - FAIL -> err("${player.name} is already banned from all your parcels") - SUCCESS -> "${player.name} is now banned from all your parcels" - } + suspend fun cmdBan(sender: Player, context: ExecutionContext, player: PlayerProfile) = + adminVersion.cmdBan(context, sender, player) @Cmd("unban", aliases = ["undeny"]) @Desc( @@ -87,11 +63,6 @@ class CommandsPrivilegesGlobal(plugin: ParcelsPlugin) : AbstractParcelCommands(p "they will still be banned there.", shortVersion = "globally unbans a player from your parcels" ) - fun cmdUnban(sender: Player, player: OfflinePlayer): Any? = - when (data[sender].unban(player)) { - FAIL_OWNER -> err("The target cannot be yourself") - FAIL -> err("${player.name} is not currently banned from all your parcels") - SUCCESS -> "${player.name} is not banned from all your parcels anymore" - } - + suspend fun cmdUnban(sender: Player, context: ExecutionContext, player: PlayerProfile) = + adminVersion.cmdUnban(context, sender, player) } \ No newline at end of file diff --git a/src/main/kotlin/io/dico/parcels2/command/CommandsPrivilegesLocal.kt b/src/main/kotlin/io/dico/parcels2/command/CommandsPrivilegesLocal.kt index 5202683..f347f06 100644 --- a/src/main/kotlin/io/dico/parcels2/command/CommandsPrivilegesLocal.kt +++ b/src/main/kotlin/io/dico/parcels2/command/CommandsPrivilegesLocal.kt @@ -3,20 +3,22 @@ package io.dico.parcels2.command import io.dico.dicore.command.Validate import io.dico.dicore.command.annotation.Cmd import io.dico.dicore.command.annotation.Desc -import io.dico.parcels2.ParcelsPlugin -import io.dico.parcels2.Privilege +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.entity.Player class CommandsPrivilegesLocal(plugin: ParcelsPlugin) : AbstractParcelCommands(plugin) { - private fun ParcelScope.checkPrivilege(sender: Player, player: OfflinePlayer) { - if (!sender.hasPermAdminManage) { - Validate.isTrue(parcel.owner != null, "This parcel is unowned") - Validate.isTrue(parcel.privilege(sender) > parcel.privilege(player), "You may not change the privilege of ${player.name}") - } + private fun ParcelScope.checkPrivilege(sender: Player, key: PrivilegeKey) { + val senderPrivilege = parcel.getEffectivePrivilege(sender, PERM_ADMIN_MANAGE) + val targetPrivilege = parcel.getStoredPrivilege(key) + Validate.isTrue(senderPrivilege > targetPrivilege, "You may not change the privilege of ${key.notNullName}") + } + + private fun ParcelScope.checkOwned(sender: Player) { + Validate.isTrue(parcel.owner != null || sender.hasPermAdminManage, "This parcel is unowned") } @Cmd("entrust") @@ -25,10 +27,11 @@ class CommandsPrivilegesLocal(plugin: ParcelsPlugin) : AbstractParcelCommands(pl shortVersion = "allows a player to manage this parcel" ) @RequireParcelPrivilege(Privilege.OWNER) - fun ParcelScope.cmdEntrust(sender: Player, player: OfflinePlayer): Any? { - Validate.isTrue(parcel.owner != null || sender.hasPermAdminManage, "This parcel is unowned") + suspend fun ParcelScope.cmdEntrust(sender: Player, player: PlayerProfile): Any? { + checkOwned(sender) - return when (parcel.allowManage(player)) { + val key = toPrivilegeKey(player) + return when (parcel.allowManage(key)) { FAIL_OWNER -> err("The target already owns the parcel") FAIL -> err("${player.name} is already allowed to manage this parcel") SUCCESS -> "${player.name} is now allowed to manage this parcel" @@ -42,10 +45,11 @@ class CommandsPrivilegesLocal(plugin: ParcelsPlugin) : AbstractParcelCommands(pl shortVersion = "disallows a player to manage this parcel" ) @RequireParcelPrivilege(Privilege.OWNER) - fun ParcelScope.cmdDistrust(sender: Player, player: OfflinePlayer): Any? { - Validate.isTrue(parcel.owner != null || sender.hasPermAdminManage, "This parcel is unowned") + suspend fun ParcelScope.cmdDistrust(sender: Player, player: PlayerProfile): Any? { + checkOwned(sender) - return when (parcel.disallowManage(player)) { + val key = toPrivilegeKey(player) + return when (parcel.disallowManage(key)) { FAIL_OWNER -> err("The target owns the parcel and can't be distrusted") FAIL -> err("${player.name} is not currently allowed to manage this parcel") SUCCESS -> "${player.name} is not allowed to manage this parcel anymore" @@ -58,10 +62,13 @@ class CommandsPrivilegesLocal(plugin: ParcelsPlugin) : AbstractParcelCommands(pl shortVersion = "allows a player to build on this parcel" ) @RequireParcelPrivilege(Privilege.CAN_MANAGE) - fun ParcelScope.cmdAllow(sender: Player, player: OfflinePlayer): Any? { - checkPrivilege(sender, player) + suspend fun ParcelScope.cmdAllow(sender: Player, player: PlayerProfile): Any? { + checkOwned(sender) + + val key = toPrivilegeKey(player) + checkPrivilege(sender, key) - return when (parcel.allowBuild(player)) { + return when (parcel.allowBuild(key)) { FAIL_OWNER -> err("The target already owns the parcel") FAIL -> err("${player.name} is already allowed to build on this parcel") SUCCESS -> "${player.name} is now allowed to build on this parcel" @@ -75,10 +82,13 @@ class CommandsPrivilegesLocal(plugin: ParcelsPlugin) : AbstractParcelCommands(pl shortVersion = "disallows a player to build on this parcel" ) @RequireParcelPrivilege(Privilege.CAN_MANAGE) - fun ParcelScope.cmdDisallow(sender: Player, player: OfflinePlayer): Any? { - checkPrivilege(sender, player) + suspend fun ParcelScope.cmdDisallow(sender: Player, player: PlayerProfile): Any? { + checkOwned(sender) + + val key = toPrivilegeKey(player) + checkPrivilege(sender, key) - return when (parcel.disallowBuild(player)) { + return when (parcel.disallowBuild(key)) { FAIL_OWNER -> err("The target owns the parcel") FAIL -> err("${player.name} is not currently allowed to build on this parcel") SUCCESS -> "${player.name} is not allowed to build on this parcel anymore" @@ -92,10 +102,13 @@ class CommandsPrivilegesLocal(plugin: ParcelsPlugin) : AbstractParcelCommands(pl shortVersion = "bans a player from this parcel" ) @RequireParcelPrivilege(Privilege.CAN_MANAGE) - fun ParcelScope.cmdBan(sender: Player, player: OfflinePlayer): Any? { - checkPrivilege(sender, player) + suspend fun ParcelScope.cmdBan(sender: Player, player: PlayerProfile): Any? { + checkOwned(sender) - return when (parcel.disallowBuild(player)) { + val key = toPrivilegeKey(player) + checkPrivilege(sender, key) + + return when (parcel.disallowEnter(key)) { FAIL_OWNER -> err("The target owns the parcel") FAIL -> err("${player.name} is already banned from this parcel") SUCCESS -> "${player.name} is now banned from this parcel" @@ -109,10 +122,13 @@ class CommandsPrivilegesLocal(plugin: ParcelsPlugin) : AbstractParcelCommands(pl shortVersion = "unbans a player from this parcel" ) @RequireParcelPrivilege(Privilege.CAN_MANAGE) - fun ParcelScope.cmdUnban(sender: Player, player: OfflinePlayer): Any? { - checkPrivilege(sender, player) + suspend fun ParcelScope.cmdUnban(sender: Player, player: PlayerProfile): Any? { + checkOwned(sender) + + val key = toPrivilegeKey(player) + checkPrivilege(sender, key) - return when (parcel.disallowBuild(player)) { + return when (parcel.allowEnter(key)) { FAIL_OWNER -> err("The target owns the parcel") FAIL -> err("${player.name} is not currently banned from this parcel") SUCCESS -> "${player.name} is not banned from this parcel anymore" diff --git a/src/main/kotlin/io/dico/parcels2/command/ParcelCommandBuilder.kt b/src/main/kotlin/io/dico/parcels2/command/ParcelCommandBuilder.kt index e7d8663..40e5253 100644 --- a/src/main/kotlin/io/dico/parcels2/command/ParcelCommandBuilder.kt +++ b/src/main/kotlin/io/dico/parcels2/command/ParcelCommandBuilder.kt @@ -1,10 +1,13 @@ package io.dico.parcels2.command import io.dico.dicore.command.* +import io.dico.dicore.command.predef.DefaultGroupCommand import io.dico.dicore.command.registration.reflect.ReflectiveRegistration import io.dico.parcels2.Interactables import io.dico.parcels2.ParcelsPlugin import io.dico.parcels2.logger +import io.dico.parcels2.util.ext.hasPermAdminManage +import org.bukkit.command.CommandSender import java.util.LinkedList import java.util.Queue @@ -37,12 +40,19 @@ fun getParcelCommands(plugin: ParcelsPlugin): ICommandDispatcher = CommandBuilde } } + val adminPrivilegesGlobal = CommandsAdminPrivilegesGlobal(plugin) + group("global", "g") { - registerCommands(CommandsPrivilegesGlobal(plugin)) + registerCommands(CommandsPrivilegesGlobal(plugin, adminVersion = adminPrivilegesGlobal)) } group("admin", "a") { + setCommand(AdminGroupCommand()) registerCommands(CommandsAdmin(plugin)) + + group("global", "g") { + registerCommands(adminPrivilegesGlobal) + } } if (!logger.isDebugEnabled) return@group @@ -118,3 +128,7 @@ class SpecialCommandAddress : ChildCommandAddress() { } } + +private class AdminGroupCommand : DefaultGroupCommand() { + override fun isVisibleTo(sender: CommandSender) = sender.hasPermAdminManage +} diff --git a/src/main/kotlin/io/dico/parcels2/command/ParcelCommandReceivers.kt b/src/main/kotlin/io/dico/parcels2/command/ParcelCommandReceivers.kt index 0ef5264..8f6dabc 100644 --- a/src/main/kotlin/io/dico/parcels2/command/ParcelCommandReceivers.kt +++ b/src/main/kotlin/io/dico/parcels2/command/ParcelCommandReceivers.kt @@ -4,10 +4,7 @@ import io.dico.dicore.command.CommandException import io.dico.dicore.command.ExecutionContext import io.dico.dicore.command.ICommandReceiver import io.dico.dicore.command.Validate -import io.dico.parcels2.Parcel -import io.dico.parcels2.ParcelProvider -import io.dico.parcels2.ParcelWorld -import io.dico.parcels2.Privilege +import io.dico.parcels2.* import io.dico.parcels2.Privilege.* import io.dico.parcels2.util.ext.hasPermAdminManage import io.dico.parcels2.util.ext.uuid diff --git a/src/main/kotlin/io/dico/parcels2/command/ParcelParameterTypes.kt b/src/main/kotlin/io/dico/parcels2/command/ParcelParameterTypes.kt index e7c4e48..8beef7f 100644 --- a/src/main/kotlin/io/dico/parcels2/command/ParcelParameterTypes.kt +++ b/src/main/kotlin/io/dico/parcels2/command/ParcelParameterTypes.kt @@ -4,10 +4,7 @@ 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.ParameterType -import io.dico.parcels2.Parcel -import io.dico.parcels2.ParcelProvider -import io.dico.parcels2.ParcelWorld -import io.dico.parcels2.PlayerProfile +import io.dico.parcels2.* import org.bukkit.command.CommandSender import org.bukkit.entity.Player diff --git a/src/main/kotlin/io/dico/parcels2/defaultimpl/GlobalPrivilegesManagerImpl.kt b/src/main/kotlin/io/dico/parcels2/defaultimpl/GlobalPrivilegesManagerImpl.kt index 2324fac..769cee6 100644 --- a/src/main/kotlin/io/dico/parcels2/defaultimpl/GlobalPrivilegesManagerImpl.kt +++ b/src/main/kotlin/io/dico/parcels2/defaultimpl/GlobalPrivilegesManagerImpl.kt @@ -13,27 +13,16 @@ class GlobalPrivilegesManagerImpl(val plugin: ParcelsPlugin) : GlobalPrivilegesM return map[owner] ?: GlobalPrivilegesImpl(owner).also { map[owner] = it } } - private inner class GlobalPrivilegesImpl( - override val keyOfOwner: PlayerProfile.Real, - data: MutablePrivilegeMap = emptyData - ) : PrivilegesHolder(data), GlobalPrivileges { + private inner class GlobalPrivilegesImpl(override val keyOfOwner: PlayerProfile.Real) : PrivilegesHolder(), GlobalPrivileges { + override var privilegeOfStar: Privilege + get() = super.privilegeOfStar + set(value) = run { super.privilegeOfStar = value } - private inline var data get() = privilegeMap; set(value) = run { privilegeMap = value } - private inline val isEmpty get() = data === emptyData - - override fun setStoredPrivilege(key: PrivilegeKey, privilege: Privilege): Boolean { - if (isEmpty) { - if (privilege == Privilege.DEFAULT) return false - data = mutableMapOf() - } - return super.setStoredPrivilege(key, privilege).alsoIfTrue { + override fun setRawStoredPrivilege(key: PrivilegeKey, privilege: Privilege): Boolean { + return super.setRawStoredPrivilege(key, privilege).alsoIfTrue { plugin.storage.setGlobalPrivilege(keyOfOwner, key, privilege) } } } - private companion object { - val emptyData = Collections.emptyMap() as MutablePrivilegeMap - } - } \ No newline at end of file diff --git a/src/main/kotlin/io/dico/parcels2/defaultimpl/ParcelImpl.kt b/src/main/kotlin/io/dico/parcels2/defaultimpl/ParcelImpl.kt index bfaeb09..243ec19 100644 --- a/src/main/kotlin/io/dico/parcels2/defaultimpl/ParcelImpl.kt +++ b/src/main/kotlin/io/dico/parcels2/defaultimpl/ParcelImpl.kt @@ -6,7 +6,6 @@ import io.dico.parcels2.Privilege.* import io.dico.parcels2.util.Vec2i import io.dico.parcels2.util.ext.alsoIfTrue import org.bukkit.Material -import org.bukkit.OfflinePlayer import org.joda.time.DateTime import java.util.concurrent.atomic.AtomicInteger @@ -36,25 +35,19 @@ class ParcelImpl( world.storage.setParcelData(this, null) } - override val privilegeMap: PrivilegeMap get() = data.privilegeMap - override fun getStoredPrivilege(key: PrivilegeKey) = data.getStoredPrivilege(key) - override fun setStoredPrivilege(key: PrivilegeKey, privilege: Privilege): Boolean { - return data.setStoredPrivilege(key, privilege).alsoIfTrue { - world.storage.setLocalPrivilege(this, key, privilege) + override var owner: PlayerProfile? + get() = data.owner + set(value) { + if (data.owner != value) { + world.storage.setParcelOwner(this, value) + world.blockManager.setOwnerBlock(this, value) + data.owner = value + } } - } - - override fun privilege(player: OfflinePlayer, adminPerm: String): Privilege { - val privilege = super.privilege(player, adminPerm) - return if (privilege == DEFAULT) globalPrivileges?.privilege(player, adminPerm) ?: DEFAULT - else privilege - } - override val globalPrivileges: GlobalPrivileges? - get() = keyOfOwner?.let { world.globalPrivileges[it] } - - override val lastClaimTime: DateTime? get() = data.lastClaimTime + override val lastClaimTime: DateTime? + get() = data.lastClaimTime override var ownerSignOutdated: Boolean get() = data.ownerSignOutdated @@ -65,21 +58,32 @@ class ParcelImpl( } } - override var owner: PlayerProfile? - get() = data.owner - set(value) { - if (data.owner != value) { - world.storage.setParcelOwner(this, value) - world.blockManager.setOwnerBlock(this, value) - data.owner = value - } + + override val privilegeMap: PrivilegeMap + get() = data.privilegeMap + + override val globalPrivileges: GlobalPrivileges? + get() = keyOfOwner?.let { world.globalPrivileges[it] } + + override fun getRawStoredPrivilege(key: PrivilegeKey) = data.getRawStoredPrivilege(key) + + override fun setRawStoredPrivilege(key: PrivilegeKey, privilege: Privilege) = + data.setRawStoredPrivilege(key, privilege).alsoIfTrue { + world.storage.setLocalPrivilege(this, key, privilege) } + override fun getStoredPrivilege(key: PrivilegeKey): Privilege = + super.getStoredPrivilege(key).takeIf { it != DEFAULT } + ?: globalPrivileges?.getStoredPrivilege(key) + ?: DEFAULT + + + private var _interactableConfig: InteractableConfiguration? = null + private fun updateInteractableConfigStorage() { world.storage.setParcelOptionsInteractConfig(this, data.interactableConfig) } - private var _interactableConfig: InteractableConfiguration? = null override var interactableConfig: InteractableConfiguration get() { if (_interactableConfig == null) { @@ -103,6 +107,7 @@ class ParcelImpl( } } + private var blockVisitors = AtomicInteger(0) override suspend fun withBlockVisitorPermit(block: suspend () -> Unit) { @@ -117,9 +122,6 @@ class ParcelImpl( override fun toString() = toStringExt() } -private operator fun Formatting.plus(other: Formatting) = toString() + other -private operator fun Formatting.plus(other: String) = toString() + other - private object ParcelInfoStringComputer { val infoStringColor1 = Formatting.GREEN val infoStringColor2 = Formatting.AQUA @@ -148,20 +150,34 @@ private object ParcelInfoStringComputer { }, value) } - private fun StringBuilder.appendAddedList(local: PrivilegeMap, global: PrivilegeMap, privilege: Privilege, fieldName: String) { - // local takes precedence over global + private fun processPrivileges(local: RawPrivileges, global: RawPrivileges?, + privilege: Privilege): Pair, Int> { + val map = linkedMapOf() + local.privilegeOfStar.takeIf { it != DEFAULT }?.let { map[PlayerProfile.Star] = it } + map.values.retainAll { it.isDistanceGrEq(privilege) } + val localCount = map.size + + if (global != null) { + global.privilegeMap.forEach { + if (it.value.isDistanceGrEq(privilege)) + map.putIfAbsent(it.key, it.value) + } + + global.privilegeOfStar.takeIf { it != DEFAULT && it.isDistanceGrEq(privilege) } + ?.let { map.putIfAbsent(PlayerProfile.Star, it) } + } - val localFiltered = local.filterValues { it.isDistanceGrEq(privilege) } - // global keys are dropped here when merged with the local ones - val all = localFiltered + global.filterValues { it.isDistanceGrEq(privilege) } - if (all.isEmpty()) return + return map to localCount + } - appendFieldWithCount(fieldName, all.size) { - val separator = "$infoStringColor1, $infoStringColor2" + private fun StringBuilder.appendAddedList(local: RawPrivileges, global: RawPrivileges?, privilege: Privilege, fieldName: String) { + val (map, localCount) = processPrivileges(local, global, privilege) + if (map.isEmpty()) return + appendFieldWithCount(fieldName, map.size) { // first [localCount] entries are local - val localCount = localFiltered.size - val iterator = all.iterator() + val separator = "$infoStringColor1, $infoStringColor2" + val iterator = map.iterator() if (localCount != 0) { appendPrivilegeEntry(false, iterator.next().toPair()) @@ -185,17 +201,17 @@ private object ParcelInfoStringComputer { private fun StringBuilder.appendPrivilegeEntry(global: Boolean, pair: Pair) { val (key, priv) = pair - // prefix. Maybe T should be M for mod or something. T means they have CAN_MANAGE privilege. + append(key.notNullName) + + // suffix. Maybe T should be M for mod or something. T means they have CAN_MANAGE privilege. append( when { - global && priv == CAN_MANAGE -> "(GT)" - global -> "(G)" - priv == CAN_MANAGE -> "(T)" + global && priv == CAN_MANAGE -> " (G) (T)" + global -> " (G)" + priv == CAN_MANAGE -> " (T)" else -> "" } ) - - append(key.notNullName) } fun getInfoString(parcel: Parcel): String = buildString { @@ -219,8 +235,8 @@ private object ParcelInfoStringComputer { append('\n') - val local = parcel.privilegeMap - val global = parcel.globalPrivileges?.privilegeMap ?: emptyMap() + val local: RawPrivileges = parcel.data + val global = parcel.globalPrivileges appendAddedList(local, global, CAN_BUILD, "Allowed") // includes CAN_MANAGE privilege append('\n') appendAddedList(local, global, BANNED, "Banned") diff --git a/src/main/kotlin/io/dico/parcels2/listener/WorldEditListener.kt b/src/main/kotlin/io/dico/parcels2/listener/WorldEditListener.kt index 77d754a..4d35a53 100644 --- a/src/main/kotlin/io/dico/parcels2/listener/WorldEditListener.kt +++ b/src/main/kotlin/io/dico/parcels2/listener/WorldEditListener.kt @@ -14,6 +14,7 @@ import com.sk89q.worldedit.world.biome.BaseBiome import com.sk89q.worldedit.world.block.BlockStateHolder import io.dico.parcels2.ParcelWorld import io.dico.parcels2.ParcelsPlugin +import io.dico.parcels2.canBuildFast import io.dico.parcels2.util.ext.hasPermBuildAnywhere import io.dico.parcels2.util.ext.sendParcelMessage import org.bukkit.entity.Player 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 c09cd86..e4c2b4c 100644 --- a/src/main/kotlin/io/dico/parcels2/util/ext/Misc.kt +++ b/src/main/kotlin/io/dico/parcels2/util/ext/Misc.kt @@ -1,5 +1,6 @@ package io.dico.parcels2.util.ext +import io.dico.dicore.Formatting import io.dico.parcels2.logger import java.io.File @@ -70,3 +71,6 @@ class EditLoopScope(val _map: MutableMap) { } } + +operator fun Formatting.plus(other: Formatting) = toString() + other +operator fun Formatting.plus(other: String) = toString() + other 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 1d3117e..1875ff8 100644 --- a/src/main/kotlin/io/dico/parcels2/util/ext/Player.kt +++ b/src/main/kotlin/io/dico/parcels2/util/ext/Player.kt @@ -5,6 +5,7 @@ import io.dico.parcels2.ParcelsPlugin import io.dico.parcels2.logger import org.bukkit.OfflinePlayer import org.bukkit.entity.Player +import org.bukkit.permissions.Permissible import org.bukkit.plugin.java.JavaPlugin inline val OfflinePlayer.uuid get() = uniqueId @@ -17,12 +18,12 @@ const val PERM_BAN_BYPASS = "parcels.admin.bypass.ban" const val PERM_BUILD_ANYWHERE = "parcels.admin.bypass.build" const val PERM_ADMIN_MANAGE = "parcels.admin.manage" -inline val Player.hasPermBanBypass get() = hasPermission(PERM_BAN_BYPASS) -inline val Player.hasPermGamemodeBypass get() = hasPermission("parcels.admin.bypass.gamemode") -inline val Player.hasPermBuildAnywhere get() = hasPermission(PERM_BUILD_ANYWHERE) -inline val Player.hasPermAdminManage get() = hasPermission(PERM_ADMIN_MANAGE) -inline val Player.hasParcelHomeOthers get() = hasPermission("parcels.command.home.others") -inline val Player.hasPermRandomSpecific get() = hasPermission("parcels.command.random.specific") +inline val Permissible.hasPermBanBypass get() = hasPermission(PERM_BAN_BYPASS) +inline val Permissible.hasPermGamemodeBypass get() = hasPermission("parcels.admin.bypass.gamemode") +inline val Permissible.hasPermBuildAnywhere get() = hasPermission(PERM_BUILD_ANYWHERE) +inline val Permissible.hasPermAdminManage get() = hasPermission(PERM_ADMIN_MANAGE) +inline val Permissible.hasParcelHomeOthers get() = hasPermission("parcels.command.home.others") +inline val Permissible.hasPermRandomSpecific get() = hasPermission("parcels.command.random.specific") val Player.parcelLimit: Int get() { for (info in effectivePermissions) { -- cgit v1.2.3