chore: fmt/lint
This commit is contained in:
parent
2670443135
commit
1e2476a27b
|
|
@ -34,9 +34,10 @@ paper {
|
||||||
description = "Command library"
|
description = "Command library"
|
||||||
version = getVersion().toString()
|
version = getVersion().toString()
|
||||||
apiVersion = "1.21.10"
|
apiVersion = "1.21.10"
|
||||||
authors = listOf(
|
authors =
|
||||||
"Hare-K02"
|
listOf(
|
||||||
)
|
"Hare-K02",
|
||||||
|
)
|
||||||
serverDependencies {
|
serverDependencies {
|
||||||
register("permits-lib") {
|
register("permits-lib") {
|
||||||
load = PaperPluginDescription.RelativeLoadOrder.BEFORE
|
load = PaperPluginDescription.RelativeLoadOrder.BEFORE
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit 72312a45e029d2e5f0e9d5af0123e701b023974f
|
Subproject commit 7eb0534d2114c6f59c40a10783dbf49d53e00c4d
|
||||||
|
|
@ -6,9 +6,11 @@ import net.hareworks.kommand_lib.permissions.PermissionOptions
|
||||||
import net.hareworks.kommand_lib.permissions.PermissionRuntime
|
import net.hareworks.kommand_lib.permissions.PermissionRuntime
|
||||||
import org.bukkit.command.CommandSender
|
import org.bukkit.command.CommandSender
|
||||||
import org.bukkit.plugin.java.JavaPlugin
|
import org.bukkit.plugin.java.JavaPlugin
|
||||||
import org.bukkit.plugin.Plugin
|
|
||||||
|
|
||||||
fun kommand(plugin: JavaPlugin, block: KommandRegistry.() -> Unit): KommandLib {
|
fun kommand(
|
||||||
|
plugin: JavaPlugin,
|
||||||
|
block: KommandRegistry.() -> Unit,
|
||||||
|
): KommandLib {
|
||||||
val registry = KommandRegistry(plugin)
|
val registry = KommandRegistry(plugin)
|
||||||
registry.block()
|
registry.block()
|
||||||
return registry.build()
|
return registry.build()
|
||||||
|
|
@ -20,12 +22,12 @@ fun kommand(plugin: JavaPlugin, block: KommandRegistry.() -> Unit): KommandLib {
|
||||||
class KommandLib internal constructor(
|
class KommandLib internal constructor(
|
||||||
private val plugin: JavaPlugin,
|
private val plugin: JavaPlugin,
|
||||||
private val definitions: List<CommandDefinition>,
|
private val definitions: List<CommandDefinition>,
|
||||||
private val permissionRuntime: PermissionRuntime?
|
private val permissionRuntime: PermissionRuntime?,
|
||||||
) {
|
) {
|
||||||
init {
|
init {
|
||||||
registerAll()
|
registerAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun registerAll() {
|
private fun registerAll() {
|
||||||
val manager = plugin.lifecycleManager
|
val manager = plugin.lifecycleManager
|
||||||
@Suppress("UnstableApiUsage")
|
@Suppress("UnstableApiUsage")
|
||||||
|
|
@ -41,8 +43,8 @@ class KommandLib internal constructor(
|
||||||
|
|
||||||
fun unregister() {
|
fun unregister() {
|
||||||
// Lifecycle API handles unregistration automatically on disable usually?
|
// Lifecycle API handles unregistration automatically on disable usually?
|
||||||
// Or we might need to verify if manual unregistration is needed.
|
// Or we might need to verify if manual unregistration is needed.
|
||||||
// For now, clearing local state.
|
// For now, clearing local state.
|
||||||
// Note: Paper Lifecycle API doesn't expose easy unregister for static commands registered in 'COMMANDS' event usually,
|
// Note: Paper Lifecycle API doesn't expose easy unregister for static commands registered in 'COMMANDS' event usually,
|
||||||
// it rebuilds the dispatcher on reload.
|
// it rebuilds the dispatcher on reload.
|
||||||
permissionRuntime?.clear()
|
permissionRuntime?.clear()
|
||||||
|
|
@ -58,5 +60,5 @@ internal data class CommandDefinition(
|
||||||
val rootCondition: (CommandSender) -> Boolean,
|
val rootCondition: (CommandSender) -> Boolean,
|
||||||
val rootExecutor: (KommandContext.() -> Unit)?,
|
val rootExecutor: (KommandContext.() -> Unit)?,
|
||||||
val nodes: List<net.hareworks.kommand_lib.nodes.KommandNode>,
|
val nodes: List<net.hareworks.kommand_lib.nodes.KommandNode>,
|
||||||
val permissionOptions: PermissionOptions
|
val permissionOptions: PermissionOptions,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package net.hareworks.kommand_lib.plugin;
|
package net.hareworks.kommand_lib.plugin
|
||||||
|
|
||||||
import org.bukkit.plugin.java.JavaPlugin
|
import org.bukkit.plugin.java.JavaPlugin
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
public class Plugin : JavaPlugin() {}
|
public class Plugin : JavaPlugin()
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ import com.mojang.brigadier.builder.LiteralArgumentBuilder
|
||||||
import com.mojang.brigadier.builder.RequiredArgumentBuilder
|
import com.mojang.brigadier.builder.RequiredArgumentBuilder
|
||||||
import com.mojang.brigadier.context.CommandContext
|
import com.mojang.brigadier.context.CommandContext
|
||||||
import com.mojang.brigadier.suggestion.SuggestionsBuilder
|
import com.mojang.brigadier.suggestion.SuggestionsBuilder
|
||||||
import com.mojang.brigadier.tree.CommandNode
|
|
||||||
import io.papermc.paper.command.brigadier.CommandSourceStack
|
import io.papermc.paper.command.brigadier.CommandSourceStack
|
||||||
import io.papermc.paper.command.brigadier.Commands
|
import io.papermc.paper.command.brigadier.Commands
|
||||||
import net.hareworks.kommand_lib.context.KommandContext
|
import net.hareworks.kommand_lib.context.KommandContext
|
||||||
|
|
@ -16,13 +15,13 @@ import org.bukkit.plugin.java.JavaPlugin
|
||||||
|
|
||||||
@Suppress("UnstableApiUsage")
|
@Suppress("UnstableApiUsage")
|
||||||
internal object TreeCompiler {
|
internal object TreeCompiler {
|
||||||
|
|
||||||
fun compile(
|
fun compile(
|
||||||
plugin: JavaPlugin,
|
plugin: JavaPlugin,
|
||||||
definition: CommandDefinition
|
definition: CommandDefinition,
|
||||||
): LiteralArgumentBuilder<CommandSourceStack> {
|
): LiteralArgumentBuilder<CommandSourceStack> {
|
||||||
val root = Commands.literal(definition.name)
|
val root =
|
||||||
.requires { source -> definition.rootCondition(source.sender) }
|
Commands.literal(definition.name)
|
||||||
|
.requires { source -> definition.rootCondition(source.sender) }
|
||||||
|
|
||||||
// Root execution
|
// Root execution
|
||||||
definition.rootExecutor?.let { executor ->
|
definition.rootExecutor?.let { executor ->
|
||||||
|
|
@ -43,18 +42,19 @@ internal object TreeCompiler {
|
||||||
|
|
||||||
private fun compileNode(
|
private fun compileNode(
|
||||||
plugin: JavaPlugin,
|
plugin: JavaPlugin,
|
||||||
node: KommandNode
|
node: KommandNode,
|
||||||
): ArgumentBuilder<CommandSourceStack, *>? {
|
): ArgumentBuilder<CommandSourceStack, *>? {
|
||||||
val builder = when (node) {
|
val builder =
|
||||||
is LiteralNode -> {
|
when (node) {
|
||||||
Commands.literal(node.literal)
|
is LiteralNode -> {
|
||||||
|
Commands.literal(node.literal)
|
||||||
|
}
|
||||||
|
is ValueNode<*> -> {
|
||||||
|
val argType = node.argument.build()
|
||||||
|
Commands.argument(node.name, argType)
|
||||||
|
}
|
||||||
|
else -> return null
|
||||||
}
|
}
|
||||||
is ValueNode<*> -> {
|
|
||||||
val argType = node.argument.build()
|
|
||||||
Commands.argument(node.name, argType)
|
|
||||||
}
|
|
||||||
else -> return null
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.requires { source -> node.isVisible(source.sender) }
|
builder.requires { source -> node.isVisible(source.sender) }
|
||||||
|
|
||||||
|
|
@ -66,15 +66,18 @@ internal object TreeCompiler {
|
||||||
1
|
1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Custom Suggestions (if any)
|
// Custom Suggestions (if any)
|
||||||
if (node is ValueNode<*> && node.suggestionProvider != null && builder is RequiredArgumentBuilder<*, *>) {
|
if (node is ValueNode<*> && node.suggestionProvider != null && builder is RequiredArgumentBuilder<*, *>) {
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
(builder as RequiredArgumentBuilder<CommandSourceStack, Any>).suggests { ctx: CommandContext<CommandSourceStack>, suggestionsBuilder: SuggestionsBuilder ->
|
(builder as RequiredArgumentBuilder<CommandSourceStack, Any>).suggests {
|
||||||
val context = KommandContext(plugin, ctx)
|
ctx: CommandContext<CommandSourceStack>,
|
||||||
val suggestions = node.suggestionProvider!!.invoke(context, suggestionsBuilder.remaining)
|
suggestionsBuilder: SuggestionsBuilder,
|
||||||
suggestions.forEach { suggestionsBuilder.suggest(it) }
|
->
|
||||||
suggestionsBuilder.buildFuture()
|
val context = KommandContext(plugin, ctx)
|
||||||
|
val suggestions = node.suggestionProvider!!.invoke(context, suggestionsBuilder.remaining)
|
||||||
|
suggestions.forEach { suggestionsBuilder.suggest(it) }
|
||||||
|
suggestionsBuilder.buildFuture()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,17 +6,14 @@ import com.mojang.brigadier.arguments.DoubleArgumentType
|
||||||
import com.mojang.brigadier.arguments.IntegerArgumentType
|
import com.mojang.brigadier.arguments.IntegerArgumentType
|
||||||
import com.mojang.brigadier.arguments.StringArgumentType
|
import com.mojang.brigadier.arguments.StringArgumentType
|
||||||
import io.papermc.paper.command.brigadier.argument.ArgumentTypes
|
import io.papermc.paper.command.brigadier.argument.ArgumentTypes
|
||||||
import io.papermc.paper.command.brigadier.argument.resolvers.selector.PlayerSelectorArgumentResolver
|
|
||||||
import io.papermc.paper.command.brigadier.argument.resolvers.selector.EntitySelectorArgumentResolver
|
import io.papermc.paper.command.brigadier.argument.resolvers.selector.EntitySelectorArgumentResolver
|
||||||
|
import io.papermc.paper.command.brigadier.argument.resolvers.selector.PlayerSelectorArgumentResolver
|
||||||
import org.bukkit.entity.Entity
|
import org.bukkit.entity.Entity
|
||||||
import org.bukkit.entity.Player
|
import org.bukkit.entity.Player
|
||||||
import org.bukkit.util.Vector
|
|
||||||
import org.bukkit.Location
|
|
||||||
import org.bukkit.command.CommandSender
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A holder for the Brigadier ArgumentType and any metadata needed for the DSL.
|
* A holder for the Brigadier ArgumentType and any metadata needed for the DSL.
|
||||||
*
|
*
|
||||||
* Note: T represents the final type that users will receive in KommandContext.argument<T>(),
|
* Note: T represents the final type that users will receive in KommandContext.argument<T>(),
|
||||||
* not necessarily the raw Brigadier return type. For example, PlayerArgument has T=Player,
|
* not necessarily the raw Brigadier return type. For example, PlayerArgument has T=Player,
|
||||||
* but Brigadier returns PlayerSelectorArgumentResolver which is resolved to Player by ArgumentResolver.
|
* but Brigadier returns PlayerSelectorArgumentResolver which is resolved to Player by ArgumentResolver.
|
||||||
|
|
@ -33,17 +30,16 @@ class GreedyStringArgument : KommandArgument<String> {
|
||||||
override fun build(): ArgumentType<String> = StringArgumentType.greedyString()
|
override fun build(): ArgumentType<String> = StringArgumentType.greedyString()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class IntegerArgument(
|
class IntegerArgument(
|
||||||
private val min: Int = Int.MIN_VALUE,
|
private val min: Int = Int.MIN_VALUE,
|
||||||
private val max: Int = Int.MAX_VALUE
|
private val max: Int = Int.MAX_VALUE,
|
||||||
) : KommandArgument<Int> {
|
) : KommandArgument<Int> {
|
||||||
override fun build(): ArgumentType<Int> = IntegerArgumentType.integer(min, max)
|
override fun build(): ArgumentType<Int> = IntegerArgumentType.integer(min, max)
|
||||||
}
|
}
|
||||||
|
|
||||||
class FloatArgument(
|
class FloatArgument(
|
||||||
private val min: Double = -Double.MAX_VALUE,
|
private val min: Double = -Double.MAX_VALUE,
|
||||||
private val max: Double = Double.MAX_VALUE
|
private val max: Double = Double.MAX_VALUE,
|
||||||
) : KommandArgument<Double> {
|
) : KommandArgument<Double> {
|
||||||
override fun build(): ArgumentType<Double> = DoubleArgumentType.doubleArg(min, max)
|
override fun build(): ArgumentType<Double> = DoubleArgumentType.doubleArg(min, max)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,30 +2,30 @@ package net.hareworks.kommand_lib.context
|
||||||
|
|
||||||
import com.mojang.brigadier.context.CommandContext
|
import com.mojang.brigadier.context.CommandContext
|
||||||
import io.papermc.paper.command.brigadier.CommandSourceStack
|
import io.papermc.paper.command.brigadier.CommandSourceStack
|
||||||
import io.papermc.paper.command.brigadier.argument.resolvers.selector.PlayerSelectorArgumentResolver
|
|
||||||
import io.papermc.paper.command.brigadier.argument.resolvers.selector.EntitySelectorArgumentResolver
|
|
||||||
import io.papermc.paper.command.brigadier.argument.resolvers.FinePositionResolver
|
|
||||||
import io.papermc.paper.command.brigadier.argument.resolvers.BlockPositionResolver
|
import io.papermc.paper.command.brigadier.argument.resolvers.BlockPositionResolver
|
||||||
import io.papermc.paper.math.Position
|
import io.papermc.paper.command.brigadier.argument.resolvers.FinePositionResolver
|
||||||
import org.bukkit.entity.Entity
|
import io.papermc.paper.command.brigadier.argument.resolvers.selector.EntitySelectorArgumentResolver
|
||||||
|
import io.papermc.paper.command.brigadier.argument.resolvers.selector.PlayerSelectorArgumentResolver
|
||||||
import org.bukkit.entity.Player
|
import org.bukkit.entity.Player
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal helper to resolve Brigadier argument types to their actual values.
|
* Internal helper to resolve Brigadier argument types to their actual values.
|
||||||
* This handles the conversion from Paper's resolver types to concrete Bukkit types.
|
* This handles the conversion from Paper's resolver types to concrete Bukkit types.
|
||||||
*
|
*
|
||||||
* Note: This is public because it's called from inline functions in KommandContext,
|
* Note: This is public because it's called from inline functions in KommandContext,
|
||||||
* but it's not intended for direct use by library consumers.
|
* but it's not intended for direct use by library consumers.
|
||||||
*/
|
*/
|
||||||
object ArgumentResolver {
|
object ArgumentResolver {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolves an argument from the command context.
|
* Resolves an argument from the command context.
|
||||||
* Handles special cases for Paper's selector resolvers and position resolvers.
|
* Handles special cases for Paper's selector resolvers and position resolvers.
|
||||||
*/
|
*/
|
||||||
inline fun <reified T> resolve(context: CommandContext<CommandSourceStack>, name: String): T {
|
inline fun <reified T> resolve(
|
||||||
|
context: CommandContext<CommandSourceStack>,
|
||||||
|
name: String,
|
||||||
|
): T {
|
||||||
val rawValue = context.getArgument(name, Any::class.java)
|
val rawValue = context.getArgument(name, Any::class.java)
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
return when {
|
return when {
|
||||||
// Single player selector
|
// Single player selector
|
||||||
|
|
@ -33,38 +33,41 @@ object ArgumentResolver {
|
||||||
rawValue.resolve(context.source).firstOrNull() as T
|
rawValue.resolve(context.source).firstOrNull() as T
|
||||||
?: throw IllegalStateException("Player selector '$name' did not resolve to any player")
|
?: throw IllegalStateException("Player selector '$name' did not resolve to any player")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Multiple players selector
|
// Multiple players selector
|
||||||
T::class.java == List::class.java && rawValue is PlayerSelectorArgumentResolver -> {
|
T::class.java == List::class.java && rawValue is PlayerSelectorArgumentResolver -> {
|
||||||
rawValue.resolve(context.source) as T
|
rawValue.resolve(context.source) as T
|
||||||
}
|
}
|
||||||
|
|
||||||
// Entity selector
|
// Entity selector
|
||||||
T::class.java == List::class.java && rawValue is EntitySelectorArgumentResolver -> {
|
T::class.java == List::class.java && rawValue is EntitySelectorArgumentResolver -> {
|
||||||
rawValue.resolve(context.source) as T
|
rawValue.resolve(context.source) as T
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fine position (coordinates with decimals)
|
// Fine position (coordinates with decimals)
|
||||||
rawValue is FinePositionResolver -> {
|
rawValue is FinePositionResolver -> {
|
||||||
rawValue.resolve(context.source) as T
|
rawValue.resolve(context.source) as T
|
||||||
}
|
}
|
||||||
|
|
||||||
// Block position (integer coordinates)
|
// Block position (integer coordinates)
|
||||||
rawValue is BlockPositionResolver -> {
|
rawValue is BlockPositionResolver -> {
|
||||||
rawValue.resolve(context.source) as T
|
rawValue.resolve(context.source) as T
|
||||||
}
|
}
|
||||||
|
|
||||||
// All other types (primitives, strings, etc.)
|
// All other types (primitives, strings, etc.)
|
||||||
else -> {
|
else -> {
|
||||||
context.getArgument(name, T::class.java)
|
context.getArgument(name, T::class.java)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolves an argument or returns null if not found.
|
* Resolves an argument or returns null if not found.
|
||||||
*/
|
*/
|
||||||
inline fun <reified T> resolveOrNull(context: CommandContext<CommandSourceStack>, name: String): T? {
|
inline fun <reified T> resolveOrNull(
|
||||||
|
context: CommandContext<CommandSourceStack>,
|
||||||
|
name: String,
|
||||||
|
): T? {
|
||||||
return try {
|
return try {
|
||||||
resolve<T>(context, name)
|
resolve<T>(context, name)
|
||||||
} catch (e: IllegalArgumentException) {
|
} catch (e: IllegalArgumentException) {
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import org.bukkit.plugin.java.JavaPlugin
|
||||||
|
|
||||||
class KommandContext internal constructor(
|
class KommandContext internal constructor(
|
||||||
val plugin: JavaPlugin,
|
val plugin: JavaPlugin,
|
||||||
val internal: CommandContext<CommandSourceStack>
|
val internal: CommandContext<CommandSourceStack>,
|
||||||
) {
|
) {
|
||||||
val sender: CommandSender
|
val sender: CommandSender
|
||||||
get() = internal.source.sender
|
get() = internal.source.sender
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,13 @@ package net.hareworks.kommand_lib.dsl
|
||||||
|
|
||||||
import net.hareworks.kommand_lib.CommandDefinition
|
import net.hareworks.kommand_lib.CommandDefinition
|
||||||
import net.hareworks.kommand_lib.arguments.*
|
import net.hareworks.kommand_lib.arguments.*
|
||||||
|
import net.hareworks.kommand_lib.nodes.KommandNode
|
||||||
|
import net.hareworks.kommand_lib.nodes.LiteralNode
|
||||||
|
import net.hareworks.kommand_lib.nodes.ValueNode
|
||||||
import net.hareworks.kommand_lib.permissions.PermissionConfigBuilder
|
import net.hareworks.kommand_lib.permissions.PermissionConfigBuilder
|
||||||
import net.hareworks.kommand_lib.permissions.PermissionOptions
|
import net.hareworks.kommand_lib.permissions.PermissionOptions
|
||||||
import net.hareworks.kommand_lib.permissions.PermissionPlanner
|
import net.hareworks.kommand_lib.permissions.PermissionPlanner
|
||||||
import net.hareworks.kommand_lib.permissions.PermissionRuntime
|
import net.hareworks.kommand_lib.permissions.PermissionRuntime
|
||||||
import net.hareworks.kommand_lib.nodes.KommandNode
|
|
||||||
import net.hareworks.kommand_lib.nodes.LiteralNode
|
|
||||||
import net.hareworks.kommand_lib.nodes.ValueNode
|
|
||||||
import org.bukkit.command.CommandSender
|
import org.bukkit.command.CommandSender
|
||||||
import org.bukkit.entity.Entity
|
import org.bukkit.entity.Entity
|
||||||
import org.bukkit.entity.Player
|
import org.bukkit.entity.Player
|
||||||
|
|
@ -19,13 +19,21 @@ class KommandRegistry internal constructor(private val plugin: JavaPlugin) {
|
||||||
private val definitions = mutableListOf<CommandDefinition>()
|
private val definitions = mutableListOf<CommandDefinition>()
|
||||||
private var permissionConfigBuilder: PermissionConfigBuilder? = null
|
private var permissionConfigBuilder: PermissionConfigBuilder? = null
|
||||||
|
|
||||||
fun command(name: String, vararg aliases: String, block: CommandBuilder.() -> Unit) {
|
fun command(
|
||||||
|
name: String,
|
||||||
|
vararg aliases: String,
|
||||||
|
block: CommandBuilder.() -> Unit,
|
||||||
|
) {
|
||||||
val builder = CommandBuilder(name, aliases.toList())
|
val builder = CommandBuilder(name, aliases.toList())
|
||||||
builder.block()
|
builder.block()
|
||||||
definitions += builder.build()
|
definitions += builder.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun command(name: String, aliases: Iterable<String>, block: CommandBuilder.() -> Unit) {
|
fun command(
|
||||||
|
name: String,
|
||||||
|
aliases: Iterable<String>,
|
||||||
|
block: CommandBuilder.() -> Unit,
|
||||||
|
) {
|
||||||
val builder = CommandBuilder(name, aliases.toList())
|
val builder = CommandBuilder(name, aliases.toList())
|
||||||
builder.block()
|
builder.block()
|
||||||
definitions += builder.build()
|
definitions += builder.build()
|
||||||
|
|
@ -39,10 +47,11 @@ class KommandRegistry internal constructor(private val plugin: JavaPlugin) {
|
||||||
internal fun build(): net.hareworks.kommand_lib.KommandLib {
|
internal fun build(): net.hareworks.kommand_lib.KommandLib {
|
||||||
val snapshot = definitions.toList()
|
val snapshot = definitions.toList()
|
||||||
val config = permissionConfigBuilder?.build()
|
val config = permissionConfigBuilder?.build()
|
||||||
val runtime = config?.let {
|
val runtime =
|
||||||
val plan = PermissionPlanner(plugin, it, snapshot).plan()
|
config?.let {
|
||||||
if (plan.isEmpty()) null else PermissionRuntime(plugin, plan)
|
val plan = PermissionPlanner(plugin, it, snapshot).plan()
|
||||||
}
|
if (plan.isEmpty()) null else PermissionRuntime(plugin, plan)
|
||||||
|
}
|
||||||
return net.hareworks.kommand_lib.KommandLib(plugin, snapshot, runtime)
|
return net.hareworks.kommand_lib.KommandLib(plugin, snapshot, runtime)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -50,7 +59,7 @@ class KommandRegistry internal constructor(private val plugin: JavaPlugin) {
|
||||||
@KommandDsl
|
@KommandDsl
|
||||||
class CommandBuilder internal constructor(
|
class CommandBuilder internal constructor(
|
||||||
val name: String,
|
val name: String,
|
||||||
val aliases: List<String>
|
val aliases: List<String>,
|
||||||
) : BranchScope(mutableListOf()) {
|
) : BranchScope(mutableListOf()) {
|
||||||
var description: String? = null
|
var description: String? = null
|
||||||
var usage: String? = null
|
var usage: String? = null
|
||||||
|
|
@ -98,18 +107,21 @@ class CommandBuilder internal constructor(
|
||||||
rootCondition = condition,
|
rootCondition = condition,
|
||||||
rootExecutor = rootExecutor,
|
rootExecutor = rootExecutor,
|
||||||
nodes = children.toList(),
|
nodes = children.toList(),
|
||||||
permissionOptions = permissionOptions
|
permissionOptions = permissionOptions,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@KommandDsl
|
@KommandDsl
|
||||||
abstract class BranchScope internal constructor(
|
abstract class BranchScope internal constructor(
|
||||||
protected val children: MutableList<KommandNode>
|
protected val children: MutableList<KommandNode>,
|
||||||
) {
|
) {
|
||||||
protected abstract val inheritedPermission: String?
|
protected abstract val inheritedPermission: String?
|
||||||
protected abstract val inheritedCondition: (CommandSender) -> Boolean
|
protected abstract val inheritedCondition: (CommandSender) -> Boolean
|
||||||
|
|
||||||
fun literal(name: String, block: LiteralBuilder.() -> Unit = {}) {
|
fun literal(
|
||||||
|
name: String,
|
||||||
|
block: LiteralBuilder.() -> Unit = {},
|
||||||
|
) {
|
||||||
val node = LiteralNode(name)
|
val node = LiteralNode(name)
|
||||||
node.permission = inheritedPermission
|
node.permission = inheritedPermission
|
||||||
node.condition = inheritedCondition
|
node.condition = inheritedCondition
|
||||||
|
|
@ -117,7 +129,11 @@ abstract class BranchScope internal constructor(
|
||||||
LiteralBuilder(node).apply(block)
|
LiteralBuilder(node).apply(block)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T> argument(name: String, type: KommandArgument<T>, block: ValueBuilder<T>.() -> Unit = {}) {
|
fun <T> argument(
|
||||||
|
name: String,
|
||||||
|
type: KommandArgument<T>,
|
||||||
|
block: ValueBuilder<T>.() -> Unit = {},
|
||||||
|
) {
|
||||||
val node = ValueNode(name, type)
|
val node = ValueNode(name, type)
|
||||||
node.permission = inheritedPermission
|
node.permission = inheritedPermission
|
||||||
node.condition = inheritedCondition
|
node.condition = inheritedCondition
|
||||||
|
|
@ -126,64 +142,69 @@ abstract class BranchScope internal constructor(
|
||||||
ValueBuilder(node).apply(block)
|
ValueBuilder(node).apply(block)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun string(name: String, block: ValueBuilder<String>.() -> Unit = {}) = argument(name, WordArgument(), block)
|
fun string(
|
||||||
|
name: String,
|
||||||
fun greedyString(name: String, block: ValueBuilder<String>.() -> Unit = {}) = argument(name, GreedyStringArgument(), block)
|
block: ValueBuilder<String>.() -> Unit = {},
|
||||||
|
) = argument(name, WordArgument(), block)
|
||||||
|
|
||||||
|
fun greedyString(
|
||||||
|
name: String,
|
||||||
|
block: ValueBuilder<String>.() -> Unit = {},
|
||||||
|
) = argument(name, GreedyStringArgument(), block)
|
||||||
|
|
||||||
fun integer(
|
fun integer(
|
||||||
name: String,
|
name: String,
|
||||||
min: Int = Int.MIN_VALUE,
|
min: Int = Int.MIN_VALUE,
|
||||||
max: Int = Int.MAX_VALUE,
|
max: Int = Int.MAX_VALUE,
|
||||||
block: ValueBuilder<Int>.() -> Unit = {}
|
block: ValueBuilder<Int>.() -> Unit = {},
|
||||||
) = argument(name, IntegerArgument(min, max), block)
|
) = argument(name, IntegerArgument(min, max), block)
|
||||||
|
|
||||||
fun float(
|
fun float(
|
||||||
name: String,
|
name: String,
|
||||||
min: Double = -Double.MAX_VALUE,
|
min: Double = -Double.MAX_VALUE,
|
||||||
max: Double = Double.MAX_VALUE,
|
max: Double = Double.MAX_VALUE,
|
||||||
block: ValueBuilder<Double>.() -> Unit = {}
|
block: ValueBuilder<Double>.() -> Unit = {},
|
||||||
) = argument(name, FloatArgument(min, max), block)
|
) = argument(name, FloatArgument(min, max), block)
|
||||||
|
|
||||||
fun bool(
|
fun bool(
|
||||||
name: String,
|
name: String,
|
||||||
block: ValueBuilder<Boolean>.() -> Unit = {}
|
block: ValueBuilder<Boolean>.() -> Unit = {},
|
||||||
) = argument(name, BooleanArgument(), block)
|
) = argument(name, BooleanArgument(), block)
|
||||||
|
|
||||||
fun player(
|
fun player(
|
||||||
name: String,
|
name: String,
|
||||||
allowSelectors: Boolean = true, // Ignored logic-wise if using native, assuming it handles selectors
|
allowSelectors: Boolean = true, // Ignored logic-wise if using native, assuming it handles selectors
|
||||||
block: ValueBuilder<Player>.() -> Unit = {}
|
block: ValueBuilder<Player>.() -> Unit = {},
|
||||||
) = argument(name, PlayerArgument(), block)
|
) = argument(name, PlayerArgument(), block)
|
||||||
|
|
||||||
fun players(
|
fun players(
|
||||||
name: String,
|
name: String,
|
||||||
allowDirectNames: Boolean = true,
|
allowDirectNames: Boolean = true,
|
||||||
block: ValueBuilder<List<Player>>.() -> Unit = {}
|
block: ValueBuilder<List<Player>>.() -> Unit = {},
|
||||||
) = argument(name, PlayersArgument(), block)
|
) = argument(name, PlayersArgument(), block)
|
||||||
|
|
||||||
fun selector(
|
fun selector(
|
||||||
name: String,
|
name: String,
|
||||||
requireMatch: Boolean = true,
|
requireMatch: Boolean = true,
|
||||||
block: ValueBuilder<List<Entity>>.() -> Unit = {}
|
block: ValueBuilder<List<Entity>>.() -> Unit = {},
|
||||||
) = argument(name, EntityArgument(), block)
|
) = argument(name, EntityArgument(), block)
|
||||||
|
|
||||||
fun coordinates(
|
fun coordinates(
|
||||||
name: String,
|
name: String,
|
||||||
allowRelative: Boolean = true,
|
allowRelative: Boolean = true,
|
||||||
block: ValueBuilder<io.papermc.paper.math.Position>.() -> Unit = {}
|
block: ValueBuilder<io.papermc.paper.math.Position>.() -> Unit = {},
|
||||||
) = argument(name, CoordinatesArgument(), block)
|
) = argument(name, CoordinatesArgument(), block)
|
||||||
|
|
||||||
fun blockCoordinates(
|
fun blockCoordinates(
|
||||||
name: String,
|
name: String,
|
||||||
allowRelative: Boolean = true,
|
allowRelative: Boolean = true,
|
||||||
block: ValueBuilder<io.papermc.paper.math.Position>.() -> Unit = {}
|
block: ValueBuilder<io.papermc.paper.math.Position>.() -> Unit = {},
|
||||||
) = argument(name, BlockPositionArgument(), block)
|
) = argument(name, BlockPositionArgument(), block)
|
||||||
}
|
}
|
||||||
|
|
||||||
@KommandDsl
|
@KommandDsl
|
||||||
abstract class NodeScope internal constructor(
|
abstract class NodeScope internal constructor(
|
||||||
protected val node: KommandNode
|
protected val node: KommandNode,
|
||||||
) : BranchScope(node.children) {
|
) : BranchScope(node.children) {
|
||||||
override val inheritedPermission: String?
|
override val inheritedPermission: String?
|
||||||
get() = node.permission
|
get() = node.permission
|
||||||
|
|
@ -215,12 +236,12 @@ abstract class NodeScope internal constructor(
|
||||||
|
|
||||||
@KommandDsl
|
@KommandDsl
|
||||||
class LiteralBuilder internal constructor(
|
class LiteralBuilder internal constructor(
|
||||||
private val literalNode: LiteralNode
|
private val literalNode: LiteralNode,
|
||||||
) : NodeScope(literalNode)
|
) : NodeScope(literalNode)
|
||||||
|
|
||||||
@KommandDsl
|
@KommandDsl
|
||||||
class ValueBuilder<T> internal constructor(
|
class ValueBuilder<T> internal constructor(
|
||||||
private val valueNode: ValueNode<T>
|
private val valueNode: ValueNode<T>,
|
||||||
) : NodeScope(valueNode) {
|
) : NodeScope(valueNode) {
|
||||||
/**
|
/**
|
||||||
* Overrides the default suggestion provider (wrapper around Brigadier logic)
|
* Overrides the default suggestion provider (wrapper around Brigadier logic)
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ class LiteralNode internal constructor(val literal: String) : KommandNode() {
|
||||||
|
|
||||||
class ValueNode<T> internal constructor(
|
class ValueNode<T> internal constructor(
|
||||||
val name: String,
|
val name: String,
|
||||||
val argument: KommandArgument<T>
|
val argument: KommandArgument<T>,
|
||||||
) : KommandNode() {
|
) : KommandNode() {
|
||||||
var suggestionProvider: ((KommandContext, String) -> List<String>)? = null
|
var suggestionProvider: ((KommandContext, String) -> List<String>)? = null
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ class PermissionConfig internal constructor(
|
||||||
val defaultDescription: (PermissionContext) -> String?,
|
val defaultDescription: (PermissionContext) -> String?,
|
||||||
val defaultValue: PermissionDefault,
|
val defaultValue: PermissionDefault,
|
||||||
val defaultWildcard: Boolean,
|
val defaultWildcard: Boolean,
|
||||||
private val sessionProvider: (JavaPlugin) -> MutationSession
|
private val sessionProvider: (JavaPlugin) -> MutationSession,
|
||||||
) {
|
) {
|
||||||
fun session(plugin: JavaPlugin): MutationSession = sessionProvider(plugin)
|
fun session(plugin: JavaPlugin): MutationSession = sessionProvider(plugin)
|
||||||
}
|
}
|
||||||
|
|
@ -61,18 +61,18 @@ class PermissionConfigBuilder internal constructor(private val plugin: JavaPlugi
|
||||||
defaultDescription = descriptionTemplate,
|
defaultDescription = descriptionTemplate,
|
||||||
defaultValue = defaultValue,
|
defaultValue = defaultValue,
|
||||||
defaultWildcard = wildcard,
|
defaultWildcard = wildcard,
|
||||||
sessionProvider = sessionFactory ?: { PermitsLib.session(it) }
|
sessionProvider = sessionFactory ?: { PermitsLib.session(it) },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
data class PermissionContext(
|
data class PermissionContext(
|
||||||
val commandName: String,
|
val commandName: String,
|
||||||
val path: List<String>,
|
val path: List<String>,
|
||||||
val kind: PermissionNodeKind
|
val kind: PermissionNodeKind,
|
||||||
)
|
)
|
||||||
|
|
||||||
enum class PermissionNodeKind {
|
enum class PermissionNodeKind {
|
||||||
COMMAND,
|
COMMAND,
|
||||||
LITERAL,
|
LITERAL,
|
||||||
ARGUMENT
|
ARGUMENT,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,11 @@ class PermissionOptions {
|
||||||
private set
|
private set
|
||||||
|
|
||||||
fun rename(vararg segments: String) {
|
fun rename(vararg segments: String) {
|
||||||
customPath = segments
|
customPath =
|
||||||
.map { it.trim() }
|
segments
|
||||||
.filter { it.isNotEmpty() }
|
.map { it.trim() }
|
||||||
.toMutableList()
|
.filter { it.isNotEmpty() }
|
||||||
|
.toMutableList()
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun renameOverride(): List<String>? = customPath?.toList()
|
internal fun renameOverride(): List<String>? = customPath?.toList()
|
||||||
|
|
@ -42,13 +43,14 @@ class PermissionOptions {
|
||||||
}
|
}
|
||||||
|
|
||||||
class WildcardOptions internal constructor(
|
class WildcardOptions internal constructor(
|
||||||
private val sink: MutableList<List<String>>
|
private val sink: MutableList<List<String>>,
|
||||||
) {
|
) {
|
||||||
fun exclude(vararg segments: String) {
|
fun exclude(vararg segments: String) {
|
||||||
val normalized = segments
|
val normalized =
|
||||||
.flatMap { it.split('.') }
|
segments
|
||||||
.map { it.trim().lowercase() }
|
.flatMap { it.split('.') }
|
||||||
.filter { it.isNotEmpty() }
|
.map { it.trim().lowercase() }
|
||||||
|
.filter { it.isNotEmpty() }
|
||||||
if (normalized.isNotEmpty()) {
|
if (normalized.isNotEmpty()) {
|
||||||
sink += normalized
|
sink += normalized
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,10 @@ import org.bukkit.permissions.PermissionDefault
|
||||||
|
|
||||||
data class PermissionPlan(
|
data class PermissionPlan(
|
||||||
val config: PermissionConfig,
|
val config: PermissionConfig,
|
||||||
val entries: List<PlannedPermission>
|
val entries: List<PlannedPermission>,
|
||||||
) {
|
) {
|
||||||
val namespace: String get() = config.namespace
|
val namespace: String get() = config.namespace
|
||||||
|
|
||||||
fun isEmpty(): Boolean = entries.isEmpty()
|
fun isEmpty(): Boolean = entries.isEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -20,5 +21,5 @@ data class PlannedPermission(
|
||||||
val wildcardExclusions: List<List<String>>,
|
val wildcardExclusions: List<List<String>>,
|
||||||
val inheritsParentDefault: Boolean,
|
val inheritsParentDefault: Boolean,
|
||||||
val wildcard: Boolean,
|
val wildcard: Boolean,
|
||||||
val registration: NodeRegistration
|
val registration: NodeRegistration,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -11,40 +11,44 @@ import org.bukkit.plugin.java.JavaPlugin
|
||||||
internal class PermissionPlanner(
|
internal class PermissionPlanner(
|
||||||
private val plugin: JavaPlugin,
|
private val plugin: JavaPlugin,
|
||||||
private val config: PermissionConfig,
|
private val config: PermissionConfig,
|
||||||
private val definitions: List<CommandDefinition>
|
private val definitions: List<CommandDefinition>,
|
||||||
) {
|
) {
|
||||||
fun plan(): PermissionPlan {
|
fun plan(): PermissionPlan {
|
||||||
val entries = linkedMapOf<String, PlannedPermission>()
|
val entries = linkedMapOf<String, PlannedPermission>()
|
||||||
val (rootPath, rootDefault) = if (config.includeRootNode && config.rootSegment.isNotBlank()) {
|
val (rootPath, rootDefault) =
|
||||||
val path = listOf(config.rootSegment)
|
if (config.includeRootNode && config.rootSegment.isNotBlank()) {
|
||||||
val entry = createEntry(
|
val path = listOf(config.rootSegment)
|
||||||
options = PermissionOptions().apply { id = buildId(path) },
|
val entry =
|
||||||
pathSegments = path,
|
createEntry(
|
||||||
context = PermissionContext(commandName = "", path = path, kind = PermissionNodeKind.LITERAL),
|
options = PermissionOptions().apply { id = buildId(path) },
|
||||||
parentDefault = config.defaultValue,
|
pathSegments = path,
|
||||||
registration = NodeRegistration.STRUCTURAL
|
context = PermissionContext(commandName = "", path = path, kind = PermissionNodeKind.LITERAL),
|
||||||
)
|
parentDefault = config.defaultValue,
|
||||||
if (entry != null) entries[entry.id] = entry
|
registration = NodeRegistration.STRUCTURAL,
|
||||||
path to (entry?.defaultValue ?: config.defaultValue)
|
)
|
||||||
} else {
|
if (entry != null) entries[entry.id] = entry
|
||||||
emptyList<String>() to config.defaultValue
|
path to (entry?.defaultValue ?: config.defaultValue)
|
||||||
}
|
} else {
|
||||||
|
emptyList<String>() to config.defaultValue
|
||||||
|
}
|
||||||
|
|
||||||
definitions.forEach { definition ->
|
definitions.forEach { definition ->
|
||||||
val overridePath = definition.permissionOptions.renameOverride()
|
val overridePath = definition.permissionOptions.renameOverride()
|
||||||
val commandPath = if (overridePath != null) {
|
val commandPath =
|
||||||
normalizeSegments(overridePath)
|
if (overridePath != null) {
|
||||||
} else {
|
normalizeSegments(overridePath)
|
||||||
val sanitized = sanitize(definition.name)
|
} else {
|
||||||
val base = if (rootPath.isNotEmpty()) rootPath else emptyList()
|
val sanitized = sanitize(definition.name)
|
||||||
base + sanitized
|
val base = if (rootPath.isNotEmpty()) rootPath else emptyList()
|
||||||
}
|
base + sanitized
|
||||||
val commandEntry = createEntry(
|
}
|
||||||
options = definition.permissionOptions,
|
val commandEntry =
|
||||||
pathSegments = commandPath,
|
createEntry(
|
||||||
context = PermissionContext(definition.name, commandPath, PermissionNodeKind.COMMAND),
|
options = definition.permissionOptions,
|
||||||
parentDefault = rootDefault
|
pathSegments = commandPath,
|
||||||
)
|
context = PermissionContext(definition.name, commandPath, PermissionNodeKind.COMMAND),
|
||||||
|
parentDefault = rootDefault,
|
||||||
|
)
|
||||||
if (commandEntry != null) {
|
if (commandEntry != null) {
|
||||||
entries[commandEntry.id] = commandEntry
|
entries[commandEntry.id] = commandEntry
|
||||||
if (definition.permission.isNullOrBlank()) {
|
if (definition.permission.isNullOrBlank()) {
|
||||||
|
|
@ -64,14 +68,16 @@ internal class PermissionPlanner(
|
||||||
basePath: List<String>,
|
basePath: List<String>,
|
||||||
entries: MutableMap<String, PlannedPermission>,
|
entries: MutableMap<String, PlannedPermission>,
|
||||||
commandName: String,
|
commandName: String,
|
||||||
parentDefault: PermissionDefault
|
parentDefault: PermissionDefault,
|
||||||
) {
|
) {
|
||||||
val rawOverride = node.permissionOptions.renameOverride()
|
val rawOverride = node.permissionOptions.renameOverride()
|
||||||
val shouldSkip =
|
val shouldSkip =
|
||||||
node.permissionOptions.skip ||
|
node.permissionOptions.skip ||
|
||||||
(node.permissionOptions.preferSkipByDefault &&
|
(
|
||||||
node.permissionOptions.id.isNullOrBlank() &&
|
node.permissionOptions.preferSkipByDefault &&
|
||||||
rawOverride == null)
|
node.permissionOptions.id.isNullOrBlank() &&
|
||||||
|
rawOverride == null
|
||||||
|
)
|
||||||
if (shouldSkip) {
|
if (shouldSkip) {
|
||||||
node.children.forEach { child ->
|
node.children.forEach { child ->
|
||||||
planNode(child, basePath, entries, commandName, parentDefault)
|
planNode(child, basePath, entries, commandName, parentDefault)
|
||||||
|
|
@ -80,44 +86,48 @@ internal class PermissionPlanner(
|
||||||
}
|
}
|
||||||
val segment = node.segment()?.let { sanitize(it) }
|
val segment = node.segment()?.let { sanitize(it) }
|
||||||
val pathAddition = rawOverride?.let { normalizeSegments(it) }
|
val pathAddition = rawOverride?.let { normalizeSegments(it) }
|
||||||
val path = when {
|
val path =
|
||||||
pathAddition != null -> basePath + pathAddition
|
when {
|
||||||
segment != null -> basePath + segment
|
pathAddition != null -> basePath + pathAddition
|
||||||
else -> basePath
|
segment != null -> basePath + segment
|
||||||
}
|
else -> basePath
|
||||||
val entry = createEntry(
|
}
|
||||||
options = node.permissionOptions,
|
val entry =
|
||||||
pathSegments = path,
|
createEntry(
|
||||||
context = PermissionContext(commandName, path, node.toKind()),
|
options = node.permissionOptions,
|
||||||
parentDefault = parentDefault
|
pathSegments = path,
|
||||||
)
|
context = PermissionContext(commandName, path, node.toKind()),
|
||||||
val currentBase = if (entry != null) {
|
parentDefault = parentDefault,
|
||||||
entries[entry.id] = entry
|
)
|
||||||
if (node.permission.isNullOrBlank()) {
|
val currentBase =
|
||||||
node.permission = entry.id
|
if (entry != null) {
|
||||||
|
entries[entry.id] = entry
|
||||||
|
if (node.permission.isNullOrBlank()) {
|
||||||
|
node.permission = entry.id
|
||||||
|
}
|
||||||
|
path
|
||||||
|
} else {
|
||||||
|
basePath
|
||||||
}
|
}
|
||||||
path
|
|
||||||
} else {
|
|
||||||
basePath
|
|
||||||
}
|
|
||||||
val nextDefault = entry?.defaultValue ?: parentDefault
|
val nextDefault = entry?.defaultValue ?: parentDefault
|
||||||
node.children.forEach { child ->
|
node.children.forEach { child ->
|
||||||
planNode(child, currentBase, entries, commandName, nextDefault)
|
planNode(child, currentBase, entries, commandName, nextDefault)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KommandNode.toKind(): PermissionNodeKind = when (this) {
|
private fun KommandNode.toKind(): PermissionNodeKind =
|
||||||
is LiteralNode -> PermissionNodeKind.LITERAL
|
when (this) {
|
||||||
is ValueNode<*> -> PermissionNodeKind.ARGUMENT
|
is LiteralNode -> PermissionNodeKind.LITERAL
|
||||||
else -> PermissionNodeKind.LITERAL
|
is ValueNode<*> -> PermissionNodeKind.ARGUMENT
|
||||||
}
|
else -> PermissionNodeKind.LITERAL
|
||||||
|
}
|
||||||
|
|
||||||
private fun createEntry(
|
private fun createEntry(
|
||||||
options: PermissionOptions,
|
options: PermissionOptions,
|
||||||
pathSegments: List<String>,
|
pathSegments: List<String>,
|
||||||
context: PermissionContext,
|
context: PermissionContext,
|
||||||
parentDefault: PermissionDefault,
|
parentDefault: PermissionDefault,
|
||||||
registration: NodeRegistration = NodeRegistration.PERMISSION
|
registration: NodeRegistration = NodeRegistration.PERMISSION,
|
||||||
): PlannedPermission? {
|
): PlannedPermission? {
|
||||||
val finalId = (options.id?.takeIf { it.isNotBlank() } ?: buildId(pathSegments)).trim()
|
val finalId = (options.id?.takeIf { it.isNotBlank() } ?: buildId(pathSegments)).trim()
|
||||||
if (finalId.isEmpty()) return null
|
if (finalId.isEmpty()) return null
|
||||||
|
|
@ -132,9 +142,10 @@ internal class PermissionPlanner(
|
||||||
val explicitDefault = options.defaultValue
|
val explicitDefault = options.defaultValue
|
||||||
val defaultValue = explicitDefault ?: parentDefault
|
val defaultValue = explicitDefault ?: parentDefault
|
||||||
val wildcard = options.wildcard ?: config.defaultWildcard
|
val wildcard = options.wildcard ?: config.defaultWildcard
|
||||||
val wildcardExclusions = options.wildcardExclusions
|
val wildcardExclusions =
|
||||||
.map { normalizeSegments(it) }
|
options.wildcardExclusions
|
||||||
.filter { it.isNotEmpty() }
|
.map { normalizeSegments(it) }
|
||||||
|
.filter { it.isNotEmpty() }
|
||||||
options.resolve(finalId)
|
options.resolve(finalId)
|
||||||
val parentPath = if (relativePath.isNotEmpty()) relativePath.dropLast(1).takeIf { it.isNotEmpty() } else null
|
val parentPath = if (relativePath.isNotEmpty()) relativePath.dropLast(1).takeIf { it.isNotEmpty() } else null
|
||||||
return PlannedPermission(
|
return PlannedPermission(
|
||||||
|
|
@ -146,16 +157,14 @@ internal class PermissionPlanner(
|
||||||
wildcardExclusions = wildcardExclusions,
|
wildcardExclusions = wildcardExclusions,
|
||||||
inheritsParentDefault = explicitDefault == null,
|
inheritsParentDefault = explicitDefault == null,
|
||||||
wildcard = wildcard,
|
wildcard = wildcard,
|
||||||
registration = registration
|
registration = registration,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun buildId(pathSegments: List<String>): String =
|
private fun buildId(pathSegments: List<String>): String =
|
||||||
(listOf(config.namespace) + pathSegments).filter { it.isNotBlank() }.joinToString(".")
|
(listOf(config.namespace) + pathSegments).filter { it.isNotBlank() }.joinToString(".")
|
||||||
|
|
||||||
private fun sanitize(segment: String): String =
|
private fun sanitize(segment: String): String = segment.trim().lowercase().replace(Regex("[^a-z0-9._-]"), "-").trim('-')
|
||||||
segment.trim().lowercase().replace(Regex("[^a-z0-9._-]"), "-").trim('-')
|
|
||||||
|
|
||||||
private fun normalizeSegments(segments: List<String>): List<String> =
|
private fun normalizeSegments(segments: List<String>): List<String> = segments.map { sanitize(it) }.filter { it.isNotBlank() }
|
||||||
segments.map { sanitize(it) }.filter { it.isNotBlank() }
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import org.bukkit.plugin.java.JavaPlugin
|
||||||
|
|
||||||
internal class PermissionRuntime(
|
internal class PermissionRuntime(
|
||||||
private val plugin: JavaPlugin,
|
private val plugin: JavaPlugin,
|
||||||
private val plan: PermissionPlan
|
private val plan: PermissionPlan,
|
||||||
) {
|
) {
|
||||||
private val session: MutationSession by lazy { plan.config.session(plugin) }
|
private val session: MutationSession by lazy { plan.config.session(plugin) }
|
||||||
val config: PermissionConfig get() = plan.config
|
val config: PermissionConfig get() = plan.config
|
||||||
|
|
@ -16,25 +16,28 @@ internal class PermissionRuntime(
|
||||||
if (plan.isEmpty()) return
|
if (plan.isEmpty()) return
|
||||||
val mutable = MutablePermissionTree.create(plan.config.namespace)
|
val mutable = MutablePermissionTree.create(plan.config.namespace)
|
||||||
val sorted = plan.entries.sortedBy { it.relativePath.size }
|
val sorted = plan.entries.sortedBy { it.relativePath.size }
|
||||||
val registrations = sorted
|
val registrations =
|
||||||
.mapNotNull { entry ->
|
sorted
|
||||||
entry.relativePath.takeIf { it.isNotEmpty() }?.joinToString(".")?.let { it to entry.registration }
|
.mapNotNull { entry ->
|
||||||
}
|
entry.relativePath.takeIf { it.isNotEmpty() }?.joinToString(".")?.let { it to entry.registration }
|
||||||
.toMap()
|
}
|
||||||
val entriesByPath = sorted
|
.toMap()
|
||||||
.filter { it.relativePath.isNotEmpty() }
|
val entriesByPath =
|
||||||
.associateBy { it.relativePath.joinToString(".") }
|
sorted
|
||||||
|
.filter { it.relativePath.isNotEmpty() }
|
||||||
|
.associateBy { it.relativePath.joinToString(".") }
|
||||||
sorted.forEach { entry ->
|
sorted.forEach { entry ->
|
||||||
if (entry.relativePath.isEmpty()) {
|
if (entry.relativePath.isEmpty()) {
|
||||||
plugin.logger.warning("Skipping permission '${entry.id}' because it resolved to the namespace root.")
|
plugin.logger.warning("Skipping permission '${entry.id}' because it resolved to the namespace root.")
|
||||||
return@forEach
|
return@forEach
|
||||||
}
|
}
|
||||||
val nodeId = entry.relativePath.joinToString(".")
|
val nodeId = entry.relativePath.joinToString(".")
|
||||||
val currentNode = mutable.node(nodeId, entry.registration) {
|
val currentNode =
|
||||||
entry.description?.let { description = it }
|
mutable.node(nodeId, entry.registration) {
|
||||||
defaultValue = entry.defaultValue
|
entry.description?.let { description = it }
|
||||||
wildcard = entry.wildcard
|
defaultValue = entry.defaultValue
|
||||||
}
|
wildcard = entry.wildcard
|
||||||
|
}
|
||||||
if (entry.wildcard && entry.wildcardExclusions.isNotEmpty()) {
|
if (entry.wildcard && entry.wildcardExclusions.isNotEmpty()) {
|
||||||
entry.wildcardExclusions.forEach { exclusion ->
|
entry.wildcardExclusions.forEach { exclusion ->
|
||||||
val absolutePath = entry.relativePath + exclusion
|
val absolutePath = entry.relativePath + exclusion
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user