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

@@ -38,15 +38,33 @@ Once installed, the plugin automatically works with your existing WorldGuard reg
2. Set the entry flag to deny: `/rg flag myregion entry deny` 2. Set the entry flag to deny: `/rg flag myregion entry deny`
3. Players who cannot enter the region will see a purple forcefield around it 3. Players who cannot enter the region will see a purple forcefield around it
### Commands
- `/forcefield debug` or `/ff debug` - Toggle debug mode on/off
- `/forcefield reload` or `/ff reload` - Reload the configuration file
- `/forcefield status` or `/ff status` - View plugin status and settings
- `/forcefield info` or `/ff info` - View information about blocked regions nearby
- `/forcefield help` or `/ff help` - Show command help
### Permissions ### Permissions
Players who are members or owners of a region can enter it even if entry is denied for others. These players will not see the forcefield. Players who are members or owners of a region can enter it even if entry is denied for others. These players will not see the forcefield.
- `regionforcefield.*` - Grants all permissions (default: op)
- `regionforcefield.command` - Allows use of `/forcefield` command (default: true)
- `regionforcefield.debug` - Allows toggling debug mode (default: op)
- `regionforcefield.reload` - Allows reloading config (default: op)
- `regionforcefield.status` - Allows viewing status (default: op)
- `regionforcefield.info` - Allows viewing region info (default: true)
## Configuration ## Configuration
Edit `plugins/RegionForcefield/config.yml`: Edit `plugins/RegionForcefield/config.yml`:
```yaml ```yaml
# Enable debug logging (useful for troubleshooting)
debug: false
# Update frequency (20 ticks = 1 second) # Update frequency (20 ticks = 1 second)
update-interval-ticks: 20 update-interval-ticks: 20
@@ -76,6 +94,31 @@ particle-size: 1.0
- Set `render-walls: false` to only show edges - Set `render-walls: false` to only show edges
- Increase `update-interval-ticks` if you don't need real-time updates - Increase `update-interval-ticks` if you don't need real-time updates
## Troubleshooting
### Forcefields not appearing
1. Enable debug mode: `/forcefield debug` or set `debug: true` in config.yml
2. Check the server console for debug messages
3. Use `/forcefield info` to see if regions are being detected
4. Verify the region has `entry deny` set: `/rg info <region>`
5. Check you're not a member/owner of the region
6. Ensure you're within render distance of the region (default: 100 blocks)
### Plugin won't load
1. Verify WorldGuard 7.0.14 or higher is installed
2. Check server logs for error messages
3. Ensure you're running Paper 1.21.8 or higher
4. Verify Java 21 is being used
### Performance issues
1. Increase `particle-spacing` (less particles)
2. Reduce `max-render-distance`
3. Set `render-walls: false` (edges only)
4. Increase `update-interval-ticks` (update less frequently)
## Building from Source ## Building from Source
```bash ```bash

View File

@@ -1,8 +1,10 @@
package loganintech.regionforcefield; package loganintech.regionforcefield;
import loganintech.regionforcefield.command.ForcefieldCommand;
import loganintech.regionforcefield.forcefield.ForcefieldRenderer; import loganintech.regionforcefield.forcefield.ForcefieldRenderer;
import loganintech.regionforcefield.region.RegionPermissionChecker; import loganintech.regionforcefield.region.RegionPermissionChecker;
import loganintech.regionforcefield.task.ForcefieldUpdateTask; import loganintech.regionforcefield.task.ForcefieldUpdateTask;
import org.bukkit.command.PluginCommand;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -33,6 +35,16 @@ public final class RegionForcefieldPlugin extends JavaPlugin {
this.permissionChecker = new RegionPermissionChecker(this); this.permissionChecker = new RegionPermissionChecker(this);
this.forcefieldRenderer = new ForcefieldRenderer(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 // Start the periodic update task
this.updateTask = new ForcefieldUpdateTask(this, permissionChecker, forcefieldRenderer); this.updateTask = new ForcefieldUpdateTask(this, permissionChecker, forcefieldRenderer);
long updateInterval = getConfig().getLong("update-interval-ticks", 20L); 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 author: loganintech
description: Renders visible forcefields around WorldGuard regions that players cannot enter description: Renders visible forcefields around WorldGuard regions that players cannot enter
website: https://github.com/loganintech 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