Skip to content

Commit bc3b04b

Browse files
authored
Merge pull request #604 from Multiverse/feat/placeholders
Add PlaceholderAPI placeholders expansion
2 parents 745fc48 + ab5507d commit bc3b04b

File tree

8 files changed

+223
-2
lines changed

8 files changed

+223
-2
lines changed

build.gradle

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ repositories {
1212
url = uri('https://repo.codemc.org/repository/maven-releases')
1313
}
1414

15+
maven {
16+
name = "helpchatRepoReleases"
17+
url = uri("https://repo.helpch.at/releases/")
18+
}
19+
1520
maven {
1621
name = 'benwoo1110'
1722
url = uri('https://repo.c0ding.party/multiverse-beta')
@@ -45,6 +50,9 @@ dependencies {
4550
// Caching
4651
shadowed("com.github.ben-manes.caffeine:caffeine:3.2.0")
4752

53+
// PlaceholderAPI
54+
externalPlugin 'me.clip:placeholderapi:2.11.6'
55+
4856
// Luckperms for group context
4957
compileOnly 'net.luckperms:api:5.4'
5058

src/main/java/org/mvplugins/multiverse/inventories/MultiverseInventories.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,13 +111,14 @@ public final void onEnable() {
111111
this.setUpLocales();
112112
this.registerCommands();
113113
this.registerDestinations();
114-
this.setupMetrics();
115114

116115
// Hook plugins that can be imported from
117116
this.hookImportables();
118117

119118
// Init other extensions
120119
this.hookLuckPerms();
120+
this.loadPlaceholderApiIntegration();
121+
this.setupMetrics();
121122
this.dupingPatch = InventoriesDupingPatch.enableDupingPatch(this);
122123
this.playerNamesMapperProvider.get().loadMap();
123124

@@ -185,6 +186,22 @@ private void hookLuckPerms() {
185186
});
186187
}
187188

189+
/**
190+
* Setup placeholder api hook
191+
*/
192+
private void loadPlaceholderApiIntegration() {
193+
if (!inventoriesConfig.get().getRegisterPapiHook()) {
194+
return;
195+
}
196+
if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) {
197+
Try.run(() -> serviceLocator.getService(PlaceholderExpansionHook.class))
198+
.onFailure(e -> {
199+
Logging.severe("Failed to load PlaceholderAPI integration.");
200+
e.printStackTrace();
201+
});
202+
}
203+
}
204+
188205
/**
189206
* Setup bstats Metrics.
190207
*/
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
package org.mvplugins.multiverse.inventories;
2+
3+
import com.google.common.collect.Lists;
4+
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
5+
import org.bukkit.Bukkit;
6+
import org.bukkit.OfflinePlayer;
7+
import org.bukkit.World;
8+
import org.bukkit.entity.Player;
9+
import org.jetbrains.annotations.NotNull;
10+
import org.jetbrains.annotations.Nullable;
11+
import org.jvnet.hk2.annotations.Service;
12+
import org.mvplugins.multiverse.core.utils.REPatterns;
13+
import org.mvplugins.multiverse.core.utils.StringFormatter;
14+
import org.mvplugins.multiverse.external.jakarta.annotation.PostConstruct;
15+
import org.mvplugins.multiverse.external.jakarta.inject.Inject;
16+
import org.mvplugins.multiverse.inventories.profile.group.WorldGroup;
17+
import org.mvplugins.multiverse.inventories.profile.group.WorldGroupManager;
18+
19+
import java.util.List;
20+
import java.util.Objects;
21+
22+
@Service
23+
final class PlaceholderExpansionHook extends PlaceholderExpansion {
24+
25+
private final MultiverseInventories plugin;
26+
private final WorldGroupManager worldGroupManager;
27+
28+
@Inject
29+
PlaceholderExpansionHook(@NotNull MultiverseInventories plugin, @NotNull WorldGroupManager worldGroupManager) {
30+
this.plugin = plugin;
31+
this.worldGroupManager = worldGroupManager;
32+
}
33+
34+
@PostConstruct
35+
@Override
36+
public boolean register() {
37+
return super.register();
38+
}
39+
40+
@NotNull
41+
@Override
42+
public String getIdentifier() {
43+
return "multiverse-inventories";
44+
}
45+
46+
@NotNull
47+
@Override
48+
public String getAuthor() {
49+
return StringFormatter.joinAnd(plugin.getDescription().getAuthors());
50+
}
51+
52+
@NotNull
53+
@Override
54+
public String getVersion() {
55+
return plugin.getDescription().getVersion();
56+
}
57+
58+
@Override
59+
public @Nullable String onRequest(OfflinePlayer offlinePlayer, @NotNull String params) {
60+
List<String> paramsArray = Lists.newArrayList(REPatterns.UNDERSCORE.split(params));
61+
if (paramsArray.isEmpty() || paramsArray.size() < 2) {
62+
warning("Placeholder has too little parameters: " + params);
63+
return null;
64+
}
65+
66+
return switch (paramsArray.get(0)) {
67+
case "world" -> worldPlaceholders(offlinePlayer, paramsArray);
68+
case "group" -> groupPlaceholders(offlinePlayer, paramsArray);
69+
default -> {
70+
warning("Unknown placeholder: " + paramsArray.get(0));
71+
yield null;
72+
}
73+
};
74+
}
75+
76+
private String worldPlaceholders(OfflinePlayer offlinePlayer, List<String> paramsArray) {
77+
String world = null;
78+
if (paramsArray.size() > 2) {
79+
world = paramsArray.get(paramsArray.size() - 1);
80+
}
81+
if (offlinePlayer instanceof Player player) {
82+
world = player.getWorld().getName();
83+
}
84+
85+
if (world == null) {
86+
warning("Please specify a world name to use with this placeholder.");
87+
return null;
88+
}
89+
90+
return switch (paramsArray.get(1)) {
91+
case "groups" -> StringFormatter.join(worldGroupManager.getGroupsForWorld(world).stream()
92+
.map(WorldGroup::getName)
93+
.toList(), ", ");
94+
case "groupcount" -> String.valueOf(worldGroupManager.getGroupsForWorld(world).size());
95+
default -> {
96+
warning("Unknown world placeholder arg: " + paramsArray.get(1));
97+
yield null;
98+
}
99+
};
100+
}
101+
102+
private String groupPlaceholders(OfflinePlayer offlinePlayer, List<String> paramsArray) {
103+
WorldGroup group = null;
104+
if (paramsArray.size() > 2) {
105+
group = worldGroupManager.getGroup(paramsArray.get(paramsArray.size() - 1));
106+
if (group == null) {
107+
warning("Group not found: " + paramsArray.get(paramsArray.size() - 1));
108+
return null;
109+
}
110+
} else if (offlinePlayer instanceof Player player) {
111+
group = worldGroupManager.getGroupsForWorld(player.getWorld().getName())
112+
.stream()
113+
.findFirst()
114+
.orElse(null);
115+
if (group == null) {
116+
return "ungrouped world";
117+
}
118+
}
119+
120+
if (group == null) {
121+
warning("Please specify a group name to use with this placeholder.");
122+
return null;
123+
}
124+
125+
return getGroupPlaceholderValue(group, paramsArray.get(1));
126+
}
127+
128+
private String getGroupPlaceholderValue(WorldGroup worldGroup, String placeholder) {
129+
return switch (placeholder) {
130+
case "name" -> worldGroup.getName();
131+
case "worlds" -> StringFormatter.join(worldGroup.getWorlds(), ", ");
132+
case "shares" -> StringFormatter.join(worldGroup.getShares().toStringList(), ", ");
133+
case "players" -> StringFormatter.join(worldGroup.getWorlds().stream()
134+
.map(Bukkit::getWorld)
135+
.filter(Objects::nonNull)
136+
.flatMap(world -> world.getPlayers().stream().map(Player::getName))
137+
.toList(), ", ");
138+
case "playercount" -> worldGroup.getWorlds().stream()
139+
.map(Bukkit::getWorld)
140+
.filter(Objects::nonNull)
141+
.map(World::getPlayers)
142+
.map(List::size)
143+
.reduce(Integer::sum)
144+
.orElse(0)
145+
.toString();
146+
default -> {
147+
warning("Unknown group placeholder arg: " + placeholder);
148+
yield null;
149+
}
150+
};
151+
}
152+
}

src/main/java/org/mvplugins/multiverse/inventories/config/InventoriesConfig.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.mvplugins.multiverse.inventories.config;
22

33
import com.dumptruckman.minecraft.util.Logging;
4+
import org.jetbrains.annotations.ApiStatus;
45
import org.jvnet.hk2.annotations.Service;
56
import org.mvplugins.multiverse.core.config.handle.CommentedConfigurationHandle;
67
import org.mvplugins.multiverse.core.config.handle.StringPropertyHandle;
@@ -255,6 +256,31 @@ public Try<Void> setGlobalProfileCacheExpiry(int globalProfileCacheExpiry) {
255256
return this.configHandle.set(configNodes.globalProfileCacheExpiry, globalProfileCacheExpiry);
256257
}
257258

259+
/**
260+
* Get the value of registerPapiHook
261+
*
262+
* @return The value of registerPapiHook
263+
*
264+
* @since 5.1
265+
*/
266+
@ApiStatus.AvailableSince("5.1")
267+
public boolean getRegisterPapiHook() {
268+
return this.configHandle.get(configNodes.registerPapiHook);
269+
}
270+
271+
/**
272+
* Sets the value of registerPapiHook
273+
*
274+
* @param registerPapiHook The value of registerPapiHook
275+
* @return The result of the operation
276+
*
277+
* @since 5.1
278+
*/
279+
@ApiStatus.AvailableSince("5.1")
280+
public Try<Void> setRegisterPapiHook(boolean registerPapiHook) {
281+
return this.configHandle.set(configNodes.registerPapiHook, registerPapiHook);
282+
}
283+
258284
/**
259285
* Tells whether this is the first time the plugin has run as set by a config flag.
260286
*

src/main/java/org/mvplugins/multiverse/inventories/config/InventoriesConfigNodes.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,18 @@ public Object serialize(Shares sharables, Class<Shares> aClass) {
224224
.name("global-profile-cache-expiry")
225225
.build());
226226

227+
private final ConfigHeaderNode miscHeader = node(ConfigHeaderNode.builder("misc")
228+
.comment("")
229+
.comment("")
230+
.build());
231+
232+
final ConfigNode<Boolean> registerPapiHook = node(ConfigNode.builder("misc.register-papi-hook", Boolean.class)
233+
.comment("This config option defines whether or not Multiverse should register the PlaceholderAPI hook.")
234+
.comment("This only applies if PlaceholderAPI is installed.")
235+
.defaultValue(true)
236+
.name("register-papi-hook")
237+
.build());
238+
227239
final ConfigNode<Boolean> firstRun = node(ConfigNode.builder("first-run", Boolean.class)
228240
.comment("")
229241
.comment("")

src/main/resources/plugin.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ api-version: 1.13
55
authors: ['dumptruckman', 'benwoo1110']
66
website: 'https://dev.bukkit.org/projects/multiverse-inventories'
77
depend: ['Multiverse-Core']
8-
softdepend: [LuckPerms, MultiInv, WorldInventories, PerWorldInventory]
8+
softdepend: [LuckPerms, PlaceholderAPI, MultiInv, WorldInventories, PerWorldInventory]

src/test/resources/config/fresh_config.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,8 @@ performance:
2525
global-profile-cache-size: 500
2626
global-profile-cache-expiry: 60
2727

28+
misc:
29+
register-papi-hook: true
30+
2831
first-run: true
2932
version: 5.0

src/test/resources/config/migrated_config.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,8 @@ performance:
2626
global-profile-cache-size: 500
2727
global-profile-cache-expiry: 60
2828

29+
misc:
30+
register-papi-hook: true
31+
2932
first-run: true
3033
version: 5.0

0 commit comments

Comments
 (0)