More work

This commit is contained in:
Luck 2019-11-18 21:19:59 +00:00
parent 7a37fcd792
commit a5e15b8a29
No known key found for this signature in database
GPG Key ID: EFA9B3EC5FD90F8B
33 changed files with 246 additions and 373 deletions

View File

@ -13,7 +13,7 @@ Still not convinced? More information can be found on the wiki, under: [Why Luck
## Useful Links ## Useful Links
The latest **downloads** can be found on the [project's homepage](https://luckperms.github.io/). The latest **downloads** can be found on the [project's homepage](https://luckperms.net/).
More information about the project & how to use the plugin can be found in the [wiki](https://github.com/lucko/LuckPerms/wiki). More information about the project & how to use the plugin can be found in the [wiki](https://github.com/lucko/LuckPerms/wiki).

View File

@ -11,6 +11,7 @@ if (project.hasProperty('sonatypeUsername') && project.hasProperty('sonatypePass
apply plugin: 'signing' apply plugin: 'signing'
javadoc { javadoc {
title = 'LuckPerms API (v' + project.ext.apiVersion + ')'
options.encoding = 'UTF-8' options.encoding = 'UTF-8'
options.charSet = 'UTF-8' options.charSet = 'UTF-8'
options.links( options.links(
@ -56,7 +57,7 @@ if (project.hasProperty('sonatypeUsername') && project.hasProperty('sonatypePass
project { project {
name 'LuckPerms API' name 'LuckPerms API'
description 'An advanced permissions plugin for Bukkit/Spigot, BungeeCord, Sponge, Nukkit and Velocity.' description 'An advanced permissions plugin for Bukkit/Spigot, BungeeCord, Sponge, Nukkit and Velocity.'
url 'https://luckperms.github.io' url 'https://luckperms.net'
licenses { licenses {
license { license {

View File

@ -160,7 +160,7 @@ public interface LuckPerms {
/** /**
* Gets the {@link ContextManager}, responsible for managing * Gets the {@link ContextManager}, responsible for managing
* {@link ContextCalculator}s, and calculating applicable contexts.</p> * {@link ContextCalculator}s, and calculating applicable contexts.
* *
* @return the context manager * @return the context manager
*/ */

View File

@ -47,6 +47,7 @@ public interface ExtensionManager {
* Loads the extension at the given path. * Loads the extension at the given path.
* *
* @param path the path to the extension * @param path the path to the extension
* @return the extension
* @throws IOException if the extension could not be loaded * @throws IOException if the extension could not be loaded
*/ */
@NonNull Extension loadExtension(Path path) throws IOException; @NonNull Extension loadExtension(Path path) throws IOException;

View File

@ -35,8 +35,8 @@ import java.util.Objects;
* <p>It is intended that {@link NodeMetadataKey}s are obtained and stored as * <p>It is intended that {@link NodeMetadataKey}s are obtained and stored as
* follows.</p> * follows.</p>
* <p><blockquote><pre> * <p><blockquote><pre>
* public static final NodeMetadataKey<SpecialMetadata> SPECIAL_METADATA_KEY = NodeMetadataKey.of("specialmetadata", SpecialMetadata.class); * public static final NodeMetadataKey&lt;SpecialMetadata&gt; SPECIAL_METADATA_KEY = NodeMetadataKey.of("specialmetadata", SpecialMetadata.class);
* </pre></blockquote></p> * </pre></blockquote>
* *
* @param <T> the metadata type * @param <T> the metadata type
*/ */
@ -70,6 +70,6 @@ public interface NodeMetadataKey<T> {
* *
* @return the type * @return the type
*/ */
@NonNull Class<T> getType(); @NonNull Class<T> type();
} }

View File

@ -44,7 +44,7 @@ final class SimpleNodeMetadataKey<T> implements NodeMetadataKey<T> {
} }
@Override @Override
public @NonNull Class<T> getType() { public @NonNull Class<T> type() {
return this.type; return this.type;
} }

View File

@ -52,6 +52,6 @@ public interface InheritanceOriginMetadata {
* *
* @return where the node was inherited from. * @return where the node was inherited from.
*/ */
@NonNull String getOrigin(); PermissionHolder.@NonNull Identifier getOrigin();
} }

View File

@ -36,8 +36,8 @@ import java.util.Objects;
* *
* <p>It is intended that {@link OptionKey}s are created and defined as follows.</p> * <p>It is intended that {@link OptionKey}s are created and defined as follows.</p>
* <p><blockquote><pre> * <p><blockquote><pre>
* public static final OptionKey<String> SPECIAL_OPTION = OptionKey.of("special", String.class); * public static final OptionKey&lt;String&gt; SPECIAL_OPTION = OptionKey.of("special", String.class);
* </pre></blockquote></p> * </pre></blockquote>
* *
* @param <T> the option type * @param <T> the option type
*/ */
@ -71,6 +71,6 @@ public interface OptionKey<T> {
* *
* @return the type * @return the type
*/ */
@NonNull Class<T> getType(); @NonNull Class<T> type();
} }

View File

@ -44,7 +44,7 @@ final class SimpleOptionKey<T> implements OptionKey<T> {
} }
@Override @Override
public @NonNull Class<T> getType() { public @NonNull Class<T> type() {
return this.type; return this.type;
} }

View File

@ -47,7 +47,8 @@ subprojects {
project.ext.majorVersion = '5' project.ext.majorVersion = '5'
project.ext.minorVersion = '0' project.ext.minorVersion = '0'
project.ext.patchVersion = determinePatchVersion() project.ext.patchVersion = determinePatchVersion()
project.ext.fullVersion = project.ext.majorVersion + '.' + project.ext.minorVersion + '.' + project.ext.patchVersion project.ext.apiVersion = project.ext.majorVersion + '.' + project.ext.minorVersion
project.ext.fullVersion = project.ext.apiVersion + '.' + project.ext.patchVersion
license { license {
header = rootProject.file('HEADER.txt') header = rootProject.file('HEADER.txt')

View File

@ -4,7 +4,7 @@
# | | | | / ` |__/ |__) |__ |__) |\/| /__` | # # | | | | / ` |__/ |__) |__ |__) |\/| /__` | #
# | |___ \__/ \__, | \ | |___ | \ | | .__/ | # # | |___ \__/ \__, | \ | |___ | \ | | .__/ | #
# | | # # | | #
# | https://luckperms.github.io | # # | https://luckperms.net | #
# | | # # | | #
# | SOURCE CODE: https://github.com/lucko/LuckPerms | # # | SOURCE CODE: https://github.com/lucko/LuckPerms | #
# | WIKI: https://github.com/lucko/LuckPerms/wiki | # # | WIKI: https://github.com/lucko/LuckPerms/wiki | #

View File

@ -2,7 +2,7 @@ name: LuckPerms
version: ${pluginVersion} version: ${pluginVersion}
description: A permissions plugin description: A permissions plugin
author: Luck author: Luck
website: https://luckperms.github.io website: https://luckperms.net
main: me.lucko.luckperms.bukkit.LPBukkitBootstrap main: me.lucko.luckperms.bukkit.LPBukkitBootstrap
load: STARTUP load: STARTUP

View File

@ -4,7 +4,7 @@
# | | | | / ` |__/ |__) |__ |__) |\/| /__` | # # | | | | / ` |__/ |__) |__ |__) |\/| /__` | #
# | |___ \__/ \__, | \ | |___ | \ | | .__/ | # # | |___ \__/ \__, | \ | |___ | \ | | .__/ | #
# | | # # | | #
# | https://luckperms.github.io | # # | https://luckperms.net | #
# | | # # | | #
# | SOURCE CODE: https://github.com/lucko/LuckPerms | # # | SOURCE CODE: https://github.com/lucko/LuckPerms | #
# | WIKI: https://github.com/lucko/LuckPerms/wiki | # # | WIKI: https://github.com/lucko/LuckPerms/wiki | #

View File

@ -69,7 +69,7 @@ import java.util.function.Consumer;
public class MetaInfo extends SharedSubCommand { public class MetaInfo extends SharedSubCommand {
private static String processLocation(Node node, PermissionHolder holder) { private static String processLocation(Node node, PermissionHolder holder) {
String location = node.metadata(InheritanceOriginMetadata.KEY).getOrigin(); String location = node.metadata(InheritanceOriginMetadata.KEY).getOrigin().getName();
return location.equalsIgnoreCase(holder.getObjectName()) ? "self" : location; return location.equalsIgnoreCase(holder.getObjectName()) ? "self" : location;
} }
@ -162,7 +162,7 @@ public class MetaInfo extends SharedSubCommand {
} }
private static Consumer<ComponentBuilder<?, ?>> makeFancy(PermissionHolder holder, String label, ChatMetaNode<?, ?> node) { private static Consumer<ComponentBuilder<?, ?>> makeFancy(PermissionHolder holder, String label, ChatMetaNode<?, ?> node) {
String location = node.metadata(InheritanceOriginMetadata.KEY).getOrigin(); String location = node.metadata(InheritanceOriginMetadata.KEY).getOrigin().getName();
if (!location.equals(holder.getObjectName())) { if (!location.equals(holder.getObjectName())) {
// inherited. // inherited.
Group group = holder.getPlugin().getGroupManager().getIfLoaded(location); Group group = holder.getPlugin().getGroupManager().getIfLoaded(location);
@ -189,7 +189,7 @@ public class MetaInfo extends SharedSubCommand {
} }
private static Consumer<ComponentBuilder<?, ?>> makeFancy(PermissionHolder holder, String label, MetaNode node) { private static Consumer<ComponentBuilder<?, ?>> makeFancy(PermissionHolder holder, String label, MetaNode node) {
String location = node.metadata(InheritanceOriginMetadata.KEY).getOrigin(); String location = node.metadata(InheritanceOriginMetadata.KEY).getOrigin().getName();
if (!location.equals(holder.getObjectName())) { if (!location.equals(holder.getObjectName())) {
// inherited. // inherited.
Group group = holder.getPlugin().getGroupManager().getIfLoaded(location); Group group = holder.getPlugin().getGroupManager().getIfLoaded(location);

View File

@ -70,7 +70,7 @@ public class PermissionCheckInherits extends SharedSubCommand {
.filter(n -> n.getKey().equalsIgnoreCase(node) && n.getContexts().equals(context)) .filter(n -> n.getKey().equalsIgnoreCase(node) && n.getContexts().equals(context))
.findFirst(); .findFirst();
String location = match.map(n -> n.metadata(InheritanceOriginMetadata.KEY).getOrigin()).orElse(null); String location = match.map(n -> n.metadata(InheritanceOriginMetadata.KEY).getOrigin().getName()).orElse(null);
if (location == null || location.equalsIgnoreCase(holder.getObjectName())) { if (location == null || location.equalsIgnoreCase(holder.getObjectName())) {
location = "self"; location = "self";

View File

@ -32,11 +32,8 @@ import me.lucko.luckperms.common.context.contextset.ImmutableContextSetImpl;
import me.lucko.luckperms.common.graph.TraversalAlgorithm; import me.lucko.luckperms.common.graph.TraversalAlgorithm;
import me.lucko.luckperms.common.metastacking.SimpleMetaStackDefinition; import me.lucko.luckperms.common.metastacking.SimpleMetaStackDefinition;
import me.lucko.luckperms.common.metastacking.StandardStackElements; import me.lucko.luckperms.common.metastacking.StandardStackElements;
import me.lucko.luckperms.common.model.PrimaryGroupHolder;
import me.lucko.luckperms.common.model.User; import me.lucko.luckperms.common.model.User;
import me.lucko.luckperms.common.primarygroup.AllParentsByWeightHolder;
import me.lucko.luckperms.common.primarygroup.ParentsByWeightHolder;
import me.lucko.luckperms.common.primarygroup.PrimaryGroupHolder;
import me.lucko.luckperms.common.primarygroup.StoredHolder;
import me.lucko.luckperms.common.storage.StorageType; import me.lucko.luckperms.common.storage.StorageType;
import me.lucko.luckperms.common.storage.implementation.split.SplitStorageType; import me.lucko.luckperms.common.storage.implementation.split.SplitStorageType;
import me.lucko.luckperms.common.storage.misc.StorageCredentials; import me.lucko.luckperms.common.storage.misc.StorageCredentials;
@ -162,11 +159,11 @@ public final class ConfigKeys {
String option = PRIMARY_GROUP_CALCULATION_METHOD.get(c); String option = PRIMARY_GROUP_CALCULATION_METHOD.get(c);
switch (option) { switch (option) {
case "stored": case "stored":
return (Function<User, PrimaryGroupHolder>) StoredHolder::new; return (Function<User, PrimaryGroupHolder>) PrimaryGroupHolder.Stored::new;
case "parents-by-weight": case "parents-by-weight":
return (Function<User, PrimaryGroupHolder>) ParentsByWeightHolder::new; return (Function<User, PrimaryGroupHolder>) PrimaryGroupHolder.ParentsByWeight::new;
default: default:
return (Function<User, PrimaryGroupHolder>) AllParentsByWeightHolder::new; return (Function<User, PrimaryGroupHolder>) PrimaryGroupHolder.AllParentsByWeight::new;
} }
})); }));

View File

@ -28,9 +28,9 @@ package me.lucko.luckperms.common.metastacking;
import me.lucko.luckperms.common.model.Track; import me.lucko.luckperms.common.model.Track;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.util.ImmutableCollectors; import me.lucko.luckperms.common.util.ImmutableCollectors;
import me.lucko.luckperms.common.util.Uuids;
import net.luckperms.api.metastacking.MetaStackElement; import net.luckperms.api.metastacking.MetaStackElement;
import net.luckperms.api.model.PermissionHolder;
import net.luckperms.api.node.ChatMetaType; import net.luckperms.api.node.ChatMetaType;
import net.luckperms.api.node.metadata.types.InheritanceOriginMetadata; import net.luckperms.api.node.metadata.types.InheritanceOriginMetadata;
import net.luckperms.api.node.types.ChatMetaNode; import net.luckperms.api.node.types.ChatMetaNode;
@ -97,8 +97,8 @@ public final class StandardStackElements {
private static final MetaStackElement TYPE_CHECK = (type, node, current) -> type.nodeType().matches(node); private static final MetaStackElement TYPE_CHECK = (type, node, current) -> type.nodeType().matches(node);
private static final MetaStackElement HIGHEST_CHECK = (type, node, current) -> current == null || node.getPriority() > current.getPriority(); private static final MetaStackElement HIGHEST_CHECK = (type, node, current) -> current == null || node.getPriority() > current.getPriority();
private static final MetaStackElement LOWEST_CHECK = (type, node, current) -> current == null || node.getPriority() < current.getPriority(); private static final MetaStackElement LOWEST_CHECK = (type, node, current) -> current == null || node.getPriority() < current.getPriority();
private static final MetaStackElement OWN_CHECK = (type, node, current) -> Uuids.fromString(node.metadata(InheritanceOriginMetadata.KEY).getOrigin()) != null; private static final MetaStackElement OWN_CHECK = (type, node, current) -> node.metadata(InheritanceOriginMetadata.KEY).getOrigin().getType().equals(PermissionHolder.Identifier.USER_TYPE);
private static final MetaStackElement INHERITED_CHECK = (type, node, current) -> Uuids.fromString(node.metadata(InheritanceOriginMetadata.KEY).getOrigin()) == null; private static final MetaStackElement INHERITED_CHECK = (type, node, current) -> node.metadata(InheritanceOriginMetadata.KEY).getOrigin().getType().equals(PermissionHolder.Identifier.GROUP_TYPE);
// implementations // implementations
@ -220,8 +220,9 @@ public final class StandardStackElements {
@Override @Override
public boolean shouldAccumulate(@NonNull ChatMetaType type, @NonNull ChatMetaNode<?, ?> node, @Nullable ChatMetaNode<?, ?> current) { public boolean shouldAccumulate(@NonNull ChatMetaType type, @NonNull ChatMetaNode<?, ?> node, @Nullable ChatMetaNode<?, ?> current) {
Track t = this.plugin.getTrackManager().getIfLoaded(this.trackName); Track track = this.plugin.getTrackManager().getIfLoaded(this.trackName);
return t != null && t.containsGroup(node.metadata(InheritanceOriginMetadata.KEY).getOrigin()); PermissionHolder.Identifier origin = node.metadata(InheritanceOriginMetadata.KEY).getOrigin();
return track != null && origin.getType().equals(PermissionHolder.Identifier.GROUP_TYPE) && track.containsGroup(origin.getName());
} }
@Override @Override
@ -249,8 +250,9 @@ public final class StandardStackElements {
@Override @Override
public boolean shouldAccumulate(@NonNull ChatMetaType type, @NonNull ChatMetaNode<?, ?> node, @Nullable ChatMetaNode<?, ?> current) { public boolean shouldAccumulate(@NonNull ChatMetaType type, @NonNull ChatMetaNode<?, ?> node, @Nullable ChatMetaNode<?, ?> current) {
Track t = this.plugin.getTrackManager().getIfLoaded(this.trackName); Track track = this.plugin.getTrackManager().getIfLoaded(this.trackName);
return t != null && !t.containsGroup(node.metadata(InheritanceOriginMetadata.KEY).getOrigin()); PermissionHolder.Identifier origin = node.metadata(InheritanceOriginMetadata.KEY).getOrigin();
return track != null && !track.containsGroup(origin.getName());
} }
@Override @Override
@ -276,7 +278,8 @@ public final class StandardStackElements {
@Override @Override
public boolean shouldAccumulate(@NonNull ChatMetaType type, @NonNull ChatMetaNode<?, ?> node, @Nullable ChatMetaNode<?, ?> current) { public boolean shouldAccumulate(@NonNull ChatMetaType type, @NonNull ChatMetaNode<?, ?> node, @Nullable ChatMetaNode<?, ?> current) {
return this.groupName.equals(node.metadata(InheritanceOriginMetadata.KEY).getOrigin()); PermissionHolder.Identifier origin = node.metadata(InheritanceOriginMetadata.KEY).getOrigin();
return origin.getType().equals(PermissionHolder.Identifier.GROUP_TYPE) && this.groupName.equals(origin.getName());
} }
@Override @Override
@ -302,7 +305,8 @@ public final class StandardStackElements {
@Override @Override
public boolean shouldAccumulate(@NonNull ChatMetaType type, @NonNull ChatMetaNode<?, ?> node, @Nullable ChatMetaNode<?, ?> current) { public boolean shouldAccumulate(@NonNull ChatMetaType type, @NonNull ChatMetaNode<?, ?> node, @Nullable ChatMetaNode<?, ?> current) {
return !this.groupName.equals(node.metadata(InheritanceOriginMetadata.KEY).getOrigin()); PermissionHolder.Identifier origin = node.metadata(InheritanceOriginMetadata.KEY).getOrigin();
return !this.groupName.equals(origin.getName());
} }
@Override @Override

View File

@ -198,11 +198,11 @@ public final class NodeMap {
private Node localise(Node node) { private Node localise(Node node) {
Optional<InheritanceOriginMetadata> metadata = node.getMetadata(InheritanceOriginMetadata.KEY); Optional<InheritanceOriginMetadata> metadata = node.getMetadata(InheritanceOriginMetadata.KEY);
if (metadata.map(InheritanceOriginMetadata::getOrigin).equals(Optional.of(this.holder.getObjectName()))) { if (metadata.isPresent() && metadata.get().getOrigin().equals(this.holder.getIdentifier())) {
return node; return node;
} }
return node.toBuilder().withMetadata(InheritanceOriginMetadata.KEY, new InheritanceOrigin(this.holder.getObjectName())).build(); return node.toBuilder().withMetadata(InheritanceOriginMetadata.KEY, new InheritanceOrigin(this.holder.getIdentifier())).build();
} }
void add(Node node) { void add(Node node) {

View File

@ -52,6 +52,7 @@ import net.luckperms.api.query.QueryOptions;
import net.luckperms.api.query.dataorder.DataQueryOrder; import net.luckperms.api.query.dataorder.DataQueryOrder;
import net.luckperms.api.query.dataorder.DataQueryOrderFunction; import net.luckperms.api.query.dataorder.DataQueryOrderFunction;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
@ -100,6 +101,11 @@ public abstract class PermissionHolder {
*/ */
private final LuckPermsPlugin plugin; private final LuckPermsPlugin plugin;
/**
* The holders identifier
*/
private @MonotonicNonNull PermissionHolderIdentifier identifier;
/** /**
* The holders persistent nodes. * The holders persistent nodes.
* *
@ -175,7 +181,10 @@ public abstract class PermissionHolder {
} }
public PermissionHolderIdentifier getIdentifier() { public PermissionHolderIdentifier getIdentifier() {
return new PermissionHolderIdentifier(getType(), getObjectName()); if (this.identifier == null) {
this.identifier = new PermissionHolderIdentifier(getType(), getObjectName());
}
return this.identifier;
} }
/** /**

View File

@ -0,0 +1,182 @@
/*
* 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.model;
import me.lucko.luckperms.common.cache.LoadingMap;
import me.lucko.luckperms.common.config.ConfigKeys;
import me.lucko.luckperms.common.inheritance.InheritanceGraph;
import me.lucko.luckperms.common.model.manager.group.GroupManager;
import net.luckperms.api.node.types.InheritanceNode;
import net.luckperms.api.query.QueryOptions;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
/**
* Calculates and caches a User's "primary group"
*/
public interface PrimaryGroupHolder {
/**
* Gets the name of the primary group, or null.
*
* @return the name of the primary group, or null.
*/
String getValue();
/**
* Gets the primary group which is stored against the user's data.
*
* @return the stored value
*/
Optional<String> getStoredValue();
/**
* Sets the primary group which is stored against the user's data.
*
* @param value the new stored value
*/
void setStoredValue(String value);
/**
* Simple implementation which just holds a stored value.
*/
class Stored implements PrimaryGroupHolder {
protected final User user;
private String value = null;
public Stored(User user) {
this.user = Objects.requireNonNull(user, "user");
}
@Override
public String getValue() {
return this.value;
}
@Override
public Optional<String> getStoredValue() {
return Optional.ofNullable(this.value);
}
@Override
public void setStoredValue(String value) {
if (value == null || value.isEmpty()) {
this.value = null;
} else {
this.value = value.toLowerCase();
}
}
}
/**
* Abstract implementation of {@link PrimaryGroupHolder} which caches all lookups by context.
*/
abstract class AbstractContextual extends Stored {
private final Map<QueryOptions, Optional<String>> cache = LoadingMap.of(this::calculateValue);
AbstractContextual(User user) {
super(user);
}
protected abstract @NonNull Optional<String> calculateValue(QueryOptions queryOptions);
public void invalidateCache() {
this.cache.clear();
}
@Override
public final String getValue() {
QueryOptions queryOptions = this.user.getPlugin().getQueryOptionsForUser(this.user).orElse(null);
if (queryOptions == null) {
queryOptions = this.user.getPlugin().getContextManager().getStaticQueryOptions();
}
return Objects.requireNonNull(this.cache.get(queryOptions))
.orElseGet(() -> getStoredValue().orElse(GroupManager.DEFAULT_GROUP_NAME));
}
}
class AllParentsByWeight extends AbstractContextual {
public AllParentsByWeight(User user) {
super(user);
}
@Override
protected @NonNull Optional<String> calculateValue(QueryOptions queryOptions) {
InheritanceGraph graph = this.user.getPlugin().getInheritanceHandler().getGraph(queryOptions);
// fully traverse the graph, obtain a list of permission holders the user inherits from in weight order.
Iterable<PermissionHolder> traversal = graph.traverse(this.user.getPlugin().getConfiguration().get(ConfigKeys.INHERITANCE_TRAVERSAL_ALGORITHM), true, this.user);
// return the name of the first found group
for (PermissionHolder holder : traversal) {
if (holder instanceof Group) {
return Optional.of(((Group) holder).getName());
}
}
return Optional.empty();
}
}
class ParentsByWeight extends AbstractContextual {
public ParentsByWeight(User user) {
super(user);
}
@Override
protected @NonNull Optional<String> calculateValue(QueryOptions queryOptions) {
Set<Group> groups = new LinkedHashSet<>();
for (InheritanceNode node : this.user.getOwnInheritanceNodes(queryOptions)) {
Group group = this.user.getPlugin().getGroupManager().getIfLoaded(node.getGroupName());
if (group != null) {
groups.add(group);
}
}
Group bestGroup = null;
int best = 0;
for (Group g : groups) {
int weight = g.getWeight().orElse(0);
if (bestGroup == null || weight > best) {
bestGroup = g;
best = weight;
}
}
return bestGroup == null ? Optional.empty() : Optional.of(bestGroup.getName());
}
}
}

View File

@ -29,8 +29,6 @@ import me.lucko.luckperms.common.api.implementation.ApiUser;
import me.lucko.luckperms.common.cacheddata.UserCachedDataManager; import me.lucko.luckperms.common.cacheddata.UserCachedDataManager;
import me.lucko.luckperms.common.config.ConfigKeys; import me.lucko.luckperms.common.config.ConfigKeys;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.primarygroup.ContextualHolder;
import me.lucko.luckperms.common.primarygroup.PrimaryGroupHolder;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
@ -73,8 +71,8 @@ public class User extends PermissionHolder {
super.invalidateCache(); super.invalidateCache();
// invalidate our caches // invalidate our caches
if (this.primaryGroup instanceof ContextualHolder) { if (this.primaryGroup instanceof PrimaryGroupHolder.AbstractContextual) {
((ContextualHolder) this.primaryGroup).invalidateCache(); ((PrimaryGroupHolder.AbstractContextual) this.primaryGroup).invalidateCache();
} }
} }

View File

@ -25,19 +25,20 @@
package me.lucko.luckperms.common.node.model; package me.lucko.luckperms.common.node.model;
import net.luckperms.api.model.PermissionHolder;
import net.luckperms.api.node.metadata.types.InheritanceOriginMetadata; import net.luckperms.api.node.metadata.types.InheritanceOriginMetadata;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
public class InheritanceOrigin implements InheritanceOriginMetadata { public class InheritanceOrigin implements InheritanceOriginMetadata {
private final String location; private final PermissionHolder.Identifier location;
public InheritanceOrigin(String location) { public InheritanceOrigin(PermissionHolder.Identifier location) {
this.location = location; this.location = location;
} }
@Override @Override
public @NonNull String getOrigin() { public PermissionHolder.@NonNull Identifier getOrigin() {
return this.location; return this.location;
} }
} }

View File

@ -1,60 +0,0 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.common.primarygroup;
import me.lucko.luckperms.common.config.ConfigKeys;
import me.lucko.luckperms.common.inheritance.InheritanceGraph;
import me.lucko.luckperms.common.model.Group;
import me.lucko.luckperms.common.model.PermissionHolder;
import me.lucko.luckperms.common.model.User;
import net.luckperms.api.query.QueryOptions;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.Optional;
public class AllParentsByWeightHolder extends ContextualHolder {
public AllParentsByWeightHolder(User user) {
super(user);
}
@Override
protected @NonNull Optional<String> calculateValue(QueryOptions queryOptions) {
InheritanceGraph graph = this.user.getPlugin().getInheritanceHandler().getGraph(queryOptions);
// fully traverse the graph, obtain a list of permission holders the user inherits from in weight order.
Iterable<PermissionHolder> traversal = graph.traverse(this.user.getPlugin().getConfiguration().get(ConfigKeys.INHERITANCE_TRAVERSAL_ALGORITHM), true, this.user);
// return the name of the first found group
for (PermissionHolder holder : traversal) {
if (holder instanceof Group) {
return Optional.of(((Group) holder).getName());
}
}
return Optional.empty();
}
}

View File

@ -1,73 +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.primarygroup;
import com.github.benmanes.caffeine.cache.LoadingCache;
import me.lucko.luckperms.common.model.User;
import me.lucko.luckperms.common.model.manager.group.GroupManager;
import me.lucko.luckperms.common.util.CaffeineFactory;
import net.luckperms.api.query.QueryOptions;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
/**
* Abstract implementation of {@link PrimaryGroupHolder} which caches all lookups.
*/
public abstract class ContextualHolder extends StoredHolder {
// cache lookups
private final LoadingCache<QueryOptions, Optional<String>> cache = CaffeineFactory.newBuilder()
.expireAfterAccess(1, TimeUnit.MINUTES)
.build(this::calculateValue);
public ContextualHolder(User user) {
super(user);
}
protected abstract @NonNull Optional<String> calculateValue(QueryOptions queryOptions);
public void invalidateCache() {
this.cache.invalidateAll();
}
@Override
public final String getValue() {
QueryOptions queryOptions = this.user.getPlugin().getQueryOptionsForUser(this.user).orElse(null);
if (queryOptions == null) {
queryOptions = this.user.getPlugin().getContextManager().getStaticQueryOptions();
}
return Objects.requireNonNull(this.cache.get(queryOptions))
.orElseGet(() -> getStoredValue().orElse(GroupManager.DEFAULT_GROUP_NAME));
}
}

View File

@ -1,68 +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.primarygroup;
import me.lucko.luckperms.common.model.Group;
import me.lucko.luckperms.common.model.User;
import net.luckperms.api.node.types.InheritanceNode;
import net.luckperms.api.query.QueryOptions;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.LinkedHashSet;
import java.util.Optional;
import java.util.Set;
public class ParentsByWeightHolder extends ContextualHolder {
public ParentsByWeightHolder(User user) {
super(user);
}
@Override
protected @NonNull Optional<String> calculateValue(QueryOptions queryOptions) {
Set<Group> groups = new LinkedHashSet<>();
for (InheritanceNode node : this.user.getOwnInheritanceNodes(queryOptions)) {
Group group = this.user.getPlugin().getGroupManager().getIfLoaded(node.getGroupName());
if (group != null) {
groups.add(group);
}
}
Group bestGroup = null;
int best = 0;
for (Group g : groups) {
int weight = g.getWeight().orElse(0);
if (bestGroup == null || weight > best) {
bestGroup = g;
best = weight;
}
}
return bestGroup == null ? Optional.empty() : Optional.of(bestGroup.getName());
}
}

View File

@ -1,56 +0,0 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.common.primarygroup;
import java.util.Optional;
/**
* Calculates and caches a User's "primary group"
*/
public interface PrimaryGroupHolder {
/**
* Gets the name of the primary group, or null.
*
* @return the name of the primary group, or null.
*/
String getValue();
/**
* Gets the primary group which is stored against the user's data.
*
* @return the stored value
*/
Optional<String> getStoredValue();
/**
* Sets the primary group which is stored against the user's data.
*
* @param storedValue the new stored value
*/
void setStoredValue(String storedValue);
}

View File

@ -1,64 +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.primarygroup;
import me.lucko.luckperms.common.model.User;
import java.util.Objects;
import java.util.Optional;
/**
* Simple implementation of {@link PrimaryGroupHolder}, which just returns the stored value.
*/
public class StoredHolder implements PrimaryGroupHolder {
protected final User user;
private String storedValue = null;
public StoredHolder(User user) {
this.user = Objects.requireNonNull(user, "user");
}
@Override
public String getValue() {
return this.storedValue;
}
@Override
public Optional<String> getStoredValue() {
return Optional.ofNullable(this.storedValue);
}
@Override
public void setStoredValue(String storedValue) {
if (storedValue == null || storedValue.isEmpty()) {
this.storedValue = null;
} else {
this.storedValue = storedValue.toLowerCase();
}
}
}

View File

@ -4,7 +4,7 @@
# | | | | / ` |__/ |__) |__ |__) |\/| /__` | # # | | | | / ` |__/ |__) |__ |__) |\/| /__` | #
# | |___ \__/ \__, | \ | |___ | \ | | .__/ | # # | |___ \__/ \__, | \ | |___ | \ | | .__/ | #
# | | # # | | #
# | https://luckperms.github.io | # # | https://luckperms.net | #
# | | # # | | #
# | SOURCE CODE: https://github.com/lucko/LuckPerms | # # | SOURCE CODE: https://github.com/lucko/LuckPerms | #
# | WIKI: https://github.com/lucko/LuckPerms/wiki | # # | WIKI: https://github.com/lucko/LuckPerms/wiki | #

View File

@ -3,7 +3,7 @@ version: ${pluginVersion}
api: ["1.0.5"] api: ["1.0.5"]
description: A permissions plugin description: A permissions plugin
author: Luck author: Luck
website: https://luckperms.github.io website: https://luckperms.net
main: me.lucko.luckperms.nukkit.LPNukkitBootstrap main: me.lucko.luckperms.nukkit.LPNukkitBootstrap
load: STARTUP load: STARTUP

View File

@ -71,7 +71,7 @@ import java.util.stream.Stream;
version = "@version@", version = "@version@",
authors = "Luck", authors = "Luck",
description = "A permissions plugin", description = "A permissions plugin",
url = "https://luckperms.github.io", url = "https://luckperms.net",
dependencies = { dependencies = {
// explicit dependency on spongeapi with no defined API version // explicit dependency on spongeapi with no defined API version
@Dependency(id = "spongeapi") @Dependency(id = "spongeapi")

View File

@ -4,7 +4,7 @@
# | | | | / ` |__/ |__) |__ |__) |\/| /__` | # # | | | | / ` |__/ |__) |__ |__) |\/| /__` | #
# | |___ \__/ \__, | \ | |___ | \ | | .__/ | # # | |___ \__/ \__, | \ | |___ | \ | | .__/ | #
# | | # # | | #
# | https://luckperms.github.io | # # | https://luckperms.net | #
# | | # # | | #
# | SOURCE CODE: https://github.com/lucko/LuckPerms | # # | SOURCE CODE: https://github.com/lucko/LuckPerms | #
# | WIKI: https://github.com/lucko/LuckPerms/wiki | # # | WIKI: https://github.com/lucko/LuckPerms/wiki | #

View File

@ -61,7 +61,7 @@ import java.util.stream.Stream;
version = "@version@", version = "@version@",
authors = "Luck", authors = "Luck",
description = "A permissions plugin", description = "A permissions plugin",
url = "https://luckperms.github.io" url = "https://luckperms.net"
) )
public class LPVelocityBootstrap implements LuckPermsBootstrap { public class LPVelocityBootstrap implements LuckPermsBootstrap {

View File

@ -4,7 +4,7 @@
# | | | | / ` |__/ |__) |__ |__) |\/| /__` | # # | | | | / ` |__/ |__) |__ |__) |\/| /__` | #
# | |___ \__/ \__, | \ | |___ | \ | | .__/ | # # | |___ \__/ \__, | \ | |___ | \ | | .__/ | #
# | | # # | | #
# | https://luckperms.github.io | # # | https://luckperms.net | #
# | | # # | | #
# | SOURCE CODE: https://github.com/lucko/LuckPerms | # # | SOURCE CODE: https://github.com/lucko/LuckPerms | #
# | WIKI: https://github.com/lucko/LuckPerms/wiki | # # | WIKI: https://github.com/lucko/LuckPerms/wiki | #