diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/AnchorCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/AnchorCommand.java index 1ed404c4..f3f8a9d5 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/AnchorCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/AnchorCommand.java @@ -17,10 +17,13 @@ import co.aikar.commands.annotation.Subcommand; import co.aikar.commands.annotation.Syntax; import com.onarandombox.MultiverseCore.MultiverseCore; import com.onarandombox.MultiverseCore.api.MultiverseWorld; -import com.onarandombox.MultiverseCore.commandtools.display.ColorAlternator; import com.onarandombox.MultiverseCore.commandtools.display.ContentCreator; -import com.onarandombox.MultiverseCore.commandtools.display.page.PageDisplay; import com.onarandombox.MultiverseCore.commandtools.contexts.PageFilter; +import com.onarandombox.MultiverseCore.displaytools.ColorAlternator; +import com.onarandombox.MultiverseCore.displaytools.ContentDisplay; +import com.onarandombox.MultiverseCore.displaytools.ContentFilter; +import com.onarandombox.MultiverseCore.displaytools.DisplayHandlers; +import com.onarandombox.MultiverseCore.displaytools.DisplaySettings; import com.onarandombox.MultiverseCore.utils.AnchorManager; import org.bukkit.ChatColor; import org.bukkit.Location; @@ -30,6 +33,7 @@ import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.Set; @@ -95,37 +99,38 @@ public class AnchorCommand extends MultiverseCoreCommand { public void onListAnchorCommand(@NotNull CommandSender sender, @NotNull PageFilter pageFilter) { - new PageDisplay().withSender(sender) - .withHeader(String.format("%s====[ Multiverse Anchor List ]====", ChatColor.LIGHT_PURPLE)) - .withCreator(buildAnchorList(sender)) - .withPageFilter(pageFilter) - .withColors(new ColorAlternator(ChatColor.YELLOW, ChatColor.DARK_AQUA)) - .build() - .runTaskAsynchronously(this.plugin); + new ContentDisplay.Builder>() + .sender(sender) + .header("%s====[ Multiverse Anchor List ]====", ChatColor.LIGHT_PURPLE) + .contents(buildAnchorList(sender)) + .emptyMessage("You do not any anchors set. See /mv anchors create to get started!") + .displayHandler(DisplayHandlers.PAGE_LIST) + .colorTool(ColorAlternator.with(ChatColor.YELLOW, ChatColor.DARK_AQUA)) + .filter(ContentFilter.getDefault()) + .setting(DisplaySettings.SHOW_PAGE, pageFilter.getPage()) + .display(this.plugin); } - private ContentCreator> buildAnchorList(@NotNull CommandSender sender) { - return () -> { - Set anchors = (sender instanceof Player) - ? this.anchorManager.getAnchors((Player) sender) - : this.anchorManager.getAllAnchors(); + private List buildAnchorList(@NotNull CommandSender sender) { + Set anchors = (sender instanceof Player) + ? this.anchorManager.getAnchors((Player) sender) + : this.anchorManager.getAllAnchors(); - List anchorContent = new ArrayList<>(); - for (String anchor : anchors) { - Location anchorLocation = this.anchorManager.getAnchorLocation(anchor); - World world = anchorLocation.getWorld(); // this.plugin.getMVWorldManager().getMVWorld(); + List anchorContent = new ArrayList<>(); + for (String anchor : anchors) { + Location anchorLocation = this.anchorManager.getAnchorLocation(anchor); + World world = anchorLocation.getWorld(); // this.plugin.getMVWorldManager().getMVWorld(); - String locationString = ChatColor.RED + "!!INVALID!!"; - if (world != null) { - MultiverseWorld mvWorld = this.plugin.getMVWorldManager().getMVWorld(world); - locationString = (mvWorld == null) - ? String.format("%s%s !!NOT MULTIVERSE WORLD!!", ChatColor.RED, world.getName()) - : String.format("%s - %s", mvWorld.getColoredWorldString(), this.plugin.getLocationManipulation().strAxis(anchorLocation)); - } - anchorContent.add(String.format("%s: %s", anchor, locationString)); + String locationString = ChatColor.RED + "!!INVALID!!"; + if (world != null) { + MultiverseWorld mvWorld = this.plugin.getMVWorldManager().getMVWorld(world); + locationString = (mvWorld == null) + ? String.format("%s%s !!NOT MULTIVERSE WORLD!!", ChatColor.RED, world.getName()) + : String.format("%s - %s", mvWorld.getColoredWorldString(), this.plugin.getLocationManipulation().strAxis(anchorLocation)); } + anchorContent.add(String.format("%s: %s", anchor, locationString)); + } - return anchorContent; - }; + return anchorContent; } } diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/ConfigCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/ConfigCommand.java index 277e7849..efa2c990 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/ConfigCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/ConfigCommand.java @@ -16,10 +16,10 @@ import co.aikar.commands.annotation.Subcommand; import co.aikar.commands.annotation.Syntax; import co.aikar.commands.annotation.Values; import com.onarandombox.MultiverseCore.MultiverseCore; -import com.onarandombox.MultiverseCore.commandtools.display.ColorAlternator; -import com.onarandombox.MultiverseCore.commandtools.display.ContentCreator; import com.onarandombox.MultiverseCore.commandtools.display.ContentFilter; -import com.onarandombox.MultiverseCore.commandtools.display.inline.KeyValueDisplay; +import com.onarandombox.MultiverseCore.displaytools.ColorAlternator; +import com.onarandombox.MultiverseCore.displaytools.ContentDisplay; +import com.onarandombox.MultiverseCore.displaytools.DisplayHandlers; import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; @@ -41,17 +41,15 @@ public class ConfigCommand extends MultiverseCoreCommand { public void onShowCommand(@NotNull CommandSender sender, @NotNull ContentFilter filter) { - new KeyValueDisplay().withSender(sender) - .withHeader(ChatColor.LIGHT_PURPLE + "===[ Multiverse Config ]===") - .withCreator(getConfigMap()) - .withFilter(filter) - .withColors(new ColorAlternator(ChatColor.GREEN, ChatColor.GOLD)) - .build() - .runTaskAsynchronously(this.plugin); - } - - private ContentCreator> getConfigMap() { - return () -> this.plugin.getMVConfig().serialize(); + new ContentDisplay.Builder>() + .sender(sender) + .header("%s===[ Multiverse Config ]===", ChatColor.LIGHT_PURPLE) + .contents(this.plugin.getMVConfig().serialize()) + .emptyMessage("No config values found.") + .displayHandler(DisplayHandlers.INLINE_MAP) + .colorTool(ColorAlternator.with(ChatColor.GREEN, ChatColor.GOLD)) + //TODO: Filter + .display(this.plugin); } @Subcommand("set") diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/GeneratorCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/GeneratorCommand.java index 19df3fb9..81496bdf 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/GeneratorCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/GeneratorCommand.java @@ -12,15 +12,16 @@ import co.aikar.commands.annotation.CommandPermission; import co.aikar.commands.annotation.Description; import co.aikar.commands.annotation.Subcommand; import com.onarandombox.MultiverseCore.MultiverseCore; -import com.onarandombox.MultiverseCore.commandtools.display.ColorAlternator; -import com.onarandombox.MultiverseCore.commandtools.display.ContentCreator; -import com.onarandombox.MultiverseCore.commandtools.display.inline.ListDisplay; import com.onarandombox.MultiverseCore.commandtools.flags.CoreFlags; +import com.onarandombox.MultiverseCore.displaytools.ColorAlternator; +import com.onarandombox.MultiverseCore.displaytools.ContentDisplay; +import com.onarandombox.MultiverseCore.displaytools.ContentFilter; +import com.onarandombox.MultiverseCore.displaytools.DisplayHandlers; import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; -import java.util.List; +import java.util.Collection; @CommandAlias("mv") public class GeneratorCommand extends MultiverseCoreCommand { @@ -33,22 +34,14 @@ public class GeneratorCommand extends MultiverseCoreCommand { @CommandPermission("multiverse.core.generator") @Description("Shows a list of Loaded Generator Plugins.") public void onGeneratorCommand(@NotNull CommandSender sender) { - showAvailableGenerator(this.plugin, sender); - } - - public static void showAvailableGenerator(@NotNull MultiverseCore plugin, - @NotNull CommandSender sender) { - - new ListDisplay().withSender(sender) - .withHeader(String.format("%s--- Available Generator Plugins ---", ChatColor.GOLD)) - .withCreator(getGeneratorContent()) - .withColors(new ColorAlternator(ChatColor.AQUA, ChatColor.WHITE)) - .withEmptyMessage(String.format("%sYou do not have any generator plugins installed.", ChatColor.RED)) - .build() - .run(); - } - - private static ContentCreator> getGeneratorContent() { - return () -> (List) CoreFlags.GENERATOR.suggestValue(); + new ContentDisplay.Builder>() + .sender(sender) + .header("%s--- Available Generator Plugins ---", ChatColor.GOLD) + .contents(CoreFlags.GENERATOR.suggestValue()) + .emptyMessage("%sYou do not have any generator plugins installed.", ChatColor.RED) + .displayHandler(DisplayHandlers.INLINE_LIST) + .colorTool(ColorAlternator.with(ChatColor.AQUA, ChatColor.WHITE)) + .filter(ContentFilter.getDefault()) + .display(this.plugin); } } diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/ListCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/ListCommand.java index a1908782..d8375df5 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/ListCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/ListCommand.java @@ -14,9 +14,12 @@ import co.aikar.commands.annotation.Subcommand; import co.aikar.commands.annotation.Syntax; import com.onarandombox.MultiverseCore.MultiverseCore; import com.onarandombox.MultiverseCore.api.MultiverseWorld; -import com.onarandombox.MultiverseCore.commandtools.display.ContentCreator; -import com.onarandombox.MultiverseCore.commandtools.display.page.PageDisplay; import com.onarandombox.MultiverseCore.commandtools.contexts.PageFilter; +import com.onarandombox.MultiverseCore.displaytools.ColorAlternator; +import com.onarandombox.MultiverseCore.displaytools.ContentDisplay; +import com.onarandombox.MultiverseCore.displaytools.ContentFilter; +import com.onarandombox.MultiverseCore.displaytools.DisplayHandlers; +import com.onarandombox.MultiverseCore.displaytools.DisplaySettings; import org.bukkit.ChatColor; import org.bukkit.World; import org.bukkit.command.CommandSender; @@ -24,6 +27,7 @@ import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; +import java.util.Collection; import java.util.List; @CommandAlias("mv") @@ -41,35 +45,35 @@ public class ListCommand extends MultiverseCoreCommand { @NotNull PageFilter pageFilter) { - new PageDisplay().withSender(sender) - .withHeader(String.format("%s====[ Multiverse World List ]====", ChatColor.GOLD)) - .withCreator(getListContents(sender)) - .withPageFilter(pageFilter) - .build() - .runTaskAsynchronously(this.plugin); + new ContentDisplay.Builder>() + .sender(sender) + .header("%s====[ Multiverse World List ]====", ChatColor.GOLD) + .contents(getListContents(sender)) + .displayHandler(DisplayHandlers.PAGE_LIST) + .colorTool(ColorAlternator.with(ChatColor.AQUA, ChatColor.GOLD)) + .filter(ContentFilter.getDefault()) + .setting(DisplaySettings.SHOW_PAGE, pageFilter.getPage()) + .display(this.plugin); } - private ContentCreator> getListContents(@NotNull CommandSender sender) { - return () -> { - Player player = (sender instanceof Player) - ? (Player) sender - : null; - List worldList = new ArrayList<>(); - plugin.getMVWorldManager().getMVWorlds().stream() - .filter(world -> player == null || plugin.getMVPerms().canEnterWorld(player, world)) - .filter(world -> canSeeWorld(player, world)) - .map(world -> hiddenText(world) + world.getColoredWorldString() + " - " + parseColouredEnvironment(world.getEnvironment())) - .sorted() - .forEach(worldList::add); + private List getListContents(@NotNull CommandSender sender) { + Player player = (sender instanceof Player) ? (Player) sender : null; + List worldList = new ArrayList<>(); - plugin.getMVWorldManager().getUnloadedWorlds().stream() - .filter(world -> plugin.getMVPerms().hasPermission(sender, "multiverse.access." + world, true)) - .map(world -> ChatColor.GRAY + world + " - UNLOADED") - .sorted() - .forEach(worldList::add); + this.plugin.getMVWorldManager().getMVWorlds().stream() + .filter(world -> player == null || plugin.getMVPerms().canEnterWorld(player, world)) + .filter(world -> canSeeWorld(player, world)) + .map(world -> hiddenText(world) + world.getColoredWorldString() + " - " + parseColouredEnvironment(world.getEnvironment())) + .sorted() + .forEach(worldList::add); - return worldList; - }; + this.plugin.getMVWorldManager().getUnloadedWorlds().stream() + .filter(world -> plugin.getMVPerms().hasPermission(sender, "multiverse.access." + world, true)) + .map(world -> ChatColor.GRAY + world + " - UNLOADED") + .sorted() + .forEach(worldList::add); + + return worldList; } private boolean canSeeWorld(Player player, MultiverseWorld world) { diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/WhoCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/WhoCommand.java index 87630c78..106fab7c 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/WhoCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/WhoCommand.java @@ -21,12 +21,15 @@ import com.onarandombox.MultiverseCore.api.MultiverseWorld; import com.onarandombox.MultiverseCore.commandtools.display.ContentCreator; import com.onarandombox.MultiverseCore.commandtools.display.ContentFilter; import com.onarandombox.MultiverseCore.commandtools.display.inline.ListDisplay; +import com.onarandombox.MultiverseCore.displaytools.ContentDisplay; +import com.onarandombox.MultiverseCore.displaytools.DisplayHandlers; import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Collection; import java.util.List; import java.util.Set; import java.util.stream.Collectors; @@ -71,7 +74,7 @@ public class WhoCommand extends MultiverseCoreCommand { String prefix = String.format("%s%s - ", world.getColoredWorldString(), ChatColor.WHITE); - display.withCreator(buildPlayerList(world, visiblePlayers)) + display.withCreator(() -> buildPlayerList(world, visiblePlayers)) .withPrefix(prefix) .withEmptyMessage(String.format("%s%sNo players found.", prefix, ChatColor.GRAY)) .build() @@ -98,20 +101,21 @@ public class WhoCommand extends MultiverseCoreCommand { Set visiblePlayers = getVisiblePlayers(player); - new ListDisplay().withSender(sender) - .withHeader(String.format("%s===[ Players in %s%s ]===", ChatColor.AQUA, world.getColoredWorldString(), ChatColor.AQUA)) - .withCreator(buildPlayerList(world, visiblePlayers)) - .withFilter(filter) - .withEmptyMessage(String.format("%sNo players found.", ChatColor.GRAY)) - .build() - .runTaskAsynchronously(this.plugin); + new ContentDisplay.Builder>() + .sender(sender) + .header("%s===[ Players in %s%s ]===", ChatColor.AQUA, world.getColoredWorldString(), ChatColor.AQUA) + .contents(buildPlayerList(world, visiblePlayers)) + .emptyMessage("%sNo players found.", ChatColor.GRAY) + .displayHandler(DisplayHandlers.PAGE_LIST) + //TODO: Filter + .display(this.plugin); } @NotNull - private ContentCreator> buildPlayerList(@NotNull MultiverseWorld world, - @NotNull Set visiblePlayers) { + private List buildPlayerList(@NotNull MultiverseWorld world, + @NotNull Set visiblePlayers) { - return () -> world.getCBWorld().getPlayers().stream() + return world.getCBWorld().getPlayers().stream() .filter(visiblePlayers::contains) .map(Player::getDisplayName) .collect(Collectors.toList()); diff --git a/src/main/java/com/onarandombox/MultiverseCore/displaytools/ColorAlternator.java b/src/main/java/com/onarandombox/MultiverseCore/displaytools/ColorAlternator.java new file mode 100644 index 00000000..27887adc --- /dev/null +++ b/src/main/java/com/onarandombox/MultiverseCore/displaytools/ColorAlternator.java @@ -0,0 +1,33 @@ +package com.onarandombox.MultiverseCore.displaytools; + +import org.bukkit.ChatColor; +import org.jetbrains.annotations.NotNull; + +public class ColorAlternator implements ColorTool { + + public static ColorAlternator with(@NotNull ChatColor colorThis, + @NotNull ChatColor colorThat) { + + return new ColorAlternator(colorThis, colorThat); + } + + private boolean switcher; + private final ChatColor thisColor; + private final ChatColor thatColor; + + public ColorAlternator() { + this(ChatColor.WHITE, ChatColor.WHITE); + } + + public ColorAlternator(@NotNull ChatColor colorThis, + @NotNull ChatColor colorThat) { + + this.thisColor = colorThis; + this.thatColor = colorThat; + } + + @Override + public ChatColor get() { + return (this.switcher ^= true) ? this.thisColor : this.thatColor; + } +} diff --git a/src/main/java/com/onarandombox/MultiverseCore/displaytools/ColorTool.java b/src/main/java/com/onarandombox/MultiverseCore/displaytools/ColorTool.java new file mode 100644 index 00000000..ebe9225f --- /dev/null +++ b/src/main/java/com/onarandombox/MultiverseCore/displaytools/ColorTool.java @@ -0,0 +1,9 @@ +package com.onarandombox.MultiverseCore.displaytools; + +import org.bukkit.ChatColor; + +public interface ColorTool { + + ChatColor get(); + +} diff --git a/src/main/java/com/onarandombox/MultiverseCore/displaytools/ContentDisplay.java b/src/main/java/com/onarandombox/MultiverseCore/displaytools/ContentDisplay.java new file mode 100644 index 00000000..fcd30c24 --- /dev/null +++ b/src/main/java/com/onarandombox/MultiverseCore/displaytools/ContentDisplay.java @@ -0,0 +1,131 @@ +package com.onarandombox.MultiverseCore.displaytools; + +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.plugin.Plugin; + +import java.util.Collection; +import java.util.Map; +import java.util.WeakHashMap; + +public class ContentDisplay { + + public static final String PAGE_PLACEHOLDER = "%page%"; + public static final String LINE_BREAK_PLACEHOLDER = "%lf%"; + + private CommandSender sender; + private String header; + private T contents; + private String emptyMessage; + private DisplayHandler displayHandler; + private ColorTool colorTool; + private ContentFilter filter; + private final Map, Object> settingsMap; + + private ContentDisplay() { + settingsMap = new WeakHashMap<>(); + } + + public void display() { + Collection formattedContent = this.displayHandler.format(this); + sendHeader(); + sendBody(formattedContent); + } + + public void sendHeader() { + this.sender.sendMessage(this.header); + } + + public void sendBody(Collection bodyContent) { + this.sender.sendMessage(bodyContent.toArray(new String[0])); + } + + public CommandSender getSender() { + return sender; + } + + public String getHeader() { + return header; + } + + public T getContents() { + return contents; + } + + public String getEmptyMessage() { + return emptyMessage; + } + + public DisplayHandler getDisplayHandler() { + return displayHandler; + } + + public ColorTool getColorTool() { + return colorTool; + } + + public ContentFilter getFilter() { + return filter; + } + + public S getSetting(DisplaySetting setting) { + return (S) settingsMap.getOrDefault(setting, setting.defaultValue()); + } + + public static class Builder { + + private final ContentDisplay display; + + public Builder() { + this.display = new ContentDisplay<>(); + } + + public Builder sender(CommandSender sender) { + this.display.sender = sender; + return this; + } + + public Builder header(String header, Object...replacements) { + this.display.header = String.format(header, replacements); + return this; + } + + public Builder contents(T contents) { + this.display.contents = contents; + return this; + } + + public Builder emptyMessage(String emptyMessage, Object...replacements) { + this.display.emptyMessage = String.format(emptyMessage, replacements); + return this; + } + + public Builder displayHandler(DisplayHandler displayHandler) { + this.display.displayHandler = displayHandler; + return this; + } + + public Builder colorTool(ColorTool colorTool) { + this.display.colorTool = colorTool; + return this; + } + + public Builder filter(ContentFilter filter) { + this.display.filter = filter; + return this; + } + + public Builder setting(DisplaySetting setting, S value) { + this.display.settingsMap.put(setting, value); + return this; + } + + public void display() { + this.display.display(); + } + + public void display(Plugin plugin) { + Bukkit.getScheduler().runTaskAsynchronously(plugin, this.display::display); + } + } +} diff --git a/src/main/java/com/onarandombox/MultiverseCore/displaytools/ContentFilter.java b/src/main/java/com/onarandombox/MultiverseCore/displaytools/ContentFilter.java new file mode 100644 index 00000000..d371fcf4 --- /dev/null +++ b/src/main/java/com/onarandombox/MultiverseCore/displaytools/ContentFilter.java @@ -0,0 +1,128 @@ +package com.onarandombox.MultiverseCore.displaytools; + +import com.dumptruckman.minecraft.util.Logging; +import org.bukkit.ChatColor; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; + +/** + * Filter content and text based on regex. + */ +public class ContentFilter { + + public static final ContentFilter DEFAULT = new ContentFilter(); + private static final Pattern REGEX_SPECIAL_CHARS = Pattern.compile("[.+*?\\[^\\]$(){}=!<>|:-\\\\]"); + + public static ContentFilter getDefault() { + return DEFAULT; + } + + private String filterString; + private Pattern filterPattern; + private boolean exactMatch; + + public ContentFilter() { + } + + public ContentFilter(@NotNull String filterString) { + this(filterString, false); + } + + public ContentFilter(@NotNull String filterString, + boolean exactMatch) { + + this.filterString = filterString; + this.exactMatch = exactMatch; + parseFilter(); + } + + /** + * Compile regex pattern based on {@link ContentFilter#filterString}. + * When prefixed with 'r=', use {@link ContentFilter#filterString} as the full regex pattern. + * Else, set to any match that contains the {@link ContentFilter#filterString}. + */ + private void parseFilter() { + if (filterString == null) { + return; + } + if (filterString.startsWith("r=")) { + convertToMatcher(filterString.substring(2)); + return; + } + String cleanedFilter = REGEX_SPECIAL_CHARS.matcher(filterString.toLowerCase()).replaceAll("\\\\$0"); + convertToMatcher("(?i).*" + cleanedFilter + ".*"); + } + + /** + * Compile and store the regex into a {@link Pattern}. + */ + private void convertToMatcher(@NotNull String regex) { + try { + this.filterPattern = Pattern.compile(regex); + Logging.finest("Parsed regex pattern: %s", this.filterPattern.toString()); + } + catch (PatternSyntaxException ignored) { + Logging.warning("Error parsing regex: %s", filterString); + } + } + + /** + * Do regex matching. + * + * @param text String to check regex on. + * @return True of matches regex pattern, false otherwise. + */ + public boolean checkMatch(@Nullable Object text) { + if (!hasFilter()) { + return true; + } + if (text == null || !hasValidPattern()) { + return false; + } + text = ChatColor.stripColor(String.valueOf(text)); + return (exactMatch) + ? filterPattern.matcher((CharSequence) text).matches() + : filterPattern.matcher((CharSequence) text).find(); + } + + public boolean hasFilter() { + return filterString != null; + } + + public boolean hasValidPattern() { + return filterPattern != null; + } + + public @Nullable String getString() { + return filterString; + } + + public @Nullable Pattern getPattern() { + return filterPattern; + } + + public boolean isExactMatch() { + return exactMatch; + } + + /** + * Nicely format the filter string to be used for showing the sender. + * + * @return formatted filter string. + */ + public @NotNull String getFormattedString() { + return String.format("%sFilter: '%s'%s", ChatColor.ITALIC, filterString, ChatColor.RESET); + } + + @Override + public String toString() { + return "ContentFilter{" + + "filterString='" + filterString + '\'' + + ", filterPattern=" + filterPattern + + ", exactMatch=" + exactMatch + + '}'; + } +} \ No newline at end of file diff --git a/src/main/java/com/onarandombox/MultiverseCore/displaytools/DisplayHandler.java b/src/main/java/com/onarandombox/MultiverseCore/displaytools/DisplayHandler.java new file mode 100644 index 00000000..733b4fb1 --- /dev/null +++ b/src/main/java/com/onarandombox/MultiverseCore/displaytools/DisplayHandler.java @@ -0,0 +1,9 @@ +package com.onarandombox.MultiverseCore.displaytools; + +import java.util.Collection; + +public interface DisplayHandler { + + Collection format(ContentDisplay display); + +} diff --git a/src/main/java/com/onarandombox/MultiverseCore/displaytools/DisplayHandlers.java b/src/main/java/com/onarandombox/MultiverseCore/displaytools/DisplayHandlers.java new file mode 100644 index 00000000..08cc066f --- /dev/null +++ b/src/main/java/com/onarandombox/MultiverseCore/displaytools/DisplayHandlers.java @@ -0,0 +1,94 @@ +package com.onarandombox.MultiverseCore.displaytools; + +import org.bukkit.command.ConsoleCommandSender; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +public class DisplayHandlers { + + public static final DisplayHandler> INLINE_LIST = display -> { + StringBuilder builder = new StringBuilder(); + String separator = display.getSetting(DisplaySettings.SEPARATOR); + + for (Iterator iterator = display.getContents().iterator(); iterator.hasNext(); ) { + String content = iterator.next(); + if (!display.getFilter().checkMatch(content)) { + continue; + } + builder.append(display.getColorTool().get()).append(content); + if (iterator.hasNext()) { + builder.append(separator); + } + } + return (builder.length() == 0) + ? Collections.singletonList(display.getEmptyMessage()) + : Collections.singleton(builder.toString()); + }; + + public static final DisplayHandler> INLINE_MAP = display -> { + StringBuilder builder = new StringBuilder(); + String separator = display.getSetting(DisplaySettings.SEPARATOR); + String operator = display.getSetting(DisplaySettings.OPERATOR); + + for (Iterator> iterator = display.getContents().entrySet().iterator(); iterator.hasNext(); ) { + Entry entry = iterator.next(); + if (!display.getFilter().checkMatch(entry.getKey()) && !display.getFilter().checkMatch(entry.getValue())) { + continue; + } + builder.append(display.getColorTool().get()) + .append(entry.getKey()) + .append(operator) + .append(display.getColorTool().get()) + .append(entry.getValue()); + if (iterator.hasNext()) { + builder.append(separator); + } + } + return (builder.length() == 0) + ? Collections.singletonList(display.getEmptyMessage()) + : Collections.singleton(builder.toString()); + }; + + public static final DisplayHandler> LIST = display -> display.getContents().stream() + .filter(display.getFilter()::checkMatch) + .collect(Collectors.toList()); + + public static final DisplayHandler> PAGE_LIST = display -> { + if (display.getSender() instanceof ConsoleCommandSender && !display.getSetting(DisplaySettings.PAGE_IN_CONSOLE)) { + return LIST.format(display); + } + + int pages = 1; + int currentLength = 0; + int targetPage = display.getSetting(DisplaySettings.SHOW_PAGE); + int linesPerPage = display.getSetting(DisplaySettings.LINES_PER_PAGE); + List content = new ArrayList<>(linesPerPage); + + for (String line : display.getContents()) { + if (!display.getFilter().checkMatch(line)) { + continue; + } + if (pages == targetPage) { + content.add(display.getColorTool().get() + line); + } + if (++currentLength > linesPerPage) { + pages++; + currentLength = 0; + } + } + + if (display.getSetting(DisplaySettings.DO_END_PADDING)) { + IntStream.range(0, linesPerPage - content.size()).forEach(i -> content.add("")); + } + + return content; + }; +} diff --git a/src/main/java/com/onarandombox/MultiverseCore/displaytools/DisplaySetting.java b/src/main/java/com/onarandombox/MultiverseCore/displaytools/DisplaySetting.java new file mode 100644 index 00000000..fc8355cd --- /dev/null +++ b/src/main/java/com/onarandombox/MultiverseCore/displaytools/DisplaySetting.java @@ -0,0 +1,11 @@ +package com.onarandombox.MultiverseCore.displaytools; + +public interface DisplaySetting { + + /** + * Gets the default value of this Display Setting. + * + * @return The default value. + */ + T defaultValue(); +} diff --git a/src/main/java/com/onarandombox/MultiverseCore/displaytools/DisplaySettings.java b/src/main/java/com/onarandombox/MultiverseCore/displaytools/DisplaySettings.java new file mode 100644 index 00000000..e35d2121 --- /dev/null +++ b/src/main/java/com/onarandombox/MultiverseCore/displaytools/DisplaySettings.java @@ -0,0 +1,36 @@ +package com.onarandombox.MultiverseCore.displaytools; + +import org.bukkit.ChatColor; + +public class DisplaySettings { + + /** + * The page to display. + */ + public static final DisplaySetting SHOW_PAGE = () -> 1; + + /** + * The max number of lines per page. This excludes header. + */ + public static final DisplaySetting LINES_PER_PAGE = () -> 8; + + /** + * Should add empty lines if content lines shown is less that {@link #LINES_PER_PAGE}. + */ + public static final DisplaySetting DO_END_PADDING = () -> true; + + /** + * Should display with paging when it's sent to console. + */ + public static final DisplaySetting PAGE_IN_CONSOLE = () -> false; + + /** + * Inline separator. + */ + public static final DisplaySetting SEPARATOR = () -> ChatColor.WHITE + ", "; + + /** + * The thing between a key value pair. E.g. 'Me = Smart' + */ + public static final DisplaySetting OPERATOR = () -> ChatColor.WHITE + " = "; +}