mirror of
https://github.com/LuckPerms/LuckPerms.git
synced 2024-12-28 03:57:36 +01:00
Final bits of API refactoring, add group data caches, fix issue with LPPermissionAttachment fake map injection
This commit is contained in:
parent
d75b29f51d
commit
a115ff8ce2
@ -25,7 +25,10 @@
|
||||
|
||||
package me.lucko.luckperms.api;
|
||||
|
||||
import me.lucko.luckperms.api.caching.GroupData;
|
||||
|
||||
import java.util.OptionalInt;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
@ -51,4 +54,23 @@ public interface Group extends PermissionHolder {
|
||||
@Nonnull
|
||||
OptionalInt getWeight();
|
||||
|
||||
/**
|
||||
* Gets the groups's {@link GroupData} cache.
|
||||
*
|
||||
* @return the groups cached data.
|
||||
* @since 4.0
|
||||
*/
|
||||
@Nonnull
|
||||
@Override
|
||||
GroupData getCachedData();
|
||||
|
||||
/**
|
||||
* Refreshes and applies any changes to the cached group data.
|
||||
*
|
||||
* @return the task future
|
||||
* @since 4.0
|
||||
*/
|
||||
@Nonnull
|
||||
CompletableFuture<Void> refreshCachedData();
|
||||
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ package me.lucko.luckperms.api;
|
||||
import com.google.common.collect.ImmutableSetMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
import me.lucko.luckperms.api.caching.CachedData;
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
|
||||
@ -70,6 +71,15 @@ public interface PermissionHolder {
|
||||
@Nonnull
|
||||
String getFriendlyName();
|
||||
|
||||
/**
|
||||
* Gets the holders {@link CachedData} cache.
|
||||
*
|
||||
* @return the holders cached data.
|
||||
* @since 3.2
|
||||
*/
|
||||
@Nonnull
|
||||
CachedData getCachedData();
|
||||
|
||||
/**
|
||||
* Gets the backing multimap containing every permission this holder has.
|
||||
*
|
||||
|
@ -84,6 +84,7 @@ public interface User extends PermissionHolder {
|
||||
* @since 3.2
|
||||
*/
|
||||
@Nonnull
|
||||
@Override
|
||||
UserData getCachedData();
|
||||
|
||||
/**
|
||||
|
404
api/src/main/java/me/lucko/luckperms/api/caching/CachedData.java
Normal file
404
api/src/main/java/me/lucko/luckperms/api/caching/CachedData.java
Normal file
@ -0,0 +1,404 @@
|
||||
/*
|
||||
* 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.api.caching;
|
||||
|
||||
import me.lucko.luckperms.api.Contexts;
|
||||
import me.lucko.luckperms.api.PermissionHolder;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* Holds cached permission and meta lookup data for a {@link PermissionHolder}.
|
||||
*
|
||||
* <p>All calls will account for inheritance, as well as any default data provided by
|
||||
* the platform. This calls are heavily cached and are therefore fast.</p>
|
||||
*
|
||||
* <p>For meta, both methods accepting {@link Contexts} and {@link MetaContexts} are provided. The only difference is that
|
||||
* the latter allows you to define how the meta stack should be structured internally. Where {@link Contexts} are passed, the
|
||||
* values from the configuration are used.</p>
|
||||
*
|
||||
* @since 4.0
|
||||
*/
|
||||
public interface CachedData {
|
||||
|
||||
/**
|
||||
* Gets PermissionData from the cache, given a specified context.
|
||||
*
|
||||
* @param contexts the contexts to get the permission data in
|
||||
* @return a permission data instance
|
||||
* @throws NullPointerException if contexts is null
|
||||
*/
|
||||
@Nonnull
|
||||
PermissionData getPermissionData(@Nonnull Contexts contexts);
|
||||
|
||||
/**
|
||||
* Gets MetaData from the cache, given a specified context.
|
||||
*
|
||||
* @param contexts the contexts to get the permission data in
|
||||
* @return a meta data instance
|
||||
* @throws NullPointerException if contexts is null
|
||||
* @since 3.2
|
||||
*/
|
||||
@Nonnull
|
||||
MetaData getMetaData(@Nonnull MetaContexts contexts);
|
||||
|
||||
/**
|
||||
* Gets MetaData from the cache, given a specified context.
|
||||
*
|
||||
* @param contexts the contexts to get the permission data in
|
||||
* @return a meta data instance
|
||||
* @throws NullPointerException if contexts is null
|
||||
*/
|
||||
@Nonnull
|
||||
MetaData getMetaData(@Nonnull Contexts contexts);
|
||||
|
||||
/**
|
||||
* Calculates permission data, bypassing the cache.
|
||||
*
|
||||
* <p>The result of this operation is calculated each time the method is called.
|
||||
* The result is not added to the internal cache.</p>
|
||||
*
|
||||
* <p>It is therefore highly recommended to use {@link #getPermissionData(Contexts)} instead.</p>
|
||||
*
|
||||
* <p>The use cases of this method are more around constructing one-time
|
||||
* instances of {@link PermissionData}, without adding the result to the cache.</p>
|
||||
*
|
||||
* @param contexts the contexts to get permission data in
|
||||
* @return a permission data instance
|
||||
* @throws NullPointerException if contexts is null
|
||||
*/
|
||||
@Nonnull
|
||||
PermissionData calculatePermissions(@Nonnull Contexts contexts);
|
||||
|
||||
/**
|
||||
* Calculates meta data, bypassing the cache.
|
||||
*
|
||||
* <p>The result of this operation is calculated each time the method is called.
|
||||
* The result is not added to the internal cache.</p>
|
||||
*
|
||||
* <p>It is therefore highly recommended to use {@link #getMetaData(MetaContexts)} instead.</p>
|
||||
*
|
||||
* <p>The use cases of this method are more around constructing one-time
|
||||
* instances of {@link MetaData}, without adding the result to the cache.</p>
|
||||
*
|
||||
* @param contexts the contexts to get meta data in
|
||||
* @return a meta data instance
|
||||
* @throws NullPointerException if contexts is null
|
||||
* @since 3.2
|
||||
*/
|
||||
@Nonnull
|
||||
MetaData calculateMeta(@Nonnull MetaContexts contexts);
|
||||
|
||||
/**
|
||||
* Calculates meta data, bypassing the cache.
|
||||
*
|
||||
* <p>The result of this operation is calculated each time the method is called.
|
||||
* The result is not added to the internal cache.</p>
|
||||
*
|
||||
* <p>It is therefore highly recommended to use {@link #getMetaData(Contexts)} instead.</p>
|
||||
*
|
||||
* <p>The use cases of this method are more around constructing one-time
|
||||
* instances of {@link MetaData}, without adding the result to the cache.</p>
|
||||
*
|
||||
* @param contexts the contexts to get meta data in
|
||||
* @return a meta data instance
|
||||
* @throws NullPointerException if contexts is null
|
||||
*/
|
||||
@Nonnull
|
||||
MetaData calculateMeta(@Nonnull Contexts contexts);
|
||||
|
||||
/**
|
||||
* (Re)calculates permission data for a given context.
|
||||
*
|
||||
* <p>This method returns immediately in all cases. The (re)calculation is
|
||||
* performed asynchronously and applied to the cache in the background.</p>
|
||||
*
|
||||
* <p>If there was a previous {@link PermissionData} instance associated with
|
||||
* the given {@link Contexts}, then that instance will continue to be returned by
|
||||
* {@link #getPermissionData(Contexts)} until the recalculation is completed.</p>
|
||||
*
|
||||
* <p>If there was no value calculated and cached prior to the call of this
|
||||
* method, then one will be calculated.</p>
|
||||
*
|
||||
* @param contexts the contexts to recalculate in.
|
||||
* @throws NullPointerException if contexts is null
|
||||
*/
|
||||
void recalculatePermissions(@Nonnull Contexts contexts);
|
||||
|
||||
/**
|
||||
* (Re)calculates meta data for a given context.
|
||||
*
|
||||
* <p>This method returns immediately in all cases. The (re)calculation is
|
||||
* performed asynchronously and applied to the cache in the background.</p>
|
||||
*
|
||||
* <p>If there was a previous {@link MetaData} instance associated with
|
||||
* the given {@link MetaContexts}, then that instance will continue to be returned by
|
||||
* {@link #getMetaData(MetaContexts)} until the recalculation is completed.</p>
|
||||
*
|
||||
* <p>If there was no value calculated and cached prior to the call of this
|
||||
* method, then one will be calculated.</p>
|
||||
*
|
||||
* @param contexts the contexts to recalculate in.
|
||||
* @throws NullPointerException if contexts is null
|
||||
* @since 3.2
|
||||
*/
|
||||
void recalculateMeta(@Nonnull MetaContexts contexts);
|
||||
|
||||
/**
|
||||
* (Re)calculates meta data for a given context.
|
||||
*
|
||||
* <p>This method returns immediately in all cases. The (re)calculation is
|
||||
* performed asynchronously and applied to the cache in the background.</p>
|
||||
*
|
||||
* <p>If there was a previous {@link MetaData} instance associated with
|
||||
* the given {@link Contexts}, then that instance will continue to be returned by
|
||||
* {@link #getMetaData(Contexts)} until the recalculation is completed.</p>
|
||||
*
|
||||
* <p>If there was no value calculated and cached prior to the call of this
|
||||
* method, then one will be calculated.</p>
|
||||
*
|
||||
* @param contexts the contexts to recalculate in.
|
||||
* @throws NullPointerException if contexts is null
|
||||
*/
|
||||
void recalculateMeta(@Nonnull Contexts contexts);
|
||||
|
||||
/**
|
||||
* (Re)loads permission data for a given context.
|
||||
*
|
||||
* <p>Unlike {@link #recalculatePermissions(Contexts)}, this method immediately
|
||||
* invalidates any previous {@link PermissionData} values contained within the cache,
|
||||
* and then schedules a task to reload a new {@link PermissionData} instance to
|
||||
* replace the one which was invalidated.</p>
|
||||
*
|
||||
* <p>The invalidation happens immediately during the execution of this method.
|
||||
* The result of the re-computation encapsulated by the future.</p>
|
||||
*
|
||||
* <p>Subsequent calls to {@link #getPermissionData(Contexts)} will block until
|
||||
* the result of this operation is complete.</p>
|
||||
*
|
||||
* <p>If there was no value calculated and cached prior to the call of this
|
||||
* method, then one will be calculated.</p>
|
||||
*
|
||||
* <p>This method returns a Future so users can optionally choose to wait
|
||||
* until the recalculation has been performed.</p>
|
||||
*
|
||||
* @param contexts the contexts to reload in.
|
||||
* @throws NullPointerException if contexts is null
|
||||
* @since 4.0
|
||||
*/
|
||||
@Nonnull
|
||||
CompletableFuture<? extends PermissionData> reloadPermissions(@Nonnull Contexts contexts);
|
||||
|
||||
/**
|
||||
* (Re)loads meta data for a given context.
|
||||
*
|
||||
* <p>Unlike {@link #recalculateMeta(MetaContexts)}, this method immediately
|
||||
* invalidates any previous {@link MetaData} values contained within the cache,
|
||||
* and then schedules a task to reload a new {@link MetaData} instance to
|
||||
* replace the one which was invalidated.</p>
|
||||
*
|
||||
* <p>The invalidation happens immediately during the execution of this method.
|
||||
* The result of the re-computation encapsulated by the future.</p>
|
||||
*
|
||||
* <p>Subsequent calls to {@link #getMetaData(MetaContexts)} will block until
|
||||
* the result of this operation is complete.</p>
|
||||
*
|
||||
* <p>If there was no value calculated and cached prior to the call of this
|
||||
* method, then one will be calculated.</p>
|
||||
*
|
||||
* <p>This method returns a Future so users can optionally choose to wait
|
||||
* until the recalculation has been performed.</p>
|
||||
*
|
||||
* @param contexts the contexts to reload in.
|
||||
* @throws NullPointerException if contexts is null
|
||||
* @since 4.0
|
||||
*/
|
||||
@Nonnull
|
||||
CompletableFuture<? extends MetaData> reloadMeta(@Nonnull MetaContexts contexts);
|
||||
|
||||
/**
|
||||
* (Re)loads meta data for a given context.
|
||||
*
|
||||
* <p>Unlike {@link #recalculateMeta(Contexts)}, this method immediately
|
||||
* invalidates any previous {@link MetaData} values contained within the cache,
|
||||
* and then schedules a task to reload a new {@link MetaData} instance to
|
||||
* replace the one which was invalidated.</p>
|
||||
*
|
||||
* <p>The invalidation happens immediately during the execution of this method.
|
||||
* The result of the re-computation encapsulated by the future.</p>
|
||||
*
|
||||
* <p>Subsequent calls to {@link #getMetaData(Contexts)} will block until
|
||||
* the result of this operation is complete.</p>
|
||||
*
|
||||
* <p>If there was no value calculated and cached prior to the call of this
|
||||
* method, then one will be calculated.</p>
|
||||
*
|
||||
* <p>This method returns a Future so users can optionally choose to wait
|
||||
* until the recalculation has been performed.</p>
|
||||
*
|
||||
* @param contexts the contexts to reload in.
|
||||
* @throws NullPointerException if contexts is null
|
||||
* @since 4.0
|
||||
*/
|
||||
@Nonnull
|
||||
CompletableFuture<? extends MetaData> reloadMeta(@Nonnull Contexts contexts);
|
||||
|
||||
/**
|
||||
* Recalculates permission data for all known contexts.
|
||||
*
|
||||
* <p>This method returns immediately. The recalculation is performed
|
||||
* asynchronously and applied to the cache in the background.</p>
|
||||
*
|
||||
* <p>The previous {@link PermissionData} instances will continue to be returned
|
||||
* by {@link #getPermissionData(Contexts)} until the recalculation is completed.</p>
|
||||
*/
|
||||
void recalculatePermissions();
|
||||
|
||||
/**
|
||||
* Recalculates meta data for all known contexts.
|
||||
*
|
||||
* <p>This method returns immediately. The recalculation is performed
|
||||
* asynchronously and applied to the cache in the background.</p>
|
||||
*
|
||||
* <p>The previous {@link MetaData} instances will continue to be returned
|
||||
* by {@link #getMetaData(MetaContexts)} and {@link #getMetaData(Contexts)}
|
||||
* until the recalculation is completed.</p>
|
||||
*/
|
||||
void recalculateMeta();
|
||||
|
||||
/**
|
||||
* Reloads permission data for all known contexts.
|
||||
*
|
||||
* <p>Unlike {@link #recalculatePermissions()}, this method immediately
|
||||
* invalidates all previous {@link PermissionData} values contained within the cache,
|
||||
* and then schedules a task to reload a new {@link PermissionData} instances to
|
||||
* replace the ones which were invalidated.</p>
|
||||
*
|
||||
* <p>The invalidation happens immediately during the execution of this method.
|
||||
* The result of the re-computation encapsulated by the future.</p>
|
||||
*
|
||||
* <p>Subsequent calls to {@link #getPermissionData(Contexts)} will block until
|
||||
* the result of this operation is complete.</p>
|
||||
*
|
||||
* <p>This method returns a Future so users can optionally choose to wait
|
||||
* until the recalculation has been performed.</p>
|
||||
*
|
||||
* @since 4.0
|
||||
*/
|
||||
@Nonnull
|
||||
CompletableFuture<Void> reloadPermissions();
|
||||
|
||||
/**
|
||||
* Reloads meta data for all known contexts.
|
||||
*
|
||||
* <p>Unlike {@link #recalculateMeta()}, this method immediately
|
||||
* invalidates all previous {@link MetaData} values contained within the cache,
|
||||
* and then schedules a task to reload a new {@link MetaData} instances to
|
||||
* replace the ones which were invalidated.</p>
|
||||
*
|
||||
* <p>The invalidation happens immediately during the execution of this method.
|
||||
* The result of the re-computation encapsulated by the future.</p>
|
||||
*
|
||||
* <p>Subsequent calls to {@link #getMetaData(MetaContexts)} and
|
||||
* {@link #getMetaData(Contexts)} will block until the result of this operation
|
||||
* is complete.</p>
|
||||
*
|
||||
* <p>This method returns a Future so users can optionally choose to wait
|
||||
* until the recalculation has been performed.</p>
|
||||
*
|
||||
* @since 4.0
|
||||
*/
|
||||
@Nonnull
|
||||
CompletableFuture<Void> reloadMeta();
|
||||
|
||||
/**
|
||||
* Pre-calculates and caches {@link PermissionData} and {@link MetaData}
|
||||
* instances for the given contexts.
|
||||
*
|
||||
* <p>If the cache already contains a value for the given context,
|
||||
* no action is taken.</p>
|
||||
*
|
||||
* <p>This method blocks until the calculation is completed.</p>
|
||||
*
|
||||
* @param contexts a set of contexts
|
||||
* @throws NullPointerException if contexts is null
|
||||
*/
|
||||
default void preCalculate(@Nonnull Set<Contexts> contexts) {
|
||||
contexts.forEach(this::preCalculate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pre-calculates and caches {@link PermissionData} and {@link MetaData}
|
||||
* instances for a given context.
|
||||
*
|
||||
* <p>If the cache already contains a value for the given context,
|
||||
* no action is taken.</p>
|
||||
*
|
||||
* <p>This method blocks until the calculation is completed.</p>
|
||||
*
|
||||
* @param contexts the contexts to pre-calculate for
|
||||
* @throws NullPointerException if contexts is null
|
||||
*/
|
||||
void preCalculate(@Nonnull Contexts contexts);
|
||||
|
||||
/**
|
||||
* Invalidates any cached {@link PermissionData} instances mapped to the given
|
||||
* {@link Contexts}.
|
||||
*
|
||||
* @param contexts the contexts to invalidate for
|
||||
* @since 4.0
|
||||
*/
|
||||
void invalidatePermissions(@Nonnull Contexts contexts);
|
||||
|
||||
/**
|
||||
* Invalidates any cached {@link MetaData} instances mapped to the given
|
||||
* {@link MetaContexts}.
|
||||
*
|
||||
* @param contexts the contexts to invalidate for
|
||||
* @since 4.0
|
||||
*/
|
||||
void invalidateMeta(@Nonnull MetaContexts contexts);
|
||||
|
||||
/**
|
||||
* Invalidates any cached {@link MetaData} instances mapped to the given
|
||||
* {@link Contexts}.
|
||||
*
|
||||
* @param contexts the contexts to invalidate for
|
||||
* @since 4.0
|
||||
*/
|
||||
void invalidateMeta(@Nonnull Contexts contexts);
|
||||
|
||||
/**
|
||||
* Invalidates all of the underlying Permission calculators.
|
||||
*
|
||||
* <p>Can be called to allow for an update in defaults.</p>
|
||||
*/
|
||||
void invalidatePermissionCalculators();
|
||||
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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.api.caching;
|
||||
|
||||
import me.lucko.luckperms.api.Contexts;
|
||||
import me.lucko.luckperms.api.Group;
|
||||
|
||||
/**
|
||||
* Holds cached permission and meta lookup data for a {@link Group}.
|
||||
*
|
||||
* <p>All calls will account for inheritance, as well as any default data provided
|
||||
* by the platform. This calls are heavily cached and are therefore fast.</p>
|
||||
*
|
||||
* <p>For meta, both methods accepting {@link Contexts} and {@link MetaContexts} are provided. The only difference is that
|
||||
* the latter allows you to define how the meta stack should be structured internally. Where {@link Contexts} are passed, the
|
||||
* values from the configuration are used.</p>
|
||||
*
|
||||
* @since 4.0
|
||||
*/
|
||||
public interface GroupData extends CachedData {
|
||||
|
||||
}
|
@ -26,16 +26,13 @@
|
||||
package me.lucko.luckperms.api.caching;
|
||||
|
||||
import me.lucko.luckperms.api.Contexts;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import me.lucko.luckperms.api.User;
|
||||
|
||||
/**
|
||||
* Holds cached permission and meta lookup data for a {@link me.lucko.luckperms.api.User}.
|
||||
* Holds cached permission and meta lookup data for a {@link User}.
|
||||
*
|
||||
* <p>Data is only likely to be available for online users. All calls will account for inheritance, as well as any
|
||||
* default data provided by the platform. This calls are heavily cached and are therefore fast.</p>
|
||||
* <p>All calls will account for inheritance, as well as any default data provided by
|
||||
* the platform. This calls are heavily cached and are therefore fast.</p>
|
||||
*
|
||||
* <p>For meta, both methods accepting {@link Contexts} and {@link MetaContexts} are provided. The only difference is that
|
||||
* the latter allows you to define how the meta stack should be structured internally. Where {@link Contexts} are passed, the
|
||||
@ -43,143 +40,6 @@ import javax.annotation.Nonnull;
|
||||
*
|
||||
* @since 2.13
|
||||
*/
|
||||
public interface UserData {
|
||||
|
||||
/**
|
||||
* Gets PermissionData from the cache, given a specified context.
|
||||
*
|
||||
* <p>If the data is not cached, it is calculated. Therefore, this call could be costly.</p>
|
||||
*
|
||||
* @param contexts the contexts to get the permission data in
|
||||
* @return a permission data instance
|
||||
* @throws NullPointerException if contexts is null
|
||||
*/
|
||||
@Nonnull
|
||||
PermissionData getPermissionData(@Nonnull Contexts contexts);
|
||||
|
||||
/**
|
||||
* Gets MetaData from the cache, given a specified context.
|
||||
*
|
||||
* <p>If the data is not cached, it is calculated. Therefore, this call could be costly.</p>
|
||||
*
|
||||
* @param contexts the contexts to get the permission data in
|
||||
* @return a meta data instance
|
||||
* @throws NullPointerException if contexts is null
|
||||
* @since 3.2
|
||||
*/
|
||||
@Nonnull
|
||||
MetaData getMetaData(@Nonnull MetaContexts contexts);
|
||||
|
||||
/**
|
||||
* Gets MetaData from the cache, given a specified context.
|
||||
*
|
||||
* <p>If the data is not cached, it is calculated. Therefore, this call could be costly.</p>
|
||||
*
|
||||
* @param contexts the contexts to get the permission data in
|
||||
* @return a meta data instance
|
||||
* @throws NullPointerException if contexts is null
|
||||
*/
|
||||
@Nonnull
|
||||
MetaData getMetaData(@Nonnull Contexts contexts);
|
||||
|
||||
/**
|
||||
* Calculates permission data, bypassing the cache.
|
||||
*
|
||||
* @param contexts the contexts to get permission data in
|
||||
* @return a permission data instance
|
||||
* @throws NullPointerException if contexts is null
|
||||
*/
|
||||
@Nonnull
|
||||
PermissionData calculatePermissions(@Nonnull Contexts contexts);
|
||||
|
||||
/**
|
||||
* Calculates meta data, bypassing the cache.
|
||||
*
|
||||
* @param contexts the contexts to get meta data in
|
||||
* @return a meta data instance
|
||||
* @throws NullPointerException if contexts is null
|
||||
* @since 3.2
|
||||
*/
|
||||
@Nonnull
|
||||
MetaData calculateMeta(@Nonnull MetaContexts contexts);
|
||||
|
||||
/**
|
||||
* Calculates meta data, bypassing the cache.
|
||||
*
|
||||
* @param contexts the contexts to get meta data in
|
||||
* @return a meta data instance
|
||||
* @throws NullPointerException if contexts is null
|
||||
*/
|
||||
@Nonnull
|
||||
MetaData calculateMeta(@Nonnull Contexts contexts);
|
||||
|
||||
/**
|
||||
* Calculates permission data and stores it in the cache.
|
||||
*
|
||||
* <p>If there is already data cached for the given contexts, and if the resultant output is different,
|
||||
* the cached value is updated.</p>
|
||||
*
|
||||
* @param contexts the contexts to recalculate in.
|
||||
* @throws NullPointerException if contexts is null
|
||||
*/
|
||||
void recalculatePermissions(@Nonnull Contexts contexts);
|
||||
|
||||
/**
|
||||
* Calculates meta data and stores it in the cache.
|
||||
*
|
||||
* <p>If there is already data cached for the given contexts, and if the resultant output is different,
|
||||
* the cached value is updated.</p>
|
||||
*
|
||||
* @param contexts the contexts to recalculate in.
|
||||
* @throws NullPointerException if contexts is null
|
||||
* @since 3.2
|
||||
*/
|
||||
void recalculateMeta(@Nonnull MetaContexts contexts);
|
||||
|
||||
/**
|
||||
* Calculates meta data and stores it in the cache.
|
||||
*
|
||||
* <p>If there is already data cached for the given contexts, and if the resultant output is different,
|
||||
* the cached value is updated.</p>
|
||||
*
|
||||
* @param contexts the contexts to recalculate in.
|
||||
* @throws NullPointerException if contexts is null
|
||||
*/
|
||||
void recalculateMeta(@Nonnull Contexts contexts);
|
||||
|
||||
/**
|
||||
* Calls {@link #recalculatePermissions(Contexts)} for all current loaded contexts
|
||||
*/
|
||||
void recalculatePermissions();
|
||||
|
||||
/**
|
||||
* Calls {@link #recalculateMeta(Contexts)} for all current loaded contexts
|
||||
*/
|
||||
void recalculateMeta();
|
||||
|
||||
/**
|
||||
* Calls {@link #preCalculate(Contexts)} for the given contexts
|
||||
*
|
||||
* @param contexts a set of contexts
|
||||
* @throws NullPointerException if contexts is null
|
||||
*/
|
||||
void preCalculate(@Nonnull Set<Contexts> contexts);
|
||||
|
||||
/**
|
||||
* Ensures that PermissionData and MetaData is cached for a context.
|
||||
*
|
||||
* <p>If the cache does not contain any data for the context, it will be calculated and saved.</p>
|
||||
*
|
||||
* @param contexts the contexts to pre-calculate for
|
||||
* @throws NullPointerException if contexts is null
|
||||
*/
|
||||
void preCalculate(@Nonnull Contexts contexts);
|
||||
|
||||
/**
|
||||
* Invalidates all of the underlying Permission calculators.
|
||||
*
|
||||
* <p>Can be called to allow for an update in defaults.</p>
|
||||
*/
|
||||
void invalidatePermissionCalculators();
|
||||
public interface UserData extends CachedData {
|
||||
|
||||
}
|
||||
|
@ -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.api.event.group;
|
||||
|
||||
import me.lucko.luckperms.api.Group;
|
||||
import me.lucko.luckperms.api.caching.GroupData;
|
||||
import me.lucko.luckperms.api.event.LuckPermsEvent;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* Called when a groups {@link GroupData} is loaded.
|
||||
*
|
||||
* @since 4.0
|
||||
*/
|
||||
public interface GroupCacheLoadEvent extends LuckPermsEvent {
|
||||
|
||||
/**
|
||||
* Gets the group whose data was loaded
|
||||
*
|
||||
* @return the group
|
||||
*/
|
||||
@Nonnull
|
||||
Group getGroup();
|
||||
|
||||
/**
|
||||
* Gets the data that was loaded
|
||||
*
|
||||
* @return the loaded data
|
||||
*/
|
||||
@Nonnull
|
||||
GroupData getLoadedData();
|
||||
|
||||
}
|
@ -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.api.event.group;
|
||||
|
||||
import me.lucko.luckperms.api.Group;
|
||||
import me.lucko.luckperms.api.caching.GroupData;
|
||||
import me.lucko.luckperms.api.event.LuckPermsEvent;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* Called when a groups cached data is refreshed
|
||||
*
|
||||
* @since 4.0
|
||||
*/
|
||||
public interface GroupDataRecalculateEvent extends LuckPermsEvent {
|
||||
|
||||
/**
|
||||
* Gets the group whose data was recalculated
|
||||
*
|
||||
* @return the group
|
||||
*/
|
||||
@Nonnull
|
||||
Group getGroup();
|
||||
|
||||
/**
|
||||
* Gets the data that was recalculated
|
||||
*
|
||||
* @return the data
|
||||
*/
|
||||
@Nonnull
|
||||
GroupData getData();
|
||||
|
||||
}
|
@ -36,8 +36,8 @@ import me.lucko.luckperms.bukkit.contexts.WorldCalculator;
|
||||
import me.lucko.luckperms.bukkit.listeners.BukkitConnectionListener;
|
||||
import me.lucko.luckperms.bukkit.listeners.BukkitPlatformListener;
|
||||
import me.lucko.luckperms.bukkit.messaging.BukkitMessagingFactory;
|
||||
import me.lucko.luckperms.bukkit.model.Injector;
|
||||
import me.lucko.luckperms.bukkit.model.LPPermissible;
|
||||
import me.lucko.luckperms.bukkit.model.PermissibleInjector;
|
||||
import me.lucko.luckperms.bukkit.model.SubscriptionMapInjector;
|
||||
import me.lucko.luckperms.bukkit.processors.BukkitProcessorsSetupTask;
|
||||
import me.lucko.luckperms.bukkit.processors.ChildPermissionProvider;
|
||||
@ -305,7 +305,7 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
||||
scheduler.doSync(() -> {
|
||||
try {
|
||||
LPPermissible lpPermissible = new LPPermissible(player, user, this);
|
||||
Injector.inject(player, lpPermissible);
|
||||
PermissibleInjector.inject(player, lpPermissible);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
@ -335,7 +335,7 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
||||
// uninject from players
|
||||
for (Player player : getServer().getOnlinePlayers()) {
|
||||
try {
|
||||
Injector.unInject(player, false);
|
||||
PermissibleInjector.unInject(player, false);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@ -346,7 +346,7 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
||||
|
||||
final User user = getUserManager().getIfLoaded(getUuidCache().getUUID(player.getUniqueId()));
|
||||
if (user != null) {
|
||||
user.getUserData().invalidateCaches();
|
||||
user.getCachedData().invalidateCaches();
|
||||
getUserManager().unload(user);
|
||||
}
|
||||
}
|
||||
@ -406,7 +406,7 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
||||
}
|
||||
|
||||
if (getConfiguration().get(ConfigKeys.AUTO_OP)) {
|
||||
Map<String, Boolean> backing = user.getUserData().getPermissionData(contextManager.getApplicableContexts(player)).getImmutableBacking();
|
||||
Map<String, Boolean> backing = user.getCachedData().getPermissionData(contextManager.getApplicableContexts(player)).getImmutableBacking();
|
||||
boolean op = Optional.ofNullable(backing.get("luckperms.autoop")).orElse(false);
|
||||
player.setOp(op);
|
||||
}
|
||||
|
@ -37,7 +37,6 @@ import me.lucko.luckperms.common.calculators.AbstractCalculatorFactory;
|
||||
import me.lucko.luckperms.common.calculators.PermissionCalculator;
|
||||
import me.lucko.luckperms.common.calculators.PermissionCalculatorMetadata;
|
||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||
import me.lucko.luckperms.common.model.User;
|
||||
import me.lucko.luckperms.common.processors.MapProcessor;
|
||||
import me.lucko.luckperms.common.processors.PermissionProcessor;
|
||||
import me.lucko.luckperms.common.processors.RegexProcessor;
|
||||
@ -50,7 +49,7 @@ public class BukkitCalculatorFactory extends AbstractCalculatorFactory {
|
||||
private final LPBukkitPlugin plugin;
|
||||
|
||||
@Override
|
||||
public PermissionCalculator build(Contexts contexts, User user) {
|
||||
public PermissionCalculator build(Contexts contexts, PermissionCalculatorMetadata metadata) {
|
||||
ImmutableList.Builder<PermissionProcessor> processors = ImmutableList.builder();
|
||||
|
||||
processors.add(new MapProcessor());
|
||||
@ -71,8 +70,7 @@ public class BukkitCalculatorFactory extends AbstractCalculatorFactory {
|
||||
processors.add(new DefaultsProcessor(contexts.isOp(), plugin.getDefaultsProvider()));
|
||||
}
|
||||
|
||||
PermissionCalculatorMetadata meta = PermissionCalculatorMetadata.of(user.getFriendlyName(), contexts.getContexts());
|
||||
return registerCalculator(new PermissionCalculator(plugin, meta, processors.build()));
|
||||
return registerCalculator(new PermissionCalculator(plugin, metadata, processors.build()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -28,8 +28,8 @@ package me.lucko.luckperms.bukkit.listeners;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
|
||||
import me.lucko.luckperms.bukkit.model.Injector;
|
||||
import me.lucko.luckperms.bukkit.model.LPPermissible;
|
||||
import me.lucko.luckperms.bukkit.model.PermissibleInjector;
|
||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||
import me.lucko.luckperms.common.locale.Message;
|
||||
import me.lucko.luckperms.common.model.User;
|
||||
@ -165,7 +165,7 @@ public class BukkitConnectionListener implements Listener {
|
||||
LPPermissible lpPermissible = new LPPermissible(player, user, plugin);
|
||||
|
||||
// Inject into the player
|
||||
Injector.inject(player, lpPermissible);
|
||||
PermissibleInjector.inject(player, lpPermissible);
|
||||
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
@ -209,7 +209,7 @@ public class BukkitConnectionListener implements Listener {
|
||||
|
||||
// Remove the custom permissible
|
||||
try {
|
||||
Injector.unInject(player, true);
|
||||
PermissibleInjector.unInject(player, true);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
@ -96,13 +96,13 @@ public class LPPermissible extends PermissibleBase {
|
||||
|
||||
@Override
|
||||
public boolean isPermissionSet(@NonNull String permission) {
|
||||
Tristate ts = user.getUserData().getPermissionData(calculateContexts()).getPermissionValue(permission, CheckOrigin.PLATFORM_LOOKUP_CHECK);
|
||||
Tristate ts = user.getCachedData().getPermissionData(calculateContexts()).getPermissionValue(permission, CheckOrigin.PLATFORM_LOOKUP_CHECK);
|
||||
return ts != Tristate.UNDEFINED || Permission.DEFAULT_PERMISSION.getValue(isOp());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPermissionSet(@NonNull Permission permission) {
|
||||
Tristate ts = user.getUserData().getPermissionData(calculateContexts()).getPermissionValue(permission.getName(), CheckOrigin.PLATFORM_LOOKUP_CHECK);
|
||||
Tristate ts = user.getCachedData().getPermissionData(calculateContexts()).getPermissionValue(permission.getName(), CheckOrigin.PLATFORM_LOOKUP_CHECK);
|
||||
if (ts != Tristate.UNDEFINED) {
|
||||
return true;
|
||||
}
|
||||
@ -116,13 +116,13 @@ public class LPPermissible extends PermissibleBase {
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(@NonNull String permission) {
|
||||
Tristate ts = user.getUserData().getPermissionData(calculateContexts()).getPermissionValue(permission, CheckOrigin.PLATFORM_PERMISSION_CHECK);
|
||||
Tristate ts = user.getCachedData().getPermissionData(calculateContexts()).getPermissionValue(permission, CheckOrigin.PLATFORM_PERMISSION_CHECK);
|
||||
return ts != Tristate.UNDEFINED ? ts.asBoolean() : Permission.DEFAULT_PERMISSION.getValue(isOp());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(@NonNull Permission permission) {
|
||||
Tristate ts = user.getUserData().getPermissionData(calculateContexts()).getPermissionValue(permission.getName(), CheckOrigin.PLATFORM_PERMISSION_CHECK);
|
||||
Tristate ts = user.getCachedData().getPermissionData(calculateContexts()).getPermissionValue(permission.getName(), CheckOrigin.PLATFORM_PERMISSION_CHECK);
|
||||
if (ts != Tristate.UNDEFINED) {
|
||||
return ts.asBoolean();
|
||||
}
|
||||
@ -164,7 +164,7 @@ public class LPPermissible extends PermissibleBase {
|
||||
public Set<PermissionAttachmentInfo> getEffectivePermissions() {
|
||||
Set<PermissionAttachmentInfo> perms = new HashSet<>();
|
||||
perms.addAll(
|
||||
user.getUserData().getPermissionData(calculateContexts()).getImmutableBacking().entrySet().stream()
|
||||
user.getCachedData().getPermissionData(calculateContexts()).getImmutableBacking().entrySet().stream()
|
||||
.map(e -> new PermissionAttachmentInfo(player, e.getKey(), null, e.getValue()))
|
||||
.collect(Collectors.toList())
|
||||
);
|
||||
|
@ -36,7 +36,6 @@ import me.lucko.luckperms.common.model.User;
|
||||
import me.lucko.luckperms.common.node.ImmutableTransientNode;
|
||||
import me.lucko.luckperms.common.node.NodeFactory;
|
||||
|
||||
import org.bukkit.permissions.PermissibleBase;
|
||||
import org.bukkit.permissions.PermissionAttachment;
|
||||
import org.bukkit.permissions.PermissionRemovedExecutor;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
@ -64,7 +63,7 @@ public class LPPermissionAttachment extends PermissionAttachment {
|
||||
static {
|
||||
Field permissionAttachmentPermissionsField;
|
||||
try {
|
||||
permissionAttachmentPermissionsField = PermissibleBase.class.getDeclaredField("permissions");
|
||||
permissionAttachmentPermissionsField = PermissionAttachment.class.getDeclaredField("permissions");
|
||||
permissionAttachmentPermissionsField.setAccessible(true);
|
||||
} catch (NoSuchFieldException e) {
|
||||
throw new RuntimeException(e);
|
||||
@ -131,9 +130,8 @@ public class LPPermissionAttachment extends PermissionAttachment {
|
||||
FakeBackingMap fakeMap = new FakeBackingMap();
|
||||
|
||||
try {
|
||||
// what's this doing, ay?
|
||||
// the field we need to modify is in the superclass - it's set to private
|
||||
// so we have to use reflection to modify it.
|
||||
// the field we need to modify is in the superclass - it has private
|
||||
// and final modifiers so we have to use reflection to modify it.
|
||||
PERMISSION_ATTACHMENT_PERMISSIONS_FIELD.set(this, fakeMap);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
@ -172,7 +170,7 @@ public class LPPermissionAttachment extends PermissionAttachment {
|
||||
// set the transient node
|
||||
User user = permissible.getUser();
|
||||
if (user.setTransientPermission(transientNode).asBoolean()) {
|
||||
user.getRefreshBuffer().request();
|
||||
user.reloadCachedData();
|
||||
}
|
||||
}
|
||||
|
||||
@ -184,7 +182,7 @@ public class LPPermissionAttachment extends PermissionAttachment {
|
||||
// remove transient permissions from the holder which were added by this attachment & equal the permission
|
||||
User user = permissible.getUser();
|
||||
if (user.removeIfTransient(n -> n instanceof ImmutableTransientNode && ((ImmutableTransientNode) n).getOwner() == this && n.getPermission().equals(name))) {
|
||||
user.getRefreshBuffer().request();
|
||||
user.reloadCachedData();
|
||||
}
|
||||
}
|
||||
|
||||
@ -192,7 +190,7 @@ public class LPPermissionAttachment extends PermissionAttachment {
|
||||
// remove all transient permissions added by this attachment
|
||||
User user = permissible.getUser();
|
||||
if (user.removeIfTransient(n -> n instanceof ImmutableTransientNode && ((ImmutableTransientNode) n).getOwner() == this)) {
|
||||
user.getRefreshBuffer().request();
|
||||
user.reloadCachedData();
|
||||
}
|
||||
}
|
||||
|
||||
@ -228,7 +226,7 @@ public class LPPermissionAttachment extends PermissionAttachment {
|
||||
return;
|
||||
}
|
||||
|
||||
// if we're not hooked, thn don't actually apply the change
|
||||
// if we're not hooked, then don't actually apply the change
|
||||
// it will get applied on hook - if that ever happens
|
||||
if (!hooked) {
|
||||
return;
|
||||
@ -253,7 +251,7 @@ public class LPPermissionAttachment extends PermissionAttachment {
|
||||
return;
|
||||
}
|
||||
|
||||
// if we're not hooked, thn don't actually apply the change
|
||||
// if we're not hooked, then don't actually apply the change
|
||||
// it will get applied on hook - if that ever happens
|
||||
if (!hooked) {
|
||||
return;
|
||||
@ -296,7 +294,6 @@ public class LPPermissionAttachment extends PermissionAttachment {
|
||||
|
||||
@Override
|
||||
public Boolean put(String key, Boolean value) {
|
||||
|
||||
// grab the previous result, so we can still satisfy the method signature of Map
|
||||
Boolean previous = perms.get(key);
|
||||
|
||||
|
@ -181,7 +181,7 @@ public class LPSubscriptionMap extends HashMap<String, Map<Permissible, Boolean>
|
||||
return result;
|
||||
}
|
||||
|
||||
// then try the map, if we haven't already
|
||||
// then try the permissible, if we haven't already
|
||||
if (!isPlayer && key instanceof Permissible) {
|
||||
Permissible p = (Permissible) key;
|
||||
if (p.isPermissionSet(permission)) {
|
||||
@ -195,8 +195,8 @@ public class LPSubscriptionMap extends HashMap<String, Map<Permissible, Boolean>
|
||||
|
||||
@Override
|
||||
public boolean containsKey(Object key) {
|
||||
// check the backing map, as well as if the permissible has the perm set
|
||||
return backing.containsKey(key) || (key instanceof Permissible && ((Permissible) key).isPermissionSet(permission));
|
||||
// delegate through the get method
|
||||
return get(key) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -43,7 +43,7 @@ import java.util.List;
|
||||
* checks made by plugins.
|
||||
*/
|
||||
@UtilityClass
|
||||
public class Injector {
|
||||
public class PermissibleInjector {
|
||||
|
||||
/**
|
||||
* All permission checks made on standard Bukkit objects are effectively proxied to a
|
@ -304,7 +304,7 @@ public class VaultChatHook extends Chat {
|
||||
world = perms.correctWorld(world);
|
||||
perms.log("Getting meta: '" + node + "' for user " + user.getFriendlyName() + " on world " + world + ", server " + perms.getServer());
|
||||
|
||||
String ret = user.getUserData().getMetaData(perms.createContextForWorldLookup(perms.getPlugin().getPlayer(user), world)).getMeta().get(node);
|
||||
String ret = user.getCachedData().getMetaData(perms.createContextForWorldLookup(perms.getPlugin().getPlayer(user), world)).getMeta().get(node);
|
||||
return ret != null ? ret : defaultValue;
|
||||
}
|
||||
|
||||
@ -316,7 +316,7 @@ public class VaultChatHook extends Chat {
|
||||
world = perms.correctWorld(world);
|
||||
perms.log("Getting " + type.name().toLowerCase() + " for user " + user.getFriendlyName() + " on world " + world + ", server " + perms.getServer());
|
||||
|
||||
MetaData data = user.getUserData().getMetaData(perms.createContextForWorldLookup(perms.getPlugin().getPlayer(user), world));
|
||||
MetaData data = user.getCachedData().getMetaData(perms.createContextForWorldLookup(perms.getPlugin().getPlayer(user), world));
|
||||
String ret = type == ChatMetaType.PREFIX ? data.getPrefix() : data.getSuffix();
|
||||
return ret != null ? ret : "";
|
||||
}
|
||||
|
@ -144,7 +144,7 @@ public class VaultPermissionHook extends Permission {
|
||||
}
|
||||
|
||||
// Effectively fallback to the standard Bukkit #hasPermission check.
|
||||
return user.getUserData().getPermissionData(createContextForWorldLookup(player, world)).getPermissionValue(permission, CheckOrigin.INTERNAL).asBoolean();
|
||||
return user.getCachedData().getPermissionData(createContextForWorldLookup(player, world)).getPermissionValue(permission, CheckOrigin.INTERNAL).asBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -54,16 +54,16 @@ public class BungeeConfigAdapter implements ConfigurationAdapter {
|
||||
|
||||
@SuppressWarnings("ResultOfMethodCallIgnored")
|
||||
private File makeFile(String file) throws IOException {
|
||||
File cfg = new File(plugin.getDataFolder(), file);
|
||||
File configFile = new File(plugin.getDataFolder(), file);
|
||||
|
||||
if (!cfg.exists()) {
|
||||
if (!configFile.exists()) {
|
||||
plugin.getDataFolder().mkdir();
|
||||
try (InputStream is = plugin.getResourceAsStream(file)) {
|
||||
Files.copy(is, cfg.toPath());
|
||||
Files.copy(is, configFile.toPath());
|
||||
}
|
||||
}
|
||||
|
||||
return cfg;
|
||||
return configFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -35,7 +35,6 @@ import me.lucko.luckperms.common.calculators.AbstractCalculatorFactory;
|
||||
import me.lucko.luckperms.common.calculators.PermissionCalculator;
|
||||
import me.lucko.luckperms.common.calculators.PermissionCalculatorMetadata;
|
||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||
import me.lucko.luckperms.common.model.User;
|
||||
import me.lucko.luckperms.common.processors.MapProcessor;
|
||||
import me.lucko.luckperms.common.processors.PermissionProcessor;
|
||||
import me.lucko.luckperms.common.processors.RegexProcessor;
|
||||
@ -48,7 +47,7 @@ public class BungeeCalculatorFactory extends AbstractCalculatorFactory {
|
||||
private final LPBungeePlugin plugin;
|
||||
|
||||
@Override
|
||||
public PermissionCalculator build(Contexts contexts, User user) {
|
||||
public PermissionCalculator build(Contexts contexts, PermissionCalculatorMetadata metadata) {
|
||||
ImmutableList.Builder<PermissionProcessor> processors = ImmutableList.builder();
|
||||
|
||||
processors.add(new MapProcessor());
|
||||
@ -61,8 +60,7 @@ public class BungeeCalculatorFactory extends AbstractCalculatorFactory {
|
||||
processors.add(new WildcardProcessor());
|
||||
}
|
||||
|
||||
PermissionCalculatorMetadata meta = PermissionCalculatorMetadata.of(user.getFriendlyName(), contexts.getContexts());
|
||||
return registerCalculator(new PermissionCalculator(plugin, meta, processors.build()));
|
||||
return registerCalculator(new PermissionCalculator(plugin, metadata, processors.build()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -60,7 +60,7 @@ public class BungeePermissionCheckListener implements Listener {
|
||||
}
|
||||
|
||||
Contexts contexts = plugin.getContextManager().getApplicableContexts(player);
|
||||
Tristate result = user.getUserData().getPermissionData(contexts).getPermissionValue(e.getPermission(), CheckOrigin.PLATFORM_PERMISSION_CHECK);
|
||||
Tristate result = user.getCachedData().getPermissionData(contexts).getPermissionValue(e.getPermission(), CheckOrigin.PLATFORM_PERMISSION_CHECK);
|
||||
if (result == Tristate.UNDEFINED && plugin.getConfiguration().get(ConfigKeys.APPLY_BUNGEE_CONFIG_PERMISSIONS)) {
|
||||
return; // just use the result provided by the proxy when the event was created
|
||||
}
|
||||
@ -83,7 +83,7 @@ public class BungeePermissionCheckListener implements Listener {
|
||||
}
|
||||
|
||||
Contexts contexts = plugin.getContextManager().getApplicableContexts(player);
|
||||
Tristate result = user.getUserData().getPermissionData(contexts).getPermissionValue(e.getPermission(), CheckOrigin.PLATFORM_LOOKUP_CHECK);
|
||||
Tristate result = user.getCachedData().getPermissionData(contexts).getPermissionValue(e.getPermission(), CheckOrigin.PLATFORM_LOOKUP_CHECK);
|
||||
if (result == Tristate.UNDEFINED && plugin.getConfiguration().get(ConfigKeys.APPLY_BUNGEE_CONFIG_PERMISSIONS)) {
|
||||
return; // just use the result provided by the proxy when the event was created
|
||||
}
|
||||
|
@ -32,8 +32,10 @@ import lombok.NonNull;
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
import me.lucko.luckperms.api.Group;
|
||||
import me.lucko.luckperms.api.caching.GroupData;
|
||||
|
||||
import java.util.OptionalInt;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public final class ApiGroup extends ApiPermissionHolder implements Group {
|
||||
public static me.lucko.luckperms.common.model.Group cast(Group g) {
|
||||
@ -59,6 +61,16 @@ public final class ApiGroup extends ApiPermissionHolder implements Group {
|
||||
return handle.getWeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public GroupData getCachedData() {
|
||||
return handle.getCachedData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> refreshCachedData() {
|
||||
return handle.getRefreshBuffer().request();
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (o == this) return true;
|
||||
if (!(o instanceof ApiGroup)) return false;
|
||||
|
@ -38,6 +38,7 @@ import me.lucko.luckperms.api.LocalizedNode;
|
||||
import me.lucko.luckperms.api.Node;
|
||||
import me.lucko.luckperms.api.PermissionHolder;
|
||||
import me.lucko.luckperms.api.Tristate;
|
||||
import me.lucko.luckperms.api.caching.CachedData;
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
import me.lucko.luckperms.common.model.Group;
|
||||
@ -71,6 +72,11 @@ public class ApiPermissionHolder implements PermissionHolder {
|
||||
return handle.getFriendlyName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CachedData getCachedData() {
|
||||
return handle.getCachedData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableSetMultimap<ImmutableContextSet, Node> getNodes() {
|
||||
return handle.getEnduringNodes();
|
||||
|
@ -82,7 +82,7 @@ public final class ApiUser extends ApiPermissionHolder implements User {
|
||||
|
||||
@Override
|
||||
public UserData getCachedData() {
|
||||
return handle.getUserData();
|
||||
return handle.getCachedData();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.caching;
|
||||
|
||||
import me.lucko.luckperms.api.caching.GroupData;
|
||||
import me.lucko.luckperms.common.model.Group;
|
||||
|
||||
/**
|
||||
* Holds an easily accessible cache of a groups's data in a number of contexts
|
||||
*/
|
||||
public class GroupCache extends HolderCache<Group> implements GroupData {
|
||||
|
||||
public GroupCache(Group holder) {
|
||||
super(holder);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getHolderName() {
|
||||
return holder.getName();
|
||||
}
|
||||
}
|
@ -0,0 +1,295 @@
|
||||
/*
|
||||
* 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.caching;
|
||||
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.CacheLoader;
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||
|
||||
import me.lucko.luckperms.api.ChatMetaType;
|
||||
import me.lucko.luckperms.api.Contexts;
|
||||
import me.lucko.luckperms.api.caching.CachedData;
|
||||
import me.lucko.luckperms.api.caching.MetaContexts;
|
||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||
import me.lucko.luckperms.common.metastacking.SimpleMetaStack;
|
||||
import me.lucko.luckperms.common.model.PermissionHolder;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Holds an easily accessible cache of a holders data in a number of contexts
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public abstract class HolderCache<T extends PermissionHolder> implements CachedData {
|
||||
|
||||
/**
|
||||
* The holder whom this data instance is representing
|
||||
*/
|
||||
protected final T holder;
|
||||
|
||||
/**
|
||||
* The cache used for {@link PermissionCache} instances.
|
||||
*/
|
||||
private final LoadingCache<Contexts, PermissionCache> permission = Caffeine.newBuilder()
|
||||
.expireAfterAccess(2, TimeUnit.MINUTES)
|
||||
.build(new PermissionCacheLoader());
|
||||
|
||||
/**
|
||||
* The cache used for {@link MetaCache} instances.
|
||||
*/
|
||||
private final LoadingCache<MetaContexts, MetaCache> meta = Caffeine.newBuilder()
|
||||
.expireAfterAccess(2, TimeUnit.MINUTES)
|
||||
.build(new MetaCacheLoader());
|
||||
|
||||
protected abstract String getHolderName();
|
||||
|
||||
/**
|
||||
* Calculates a {@link PermissionCache} instance.
|
||||
*
|
||||
* @param contexts the contexts to calculate in
|
||||
* @param data an old data instance to try to reuse - ignored if null
|
||||
* @return the calculated instance
|
||||
*/
|
||||
private PermissionCache calculatePermissions(@NonNull Contexts contexts, PermissionCache data) {
|
||||
if (data == null) {
|
||||
data = new PermissionCache(contexts, getHolderName(), holder.getPlugin().getCalculatorFactory());
|
||||
}
|
||||
|
||||
if (contexts == Contexts.allowAll()) {
|
||||
data.setPermissions(holder.exportNodesAndShorthand(true));
|
||||
} else {
|
||||
data.setPermissions(holder.exportNodesAndShorthand(contexts, true));
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates a {@link MetaCache} instance.
|
||||
*
|
||||
* @param contexts the contexts to calculate in
|
||||
* @param data an old data instance to try to reuse - ignored if null
|
||||
* @return the calculated instance
|
||||
*/
|
||||
private MetaCache calculateMeta(@NonNull MetaContexts contexts, MetaCache data) {
|
||||
if (data == null) {
|
||||
data = new MetaCache();
|
||||
}
|
||||
|
||||
if (contexts.getContexts() == Contexts.allowAll()) {
|
||||
data.loadMeta(holder.accumulateMeta(newAccumulator(contexts), null));
|
||||
} else {
|
||||
data.loadMeta(holder.accumulateMeta(newAccumulator(contexts), null, contexts.getContexts()));
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionCache getPermissionData(@NonNull Contexts contexts) {
|
||||
//noinspection ConstantConditions
|
||||
return permission.get(contexts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MetaCache getMetaData(@NonNull MetaContexts contexts) {
|
||||
//noinspection ConstantConditions
|
||||
return meta.get(contexts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MetaCache getMetaData(@NonNull Contexts contexts) {
|
||||
return getMetaData(makeFromMetaContextsConfig(contexts, holder.getPlugin()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionCache calculatePermissions(@NonNull Contexts contexts) {
|
||||
return calculatePermissions(contexts, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MetaCache calculateMeta(@NonNull MetaContexts contexts) {
|
||||
return calculateMeta(contexts, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MetaCache calculateMeta(@NonNull Contexts contexts) {
|
||||
return calculateMeta(makeFromMetaContextsConfig(contexts, holder.getPlugin()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recalculatePermissions(@NonNull Contexts contexts) {
|
||||
permission.refresh(contexts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recalculateMeta(@NonNull MetaContexts contexts) {
|
||||
meta.refresh(contexts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recalculateMeta(@NonNull Contexts contexts) {
|
||||
recalculateMeta(makeFromMetaContextsConfig(contexts, holder.getPlugin()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<PermissionCache> reloadPermissions(@NonNull Contexts contexts) {
|
||||
// get the previous value - to use when recalculating
|
||||
PermissionCache previous = permission.getIfPresent(contexts);
|
||||
|
||||
// invalidate the entry
|
||||
permission.invalidate(contexts);
|
||||
|
||||
// repopulate the cache
|
||||
return CompletableFuture.supplyAsync(() -> permission.get(contexts, c -> calculatePermissions(c, previous)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<MetaCache> reloadMeta(@NonNull MetaContexts contexts) {
|
||||
// get the previous value - to use when recalculating
|
||||
MetaCache previous = meta.getIfPresent(contexts);
|
||||
|
||||
// invalidate the entry
|
||||
meta.invalidate(contexts);
|
||||
|
||||
// repopulate the cache
|
||||
return CompletableFuture.supplyAsync(() -> meta.get(contexts, c -> calculateMeta(c, previous)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<MetaCache> reloadMeta(@NonNull Contexts contexts) {
|
||||
return reloadMeta(makeFromMetaContextsConfig(contexts, holder.getPlugin()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recalculatePermissions() {
|
||||
Set<Contexts> keys = permission.asMap().keySet();
|
||||
keys.forEach(this::recalculatePermissions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recalculateMeta() {
|
||||
Set<MetaContexts> keys = meta.asMap().keySet();
|
||||
keys.forEach(this::recalculateMeta);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> reloadPermissions() {
|
||||
Set<Contexts> keys = new HashSet<>(permission.asMap().keySet());
|
||||
return CompletableFuture.allOf(keys.stream().map(this::reloadPermissions).toArray(CompletableFuture[]::new));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> reloadMeta() {
|
||||
Set<MetaContexts> keys = new HashSet<>(meta.asMap().keySet());
|
||||
return CompletableFuture.allOf(keys.stream().map(this::reloadMeta).toArray(CompletableFuture[]::new));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preCalculate(@NonNull Contexts contexts) {
|
||||
// pre-calculate just by requesting the data from this cache.
|
||||
// if the data isn't already loaded, it will be calculated.
|
||||
getPermissionData(contexts);
|
||||
getMetaData(contexts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidatePermissions(Contexts contexts) {
|
||||
permission.invalidate(contexts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateMeta(MetaContexts contexts) {
|
||||
meta.invalidate(contexts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateMeta(Contexts contexts) {
|
||||
meta.invalidate(makeFromMetaContextsConfig(contexts, holder.getPlugin()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidatePermissionCalculators() {
|
||||
permission.asMap().values().forEach(PermissionCache::invalidateCache);
|
||||
}
|
||||
|
||||
public void invalidateCaches() {
|
||||
permission.invalidateAll();
|
||||
meta.invalidateAll();
|
||||
}
|
||||
|
||||
public void doCacheCleanup() {
|
||||
permission.cleanUp();
|
||||
meta.cleanUp();
|
||||
}
|
||||
|
||||
private final class PermissionCacheLoader implements CacheLoader<Contexts, PermissionCache> {
|
||||
@Override
|
||||
public PermissionCache load(Contexts contexts) {
|
||||
return calculatePermissions(contexts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionCache reload(Contexts contexts, PermissionCache oldData) {
|
||||
return calculatePermissions(contexts, oldData);
|
||||
}
|
||||
}
|
||||
|
||||
private final class MetaCacheLoader implements CacheLoader<MetaContexts, MetaCache> {
|
||||
@Override
|
||||
public MetaCache load(MetaContexts contexts) {
|
||||
return calculateMeta(contexts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MetaCache reload(MetaContexts contexts, MetaCache oldData) {
|
||||
return calculateMeta(contexts, oldData);
|
||||
}
|
||||
}
|
||||
|
||||
private static MetaContexts makeFromMetaContextsConfig(Contexts contexts, LuckPermsPlugin plugin) {
|
||||
return new MetaContexts(
|
||||
contexts,
|
||||
plugin.getConfiguration().get(ConfigKeys.PREFIX_FORMATTING_OPTIONS),
|
||||
plugin.getConfiguration().get(ConfigKeys.SUFFIX_FORMATTING_OPTIONS)
|
||||
);
|
||||
}
|
||||
|
||||
private static MetaAccumulator newAccumulator(MetaContexts contexts) {
|
||||
return new MetaAccumulator(
|
||||
new SimpleMetaStack(contexts.getPrefixStackDefinition(), ChatMetaType.PREFIX),
|
||||
new SimpleMetaStack(contexts.getSuffixStackDefinition(), ChatMetaType.SUFFIX)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -45,7 +45,7 @@ import java.util.concurrent.locks.ReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
/**
|
||||
* Holds a user's cached meta for a given context
|
||||
* Holds cached meta for a given context
|
||||
*/
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
|
@ -32,7 +32,7 @@ import me.lucko.luckperms.api.Tristate;
|
||||
import me.lucko.luckperms.api.caching.PermissionData;
|
||||
import me.lucko.luckperms.common.calculators.CalculatorFactory;
|
||||
import me.lucko.luckperms.common.calculators.PermissionCalculator;
|
||||
import me.lucko.luckperms.common.model.User;
|
||||
import me.lucko.luckperms.common.calculators.PermissionCalculatorMetadata;
|
||||
import me.lucko.luckperms.common.verbose.CheckOrigin;
|
||||
|
||||
import java.util.Collections;
|
||||
@ -40,7 +40,7 @@ import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Holds a user's cached permissions for a given context
|
||||
* Holds cached permissions data for a given context
|
||||
*/
|
||||
public class PermissionCache implements PermissionData {
|
||||
|
||||
@ -61,11 +61,13 @@ public class PermissionCache implements PermissionData {
|
||||
*/
|
||||
private final PermissionCalculator calculator;
|
||||
|
||||
public PermissionCache(Contexts contexts, User user, CalculatorFactory calculatorFactory) {
|
||||
public PermissionCache(Contexts contexts, String friendlyName, CalculatorFactory calculatorFactory) {
|
||||
permissions = new ConcurrentHashMap<>();
|
||||
permissionsUnmodifiable = Collections.unmodifiableMap(permissions);
|
||||
|
||||
calculator = calculatorFactory.build(contexts, user);
|
||||
PermissionCalculatorMetadata metadata = PermissionCalculatorMetadata.of(friendlyName, contexts.getContexts());
|
||||
|
||||
calculator = calculatorFactory.build(contexts, metadata);
|
||||
calculator.updateBacking(permissions); // Initial setup.
|
||||
}
|
||||
|
||||
@ -74,16 +76,16 @@ public class PermissionCache implements PermissionData {
|
||||
calculator.invalidateCache();
|
||||
}
|
||||
|
||||
public void setPermissions(Map<String, Boolean> permissions) {
|
||||
private void setPermissionsInternal(Map<String, Boolean> permissions) {
|
||||
this.permissions.clear();
|
||||
this.permissions.putAll(permissions);
|
||||
calculator.updateBacking(this.permissions);
|
||||
invalidateCache();
|
||||
}
|
||||
|
||||
public void comparePermissions(Map<String, Boolean> toApply) {
|
||||
public void setPermissions(Map<String, Boolean> toApply) {
|
||||
if (!permissions.equals(toApply)) {
|
||||
setPermissions(toApply);
|
||||
setPermissionsInternal(toApply);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,198 +25,20 @@
|
||||
|
||||
package me.lucko.luckperms.common.caching;
|
||||
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.CacheLoader;
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||
|
||||
import me.lucko.luckperms.api.ChatMetaType;
|
||||
import me.lucko.luckperms.api.Contexts;
|
||||
import me.lucko.luckperms.api.caching.MetaContexts;
|
||||
import me.lucko.luckperms.api.caching.UserData;
|
||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||
import me.lucko.luckperms.common.metastacking.SimpleMetaStack;
|
||||
import me.lucko.luckperms.common.model.User;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Holds an easily accessible cache of a user's data in a number of contexts
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public class UserCache implements UserData {
|
||||
public class UserCache extends HolderCache<User> implements UserData {
|
||||
|
||||
/**
|
||||
* The user whom this data instance is representing
|
||||
*/
|
||||
private final User user;
|
||||
|
||||
private final LoadingCache<Contexts, PermissionCache> permission = Caffeine.newBuilder()
|
||||
.expireAfterAccess(2, TimeUnit.MINUTES)
|
||||
.build(new PermissionCacheLoader());
|
||||
|
||||
private final LoadingCache<MetaContexts, MetaCache> meta = Caffeine.newBuilder()
|
||||
.expireAfterAccess(2, TimeUnit.MINUTES)
|
||||
.build(new MetaCacheLoader());
|
||||
|
||||
@Override
|
||||
public PermissionCache getPermissionData(@NonNull Contexts contexts) {
|
||||
//noinspection ConstantConditions
|
||||
return permission.get(contexts);
|
||||
public UserCache(User holder) {
|
||||
super(holder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MetaCache getMetaData(@NonNull MetaContexts contexts) {
|
||||
//noinspection ConstantConditions
|
||||
return meta.get(contexts);
|
||||
protected String getHolderName() {
|
||||
return holder.getFriendlyName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MetaCache getMetaData(@NonNull Contexts contexts) {
|
||||
// just create a MetaContexts instance using the values in the config
|
||||
return getMetaData(makeFromMetaContextsConfig(contexts, user.getPlugin()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionCache calculatePermissions(@NonNull Contexts contexts) {
|
||||
PermissionCache data = new PermissionCache(contexts, user, user.getPlugin().getCalculatorFactory());
|
||||
|
||||
if (contexts == Contexts.allowAll()) {
|
||||
data.setPermissions(user.exportNodesAndShorthand(true));
|
||||
} else {
|
||||
data.setPermissions(user.exportNodesAndShorthand(contexts, true));
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MetaCache calculateMeta(@NonNull MetaContexts contexts) {
|
||||
MetaCache data = new MetaCache();
|
||||
|
||||
if (contexts.getContexts() == Contexts.allowAll()) {
|
||||
data.loadMeta(user.accumulateMeta(newAccumulator(contexts), null));
|
||||
} else {
|
||||
data.loadMeta(user.accumulateMeta(newAccumulator(contexts), null, contexts.getContexts()));
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MetaCache calculateMeta(@NonNull Contexts contexts) {
|
||||
// just create a MetaContexts instance using the values in the config
|
||||
return calculateMeta(makeFromMetaContextsConfig(contexts, user.getPlugin()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recalculatePermissions(@NonNull Contexts contexts) {
|
||||
permission.refresh(contexts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recalculateMeta(@NonNull MetaContexts contexts) {
|
||||
meta.refresh(contexts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recalculateMeta(@NonNull Contexts contexts) {
|
||||
recalculateMeta(makeFromMetaContextsConfig(contexts, user.getPlugin()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recalculatePermissions() {
|
||||
Set<Contexts> keys = permission.asMap().keySet();
|
||||
keys.forEach(this::recalculatePermissions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recalculateMeta() {
|
||||
Set<MetaContexts> keys = meta.asMap().keySet();
|
||||
keys.forEach(this::recalculateMeta);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preCalculate(@NonNull Set<Contexts> contexts) {
|
||||
contexts.forEach(this::preCalculate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preCalculate(@NonNull Contexts contexts) {
|
||||
// pre-calculate just by requesting the data from this cache.
|
||||
// if the data isn't already loaded, it will be calculated.
|
||||
getPermissionData(contexts);
|
||||
getMetaData(contexts);
|
||||
}
|
||||
|
||||
public void invalidateCaches() {
|
||||
permission.invalidateAll();
|
||||
meta.invalidateAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidatePermissionCalculators() {
|
||||
permission.asMap().values().forEach(PermissionCache::invalidateCache);
|
||||
}
|
||||
|
||||
public void doCacheCleanup() {
|
||||
permission.cleanUp();
|
||||
meta.cleanUp();
|
||||
}
|
||||
|
||||
private final class PermissionCacheLoader implements CacheLoader<Contexts, PermissionCache> {
|
||||
@Override
|
||||
public PermissionCache load(Contexts contexts) {
|
||||
return calculatePermissions(contexts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionCache reload(Contexts contexts, PermissionCache oldData) {
|
||||
if (contexts == Contexts.allowAll()) {
|
||||
oldData.comparePermissions(user.exportNodesAndShorthand(true));
|
||||
} else {
|
||||
oldData.comparePermissions(user.exportNodesAndShorthand(contexts, true));
|
||||
}
|
||||
|
||||
return oldData;
|
||||
}
|
||||
}
|
||||
|
||||
private final class MetaCacheLoader implements CacheLoader<MetaContexts, MetaCache> {
|
||||
@Override
|
||||
public MetaCache load(MetaContexts contexts) {
|
||||
return calculateMeta(contexts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MetaCache reload(MetaContexts contexts, MetaCache oldData) {
|
||||
if (contexts.getContexts() == Contexts.allowAll()) {
|
||||
oldData.loadMeta(user.accumulateMeta(newAccumulator(contexts), null));
|
||||
} else {
|
||||
oldData.loadMeta(user.accumulateMeta(newAccumulator(contexts), null, contexts.getContexts()));
|
||||
}
|
||||
|
||||
return oldData;
|
||||
}
|
||||
}
|
||||
|
||||
private static MetaContexts makeFromMetaContextsConfig(Contexts contexts, LuckPermsPlugin plugin) {
|
||||
return new MetaContexts(
|
||||
contexts,
|
||||
plugin.getConfiguration().get(ConfigKeys.PREFIX_FORMATTING_OPTIONS),
|
||||
plugin.getConfiguration().get(ConfigKeys.SUFFIX_FORMATTING_OPTIONS)
|
||||
);
|
||||
}
|
||||
|
||||
private static MetaAccumulator newAccumulator(MetaContexts contexts) {
|
||||
return new MetaAccumulator(
|
||||
new SimpleMetaStack(contexts.getPrefixStackDefinition(), ChatMetaType.PREFIX),
|
||||
new SimpleMetaStack(contexts.getSuffixStackDefinition(), ChatMetaType.SUFFIX)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -26,7 +26,6 @@
|
||||
package me.lucko.luckperms.common.calculators;
|
||||
|
||||
import me.lucko.luckperms.api.Contexts;
|
||||
import me.lucko.luckperms.common.model.User;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -39,10 +38,10 @@ public interface CalculatorFactory {
|
||||
* Builds a PermissionCalculator for the user in the given context
|
||||
*
|
||||
* @param contexts the contexts to build the calculator in
|
||||
* @param user the user to build for
|
||||
* @param metadata the calculator metadata
|
||||
* @return a permission calculator instance
|
||||
*/
|
||||
PermissionCalculator build(Contexts contexts, User user);
|
||||
PermissionCalculator build(Contexts contexts, PermissionCalculatorMetadata metadata);
|
||||
|
||||
/**
|
||||
* Gets the processors which are currently being added to built calculators
|
||||
|
@ -68,7 +68,7 @@ public class CheckCommand extends SingleCommand {
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
|
||||
Tristate tristate = user.getUserData().getPermissionData(plugin.getContextForUser(user)).getPermissionValue(permission, CheckOrigin.INTERNAL);
|
||||
Tristate tristate = user.getCachedData().getPermissionData(plugin.getContextForUser(user)).getPermissionValue(permission, CheckOrigin.INTERNAL);
|
||||
Message.CHECK_RESULT.send(sender, user.getFriendlyName(), permission, Util.formatTristate(tristate));
|
||||
return CommandResult.SUCCESS;
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ public class TreeCommand extends SingleCommand {
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
|
||||
PermissionCache permissionData = user.getUserData().getPermissionData(plugin.getContextForUser(user));
|
||||
PermissionCache permissionData = user.getCachedData().getPermissionData(plugin.getContextForUser(user));
|
||||
TreeView view = TreeViewBuilder.newBuilder().rootPosition(selection).maxLevels(maxLevel).build(plugin.getPermissionVault());
|
||||
|
||||
if (!view.hasData()) {
|
||||
|
@ -106,7 +106,7 @@ public class UserInfo extends SubCommand<User> {
|
||||
.map(e -> Util.contextToString(e.getKey(), e.getValue()))
|
||||
.collect(Collectors.joining(" "));
|
||||
|
||||
MetaData meta = user.getUserData().getMetaData(contexts);
|
||||
MetaData meta = user.getCachedData().getMetaData(contexts);
|
||||
if (meta.getPrefix() != null) {
|
||||
prefix = "&f\"" + meta.getPrefix() + "&f\"";
|
||||
}
|
||||
|
@ -32,13 +32,16 @@ import com.google.common.collect.ImmutableSet;
|
||||
|
||||
import me.lucko.luckperms.api.LogEntry;
|
||||
import me.lucko.luckperms.api.Node;
|
||||
import me.lucko.luckperms.api.caching.GroupData;
|
||||
import me.lucko.luckperms.api.caching.UserData;
|
||||
import me.lucko.luckperms.api.event.LuckPermsEvent;
|
||||
import me.lucko.luckperms.api.event.cause.CreationCause;
|
||||
import me.lucko.luckperms.api.event.cause.DeletionCause;
|
||||
import me.lucko.luckperms.api.event.log.LogBroadcastEvent;
|
||||
import me.lucko.luckperms.common.event.impl.EventConfigReload;
|
||||
import me.lucko.luckperms.common.event.impl.EventGroupCacheLoad;
|
||||
import me.lucko.luckperms.common.event.impl.EventGroupCreate;
|
||||
import me.lucko.luckperms.common.event.impl.EventGroupDataRecalculate;
|
||||
import me.lucko.luckperms.common.event.impl.EventGroupDelete;
|
||||
import me.lucko.luckperms.common.event.impl.EventGroupLoad;
|
||||
import me.lucko.luckperms.common.event.impl.EventGroupLoadAll;
|
||||
@ -88,11 +91,21 @@ public final class EventFactory {
|
||||
eventBus.fireEvent(event);
|
||||
}
|
||||
|
||||
public void handleGroupCacheLoad(Group group, GroupData data) {
|
||||
EventGroupCacheLoad event = new EventGroupCacheLoad(group.getDelegate(), data);
|
||||
fireEventAsync(event);
|
||||
}
|
||||
|
||||
public void handleGroupCreate(Group group, CreationCause cause) {
|
||||
EventGroupCreate event = new EventGroupCreate(group.getDelegate(), cause);
|
||||
fireEventAsync(event);
|
||||
}
|
||||
|
||||
public void handleGroupDataRecalculate(Group group, GroupData data) {
|
||||
EventGroupDataRecalculate event = new EventGroupDataRecalculate(group.getDelegate(), data);
|
||||
fireEventAsync(event);
|
||||
}
|
||||
|
||||
public void handleGroupDelete(Group group, DeletionCause cause) {
|
||||
EventGroupDelete event = new EventGroupDelete(group.getName(), ImmutableSet.copyOf(group.getEnduringNodes().values()), cause);
|
||||
fireEventAsync(event);
|
||||
|
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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.event.impl;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
|
||||
import me.lucko.luckperms.api.Group;
|
||||
import me.lucko.luckperms.api.caching.GroupData;
|
||||
import me.lucko.luckperms.api.event.group.GroupCacheLoadEvent;
|
||||
import me.lucko.luckperms.common.event.AbstractEvent;
|
||||
|
||||
@Getter
|
||||
@ToString
|
||||
@AllArgsConstructor
|
||||
public class EventGroupCacheLoad extends AbstractEvent implements GroupCacheLoadEvent {
|
||||
|
||||
private final Group group;
|
||||
private final GroupData loadedData;
|
||||
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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.event.impl;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
|
||||
import me.lucko.luckperms.api.Group;
|
||||
import me.lucko.luckperms.api.caching.GroupData;
|
||||
import me.lucko.luckperms.api.event.group.GroupDataRecalculateEvent;
|
||||
import me.lucko.luckperms.common.event.AbstractEvent;
|
||||
|
||||
@Getter
|
||||
@ToString
|
||||
@AllArgsConstructor
|
||||
public class EventGroupDataRecalculate extends AbstractEvent implements GroupDataRecalculateEvent {
|
||||
|
||||
private final Group group;
|
||||
private final GroupData data;
|
||||
|
||||
}
|
@ -101,7 +101,7 @@ public class GenericUserManager extends AbstractManager<UserIdentifier, User> im
|
||||
plugin.getScheduler().asyncLater(() -> {
|
||||
User user = getIfLoaded(plugin.getUuidCache().getUUID(uuid));
|
||||
if (user != null && !plugin.isPlayerOnline(uuid)) {
|
||||
user.getUserData().invalidateCaches();
|
||||
user.getCachedData().invalidateCaches();
|
||||
unload(user);
|
||||
plugin.getUuidCache().clearCache(uuid);
|
||||
}
|
||||
|
@ -32,12 +32,15 @@ import lombok.ToString;
|
||||
import me.lucko.luckperms.api.Node;
|
||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
import me.lucko.luckperms.common.api.delegates.model.ApiGroup;
|
||||
import me.lucko.luckperms.common.buffers.BufferedRequest;
|
||||
import me.lucko.luckperms.common.caching.GroupCache;
|
||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.references.GroupReference;
|
||||
import me.lucko.luckperms.common.references.Identifiable;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@ToString(of = {"name"})
|
||||
@EqualsAndHashCode(of = {"name"}, callSuper = false)
|
||||
@ -52,9 +55,25 @@ public class Group extends PermissionHolder implements Identifiable<String> {
|
||||
@Getter
|
||||
private final ApiGroup delegate = new ApiGroup(this);
|
||||
|
||||
/**
|
||||
* The groups data cache instance
|
||||
*/
|
||||
@Getter
|
||||
private final GroupCache cachedData;
|
||||
|
||||
@Getter
|
||||
private BufferedRequest<Void> refreshBuffer;
|
||||
|
||||
public Group(String name, LuckPermsPlugin plugin) {
|
||||
super(name, plugin);
|
||||
this.name = name.toLowerCase();
|
||||
|
||||
this.refreshBuffer = new GroupRefreshBuffer(plugin, this);
|
||||
this.cachedData = new GroupCache(this);
|
||||
getPlugin().getApiProvider().getEventFactory().handleGroupCacheLoad(this, cachedData);
|
||||
|
||||
// invalidate out caches when data is updated
|
||||
getStateListeners().add(() -> refreshBuffer.request());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -91,4 +110,25 @@ public class Group extends PermissionHolder implements Identifiable<String> {
|
||||
public GroupReference toReference() {
|
||||
return GroupReference.of(getId());
|
||||
}
|
||||
|
||||
private CompletableFuture<Void> reloadCachedData() {
|
||||
return CompletableFuture.allOf(cachedData.reloadPermissions(), cachedData.reloadMeta()).thenAccept(n -> {
|
||||
getPlugin().getApiProvider().getEventFactory().handleGroupDataRecalculate(this, cachedData);
|
||||
});
|
||||
}
|
||||
|
||||
private static final class GroupRefreshBuffer extends BufferedRequest<Void> {
|
||||
private final Group group;
|
||||
|
||||
private GroupRefreshBuffer(LuckPermsPlugin plugin, Group group) {
|
||||
super(50L, 5L, plugin.getScheduler().async());
|
||||
this.group = group;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void perform() {
|
||||
return group.reloadCachedData().join();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -47,6 +47,7 @@ import me.lucko.luckperms.api.context.ContextSet;
|
||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
import me.lucko.luckperms.common.api.delegates.model.ApiPermissionHolder;
|
||||
import me.lucko.luckperms.common.buffers.Cache;
|
||||
import me.lucko.luckperms.common.caching.HolderCache;
|
||||
import me.lucko.luckperms.common.caching.MetaAccumulator;
|
||||
import me.lucko.luckperms.common.caching.handlers.StateListener;
|
||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||
@ -250,6 +251,13 @@ public abstract class PermissionHolder {
|
||||
*/
|
||||
public abstract String getFriendlyName();
|
||||
|
||||
/**
|
||||
* Gets the holders cached data
|
||||
*
|
||||
* @return the holders cached data
|
||||
*/
|
||||
public abstract HolderCache<?> getCachedData();
|
||||
|
||||
/**
|
||||
* Forms a HolderReference for this PermissionHolder.
|
||||
*
|
||||
|
@ -42,6 +42,7 @@ import me.lucko.luckperms.common.references.UserReference;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@ToString(of = {"uuid"})
|
||||
@EqualsAndHashCode(of = {"uuid"}, callSuper = false)
|
||||
@ -65,10 +66,10 @@ public class User extends PermissionHolder implements Identifiable<UserIdentifie
|
||||
private final PrimaryGroupHolder primaryGroup;
|
||||
|
||||
/**
|
||||
* The users data cache instance, if present.
|
||||
* The users data cache instance
|
||||
*/
|
||||
@Getter
|
||||
private final UserCache userData;
|
||||
private final UserCache cachedData;
|
||||
|
||||
@Getter
|
||||
private BufferedRequest<Void> refreshBuffer;
|
||||
@ -83,8 +84,8 @@ public class User extends PermissionHolder implements Identifiable<UserIdentifie
|
||||
this.refreshBuffer = new UserRefreshBuffer(plugin, this);
|
||||
this.primaryGroup = plugin.getConfiguration().get(ConfigKeys.PRIMARY_GROUP_CALCULATION).apply(this);
|
||||
|
||||
this.userData = new UserCache(this);
|
||||
getPlugin().getApiProvider().getEventFactory().handleUserCacheLoad(this, userData);
|
||||
this.cachedData = new UserCache(this);
|
||||
getPlugin().getApiProvider().getEventFactory().handleUserCacheLoad(this, cachedData);
|
||||
}
|
||||
|
||||
public User(UUID uuid, String name, LuckPermsPlugin plugin) {
|
||||
@ -95,8 +96,8 @@ public class User extends PermissionHolder implements Identifiable<UserIdentifie
|
||||
this.refreshBuffer = new UserRefreshBuffer(plugin, this);
|
||||
this.primaryGroup = plugin.getConfiguration().get(ConfigKeys.PRIMARY_GROUP_CALCULATION).apply(this);
|
||||
|
||||
this.userData = new UserCache(this);
|
||||
getPlugin().getApiProvider().getEventFactory().handleUserCacheLoad(this, userData);
|
||||
this.cachedData = new UserCache(this);
|
||||
getPlugin().getApiProvider().getEventFactory().handleUserCacheLoad(this, cachedData);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -168,24 +169,20 @@ public class User extends PermissionHolder implements Identifiable<UserIdentifie
|
||||
* Sets up the UserData cache
|
||||
* Blocking call.
|
||||
*/
|
||||
public synchronized void preCalculateData() {
|
||||
public void preCalculateData() {
|
||||
// first try to refresh any existing permissions
|
||||
refreshPermissions();
|
||||
refreshBuffer.requestDirectly();
|
||||
|
||||
// pre-calc the allowall & global contexts
|
||||
// since contexts change so frequently, it's not worth trying to calculate any more than this.
|
||||
userData.preCalculate(Contexts.allowAll());
|
||||
userData.preCalculate(Contexts.global());
|
||||
cachedData.preCalculate(Contexts.allowAll());
|
||||
cachedData.preCalculate(Contexts.global());
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh and re-assign the users permissions
|
||||
* Blocking call.
|
||||
*/
|
||||
private synchronized void refreshPermissions() {
|
||||
userData.recalculatePermissions();
|
||||
userData.recalculateMeta();
|
||||
getPlugin().getApiProvider().getEventFactory().handleUserDataRecalculate(this, userData);
|
||||
public CompletableFuture<Void> reloadCachedData() {
|
||||
return CompletableFuture.allOf(cachedData.reloadPermissions(), cachedData.reloadMeta()).thenAccept(n -> {
|
||||
getPlugin().getApiProvider().getEventFactory().handleUserDataRecalculate(this, cachedData);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -213,14 +210,13 @@ public class User extends PermissionHolder implements Identifiable<UserIdentifie
|
||||
private final User user;
|
||||
|
||||
private UserRefreshBuffer(LuckPermsPlugin plugin, User user) {
|
||||
super(250L, 50L, plugin.getScheduler().async());
|
||||
super(50L, 5L, plugin.getScheduler().async());
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void perform() {
|
||||
user.refreshPermissions();
|
||||
return null;
|
||||
return user.reloadCachedData().join();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -400,6 +400,7 @@ public abstract class ConfigurateDao extends AbstractDao {
|
||||
} finally {
|
||||
user.getIoLock().unlock();
|
||||
}
|
||||
user.getRefreshBuffer().requestDirectly();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -495,6 +496,7 @@ public abstract class ConfigurateDao extends AbstractDao {
|
||||
} finally {
|
||||
group.getIoLock().unlock();
|
||||
}
|
||||
group.getRefreshBuffer().requestDirectly();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -528,6 +530,7 @@ public abstract class ConfigurateDao extends AbstractDao {
|
||||
group.getIoLock().unlock();
|
||||
}
|
||||
}
|
||||
group.getRefreshBuffer().requestDirectly();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -331,8 +331,8 @@ public class MongoDao extends AbstractDao {
|
||||
return reportException(e);
|
||||
} finally {
|
||||
user.getIoLock().unlock();
|
||||
user.getRefreshBuffer().requestDirectly();
|
||||
}
|
||||
user.getRefreshBuffer().requestDirectly();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -433,6 +433,7 @@ public class MongoDao extends AbstractDao {
|
||||
} finally {
|
||||
group.getIoLock().unlock();
|
||||
}
|
||||
group.getRefreshBuffer().requestDirectly();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -444,22 +445,23 @@ public class MongoDao extends AbstractDao {
|
||||
MongoCollection<Document> c = database.getCollection(prefix + "groups");
|
||||
|
||||
try (MongoCursor<Document> cursor = c.find(new Document("_id", group.getName())).iterator()) {
|
||||
if (cursor.hasNext()) {
|
||||
Document d = cursor.next();
|
||||
|
||||
group.setEnduringNodes(revert((Map<String, Boolean>) d.get("perms")).entrySet().stream()
|
||||
.map(e -> NodeFactory.fromSerializedNode(e.getKey(), e.getValue()))
|
||||
.collect(Collectors.toSet())
|
||||
);
|
||||
return true;
|
||||
if (!cursor.hasNext()) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
|
||||
Document d = cursor.next();
|
||||
group.setEnduringNodes(revert((Map<String, Boolean>) d.get("perms")).entrySet().stream()
|
||||
.map(e -> NodeFactory.fromSerializedNode(e.getKey(), e.getValue()))
|
||||
.collect(Collectors.toSet())
|
||||
);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return reportException(e);
|
||||
} finally {
|
||||
group.getIoLock().unlock();
|
||||
}
|
||||
group.getRefreshBuffer().requestDirectly();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -388,12 +388,11 @@ public class SqlDao extends AbstractDao {
|
||||
plugin.getUserManager().giveDefaultIfNeeded(user, false);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
} finally {
|
||||
user.getIoLock().unlock();
|
||||
user.getRefreshBuffer().requestDirectly();
|
||||
}
|
||||
user.getRefreshBuffer().requestDirectly();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -659,11 +658,11 @@ public class SqlDao extends AbstractDao {
|
||||
} else {
|
||||
group.clearNodes();
|
||||
}
|
||||
|
||||
return true;
|
||||
} finally {
|
||||
group.getIoLock().unlock();
|
||||
}
|
||||
group.getRefreshBuffer().requestDirectly();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -27,6 +27,7 @@ package me.lucko.luckperms.common.tasks;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import me.lucko.luckperms.common.model.Group;
|
||||
import me.lucko.luckperms.common.model.User;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
|
||||
@ -37,7 +38,10 @@ public class CacheHousekeepingTask implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
for (User user : plugin.getUserManager().getAll().values()) {
|
||||
user.getUserData().doCacheCleanup();
|
||||
user.getCachedData().doCacheCleanup();
|
||||
}
|
||||
for (Group group : plugin.getGroupManager().getAll().values()) {
|
||||
group.getCachedData().doCacheCleanup();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -102,10 +102,4 @@ public class LoginHelper {
|
||||
return user;
|
||||
}
|
||||
|
||||
public static void refreshPlayer(LuckPermsPlugin plugin, UUID uuid) {
|
||||
final User user = plugin.getUserManager().getIfLoaded(plugin.getUuidCache().getUUID(uuid));
|
||||
if (user != null) {
|
||||
user.getRefreshBuffer().requestDirectly();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,8 +29,6 @@ import com.google.common.collect.ImmutableCollection;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import me.lucko.luckperms.api.Contexts;
|
||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
|
||||
import org.spongepowered.api.plugin.PluginContainer;
|
||||
@ -83,7 +81,5 @@ public interface LPPermissionService {
|
||||
// utils
|
||||
ImmutableList<SubjectReference> sortSubjects(Collection<SubjectReference> s);
|
||||
|
||||
Contexts calculateContexts(ImmutableContextSet contextSet);
|
||||
|
||||
void invalidateAllCaches(LPSubject.CacheLevel cacheLevel);
|
||||
}
|
||||
|
@ -34,7 +34,6 @@ import me.lucko.luckperms.common.calculators.AbstractCalculatorFactory;
|
||||
import me.lucko.luckperms.common.calculators.PermissionCalculator;
|
||||
import me.lucko.luckperms.common.calculators.PermissionCalculatorMetadata;
|
||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||
import me.lucko.luckperms.common.model.User;
|
||||
import me.lucko.luckperms.common.processors.MapProcessor;
|
||||
import me.lucko.luckperms.common.processors.PermissionProcessor;
|
||||
import me.lucko.luckperms.common.processors.RegexProcessor;
|
||||
@ -50,7 +49,7 @@ public class SpongeCalculatorFactory extends AbstractCalculatorFactory {
|
||||
private final LPSpongePlugin plugin;
|
||||
|
||||
@Override
|
||||
public PermissionCalculator build(Contexts contexts, User user) {
|
||||
public PermissionCalculator build(Contexts contexts, PermissionCalculatorMetadata metadata) {
|
||||
ImmutableList.Builder<PermissionProcessor> processors = ImmutableList.builder();
|
||||
|
||||
processors.add(new MapProcessor());
|
||||
@ -71,8 +70,7 @@ public class SpongeCalculatorFactory extends AbstractCalculatorFactory {
|
||||
processors.add(new DefaultsProcessor(plugin.getService(), contexts.getContexts().makeImmutable()));
|
||||
}
|
||||
|
||||
PermissionCalculatorMetadata meta = PermissionCalculatorMetadata.of(user.getFriendlyName(), contexts.getContexts());
|
||||
return registerCalculator(new PermissionCalculator(plugin, meta, processors.build()));
|
||||
return registerCalculator(new PermissionCalculator(plugin, metadata, processors.build()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -171,12 +171,6 @@ public class SpongeConnectionListener {
|
||||
}
|
||||
}
|
||||
|
||||
@Listener(order = Order.EARLY)
|
||||
public void onClientJoin(ClientConnectionEvent.Join e) {
|
||||
// Refresh permissions again
|
||||
plugin.getScheduler().doAsync(() -> LoginHelper.refreshPlayer(plugin, e.getTargetEntity().getUniqueId()));
|
||||
}
|
||||
|
||||
@Listener(order = Order.POST)
|
||||
public void onClientLeave(ClientConnectionEvent.Disconnect e) {
|
||||
/* We don't actually remove the user instance here, as Sponge likes to keep performing checks
|
||||
|
@ -27,38 +27,27 @@ package me.lucko.luckperms.sponge.model;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ListMultimap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
import me.lucko.luckperms.api.ChatMetaType;
|
||||
import me.lucko.luckperms.api.LocalizedNode;
|
||||
import me.lucko.luckperms.api.Node;
|
||||
import me.lucko.luckperms.api.Tristate;
|
||||
import me.lucko.luckperms.api.caching.MetaData;
|
||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
import me.lucko.luckperms.common.caching.MetaAccumulator;
|
||||
import me.lucko.luckperms.common.model.Group;
|
||||
import me.lucko.luckperms.common.verbose.CheckOrigin;
|
||||
import me.lucko.luckperms.sponge.LPSpongePlugin;
|
||||
import me.lucko.luckperms.sponge.service.LuckPermsService;
|
||||
import me.lucko.luckperms.sponge.service.LuckPermsSubjectData;
|
||||
import me.lucko.luckperms.sponge.service.ProxyFactory;
|
||||
import me.lucko.luckperms.sponge.service.model.CompatibilityUtil;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubject;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubjectCollection;
|
||||
import me.lucko.luckperms.sponge.service.model.SubjectReference;
|
||||
|
||||
import org.spongepowered.api.command.CommandSource;
|
||||
import org.spongepowered.api.service.permission.NodeTree;
|
||||
import org.spongepowered.api.service.permission.PermissionService;
|
||||
import org.spongepowered.api.service.permission.Subject;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class SpongeGroup extends Group {
|
||||
|
||||
@ -74,11 +63,7 @@ public class SpongeGroup extends Group {
|
||||
}
|
||||
|
||||
public static class GroupSubject implements LPSubject {
|
||||
|
||||
@Getter
|
||||
private final SpongeGroup parent;
|
||||
|
||||
@Getter
|
||||
private final LPSpongePlugin plugin;
|
||||
|
||||
@Getter
|
||||
@ -87,61 +72,11 @@ public class SpongeGroup extends Group {
|
||||
@Getter
|
||||
private final LuckPermsSubjectData transientSubjectData;
|
||||
|
||||
private final LoadingCache<ImmutableContextSet, NodeTree> permissionCache = Caffeine.newBuilder()
|
||||
.expireAfterAccess(10, TimeUnit.MINUTES)
|
||||
.build(contexts -> {
|
||||
// TODO move this away from NodeTree
|
||||
Map<String, Boolean> permissions = getParent().getAllNodes(getPlugin().getService().calculateContexts(contexts)).stream()
|
||||
.map(LocalizedNode::getNode)
|
||||
.collect(Collectors.toMap(Node::getPermission, Node::getValuePrimitive));
|
||||
|
||||
return NodeTree.of(permissions);
|
||||
});
|
||||
|
||||
private final LoadingCache<ImmutableContextSet, ImmutableList<SubjectReference>> parentCache = Caffeine.newBuilder()
|
||||
.expireAfterWrite(10, TimeUnit.MINUTES)
|
||||
.build(contexts -> {
|
||||
Set<SubjectReference> subjects = getParent().getAllNodes(getPlugin().getService().calculateContexts(contexts)).stream()
|
||||
.map(LocalizedNode::getNode)
|
||||
.filter(Node::isGroupNode)
|
||||
.map(Node::getGroupName)
|
||||
.distinct()
|
||||
.map(n -> Optional.ofNullable(getPlugin().getGroupManager().getIfLoaded(n)))
|
||||
.filter(Optional::isPresent)
|
||||
.map(Optional::get)
|
||||
.map(SpongeGroup::sponge)
|
||||
.map(LPSubject::toReference)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
subjects.addAll(getPlugin().getService().getGroupSubjects().getDefaults().getParents(contexts));
|
||||
subjects.addAll(getPlugin().getService().getDefaults().getParents(contexts));
|
||||
|
||||
return getService().sortSubjects(subjects);
|
||||
});
|
||||
|
||||
private GroupSubject(LPSpongePlugin plugin, SpongeGroup parent) {
|
||||
this.parent = parent;
|
||||
this.plugin = plugin;
|
||||
this.subjectData = new LuckPermsSubjectData(true, plugin.getService(), parent, this);
|
||||
this.transientSubjectData = new LuckPermsSubjectData(false, plugin.getService(), parent, this);
|
||||
|
||||
parent.getStateListeners().add(() -> invalidateCaches(CacheLevel.PERMISSION));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateCaches(CacheLevel type) {
|
||||
if (type == CacheLevel.OPTION) {
|
||||
return; // don't invalidate for option changes
|
||||
}
|
||||
|
||||
permissionCache.invalidateAll();
|
||||
parentCache.invalidateAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void performCleanup() {
|
||||
permissionCache.cleanUp();
|
||||
parentCache.cleanUp();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -176,19 +111,7 @@ public class SpongeGroup extends Group {
|
||||
|
||||
@Override
|
||||
public Tristate getPermissionValue(ImmutableContextSet contexts, String permission) {
|
||||
NodeTree nt = permissionCache.get(contexts);
|
||||
Tristate t = CompatibilityUtil.convertTristate(nt.get(permission));
|
||||
if (t != Tristate.UNDEFINED) {
|
||||
return t;
|
||||
}
|
||||
|
||||
t = plugin.getService().getGroupSubjects().getDefaults().getPermissionValue(contexts, permission);
|
||||
if (t != Tristate.UNDEFINED) {
|
||||
return t;
|
||||
}
|
||||
|
||||
t = plugin.getService().getDefaults().getPermissionValue(contexts, permission);
|
||||
return t;
|
||||
return parent.getCachedData().getPermissionData(plugin.getContextManager().formContexts(contexts)).getPermissionValue(permission, CheckOrigin.PLATFORM_LOOKUP_CHECK);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -198,29 +121,48 @@ public class SpongeGroup extends Group {
|
||||
|
||||
@Override
|
||||
public ImmutableList<SubjectReference> getParents(ImmutableContextSet contexts) {
|
||||
return parentCache.get(contexts);
|
||||
ImmutableSet.Builder<SubjectReference> subjects = ImmutableSet.builder();
|
||||
|
||||
for (String perm : parent.getCachedData().getPermissionData(plugin.getContextManager().formContexts(contexts)).getImmutableBacking().keySet()) {
|
||||
if (!perm.startsWith("group.")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String groupName = perm.substring("group.".length());
|
||||
if (plugin.getGroupManager().isLoaded(groupName)) {
|
||||
subjects.add(plugin.getService().getGroupSubjects().loadSubject(groupName).join().toReference());
|
||||
}
|
||||
}
|
||||
|
||||
subjects.addAll(plugin.getService().getGroupSubjects().getDefaults().getParents(contexts));
|
||||
subjects.addAll(plugin.getService().getDefaults().getParents(contexts));
|
||||
|
||||
return getService().sortSubjects(subjects.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<String> getOption(ImmutableContextSet contexts, String s) {
|
||||
Optional<String> option;
|
||||
MetaData data = parent.getCachedData().getMetaData(plugin.getContextManager().formContexts(contexts));
|
||||
if (s.equalsIgnoreCase("prefix")) {
|
||||
option = getChatMeta(contexts, ChatMetaType.PREFIX);
|
||||
|
||||
} else if (s.equalsIgnoreCase("suffix")) {
|
||||
option = getChatMeta(contexts, ChatMetaType.SUFFIX);
|
||||
|
||||
} else {
|
||||
option = getMeta(contexts, s);
|
||||
if (data.getPrefix() != null) {
|
||||
return Optional.of(data.getPrefix());
|
||||
}
|
||||
}
|
||||
|
||||
if (option.isPresent()) {
|
||||
return option;
|
||||
if (s.equalsIgnoreCase("suffix")) {
|
||||
if (data.getSuffix() != null) {
|
||||
return Optional.of(data.getSuffix());
|
||||
}
|
||||
}
|
||||
|
||||
option = plugin.getService().getGroupSubjects().getDefaults().getOption(contexts, s);
|
||||
if (option.isPresent()) {
|
||||
return option;
|
||||
String val = data.getMeta().get(s);
|
||||
if (val != null) {
|
||||
return Optional.of(val);
|
||||
}
|
||||
|
||||
Optional<String> v = plugin.getService().getGroupSubjects().getDefaults().getOption(contexts, s);
|
||||
if (v.isPresent()) {
|
||||
return v;
|
||||
}
|
||||
|
||||
return plugin.getService().getDefaults().getOption(contexts, s);
|
||||
@ -231,16 +173,11 @@ public class SpongeGroup extends Group {
|
||||
return plugin.getContextManager().getApplicableContext(this.sponge());
|
||||
}
|
||||
|
||||
private Optional<String> getChatMeta(ImmutableContextSet contexts, ChatMetaType type) {
|
||||
MetaAccumulator metaAccumulator = parent.accumulateMeta(null, null, plugin.getService().calculateContexts(contexts));
|
||||
return Optional.ofNullable(metaAccumulator.getStack(type).toFormattedString());
|
||||
}
|
||||
|
||||
private Optional<String> getMeta(ImmutableContextSet contexts, String key) {
|
||||
MetaAccumulator metaAccumulator = parent.accumulateMeta(null, null, plugin.getService().calculateContexts(contexts));
|
||||
ListMultimap<String, String> meta = metaAccumulator.getMeta();
|
||||
List<String> ret = meta.get(key);
|
||||
return ret.isEmpty() ? Optional.empty() : Optional.of(ret.get(0));
|
||||
@Override
|
||||
public void invalidateCaches(CacheLevel cacheLevel) {
|
||||
// invalidate for all changes
|
||||
parent.getCachedData().invalidateCaches();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -45,12 +45,12 @@ import me.lucko.luckperms.sponge.service.model.SubjectReference;
|
||||
|
||||
import org.spongepowered.api.Sponge;
|
||||
import org.spongepowered.api.command.CommandSource;
|
||||
import org.spongepowered.api.entity.living.player.Player;
|
||||
import org.spongepowered.api.service.permission.PermissionService;
|
||||
import org.spongepowered.api.service.permission.Subject;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class SpongeUser extends User {
|
||||
|
||||
@ -100,13 +100,7 @@ public class SpongeUser extends User {
|
||||
@Override
|
||||
public Optional<CommandSource> getCommandSource() {
|
||||
final UUID uuid = plugin.getUuidCache().getExternalUUID(parent.getUuid());
|
||||
|
||||
Optional<Player> p = Sponge.getServer().getPlayer(uuid);
|
||||
if (p.isPresent()) {
|
||||
return Optional.of(p.get());
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
return Sponge.getServer().getPlayer(uuid).map(Function.identity());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -126,7 +120,7 @@ public class SpongeUser extends User {
|
||||
|
||||
@Override
|
||||
public Tristate getPermissionValue(ImmutableContextSet contexts, String permission) {
|
||||
return parent.getUserData().getPermissionData(plugin.getService().calculateContexts(contexts)).getPermissionValue(permission, CheckOrigin.PLATFORM_LOOKUP_CHECK);
|
||||
return parent.getCachedData().getPermissionData(plugin.getContextManager().formContexts(contexts)).getPermissionValue(permission, CheckOrigin.PLATFORM_LOOKUP_CHECK);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -138,7 +132,7 @@ public class SpongeUser extends User {
|
||||
public ImmutableList<SubjectReference> getParents(ImmutableContextSet contexts) {
|
||||
ImmutableSet.Builder<SubjectReference> subjects = ImmutableSet.builder();
|
||||
|
||||
for (String perm : parent.getUserData().getPermissionData(plugin.getService().calculateContexts(contexts)).getImmutableBacking().keySet()) {
|
||||
for (String perm : parent.getCachedData().getPermissionData(plugin.getContextManager().formContexts(contexts)).getImmutableBacking().keySet()) {
|
||||
if (!perm.startsWith("group.")) {
|
||||
continue;
|
||||
}
|
||||
@ -157,7 +151,7 @@ public class SpongeUser extends User {
|
||||
|
||||
@Override
|
||||
public Optional<String> getOption(ImmutableContextSet contexts, String s) {
|
||||
MetaData data = parent.getUserData().getMetaData(plugin.getService().calculateContexts(contexts));
|
||||
MetaData data = parent.getCachedData().getMetaData(plugin.getContextManager().formContexts(contexts));
|
||||
if (s.equalsIgnoreCase("prefix")) {
|
||||
if (data.getPrefix() != null) {
|
||||
return Optional.of(data.getPrefix());
|
||||
@ -191,7 +185,7 @@ public class SpongeUser extends User {
|
||||
@Override
|
||||
public void invalidateCaches(CacheLevel cacheLevel) {
|
||||
// invalidate for all changes
|
||||
parent.getUserData().invalidateCaches();
|
||||
parent.getCachedData().invalidateCaches();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,8 +35,6 @@ import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
import me.lucko.luckperms.api.Contexts;
|
||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
import me.lucko.luckperms.common.model.Group;
|
||||
import me.lucko.luckperms.common.utils.Predicates;
|
||||
import me.lucko.luckperms.sponge.LPSpongePlugin;
|
||||
@ -230,11 +228,6 @@ public class LuckPermsService implements LPPermissionService {
|
||||
return ImmutableList.copyOf(ret);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Contexts calculateContexts(ImmutableContextSet contextSet) {
|
||||
return plugin.getContextManager().formContexts(null, contextSet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateAllCaches(LPSubject.CacheLevel cacheLevel) {
|
||||
for (LPSubjectCollection collection : collections.asMap().values()) {
|
||||
|
@ -353,7 +353,7 @@ public class LuckPermsSubjectData implements LPSubjectData {
|
||||
|
||||
toRemove.forEach(makeUnsetConsumer(enduring));
|
||||
|
||||
MetaAccumulator metaAccumulator = holder.accumulateMeta(null, null, service.calculateContexts(context));
|
||||
MetaAccumulator metaAccumulator = holder.accumulateMeta(null, null, service.getPlugin().getContextManager().formContexts(context));
|
||||
int priority = metaAccumulator.getChatMeta(type).keySet().stream().mapToInt(e -> e).max().orElse(0);
|
||||
priority += 10;
|
||||
|
||||
@ -451,23 +451,21 @@ public class LuckPermsSubjectData implements LPSubjectData {
|
||||
} else {
|
||||
if (t instanceof User) {
|
||||
User user = ((User) t);
|
||||
return service.getPlugin().getStorage().saveUser(user).thenApplyAsync(success -> {
|
||||
return service.getPlugin().getStorage().saveUser(user).thenComposeAsync(success -> {
|
||||
if (!success) {
|
||||
return null;
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
|
||||
user.getRefreshBuffer().request().join();
|
||||
return null;
|
||||
return user.getRefreshBuffer().request();
|
||||
}, service.getPlugin().getScheduler().async());
|
||||
} else {
|
||||
Group group = ((Group) t);
|
||||
return service.getPlugin().getStorage().saveGroup(group).thenApplyAsync(success -> {
|
||||
return service.getPlugin().getStorage().saveGroup(group).thenComposeAsync(success -> {
|
||||
if (!success) {
|
||||
return null;
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
|
||||
service.getPlugin().getUpdateTaskBuffer().request().join();
|
||||
return null;
|
||||
return service.getPlugin().getUpdateTaskBuffer().request();
|
||||
}, service.getPlugin().getScheduler().async());
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user