mirror of
https://github.com/loganintech/render-region-forcefield.git
synced 2026-05-30 14:21:14 +00:00
Add in-game commands
This commit is contained in:
43
README.md
43
README.md
@@ -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`
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
Edit `plugins/RegionForcefield/config.yml`:
|
||||
|
||||
```yaml
|
||||
# Enable debug logging (useful for troubleshooting)
|
||||
debug: false
|
||||
|
||||
# Update frequency (20 ticks = 1 second)
|
||||
update-interval-ticks: 20
|
||||
|
||||
@@ -76,6 +94,31 @@ particle-size: 1.0
|
||||
- Set `render-walls: false` to only show edges
|
||||
- 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
|
||||
|
||||
```bash
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user