1
0
mirror of https://github.com/lucko/LuckPerms.git synced 2025-09-01 18:32:33 +02:00

Update Sponge module to API 12

This commit is contained in:
Luck
2025-01-05 14:38:15 +00:00
parent 0fef481d48
commit 5b82837b80
18 changed files with 63 additions and 90 deletions

View File

@@ -0,0 +1,18 @@
repositories {
maven { url 'https://repo.spongepowered.org/repository/maven-public/' }
}
sourceCompatibility = 17
targetCompatibility = 21
dependencies {
implementation project(':common')
implementation project(':sponge:sponge-service')
compileOnly('org.spongepowered:spongeapi:12.0.0') {
exclude(module: 'configurate-core')
exclude(module: 'configurate-hocon')
exclude(module: 'configurate-gson')
exclude(module: 'configurate-yaml')
}
}

View File

@@ -0,0 +1,130 @@
/*
* 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.sponge.service.proxy;
import me.lucko.luckperms.common.context.ImmutableContextSetImpl;
import me.lucko.luckperms.sponge.service.model.LPPermissionDescription;
import me.lucko.luckperms.sponge.service.model.LPPermissionService;
import me.lucko.luckperms.sponge.service.model.LPProxiedServiceObject;
import me.lucko.luckperms.sponge.service.model.LPSubject;
import me.lucko.luckperms.sponge.service.model.LPSubjectCollection;
import net.kyori.adventure.text.Component;
import net.luckperms.api.util.Tristate;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.spongepowered.api.service.permission.PermissionDescription;
import org.spongepowered.api.service.permission.PermissionService;
import org.spongepowered.plugin.PluginContainer;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
public final class DescriptionBuilder implements PermissionDescription.Builder, LPProxiedServiceObject {
private final @NonNull LPPermissionService service;
private final @NonNull PluginContainer container;
private final @NonNull Map<String, Tristate> roles = new HashMap<>();
private @Nullable String id = null;
private @Nullable Component description = null;
public DescriptionBuilder(LPPermissionService service, PluginContainer container) {
this.service = Objects.requireNonNull(service, "service");
this.container = Objects.requireNonNull(container, "container");
}
@Override
public PermissionDescription.@NonNull Builder id(@NonNull String id) {
this.id = Objects.requireNonNull(id, "id");
return this;
}
@Override
public PermissionDescription.@NonNull Builder description(@Nullable Component description) {
this.description = description;
return this;
}
@Override
public PermissionDescription.@NonNull Builder assign(@NonNull String role, boolean value) {
Objects.requireNonNull(role, "role");
this.roles.put(role, Tristate.of(value));
return this;
}
@Override
public PermissionDescription.Builder defaultValue(org.spongepowered.api.util.Tristate defaultValue) {
throw new UnsupportedOperationException("LuckPerms does not support assigning a default value to permission descriptions");
}
@Override
public @NonNull PermissionDescription register() throws IllegalStateException {
if (this.id == null) {
throw new IllegalStateException("id cannot be null");
}
LPPermissionDescription description = this.service.registerPermissionDescription(this.id, this.description, this.container);
// Set role-templates
LPSubjectCollection subjects = this.service.getCollection(PermissionService.SUBJECTS_ROLE_TEMPLATE);
for (Map.Entry<String, Tristate> assignment : this.roles.entrySet()) {
LPSubject roleSubject = subjects.loadSubject(assignment.getKey()).join();
roleSubject.getTransientSubjectData().setPermission(ImmutableContextSetImpl.EMPTY, this.id, assignment.getValue());
}
// null stuff so this instance can be reused
this.roles.clear();
this.id = null;
this.description = null;
return description.sponge();
}
@Override
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof DescriptionBuilder)) return false;
final DescriptionBuilder other = (DescriptionBuilder) o;
return this.container.equals(other.container) &&
this.roles.equals(other.roles) &&
Objects.equals(this.id, other.id) &&
Objects.equals(this.description, other.description);
}
@Override
public int hashCode() {
return Objects.hash(this.container, this.roles, this.id, this.description);
}
@Override
public String toString() {
return "SimpleDescriptionBuilder(" +
"container=" + this.container + ", " +
"roles=" + this.roles + ", " +
"id=" + this.id + ", " +
"description=" + this.description + ")";
}
}

View File

@@ -0,0 +1,135 @@
/*
* 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.sponge.service.proxy;
import me.lucko.luckperms.common.util.ImmutableCollectors;
import me.lucko.luckperms.sponge.service.model.LPPermissionDescription;
import me.lucko.luckperms.sponge.service.model.LPPermissionService;
import me.lucko.luckperms.sponge.service.model.LPProxiedServiceObject;
import net.kyori.adventure.text.Component;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.spongepowered.api.ResourceKey;
import org.spongepowered.api.service.permission.PermissionDescription;
import org.spongepowered.api.service.permission.Subject;
import org.spongepowered.api.service.permission.SubjectReference;
import org.spongepowered.api.util.Tristate;
import org.spongepowered.plugin.PluginContainer;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
public final class PermissionDescriptionProxy implements PermissionDescription, LPProxiedServiceObject {
private final LPPermissionService service;
private final LPPermissionDescription handle;
public PermissionDescriptionProxy(LPPermissionService service, LPPermissionDescription handle) {
this.service = service;
this.handle = handle;
}
@Override
public @NonNull String id() {
return this.handle.getId();
}
@Override
public @NonNull Optional<Component> description() {
return this.handle.getDescription();
}
@Override
public @NonNull Optional<PluginContainer> owner() {
return this.handle.getOwner();
}
@Override
public Tristate defaultValue() {
return Tristate.UNDEFINED;
}
@Override
public @NonNull Map<Subject, Boolean> assignedSubjects(@NonNull String s) {
return this.handle.getAssignedSubjects(s).entrySet().stream()
.collect(ImmutableCollectors.toMap(
e -> new SubjectProxy(this.service, e.getKey().toReference()),
Map.Entry::getValue
));
}
@Override
public boolean query(Subject subj) {
return subj.hasPermission(this.handle.getId());
}
@Override
public boolean query(Subject subj, String parameter) {
Objects.requireNonNull(parameter, "parameter");
return subj.hasPermission(this.handle.getId() + '.' + parameter);
}
@Override
public boolean query(Subject subj, ResourceKey key) {
return query(subj, key.namespace() + '.' + key.value());
}
@Override
public boolean query(Subject subj, String... parameters) {
if (parameters.length == 0) {
return this.query(subj);
} else if (parameters.length == 1) {
return this.query(subj, parameters[0]);
}
StringBuilder builder = new StringBuilder(this.handle.getId());
for (String parameter : parameters) {
builder.append('.').append(parameter);
}
return subj.hasPermission(builder.toString());
}
@Override
@SuppressWarnings({"unchecked", "rawtypes"})
public @NonNull CompletableFuture<Map<SubjectReference, Boolean>> findAssignedSubjects(@NonNull String s) {
return (CompletableFuture) this.handle.findAssignedSubjects(s);
}
@Override
public boolean equals(Object o) {
return o == this || o instanceof PermissionDescriptionProxy && this.handle.equals(((PermissionDescriptionProxy) o).handle);
}
@Override
public int hashCode() {
return this.handle.hashCode();
}
@Override
public String toString() {
return "luckperms.PermissionDescriptionProxy(handle=" + this.handle + ")";
}
}

View File

@@ -0,0 +1,174 @@
/*
* 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.sponge.service.proxy;
import com.google.common.collect.ImmutableSet;
import me.lucko.luckperms.common.util.ImmutableCollectors;
import me.lucko.luckperms.sponge.service.CompatibilityUtil;
import me.lucko.luckperms.sponge.service.PermissionAndContextService;
import me.lucko.luckperms.sponge.service.model.LPPermissionDescription;
import me.lucko.luckperms.sponge.service.model.LPPermissionService;
import me.lucko.luckperms.sponge.service.model.LPProxiedServiceObject;
import me.lucko.luckperms.sponge.service.model.LPSubjectCollection;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.spongepowered.api.event.Cause;
import org.spongepowered.api.service.context.Context;
import org.spongepowered.api.service.context.ContextCalculator;
import org.spongepowered.api.service.permission.PermissionDescription;
import org.spongepowered.api.service.permission.PermissionService;
import org.spongepowered.api.service.permission.Subject;
import org.spongepowered.api.service.permission.SubjectCollection;
import org.spongepowered.api.service.permission.SubjectReference;
import org.spongepowered.plugin.PluginContainer;
import java.util.Collection;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.function.Predicate;
public final class PermissionServiceProxy implements PermissionAndContextService, LPProxiedServiceObject {
private final LPPermissionService handle;
public PermissionServiceProxy(LPPermissionService handle) {
this.handle = handle;
}
@Override
public @NonNull SubjectCollection userSubjects() {
return this.handle.getUserSubjects().sponge();
}
@Override
public @NonNull SubjectCollection groupSubjects() {
return this.handle.getGroupSubjects().sponge();
}
@Override
public @NonNull Subject defaults() {
return this.handle.getRootDefaults().sponge();
}
@Override
public @NonNull Predicate<String> identifierValidityPredicate() {
return this.handle.getIdentifierValidityPredicate();
}
@Override
public CompletableFuture<SubjectCollection> loadCollection(@NonNull String s) {
return CompletableFuture.completedFuture(this.handle.getCollection(s).sponge());
}
@Override
public @NonNull Optional<SubjectCollection> collection(String s) {
return Optional.ofNullable(this.handle.getLoadedCollections().get(s.toLowerCase(Locale.ROOT))).map(LPSubjectCollection::sponge);
}
@Override
public CompletableFuture<Boolean> hasCollection(String s) {
return CompletableFuture.completedFuture(this.handle.getLoadedCollections().containsKey(s.toLowerCase(Locale.ROOT)));
}
@Override
public @NonNull Map<String, SubjectCollection> loadedCollections() {
return this.handle.getLoadedCollections().entrySet().stream()
.collect(ImmutableCollectors.toMap(
Map.Entry::getKey,
e -> e.getValue().sponge()
));
}
@Override
public CompletableFuture<? extends Set<String>> allIdentifiers() {
return CompletableFuture.completedFuture(ImmutableSet.copyOf(this.handle.getLoadedCollections().keySet()));
}
@Override
public @NonNull SubjectReference newSubjectReference(@NonNull String collectionIdentifier, @NonNull String subjectIdentifier) {
Objects.requireNonNull(collectionIdentifier, "collectionIdentifier");
Objects.requireNonNull(subjectIdentifier, "subjectIdentifier");
// test the identifiers
if (collectionIdentifier.equalsIgnoreCase(PermissionService.SUBJECTS_USER) &&
!this.handle.getUserSubjects().getIdentifierValidityPredicate().test(subjectIdentifier)) {
throw new IllegalArgumentException("Subject identifier '" + subjectIdentifier + "' does not pass the validity predicate for the user subject collection");
} else if (collectionIdentifier.equalsIgnoreCase(PermissionService.SUBJECTS_GROUP) &&
!this.handle.getGroupSubjects().getIdentifierValidityPredicate().test(subjectIdentifier)) {
throw new IllegalArgumentException("Subject identifier '" + subjectIdentifier + "' does not pass the validity predicate for the group subject collection");
}
// obtain a reference
return this.handle.getReferenceFactory().obtain(collectionIdentifier, subjectIdentifier);
}
@Override
public PermissionDescription.Builder newDescriptionBuilder(@NonNull PluginContainer container) {
return new DescriptionBuilder(this.handle, container);
}
@Override
public @NonNull Optional<PermissionDescription> description(@NonNull String s) {
return this.handle.getDescription(s).map(LPPermissionDescription::sponge);
}
@Override
public @NonNull Collection<PermissionDescription> descriptions() {
return this.handle.getDescriptions().stream().map(LPPermissionDescription::sponge).collect(ImmutableCollectors.toSet());
}
@Override
public Set<Context> contexts() {
return CompatibilityUtil.convertContexts(this.handle.getContextsForCurrentCause());
}
@Override
public Set<Context> contextsFor(Cause cause) {
return CompatibilityUtil.convertContexts(this.handle.getContextsForCause(cause));
}
@Override
public void registerContextCalculator(@NonNull ContextCalculator contextCalculator) {
this.handle.registerContextCalculator(contextCalculator);
}
@Override
public boolean equals(Object o) {
return o == this || o instanceof PermissionServiceProxy && this.handle.equals(((PermissionServiceProxy) o).handle);
}
@Override
public int hashCode() {
return this.handle.hashCode();
}
@Override
public String toString() {
return "luckperms.PermissionServiceProxy(handle=" + this.handle + ")";
}
}

View File

@@ -0,0 +1,159 @@
/*
* 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.sponge.service.proxy;
import me.lucko.luckperms.common.util.ImmutableCollectors;
import me.lucko.luckperms.sponge.service.model.LPProxiedServiceObject;
import me.lucko.luckperms.sponge.service.model.LPSubject;
import me.lucko.luckperms.sponge.service.model.LPSubjectCollection;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.spongepowered.api.event.Cause;
import org.spongepowered.api.service.permission.Subject;
import org.spongepowered.api.service.permission.SubjectCollection;
import org.spongepowered.api.service.permission.SubjectReference;
import java.util.Collection;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.function.Predicate;
public final class SubjectCollectionProxy implements SubjectCollection, LPProxiedServiceObject {
private final LPSubjectCollection handle;
public SubjectCollectionProxy(LPSubjectCollection handle) {
this.handle = handle;
}
@Override
public @NonNull String identifier() {
return this.handle.getIdentifier();
}
@Override
public @NonNull Predicate<String> identifierValidityPredicate() {
return this.handle.getIdentifierValidityPredicate();
}
@Override
public @NonNull CompletableFuture<Subject> loadSubject(@NonNull String s) {
return this.handle.loadSubject(s).thenApply(LPSubject::sponge);
}
@Override
public @NonNull Optional<Subject> subject(@NonNull String s) {
return this.handle.getSubject(s).map(LPSubject::sponge);
}
@Override
public @NonNull CompletableFuture<Boolean> hasSubject(@NonNull String s) {
return this.handle.hasRegistered(s);
}
@Override
public @NonNull CompletableFuture<Map<String, Subject>> loadSubjects(@NonNull Iterable<String> set) {
return this.handle.loadSubjects(set).thenApply(subs -> subs.stream().collect(ImmutableCollectors.toMap(lpSubject -> lpSubject.getIdentifier().getName(), LPSubject::sponge)));
}
@Override
public @NonNull Collection<Subject> loadedSubjects() {
return this.handle.getLoadedSubjects().stream().map(LPSubject::sponge).collect(ImmutableCollectors.toSet());
}
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
public @NonNull CompletableFuture<Set<String>> allIdentifiers() {
return (CompletableFuture) this.handle.getAllIdentifiers();
}
@Override
public @NonNull SubjectReference newSubjectReference(@NonNull String subjectIdentifier) {
Objects.requireNonNull(subjectIdentifier, "identifier");
if (!this.handle.getIdentifierValidityPredicate().test(subjectIdentifier)) {
throw new IllegalArgumentException("Subject identifier '" + subjectIdentifier + "' does not pass the validity predicate");
}
return this.handle.getService().getReferenceFactory().obtain(identifier(), subjectIdentifier);
}
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
public @NonNull CompletableFuture<Map<SubjectReference, Boolean>> allWithPermission(@NonNull String s) {
return (CompletableFuture) this.handle.getAllWithPermission(s);
}
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
public @NonNull CompletableFuture<Map<SubjectReference, Boolean>> allWithPermission(@NonNull String s, @NonNull Cause cause) {
return (CompletableFuture) this.handle.getAllWithPermission(this.handle.getService().getContextsForCause(cause), s);
}
@Override
public @NonNull Map<Subject, Boolean> loadedWithPermission(@NonNull String s) {
return this.handle.getLoadedWithPermission(s).entrySet().stream()
.collect(ImmutableCollectors.toMap(
sub -> sub.getKey().sponge(),
Map.Entry::getValue
));
}
@Override
public @NonNull Map<Subject, Boolean> loadedWithPermission(@NonNull String s, @NonNull Cause cause) {
return this.handle.getLoadedWithPermission(this.handle.getService().getContextsForCause(cause), s).entrySet().stream()
.collect(ImmutableCollectors.toMap(
sub -> sub.getKey().sponge(),
Map.Entry::getValue
));
}
@Override
public @NonNull Subject defaults() {
return this.handle.getDefaults().sponge();
}
@Override
public void suggestUnload(@NonNull String s) {
// unused by lp
}
@Override
public boolean equals(Object o) {
return o == this || o instanceof SubjectCollectionProxy && this.handle.equals(((SubjectCollectionProxy) o).handle);
}
@Override
public int hashCode() {
return this.handle.hashCode();
}
@Override
public String toString() {
return "luckperms.SubjectCollectionProxy(handle=" + this.handle + ")";
}
}

View File

@@ -0,0 +1,257 @@
/*
* 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.sponge.service.proxy;
import com.google.common.collect.ImmutableMap;
import me.lucko.luckperms.common.util.CompletableFutures;
import me.lucko.luckperms.common.util.ImmutableCollectors;
import me.lucko.luckperms.sponge.service.CompatibilityUtil;
import me.lucko.luckperms.sponge.service.model.LPPermissionService;
import me.lucko.luckperms.sponge.service.model.LPProxiedServiceObject;
import me.lucko.luckperms.sponge.service.model.LPSubject;
import me.lucko.luckperms.sponge.service.model.LPSubjectData;
import me.lucko.luckperms.sponge.service.model.LPSubjectReference;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.spongepowered.api.service.context.Context;
import org.spongepowered.api.service.permission.Subject;
import org.spongepowered.api.service.permission.SubjectData;
import org.spongepowered.api.service.permission.SubjectReference;
import org.spongepowered.api.service.permission.TransferMethod;
import org.spongepowered.api.util.Tristate;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
public final class SubjectDataProxy implements SubjectData, LPProxiedServiceObject {
private final LPPermissionService service;
private final LPSubjectReference ref;
private final boolean enduring;
public SubjectDataProxy(LPPermissionService service, LPSubjectReference ref, boolean enduring) {
this.service = service;
this.ref = ref;
this.enduring = enduring;
}
private CompletableFuture<LPSubjectData> handle() {
return this.enduring ?
this.ref.resolveLp().thenApply(LPSubject::getSubjectData) :
this.ref.resolveLp().thenApply(LPSubject::getTransientSubjectData);
}
@Override
public Subject subject() {
return handle().thenApply(handle -> handle.getParentSubject().sponge()).join();
}
@Override
public boolean isTransient() {
return !this.enduring;
}
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
public @NonNull Map<Set<Context>, Map<String, Boolean>> allPermissions() {
return (Map) handle().thenApply(handle -> handle.getAllPermissions().entrySet().stream()
.collect(ImmutableCollectors.toMap(
e -> CompatibilityUtil.convertContexts(e.getKey()),
Map.Entry::getValue
))).join();
}
@Override
public @NonNull Map<String, Boolean> permissions(@NonNull Set<Context> contexts) {
return handle().thenApply(handle -> handle.getPermissions(CompatibilityUtil.convertContexts(contexts))).join();
}
@Override
public @NonNull CompletableFuture<Boolean> setPermission(@NonNull Set<Context> contexts, @NonNull String permission, @NonNull Tristate value) {
return handle().thenCompose(handle -> handle.setPermission(
CompatibilityUtil.convertContexts(contexts),
permission,
CompatibilityUtil.convertTristate(value)
));
}
@Override
public CompletableFuture<Boolean> setPermissions(Set<Context> contexts, Map<String, Boolean> permissions, TransferMethod method) {
CompletableFuture<Boolean> fut;
if (method == TransferMethod.OVERWRITE) {
fut = clearPermissions(contexts);
} else {
fut = CompletableFuture.completedFuture(true);
}
return fut.thenCompose(bool -> permissions.entrySet().stream()
.map(entry -> setPermission(contexts, entry.getKey(), Tristate.fromBoolean(entry.getValue())))
.collect(CompletableFutures.collector())
)
.thenApply(x -> true);
}
@Override
public Tristate fallbackPermissionValue(Set<Context> contexts) {
// TODO: check subject type here to return a more appropriate value?
return Tristate.UNDEFINED;
}
@Override
public Map<Set<Context>, Tristate> allFallbackPermissionValues() {
return ImmutableMap.of();
}
@Override
public CompletableFuture<Boolean> setFallbackPermissionValue(Set<Context> contexts, Tristate fallback) {
throw new UnsupportedOperationException("LuckPerms does not support setting fallback permission values");
}
@Override
public CompletableFuture<Boolean> clearFallbackPermissionValues() {
return CompletableFuture.completedFuture(true);
}
@Override
public @NonNull CompletableFuture<Boolean> clearPermissions() {
return handle().thenCompose(LPSubjectData::clearPermissions);
}
@Override
public @NonNull CompletableFuture<Boolean> clearPermissions(@NonNull Set<Context> contexts) {
return handle().thenCompose(handle -> handle.clearPermissions(CompatibilityUtil.convertContexts(contexts)));
}
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
public @NonNull Map<Set<Context>, List<org.spongepowered.api.service.permission.SubjectReference>> allParents() {
return (Map) handle().thenApply(handle -> handle.getAllParents().entrySet().stream()
.collect(ImmutableCollectors.toMap(
e -> CompatibilityUtil.convertContexts(e.getKey()),
Map.Entry::getValue
))).join();
}
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
public @NonNull List<org.spongepowered.api.service.permission.SubjectReference> parents(@NonNull Set<Context> contexts) {
return (List) handle().thenApply(handle -> handle.getParents(CompatibilityUtil.convertContexts(contexts))).join();
}
@Override
public CompletableFuture<Boolean> setParents(Set<Context> contexts, List<? extends SubjectReference> parents, TransferMethod method) {
return null;
}
@Override
public @NonNull CompletableFuture<Boolean> addParent(@NonNull Set<Context> contexts, org.spongepowered.api.service.permission.@NonNull SubjectReference ref) {
return handle().thenCompose(handle -> handle.addParent(CompatibilityUtil.convertContexts(contexts), this.service.getReferenceFactory().obtain(ref)));
}
@Override
public @NonNull CompletableFuture<Boolean> removeParent(@NonNull Set<Context> contexts, org.spongepowered.api.service.permission.@NonNull SubjectReference ref) {
return handle().thenCompose(handle -> handle.removeParent(CompatibilityUtil.convertContexts(contexts), this.service.getReferenceFactory().obtain(ref)));
}
@Override
public @NonNull CompletableFuture<Boolean> clearParents() {
return handle().thenCompose(LPSubjectData::clearParents);
}
@Override
public @NonNull CompletableFuture<Boolean> clearParents(@NonNull Set<Context> contexts) {
return handle().thenCompose(handle -> handle.clearParents(CompatibilityUtil.convertContexts(contexts)));
}
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
public @NonNull Map<Set<Context>, Map<String, String>> allOptions() {
return (Map) handle().thenApply(handle -> handle.getAllOptions().entrySet().stream()
.collect(ImmutableCollectors.toMap(
e -> CompatibilityUtil.convertContexts(e.getKey()),
Map.Entry::getValue
))).join();
}
@Override
public @NonNull Map<String, String> options(@NonNull Set<Context> contexts) {
return handle().thenApply(handle -> handle.getOptions(CompatibilityUtil.convertContexts(contexts))).join();
}
@Override
public @NonNull CompletableFuture<Boolean> setOption(@NonNull Set<Context> contexts, @NonNull String key, @Nullable String value) {
if (value == null) {
return handle().thenCompose(handle -> handle.unsetOption(CompatibilityUtil.convertContexts(contexts), key));
} else {
return handle().thenCompose(handle -> handle.setOption(CompatibilityUtil.convertContexts(contexts), key, value));
}
}
@Override
public CompletableFuture<Boolean> setOptions(Set<Context> contexts, Map<String, String> options, TransferMethod method) {
return null;
}
@Override
public @NonNull CompletableFuture<Boolean> clearOptions() {
return handle().thenCompose(LPSubjectData::clearOptions);
}
@Override
public @NonNull CompletableFuture<Boolean> clearOptions(@NonNull Set<Context> contexts) {
return handle().thenCompose(handle -> handle.clearOptions(CompatibilityUtil.convertContexts(contexts)));
}
@Override
public CompletableFuture<Boolean> copyFrom(SubjectData other, TransferMethod method) {
return null;
}
@Override
public CompletableFuture<Boolean> moveFrom(SubjectData other, TransferMethod method) {
return null;
}
@Override
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof SubjectDataProxy)) return false;
final SubjectDataProxy other = (SubjectDataProxy) o;
return this.ref.equals(other.ref) && this.enduring == other.enduring;
}
@Override
public int hashCode() {
return Objects.hash(this.ref, this.enduring);
}
@Override
public String toString() {
return "luckperms.SubjectDataProxy(ref=" + this.ref + ", enduring=" + this.enduring + ")";
}
}

View File

@@ -0,0 +1,173 @@
/*
* 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.sponge.service.proxy;
import me.lucko.luckperms.sponge.service.CompatibilityUtil;
import me.lucko.luckperms.sponge.service.model.LPPermissionService;
import me.lucko.luckperms.sponge.service.model.LPProxiedServiceObject;
import me.lucko.luckperms.sponge.service.model.LPProxiedSubject;
import me.lucko.luckperms.sponge.service.model.LPSubject;
import me.lucko.luckperms.sponge.service.model.LPSubjectReference;
import me.lucko.luckperms.sponge.service.model.LPSubjectUser;
import net.luckperms.api.query.QueryOptions;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.spongepowered.api.entity.living.player.server.ServerPlayer;
import org.spongepowered.api.event.Cause;
import org.spongepowered.api.service.context.Context;
import org.spongepowered.api.service.permission.PermissionService;
import org.spongepowered.api.service.permission.Subject;
import org.spongepowered.api.service.permission.SubjectCollection;
import org.spongepowered.api.service.permission.SubjectData;
import org.spongepowered.api.service.permission.SubjectReference;
import org.spongepowered.api.util.Tristate;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
public final class SubjectProxy implements Subject, LPProxiedSubject, LPProxiedServiceObject {
private final LPPermissionService service;
private final LPSubjectReference ref;
public SubjectProxy(LPPermissionService service, LPSubjectReference ref) {
this.service = service;
this.ref = ref;
}
private CompletableFuture<LPSubject> handle() {
return this.ref.resolveLp();
}
@Override
public @NonNull LPSubjectReference asSubjectReference() {
return this.ref;
}
@Override
public @NonNull QueryOptions getQueryOptions() {
return this.service.getContextManager().getQueryOptions(this);
}
@Override
public @NonNull SubjectCollection containingCollection() {
return this.service.getCollection(this.ref.collectionIdentifier()).sponge();
}
@Override
public boolean isSubjectDataPersisted() {
return true;
}
@Override
public SubjectData subjectData() {
return new SubjectDataProxy(this.service, this.ref, true);
}
@Override
public SubjectData transientSubjectData() {
return new SubjectDataProxy(this.service, this.ref, false);
}
@Override
public @NonNull Tristate permissionValue(@NonNull String permission, @NonNull Cause cause) {
return handle().thenApply(handle -> CompatibilityUtil.convertTristate(handle.getPermissionValue(this.service.getContextsForCause(cause), permission))).join();
}
@Override
public @NonNull Tristate permissionValue(@NonNull String permission, @NonNull Set<Context> contexts) {
return handle().thenApply(handle -> CompatibilityUtil.convertTristate(handle.getPermissionValue(CompatibilityUtil.convertContexts(contexts), permission))).join();
}
@Override
public boolean isChildOf(@NonNull SubjectReference parent, @NonNull Cause cause) {
return handle().thenApply(handle -> handle.isChildOf(this.service.getContextsForCause(cause), this.service.getReferenceFactory().obtain(parent))).join();
}
@Override
public boolean isChildOf(@NonNull SubjectReference parent, @NonNull Set<Context> contexts) {
return handle().thenApply(handle -> handle.isChildOf(CompatibilityUtil.convertContexts(contexts), this.service.getReferenceFactory().obtain(parent))).join();
}
@Override
public List<? extends SubjectReference> parents(@NonNull Cause cause) {
return handle().thenApply(handle -> handle.getParents(this.service.getContextsForCause(cause))).join();
}
@Override
public @NonNull List<? extends SubjectReference> parents(@NonNull Set<Context> contexts) {
return handle().thenApply(handle -> handle.getParents(CompatibilityUtil.convertContexts(contexts))).join();
}
@Override
public Optional<String> option(@NonNull String key, @NonNull Cause cause) {
return handle().thenApply(handle -> handle.getOption(this.service.getContextsForCause(cause), key)).join();
}
@Override
public @NonNull Optional<String> option(@NonNull String key, @NonNull Set<Context> contexts) {
return handle().thenApply(handle -> handle.getOption(CompatibilityUtil.convertContexts(contexts), key)).join();
}
@Override
public String identifier() {
return this.ref.subjectIdentifier();
}
@Override
public @NonNull Optional<String> friendlyIdentifier() {
return handle().thenApply(LPSubject::getFriendlyIdentifier).join();
}
@Override
public Optional<?> associatedObject() {
if (this.ref.collectionIdentifier().equals(PermissionService.SUBJECTS_USER)) {
LPSubject lpSubject = handle().join();
if (lpSubject instanceof LPSubjectUser) {
ServerPlayer player = ((LPSubjectUser) lpSubject).resolvePlayer().orElse(null);
if (player != null) {
return Optional.of(player);
}
}
}
return Optional.empty();
}
@Override
public boolean equals(Object o) {
return o == this || o instanceof SubjectProxy && this.ref.equals(((SubjectProxy) o).ref);
}
@Override
public int hashCode() {
return this.ref.hashCode();
}
@Override
public String toString() {
return "luckperms.SubjectProxy(ref=" + this.ref + ")";
}
}