|
2 | 2 |
|
3 | 3 | import java.util.UUID; |
4 | 4 | import java.util.concurrent.CompletableFuture; |
5 | | -import java.util.concurrent.ExecutionException; |
6 | 5 | import java.util.concurrent.TimeUnit; |
7 | | -import java.util.concurrent.TimeoutException; |
8 | 6 |
|
9 | 7 | import org.bukkit.Bukkit; |
| 8 | +import org.bukkit.entity.Player; |
10 | 9 | import org.bukkit.plugin.RegisteredServiceProvider; |
11 | 10 |
|
12 | 11 | import com.bencodez.advancedcore.AdvancedCorePlugin; |
13 | 12 |
|
14 | 13 | import lombok.Getter; |
15 | 14 | import net.luckperms.api.LuckPerms; |
16 | 15 | import net.luckperms.api.model.user.User; |
| 16 | +import net.luckperms.api.query.QueryOptions; |
17 | 17 |
|
18 | 18 | public class LuckPermsHandle { |
19 | 19 | @Getter |
20 | | - LuckPerms api = null; |
| 20 | + private LuckPerms api; |
21 | 21 |
|
| 22 | + public void load(AdvancedCorePlugin plugin) { |
| 23 | + RegisteredServiceProvider<LuckPerms> provider = Bukkit.getServicesManager().getRegistration(LuckPerms.class); |
| 24 | + if (provider != null) { |
| 25 | + api = provider.getProvider(); |
| 26 | + plugin.getLogger().info("Loaded LuckPerms hook!"); |
| 27 | + } |
| 28 | + } |
| 29 | + |
| 30 | + public boolean luckpermsApiLoaded() { |
| 31 | + return api != null; |
| 32 | + } |
| 33 | + |
| 34 | + /** |
| 35 | + * Synchronous permission check. |
| 36 | + * |
| 37 | + * - If player is online, uses Bukkit (fast). - If player is offline, requires |
| 38 | + * LuckPerms User load. |
| 39 | + * |
| 40 | + * IMPORTANT: This method will NOT block the main thread. If called on the main |
| 41 | + * thread for an offline user, it returns false. |
| 42 | + */ |
22 | 43 | public boolean hasPermission(UUID uuid, String permission) { |
| 44 | + if (api == null) { |
| 45 | + return false; |
| 46 | + } |
| 47 | + |
| 48 | + // Handle your "!perm" convention |
| 49 | + boolean negate = permission.startsWith("!"); |
| 50 | + if (negate) { |
| 51 | + permission = permission.substring(1); |
| 52 | + } |
| 53 | + |
| 54 | + // Online fast path (and best context accuracy) |
| 55 | + Player player = Bukkit.getPlayer(uuid); |
| 56 | + if (player != null) { |
| 57 | + boolean has = player.hasPermission(permission); |
| 58 | + return negate ? !has : has; |
| 59 | + } |
| 60 | + |
| 61 | + // Offline: do NOT block main thread |
| 62 | + if (Bukkit.isPrimaryThread()) { |
| 63 | + // If you want: plugin.getLogger().fine(...) here, but you don't have plugin in |
| 64 | + // this class right now. |
| 65 | + return negate; // treat missing as false, so negation returns true? Usually NOT desired. |
| 66 | + // I'd recommend: return false; (see note below) |
| 67 | + } |
| 68 | + |
| 69 | + // We're async here, safe to wait briefly |
23 | 70 | User user = api.getUserManager().getUser(uuid); |
24 | 71 | if (user == null) { |
25 | | - CompletableFuture<User> loadedUser = api.getUserManager().loadUser(uuid); |
26 | 72 | try { |
27 | | - user = loadedUser.get(10, TimeUnit.SECONDS); |
28 | | - } catch (InterruptedException | ExecutionException | TimeoutException e) { |
29 | | - e.printStackTrace(); |
| 73 | + user = api.getUserManager().loadUser(uuid).get(10, TimeUnit.SECONDS); |
| 74 | + } catch (Exception e) { |
30 | 75 | return false; |
31 | 76 | } |
32 | 77 | } |
33 | | - return user.getCachedData().getPermissionData().checkPermission(permission).asBoolean(); |
| 78 | + |
| 79 | + boolean has = checkUserPermission(user, permission, null); |
| 80 | + return negate ? !has : has; |
34 | 81 | } |
35 | 82 |
|
36 | | - public void load(AdvancedCorePlugin plugin) { |
37 | | - RegisteredServiceProvider<LuckPerms> provider = Bukkit.getServicesManager().getRegistration(LuckPerms.class); |
38 | | - if (provider != null) { |
39 | | - api = provider.getProvider(); |
40 | | - plugin.getLogger().info("Loaded LuckPerms hook!"); |
| 83 | + /** |
| 84 | + * Async permission check for offline users. Safe to call from the main thread. |
| 85 | + */ |
| 86 | + public CompletableFuture<Boolean> hasPermissionAsync(UUID uuid, String permission) { |
| 87 | + if (api == null) { |
| 88 | + return CompletableFuture.completedFuture(false); |
41 | 89 | } |
| 90 | + |
| 91 | + boolean negate = permission.startsWith("!"); |
| 92 | + if (negate) { |
| 93 | + permission = permission.substring(1); |
| 94 | + } |
| 95 | + |
| 96 | + // Online fast path |
| 97 | + Player player = Bukkit.getPlayer(uuid); |
| 98 | + if (player != null) { |
| 99 | + boolean has = player.hasPermission(permission); |
| 100 | + return CompletableFuture.completedFuture(negate ? !has : has); |
| 101 | + } |
| 102 | + |
| 103 | + final String permFinal = permission; |
| 104 | + return api.getUserManager().loadUser(uuid).thenApply(user -> { |
| 105 | + if (user == null) { |
| 106 | + return false; |
| 107 | + } |
| 108 | + boolean has = checkUserPermission(user, permFinal, null); |
| 109 | + return negate ? !has : has; |
| 110 | + }); |
42 | 111 | } |
43 | 112 |
|
44 | | - public boolean luckpermsApiLoaded() { |
45 | | - return api != null; |
| 113 | + private boolean checkUserPermission(User user, String permission, Player playerContext) { |
| 114 | + QueryOptions options; |
| 115 | + |
| 116 | + if (playerContext != null) { |
| 117 | + options = api.getContextManager().getQueryOptions(playerContext); |
| 118 | + } else { |
| 119 | + options = api.getContextManager().getStaticQueryOptions(); |
| 120 | + } |
| 121 | + |
| 122 | + return user.getCachedData().getPermissionData(options).checkPermission(permission).asBoolean(); |
46 | 123 | } |
47 | 124 | } |
0 commit comments