Compare commits
56
Commits
feat/filter
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bbe60a1bf4
|
||
|
|
06aca10e5d
|
||
|
|
625bb0c6a9 | ||
|
|
bb8fe0f528 | ||
|
|
863d10273c | ||
|
|
a57ba166ff | ||
|
|
0b91732cd3 | ||
|
|
a087f14aa2 | ||
|
|
d666a2a798 | ||
|
|
c27cfcb10b | ||
|
|
52464c6bec | ||
|
|
65c42b9b09 | ||
|
|
73d710a89e | ||
|
|
ed863b275d | ||
|
|
c20776d6aa | ||
|
|
3aca721f96 | ||
|
|
8d9c5bf401 | ||
|
|
0af1038d81 | ||
|
|
51fe574a51 | ||
|
|
bac0edd90e | ||
|
|
8ab9910ef8 | ||
|
|
9538cb9dad | ||
|
|
0486bc885b | ||
|
|
27e7551e2b | ||
|
|
b77d5759d3 | ||
|
|
96abc0d4fe | ||
|
|
1a24a6a155 | ||
|
|
95ea491787 | ||
|
|
626d08431e | ||
|
|
94e7e11183 | ||
|
|
f64bf04ba4 | ||
|
|
7744913df2 | ||
|
|
6b7283ac83 | ||
|
|
9bc8a61e2d | ||
|
|
5e24a7068c | ||
|
|
f351369a51 | ||
|
|
1bf0deb5a5 | ||
|
|
5b82837b80 | ||
|
|
0fef481d48 | ||
|
|
f2040ab815 | ||
|
|
b18717edef | ||
|
|
29c93fac4f | ||
|
|
2e67011f45 | ||
|
|
a92e04f605 | ||
|
|
8d65693d9a | ||
|
|
8973abd7f1 | ||
|
|
9420efd3ac | ||
|
|
c773126a0f | ||
|
|
9d80de5d5c | ||
|
|
9bf30fc839 | ||
|
|
136a4859f3 | ||
|
|
642f1d3019 | ||
|
|
b21753f5e9 | ||
|
|
9cc129466b | ||
|
|
55440cac01 | ||
|
|
9e7a3d26e4 |
No files matched your search
@@ -0,0 +1,6 @@
|
||||
#
|
||||
# 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
|
||||
@@ -0,0 +1,3 @@
|
||||
# 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
|
||||
@@ -1,2 +0,0 @@
|
||||
github: lucko
|
||||
patreon: luckdev
|
||||
@@ -1,63 +0,0 @@
|
||||
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
|
||||
@@ -1,5 +0,0 @@
|
||||
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!
|
||||
@@ -1,31 +0,0 @@
|
||||
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
|
||||
@@ -1,130 +0,0 @@
|
||||
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: '21'
|
||||
|
||||
- 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: Remove version number from jar artifact name
|
||||
run: mv standalone/docker/LuckPerms-Standalone-*.jar standalone/docker/luckperms-standalone.jar
|
||||
|
||||
- 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 }}
|
||||
@@ -1,26 +0,0 @@
|
||||
### :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.
|
||||
@@ -1,106 +0,0 @@
|
||||
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,5.5')
|
||||
|
||||
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/')
|
||||
}
|
||||
}
|
||||
|
||||
java {
|
||||
withJavadocJar()
|
||||
withSourcesJar()
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
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 publishing.publications.mavenJava
|
||||
required = true
|
||||
}
|
||||
}
|
||||
*/
|
||||
@@ -1,6 +1,6 @@
|
||||
<body>
|
||||
<p>
|
||||
LuckPerms is a permissions plugin for Minecraft servers. It allows server admins to control what
|
||||
LuckPerms is a permissions manager 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,6 +26,7 @@
|
||||
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;
|
||||
@@ -267,4 +268,14 @@ public interface LuckPerms {
|
||||
@Internal
|
||||
@NonNull NodeMatcherFactory getNodeMatcherFactory();
|
||||
|
||||
/**
|
||||
* Gets the {@link ActionFilterFactory}.
|
||||
*
|
||||
* @return the action filter factory
|
||||
* @since 5.5
|
||||
*/
|
||||
@Internal
|
||||
@NonNull
|
||||
ActionFilterFactory getActionFilterFactory();
|
||||
|
||||
}
|
||||
@@ -79,7 +79,8 @@ 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";
|
||||
" (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";
|
||||
|
||||
NotLoadedException() {
|
||||
super(MESSAGE);
|
||||
|
||||
@@ -28,6 +28,7 @@ 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;
|
||||
@@ -35,7 +36,10 @@ 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> {
|
||||
|
||||
/**
|
||||
@@ -81,6 +85,7 @@ public interface Action extends Comparable<Action> {
|
||||
/**
|
||||
* Represents the source of an action.
|
||||
*/
|
||||
@NonExtendable
|
||||
interface Source {
|
||||
|
||||
/**
|
||||
@@ -102,6 +107,7 @@ public interface Action extends Comparable<Action> {
|
||||
/**
|
||||
* Represents the target of an action.
|
||||
*/
|
||||
@NonExtendable
|
||||
interface Target {
|
||||
|
||||
/**
|
||||
@@ -126,7 +132,7 @@ public interface Action extends Comparable<Action> {
|
||||
@NonNull Type getType();
|
||||
|
||||
/**
|
||||
* Represents the type of a {@link Target}.
|
||||
* Represents the type of {@link Target}.
|
||||
*/
|
||||
enum Type {
|
||||
USER, GROUP, TRACK
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
package net.luckperms.api.actionlog;
|
||||
|
||||
import net.luckperms.api.actionlog.filter.ActionFilter;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.jetbrains.annotations.Unmodifiable;
|
||||
|
||||
@@ -40,7 +41,11 @@ 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,9 +25,11 @@
|
||||
|
||||
package net.luckperms.api.actionlog;
|
||||
|
||||
import net.luckperms.api.messaging.MessagingService;
|
||||
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.concurrent.CompletableFuture;
|
||||
|
||||
/**
|
||||
@@ -46,43 +48,78 @@ 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();
|
||||
|
||||
/**
|
||||
* Submits a log entry to the plugin to be handled.
|
||||
* Gets all actions from the action log matching the given {@code filter}.
|
||||
*
|
||||
* <p>This method submits the log to the storage provider and broadcasts
|
||||
* it.</p>
|
||||
* <p>If the filter is {@code null}, all actions will be returned.</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>
|
||||
* <p>Unlike {@link #queryActions(ActionFilter, int, int)}, this method does not implement any pagination and will return
|
||||
* all entries at once.</p>
|
||||
*
|
||||
* <p>If you want to submit a log entry but don't know which method to pick,
|
||||
* @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,
|
||||
* use this one.</p>
|
||||
*
|
||||
* @param entry the entry to submit
|
||||
* @return a future which will complete when the action is done
|
||||
* @return a future which will complete when the action is submitted
|
||||
*/
|
||||
@NonNull CompletableFuture<Void> submit(@NonNull Action entry);
|
||||
|
||||
/**
|
||||
* Submits a log entry to the plugins storage handler.
|
||||
* 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>
|
||||
*
|
||||
* @param entry the entry to submit
|
||||
* @return a future which will complete when the action is done
|
||||
* @return a future which will complete when the action is submitted
|
||||
*/
|
||||
@NonNull CompletableFuture<Void> submitToStorage(@NonNull Action entry);
|
||||
|
||||
/**
|
||||
* Submits a log entry to the plugins log broadcasting handler.
|
||||
* Submits a logged action to LuckPerms and broadcasts it to administrators.
|
||||
*
|
||||
* <p>If enabled, this method will also dispatch the log entry via the
|
||||
* plugins {@link MessagingService}.</p>
|
||||
* <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>
|
||||
*
|
||||
* @param entry the entry to submit
|
||||
* @return a future which will complete when the action is done
|
||||
* @return a future which will complete when the action is broadcasted
|
||||
*/
|
||||
@NonNull CompletableFuture<Void> broadcastAction(@NonNull Action entry);
|
||||
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 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);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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;
|
||||
@@ -26,7 +26,6 @@
|
||||
package net.luckperms.api.event.sync;
|
||||
|
||||
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;
|
||||
|
||||
@@ -63,6 +63,7 @@ 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,6 +67,7 @@ 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,6 +71,7 @@ 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,6 +88,7 @@ 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,6 +75,7 @@ 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,6 +76,7 @@ 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}.
|
||||
* {@code predicate} (commonly one of the values in {@link DataTypeFilter}).
|
||||
*
|
||||
* @param predicate the predicate
|
||||
* @return the data type filter function
|
||||
|
||||
+24
-13
@@ -23,20 +23,31 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.fabric.event;
|
||||
package net.luckperms.api.util;
|
||||
|
||||
import net.fabricmc.fabric.api.event.Event;
|
||||
import net.fabricmc.fabric.api.event.EventFactory;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
// TODO: Use Fabric API alternative when merged.
|
||||
public interface PlayerChangeWorldCallback {
|
||||
Event<PlayerChangeWorldCallback> EVENT = EventFactory.createArrayBacked(PlayerChangeWorldCallback.class, callbacks -> (originalWorld, destination, player) -> {
|
||||
for (PlayerChangeWorldCallback callback : callbacks) {
|
||||
callback.onChangeWorld(originalWorld, destination, player);
|
||||
}
|
||||
});
|
||||
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();
|
||||
|
||||
void onChangeWorld(ServerWorld originalWorld, ServerWorld destination, ServerPlayerEntity player);
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
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 {
|
||||
// Fix issue with lwjgl-freetype not being found on macOS / ForgeGradle issue
|
||||
//
|
||||
// Could not resolve all files for configuration ':_compileJava_1'.
|
||||
// Could not find lwjgl-freetype-3.3.3-natives-macos-patch.jar (org.lwjgl:lwjgl-freetype:3.3.3).
|
||||
maven {
|
||||
url "https://libraries.minecraft.net"
|
||||
content {
|
||||
includeModule("org.lwjgl", "lwjgl-freetype")
|
||||
}
|
||||
}
|
||||
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/' }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,348 @@
|
||||
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")) }
|
||||
@@ -1,45 +0,0 @@
|
||||
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
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
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
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
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.3.3') {
|
||||
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
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
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-${project.ext.fullVersion}.jar"
|
||||
|
||||
from {
|
||||
project(':bukkit').tasks.shadowJar.archiveFile
|
||||
}
|
||||
|
||||
manifest {
|
||||
attributes(["paperweight-mappings-namespace": "mojang"])
|
||||
}
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives shadowJar
|
||||
}
|
||||
@@ -307,7 +307,7 @@ public class LPBukkitBootstrap implements LuckPermsBootstrap, LoaderBootstrap, B
|
||||
try {
|
||||
Class.forName("com.google.gson.JsonElement");
|
||||
return false;
|
||||
} catch (ClassNotFoundException e) {
|
||||
} catch (Exception e) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,10 +221,12 @@ public class LPBukkitPlugin extends AbstractLuckPermsPlugin {
|
||||
* - https://hub.spigotmc.org/jira/browse/SPIGOT-5546
|
||||
* - https://github.com/PaperMC/Paper/pull/3509
|
||||
*/
|
||||
PluginManagerUtil.injectDependency(this.bootstrap.getServer().getPluginManager(), this.bootstrap.getLoader().getName(), "Vault");
|
||||
if (getConfiguration().get(ConfigKeys.VAULT_ENABLED)) {
|
||||
PluginManagerUtil.injectDependency(this.bootstrap.getServer().getPluginManager(), this.bootstrap.getLoader().getName(), "Vault");
|
||||
|
||||
// Provide vault support
|
||||
tryVaultHook(false);
|
||||
// Provide vault support
|
||||
tryVaultHook(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -237,6 +239,10 @@ 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);
|
||||
@@ -347,7 +353,7 @@ public class LPBukkitPlugin extends AbstractLuckPermsPlugin {
|
||||
try {
|
||||
Class.forName(className);
|
||||
return true;
|
||||
} catch (ClassNotFoundException e) {
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,85 +25,46 @@
|
||||
|
||||
package me.lucko.luckperms.bukkit.context;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
|
||||
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 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 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 ContextManager<Player, Player> {
|
||||
public class BukkitContextManager extends DetachedContextManager<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 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);
|
||||
public @Nullable QueryOptionsSupplier getQueryOptionsSupplier(Player subject) {
|
||||
Objects.requireNonNull(subject, "subject");
|
||||
LuckPermsPermissible permissible = PermissibleInjector.get(subject);
|
||||
if (permissible != null) {
|
||||
return permissible.getQueryOptionsSupplier();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
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();
|
||||
public void customizeQueryOptions(Player subject, QueryOptions.Builder builder) {
|
||||
if (subject.isOp()) {
|
||||
queryOptions.option(OP_OPTION, true);
|
||||
builder.option(OP_OPTION, true);
|
||||
}
|
||||
|
||||
return queryOptions.context(contextSet).build();
|
||||
}
|
||||
}
|
||||
+11
-9
@@ -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.QueryOptionsCache;
|
||||
import me.lucko.luckperms.common.context.manager.QueryOptionsSupplier;
|
||||
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,
|
||||
* is is safe to call Player#hasPermission asynchronously.
|
||||
* it 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 QueryOptionsCache<Player> queryOptionsSupplier;
|
||||
private final QueryOptionsSupplier 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().getCacheFor(player);
|
||||
this.queryOptionsSupplier = plugin.getContextManager().createQueryOptionsSupplier(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.invalidate();
|
||||
this.queryOptionsSupplier.invalidateCache();
|
||||
}
|
||||
|
||||
// but we don't need to do anything else in this method, unlike the CB impl.
|
||||
@@ -316,6 +316,10 @@ public class LuckPermsPermissible extends PermissibleBase {
|
||||
return this.plugin;
|
||||
}
|
||||
|
||||
public QueryOptionsSupplier getQueryOptionsSupplier() {
|
||||
return this.queryOptionsSupplier;
|
||||
}
|
||||
|
||||
PermissibleBase getOldPermissible() {
|
||||
return this.oldPermissible;
|
||||
}
|
||||
@@ -409,9 +413,7 @@ 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,6 +30,7 @@ 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;
|
||||
@@ -161,6 +162,19 @@ 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,9 +253,6 @@ 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);
|
||||
}
|
||||
|
||||
|
||||
+23
-2
@@ -36,13 +36,26 @@ 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 final LPBukkitPlugin plugin;
|
||||
|
||||
public BukkitPlatformListener(LPBukkitPlugin plugin) {
|
||||
@@ -81,7 +94,15 @@ public class BukkitPlatformListener implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onPluginEnable(PluginEnableEvent e) {
|
||||
if (e.getPlugin().getName().equalsIgnoreCase("Vault")) {
|
||||
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) {
|
||||
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: false
|
||||
use-server-uuid-cache: true
|
||||
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ use-server-uuid-cache: false
|
||||
#
|
||||
# - A H2 database is the default option.
|
||||
# - If you want to edit data manually in "traditional" storage files, we suggest using YAML.
|
||||
storage-method: h2
|
||||
storage-method: postgresql
|
||||
|
||||
# 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: minecraft
|
||||
database: luckperms
|
||||
|
||||
# Credentials for the database.
|
||||
username: root
|
||||
password: ''
|
||||
username: '^{POSTGRES_USER}'
|
||||
password: '^{POSTGRES_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: 0
|
||||
keepalive-time: 120000
|
||||
|
||||
# This setting controls the maximum number of milliseconds that the plugin will wait for a
|
||||
# connection from the pool, before timing out.
|
||||
connection-timeout: 5000 # 5 seconds
|
||||
connection-timeout: 10000 # 10 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: true
|
||||
watch-files: false
|
||||
|
||||
# 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: true
|
||||
broadcast-received-log-entries: false
|
||||
|
||||
# Settings for Redis.
|
||||
# Settings for Keydb.
|
||||
# Port 6379 is used by default; set address to "host:port" if differs
|
||||
# Multiple Redis nodes can be specified in the same format as a string list under the name "addresses".
|
||||
# Multiple Keydb nodes can be specified in the same format as a string list under the name "addresses".
|
||||
redis:
|
||||
enabled: false
|
||||
enabled: true
|
||||
address: localhost
|
||||
username: ''
|
||||
password: ''
|
||||
username: 'default'
|
||||
password: 'bookchin'
|
||||
|
||||
# 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: false
|
||||
require-sender-group-membership-to-modify: true
|
||||
|
||||
# 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,8 +627,19 @@ 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
|
||||
@@ -719,3 +730,33 @@ 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
|
||||
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
|
||||
@@ -1,47 +0,0 @@
|
||||
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.3.3') {
|
||||
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
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
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 (ClassNotFoundException e) {
|
||||
} catch (Exception e) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,25 +25,13 @@
|
||||
|
||||
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.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 me.lucko.luckperms.common.context.manager.SimpleContextManager;
|
||||
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);
|
||||
}
|
||||
@@ -52,35 +40,4 @@ public class BungeeContextManager extends ContextManager<ProxiedPlayer, ProxiedP
|
||||
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,3 +611,33 @@ 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
|
||||
@@ -1,93 +0,0 @@
|
||||
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:5.11.0'
|
||||
testImplementation 'org.mockito:mockito-junit-jupiter:5.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'
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
// nothing special to do here (yet)!
|
||||
@@ -1,108 +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;
|
||||
|
||||
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,12 +29,14 @@ 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 {
|
||||
@@ -64,7 +66,12 @@ public class LogDispatcher {
|
||||
return !this.plugin.getEventDispatcher().dispatchLogBroadcast(cancelled, entry, origin);
|
||||
}
|
||||
|
||||
private void broadcast(LoggedAction entry, LogNotifyEvent.Origin origin, Sender sender) {
|
||||
// broadcast the entry to online players
|
||||
private void broadcast(LoggedAction entry, LogBroadcastEvent.Origin broadcastOrigin, LogNotifyEvent.Origin origin, Sender sender) {
|
||||
if (!shouldBroadcast(entry, broadcastOrigin)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.plugin.getOnlineSenders()
|
||||
.filter(CommandPermission.LOG_NOTIFY::isAuthorized)
|
||||
.filter(s -> {
|
||||
@@ -74,41 +81,46 @@ public class LogDispatcher {
|
||||
.forEach(s -> Message.LOG.send(s, entry));
|
||||
}
|
||||
|
||||
public void dispatch(LoggedAction entry, Sender sender) {
|
||||
// log the entry to storage
|
||||
public CompletableFuture<Void> logToStorage(LoggedAction entry) {
|
||||
if (!this.plugin.getEventDispatcher().dispatchLogPublish(false, entry)) {
|
||||
this.plugin.getStorage().logAction(entry);
|
||||
return this.plugin.getStorage().logAction(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 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);
|
||||
}
|
||||
}
|
||||
|
||||
// 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) {
|
||||
this.plugin.getMessagingService().ifPresent(extendedMessagingService -> extendedMessagingService.pushLog(entry));
|
||||
|
||||
if (shouldBroadcast(entry, LogBroadcastEvent.Origin.LOCAL_API)) {
|
||||
broadcast(entry, LogNotifyEvent.Origin.LOCAL_API, null);
|
||||
}
|
||||
broadcast(entry, LogBroadcastEvent.Origin.LOCAL_API, LogNotifyEvent.Origin.LOCAL_API, 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);
|
||||
}
|
||||
public void broadcastFromRemote(LoggedAction entry) {
|
||||
broadcast(entry, LogBroadcastEvent.Origin.REMOTE, LogNotifyEvent.Origin.REMOTE, null);
|
||||
}
|
||||
}
|
||||
+30
-34
@@ -23,54 +23,50 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.util;
|
||||
package me.lucko.luckperms.common.actionlog;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import me.lucko.luckperms.common.filter.PageParameters;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* A simple pagination utility
|
||||
*
|
||||
* @param <T> the element type
|
||||
*/
|
||||
public class Paginated<T> {
|
||||
private final List<T> content;
|
||||
|
||||
public Paginated(Collection<T> content) {
|
||||
this.content = ImmutableList.copyOf(content);
|
||||
public class LogPage {
|
||||
public static LogPage of(List<LoggedAction> content, @Nullable PageParameters params, int totalEntries) {
|
||||
return new LogPage(content, params, totalEntries);
|
||||
}
|
||||
|
||||
public List<T> getContent() {
|
||||
private final List<LoggedAction> content;
|
||||
private final @Nullable PageParameters params;
|
||||
private final int totalEntries;
|
||||
|
||||
LogPage(List<LoggedAction> content, @Nullable PageParameters params, int totalEntries) {
|
||||
this.content = ImmutableList.copyOf(content);
|
||||
this.params = params;
|
||||
this.totalEntries = totalEntries;
|
||||
}
|
||||
|
||||
public List<LoggedAction> getContent() {
|
||||
return this.content;
|
||||
}
|
||||
|
||||
public int getMaxPages(int entriesPerPage) {
|
||||
return (int) Math.ceil((double) this.content.size() / (double) entriesPerPage);
|
||||
public List<Entry<LoggedAction>> getNumberedContent() {
|
||||
int startIndex = this.params != null
|
||||
? this.params.pageSize() * (this.params.pageNumber() - 1)
|
||||
: 0;
|
||||
|
||||
List<Entry<LoggedAction>> numberedContent = new ArrayList<>();
|
||||
for (int i = 0; i < this.content.size(); i++) {
|
||||
int index = startIndex + i + 1;
|
||||
numberedContent.add(new Entry<>(index, this.content.get(i)));
|
||||
}
|
||||
return numberedContent;
|
||||
}
|
||||
|
||||
public List<Entry<T>> getPage(int pageNo, int pageSize) {
|
||||
if (pageNo < 1) {
|
||||
throw new IllegalArgumentException("pageNo cannot be less than 1: " + pageNo);
|
||||
}
|
||||
|
||||
int first = (pageNo - 1) * pageSize;
|
||||
if (this.content.size() <= first) {
|
||||
throw new IllegalStateException("Content does not contain that many elements. (requested page: " + pageNo +
|
||||
", page size: " + pageSize + ", page first index: " + first + ", content size: " + this.content.size() + ")");
|
||||
}
|
||||
|
||||
int last = first + pageSize - 1;
|
||||
List<Entry<T>> out = new ArrayList<>(pageSize);
|
||||
|
||||
for (int i = first; i <= last && i < this.content.size(); i++) {
|
||||
out.add(new Entry<>(i + 1, this.content.get(i)));
|
||||
}
|
||||
|
||||
return out;
|
||||
public int getTotalEntries() {
|
||||
return this.totalEntries;
|
||||
}
|
||||
|
||||
public static final class Entry<T> {
|
||||
@@ -26,6 +26,7 @@
|
||||
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;
|
||||
@@ -44,10 +45,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},
|
||||
@@ -123,15 +124,11 @@ 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) {
|
||||
plugin.getLogDispatcher().dispatch(this, sender);
|
||||
CompletableFuture<Void> future = plugin.getLogDispatcher().dispatch(this, sender);
|
||||
if (plugin.getConfiguration().get(ConfigKeys.LOG_SYNCHRONOUSLY_IN_COMMANDS)) {
|
||||
future.join();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -393,14 +390,14 @@ public class LoggedAction implements Action {
|
||||
}
|
||||
}
|
||||
|
||||
public static char getTypeCharacter(Target.Type type) {
|
||||
public static String getTypeString(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();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* 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,6 +25,7 @@
|
||||
|
||||
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;
|
||||
@@ -47,6 +48,7 @@ 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;
|
||||
@@ -225,4 +227,8 @@ public class LuckPermsApiProvider implements LuckPerms {
|
||||
return ApiNodeMatcherFactory.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull ActionFilterFactory getActionFilterFactory() {
|
||||
return ApiActionFilterFactory.INSTANCE;
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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));
|
||||
}
|
||||
|
||||
}
|
||||
+24
-11
@@ -25,50 +25,63 @@
|
||||
|
||||
package me.lucko.luckperms.common.api.implementation;
|
||||
|
||||
import me.lucko.luckperms.common.actionlog.Log;
|
||||
import me.lucko.luckperms.common.api.ApiUtils;
|
||||
import com.google.common.collect.ImmutableSortedSet;
|
||||
import me.lucko.luckperms.common.actionlog.LoggedAction;
|
||||
import me.lucko.luckperms.common.util.ImmutableCollectors;
|
||||
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;
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
@Deprecated
|
||||
public class ApiActionLog implements ActionLog {
|
||||
private final Log handle;
|
||||
private final SortedSet<Action> content;
|
||||
|
||||
public ApiActionLog(Log handle) {
|
||||
this.handle = handle;
|
||||
public ApiActionLog(List<LoggedAction> content) {
|
||||
this.content = ImmutableSortedSet.copyOf(content);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull SortedSet<Action> getContent() {
|
||||
return (SortedSet) this.handle.getContent();
|
||||
return this.content;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull SortedSet<Action> getContent(@NonNull UUID actor) {
|
||||
Objects.requireNonNull(actor, "actor");
|
||||
return (SortedSet) this.handle.getContent(actor);
|
||||
return this.content.stream()
|
||||
.filter(e -> e.getSource().getUniqueId().equals(actor))
|
||||
.collect(ImmutableCollectors.toSortedSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull SortedSet<Action> getUserHistory(@NonNull UUID uniqueId) {
|
||||
Objects.requireNonNull(uniqueId, "uuid");
|
||||
return (SortedSet) this.handle.getUserHistory(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());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull SortedSet<Action> getGroupHistory(@NonNull String name) {
|
||||
Objects.requireNonNull(name, "name");
|
||||
return (SortedSet) this.handle.getGroupHistory(ApiUtils.checkName(name));
|
||||
return this.content.stream()
|
||||
.filter(e -> e.getTarget().getType() == Action.Target.Type.GROUP)
|
||||
.filter(e -> e.getTarget().getName().equals(name))
|
||||
.collect(ImmutableCollectors.toSortedSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull SortedSet<Action> getTrackHistory(@NonNull String name) {
|
||||
Objects.requireNonNull(name, "name");
|
||||
return (SortedSet) this.handle.getTrackHistory(ApiUtils.checkName(name));
|
||||
return this.content.stream()
|
||||
.filter(e -> e.getTarget().getType() == Action.Target.Type.TRACK)
|
||||
.filter(e -> e.getTarget().getName().equals(name))
|
||||
.collect(ImmutableCollectors.toSortedSet());
|
||||
}
|
||||
}
|
||||
+57
-4
@@ -25,13 +25,22 @@
|
||||
|
||||
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 {
|
||||
@@ -47,22 +56,66 @@ public class ApiActionLogger implements ActionLogger {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public @NonNull CompletableFuture<ActionLog> getLog() {
|
||||
return this.plugin.getStorage().getLog().thenApply(ApiActionLog::new);
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull CompletableFuture<Void> submit(@NonNull Action entry) {
|
||||
return CompletableFuture.runAsync(() -> this.plugin.getLogDispatcher().dispatchFromApi((LoggedAction) entry), this.plugin.getBootstrap().getScheduler().async());
|
||||
return this.plugin.getLogDispatcher().dispatchFromApi((LoggedAction) entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull CompletableFuture<Void> submitToStorage(@NonNull Action entry) {
|
||||
return this.plugin.getStorage().logAction(entry);
|
||||
return this.plugin.getLogDispatcher().logToStorage((LoggedAction) entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull CompletableFuture<Void> broadcastAction(@NonNull Action entry) {
|
||||
return CompletableFuture.runAsync(() -> this.plugin.getLogDispatcher().broadcastFromApi((LoggedAction) entry), this.plugin.getBootstrap().getScheduler().async());
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -26,8 +26,8 @@
|
||||
package me.lucko.luckperms.common.api.implementation;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import me.lucko.luckperms.common.metastacking.SimpleMetaStackDefinition;
|
||||
import me.lucko.luckperms.common.metastacking.StandardStackElements;
|
||||
import me.lucko.luckperms.common.cacheddata.metastack.SimpleMetaStackDefinition;
|
||||
import me.lucko.luckperms.common.cacheddata.metastack.StandardStackElements;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import net.luckperms.api.metastacking.DuplicateRemovalFunction;
|
||||
import net.luckperms.api.metastacking.MetaStackDefinition;
|
||||
|
||||
@@ -25,14 +25,13 @@
|
||||
|
||||
package me.lucko.luckperms.common.bulkupdate;
|
||||
|
||||
import me.lucko.luckperms.common.bulkupdate.action.Action;
|
||||
import me.lucko.luckperms.common.bulkupdate.query.Query;
|
||||
import me.lucko.luckperms.common.bulkupdate.action.BulkUpdateAction;
|
||||
import me.lucko.luckperms.common.filter.FilterList;
|
||||
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;
|
||||
|
||||
@@ -46,35 +45,30 @@ public final class BulkUpdate {
|
||||
private final DataType dataType;
|
||||
|
||||
// the action to apply to the data which matches the constraints
|
||||
private final Action action;
|
||||
private final BulkUpdateAction action;
|
||||
|
||||
// a set of constraints which data must match to be acted upon
|
||||
private final List<Query> queries;
|
||||
// a set of filters which data must match to be acted upon
|
||||
private final FilterList<Node> filters;
|
||||
|
||||
// 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, Action action, List<Query> queries, boolean trackStatistics) {
|
||||
public BulkUpdate(DataType dataType, BulkUpdateAction action, FilterList<Node> filters, boolean trackStatistics) {
|
||||
this.dataType = dataType;
|
||||
this.action = action;
|
||||
this.queries = queries;
|
||||
this.filters = filters;
|
||||
this.trackStatistics = trackStatistics;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if a Node instance satisfies the constrints of this query
|
||||
* Check to see if a Node instance satisfies the constraints of this query
|
||||
*
|
||||
* @param node the node to check
|
||||
* @return true if satisfied
|
||||
*/
|
||||
public boolean satisfiesConstraints(Node node) {
|
||||
for (Query query : this.queries) {
|
||||
if (!query.isSatisfiedBy(node)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
public boolean satisfiesFilters(Node node) {
|
||||
return this.filters.evaluate(node);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -84,7 +78,7 @@ public final class BulkUpdate {
|
||||
* @return the transformed node, or null if the node should be deleted
|
||||
*/
|
||||
private Node apply(Node node) {
|
||||
if (!satisfiesConstraints(node)) {
|
||||
if (!satisfiesFilters(node)) {
|
||||
return node; // make no change
|
||||
}
|
||||
|
||||
@@ -129,63 +123,16 @@ 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 Action getAction() {
|
||||
public BulkUpdateAction getAction() {
|
||||
return this.action;
|
||||
}
|
||||
|
||||
public List<Query> getQueries() {
|
||||
return this.queries;
|
||||
public FilterList<Node> getFilters() {
|
||||
return this.filters;
|
||||
}
|
||||
|
||||
public boolean isTrackingStatistics() {
|
||||
@@ -204,12 +151,12 @@ public final class BulkUpdate {
|
||||
|
||||
return this.getDataType() == that.getDataType() &&
|
||||
Objects.equals(this.getAction(), that.getAction()) &&
|
||||
Objects.equals(this.getQueries(), that.getQueries());
|
||||
Objects.equals(this.getFilters(), that.getFilters());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(getDataType(), getAction(), getQueries(), isTrackingStatistics());
|
||||
return Objects.hash(getDataType(), getAction(), getFilters(), isTrackingStatistics());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -217,7 +164,7 @@ public final class BulkUpdate {
|
||||
return "BulkUpdate(" +
|
||||
"dataType=" + this.getDataType() + ", " +
|
||||
"action=" + this.getAction() + ", " +
|
||||
"constraints=" + this.getQueries() + ", " +
|
||||
"constraints=" + this.getFilters() + ", " +
|
||||
"trackStatistics=" + this.isTrackingStatistics() + ")";
|
||||
}
|
||||
}
|
||||
@@ -26,8 +26,12 @@
|
||||
package me.lucko.luckperms.common.bulkupdate;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import me.lucko.luckperms.common.bulkupdate.action.Action;
|
||||
import me.lucko.luckperms.common.bulkupdate.query.Query;
|
||||
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 java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
@@ -45,18 +49,18 @@ public class BulkUpdateBuilder {
|
||||
private DataType dataType = DataType.ALL;
|
||||
|
||||
// the action to apply to the data which matches the constraints
|
||||
private Action action = null;
|
||||
private BulkUpdateAction action = null;
|
||||
|
||||
// should the operation count the number of affected nodes, users and groups
|
||||
private boolean trackStatistics = false;
|
||||
|
||||
// a set of constraints which data must match to be acted upon
|
||||
private final Set<Query> queries = new LinkedHashSet<>();
|
||||
// a set of filters which data must match to be acted upon
|
||||
private final Set<Filter<Node, String>> filters = new LinkedHashSet<>();
|
||||
|
||||
private BulkUpdateBuilder() {
|
||||
}
|
||||
|
||||
public BulkUpdateBuilder action(Action action) {
|
||||
public BulkUpdateBuilder action(BulkUpdateAction action) {
|
||||
this.action = action;
|
||||
return this;
|
||||
}
|
||||
@@ -71,8 +75,8 @@ public class BulkUpdateBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public BulkUpdateBuilder query(Query query) {
|
||||
this.queries.add(query);
|
||||
public BulkUpdateBuilder filter(BulkUpdateField field, Comparison comparison, String value) {
|
||||
this.filters.add(new Filter<>(field, ConstraintFactory.STRINGS.build(comparison, value)));
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -81,7 +85,8 @@ public class BulkUpdateBuilder {
|
||||
throw new IllegalStateException("no action specified");
|
||||
}
|
||||
|
||||
return new BulkUpdate(this.dataType, this.action, ImmutableList.copyOf(this.queries), this.trackStatistics);
|
||||
FilterList<Node> filters = new FilterList<>(FilterList.LogicalOperator.AND, ImmutableList.copyOf(this.filters));
|
||||
return new BulkUpdate(this.dataType, this.action, filters, this.trackStatistics);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -89,7 +94,7 @@ public class BulkUpdateBuilder {
|
||||
return "BulkUpdateBuilder(" +
|
||||
"dataType=" + this.dataType + ", " +
|
||||
"action=" + this.action + ", " +
|
||||
"constraints=" + this.queries + ", " +
|
||||
"constraints=" + this.filters + ", " +
|
||||
"trackStatistics=" + this.trackStatistics + ")";
|
||||
}
|
||||
}
|
||||
+31
-21
@@ -23,35 +23,45 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.plugin.classpath;
|
||||
package me.lucko.luckperms.common.bulkupdate;
|
||||
|
||||
import me.lucko.luckperms.common.plugin.bootstrap.LuckPermsBootstrap;
|
||||
import me.lucko.luckperms.common.filter.FilterField;
|
||||
import net.luckperms.api.context.DefaultContextKeys;
|
||||
import net.luckperms.api.node.Node;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URLClassLoader;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Locale;
|
||||
|
||||
public class ReflectionClassPathAppender implements ClassPathAppender {
|
||||
private final URLClassLoaderAccess classLoaderAccess;
|
||||
/**
|
||||
* Represents a field being used in a bulk update
|
||||
*/
|
||||
public enum BulkUpdateField implements FilterField<Node, String> {
|
||||
|
||||
public ReflectionClassPathAppender(ClassLoader classLoader) throws IllegalStateException {
|
||||
if (classLoader instanceof URLClassLoader) {
|
||||
this.classLoaderAccess = URLClassLoaderAccess.create((URLClassLoader) classLoader);
|
||||
} else {
|
||||
throw new IllegalStateException("ClassLoader is not instance of URLClassLoader");
|
||||
PERMISSION {
|
||||
@Override
|
||||
public String getValue(Node node) {
|
||||
return node.getKey();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
public ReflectionClassPathAppender(LuckPermsBootstrap bootstrap) throws IllegalStateException {
|
||||
this(bootstrap.getClass().getClassLoader());
|
||||
}
|
||||
SERVER {
|
||||
@Override
|
||||
public String getValue(Node node) {
|
||||
return node.getContexts().getAnyValue(DefaultContextKeys.SERVER_KEY).orElse("global");
|
||||
}
|
||||
},
|
||||
|
||||
@Override
|
||||
public void addJarToClasspath(Path file) {
|
||||
WORLD {
|
||||
@Override
|
||||
public String getValue(Node node) {
|
||||
return node.getContexts().getAnyValue(DefaultContextKeys.WORLD_KEY).orElse("global");
|
||||
}
|
||||
};
|
||||
|
||||
public static BulkUpdateField of(String s) {
|
||||
try {
|
||||
this.classLoaderAccess.addURL(file.toUri().toURL());
|
||||
} catch (MalformedURLException e) {
|
||||
throw new RuntimeException(e);
|
||||
return valueOf(s.toUpperCase(Locale.ROOT));
|
||||
} catch (IllegalArgumentException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+2
-12
@@ -25,13 +25,12 @@
|
||||
|
||||
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 Action {
|
||||
public interface BulkUpdateAction {
|
||||
|
||||
/**
|
||||
* Gets the name of this action
|
||||
@@ -44,17 +43,8 @@ public interface Action {
|
||||
* Applies this action to the given NodeModel, and returns the result.
|
||||
*
|
||||
* @param from the node to base changes from
|
||||
* @return the new nodemodel instance, or null if the node should be deleted.
|
||||
* @return the new node 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,10 +25,9 @@
|
||||
|
||||
package me.lucko.luckperms.common.bulkupdate.action;
|
||||
|
||||
import me.lucko.luckperms.common.bulkupdate.PreparedStatementBuilder;
|
||||
import net.luckperms.api.node.Node;
|
||||
|
||||
public class DeleteAction implements Action {
|
||||
public class DeleteAction implements BulkUpdateAction {
|
||||
|
||||
public static DeleteAction create() {
|
||||
return new DeleteAction();
|
||||
@@ -46,9 +45,4 @@ public class DeleteAction implements Action {
|
||||
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}");
|
||||
}
|
||||
}
|
||||
+20
-19
@@ -25,28 +25,27 @@
|
||||
|
||||
package me.lucko.luckperms.common.bulkupdate.action;
|
||||
|
||||
import me.lucko.luckperms.common.bulkupdate.PreparedStatementBuilder;
|
||||
import me.lucko.luckperms.common.bulkupdate.query.QueryField;
|
||||
import me.lucko.luckperms.common.bulkupdate.BulkUpdateField;
|
||||
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 Action {
|
||||
public class UpdateAction implements BulkUpdateAction {
|
||||
|
||||
public static UpdateAction of(QueryField field, String value) {
|
||||
public static UpdateAction of(BulkUpdateField field, String value) {
|
||||
return new UpdateAction(field, value);
|
||||
}
|
||||
|
||||
// the field we're updating
|
||||
private final QueryField field;
|
||||
private final BulkUpdateField field;
|
||||
|
||||
// the new value of the field
|
||||
private final String value;
|
||||
private final String newValue;
|
||||
|
||||
private UpdateAction(QueryField field, String value) {
|
||||
private UpdateAction(BulkUpdateField field, String newValue) {
|
||||
this.field = field;
|
||||
this.value = value;
|
||||
this.newValue = newValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -54,11 +53,19 @@ public class UpdateAction implements Action {
|
||||
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.value)
|
||||
return NodeBuilders.determineMostApplicable(this.newValue)
|
||||
.value(from.getValue())
|
||||
.expiry(from.getExpiry())
|
||||
.context(from.getContexts())
|
||||
@@ -66,8 +73,8 @@ public class UpdateAction implements Action {
|
||||
case SERVER: {
|
||||
MutableContextSet contexts = from.getContexts().mutableCopy();
|
||||
contexts.removeAll(DefaultContextKeys.SERVER_KEY);
|
||||
if (!this.value.equals("global")) {
|
||||
contexts.add(DefaultContextKeys.SERVER_KEY, this.value);
|
||||
if (!this.newValue.equals("global")) {
|
||||
contexts.add(DefaultContextKeys.SERVER_KEY, this.newValue);
|
||||
}
|
||||
|
||||
return from.toBuilder()
|
||||
@@ -77,8 +84,8 @@ public class UpdateAction implements Action {
|
||||
case WORLD: {
|
||||
MutableContextSet contexts = from.getContexts().mutableCopy();
|
||||
contexts.removeAll(DefaultContextKeys.WORLD_KEY);
|
||||
if (!this.value.equals("global")) {
|
||||
contexts.add(DefaultContextKeys.WORLD_KEY, this.value);
|
||||
if (!this.newValue.equals("global")) {
|
||||
contexts.add(DefaultContextKeys.WORLD_KEY, this.newValue);
|
||||
}
|
||||
|
||||
return from.toBuilder()
|
||||
@@ -89,10 +96,4 @@ public class UpdateAction implements Action {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendSql(PreparedStatementBuilder builder) {
|
||||
builder.append("UPDATE {table} SET " + this.field.getSqlName() + "=");
|
||||
builder.variable(this.value);
|
||||
}
|
||||
}
|
||||
-112
@@ -1,112 +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.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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,83 +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.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;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -193,7 +193,7 @@ public abstract class AbstractCachedDataManager implements CachedDataManager {
|
||||
}
|
||||
|
||||
public void cleanup() {
|
||||
this.cache.values().removeIf(value -> ((UsageTracked) value).usedSince(TimeUnit.MINUTES.toMillis(2)));
|
||||
this.cache.values().removeIf(value -> !((UsageTracked) value).usedInTheLast(2, TimeUnit.MINUTES));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -25,14 +25,20 @@
|
||||
|
||||
package me.lucko.luckperms.common.cacheddata;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public abstract class UsageTracked {
|
||||
private long lastUsed = System.currentTimeMillis();
|
||||
|
||||
@VisibleForTesting
|
||||
protected long lastUsed = System.currentTimeMillis();
|
||||
|
||||
public void recordUsage() {
|
||||
this.lastUsed = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public boolean usedSince(long duration) {
|
||||
return this.lastUsed > System.currentTimeMillis() - duration;
|
||||
public boolean usedInTheLast(long duration, TimeUnit unit) {
|
||||
return this.lastUsed > System.currentTimeMillis() - unit.toMillis(duration);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -23,7 +23,7 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.metastacking;
|
||||
package me.lucko.luckperms.common.cacheddata.metastack;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
+1
-1
@@ -23,7 +23,7 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.metastacking;
|
||||
package me.lucko.luckperms.common.cacheddata.metastack;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import net.luckperms.api.metastacking.DuplicateRemovalFunction;
|
||||
+10
-4
@@ -23,7 +23,7 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.metastacking;
|
||||
package me.lucko.luckperms.common.cacheddata.metastack;
|
||||
|
||||
import me.lucko.luckperms.common.model.Track;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
@@ -220,8 +220,11 @@ public final class StandardStackElements {
|
||||
@Override
|
||||
public boolean shouldAccumulate(@NonNull ChatMetaType type, @NonNull ChatMetaNode<?, ?> node, @Nullable ChatMetaNode<?, ?> current) {
|
||||
Track track = this.plugin.getTrackManager().getIfLoaded(this.trackName);
|
||||
if (track == null) {
|
||||
return false;
|
||||
}
|
||||
PermissionHolder.Identifier origin = node.metadata(InheritanceOriginMetadata.KEY).getOrigin();
|
||||
return track != null && origin.getType().equals(PermissionHolder.Identifier.GROUP_TYPE) && track.containsGroup(origin.getName());
|
||||
return origin.getType().equals(PermissionHolder.Identifier.GROUP_TYPE) && track.containsGroup(origin.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -250,8 +253,11 @@ public final class StandardStackElements {
|
||||
@Override
|
||||
public boolean shouldAccumulate(@NonNull ChatMetaType type, @NonNull ChatMetaNode<?, ?> node, @Nullable ChatMetaNode<?, ?> current) {
|
||||
Track track = this.plugin.getTrackManager().getIfLoaded(this.trackName);
|
||||
if (track == null) {
|
||||
return false;
|
||||
}
|
||||
PermissionHolder.Identifier origin = node.metadata(InheritanceOriginMetadata.KEY).getOrigin();
|
||||
return track != null && !track.containsGroup(origin.getName());
|
||||
return !(origin.getType().equals(PermissionHolder.Identifier.GROUP_TYPE) && track.containsGroup(origin.getName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -305,7 +311,7 @@ public final class StandardStackElements {
|
||||
@Override
|
||||
public boolean shouldAccumulate(@NonNull ChatMetaType type, @NonNull ChatMetaNode<?, ?> node, @Nullable ChatMetaNode<?, ?> current) {
|
||||
PermissionHolder.Identifier origin = node.metadata(InheritanceOriginMetadata.KEY).getOrigin();
|
||||
return !this.groupName.equals(origin.getName());
|
||||
return !(origin.getType().equals(PermissionHolder.Identifier.GROUP_TYPE) && this.groupName.equals(origin.getName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
}
|
||||
+2
-22
@@ -25,30 +25,23 @@
|
||||
|
||||
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> implements Result<Integer, N> {
|
||||
public final class IntegerResult<N extends Node> extends AbstractResult<Integer, N, IntegerResult<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
|
||||
@@ -73,19 +66,6 @@ public final class IntegerResult<N extends Node> implements Result<Integer, N> {
|
||||
}
|
||||
}
|
||||
|
||||
@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,7 +25,6 @@
|
||||
|
||||
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;
|
||||
@@ -36,19 +35,14 @@ import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
*
|
||||
* @param <N> the node type
|
||||
*/
|
||||
public final class StringResult<N extends Node> implements Result<String, N> {
|
||||
public final class StringResult<N extends Node> extends AbstractResult<String, N, StringResult<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
|
||||
@@ -56,19 +50,6 @@ public final class StringResult<N extends Node> implements Result<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);
|
||||
}
|
||||
|
||||
+2
-20
@@ -27,7 +27,6 @@ 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;
|
||||
@@ -36,20 +35,16 @@ import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
/**
|
||||
* Represents the result of a {@link PermissionCalculator} lookup.
|
||||
*/
|
||||
public final class TristateResult implements Result<Tristate, Node> {
|
||||
public final class TristateResult extends AbstractResult<Tristate, Node, TristateResult> {
|
||||
|
||||
/** 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;
|
||||
}
|
||||
|
||||
@@ -58,11 +53,6 @@ public final class TristateResult implements Result<Tristate, Node> {
|
||||
return this.result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Node node() {
|
||||
return this.node;
|
||||
}
|
||||
|
||||
public @Nullable Class<? extends PermissionProcessor> processorClass() {
|
||||
return this.processorClass;
|
||||
}
|
||||
@@ -79,14 +69,6 @@ public final class TristateResult implements Result<Tristate, Node> {
|
||||
}
|
||||
}
|
||||
|
||||
public @Nullable TristateResult overriddenResult() {
|
||||
return this.overriddenResult;
|
||||
}
|
||||
|
||||
public void setOverriddenResult(TristateResult overriddenResult) {
|
||||
this.overriddenResult = overriddenResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TristateResult(" +
|
||||
|
||||
@@ -79,6 +79,7 @@ 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;
|
||||
@@ -101,7 +102,7 @@ public class CommandManager {
|
||||
.build()
|
||||
);
|
||||
private final AtomicBoolean executingCommand = new AtomicBoolean(false);
|
||||
private final ExpiringSet<UUID> playerRateLimit = new ExpiringSet<>(500, TimeUnit.MILLISECONDS);
|
||||
private final Set<UUID> playerRateLimit = ExpiringSet.newExpiringSet(500, TimeUnit.MILLISECONDS);
|
||||
private final TabCompletions tabCompletions;
|
||||
private final Map<String, Command<?>> mainCommands;
|
||||
|
||||
@@ -154,11 +155,20 @@ 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() && !this.playerRateLimit.add(uniqueId)) {
|
||||
if (this.plugin.getConfiguration().get(ConfigKeys.COMMANDS_RATE_LIMIT) && !sender.isConsole() && !Sender.CONSOLE_UUID.equals(uniqueId) && !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);
|
||||
|
||||
@@ -285,6 +295,14 @@ 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()
|
||||
|
||||
+2
-1
@@ -31,6 +31,7 @@ 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;
|
||||
|
||||
@@ -66,7 +67,7 @@ public abstract class ChildCommand<T> extends Command<T> {
|
||||
.collect(Collectors.toList());
|
||||
|
||||
builder.append(Component.text(" - ", NamedTextColor.DARK_AQUA))
|
||||
.append(Component.join(Component.space(), argUsages))
|
||||
.append(Component.join(JoinConfiguration.separator(Component.space()), argUsages))
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -35,6 +35,7 @@ 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;
|
||||
|
||||
@@ -114,7 +115,7 @@ public abstract class GenericChildCommand {
|
||||
.collect(Collectors.toList());
|
||||
|
||||
builder.append(Component.text(" - ", NamedTextColor.DARK_AQUA))
|
||||
.append(Component.join(Component.space(), argUsages))
|
||||
.append(Component.join(JoinConfiguration.separator(Component.space()), argUsages))
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
+42
-27
@@ -86,39 +86,44 @@ public abstract class ParentCommand<T, I> extends Command<Void> {
|
||||
return;
|
||||
}
|
||||
|
||||
final String targetArgument = args.get(0);
|
||||
I targetId = null;
|
||||
if (this.type == Type.TAKES_ARGUMENT_FOR_TARGET) {
|
||||
targetId = parseTarget(targetArgument, plugin, sender);
|
||||
if (this.type == Type.TARGETED) {
|
||||
final String targetArgument = args.get(0);
|
||||
I 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;
|
||||
}
|
||||
|
||||
ReentrantLock lock = getLockForTarget(targetId);
|
||||
lock.lock();
|
||||
try {
|
||||
sub.execute(plugin, sender, target, args.subList(this.type.minArgs, args.size()), label);
|
||||
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();
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
sub.execute(plugin, sender, null, 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 TAKES_ARGUMENT_FOR_TARGET:
|
||||
case TARGETED:
|
||||
return TabCompleter.create()
|
||||
.at(0, CompletionSupplier.startsWith(() -> getTargets(plugin).stream()))
|
||||
.at(1, CompletionSupplier.startsWith(() -> getChildren().stream()
|
||||
@@ -133,7 +138,7 @@ public abstract class ParentCommand<T, I> extends Command<Void> {
|
||||
.orElse(Collections.emptyList())
|
||||
)
|
||||
.complete(args);
|
||||
case NO_TARGET_ARGUMENT:
|
||||
case NOT_TARGETED:
|
||||
return TabCompleter.create()
|
||||
.at(0, CompletionSupplier.startsWith(() -> getChildren().stream()
|
||||
.filter(s -> s.isAuthorized(sender))
|
||||
@@ -178,21 +183,31 @@ public abstract class ParentCommand<T, I> extends Command<Void> {
|
||||
return getChildren().stream().anyMatch(sc -> sc.isAuthorized(sender));
|
||||
}
|
||||
|
||||
protected abstract List<String> getTargets(LuckPermsPlugin plugin);
|
||||
protected List<String> getTargets(LuckPermsPlugin plugin) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
protected abstract I parseTarget(String target, LuckPermsPlugin plugin, Sender sender);
|
||||
protected I parseTarget(String target, LuckPermsPlugin plugin, Sender sender) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
protected abstract ReentrantLock getLockForTarget(I target);
|
||||
protected ReentrantLock getLockForTarget(I target) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
protected abstract T getTarget(I target, LuckPermsPlugin plugin, Sender sender);
|
||||
protected T getTarget(I target, LuckPermsPlugin plugin, Sender sender) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
protected abstract void cleanup(T t, LuckPermsPlugin plugin);
|
||||
protected void cleanup(T t, LuckPermsPlugin plugin) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public enum Type {
|
||||
// e.g. /lp log sub-command....
|
||||
NO_TARGET_ARGUMENT(0),
|
||||
NOT_TARGETED(0),
|
||||
// e.g. /lp user <USER> sub-command....
|
||||
TAKES_ARGUMENT_FOR_TARGET(1);
|
||||
TARGETED(1);
|
||||
|
||||
private final int cmdIndex;
|
||||
private final int minArgs;
|
||||
|
||||
+2
-1
@@ -33,6 +33,7 @@ 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;
|
||||
|
||||
@@ -70,7 +71,7 @@ public abstract class SingleCommand extends Command<Void> {
|
||||
.collect(Collectors.toList());
|
||||
|
||||
builder.append(Component.text(" - ", NamedTextColor.DARK_AQUA))
|
||||
.append(Component.join(Component.space(), argUsages))
|
||||
.append(Component.join(JoinConfiguration.separator(Component.space()), argUsages))
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
+137
-131
@@ -32,143 +32,143 @@ import me.lucko.luckperms.common.sender.Sender;
|
||||
*/
|
||||
public enum CommandPermission {
|
||||
|
||||
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),
|
||||
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),
|
||||
|
||||
CREATE_GROUP("creategroup", Type.NONE),
|
||||
DELETE_GROUP("deletegroup", Type.NONE),
|
||||
LIST_GROUPS("listgroups", Type.NONE),
|
||||
CREATE_GROUP("creategroup", Type.NONE, false),
|
||||
DELETE_GROUP("deletegroup", Type.NONE, false),
|
||||
LIST_GROUPS("listgroups", Type.NONE, true),
|
||||
|
||||
CREATE_TRACK("createtrack", Type.NONE),
|
||||
DELETE_TRACK("deletetrack", Type.NONE),
|
||||
LIST_TRACKS("listtracks", Type.NONE),
|
||||
CREATE_TRACK("createtrack", Type.NONE, false),
|
||||
DELETE_TRACK("deletetrack", Type.NONE, false),
|
||||
LIST_TRACKS("listtracks", Type.NONE, true),
|
||||
|
||||
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),
|
||||
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),
|
||||
|
||||
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),
|
||||
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),
|
||||
|
||||
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),
|
||||
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),
|
||||
|
||||
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),
|
||||
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),
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
public static final String ROOT = "luckperms.";
|
||||
|
||||
@@ -176,9 +176,11 @@ public enum CommandPermission {
|
||||
private final String permission;
|
||||
|
||||
private final Type type;
|
||||
private final boolean readOnly;
|
||||
|
||||
CommandPermission(String node, Type type) {
|
||||
CommandPermission(String node, Type type, boolean readOnly) {
|
||||
this.type = type;
|
||||
this.readOnly = readOnly;
|
||||
|
||||
if (type == Type.NONE) {
|
||||
this.node = node;
|
||||
@@ -205,6 +207,10 @@ public enum CommandPermission {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public boolean isReadOnly() {
|
||||
return this.readOnly;
|
||||
}
|
||||
|
||||
public enum Type {
|
||||
|
||||
NONE(null),
|
||||
|
||||
@@ -28,12 +28,9 @@ 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;
|
||||
@@ -43,6 +40,7 @@ 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;
|
||||
@@ -115,7 +113,7 @@ public class DeleteGroup extends SingleCommand {
|
||||
.trackStatistics(false)
|
||||
.dataType(DataType.ALL)
|
||||
.action(DeleteAction.create())
|
||||
.query(Query.of(QueryField.PERMISSION, Constraint.of(StandardComparison.EQUAL, Inheritance.key(groupName))))
|
||||
.filter(BulkUpdateField.PERMISSION, Comparison.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.TAKES_ARGUMENT_FOR_TARGET, ImmutableList.<Command<Group>>builder()
|
||||
super(CommandSpec.GROUP, "Group", Type.TARGETED, ImmutableList.<Command<Group>>builder()
|
||||
.add(new GroupInfo())
|
||||
.add(new CommandPermission<>(HolderType.GROUP))
|
||||
.add(new CommandParent<>(HolderType.GROUP))
|
||||
|
||||
@@ -28,11 +28,8 @@ 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.action.UpdateAction;
|
||||
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.ChildCommand;
|
||||
import me.lucko.luckperms.common.command.access.ArgumentPermissions;
|
||||
import me.lucko.luckperms.common.command.access.CommandPermission;
|
||||
@@ -41,6 +38,7 @@ import me.lucko.luckperms.common.command.tabcomplete.CompletionSupplier;
|
||||
import me.lucko.luckperms.common.command.tabcomplete.TabCompleter;
|
||||
import me.lucko.luckperms.common.command.utils.ArgumentList;
|
||||
import me.lucko.luckperms.common.command.utils.StorageAssistant;
|
||||
import me.lucko.luckperms.common.filter.Comparison;
|
||||
import me.lucko.luckperms.common.locale.Message;
|
||||
import me.lucko.luckperms.common.model.Group;
|
||||
import me.lucko.luckperms.common.node.types.Inheritance;
|
||||
@@ -112,8 +110,8 @@ public class GroupRename extends ChildCommand<Group> {
|
||||
BulkUpdate operation = BulkUpdateBuilder.create()
|
||||
.trackStatistics(false)
|
||||
.dataType(me.lucko.luckperms.common.bulkupdate.DataType.ALL)
|
||||
.action(UpdateAction.of(QueryField.PERMISSION, Inheritance.key(newGroupName)))
|
||||
.query(Query.of(QueryField.PERMISSION, Constraint.of(StandardComparison.EQUAL, Inheritance.key(target.getName()))))
|
||||
.action(UpdateAction.of(BulkUpdateField.PERMISSION, Inheritance.key(newGroupName)))
|
||||
.filter(BulkUpdateField.PERMISSION, Comparison.EQUAL, Inheritance.key(target.getName()))
|
||||
.build();
|
||||
return plugin.getStorage().applyBulkUpdate(operation);
|
||||
} else {
|
||||
|
||||
@@ -25,25 +25,26 @@
|
||||
|
||||
package me.lucko.luckperms.common.commands.log;
|
||||
|
||||
import me.lucko.luckperms.common.actionlog.Log;
|
||||
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.command.abstraction.ChildCommand;
|
||||
import me.lucko.luckperms.common.command.access.CommandPermission;
|
||||
import me.lucko.luckperms.common.command.spec.CommandSpec;
|
||||
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.filter.PageParameters;
|
||||
import me.lucko.luckperms.common.locale.Message;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.storage.misc.DataConstraints;
|
||||
import me.lucko.luckperms.common.util.Paginated;
|
||||
import me.lucko.luckperms.common.util.Predicates;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
public class LogGroupHistory extends ChildCommand<Log> {
|
||||
public class LogGroupHistory extends ChildCommand<Void> {
|
||||
private static final int ENTRIES_PER_PAGE = 10;
|
||||
|
||||
public LogGroupHistory() {
|
||||
@@ -51,44 +52,34 @@ public class LogGroupHistory extends ChildCommand<Log> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(LuckPermsPlugin plugin, Sender sender, Log log, ArgumentList args, String label) {
|
||||
public void execute(LuckPermsPlugin plugin, Sender sender, Void ignored, ArgumentList args, String label) {
|
||||
String group = args.get(0).toLowerCase(Locale.ROOT);
|
||||
if (!DataConstraints.GROUP_NAME_TEST.test(group)) {
|
||||
Message.GROUP_INVALID_ENTRY.send(sender, group);
|
||||
return;
|
||||
}
|
||||
|
||||
Paginated<LoggedAction> content = new Paginated<>(log.getGroupHistory(group));
|
||||
PageParameters pageParams = new PageParameters(ENTRIES_PER_PAGE, args.getIntOrDefault(1, 1));
|
||||
LogPage log = plugin.getStorage().getLogPage(ActionFilters.group(group), pageParams).join();
|
||||
|
||||
int page = args.getIntOrDefault(1, Integer.MIN_VALUE);
|
||||
if (page != Integer.MIN_VALUE) {
|
||||
showLog(page, sender, content);
|
||||
} else {
|
||||
showLog(content.getMaxPages(ENTRIES_PER_PAGE), sender, content);
|
||||
}
|
||||
}
|
||||
int page = pageParams.pageNumber();
|
||||
int maxPage = pageParams.getMaxPage(log.getTotalEntries());
|
||||
|
||||
private static void showLog(int page, Sender sender, Paginated<LoggedAction> log) {
|
||||
int maxPage = log.getMaxPages(ENTRIES_PER_PAGE);
|
||||
if (maxPage == 0) {
|
||||
if (log.getTotalEntries() == 0) {
|
||||
Message.LOG_NO_ENTRIES.send(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
if (page == Integer.MIN_VALUE) {
|
||||
page = maxPage;
|
||||
}
|
||||
|
||||
if (page < 1 || page > maxPage) {
|
||||
Message.LOG_INVALID_PAGE_RANGE.send(sender, maxPage);
|
||||
return;
|
||||
}
|
||||
|
||||
List<Paginated.Entry<LoggedAction>> entries = log.getPage(page, ENTRIES_PER_PAGE);
|
||||
List<LogPage.Entry<LoggedAction>> entries = log.getNumberedContent();
|
||||
String name = entries.stream().findAny().get().value().getTarget().getName();
|
||||
Message.LOG_HISTORY_GROUP_HEADER.send(sender, name, page, maxPage);
|
||||
|
||||
for (Paginated.Entry<LoggedAction> e : entries) {
|
||||
for (LogPage.Entry<LoggedAction> e : entries) {
|
||||
Message.LOG_ENTRY.send(sender, e.position(), e.value());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
|
||||
package me.lucko.luckperms.common.commands.log;
|
||||
|
||||
import me.lucko.luckperms.common.actionlog.Log;
|
||||
import me.lucko.luckperms.common.command.abstraction.ChildCommand;
|
||||
import me.lucko.luckperms.common.command.access.CommandPermission;
|
||||
import me.lucko.luckperms.common.command.spec.CommandSpec;
|
||||
@@ -43,7 +42,7 @@ import net.luckperms.api.node.Node;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public class LogNotify extends ChildCommand<Log> {
|
||||
public class LogNotify extends ChildCommand<Void> {
|
||||
private static final String IGNORE_NODE = "luckperms.log.notify.ignoring";
|
||||
|
||||
public LogNotify() {
|
||||
@@ -83,7 +82,7 @@ public class LogNotify extends ChildCommand<Log> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(LuckPermsPlugin plugin, Sender sender, Log log, ArgumentList args, String label) {
|
||||
public void execute(LuckPermsPlugin plugin, Sender sender, Void ignored, ArgumentList args, String label) {
|
||||
if (sender.isConsole()) {
|
||||
Message.LOG_NOTIFY_CONSOLE.send(sender);
|
||||
return;
|
||||
|
||||
@@ -26,22 +26,13 @@
|
||||
package me.lucko.luckperms.common.commands.log;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import me.lucko.luckperms.common.actionlog.Log;
|
||||
import me.lucko.luckperms.common.command.abstraction.Command;
|
||||
import me.lucko.luckperms.common.command.abstraction.ParentCommand;
|
||||
import me.lucko.luckperms.common.command.spec.CommandSpec;
|
||||
import me.lucko.luckperms.common.locale.Message;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public class LogParentCommand extends ParentCommand<Log, Void> {
|
||||
private final ReentrantLock lock = new ReentrantLock();
|
||||
|
||||
public class LogParentCommand extends ParentCommand<Void, Void> {
|
||||
public LogParentCommand() {
|
||||
super(CommandSpec.LOG, "Log", Type.NO_TARGET_ARGUMENT, ImmutableList.<Command<Log>>builder()
|
||||
super(CommandSpec.LOG, "Log", Type.NOT_TARGETED, ImmutableList.<Command<Void>>builder()
|
||||
.add(new LogRecent())
|
||||
.add(new LogSearch())
|
||||
.add(new LogNotify())
|
||||
@@ -51,38 +42,4 @@ public class LogParentCommand extends ParentCommand<Log, Void> {
|
||||
.build()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ReentrantLock getLockForTarget(Void target) {
|
||||
return this.lock; // all commands target the same log, so we share a lock between all "targets"
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Log getTarget(Void target, LuckPermsPlugin plugin, Sender sender) {
|
||||
Log log = plugin.getStorage().getLog().join();
|
||||
|
||||
if (log == null) {
|
||||
Message.LOG_LOAD_ERROR.send(sender);
|
||||
}
|
||||
|
||||
return log;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void cleanup(Log log, LuckPermsPlugin plugin) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> getTargets(LuckPermsPlugin plugin) {
|
||||
// should never be called if we specify Type.NO_TARGET_ARGUMENT in the constructor
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void parseTarget(String target, LuckPermsPlugin plugin, Sender sender) {
|
||||
// should never be called if we specify Type.NO_TARGET_ARGUMENT in the constructor
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -25,22 +25,23 @@
|
||||
|
||||
package me.lucko.luckperms.common.commands.log;
|
||||
|
||||
import me.lucko.luckperms.common.actionlog.Log;
|
||||
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.command.abstraction.ChildCommand;
|
||||
import me.lucko.luckperms.common.command.access.CommandPermission;
|
||||
import me.lucko.luckperms.common.command.spec.CommandSpec;
|
||||
import me.lucko.luckperms.common.command.utils.ArgumentList;
|
||||
import me.lucko.luckperms.common.filter.PageParameters;
|
||||
import me.lucko.luckperms.common.locale.Message;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.util.Paginated;
|
||||
import me.lucko.luckperms.common.util.Predicates;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class LogRecent extends ChildCommand<Log> {
|
||||
public class LogRecent extends ChildCommand<Void> {
|
||||
private static final int ENTRIES_PER_PAGE = 10;
|
||||
|
||||
public LogRecent() {
|
||||
@@ -48,39 +49,32 @@ public class LogRecent extends ChildCommand<Log> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(LuckPermsPlugin plugin, Sender sender, Log log, ArgumentList args, String label) {
|
||||
if (args.isEmpty()) {
|
||||
// No page or user
|
||||
Paginated<LoggedAction> content = new Paginated<>(log.getContent());
|
||||
showLog(content.getMaxPages(ENTRIES_PER_PAGE), false, sender, content);
|
||||
return;
|
||||
public void execute(LuckPermsPlugin plugin, Sender sender, Void ignored, ArgumentList args, String label) {
|
||||
int page = 1;
|
||||
UUID uuid = null;
|
||||
|
||||
if (!args.isEmpty()) {
|
||||
int pageNo = args.getIntOrDefault(0, Integer.MIN_VALUE);
|
||||
if (pageNo != Integer.MIN_VALUE) {
|
||||
page = pageNo;
|
||||
} else {
|
||||
uuid = args.getUserTarget(0, plugin, sender);
|
||||
if (uuid == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
pageNo = args.getIntOrDefault(1, Integer.MIN_VALUE);
|
||||
if (pageNo != Integer.MIN_VALUE) {
|
||||
page = pageNo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int page = args.getIntOrDefault(0, Integer.MIN_VALUE);
|
||||
if (page != Integer.MIN_VALUE) {
|
||||
Paginated<LoggedAction> content = new Paginated<>(log.getContent());
|
||||
showLog(page, false, sender, content);
|
||||
return;
|
||||
}
|
||||
PageParameters pageParams = new PageParameters(ENTRIES_PER_PAGE, page);
|
||||
LogPage log = plugin.getStorage().getLogPage(uuid == null ? ActionFilters.all() : ActionFilters.source(uuid), pageParams).join();
|
||||
|
||||
// User and possibly page
|
||||
UUID uuid = args.getUserTarget(0, plugin, sender);
|
||||
if (uuid == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Paginated<LoggedAction> content = new Paginated<>(log.getContent(uuid));
|
||||
page = args.getIntOrDefault(1, Integer.MIN_VALUE);
|
||||
if (page != Integer.MIN_VALUE) {
|
||||
showLog(page, true, sender, content);
|
||||
} else {
|
||||
showLog(content.getMaxPages(ENTRIES_PER_PAGE), true, sender, content);
|
||||
}
|
||||
}
|
||||
|
||||
private static void showLog(int page, boolean specificUser, Sender sender, Paginated<LoggedAction> log) {
|
||||
int maxPage = log.getMaxPages(ENTRIES_PER_PAGE);
|
||||
if (maxPage == 0) {
|
||||
int maxPage = pageParams.getMaxPage(log.getTotalEntries());
|
||||
if (log.getTotalEntries() == 0) {
|
||||
Message.LOG_NO_ENTRIES.send(sender);
|
||||
return;
|
||||
}
|
||||
@@ -90,8 +84,8 @@ public class LogRecent extends ChildCommand<Log> {
|
||||
return;
|
||||
}
|
||||
|
||||
List<Paginated.Entry<LoggedAction>> entries = log.getPage(page, ENTRIES_PER_PAGE);
|
||||
if (specificUser) {
|
||||
List<LogPage.Entry<LoggedAction>> entries = log.getNumberedContent();
|
||||
if (uuid != null) {
|
||||
String name = entries.stream().findAny().get().value().getSource().getName();
|
||||
if (name.contains("@")) {
|
||||
name = name.split("@")[0];
|
||||
@@ -101,8 +95,9 @@ public class LogRecent extends ChildCommand<Log> {
|
||||
Message.LOG_RECENT_HEADER.send(sender, page, maxPage);
|
||||
}
|
||||
|
||||
for (Paginated.Entry<LoggedAction> e : entries) {
|
||||
for (LogPage.Entry<LoggedAction> e : entries) {
|
||||
Message.LOG_ENTRY.send(sender, e.position(), e.value());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -25,21 +25,22 @@
|
||||
|
||||
package me.lucko.luckperms.common.commands.log;
|
||||
|
||||
import me.lucko.luckperms.common.actionlog.Log;
|
||||
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.command.abstraction.ChildCommand;
|
||||
import me.lucko.luckperms.common.command.access.CommandPermission;
|
||||
import me.lucko.luckperms.common.command.spec.CommandSpec;
|
||||
import me.lucko.luckperms.common.command.utils.ArgumentList;
|
||||
import me.lucko.luckperms.common.filter.PageParameters;
|
||||
import me.lucko.luckperms.common.locale.Message;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.util.Paginated;
|
||||
import me.lucko.luckperms.common.util.Predicates;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class LogSearch extends ChildCommand<Log> {
|
||||
public class LogSearch extends ChildCommand<Void> {
|
||||
private static final int ENTRIES_PER_PAGE = 10;
|
||||
|
||||
public LogSearch() {
|
||||
@@ -47,8 +48,8 @@ public class LogSearch extends ChildCommand<Log> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(LuckPermsPlugin plugin, Sender sender, Log log, ArgumentList args, String label) {
|
||||
int page = Integer.MIN_VALUE;
|
||||
public void execute(LuckPermsPlugin plugin, Sender sender, Void ignored, ArgumentList args, String label) {
|
||||
int page = 1;
|
||||
if (args.size() > 1) {
|
||||
try {
|
||||
page = Integer.parseInt(args.get(args.size() - 1));
|
||||
@@ -59,36 +60,26 @@ public class LogSearch extends ChildCommand<Log> {
|
||||
}
|
||||
|
||||
final String query = String.join(" ", args);
|
||||
Paginated<LoggedAction> content = new Paginated<>(log.getSearch(query));
|
||||
PageParameters pageParams = new PageParameters(ENTRIES_PER_PAGE, page);
|
||||
LogPage log = plugin.getStorage().getLogPage(ActionFilters.search(query), pageParams).join();
|
||||
|
||||
if (page != Integer.MIN_VALUE) {
|
||||
showLog(page, query, sender, content);
|
||||
} else {
|
||||
showLog(content.getMaxPages(ENTRIES_PER_PAGE), query, sender, content);
|
||||
}
|
||||
}
|
||||
|
||||
private static void showLog(int page, String query, Sender sender, Paginated<LoggedAction> log) {
|
||||
int maxPage = log.getMaxPages(ENTRIES_PER_PAGE);
|
||||
if (maxPage == 0) {
|
||||
int maxPage = pageParams.getMaxPage(log.getTotalEntries());
|
||||
if (log.getTotalEntries() == 0) {
|
||||
Message.LOG_NO_ENTRIES.send(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
if (page == Integer.MIN_VALUE) {
|
||||
page = maxPage;
|
||||
}
|
||||
|
||||
if (page < 1 || page > maxPage) {
|
||||
Message.LOG_INVALID_PAGE_RANGE.send(sender, maxPage);
|
||||
return;
|
||||
}
|
||||
|
||||
List<Paginated.Entry<LoggedAction>> entries = log.getPage(page, ENTRIES_PER_PAGE);
|
||||
List<LogPage.Entry<LoggedAction>> entries = log.getNumberedContent();
|
||||
Message.LOG_SEARCH_HEADER.send(sender, query, page, maxPage);
|
||||
|
||||
for (Paginated.Entry<LoggedAction> e : entries) {
|
||||
for (LogPage.Entry<LoggedAction> e : entries) {
|
||||
Message.LOG_ENTRY.send(sender, e.position(), e.value());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -25,25 +25,26 @@
|
||||
|
||||
package me.lucko.luckperms.common.commands.log;
|
||||
|
||||
import me.lucko.luckperms.common.actionlog.Log;
|
||||
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.command.abstraction.ChildCommand;
|
||||
import me.lucko.luckperms.common.command.access.CommandPermission;
|
||||
import me.lucko.luckperms.common.command.spec.CommandSpec;
|
||||
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.filter.PageParameters;
|
||||
import me.lucko.luckperms.common.locale.Message;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.storage.misc.DataConstraints;
|
||||
import me.lucko.luckperms.common.util.Paginated;
|
||||
import me.lucko.luckperms.common.util.Predicates;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
public class LogTrackHistory extends ChildCommand<Log> {
|
||||
public class LogTrackHistory extends ChildCommand<Void> {
|
||||
private static final int ENTRIES_PER_PAGE = 10;
|
||||
|
||||
public LogTrackHistory() {
|
||||
@@ -51,44 +52,33 @@ public class LogTrackHistory extends ChildCommand<Log> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(LuckPermsPlugin plugin, Sender sender, Log log, ArgumentList args, String label) {
|
||||
public void execute(LuckPermsPlugin plugin, Sender sender, Void ignored, ArgumentList args, String label) {
|
||||
String track = args.get(0).toLowerCase(Locale.ROOT);
|
||||
if (!DataConstraints.TRACK_NAME_TEST.test(track)) {
|
||||
Message.TRACK_INVALID_ENTRY.send(sender, track);
|
||||
return;
|
||||
}
|
||||
PageParameters pageParams = new PageParameters(ENTRIES_PER_PAGE, args.getIntOrDefault(1, 1));
|
||||
LogPage log = plugin.getStorage().getLogPage(ActionFilters.track(track), pageParams).join();
|
||||
|
||||
Paginated<LoggedAction> content = new Paginated<>(log.getTrackHistory(track));
|
||||
int page = pageParams.pageNumber();
|
||||
int maxPage = pageParams.getMaxPage(log.getTotalEntries());
|
||||
|
||||
int page = args.getIntOrDefault(1, Integer.MIN_VALUE);
|
||||
if (page != Integer.MIN_VALUE) {
|
||||
showLog(page, sender, content);
|
||||
} else {
|
||||
showLog(content.getMaxPages(ENTRIES_PER_PAGE), sender, content);
|
||||
}
|
||||
}
|
||||
|
||||
private static void showLog(int page, Sender sender, Paginated<LoggedAction> log) {
|
||||
int maxPage = log.getMaxPages(ENTRIES_PER_PAGE);
|
||||
if (maxPage == 0) {
|
||||
if (log.getTotalEntries() == 0) {
|
||||
Message.LOG_NO_ENTRIES.send(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
if (page == Integer.MIN_VALUE) {
|
||||
page = maxPage;
|
||||
}
|
||||
|
||||
if (page < 1 || page > maxPage) {
|
||||
Message.LOG_INVALID_PAGE_RANGE.send(sender, maxPage);
|
||||
return;
|
||||
}
|
||||
|
||||
List<Paginated.Entry<LoggedAction>> entries = log.getPage(page, ENTRIES_PER_PAGE);
|
||||
List<LogPage.Entry<LoggedAction>> entries = log.getNumberedContent();
|
||||
String name = entries.stream().findAny().get().value().getTarget().getName();
|
||||
Message.LOG_HISTORY_TRACK_HEADER.send(sender, name, page, maxPage);
|
||||
|
||||
for (Paginated.Entry<LoggedAction> e : entries) {
|
||||
for (LogPage.Entry<LoggedAction> e : entries) {
|
||||
Message.LOG_ENTRY.send(sender, e.position(), e.value());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,22 +25,23 @@
|
||||
|
||||
package me.lucko.luckperms.common.commands.log;
|
||||
|
||||
import me.lucko.luckperms.common.actionlog.Log;
|
||||
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.command.abstraction.ChildCommand;
|
||||
import me.lucko.luckperms.common.command.access.CommandPermission;
|
||||
import me.lucko.luckperms.common.command.spec.CommandSpec;
|
||||
import me.lucko.luckperms.common.command.utils.ArgumentList;
|
||||
import me.lucko.luckperms.common.filter.PageParameters;
|
||||
import me.lucko.luckperms.common.locale.Message;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.util.Paginated;
|
||||
import me.lucko.luckperms.common.util.Predicates;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class LogUserHistory extends ChildCommand<Log> {
|
||||
public class LogUserHistory extends ChildCommand<Void> {
|
||||
private static final int ENTRIES_PER_PAGE = 10;
|
||||
|
||||
public LogUserHistory() {
|
||||
@@ -48,25 +49,19 @@ public class LogUserHistory extends ChildCommand<Log> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(LuckPermsPlugin plugin, Sender sender, Log log, ArgumentList args, String label) {
|
||||
public void execute(LuckPermsPlugin plugin, Sender sender, Void ignored, ArgumentList args, String label) {
|
||||
UUID uuid = args.getUserTarget(0, plugin, sender);
|
||||
if (uuid == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Paginated<LoggedAction> content = new Paginated<>(log.getUserHistory(uuid));
|
||||
PageParameters pageParams = new PageParameters(ENTRIES_PER_PAGE, args.getIntOrDefault(1, 1));
|
||||
LogPage log = plugin.getStorage().getLogPage(ActionFilters.user(uuid), pageParams).join();
|
||||
|
||||
int page = args.getIntOrDefault(1, Integer.MIN_VALUE);
|
||||
if (page != Integer.MIN_VALUE) {
|
||||
showLog(page, sender, content);
|
||||
} else {
|
||||
showLog(content.getMaxPages(ENTRIES_PER_PAGE), sender, content);
|
||||
}
|
||||
}
|
||||
int page = pageParams.pageNumber();
|
||||
int maxPage = pageParams.getMaxPage(log.getTotalEntries());
|
||||
|
||||
private static void showLog(int page, Sender sender, Paginated<LoggedAction> log) {
|
||||
int maxPage = log.getMaxPages(ENTRIES_PER_PAGE);
|
||||
if (maxPage == 0) {
|
||||
if (log.getTotalEntries() == 0) {
|
||||
Message.LOG_NO_ENTRIES.send(sender);
|
||||
return;
|
||||
}
|
||||
@@ -76,11 +71,11 @@ public class LogUserHistory extends ChildCommand<Log> {
|
||||
return;
|
||||
}
|
||||
|
||||
List<Paginated.Entry<LoggedAction>> entries = log.getPage(page, ENTRIES_PER_PAGE);
|
||||
List<LogPage.Entry<LoggedAction>> entries = log.getNumberedContent();
|
||||
String name = entries.stream().findAny().get().value().getTarget().getName();
|
||||
Message.LOG_HISTORY_USER_HEADER.send(sender, name, page, maxPage);
|
||||
|
||||
for (Paginated.Entry<LoggedAction> e : entries) {
|
||||
for (LogPage.Entry<LoggedAction> e : entries) {
|
||||
Message.LOG_ENTRY.send(sender, e.position(), e.value());
|
||||
}
|
||||
}
|
||||
|
||||
+12
-10
@@ -28,15 +28,12 @@ package me.lucko.luckperms.common.commands.misc;
|
||||
import com.github.benmanes.caffeine.cache.Cache;
|
||||
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.BulkUpdateSqlBuilder;
|
||||
import me.lucko.luckperms.common.bulkupdate.BulkUpdateStatistics;
|
||||
import me.lucko.luckperms.common.bulkupdate.DataType;
|
||||
import me.lucko.luckperms.common.bulkupdate.action.DeleteAction;
|
||||
import me.lucko.luckperms.common.bulkupdate.action.UpdateAction;
|
||||
import me.lucko.luckperms.common.bulkupdate.comparison.Comparison;
|
||||
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.CommandException;
|
||||
import me.lucko.luckperms.common.command.abstraction.SingleCommand;
|
||||
import me.lucko.luckperms.common.command.access.CommandPermission;
|
||||
@@ -44,6 +41,7 @@ import me.lucko.luckperms.common.command.spec.CommandSpec;
|
||||
import me.lucko.luckperms.common.command.utils.ArgumentException;
|
||||
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.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
@@ -112,7 +110,7 @@ public class BulkUpdateCommand extends SingleCommand {
|
||||
}
|
||||
|
||||
String field = args.remove(0);
|
||||
QueryField queryField = QueryField.of(field);
|
||||
BulkUpdateField queryField = BulkUpdateField.of(field);
|
||||
if (queryField == null) {
|
||||
throw new ArgumentException.DetailedUsage();
|
||||
}
|
||||
@@ -131,20 +129,20 @@ public class BulkUpdateCommand extends SingleCommand {
|
||||
return;
|
||||
}
|
||||
|
||||
QueryField field = QueryField.of(parts[0]);
|
||||
BulkUpdateField field = BulkUpdateField.of(parts[0]);
|
||||
if (field == null) {
|
||||
Message.BULK_UPDATE_INVALID_CONSTRAINT.send(sender, constraint);
|
||||
return;
|
||||
}
|
||||
|
||||
Comparison comparison = StandardComparison.parseComparison(parts[1]);
|
||||
Comparison comparison = Comparison.parse(parts[1]);
|
||||
if (comparison == null) {
|
||||
Message.BULK_UPDATE_INVALID_COMPARISON.send(sender, parts[1]);
|
||||
return;
|
||||
}
|
||||
|
||||
String expr = parts[2];
|
||||
bulkUpdateBuilder.query(Query.of(field, Constraint.of(comparison, expr)));
|
||||
bulkUpdateBuilder.filter(field, comparison, expr);
|
||||
}
|
||||
|
||||
BulkUpdate bulkUpdate = bulkUpdateBuilder.build();
|
||||
@@ -155,7 +153,11 @@ public class BulkUpdateCommand extends SingleCommand {
|
||||
String id = String.format("%04d", ThreadLocalRandom.current().nextInt(10000));
|
||||
this.pendingOperations.put(id, bulkUpdate);
|
||||
|
||||
Message.BULK_UPDATE_QUEUED.send(sender, bulkUpdate.buildAsSql().toReadableString().replace("{table}", bulkUpdate.getDataType().getName()));
|
||||
BulkUpdateSqlBuilder sqlBuilder = new BulkUpdateSqlBuilder();
|
||||
sqlBuilder.visit(bulkUpdate);
|
||||
String readableSql = sqlBuilder.builder().toReadableString().replace("{table}", bulkUpdate.getDataType().getName());
|
||||
|
||||
Message.BULK_UPDATE_QUEUED.send(sender, readableSql);
|
||||
Message.BULK_UPDATE_CONFIRM.send(sender, label, id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,9 +26,6 @@
|
||||
package me.lucko.luckperms.common.commands.misc;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import me.lucko.luckperms.common.bulkupdate.comparison.Comparison;
|
||||
import me.lucko.luckperms.common.bulkupdate.comparison.Constraint;
|
||||
import me.lucko.luckperms.common.bulkupdate.comparison.StandardComparison;
|
||||
import me.lucko.luckperms.common.cache.LoadingMap;
|
||||
import me.lucko.luckperms.common.command.abstraction.SingleCommand;
|
||||
import me.lucko.luckperms.common.command.access.CommandPermission;
|
||||
@@ -36,6 +33,7 @@ import me.lucko.luckperms.common.command.spec.CommandSpec;
|
||||
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.filter.Comparison;
|
||||
import me.lucko.luckperms.common.locale.Message;
|
||||
import me.lucko.luckperms.common.model.HolderType;
|
||||
import me.lucko.luckperms.common.node.comparator.NodeEntryComparator;
|
||||
@@ -62,13 +60,13 @@ public class SearchCommand extends SingleCommand {
|
||||
|
||||
@Override
|
||||
public void execute(LuckPermsPlugin plugin, Sender sender, ArgumentList args, String label) {
|
||||
Comparison comparison = StandardComparison.parseComparison(args.get(0));
|
||||
Comparison comparison = Comparison.parse(args.get(0));
|
||||
if (comparison == null) {
|
||||
comparison = StandardComparison.EQUAL;
|
||||
comparison = Comparison.EQUAL;
|
||||
args.add(0, "==");
|
||||
}
|
||||
|
||||
ConstraintNodeMatcher<Node> matcher = StandardNodeMatchers.of(Constraint.of(comparison, args.get(1)));
|
||||
ConstraintNodeMatcher<Node> matcher = StandardNodeMatchers.key(args.get(1), comparison);
|
||||
int page = args.getIntOrDefault(2, 1);
|
||||
|
||||
Message.SEARCH_SEARCHING.send(sender, matcher.toString());
|
||||
@@ -120,7 +118,7 @@ public class SearchCommand extends SingleCommand {
|
||||
headerMessage.send(sender, page, pages.size(), results.size());
|
||||
|
||||
for (Map.Entry<String, NodeEntry<T, Node>> ent : mappedContent) {
|
||||
Message.SEARCH_NODE_ENTRY.send(sender, comparison != StandardComparison.EQUAL, ent.getValue().getNode(), ent.getKey(), holderType, label, sender.getPlugin());
|
||||
Message.SEARCH_NODE_ENTRY.send(sender, comparison != Comparison.EQUAL, ent.getValue().getNode(), ent.getKey(), holderType, label, sender.getPlugin());
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -53,7 +53,7 @@ public class TrackParentCommand extends ParentCommand<Track, String> {
|
||||
.build(key -> new ReentrantLock());
|
||||
|
||||
public TrackParentCommand() {
|
||||
super(CommandSpec.TRACK, "Track", Type.TAKES_ARGUMENT_FOR_TARGET, ImmutableList.<Command<Track>>builder()
|
||||
super(CommandSpec.TRACK, "Track", Type.TARGETED, ImmutableList.<Command<Track>>builder()
|
||||
.add(new TrackInfo())
|
||||
.add(new TrackEditor())
|
||||
.add(new TrackAppend())
|
||||
|
||||
@@ -62,7 +62,7 @@ public class UserParentCommand extends ParentCommand<User, UserIdentifier> {
|
||||
.build(key -> new ReentrantLock());
|
||||
|
||||
public UserParentCommand() {
|
||||
super(CommandSpec.USER, "User", Type.TAKES_ARGUMENT_FOR_TARGET, ImmutableList.<Command<User>>builder()
|
||||
super(CommandSpec.USER, "User", Type.TARGETED, ImmutableList.<Command<User>>builder()
|
||||
.add(new UserInfo())
|
||||
.add(new CommandPermission<>(HolderType.USER))
|
||||
.add(new CommandParent<>(HolderType.USER))
|
||||
|
||||
Loaded 100 of 329 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user