mirror of
https://github.com/PaperMC/Paper.git
synced 2025-01-05 18:27:17 +01:00
[Bleeding] Added Help API. Addresses BUKKIT-863
By: rmichela <deltahat@gmail.com>
This commit is contained in:
parent
2280c6be2b
commit
10cd1cbb5c
16 changed files with 596 additions and 35 deletions
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
44
paper-api/src/main/java/org/bukkit/help/HelpMap.java
Normal file
44
paper-api/src/main/java/org/bukkit/help/HelpMap.java
Normal 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);
|
||||
}
|
90
paper-api/src/main/java/org/bukkit/help/HelpTopic.java
Normal file
90
paper-api/src/main/java/org/bukkit/help/HelpTopic.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
137
paper-api/src/main/java/org/bukkit/util/ChatPaginator.java
Normal file
137
paper-api/src/main/java/org/bukkit/util/ChatPaginator.java
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
157
paper-api/src/test/java/org/bukkit/ChatPaginatorTest.java
Normal file
157
paper-api/src/test/java/org/bukkit/ChatPaginatorTest.java
Normal 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"));
|
||||
}
|
||||
}
|
|
@ -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.");
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue