Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e9ea98e84e |
No files matched your search
@@ -1,6 +0,0 @@
|
||||
#
|
||||
# https://help.github.com/articles/dealing-with-line-endings/
|
||||
#
|
||||
# These are explicitly windows files and should use crlf
|
||||
*.bat text eol=crlf
|
||||
.gitea/CODEOWNERS linguist-detectable=false
|
||||
@@ -1,3 +0,0 @@
|
||||
# Pull requests request review from the eligible staff team(s).
|
||||
# One approval from either an Admin or Developer satisfies branch protection.
|
||||
* @trueog/Admins @trueog/Developers
|
||||
@@ -0,0 +1,2 @@
|
||||
github: lucko
|
||||
patreon: luckdev
|
||||
@@ -0,0 +1,63 @@
|
||||
name: 🐛 Bug report
|
||||
description: Report an issue or problem with the way LuckPerms is functioning.
|
||||
labels: ["type: issue"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: "Before going any further, please check to see if your problem is fixed by updating to a newer version. The latest development builds can be obtained from https://luckperms.net/download"
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Description
|
||||
description: Please provide a short description of the issue in the space below.
|
||||
placeholder: Description goes here!
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: reproduction-steps
|
||||
attributes:
|
||||
label: Reproduction Steps
|
||||
description: Please provide a clear list of steps we should follow in order to reproduce your issue in the space below.
|
||||
placeholder: List reproduction steps here, please!
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: expected-behaviour
|
||||
attributes:
|
||||
label: Expected Behaviour
|
||||
description: Please provide a description of what you expected to happen.
|
||||
placeholder: Describe what you expected to happen here.
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: server-info
|
||||
attributes:
|
||||
label: Server Details
|
||||
description: Please provide a description of the server details, including type and specific version number.
|
||||
placeholder: 'git-Paper-124 (MC: 1.17.1)'
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: luckperms-version
|
||||
attributes:
|
||||
label: LuckPerms Version
|
||||
description: Please provide the specific, precise version number of LuckPerms you are using to reproduce this bug.
|
||||
placeholder: v5.3.70
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Logs and Configs
|
||||
description: If you think it would be helpful, please also include a pastebin of any relevant config files or log output. You should use https://gist.github.com/ to upload, then include the link below.
|
||||
placeholder: https://gist.github.com/HelpfulBugReporter/ThisIsAVeryUsefulLogOutput
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: extra-info
|
||||
attributes:
|
||||
label: Extra Details
|
||||
description: Please include any other relevant details in the space below.
|
||||
placeholder: I was able to reproduce this only at the end of a rainbow.
|
||||
validations:
|
||||
required: false
|
||||
@@ -0,0 +1,5 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: 💬 Ask a question
|
||||
url: https://discord.gg/luckperms
|
||||
about: We use Discord to provide support for the project. If you have a question, need help, or aren't sure if you've found a bug or not, please come and talk to us there!
|
||||
@@ -0,0 +1,31 @@
|
||||
name: 💡 Suggestion
|
||||
description: Suggest an idea for an improvement or change to LuckPerms.
|
||||
labels: ["type: suggestion"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: "Before going any further, please check to see if your suggestion has already been added by checking the [wiki](https://luckperms.net/wiki/Home). The latest development builds can be obtained from https://luckperms.net/download"
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Description
|
||||
description: Please provide a short description of your suggestion in the space below.
|
||||
placeholder: Hello, perhaps you should...
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: proposed-behaviour
|
||||
attributes:
|
||||
label: Proposed Behaviour
|
||||
description: Please provide a short explanation of how the feature should work / be changed, and how this will affect the project.
|
||||
placeholder: It would...
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: extra-info
|
||||
attributes:
|
||||
label: Extra Details
|
||||
description: Please include any other relevant details in the space below.
|
||||
placeholder: I think this should only function at the end of a rainbow.
|
||||
validations:
|
||||
required: false
|
||||
@@ -0,0 +1,127 @@
|
||||
name: Build Gradle and Publish Docker image
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
tags:
|
||||
- 'v*'
|
||||
pull_request:
|
||||
branches:
|
||||
- 'master'
|
||||
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
IMAGE_NAME: ${{ github.repository }}
|
||||
|
||||
jobs:
|
||||
build-gradle:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: validate gradle wrapper
|
||||
uses: gradle/wrapper-validation-action@v1
|
||||
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '17'
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: gradle/gradle-build-action@v2
|
||||
|
||||
- name: Run build and tests with Gradle wrapper
|
||||
run: ./gradlew test build -PdockerTests
|
||||
|
||||
- name: Publish test report
|
||||
uses: mikepenz/action-junit-report@v3
|
||||
if: success() || failure()
|
||||
with:
|
||||
report_paths: '**/build/test-results/test/TEST-*.xml'
|
||||
annotate_notice: true
|
||||
detailed_summary: true
|
||||
|
||||
- name: Upload all artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: jars
|
||||
path: |
|
||||
bukkit/loader/build/libs/LuckPerms-Bukkit-*.jar
|
||||
bukkit-legacy/loader/build/libs/LuckPerms-Bukkit-Legacy-*.jar
|
||||
bungee/loader/build/libs/LuckPerms-Bungee-*.jar
|
||||
sponge/loader/build/libs/LuckPerms-Sponge-*.jar
|
||||
nukkit/loader/build/libs/LuckPerms-Nukkit-*.jar
|
||||
velocity/build/libs/LuckPerms-Velocity-*.jar
|
||||
fabric/build/libs/LuckPerms-Fabric-*.jar
|
||||
forge/loader/build/libs/LuckPerms-Forge-*.jar
|
||||
standalone/loader/build/libs/LuckPerms-Standalone-*.jar
|
||||
|
||||
- name: Upload standalone artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: standalone-binary
|
||||
path: standalone/loader/build/libs/LuckPerms-Standalone-*.jar
|
||||
|
||||
|
||||
build-docker:
|
||||
needs: build-gradle
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Retrieve saved standalone jar artifact
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: standalone-binary
|
||||
path: standalone/docker/
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Determine the LuckPerms version
|
||||
run: |
|
||||
echo "luckperms_version=$(git describe --tags | awk -F "-" '{print $1 "." $2}')" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Extract metadata for Docker
|
||||
id: meta
|
||||
uses: docker/metadata-action@v3
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
flavor: |
|
||||
latest=${{ github.ref == 'refs/heads/master' }}
|
||||
tags: |
|
||||
type=schedule
|
||||
type=ref,event=branch
|
||||
type=ref,event=tag
|
||||
type=ref,event=pr
|
||||
type=raw,enable=${{ github.ref == 'refs/heads/master' }},value=${{ env.luckperms_version }}
|
||||
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
context: standalone/docker/
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
@@ -0,0 +1,26 @@
|
||||
### :speech_balloon: Looking for support?
|
||||
|
||||
Details about support for the project can be found [here, on the Wiki Homepage](https://luckperms.net/wiki/Home#support).
|
||||
|
||||
### :bug: Reporting bugs?
|
||||
|
||||
Before reporting a bug or issue, please make sure that the issue is actually being caused by or related to LuckPerms. We get a lot of reports which are caused by other software - please double check!
|
||||
|
||||
If you're unsure, feel free to ask using the above resources BEFORE making a report.
|
||||
|
||||
Bugs or issues should be reported using the [GitHub Issues tab](https://github.com/LuckPerms/LuckPerms/issues).
|
||||
|
||||
### :pencil: Want to contribute code?
|
||||
#### Pull Requests
|
||||
If you make any changes or improvements to the plugin which you think would be beneficial to others, please consider making a pull request to merge your changes back into the upstream project. (especially if your changes are bug fixes!)
|
||||
|
||||
LuckPerms loosely follows the [Google Java Style Guide](https://google.github.io/styleguide/javaguide.html). Generally, try to copy the style of code found in the class you're editing.
|
||||
|
||||
If you're considering submitting a substantial pull request, please open an issue so we can discuss the change before starting work on the contribution. Most pull requests are happily accepted, but larger changes may have an impact on the maintainability of the project, and require more consideration.
|
||||
|
||||
#### Project Layout
|
||||
The project is split up into a few separate modules.
|
||||
|
||||
* **API** - The public, semantically versioned API used by other plugins wishing to integrate with and retrieve data from LuckPerms. This module (for the most part) does not contain any implementation itself, and is provided by the plugin.
|
||||
* **Common** - The common module contains most of the code which implements the respective LuckPerms plugins. This abstract module reduces duplicated code throughout the project.
|
||||
* **Bukkit, BungeeCord, Fabric, Forge, Nukkit, Sponge & Velocity** - Each use the common module to implement plugins on the respective server platforms.
|
||||
@@ -24,7 +24,7 @@ For more information, see the wiki article on [Why LuckPerms?](https://luckperms
|
||||
LuckPerms uses Gradle to handle dependencies & building.
|
||||
|
||||
#### Requirements
|
||||
* Java 21 JDK or newer
|
||||
* Java 17 JDK or newer
|
||||
* Git
|
||||
|
||||
#### Compiling from source
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
group = 'net.luckperms'
|
||||
project.version = '5.4'
|
||||
|
||||
jar {
|
||||
manifest {
|
||||
attributes('Automatic-Module-Name': 'net.luckperms.api')
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly 'org.checkerframework:checker-qual:3.21.2'
|
||||
compileOnly 'org.jetbrains:annotations:23.1.0'
|
||||
}
|
||||
|
||||
// Only used occasionally for deployment - not needed for normal builds.
|
||||
/*
|
||||
if (project.hasProperty('sonatypeUsername') && project.hasProperty('sonatypePassword')) {
|
||||
apply plugin: 'signing'
|
||||
|
||||
javadoc {
|
||||
title = 'LuckPerms API (v' + project.ext.apiVersion + ')'
|
||||
options.overview = 'javadoc/overview.html'
|
||||
options.encoding = 'UTF-8'
|
||||
options.charSet = 'UTF-8'
|
||||
options.links(
|
||||
'https://checkerframework.org/api/',
|
||||
'https://javadoc.io/static/org.jetbrains/annotations/23.0.0/'
|
||||
)
|
||||
options.addStringOption('Xdoclint:none', '-quiet')
|
||||
options.addStringOption('-since', '5.0,5.1,5.2,5.3,5.4')
|
||||
|
||||
if (JavaVersion.current() > JavaVersion.VERSION_1_8) {
|
||||
options.links.add('https://docs.oracle.com/en/java/javase/11/docs/api/')
|
||||
} else {
|
||||
options.links.add('https://docs.oracle.com/javase/8/docs/api/')
|
||||
}
|
||||
}
|
||||
|
||||
task javadocJar(type: Jar, dependsOn: javadoc) {
|
||||
classifier 'javadoc'
|
||||
from javadoc.destinationDir
|
||||
}
|
||||
|
||||
task sourcesJar(type: Jar) {
|
||||
classifier 'sources'
|
||||
from sourceSets.main.allSource
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives javadocJar
|
||||
archives sourcesJar
|
||||
}
|
||||
|
||||
publishing {
|
||||
repositories {
|
||||
maven {
|
||||
def releasesRepoUrl = 'https://oss.sonatype.org/service/local/staging/deploy/maven2/'
|
||||
def snapshotsRepoUrl = 'https://oss.sonatype.org/content/repositories/snapshots/'
|
||||
url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl
|
||||
|
||||
credentials {
|
||||
username sonatypeUsername
|
||||
password sonatypePassword
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
publications {
|
||||
mavenJava(MavenPublication) {
|
||||
artifactId = 'api'
|
||||
|
||||
from components.java
|
||||
artifact sourcesJar
|
||||
artifact javadocJar
|
||||
|
||||
pom {
|
||||
name = 'LuckPerms API'
|
||||
description = 'A permissions plugin for Minecraft servers.'
|
||||
url = 'https://luckperms.net'
|
||||
|
||||
licenses {
|
||||
license {
|
||||
name = 'MIT'
|
||||
url = 'https://opensource.org/licenses/MIT'
|
||||
}
|
||||
}
|
||||
|
||||
developers {
|
||||
developer {
|
||||
id = 'lucko'
|
||||
name = 'Luck'
|
||||
url = 'https://lucko.me'
|
||||
email = 'git@lucko.me'
|
||||
}
|
||||
}
|
||||
|
||||
scm {
|
||||
connection = 'scm:git:https://github.com/LuckPerms/LuckPerms.git'
|
||||
developerConnection = 'scm:git:git@github.com:LuckPerms/LuckPerms.git'
|
||||
url = 'https://github.com/LuckPerms/LuckPerms'
|
||||
}
|
||||
|
||||
issueManagement {
|
||||
system = 'GitHub'
|
||||
url = 'https://github.com/LuckPerms/LuckPerms/issues'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
signing {
|
||||
useGpgCmd()
|
||||
sign configurations.archives
|
||||
sign publishing.publications.mavenJava
|
||||
required = true
|
||||
}
|
||||
}
|
||||
*/
|
||||
@@ -1,6 +1,6 @@
|
||||
<body>
|
||||
<p>
|
||||
LuckPerms is a permissions manager for Minecraft servers. It allows server admins to control what
|
||||
LuckPerms is a permissions plugin for Minecraft servers. It allows server admins to control what
|
||||
features players can use by creating groups and assigning permissions.
|
||||
</p>
|
||||
<h4>Useful Links</h4>
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
package net.luckperms.api;
|
||||
|
||||
import net.luckperms.api.actionlog.ActionLogger;
|
||||
import net.luckperms.api.actionlog.filter.ActionFilterFactory;
|
||||
import net.luckperms.api.context.ContextCalculator;
|
||||
import net.luckperms.api.context.ContextManager;
|
||||
import net.luckperms.api.event.EventBus;
|
||||
@@ -41,7 +40,6 @@ import net.luckperms.api.model.user.User;
|
||||
import net.luckperms.api.model.user.UserManager;
|
||||
import net.luckperms.api.node.NodeBuilderRegistry;
|
||||
import net.luckperms.api.node.matcher.NodeMatcherFactory;
|
||||
import net.luckperms.api.platform.Health;
|
||||
import net.luckperms.api.platform.Platform;
|
||||
import net.luckperms.api.platform.PlayerAdapter;
|
||||
import net.luckperms.api.platform.PluginMetadata;
|
||||
@@ -221,17 +219,6 @@ public interface LuckPerms {
|
||||
*/
|
||||
@NonNull CompletableFuture<Void> runUpdateTask();
|
||||
|
||||
/**
|
||||
* Executes a health check.
|
||||
*
|
||||
* <p>This task checks if the LuckPerms implementation is running and
|
||||
* whether it has a connection to the database (if applicable).</p>
|
||||
*
|
||||
* @return the health status
|
||||
* @since 5.5
|
||||
*/
|
||||
@NonNull Health runHealthCheck();
|
||||
|
||||
/**
|
||||
* Registers a {@link MessengerProvider} for use by the platform.
|
||||
*
|
||||
@@ -268,14 +255,4 @@ public interface LuckPerms {
|
||||
@Internal
|
||||
@NonNull NodeMatcherFactory getNodeMatcherFactory();
|
||||
|
||||
/**
|
||||
* Gets the {@link ActionFilterFactory}.
|
||||
*
|
||||
* @return the action filter factory
|
||||
* @since 5.5
|
||||
*/
|
||||
@Internal
|
||||
@NonNull
|
||||
ActionFilterFactory getActionFilterFactory();
|
||||
|
||||
}
|
||||
@@ -79,8 +79,7 @@ public final class LuckPermsProvider {
|
||||
" a) the LuckPerms plugin is not installed or it failed to enable\n" +
|
||||
" b) the plugin in the stacktrace does not declare a dependency on LuckPerms\n" +
|
||||
" c) the plugin in the stacktrace is retrieving the API before the plugin 'enable' phase\n" +
|
||||
" (call the #get method in onEnable, not the constructor!)\n" +
|
||||
" d) the plugin in the stacktrace is incorrectly 'shading' the LuckPerms API into its jar\n";
|
||||
" (call the #get method in onEnable, not the constructor!)\n";
|
||||
|
||||
NotLoadedException() {
|
||||
super(MESSAGE);
|
||||
|
||||
@@ -28,7 +28,6 @@ package net.luckperms.api.actionlog;
|
||||
import net.luckperms.api.LuckPermsProvider;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.jetbrains.annotations.ApiStatus.NonExtendable;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Optional;
|
||||
@@ -36,10 +35,7 @@ import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Represents a logged action.
|
||||
*
|
||||
* <p>API users should not implement this interface directly.</p>
|
||||
*/
|
||||
@NonExtendable
|
||||
public interface Action extends Comparable<Action> {
|
||||
|
||||
/**
|
||||
@@ -85,7 +81,6 @@ public interface Action extends Comparable<Action> {
|
||||
/**
|
||||
* Represents the source of an action.
|
||||
*/
|
||||
@NonExtendable
|
||||
interface Source {
|
||||
|
||||
/**
|
||||
@@ -107,7 +102,6 @@ public interface Action extends Comparable<Action> {
|
||||
/**
|
||||
* Represents the target of an action.
|
||||
*/
|
||||
@NonExtendable
|
||||
interface Target {
|
||||
|
||||
/**
|
||||
@@ -132,7 +126,7 @@ public interface Action extends Comparable<Action> {
|
||||
@NonNull Type getType();
|
||||
|
||||
/**
|
||||
* Represents the type of {@link Target}.
|
||||
* Represents the type of a {@link Target}.
|
||||
*/
|
||||
enum Type {
|
||||
USER, GROUP, TRACK
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
|
||||
package net.luckperms.api.actionlog;
|
||||
|
||||
import net.luckperms.api.actionlog.filter.ActionFilter;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.jetbrains.annotations.Unmodifiable;
|
||||
|
||||
@@ -41,11 +40,7 @@ import java.util.UUID;
|
||||
* You can add to the log using the {@link ActionLogger}, and then request an updated copy.</p>
|
||||
*
|
||||
* <p>All methods are thread safe, and return immutable and thread safe collections.</p>
|
||||
*
|
||||
* @deprecated Use {@link ActionLogger#queryActions(ActionFilter)} or
|
||||
* {@link ActionLogger#queryActions(ActionFilter, int, int)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public interface ActionLog {
|
||||
|
||||
/**
|
||||
|
||||
@@ -25,11 +25,9 @@
|
||||
|
||||
package net.luckperms.api.actionlog;
|
||||
|
||||
import net.luckperms.api.actionlog.filter.ActionFilter;
|
||||
import net.luckperms.api.util.Page;
|
||||
import net.luckperms.api.messaging.MessagingService;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/**
|
||||
@@ -48,78 +46,43 @@ public interface ActionLogger {
|
||||
* Gets a {@link ActionLog} instance from the plugin storage.
|
||||
*
|
||||
* @return a log instance
|
||||
* @deprecated Use {@link #queryActions(ActionFilter)} or {@link #queryActions(ActionFilter, int, int)} instead. These methods
|
||||
* are more efficient (they don't load the full action log into memory) and allow for pagination.
|
||||
*/
|
||||
@Deprecated
|
||||
@NonNull CompletableFuture<ActionLog> getLog();
|
||||
|
||||
/**
|
||||
* Gets all actions from the action log matching the given {@code filter}.
|
||||
* Submits a log entry to the plugin to be handled.
|
||||
*
|
||||
* <p>If the filter is {@code null}, all actions will be returned.</p>
|
||||
* <p>This method submits the log to the storage provider and broadcasts
|
||||
* it.</p>
|
||||
*
|
||||
* <p>Unlike {@link #queryActions(ActionFilter, int, int)}, this method does not implement any pagination and will return
|
||||
* all entries at once.</p>
|
||||
* <p>It is therefore roughly equivalent to calling
|
||||
* {@link #submitToStorage(Action)} and {@link #broadcastAction(Action)},
|
||||
* however, using this method is preferred to making the calls individually.</p>
|
||||
*
|
||||
* @param filter the filter, optional
|
||||
* @return the actions
|
||||
* @since 5.5
|
||||
*/
|
||||
@NonNull CompletableFuture<List<Action>> queryActions(@NonNull ActionFilter filter);
|
||||
|
||||
/**
|
||||
* Gets a page of actions from the action log matching the given {@code filter}.
|
||||
*
|
||||
* <p>If the filter is {@code null}, all actions will be returned.</p>
|
||||
*
|
||||
* @param filter the filter, optional
|
||||
* @param pageSize the size of the page
|
||||
* @param pageNumber the page number
|
||||
* @return the page of actions
|
||||
* @since 5.5
|
||||
*/
|
||||
@NonNull CompletableFuture<Page<Action>> queryActions(@NonNull ActionFilter filter, int pageSize, int pageNumber);
|
||||
|
||||
/**
|
||||
* Submits a logged action to LuckPerms.
|
||||
*
|
||||
* <p>This method submits the action to the storage provider to be persisted in the action log.
|
||||
* It also broadcasts it to administrator players on the current instance and to admins on other
|
||||
* connected servers if a messaging service is configured.</p>
|
||||
*
|
||||
* <p>It is roughly equivalent to calling
|
||||
* {@link #submitToStorage(Action)} followed by {@link #broadcastAction(Action)},
|
||||
* however using this method is preferred to making the calls individually.</p>
|
||||
*
|
||||
* <p>If you want to submit an action log entry but don't know which method to pick,
|
||||
* <p>If you want to submit a log entry but don't know which method to pick,
|
||||
* use this one.</p>
|
||||
*
|
||||
* @param entry the entry to submit
|
||||
* @return a future which will complete when the action is submitted
|
||||
* @return a future which will complete when the action is done
|
||||
*/
|
||||
@NonNull CompletableFuture<Void> submit(@NonNull Action entry);
|
||||
|
||||
/**
|
||||
* Submits a logged action to LuckPerms and persists it in the storage backend.
|
||||
*
|
||||
* <p>This method does not broadcast the action or send it through the messaging service.</p>
|
||||
* Submits a log entry to the plugins storage handler.
|
||||
*
|
||||
* @param entry the entry to submit
|
||||
* @return a future which will complete when the action is submitted
|
||||
* @return a future which will complete when the action is done
|
||||
*/
|
||||
@NonNull CompletableFuture<Void> submitToStorage(@NonNull Action entry);
|
||||
|
||||
/**
|
||||
* Submits a logged action to LuckPerms and broadcasts it to administrators.
|
||||
* Submits a log entry to the plugins log broadcasting handler.
|
||||
*
|
||||
* <p>The broadcast is made to administrator players on the current instance
|
||||
* and to admins on other connected servers if a messaging service is configured.</p>
|
||||
*
|
||||
* <p>This method does not save the action to the plugin storage backend.</p>
|
||||
* <p>If enabled, this method will also dispatch the log entry via the
|
||||
* plugins {@link MessagingService}.</p>
|
||||
*
|
||||
* @param entry the entry to submit
|
||||
* @return a future which will complete when the action is broadcasted
|
||||
* @return a future which will complete when the action is done
|
||||
*/
|
||||
@NonNull CompletableFuture<Void> broadcastAction(@NonNull Action entry);
|
||||
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.luckperms.api.actionlog.filter;
|
||||
|
||||
import net.luckperms.api.LuckPermsProvider;
|
||||
import net.luckperms.api.actionlog.Action;
|
||||
import org.jetbrains.annotations.ApiStatus.NonExtendable;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* A predicate filter which matches certain {@link Action}s.
|
||||
*
|
||||
* <p>API users should not implement this interface directly.</p>
|
||||
*
|
||||
* @since 5.5
|
||||
*/
|
||||
@NonExtendable
|
||||
public interface ActionFilter extends Predicate<Action> {
|
||||
|
||||
/**
|
||||
* Gets an {@link ActionFilter} which matches any action.
|
||||
*
|
||||
* @return the matcher
|
||||
*/
|
||||
static ActionFilter any() {
|
||||
return LuckPermsProvider.get().getActionFilterFactory().any();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an {@link ActionFilter} which matches actions with a specific source user.
|
||||
*
|
||||
* @param uniqueId the source user unique id
|
||||
* @return the matcher
|
||||
*/
|
||||
static ActionFilter source(UUID uniqueId) {
|
||||
return LuckPermsProvider.get().getActionFilterFactory().source(uniqueId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an {@link ActionFilter} which matches actions which target a specific user.
|
||||
*
|
||||
* @param uniqueId the target user unique id
|
||||
* @return the matcher
|
||||
*/
|
||||
static ActionFilter user(UUID uniqueId) {
|
||||
return LuckPermsProvider.get().getActionFilterFactory().user(uniqueId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an {@link ActionFilter} which matches actions which target a specific group.
|
||||
*
|
||||
* @param name the target group name
|
||||
* @return the matcher
|
||||
*/
|
||||
static ActionFilter group(String name) {
|
||||
return LuckPermsProvider.get().getActionFilterFactory().group(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an {@link ActionFilter} which matches actions which target a specific track.
|
||||
*
|
||||
* @param name the target track name
|
||||
* @return the matcher
|
||||
*/
|
||||
static ActionFilter track(String name) {
|
||||
return LuckPermsProvider.get().getActionFilterFactory().track(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an {@link ActionFilter} which matches actions which contain a specific search query in the source name,
|
||||
* target name or description.
|
||||
*
|
||||
* @param query the search query
|
||||
* @return the matcher
|
||||
*/
|
||||
static ActionFilter search(String query) {
|
||||
return LuckPermsProvider.get().getActionFilterFactory().search(query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests to see if the given {@link Action} matches the filter.
|
||||
*
|
||||
* @param action the action to test
|
||||
* @return true if the action matched
|
||||
*/
|
||||
@Override
|
||||
boolean test(Action action);
|
||||
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.luckperms.api.actionlog.filter;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus.Internal;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* A factory which creates {@link ActionFilter}s.
|
||||
*
|
||||
* @since 5.5
|
||||
*/
|
||||
@Internal
|
||||
public interface ActionFilterFactory {
|
||||
|
||||
/**
|
||||
* Gets an {@link ActionFilter} which matches any action.
|
||||
*
|
||||
* @return the matcher
|
||||
*/
|
||||
ActionFilter any();
|
||||
|
||||
/**
|
||||
* Gets an {@link ActionFilter} which matches actions with a specific source user.
|
||||
*
|
||||
* @param uniqueId the source user unique id
|
||||
* @return the matcher
|
||||
*/
|
||||
ActionFilter source(UUID uniqueId);
|
||||
|
||||
/**
|
||||
* Gets an {@link ActionFilter} which matches actions which target a specific user.
|
||||
*
|
||||
* @param uniqueId the target user unique id
|
||||
* @return the matcher
|
||||
*/
|
||||
ActionFilter user(UUID uniqueId);
|
||||
|
||||
/**
|
||||
* Gets an {@link ActionFilter} which matches actions which target a specific group.
|
||||
*
|
||||
* @param name the target group name
|
||||
* @return the matcher
|
||||
*/
|
||||
ActionFilter group(String name);
|
||||
|
||||
/**
|
||||
* Gets an {@link ActionFilter} which matches actions which target a specific track.
|
||||
*
|
||||
* @param name the target track name
|
||||
* @return the matcher
|
||||
*/
|
||||
ActionFilter track(String name);
|
||||
|
||||
/**
|
||||
* Gets an {@link ActionFilter} which matches actions which contain a specific search query in the source name,
|
||||
* target name or description.
|
||||
*
|
||||
* @param query the search query
|
||||
* @return the matcher
|
||||
*/
|
||||
ActionFilter search(String query);
|
||||
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* {@link net.luckperms.api.actionlog.Action} filters.
|
||||
*/
|
||||
package net.luckperms.api.actionlog.filter;
|
||||
@@ -33,11 +33,7 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Called when a log entry is received via the MessagingService.
|
||||
*
|
||||
* <p>Note: listening to this event is the same as listening to the {@link LogBroadcastEvent}
|
||||
* and filtering for {@link LogBroadcastEvent#getOrigin() origin} =
|
||||
* {@link net.luckperms.api.event.log.LogBroadcastEvent.Origin#REMOTE REMOTE}.</p>
|
||||
* Called when a log entry is received via the MessagingService
|
||||
*/
|
||||
public interface LogReceiveEvent extends LuckPermsEvent {
|
||||
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.luckperms.api.event.messaging;
|
||||
|
||||
import net.luckperms.api.event.LuckPermsEvent;
|
||||
import net.luckperms.api.event.util.Param;
|
||||
import net.luckperms.api.messaging.MessagingService;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
/**
|
||||
* Called when a custom payload message is received via the {@link MessagingService}.
|
||||
*
|
||||
* <p>This event is effectively the 'other end' of
|
||||
* {@link MessagingService#sendCustomMessage(String, String)}.</p>
|
||||
*
|
||||
* @since 5.5
|
||||
*/
|
||||
public interface CustomMessageReceiveEvent extends LuckPermsEvent {
|
||||
|
||||
/**
|
||||
* Gets the channel id.
|
||||
*
|
||||
* @return the channel id
|
||||
*/
|
||||
@Param(0)
|
||||
@NonNull String getChannelId();
|
||||
|
||||
/**
|
||||
* Gets the custom payload that was sent.
|
||||
*
|
||||
* @return the custom payload
|
||||
*/
|
||||
@Param(1)
|
||||
@NonNull String getPayload();
|
||||
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Events relating to the {@link net.luckperms.api.messaging.MessagingService}.
|
||||
*/
|
||||
package net.luckperms.api.event.messaging;
|
||||
@@ -1,81 +0,0 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.luckperms.api.event.sync;
|
||||
|
||||
import net.luckperms.api.event.LuckPermsEvent;
|
||||
import net.luckperms.api.event.util.Param;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Called after a network synchronisation task has been completed.
|
||||
*
|
||||
* <p>Note: the generic {@link PostSyncEvent} will also be called for {@link SyncType#FULL full syncs}.</p>
|
||||
*
|
||||
* @since 5.5
|
||||
*/
|
||||
public interface PostNetworkSyncEvent extends LuckPermsEvent {
|
||||
|
||||
/**
|
||||
* Gets the ID of the sync request
|
||||
*
|
||||
* @return the id of the sync request
|
||||
*/
|
||||
@Param(0)
|
||||
@NonNull UUID getSyncId();
|
||||
|
||||
/**
|
||||
* Gets the sync type.
|
||||
*
|
||||
* @return the sync type
|
||||
*/
|
||||
@Param(1)
|
||||
@NonNull SyncType getType();
|
||||
|
||||
/**
|
||||
* Gets if a sync occurred.
|
||||
*
|
||||
* <p>For {@link SyncType} = {@link SyncType#FULL FULL}, this method always returns true.</p>
|
||||
*
|
||||
* <p>For {@link SyncType} = {@link SyncType#SPECIFIC_USER SPECIFIC_USER}, this method returns true if the
|
||||
* user in question was online/loaded in memory at the time, and false otherwise.</p>
|
||||
*
|
||||
* @return if a sync occurred
|
||||
*/
|
||||
@Param(2)
|
||||
boolean didSyncOccur();
|
||||
|
||||
/**
|
||||
* Gets the unique id of the specific user that has been synced, if applicable.
|
||||
*
|
||||
* @return the unique id of the specific user
|
||||
*/
|
||||
@Param(3)
|
||||
@Nullable UUID getSpecificUserUniqueId();
|
||||
|
||||
}
|
||||
@@ -28,10 +28,7 @@ package net.luckperms.api.event.sync;
|
||||
import net.luckperms.api.event.LuckPermsEvent;
|
||||
|
||||
/**
|
||||
* Called after a full synchronisation task has been completed.
|
||||
*
|
||||
* <p>Note: this event is also called after synchronisations that were triggered over the network.
|
||||
* In other words, this event will be called in addition to {@link PostNetworkSyncEvent}.</p>
|
||||
* Called when an sync task has been completed
|
||||
*/
|
||||
public interface PostSyncEvent extends LuckPermsEvent {
|
||||
|
||||
|
||||
@@ -29,15 +29,11 @@ import net.luckperms.api.event.LuckPermsEvent;
|
||||
import net.luckperms.api.event.type.Cancellable;
|
||||
import net.luckperms.api.event.util.Param;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Called after a request for synchronisation has been received via the messaging service,
|
||||
* but before it has actually been completed.
|
||||
*
|
||||
* <p>Note: the generic {@link PreSyncEvent} will also be called for {@link SyncType#FULL full syncs}.</p>
|
||||
* Called before a received network sync task runs
|
||||
*/
|
||||
public interface PreNetworkSyncEvent extends LuckPermsEvent, Cancellable {
|
||||
|
||||
@@ -49,22 +45,4 @@ public interface PreNetworkSyncEvent extends LuckPermsEvent, Cancellable {
|
||||
@Param(0)
|
||||
@NonNull UUID getSyncId();
|
||||
|
||||
/**
|
||||
* Gets the sync type.
|
||||
*
|
||||
* @return the sync type
|
||||
* @since 5.5
|
||||
*/
|
||||
@Param(1)
|
||||
@NonNull SyncType getType();
|
||||
|
||||
/**
|
||||
* Gets the unique id of the specific user that will be synced, if applicable.
|
||||
*
|
||||
* @return the unique id of the specific user
|
||||
* @since 5.5
|
||||
*/
|
||||
@Param(2)
|
||||
@Nullable UUID getSpecificUserUniqueId();
|
||||
|
||||
}
|
||||
@@ -29,10 +29,7 @@ import net.luckperms.api.event.LuckPermsEvent;
|
||||
import net.luckperms.api.event.type.Cancellable;
|
||||
|
||||
/**
|
||||
* Called just before a full synchronisation task runs.
|
||||
*
|
||||
* <p>Note: this event is also called before synchronisations that were triggered over the network.
|
||||
* In other words, this event will be called in addition to {@link PreNetworkSyncEvent}.</p>
|
||||
* Called before a sync task runs
|
||||
*/
|
||||
public interface PreSyncEvent extends LuckPermsEvent, Cancellable {
|
||||
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.luckperms.api.event.sync;
|
||||
|
||||
/**
|
||||
* Represents the type of synchronisation task.
|
||||
*
|
||||
* @since 5.5
|
||||
*/
|
||||
public enum SyncType {
|
||||
|
||||
/**
|
||||
* A full sync will be performed - all groups, users and tracks
|
||||
*/
|
||||
FULL,
|
||||
|
||||
/**
|
||||
* Only a specific user will be synced
|
||||
*/
|
||||
SPECIFIC_USER
|
||||
|
||||
}
|
||||
@@ -26,12 +26,11 @@
|
||||
package net.luckperms.api.messaging;
|
||||
|
||||
import net.luckperms.api.LuckPerms;
|
||||
import net.luckperms.api.event.messaging.CustomMessageReceiveEvent;
|
||||
import net.luckperms.api.model.user.User;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
/**
|
||||
* A means to send messages to other servers using the platforms networking
|
||||
* A means to push changes to other servers using the platforms networking
|
||||
*/
|
||||
public interface MessagingService {
|
||||
|
||||
@@ -72,44 +71,4 @@ public interface MessagingService {
|
||||
*/
|
||||
void pushUserUpdate(@NonNull User user);
|
||||
|
||||
/**
|
||||
* Uses the messaging service to send a message with a custom payload.
|
||||
*
|
||||
* <p>The intended use case of this functionality is to allow plugins/mods
|
||||
* to send <b>lightweight</b> and <b>permissions-related</b> custom messages
|
||||
* between instances, piggy-backing on top of the messenger abstraction
|
||||
* already built into LuckPerms.</p>
|
||||
*
|
||||
* <p>It is <b>not</b> intended as a full message broker replacement/abstraction.
|
||||
* Note that some of the messenger implementations in LuckPerms cannot handle
|
||||
* a high volume of messages being sent (for example the SQL messenger).
|
||||
* Additionally, some implementations do not give any guarantees that a message
|
||||
* will be delivered on time or even at all (for example the plugin message
|
||||
* messengers).</p>
|
||||
*
|
||||
* <p>With all of that in mind, please consider that if you are using this
|
||||
* functionality to send messages that have nothing to do with LuckPerms or
|
||||
* permissions, or that require guarantees around delivery reliability, you
|
||||
* are most likely misusing the API and would be better off building your own
|
||||
* integration with a message broker.</p>
|
||||
*
|
||||
* <p>Whilst there is (currently) no strict validation, it is recommended
|
||||
* that the channel id should use the same format as Minecraft resource locations /
|
||||
* namespaced keys. For example, a plugin called "SuperRanks" sending rank-up
|
||||
* notifications using custom payload messages might use the channel id
|
||||
* {@code "superranks:notifications"} for this purpose.</p>
|
||||
*
|
||||
* <p>The payload can be any valid UTF-8 string.</p>
|
||||
*
|
||||
* <p>The message will be delivered asynchronously.</p>
|
||||
*
|
||||
* <p>Other LuckPerms instances that receive the message will publish it to API
|
||||
* consumers using the {@link CustomMessageReceiveEvent}.</p>
|
||||
*
|
||||
* @param channelId the channel id
|
||||
* @param payload the message payload
|
||||
* @since 5.5
|
||||
*/
|
||||
void sendCustomMessage(@NonNull String channelId, @NonNull String payload);
|
||||
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.luckperms.api.messenger.message.type;
|
||||
|
||||
import net.luckperms.api.messenger.message.Message;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
/**
|
||||
* Represents a "custom payload" message.
|
||||
*
|
||||
* <p>Used by API consumers to send custom messages between servers.</p>
|
||||
*
|
||||
* @see net.luckperms.api.messaging.MessagingService#sendCustomMessage(String, String)
|
||||
* @see net.luckperms.api.event.messaging.CustomMessageReceiveEvent
|
||||
* @since 5.5
|
||||
*/
|
||||
public interface CustomMessage extends Message {
|
||||
|
||||
/**
|
||||
* Gets the channel identifier.
|
||||
*
|
||||
* @return the namespace
|
||||
*/
|
||||
@NonNull String getChannelId();
|
||||
|
||||
/**
|
||||
* Gets the payload.
|
||||
*
|
||||
* @return the payload
|
||||
*/
|
||||
@NonNull String getPayload();
|
||||
|
||||
}
|
||||
@@ -63,7 +63,6 @@ public interface DisplayNameNode extends ScopedNode<DisplayNameNode, DisplayName
|
||||
*
|
||||
* @param displayName the display name to set
|
||||
* @return the builder
|
||||
* @throws IllegalArgumentException if {@code displayName} is empty
|
||||
*/
|
||||
static @NonNull Builder builder(@NonNull String displayName) {
|
||||
return builder().displayName(displayName);
|
||||
|
||||
@@ -67,7 +67,6 @@ public interface InheritanceNode extends ScopedNode<InheritanceNode, Inheritance
|
||||
*
|
||||
* @param group the group to set
|
||||
* @return the builder
|
||||
* @throws IllegalArgumentException if {@code group} is not a valid group name
|
||||
*/
|
||||
static @NonNull Builder builder(@NonNull String group) {
|
||||
return builder().group(group);
|
||||
|
||||
@@ -71,7 +71,6 @@ public interface MetaNode extends ScopedNode<MetaNode, MetaNode.Builder> {
|
||||
* @param key the meta key to set
|
||||
* @param value the meta value to set
|
||||
* @return the builder
|
||||
* @throws IllegalArgumentException if {@code key} is empty
|
||||
*/
|
||||
static @NonNull Builder builder(@NonNull String key, @NonNull String value) {
|
||||
return builder().key(key).value(value);
|
||||
|
||||
@@ -88,7 +88,6 @@ public interface PermissionNode extends ScopedNode<PermissionNode, PermissionNod
|
||||
*
|
||||
* @param permission the permission to set
|
||||
* @return the builder
|
||||
* @throws IllegalArgumentException if {@code permission} is empty
|
||||
*/
|
||||
static @NonNull Builder builder(@NonNull String permission) {
|
||||
return builder().permission(permission);
|
||||
|
||||
@@ -75,7 +75,6 @@ public interface RegexPermissionNode extends ScopedNode<RegexPermissionNode, Reg
|
||||
*
|
||||
* @param pattern the pattern to set
|
||||
* @return the builder
|
||||
* @throws IllegalArgumentException if {@code pattern} is empty
|
||||
*/
|
||||
static @NonNull Builder builder(@NonNull String pattern) {
|
||||
return builder().pattern(pattern);
|
||||
|
||||
@@ -76,7 +76,6 @@ public interface Platform {
|
||||
NUKKIT("Nukkit"),
|
||||
VELOCITY("Velocity"),
|
||||
FABRIC("Fabric"),
|
||||
NEOFORGE("NeoForge"),
|
||||
FORGE("Forge"),
|
||||
STANDALONE("Standalone");
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ public interface DataTypeFilterFunction {
|
||||
|
||||
/**
|
||||
* Creates a {@link DataTypeFilterFunction} that always returns the given
|
||||
* {@code predicate} (commonly one of the values in {@link DataTypeFilter}).
|
||||
* {@code predicate}.
|
||||
*
|
||||
* @param predicate the predicate
|
||||
* @return the data type filter function
|
||||
|
||||
@@ -96,27 +96,6 @@ public interface TrackManager {
|
||||
*/
|
||||
@NonNull CompletableFuture<Void> deleteTrack(@NonNull Track track);
|
||||
|
||||
/**
|
||||
* Loads (or creates) a track from the plugin's storage provider, applies the given {@code action},
|
||||
* then saves the track's data back to storage.
|
||||
*
|
||||
* <p>This method effectively calls {@link #createAndLoadTrack(String)}, followed by the
|
||||
* {@code action}, then {@link #saveTrack(Track)}, and returns an encapsulation of the whole
|
||||
* process as a {@link CompletableFuture}. </p>
|
||||
*
|
||||
* @param name the name of the track
|
||||
* @param action the action to apply to the track
|
||||
* @return a future to encapsulate the operation
|
||||
* @since 5.5
|
||||
*/
|
||||
default @NonNull CompletableFuture<Void> modifyTrack(@NonNull String name, @NonNull Consumer<? super Track> action) {
|
||||
/* This default method is overridden in the implementation, and is just here
|
||||
to demonstrate what this method does in the API sources. */
|
||||
return createAndLoadTrack(name)
|
||||
.thenApplyAsync(track -> { action.accept(track); return track; })
|
||||
.thenCompose(this::saveTrack);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads all tracks into memory.
|
||||
*
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.luckperms.api.util;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Represents a page of entries.
|
||||
*
|
||||
* @since 5.5
|
||||
*/
|
||||
public interface Page<T> {
|
||||
|
||||
/**
|
||||
* Gets the entries on this page.
|
||||
*
|
||||
* @return the entries
|
||||
*/
|
||||
@NonNull List<T> entries();
|
||||
|
||||
/**
|
||||
* Gets the total/overall number of entries (not just the number of entries on this page).
|
||||
*
|
||||
* @return the total number of entries
|
||||
*/
|
||||
int overallSize();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
plugins {
|
||||
alias(libs.plugins.licenser) apply false
|
||||
}
|
||||
|
||||
import org.gradle.api.tasks.testing.logging.TestExceptionFormat
|
||||
import org.gradle.api.tasks.testing.logging.TestLogEvent
|
||||
|
||||
defaultTasks 'licenseFormat', 'build'
|
||||
|
||||
subprojects {
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'maven-publish'
|
||||
apply plugin: 'org.cadixdev.licenser'
|
||||
|
||||
group = 'me.lucko.luckperms'
|
||||
version = '5.4-SNAPSHOT'
|
||||
|
||||
sourceCompatibility = 1.8
|
||||
targetCompatibility = 1.8
|
||||
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
options.encoding = 'UTF-8'
|
||||
}
|
||||
|
||||
tasks.withType(Test).configureEach {
|
||||
testLogging {
|
||||
events = [TestLogEvent.PASSED, TestLogEvent.FAILED, TestLogEvent.SKIPPED]
|
||||
exceptionFormat = TestExceptionFormat.FULL
|
||||
showExceptions = true
|
||||
showCauses = true
|
||||
showStackTraces = true
|
||||
}
|
||||
}
|
||||
|
||||
jar {
|
||||
from '../LICENSE.txt'
|
||||
}
|
||||
|
||||
def determinePatchVersion = {
|
||||
// get the name of the last tag
|
||||
def tagInfo = new ByteArrayOutputStream()
|
||||
exec {
|
||||
commandLine 'git', 'describe', '--tags'
|
||||
standardOutput = tagInfo
|
||||
}
|
||||
tagInfo = tagInfo.toString()
|
||||
|
||||
if (!tagInfo.contains('-')) {
|
||||
return 0
|
||||
}
|
||||
return tagInfo.split("-")[1]
|
||||
}
|
||||
|
||||
project.ext.majorVersion = '5'
|
||||
project.ext.minorVersion = '4'
|
||||
project.ext.patchVersion = determinePatchVersion()
|
||||
project.ext.apiVersion = project.ext.majorVersion + '.' + project.ext.minorVersion
|
||||
project.ext.fullVersion = project.ext.apiVersion + '.' + project.ext.patchVersion
|
||||
|
||||
license {
|
||||
header = rootProject.file('HEADER.txt')
|
||||
include '**/*.java'
|
||||
newLine = true
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven { url 'https://s01.oss.sonatype.org/content/repositories/snapshots/' }
|
||||
maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
|
||||
maven { url 'https://repo.lucko.me/' }
|
||||
maven { url 'https://libraries.minecraft.net/' }
|
||||
}
|
||||
}
|
||||
@@ -1,348 +0,0 @@
|
||||
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
|
||||
import org.gradle.kotlin.dsl.provideDelegate
|
||||
|
||||
/* ------------------------------ Plugins ------------------------------ */
|
||||
plugins {
|
||||
id("java") // Import Java plugin.
|
||||
id("java-library") // Import Java Library plugin.
|
||||
id("com.diffplug.spotless") version "7.0.4" // Import Spotless plugin.
|
||||
id("com.gradleup.shadow") version "8.3.8" // Import Shadow plugin.
|
||||
id("checkstyle") // Import Checkstyle plugin.
|
||||
eclipse // Import Eclipse plugin.
|
||||
kotlin("jvm") version "2.1.21" // Import Kotlin JVM plugin.
|
||||
}
|
||||
|
||||
extra["kotlinAttribute"] = Attribute.of("kotlin-tag", Boolean::class.javaObjectType)
|
||||
|
||||
val kotlinAttribute: Attribute<Boolean> by rootProject.extra
|
||||
|
||||
/* --------------------------- JDK / Kotlin ---------------------------- */
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_17 // Compile with JDK 17 compatibility.
|
||||
toolchain { // Select Java toolchain.
|
||||
languageVersion.set(JavaLanguageVersion.of(17)) // Use JDK 17.
|
||||
vendor.set(JvmVendorSpec.GRAAL_VM) // Use GraalVM CE.
|
||||
}
|
||||
}
|
||||
|
||||
kotlin { jvmToolchain(17) }
|
||||
|
||||
/* ----------------------------- Metadata ------------------------------ */
|
||||
group = "me.lucko.luckperms" // Declare bundle identifier.
|
||||
|
||||
version = "5.5.0-SNAPSHOT" // Declare plugin version (will be in .jar).
|
||||
|
||||
val apiVersion = "1.19" // Declare minecraft server target version.
|
||||
|
||||
/* ----------------------------- Resources ----------------------------- */
|
||||
tasks.named<ProcessResources>("processResources") {
|
||||
val props = mapOf("version" to version, "apiVersion" to apiVersion)
|
||||
inputs.properties(props) // Indicates to rerun if version changes.
|
||||
filesMatching("plugin.yml") { expand(props) }
|
||||
from("LICENSE") { into("/") } // Bundle licenses into jarfiles.
|
||||
}
|
||||
|
||||
/* ---------------------------- Repos ---------------------------------- */
|
||||
repositories {
|
||||
// Fix issue with lwjgl-freetype not being found on macOS / ForgeGradle issue
|
||||
maven("https://libraries.minecraft.net") { content { includeModule("org.lwjgl", "lwjgl-freetype") } }
|
||||
mavenCentral()
|
||||
maven { url = uri("https://repo.lucko.me/") }
|
||||
maven { url = uri("https://libraries.minecraft.net/") }
|
||||
maven { url = uri("https://repo.papermc.io/repository/maven-public/") }
|
||||
maven { url = uri("file://${System.getProperty("user.home")}/.m2/repository") }
|
||||
System.getProperty("SELF_MAVEN_LOCAL_REPO")?.let {
|
||||
val dir = file(it)
|
||||
if (dir.isDirectory) {
|
||||
println("Using SELF_MAVEN_LOCAL_REPO at: $it")
|
||||
maven { url = uri("file://${dir.absolutePath}") }
|
||||
} else {
|
||||
mavenLocal()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------- Java project deps ---------------------------- */
|
||||
dependencies {
|
||||
// Root project carries no direct compile deps; subprojects declare their own.
|
||||
}
|
||||
|
||||
/* ---------------------- Reproducible jars ---------------------------- */
|
||||
tasks.withType<AbstractArchiveTask>().configureEach { // Ensure reproducible .jars
|
||||
isPreserveFileTimestamps = false
|
||||
isReproducibleFileOrder = true
|
||||
}
|
||||
|
||||
/* ----------------------------- Shadow -------------------------------- */
|
||||
tasks.shadowJar {
|
||||
archiveClassifier.set("") // Use empty string instead of null.
|
||||
minimize()
|
||||
}
|
||||
|
||||
tasks.jar { archiveClassifier.set("part") } // Applies to root jarfile only.
|
||||
|
||||
tasks.build { dependsOn(tasks.spotlessApply) } // Build depends on spotless and shadow.
|
||||
|
||||
/* --------------------------- Javac opts ------------------------------- */
|
||||
tasks.withType<JavaCompile>().configureEach {
|
||||
options.compilerArgs.add("-parameters") // Enable reflection for java code.
|
||||
options.isFork = true // Run javac in its own process.
|
||||
options.compilerArgs.add("-Xlint:deprecation") // Trigger deprecation warning messages.
|
||||
options.encoding = "UTF-8" // Use UTF-8 file encoding.
|
||||
}
|
||||
|
||||
/* ----------------------------- Auto Formatting ------------------------ */
|
||||
spotless {
|
||||
java {
|
||||
eclipse().configFile("config/formatter/eclipse-java-formatter.xml") // Eclipse java formatting.
|
||||
leadingTabsToSpaces() // Convert leftover leading tabs to spaces.
|
||||
removeUnusedImports() // Remove imports that aren't being called.
|
||||
}
|
||||
kotlinGradle {
|
||||
ktfmt().kotlinlangStyle().configure { it.setMaxWidth(120) } // JetBrains Kotlin formatting.
|
||||
target("build.gradle.kts", "settings.gradle.kts") // Gradle files to format.
|
||||
}
|
||||
}
|
||||
|
||||
checkstyle {
|
||||
toolVersion = "10.18.1" // Declare checkstyle version to use.
|
||||
configFile = file("config/checkstyle/checkstyle.xml") // Point checkstyle to config file.
|
||||
isIgnoreFailures = true // Don't fail the build if checkstyle does not pass.
|
||||
isShowViolations = true // Show the violations in any IDE with the checkstyle plugin.
|
||||
}
|
||||
|
||||
tasks.named("compileJava") {
|
||||
dependsOn("spotlessApply") // Run spotless before compiling with the JDK.
|
||||
}
|
||||
|
||||
tasks.named("spotlessCheck") {
|
||||
dependsOn("spotlessApply") // Run spotless before checking if spotless ran.
|
||||
}
|
||||
|
||||
/* --------------------------- LuckPerms modules ------------------------ */
|
||||
|
||||
subprojects {
|
||||
apply(plugin = "java-library")
|
||||
apply(plugin = "eclipse")
|
||||
|
||||
group = "me.lucko.luckperms"
|
||||
version = rootProject.version
|
||||
|
||||
repositories {
|
||||
maven("https://libraries.minecraft.net") { content { includeModule("org.lwjgl", "lwjgl-freetype") } }
|
||||
mavenCentral()
|
||||
maven { url = uri("https://repo.lucko.me/") }
|
||||
maven { url = uri("https://libraries.minecraft.net/") }
|
||||
maven { url = uri("https://repo.papermc.io/repository/maven-public/") }
|
||||
maven { url = uri("file://${System.getProperty("user.home")}/.m2/repository") }
|
||||
System.getProperty("SELF_MAVEN_LOCAL_REPO")?.let {
|
||||
val dir = file(it)
|
||||
if (dir.isDirectory) {
|
||||
println("Using SELF_MAVEN_LOCAL_REPO at: $it")
|
||||
maven { url = uri("file://${dir.absolutePath}") }
|
||||
} else {
|
||||
mavenLocal()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType<Test>().configureEach {
|
||||
testLogging {
|
||||
events("PASSED", "FAILED", "SKIPPED")
|
||||
exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL
|
||||
showExceptions = true
|
||||
showCauses = true
|
||||
showStackTraces = true
|
||||
}
|
||||
useJUnitPlatform()
|
||||
}
|
||||
|
||||
tasks.withType<JavaCompile>().configureEach { options.encoding = "UTF-8" }
|
||||
|
||||
tasks.withType<Jar>().configureEach { from(rootProject.file("LICENSE.txt")) }
|
||||
}
|
||||
|
||||
/* :api */
|
||||
project(":api") {
|
||||
dependencies {
|
||||
compileOnly("org.checkerframework:checker-qual:3.49.3")
|
||||
compileOnly("org.jetbrains:annotations:26.0.2")
|
||||
}
|
||||
tasks.jar { manifest { attributes(mapOf("Automatic-Module-Name" to "net.luckperms.api")) } }
|
||||
}
|
||||
|
||||
/* :common */
|
||||
project(":common") {
|
||||
apply(plugin = "jacoco")
|
||||
|
||||
val patchedDir = layout.buildDirectory.dir("patchedSrc/commonMain/java")
|
||||
val patchCommonForJ17 =
|
||||
tasks.register<Copy>("patchCommonForJ17") {
|
||||
from("src/main/java")
|
||||
into(patchedDir)
|
||||
filteringCharset = "UTF-8"
|
||||
filesMatching("**/*.java") {
|
||||
filter { line ->
|
||||
if (
|
||||
line.contains(".reversed()") &&
|
||||
!line.contains("Comparator") &&
|
||||
!line.contains("comparing") &&
|
||||
!line.contains("thenComparing") &&
|
||||
!line.contains("INSTANCE") &&
|
||||
!line.contains("normal()")
|
||||
) {
|
||||
line.replace(
|
||||
".reversed()",
|
||||
".stream().collect(java.util.stream.Collectors.collectingAndThen(" +
|
||||
"java.util.stream.Collectors.toList(), l -> { java.util.Collections.reverse(l); return l; }))",
|
||||
)
|
||||
} else line
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sourceSets.named("main") {
|
||||
java.setSrcDirs(emptyList<Any>())
|
||||
java.srcDir(patchedDir)
|
||||
}
|
||||
tasks.named<JavaCompile>("compileJava") { dependsOn(patchCommonForJ17) }
|
||||
|
||||
dependencies {
|
||||
testImplementation("org.slf4j:slf4j-simple:1.7.36")
|
||||
testImplementation("org.junit.jupiter:junit-jupiter:5.13.0")
|
||||
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
||||
testImplementation("org.testcontainers:junit-jupiter:1.21.1")
|
||||
testImplementation("org.mockito:mockito-core:5.18.0")
|
||||
testImplementation("org.mockito:mockito-junit-jupiter:5.18.0")
|
||||
testImplementation("com.h2database:h2:2.1.214")
|
||||
testImplementation("org.mongodb:mongodb-driver-legacy:5.5.0")
|
||||
testImplementation("org.spongepowered:configurate-yaml:3.7.3")
|
||||
testImplementation("org.spongepowered:configurate-hocon:3.7.3")
|
||||
testImplementation("me.lucko.configurate:configurate-toml:3.7")
|
||||
testImplementation("net.luckperms:rest-api-java-client:0.1")
|
||||
|
||||
api(project(":api"))
|
||||
api("org.checkerframework:checker-qual:3.12.0")
|
||||
compileOnly(project(":common:loader-utils"))
|
||||
compileOnly("com.mojang:brigadier:1.0.18")
|
||||
compileOnly("org.slf4j:slf4j-api:1.7.30")
|
||||
compileOnly("org.apache.logging.log4j:log4j-api:2.14.0")
|
||||
|
||||
api("net.kyori:adventure-api:4.21.0") {
|
||||
exclude(module = "adventure-bom")
|
||||
exclude(module = "checker-qual")
|
||||
exclude(module = "annotations")
|
||||
}
|
||||
api("net.kyori:adventure-text-serializer-gson:4.21.0") {
|
||||
exclude(module = "adventure-bom")
|
||||
exclude(module = "adventure-api")
|
||||
exclude(module = "gson")
|
||||
}
|
||||
api("net.kyori:adventure-text-serializer-legacy:4.21.0") {
|
||||
exclude(module = "adventure-bom")
|
||||
exclude(module = "adventure-api")
|
||||
}
|
||||
api("net.kyori:adventure-text-serializer-plain:4.21.0") {
|
||||
exclude(module = "adventure-bom")
|
||||
exclude(module = "adventure-api")
|
||||
}
|
||||
api("net.kyori:adventure-text-minimessage:4.21.0") {
|
||||
exclude(module = "adventure-bom")
|
||||
exclude(module = "adventure-api")
|
||||
}
|
||||
api("net.kyori:event-api:3.0.0") {
|
||||
exclude(module = "checker-qual")
|
||||
exclude(module = "guava")
|
||||
}
|
||||
|
||||
api("com.google.code.gson:gson:2.7")
|
||||
api("com.google.guava:guava:19.0")
|
||||
api("com.github.ben-manes.caffeine:caffeine:3.2.0")
|
||||
api("com.squareup.okhttp3:okhttp:3.14.9")
|
||||
api("com.squareup.okio:okio:1.17.6")
|
||||
api("net.bytebuddy:byte-buddy:1.15.11")
|
||||
|
||||
api("org.spongepowered:configurate-core:3.7.3") { isTransitive = false }
|
||||
api("org.spongepowered:configurate-yaml:3.7.3") { isTransitive = false }
|
||||
api("org.spongepowered:configurate-gson:3.7.3") { isTransitive = false }
|
||||
api("org.spongepowered:configurate-hocon:3.7.3") { isTransitive = false }
|
||||
api("me.lucko.configurate:configurate-toml:3.7") { isTransitive = false }
|
||||
|
||||
compileOnly("com.zaxxer:HikariCP:6.3.0")
|
||||
compileOnly("redis.clients:jedis:5.2.0")
|
||||
compileOnly("io.nats:jnats:2.21.1")
|
||||
compileOnly("com.rabbitmq:amqp-client:5.25.0")
|
||||
compileOnly("org.mongodb:mongodb-driver-legacy:5.5.0")
|
||||
compileOnly("org.postgresql:postgresql:42.7.6")
|
||||
compileOnly("org.yaml:snakeyaml:1.33")
|
||||
compileOnly("net.luckperms:rest-api-java-client:0.1")
|
||||
}
|
||||
}
|
||||
|
||||
/* :common:loader-utils */
|
||||
project(":common:loader-utils") {
|
||||
// nothing special
|
||||
}
|
||||
|
||||
/* :bukkit */
|
||||
project(":bukkit") {
|
||||
apply(plugin = "com.gradleup.shadow")
|
||||
dependencies {
|
||||
implementation(project(":common"))
|
||||
compileOnly(project(":common:loader-utils"))
|
||||
|
||||
compileOnly("com.destroystokyo.paper:paper-api:1.15.2-R0.1-SNAPSHOT")
|
||||
compileOnly("net.kyori:adventure-platform-bukkit:4.4.0") {
|
||||
exclude(module = "adventure-bom")
|
||||
exclude(module = "adventure-api")
|
||||
exclude(module = "adventure-nbt")
|
||||
}
|
||||
compileOnly("me.lucko:commodore:2.0")
|
||||
compileOnly("net.milkbowl.vault:VaultAPI:1.7") { exclude(module = "bukkit") }
|
||||
compileOnly("lilypad.client.connect:api:0.0.1-SNAPSHOT")
|
||||
}
|
||||
tasks.named<ShadowJar>("shadowJar") {
|
||||
archiveFileName.set("luckperms-bukkit.jarinjar")
|
||||
dependencies { include(dependency("me.lucko.luckperms:.*")) }
|
||||
relocate("net.kyori.adventure", "me.lucko.luckperms.lib.adventure")
|
||||
relocate("net.kyori.event", "me.lucko.luckperms.lib.eventbus")
|
||||
relocate("com.github.benmanes.caffeine", "me.lucko.luckperms.lib.caffeine")
|
||||
relocate("okio", "me.lucko.luckperms.lib.okio")
|
||||
relocate("okhttp3", "me.lucko.luckperms.lib.okhttp3")
|
||||
relocate("net.bytebuddy", "me.lucko.luckperms.lib.bytebuddy")
|
||||
relocate("me.lucko.commodore", "me.lucko.luckperms.lib.commodore")
|
||||
relocate("org.mariadb.jdbc", "me.lucko.luckperms.lib.mariadb")
|
||||
relocate("com.mysql", "me.lucko.luckperms.lib.mysql")
|
||||
relocate("org.postgresql", "me.lucko.luckperms.lib.postgresql")
|
||||
relocate("com.zaxxer.hikari", "me.lucko.luckperms.lib.hikari")
|
||||
relocate("com.mongodb", "me.lucko.luckperms.lib.mongodb")
|
||||
relocate("org.bson", "me.lucko.luckperms.lib.bson")
|
||||
relocate("redis.clients.jedis", "me.lucko.luckperms.lib.jedis")
|
||||
relocate("io.nats.client", "me.lucko.luckperms.lib.nats")
|
||||
relocate("com.rabbitmq", "me.lucko.luckperms.lib.rabbitmq")
|
||||
relocate("org.apache.commons.pool2", "me.lucko.luckperms.lib.commonspool2")
|
||||
relocate("ninja.leaping.configurate", "me.lucko.luckperms.lib.configurate")
|
||||
}
|
||||
}
|
||||
|
||||
/* :bukkit:loader */
|
||||
project(":bukkit:loader") {
|
||||
apply(plugin = "com.gradleup.shadow")
|
||||
dependencies {
|
||||
compileOnly("com.destroystokyo.paper:paper-api:1.15.2-R0.1-SNAPSHOT")
|
||||
implementation(project(":api"))
|
||||
implementation(project(":common:loader-utils"))
|
||||
}
|
||||
tasks.processResources {
|
||||
filesMatching("plugin.yml") { expand(mapOf("pluginVersion" to rootProject.version.toString())) }
|
||||
}
|
||||
tasks.named<ShadowJar>("shadowJar") {
|
||||
archiveFileName.set("LuckPerms-${rootProject.version}.jar")
|
||||
from(project(":bukkit").tasks.named<ShadowJar>("shadowJar").flatMap { it.archiveFile })
|
||||
manifest { attributes(mapOf("paperweight-mappings-namespace" to "mojang")) }
|
||||
destinationDirectory.set(rootProject.layout.buildDirectory.dir("libs"))
|
||||
}
|
||||
}
|
||||
|
||||
/* Build root produces the server jar */
|
||||
tasks.named("build") { dependsOn(project(":bukkit:loader").tasks.named("shadowJar")) }
|
||||
@@ -0,0 +1,45 @@
|
||||
plugins {
|
||||
alias(libs.plugins.shadow)
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation project(':bukkit')
|
||||
implementation 'com.google.code.gson:gson:2.7'
|
||||
implementation 'com.google.guava:guava:19.0'
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
archiveFileName = 'luckperms-bukkitlegacy.jarinjar'
|
||||
|
||||
dependencies {
|
||||
include(dependency('me.lucko.luckperms:.*'))
|
||||
include(dependency('com.google.guava:guava:.*'))
|
||||
include(dependency('com.google.code.gson:gson:.*'))
|
||||
}
|
||||
|
||||
relocate 'com.google.common', 'me.lucko.luckperms.lib.guava'
|
||||
relocate 'com.google.gson', 'me.lucko.luckperms.lib.gson'
|
||||
|
||||
relocate 'net.kyori.adventure', 'me.lucko.luckperms.lib.adventure'
|
||||
relocate 'net.kyori.event', 'me.lucko.luckperms.lib.eventbus'
|
||||
relocate 'com.github.benmanes.caffeine', 'me.lucko.luckperms.lib.caffeine'
|
||||
relocate 'okio', 'me.lucko.luckperms.lib.okio'
|
||||
relocate 'okhttp3', 'me.lucko.luckperms.lib.okhttp3'
|
||||
relocate 'net.bytebuddy', 'me.lucko.luckperms.lib.bytebuddy'
|
||||
relocate 'me.lucko.commodore', 'me.lucko.luckperms.lib.commodore'
|
||||
relocate 'org.mariadb.jdbc', 'me.lucko.luckperms.lib.mariadb'
|
||||
relocate 'com.mysql', 'me.lucko.luckperms.lib.mysql'
|
||||
relocate 'org.postgresql', 'me.lucko.luckperms.lib.postgresql'
|
||||
relocate 'com.zaxxer.hikari', 'me.lucko.luckperms.lib.hikari'
|
||||
relocate 'com.mongodb', 'me.lucko.luckperms.lib.mongodb'
|
||||
relocate 'org.bson', 'me.lucko.luckperms.lib.bson'
|
||||
relocate 'redis.clients.jedis', 'me.lucko.luckperms.lib.jedis'
|
||||
relocate 'io.nats.client', 'me.lucko.luckperms.lib.nats'
|
||||
relocate 'com.rabbitmq', 'me.lucko.luckperms.lib.rabbitmq'
|
||||
relocate 'org.apache.commons.pool2', 'me.lucko.luckperms.lib.commonspool2'
|
||||
relocate 'ninja.leaping.configurate', 'me.lucko.luckperms.lib.configurate'
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives shadowJar
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
plugins {
|
||||
alias(libs.plugins.shadow)
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven { url 'https://repo.papermc.io/repository/maven-public/' }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly 'com.destroystokyo.paper:paper-api:1.15.2-R0.1-SNAPSHOT'
|
||||
|
||||
implementation project(':api')
|
||||
implementation project(':common:loader-utils')
|
||||
}
|
||||
|
||||
processResources {
|
||||
filesMatching('plugin.yml') {
|
||||
expand 'pluginVersion': project.ext.fullVersion
|
||||
}
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
archiveFileName = "LuckPerms-Bukkit-Legacy-${project.ext.fullVersion}.jar"
|
||||
|
||||
from {
|
||||
project(':bukkit-legacy').tasks.shadowJar.archiveFile
|
||||
}
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives shadowJar
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
plugins {
|
||||
alias(libs.plugins.shadow)
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven { url 'https://repo.papermc.io/repository/maven-public/' }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation project(':common')
|
||||
compileOnly project(':common:loader-utils')
|
||||
|
||||
compileOnly 'com.destroystokyo.paper:paper-api:1.15.2-R0.1-SNAPSHOT'
|
||||
compileOnly('net.kyori:adventure-platform-bukkit:4.1.0') {
|
||||
exclude(module: 'adventure-bom')
|
||||
exclude(module: 'adventure-api')
|
||||
exclude(module: 'adventure-nbt')
|
||||
}
|
||||
compileOnly 'me.lucko:commodore:2.0'
|
||||
compileOnly('net.milkbowl.vault:VaultAPI:1.7') {
|
||||
exclude(module: 'bukkit')
|
||||
}
|
||||
compileOnly 'lilypad.client.connect:api:0.0.1-SNAPSHOT'
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
archiveFileName = 'luckperms-bukkit.jarinjar'
|
||||
|
||||
dependencies {
|
||||
include(dependency('me.lucko.luckperms:.*'))
|
||||
}
|
||||
|
||||
relocate 'net.kyori.adventure', 'me.lucko.luckperms.lib.adventure'
|
||||
relocate 'net.kyori.event', 'me.lucko.luckperms.lib.eventbus'
|
||||
relocate 'com.github.benmanes.caffeine', 'me.lucko.luckperms.lib.caffeine'
|
||||
relocate 'okio', 'me.lucko.luckperms.lib.okio'
|
||||
relocate 'okhttp3', 'me.lucko.luckperms.lib.okhttp3'
|
||||
relocate 'net.bytebuddy', 'me.lucko.luckperms.lib.bytebuddy'
|
||||
relocate 'me.lucko.commodore', 'me.lucko.luckperms.lib.commodore'
|
||||
relocate 'org.mariadb.jdbc', 'me.lucko.luckperms.lib.mariadb'
|
||||
relocate 'com.mysql', 'me.lucko.luckperms.lib.mysql'
|
||||
relocate 'org.postgresql', 'me.lucko.luckperms.lib.postgresql'
|
||||
relocate 'com.zaxxer.hikari', 'me.lucko.luckperms.lib.hikari'
|
||||
relocate 'com.mongodb', 'me.lucko.luckperms.lib.mongodb'
|
||||
relocate 'org.bson', 'me.lucko.luckperms.lib.bson'
|
||||
relocate 'redis.clients.jedis', 'me.lucko.luckperms.lib.jedis'
|
||||
relocate 'io.nats.client', 'me.lucko.luckperms.lib.nats'
|
||||
relocate 'com.rabbitmq', 'me.lucko.luckperms.lib.rabbitmq'
|
||||
relocate 'org.apache.commons.pool2', 'me.lucko.luckperms.lib.commonspool2'
|
||||
relocate 'ninja.leaping.configurate', 'me.lucko.luckperms.lib.configurate'
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives shadowJar
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
plugins {
|
||||
alias(libs.plugins.shadow)
|
||||
}
|
||||
|
||||
configurations {
|
||||
testJar
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven { url 'https://repo.papermc.io/repository/maven-public/' }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly 'com.destroystokyo.paper:paper-api:1.15.2-R0.1-SNAPSHOT'
|
||||
|
||||
implementation project(':api')
|
||||
implementation project(':common:loader-utils')
|
||||
}
|
||||
|
||||
processResources {
|
||||
filesMatching('plugin.yml') {
|
||||
expand 'pluginVersion': project.ext.fullVersion
|
||||
}
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
archiveFileName = "LuckPerms-Bukkit-${project.ext.fullVersion}.jar"
|
||||
|
||||
from {
|
||||
project(':bukkit').tasks.shadowJar.archiveFile
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register('copyTestJar', Copy) {
|
||||
from tasks.shadowJar.archiveFile
|
||||
into layout.buildDirectory.dir('testJars')
|
||||
rename { String fileName ->
|
||||
return 'luckperms-bukkit.testjar'
|
||||
}
|
||||
}
|
||||
|
||||
artifacts.add('testJar', layout.buildDirectory.dir('testJars')) {
|
||||
builtBy('copyTestJar')
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives shadowJar
|
||||
}
|
||||
@@ -307,7 +307,7 @@ public class LPBukkitBootstrap implements LuckPermsBootstrap, LoaderBootstrap, B
|
||||
try {
|
||||
Class.forName("com.google.gson.JsonElement");
|
||||
return false;
|
||||
} catch (Exception e) {
|
||||
} catch (ClassNotFoundException e) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,12 +221,10 @@ public class LPBukkitPlugin extends AbstractLuckPermsPlugin {
|
||||
* - https://hub.spigotmc.org/jira/browse/SPIGOT-5546
|
||||
* - https://github.com/PaperMC/Paper/pull/3509
|
||||
*/
|
||||
if (getConfiguration().get(ConfigKeys.VAULT_ENABLED)) {
|
||||
PluginManagerUtil.injectDependency(this.bootstrap.getServer().getPluginManager(), this.bootstrap.getLoader().getName(), "Vault");
|
||||
PluginManagerUtil.injectDependency(this.bootstrap.getServer().getPluginManager(), this.bootstrap.getLoader().getName(), "Vault");
|
||||
|
||||
// Provide vault support
|
||||
tryVaultHook(false);
|
||||
}
|
||||
// Provide vault support
|
||||
tryVaultHook(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -239,10 +237,6 @@ public class LPBukkitPlugin extends AbstractLuckPermsPlugin {
|
||||
return; // already hooked
|
||||
}
|
||||
|
||||
if (!getConfiguration().get(ConfigKeys.VAULT_ENABLED)) {
|
||||
return; // disabled in config
|
||||
}
|
||||
|
||||
try {
|
||||
if (force || this.bootstrap.getServer().getPluginManager().isPluginEnabled("Vault")) {
|
||||
this.vaultHookManager = new VaultHookManager(this);
|
||||
@@ -353,7 +347,7 @@ public class LPBukkitPlugin extends AbstractLuckPermsPlugin {
|
||||
try {
|
||||
Class.forName(className);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
} catch (ClassNotFoundException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,46 +25,85 @@
|
||||
|
||||
package me.lucko.luckperms.bukkit.context;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
|
||||
import me.lucko.luckperms.bukkit.inject.permissible.LuckPermsPermissible;
|
||||
import me.lucko.luckperms.bukkit.inject.permissible.PermissibleInjector;
|
||||
import me.lucko.luckperms.common.context.manager.DetachedContextManager;
|
||||
import me.lucko.luckperms.common.context.manager.QueryOptionsSupplier;
|
||||
import me.lucko.luckperms.common.cache.LoadingMap;
|
||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||
import me.lucko.luckperms.common.context.manager.ContextManager;
|
||||
import me.lucko.luckperms.common.context.manager.QueryOptionsCache;
|
||||
import me.lucko.luckperms.common.util.CaffeineFactory;
|
||||
import net.luckperms.api.context.ImmutableContextSet;
|
||||
import net.luckperms.api.query.OptionKey;
|
||||
import net.luckperms.api.query.QueryOptions;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class BukkitContextManager extends DetachedContextManager<Player, Player> {
|
||||
public class BukkitContextManager extends ContextManager<Player, Player> {
|
||||
|
||||
public static final OptionKey<Boolean> OP_OPTION = OptionKey.of("op", Boolean.class);
|
||||
|
||||
// cache the creation of ContextsCache instances for online players with no expiry
|
||||
private final LoadingMap<Player, QueryOptionsCache<Player>> onlineSubjectCaches = LoadingMap.of(key -> new QueryOptionsCache<>(key, this));
|
||||
|
||||
// cache the creation of ContextsCache instances for offline players with a 1m expiry
|
||||
private final LoadingCache<Player, QueryOptionsCache<Player>> offlineSubjectCaches = CaffeineFactory.newBuilder()
|
||||
.expireAfterAccess(1, TimeUnit.MINUTES)
|
||||
.build(key -> {
|
||||
QueryOptionsCache<Player> cache = this.onlineSubjectCaches.getIfPresent(key);
|
||||
if (cache != null) {
|
||||
return cache;
|
||||
}
|
||||
return new QueryOptionsCache<>(key, this);
|
||||
});
|
||||
|
||||
public BukkitContextManager(LPBukkitPlugin plugin) {
|
||||
super(plugin, Player.class, Player.class);
|
||||
}
|
||||
|
||||
public void onPlayerQuit(Player player) {
|
||||
this.onlineSubjectCaches.remove(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUniqueId(Player player) {
|
||||
return player.getUniqueId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable QueryOptionsSupplier getQueryOptionsSupplier(Player subject) {
|
||||
Objects.requireNonNull(subject, "subject");
|
||||
LuckPermsPermissible permissible = PermissibleInjector.get(subject);
|
||||
if (permissible != null) {
|
||||
return permissible.getQueryOptionsSupplier();
|
||||
public QueryOptionsCache<Player> getCacheFor(Player subject) {
|
||||
if (subject == null) {
|
||||
throw new NullPointerException("subject");
|
||||
}
|
||||
|
||||
if (subject.isOnline()) {
|
||||
return this.onlineSubjectCaches.get(subject);
|
||||
} else {
|
||||
return this.offlineSubjectCaches.get(subject);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void customizeQueryOptions(Player subject, QueryOptions.Builder builder) {
|
||||
if (subject.isOp()) {
|
||||
builder.option(OP_OPTION, true);
|
||||
protected void invalidateCache(Player subject) {
|
||||
QueryOptionsCache<Player> cache = this.onlineSubjectCaches.getIfPresent(subject);
|
||||
if (cache != null) {
|
||||
cache.invalidate();
|
||||
}
|
||||
|
||||
cache = this.offlineSubjectCaches.getIfPresent(subject);
|
||||
if (cache != null) {
|
||||
cache.invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryOptions formQueryOptions(Player subject, ImmutableContextSet contextSet) {
|
||||
QueryOptions.Builder queryOptions = this.plugin.getConfiguration().get(ConfigKeys.GLOBAL_QUERY_OPTIONS).toBuilder();
|
||||
if (subject.isOp()) {
|
||||
queryOptions.option(OP_OPTION, true);
|
||||
}
|
||||
|
||||
return queryOptions.context(contextSet).build();
|
||||
}
|
||||
}
|
||||
+9
-11
@@ -32,7 +32,7 @@ import me.lucko.luckperms.bukkit.calculator.OpProcessor;
|
||||
import me.lucko.luckperms.bukkit.calculator.PermissionMapProcessor;
|
||||
import me.lucko.luckperms.common.cacheddata.result.TristateResult;
|
||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||
import me.lucko.luckperms.common.context.manager.QueryOptionsSupplier;
|
||||
import me.lucko.luckperms.common.context.manager.QueryOptionsCache;
|
||||
import me.lucko.luckperms.common.model.User;
|
||||
import me.lucko.luckperms.common.verbose.event.CheckOrigin;
|
||||
import net.luckperms.api.query.QueryOptions;
|
||||
@@ -68,7 +68,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
* "Hot" method calls, (namely #hasPermission) are significantly faster than the base implementation.
|
||||
*
|
||||
* This class is **thread safe**. This means that when LuckPerms is installed on the server,
|
||||
* it is safe to call Player#hasPermission asynchronously.
|
||||
* is is safe to call Player#hasPermission asynchronously.
|
||||
*/
|
||||
public class LuckPermsPermissible extends PermissibleBase {
|
||||
|
||||
@@ -93,7 +93,7 @@ public class LuckPermsPermissible extends PermissibleBase {
|
||||
private final LPBukkitPlugin plugin;
|
||||
|
||||
// caches context lookups for the player
|
||||
private final QueryOptionsSupplier queryOptionsSupplier;
|
||||
private final QueryOptionsCache<Player> queryOptionsSupplier;
|
||||
|
||||
// the players previous permissible. (the one they had before this one was injected)
|
||||
private PermissibleBase oldPermissible = null;
|
||||
@@ -110,7 +110,7 @@ public class LuckPermsPermissible extends PermissibleBase {
|
||||
this.user = Objects.requireNonNull(user, "user");
|
||||
this.player = Objects.requireNonNull(player, "player");
|
||||
this.plugin = Objects.requireNonNull(plugin, "plugin");
|
||||
this.queryOptionsSupplier = plugin.getContextManager().createQueryOptionsSupplier(player);
|
||||
this.queryOptionsSupplier = plugin.getContextManager().getCacheFor(player);
|
||||
|
||||
injectFakeAttachmentsList();
|
||||
}
|
||||
@@ -293,7 +293,7 @@ public class LuckPermsPermissible extends PermissibleBase {
|
||||
// the query options cache when op status changes.
|
||||
// (#invalidate is a fast call)
|
||||
if (this.queryOptionsSupplier != null) { // this method is called by the super class constructor, before this class has fully initialised
|
||||
this.queryOptionsSupplier.invalidateCache();
|
||||
this.queryOptionsSupplier.invalidate();
|
||||
}
|
||||
|
||||
// but we don't need to do anything else in this method, unlike the CB impl.
|
||||
@@ -316,10 +316,6 @@ public class LuckPermsPermissible extends PermissibleBase {
|
||||
return this.plugin;
|
||||
}
|
||||
|
||||
public QueryOptionsSupplier getQueryOptionsSupplier() {
|
||||
return this.queryOptionsSupplier;
|
||||
}
|
||||
|
||||
PermissibleBase getOldPermissible() {
|
||||
return this.oldPermissible;
|
||||
}
|
||||
@@ -413,7 +409,9 @@ public class LuckPermsPermissible extends PermissibleBase {
|
||||
@Override public PermissionAttachment remove(int index) { throw new UnsupportedOperationException(); }
|
||||
@Override public int indexOf(Object o) { throw new UnsupportedOperationException(); }
|
||||
@Override public int lastIndexOf(Object o) { throw new UnsupportedOperationException(); }
|
||||
@Override public @NonNull ListIterator<PermissionAttachment> listIterator(int index) { throw new UnsupportedOperationException(); }
|
||||
@Override public @NonNull List<PermissionAttachment> subList(int fromIndex, int toIndex) { throw new UnsupportedOperationException(); }
|
||||
@Override
|
||||
public @NonNull ListIterator<PermissionAttachment> listIterator(int index) { throw new UnsupportedOperationException(); }
|
||||
@Override
|
||||
public @NonNull List<PermissionAttachment> subList(int fromIndex, int toIndex) { throw new UnsupportedOperationException(); }
|
||||
}
|
||||
}
|
||||
-14
@@ -30,7 +30,6 @@ import me.lucko.luckperms.common.plugin.logging.PluginLogger;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.permissions.PermissibleBase;
|
||||
import org.bukkit.permissions.PermissionAttachment;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.List;
|
||||
@@ -162,19 +161,6 @@ public final class PermissibleInjector {
|
||||
}
|
||||
}
|
||||
|
||||
public static @Nullable LuckPermsPermissible get(Player player) {
|
||||
PermissibleBase permissibleBase;
|
||||
try {
|
||||
permissibleBase = (PermissibleBase) HUMAN_ENTITY_PERMISSIBLE_FIELD.get(player);
|
||||
} catch (IllegalAccessException e) {
|
||||
return null;
|
||||
}
|
||||
if (permissibleBase instanceof LuckPermsPermissible) {
|
||||
return (LuckPermsPermissible) permissibleBase;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void checkInjected(Player player, PluginLogger logger) {
|
||||
PermissibleBase permissibleBase;
|
||||
try {
|
||||
|
||||
@@ -253,6 +253,9 @@ public class BukkitConnectionListener extends AbstractConnectionListener impleme
|
||||
if (this.plugin.getConfiguration().get(ConfigKeys.AUTO_OP)) {
|
||||
player.setOp(false);
|
||||
}
|
||||
|
||||
// remove their contexts cache
|
||||
this.plugin.getContextManager().onPlayerQuit(player);
|
||||
}, 1L);
|
||||
}
|
||||
|
||||
|
||||
+6
-27
@@ -36,25 +36,12 @@ import org.bukkit.event.player.PlayerCommandPreprocessEvent;
|
||||
import org.bukkit.event.server.PluginEnableEvent;
|
||||
import org.bukkit.event.server.RemoteServerCommandEvent;
|
||||
import org.bukkit.event.server.ServerCommandEvent;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.PluginDescriptionFile;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class BukkitPlatformListener implements Listener {
|
||||
private static final Pattern OP_COMMAND_PATTERN = Pattern.compile("^/?(\\w+:)?(deop|op)( .*)?$", Pattern.CASE_INSENSITIVE);
|
||||
|
||||
private static final boolean PLUGIN_DESCRIPTION_FILE_PROVIDES_SUPPORTED;
|
||||
|
||||
static {
|
||||
boolean supported = false;
|
||||
try {
|
||||
PluginDescriptionFile.class.getMethod("getProvides");
|
||||
supported = true;
|
||||
} catch (NoSuchMethodException ignored) {
|
||||
}
|
||||
PLUGIN_DESCRIPTION_FILE_PROVIDES_SUPPORTED = supported;
|
||||
}
|
||||
private static final Pattern OP_COMMAND_PATTERN = Pattern.compile("^/?(\\w+:)?(deop|op)( .*)?$");
|
||||
|
||||
private final LPBukkitPlugin plugin;
|
||||
|
||||
@@ -64,17 +51,17 @@ public class BukkitPlatformListener implements Listener {
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onPlayerCommand(PlayerCommandPreprocessEvent e) {
|
||||
handleCommand(e.getPlayer(), e.getMessage(), e);
|
||||
handleCommand(e.getPlayer(), e.getMessage().toLowerCase(Locale.ROOT), e);
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onServerCommand(ServerCommandEvent e) {
|
||||
handleCommand(e.getSender(), e.getCommand(), e);
|
||||
handleCommand(e.getSender(), e.getCommand().toLowerCase(Locale.ROOT), e);
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onRemoteServerCommand(RemoteServerCommandEvent e) {
|
||||
handleCommand(e.getSender(), e.getCommand(), e);
|
||||
handleCommand(e.getSender(), e.getCommand().toLowerCase(Locale.ROOT), e);
|
||||
}
|
||||
|
||||
private void handleCommand(CommandSender sender, String cmdLine, Cancellable event) {
|
||||
@@ -94,15 +81,7 @@ public class BukkitPlatformListener implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onPluginEnable(PluginEnableEvent e) {
|
||||
if (!this.plugin.getConfiguration().get(ConfigKeys.VAULT_ENABLED)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Plugin p = e.getPlugin();
|
||||
boolean shouldHook = p.getName().equalsIgnoreCase("Vault") ||
|
||||
(PLUGIN_DESCRIPTION_FILE_PROVIDES_SUPPORTED && p.getDescription().getProvides().contains("Vault"));
|
||||
|
||||
if (shouldHook) {
|
||||
if (e.getPlugin().getName().equalsIgnoreCase("Vault")) {
|
||||
this.plugin.tryVaultHook(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ server: global
|
||||
# - To get around this, you can use a player's uuid directly in the command, or enable this option.
|
||||
# - When this is set to 'true', the server facility is used. This may use a number of methods,
|
||||
# including checking the servers local cache, or making a request to the Mojang API.
|
||||
use-server-uuid-cache: true
|
||||
use-server-uuid-cache: false
|
||||
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ use-server-uuid-cache: true
|
||||
#
|
||||
# - A H2 database is the default option.
|
||||
# - If you want to edit data manually in "traditional" storage files, we suggest using YAML.
|
||||
storage-method: postgresql
|
||||
storage-method: h2
|
||||
|
||||
# The following block defines the settings for remote database storage methods.
|
||||
#
|
||||
@@ -99,11 +99,11 @@ data:
|
||||
|
||||
# The name of the database to store LuckPerms data in.
|
||||
# - This must be created already. Don't worry about this setting if you're using MongoDB.
|
||||
database: luckperms
|
||||
database: minecraft
|
||||
|
||||
# Credentials for the database.
|
||||
username: '^{POSTGRES_USER}'
|
||||
password: '^{POSTGRES_PASSWORD}'
|
||||
username: root
|
||||
password: ''
|
||||
|
||||
# These settings apply to the MySQL connection pool.
|
||||
# - The default values will be suitable for the majority of users.
|
||||
@@ -132,11 +132,11 @@ data:
|
||||
# from being timed out by the database or network infrastructure, measured in milliseconds.
|
||||
# - The value should be less than maximum-lifetime and greater than 30000 (30 seconds).
|
||||
# - Setting the value to zero will disable the keepalive functionality.
|
||||
keepalive-time: 120000
|
||||
keepalive-time: 0
|
||||
|
||||
# This setting controls the maximum number of milliseconds that the plugin will wait for a
|
||||
# connection from the pool, before timing out.
|
||||
connection-timeout: 10000 # 10 seconds
|
||||
connection-timeout: 5000 # 5 seconds
|
||||
|
||||
# This setting allows you to define extra properties for connections.
|
||||
#
|
||||
@@ -216,7 +216,7 @@ sync-minutes: -1
|
||||
# - When using a file-based storage type, LuckPerms can monitor the data files for changes, and
|
||||
# automatically update when changes are detected.
|
||||
# - If you don't want this feature to be active, set this option to false.
|
||||
watch-files: false
|
||||
watch-files: true
|
||||
|
||||
# Define which messaging service should be used by the plugin.
|
||||
#
|
||||
@@ -258,16 +258,16 @@ push-log-entries: true
|
||||
# - If you have LuckPerms installed on your backend servers as well as a BungeeCord proxy, you
|
||||
# should set this option to false on either your backends or your proxies, to avoid players being
|
||||
# messaged twice about log entries.
|
||||
broadcast-received-log-entries: false
|
||||
broadcast-received-log-entries: true
|
||||
|
||||
# Settings for Keydb.
|
||||
# Settings for Redis.
|
||||
# Port 6379 is used by default; set address to "host:port" if differs
|
||||
# Multiple Keydb nodes can be specified in the same format as a string list under the name "addresses".
|
||||
# Multiple Redis nodes can be specified in the same format as a string list under the name "addresses".
|
||||
redis:
|
||||
enabled: true
|
||||
enabled: false
|
||||
address: localhost
|
||||
username: 'default'
|
||||
password: 'bookchin'
|
||||
username: ''
|
||||
password: ''
|
||||
|
||||
# Settings for Nats.
|
||||
# Port 4222 is used by default; set address to "host:port" if differs
|
||||
@@ -335,7 +335,7 @@ argument-based-command-permissions: false
|
||||
# If the plugin should check whether senders are a member of a given group before they're able to
|
||||
# edit the groups data or add/remove other users to/from it.
|
||||
# Note: these limitations do not apply to the web editor!
|
||||
require-sender-group-membership-to-modify: true
|
||||
require-sender-group-membership-to-modify: false
|
||||
|
||||
# If the plugin should send log notifications to users whenever permissions are modified.
|
||||
#
|
||||
@@ -408,14 +408,14 @@ meta-formatting:
|
||||
duplicates: first-only
|
||||
start-spacer: ""
|
||||
middle-spacer: " "
|
||||
end-spacer: " "
|
||||
end-spacer: ""
|
||||
suffix:
|
||||
format:
|
||||
- "highest"
|
||||
duplicates: first-only
|
||||
start-spacer: " "
|
||||
start-spacer: ""
|
||||
middle-spacer: " "
|
||||
end-spacer: " "
|
||||
end-spacer: ""
|
||||
|
||||
|
||||
|
||||
@@ -627,19 +627,8 @@ commands-allow-op: true
|
||||
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
# | Vault integration settings | #
|
||||
# | | #
|
||||
# | Disabled by default (vault-enabled: false). The remaining vault-* settings below only take | #
|
||||
# | effect when vault-enabled is set to true. | #
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
|
||||
# If the Vault API bridge should be registered.
|
||||
#
|
||||
# - When false (default), LuckPerms will not hook into Vault at all. Vault-dependent plugins will
|
||||
# fall back to SuperPerms and will not see LuckPerms groups, prefixes, or meta.
|
||||
# - When true, LuckPerms will register Vault permission and chat providers if the Vault plugin is
|
||||
# installed. Required for any plugin that reads groups/prefix/suffix via the Vault API.
|
||||
vault-enabled: false
|
||||
|
||||
# If Vault lookups for offline players on the main server thread should be enabled.
|
||||
#
|
||||
# LuckPerms has a "catch" for plugins attempting to perform unsafe offline player data lookups
|
||||
@@ -728,35 +717,5 @@ update-client-command-list: true
|
||||
register-command-list-data: true
|
||||
|
||||
# If LuckPerms should attempt to resolve Vanilla command target selectors for LP commands.
|
||||
# See here for more info: https://minecraft.wiki/w/Target_selectors
|
||||
# See here for more info: https://minecraft.gamepedia.com/Commands#Target_selectors
|
||||
resolve-command-selectors: false
|
||||
|
||||
# If the plugin should run in "read-only" mode for commands.
|
||||
#
|
||||
# In this mode, players or the console will only be able to execute commands that read or view
|
||||
# data, and will not be able to execute any LP commands that modify data.
|
||||
#
|
||||
# If enabling read-only mode for just players, be aware that some other plugins may allow players
|
||||
# to execute commands as the console, allowing them to run LP commands indirectly.
|
||||
#
|
||||
# Note: This does not affect interactions with LuckPerms via the API.
|
||||
commands-read-only-mode:
|
||||
players: true
|
||||
console: false
|
||||
|
||||
# If LuckPerms commands should be disabled. When true, this will prevent all LP commands from being
|
||||
# executed. In a sense this is a more extreme version of read-only mode (see above).
|
||||
#
|
||||
# LuckPerms will still act as the permission manager, but server administrators will be unable to
|
||||
# make changes via commands.
|
||||
#
|
||||
# If disabling commands just for players, be aware that some other plugins may allow players to
|
||||
# execute commands as the console, allowing them to run commands indirectly.
|
||||
#
|
||||
# If commands are disabled for both players and the console, LuckPerms will not attempt to register
|
||||
# a command with the server at all & in a sense will be invisible to both players and admins.
|
||||
#
|
||||
# Note: This does not affect interactions with LuckPerms via the API.
|
||||
disable-luckperms-commands:
|
||||
players: true
|
||||
console: false
|
||||
@@ -0,0 +1,47 @@
|
||||
plugins {
|
||||
alias(libs.plugins.shadow)
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation project(':common')
|
||||
compileOnly project(':common:loader-utils')
|
||||
|
||||
compileOnly 'net.md-5:bungeecord-api:1.16-R0.4'
|
||||
compileOnly('net.kyori:adventure-platform-bungeecord:4.1.0') {
|
||||
exclude(module: 'adventure-bom')
|
||||
exclude(module: 'adventure-api')
|
||||
exclude(module: 'adventure-nbt')
|
||||
}
|
||||
compileOnly 'com.imaginarycode.minecraft:RedisBungee:0.4'
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
archiveFileName = 'luckperms-bungee.jarinjar'
|
||||
|
||||
dependencies {
|
||||
include(dependency('me.lucko.luckperms:.*'))
|
||||
}
|
||||
|
||||
relocate 'net.kyori.adventure', 'me.lucko.luckperms.lib.adventure'
|
||||
relocate 'net.kyori.event', 'me.lucko.luckperms.lib.eventbus'
|
||||
relocate 'com.github.benmanes.caffeine', 'me.lucko.luckperms.lib.caffeine'
|
||||
relocate 'okio', 'me.lucko.luckperms.lib.okio'
|
||||
relocate 'okhttp3', 'me.lucko.luckperms.lib.okhttp3'
|
||||
relocate 'net.bytebuddy', 'me.lucko.luckperms.lib.bytebuddy'
|
||||
relocate 'me.lucko.commodore', 'me.lucko.luckperms.lib.commodore'
|
||||
relocate 'org.mariadb.jdbc', 'me.lucko.luckperms.lib.mariadb'
|
||||
relocate 'com.mysql', 'me.lucko.luckperms.lib.mysql'
|
||||
relocate 'org.postgresql', 'me.lucko.luckperms.lib.postgresql'
|
||||
relocate 'com.zaxxer.hikari', 'me.lucko.luckperms.lib.hikari'
|
||||
relocate 'com.mongodb', 'me.lucko.luckperms.lib.mongodb'
|
||||
relocate 'org.bson', 'me.lucko.luckperms.lib.bson'
|
||||
relocate 'redis.clients.jedis', 'me.lucko.luckperms.lib.jedis'
|
||||
relocate 'io.nats.client', 'me.lucko.luckperms.lib.nats'
|
||||
relocate 'com.rabbitmq', 'me.lucko.luckperms.lib.rabbitmq'
|
||||
relocate 'org.apache.commons.pool2', 'me.lucko.luckperms.lib.commonspool2'
|
||||
relocate 'ninja.leaping.configurate', 'me.lucko.luckperms.lib.configurate'
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives shadowJar
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
plugins {
|
||||
alias(libs.plugins.shadow)
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly 'net.md-5:bungeecord-api:1.15-SNAPSHOT'
|
||||
|
||||
implementation project(':api')
|
||||
implementation project(':common:loader-utils')
|
||||
}
|
||||
|
||||
processResources {
|
||||
filesMatching('plugin.yml') {
|
||||
expand 'pluginVersion': project.ext.fullVersion
|
||||
}
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
archiveFileName = "LuckPerms-Bungee-${project.ext.fullVersion}.jar"
|
||||
|
||||
from {
|
||||
project(':bungee').tasks.shadowJar.archiveFile
|
||||
}
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives shadowJar
|
||||
}
|
||||
@@ -302,7 +302,7 @@ public class LPBungeeBootstrap implements LuckPermsBootstrap, LoaderBootstrap, B
|
||||
try {
|
||||
Class.forName("com.google.gson.internal.bind.TreeTypeAdapter");
|
||||
return false;
|
||||
} catch (Exception e) {
|
||||
} catch (ClassNotFoundException e) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,13 +25,25 @@
|
||||
|
||||
package me.lucko.luckperms.bungee.context;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||
import me.lucko.luckperms.bungee.LPBungeePlugin;
|
||||
import me.lucko.luckperms.common.context.manager.SimpleContextManager;
|
||||
import me.lucko.luckperms.common.context.manager.ContextManager;
|
||||
import me.lucko.luckperms.common.context.manager.InlineQueryOptionsSupplier;
|
||||
import me.lucko.luckperms.common.context.manager.QueryOptionsSupplier;
|
||||
import me.lucko.luckperms.common.util.CaffeineFactory;
|
||||
import net.luckperms.api.context.ImmutableContextSet;
|
||||
import net.luckperms.api.query.QueryOptions;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class BungeeContextManager extends ContextManager<ProxiedPlayer, ProxiedPlayer> {
|
||||
|
||||
private final LoadingCache<ProxiedPlayer, QueryOptions> contextsCache = CaffeineFactory.newBuilder()
|
||||
.expireAfterWrite(50, TimeUnit.MILLISECONDS)
|
||||
.build(this::calculate);
|
||||
|
||||
public class BungeeContextManager extends SimpleContextManager<ProxiedPlayer, ProxiedPlayer> {
|
||||
public BungeeContextManager(LPBungeePlugin plugin) {
|
||||
super(plugin, ProxiedPlayer.class, ProxiedPlayer.class);
|
||||
}
|
||||
@@ -40,4 +52,35 @@ public class BungeeContextManager extends SimpleContextManager<ProxiedPlayer, Pr
|
||||
public UUID getUniqueId(ProxiedPlayer player) {
|
||||
return player.getUniqueId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryOptionsSupplier getCacheFor(ProxiedPlayer subject) {
|
||||
if (subject == null) {
|
||||
throw new NullPointerException("subject");
|
||||
}
|
||||
|
||||
return new InlineQueryOptionsSupplier<>(subject, this.contextsCache);
|
||||
}
|
||||
|
||||
// override getContext, getQueryOptions and invalidateCache to skip the QueryOptionsSupplier
|
||||
@Override
|
||||
public ImmutableContextSet getContext(ProxiedPlayer subject) {
|
||||
return getQueryOptions(subject).context();
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryOptions getQueryOptions(ProxiedPlayer subject) {
|
||||
return this.contextsCache.get(subject);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void invalidateCache(ProxiedPlayer subject) {
|
||||
this.contextsCache.invalidate(subject);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryOptions formQueryOptions(ProxiedPlayer subject, ImmutableContextSet contextSet) {
|
||||
return formQueryOptions(contextSet);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -611,33 +611,3 @@ disable-bulkupdate: false
|
||||
#
|
||||
# - When this happens, the plugin will set their primary group back to default.
|
||||
prevent-primary-group-removal: false
|
||||
|
||||
# If the plugin should run in "read-only" mode for commands.
|
||||
#
|
||||
# In this mode, players or the console will only be able to execute commands that read or view
|
||||
# data, and will not be able to execute any LP commands that modify data.
|
||||
#
|
||||
# If enabling read-only mode for just players, be aware that some other plugins may allow players
|
||||
# to execute commands as the console, allowing them to run LP commands indirectly.
|
||||
#
|
||||
# Note: This does not affect interactions with LuckPerms via the API.
|
||||
commands-read-only-mode:
|
||||
players: false
|
||||
console: false
|
||||
|
||||
# If LuckPerms commands should be disabled. When true, this will prevent all LP commands from being
|
||||
# executed. In a sense this is a more extreme version of read-only mode (see above).
|
||||
#
|
||||
# LuckPerms will still act as the permission manager, but server administrators will be unable to
|
||||
# make changes via commands.
|
||||
#
|
||||
# If disabling commands just for players, be aware that some other plugins may allow players to
|
||||
# execute commands as the console, allowing them to run commands indirectly.
|
||||
#
|
||||
# If commands are disabled for both players and the console, LuckPerms will not attempt to register
|
||||
# a command with the server at all & in a sense will be invisible to both players and admins.
|
||||
#
|
||||
# Note: This does not affect interactions with LuckPerms via the API.
|
||||
disable-luckperms-commands:
|
||||
players: false
|
||||
console: false
|
||||
@@ -0,0 +1,93 @@
|
||||
plugins {
|
||||
id("java-library")
|
||||
id("jacoco")
|
||||
}
|
||||
|
||||
test {
|
||||
useJUnitPlatform {}
|
||||
}
|
||||
|
||||
jacocoTestReport {
|
||||
dependsOn test
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.1'
|
||||
testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.9.1'
|
||||
testImplementation 'org.junit.jupiter:junit-jupiter-params:5.9.1'
|
||||
testImplementation 'org.mockito:mockito-core:4.11.0'
|
||||
testImplementation 'org.mockito:mockito-junit-jupiter:4.11.0'
|
||||
testImplementation 'com.h2database:h2:2.1.214'
|
||||
|
||||
api project(':api')
|
||||
api 'org.checkerframework:checker-qual:3.12.0'
|
||||
|
||||
compileOnly project(':common:loader-utils')
|
||||
|
||||
compileOnly 'com.mojang:brigadier:1.0.18'
|
||||
compileOnly 'org.slf4j:slf4j-api:1.7.30'
|
||||
compileOnly 'org.apache.logging.log4j:log4j-api:2.14.0'
|
||||
|
||||
api('net.kyori:adventure-api:4.11.0') {
|
||||
exclude(module: 'adventure-bom')
|
||||
exclude(module: 'checker-qual')
|
||||
exclude(module: 'annotations')
|
||||
}
|
||||
|
||||
api('net.kyori:adventure-text-serializer-gson:4.11.0') {
|
||||
exclude(module: 'adventure-bom')
|
||||
exclude(module: 'adventure-api')
|
||||
exclude(module: 'gson')
|
||||
}
|
||||
|
||||
api('net.kyori:adventure-text-serializer-legacy:4.11.0') {
|
||||
exclude(module: 'adventure-bom')
|
||||
exclude(module: 'adventure-api')
|
||||
}
|
||||
|
||||
api('net.kyori:adventure-text-serializer-plain:4.11.0') {
|
||||
exclude(module: 'adventure-bom')
|
||||
exclude(module: 'adventure-api')
|
||||
}
|
||||
|
||||
api("net.kyori:adventure-text-minimessage:4.11.0") {
|
||||
exclude(module: 'adventure-bom')
|
||||
exclude(module: 'adventure-api')
|
||||
}
|
||||
|
||||
api('net.kyori:event-api:3.0.0') {
|
||||
exclude(module: 'checker-qual')
|
||||
exclude(module: 'guava')
|
||||
}
|
||||
|
||||
api 'com.google.code.gson:gson:2.7'
|
||||
api 'com.google.guava:guava:19.0'
|
||||
|
||||
api 'com.github.ben-manes.caffeine:caffeine:2.9.0'
|
||||
api 'com.squareup.okhttp3:okhttp:3.14.9'
|
||||
api 'com.squareup.okio:okio:1.17.5'
|
||||
api 'net.bytebuddy:byte-buddy:1.10.22'
|
||||
|
||||
api('org.spongepowered:configurate-core:3.7.2') {
|
||||
transitive = false
|
||||
}
|
||||
api('org.spongepowered:configurate-yaml:3.7.2') {
|
||||
transitive = false
|
||||
}
|
||||
api('org.spongepowered:configurate-gson:3.7.2') {
|
||||
transitive = false
|
||||
}
|
||||
api('org.spongepowered:configurate-hocon:3.7.2') {
|
||||
transitive = false
|
||||
}
|
||||
api('me.lucko.configurate:configurate-toml:3.7') {
|
||||
transitive = false
|
||||
}
|
||||
compileOnly 'com.zaxxer:HikariCP:4.0.3'
|
||||
compileOnly 'redis.clients:jedis:4.4.3'
|
||||
compileOnly 'io.nats:jnats:2.16.4'
|
||||
compileOnly 'com.rabbitmq:amqp-client:5.12.0'
|
||||
compileOnly 'org.mongodb:mongodb-driver-legacy:4.5.0'
|
||||
compileOnly 'org.postgresql:postgresql:42.6.0'
|
||||
compileOnly 'org.yaml:snakeyaml:1.28'
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
// nothing special to do here (yet)!
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.actionlog;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSortedSet;
|
||||
import me.lucko.luckperms.common.util.ImmutableCollectors;
|
||||
import net.luckperms.api.actionlog.Action;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.SortedSet;
|
||||
import java.util.UUID;
|
||||
|
||||
public class Log {
|
||||
private static final Log EMPTY = new Log(ImmutableList.of());
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public static Log empty() {
|
||||
return EMPTY;
|
||||
}
|
||||
|
||||
private final SortedSet<LoggedAction> content;
|
||||
|
||||
Log(List<LoggedAction> content) {
|
||||
this.content = ImmutableSortedSet.copyOf(content);
|
||||
}
|
||||
|
||||
public SortedSet<LoggedAction> getContent() {
|
||||
return this.content;
|
||||
}
|
||||
|
||||
public SortedSet<LoggedAction> getContent(UUID actor) {
|
||||
return this.content.stream()
|
||||
.filter(e -> e.getSource().getUniqueId().equals(actor))
|
||||
.collect(ImmutableCollectors.toSortedSet());
|
||||
}
|
||||
|
||||
public SortedSet<LoggedAction> getUserHistory(UUID uniqueId) {
|
||||
return this.content.stream()
|
||||
.filter(e -> e.getTarget().getType() == Action.Target.Type.USER)
|
||||
.filter(e -> e.getTarget().getUniqueId().isPresent() && e.getTarget().getUniqueId().get().equals(uniqueId))
|
||||
.collect(ImmutableCollectors.toSortedSet());
|
||||
}
|
||||
|
||||
public SortedSet<LoggedAction> getGroupHistory(String name) {
|
||||
return this.content.stream()
|
||||
.filter(e -> e.getTarget().getType() == Action.Target.Type.GROUP)
|
||||
.filter(e -> e.getTarget().getName().equals(name))
|
||||
.collect(ImmutableCollectors.toSortedSet());
|
||||
}
|
||||
|
||||
public SortedSet<LoggedAction> getTrackHistory(String name) {
|
||||
return this.content.stream()
|
||||
.filter(e -> e.getTarget().getType() == Action.Target.Type.TRACK)
|
||||
.filter(e -> e.getTarget().getName().equals(name))
|
||||
.collect(ImmutableCollectors.toSortedSet());
|
||||
}
|
||||
|
||||
public SortedSet<LoggedAction> getSearch(String query) {
|
||||
return this.content.stream()
|
||||
.filter(e -> e.matchesSearch(query))
|
||||
.collect(ImmutableCollectors.toSortedSet());
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private final List<LoggedAction> content = new ArrayList<>();
|
||||
|
||||
public Builder add(LoggedAction e) {
|
||||
this.content.add(e);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Log build() {
|
||||
if (this.content.isEmpty()) {
|
||||
return EMPTY;
|
||||
}
|
||||
return new Log(this.content);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -29,14 +29,12 @@ import me.lucko.luckperms.common.command.access.CommandPermission;
|
||||
import me.lucko.luckperms.common.commands.log.LogNotify;
|
||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||
import me.lucko.luckperms.common.locale.Message;
|
||||
import me.lucko.luckperms.common.messaging.InternalMessagingService;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import net.luckperms.api.event.log.LogBroadcastEvent;
|
||||
import net.luckperms.api.event.log.LogNotifyEvent;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class LogDispatcher {
|
||||
@@ -66,12 +64,7 @@ public class LogDispatcher {
|
||||
return !this.plugin.getEventDispatcher().dispatchLogBroadcast(cancelled, entry, origin);
|
||||
}
|
||||
|
||||
// broadcast the entry to online players
|
||||
private void broadcast(LoggedAction entry, LogBroadcastEvent.Origin broadcastOrigin, LogNotifyEvent.Origin origin, Sender sender) {
|
||||
if (!shouldBroadcast(entry, broadcastOrigin)) {
|
||||
return;
|
||||
}
|
||||
|
||||
private void broadcast(LoggedAction entry, LogNotifyEvent.Origin origin, Sender sender) {
|
||||
this.plugin.getOnlineSenders()
|
||||
.filter(CommandPermission.LOG_NOTIFY::isAuthorized)
|
||||
.filter(s -> {
|
||||
@@ -81,46 +74,41 @@ public class LogDispatcher {
|
||||
.forEach(s -> Message.LOG.send(s, entry));
|
||||
}
|
||||
|
||||
// log the entry to storage
|
||||
public CompletableFuture<Void> logToStorage(LoggedAction entry) {
|
||||
public void dispatch(LoggedAction entry, Sender sender) {
|
||||
if (!this.plugin.getEventDispatcher().dispatchLogPublish(false, entry)) {
|
||||
return this.plugin.getStorage().logAction(entry);
|
||||
} else {
|
||||
return CompletableFuture.completedFuture(null);
|
||||
this.plugin.getStorage().logAction(entry);
|
||||
}
|
||||
}
|
||||
|
||||
// log the entry to messaging
|
||||
public CompletableFuture<Void> logToMessaging(LoggedAction entry) {
|
||||
InternalMessagingService messagingService = this.plugin.getMessagingService().orElse(null);
|
||||
if (messagingService != null) {
|
||||
return messagingService.pushLog(entry);
|
||||
} else {
|
||||
return CompletableFuture.completedFuture(null);
|
||||
this.plugin.getMessagingService().ifPresent(service -> service.pushLog(entry));
|
||||
|
||||
if (shouldBroadcast(entry, LogBroadcastEvent.Origin.LOCAL)) {
|
||||
broadcast(entry, LogNotifyEvent.Origin.LOCAL, sender);
|
||||
}
|
||||
}
|
||||
|
||||
// log the entry to storage and messaging, and broadcast it to online players
|
||||
private CompletableFuture<Void> dispatch(LoggedAction entry, Sender sender, LogBroadcastEvent.Origin broadcastOrigin, LogNotifyEvent.Origin origin) {
|
||||
CompletableFuture<Void> storageFuture = logToStorage(entry);
|
||||
CompletableFuture<Void> messagingFuture = logToMessaging(entry);
|
||||
broadcast(entry, broadcastOrigin, origin, sender);
|
||||
return CompletableFuture.allOf(storageFuture, messagingFuture);
|
||||
}
|
||||
|
||||
public CompletableFuture<Void> dispatch(LoggedAction entry, Sender sender) {
|
||||
return dispatch(entry, sender, LogBroadcastEvent.Origin.LOCAL, LogNotifyEvent.Origin.LOCAL);
|
||||
}
|
||||
|
||||
public CompletableFuture<Void> dispatchFromApi(LoggedAction entry) {
|
||||
return dispatch(entry, null, LogBroadcastEvent.Origin.LOCAL_API, LogNotifyEvent.Origin.LOCAL_API);
|
||||
}
|
||||
|
||||
public void broadcastFromApi(LoggedAction entry) {
|
||||
broadcast(entry, LogBroadcastEvent.Origin.LOCAL_API, LogNotifyEvent.Origin.LOCAL_API, null);
|
||||
this.plugin.getMessagingService().ifPresent(extendedMessagingService -> extendedMessagingService.pushLog(entry));
|
||||
|
||||
if (shouldBroadcast(entry, LogBroadcastEvent.Origin.LOCAL_API)) {
|
||||
broadcast(entry, LogNotifyEvent.Origin.LOCAL_API, null);
|
||||
}
|
||||
}
|
||||
|
||||
public void broadcastFromRemote(LoggedAction entry) {
|
||||
broadcast(entry, LogBroadcastEvent.Origin.REMOTE, LogNotifyEvent.Origin.REMOTE, null);
|
||||
public void dispatchFromApi(LoggedAction entry) {
|
||||
if (!this.plugin.getEventDispatcher().dispatchLogPublish(false, entry)) {
|
||||
try {
|
||||
this.plugin.getStorage().logAction(entry).get();
|
||||
} catch (Exception e) {
|
||||
this.plugin.getLogger().warn("Error whilst storing action", e);
|
||||
}
|
||||
}
|
||||
|
||||
broadcastFromApi(entry);
|
||||
}
|
||||
|
||||
public void dispatchFromRemote(LoggedAction entry) {
|
||||
if (shouldBroadcast(entry, LogBroadcastEvent.Origin.REMOTE)) {
|
||||
broadcast(entry, LogNotifyEvent.Origin.REMOTE, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,6 @@
|
||||
package me.lucko.luckperms.common.actionlog;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||
import me.lucko.luckperms.common.model.Group;
|
||||
import me.lucko.luckperms.common.model.HolderType;
|
||||
import me.lucko.luckperms.common.model.PermissionHolder;
|
||||
@@ -45,10 +44,10 @@ import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/**
|
||||
* An implementation of {@link Action} and {@link Action.Builder},
|
||||
@@ -124,11 +123,15 @@ public class LoggedAction implements Action {
|
||||
return ActionComparator.INSTANCE.compare(this, other);
|
||||
}
|
||||
|
||||
public boolean matchesSearch(String query) {
|
||||
query = Objects.requireNonNull(query, "query").toLowerCase(Locale.ROOT);
|
||||
return this.source.name.toLowerCase(Locale.ROOT).contains(query) ||
|
||||
this.target.name.toLowerCase(Locale.ROOT).contains(query) ||
|
||||
this.description.toLowerCase(Locale.ROOT).contains(query);
|
||||
}
|
||||
|
||||
public void submit(LuckPermsPlugin plugin, Sender sender) {
|
||||
CompletableFuture<Void> future = plugin.getLogDispatcher().dispatch(this, sender);
|
||||
if (plugin.getConfiguration().get(ConfigKeys.LOG_SYNCHRONOUSLY_IN_COMMANDS)) {
|
||||
future.join();
|
||||
}
|
||||
plugin.getLogDispatcher().dispatch(this, sender);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -390,14 +393,14 @@ public class LoggedAction implements Action {
|
||||
}
|
||||
}
|
||||
|
||||
public static String getTypeString(Target.Type type) {
|
||||
public static char getTypeCharacter(Target.Type type) {
|
||||
switch (type) {
|
||||
case USER:
|
||||
return "U";
|
||||
return 'U';
|
||||
case GROUP:
|
||||
return "G";
|
||||
return 'G';
|
||||
case TRACK:
|
||||
return "T";
|
||||
return 'T';
|
||||
default:
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.actionlog.filter;
|
||||
|
||||
import me.lucko.luckperms.common.filter.FilterField;
|
||||
import net.luckperms.api.actionlog.Action;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public final class ActionFields {
|
||||
|
||||
public static final FilterField<Action, UUID> SOURCE_UNIQUE_ID = FilterField.named(
|
||||
"SOURCE_UNIQUE_ID",
|
||||
action -> action.getSource().getUniqueId()
|
||||
);
|
||||
public static final FilterField<Action, String> SOURCE_NAME = FilterField.named(
|
||||
"SOURCE_NAME",
|
||||
action -> action.getSource().getName()
|
||||
);
|
||||
public static final FilterField<Action, Action.Target.Type> TARGET_TYPE = FilterField.named(
|
||||
"TARGET_TYPE",
|
||||
action -> action.getTarget().getType()
|
||||
);
|
||||
public static final FilterField<Action, UUID> TARGET_UNIQUE_ID = FilterField.named(
|
||||
"TARGET_UNIQUE_ID",
|
||||
action -> action.getTarget().getUniqueId().orElse(null)
|
||||
);
|
||||
public static final FilterField<Action, String> TARGET_NAME = FilterField.named(
|
||||
"TARGET_NAME",
|
||||
action -> action.getTarget().getName()
|
||||
);
|
||||
public static final FilterField<Action, String> DESCRIPTION = FilterField.named(
|
||||
"DESCRIPTION",
|
||||
action -> action.getDescription()
|
||||
);
|
||||
|
||||
}
|
||||
-70
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.actionlog.filter;
|
||||
|
||||
import me.lucko.luckperms.common.filter.FilterField;
|
||||
import me.lucko.luckperms.common.filter.mongo.FilterMongoBuilder;
|
||||
import net.luckperms.api.actionlog.Action;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public final class ActionFilterMongoBuilder extends FilterMongoBuilder<Action> {
|
||||
public static final ActionFilterMongoBuilder INSTANCE = new ActionFilterMongoBuilder();
|
||||
|
||||
private ActionFilterMongoBuilder() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String mapFieldName(FilterField<Action, ?> field) {
|
||||
if (field == ActionFields.SOURCE_UNIQUE_ID) {
|
||||
return "source.uniqueId";
|
||||
} else if (field == ActionFields.SOURCE_NAME) {
|
||||
return "source.name";
|
||||
} else if (field == ActionFields.TARGET_TYPE) {
|
||||
return "target.type";
|
||||
} else if (field == ActionFields.TARGET_UNIQUE_ID) {
|
||||
return "target.uniqueId";
|
||||
} else if (field == ActionFields.TARGET_NAME) {
|
||||
return "target.name";
|
||||
} else if (field == ActionFields.DESCRIPTION) {
|
||||
return "description";
|
||||
}
|
||||
throw new AssertionError(field);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object mapConstraintValue(Object value) {
|
||||
if (value instanceof String | value instanceof UUID) {
|
||||
return value;
|
||||
} else if (value instanceof Action.Target.Type) {
|
||||
return ((Action.Target.Type) value).name();
|
||||
} else {
|
||||
throw new IllegalArgumentException("Don't know how to map value with type: " + value.getClass().getName());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-69
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.actionlog.filter;
|
||||
|
||||
import me.lucko.luckperms.common.actionlog.LoggedAction;
|
||||
import me.lucko.luckperms.common.filter.FilterField;
|
||||
import me.lucko.luckperms.common.filter.sql.FilterSqlBuilder;
|
||||
import net.luckperms.api.actionlog.Action;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class ActionFilterSqlBuilder extends FilterSqlBuilder<Action> {
|
||||
|
||||
@Override
|
||||
public void visitFieldName(FilterField<Action, ?> field) {
|
||||
if (field == ActionFields.SOURCE_UNIQUE_ID) {
|
||||
this.builder.append("actor_uuid");
|
||||
} else if (field == ActionFields.SOURCE_NAME) {
|
||||
this.builder.append("actor_name");
|
||||
} else if (field == ActionFields.TARGET_TYPE) {
|
||||
this.builder.append("type");
|
||||
} else if (field == ActionFields.TARGET_UNIQUE_ID) {
|
||||
this.builder.append("acted_uuid");
|
||||
} else if (field == ActionFields.TARGET_NAME) {
|
||||
this.builder.append("acted_name");
|
||||
} else if (field == ActionFields.DESCRIPTION) {
|
||||
this.builder.append("action");
|
||||
} else {
|
||||
throw new AssertionError(field);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConstraintValue(Object value) {
|
||||
if (value instanceof String) {
|
||||
this.builder.variable(((String) value));
|
||||
} else if (value instanceof UUID) {
|
||||
this.builder.variable(value.toString());
|
||||
} else if (value instanceof Action.Target.Type) {
|
||||
this.builder.variable(LoggedAction.getTypeString((Action.Target.Type) value));
|
||||
} else {
|
||||
throw new IllegalArgumentException("Don't know how to write value with type: " + value.getClass().getName());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.actionlog.filter;
|
||||
|
||||
import me.lucko.luckperms.common.filter.Comparison;
|
||||
import me.lucko.luckperms.common.filter.ConstraintFactory;
|
||||
import me.lucko.luckperms.common.filter.FilterList;
|
||||
import net.luckperms.api.actionlog.Action;
|
||||
import net.luckperms.api.actionlog.Action.Target;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public final class ActionFilters {
|
||||
private ActionFilters() {}
|
||||
|
||||
// all actions
|
||||
public static FilterList<Action> all() {
|
||||
return FilterList.empty();
|
||||
}
|
||||
|
||||
// all actions performed by a given source (actor)
|
||||
public static FilterList<Action> source(UUID uniqueId) {
|
||||
return FilterList.and(
|
||||
ActionFields.SOURCE_UNIQUE_ID.isEqualTo(uniqueId, ConstraintFactory.UUIDS)
|
||||
);
|
||||
}
|
||||
|
||||
// all actions affecting a given user
|
||||
public static FilterList<Action> user(UUID uniqueId) {
|
||||
return FilterList.and(
|
||||
ActionFields.TARGET_TYPE.isEqualTo(Target.Type.USER, TARGET_TYPE_CONSTRAINT_FACTORY),
|
||||
ActionFields.TARGET_UNIQUE_ID.isEqualTo(uniqueId, ConstraintFactory.UUIDS)
|
||||
);
|
||||
}
|
||||
|
||||
// all actions affecting a given group
|
||||
public static FilterList<Action> group(String name) {
|
||||
return FilterList.and(
|
||||
ActionFields.TARGET_TYPE.isEqualTo(Target.Type.GROUP, TARGET_TYPE_CONSTRAINT_FACTORY),
|
||||
ActionFields.TARGET_NAME.isEqualTo(name, ConstraintFactory.STRINGS)
|
||||
);
|
||||
}
|
||||
|
||||
// all actions affecting a given track
|
||||
public static FilterList<Action> track(String name) {
|
||||
return FilterList.and(
|
||||
ActionFields.TARGET_TYPE.isEqualTo(Target.Type.TRACK, TARGET_TYPE_CONSTRAINT_FACTORY),
|
||||
ActionFields.TARGET_NAME.isEqualTo(name, ConstraintFactory.STRINGS)
|
||||
);
|
||||
}
|
||||
|
||||
// all actions matching the given search query
|
||||
public static FilterList<Action> search(String query) {
|
||||
return FilterList.or(
|
||||
ActionFields.SOURCE_NAME.isSimilarTo("%" + query + "%", ConstraintFactory.STRINGS),
|
||||
ActionFields.TARGET_NAME.isSimilarTo("%" + query + "%", ConstraintFactory.STRINGS),
|
||||
ActionFields.DESCRIPTION.isSimilarTo("%" + query + "%", ConstraintFactory.STRINGS)
|
||||
);
|
||||
}
|
||||
|
||||
private static final ConstraintFactory<Target.Type> TARGET_TYPE_CONSTRAINT_FACTORY = new ConstraintFactory<Target.Type>() {
|
||||
@Override
|
||||
public Predicate<Target.Type> equal(Target.Type value) {
|
||||
return value::equals;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Predicate<Target.Type> notEqual(Target.Type value) {
|
||||
return string -> !value.equals(string);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Predicate<Target.Type> similar(Target.Type value) {
|
||||
Pattern pattern = Comparison.compilePatternForLikeSyntax(value.toString());
|
||||
return type -> pattern.matcher(type.toString()).matches();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Predicate<Target.Type> notSimilar(Target.Type value) {
|
||||
Pattern pattern = Comparison.compilePatternForLikeSyntax(value.toString());
|
||||
return type -> !pattern.matcher(type.toString()).matches();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -25,7 +25,6 @@
|
||||
|
||||
package me.lucko.luckperms.common.api;
|
||||
|
||||
import me.lucko.luckperms.common.api.implementation.ApiActionFilterFactory;
|
||||
import me.lucko.luckperms.common.api.implementation.ApiActionLogger;
|
||||
import me.lucko.luckperms.common.api.implementation.ApiContextManager;
|
||||
import me.lucko.luckperms.common.api.implementation.ApiGroupManager;
|
||||
@@ -48,7 +47,6 @@ import me.lucko.luckperms.common.plugin.logging.PluginLogger;
|
||||
import net.luckperms.api.LuckPerms;
|
||||
import net.luckperms.api.LuckPermsProvider;
|
||||
import net.luckperms.api.actionlog.ActionLogger;
|
||||
import net.luckperms.api.actionlog.filter.ActionFilterFactory;
|
||||
import net.luckperms.api.context.ContextManager;
|
||||
import net.luckperms.api.messaging.MessagingService;
|
||||
import net.luckperms.api.messenger.MessengerProvider;
|
||||
@@ -57,7 +55,6 @@ import net.luckperms.api.model.group.GroupManager;
|
||||
import net.luckperms.api.model.user.UserManager;
|
||||
import net.luckperms.api.node.NodeBuilderRegistry;
|
||||
import net.luckperms.api.node.matcher.NodeMatcherFactory;
|
||||
import net.luckperms.api.platform.Health;
|
||||
import net.luckperms.api.platform.Platform;
|
||||
import net.luckperms.api.platform.PlayerAdapter;
|
||||
import net.luckperms.api.platform.PluginMetadata;
|
||||
@@ -175,11 +172,6 @@ public class LuckPermsApiProvider implements LuckPerms {
|
||||
return this.plugin.getSyncTaskBuffer().request();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull Health runHealthCheck() {
|
||||
return this.plugin.runHealthCheck();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull AbstractEventBus<?> getEventBus() {
|
||||
return this.plugin.getEventDispatcher().getEventBus();
|
||||
@@ -227,8 +219,4 @@ public class LuckPermsApiProvider implements LuckPerms {
|
||||
return ApiNodeMatcherFactory.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull ActionFilterFactory getActionFilterFactory() {
|
||||
return ApiActionFilterFactory.INSTANCE;
|
||||
}
|
||||
}
|
||||
-47
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.api.implementation;
|
||||
|
||||
import me.lucko.luckperms.common.filter.FilterList;
|
||||
import net.luckperms.api.actionlog.Action;
|
||||
import net.luckperms.api.actionlog.filter.ActionFilter;
|
||||
|
||||
public class ApiActionFilter implements ActionFilter {
|
||||
private final FilterList<Action> filter;
|
||||
|
||||
public ApiActionFilter(FilterList<Action> filter) {
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(Action action) {
|
||||
return this.filter.evaluate(action);
|
||||
}
|
||||
|
||||
public FilterList<Action> getFilter() {
|
||||
return this.filter;
|
||||
}
|
||||
}
|
||||
-77
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.api.implementation;
|
||||
|
||||
import me.lucko.luckperms.common.actionlog.filter.ActionFilters;
|
||||
import net.luckperms.api.actionlog.filter.ActionFilter;
|
||||
import net.luckperms.api.actionlog.filter.ActionFilterFactory;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
public final class ApiActionFilterFactory implements ActionFilterFactory {
|
||||
public static final ApiActionFilterFactory INSTANCE = new ApiActionFilterFactory();
|
||||
|
||||
private ApiActionFilterFactory() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionFilter any() {
|
||||
return new ApiActionFilter(ActionFilters.all());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionFilter source(UUID uniqueId) {
|
||||
Objects.requireNonNull(uniqueId, "uniqueId");
|
||||
return new ApiActionFilter(ActionFilters.source(uniqueId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionFilter user(UUID uniqueId) {
|
||||
Objects.requireNonNull(uniqueId, "uniqueId");
|
||||
return new ApiActionFilter(ActionFilters.user(uniqueId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionFilter group(String name) {
|
||||
Objects.requireNonNull(name, "name");
|
||||
return new ApiActionFilter(ActionFilters.group(name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionFilter track(String name) {
|
||||
Objects.requireNonNull(name, "name");
|
||||
return new ApiActionFilter(ActionFilters.track(name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionFilter search(String query) {
|
||||
Objects.requireNonNull(query, "query");
|
||||
return new ApiActionFilter(ActionFilters.search(query));
|
||||
}
|
||||
|
||||
}
|
||||
+11
-24
@@ -25,63 +25,50 @@
|
||||
|
||||
package me.lucko.luckperms.common.api.implementation;
|
||||
|
||||
import com.google.common.collect.ImmutableSortedSet;
|
||||
import me.lucko.luckperms.common.actionlog.LoggedAction;
|
||||
import me.lucko.luckperms.common.util.ImmutableCollectors;
|
||||
import me.lucko.luckperms.common.actionlog.Log;
|
||||
import me.lucko.luckperms.common.api.ApiUtils;
|
||||
import net.luckperms.api.actionlog.Action;
|
||||
import net.luckperms.api.actionlog.ActionLog;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.SortedSet;
|
||||
import java.util.UUID;
|
||||
|
||||
@Deprecated
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public class ApiActionLog implements ActionLog {
|
||||
private final SortedSet<Action> content;
|
||||
private final Log handle;
|
||||
|
||||
public ApiActionLog(List<LoggedAction> content) {
|
||||
this.content = ImmutableSortedSet.copyOf(content);
|
||||
public ApiActionLog(Log handle) {
|
||||
this.handle = handle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull SortedSet<Action> getContent() {
|
||||
return this.content;
|
||||
return (SortedSet) this.handle.getContent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull SortedSet<Action> getContent(@NonNull UUID actor) {
|
||||
Objects.requireNonNull(actor, "actor");
|
||||
return this.content.stream()
|
||||
.filter(e -> e.getSource().getUniqueId().equals(actor))
|
||||
.collect(ImmutableCollectors.toSortedSet());
|
||||
return (SortedSet) this.handle.getContent(actor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull SortedSet<Action> getUserHistory(@NonNull UUID uniqueId) {
|
||||
Objects.requireNonNull(uniqueId, "uuid");
|
||||
return this.content.stream()
|
||||
.filter(e -> e.getTarget().getType() == Action.Target.Type.USER)
|
||||
.filter(e -> e.getTarget().getUniqueId().isPresent() && e.getTarget().getUniqueId().get().equals(uniqueId))
|
||||
.collect(ImmutableCollectors.toSortedSet());
|
||||
return (SortedSet) this.handle.getUserHistory(uniqueId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull SortedSet<Action> getGroupHistory(@NonNull String name) {
|
||||
Objects.requireNonNull(name, "name");
|
||||
return this.content.stream()
|
||||
.filter(e -> e.getTarget().getType() == Action.Target.Type.GROUP)
|
||||
.filter(e -> e.getTarget().getName().equals(name))
|
||||
.collect(ImmutableCollectors.toSortedSet());
|
||||
return (SortedSet) this.handle.getGroupHistory(ApiUtils.checkName(name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull SortedSet<Action> getTrackHistory(@NonNull String name) {
|
||||
Objects.requireNonNull(name, "name");
|
||||
return this.content.stream()
|
||||
.filter(e -> e.getTarget().getType() == Action.Target.Type.TRACK)
|
||||
.filter(e -> e.getTarget().getName().equals(name))
|
||||
.collect(ImmutableCollectors.toSortedSet());
|
||||
return (SortedSet) this.handle.getTrackHistory(ApiUtils.checkName(name));
|
||||
}
|
||||
}
|
||||
+4
-57
@@ -25,22 +25,13 @@
|
||||
|
||||
package me.lucko.luckperms.common.api.implementation;
|
||||
|
||||
import me.lucko.luckperms.common.actionlog.LogDispatcher;
|
||||
import me.lucko.luckperms.common.actionlog.LogPage;
|
||||
import me.lucko.luckperms.common.actionlog.LoggedAction;
|
||||
import me.lucko.luckperms.common.actionlog.filter.ActionFilters;
|
||||
import me.lucko.luckperms.common.filter.FilterList;
|
||||
import me.lucko.luckperms.common.filter.PageParameters;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import net.luckperms.api.actionlog.Action;
|
||||
import net.luckperms.api.actionlog.ActionLog;
|
||||
import net.luckperms.api.actionlog.ActionLogger;
|
||||
import net.luckperms.api.actionlog.filter.ActionFilter;
|
||||
import net.luckperms.api.util.Page;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class ApiActionLogger implements ActionLogger {
|
||||
@@ -56,66 +47,22 @@ public class ApiActionLogger implements ActionLogger {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public @NonNull CompletableFuture<ActionLog> getLog() {
|
||||
return this.plugin.getStorage().getLogPage(ActionFilters.all(), null)
|
||||
.thenApply(result -> new ApiActionLog(result.getContent()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull CompletableFuture<List<Action>> queryActions(@NonNull ActionFilter filter) {
|
||||
return this.plugin.getStorage().getLogPage(getFilterList(filter), null).thenApply(ActionPage::new).thenApply(Page::entries);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull CompletableFuture<Page<Action>> queryActions(@NonNull ActionFilter filter, int pageSize, int pageNumber) {
|
||||
return this.plugin.getStorage().getLogPage(getFilterList(filter), new PageParameters(pageSize, pageNumber)).thenApply(ActionPage::new);
|
||||
return this.plugin.getStorage().getLog().thenApply(ApiActionLog::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull CompletableFuture<Void> submit(@NonNull Action entry) {
|
||||
return this.plugin.getLogDispatcher().dispatchFromApi((LoggedAction) entry);
|
||||
return CompletableFuture.runAsync(() -> this.plugin.getLogDispatcher().dispatchFromApi((LoggedAction) entry), this.plugin.getBootstrap().getScheduler().async());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull CompletableFuture<Void> submitToStorage(@NonNull Action entry) {
|
||||
return this.plugin.getLogDispatcher().logToStorage((LoggedAction) entry);
|
||||
return this.plugin.getStorage().logAction(entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull CompletableFuture<Void> broadcastAction(@NonNull Action entry) {
|
||||
LogDispatcher dispatcher = this.plugin.getLogDispatcher();
|
||||
|
||||
CompletableFuture<Void> messagingFuture = dispatcher.logToStorage(((LoggedAction) entry));
|
||||
dispatcher.broadcastFromApi(((LoggedAction) entry));
|
||||
return messagingFuture;
|
||||
}
|
||||
|
||||
private static FilterList<Action> getFilterList(ActionFilter filter) {
|
||||
Objects.requireNonNull(filter, "filter");
|
||||
if (filter instanceof ApiActionFilter) {
|
||||
return ((ApiActionFilter) filter).getFilter();
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unknown filter type: " + filter.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
private static final class ActionPage implements Page<Action> {
|
||||
private final LogPage page;
|
||||
|
||||
private ActionPage(LogPage page) {
|
||||
this.page = page;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
@Override
|
||||
public @NonNull List<Action> entries() {
|
||||
return (List) this.page.getContent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int overallSize() {
|
||||
return this.page.getTotalEntries();
|
||||
}
|
||||
return CompletableFuture.runAsync(() -> this.plugin.getLogDispatcher().broadcastFromApi((LoggedAction) entry), this.plugin.getBootstrap().getScheduler().async());
|
||||
}
|
||||
}
|
||||
-7
@@ -54,11 +54,4 @@ public class ApiMessagingService implements MessagingService {
|
||||
Objects.requireNonNull(user, "user");
|
||||
this.handle.pushUserUpdate(ApiUser.cast(user));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendCustomMessage(@NonNull String channelId, @NonNull String payload) {
|
||||
Objects.requireNonNull(channelId, "channelId");
|
||||
Objects.requireNonNull(payload, "payload");
|
||||
this.handle.pushCustomPayload(channelId, payload);
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -26,8 +26,8 @@
|
||||
package me.lucko.luckperms.common.api.implementation;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import me.lucko.luckperms.common.cacheddata.metastack.SimpleMetaStackDefinition;
|
||||
import me.lucko.luckperms.common.cacheddata.metastack.StandardStackElements;
|
||||
import me.lucko.luckperms.common.metastacking.SimpleMetaStackDefinition;
|
||||
import me.lucko.luckperms.common.metastacking.StandardStackElements;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import net.luckperms.api.metastacking.DuplicateRemovalFunction;
|
||||
import net.luckperms.api.metastacking.MetaStackDefinition;
|
||||
|
||||
-14
@@ -38,7 +38,6 @@ import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class ApiTrackManager extends ApiAbstractManager<Track, net.luckperms.api.track.Track, TrackManager<?>> implements net.luckperms.api.track.TrackManager {
|
||||
public ApiTrackManager(LuckPermsPlugin plugin, TrackManager<?> handle) {
|
||||
@@ -75,19 +74,6 @@ public class ApiTrackManager extends ApiAbstractManager<Track, net.luckperms.api
|
||||
return this.plugin.getStorage().deleteTrack(ApiTrack.cast(track), DeletionCause.API);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull CompletableFuture<Void> modifyTrack(@NonNull String name, @NonNull Consumer<? super net.luckperms.api.track.Track> action) {
|
||||
Objects.requireNonNull(name, "name");
|
||||
Objects.requireNonNull(action, "action");
|
||||
|
||||
return this.plugin.getStorage().createAndLoadTrack(name, CreationCause.API)
|
||||
.thenApplyAsync(track -> {
|
||||
action.accept(track.getApiProxy());
|
||||
return track;
|
||||
}, this.plugin.getBootstrap().getScheduler().async())
|
||||
.thenCompose(track -> this.plugin.getStorage().saveTrack(track));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull CompletableFuture<Void> loadAllTracks() {
|
||||
return this.plugin.getStorage().loadAllTracks();
|
||||
|
||||
@@ -25,13 +25,14 @@
|
||||
|
||||
package me.lucko.luckperms.common.bulkupdate;
|
||||
|
||||
import me.lucko.luckperms.common.bulkupdate.action.BulkUpdateAction;
|
||||
import me.lucko.luckperms.common.filter.FilterList;
|
||||
import me.lucko.luckperms.common.bulkupdate.action.Action;
|
||||
import me.lucko.luckperms.common.bulkupdate.query.Query;
|
||||
import me.lucko.luckperms.common.model.HolderType;
|
||||
import net.luckperms.api.node.Node;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -45,30 +46,35 @@ public final class BulkUpdate {
|
||||
private final DataType dataType;
|
||||
|
||||
// the action to apply to the data which matches the constraints
|
||||
private final BulkUpdateAction action;
|
||||
private final Action action;
|
||||
|
||||
// a set of filters which data must match to be acted upon
|
||||
private final FilterList<Node> filters;
|
||||
// a set of constraints which data must match to be acted upon
|
||||
private final List<Query> queries;
|
||||
|
||||
// update statistics of the operation (number of nodes, users and groups affected)
|
||||
private final BulkUpdateStatistics statistics = new BulkUpdateStatistics();
|
||||
private final boolean trackStatistics;
|
||||
|
||||
public BulkUpdate(DataType dataType, BulkUpdateAction action, FilterList<Node> filters, boolean trackStatistics) {
|
||||
public BulkUpdate(DataType dataType, Action action, List<Query> queries, boolean trackStatistics) {
|
||||
this.dataType = dataType;
|
||||
this.action = action;
|
||||
this.filters = filters;
|
||||
this.queries = queries;
|
||||
this.trackStatistics = trackStatistics;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if a Node instance satisfies the constraints of this query
|
||||
* Check to see if a Node instance satisfies the constrints of this query
|
||||
*
|
||||
* @param node the node to check
|
||||
* @return true if satisfied
|
||||
*/
|
||||
public boolean satisfiesFilters(Node node) {
|
||||
return this.filters.evaluate(node);
|
||||
public boolean satisfiesConstraints(Node node) {
|
||||
for (Query query : this.queries) {
|
||||
if (!query.isSatisfiedBy(node)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -78,7 +84,7 @@ public final class BulkUpdate {
|
||||
* @return the transformed node, or null if the node should be deleted
|
||||
*/
|
||||
private Node apply(Node node) {
|
||||
if (!satisfiesFilters(node)) {
|
||||
if (!satisfiesConstraints(node)) {
|
||||
return node; // make no change
|
||||
}
|
||||
|
||||
@@ -123,16 +129,63 @@ public final class BulkUpdate {
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this {@link BulkUpdate} to SQL syntax
|
||||
*
|
||||
* @return this query in SQL form
|
||||
*/
|
||||
public PreparedStatementBuilder buildAsSql() {
|
||||
// DELETE FROM {table} WHERE ...
|
||||
// UPDATE {table} SET ... WHERE ...
|
||||
|
||||
PreparedStatementBuilder builder = new PreparedStatementBuilder();
|
||||
|
||||
// add the action
|
||||
// (DELETE FROM or UPDATE)
|
||||
this.action.appendSql(builder);
|
||||
|
||||
return appendConstraintsAsSql(builder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the constraints of this {@link BulkUpdate} to the provided statement builder in SQL syntax
|
||||
*
|
||||
* @param builder the statement builder to append the constraints to
|
||||
* @return the same statement builder provided as input
|
||||
*/
|
||||
public PreparedStatementBuilder appendConstraintsAsSql(PreparedStatementBuilder builder) {
|
||||
|
||||
// if there are no constraints, just return without a WHERE clause
|
||||
if (this.queries.isEmpty()) {
|
||||
return builder;
|
||||
}
|
||||
|
||||
// append constraints
|
||||
builder.append(" WHERE");
|
||||
for (int i = 0; i < this.queries.size(); i++) {
|
||||
Query query = this.queries.get(i);
|
||||
|
||||
builder.append(" ");
|
||||
if (i != 0) {
|
||||
builder.append("AND ");
|
||||
}
|
||||
|
||||
query.appendSql(builder);
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public DataType getDataType() {
|
||||
return this.dataType;
|
||||
}
|
||||
|
||||
public BulkUpdateAction getAction() {
|
||||
public Action getAction() {
|
||||
return this.action;
|
||||
}
|
||||
|
||||
public FilterList<Node> getFilters() {
|
||||
return this.filters;
|
||||
public List<Query> getQueries() {
|
||||
return this.queries;
|
||||
}
|
||||
|
||||
public boolean isTrackingStatistics() {
|
||||
@@ -151,12 +204,12 @@ public final class BulkUpdate {
|
||||
|
||||
return this.getDataType() == that.getDataType() &&
|
||||
Objects.equals(this.getAction(), that.getAction()) &&
|
||||
Objects.equals(this.getFilters(), that.getFilters());
|
||||
Objects.equals(this.getQueries(), that.getQueries());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(getDataType(), getAction(), getFilters(), isTrackingStatistics());
|
||||
return Objects.hash(getDataType(), getAction(), getQueries(), isTrackingStatistics());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -164,7 +217,7 @@ public final class BulkUpdate {
|
||||
return "BulkUpdate(" +
|
||||
"dataType=" + this.getDataType() + ", " +
|
||||
"action=" + this.getAction() + ", " +
|
||||
"constraints=" + this.getFilters() + ", " +
|
||||
"constraints=" + this.getQueries() + ", " +
|
||||
"trackStatistics=" + this.isTrackingStatistics() + ")";
|
||||
}
|
||||
}
|
||||
@@ -26,12 +26,8 @@
|
||||
package me.lucko.luckperms.common.bulkupdate;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import me.lucko.luckperms.common.bulkupdate.action.BulkUpdateAction;
|
||||
import me.lucko.luckperms.common.filter.Comparison;
|
||||
import me.lucko.luckperms.common.filter.ConstraintFactory;
|
||||
import me.lucko.luckperms.common.filter.Filter;
|
||||
import me.lucko.luckperms.common.filter.FilterList;
|
||||
import net.luckperms.api.node.Node;
|
||||
import me.lucko.luckperms.common.bulkupdate.action.Action;
|
||||
import me.lucko.luckperms.common.bulkupdate.query.Query;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
@@ -49,18 +45,18 @@ public class BulkUpdateBuilder {
|
||||
private DataType dataType = DataType.ALL;
|
||||
|
||||
// the action to apply to the data which matches the constraints
|
||||
private BulkUpdateAction action = null;
|
||||
private Action action = null;
|
||||
|
||||
// should the operation count the number of affected nodes, users and groups
|
||||
private boolean trackStatistics = false;
|
||||
|
||||
// a set of filters which data must match to be acted upon
|
||||
private final Set<Filter<Node, String>> filters = new LinkedHashSet<>();
|
||||
// a set of constraints which data must match to be acted upon
|
||||
private final Set<Query> queries = new LinkedHashSet<>();
|
||||
|
||||
private BulkUpdateBuilder() {
|
||||
}
|
||||
|
||||
public BulkUpdateBuilder action(BulkUpdateAction action) {
|
||||
public BulkUpdateBuilder action(Action action) {
|
||||
this.action = action;
|
||||
return this;
|
||||
}
|
||||
@@ -75,8 +71,8 @@ public class BulkUpdateBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public BulkUpdateBuilder filter(BulkUpdateField field, Comparison comparison, String value) {
|
||||
this.filters.add(new Filter<>(field, ConstraintFactory.STRINGS.build(comparison, value)));
|
||||
public BulkUpdateBuilder query(Query query) {
|
||||
this.queries.add(query);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -85,8 +81,7 @@ public class BulkUpdateBuilder {
|
||||
throw new IllegalStateException("no action specified");
|
||||
}
|
||||
|
||||
FilterList<Node> filters = new FilterList<>(FilterList.LogicalOperator.AND, ImmutableList.copyOf(this.filters));
|
||||
return new BulkUpdate(this.dataType, this.action, filters, this.trackStatistics);
|
||||
return new BulkUpdate(this.dataType, this.action, ImmutableList.copyOf(this.queries), this.trackStatistics);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -94,7 +89,7 @@ public class BulkUpdateBuilder {
|
||||
return "BulkUpdateBuilder(" +
|
||||
"dataType=" + this.dataType + ", " +
|
||||
"action=" + this.action + ", " +
|
||||
"constraints=" + this.filters + ", " +
|
||||
"constraints=" + this.queries + ", " +
|
||||
"trackStatistics=" + this.trackStatistics + ")";
|
||||
}
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.bulkupdate;
|
||||
|
||||
import me.lucko.luckperms.common.bulkupdate.action.BulkUpdateAction;
|
||||
import me.lucko.luckperms.common.bulkupdate.action.DeleteAction;
|
||||
import me.lucko.luckperms.common.bulkupdate.action.UpdateAction;
|
||||
import me.lucko.luckperms.common.filter.FilterField;
|
||||
import me.lucko.luckperms.common.filter.sql.FilterSqlBuilder;
|
||||
import net.luckperms.api.node.Node;
|
||||
|
||||
public class BulkUpdateSqlBuilder extends FilterSqlBuilder<Node> {
|
||||
|
||||
public void visit(BulkUpdate update) {
|
||||
visit(update.getAction());
|
||||
visit(update.getFilters());
|
||||
}
|
||||
|
||||
public void visit(BulkUpdateAction action) {
|
||||
if (action instanceof UpdateAction) {
|
||||
visit(((UpdateAction) action));
|
||||
} else if (action instanceof DeleteAction) {
|
||||
visit(((DeleteAction) action));
|
||||
} else {
|
||||
throw new UnsupportedOperationException(action.getClass().getName());
|
||||
}
|
||||
}
|
||||
|
||||
public void visit(UpdateAction action) {
|
||||
this.builder.append("UPDATE {table} SET ");
|
||||
visitFieldName(action.getField());
|
||||
this.builder.append("=");
|
||||
this.builder.variable(action.getNewValue());
|
||||
}
|
||||
|
||||
public void visit(DeleteAction action) {
|
||||
this.builder.append("DELETE FROM {table}");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitFieldName(FilterField<Node, ?> field) {
|
||||
if (field == BulkUpdateField.PERMISSION) {
|
||||
this.builder.append("permission");
|
||||
} else if (field == BulkUpdateField.SERVER) {
|
||||
this.builder.append("server");
|
||||
} else if (field == BulkUpdateField.WORLD) {
|
||||
this.builder.append("world");
|
||||
} else {
|
||||
throw new AssertionError(field);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+8
-22
@@ -23,15 +23,14 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.storage.implementation.sql.builder;
|
||||
|
||||
import me.lucko.luckperms.common.storage.implementation.sql.StatementProcessor;
|
||||
package me.lucko.luckperms.common.bulkupdate;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class PreparedStatementBuilder {
|
||||
private final StringBuilder sb = new StringBuilder();
|
||||
@@ -57,22 +56,13 @@ public class PreparedStatementBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public PreparedStatement build(Connection connection, StatementProcessor processor) throws SQLException {
|
||||
PreparedStatement statement = null;
|
||||
try {
|
||||
statement = connection.prepareStatement(processor.process(this.sb.toString()));
|
||||
for (int i = 0; i < this.variables.size(); i++) {
|
||||
String var = this.variables.get(i);
|
||||
statement.setString(i + 1, var);
|
||||
}
|
||||
return statement;
|
||||
} catch (SQLException e) {
|
||||
// if an exception is thrown, any try-with-resources block above this call won't be able to close the statement
|
||||
if (statement != null) {
|
||||
statement.close();
|
||||
}
|
||||
throw e;
|
||||
public PreparedStatement build(Connection connection, Function<String, String> mapping) throws SQLException {
|
||||
PreparedStatement statement = connection.prepareStatement(mapping.apply(this.sb.toString()));
|
||||
for (int i = 0; i < this.variables.size(); i++) {
|
||||
String var = this.variables.get(i);
|
||||
statement.setString(i + 1, var);
|
||||
}
|
||||
return statement;
|
||||
}
|
||||
|
||||
public String toReadableString() {
|
||||
@@ -82,8 +72,4 @@ public class PreparedStatementBuilder {
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
public String toQueryString() {
|
||||
return this.sb.toString();
|
||||
}
|
||||
}
|
||||
+12
-2
@@ -25,12 +25,13 @@
|
||||
|
||||
package me.lucko.luckperms.common.bulkupdate.action;
|
||||
|
||||
import me.lucko.luckperms.common.bulkupdate.PreparedStatementBuilder;
|
||||
import net.luckperms.api.node.Node;
|
||||
|
||||
/**
|
||||
* Represents an action to be applied to a given node.
|
||||
*/
|
||||
public interface BulkUpdateAction {
|
||||
public interface Action {
|
||||
|
||||
/**
|
||||
* Gets the name of this action
|
||||
@@ -43,8 +44,17 @@ public interface BulkUpdateAction {
|
||||
* Applies this action to the given NodeModel, and returns the result.
|
||||
*
|
||||
* @param from the node to base changes from
|
||||
* @return the new node instance, or null if the node should be deleted.
|
||||
* @return the new nodemodel instance, or null if the node should be deleted.
|
||||
*/
|
||||
Node apply(Node from);
|
||||
|
||||
/**
|
||||
* Gets this action in SQL form.
|
||||
*
|
||||
* Will include a placeholder for the table, as "{table}".
|
||||
*
|
||||
* @param builder the statement builder
|
||||
*/
|
||||
void appendSql(PreparedStatementBuilder builder);
|
||||
|
||||
}
|
||||
@@ -25,9 +25,10 @@
|
||||
|
||||
package me.lucko.luckperms.common.bulkupdate.action;
|
||||
|
||||
import me.lucko.luckperms.common.bulkupdate.PreparedStatementBuilder;
|
||||
import net.luckperms.api.node.Node;
|
||||
|
||||
public class DeleteAction implements BulkUpdateAction {
|
||||
public class DeleteAction implements Action {
|
||||
|
||||
public static DeleteAction create() {
|
||||
return new DeleteAction();
|
||||
@@ -45,4 +46,9 @@ public class DeleteAction implements BulkUpdateAction {
|
||||
public Node apply(Node from) {
|
||||
return null; // this action just deletes nodes, so return null
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendSql(PreparedStatementBuilder builder) {
|
||||
builder.append("DELETE FROM {table}");
|
||||
}
|
||||
}
|
||||
+19
-20
@@ -25,27 +25,28 @@
|
||||
|
||||
package me.lucko.luckperms.common.bulkupdate.action;
|
||||
|
||||
import me.lucko.luckperms.common.bulkupdate.BulkUpdateField;
|
||||
import me.lucko.luckperms.common.bulkupdate.PreparedStatementBuilder;
|
||||
import me.lucko.luckperms.common.bulkupdate.query.QueryField;
|
||||
import me.lucko.luckperms.common.node.factory.NodeBuilders;
|
||||
import net.luckperms.api.context.DefaultContextKeys;
|
||||
import net.luckperms.api.context.MutableContextSet;
|
||||
import net.luckperms.api.node.Node;
|
||||
|
||||
public class UpdateAction implements BulkUpdateAction {
|
||||
public class UpdateAction implements Action {
|
||||
|
||||
public static UpdateAction of(BulkUpdateField field, String value) {
|
||||
public static UpdateAction of(QueryField field, String value) {
|
||||
return new UpdateAction(field, value);
|
||||
}
|
||||
|
||||
// the field we're updating
|
||||
private final BulkUpdateField field;
|
||||
private final QueryField field;
|
||||
|
||||
// the new value of the field
|
||||
private final String newValue;
|
||||
private final String value;
|
||||
|
||||
private UpdateAction(BulkUpdateField field, String newValue) {
|
||||
private UpdateAction(QueryField field, String value) {
|
||||
this.field = field;
|
||||
this.newValue = newValue;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -53,19 +54,11 @@ public class UpdateAction implements BulkUpdateAction {
|
||||
return "update";
|
||||
}
|
||||
|
||||
public BulkUpdateField getField() {
|
||||
return this.field;
|
||||
}
|
||||
|
||||
public String getNewValue() {
|
||||
return this.newValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node apply(Node from) {
|
||||
switch (this.field) {
|
||||
case PERMISSION:
|
||||
return NodeBuilders.determineMostApplicable(this.newValue)
|
||||
return NodeBuilders.determineMostApplicable(this.value)
|
||||
.value(from.getValue())
|
||||
.expiry(from.getExpiry())
|
||||
.context(from.getContexts())
|
||||
@@ -73,8 +66,8 @@ public class UpdateAction implements BulkUpdateAction {
|
||||
case SERVER: {
|
||||
MutableContextSet contexts = from.getContexts().mutableCopy();
|
||||
contexts.removeAll(DefaultContextKeys.SERVER_KEY);
|
||||
if (!this.newValue.equals("global")) {
|
||||
contexts.add(DefaultContextKeys.SERVER_KEY, this.newValue);
|
||||
if (!this.value.equals("global")) {
|
||||
contexts.add(DefaultContextKeys.SERVER_KEY, this.value);
|
||||
}
|
||||
|
||||
return from.toBuilder()
|
||||
@@ -84,8 +77,8 @@ public class UpdateAction implements BulkUpdateAction {
|
||||
case WORLD: {
|
||||
MutableContextSet contexts = from.getContexts().mutableCopy();
|
||||
contexts.removeAll(DefaultContextKeys.WORLD_KEY);
|
||||
if (!this.newValue.equals("global")) {
|
||||
contexts.add(DefaultContextKeys.WORLD_KEY, this.newValue);
|
||||
if (!this.value.equals("global")) {
|
||||
contexts.add(DefaultContextKeys.WORLD_KEY, this.value);
|
||||
}
|
||||
|
||||
return from.toBuilder()
|
||||
@@ -96,4 +89,10 @@ public class UpdateAction implements BulkUpdateAction {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendSql(PreparedStatementBuilder builder) {
|
||||
builder.append("UPDATE {table} SET " + this.field.getSqlName() + "=");
|
||||
builder.variable(this.value);
|
||||
}
|
||||
}
|
||||
+27
-39
@@ -23,60 +23,48 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.filter;
|
||||
package me.lucko.luckperms.common.bulkupdate.comparison;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
import me.lucko.luckperms.common.bulkupdate.PreparedStatementBuilder;
|
||||
|
||||
/**
|
||||
* A method of comparing two strings
|
||||
*/
|
||||
public enum Comparison {
|
||||
|
||||
EQUAL("=="),
|
||||
NOT_EQUAL("!="),
|
||||
SIMILAR("~~"),
|
||||
NOT_SIMILAR("!~");
|
||||
|
||||
public static final String WILDCARD = "%";
|
||||
public static final String WILDCARD_ONE = "_";
|
||||
|
||||
private final String symbol;
|
||||
|
||||
Comparison(String symbol) {
|
||||
this.symbol = symbol;
|
||||
}
|
||||
public interface Comparison {
|
||||
|
||||
/**
|
||||
* Gets the symbol which represents this comparison
|
||||
*
|
||||
* @return the comparison symbol
|
||||
*/
|
||||
public String getSymbol() {
|
||||
return this.symbol;
|
||||
}
|
||||
String getSymbol();
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.symbol;
|
||||
}
|
||||
/**
|
||||
* Creates a {@link CompiledExpression} for the given expression
|
||||
*
|
||||
* @param expression the expression
|
||||
* @return the compiled expression
|
||||
*/
|
||||
CompiledExpression compile(String expression);
|
||||
|
||||
public static Comparison parse(String s) {
|
||||
for (Comparison t : values()) {
|
||||
if (t.getSymbol().equals(s)) {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* Returns the comparison operator in SQL form
|
||||
*/
|
||||
void appendSql(PreparedStatementBuilder builder);
|
||||
|
||||
public static Pattern compilePatternForLikeSyntax(String expression) {
|
||||
expression = expression.replace(".", "\\.");
|
||||
/**
|
||||
* An instance of {@link Comparison} which is bound to an expression.
|
||||
*/
|
||||
interface CompiledExpression {
|
||||
|
||||
// convert from SQL LIKE syntax to regex
|
||||
expression = expression.replace(WILDCARD_ONE, ".");
|
||||
expression = expression.replace(WILDCARD, ".*");
|
||||
|
||||
return Pattern.compile(expression, Pattern.CASE_INSENSITIVE);
|
||||
/**
|
||||
* Tests the expression against a given string, according to the
|
||||
* rules of the parent {@link Comparison}.
|
||||
*
|
||||
* @param string the string
|
||||
* @return if there was a match
|
||||
*/
|
||||
boolean test(String string);
|
||||
}
|
||||
|
||||
}
|
||||
+23
-19
@@ -23,28 +23,24 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.filter;
|
||||
package me.lucko.luckperms.common.bulkupdate.comparison;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
import me.lucko.luckperms.common.bulkupdate.PreparedStatementBuilder;
|
||||
|
||||
public class Constraint<T> {
|
||||
public class Constraint {
|
||||
|
||||
public static Constraint of(Comparison comparison, String expression) {
|
||||
return new Constraint(comparison, expression);
|
||||
}
|
||||
|
||||
private final Comparison comparison;
|
||||
private final T value;
|
||||
private final Predicate<T> predicate;
|
||||
private final String expressionValue;
|
||||
private final Comparison.CompiledExpression compiledExpression;
|
||||
|
||||
Constraint(Comparison comparison, T value, Predicate<T> predicate) {
|
||||
private Constraint(Comparison comparison, String expression) {
|
||||
this.comparison = comparison;
|
||||
this.value = value;
|
||||
this.predicate = predicate;
|
||||
}
|
||||
|
||||
public Comparison comparison() {
|
||||
return this.comparison;
|
||||
}
|
||||
|
||||
public T value() {
|
||||
return this.value;
|
||||
this.expressionValue = expression;
|
||||
this.compiledExpression = this.comparison.compile(this.expressionValue);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -53,12 +49,20 @@ public class Constraint<T> {
|
||||
* @param value the value
|
||||
* @return true if satisfied
|
||||
*/
|
||||
public boolean evaluate(T value) {
|
||||
return this.predicate.test(value);
|
||||
public boolean eval(String value) {
|
||||
return this.compiledExpression.test(value);
|
||||
}
|
||||
|
||||
public void appendSql(PreparedStatementBuilder builder, String field) {
|
||||
// e.g. field LIKE ?
|
||||
builder.append(field).append(' ');
|
||||
this.comparison.appendSql(builder);
|
||||
builder.append(' ');
|
||||
builder.variable(this.expressionValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.comparison + " " + this.value;
|
||||
return this.comparison + " " + this.expressionValue;
|
||||
}
|
||||
}
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.bulkupdate.comparison;
|
||||
|
||||
import me.lucko.luckperms.common.bulkupdate.PreparedStatementBuilder;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* An enumeration of standard {@link Comparison}s.
|
||||
*/
|
||||
public enum StandardComparison implements Comparison {
|
||||
|
||||
EQUAL("==", "=") {
|
||||
@Override
|
||||
public CompiledExpression compile(String expression) {
|
||||
return expression::equalsIgnoreCase;
|
||||
}
|
||||
},
|
||||
|
||||
NOT_EQUAL("!=", "!=") {
|
||||
@Override
|
||||
public CompiledExpression compile(String expression) {
|
||||
return string -> !expression.equalsIgnoreCase(string);
|
||||
}
|
||||
},
|
||||
|
||||
SIMILAR("~~", "LIKE") {
|
||||
@Override
|
||||
public CompiledExpression compile(String expression) {
|
||||
Pattern pattern = StandardComparison.compilePatternForLikeSyntax(expression);
|
||||
return string -> pattern.matcher(string).matches();
|
||||
}
|
||||
},
|
||||
|
||||
NOT_SIMILAR("!~", "NOT LIKE") {
|
||||
@Override
|
||||
public CompiledExpression compile(String expression) {
|
||||
Pattern pattern = StandardComparison.compilePatternForLikeSyntax(expression);
|
||||
return string -> !pattern.matcher(string).matches();
|
||||
}
|
||||
};
|
||||
|
||||
public static final String WILDCARD = "%";
|
||||
public static final String WILDCARD_ONE = "_";
|
||||
|
||||
private final String symbol;
|
||||
private final String asSql;
|
||||
|
||||
StandardComparison(String symbol, String asSql) {
|
||||
this.symbol = symbol;
|
||||
this.asSql = asSql;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSymbol() {
|
||||
return this.symbol;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendSql(PreparedStatementBuilder builder) {
|
||||
builder.append(this.asSql);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.symbol;
|
||||
}
|
||||
|
||||
public static StandardComparison parseComparison(String s) {
|
||||
for (StandardComparison t : values()) {
|
||||
if (t.getSymbol().equals(s)) {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static Pattern compilePatternForLikeSyntax(String expression) {
|
||||
expression = expression.replace(".", "\\.");
|
||||
|
||||
// convert from SQL LIKE syntax to regex
|
||||
expression = expression.replace(WILDCARD_ONE, ".");
|
||||
expression = expression.replace(WILDCARD, ".*");
|
||||
|
||||
return Pattern.compile(expression, Pattern.CASE_INSENSITIVE);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.bulkupdate.query;
|
||||
|
||||
import me.lucko.luckperms.common.bulkupdate.PreparedStatementBuilder;
|
||||
import me.lucko.luckperms.common.bulkupdate.comparison.Constraint;
|
||||
import net.luckperms.api.context.DefaultContextKeys;
|
||||
import net.luckperms.api.node.Node;
|
||||
|
||||
/**
|
||||
* Represents a query component
|
||||
*/
|
||||
public class Query {
|
||||
|
||||
public static Query of(QueryField field, Constraint constraint) {
|
||||
return new Query(field, constraint);
|
||||
}
|
||||
|
||||
// the field this query is comparing against
|
||||
private final QueryField field;
|
||||
|
||||
// the constraint
|
||||
private final Constraint constraint;
|
||||
|
||||
private Query(QueryField field, Constraint constraint) {
|
||||
this.field = field;
|
||||
this.constraint = constraint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the given node satisfies this query
|
||||
*
|
||||
* @param node the node
|
||||
* @return true if satisfied
|
||||
*/
|
||||
public boolean isSatisfiedBy(Node node) {
|
||||
switch (this.field) {
|
||||
case PERMISSION:
|
||||
return this.constraint.eval(node.getKey());
|
||||
case SERVER:
|
||||
return this.constraint.eval(node.getContexts().getAnyValue(DefaultContextKeys.SERVER_KEY).orElse("global"));
|
||||
case WORLD:
|
||||
return this.constraint.eval(node.getContexts().getAnyValue(DefaultContextKeys.WORLD_KEY).orElse("global"));
|
||||
default:
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
public void appendSql(PreparedStatementBuilder builder) {
|
||||
this.constraint.appendSql(builder, this.field.getSqlName());
|
||||
}
|
||||
|
||||
public QueryField getField() {
|
||||
return this.field;
|
||||
}
|
||||
|
||||
public Constraint getConstraint() {
|
||||
return this.constraint;
|
||||
}
|
||||
}
|
||||
+22
-14
@@ -23,26 +23,34 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.standalone.app.integration;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.luckperms.api.util.Tristate;
|
||||
package me.lucko.luckperms.common.bulkupdate.query;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface StandaloneSender {
|
||||
String getName();
|
||||
/**
|
||||
* Represents a field being used in an update
|
||||
*/
|
||||
public enum QueryField {
|
||||
|
||||
UUID getUniqueId();
|
||||
PERMISSION("permission"),
|
||||
SERVER("server"),
|
||||
WORLD("world");
|
||||
|
||||
void sendMessage(Component component);
|
||||
private final String sqlName;
|
||||
|
||||
Tristate getPermissionValue(String permission);
|
||||
public static QueryField of(String s) {
|
||||
try {
|
||||
return valueOf(s.toUpperCase(Locale.ROOT));
|
||||
} catch (IllegalArgumentException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
boolean hasPermission(String permission);
|
||||
QueryField(String sqlName) {
|
||||
this.sqlName = sqlName;
|
||||
}
|
||||
|
||||
boolean isConsole();
|
||||
|
||||
Locale getLocale();
|
||||
public String getSqlName() {
|
||||
return this.sqlName;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -193,7 +193,7 @@ public abstract class AbstractCachedDataManager implements CachedDataManager {
|
||||
}
|
||||
|
||||
public void cleanup() {
|
||||
this.cache.values().removeIf(value -> !((UsageTracked) value).usedInTheLast(2, TimeUnit.MINUTES));
|
||||
this.cache.values().removeIf(value -> ((UsageTracked) value).usedSince(TimeUnit.MINUTES.toMillis(2)));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -25,20 +25,14 @@
|
||||
|
||||
package me.lucko.luckperms.common.cacheddata;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public abstract class UsageTracked {
|
||||
|
||||
@VisibleForTesting
|
||||
protected long lastUsed = System.currentTimeMillis();
|
||||
private long lastUsed = System.currentTimeMillis();
|
||||
|
||||
public void recordUsage() {
|
||||
this.lastUsed = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public boolean usedInTheLast(long duration, TimeUnit unit) {
|
||||
return this.lastUsed > System.currentTimeMillis() - unit.toMillis(duration);
|
||||
public boolean usedSince(long duration) {
|
||||
return this.lastUsed > System.currentTimeMillis() - duration;
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.cacheddata.result;
|
||||
|
||||
import net.luckperms.api.cacheddata.Result;
|
||||
import net.luckperms.api.node.Node;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public abstract class AbstractResult<T, N extends Node, S extends AbstractResult<T, N, S>> implements Result<T, N> {
|
||||
|
||||
/** The node that caused the result */
|
||||
protected final N node;
|
||||
/** A reference to another result that this one overrides */
|
||||
protected S overriddenResult;
|
||||
|
||||
public AbstractResult(N node, S overriddenResult) {
|
||||
this.node = node;
|
||||
this.overriddenResult = overriddenResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final @Nullable N node() {
|
||||
return this.node;
|
||||
}
|
||||
|
||||
public final @Nullable S overriddenResult() {
|
||||
return this.overriddenResult;
|
||||
}
|
||||
|
||||
public final void setOverriddenResult(S overriddenResult) {
|
||||
this.overriddenResult = overriddenResult;
|
||||
}
|
||||
|
||||
}
|
||||
+22
-2
@@ -25,23 +25,30 @@
|
||||
|
||||
package me.lucko.luckperms.common.cacheddata.result;
|
||||
|
||||
import net.luckperms.api.cacheddata.Result;
|
||||
import net.luckperms.api.node.Node;
|
||||
import net.luckperms.api.node.types.WeightNode;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
/**
|
||||
* Represents the result of an integer meta lookup
|
||||
*
|
||||
* @param <N> the node type
|
||||
*/
|
||||
public final class IntegerResult<N extends Node> extends AbstractResult<Integer, N, IntegerResult<N>> {
|
||||
public final class IntegerResult<N extends Node> implements Result<Integer, N> {
|
||||
|
||||
/** The result */
|
||||
private final int result;
|
||||
/** The node that caused the result */
|
||||
private final N node;
|
||||
/** A reference to another result that this one overrides */
|
||||
private IntegerResult<N> overriddenResult;
|
||||
|
||||
public IntegerResult(int result, N node, IntegerResult<N> overriddenResult) {
|
||||
super(node, overriddenResult);
|
||||
this.result = result;
|
||||
this.node = node;
|
||||
this.overriddenResult = overriddenResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -66,6 +73,19 @@ public final class IntegerResult<N extends Node> extends AbstractResult<Integer,
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable N node() {
|
||||
return this.node;
|
||||
}
|
||||
|
||||
public @Nullable IntegerResult<N> overriddenResult() {
|
||||
return this.overriddenResult;
|
||||
}
|
||||
|
||||
public void setOverriddenResult(IntegerResult<N> overriddenResult) {
|
||||
this.overriddenResult = overriddenResult;
|
||||
}
|
||||
|
||||
public boolean isNull() {
|
||||
return this == NULL_RESULT;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
package me.lucko.luckperms.common.cacheddata.result;
|
||||
|
||||
import net.luckperms.api.cacheddata.Result;
|
||||
import net.luckperms.api.node.Node;
|
||||
import net.luckperms.api.node.types.ChatMetaNode;
|
||||
import net.luckperms.api.node.types.MetaNode;
|
||||
@@ -35,14 +36,19 @@ import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
*
|
||||
* @param <N> the node type
|
||||
*/
|
||||
public final class StringResult<N extends Node> extends AbstractResult<String, N, StringResult<N>> {
|
||||
public final class StringResult<N extends Node> implements Result<String, N> {
|
||||
|
||||
/** The result, nullable */
|
||||
private final String result;
|
||||
/** The node that caused the result */
|
||||
private final N node;
|
||||
/** A reference to another result that this one overrides */
|
||||
private StringResult<N> overriddenResult;
|
||||
|
||||
public StringResult(String result, N node, StringResult<N> overriddenResult) {
|
||||
super(node, overriddenResult);
|
||||
this.result = result;
|
||||
this.node = node;
|
||||
this.overriddenResult = overriddenResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -50,6 +56,19 @@ public final class StringResult<N extends Node> extends AbstractResult<String, N
|
||||
return this.result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable N node() {
|
||||
return this.node;
|
||||
}
|
||||
|
||||
public @Nullable StringResult<N> overriddenResult() {
|
||||
return this.overriddenResult;
|
||||
}
|
||||
|
||||
public void setOverriddenResult(StringResult<N> overriddenResult) {
|
||||
this.overriddenResult = overriddenResult;
|
||||
}
|
||||
|
||||
public StringResult<N> copy() {
|
||||
return new StringResult<>(this.result, this.node, this.overriddenResult);
|
||||
}
|
||||
|
||||
+20
-2
@@ -27,6 +27,7 @@ package me.lucko.luckperms.common.cacheddata.result;
|
||||
|
||||
import me.lucko.luckperms.common.calculator.PermissionCalculator;
|
||||
import me.lucko.luckperms.common.calculator.processor.PermissionProcessor;
|
||||
import net.luckperms.api.cacheddata.Result;
|
||||
import net.luckperms.api.node.Node;
|
||||
import net.luckperms.api.util.Tristate;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
@@ -35,16 +36,20 @@ import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
/**
|
||||
* Represents the result of a {@link PermissionCalculator} lookup.
|
||||
*/
|
||||
public final class TristateResult extends AbstractResult<Tristate, Node, TristateResult> {
|
||||
public final class TristateResult implements Result<Tristate, Node> {
|
||||
|
||||
/** The result */
|
||||
private final Tristate result;
|
||||
/** The node that caused the result */
|
||||
private final Node node;
|
||||
/** The permission processor that provided the result */
|
||||
private final Class<? extends PermissionProcessor> processorClass;
|
||||
/** A reference to another result that this one overrides */
|
||||
private TristateResult overriddenResult;
|
||||
|
||||
private TristateResult(Tristate result, Node node, Class<? extends PermissionProcessor> processorClass) {
|
||||
super(node, null);
|
||||
this.result = result;
|
||||
this.node = node;
|
||||
this.processorClass = processorClass;
|
||||
}
|
||||
|
||||
@@ -53,6 +58,11 @@ public final class TristateResult extends AbstractResult<Tristate, Node, Tristat
|
||||
return this.result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Node node() {
|
||||
return this.node;
|
||||
}
|
||||
|
||||
public @Nullable Class<? extends PermissionProcessor> processorClass() {
|
||||
return this.processorClass;
|
||||
}
|
||||
@@ -69,6 +79,14 @@ public final class TristateResult extends AbstractResult<Tristate, Node, Tristat
|
||||
}
|
||||
}
|
||||
|
||||
public @Nullable TristateResult overriddenResult() {
|
||||
return this.overriddenResult;
|
||||
}
|
||||
|
||||
public void setOverriddenResult(TristateResult overriddenResult) {
|
||||
this.overriddenResult = overriddenResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TristateResult(" +
|
||||
|
||||
@@ -79,7 +79,6 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
@@ -102,7 +101,7 @@ public class CommandManager {
|
||||
.build()
|
||||
);
|
||||
private final AtomicBoolean executingCommand = new AtomicBoolean(false);
|
||||
private final Set<UUID> playerRateLimit = ExpiringSet.newExpiringSet(500, TimeUnit.MILLISECONDS);
|
||||
private final ExpiringSet<UUID> playerRateLimit = new ExpiringSet<>(500, TimeUnit.MILLISECONDS);
|
||||
private final TabCompletions tabCompletions;
|
||||
private final Map<String, Command<?>> mainCommands;
|
||||
|
||||
@@ -155,20 +154,11 @@ public class CommandManager {
|
||||
|
||||
public CompletableFuture<Void> executeCommand(Sender sender, String label, List<String> args) {
|
||||
UUID uniqueId = sender.getUniqueId();
|
||||
if (this.plugin.getConfiguration().get(ConfigKeys.COMMANDS_RATE_LIMIT) && !sender.isConsole() && !Sender.CONSOLE_UUID.equals(uniqueId) && !this.playerRateLimit.add(uniqueId)) {
|
||||
if (this.plugin.getConfiguration().get(ConfigKeys.COMMANDS_RATE_LIMIT) && !sender.isConsole() && !this.playerRateLimit.add(uniqueId)) {
|
||||
this.plugin.getLogger().warn("Player '" + uniqueId + "' is spamming LuckPerms commands. Ignoring further inputs.");
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
|
||||
boolean commandsDisabled = sender.isConsole()
|
||||
? this.plugin.getConfiguration().get(ConfigKeys.DISABLE_LUCKPERMS_COMMANDS_CONSOLE)
|
||||
: this.plugin.getConfiguration().get(ConfigKeys.DISABLE_LUCKPERMS_COMMANDS_PLAYERS);
|
||||
|
||||
if (commandsDisabled) {
|
||||
Message.COMMANDS_DISABLED.send(sender);
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
|
||||
SchedulerAdapter scheduler = this.plugin.getBootstrap().getScheduler();
|
||||
List<String> argsCopy = new ArrayList<>(args);
|
||||
|
||||
@@ -295,14 +285,6 @@ public class CommandManager {
|
||||
}
|
||||
|
||||
public List<String> tabCompleteCommand(Sender sender, List<String> arguments) {
|
||||
boolean commandsDisabled = sender.isConsole()
|
||||
? this.plugin.getConfiguration().get(ConfigKeys.DISABLE_LUCKPERMS_COMMANDS_CONSOLE)
|
||||
: this.plugin.getConfiguration().get(ConfigKeys.DISABLE_LUCKPERMS_COMMANDS_PLAYERS);
|
||||
|
||||
if (commandsDisabled) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
applyConvenienceAliases(arguments, false);
|
||||
|
||||
final List<Command<?>> mains = this.mainCommands.values().stream()
|
||||
|
||||
+1
-2
@@ -31,7 +31,6 @@ import me.lucko.luckperms.common.command.spec.CommandSpec;
|
||||
import me.lucko.luckperms.common.locale.Message;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.JoinConfiguration;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
|
||||
@@ -67,7 +66,7 @@ public abstract class ChildCommand<T> extends Command<T> {
|
||||
.collect(Collectors.toList());
|
||||
|
||||
builder.append(Component.text(" - ", NamedTextColor.DARK_AQUA))
|
||||
.append(Component.join(JoinConfiguration.separator(Component.space()), argUsages))
|
||||
.append(Component.join(Component.space(), argUsages))
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
+1
-2
@@ -35,7 +35,6 @@ import me.lucko.luckperms.common.model.PermissionHolder;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.JoinConfiguration;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
|
||||
@@ -115,7 +114,7 @@ public abstract class GenericChildCommand {
|
||||
.collect(Collectors.toList());
|
||||
|
||||
builder.append(Component.text(" - ", NamedTextColor.DARK_AQUA))
|
||||
.append(Component.join(JoinConfiguration.separator(Component.space()), argUsages))
|
||||
.append(Component.join(Component.space(), argUsages))
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
+26
-41
@@ -86,44 +86,39 @@ public abstract class ParentCommand<T, I> extends Command<Void> {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.type == Type.TARGETED) {
|
||||
final String targetArgument = args.get(0);
|
||||
I targetId = parseTarget(targetArgument, plugin, sender);
|
||||
final String targetArgument = args.get(0);
|
||||
I targetId = null;
|
||||
if (this.type == Type.TAKES_ARGUMENT_FOR_TARGET) {
|
||||
targetId = parseTarget(targetArgument, plugin, sender);
|
||||
if (targetId == null) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ReentrantLock lock = getLockForTarget(targetId);
|
||||
lock.lock();
|
||||
try {
|
||||
T target = getTarget(targetId, plugin, sender);
|
||||
if (target == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
sub.execute(plugin, sender, target, args.subList(this.type.minArgs, args.size()), label);
|
||||
} catch (CommandException e) {
|
||||
e.handle(sender, label, sub);
|
||||
}
|
||||
|
||||
cleanup(target, plugin);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
ReentrantLock lock = getLockForTarget(targetId);
|
||||
lock.lock();
|
||||
try {
|
||||
T target = getTarget(targetId, plugin, sender);
|
||||
if (target == null) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
|
||||
try {
|
||||
sub.execute(plugin, sender, null, args.subList(this.type.minArgs, args.size()), label);
|
||||
sub.execute(plugin, sender, target, args.subList(this.type.minArgs, args.size()), label);
|
||||
} catch (CommandException e) {
|
||||
e.handle(sender, label, sub);
|
||||
}
|
||||
|
||||
cleanup(target, plugin);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> tabComplete(LuckPermsPlugin plugin, Sender sender, ArgumentList args) {
|
||||
switch (this.type) {
|
||||
case TARGETED:
|
||||
case TAKES_ARGUMENT_FOR_TARGET:
|
||||
return TabCompleter.create()
|
||||
.at(0, CompletionSupplier.startsWith(() -> getTargets(plugin).stream()))
|
||||
.at(1, CompletionSupplier.startsWith(() -> getChildren().stream()
|
||||
@@ -138,7 +133,7 @@ public abstract class ParentCommand<T, I> extends Command<Void> {
|
||||
.orElse(Collections.emptyList())
|
||||
)
|
||||
.complete(args);
|
||||
case NOT_TARGETED:
|
||||
case NO_TARGET_ARGUMENT:
|
||||
return TabCompleter.create()
|
||||
.at(0, CompletionSupplier.startsWith(() -> getChildren().stream()
|
||||
.filter(s -> s.isAuthorized(sender))
|
||||
@@ -183,31 +178,21 @@ public abstract class ParentCommand<T, I> extends Command<Void> {
|
||||
return getChildren().stream().anyMatch(sc -> sc.isAuthorized(sender));
|
||||
}
|
||||
|
||||
protected List<String> getTargets(LuckPermsPlugin plugin) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
protected abstract List<String> getTargets(LuckPermsPlugin plugin);
|
||||
|
||||
protected I parseTarget(String target, LuckPermsPlugin plugin, Sender sender) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
protected abstract I parseTarget(String target, LuckPermsPlugin plugin, Sender sender);
|
||||
|
||||
protected ReentrantLock getLockForTarget(I target) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
protected abstract ReentrantLock getLockForTarget(I target);
|
||||
|
||||
protected T getTarget(I target, LuckPermsPlugin plugin, Sender sender) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
protected abstract T getTarget(I target, LuckPermsPlugin plugin, Sender sender);
|
||||
|
||||
protected void cleanup(T t, LuckPermsPlugin plugin) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
protected abstract void cleanup(T t, LuckPermsPlugin plugin);
|
||||
|
||||
public enum Type {
|
||||
// e.g. /lp log sub-command....
|
||||
NOT_TARGETED(0),
|
||||
NO_TARGET_ARGUMENT(0),
|
||||
// e.g. /lp user <USER> sub-command....
|
||||
TARGETED(1);
|
||||
TAKES_ARGUMENT_FOR_TARGET(1);
|
||||
|
||||
private final int cmdIndex;
|
||||
private final int minArgs;
|
||||
|
||||
+1
-2
@@ -33,7 +33,6 @@ import me.lucko.luckperms.common.locale.Message;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.JoinConfiguration;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
|
||||
@@ -71,7 +70,7 @@ public abstract class SingleCommand extends Command<Void> {
|
||||
.collect(Collectors.toList());
|
||||
|
||||
builder.append(Component.text(" - ", NamedTextColor.DARK_AQUA))
|
||||
.append(Component.join(JoinConfiguration.separator(Component.space()), argUsages))
|
||||
.append(Component.join(Component.space(), argUsages))
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
+131
-137
@@ -32,143 +32,143 @@ import me.lucko.luckperms.common.sender.Sender;
|
||||
*/
|
||||
public enum CommandPermission {
|
||||
|
||||
SYNC("sync", Type.NONE, true),
|
||||
INFO("info", Type.NONE, true),
|
||||
EDITOR("editor", Type.NONE, true),
|
||||
VERBOSE("verbose", Type.NONE, true),
|
||||
VERBOSE_COMMAND_OTHERS("verbose.command.others", Type.NONE, false),
|
||||
TREE("tree", Type.NONE, true),
|
||||
SEARCH("search", Type.NONE, true),
|
||||
IMPORT("import", Type.NONE, false),
|
||||
EXPORT("export", Type.NONE, true),
|
||||
RELOAD_CONFIG("reloadconfig", Type.NONE, true),
|
||||
BULK_UPDATE("bulkupdate", Type.NONE, false),
|
||||
APPLY_EDITS("applyedits", Type.NONE, false),
|
||||
TRUST_EDITOR("trusteditor", Type.NONE, false),
|
||||
TRANSLATIONS("translations", Type.NONE, true),
|
||||
SYNC("sync", Type.NONE),
|
||||
INFO("info", Type.NONE),
|
||||
EDITOR("editor", Type.NONE),
|
||||
VERBOSE("verbose", Type.NONE),
|
||||
VERBOSE_COMMAND_OTHERS("verbose.command.others", Type.NONE),
|
||||
TREE("tree", Type.NONE),
|
||||
SEARCH("search", Type.NONE),
|
||||
IMPORT("import", Type.NONE),
|
||||
EXPORT("export", Type.NONE),
|
||||
RELOAD_CONFIG("reloadconfig", Type.NONE),
|
||||
BULK_UPDATE("bulkupdate", Type.NONE),
|
||||
APPLY_EDITS("applyedits", Type.NONE),
|
||||
TRUST_EDITOR("trusteditor", Type.NONE),
|
||||
TRANSLATIONS("translations", Type.NONE),
|
||||
|
||||
CREATE_GROUP("creategroup", Type.NONE, false),
|
||||
DELETE_GROUP("deletegroup", Type.NONE, false),
|
||||
LIST_GROUPS("listgroups", Type.NONE, true),
|
||||
CREATE_GROUP("creategroup", Type.NONE),
|
||||
DELETE_GROUP("deletegroup", Type.NONE),
|
||||
LIST_GROUPS("listgroups", Type.NONE),
|
||||
|
||||
CREATE_TRACK("createtrack", Type.NONE, false),
|
||||
DELETE_TRACK("deletetrack", Type.NONE, false),
|
||||
LIST_TRACKS("listtracks", Type.NONE, true),
|
||||
CREATE_TRACK("createtrack", Type.NONE),
|
||||
DELETE_TRACK("deletetrack", Type.NONE),
|
||||
LIST_TRACKS("listtracks", Type.NONE),
|
||||
|
||||
USER_INFO("info", Type.USER, true),
|
||||
USER_PERM_INFO("permission.info", Type.USER, true),
|
||||
USER_PERM_SET("permission.set", Type.USER, false),
|
||||
USER_PERM_UNSET("permission.unset", Type.USER, false),
|
||||
USER_PERM_SET_TEMP("permission.settemp", Type.USER, false),
|
||||
USER_PERM_UNSET_TEMP("permission.unsettemp", Type.USER, false),
|
||||
USER_PERM_CHECK("permission.check", Type.USER, true),
|
||||
USER_PERM_CLEAR("permission.clear", Type.USER, false),
|
||||
USER_PARENT_INFO("parent.info", Type.USER, true),
|
||||
USER_PARENT_SET("parent.set", Type.USER, false),
|
||||
USER_PARENT_SET_TRACK("parent.settrack", Type.USER, false),
|
||||
USER_PARENT_ADD("parent.add", Type.USER, false),
|
||||
USER_PARENT_REMOVE("parent.remove", Type.USER, false),
|
||||
USER_PARENT_ADD_TEMP("parent.addtemp", Type.USER, false),
|
||||
USER_PARENT_REMOVE_TEMP("parent.removetemp", Type.USER, false),
|
||||
USER_PARENT_CLEAR("parent.clear", Type.USER, false),
|
||||
USER_PARENT_CLEAR_TRACK("parent.cleartrack", Type.USER, false),
|
||||
USER_PARENT_SWITCHPRIMARYGROUP("parent.switchprimarygroup", Type.USER, false),
|
||||
USER_META_INFO("meta.info", Type.USER, true),
|
||||
USER_META_SET("meta.set", Type.USER, false),
|
||||
USER_META_UNSET("meta.unset", Type.USER, false),
|
||||
USER_META_SET_TEMP("meta.settemp", Type.USER, false),
|
||||
USER_META_UNSET_TEMP("meta.unsettemp", Type.USER, false),
|
||||
USER_META_ADD_PREFIX("meta.addprefix", Type.USER, false),
|
||||
USER_META_ADD_SUFFIX("meta.addsuffix", Type.USER, false),
|
||||
USER_META_SET_PREFIX("meta.setprefix", Type.USER, false),
|
||||
USER_META_SET_SUFFIX("meta.setsuffix", Type.USER, false),
|
||||
USER_META_REMOVE_PREFIX("meta.removeprefix", Type.USER, false),
|
||||
USER_META_REMOVE_SUFFIX("meta.removesuffix", Type.USER, false),
|
||||
USER_META_ADD_TEMP_PREFIX("meta.addtempprefix", Type.USER, false),
|
||||
USER_META_ADD_TEMP_SUFFIX("meta.addtempsuffix", Type.USER, false),
|
||||
USER_META_SET_TEMP_PREFIX("meta.settempprefix", Type.USER, false),
|
||||
USER_META_SET_TEMP_SUFFIX("meta.settempsuffix", Type.USER, false),
|
||||
USER_META_REMOVE_TEMP_PREFIX("meta.removetempprefix", Type.USER, false),
|
||||
USER_META_REMOVE_TEMP_SUFFIX("meta.removetempsuffix", Type.USER, false),
|
||||
USER_META_CLEAR("meta.clear", Type.USER, false),
|
||||
USER_EDITOR("editor", Type.USER, true),
|
||||
USER_SHOW_TRACKS("showtracks", Type.USER, true),
|
||||
USER_PROMOTE("promote", Type.USER, false),
|
||||
USER_DEMOTE("demote", Type.USER, false),
|
||||
USER_CLEAR("clear", Type.USER, false),
|
||||
USER_CLONE("clone", Type.USER, false),
|
||||
USER_INFO("info", Type.USER),
|
||||
USER_PERM_INFO("permission.info", Type.USER),
|
||||
USER_PERM_SET("permission.set", Type.USER),
|
||||
USER_PERM_UNSET("permission.unset", Type.USER),
|
||||
USER_PERM_SET_TEMP("permission.settemp", Type.USER),
|
||||
USER_PERM_UNSET_TEMP("permission.unsettemp", Type.USER),
|
||||
USER_PERM_CHECK("permission.check", Type.USER),
|
||||
USER_PERM_CLEAR("permission.clear", Type.USER),
|
||||
USER_PARENT_INFO("parent.info", Type.USER),
|
||||
USER_PARENT_SET("parent.set", Type.USER),
|
||||
USER_PARENT_SET_TRACK("parent.settrack", Type.USER),
|
||||
USER_PARENT_ADD("parent.add", Type.USER),
|
||||
USER_PARENT_REMOVE("parent.remove", Type.USER),
|
||||
USER_PARENT_ADD_TEMP("parent.addtemp", Type.USER),
|
||||
USER_PARENT_REMOVE_TEMP("parent.removetemp", Type.USER),
|
||||
USER_PARENT_CLEAR("parent.clear", Type.USER),
|
||||
USER_PARENT_CLEAR_TRACK("parent.cleartrack", Type.USER),
|
||||
USER_PARENT_SWITCHPRIMARYGROUP("parent.switchprimarygroup", Type.USER),
|
||||
USER_META_INFO("meta.info", Type.USER),
|
||||
USER_META_SET("meta.set", Type.USER),
|
||||
USER_META_UNSET("meta.unset", Type.USER),
|
||||
USER_META_SET_TEMP("meta.settemp", Type.USER),
|
||||
USER_META_UNSET_TEMP("meta.unsettemp", Type.USER),
|
||||
USER_META_ADD_PREFIX("meta.addprefix", Type.USER),
|
||||
USER_META_ADD_SUFFIX("meta.addsuffix", Type.USER),
|
||||
USER_META_SET_PREFIX("meta.setprefix", Type.USER),
|
||||
USER_META_SET_SUFFIX("meta.setsuffix", Type.USER),
|
||||
USER_META_REMOVE_PREFIX("meta.removeprefix", Type.USER),
|
||||
USER_META_REMOVE_SUFFIX("meta.removesuffix", Type.USER),
|
||||
USER_META_ADD_TEMP_PREFIX("meta.addtempprefix", Type.USER),
|
||||
USER_META_ADD_TEMP_SUFFIX("meta.addtempsuffix", Type.USER),
|
||||
USER_META_SET_TEMP_PREFIX("meta.settempprefix", Type.USER),
|
||||
USER_META_SET_TEMP_SUFFIX("meta.settempsuffix", Type.USER),
|
||||
USER_META_REMOVE_TEMP_PREFIX("meta.removetempprefix", Type.USER),
|
||||
USER_META_REMOVE_TEMP_SUFFIX("meta.removetempsuffix", Type.USER),
|
||||
USER_META_CLEAR("meta.clear", Type.USER),
|
||||
USER_EDITOR("editor", Type.USER),
|
||||
USER_SHOW_TRACKS("showtracks", Type.USER),
|
||||
USER_PROMOTE("promote", Type.USER),
|
||||
USER_DEMOTE("demote", Type.USER),
|
||||
USER_CLEAR("clear", Type.USER),
|
||||
USER_CLONE("clone", Type.USER),
|
||||
|
||||
GROUP_INFO("info", Type.GROUP, true),
|
||||
GROUP_PERM_INFO("permission.info", Type.GROUP, true),
|
||||
GROUP_PERM_SET("permission.set", Type.GROUP, false),
|
||||
GROUP_PERM_UNSET("permission.unset", Type.GROUP, false),
|
||||
GROUP_PERM_SET_TEMP("permission.settemp", Type.GROUP, false),
|
||||
GROUP_PERM_UNSET_TEMP("permission.unsettemp", Type.GROUP, false),
|
||||
GROUP_PERM_CHECK("permission.check", Type.GROUP, true),
|
||||
GROUP_PERM_CLEAR("permission.clear", Type.GROUP, false),
|
||||
GROUP_PARENT_INFO("parent.info", Type.GROUP, true),
|
||||
GROUP_PARENT_SET("parent.set", Type.GROUP, false),
|
||||
GROUP_PARENT_SET_TRACK("parent.settrack", Type.GROUP, false),
|
||||
GROUP_PARENT_ADD("parent.add", Type.GROUP, false),
|
||||
GROUP_PARENT_REMOVE("parent.remove", Type.GROUP, false),
|
||||
GROUP_PARENT_ADD_TEMP("parent.addtemp", Type.GROUP, false),
|
||||
GROUP_PARENT_REMOVE_TEMP("parent.removetemp", Type.GROUP, false),
|
||||
GROUP_PARENT_CLEAR("parent.clear", Type.GROUP, false),
|
||||
GROUP_PARENT_CLEAR_TRACK("parent.cleartrack", Type.GROUP, false),
|
||||
GROUP_META_INFO("meta.info", Type.GROUP, true),
|
||||
GROUP_META_SET("meta.set", Type.GROUP, false),
|
||||
GROUP_META_UNSET("meta.unset", Type.GROUP, false),
|
||||
GROUP_META_SET_TEMP("meta.settemp", Type.GROUP, false),
|
||||
GROUP_META_UNSET_TEMP("meta.unsettemp", Type.GROUP, false),
|
||||
GROUP_META_ADD_PREFIX("meta.addprefix", Type.GROUP, false),
|
||||
GROUP_META_ADD_SUFFIX("meta.addsuffix", Type.GROUP, false),
|
||||
GROUP_META_SET_PREFIX("meta.setprefix", Type.GROUP, false),
|
||||
GROUP_META_SET_SUFFIX("meta.setsuffix", Type.GROUP, false),
|
||||
GROUP_META_REMOVE_PREFIX("meta.removeprefix", Type.GROUP, false),
|
||||
GROUP_META_REMOVE_SUFFIX("meta.removesuffix", Type.GROUP, false),
|
||||
GROUP_META_ADD_TEMP_PREFIX("meta.addtempprefix", Type.GROUP, false),
|
||||
GROUP_META_ADD_TEMP_SUFFIX("meta.addtempsuffix", Type.GROUP, false),
|
||||
GROUP_META_SET_TEMP_PREFIX("meta.settempprefix", Type.GROUP, false),
|
||||
GROUP_META_SET_TEMP_SUFFIX("meta.settempsuffix", Type.GROUP, false),
|
||||
GROUP_META_REMOVE_TEMP_PREFIX("meta.removetempprefix", Type.GROUP, false),
|
||||
GROUP_META_REMOVE_TEMP_SUFFIX("meta.removetempsuffix", Type.GROUP, false),
|
||||
GROUP_META_CLEAR("meta.clear", Type.GROUP, false),
|
||||
GROUP_EDITOR("editor", Type.GROUP, true),
|
||||
GROUP_LIST_MEMBERS("listmembers", Type.GROUP, true),
|
||||
GROUP_SHOW_TRACKS("showtracks", Type.GROUP, true),
|
||||
GROUP_SET_WEIGHT("setweight", Type.GROUP, false),
|
||||
GROUP_SET_DISPLAY_NAME("setdisplayname", Type.GROUP, false),
|
||||
GROUP_CLEAR("clear", Type.GROUP, false),
|
||||
GROUP_RENAME("rename", Type.GROUP, false),
|
||||
GROUP_CLONE("clone", Type.GROUP, false),
|
||||
GROUP_INFO("info", Type.GROUP),
|
||||
GROUP_PERM_INFO("permission.info", Type.GROUP),
|
||||
GROUP_PERM_SET("permission.set", Type.GROUP),
|
||||
GROUP_PERM_UNSET("permission.unset", Type.GROUP),
|
||||
GROUP_PERM_SET_TEMP("permission.settemp", Type.GROUP),
|
||||
GROUP_PERM_UNSET_TEMP("permission.unsettemp", Type.GROUP),
|
||||
GROUP_PERM_CHECK("permission.check", Type.GROUP),
|
||||
GROUP_PERM_CLEAR("permission.clear", Type.GROUP),
|
||||
GROUP_PARENT_INFO("parent.info", Type.GROUP),
|
||||
GROUP_PARENT_SET("parent.set", Type.GROUP),
|
||||
GROUP_PARENT_SET_TRACK("parent.settrack", Type.GROUP),
|
||||
GROUP_PARENT_ADD("parent.add", Type.GROUP),
|
||||
GROUP_PARENT_REMOVE("parent.remove", Type.GROUP),
|
||||
GROUP_PARENT_ADD_TEMP("parent.addtemp", Type.GROUP),
|
||||
GROUP_PARENT_REMOVE_TEMP("parent.removetemp", Type.GROUP),
|
||||
GROUP_PARENT_CLEAR("parent.clear", Type.GROUP),
|
||||
GROUP_PARENT_CLEAR_TRACK("parent.cleartrack", Type.GROUP),
|
||||
GROUP_META_INFO("meta.info", Type.GROUP),
|
||||
GROUP_META_SET("meta.set", Type.GROUP),
|
||||
GROUP_META_UNSET("meta.unset", Type.GROUP),
|
||||
GROUP_META_SET_TEMP("meta.settemp", Type.GROUP),
|
||||
GROUP_META_UNSET_TEMP("meta.unsettemp", Type.GROUP),
|
||||
GROUP_META_ADD_PREFIX("meta.addprefix", Type.GROUP),
|
||||
GROUP_META_ADD_SUFFIX("meta.addsuffix", Type.GROUP),
|
||||
GROUP_META_SET_PREFIX("meta.setprefix", Type.GROUP),
|
||||
GROUP_META_SET_SUFFIX("meta.setsuffix", Type.GROUP),
|
||||
GROUP_META_REMOVE_PREFIX("meta.removeprefix", Type.GROUP),
|
||||
GROUP_META_REMOVE_SUFFIX("meta.removesuffix", Type.GROUP),
|
||||
GROUP_META_ADD_TEMP_PREFIX("meta.addtempprefix", Type.GROUP),
|
||||
GROUP_META_ADD_TEMP_SUFFIX("meta.addtempsuffix", Type.GROUP),
|
||||
GROUP_META_SET_TEMP_PREFIX("meta.settempprefix", Type.GROUP),
|
||||
GROUP_META_SET_TEMP_SUFFIX("meta.settempsuffix", Type.GROUP),
|
||||
GROUP_META_REMOVE_TEMP_PREFIX("meta.removetempprefix", Type.GROUP),
|
||||
GROUP_META_REMOVE_TEMP_SUFFIX("meta.removetempsuffix", Type.GROUP),
|
||||
GROUP_META_CLEAR("meta.clear", Type.GROUP),
|
||||
GROUP_EDITOR("editor", Type.GROUP),
|
||||
GROUP_LIST_MEMBERS("listmembers", Type.GROUP),
|
||||
GROUP_SHOW_TRACKS("showtracks", Type.GROUP),
|
||||
GROUP_SET_WEIGHT("setweight", Type.GROUP),
|
||||
GROUP_SET_DISPLAY_NAME("setdisplayname", Type.GROUP),
|
||||
GROUP_CLEAR("clear", Type.GROUP),
|
||||
GROUP_RENAME("rename", Type.GROUP),
|
||||
GROUP_CLONE("clone", Type.GROUP),
|
||||
|
||||
TRACK_INFO("info", Type.TRACK, true),
|
||||
TRACK_EDITOR("editor", Type.TRACK, true),
|
||||
TRACK_APPEND("append", Type.TRACK, false),
|
||||
TRACK_INSERT("insert", Type.TRACK, false),
|
||||
TRACK_REMOVE("remove", Type.TRACK, false),
|
||||
TRACK_CLEAR("clear", Type.TRACK, false),
|
||||
TRACK_RENAME("rename", Type.TRACK, false),
|
||||
TRACK_CLONE("clone", Type.TRACK, false),
|
||||
TRACK_INFO("info", Type.TRACK),
|
||||
TRACK_EDITOR("editor", Type.TRACK),
|
||||
TRACK_APPEND("append", Type.TRACK),
|
||||
TRACK_INSERT("insert", Type.TRACK),
|
||||
TRACK_REMOVE("remove", Type.TRACK),
|
||||
TRACK_CLEAR("clear", Type.TRACK),
|
||||
TRACK_RENAME("rename", Type.TRACK),
|
||||
TRACK_CLONE("clone", Type.TRACK),
|
||||
|
||||
LOG_RECENT("recent", Type.LOG, true),
|
||||
LOG_USER_HISTORY("userhistory", Type.LOG, true),
|
||||
LOG_GROUP_HISTORY("grouphistory", Type.LOG, true),
|
||||
LOG_TRACK_HISTORY("trackhistory", Type.LOG, true),
|
||||
LOG_SEARCH("search", Type.LOG, true),
|
||||
LOG_NOTIFY("notify", Type.LOG, true),
|
||||
LOG_RECENT("recent", Type.LOG),
|
||||
LOG_USER_HISTORY("userhistory", Type.LOG),
|
||||
LOG_GROUP_HISTORY("grouphistory", Type.LOG),
|
||||
LOG_TRACK_HISTORY("trackhistory", Type.LOG),
|
||||
LOG_SEARCH("search", Type.LOG),
|
||||
LOG_NOTIFY("notify", Type.LOG),
|
||||
|
||||
SPONGE_PERMISSION_INFO("permission.info", Type.SPONGE, true),
|
||||
SPONGE_PERMISSION_SET("permission.set", Type.SPONGE, false),
|
||||
SPONGE_PERMISSION_CLEAR("permission.clear", Type.SPONGE, false),
|
||||
SPONGE_PARENT_INFO("parent.info", Type.SPONGE, true),
|
||||
SPONGE_PARENT_ADD("parent.add", Type.SPONGE, false),
|
||||
SPONGE_PARENT_REMOVE("parent.remove", Type.SPONGE, false),
|
||||
SPONGE_PARENT_CLEAR("parent.clear", Type.SPONGE, false),
|
||||
SPONGE_OPTION_INFO("option.info", Type.SPONGE, true),
|
||||
SPONGE_OPTION_SET("option.set", Type.SPONGE, false),
|
||||
SPONGE_OPTION_UNSET("option.unset", Type.SPONGE, false),
|
||||
SPONGE_OPTION_CLEAR("option.clear", Type.SPONGE, false);
|
||||
SPONGE_PERMISSION_INFO("permission.info", Type.SPONGE),
|
||||
SPONGE_PERMISSION_SET("permission.set", Type.SPONGE),
|
||||
SPONGE_PERMISSION_CLEAR("permission.clear", Type.SPONGE),
|
||||
SPONGE_PARENT_INFO("parent.info", Type.SPONGE),
|
||||
SPONGE_PARENT_ADD("parent.add", Type.SPONGE),
|
||||
SPONGE_PARENT_REMOVE("parent.remove", Type.SPONGE),
|
||||
SPONGE_PARENT_CLEAR("parent.clear", Type.SPONGE),
|
||||
SPONGE_OPTION_INFO("option.info", Type.SPONGE),
|
||||
SPONGE_OPTION_SET("option.set", Type.SPONGE),
|
||||
SPONGE_OPTION_UNSET("option.unset", Type.SPONGE),
|
||||
SPONGE_OPTION_CLEAR("option.clear", Type.SPONGE);
|
||||
|
||||
public static final String ROOT = "luckperms.";
|
||||
|
||||
@@ -176,11 +176,9 @@ public enum CommandPermission {
|
||||
private final String permission;
|
||||
|
||||
private final Type type;
|
||||
private final boolean readOnly;
|
||||
|
||||
CommandPermission(String node, Type type, boolean readOnly) {
|
||||
CommandPermission(String node, Type type) {
|
||||
this.type = type;
|
||||
this.readOnly = readOnly;
|
||||
|
||||
if (type == Type.NONE) {
|
||||
this.node = node;
|
||||
@@ -207,10 +205,6 @@ public enum CommandPermission {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public boolean isReadOnly() {
|
||||
return this.readOnly;
|
||||
}
|
||||
|
||||
public enum Type {
|
||||
|
||||
NONE(null),
|
||||
|
||||
@@ -28,9 +28,12 @@ package me.lucko.luckperms.common.commands.group;
|
||||
import me.lucko.luckperms.common.actionlog.LoggedAction;
|
||||
import me.lucko.luckperms.common.bulkupdate.BulkUpdate;
|
||||
import me.lucko.luckperms.common.bulkupdate.BulkUpdateBuilder;
|
||||
import me.lucko.luckperms.common.bulkupdate.BulkUpdateField;
|
||||
import me.lucko.luckperms.common.bulkupdate.DataType;
|
||||
import me.lucko.luckperms.common.bulkupdate.action.DeleteAction;
|
||||
import me.lucko.luckperms.common.bulkupdate.comparison.Constraint;
|
||||
import me.lucko.luckperms.common.bulkupdate.comparison.StandardComparison;
|
||||
import me.lucko.luckperms.common.bulkupdate.query.Query;
|
||||
import me.lucko.luckperms.common.bulkupdate.query.QueryField;
|
||||
import me.lucko.luckperms.common.command.abstraction.SingleCommand;
|
||||
import me.lucko.luckperms.common.command.access.ArgumentPermissions;
|
||||
import me.lucko.luckperms.common.command.access.CommandPermission;
|
||||
@@ -40,7 +43,6 @@ import me.lucko.luckperms.common.command.tabcomplete.TabCompleter;
|
||||
import me.lucko.luckperms.common.command.tabcomplete.TabCompletions;
|
||||
import me.lucko.luckperms.common.command.utils.ArgumentList;
|
||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||
import me.lucko.luckperms.common.filter.Comparison;
|
||||
import me.lucko.luckperms.common.locale.Message;
|
||||
import me.lucko.luckperms.common.messaging.InternalMessagingService;
|
||||
import me.lucko.luckperms.common.model.Group;
|
||||
@@ -113,7 +115,7 @@ public class DeleteGroup extends SingleCommand {
|
||||
.trackStatistics(false)
|
||||
.dataType(DataType.ALL)
|
||||
.action(DeleteAction.create())
|
||||
.filter(BulkUpdateField.PERMISSION, Comparison.EQUAL, Inheritance.key(groupName))
|
||||
.query(Query.of(QueryField.PERMISSION, Constraint.of(StandardComparison.EQUAL, Inheritance.key(groupName))))
|
||||
.build();
|
||||
plugin.getStorage().applyBulkUpdate(operation).whenCompleteAsync((v, ex) -> {
|
||||
if (ex != null) {
|
||||
|
||||
+1
-1
@@ -60,7 +60,7 @@ public class GroupParentCommand extends ParentCommand<Group, String> {
|
||||
.build(key -> new ReentrantLock());
|
||||
|
||||
public GroupParentCommand() {
|
||||
super(CommandSpec.GROUP, "Group", Type.TARGETED, ImmutableList.<Command<Group>>builder()
|
||||
super(CommandSpec.GROUP, "Group", Type.TAKES_ARGUMENT_FOR_TARGET, ImmutableList.<Command<Group>>builder()
|
||||
.add(new GroupInfo())
|
||||
.add(new CommandPermission<>(HolderType.GROUP))
|
||||
.add(new CommandParent<>(HolderType.GROUP))
|
||||
|
||||
Loaded 100 of 365 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user