Add in-game commands

This commit is contained in:
Logan Saso
2025-10-04 21:47:07 -07:00
parent 8a95a982bb
commit ffb44ca4bd
4 changed files with 311 additions and 0 deletions

View File

@@ -1,8 +1,10 @@
package loganintech.regionforcefield;
import loganintech.regionforcefield.command.ForcefieldCommand;
import loganintech.regionforcefield.forcefield.ForcefieldRenderer;
import loganintech.regionforcefield.region.RegionPermissionChecker;
import loganintech.regionforcefield.task.ForcefieldUpdateTask;
import org.bukkit.command.PluginCommand;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
@@ -33,6 +35,16 @@ public final class RegionForcefieldPlugin extends JavaPlugin {
this.permissionChecker = new RegionPermissionChecker(this);
this.forcefieldRenderer = new ForcefieldRenderer(this);
// Register commands
ForcefieldCommand commandExecutor = new ForcefieldCommand(this);
PluginCommand command = getCommand("forcefield");
if (command != null) {
command.setExecutor(commandExecutor);
command.setTabCompleter(commandExecutor);
} else {
getLogger().warning("Failed to register /forcefield command!");
}
// Start the periodic update task
this.updateTask = new ForcefieldUpdateTask(this, permissionChecker, forcefieldRenderer);
long updateInterval = getConfig().getLong("update-interval-ticks", 20L);

View File

@@ -0,0 +1,223 @@
package loganintech.regionforcefield.command;
import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import loganintech.regionforcefield.RegionForcefieldPlugin;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
/**
* Handles the /forcefield command and its subcommands.
*/
public class ForcefieldCommand implements CommandExecutor, TabCompleter {
private final RegionForcefieldPlugin plugin;
public ForcefieldCommand(@NotNull RegionForcefieldPlugin plugin) {
this.plugin = plugin;
}
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command,
@NotNull String label, @NotNull String[] args) {
if (args.length == 0) {
sendHelp(sender);
return true;
}
switch (args[0].toLowerCase()) {
case "debug":
return handleDebug(sender);
case "reload":
return handleReload(sender);
case "status":
return handleStatus(sender);
case "info":
return handleInfo(sender);
case "help":
sendHelp(sender);
return true;
default:
sender.sendMessage(ChatColor.RED + "Unknown subcommand. Use /forcefield help");
return true;
}
}
private boolean handleDebug(@NotNull CommandSender sender) {
if (!sender.hasPermission("regionforcefield.debug")) {
sender.sendMessage(ChatColor.RED + "You don't have permission to use this command.");
return true;
}
boolean currentDebug = plugin.getConfig().getBoolean("debug", false);
boolean newDebug = !currentDebug;
plugin.getConfig().set("debug", newDebug);
plugin.saveConfig();
sender.sendMessage(ChatColor.GREEN + "Debug mode " +
(newDebug ? ChatColor.YELLOW + "enabled" : ChatColor.GRAY + "disabled") +
ChatColor.GREEN + ".");
plugin.getLogger().info(sender.getName() + " toggled debug mode: " + newDebug);
return true;
}
private boolean handleReload(@NotNull CommandSender sender) {
if (!sender.hasPermission("regionforcefield.reload")) {
sender.sendMessage(ChatColor.RED + "You don't have permission to use this command.");
return true;
}
try {
plugin.reloadConfig();
sender.sendMessage(ChatColor.GREEN + "Configuration reloaded successfully!");
plugin.getLogger().info(sender.getName() + " reloaded the configuration.");
} catch (Exception e) {
sender.sendMessage(ChatColor.RED + "Error reloading configuration: " + e.getMessage());
plugin.getLogger().warning("Error reloading configuration: " + e.getMessage());
e.printStackTrace();
}
return true;
}
private boolean handleStatus(@NotNull CommandSender sender) {
if (!sender.hasPermission("regionforcefield.status")) {
sender.sendMessage(ChatColor.RED + "You don't have permission to use this command.");
return true;
}
sender.sendMessage(ChatColor.GOLD + "=== RegionForcefield Status ===");
sender.sendMessage(ChatColor.YELLOW + "Version: " + ChatColor.WHITE + plugin.getDescription().getVersion());
sender.sendMessage(ChatColor.YELLOW + "Debug Mode: " + ChatColor.WHITE +
(plugin.getConfig().getBoolean("debug", false) ? "Enabled" : "Disabled"));
sender.sendMessage(ChatColor.YELLOW + "Update Interval: " + ChatColor.WHITE +
plugin.getConfig().getLong("update-interval-ticks", 20L) + " ticks");
sender.sendMessage(ChatColor.YELLOW + "Max Render Distance: " + ChatColor.WHITE +
plugin.getConfig().getInt("max-render-distance", 100) + " blocks");
sender.sendMessage(ChatColor.YELLOW + "Particle Spacing: " + ChatColor.WHITE +
plugin.getConfig().getDouble("particle-spacing", 0.5) + " blocks");
sender.sendMessage(ChatColor.YELLOW + "Render Walls: " + ChatColor.WHITE +
(plugin.getConfig().getBoolean("render-walls", true) ? "Yes" : "No"));
int red = plugin.getConfig().getInt("particle-color.red", 147);
int green = plugin.getConfig().getInt("particle-color.green", 112);
int blue = plugin.getConfig().getInt("particle-color.blue", 219);
sender.sendMessage(ChatColor.YELLOW + "Particle Color: " + ChatColor.WHITE +
"RGB(" + red + ", " + green + ", " + blue + ")");
sender.sendMessage(ChatColor.YELLOW + "Online Players: " + ChatColor.WHITE +
plugin.getServer().getOnlinePlayers().size());
return true;
}
private boolean handleInfo(@NotNull CommandSender sender) {
if (!(sender instanceof Player)) {
sender.sendMessage(ChatColor.RED + "This command can only be used by players.");
return true;
}
if (!sender.hasPermission("regionforcefield.info")) {
sender.sendMessage(ChatColor.RED + "You don't have permission to use this command.");
return true;
}
Player player = (Player) sender;
try {
// Get regions the player is blocked from
Set<ProtectedRegion> blockedRegions = plugin.getPermissionChecker()
.getBlockedRegions(player, player.getWorld());
sender.sendMessage(ChatColor.GOLD + "=== Region Information ===");
sender.sendMessage(ChatColor.YELLOW + "World: " + ChatColor.WHITE + player.getWorld().getName());
// Get all regions in the world
RegionManager regionManager = WorldGuard.getInstance()
.getPlatform()
.getRegionContainer()
.get(com.sk89q.worldedit.bukkit.BukkitAdapter.adapt(player.getWorld()));
if (regionManager != null) {
int totalRegions = regionManager.getRegions().size();
sender.sendMessage(ChatColor.YELLOW + "Total Regions: " + ChatColor.WHITE + totalRegions);
sender.sendMessage(ChatColor.YELLOW + "Blocked Regions: " + ChatColor.WHITE + blockedRegions.size());
if (!blockedRegions.isEmpty()) {
sender.sendMessage(ChatColor.GOLD + "Regions you cannot enter:");
for (ProtectedRegion region : blockedRegions) {
double distance = calculateDistance(player, region);
sender.sendMessage(ChatColor.GRAY + " - " + ChatColor.WHITE + region.getId() +
ChatColor.GRAY + " (distance: " + String.format("%.1f", distance) + " blocks)");
}
} else {
sender.sendMessage(ChatColor.GREEN + "You can enter all regions in this world!");
}
} else {
sender.sendMessage(ChatColor.RED + "No region manager found for this world.");
}
} catch (Exception e) {
sender.sendMessage(ChatColor.RED + "Error retrieving region information: " + e.getMessage());
plugin.getLogger().warning("Error in info command: " + e.getMessage());
e.printStackTrace();
}
return true;
}
private void sendHelp(@NotNull CommandSender sender) {
sender.sendMessage(ChatColor.GOLD + "=== RegionForcefield Commands ===");
sender.sendMessage(ChatColor.YELLOW + "/forcefield debug " + ChatColor.GRAY + "- Toggle debug mode");
sender.sendMessage(ChatColor.YELLOW + "/forcefield reload " + ChatColor.GRAY + "- Reload configuration");
sender.sendMessage(ChatColor.YELLOW + "/forcefield status " + ChatColor.GRAY + "- Show plugin status");
sender.sendMessage(ChatColor.YELLOW + "/forcefield info " + ChatColor.GRAY + "- Show region information");
sender.sendMessage(ChatColor.YELLOW + "/forcefield help " + ChatColor.GRAY + "- Show this help message");
}
private double calculateDistance(@NotNull Player player, @NotNull ProtectedRegion region) {
double playerX = player.getLocation().getX();
double playerY = player.getLocation().getY();
double playerZ = player.getLocation().getZ();
double regionCenterX = (region.getMinimumPoint().x() + region.getMaximumPoint().x()) / 2.0;
double regionCenterY = (region.getMinimumPoint().y() + region.getMaximumPoint().y()) / 2.0;
double regionCenterZ = (region.getMinimumPoint().z() + region.getMaximumPoint().z()) / 2.0;
return Math.sqrt(
Math.pow(playerX - regionCenterX, 2) +
Math.pow(playerY - regionCenterY, 2) +
Math.pow(playerZ - regionCenterZ, 2)
);
}
@Override
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command,
@NotNull String alias, @NotNull String[] args) {
List<String> completions = new ArrayList<>();
if (args.length == 1) {
List<String> subcommands = Arrays.asList("debug", "reload", "status", "info", "help");
String input = args[0].toLowerCase();
for (String subcommand : subcommands) {
if (subcommand.startsWith(input)) {
completions.add(subcommand);
}
}
}
return completions;
}
}

View File

@@ -6,3 +6,36 @@ depend: [WorldGuard]
author: loganintech
description: Renders visible forcefields around WorldGuard regions that players cannot enter
website: https://github.com/loganintech
commands:
forcefield:
description: Manage RegionForcefield plugin
usage: /<command> [debug|reload|status|info|help]
aliases: [ff, regionforcefield]
permission: regionforcefield.command
permissions:
regionforcefield.*:
description: Grants all RegionForcefield permissions
default: op
children:
regionforcefield.command: true
regionforcefield.debug: true
regionforcefield.reload: true
regionforcefield.status: true
regionforcefield.info: true
regionforcefield.command:
description: Allows access to the base /forcefield command
default: true
regionforcefield.debug:
description: Allows toggling debug mode
default: op
regionforcefield.reload:
description: Allows reloading the plugin configuration
default: op
regionforcefield.status:
description: Allows viewing plugin status
default: op
regionforcefield.info:
description: Allows viewing region information
default: true