Compare commits
2
Commits
58ad0e67c9
...
00d5860457
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
00d5860457 | ||
|
|
a6e951b48c |
@@ -18,10 +18,10 @@ class ExamplePlugin : JavaPlugin() {
|
||||
node("command", NodeRegistration.STRUCTURAL) {
|
||||
description = "Access to all example commands"
|
||||
defaultValue = PermissionDefault.OP
|
||||
wildcard = true // create example.command.*
|
||||
|
||||
node("reload", NodeRegistration.PERMISSION) {
|
||||
description = "Allows /example reload (permission example.command.reload)"
|
||||
wildcard = true // include reload in example.command.*
|
||||
}
|
||||
|
||||
// Link to a helper node defined elsewhere under the command branch:
|
||||
@@ -32,7 +32,7 @@ class ExamplePlugin : JavaPlugin() {
|
||||
|
||||
node("cooldown", NodeRegistration.PERMISSION) {
|
||||
description = "Allows /example cooldown tweaks"
|
||||
wildcard = true // opt in so example.command.* grants cooldown
|
||||
wildcard = false // keep cooldown out of example.command.*
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ class ExamplePlugin : JavaPlugin() {
|
||||
// The tree above materializes as permissions such as:
|
||||
// example.command, example.command.reload, example.command.helper, example.command.cooldown,
|
||||
// example.tools.repair,
|
||||
// plus the auto-generated example.command.* wildcard (because reload/cooldown set wildcard = true)
|
||||
// plus the auto-generated example.command.* wildcard (command opted in while cooldown did not).
|
||||
// export to plugin.yml or inspect Bukkit's /permissions output).
|
||||
|
||||
configureRuntimePermissions()
|
||||
@@ -66,9 +66,11 @@ class ExamplePlugin : JavaPlugin() {
|
||||
// Update an existing node and link it to new children
|
||||
node("command", NodeRegistration.STRUCTURAL) {
|
||||
description = "Admins for every command path"
|
||||
wildcard = true
|
||||
node("debug", NodeRegistration.PERMISSION) {
|
||||
description = "Allows /example debug"
|
||||
defaultValue = PermissionDefault.OP
|
||||
wildcard = true
|
||||
}
|
||||
}
|
||||
// Remove deprecated permissions entirely
|
||||
@@ -86,15 +88,18 @@ mutate it procedurally, and then apply the result:
|
||||
```kotlin
|
||||
val baseTree = permissionTree("example") {
|
||||
node("command", NodeRegistration.STRUCTURAL) {
|
||||
wildcard = true
|
||||
node("reload", NodeRegistration.PERMISSION)
|
||||
}
|
||||
}
|
||||
|
||||
val mutable = MutablePermissionTree.from(baseTree)
|
||||
mutable.node("command", NodeRegistration.STRUCTURAL) {
|
||||
wildcard = true
|
||||
node("debug", NodeRegistration.PERMISSION) {
|
||||
description = "Allows /example debug"
|
||||
defaultValue = PermissionDefault.OP
|
||||
wildcard = true
|
||||
}
|
||||
child("helper", value = false) // unlink helper if present
|
||||
}
|
||||
@@ -109,8 +114,8 @@ stage edits procedurally before ever touching `MutationSession`.
|
||||
### Concepts
|
||||
|
||||
- **Permission tree** – immutable graph of `PermissionNode`s. Nodes specify description, default value,
|
||||
boolean children map, optional tags, and the `wildcard` flag (disabled by default) that, when enabled,
|
||||
makes the library create/update `namespace.path.*` aggregate permissions automatically.
|
||||
boolean children map, and the `wildcard` flag (disabled by default) that, when enabled per node, keeps
|
||||
`namespace.path.*` aggregate permissions in sync automatically.
|
||||
- **DSL** – `permissionTree("namespace") { ... }` ensures consistent prefixes and validation (no cycles). Every `node("command", NodeRegistration.PERMISSION)` (or `.STRUCTURAL`) is relative to that namespace, so you never include the namespace manually at the root.
|
||||
- **Nested nodes** – `node("command", NodeRegistration.STRUCTURAL) { node("reload", NodeRegistration.PERMISSION) { ... } }` automatically produces
|
||||
`namespace.command` and `namespace.command.reload` plus wires the parent/child relationship so you don't
|
||||
@@ -125,9 +130,9 @@ stage edits procedurally before ever touching `MutationSession`.
|
||||
other namespaces.
|
||||
- **PermissionRegistry** – calculates a diff between snapshots and performs the minimum additions,
|
||||
removals, or updates via Bukkit's `PluginManager`.
|
||||
- **Wildcards** – opt-in via `wildcard = true` to have the generated `namespace.command.*` child kept in sync,
|
||||
so granting `example.command.*` automatically grants every nested node you marked; leave it `false` (default)
|
||||
to keep nodes out of the wildcard.
|
||||
- **Wildcards** – disabled by default; opt in by setting `wildcard = true` on any permission you want pulled
|
||||
into its parent `namespace.command.*`. Enabled nodes automatically add their wildcard descendants (e.g.,
|
||||
`example.command.debug.*`) so granting a parent wildcard cascades through the tree.
|
||||
- **Mutable edits** – `permits.edit { ... }` clones the currently registered tree, lets you mutate nodes
|
||||
imperatively, re-validates, and only pushes the structural diff to Bukkit.
|
||||
- **AttachmentSynchronizer** – manages identity-based `PermissionAttachment`s and exposes high-level
|
||||
|
||||
@@ -70,15 +70,6 @@ class MutablePermissionTree internal constructor(
|
||||
draft.registration = value
|
||||
}
|
||||
|
||||
val tags: MutableSet<String>
|
||||
get() = draft.tags
|
||||
|
||||
fun tag(value: String) {
|
||||
if (value.isNotBlank()) {
|
||||
draft.tags += value.trim()
|
||||
}
|
||||
}
|
||||
|
||||
fun child(id: String, value: Boolean = true) {
|
||||
require(id.isNotBlank()) { "Child id must not be blank." }
|
||||
val permissionId = PermissionId.of("${this.id.value}.${id.lowercase()}")
|
||||
@@ -158,7 +149,6 @@ class MutablePermissionTree internal constructor(
|
||||
description = draft.description,
|
||||
defaultValue = draft.defaultValue,
|
||||
children = draft.children.toMutableMap(),
|
||||
tags = draft.tags.toMutableSet(),
|
||||
wildcard = draft.wildcard,
|
||||
registration = draft.registration
|
||||
)
|
||||
|
||||
@@ -13,7 +13,6 @@ data class PermissionNode(
|
||||
val description: String? = null,
|
||||
val defaultValue: PermissionDefault = PermissionDefault.FALSE,
|
||||
val children: Map<PermissionId, Boolean> = emptyMap(),
|
||||
val tags: Set<String> = emptySet(),
|
||||
val wildcard: Boolean = false,
|
||||
val registration: NodeRegistration = NodeRegistration.PERMISSION
|
||||
) {
|
||||
|
||||
@@ -7,7 +7,6 @@ internal data class PermissionNodeDraft(
|
||||
var description: String? = null,
|
||||
var defaultValue: PermissionDefault = PermissionDefault.FALSE,
|
||||
val children: MutableMap<PermissionId, Boolean> = linkedMapOf(),
|
||||
val tags: MutableSet<String> = linkedSetOf(),
|
||||
var wildcard: Boolean = false,
|
||||
var registration: NodeRegistration = NodeRegistration.PERMISSION
|
||||
) {
|
||||
@@ -17,7 +16,6 @@ internal data class PermissionNodeDraft(
|
||||
description = description,
|
||||
defaultValue = defaultValue,
|
||||
children = children.toMap(),
|
||||
tags = tags.toSet(),
|
||||
wildcard = wildcard,
|
||||
registration = registration
|
||||
)
|
||||
@@ -29,7 +27,6 @@ internal data class PermissionNodeDraft(
|
||||
description = node.description,
|
||||
defaultValue = node.defaultValue,
|
||||
children = node.children.toMutableMap(),
|
||||
tags = node.tags.toMutableSet(),
|
||||
wildcard = node.wildcard,
|
||||
registration = node.registration
|
||||
)
|
||||
|
||||
@@ -25,9 +25,6 @@ class TreeSnapshot internal constructor(
|
||||
digest.update(childId.value.toByteArray())
|
||||
digest.update(if (flag) 1 else 0)
|
||||
}
|
||||
node.tags.sorted().forEach { tag ->
|
||||
digest.update(tag.toByteArray())
|
||||
}
|
||||
digest.update(if (node.wildcard) 1 else 0)
|
||||
digest.update(node.registration.name.toByteArray())
|
||||
}
|
||||
|
||||
@@ -11,24 +11,19 @@ internal object WildcardAugmentor {
|
||||
if (!node.wildcard) return@forEach
|
||||
if (node.id.value.endsWith(".*")) return@forEach
|
||||
|
||||
val wildcardId = parentWildcardId(node.id) ?: return@forEach
|
||||
val existing = result[wildcardId]
|
||||
val updatedChildren = (existing?.children ?: emptyMap()).toMutableMap()
|
||||
val alreadyPresent = updatedChildren[node.id] == true
|
||||
if (!alreadyPresent) {
|
||||
updatedChildren[node.id] = true
|
||||
}
|
||||
val wildcardId = PermissionId.of("${node.id.value}.*")
|
||||
val updatedChildren = node.children.toMutableMap()
|
||||
|
||||
val existing = result[wildcardId]
|
||||
if (existing == null) {
|
||||
result[wildcardId] = PermissionNode(
|
||||
id = wildcardId,
|
||||
description = "Wildcard for ${wildcardId.value}",
|
||||
description = "Wildcard for ${node.id.value}",
|
||||
defaultValue = node.defaultValue,
|
||||
children = updatedChildren,
|
||||
tags = setOf("wildcard"),
|
||||
wildcard = false
|
||||
)
|
||||
} else if (!alreadyPresent) {
|
||||
} else {
|
||||
result[wildcardId] = existing.copy(children = updatedChildren)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,12 +34,6 @@ class PermissionNodeBuilder internal constructor(
|
||||
draft.registration = value
|
||||
}
|
||||
|
||||
fun tag(value: String) {
|
||||
if (value.isNotBlank()) {
|
||||
draft.tags += value.trim()
|
||||
}
|
||||
}
|
||||
|
||||
fun child(id: String, value: Boolean = true) {
|
||||
treeBuilder.childRelative(draft, id, value)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user