Skip to content

Commit 8166461

Browse files
authored
feat: LuckPerms clan contexts (#1)
1 parent 35065bf commit 8166461

11 files changed

Lines changed: 194 additions & 0 deletions

File tree

pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,12 @@
250250
<version>1.28.0</version>
251251
<scope>provided</scope>
252252
</dependency>
253+
<dependency>
254+
<groupId>net.luckperms</groupId>
255+
<artifactId>api</artifactId>
256+
<version>5.4</version>
257+
<scope>provided</scope>
258+
</dependency>
253259
<dependency>
254260
<groupId>biz.princeps</groupId>
255261
<artifactId>landlord-latest</artifactId>

src/main/java/net/sacredlabyrinth/phaed/simpleclans/Clan.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1015,6 +1015,7 @@ public void addPlayerToClan(ClanPlayer cp) {
10151015
if (player != null) {
10161016
SimpleClans.getInstance().getClanManager().updateDisplayName(player);
10171017
}
1018+
SimpleClans.getInstance().signalContextUpdate(player);
10181019
Bukkit.getPluginManager().callEvent(new PlayerJoinedClanEvent(this, cp));
10191020
}
10201021

@@ -1054,6 +1055,7 @@ public void removePlayerFromClan(UUID playerUniqueId) {
10541055
if (matched != null) {
10551056
SimpleClans.getInstance().getClanManager().updateDisplayName(matched);
10561057
}
1058+
SimpleClans.getInstance().signalContextUpdate(matched);
10571059
Bukkit.getPluginManager().callEvent(new PlayerKickedClanEvent(this, cp));
10581060
}
10591061

@@ -1076,6 +1078,7 @@ public void promote(UUID playerUniqueId) {
10761078

10771079
// add clan permission
10781080
SimpleClans.getInstance().getPermissionsManager().addClanPermissions(cp);
1081+
SimpleClans.getInstance().signalContextUpdate(cp.toPlayer());
10791082
Bukkit.getPluginManager().callEvent(new PlayerPromoteEvent(this, cp));
10801083
}
10811084

@@ -1097,6 +1100,7 @@ public void demote(UUID playerUniqueId) {
10971100

10981101
// add clan permission
10991102
SimpleClans.getInstance().getPermissionsManager().addClanPermissions(cp);
1103+
SimpleClans.getInstance().signalContextUpdate(cp.toPlayer());
11001104
Bukkit.getPluginManager().callEvent(new PlayerDemoteEvent(this, cp));
11011105
}
11021106

@@ -1418,6 +1422,7 @@ public void disband(@Nullable CommandSender sender, boolean announce, boolean fo
14181422
cp.setLeader(false);
14191423
}
14201424
}
1425+
SimpleClans.getInstance().signalContextUpdate(this);
14211426

14221427
Bukkit.getPluginManager().callEvent(new DisbandClanEvent(sender, this));
14231428
clans.remove(this);

src/main/java/net/sacredlabyrinth/phaed/simpleclans/SimpleClans.java

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import co.aikar.commands.BukkitCommandIssuer;
44
import net.sacredlabyrinth.phaed.simpleclans.commands.SCCommandManager;
5+
import net.sacredlabyrinth.phaed.simpleclans.hooks.luckperms.LuckPermsContextHook;
56
import net.sacredlabyrinth.phaed.simpleclans.hooks.papi.SimpleClansExpansion;
67
import net.sacredlabyrinth.phaed.simpleclans.language.LanguageResource;
78
import net.sacredlabyrinth.phaed.simpleclans.listeners.*;
@@ -60,6 +61,7 @@ public class SimpleClans extends JavaPlugin {
6061
private ProtectionManager protectionManager;
6162
private ChatManager chatManager;
6263
private ProxyManager proxyManager;
64+
private LuckPermsContextHook luckPermsContextHook;
6365
private boolean hasUUID;
6466
private static final Pattern ACF_PLACEHOLDER_PATTERN = Pattern.compile("\\{(?<key>[a-zA-Z]+?)}");
6567

@@ -127,6 +129,7 @@ public void onEnable() {
127129
startTasks();
128130
startMetrics();
129131
hookIntoPAPI();
132+
hookIntoLuckPerms();
130133
new UpdateChecker(this).check();
131134
}
132135

@@ -155,6 +158,42 @@ private void hookIntoPAPI() {
155158
}
156159
}
157160

161+
/**
162+
* Registers or unregisters the LuckPerms hook, according to the plugin availability
163+
* and to the current settings. Can be called at any time, to apply setting changes.
164+
*/
165+
public void hookIntoLuckPerms() {
166+
boolean enabled = getPluginManager().isPluginEnabled("LuckPerms")
167+
&& settingsManager.is(PERMISSIONS_LUCKPERMS_CONTEXTS);
168+
169+
if (enabled && luckPermsContextHook == null) {
170+
getLogger().info("LuckPerms found. Registering contexts...");
171+
luckPermsContextHook = new LuckPermsContextHook(this);
172+
luckPermsContextHook.register();
173+
} else if (!enabled && luckPermsContextHook != null) {
174+
luckPermsContextHook.unregister();
175+
luckPermsContextHook = null;
176+
}
177+
}
178+
179+
/**
180+
* Invalidates the LuckPerms contexts of an online player, if the hook is enabled
181+
*/
182+
public void signalContextUpdate(@Nullable Player player) {
183+
if (luckPermsContextHook != null && player != null) {
184+
luckPermsContextHook.signalContextUpdate(player);
185+
}
186+
}
187+
188+
/**
189+
* Invalidates the LuckPerms contexts of all online members of a clan, if the hook is enabled
190+
*/
191+
public void signalContextUpdate(@NotNull Clan clan) {
192+
if (luckPermsContextHook != null) {
193+
luckPermsContextHook.signalContextUpdate(clan);
194+
}
195+
}
196+
158197
private void startMetrics() {
159198
Metrics metrics = new Metrics(this, 7131);
160199
SettingsManager sm = getSettingsManager();
@@ -198,6 +237,9 @@ private void startTasks() {
198237

199238
@Override
200239
public void onDisable() {
240+
if (luckPermsContextHook != null) {
241+
luckPermsContextHook.unregister();
242+
}
201243
if (getSettingsManager().is(PERFORMANCE_SAVE_PERIODICALLY)) {
202244
getStorageManager().saveModified();
203245
}

src/main/java/net/sacredlabyrinth/phaed/simpleclans/commands/clan/LeaderCommands.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ public void trust(Player player, Clan clan, @Conditions("same_clan") @Name("memb
163163
player.getName()));
164164
trustedInput.setTrusted(true);
165165
storage.updateClanPlayer(trustedInput);
166+
plugin.signalContextUpdate(trustedInput.toPlayer());
166167
}
167168

168169
@Subcommand("%untrust")
@@ -188,6 +189,7 @@ public void untrust(Player player, Clan clan, @Conditions("same_clan") @Name("me
188189
player.getName()));
189190
trustedInput.setTrusted(false);
190191
storage.updateClanPlayer(trustedInput);
192+
plugin.signalContextUpdate(trustedInput.toPlayer());
191193
}
192194

193195
@Subcommand("%rename")

src/main/java/net/sacredlabyrinth/phaed/simpleclans/commands/staff/StaffCommands.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,11 @@ public void reload(CommandSender sender) {
119119
settings.loadAndSave();
120120
storage.importFromDatabase();
121121
permissions.loadPermissions();
122+
plugin.hookIntoLuckPerms();
122123

123124
for (Clan clan : cm.getClans()) {
124125
permissions.updateClanPermissions(clan);
126+
plugin.signalContextUpdate(clan);
125127
}
126128
Bukkit.getPluginManager().callEvent(new ReloadEvent(sender));
127129

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package net.sacredlabyrinth.phaed.simpleclans.hooks.luckperms;
2+
3+
import net.luckperms.api.context.ContextCalculator;
4+
import net.luckperms.api.context.ContextConsumer;
5+
import net.luckperms.api.context.ContextSet;
6+
import net.luckperms.api.context.ImmutableContextSet;
7+
import net.sacredlabyrinth.phaed.simpleclans.Clan;
8+
import net.sacredlabyrinth.phaed.simpleclans.ClanPlayer;
9+
import net.sacredlabyrinth.phaed.simpleclans.Helper;
10+
import net.sacredlabyrinth.phaed.simpleclans.managers.ClanManager;
11+
import org.bukkit.entity.Player;
12+
import org.jetbrains.annotations.NotNull;
13+
14+
/**
15+
* Exposes clan membership as LuckPerms contexts, allowing permissions to be
16+
* granted by clan facts, without SimpleClans creating groups or nodes.
17+
* <p>
18+
* Provided contexts:
19+
* </p>
20+
* <ul>
21+
* <li>{@code simpleclans:in-clan} - true/false</li>
22+
* <li>{@code simpleclans:rank} - leader/trusted/member</li>
23+
* <li>{@code simpleclans:tag} - the clan tag, without colors, lowercased</li>
24+
* </ul>
25+
* Contexts are resolved for online players only.
26+
*/
27+
public class ClanContextCalculator implements ContextCalculator<Player> {
28+
29+
public static final String IN_CLAN_KEY = "simpleclans:in-clan";
30+
public static final String RANK_KEY = "simpleclans:rank";
31+
public static final String TAG_KEY = "simpleclans:tag";
32+
33+
private static final String LEADER = "leader";
34+
private static final String TRUSTED = "trusted";
35+
private static final String MEMBER = "member";
36+
37+
private final ClanManager clanManager;
38+
39+
public ClanContextCalculator(@NotNull ClanManager clanManager) {
40+
this.clanManager = clanManager;
41+
}
42+
43+
@Override
44+
public void calculate(@NotNull Player target, @NotNull ContextConsumer consumer) {
45+
ClanPlayer cp = clanManager.getClanPlayer(target.getUniqueId());
46+
Clan clan = cp != null ? cp.getClan() : null;
47+
48+
if (clan == null) {
49+
consumer.accept(IN_CLAN_KEY, "false");
50+
return;
51+
}
52+
53+
consumer.accept(IN_CLAN_KEY, "true");
54+
consumer.accept(RANK_KEY, getRank(cp));
55+
consumer.accept(TAG_KEY, Helper.cleanTag(clan.getTag()));
56+
}
57+
58+
@Override
59+
public @NotNull ContextSet estimatePotentialContexts() {
60+
ImmutableContextSet.Builder builder = ImmutableContextSet.builder();
61+
builder.add(IN_CLAN_KEY, "true");
62+
builder.add(IN_CLAN_KEY, "false");
63+
builder.add(RANK_KEY, LEADER);
64+
builder.add(RANK_KEY, TRUSTED);
65+
builder.add(RANK_KEY, MEMBER);
66+
67+
for (Clan clan : clanManager.getClans()) {
68+
builder.add(TAG_KEY, Helper.cleanTag(clan.getTag()));
69+
}
70+
71+
return builder.build();
72+
}
73+
74+
@NotNull
75+
private String getRank(@NotNull ClanPlayer cp) {
76+
if (cp.isLeader()) {
77+
return LEADER;
78+
}
79+
return cp.isTrusted() ? TRUSTED : MEMBER;
80+
}
81+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package net.sacredlabyrinth.phaed.simpleclans.hooks.luckperms;
2+
3+
import net.luckperms.api.LuckPerms;
4+
import net.luckperms.api.LuckPermsProvider;
5+
import net.sacredlabyrinth.phaed.simpleclans.Clan;
6+
import net.sacredlabyrinth.phaed.simpleclans.ClanPlayer;
7+
import net.sacredlabyrinth.phaed.simpleclans.SimpleClans;
8+
import org.bukkit.entity.Player;
9+
import org.jetbrains.annotations.NotNull;
10+
11+
/**
12+
* Registers the {@link ClanContextCalculator} in LuckPerms and signals it,
13+
* when clan data of an online player changes.
14+
*/
15+
public class LuckPermsContextHook {
16+
17+
private final LuckPerms luckPerms;
18+
private final ClanContextCalculator calculator;
19+
20+
public LuckPermsContextHook(@NotNull SimpleClans plugin) {
21+
luckPerms = LuckPermsProvider.get();
22+
calculator = new ClanContextCalculator(plugin.getClanManager());
23+
}
24+
25+
public void register() {
26+
luckPerms.getContextManager().registerCalculator(calculator);
27+
}
28+
29+
public void unregister() {
30+
luckPerms.getContextManager().unregisterCalculator(calculator);
31+
}
32+
33+
/**
34+
* Invalidates the cached contexts of a player
35+
*/
36+
public void signalContextUpdate(@NotNull Player player) {
37+
luckPerms.getContextManager().signalContextUpdate(player);
38+
}
39+
40+
/**
41+
* Invalidates the cached contexts of all online members of a clan
42+
*/
43+
public void signalContextUpdate(@NotNull Clan clan) {
44+
for (ClanPlayer cp : clan.getOnlineMembers()) {
45+
Player player = cp.toPlayer();
46+
if (player != null) {
47+
signalContextUpdate(player);
48+
}
49+
}
50+
}
51+
}

src/main/java/net/sacredlabyrinth/phaed/simpleclans/listeners/SCPlayerListener.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ public void onPlayerJoin(PlayerJoinEvent event) {
9696
}
9797

9898
plugin.getPermissionsManager().addClanPermissions(cp);
99+
plugin.signalContextUpdate(player);
99100
}
100101

101102
@EventHandler(priority = EventPriority.HIGHEST)

src/main/java/net/sacredlabyrinth/phaed/simpleclans/managers/ClanManager.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ public void createClan(Player player, String colorTag, String name) {
152152

153153
plugin.getRequestManager().deny(cp); // denies any previous invitation
154154
SimpleClans.getInstance().getPermissionsManager().updateClanPermissions(clan);
155+
SimpleClans.getInstance().signalContextUpdate(clan);
155156
SimpleClans.getInstance().getServer().getPluginManager().callEvent(new CreateClanEvent(clan));
156157
}
157158

@@ -493,6 +494,7 @@ public void ban(UUID uuid) {
493494

494495
plugin.getStorageManager().updateClanPlayer(cp);
495496
plugin.getStorageManager().updateClan(clan);
497+
plugin.signalContextUpdate(cp.toPlayer());
496498
}
497499
}
498500

src/main/java/net/sacredlabyrinth/phaed/simpleclans/managers/SettingsManager.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,7 @@ public enum ConfigField {
584584
================
585585
*/
586586
PERMISSIONS_AUTO_GROUP_GROUPNAME("permissions.auto-group-groupname", false),
587+
PERMISSIONS_LUCKPERMS_CONTEXTS("permissions.luckperms-contexts", false),
587588
/*
588589
================
589590
> Performance Settings

0 commit comments

Comments
 (0)