Dateien nach "src/main/java/com/wimbli/WorldBorder/cmd" hochladen

This commit is contained in:
2025-12-14 10:21:11 +00:00
parent c97a081671
commit 2665a642a5
31 changed files with 1789 additions and 0 deletions

View File

@@ -0,0 +1,85 @@
package com.wimbli.WorldBorder.cmd;
import com.wimbli.WorldBorder.Config;
import com.wimbli.WorldBorder.UUID.UUIDFetcher;
import com.wimbli.WorldBorder.WorldBorder;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.List;
import java.util.UUID;
public class CmdBypass extends WBCmd {
public CmdBypass() {
name = permission = "bypass";
minParams = 0;
maxParams = 2;
addCmdExample(nameEmphasized() + "{player} [on|off] - let player go beyond border.");
helpText = "If [player] isn't specified, command sender is used. If [on|off] isn't specified, the value will " +
"be toggled. Once bypass is enabled, the player will not be stopped by any borders until bypass is " +
"disabled for them again. Use the " + commandEmphasized("bypasslist") + C_DESC + "command to list all " +
"players with bypass enabled.";
}
@Override
public void cmdStatus(CommandSender sender) {
if (!(sender instanceof Player))
return;
boolean bypass = Config.isPlayerBypassing(((Player) sender).getUniqueId());
sender.sendMessage(C_HEAD + "Border bypass is currently " + enabledColored(bypass) + C_HEAD + " for you.");
}
@Override
public void execute(final CommandSender sender, final Player player, final List<String> params, String worldName) {
if (player == null && params.isEmpty()) {
sendErrorAndHelp(sender, "When running this command from console, you must specify a player.");
return;
}
Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(WorldBorder.plugin, new Runnable() {
@Override
public void run() {
final String sPlayer = (params.isEmpty()) ? player.getName() : params.get(0);
UUID uPlayer = (params.isEmpty()) ? player.getUniqueId() : null;
if (uPlayer == null) {
Player p = Bukkit.getPlayer(sPlayer);
if (p != null) {
uPlayer = p.getUniqueId();
} else {
// only do UUID lookup using Mojang server if specified player isn't online
try {
uPlayer = UUIDFetcher.getUUID(sPlayer);
} catch (Exception ex) {
sendErrorAndHelp(sender, "Failed to look up UUID for the player name you specified. " + ex.getLocalizedMessage());
return;
}
}
}
if (uPlayer == null) {
sendErrorAndHelp(sender, "Failed to look up UUID for the player name you specified; null value returned.");
return;
}
boolean bypassing = !Config.isPlayerBypassing(uPlayer);
if (params.size() > 1)
bypassing = strAsBool(params.get(1));
Config.setPlayerBypass(uPlayer, bypassing);
Player target = Bukkit.getPlayer(sPlayer);
if (target != null && target.isOnline())
target.sendMessage("Border bypass is now " + enabledColored(bypassing) + ".");
Config.log("Border bypass for player \"" + sPlayer + "\" is " + (bypassing ? "enabled" : "disabled") +
(player != null ? " at the command of player \"" + player.getName() + "\"" : "") + ".");
if (player != null && player != target)
sender.sendMessage("Border bypass for player \"" + sPlayer + "\" is " + enabledColored(bypassing) + ".");
}
});
}
}

View File

@@ -0,0 +1,49 @@
package com.wimbli.WorldBorder.cmd;
import com.wimbli.WorldBorder.Config;
import com.wimbli.WorldBorder.UUID.UUIDFetcher;
import com.wimbli.WorldBorder.WorldBorder;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
public class CmdBypasslist extends WBCmd {
public CmdBypasslist() {
name = permission = "bypasslist";
minParams = maxParams = 0;
addCmdExample(nameEmphasized() + "- list players with border bypass enabled.");
helpText = "The bypass list will persist between server restarts, and applies to all worlds. Use the " +
commandEmphasized("bypass") + C_DESC + "command to add or remove players.";
}
@Override
public void execute(final CommandSender sender, Player player, List<String> params, String worldName) {
final ArrayList<UUID> uuids = Config.getPlayerBypassList();
if (uuids == null || uuids.isEmpty()) {
sender.sendMessage("Players with border bypass enabled: <none>");
return;
}
Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(WorldBorder.plugin, new Runnable() {
@Override
public void run() {
try {
Map<UUID, String> names = UUIDFetcher.getNameList(uuids);
String nameString = names.values().toString();
sender.sendMessage("Players with border bypass enabled: " + nameString.substring(1, nameString.length() - 1));
} catch (Exception ex) {
sendErrorAndHelp(sender, "Failed to look up names for the UUIDs in the border bypass list. " + ex.getLocalizedMessage());
return;
}
}
});
}
}

View File

@@ -0,0 +1,60 @@
package com.wimbli.WorldBorder.cmd;
import com.wimbli.WorldBorder.BorderData;
import com.wimbli.WorldBorder.Config;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.List;
public class CmdClear extends WBCmd {
public CmdClear() {
name = permission = "clear";
hasWorldNameInput = true;
consoleRequiresWorldName = false;
minParams = 0;
maxParams = 1;
addCmdExample(nameEmphasizedW() + "- remove border for this world.");
addCmdExample(nameEmphasized() + "^all - remove border for all worlds.");
helpText = "If run by an in-game player and [world] or \"all\" isn't specified, the world you are currently " +
"in is used.";
}
@Override
public void execute(CommandSender sender, Player player, List<String> params, String worldName) {
// handle "clear all" command separately
if (params.size() == 1 && params.get(0).equalsIgnoreCase("all")) {
if (worldName != null) {
sendErrorAndHelp(sender, "You should not specify a world with \"clear all\".");
return;
}
Config.removeAllBorders();
if (player != null)
sender.sendMessage("All borders have been cleared for all worlds.");
return;
}
if (worldName == null) {
if (player == null) {
sendErrorAndHelp(sender, "You must specify a world name from console if not using \"clear all\".");
return;
}
worldName = player.getWorld().getName();
}
BorderData border = Config.Border(worldName);
if (border == null) {
sendErrorAndHelp(sender, "This world (\"" + worldName + "\") does not have a border set.");
return;
}
Config.removeBorder(worldName);
if (player != null)
sender.sendMessage("Border cleared for world \"" + worldName + "\".");
}
}

View File

@@ -0,0 +1,63 @@
package com.wimbli.WorldBorder.cmd;
import com.wimbli.WorldBorder.WorldBorder;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.List;
public class CmdCommands extends WBCmd {
private static final int pageSize = 8; // examples to list per page; 10 lines available, 1 for header, 1 for footer
public CmdCommands() {
name = "commands";
permission = "help";
hasWorldNameInput = false;
}
@Override
public void execute(CommandSender sender, Player player, List<String> params, String worldName) {
// determine which page we're viewing
int page = (player == null) ? 0 : 1;
if (!params.isEmpty()) {
try {
page = Integer.parseInt(params.get(0));
} catch (NumberFormatException ignored) {
}
}
// see whether we're showing examples to player or to console, and determine number of pages available
List<String> examples = (player == null) ? cmdExamplesConsole : cmdExamplesPlayer;
int pageCount = (int) Math.ceil(examples.size() / (double) pageSize);
// if specified page number is negative or higher than we have available, default back to first page
if (page < 0 || page > pageCount)
page = (player == null) ? 0 : 1;
// send command example header
sender.sendMessage(C_HEAD + WorldBorder.plugin.getDescription().getFullName() + " - key: " +
commandEmphasized("command") + C_REQ + "<required> " + C_OPT + "[optional]");
if (page > 0) {
// send examples for this page
int first = ((page - 1) * pageSize);
int count = Math.min(pageSize, examples.size() - first);
for (int i = first; i < first + count; i++) {
sender.sendMessage(examples.get(i));
}
// send page footer, if relevant; manual spacing to get right side lined up near edge is crude, but sufficient
String footer = C_HEAD + " (Page " + page + "/" + pageCount + ") " + cmd(sender);
if (page < pageCount)
sender.sendMessage(footer + (page + 1) + C_DESC + " - view next page of commands.");
else if (page > 1)
sender.sendMessage(footer + C_DESC + "- view first page of commands.");
} else {
// if page "0" is specified, send all examples; done by default for console but can be specified by player
for (String example : examples) {
sender.sendMessage(example);
}
}
}
}

View File

@@ -0,0 +1,34 @@
package com.wimbli.WorldBorder.cmd;
import com.wimbli.WorldBorder.Config;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.List;
public class CmdDebug extends WBCmd {
public CmdDebug() {
name = permission = "debug";
minParams = maxParams = 1;
addCmdExample(nameEmphasized() + "<on|off> - turn console debug output on or off.");
helpText = "Default value: off. Debug mode will show some extra debugging data in the server console/log when " +
"players are knocked back from the border or are teleported.";
}
@Override
public void cmdStatus(CommandSender sender) {
sender.sendMessage(C_HEAD + "Debug mode is " + enabledColored(Config.Debug()) + C_HEAD + ".");
}
@Override
public void execute(CommandSender sender, Player player, List<String> params, String worldName) {
Config.setDebug(strAsBool(params.get(0)));
if (player != null) {
Config.log((Config.Debug() ? "Enabled" : "Disabled") + " debug output at the command of player \"" + player.getName() + "\".");
cmdStatus(sender);
}
}
}

View File

@@ -0,0 +1,43 @@
package com.wimbli.WorldBorder.cmd;
import com.wimbli.WorldBorder.Config;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.List;
public class CmdDelay extends WBCmd {
public CmdDelay() {
name = permission = "delay";
minParams = maxParams = 1;
addCmdExample(nameEmphasized() + "<amount> - time between border checks.");
helpText = "Default value: 5. The <amount> is in server ticks, of which there are roughly 20 every second, each " +
"tick taking ~50ms. The default value therefore has border checks run about 4 times per second.";
}
@Override
public void cmdStatus(CommandSender sender) {
int delay = Config.TimerTicks();
sender.sendMessage(C_HEAD + "Timer delay is set to " + delay + " tick(s). That is roughly " + (delay * 50) + "ms.");
}
@Override
public void execute(CommandSender sender, Player player, List<String> params, String worldName) {
int delay = 0;
try {
delay = Integer.parseInt(params.get(0));
if (delay < 1)
throw new NumberFormatException();
} catch (NumberFormatException ex) {
sendErrorAndHelp(sender, "The timer delay must be an integer of 1 or higher.");
return;
}
Config.setTimerTicks(delay);
if (player != null)
cmdStatus(sender);
}
}

View File

@@ -0,0 +1,36 @@
package com.wimbli.WorldBorder.cmd;
import com.wimbli.WorldBorder.Config;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.List;
public class CmdDenypearl extends WBCmd {
public CmdDenypearl() {
name = permission = "denypearl";
minParams = maxParams = 1;
addCmdExample(nameEmphasized() + "<on|off> - stop ender pearls past the border.");
helpText = "Default value: on. When enabled, this setting will directly cancel attempts to use an ender pearl to " +
"get past the border rather than just knocking the player back. This should prevent usage of ender " +
"pearls to glitch into areas otherwise inaccessible at the border edge.";
}
@Override
public void cmdStatus(CommandSender sender) {
sender.sendMessage(C_HEAD + "Direct cancellation of ender pearls thrown past the border is " +
enabledColored(Config.getDenyEnderpearl()) + C_HEAD + ".");
}
@Override
public void execute(CommandSender sender, Player player, List<String> params, String worldName) {
Config.setDenyEnderpearl(strAsBool(params.get(0)));
if (player != null) {
Config.log((Config.getDenyEnderpearl() ? "Enabled" : "Disabled") + " direct cancellation of ender pearls thrown past the border at the command of player \"" + player.getName() + "\".");
cmdStatus(sender);
}
}
}

View File

@@ -0,0 +1,34 @@
package com.wimbli.WorldBorder.cmd;
import com.wimbli.WorldBorder.Config;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.List;
public class CmdDynmap extends WBCmd {
public CmdDynmap() {
name = permission = "dynmap";
minParams = maxParams = 1;
addCmdExample(nameEmphasized() + "<on|off> - turn DynMap border display on or off.");
helpText = "Default value: on. If you are running the DynMap plugin and this setting is enabled, all borders will " +
"be visually shown in DynMap.";
}
@Override
public void cmdStatus(CommandSender sender) {
sender.sendMessage(C_HEAD + "DynMap border display is " + enabledColored(Config.DynmapBorderEnabled()) + C_HEAD + ".");
}
@Override
public void execute(CommandSender sender, Player player, List<String> params, String worldName) {
Config.setDynmapBorderEnabled(strAsBool(params.get(0)));
if (player != null) {
cmdStatus(sender);
Config.log((Config.DynmapBorderEnabled() ? "Enabled" : "Disabled") + " DynMap border display at the command of player \"" + player.getName() + "\".");
}
}
}

View File

@@ -0,0 +1,42 @@
package com.wimbli.WorldBorder.cmd;
import com.wimbli.WorldBorder.Config;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.List;
public class CmdDynmaplabel extends WBCmd {
public CmdDynmaplabel() {
name = permission = "dynmaplabel";
minParams = 1;
addCmdExample(nameEmphasized() + "<text> - DynMap border layer labels will show this.");
helpText = "Default value: \"WorldBorder.\". If you are running the DynMap plugin and the " +
commandEmphasized("dynmap") + C_DESC + "command setting is enabled, the border layer shown in DynMap will " +
"be labelled with this text.";
}
@Override
public void cmdStatus(CommandSender sender) {
sender.sendMessage(C_HEAD + "DynMap border layer label is set to: " + C_ERR + Config.DynmapLayerLabel());
}
@Override
public void execute(CommandSender sender, Player player, List<String> params, String worldName) {
StringBuilder message = new StringBuilder();
boolean first = true;
for (String param : params) {
if (!first)
message.append(" ");
message.append(param);
first = false;
}
Config.setDynmapLayerLabel(message.toString());
if (player != null)
cmdStatus(sender);
}
}

View File

@@ -0,0 +1,42 @@
package com.wimbli.WorldBorder.cmd;
import com.wimbli.WorldBorder.Config;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.List;
public class CmdDynmapmsg extends WBCmd {
public CmdDynmapmsg() {
name = permission = "dynmapmsg";
minParams = 1;
addCmdExample(nameEmphasized() + "<text> - DynMap border labels will show this.");
helpText = "Default value: \"The border of the world.\". If you are running the DynMap plugin and the " +
commandEmphasized("dynmap") + C_DESC + "command setting is enabled, the borders shown in DynMap will " +
"be labelled with this text.";
}
@Override
public void cmdStatus(CommandSender sender) {
sender.sendMessage(C_HEAD + "DynMap border label is set to: " + C_ERR + Config.DynmapMessage());
}
@Override
public void execute(CommandSender sender, Player player, List<String> params, String worldName) {
StringBuilder message = new StringBuilder();
boolean first = true;
for (String param : params) {
if (!first)
message.append(" ");
message.append(param);
first = false;
}
Config.setDynmapMessage(message.toString());
if (player != null)
cmdStatus(sender);
}
}

View File

@@ -0,0 +1,161 @@
package com.wimbli.WorldBorder.cmd;
import com.wimbli.WorldBorder.Config;
import com.wimbli.WorldBorder.CoordXZ;
import com.wimbli.WorldBorder.WorldBorder;
import com.wimbli.WorldBorder.WorldFillTask;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.List;
public class CmdFill extends WBCmd {
/* with "view-distance=10" in server.properties on a fast VM test server and "Render Distance: Far" in client,
* hitting border during testing was loading 11+ chunks beyond the border in a couple of directions (10 chunks in
* the other two directions). This could be worse on a more loaded or worse server, so:
*/
private final int defaultPadding = CoordXZ.chunkToBlock(13);
private String fillWorld = "";
private int fillFrequency = 20;
private int fillPadding = defaultPadding;
private boolean fillForceLoad = false;
public CmdFill() {
name = permission = "fill";
hasWorldNameInput = true;
consoleRequiresWorldName = false;
minParams = 0;
maxParams = 3;
addCmdExample(nameEmphasizedW() + "[freq] [pad] [force] - fill world to border.");
helpText = "This command will generate missing world chunks inside your border. [freq] is the frequency " +
"of chunks per second that will be checked (default 20). [pad] is the number of blocks padding added " +
"beyond the border itself (default 208, to cover player visual range). [force] can be specified as true " +
"to force all chunks to be loaded even if they seem to be fully generated (default false).";
}
@Override
public void execute(CommandSender sender, Player player, List<String> params, String worldName) {
boolean confirm = false;
// check for "cancel", "pause", or "confirm"
if (params.size() >= 1) {
String check = params.get(0).toLowerCase();
if (check.equals("cancel") || check.equals("stop")) {
if (!makeSureFillIsRunning(sender))
return;
sender.sendMessage(C_HEAD + "Cancelling the world map generation task.");
fillDefaults();
Config.StopFillTask(true);
return;
} else if (check.equals("pause")) {
if (!makeSureFillIsRunning(sender))
return;
Config.fillTask.pause();
sender.sendMessage(C_HEAD + "The world map generation task is now " + (Config.fillTask.isPaused() ? "" : "un") + "paused.");
return;
}
confirm = check.equals("confirm");
}
// if not just confirming, make sure a world name is available
if (worldName == null && !confirm) {
if (player != null)
worldName = player.getWorld().getName();
else {
sendErrorAndHelp(sender, "You must specify a world!");
return;
}
}
// colorized "/wb fill "
String cmd = cmd(sender) + nameEmphasized() + C_CMD;
// make sure Fill isn't already running
if (Config.fillTask != null && Config.fillTask.valid()) {
sender.sendMessage(C_ERR + "The world map generation task is already running.");
sender.sendMessage(C_DESC + "You can cancel at any time with " + cmd + "cancel" + C_DESC + ", or pause/unpause with " + cmd + "pause" + C_DESC + ".");
return;
}
// set frequency and/or padding if those were specified
try {
if (params.size() >= 1 && !confirm)
fillFrequency = Math.abs(Integer.parseInt(params.get(0)));
if (params.size() >= 2 && !confirm)
fillPadding = Math.abs(Integer.parseInt(params.get(1)));
} catch (NumberFormatException ex) {
sendErrorAndHelp(sender, "The frequency and padding values must be integers.");
fillDefaults();
return;
}
if (fillFrequency <= 0) {
sendErrorAndHelp(sender, "The frequency value must be greater than zero.");
fillDefaults();
return;
}
// see if the command specifies to load even chunks which should already be fully generated
if (params.size() == 3)
fillForceLoad = strAsBool(params.get(2));
// set world if it was specified
if (worldName != null)
fillWorld = worldName;
if (confirm) { // command confirmed, go ahead with it
if (fillWorld.isEmpty()) {
sendErrorAndHelp(sender, "You must first use this command successfully without confirming.");
return;
}
if (player != null)
Config.log("Filling out world to border at the command of player \"" + player.getName() + "\".");
int ticks = 1, repeats = 1;
if (fillFrequency > 20)
repeats = fillFrequency / 20;
else
ticks = 20 / fillFrequency;
/* */
Config.log("world: " + fillWorld + " padding: " + fillPadding + " repeats: " + repeats + " ticks: " + ticks);
Config.fillTask = new WorldFillTask(Bukkit.getServer(), player, fillWorld, fillPadding, repeats, ticks, fillForceLoad);
if (Config.fillTask.valid()) {
int task = Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(WorldBorder.plugin, Config.fillTask, ticks, ticks);
Config.fillTask.setTaskID(task);
sender.sendMessage("WorldBorder map generation task for world \"" + fillWorld + "\" started.");
} else
sender.sendMessage(C_ERR + "The world map generation task failed to start.");
fillDefaults();
} else {
if (fillWorld.isEmpty()) {
sendErrorAndHelp(sender, "You must first specify a valid world.");
return;
}
sender.sendMessage(C_HEAD + "World generation task is ready for world \"" + fillWorld + "\", attempting to process up to " + fillFrequency + " chunks per second (default 20). The map will be padded out " + fillPadding + " blocks beyond the border (default " + defaultPadding + "). Parts of the world which are already fully generated will be " + (fillForceLoad ? "loaded anyway." : "skipped."));
sender.sendMessage(C_HEAD + "This process can take a very long time depending on the world's border size. Also, depending on the chunk processing rate, players will likely experience severe lag for the duration.");
sender.sendMessage(C_DESC + "You should now use " + cmd + "confirm" + C_DESC + " to start the process.");
sender.sendMessage(C_DESC + "You can cancel at any time with " + cmd + "cancel" + C_DESC + ", or pause/unpause with " + cmd + "pause" + C_DESC + ".");
}
}
private void fillDefaults() {
fillWorld = "";
fillFrequency = 20;
fillPadding = defaultPadding;
fillForceLoad = false;
}
private boolean makeSureFillIsRunning(CommandSender sender) {
if (Config.fillTask != null && Config.fillTask.valid())
return true;
sendErrorAndHelp(sender, "The world map generation task is not currently running.");
return false;
}
}

View File

@@ -0,0 +1,50 @@
package com.wimbli.WorldBorder.cmd;
import com.wimbli.WorldBorder.Config;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.List;
public class CmdFillautosave extends WBCmd {
public CmdFillautosave() {
name = permission = "fillautosave";
minParams = maxParams = 1;
addCmdExample(nameEmphasized() + "<seconds> - world save interval for Fill.");
helpText = "Default value: 30 seconds.";
}
@Override
public void cmdStatus(CommandSender sender) {
int seconds = Config.FillAutosaveFrequency();
if (seconds == 0) {
sender.sendMessage(C_HEAD + "World autosave frequency during Fill process is set to 0, disabling it.");
sender.sendMessage(C_HEAD + "Note that much progress can be lost this way if there is a bug or crash in " +
"the world generation process from Bukkit or any world generation plugin you use.");
} else {
sender.sendMessage(C_HEAD + "World autosave frequency during Fill process is set to " + seconds + " seconds (rounded to a multiple of 5).");
sender.sendMessage(C_HEAD + "New chunks generated by the Fill process will be forcibly saved to disk " +
"this often to prevent loss of progress due to bugs or crashes in the world generation process.");
}
}
@Override
public void execute(CommandSender sender, Player player, List<String> params, String worldName) {
int seconds = 0;
try {
seconds = Integer.parseInt(params.get(0));
if (seconds < 0)
throw new NumberFormatException();
} catch (NumberFormatException ex) {
sendErrorAndHelp(sender, "The world autosave frequency must be an integer of 0 or higher. Setting to 0 will disable autosaving of the world during the Fill process.");
return;
}
Config.setFillAutosaveFrequency(seconds);
if (player != null)
cmdStatus(sender);
}
}

View File

@@ -0,0 +1,26 @@
package com.wimbli.WorldBorder.cmd;
import com.wimbli.WorldBorder.Config;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.List;
public class CmdGetmsg extends WBCmd {
public CmdGetmsg() {
name = permission = "getmsg";
minParams = maxParams = 0;
addCmdExample(nameEmphasized() + "- display border message.");
helpText = "This command simply displays the message shown to players knocked back from the border.";
}
@Override
public void execute(CommandSender sender, Player player, List<String> params, String worldName) {
sender.sendMessage("Border message is currently set to:");
sender.sendMessage(Config.MessageRaw());
sender.sendMessage("Formatted border message:");
sender.sendMessage(Config.Message());
}
}

View File

@@ -0,0 +1,45 @@
package com.wimbli.WorldBorder.cmd;
import com.wimbli.WorldBorder.WorldBorder;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.List;
import java.util.Set;
public class CmdHelp extends WBCmd {
public CmdHelp() {
name = permission = "help";
minParams = 0;
maxParams = 10;
addCmdExample(nameEmphasized() + "[command] - get help on command usage.");
// helpText = "If [command] is specified, info for that particular command will be provided.";
}
@Override
public void cmdStatus(CommandSender sender) {
String commands = WorldBorder.wbCommand.getCommandNames().toString().replace(", ", C_DESC + ", " + C_CMD);
sender.sendMessage(C_HEAD + "Commands: " + C_CMD + commands.substring(1, commands.length() - 1));
sender.sendMessage("Example, for info on \"set\" command: " + cmd(sender) + nameEmphasized() + C_CMD + "set");
sender.sendMessage(C_HEAD + "For a full command example list, simply run the root " + cmd(sender) + C_HEAD + "command by itself with nothing specified.");
}
@Override
public void execute(CommandSender sender, Player player, List<String> params, String worldName) {
if (params.isEmpty()) {
sendCmdHelp(sender);
return;
}
Set<String> commands = WorldBorder.wbCommand.getCommandNames();
for (String param : params) {
if (commands.contains(param.toLowerCase())) {
WorldBorder.wbCommand.subCommands.get(param.toLowerCase()).sendCmdHelp(sender);
return;
}
}
sendErrorAndHelp(sender, "No command recognized.");
}
}

View File

@@ -0,0 +1,45 @@
package com.wimbli.WorldBorder.cmd;
import com.wimbli.WorldBorder.Config;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.List;
public class CmdKnockback extends WBCmd {
public CmdKnockback() {
name = permission = "knockback";
minParams = maxParams = 1;
addCmdExample(nameEmphasized() + "<distance> - how far to move the player back.");
helpText = "Default value: 3.0 (blocks). Players who cross the border will be knocked back to this distance inside.";
}
@Override
public void cmdStatus(CommandSender sender) {
double kb = Config.KnockBack();
if (kb < 1)
sender.sendMessage(C_HEAD + "Knockback is set to 0, disabling border enforcement.");
else
sender.sendMessage(C_HEAD + "Knockback is set to " + kb + " blocks inside the border.");
}
@Override
public void execute(CommandSender sender, Player player, List<String> params, String worldName) {
double numBlocks = 0.0;
try {
numBlocks = Double.parseDouble(params.get(0));
if (numBlocks < 0.0 || (numBlocks > 0.0 && numBlocks < 1.0))
throw new NumberFormatException();
} catch (NumberFormatException ex) {
sendErrorAndHelp(sender, "The knockback must be a decimal value of at least 1.0, or it can be 0.");
return;
}
Config.setKnockBack(numBlocks);
if (player != null)
cmdStatus(sender);
}
}

View File

@@ -0,0 +1,36 @@
package com.wimbli.WorldBorder.cmd;
import com.wimbli.WorldBorder.Config;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.List;
import java.util.Set;
public class CmdList extends WBCmd {
public CmdList() {
name = permission = "list";
minParams = maxParams = 0;
addCmdExample(nameEmphasized() + "- show border information for all worlds.");
helpText = "This command will list full information for every border you have set including position, " +
"radius, and shape. The default border shape will also be indicated.";
}
@Override
public void execute(CommandSender sender, Player player, List<String> params, String worldName) {
sender.sendMessage("Default border shape for all worlds is \"" + Config.ShapeName() + "\".");
Set<String> list = Config.BorderDescriptions();
if (list.isEmpty()) {
sender.sendMessage("There are no borders currently set.");
return;
}
for (String borderDesc : list) {
sender.sendMessage(borderDesc);
}
}
}

View File

@@ -0,0 +1,35 @@
package com.wimbli.WorldBorder.cmd;
import com.wimbli.WorldBorder.Config;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.List;
public class CmdPortal extends WBCmd {
public CmdPortal() {
name = permission = "portal";
minParams = maxParams = 1;
addCmdExample(nameEmphasized() + "<on|off> - turn portal redirection on or off.");
helpText = "Default value: on. This feature monitors new portal creation and changes the target new portal " +
"location if it is outside of the border. Try disabling this if you have problems with other plugins " +
"related to portals.";
}
@Override
public void cmdStatus(CommandSender sender) {
sender.sendMessage(C_HEAD + "Portal redirection is " + enabledColored(Config.portalRedirection()) + C_HEAD + ".");
}
@Override
public void execute(CommandSender sender, Player player, List<String> params, String worldName) {
Config.setPortalRedirection(strAsBool(params.get(0)));
if (player != null) {
Config.log((Config.portalRedirection() ? "Enabled" : "Disabled") + " portal redirection at the command of player \"" + player.getName() + "\".");
cmdStatus(sender);
}
}
}

View File

@@ -0,0 +1,33 @@
package com.wimbli.WorldBorder.cmd;
import com.wimbli.WorldBorder.Config;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.List;
public class CmdPreventPlace extends WBCmd {
public CmdPreventPlace() {
name = permission = "preventblockplace";
minParams = maxParams = 1;
addCmdExample(nameEmphasized() + "<on|off> - stop block placement past border.");
helpText = "Default value: off. When enabled, this setting will prevent players from placing blocks outside the world's border.";
}
@Override
public void cmdStatus(CommandSender sender) {
sender.sendMessage(C_HEAD + "Prevention of block placement outside the border is " + enabledColored(Config.preventBlockPlace()) + C_HEAD + ".");
}
@Override
public void execute(CommandSender sender, Player player, List<String> params, String worldName) {
Config.setPreventBlockPlace(strAsBool(params.get(0)));
if (player != null) {
Config.log((Config.preventBlockPlace() ? "Enabled" : "Disabled") + " preventblockplace at the command of player \"" + player.getName() + "\".");
cmdStatus(sender);
}
}
}

View File

@@ -0,0 +1,33 @@
package com.wimbli.WorldBorder.cmd;
import com.wimbli.WorldBorder.Config;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.List;
public class CmdPreventSpawn extends WBCmd {
public CmdPreventSpawn() {
name = permission = "preventmobspawn";
minParams = maxParams = 1;
addCmdExample(nameEmphasized() + "<on|off> - stop mob spawning past border.");
helpText = "Default value: off. When enabled, this setting will prevent mobs from naturally spawning outside the world's border.";
}
@Override
public void cmdStatus(CommandSender sender) {
sender.sendMessage(C_HEAD + "Prevention of mob spawning outside the border is " + enabledColored(Config.preventMobSpawn()) + C_HEAD + ".");
}
@Override
public void execute(CommandSender sender, Player player, List<String> params, String worldName) {
Config.setPreventMobSpawn(strAsBool(params.get(0)));
if (player != null) {
Config.log((Config.preventMobSpawn() ? "Enabled" : "Disabled") + " preventmobspawn at the command of player \"" + player.getName() + "\".");
cmdStatus(sender);
}
}
}

View File

@@ -0,0 +1,74 @@
package com.wimbli.WorldBorder.cmd;
import com.wimbli.WorldBorder.BorderData;
import com.wimbli.WorldBorder.Config;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.List;
public class CmdRadius extends WBCmd {
public CmdRadius() {
name = permission = "radius";
hasWorldNameInput = true;
minParams = 1;
maxParams = 2;
addCmdExample(nameEmphasizedW() + "<radiusX> [radiusZ] - change radius.");
helpText = "Using this command you can adjust the radius of an existing border. If [radiusZ] is not " +
"specified, the radiusX value will be used for both. You can also optionally specify + or - at the start " +
"of <radiusX> and [radiusZ] to increase or decrease the existing radius rather than setting a new value.";
}
@Override
public void execute(CommandSender sender, Player player, List<String> params, String worldName) {
if (worldName == null)
worldName = player.getWorld().getName();
BorderData border = Config.Border(worldName);
if (border == null) {
sendErrorAndHelp(sender, "This world (\"" + worldName + "\") must first have a border set normally.");
return;
}
double x = border.getX();
double z = border.getZ();
double radiusX;
double radiusZ;
try {
if (params.get(0).startsWith("+")) {
// Add to the current radius
radiusX = border.getRadiusX();
radiusX += Integer.parseInt(params.get(0).substring(1));
} else if (params.get(0).startsWith("-")) {
// Subtract from the current radius
radiusX = border.getRadiusX();
radiusX -= Integer.parseInt(params.get(0).substring(1));
} else
radiusX = Integer.parseInt(params.get(0));
if (params.size() == 2) {
if (params.get(1).startsWith("+")) {
// Add to the current radius
radiusZ = border.getRadiusZ();
radiusZ += Integer.parseInt(params.get(1).substring(1));
} else if (params.get(1).startsWith("-")) {
// Subtract from the current radius
radiusZ = border.getRadiusZ();
radiusZ -= Integer.parseInt(params.get(1).substring(1));
} else
radiusZ = Integer.parseInt(params.get(1));
} else
radiusZ = radiusX;
} catch (NumberFormatException ex) {
sendErrorAndHelp(sender, "The radius value(s) must be integers.");
return;
}
Config.setBorder(worldName, radiusX, radiusZ, x, z);
if (player != null)
sender.sendMessage("Radius has been set. " + Config.BorderDescription(worldName));
}
}

View File

@@ -0,0 +1,31 @@
package com.wimbli.WorldBorder.cmd;
import com.wimbli.WorldBorder.Config;
import com.wimbli.WorldBorder.WorldBorder;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.List;
public class CmdReload extends WBCmd {
public CmdReload() {
name = permission = "reload";
minParams = maxParams = 0;
addCmdExample(nameEmphasized() + "- re-load data from config.yml.");
helpText = "If you make manual changes to config.yml while the server is running, you can use this command " +
"to make WorldBorder load the changes without needing to restart the server.";
}
@Override
public void execute(CommandSender sender, Player player, List<String> params, String worldName) {
if (player != null)
Config.log("Reloading config file at the command of player \"" + player.getName() + "\".");
Config.load(WorldBorder.plugin, true);
if (player != null)
sender.sendMessage("WorldBorder configuration reloaded.");
}
}

View File

@@ -0,0 +1,50 @@
package com.wimbli.WorldBorder.cmd;
import com.wimbli.WorldBorder.Config;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.List;
public class CmdRemount extends WBCmd {
public CmdRemount() {
name = permission = "remount";
minParams = maxParams = 1;
addCmdExample(nameEmphasized() + "<amount> - player remount delay after knockback.");
helpText = "Default value: 0 (disabled). If set higher than 0, WorldBorder will attempt to re-mount players who " +
"are knocked back from the border while riding something after this many server ticks. This setting can " +
"cause really nasty glitches if enabled and set too low due to CraftBukkit teleportation problems.";
}
@Override
public void cmdStatus(CommandSender sender) {
int delay = Config.RemountTicks();
if (delay == 0)
sender.sendMessage(C_HEAD + "Remount delay set to 0. Players will be left dismounted when knocked back from the border while on a vehicle.");
else {
sender.sendMessage(C_HEAD + "Remount delay set to " + delay + " tick(s). That is roughly " + (delay * 50) + "ms / " + (((double) delay * 50.0) / 1000.0) + " seconds. Setting to 0 would disable remounting.");
if (delay < 10)
sender.sendMessage(C_ERR + "WARNING:" + C_DESC + " setting this to less than 10 (and greater than 0) is not recommended. This can lead to nasty client glitches.");
}
}
@Override
public void execute(CommandSender sender, Player player, List<String> params, String worldName) {
int delay = 0;
try {
delay = Integer.parseInt(params.get(0));
if (delay < 0)
throw new NumberFormatException();
} catch (NumberFormatException ex) {
sendErrorAndHelp(sender, "The remount delay must be an integer of 0 or higher. Setting to 0 will disable remounting.");
return;
}
Config.setRemountTicks(delay);
if (player != null)
cmdStatus(sender);
}
}

View File

@@ -0,0 +1,119 @@
package com.wimbli.WorldBorder.cmd;
import com.wimbli.WorldBorder.Config;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.List;
public class CmdSet extends WBCmd {
public CmdSet() {
name = permission = "set";
hasWorldNameInput = true;
consoleRequiresWorldName = false;
minParams = 1;
maxParams = 4;
addCmdExample(nameEmphasizedW() + "<radiusX> [radiusZ] <x> <z> - use x/z coords.");
addCmdExample(nameEmphasizedW() + "<radiusX> [radiusZ] ^spawn - use spawn point.");
addCmdExample(nameEmphasized() + "<radiusX> [radiusZ] - set border, centered on you.", true, false, true);
addCmdExample(nameEmphasized() + "<radiusX> [radiusZ] ^player <name> - center on player.");
helpText = "Set a border for a world, with several options for defining the center location. [world] is " +
"optional for players and defaults to the world the player is in. If [radiusZ] is not specified, the " +
"radiusX value will be used for both. The <x> and <z> coordinates can be decimal values (ex. 1.234).";
}
@Override
public void execute(CommandSender sender, Player player, List<String> params, String worldName) {
// passsing a single parameter (radiusX) is only acceptable from player
if ((params.size() == 1) && player == null) {
sendErrorAndHelp(sender, "You have not provided a sufficient number of parameters.");
return;
}
// "set" command from player or console, world specified
if (worldName != null) {
if (params.size() == 2 && !params.get(params.size() - 1).equalsIgnoreCase("spawn")) { // command can only be this short if "spawn" is specified rather than x + z or player name
sendErrorAndHelp(sender, "You have not provided a sufficient number of arguments.");
return;
}
World world = sender.getServer().getWorld(worldName);
if (world == null) {
if (params.get(params.size() - 1).equalsIgnoreCase("spawn")) {
sendErrorAndHelp(sender, "The world you specified (\"" + worldName + "\") could not be found on the server, so the spawn point cannot be determined.");
return;
}
sender.sendMessage("The world you specified (\"" + worldName + "\") could not be found on the server, but data for it will be stored anyway.");
}
}
// "set" command from player using current world since it isn't specified, or allowed from console only if player name is specified
else {
if (player == null) {
if (!params.get(params.size() - 2).equalsIgnoreCase("player")) { // command can only be called by console without world specified if player is specified instead
sendErrorAndHelp(sender, "You must specify a world name from console if not specifying a player name.");
return;
}
player = Bukkit.getPlayer(params.get(params.size() - 1));
if (player == null || !player.isOnline()) {
sendErrorAndHelp(sender, "The player you specified (\"" + params.get(params.size() - 1) + "\") does not appear to be online.");
return;
}
}
worldName = player.getWorld().getName();
}
int radiusX, radiusZ;
double x, z;
int radiusCount = params.size();
try {
if (params.get(params.size() - 1).equalsIgnoreCase("spawn")) { // "spawn" specified for x/z coordinates
Location loc = sender.getServer().getWorld(worldName).getSpawnLocation();
x = loc.getX();
z = loc.getZ();
radiusCount -= 1;
} else if (params.size() > 2 && params.get(params.size() - 2).equalsIgnoreCase("player")) { // player name specified for x/z coordinates
Player playerT = Bukkit.getPlayer(params.get(params.size() - 1));
if (playerT == null || !playerT.isOnline()) {
sendErrorAndHelp(sender, "The player you specified (\"" + params.get(params.size() - 1) + "\") does not appear to be online.");
return;
}
worldName = playerT.getWorld().getName();
x = playerT.getLocation().getX();
z = playerT.getLocation().getZ();
radiusCount -= 2;
} else {
if (player == null || radiusCount > 2) { // x and z specified
x = Double.parseDouble(params.get(params.size() - 2));
z = Double.parseDouble(params.get(params.size() - 1));
radiusCount -= 2;
} else { // using coordinates of command sender (player)
x = player.getLocation().getX();
z = player.getLocation().getZ();
}
}
radiusX = Integer.parseInt(params.get(0));
if (radiusCount < 2)
radiusZ = radiusX;
else
radiusZ = Integer.parseInt(params.get(1));
if (radiusX < Config.KnockBack() || radiusZ < Config.KnockBack()) {
sendErrorAndHelp(sender, "Radius value(s) must be more than the knockback distance.");
return;
}
} catch (NumberFormatException ex) {
sendErrorAndHelp(sender, "Radius value(s) must be integers and x and z values must be numerical.");
return;
}
Config.setBorder(worldName, radiusX, radiusZ, x, z);
sender.sendMessage("Border has been set. " + Config.BorderDescription(worldName));
}
}

View File

@@ -0,0 +1,48 @@
package com.wimbli.WorldBorder.cmd;
import com.wimbli.WorldBorder.Config;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.List;
public class CmdSetcorners extends WBCmd {
public CmdSetcorners() {
name = "setcorners";
permission = "set";
hasWorldNameInput = true;
minParams = maxParams = 4;
addCmdExample(nameEmphasizedW() + "<x1> <z1> <x2> <z2> - corner coords.");
helpText = "This is an alternate way to set a border, by specifying the X and Z coordinates of two opposite " +
"corners of the border area ((x1, z1) to (x2, z2)). [world] is optional for players and defaults to the " +
"world the player is in.";
}
@Override
public void execute(CommandSender sender, Player player, List<String> params, String worldName) {
if (worldName == null) {
worldName = player.getWorld().getName();
} else {
World worldTest = sender.getServer().getWorld(worldName);
if (worldTest == null)
sender.sendMessage("The world you specified (\"" + worldName + "\") could not be found on the server, but data for it will be stored anyway.");
}
try {
double x1 = Double.parseDouble(params.get(0));
double z1 = Double.parseDouble(params.get(1));
double x2 = Double.parseDouble(params.get(2));
double z2 = Double.parseDouble(params.get(3));
Config.setBorderCorners(worldName, x1, z1, x2, z2);
} catch (NumberFormatException ex) {
sendErrorAndHelp(sender, "The x1, z1, x2, and z2 coordinate values must be numerical.");
return;
}
if (player != null)
sender.sendMessage("Border has been set. " + Config.BorderDescription(worldName));
}
}

View File

@@ -0,0 +1,42 @@
package com.wimbli.WorldBorder.cmd;
import com.wimbli.WorldBorder.Config;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.List;
public class CmdSetmsg extends WBCmd {
public CmdSetmsg() {
name = permission = "setmsg";
minParams = 1;
addCmdExample(nameEmphasized() + "<text> - set border message.");
helpText = "Default value: \"&cYou have reached the edge of this world.\". This command lets you set the message shown to players who are knocked back from the border.";
}
@Override
public void cmdStatus(CommandSender sender) {
sender.sendMessage(C_HEAD + "Border message is set to:");
sender.sendMessage(Config.MessageRaw());
sender.sendMessage(C_HEAD + "Formatted border message:");
sender.sendMessage(Config.Message());
}
@Override
public void execute(CommandSender sender, Player player, List<String> params, String worldName) {
StringBuilder message = new StringBuilder();
boolean first = true;
for (String param : params) {
if (!first)
message.append(" ");
message.append(param);
first = false;
}
Config.setMessage(message.toString());
cmdStatus(sender);
}
}

View File

@@ -0,0 +1,43 @@
package com.wimbli.WorldBorder.cmd;
import com.wimbli.WorldBorder.Config;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.List;
public class CmdShape extends WBCmd {
public CmdShape() {
name = permission = "shape";
minParams = maxParams = 1;
addCmdExample(nameEmphasized() + "<round|square> - set the default border shape.");
addCmdExample(nameEmphasized() + "<elliptic|rectangular> - same as above.");
helpText = "Default value: square/rectangular. The default border shape will be used on all worlds which don't " +
"have an individual shape set using the " + commandEmphasized("wshape") + C_DESC + "command. Elliptic " +
"and round work the same, as rectangular and square do. The difference is down to whether the X and Z " +
"radius are the same.";
}
@Override
public void cmdStatus(CommandSender sender) {
sender.sendMessage(C_HEAD + "The default border shape for all worlds is currently set to \"" + Config.ShapeName() + "\".");
}
@Override
public void execute(CommandSender sender, Player player, List<String> params, String worldName) {
String shape = params.get(0).toLowerCase();
if (shape.equals("rectangular") || shape.equals("square"))
Config.setShape(false);
else if (shape.equals("elliptic") || shape.equals("round"))
Config.setShape(true);
else {
sendErrorAndHelp(sender, "You must specify one of the 4 valid shape names below.");
return;
}
if (player != null)
cmdStatus(sender);
}
}

View File

@@ -0,0 +1,152 @@
package com.wimbli.WorldBorder.cmd;
import com.wimbli.WorldBorder.Config;
import com.wimbli.WorldBorder.CoordXZ;
import com.wimbli.WorldBorder.WorldBorder;
import com.wimbli.WorldBorder.WorldTrimTask;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.List;
public class CmdTrim extends WBCmd {
/* with "view-distance=10" in server.properties on a fast VM test server and "Render Distance: Far" in client,
* hitting border during testing was loading 11+ chunks beyond the border in a couple of directions (10 chunks in
* the other two directions). This could be worse on a more loaded or worse server, so:
*/
private final int defaultPadding = CoordXZ.chunkToBlock(13);
private String trimWorld = "";
private int trimFrequency = 5000;
private int trimPadding = defaultPadding;
public CmdTrim() {
name = permission = "trim";
hasWorldNameInput = true;
consoleRequiresWorldName = false;
minParams = 0;
maxParams = 2;
addCmdExample(nameEmphasizedW() + "[freq] [pad] - trim world outside of border.");
helpText = "This command will remove chunks which are outside the world's border (even modified chunks!). [freq] is the frequency " +
"of chunks per second that will be checked (default 5000). [pad] is the number of blocks padding kept " +
"beyond the border itself (default 208, to cover player visual range).";
}
@Override
public void execute(CommandSender sender, Player player, List<String> params, String worldName) {
boolean confirm = false;
// check for "cancel", "pause", or "confirm"
if (params.size() >= 1) {
String check = params.get(0).toLowerCase();
if (check.equals("cancel") || check.equals("stop")) {
if (!makeSureTrimIsRunning(sender))
return;
sender.sendMessage(C_HEAD + "Cancelling the world map trimming task.");
trimDefaults();
Config.StopTrimTask();
return;
} else if (check.equals("pause")) {
if (!makeSureTrimIsRunning(sender))
return;
Config.trimTask.pause();
sender.sendMessage(C_HEAD + "The world map trimming task is now " + (Config.trimTask.isPaused() ? "" : "un") + "paused.");
return;
}
confirm = check.equals("confirm");
}
// if not just confirming, make sure a world name is available
if (worldName == null && !confirm) {
if (player != null)
worldName = player.getWorld().getName();
else {
sendErrorAndHelp(sender, "You must specify a world!");
return;
}
}
// colorized "/wb trim "
String cmd = cmd(sender) + nameEmphasized() + C_CMD;
// make sure Trim isn't already running
if (Config.trimTask != null && Config.trimTask.valid()) {
sender.sendMessage(C_ERR + "The world map trimming task is already running.");
sender.sendMessage(C_DESC + "You can cancel at any time with " + cmd + "cancel" + C_DESC + ", or pause/unpause with " + cmd + "pause" + C_DESC + ".");
return;
}
// set frequency and/or padding if those were specified
try {
if (params.size() >= 1 && !confirm)
trimFrequency = Math.abs(Integer.parseInt(params.get(0)));
if (params.size() >= 2 && !confirm)
trimPadding = Math.abs(Integer.parseInt(params.get(1)));
} catch (NumberFormatException ex) {
sendErrorAndHelp(sender, "The frequency and padding values must be integers.");
trimDefaults();
return;
}
if (trimFrequency <= 0) {
sendErrorAndHelp(sender, "The frequency value must be greater than zero.");
trimDefaults();
return;
}
// set world if it was specified
if (worldName != null)
trimWorld = worldName;
if (confirm) { // command confirmed, go ahead with it
if (trimWorld.isEmpty()) {
sendErrorAndHelp(sender, "You must first use this command successfully without confirming.");
return;
}
if (player != null)
Config.log("Trimming world beyond border at the command of player \"" + player.getName() + "\".");
int ticks = 1, repeats = 1;
if (trimFrequency > 20)
repeats = trimFrequency / 20;
else
ticks = 20 / trimFrequency;
Config.trimTask = new WorldTrimTask(Bukkit.getServer(), player, trimWorld, trimPadding, repeats);
if (Config.trimTask.valid()) {
int task = Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(WorldBorder.plugin, Config.trimTask, ticks, ticks);
Config.trimTask.setTaskID(task);
sender.sendMessage("WorldBorder map trimming task for world \"" + trimWorld + "\" started.");
} else
sender.sendMessage(C_ERR + "The world map trimming task failed to start.");
trimDefaults();
} else {
if (trimWorld.isEmpty()) {
sendErrorAndHelp(sender, "You must first specify a valid world.");
return;
}
sender.sendMessage(C_HEAD + "World trimming task is ready for world \"" + trimWorld + "\", attempting to process up to " + trimFrequency + " chunks per second (default 20). The map will be trimmed past " + trimPadding + " blocks beyond the border (default " + defaultPadding + ").");
sender.sendMessage(C_HEAD + "This process can take a very long time depending on the world's overall size. Also, depending on the chunk processing rate, players may experience lag for the duration.");
sender.sendMessage(C_DESC + "You should now use " + cmd + "confirm" + C_DESC + " to start the process.");
sender.sendMessage(C_DESC + "You can cancel at any time with " + cmd + "cancel" + C_DESC + ", or pause/unpause with " + cmd + "pause" + C_DESC + ".");
}
}
private void trimDefaults() {
trimWorld = "";
trimFrequency = 5000;
trimPadding = defaultPadding;
}
private boolean makeSureTrimIsRunning(CommandSender sender) {
if (Config.trimTask != null && Config.trimTask.valid())
return true;
sendErrorAndHelp(sender, "The world map trimming task is not currently running.");
return false;
}
}

View File

@@ -0,0 +1,34 @@
package com.wimbli.WorldBorder.cmd;
import com.wimbli.WorldBorder.Config;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.List;
public class CmdWhoosh extends WBCmd {
public CmdWhoosh() {
name = permission = "whoosh";
minParams = maxParams = 1;
addCmdExample(nameEmphasized() + "<on|off> - turn knockback effect on or off.");
helpText = "Default value: on. This will show a particle effect and play a sound where a player is knocked " +
"back from the border.";
}
@Override
public void cmdStatus(CommandSender sender) {
sender.sendMessage(C_HEAD + "\"Whoosh\" knockback effect is " + enabledColored(Config.whooshEffect()) + C_HEAD + ".");
}
@Override
public void execute(CommandSender sender, Player player, List<String> params, String worldName) {
Config.setWhooshEffect(strAsBool(params.get(0)));
if (player != null) {
Config.log((Config.whooshEffect() ? "Enabled" : "Disabled") + " \"whoosh\" knockback effect at the command of player \"" + player.getName() + "\".");
cmdStatus(sender);
}
}
}

View File

@@ -0,0 +1,54 @@
package com.wimbli.WorldBorder.cmd;
import com.wimbli.WorldBorder.BorderData;
import com.wimbli.WorldBorder.Config;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.List;
public class CmdWrap extends WBCmd {
public CmdWrap() {
name = permission = "wrap";
minParams = 1;
maxParams = 2;
addCmdExample(nameEmphasized() + "{world} <on|off> - can make border crossings wrap.");
helpText = "When border wrapping is enabled for a world, players will be sent around to the opposite edge " +
"of the border when they cross it instead of being knocked back. [world] is optional for players and " +
"defaults to the world the player is in.";
}
@Override
public void execute(CommandSender sender, Player player, List<String> params, String worldName) {
if (player == null && params.size() == 1) {
sendErrorAndHelp(sender, "When running this command from console, you must specify a world.");
return;
}
boolean wrap = false;
// world and wrap on/off specified
if (params.size() == 2) {
worldName = params.get(0);
wrap = strAsBool(params.get(1));
}
// no world specified, just wrap on/off
else {
worldName = player.getWorld().getName();
wrap = strAsBool(params.get(0));
}
BorderData border = Config.Border(worldName);
if (border == null) {
sendErrorAndHelp(sender, "This world (\"" + worldName + "\") does not have a border set.");
return;
}
border.setWrapping(wrap);
Config.setBorder(worldName, border, false);
sender.sendMessage("Border for world \"" + worldName + "\" is now set to " + (wrap ? "" : "not ") + "wrap around.");
}
}

View File

@@ -0,0 +1,62 @@
package com.wimbli.WorldBorder.cmd;
import com.wimbli.WorldBorder.BorderData;
import com.wimbli.WorldBorder.Config;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.List;
public class CmdWshape extends WBCmd {
public CmdWshape() {
name = permission = "wshape";
minParams = 1;
maxParams = 2;
addCmdExample(nameEmphasized() + "{world} <elliptic|rectangular|default> - shape");
addCmdExample(C_DESC + " override for a single world.", true, true, false);
addCmdExample(nameEmphasized() + "{world} <round|square|default> - same as above.");
helpText = "This will override the default border shape for a single world. The value \"default\" implies " +
"a world is just using the default border shape. See the " + commandEmphasized("shape") + C_DESC +
"command for more info and to set the default border shape.";
}
@Override
public void execute(CommandSender sender, Player player, List<String> params, String worldName) {
if (player == null && params.size() == 1) {
sendErrorAndHelp(sender, "When running this command from console, you must specify a world.");
return;
}
String shapeName = "";
// world and shape specified
if (params.size() == 2) {
worldName = params.get(0);
shapeName = params.get(1).toLowerCase();
}
// no world specified, just shape
else {
worldName = player.getWorld().getName();
shapeName = params.get(0).toLowerCase();
}
BorderData border = Config.Border(worldName);
if (border == null) {
sendErrorAndHelp(sender, "This world (\"" + worldName + "\") does not have a border set.");
return;
}
Boolean shape = null;
if (shapeName.equals("rectangular") || shapeName.equals("square"))
shape = false;
else if (shapeName.equals("elliptic") || shapeName.equals("round"))
shape = true;
border.setShape(shape);
Config.setBorder(worldName, border, false);
sender.sendMessage("Border shape for world \"" + worldName + "\" is now set to \"" + Config.ShapeName(shape) + "\".");
}
}

View File

@@ -0,0 +1,128 @@
package com.wimbli.WorldBorder.cmd;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.List;
public abstract class WBCmd {
/*
* Primary variables, should be set as needed in constructors for the subclassed commands
*/
// color values for strings
public final static String C_CMD = ChatColor.AQUA.toString(); // main commands
public final static String C_DESC = ChatColor.WHITE.toString(); // command descriptions
public final static String C_ERR = ChatColor.RED.toString(); // errors / notices
public final static String C_HEAD = ChatColor.YELLOW.toString(); // command listing header
public final static String C_OPT = ChatColor.DARK_GREEN.toString(); // optional values
public final static String C_REQ = ChatColor.GREEN.toString(); // required values
// colorized root command, for console and for player
public final static String CMD_C = C_CMD + "wb ";
public final static String CMD_P = C_CMD + "/wb ";
// much like the above, but used for displaying command list from root /wb command, listing all commands
public final static List<String> cmdExamplesConsole = new ArrayList<String>(48); // 48 command capacity, 6 full pages
/*
* Helper variables and methods
*/
public final static List<String> cmdExamplesPlayer = new ArrayList<String>(48); // still, could need to increase later
// list of command examples for this command to be displayed as usage reference, separate between players and console
// ... these generally should be set indirectly using addCmdExample() within the constructor for each command class
public final List<String> cmdExamplePlayer = new ArrayList<String>();
public final List<String> cmdExampleConsole = new ArrayList<String>();
// command name, command permission; normally the same thing
public String name = "";
public String permission = null;
// whether command can accept a world name before itself
public boolean hasWorldNameInput = false;
public boolean consoleRequiresWorldName = true;
// minimum and maximum number of accepted parameters
public int minParams = 0;
public int maxParams = 9999;
// help/explanation text to be shown after command example(s) for this command
public String helpText = null;
/*
* The guts of the command run in here; needs to be overriden in the subclassed commands
*/
public abstract void execute(CommandSender sender, Player player, List<String> params, String worldName);
/*
* This is an optional override, used to provide some extra command status info, like the currently set value
*/
public void cmdStatus(CommandSender sender) {
}
// add command examples for use the default "/wb" command list and for internal usage reference, formatted and colorized
public void addCmdExample(String example) {
addCmdExample(example, true, true, true);
}
public void addCmdExample(String example, boolean forPlayer, boolean forConsole, boolean prefix) {
// go ahead and colorize required "<>" and optional "[]" parameters, extra command words, and description
example = example.replace("<", C_REQ + "<").replace("[", C_OPT + "[").replace("^", C_CMD).replace("- ", C_DESC + "- ");
// all "{}" are replaced by "[]" (optional) for player, "<>" (required) for console
if (forPlayer) {
String exampleP = (prefix ? CMD_P : "") + example.replace("{", C_OPT + "[").replace("}", "]");
cmdExamplePlayer.add(exampleP);
cmdExamplesPlayer.add(exampleP);
}
if (forConsole) {
String exampleC = (prefix ? CMD_C : "") + example.replace("{", C_REQ + "<").replace("}", ">");
cmdExampleConsole.add(exampleC);
cmdExamplesConsole.add(exampleC);
}
}
// return root command formatted for player or console, based on sender
public String cmd(CommandSender sender) {
return (sender instanceof Player) ? CMD_P : CMD_C;
}
// formatted and colorized text, intended for marking command name
public String commandEmphasized(String text) {
return C_CMD + ChatColor.UNDERLINE + text + ChatColor.RESET + " ";
}
// returns green "enabled" or red "disabled" text
public String enabledColored(boolean enabled) {
return enabled ? C_REQ + "enabled" : C_ERR + "disabled";
}
// formatted and colorized command name, optionally prefixed with "[world]" (for player) / "<world>" (for console)
public String nameEmphasized() {
return commandEmphasized(name);
}
public String nameEmphasizedW() {
return "{world} " + nameEmphasized();
}
// send command example message(s) and other helpful info
public void sendCmdHelp(CommandSender sender) {
for (String example : ((sender instanceof Player) ? cmdExamplePlayer : cmdExampleConsole)) {
sender.sendMessage(example);
}
cmdStatus(sender);
if (helpText != null && !helpText.isEmpty())
sender.sendMessage(C_DESC + helpText);
}
// send error message followed by command example message(s)
public void sendErrorAndHelp(CommandSender sender, String error) {
sender.sendMessage(C_ERR + error);
sendCmdHelp(sender);
}
// interpret string as boolean value (yes/no, true/false, on/off, +/-, 1/0)
public boolean strAsBool(String str) {
str = str.toLowerCase();
return str.startsWith("y") || str.startsWith("t") || str.startsWith("on") || str.startsWith("+") || str.startsWith("1");
}
}