Added command system structure.

This commit is contained in:
Harrison Deng 2020-05-09 00:25:43 -05:00
parent 3ab1e05569
commit 759a604e4e
7 changed files with 323 additions and 5 deletions

View File

@ -1,30 +1,38 @@
package ca.recrown.islandsurvivalcraft;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
import ca.recrown.islandsurvivalcraft.interaction.commands.CommandProcessor;
import ca.recrown.islandsurvivalcraft.world.WorldInfoManager;
import ca.recrown.islandsurvivalcraft.world.generation.GeneratorModes;
public class IslandSurvivalCraft extends JavaPlugin implements Listener {
private PluginManager pluginManager;
private WorldInfoManager worldInfos;
private WorldInfoManager worldInfoManager;
private CommandProcessor commandProcessor;
public IslandSurvivalCraft() {
worldInfos = new WorldInfoManager();
worldInfoManager = new WorldInfoManager();
}
@Override
public void onEnable() {
pluginManager = getServer().getPluginManager();
pluginManager.registerEvents(worldInfos, this);
pluginManager.registerEvents(worldInfoManager, this);
commandProcessor = new CommandProcessor(this);
super.onEnable();
}
@Override
public void onDisable() {
HandlerList.unregisterAll(worldInfoManager);
commandProcessor = null;
super.onDisable();
}
@ -36,7 +44,18 @@ public class IslandSurvivalCraft extends JavaPlugin implements Listener {
} catch (NullPointerException | IllegalArgumentException e) {
gID = GeneratorModes.UNIQUE;
}
return worldInfos.getChunkGenerator(getServer().getWorld(worldName), gID);
return worldInfoManager.getChunkGenerator(getServer().getWorld(worldName), gID);
}
/**
* @return the world information manager.
*/
public WorldInfoManager getWorldInfoManager() {
return worldInfoManager;
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
return commandProcessor.onCommand(sender, command, label, args);
}
}

View File

@ -0,0 +1,45 @@
package ca.recrown.islandsurvivalcraft.interaction.commands;
import java.util.Arrays;
import java.util.HashSet;
import java.util.concurrent.CompletableFuture;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import ca.recrown.islandsurvivalcraft.IslandSurvivalCraft;
public class CommandProcessor implements CommandExecutor {
private IslandSurvivalCraft islandSurvivalCraft;
private HashSet<Commands> initializedCommands = new HashSet<>();
public CommandProcessor(IslandSurvivalCraft islandSurvivalCraft) {
this.islandSurvivalCraft = islandSurvivalCraft;
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (args.length < 1 || args[0].isEmpty()) return false;
Commands currentCommand = null;
try {
currentCommand = Commands.valueOf(args[0].toUpperCase());
} catch (IllegalArgumentException e) {
sender.sendMessage(ChatColor.LIGHT_PURPLE + "This command was not understood. Refer to \"/IslandSurvivalCraft help\" for more info.");
}
if (initializedCommands.add(currentCommand)) currentCommand.initialize(islandSurvivalCraft);
String[] commandArguments = Arrays.copyOfRange(args, 1, args.length);
CompletableFuture<String> results = currentCommand.invoke(sender, commandArguments);
results.thenAccept(s -> {
if (sender instanceof Player) {
Player player = (Player) sender;
if (!player.isOnline()) return;
}
sender.sendMessage(s != null ? s : "");
});
return true;
}
}

View File

@ -0,0 +1,52 @@
package ca.recrown.islandsurvivalcraft.interaction.commands;
import ca.recrown.islandsurvivalcraft.interaction.commands.runnables.HighlightIslandCommand;
import java.util.concurrent.CompletableFuture;
import org.bukkit.command.CommandSender;
import ca.recrown.islandsurvivalcraft.IslandSurvivalCraft;
import ca.recrown.islandsurvivalcraft.interaction.commands.runnables.CommandRunnable;
import ca.recrown.islandsurvivalcraft.interaction.commands.runnables.HelpCommand;
public enum Commands implements CommandRunnable {
HIGHLIGHT(new HighlightIslandCommand()),
HELP(new HelpCommand()),
;
private final CommandRunnable commandRunnable;
private boolean initialized = false;
private Commands(CommandRunnable runnable) {
this.commandRunnable = runnable;
}
@Override
public String toString() {
return name().toLowerCase();
}
@Override
public CompletableFuture<String> invoke(CommandSender sender, String[] args) {
return commandRunnable.invoke(sender, args);
}
@Override
public void initialize(IslandSurvivalCraft islandSurvivalCraft) {
if (initialized) throw new IllegalStateException("Command already initialized.");
initialized = true;
commandRunnable.initialize(islandSurvivalCraft);
}
@Override
public String getDescription() {
return commandRunnable.getDescription();
}
@Override
public String getDetailedDescription() {
return commandRunnable.getDetailedDescription();
}
}

View File

@ -0,0 +1,34 @@
package ca.recrown.islandsurvivalcraft.interaction.commands.runnables;
import java.util.concurrent.CompletableFuture;
import org.bukkit.command.CommandSender;
import ca.recrown.islandsurvivalcraft.IslandSurvivalCraft;
public interface CommandRunnable {
/**
* @return a string that gives users an idea of what this command does. Should be short and not include details on arguments.
*/
public String getDescription();
/**
* @return A more detailed description. Doesn't need to contain information already present in normal description as will print with that one. This string should describe proper usage arguments required.
*/
public String getDetailedDescription();
/**
* Invokes this particular command.
* Should check for correct arguments.
* @param sender The sender of this command.
* @param args The arguments given for this command. May be length of 0, in which case there were no arguments.
* @return The completable future for the command. The completable future should ultimately return a message in the form of the string letting the user know the the completed execution, or a failure message.
*/
public CompletableFuture<String> invoke(CommandSender sender, String[] args);
/**
* Initializes the command. Is run the first time this command is run.
* @param islandSurvivalCraft
*/
public void initialize(IslandSurvivalCraft islandSurvivalCraft);
}

View File

@ -0,0 +1,61 @@
package ca.recrown.islandsurvivalcraft.interaction.commands.runnables;
import java.util.concurrent.CompletableFuture;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import ca.recrown.islandsurvivalcraft.IslandSurvivalCraft;
import ca.recrown.islandsurvivalcraft.interaction.commands.Commands;
public class HelpCommand implements CommandRunnable {
private String helpMessage;
@Override
public String getDescription() {
return "Displays these help messages.";
}
@Override
public CompletableFuture<String> invoke(CommandSender sender, String[] args) {
CompletableFuture<String> completableFuture = new CompletableFuture<>();
if (args == null || args.length == 0) {
completableFuture.complete(helpMessage);
} else {
Commands command = null;
try {
command = Commands.valueOf(args[0].toUpperCase());
} catch (IllegalArgumentException e) {
completableFuture.complete(ChatColor.LIGHT_PURPLE + String.format("The request %s does not exist. Please type \"/IslandSurvivalCraft help\" for more info.", args[0]));
return completableFuture;
}
StringBuilder sb = new StringBuilder();
sb.append(ChatColor.YELLOW + args[0]);
sb.append(": " + ChatColor.GRAY);
sb.append(command.getDescription());
sb.append("\n" + ChatColor.WHITE);
sb.append(command.getDetailedDescription());
completableFuture.complete(sb.toString().trim());
}
return completableFuture;
}
@Override
public void initialize(IslandSurvivalCraft islandSurvivalCraft) {
StringBuilder stringBuilder = new StringBuilder();
Commands[] commands = Commands.values();
stringBuilder.append(ChatColor.YELLOW + "Commands:\n");
for (int i = 0; i < commands.length; i++) {
stringBuilder.append(ChatColor.GREEN + commands[i].toString());
stringBuilder.append(": " + ChatColor.WHITE);
stringBuilder.append(commands[i].getDescription());
stringBuilder.append("\n");
}
helpMessage = stringBuilder.toString().trim();
}
@Override
public String getDetailedDescription() {
return " \"islandsurvivalcraft help [command]\". Where [command] is a listed command, can optionally be added to get a detailed look at the command. Help is a command that lists all the other potential commands that may be run. Can also look at the detailed commands. But you knew this since your using help with help...";
}
}

View File

@ -0,0 +1,97 @@
package ca.recrown.islandsurvivalcraft.interaction.commands.runnables;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.concurrent.CompletableFuture;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Particle;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import ca.recrown.islandsurvivalcraft.IslandSurvivalCraft;
import ca.recrown.islandsurvivalcraft.world.WorldInfo;
public class HighlightIslandCommand implements CommandRunnable {
private final int CHECK_RADIUS = 3;
private final int PARTICLE_AMOUNT = 2;
private final Particle PARTICLE_TYPE = Particle.FIREWORKS_SPARK;
private final double OFFSET_X = 0.0d, OFFSET_Y = 0.0d, OFFSET_Z = 0.0d;
HashSet<Player> playersHighlighting = new HashSet<>();
LinkedList<Player> waitingList = new LinkedList<>();
@Override
public String getDescription() {
return "Displays particle effects at edge of islands.";
}
@Override
public CompletableFuture<String> invoke(CommandSender sender, String[] args) {
CompletableFuture<String> completableFuture = new CompletableFuture<>();
if (!(sender instanceof Player)) {
completableFuture.complete("This command can only be run as a player!");
return completableFuture;
}
Player player = (Player) sender;
if (args[0].isEmpty()) {
completableFuture.complete("Arguments required. Please refer to \"/IslandSurvivalCraft help\" for more info.");
return completableFuture;
}
if (args[0].toLowerCase().equals("start")) {
if (playersHighlighting.add(player)) {
waitingList.add(player);
completableFuture.complete("You are now highlighting islands.");
} else {
completableFuture.complete("You are already highlighting islands.");
}
} else if (args[0].toLowerCase().equals("stop")) {
if (playersHighlighting.remove(player)) {
completableFuture.complete("You are no longer highlighting islands.");
} else {
completableFuture.complete("You weren't highlighting islands.");
}
} else {
completableFuture.complete(String.format("Argument \"%d\" was not understood. Please refer to \"/IslandSurvivalCraft help\" for more info.", args[0]));
}
return completableFuture;
}
@Override
public void initialize(IslandSurvivalCraft islandsurvivalcraft) {
Bukkit.getScheduler().scheduleSyncRepeatingTask(islandsurvivalcraft, new Runnable() {
@Override
public void run() {
Player player = waitingList.poll();
if (player == null || !player.isOnline() || !playersHighlighting.contains(player)) {
playersHighlighting.remove(player);
return;
}
World world = player.getWorld();
WorldInfo worldInfo = islandsurvivalcraft.getWorldInfoManager().retrieve(world);
Location playerLocation = player.getLocation();
int playerX = playerLocation.getBlockX(), playerY = playerLocation.getBlockY(), playerZ = playerLocation.getBlockZ();
for (int x = 1; x < CHECK_RADIUS; x++) {
for (int z = 1; z < CHECK_RADIUS; z++) {
if (worldInfo.getIslandMap().isIsland(playerX + x, playerZ + z)) {
world.spawnParticle(PARTICLE_TYPE, x + playerX, playerY, z + playerZ, PARTICLE_AMOUNT, OFFSET_X, OFFSET_Y, OFFSET_Z);
}
if (worldInfo.getIslandMap().isIsland(playerX - x, playerZ - z)) {
world.spawnParticle(PARTICLE_TYPE, playerX - x, playerY, playerZ - z, PARTICLE_AMOUNT, OFFSET_X, OFFSET_Y, OFFSET_Z);
}
}
}
waitingList.add(player);
}
}, 0, 5);
}
@Override
public String getDetailedDescription() {
return "A helpful debugging command to analyze what the plugin considers an island by displaying particle effects around the player that is a part of the island. The <start | stop> argument is required to dicate whether or not to start the highlighting or stop it.";
}
}

View File

@ -7,3 +7,13 @@ depend: []
load: startup
api-version: 1.15
commands:
IslandSurvivalCraft:
aliases: [isc]
description: The administration command for Island Survival Craft.
usage: Type "/IslandSurvivalCraft help" (or any of its aliases) for a list of commands.
permission: islandsurvivalcraft.admin
permission-message: This command isn't needed for normal gameplay, and therefore, by default, only operators have access to it.
permissions:
islandsurvivalcraft.admin:
description: Gives ability to configure and test Island Survival Craft features in game.
default: op