Start adding listeners as per RedstonerServer/Parcels
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
package io.dico.dicore;
|
||||
|
||||
import org.bukkit.event.EventPriority;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
public @interface ListenerMarker {
|
||||
|
||||
String[] events() default {};
|
||||
|
||||
EventPriority priority() default EventPriority.HIGHEST;
|
||||
|
||||
boolean ignoreCancelled() default true;
|
||||
}
|
||||
@@ -11,10 +11,6 @@ import org.bukkit.plugin.EventExecutor;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.RegisteredListener;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.reflect.*;
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
@@ -434,22 +430,6 @@ public final class Registrator {
|
||||
// # Public types
|
||||
// ############################################
|
||||
|
||||
public interface IEventListener<T extends Event> extends Consumer<T> {
|
||||
@Override
|
||||
void accept(T event);
|
||||
}
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
public @interface ListenerInfo {
|
||||
|
||||
String[] events() default {};
|
||||
|
||||
EventPriority priority() default EventPriority.HIGHEST;
|
||||
|
||||
boolean ignoreCancelled() default true;
|
||||
}
|
||||
|
||||
public static class Registration extends RegisteredListener {
|
||||
|
||||
private final EventExecutor executor;
|
||||
@@ -658,17 +638,17 @@ public final class Registrator {
|
||||
fieldLoop:
|
||||
for (Field f : fields) {
|
||||
if (isStatic != Modifier.isStatic(f.getModifiers())
|
||||
|| !f.isAnnotationPresent(ListenerInfo.class)) {
|
||||
|| !f.isAnnotationPresent(ListenerMarker.class)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!IEventListener.class.isAssignableFrom(f.getType())) {
|
||||
handleListenerFieldError(new ListenerFieldError(f, "Field type cannot be assigned to IEventListener: " + f.getGenericType().getTypeName()));
|
||||
if (!RegistratorListener.class.isAssignableFrom(f.getType())) {
|
||||
handleListenerFieldError(new ListenerFieldError(f, "Field type cannot be assigned to RegistratorListener: " + f.getGenericType().getTypeName()));
|
||||
continue;
|
||||
}
|
||||
|
||||
Type eventType = null;
|
||||
if (f.getType() == IEventListener.class) {
|
||||
if (f.getType() == RegistratorListener.class) {
|
||||
|
||||
Type[] typeArgs;
|
||||
if (!(f.getGenericType() instanceof ParameterizedType)
|
||||
@@ -681,7 +661,7 @@ public final class Registrator {
|
||||
eventType = typeArgs[0];
|
||||
|
||||
} else {
|
||||
// field type is subtype of IEventListener.
|
||||
// field type is subtype of RegistratorListener.
|
||||
// TODO: link type arguments from field declaration (f.getGenericType()) to matching TypeVariables
|
||||
Type[] interfaces = f.getType().getGenericInterfaces();
|
||||
for (Type itf : interfaces) {
|
||||
@@ -702,7 +682,7 @@ public final class Registrator {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (itfClass == IEventListener.class) {
|
||||
if (itfClass == RegistratorListener.class) {
|
||||
if (arguments == null || arguments.length != 1) {
|
||||
// Log a warning or throw an exception
|
||||
handleListenerFieldError(new ListenerFieldError(f, ""));
|
||||
@@ -749,7 +729,7 @@ public final class Registrator {
|
||||
|
||||
Class<? extends Event> baseEventClass = (Class<? extends Event>) eventType;
|
||||
|
||||
ListenerInfo anno = f.getAnnotation(ListenerInfo.class);
|
||||
ListenerMarker anno = f.getAnnotation(ListenerMarker.class);
|
||||
String[] eventClassNames = anno.events();
|
||||
if (eventClassNames.length > 0) {
|
||||
|
||||
@@ -844,9 +824,9 @@ public final class Registrator {
|
||||
private static final class ListenerFieldInfo {
|
||||
final Class<? extends Event> eventClass;
|
||||
final Consumer<? super Event> lambda;
|
||||
final ListenerInfo anno;
|
||||
final ListenerMarker anno;
|
||||
|
||||
ListenerFieldInfo(Class<? extends Event> eventClass, Consumer<? super Event> lambda, ListenerInfo anno) {
|
||||
ListenerFieldInfo(Class<? extends Event> eventClass, Consumer<? super Event> lambda, ListenerMarker anno) {
|
||||
this.eventClass = eventClass;
|
||||
this.lambda = lambda;
|
||||
this.anno = anno;
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package io.dico.dicore;
|
||||
|
||||
import org.bukkit.event.Event;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public interface RegistratorListener<T extends Event> extends Consumer<T> {
|
||||
@Override
|
||||
void accept(T event);
|
||||
}
|
||||
@@ -90,6 +90,8 @@ class Parcel(val world: ParcelWorld, val pos: Vec2i) : ParcelData {
|
||||
world.storage.setParcelAllowsInteractInventory(this, value)
|
||||
data.allowInteractInventory = value
|
||||
}
|
||||
|
||||
var hasBlockVisitors: Boolean = false; private set
|
||||
}
|
||||
|
||||
class ParcelDataHolder : ParcelData {
|
||||
|
||||
@@ -36,12 +36,9 @@ class ParcelCommands(val plugin: ParcelsPlugin) : ICommandReceiver.Factory {
|
||||
"and gives it to you",
|
||||
shortVersion = "sets you up with a fresh, unclaimed parcel")
|
||||
suspend fun WorldScope.cmdAuto(player: Player): Any? {
|
||||
logger.info("cmdAuto thread before await: ${Thread.currentThread().name}")
|
||||
val numOwnedParcels = plugin.storage.getNumParcels(ParcelOwner(uuid = player.uuid)).await()
|
||||
logger.info("cmdAuto thread before await: ${Thread.currentThread().name}")
|
||||
|
||||
val limit = player.parcelLimit
|
||||
|
||||
if (numOwnedParcels >= limit) {
|
||||
error("You have enough plots for now")
|
||||
}
|
||||
@@ -67,15 +64,12 @@ class ParcelCommands(val plugin: ParcelsPlugin) : ICommandReceiver.Factory {
|
||||
shortVersion = "teleports you to parcels")
|
||||
@RequireParameters(0)
|
||||
suspend fun cmdHome(player: Player,
|
||||
@NamedParcelDefault(FIRST_OWNED) target: NamedParcelTarget): Any?
|
||||
{
|
||||
@NamedParcelDefault(FIRST_OWNED) target: NamedParcelTarget): Any? {
|
||||
if (player !== target.player && !player.hasParcelHomeOthers) {
|
||||
error("You do not have permission to teleport to other people's parcels")
|
||||
}
|
||||
|
||||
logger.info("cmdHome thread before await: ${Thread.currentThread().name}")
|
||||
val ownedParcelsResult = plugin.storage.getOwnedParcels(ParcelOwner(uuid = target.player.uuid)).await()
|
||||
logger.info("cmdHome thread after await: ${Thread.currentThread().name}")
|
||||
|
||||
val uuid = target.player.uuid
|
||||
val ownedParcels = ownedParcelsResult
|
||||
|
||||
248
src/main/kotlin/io/dico/parcels2/listener/ParcelEditListener.kt
Normal file
248
src/main/kotlin/io/dico/parcels2/listener/ParcelEditListener.kt
Normal file
@@ -0,0 +1,248 @@
|
||||
package io.dico.parcels2.listener
|
||||
|
||||
import gnu.trove.TLongCollection
|
||||
import io.dico.dicore.ListenerMarker
|
||||
import io.dico.dicore.RegistratorListener
|
||||
import io.dico.parcels2.Parcel
|
||||
import io.dico.parcels2.ParcelWorld
|
||||
import io.dico.parcels2.Worlds
|
||||
import io.dico.parcels2.util.hasBanBypass
|
||||
import io.dico.parcels2.util.hasBuildAnywhere
|
||||
import io.dico.parcels2.util.sendParcelMessage
|
||||
import io.dico.parcels2.util.uuid
|
||||
import org.bukkit.Material.*
|
||||
import org.bukkit.block.Biome
|
||||
import org.bukkit.block.Block
|
||||
import org.bukkit.block.data.type.Bed
|
||||
import org.bukkit.entity.Player
|
||||
import org.bukkit.event.EventPriority.NORMAL
|
||||
import org.bukkit.event.block.*
|
||||
import org.bukkit.event.entity.EntityExplodeEvent
|
||||
import org.bukkit.event.entity.ExplosionPrimeEvent
|
||||
import org.bukkit.event.player.PlayerInteractEvent
|
||||
import org.bukkit.event.player.PlayerMoveEvent
|
||||
import org.bukkit.inventory.InventoryHolder
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
class ParcelEditListener(val worlds: Worlds) {
|
||||
val entityTracker = ParcelEntityTracker()
|
||||
|
||||
private inline fun <T> T?.isNullOr(condition: T.() -> Boolean): Boolean = this == null || condition()
|
||||
private inline fun <T> T?.isPresentAnd(condition: T.() -> Boolean): Boolean = this != null && condition()
|
||||
private inline fun
|
||||
fun Parcel?.canBuildN(user: Player) = isPresentAnd { canBuild(user) } || user.hasBuildAnywhere
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
private fun getWoAndPPa(block: Block): Pair<ParcelWorld, Parcel?>? {
|
||||
val world = worlds.getWorld(block.world) ?: return null
|
||||
return world to world.parcelAt(block)
|
||||
}
|
||||
|
||||
/*
|
||||
* Prevents players from entering plots they are banned from
|
||||
*/
|
||||
@ListenerMarker(priority = NORMAL)
|
||||
val onPlayerMove = RegistratorListener<PlayerMoveEvent> l@{ event ->
|
||||
val user = event.player
|
||||
if (user.hasBanBypass) return@l
|
||||
val parcel = worlds.getParcelAt(event.to) ?: return@l
|
||||
if (parcel.isBanned(user.uuid)) {
|
||||
worlds.getParcelAt(event.from)?.also {
|
||||
user.teleport(it.homeLocation)
|
||||
user.sendParcelMessage(nopermit = true, message = "You are banned from this parcel")
|
||||
} ?: run { event.to = event.from }
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Prevents players from breaking blocks outside of their parcels
|
||||
* Prevents containers from dropping their contents when broken, if configured
|
||||
*/
|
||||
@ListenerMarker(priority = NORMAL)
|
||||
val onBlockBreak = RegistratorListener<BlockBreakEvent> l@{ event ->
|
||||
val (wo, ppa) = getWoAndPPa(event.block) ?: return@l
|
||||
if (!event.player.hasBuildAnywhere && ppa.isNullOr { !canBuild(event.player) }) {
|
||||
event.isCancelled = true; return@l
|
||||
}
|
||||
|
||||
if (!wo.options.dropEntityItems) {
|
||||
val state = event.block.state
|
||||
if (state is InventoryHolder) {
|
||||
state.inventory.clear()
|
||||
state.update()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Prevents players from placing blocks outside of their parcels
|
||||
*/
|
||||
@ListenerMarker(priority = NORMAL)
|
||||
val onBlockPlace = RegistratorListener<BlockBreakEvent> l@{ event ->
|
||||
val (wo, ppa) = getWoAndPPa(event.block) ?: return@l
|
||||
if (!event.player.hasBuildAnywhere && !ppa.isNullOr { !canBuild(event.player) }) {
|
||||
event.isCancelled = true
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Control pistons
|
||||
*/
|
||||
@ListenerMarker(priority = NORMAL)
|
||||
val onBlockPistonExtend = RegistratorListener<BlockPistonExtendEvent> l@{ event ->
|
||||
checkPistonMovement(event, event.blocks)
|
||||
}
|
||||
|
||||
@ListenerMarker(priority = NORMAL)
|
||||
val onBlockPistonRetractEvent = RegistratorListener<BlockPistonRetractEvent> l@{ event ->
|
||||
checkPistonMovement(event, event.blocks)
|
||||
}
|
||||
|
||||
// Doing some unnecessary optimizations here..
|
||||
//@formatter:off
|
||||
private inline fun Column(x: Int, z: Int): Long = x.toLong() or (z.toLong().shl(32))
|
||||
|
||||
private inline val Long.columnX get() = and(0xFFFF_FFFFL).toInt()
|
||||
private inline val Long.columnZ get() = ushr(32).and(0xFFFF_FFFFL).toInt()
|
||||
private inline fun TLongCollection.forEachInline(block: (Long) -> Unit) = iterator().let { while (it.hasNext()) block(it.next()) }
|
||||
//@formatter:on
|
||||
private fun checkPistonMovement(event: BlockPistonEvent, blocks: List<Block>) {
|
||||
val world = worlds.getWorld(event.block.world) ?: return
|
||||
val direction = event.direction
|
||||
val columns = gnu.trove.set.hash.TLongHashSet(blocks.size * 2)
|
||||
|
||||
blocks.forEach {
|
||||
columns.add(Column(it.x, it.z))
|
||||
it.getRelative(direction).let { columns.add(Column(it.x, it.z)) }
|
||||
}
|
||||
|
||||
columns.forEachInline {
|
||||
val ppa = world.parcelAt(it.columnX, it.columnZ)
|
||||
if (ppa.isNullOr { hasBlockVisitors }) {
|
||||
event.isCancelled = true
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Prevents explosions if enabled by the configs for that world
|
||||
*/
|
||||
@ListenerMarker(priority = NORMAL)
|
||||
val onExplosionPrimeEvent = RegistratorListener<ExplosionPrimeEvent> l@{ event ->
|
||||
val (wo, ppa) = getWoAndPPa(event.entity.location.block) ?: return@l
|
||||
if (ppa?.hasBlockVisitors == true) {
|
||||
event.radius = 0F; event.isCancelled = true
|
||||
} else if (wo.options.disableExplosions) {
|
||||
event.radius = 0F
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Prevents creepers and tnt minecarts from exploding if explosions are disabled
|
||||
*/
|
||||
@ListenerMarker(priority = NORMAL)
|
||||
val onEntityExplodeEvent = RegistratorListener<EntityExplodeEvent> l@{ event ->
|
||||
entityTracker.untrack(event.entity)
|
||||
val world = worlds.getWorld(event.entity.world) ?: return@l
|
||||
if (world.options.disableExplosions || world.parcelAt(event.entity).isPresentAnd { hasBlockVisitors }) {
|
||||
event.isCancelled = true
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Prevents creepers and tnt minecarts from exploding if explosions are disabled
|
||||
*/
|
||||
@ListenerMarker(priority = NORMAL)
|
||||
val onBlockFromToEvent = RegistratorListener<BlockFromToEvent> l@{ event ->
|
||||
val (wo, ppa) = getWoAndPPa(event.toBlock) ?: return@l
|
||||
if (ppa.isNullOr { hasBlockVisitors }) event.isCancelled = true
|
||||
}
|
||||
|
||||
/*
|
||||
* Prevents players from placing liquids, using flint and steel, changing redstone components,
|
||||
* using inputs (unless allowed by the plot),
|
||||
* and using items disabled in the configuration for that world.
|
||||
* Prevents player from using beds in HELL or SKY biomes if explosions are disabled.
|
||||
*/
|
||||
@Suppress("NON_EXHAUSTIVE_WHEN")
|
||||
@ListenerMarker(priority = NORMAL)
|
||||
val onPlayerInteractEvent = RegistratorListener<PlayerInteractEvent> l@{ event ->
|
||||
val user = event.player
|
||||
val world = worlds.getWorld(user.world) ?: return@l
|
||||
val clickedBlock = event.clickedBlock
|
||||
val parcel = clickedBlock?.let { world.parcelAt(it) }
|
||||
|
||||
if (!user.hasBuildAnywhere && parcel.isPresentAnd { isBanned(user.uuid) }) {
|
||||
user.sendParcelMessage(nopermit = true, message = "You cannot interact with parcels you're banned from")
|
||||
event.isCancelled = true; return@l
|
||||
}
|
||||
|
||||
when (event.action) {
|
||||
Action.RIGHT_CLICK_BLOCK -> when (clickedBlock.type) {
|
||||
REPEATER,
|
||||
COMPARATOR -> run {
|
||||
if (!parcel.canBuildN(user)) {
|
||||
event.isCancelled = true; return@l
|
||||
}
|
||||
}
|
||||
LEVER,
|
||||
STONE_BUTTON,
|
||||
ANVIL,
|
||||
TRAPPED_CHEST,
|
||||
OAK_BUTTON, BIRCH_BUTTON, SPRUCE_BUTTON, JUNGLE_BUTTON, ACACIA_BUTTON, DARK_OAK_BUTTON,
|
||||
OAK_FENCE_GATE, BIRCH_FENCE_GATE, SPRUCE_FENCE_GATE, JUNGLE_FENCE_GATE, ACACIA_FENCE_GATE, DARK_OAK_FENCE_GATE,
|
||||
OAK_DOOR, BIRCH_DOOR, SPRUCE_DOOR, JUNGLE_DOOR, ACACIA_DOOR, DARK_OAK_DOOR,
|
||||
OAK_TRAPDOOR, BIRCH_TRAPDOOR, SPRUCE_TRAPDOOR, JUNGLE_TRAPDOOR, ACACIA_TRAPDOOR, DARK_OAK_TRAPDOOR
|
||||
-> run {
|
||||
if (!user.hasBuildAnywhere && !parcel.isNullOr { canBuild(user) || allowInteractInputs }) {
|
||||
user.sendParcelMessage(nopermit = true, message = "You cannot use inputs in this parcel")
|
||||
event.isCancelled = true; return@l
|
||||
}
|
||||
}
|
||||
|
||||
WHITE_BED, ORANGE_BED, MAGENTA_BED, LIGHT_BLUE_BED, YELLOW_BED, LIME_BED, PINK_BED, GRAY_BED, LIGHT_GRAY_BED, CYAN_BED, PURPLE_BED, BLUE_BED, BROWN_BED, GREEN_BED, RED_BED, BLACK_BED
|
||||
-> run {
|
||||
if (world.options.disableExplosions) {
|
||||
val bed = clickedBlock.blockData as Bed
|
||||
val head = if (bed == Bed.Part.FOOT) clickedBlock.getRelative(bed.facing) else clickedBlock
|
||||
when (head.biome) {
|
||||
Biome.NETHER, Biome.THE_END -> run {
|
||||
user.sendParcelMessage(nopermit = true, message = "You cannot use this bed because it would explode")
|
||||
event.isCancelled = true; return@l
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Action.RIGHT_CLICK_AIR -> if (event.hasItem()) {
|
||||
val item = event.item.type
|
||||
if (world.options.blockedItems.contains(item)) {
|
||||
user.sendParcelMessage(nopermit = true, message = "You cannot use this bed because it would explode")
|
||||
event.isCancelled = true; return@l
|
||||
}
|
||||
|
||||
if (!parcel.canBuildN(user)) {
|
||||
when (item) {
|
||||
LAVA_BUCKET, WATER_BUCKET, BUCKET, FLINT_AND_STEEL -> event.isCancelled = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Action.PHYSICAL -> if (!user.hasBuildAnywhere && !parcel.isPresentAnd { canBuild(user) || allowInteractInputs }) {
|
||||
event.isCancelled = true; return@l
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package io.dico.parcels2.listener
|
||||
|
||||
import io.dico.parcels2.Parcel
|
||||
import org.bukkit.entity.Entity
|
||||
|
||||
class ParcelEntityTracker {
|
||||
val map = mutableMapOf<Entity, Parcel>()
|
||||
|
||||
fun untrack(entity: Entity) {
|
||||
map.remove(entity)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
92
src/main/kotlin/io/dico/parcels2/util/MaterialExtensions.kt
Normal file
92
src/main/kotlin/io/dico/parcels2/util/MaterialExtensions.kt
Normal file
@@ -0,0 +1,92 @@
|
||||
package io.dico.parcels2.util
|
||||
|
||||
import org.bukkit.Material
|
||||
import org.bukkit.Material.*
|
||||
|
||||
/*
|
||||
colors:
|
||||
WHITE_$,
|
||||
ORANGE_$,
|
||||
MAGENTA_$,
|
||||
LIGHT_BLUE_$,
|
||||
YELLOW_$,
|
||||
LIME_$,
|
||||
PINK_$,
|
||||
GRAY_$,
|
||||
LIGHT_GRAY_$,
|
||||
CYAN_$,
|
||||
PURPLE_$,
|
||||
BLUE_$,
|
||||
BROWN_$,
|
||||
GREEN_$,
|
||||
RED_$,
|
||||
BLACK_$,
|
||||
|
||||
wood:
|
||||
OAK_$,
|
||||
BIRCH_$,
|
||||
SPRUCE_$,
|
||||
JUNGLE_$,
|
||||
ACACIA_$,
|
||||
DARK_OAK_$,
|
||||
*/
|
||||
|
||||
val Material.isBed get() = when(this) {
|
||||
WHITE_BED,
|
||||
ORANGE_BED,
|
||||
MAGENTA_BED,
|
||||
LIGHT_BLUE_BED,
|
||||
YELLOW_BED,
|
||||
LIME_BED,
|
||||
PINK_BED,
|
||||
GRAY_BED,
|
||||
LIGHT_GRAY_BED,
|
||||
CYAN_BED,
|
||||
PURPLE_BED,
|
||||
BLUE_BED,
|
||||
BROWN_BED,
|
||||
GREEN_BED,
|
||||
RED_BED,
|
||||
BLACK_BED -> true
|
||||
else -> false
|
||||
}
|
||||
|
||||
val Material.isWoodDoor get() = when(this) {
|
||||
OAK_DOOR,
|
||||
BIRCH_DOOR,
|
||||
SPRUCE_DOOR,
|
||||
JUNGLE_DOOR,
|
||||
ACACIA_DOOR,
|
||||
DARK_OAK_DOOR -> true
|
||||
else -> false
|
||||
}
|
||||
|
||||
val Material.isWoodTrapdoor get() = when(this) {
|
||||
OAK_TRAPDOOR,
|
||||
BIRCH_TRAPDOOR,
|
||||
SPRUCE_TRAPDOOR,
|
||||
JUNGLE_TRAPDOOR,
|
||||
ACACIA_TRAPDOOR,
|
||||
DARK_OAK_TRAPDOOR -> true
|
||||
else -> false
|
||||
}
|
||||
|
||||
val Material.isWoodFenceGate get() = when(this) {
|
||||
OAK_FENCE_GATE,
|
||||
BIRCH_FENCE_GATE,
|
||||
SPRUCE_FENCE_GATE,
|
||||
JUNGLE_FENCE_GATE,
|
||||
ACACIA_FENCE_GATE,
|
||||
DARK_OAK_FENCE_GATE -> true
|
||||
else -> false
|
||||
}
|
||||
|
||||
val Material.isWoodButton get() = when(this) {
|
||||
OAK_BUTTON,
|
||||
BIRCH_BUTTON,
|
||||
SPRUCE_BUTTON,
|
||||
JUNGLE_BUTTON,
|
||||
ACACIA_BUTTON,
|
||||
DARK_OAK_BUTTON -> true
|
||||
else -> false
|
||||
}
|
||||
@@ -9,8 +9,8 @@ import org.bukkit.plugin.java.JavaPlugin
|
||||
|
||||
inline val OfflinePlayer.uuid get() = uniqueId
|
||||
inline val Player.hasBanBypass get() = hasPermission("parcels.admin.bypass.ban")
|
||||
inline val Player.hasBuildAnywhere get() = hasPermission("parcels.admin.bypass.build")
|
||||
inline val Player.hasGamemodeBypass get() = hasPermission("parcels.admin.bypass.gamemode")
|
||||
inline val Player.hasBuildAnywhere get() = hasPermission("parcels.admin.bypass.build")
|
||||
inline val Player.hasAdminManage get() = hasPermission("parcels.admin.manage")
|
||||
inline val Player.hasParcelHomeOthers get() = hasPermission("parcels.command.home.others")
|
||||
inline val Player.hasRandomSpecific get() = hasPermission("parcels.command.random.specific")
|
||||
|
||||
Reference in New Issue
Block a user