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()); + } + +}