Cleanup of privilege and listeners
This commit is contained in:
@@ -1,10 +1,7 @@
|
||||
package io.dico.parcels2
|
||||
|
||||
import io.dico.parcels2.util.Vec2i
|
||||
import io.dico.parcels2.util.ext.hasPermBuildAnywhere
|
||||
import org.bukkit.Location
|
||||
import org.bukkit.OfflinePlayer
|
||||
import org.bukkit.entity.Player
|
||||
import org.joda.time.DateTime
|
||||
import java.util.UUID
|
||||
|
||||
@@ -16,7 +13,7 @@ import java.util.UUID
|
||||
* However, this implementation is intentionally not thread-safe.
|
||||
* Therefore, database query callbacks should schedule their updates using the bukkit scheduler.
|
||||
*/
|
||||
interface Parcel : ParcelData {
|
||||
interface Parcel : ParcelData, Privileges {
|
||||
val id: ParcelId
|
||||
val world: ParcelWorld
|
||||
val pos: Vec2i
|
||||
@@ -25,6 +22,10 @@ interface Parcel : ParcelData {
|
||||
val data: ParcelData
|
||||
val infoString: String
|
||||
val hasBlockVisitors: Boolean
|
||||
val globalPrivileges: GlobalPrivileges?
|
||||
|
||||
override val keyOfOwner: PlayerProfile.Real?
|
||||
get() = owner as? PlayerProfile.Real
|
||||
|
||||
fun copyDataIgnoringDatabase(data: ParcelData)
|
||||
|
||||
@@ -37,13 +38,13 @@ interface Parcel : ParcelData {
|
||||
val homeLocation: Location get() = world.blockManager.getHomeLocation(id)
|
||||
}
|
||||
|
||||
interface ParcelData : Privileges {
|
||||
interface ParcelData : PrivilegesMinimal {
|
||||
var owner: PlayerProfile?
|
||||
val lastClaimTime: DateTime?
|
||||
var ownerSignOutdated: Boolean
|
||||
var interactableConfig: InteractableConfiguration
|
||||
|
||||
fun canBuild(player: OfflinePlayer, checkAdmin: Boolean = true, checkGlobal: Boolean = true): Boolean
|
||||
//fun canBuild(player: OfflinePlayer, checkAdmin: Boolean = true, checkGlobal: Boolean = true): Boolean
|
||||
|
||||
fun isOwner(uuid: UUID): Boolean {
|
||||
return owner?.uuid == uuid
|
||||
@@ -59,10 +60,11 @@ 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 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()
|
||||
}
|
||||
|
||||
146
src/main/kotlin/io/dico/parcels2/Privilege.kt
Normal file
146
src/main/kotlin/io/dico/parcels2/Privilege.kt
Normal file
@@ -0,0 +1,146 @@
|
||||
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
|
||||
|
||||
enum class Privilege(
|
||||
val number: Int,
|
||||
val transient: Boolean = false
|
||||
) {
|
||||
BANNED(1),
|
||||
DEFAULT(2),
|
||||
CAN_BUILD(3),
|
||||
CAN_MANAGE(4),
|
||||
|
||||
OWNER(-1, transient = true),
|
||||
ADMIN(-1, transient = true);
|
||||
|
||||
fun isDistanceGrEq(other: Privilege): Boolean =
|
||||
when { // used for example when disallowBuild is called and CAN_MANAGE is the privilege.
|
||||
other > DEFAULT -> this >= other
|
||||
other == DEFAULT -> this == other
|
||||
else -> this <= other
|
||||
}
|
||||
|
||||
fun isChangeInDirection(positiveDirection: Boolean, update: Privilege): Boolean =
|
||||
if (positiveDirection) update > this
|
||||
else update < this
|
||||
|
||||
fun requireNonTransient(): Privilege {
|
||||
if (transient) {
|
||||
throw IllegalArgumentException("Transient privilege $this is invalid")
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
/*
|
||||
fun canEnter() = this >= BANNED
|
||||
fun canBuild() = this >= CAN_BUILD
|
||||
fun canManage() = this >= CAN_MANAGE
|
||||
*/
|
||||
|
||||
companion object {
|
||||
fun getByNumber(id: Int) =
|
||||
when (id) {
|
||||
1 -> BANNED
|
||||
2 -> DEFAULT
|
||||
3 -> CAN_BUILD
|
||||
4 -> CAN_MANAGE
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typealias PrivilegeKey = PlayerProfile.Real
|
||||
typealias MutablePrivilegeMap = MutableMap<PrivilegeKey, Privilege>
|
||||
typealias PrivilegeMap = Map<PrivilegeKey, Privilege>
|
||||
|
||||
@Suppress("FunctionName")
|
||||
fun MutablePrivilegeMap(): MutablePrivilegeMap = hashMapOf()
|
||||
|
||||
interface PrivilegesMinimal {
|
||||
val map: 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, 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
|
||||
}
|
||||
|
||||
enum class PrivilegeChangeResult {
|
||||
SUCCESS, FAIL, FAIL_OWNER
|
||||
}
|
||||
|
||||
val OfflinePlayer.privilegeKey: PrivilegeKey
|
||||
inline get() = PlayerProfile.nameless(this)
|
||||
|
||||
open class PrivilegesHolder(override var map: MutablePrivilegeMap = MutablePrivilegeMap()) : PrivilegesMinimal {
|
||||
override var privilegeOfStar: Privilege = DEFAULT
|
||||
set(value) = run { field = value.requireNonTransient() }
|
||||
|
||||
override fun getStoredPrivilege(key: PrivilegeKey) =
|
||||
if (key.isStar) privilegeOfStar
|
||||
else map.getOrDefault(key, privilegeOfStar)
|
||||
|
||||
override fun setStoredPrivilege(key: PrivilegeKey, privilege: Privilege): Boolean {
|
||||
privilege.requireNonTransient()
|
||||
|
||||
if (key.isStar) {
|
||||
if (privilegeOfStar == privilege) return false
|
||||
privilegeOfStar = privilege
|
||||
return true
|
||||
}
|
||||
|
||||
return if (privilege == DEFAULT) map.remove(key) != null
|
||||
else map.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)
|
||||
}
|
||||
@@ -1,128 +0,0 @@
|
||||
package io.dico.parcels2
|
||||
|
||||
import io.dico.parcels2.Privilege.*
|
||||
import org.bukkit.OfflinePlayer
|
||||
|
||||
enum class Privilege(
|
||||
val number: Int,
|
||||
val transient: Boolean = false
|
||||
) {
|
||||
BANNED(1),
|
||||
DEFAULT(2),
|
||||
CAN_BUILD(3),
|
||||
CAN_MANAGE(4),
|
||||
|
||||
OWNER(-1, transient = true),
|
||||
ADMIN(-1, transient = true);
|
||||
|
||||
fun isDistanceGrEq(other: Privilege): Boolean =
|
||||
when { // used for example when disallowBuild is called and CAN_MANAGE is the privilege.
|
||||
other > DEFAULT -> this >= other
|
||||
other == DEFAULT -> this == other
|
||||
else -> this <= other
|
||||
}
|
||||
|
||||
fun requireNonTransient(): Privilege {
|
||||
if (transient) {
|
||||
throw IllegalArgumentException("Transient privilege $this is invalid")
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
/*
|
||||
fun canEnter() = this >= BANNED
|
||||
fun canBuild() = this >= CAN_BUILD
|
||||
fun canManage() = this >= CAN_MANAGE
|
||||
*/
|
||||
|
||||
companion object {
|
||||
fun getByNumber(id: Int) =
|
||||
when (id) {
|
||||
1 -> BANNED
|
||||
2 -> DEFAULT
|
||||
3 -> CAN_BUILD
|
||||
4 -> CAN_MANAGE
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typealias PrivilegeKey = PlayerProfile.Real
|
||||
typealias MutablePrivilegeMap = MutableMap<PrivilegeKey, Privilege>
|
||||
typealias PrivilegeMap = Map<PrivilegeKey, Privilege>
|
||||
|
||||
@Suppress("FunctionName")
|
||||
fun MutablePrivilegeMap(): MutablePrivilegeMap = hashMapOf()
|
||||
|
||||
/**
|
||||
* Privileges object never returns a transient privilege.
|
||||
*/
|
||||
interface Privileges {
|
||||
val map: PrivilegeMap
|
||||
var privilegeOfStar: Privilege
|
||||
|
||||
fun privilege(key: PrivilegeKey): Privilege
|
||||
fun privilege(player: OfflinePlayer) = privilege(player.privilegeKey)
|
||||
fun setPrivilege(key: PrivilegeKey, privilege: Privilege): Boolean
|
||||
fun setPrivilege(player: OfflinePlayer, privilege: Privilege) = setPrivilege(player.privilegeKey, privilege)
|
||||
fun changePrivilege(key: PrivilegeKey, expect: Privilege, update: Privilege): Boolean =
|
||||
privilege(key).isDistanceGrEq(expect) && setPrivilege(key, update)
|
||||
|
||||
fun hasPrivilegeToManage(key: PrivilegeKey) = privilege(key) >= CAN_MANAGE
|
||||
fun allowManage(key: PrivilegeKey) = setPrivilege(key, CAN_MANAGE)
|
||||
fun disallowManage(key: PrivilegeKey) = changePrivilege(key, CAN_MANAGE, CAN_BUILD)
|
||||
|
||||
fun hasPrivilegeToBuild(key: PrivilegeKey) = privilege(key) >= CAN_BUILD
|
||||
fun allowBuild(key: PrivilegeKey) = setPrivilege(key, CAN_BUILD)
|
||||
fun disallowBuild(key: PrivilegeKey) = changePrivilege(key, CAN_BUILD, DEFAULT)
|
||||
|
||||
fun isBanned(key: PrivilegeKey) = privilege(key) == BANNED
|
||||
fun ban(key: PrivilegeKey) = setPrivilege(key, BANNED)
|
||||
fun unban(key: PrivilegeKey) = changePrivilege(key, BANNED, DEFAULT)
|
||||
|
||||
/* OfflinePlayer overloads */
|
||||
|
||||
fun hasPrivilegeToManage(player: OfflinePlayer) = hasPrivilegeToManage(player.privilegeKey)
|
||||
fun allowManage(player: OfflinePlayer) = allowManage(player.privilegeKey)
|
||||
fun disallowManage(player: OfflinePlayer) = disallowManage(player.privilegeKey)
|
||||
|
||||
fun hasPrivilegeToBuild(player: OfflinePlayer) = hasPrivilegeToBuild(player.privilegeKey)
|
||||
fun allowBuild(player: OfflinePlayer) = allowBuild(player.privilegeKey)
|
||||
fun disallowBuild(player: OfflinePlayer) = disallowBuild(player.privilegeKey)
|
||||
|
||||
fun isBanned(player: OfflinePlayer) = isBanned(player.privilegeKey)
|
||||
fun ban(player: OfflinePlayer) = ban(player.privilegeKey)
|
||||
fun unban(player: OfflinePlayer) = unban(player.privilegeKey)
|
||||
}
|
||||
|
||||
val OfflinePlayer.privilegeKey: PrivilegeKey
|
||||
inline get() = PlayerProfile.nameless(this)
|
||||
|
||||
open class PrivilegesHolder(override var map: MutablePrivilegeMap = MutablePrivilegeMap()) : Privileges {
|
||||
override var privilegeOfStar: Privilege = DEFAULT
|
||||
set(value) = run { field = value.requireNonTransient() }
|
||||
|
||||
override fun privilege(key: PrivilegeKey): Privilege = map.getOrDefault(key, privilegeOfStar)
|
||||
|
||||
override fun setPrivilege(key: PrivilegeKey, privilege: Privilege): Boolean {
|
||||
privilege.requireNonTransient()
|
||||
|
||||
if (key.isStar) {
|
||||
if (privilegeOfStar == privilege) return false
|
||||
privilegeOfStar = privilege
|
||||
return true
|
||||
}
|
||||
|
||||
return if (privilege == DEFAULT) map.remove(key) != null
|
||||
else map.put(key, privilege) != privilege
|
||||
}
|
||||
}
|
||||
|
||||
interface GlobalPrivileges : Privileges {
|
||||
val owner: PlayerProfile
|
||||
}
|
||||
|
||||
interface GlobalPrivilegesManager {
|
||||
operator fun get(owner: PlayerProfile): GlobalPrivileges
|
||||
operator fun get(owner: OfflinePlayer): GlobalPrivileges = get(owner.privilegeKey)
|
||||
}
|
||||
@@ -20,9 +20,8 @@ import org.bukkit.block.Biome
|
||||
import org.bukkit.block.BlockFace
|
||||
import org.bukkit.block.Skull
|
||||
import org.bukkit.block.data.BlockData
|
||||
import org.bukkit.block.data.type.Sign
|
||||
import org.bukkit.block.data.type.Slab
|
||||
import java.lang.IllegalArgumentException
|
||||
import org.bukkit.block.data.type.WallSign
|
||||
import java.util.Random
|
||||
|
||||
private val airType = Bukkit.createBlockData(Material.AIR)
|
||||
@@ -201,8 +200,7 @@ class DefaultParcelGenerator(
|
||||
o.wallType
|
||||
|
||||
wallBlock.blockData = wallBlockType
|
||||
|
||||
signBlock.blockData = (Bukkit.createBlockData(Material.WALL_SIGN) as Sign).apply { rotation = BlockFace.NORTH }
|
||||
signBlock.blockData = (Bukkit.createBlockData(Material.WALL_SIGN) as WallSign).apply { facing = BlockFace.NORTH }
|
||||
|
||||
val sign = signBlock.state as org.bukkit.block.Sign
|
||||
sign.setLine(0, "${parcel.x},${parcel.z}")
|
||||
|
||||
@@ -9,25 +9,25 @@ import java.util.Collections
|
||||
class GlobalPrivilegesManagerImpl(val plugin: ParcelsPlugin) : GlobalPrivilegesManager {
|
||||
private val map = mutableMapOf<PlayerProfile, GlobalPrivileges>()
|
||||
|
||||
override fun get(owner: PlayerProfile): GlobalPrivileges {
|
||||
override fun get(owner: PlayerProfile.Real): GlobalPrivileges {
|
||||
return map[owner] ?: GlobalPrivilegesImpl(owner).also { map[owner] = it }
|
||||
}
|
||||
|
||||
private inner class GlobalPrivilegesImpl(
|
||||
override val owner: PlayerProfile,
|
||||
override val keyOfOwner: PlayerProfile.Real,
|
||||
data: MutablePrivilegeMap = emptyData
|
||||
) : PrivilegesHolder(data), GlobalPrivileges {
|
||||
|
||||
private inline var data get() = map; set(value) = run { map = value }
|
||||
private inline val isEmpty get() = data === emptyData
|
||||
|
||||
override fun setPrivilege(key: PrivilegeKey, privilege: Privilege): Boolean {
|
||||
override fun setStoredPrivilege(key: PrivilegeKey, privilege: Privilege): Boolean {
|
||||
if (isEmpty) {
|
||||
if (privilege == Privilege.DEFAULT) return false
|
||||
data = mutableMapOf()
|
||||
}
|
||||
return super<PrivilegesHolder>.setPrivilege(key, privilege).alsoIfTrue {
|
||||
plugin.storage.setGlobalPrivilege(owner, key, privilege)
|
||||
return super.setStoredPrivilege(key, privilege).alsoIfTrue {
|
||||
plugin.storage.setGlobalPrivilege(keyOfOwner, key, privilege)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package io.dico.parcels2.defaultimpl
|
||||
|
||||
import io.dico.dicore.Formatting
|
||||
import io.dico.parcels2.*
|
||||
import io.dico.parcels2.Privilege.*
|
||||
import io.dico.parcels2.util.Vec2i
|
||||
import io.dico.parcels2.util.ext.alsoIfTrue
|
||||
import org.bukkit.Material
|
||||
@@ -36,19 +37,26 @@ class ParcelImpl(
|
||||
}
|
||||
|
||||
override val map: PrivilegeMap get() = data.map
|
||||
override fun privilege(key: PrivilegeKey) = data.privilege(key)
|
||||
override fun isBanned(key: PrivilegeKey) = data.isBanned(key)
|
||||
override fun hasPrivilegeToBuild(key: PrivilegeKey) = data.hasPrivilegeToBuild(key)
|
||||
override fun canBuild(player: OfflinePlayer, checkAdmin: Boolean, checkGlobal: Boolean): Boolean {
|
||||
return (data.canBuild(player, checkAdmin, false))
|
||||
|| checkGlobal && world.globalPrivileges[owner ?: return false].hasPrivilegeToBuild(player)
|
||||
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 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 var privilegeOfStar: Privilege
|
||||
get() = data.privilegeOfStar
|
||||
set(value) = run { setPrivilege(PlayerProfile.Star, value) }
|
||||
get() = data.privilegeOfStar.let { if (it == DEFAULT) globalPrivileges?.privilegeOfStar ?: DEFAULT else it }
|
||||
set(value) = run { setStoredPrivilege(PlayerProfile.Star, value) }
|
||||
|
||||
val globalAddedMap: PrivilegeMap? get() = owner?.let { world.globalPrivileges[it].map }
|
||||
override val globalPrivileges: GlobalPrivileges?
|
||||
get() = keyOfOwner?.let { world.globalPrivileges[it] }
|
||||
|
||||
override val lastClaimTime: DateTime? get() = data.lastClaimTime
|
||||
|
||||
@@ -71,12 +79,6 @@ class ParcelImpl(
|
||||
}
|
||||
}
|
||||
|
||||
override fun setPrivilege(key: PrivilegeKey, privilege: Privilege): Boolean {
|
||||
return data.setPrivilege(key, privilege).alsoIfTrue {
|
||||
world.storage.setLocalPrivilege(this, key, privilege)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateInteractableConfigStorage() {
|
||||
world.storage.setParcelOptionsInteractConfig(this, data.interactableConfig)
|
||||
}
|
||||
@@ -188,12 +190,14 @@ private object ParcelInfoStringComputer {
|
||||
val (key, priv) = pair
|
||||
|
||||
// prefix. Maybe T should be M for mod or something. T means they have CAN_MANAGE privilege.
|
||||
append(when {
|
||||
global && priv == Privilege.CAN_MANAGE -> "(GT)"
|
||||
global -> "(G)"
|
||||
priv == Privilege.CAN_MANAGE -> "(T)"
|
||||
else -> ""
|
||||
})
|
||||
append(
|
||||
when {
|
||||
global && priv == CAN_MANAGE -> "(GT)"
|
||||
global -> "(G)"
|
||||
priv == CAN_MANAGE -> "(T)"
|
||||
else -> ""
|
||||
}
|
||||
)
|
||||
|
||||
append(key.notNullName)
|
||||
}
|
||||
@@ -219,11 +223,11 @@ private object ParcelInfoStringComputer {
|
||||
|
||||
append('\n')
|
||||
|
||||
val global = owner?.let { parcel.world.globalPrivileges[owner].map } ?: emptyMap()
|
||||
val local = parcel.map
|
||||
appendAddedList(local, global, Privilege.CAN_BUILD, "Allowed") // includes CAN_MANAGE privilege
|
||||
val global = parcel.globalPrivileges?.map ?: emptyMap()
|
||||
appendAddedList(local, global, CAN_BUILD, "Allowed") // includes CAN_MANAGE privilege
|
||||
append('\n')
|
||||
appendAddedList(local, global, Privilege.BANNED, "Banned")
|
||||
appendAddedList(local, global, BANNED, "Banned")
|
||||
|
||||
if (!parcel.interactableConfig.isDefault()) {
|
||||
val interactables = parcel.interactableConfig.interactableClasses
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package io.dico.parcels2.listener
|
||||
|
||||
import gnu.trove.TLongCollection
|
||||
import gnu.trove.set.hash.TLongHashSet
|
||||
import io.dico.dicore.ListenerMarker
|
||||
import io.dico.dicore.RegistratorListener
|
||||
import io.dico.parcels2.*
|
||||
@@ -30,21 +31,23 @@ import org.bukkit.event.world.StructureGrowEvent
|
||||
import org.bukkit.inventory.InventoryHolder
|
||||
import java.util.EnumSet
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
class ParcelListeners(
|
||||
val parcelProvider: ParcelProvider,
|
||||
val entityTracker: ParcelEntityTracker,
|
||||
val storage: Storage
|
||||
) {
|
||||
private inline fun Parcel?.canBuildN(user: Player) = isPresentAnd { canBuild(user) } || user.hasPermBuildAnywhere
|
||||
private fun canBuildOnArea(user: Player, area: Parcel?) =
|
||||
if (area == null) user.hasPermBuildAnywhere else area.canBuild(user)
|
||||
|
||||
private fun canInteract(user: Player, area: Parcel?, interactClass: String) =
|
||||
canBuildOnArea(user, area) || (area != null && area.interactableConfig(interactClass))
|
||||
|
||||
/**
|
||||
* Get the world and parcel that the block resides in
|
||||
* wo is the world, ppa is the parcel
|
||||
* ppa for possibly a parcel - it will be null if not in an existing parcel
|
||||
* returns null if not in a registered parcel world
|
||||
* the parcel is nullable, and often named area because that means path.
|
||||
* returns null if not in a registered parcel world - should always return in that case to not affect other worlds.
|
||||
*/
|
||||
private fun getWoAndPPa(block: Block): Pair<ParcelWorld, Parcel?>? {
|
||||
private fun getWorldAndArea(block: Block): Pair<ParcelWorld, Parcel?>? {
|
||||
val world = parcelProvider.getWorld(block.world) ?: return null
|
||||
return world to world.getParcelAt(block)
|
||||
}
|
||||
@@ -57,7 +60,7 @@ class ParcelListeners(
|
||||
val user = event.player
|
||||
if (user.hasPermBanBypass) return@l
|
||||
val parcel = parcelProvider.getParcelAt(event.to) ?: return@l
|
||||
if (parcel.isBanned(user.privilegeKey)) {
|
||||
if (!parcel.canEnter(user)) {
|
||||
parcelProvider.getParcelAt(event.from)?.also {
|
||||
user.teleport(it.homeLocation)
|
||||
user.sendParcelMessage(nopermit = true, message = "You are banned from this parcel")
|
||||
@@ -71,12 +74,12 @@ class ParcelListeners(
|
||||
*/
|
||||
@field:ListenerMarker(priority = NORMAL)
|
||||
val onBlockBreakEvent = RegistratorListener<BlockBreakEvent> l@{ event ->
|
||||
val (wo, ppa) = getWoAndPPa(event.block) ?: return@l
|
||||
if (!event.player.hasPermBuildAnywhere && ppa.isNullOr { !canBuild(event.player) }) {
|
||||
val (world, area) = getWorldAndArea(event.block) ?: return@l
|
||||
if (!canBuildOnArea(event.player, area)) {
|
||||
event.isCancelled = true; return@l
|
||||
}
|
||||
|
||||
if (!wo.options.dropEntityItems) {
|
||||
if (!world.options.dropEntityItems) {
|
||||
val state = event.block.state
|
||||
if (state is InventoryHolder) {
|
||||
state.inventory.clear()
|
||||
@@ -90,8 +93,8 @@ class ParcelListeners(
|
||||
*/
|
||||
@field:ListenerMarker(priority = NORMAL)
|
||||
val onBlockPlaceEvent = RegistratorListener<BlockPlaceEvent> l@{ event ->
|
||||
val (wo, ppa) = getWoAndPPa(event.block) ?: return@l
|
||||
if (!event.player.hasPermBuildAnywhere && ppa.isNullOr { !canBuild(event.player) }) {
|
||||
val (_, area) = getWorldAndArea(event.block) ?: return@l
|
||||
if (!canBuildOnArea(event.player, area)) {
|
||||
event.isCancelled = true
|
||||
}
|
||||
}
|
||||
@@ -120,7 +123,7 @@ class ParcelListeners(
|
||||
private fun checkPistonMovement(event: BlockPistonEvent, blocks: List<Block>) {
|
||||
val world = parcelProvider.getWorld(event.block.world) ?: return
|
||||
val direction = event.direction
|
||||
val columns = gnu.trove.set.hash.TLongHashSet(blocks.size * 2)
|
||||
val columns = TLongHashSet(blocks.size * 2)
|
||||
|
||||
blocks.forEach {
|
||||
columns.add(Column(it.x, it.z))
|
||||
@@ -128,8 +131,8 @@ class ParcelListeners(
|
||||
}
|
||||
|
||||
columns.troveForEach {
|
||||
val ppa = world.getParcelAt(it.columnX, it.columnZ)
|
||||
if (ppa.isNullOr { hasBlockVisitors }) {
|
||||
val area = world.getParcelAt(it.columnX, it.columnZ)
|
||||
if (area == null || area.hasBlockVisitors) {
|
||||
event.isCancelled = true
|
||||
return
|
||||
}
|
||||
@@ -141,10 +144,10 @@ class ParcelListeners(
|
||||
*/
|
||||
@field:ListenerMarker(priority = NORMAL)
|
||||
val onExplosionPrimeEvent = RegistratorListener<ExplosionPrimeEvent> l@{ event ->
|
||||
val (wo, ppa) = getWoAndPPa(event.entity.location.block) ?: return@l
|
||||
if (ppa?.hasBlockVisitors == true) {
|
||||
val (world, area) = getWorldAndArea(event.entity.location.block) ?: return@l
|
||||
if (area != null && area.hasBlockVisitors) {
|
||||
event.radius = 0F; event.isCancelled = true
|
||||
} else if (wo.options.disableExplosions) {
|
||||
} else if (world.options.disableExplosions) {
|
||||
event.radius = 0F
|
||||
}
|
||||
}
|
||||
@@ -156,18 +159,18 @@ class ParcelListeners(
|
||||
val onEntityExplodeEvent = RegistratorListener<EntityExplodeEvent> l@{ event ->
|
||||
entityTracker.untrack(event.entity)
|
||||
val world = parcelProvider.getWorld(event.entity.world) ?: return@l
|
||||
if (world.options.disableExplosions || world.getParcelAt(event.entity).isPresentAnd { hasBlockVisitors }) {
|
||||
if (world.options.disableExplosions || world.getParcelAt(event.entity).let { it != null && it.hasBlockVisitors }) {
|
||||
event.isCancelled = true
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Prevents creepers and tnt minecarts from exploding if explosions are disabled
|
||||
* Prevents liquids from flowing out of plots
|
||||
*/
|
||||
@field:ListenerMarker(priority = NORMAL)
|
||||
val onBlockFromToEvent = RegistratorListener<BlockFromToEvent> l@{ event ->
|
||||
val (wo, ppa) = getWoAndPPa(event.toBlock) ?: return@l
|
||||
if (ppa.isNullOr { hasBlockVisitors }) event.isCancelled = true
|
||||
val (_, area) = getWorldAndArea(event.toBlock) ?: return@l
|
||||
if (area == null || area.hasBlockVisitors) event.isCancelled = true
|
||||
}
|
||||
|
||||
private val bedTypes = EnumSet.copyOf(getMaterialsWithWoolColorPrefix("BED").toList())
|
||||
@@ -185,7 +188,7 @@ class ParcelListeners(
|
||||
val clickedBlock = event.clickedBlock
|
||||
val parcel = clickedBlock?.let { world.getParcelAt(it) }
|
||||
|
||||
if (!user.hasPermBuildAnywhere && parcel.isPresentAnd { isBanned(user.privilegeKey) }) {
|
||||
if (!user.hasPermBuildAnywhere && parcel != null && !parcel.canEnter(user)) {
|
||||
user.sendParcelMessage(nopermit = true, message = "You cannot interact with parcels you're banned from")
|
||||
event.isCancelled = true; return@l
|
||||
}
|
||||
@@ -193,7 +196,8 @@ class ParcelListeners(
|
||||
when (event.action) {
|
||||
Action.RIGHT_CLICK_BLOCK -> run {
|
||||
val type = clickedBlock.type
|
||||
val interactable = parcel.effectiveInteractableConfig.isInteractable(type) || parcel.isPresentAnd { canBuild(user) }
|
||||
val interactable = Interactables.listedMaterials.containsKey(type)
|
||||
&& (parcel.effectiveInteractableConfig.isInteractable(type) || (parcel != null && parcel.canBuild(user)))
|
||||
if (!interactable) {
|
||||
val interactableClassName = Interactables[type]!!.name
|
||||
user.sendParcelMessage(nopermit = true, message = "You cannot interact with $interactableClassName in this parcel")
|
||||
@@ -206,19 +210,24 @@ class ParcelListeners(
|
||||
val head = if (bed == Bed.Part.FOOT) clickedBlock.getRelative(bed.facing) else clickedBlock
|
||||
when (head.biome) {
|
||||
Biome.NETHER, Biome.THE_END -> {
|
||||
if (world.options.disableExplosions || parcel.isNullOr { !canBuild(user) }) {
|
||||
if (world.options.disableExplosions) {
|
||||
user.sendParcelMessage(nopermit = true, message = "You cannot use this bed because it would explode")
|
||||
event.isCancelled = true; return@l
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!canBuildOnArea(user, parcel)) {
|
||||
user.sendParcelMessage(nopermit = true, message = "You may not sleep here")
|
||||
event.isCancelled = true; return@l
|
||||
}
|
||||
}
|
||||
|
||||
onPlayerInteractEvent_RightClick(event, world, parcel)
|
||||
}
|
||||
|
||||
Action.RIGHT_CLICK_AIR -> onPlayerInteractEvent_RightClick(event, world, parcel)
|
||||
Action.PHYSICAL -> if (!user.hasPermBuildAnywhere && !parcel.isPresentAnd { canBuild(user) || interactableConfig("pressure_plates") }) {
|
||||
Action.PHYSICAL -> if (!canBuildOnArea(user, parcel) && !(parcel != null && parcel.interactableConfig("pressure_plates"))) {
|
||||
user.sendParcelMessage(nopermit = true, message = "You cannot use inputs in this parcel")
|
||||
event.isCancelled = true; return@l
|
||||
}
|
||||
@@ -234,7 +243,7 @@ class ParcelListeners(
|
||||
event.isCancelled = true; return
|
||||
}
|
||||
|
||||
if (!parcel.canBuildN(event.player)) {
|
||||
if (!canBuildOnArea(event.player, parcel)) {
|
||||
when (item) {
|
||||
LAVA_BUCKET, WATER_BUCKET, BUCKET, FLINT_AND_STEEL -> event.isCancelled = true
|
||||
}
|
||||
@@ -249,8 +258,8 @@ class ParcelListeners(
|
||||
@Suppress("NON_EXHAUSTIVE_WHEN")
|
||||
@field:ListenerMarker(priority = NORMAL)
|
||||
val onPlayerInteractEntityEvent = RegistratorListener<PlayerInteractEntityEvent> l@{ event ->
|
||||
val (wo, ppa) = getWoAndPPa(event.rightClicked.location.block) ?: return@l
|
||||
if (ppa.canBuildN(event.player)) return@l
|
||||
val (_, area) = getWorldAndArea(event.rightClicked.location.block) ?: return@l
|
||||
if (canBuildOnArea(event.player, area)) return@l
|
||||
when (event.rightClicked.type) {
|
||||
EntityType.BOAT,
|
||||
EntityType.MINECART,
|
||||
@@ -281,14 +290,14 @@ class ParcelListeners(
|
||||
*/
|
||||
@field:ListenerMarker(priority = NORMAL)
|
||||
val onEntityChangeBlockEvent = RegistratorListener<EntityChangeBlockEvent> l@{ event ->
|
||||
val (wo, ppa) = getWoAndPPa(event.block) ?: return@l
|
||||
if (event.entity.type == EntityType.ENDERMAN || ppa.isNullOr { hasBlockVisitors }) {
|
||||
val (_, area) = getWorldAndArea(event.block) ?: return@l
|
||||
if (event.entity.type == EntityType.ENDERMAN || area == null || area.hasBlockVisitors) {
|
||||
event.isCancelled = true; return@l
|
||||
}
|
||||
|
||||
if (event.entity.type == EntityType.FALLING_BLOCK) {
|
||||
// a sand block started falling. Track it and delete it if it gets out of this parcel.
|
||||
entityTracker.track(event.entity, ppa)
|
||||
entityTracker.track(event.entity, area)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -306,8 +315,8 @@ class ParcelListeners(
|
||||
*/
|
||||
@field:ListenerMarker(priority = NORMAL)
|
||||
val onPlayerDropItemEvent = RegistratorListener<PlayerDropItemEvent> l@{ event ->
|
||||
val (wo, ppa) = getWoAndPPa(event.itemDrop.location.block) ?: return@l
|
||||
if (!ppa.canBuildN(event.player) && !ppa.isPresentAnd { interactableConfig("containers") }) event.isCancelled = true
|
||||
val (_, area) = getWorldAndArea(event.itemDrop.location.block) ?: return@l
|
||||
if (!canInteract(event.player, area, "containers")) event.isCancelled = true
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -316,8 +325,8 @@ class ParcelListeners(
|
||||
@field:ListenerMarker(priority = NORMAL)
|
||||
val onEntityPickupItemEvent = RegistratorListener<EntityPickupItemEvent> l@{ event ->
|
||||
val user = event.entity as? Player ?: return@l
|
||||
val (wo, ppa) = getWoAndPPa(event.item.location.block) ?: return@l
|
||||
if (!ppa.canBuildN(user)) event.isCancelled = true
|
||||
val (_, area) = getWorldAndArea(event.item.location.block) ?: return@l
|
||||
if (!canInteract(user, area, "containers")) event.isCancelled = true
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -327,8 +336,8 @@ class ParcelListeners(
|
||||
val onInventoryClickEvent = RegistratorListener<InventoryInteractEvent> l@{ event ->
|
||||
val user = event.whoClicked as? Player ?: return@l
|
||||
if ((event.inventory ?: return@l).holder === user) return@l // inventory null: hotbar
|
||||
val (wo, ppa) = getWoAndPPa(event.inventory.location.block) ?: return@l
|
||||
if (ppa.isNullOr { !canBuild(user) && !interactableConfig("containers") }) {
|
||||
val (_, area) = getWorldAndArea(event.inventory.location.block) ?: return@l
|
||||
if (!canInteract(user, area, "containers")) {
|
||||
event.isCancelled = true
|
||||
}
|
||||
}
|
||||
@@ -358,10 +367,10 @@ class ParcelListeners(
|
||||
@ListenerMarker(priority = NORMAL)
|
||||
val onBlockFormEvent = RegistratorListener<BlockFormEvent> l@{ event ->
|
||||
val block = event.block
|
||||
val (wo, ppa) = getWoAndPPa(block) ?: return@l
|
||||
val (world, area) = getWorldAndArea(block) ?: return@l
|
||||
|
||||
// prevent any generation whatsoever on paths
|
||||
if (ppa == null) {
|
||||
if (area == null) {
|
||||
event.isCancelled = true; return@l
|
||||
}
|
||||
|
||||
@@ -371,10 +380,10 @@ class ParcelListeners(
|
||||
val cancel: Boolean = when (event.newState.type) {
|
||||
|
||||
// prevent ice generation from Frost Walkers enchantment
|
||||
FROSTED_ICE -> player != null && !ppa.canBuild(player)
|
||||
FROSTED_ICE -> player != null && !area.canBuild(player)
|
||||
|
||||
// prevent snow generation from weather
|
||||
SNOW -> !hasEntity && wo.options.preventWeatherBlockChanges
|
||||
SNOW -> !hasEntity && world.options.preventWeatherBlockChanges
|
||||
|
||||
else -> false
|
||||
}
|
||||
@@ -392,7 +401,7 @@ class ParcelListeners(
|
||||
val world = parcelProvider.getWorld(event.entity.world) ?: return@l
|
||||
if (event.entity is Creature && world.options.blockMobSpawning) {
|
||||
event.isCancelled = true
|
||||
} else if (world.getParcelAt(event.entity).isPresentAnd { hasBlockVisitors }) {
|
||||
} else if (world.getParcelAt(event.entity).let { it != null && it.hasBlockVisitors }) {
|
||||
event.isCancelled = true
|
||||
}
|
||||
}
|
||||
@@ -402,8 +411,8 @@ class ParcelListeners(
|
||||
*/
|
||||
@field:ListenerMarker(priority = NORMAL)
|
||||
val onVehicleMoveEvent = RegistratorListener<VehicleMoveEvent> l@{ event ->
|
||||
val (wo, ppa) = getWoAndPPa(event.to.block) ?: return@l
|
||||
if (ppa == null) {
|
||||
val (_, area) = getWorldAndArea(event.to.block) ?: return@l
|
||||
if (area == null) {
|
||||
event.vehicle.passengers.forEach {
|
||||
if (it.type == EntityType.PLAYER) {
|
||||
(it as Player).sendParcelMessage(except = true, message = "Your ride ends here")
|
||||
@@ -411,7 +420,7 @@ class ParcelListeners(
|
||||
}
|
||||
event.vehicle.eject()
|
||||
event.vehicle.remove()
|
||||
} else if (ppa.hasBlockVisitors) {
|
||||
} else if (area.hasBlockVisitors) {
|
||||
event.to.subtract(event.to).add(event.from)
|
||||
}
|
||||
}
|
||||
@@ -432,7 +441,7 @@ class ParcelListeners(
|
||||
?: (event.damager as? Projectile)?.let { it.shooter as? Player }
|
||||
?: return@l
|
||||
|
||||
if (!world.getParcelAt(event.entity).canBuildN(user)) {
|
||||
if (!canBuildOnArea(user, world.getParcelAt(event.entity))) {
|
||||
event.isCancelled = true
|
||||
}
|
||||
}
|
||||
@@ -444,7 +453,7 @@ class ParcelListeners(
|
||||
event.isCancelled = true; return@l
|
||||
}
|
||||
|
||||
if (world.getParcelAt(event.entity).isPresentAnd { hasBlockVisitors }) {
|
||||
if (world.getParcelAt(event.entity).let { it != null && it.hasBlockVisitors }) {
|
||||
event.isCancelled = true
|
||||
}
|
||||
}
|
||||
@@ -457,7 +466,7 @@ class ParcelListeners(
|
||||
val onHangingBreakByEntityEvent = RegistratorListener<HangingBreakByEntityEvent> l@{ event ->
|
||||
val world = parcelProvider.getWorld(event.entity.world) ?: return@l
|
||||
val user = event.remover as? Player ?: return@l
|
||||
if (!world.getParcelAt(event.entity).canBuildN(user)) {
|
||||
if (!canBuildOnArea(user, world.getParcelAt(event.entity))) {
|
||||
event.isCancelled = true
|
||||
}
|
||||
}
|
||||
@@ -469,7 +478,7 @@ class ParcelListeners(
|
||||
val onHangingPlaceEvent = RegistratorListener<HangingPlaceEvent> l@{ event ->
|
||||
val world = parcelProvider.getWorld(event.entity.world) ?: return@l
|
||||
val block = event.block.getRelative(event.blockFace)
|
||||
if (!world.getParcelAt(block).canBuildN(event.player)) {
|
||||
if (!canBuildOnArea(event.player, world.getParcelAt(block))) {
|
||||
event.isCancelled = true
|
||||
}
|
||||
}
|
||||
@@ -479,16 +488,16 @@ class ParcelListeners(
|
||||
*/
|
||||
@field:ListenerMarker(priority = NORMAL)
|
||||
val onStructureGrowEvent = RegistratorListener<StructureGrowEvent> l@{ event ->
|
||||
val (wo, ppa) = getWoAndPPa(event.location.block) ?: return@l
|
||||
if (ppa == null) {
|
||||
val (world, area) = getWorldAndArea(event.location.block) ?: return@l
|
||||
if (area == null) {
|
||||
event.isCancelled = true; return@l
|
||||
}
|
||||
|
||||
if (!event.player.hasPermBuildAnywhere && !ppa.canBuild(event.player)) {
|
||||
if (!event.player.hasPermBuildAnywhere && !area.canBuild(event.player)) {
|
||||
event.isCancelled = true; return@l
|
||||
}
|
||||
|
||||
event.blocks.removeIf { wo.getParcelAt(it.block) !== ppa }
|
||||
event.blocks.removeIf { world.getParcelAt(it.block) !== area }
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -511,9 +520,9 @@ class ParcelListeners(
|
||||
*/
|
||||
@field:ListenerMarker(priority = NORMAL)
|
||||
val onItemSpawnEvent = RegistratorListener<ItemSpawnEvent> l@{ event ->
|
||||
val (wo, ppa) = getWoAndPPa(event.location.block) ?: return@l
|
||||
if (ppa == null) event.isCancelled = true
|
||||
else entityTracker.track(event.entity, ppa)
|
||||
val (_, area) = getWorldAndArea(event.location.block) ?: return@l
|
||||
if (area == null) event.isCancelled = true
|
||||
else entityTracker.track(event.entity, area)
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -521,8 +530,8 @@ class ParcelListeners(
|
||||
*/
|
||||
@field:ListenerMarker(priority = NORMAL)
|
||||
val onEntityTeleportEvent = RegistratorListener<EntityTeleportEvent> l@{ event ->
|
||||
val (wo, ppa) = getWoAndPPa(event.from.block) ?: return@l
|
||||
if (ppa !== wo.getParcelAt(event.to)) {
|
||||
val (world, area) = getWorldAndArea(event.from.block) ?: return@l
|
||||
if (area !== world.getParcelAt(event.to)) {
|
||||
event.isCancelled = true
|
||||
}
|
||||
}
|
||||
@@ -533,11 +542,11 @@ class ParcelListeners(
|
||||
*/
|
||||
@field:ListenerMarker(priority = NORMAL)
|
||||
val onProjectileLaunchEvent = RegistratorListener<ProjectileLaunchEvent> l@{ event ->
|
||||
val (wo, ppa) = getWoAndPPa(event.entity.location.block) ?: return@l
|
||||
if (ppa == null || (event.entity.shooter as? Player)?.let { !ppa.canBuildN(it) } == true) {
|
||||
val (_, area) = getWorldAndArea(event.entity.location.block) ?: return@l
|
||||
if (area == null || (event.entity.shooter as? Player)?.let { !canBuildOnArea(it, area) } == true) {
|
||||
event.isCancelled = true
|
||||
} else {
|
||||
entityTracker.track(event.entity, ppa)
|
||||
entityTracker.track(event.entity, area)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ class WorldEditListener(val parcels: ParcelsPlugin, val worldEdit: WorldEdit) {
|
||||
|
||||
private fun canBuild(x: Int, z: Int): Boolean {
|
||||
world.getParcelAt(x, z)?.let { parcel ->
|
||||
if (parcel.canBuild(player, checkAdmin = false)) {
|
||||
if (parcel.canBuildFast(player)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,8 @@ import io.dico.parcels2.Privilege.DEFAULT
|
||||
import kotlinx.coroutines.channels.SendChannel
|
||||
import org.jetbrains.exposed.sql.*
|
||||
|
||||
object PrivilegesLocalT : PrivilegesTable<ParcelId>("parcels_added_local", ParcelsT)
|
||||
object PrivilegesGlobalT : PrivilegesTable<PlayerProfile>("parcels_added_global", ProfilesT)
|
||||
object PrivilegesLocalT : PrivilegesTable<ParcelId>("parcels_privilege_local", ParcelsT)
|
||||
object PrivilegesGlobalT : PrivilegesTable<PlayerProfile>("parcels_privilege_global", ProfilesT)
|
||||
|
||||
object ParcelOptionsT : Table("parcel_options") {
|
||||
val parcel_id = integer("parcel_id").primaryKey().references(ParcelsT.id, ReferenceOption.CASCADE)
|
||||
|
||||
@@ -20,8 +20,8 @@ inline fun Boolean.alsoIfFalse(block: () -> Unit): Boolean = also { if (!it) blo
|
||||
|
||||
inline fun <R> Any.synchronized(block: () -> R): R = synchronized(this, block)
|
||||
|
||||
inline fun <T> T?.isNullOr(condition: T.() -> Boolean): Boolean = this == null || condition()
|
||||
inline fun <T> T?.isPresentAnd(condition: T.() -> Boolean): Boolean = this != null && condition()
|
||||
//inline fun <T> T?.isNullOr(condition: T.() -> Boolean): Boolean = this == null || condition()
|
||||
//inline fun <T> T?.isPresentAnd(condition: T.() -> Boolean): Boolean = this != null && condition()
|
||||
inline fun <T> T?.ifNullRun(block: () -> Unit): T? {
|
||||
if (this == null) block()
|
||||
return this
|
||||
|
||||
@@ -13,10 +13,14 @@ inline val OfflinePlayer.uuid get() = uniqueId
|
||||
inline val OfflinePlayer.isValid
|
||||
get() = isOnline() || hasPlayedBefore()
|
||||
|
||||
inline val Player.hasPermBanBypass get() = hasPermission("parcels.admin.bypass.ban")
|
||||
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("parcels.admin.bypass.build")
|
||||
inline val Player.hasPermAdminManage get() = hasPermission("parcels.admin.manage")
|
||||
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")
|
||||
val Player.parcelLimit: Int
|
||||
|
||||
Reference in New Issue
Block a user