diff --git a/src/main/java/world/bentobox/bentobox/BentoBox.java b/src/main/java/world/bentobox/bentobox/BentoBox.java
index cfd8f5506..a2044e1eb 100644
--- a/src/main/java/world/bentobox/bentobox/BentoBox.java
+++ b/src/main/java/world/bentobox/bentobox/BentoBox.java
@@ -30,6 +30,7 @@
import world.bentobox.bentobox.managers.AddonsManager;
import world.bentobox.bentobox.managers.CommandsManager;
import world.bentobox.bentobox.managers.FlagsManager;
+import world.bentobox.bentobox.managers.GameModePlaceholderManager;
import world.bentobox.bentobox.managers.HooksManager;
import world.bentobox.bentobox.managers.IslandDeletionManager;
import world.bentobox.bentobox.managers.IslandWorldManager;
@@ -154,6 +155,10 @@ public void onEnable(){
addonsManager.loadAddons();
// Enable addons
addonsManager.enableAddons();
+
+ // Register default gamemode placeholders
+ GameModePlaceholderManager gmp = new GameModePlaceholderManager(this);
+ addonsManager.getGameModeAddons().forEach(gmp::registerGameModePlaceholders);
getServer().getScheduler().runTask(instance, () -> {
// Register Listeners
diff --git a/src/main/java/world/bentobox/bentobox/api/placeholders/placeholderapi/BasicPlaceholderExpansion.java b/src/main/java/world/bentobox/bentobox/api/placeholders/placeholderapi/BasicPlaceholderExpansion.java
index d80d33ada..4af25ebf9 100644
--- a/src/main/java/world/bentobox/bentobox/api/placeholders/placeholderapi/BasicPlaceholderExpansion.java
+++ b/src/main/java/world/bentobox/bentobox/api/placeholders/placeholderapi/BasicPlaceholderExpansion.java
@@ -49,4 +49,14 @@ public String onPlaceholderRequest(Player p, String placeholder) {
}
return null;
}
+
+ /**
+ * Checks if a placeholder with this name is already registered
+ * @param placeholder - name of placeholder
+ * @return true if a placeholder with this name is already registered
+ * @since 1.4.0
+ */
+ public boolean isPlaceholder(@NonNull String placeholder) {
+ return placeholders.containsKey(placeholder);
+ }
}
\ No newline at end of file
diff --git a/src/main/java/world/bentobox/bentobox/hooks/PlaceholderAPIHook.java b/src/main/java/world/bentobox/bentobox/hooks/PlaceholderAPIHook.java
index 33ac9e877..9e81f4bda 100644
--- a/src/main/java/world/bentobox/bentobox/hooks/PlaceholderAPIHook.java
+++ b/src/main/java/world/bentobox/bentobox/hooks/PlaceholderAPIHook.java
@@ -107,4 +107,15 @@ public void unregisterPlaceholder(@NonNull Addon addon, @NonNull String placehol
public void registerAddonPlaceholder(Addon addon, String placeholder, PlaceholderReplacer replacer) {
registerPlaceholder(addon, placeholder, replacer);
}
+
+ /**
+ * Checks if a placeholder with this name is already registered
+ * @param addon the addon, not null
+ * @param placeholder - name of placeholder
+ * @return true if a placeholder with this name is already registered
+ * @since 1.4.0
+ */
+ public boolean isPlaceholder(@NonNull Addon addon, @NonNull String placeholder) {
+ return addonsExpansions.containsKey(addon) ? addonsExpansions.get(addon).isPlaceholder(placeholder) : false;
+ }
}
diff --git a/src/main/java/world/bentobox/bentobox/lists/GameModePlaceholders.java b/src/main/java/world/bentobox/bentobox/lists/GameModePlaceholders.java
new file mode 100644
index 000000000..63eaef882
--- /dev/null
+++ b/src/main/java/world/bentobox/bentobox/lists/GameModePlaceholders.java
@@ -0,0 +1,22 @@
+package world.bentobox.bentobox.lists;
+
+public enum GameModePlaceholders {
+
+ WORLD_FRIENDLY_NAME("world-friendlyname"),
+ ISLAND_DISTANCE("island-distance"),
+ ISLAND_PROTECTION_RANGE("island-protection-range"),
+ ISLAND_OWNER("island-owner"),
+ ISLAND_CREATION_DATE("island-creation-date"),
+ ISLAND_SPAWNPOINT("island-spawnpoint"),
+ ISLAND_NAME("island-name");
+
+ private String placeholder;
+
+ GameModePlaceholders(String placeholder) {
+ this.placeholder = placeholder;
+ }
+
+ public String getPlaceholder() {
+ return placeholder;
+ }
+}
diff --git a/src/main/java/world/bentobox/bentobox/managers/GameModePlaceholderManager.java b/src/main/java/world/bentobox/bentobox/managers/GameModePlaceholderManager.java
new file mode 100644
index 000000000..a220621e6
--- /dev/null
+++ b/src/main/java/world/bentobox/bentobox/managers/GameModePlaceholderManager.java
@@ -0,0 +1,84 @@
+package world.bentobox.bentobox.managers;
+
+import world.bentobox.bentobox.BentoBox;
+import world.bentobox.bentobox.api.addons.GameModeAddon;
+import world.bentobox.bentobox.api.placeholders.PlaceholderReplacer;
+import world.bentobox.bentobox.api.user.User;
+import world.bentobox.bentobox.database.objects.Island;
+import world.bentobox.bentobox.lists.GameModePlaceholders;
+import world.bentobox.bentobox.util.Util;
+
+import java.text.DateFormat;
+import java.time.Instant;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.EnumMap;
+import java.util.Map;
+
+/**
+ *
+ * Registers default placeholders for all GameModes. Will not overwrite any that the gamemode addon itself implements.
+ * @author tastybento
+ *
+ */
+public class GameModePlaceholderManager {
+
+ private BentoBox plugin;
+
+ public GameModePlaceholderManager(BentoBox plugin) {
+ super();
+ this.plugin = plugin;
+ }
+
+ public void registerGameModePlaceholders(GameModeAddon addon) {
+ String prefix = addon.getDescription().getName().toLowerCase();
+ Map placeholders = new EnumMap<>(GameModePlaceholders.class);
+ Arrays.stream(GameModePlaceholders.values()).forEach(placeholder -> placeholders.put(placeholder, prefix + "-" + placeholder.getPlaceholder()));
+
+ // Register placeholders only if they have not already been registered by the addon itself
+ placeholders.entrySet().stream().filter(en -> !plugin.getPlaceholdersManager().isPlaceholder(addon, en.getValue()))
+ .forEach(en -> plugin.getPlaceholdersManager().registerPlaceholder(en.getValue(), new DefaultPlaceholder(addon, en.getKey())));
+ }
+}
+
+class DefaultPlaceholder implements PlaceholderReplacer {
+ private final GameModeAddon addon;
+ private final GameModePlaceholders type;
+ public DefaultPlaceholder(GameModeAddon addon, GameModePlaceholders type) {
+ super();
+ this.addon = addon;
+ this.type = type;
+ }
+ /* (non-Javadoc)
+ * @see world.bentobox.bentobox.api.placeholders.PlaceholderReplacer#onReplace(world.bentobox.bentobox.api.user.User)
+ */
+ @Override
+ public String onReplace(User user) {
+ if (user == null) {
+ return "";
+ }
+ Island island = addon.getIslands().getIsland(addon.getOverWorld(), user);
+ switch (type) {
+ case WORLD_FRIENDLY_NAME:
+ return addon.getWorldSettings().getFriendlyName();
+ case ISLAND_CREATION_DATE:
+ return island == null ? "" : DateFormat.getInstance().format(Date.from(Instant.ofEpochMilli(island.getCreatedDate())));
+ case ISLAND_DISTANCE:
+ return String.valueOf(addon.getWorldSettings().getIslandDistance());
+ case ISLAND_NAME:
+ return island == null ? "" : (island.getName() == null ? "" : island.getName());
+ case ISLAND_OWNER:
+ return island == null ? "" : addon.getPlayers().getName(island.getOwner());
+ case ISLAND_PROTECTION_RANGE:
+ return island == null ? "" : String.valueOf(island.getProtectionRange());
+ case ISLAND_SPAWNPOINT:
+ return island == null ? "" : Util.xyz(island.getCenter().toVector());
+ default:
+ return "";
+ }
+ }
+
+}
+
+
+
diff --git a/src/main/java/world/bentobox/bentobox/managers/PlaceholdersManager.java b/src/main/java/world/bentobox/bentobox/managers/PlaceholdersManager.java
index a9fe0c1e8..f3b7ec5ef 100644
--- a/src/main/java/world/bentobox/bentobox/managers/PlaceholdersManager.java
+++ b/src/main/java/world/bentobox/bentobox/managers/PlaceholdersManager.java
@@ -1,7 +1,5 @@
package world.bentobox.bentobox.managers;
-import com.mongodb.lang.NonNull;
-import com.mongodb.lang.Nullable;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.addons.Addon;
import world.bentobox.bentobox.api.placeholders.PlaceholderReplacer;
@@ -9,6 +7,9 @@
import java.util.Optional;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+
/**
* Manages placeholder integration.
*
@@ -85,4 +86,15 @@ public void unregisterPlaceholder(@Nullable Addon addon, @NonNull String placeho
private Optional getPlaceholderAPIHook() {
return plugin.getHooks().getHook("PlaceholderAPI").map(hook -> (PlaceholderAPIHook) hook);
}
+
+ /**
+ * Checks if a placeholder with this name is already registered
+ * @param addon the addon, not null
+ * @param placeholder - name of placeholder
+ * @return true if a placeholder with this name is already registered
+ * @since 1.4.0
+ */
+ public boolean isPlaceholder(@NonNull Addon addon, @NonNull String placeholder) {
+ return addon == null ? false : getPlaceholderAPIHook().map(h -> h.isPlaceholder(addon, placeholder)).orElse(false);
+ }
}
diff --git a/src/test/java/world/bentobox/bentobox/managers/AddonsManagerTest.java b/src/test/java/world/bentobox/bentobox/managers/AddonsManagerTest.java
index 4c3e57b5b..2c68a9b1f 100644
--- a/src/test/java/world/bentobox/bentobox/managers/AddonsManagerTest.java
+++ b/src/test/java/world/bentobox/bentobox/managers/AddonsManagerTest.java
@@ -16,7 +16,7 @@
@PrepareForTest( { BentoBox.class} )
public class AddonsManagerTest {
- private static BentoBox plugin;
+ private BentoBox plugin;
@Before
public void setup() {
diff --git a/src/test/java/world/bentobox/bentobox/managers/GameModePlaceholderManagerTest.java b/src/test/java/world/bentobox/bentobox/managers/GameModePlaceholderManagerTest.java
new file mode 100644
index 000000000..423926cfd
--- /dev/null
+++ b/src/test/java/world/bentobox/bentobox/managers/GameModePlaceholderManagerTest.java
@@ -0,0 +1,88 @@
+/**
+ *
+ */
+package world.bentobox.bentobox.managers;
+
+import static org.mockito.Mockito.when;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import world.bentobox.bentobox.BentoBox;
+import world.bentobox.bentobox.api.addons.AddonDescription;
+import world.bentobox.bentobox.api.addons.GameModeAddon;
+
+/**
+ * @author tastybento
+ *
+ */
+@RunWith(PowerMockRunner.class)
+@PrepareForTest( {BentoBox.class} )
+public class GameModePlaceholderManagerTest {
+
+ @Mock
+ private BentoBox plugin;
+ @Mock
+ private GameModeAddon addon;
+ @Mock
+ private PlaceholdersManager pm;
+
+
+
+ private GameModePlaceholderManager gpm;
+
+ /**
+ * @throws java.lang.Exception
+ */
+ @Before
+ public void setUp() throws Exception {
+ gpm = new GameModePlaceholderManager(plugin);
+ // Addon
+ @NonNull
+ AddonDescription desc = new AddonDescription.Builder("main", "bskyblock", "1.0").build();
+ when(addon.getDescription()).thenReturn(desc);
+
+ when(plugin.getPlaceholdersManager()).thenReturn(pm);
+ // No placeholders registered yet
+ when(pm.isPlaceholder(Mockito.any(), Mockito.any())).thenReturn(false);
+ }
+
+ /**
+ * @throws java.lang.Exception
+ */
+ @After
+ public void tearDown() throws Exception {
+ }
+
+ /**
+ * Test method for {@link world.bentobox.bentobox.managers.GameModePlaceholderManager#registerGameModePlaceholders(world.bentobox.bentobox.api.addons.GameModeAddon)}.
+ */
+ @Test
+ public void testRegisterGameModePlaceholdersAllDefaults() {
+ gpm.registerGameModePlaceholders(addon);
+ // 7 registrations for this addon
+ Mockito.verify(pm, Mockito.times(7)).registerPlaceholder(Mockito.anyString(), Mockito.any());
+ }
+
+ /**
+ * Test method for {@link world.bentobox.bentobox.managers.GameModePlaceholderManager#registerGameModePlaceholders(world.bentobox.bentobox.api.addons.GameModeAddon)}.
+ */
+ @Test
+ public void testRegisterGameModePlaceholdersSomePreregistered() {
+ // Some duplicates
+ when(pm.isPlaceholder(Mockito.any(), Mockito.any())).thenReturn(false, true, true, false, false, true, false);
+
+ gpm.registerGameModePlaceholders(addon);
+
+ // 3 registrations for this addon
+ Mockito.verify(pm, Mockito.times(4)).registerPlaceholder(Mockito.anyString(), Mockito.any());
+ }
+
+}