Skip to content

Commit add5eb7

Browse files
authored
Add permission cache system + permission for vanish item pickup (#6488)
Fixes #6270
1 parent ddaadf2 commit add5eb7

File tree

7 files changed

+104
-7
lines changed

7 files changed

+104
-7
lines changed

Essentials/src/main/java/com/earth2me/essentials/EssentialsPlayerListener.java

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1230,19 +1230,23 @@ private final class PickupListenerPre1_12 implements Listener {
12301230
public void onPlayerPickupItem(final org.bukkit.event.player.PlayerPickupItemEvent event) {
12311231
if (event.getItem().hasMetadata(Commandfireball.FIREBALL_META_KEY)) {
12321232
event.setCancelled(true);
1233-
} else if (ess.getSettings().getDisableItemPickupWhileAfk()) {
1234-
if (ess.getUser(event.getPlayer()).isAfk()) {
1235-
event.setCancelled(true);
1236-
}
1233+
return;
1234+
}
1235+
final User user = ess.getUser(event.getPlayer());
1236+
if ((ess.getSettings().getDisableItemPickupWhileAfk() && user.isAfk())
1237+
|| (user.isVanished() && !user.isAuthorizedCached("essentials.vanish.pickup"))) {
1238+
event.setCancelled(true);
12371239
}
12381240
}
12391241
}
12401242

12411243
private final class PickupListener1_12 implements Listener {
12421244
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
12431245
public void onPlayerPickupItem(final org.bukkit.event.entity.EntityPickupItemEvent event) {
1244-
if (ess.getSettings().getDisableItemPickupWhileAfk() && event.getEntity() instanceof Player) {
1245-
if (ess.getUser((Player) event.getEntity()).isAfk()) {
1246+
if (event.getEntity() instanceof Player) {
1247+
final User user = ess.getUser((Player) event.getEntity());
1248+
if ((ess.getSettings().getDisableItemPickupWhileAfk() && user.isAfk())
1249+
|| (user.isVanished() && !user.isAuthorizedCached("essentials.vanish.pickup"))) {
12461250
event.setCancelled(true);
12471251
}
12481252
}
@@ -1261,6 +1265,10 @@ public void onGameEvent(final org.bukkit.event.block.BlockReceiveGameEvent event
12611265
private final class CommandSendFilter implements CommandSendListenerProvider.Filter {
12621266
@Override
12631267
public Predicate<String> apply(Player player) {
1268+
// There is no event for op status changes, but the command list is resent when
1269+
// a player is opped/deopped, so we invalidate cached permissions here.
1270+
ess.getPermissionsHandler().invalidatePermissionCache(player.getUniqueId());
1271+
12641272
final User user = ess.getUser(player);
12651273
final Set<PluginCommand> checked = new HashSet<>();
12661274
final Set<PluginCommand> toRemove = new HashSet<>();

Essentials/src/main/java/com/earth2me/essentials/IUser.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
public interface IUser {
3333
boolean isAuthorized(String node);
3434

35+
boolean isAuthorizedCached(String node);
36+
3537
boolean isAuthorized(IEssentialsCommand cmd);
3638

3739
boolean isAuthorized(IEssentialsCommand cmd, String permissionPrefix);

Essentials/src/main/java/com/earth2me/essentials/User.java

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,19 @@ public boolean isAuthorized(final String node) {
147147
return result;
148148
}
149149

150+
@Override
151+
public boolean isAuthorizedCached(final String node) {
152+
if (Essentials.TESTING) {
153+
return false;
154+
}
155+
156+
final boolean result = isAuthorizedCachedCheck(node);
157+
if (ess.getSettings().isDebug()) {
158+
ess.getLogger().log(Level.INFO, "checking if " + base.getName() + " has " + node + " (cached) - " + result);
159+
}
160+
return result;
161+
}
162+
150163
@Override
151164
public boolean isPermissionSet(final String node) {
152165
if (Essentials.TESTING) {
@@ -186,6 +199,24 @@ private boolean isAuthorizedCheck(final String node) {
186199
}
187200
}
188201

202+
private boolean isAuthorizedCachedCheck(final String node) {
203+
if (base instanceof OfflinePlayerStub) {
204+
return false;
205+
}
206+
207+
try {
208+
return ess.getPermissionsHandler().hasPermissionCached(base, node);
209+
} catch (final Exception ex) {
210+
if (ess.getSettings().isDebug()) {
211+
ess.getLogger().log(Level.SEVERE, "Permission System Error: " + ess.getPermissionsHandler().getName() + " returned: " + ex.getMessage(), ex);
212+
} else {
213+
ess.getLogger().log(Level.SEVERE, "Permission System Error: " + ess.getPermissionsHandler().getName() + " returned: " + ex.getMessage());
214+
}
215+
216+
return false;
217+
}
218+
}
219+
189220
private boolean isPermSetCheck(final String node) {
190221
if (base instanceof OfflinePlayerStub) {
191222
return false;
@@ -872,7 +903,7 @@ public void checkActivity() {
872903
}
873904
}
874905
final long autoafk = ess.getSettings().getAutoAfk();
875-
if (!isAfk() && autoafk > 0 && lastActivity + autoafk * 1000 < System.currentTimeMillis() && isAuthorized("essentials.afk.auto")) {
906+
if (!isAfk() && autoafk > 0 && lastActivity + autoafk * 1000 < System.currentTimeMillis() && isAuthorizedCached("essentials.afk.auto")) {
876907
setAfk(true, AfkStatusChangeEvent.Cause.ACTIVITY);
877908
if (isAfk() && !isHidden()) {
878909
setDisplayNick();

Essentials/src/main/java/com/earth2me/essentials/perm/IPermissionsHandler.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,13 @@ public interface IPermissionsHandler {
2828

2929
boolean hasPermission(Player base, String node);
3030

31+
default boolean hasPermissionCached(Player base, String node) {
32+
return hasPermission(base, node);
33+
}
34+
35+
default void invalidatePermissionCache(UUID uuid) {
36+
}
37+
3138
// Does not check for * permissions
3239
boolean isPermissionSet(Player base, String node);
3340

Essentials/src/main/java/com/earth2me/essentials/perm/PermissionsHandler.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,16 @@ public boolean hasPermission(final Player base, final String node) {
105105
return handler.hasPermission(base, node);
106106
}
107107

108+
@Override
109+
public boolean hasPermissionCached(final Player base, final String node) {
110+
return handler.hasPermissionCached(base, node);
111+
}
112+
113+
@Override
114+
public void invalidatePermissionCache(final UUID uuid) {
115+
handler.invalidatePermissionCache(uuid);
116+
}
117+
108118
@Override
109119
public boolean isPermissionSet(final Player base, final String node) {
110120
return handler.isPermissionSet(base, node);

Essentials/src/main/java/com/earth2me/essentials/perm/impl/LuckPermsHandler.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,31 @@
77
import net.luckperms.api.context.ContextConsumer;
88
import net.luckperms.api.context.ContextSet;
99
import net.luckperms.api.context.ImmutableContextSet;
10+
import net.luckperms.api.event.EventSubscription;
11+
import net.luckperms.api.event.user.UserDataRecalculateEvent;
1012
import net.luckperms.api.model.group.Group;
1113
import net.luckperms.api.query.QueryOptions;
1214
import org.bukkit.Bukkit;
1315
import org.bukkit.entity.Player;
1416
import org.bukkit.plugin.RegisteredServiceProvider;
1517

18+
import java.util.logging.Level;
1619
import java.util.ArrayList;
1720
import java.util.HashSet;
1821
import java.util.List;
22+
import java.util.Map;
1923
import java.util.Set;
2024
import java.util.UUID;
25+
import java.util.concurrent.ConcurrentHashMap;
2126
import java.util.function.Function;
2227
import java.util.function.Supplier;
2328

2429
public class LuckPermsHandler extends ModernVaultHandler {
2530
private LuckPerms luckPerms;
2631
private Essentials ess;
2732
private CombinedCalculator calculator;
33+
private final Map<UUID, Map<String, Boolean>> permissionCache = new ConcurrentHashMap<>();
34+
private EventSubscription<UserDataRecalculateEvent> recalculateSubscription;
2835

2936
@Override
3037
public void registerContext(final String context, final Function<User, Iterable<String>> calculator, final Supplier<Iterable<String>> suggestions) {
@@ -41,6 +48,30 @@ public void unregisterContexts() {
4148
this.luckPerms.getContextManager().unregisterCalculator(this.calculator);
4249
this.calculator = null;
4350
}
51+
if (this.recalculateSubscription != null) {
52+
this.recalculateSubscription.close();
53+
this.recalculateSubscription = null;
54+
}
55+
this.permissionCache.clear();
56+
}
57+
58+
@Override
59+
public boolean hasPermissionCached(final Player base, final String node) {
60+
final UUID uuid = base.getUniqueId();
61+
final Map<String, Boolean> userCache = permissionCache.computeIfAbsent(uuid, k -> new ConcurrentHashMap<>());
62+
return userCache.computeIfAbsent(node, k -> hasPermission(base, node));
63+
}
64+
65+
@Override
66+
public void invalidatePermissionCache(final UUID uuid) {
67+
invalidateCache(uuid);
68+
}
69+
70+
public void invalidateCache(final UUID uuid) {
71+
if (ess.getSettings().isDebug()) {
72+
ess.getLogger().log(Level.INFO, "Invalidating permission cache for " + uuid);
73+
}
74+
permissionCache.remove(uuid);
4475
}
4576

4677
@Override
@@ -77,6 +108,11 @@ public boolean tryProvider(Essentials ess) {
77108
if (provider != null) {
78109
this.luckPerms = provider.getProvider();
79110
this.ess = ess;
111+
this.recalculateSubscription = this.luckPerms.getEventBus().subscribe(
112+
ess,
113+
UserDataRecalculateEvent.class,
114+
event -> invalidateCache(event.getUser().getUniqueId())
115+
);
80116
}
81117
return luckPerms != null && super.tryProvider(ess);
82118
}

Essentials/src/main/resources/plugin.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1374,6 +1374,9 @@ permissions:
13741374
description: Applies invisibility effects to the player when they are in vanish mode
13751375
essentials.vanish.interact:
13761376
description: Allows the bearer to interact with players in vanish mode
1377+
essentials.vanish.pickup:
1378+
description: Allows the bearer to pick up items while in vanish mode
1379+
default: false
13771380
essentials.version:
13781381
description: Allows access to the /version command
13791382
essentials.warp:

0 commit comments

Comments
 (0)