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