[Bleeding] Added Help API. Addresses BUKKIT-863

By: rmichela <deltahat@gmail.com>
This commit is contained in:
Bukkit/Spigot 2012-03-01 00:07:05 -05:00
parent 2280c6be2b
commit 10cd1cbb5c
16 changed files with 596 additions and 35 deletions

View file

@ -12,8 +12,9 @@ import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.command.PluginCommand;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.help.HelpMap;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.Recipe;
@ -336,4 +337,8 @@ public final class Bukkit {
public static Inventory createInventory(InventoryHolder owner, int size, String title) {
return server.createInventory(owner, size, title);
}
public static HelpMap getHelpMap() {
return server.getHelpMap();
}
}

View file

@ -14,6 +14,7 @@ import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.command.PluginCommand;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.help.HelpMap;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
@ -564,6 +565,13 @@ public interface Server extends PluginMessageRecipient {
*/
public Messenger getMessenger();
/**
* Gets the {@link HelpMap} providing help topics for this server.
*
* @return The server's HelpMap.
*/
public HelpMap getHelpMap();
/**
* Creates an empty inventory of the specified type. If the type is {@link InventoryType#CHEST},
* the new inventory has a size of 27; otherwise the new inventory has the normal size for
@ -592,4 +600,4 @@ public interface Server extends PluginMessageRecipient {
* @throws IllegalArgumentException If the size is not a multiple of 9.
*/
Inventory createInventory(InventoryHolder owner, int size, String title);
}
}

View file

@ -83,7 +83,7 @@ public abstract class Command {
* @return true if they can use it, otherwise false
*/
public boolean testPermission(CommandSender target) {
if ((permission == null) || (permission.length() == 0) || (target.hasPermission(permission))) {
if (testPermissionSilent(target)) {
return true;
}
@ -98,6 +98,28 @@ public abstract class Command {
return false;
}
/**
* Tests the given {@link CommandSender} to see if they can perform this command.
* <p />
* No error is sent to the sender.
*
* @param target User to test
* @return true if they can use it, otherwise false
*/
public boolean testPermissionSilent(CommandSender target) {
if ((permission == null) || (permission.length() == 0)) {
return true;
}
for (String p : permission.split(";")) {
if (target.hasPermission(p)) {
return true;
}
}
return false;
}
/**
* Returns the current lable for this command
*

View file

@ -12,6 +12,13 @@ public interface CommandSender extends Permissible {
*/
public void sendMessage(String message);
/**
* Sends this sender multiple messages
*
* @param messages An array of messages to be displayed
*/
public void sendMessage(String[] messages);
/**
* Returns the server instance that this command is running on
*

View file

@ -10,6 +10,10 @@ public class MultipleCommandAlias extends Command {
super(name);
this.commands = commands;
}
public Command[] getCommands() {
return commands;
}
@Override
public boolean execute(CommandSender sender, String commandLabel, String[] args) {

View file

@ -1,13 +1,9 @@
package org.bukkit.command;
import org.bukkit.command.defaults.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Iterator;
import java.util.*;
import org.bukkit.Server;
import static org.bukkit.util.Java15Compat.Arrays_copyOfRange;
@ -143,6 +139,10 @@ public class SimpleCommandMap implements CommandMap {
return null;
}
public Set<VanillaCommand> getFallbackCommands() {
return Collections.unmodifiableSet(fallbackCommands);
}
/**
* {@inheritDoc}
@ -156,9 +156,7 @@ public class SimpleCommandMap implements CommandMap {
String sentCommandLabel = args[0].toLowerCase();
Command target = getCommand(sentCommandLabel);
if (target == null) {
target = getFallback(commandLine.toLowerCase());
}
if (target == null) {
return false;
}
@ -186,7 +184,15 @@ public class SimpleCommandMap implements CommandMap {
}
public Command getCommand(String name) {
return knownCommands.get(name.toLowerCase());
Command target = knownCommands.get(name.toLowerCase());
if (target == null) {
target = getFallback(name);
}
return target;
}
public Collection<Command> getCommands() {
return knownCommands.values();
}
public void registerServerAliases() {

View file

@ -1,12 +1,23 @@
package org.bukkit.command.defaults;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.help.HelpMap;
import org.bukkit.help.HelpTopic;
import org.bukkit.util.ChatPaginator;
import java.util.Arrays;
public class HelpCommand extends VanillaCommand {
public HelpCommand() {
super("help");
this.description = "Shows the help menu";
this.usageMessage = "/help";
this.usageMessage = "/help <pageNumber>\n/help <topic>\n/help <topic> <pageNumber>";
this.setPermission("bukkit.command.help");
}
@ -14,25 +25,62 @@ public class HelpCommand extends VanillaCommand {
public boolean execute(CommandSender sender, String currentAlias, String[] args) {
if (!testPermission(sender)) return true;
sender.sendMessage("help or ? shows this message");
sender.sendMessage("kick <player> removes a player from the server");
sender.sendMessage("ban <player> bans a player from the server");
sender.sendMessage("pardon <player> pardons a banned player so that they can connect again");
sender.sendMessage("ban-ip <ip> bans an IP address from the server");
sender.sendMessage("pardon-ip <ip> pardons a banned IP address so that they can connect again");
sender.sendMessage("op <player> turns a player into an op");
sender.sendMessage("deop <player> removes op status from a player");
sender.sendMessage("tp <player1> <player2> moves one player to the same location as another player");
sender.sendMessage("give <player> <id> [num] gives a player a resource");
sender.sendMessage("tell <player> <message> sends a private message to a player");
sender.sendMessage("stop gracefully stops the server");
sender.sendMessage("save-all forces a server-wide level save");
sender.sendMessage("save-off disables terrain saving (useful for backup scripts)");
sender.sendMessage("save-on re-enables terrain saving");
sender.sendMessage("list lists all currently connected players");
sender.sendMessage("say <message> broadcasts a message to all players");
sender.sendMessage("time <add|set> <amount> adds to or sets the world time (0-24000)");
sender.sendMessage("gamemode <player> <mode> sets player\'s game mode (0 or 1)");
String command;
int pageNumber;
int pageHeight;
int pageWidth;
if (args.length == 0) {
command = "";
pageNumber = 1;
} else if (NumberUtils.isDigits(args[args.length - 1])) {
command = StringUtils.join(ArrayUtils.subarray(args, 0, args.length - 1), " ");
pageNumber = NumberUtils.createInteger(args[args.length - 1]);
} else {
command = StringUtils.join(args, " ");
pageNumber = 1;
}
if (sender instanceof ConsoleCommandSender) {
pageHeight = ChatPaginator.UNBOUNDED_PAGE_HEIGHT;
pageWidth = ChatPaginator.UNBOUNDED_PAGE_WIDTH;
} else {
pageHeight = ChatPaginator.CLOSED_CHAT_PAGE_HEIGHT - 1;
pageWidth = ChatPaginator.AVERAGE_CHAT_PAGE_WIDTH;
}
HelpMap helpMap = Bukkit.getServer().getHelpMap();
HelpTopic topic = helpMap.getHelpTopic(command);
if (topic == null) {
topic = helpMap.getHelpTopic("/" + command);
}
if (topic == null || !topic.canSee(sender)) {
sender.sendMessage(ChatColor.RED + "No help for " + command);
return true;
}
ChatPaginator.ChatPage page = ChatPaginator.paginate(topic.getFullText(sender), pageNumber, pageWidth, pageHeight);
StringBuilder header = new StringBuilder();
header.append(ChatColor.GREEN);
header.append("===== Help: ");
header.append(topic.getName());
header.append(" ");
if (page.getTotalPages() > 1) {
header.append("(");
header.append(page.getPageNumber());
header.append(" of ");
header.append(page.getTotalPages());
header.append(") ");
}
for (int i = header.length(); i < ChatPaginator.GUARANTEED_NO_WRAP_CHAT_PAGE_WIDTH; i++) {
header.append("=");
}
sender.sendMessage(header.toString());
sender.sendMessage(page.getLines());
return true;
}

View file

@ -11,6 +11,7 @@ public class TimeCommand extends VanillaCommand {
super("time");
this.description = "Changes the time on each world";
this.usageMessage = "/time set <value>\n/time add <value>";
this.setPermission("bukkit.command.time.add;bukkit.command.time.set");
}
@Override

View file

@ -11,6 +11,7 @@ public class WhitelistCommand extends VanillaCommand {
super("whitelist");
this.description = "Prevents the specified player from using this server";
this.usageMessage = "/whitelist (add|remove) <player>\n/whitelist (on|off|list|reload)";
this.setPermission("bukkit.command.whitelist.reload;bukkit.command.whitelist.enable;bukkit.command.whitelist.disable;bukkit.command.whitelist.list;bukkit.command.whitelist.add;bukkit.command.whitelist.remove");
}
@Override

View file

@ -0,0 +1,44 @@
package org.bukkit.help;
/**
* The HelpMap tracks all help topics registered in a Bukkit server. When the server starts up or is reloaded,
* help is processed and topics are added in the following order:
*
* 1. General topics are loaded from the help.yml
* 2. Plugins load and optionally call {@code addTopic()}
* 3. Registered plugin commands are processed by {@link HelpTopicFactory} objects to create topics
* 4. Topic contents are amended as directed in help.yml
*/
public interface HelpMap {
/**
* Returns a help topic for a given topic name.
*
* @param topicName The help topic name to look up.
* @return A {@link HelpTopic} object matching the topic name or null if none can be found.
*/
public HelpTopic getHelpTopic(String topicName);
/**
* Adds a topic to the server's help index.
*
* @param topic The new help topic to add.
*/
public void addTopic(HelpTopic topic);
/**
* Clears out the contents of the help index. Normally called during server reload.
*/
public void clear();
/**
* Associates a {@link HelpTopicFactory} object with given command base class. Plugins typically
* call this method during {@code onLoad()}. Once registered, the custom HelpTopicFactory will
* be used to create a custom {@link HelpTopic} for all commands deriving from the {@code commandClass}
* base class.
*
* @param commandClass The class for which the custom HelpTopicFactory applies. Must derive from {@link org.bukkit.command.Command}.
* @param factory The {@link HelpTopicFactory} implementation to associate with the {@code commandClass}.
* @throws IllegalArgumentException Thrown if {@code commandClass} does not derive from Command.
*/
public void registerHelpTopicFactory(Class commandClass, HelpTopicFactory factory);
}

View file

@ -0,0 +1,90 @@
package org.bukkit.help;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
/**
* HelpTopic implementations are displayed to the user when the user uses the /help command.
*
* Custom implementations of this class can work at two levels. A simple implementation only
* needs to set the value of {@code name}, {@code shortText}, and {@code fullText} int the
* constructor. This base class will take care of the rest.
*
* Complex implementations can be created by overriding the behavior of all the methods in
* this class.
*/
public abstract class HelpTopic {
protected String name;
protected String shortText;
protected String fullText;
/**
* Determines if a {@link Player} is allowed to see this help topic.
*
* @param player The Player in question.
* @return True of the Player can see this help topic, false otherwise.
*/
public abstract boolean canSee(CommandSender player);
/**
* Returns the name of this help topic.
* @return The topic name.
*/
public String getName() {
return name;
}
/**
* Returns a brief description that will be displayed in the topic index.
* @return A brief topic description.
*/
public String getShortText() {
return shortText;
}
/**
* Returns the full description of this help topic that is displayed when the user requests this topic's details.
* The result will be paginated to properly fit the user's client.
*
* @param forWho The player or console requesting the full text. Useful for further security trimming
* the command's full text based on sub-permissions in custom implementations.
*
* @return A full topic description.
*/
public String getFullText(CommandSender forWho) {
return fullText;
}
/**
* Allows the server admin (or another plugin) to add or replace the contents of a help topic. A null in
* either parameter will leave that part of the topic unchanged. In either amending parameter, the string
* {@literal <text>} is replaced with the existing contents in the help topic. Use this to append or prepend
* additional content into an automatically generated help topic.
*
* @param amendedShortText The new topic short text to use, or null to leave alone.
* @param amendedFullText The new topic full text to use, or null to leave alone.
*/
public void amendTopic(String amendedShortText, String amendedFullText) {
shortText = applyAmendment(shortText, amendedShortText);
fullText = applyAmendment(fullText, amendedFullText);
}
/**
* Developers implementing their own custom HelpTopic implementations can use this utility method to ensure
* their implementations comply with the expected behavior of the {@link HelpTopic#amendTopic(String, String)}
* method.
*
* @param baseText The existing text of the help topic.
* @param amendment The amending text from the amendTopic() method.
*
* @return The application of the amending text to the existing text, according to the expected rules of
* amendTopic().
*/
protected String applyAmendment(String baseText, String amendment) {
if (amendment == null) {
return baseText;
} else {
return amendment.replaceAll("<text>", baseText);
}
}
}

View file

@ -0,0 +1,27 @@
package org.bukkit.help;
import org.bukkit.command.Command;
/**
* A HelpTopicFactory is used to create custom {@link HelpTopic} objects from commands that inherit from a
* common base class. You can use a custom HelpTopic to change the way all the commands in your plugin display
* in the help. If your plugin implements a complex permissions system, a custom help topic may also be appropriate.
*
* To automatically bind your plugin's commands to your custom HelpTopic implementation, first make sure all your
* commands derive from a custom base class (it doesn't have to do anything). Next implement a custom HelpTopicFactory
* for that accepts your custom command base class and instantiates an instance of your custom HelpTopic from it.
* Finally, register your HelpTopicFactory against your command base class using the {@link HelpMap#registerHelpTopicFactory(Class, HelpTopicFactory)}
* method.
*
* @param <TCommand> The base class for your custom commands.
*/
public interface HelpTopicFactory<TCommand extends Command> {
/**
* This method accepts a command deriving from a custom command base class and constructs a custom HelpTopic
* for it.
*
* @param command The custom command to build a help topic for.
* @return A new custom help topic.
*/
public HelpTopic createTopic(TCommand command);
}

View file

@ -0,0 +1,137 @@
package org.bukkit.util;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
/**
* The ChatPaginator takes a raw string of arbitrary length and breaks it down into an array of strings appropriate
* for displaying on the Minecraft player console.
*/
public class ChatPaginator {
public static final int GUARANTEED_NO_WRAP_CHAT_PAGE_WIDTH = 55; // Will never wrap, even with the largest characters
public static final int AVERAGE_CHAT_PAGE_WIDTH = 65; // Will typically not wrap using an average character distribution
public static final int UNBOUNDED_PAGE_WIDTH = Integer.MAX_VALUE;
public static final int OPEN_CHAT_PAGE_HEIGHT = 20; // The height of an expanded chat window
public static final int CLOSED_CHAT_PAGE_HEIGHT = 10; // The height of the default chat window
public static final int UNBOUNDED_PAGE_HEIGHT = Integer.MAX_VALUE;
/**
* Breaks a raw string up into pages using the default width and height.
* @param unpaginatedString The raw string to break.
* @param pageNumber The page number to fetch.
* @return A single chat page.
*/
public static ChatPage paginate(String unpaginatedString, int pageNumber) {
return paginate(unpaginatedString, pageNumber, GUARANTEED_NO_WRAP_CHAT_PAGE_WIDTH, CLOSED_CHAT_PAGE_HEIGHT);
}
/**
* Breaks a raw string up into pages using a provided width and height.
* @param unpaginatedString The raw string to break.
* @param pageNumber The page number to fetch.
* @param lineLength The desired width of a chat line.
* @param pageHeight The desired number of lines in a page.
* @return A single chat page.
*/
public static ChatPage paginate(String unpaginatedString, int pageNumber, int lineLength, int pageHeight) {
String[] lines = wordWrap(unpaginatedString, lineLength);
int totalPages = lines.length / pageHeight + (lines.length % pageHeight == 0 ? 0 : 1);
int actualPageNumber = pageNumber <= totalPages ? pageNumber : totalPages;
int from = (actualPageNumber - 1) * pageHeight;
int to = from + pageHeight <= lines.length ? from + pageHeight : lines.length;
String[] selectedLines = Arrays.copyOfRange(lines, from, to);
return new ChatPage(selectedLines, actualPageNumber, totalPages);
}
/**
* Breaks a raw string up into a series of lines. Words are wrapped using spaces as decimeters and the newline
* character is respected.
* @param rawString The raw string to break.
* @param lineLength The length of a line of text.
* @return An array of word-wrapped lines.
*/
public static String[] wordWrap(String rawString, int lineLength) {
// A null string is a single line
if (rawString == null) {
return new String[] {""};
}
// A string shorter than the lineWidth is a single line
if (rawString.length() <= lineLength && !rawString.contains("\n")) {
return new String[] {rawString};
}
char[] rawChars = (rawString + ' ').toCharArray(); // add a trailing space to trigger pagination
StringBuilder word = new StringBuilder();
StringBuilder line = new StringBuilder();
List<String> lines = new LinkedList<String>();
for (char c : rawChars) {
if (c == ' ' || c == '\n') {
if (line.length() == 0 && word.length() > lineLength) { // special case: extremely long word begins a line
for (String partialWord : word.toString().split("(?<=\\G.{" + lineLength + "})")) {
lines.add(partialWord);
}
} else if (line.length() + word.length() == lineLength) { // Line exactly the correct length...newline
line.append(word);
lines.add(line.toString());
line = new StringBuilder();
} else if (line.length() + 1 + word.length() > lineLength) { // Line too long...break the line
for (String partialWord : word.toString().split("(?<=\\G.{" + lineLength + "})")) {
lines.add(line.toString());
line = new StringBuilder(partialWord);
}
} else {
if (line.length() > 0) {
line.append(' ');
}
line.append(word);
}
word = new StringBuilder();
if (c == '\n') { // Newline forces the line to flush
lines.add(line.toString());
line = new StringBuilder();
}
} else {
word.append(c);
}
}
if(line.length() > 0) { // Only add the last line if there is anything to add
lines.add(line.toString());
}
return lines.toArray(new String[0]);
}
public static class ChatPage {
private String[] lines;
private int pageNumber;
private int totalPages;
public ChatPage(String[] lines, int pageNumber, int totalPages) {
this.lines = lines;
this.pageNumber = pageNumber;
this.totalPages = totalPages;
}
public int getPageNumber() {
return pageNumber;
}
public int getTotalPages() {
return totalPages;
}
public String[] getLines() {
return lines;
}
}
}

View file

@ -99,7 +99,7 @@ public final class CommandPermissions {
DefaultPermissions.registerPermission(PREFIX + "kick", "Allows the user to kick players", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(PREFIX + "stop", "Allows the user to stop the server", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(PREFIX + "list", "Allows the user to list all online players", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(PREFIX + "help", "Allows the user to view the vanilla help menu", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(PREFIX + "help", "Allows the user to view the vanilla help menu", PermissionDefault.TRUE, commands);
DefaultPermissions.registerPermission(PREFIX + "plugins", "Allows the user to view the list of plugins running on this server", PermissionDefault.TRUE, commands);
DefaultPermissions.registerPermission(PREFIX + "reload", "Allows the user to reload the server settings", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(PREFIX + "version", "Allows the user to view the version of the server", PermissionDefault.TRUE, commands);

View file

@ -0,0 +1,157 @@
package org.bukkit;
import org.bukkit.util.ChatPaginator;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertThat;
/**
*/
public class ChatPaginatorTest {
@Test
public void testWordWrap1() {
String rawString = "123456789 123456789 123456789";
String[] lines = ChatPaginator.wordWrap(rawString, 19);
assertThat(lines.length, is(2));
assertThat(lines[0], is("123456789 123456789"));
assertThat(lines[1], is("123456789"));
}
@Test
public void testWordWrap2() {
String rawString = "123456789 123456789 123456789";
String[] lines = ChatPaginator.wordWrap(rawString, 22);
assertThat(lines.length, is(2));
assertThat(lines[0], is("123456789 123456789"));
assertThat(lines[1], is("123456789"));
}
@Test
public void testWordWrap3() {
String rawString = "123456789 123456789 123456789";
String[] lines = ChatPaginator.wordWrap(rawString, 16);
assertThat(lines.length, is(3));
assertThat(lines[0], is("123456789"));
assertThat(lines[1], is("123456789"));
assertThat(lines[2], is("123456789"));
}
@Test
public void testWordWrap4() {
String rawString = "123456789 123456789 123456789 12345";
String[] lines = ChatPaginator.wordWrap(rawString, 19);
assertThat(lines.length, is(2));
assertThat(lines[0], is("123456789 123456789"));
assertThat(lines[1], is("123456789 12345"));
}
@Test
public void testWordWrap5() {
String rawString = "123456789\n123456789 123456789";
String[] lines = ChatPaginator.wordWrap(rawString, 19);
assertThat(lines.length, is(2));
assertThat(lines[0], is("123456789"));
assertThat(lines[1], is("123456789 123456789"));
}
@Test
public void testWordWrap6() {
String rawString = "12345678 23456789 123456789";
String[] lines = ChatPaginator.wordWrap(rawString, 19);
assertThat(lines.length, is(2));
assertThat(lines[0], is("12345678 23456789"));
assertThat(lines[1], is("123456789"));
}
@Test
public void testWordWrap7() {
String rawString = "12345678 23456789 123456789";
String[] lines = ChatPaginator.wordWrap(rawString, 19);
assertThat(lines.length, is(2));
assertThat(lines[0], is("12345678 23456789"));
assertThat(lines[1], is("123456789"));
}
@Test
public void testWordWrap8() {
String rawString = "123456789 123456789 123456789";
String[] lines = ChatPaginator.wordWrap(rawString, 6);
assertThat(lines.length, is(6));
assertThat(lines[0], is("123456"));
assertThat(lines[1], is("789"));
assertThat(lines[2], is("123456"));
assertThat(lines[3], is("789"));
assertThat(lines[4], is("123456"));
assertThat(lines[5], is("789"));
}
@Test
public void testWordWrap9() {
String rawString = "1234 123456789 123456789 123456789";
String[] lines = ChatPaginator.wordWrap(rawString, 6);
assertThat(lines.length, is(7));
assertThat(lines[0], is("1234"));
assertThat(lines[1], is("123456"));
assertThat(lines[2], is("789"));
assertThat(lines[3], is("123456"));
assertThat(lines[4], is("789"));
assertThat(lines[5], is("123456"));
assertThat(lines[6], is("789"));
}
@Test
public void testWordWrap10() {
String rawString = "123456789\n123456789";
String[] lines = ChatPaginator.wordWrap(rawString, 19);
assertThat(lines.length, is(2));
assertThat(lines[0], is("123456789"));
assertThat(lines[1], is("123456789"));
}
@Test
public void testPaginate1() {
String rawString = "1234 123456789 123456789 123456789";
ChatPaginator.ChatPage page = ChatPaginator.paginate(rawString, 1, 6, 2);
assertThat(page.getPageNumber(), is(1));
assertThat(page.getTotalPages(), is(4));
assertThat(page.getLines().length, is(2));
assertThat(page.getLines()[0], is("1234"));
assertThat(page.getLines()[1], is("123456"));
}
@Test
public void testPaginate2() {
String rawString = "1234 123456789 123456789 123456789";
ChatPaginator.ChatPage page = ChatPaginator.paginate(rawString, 2, 6, 2);
assertThat(page.getPageNumber(), is(2));
assertThat(page.getTotalPages(), is(4));
assertThat(page.getLines().length, is(2));
assertThat(page.getLines()[0], is("789"));
assertThat(page.getLines()[1], is("123456"));
}
@Test
public void testPaginate3() {
String rawString = "1234 123456789 123456789 123456789";
ChatPaginator.ChatPage page = ChatPaginator.paginate(rawString, 4, 6, 2);
assertThat(page.getPageNumber(), is(4));
assertThat(page.getTotalPages(), is(4));
assertThat(page.getLines().length, is(1));
assertThat(page.getLines()[0], is("789"));
}
}

View file

@ -556,6 +556,10 @@ public class TestPlayer implements Player {
throw new UnsupportedOperationException("Not supported yet.");
}
public void sendMessage(String[] messages) {
throw new UnsupportedOperationException("Not supported yet.");
}
public boolean isOnline() {
throw new UnsupportedOperationException("Not supported yet.");
}