mirror of
https://github.com/loganintech/render-region-forcefield.git
synced 2026-05-30 14:21:14 +00:00
Added more
This commit is contained in:
23
README.md
23
README.md
@@ -5,10 +5,14 @@ A Minecraft plugin that renders visible particle forcefields around WorldGuard r
|
||||
## Features
|
||||
|
||||
- Automatically detects WorldGuard regions with `entry deny` flag
|
||||
- Renders particle forcefields only visible to players who cannot enter
|
||||
- Renders **visible glass pane barriers** and particle effects for blocked regions
|
||||
- Only shows forcefields to players who **actually cannot enter** (respects bypass permissions and ops)
|
||||
- Glass panes only placed where there's currently air (doesn't cover existing blocks)
|
||||
- Configurable particle color, size, spacing, and render distance
|
||||
- Configurable block material (glass panes, barriers, etc.)
|
||||
- Supports cuboid and polygonal region types
|
||||
- Performance-optimized with distance-based rendering
|
||||
- Automatic cleanup when players move away or disconnect
|
||||
- Clean, readable, and well-documented code
|
||||
|
||||
## Requirements
|
||||
@@ -85,14 +89,27 @@ particle-color:
|
||||
|
||||
# Particle size (0.5-2.0 recommended)
|
||||
particle-size: 1.0
|
||||
|
||||
# Block rendering settings
|
||||
# Whether to render actual blocks (glass panes) in addition to particles
|
||||
render-blocks: true
|
||||
|
||||
# Distance between blocks (in blocks)
|
||||
block-spacing: 1.0
|
||||
|
||||
# Block material to use (e.g., PURPLE_STAINED_GLASS_PANE, BARRIER, GLASS)
|
||||
block-material: PURPLE_STAINED_GLASS_PANE
|
||||
```
|
||||
|
||||
## Performance Tips
|
||||
|
||||
- Reduce `max-render-distance` for servers with many regions
|
||||
- Increase `particle-spacing` to reduce particle count
|
||||
- Increase `block-spacing` to reduce block count
|
||||
- Set `render-blocks: false` to disable glass panes and only use particles
|
||||
- Set `render-walls: false` to only show edges
|
||||
- Increase `update-interval-ticks` if you don't need real-time updates
|
||||
- Use `BARRIER` blocks instead of glass panes (less visible but lighter)
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
@@ -102,8 +119,10 @@ particle-size: 1.0
|
||||
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
|
||||
5. **Check you can't actually enter** - ops and members won't see forcefields
|
||||
6. Ensure you're within render distance of the region (default: 100 blocks)
|
||||
7. Try setting `render-blocks: true` if you only see particles
|
||||
8. Check that locations aren't already occupied by blocks
|
||||
|
||||
### Plugin won't load
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package loganintech.regionforcefield;
|
||||
|
||||
import loganintech.regionforcefield.command.ForcefieldCommand;
|
||||
import loganintech.regionforcefield.forcefield.ForcefieldRenderer;
|
||||
import loganintech.regionforcefield.listener.PlayerListener;
|
||||
import loganintech.regionforcefield.region.RegionPermissionChecker;
|
||||
import loganintech.regionforcefield.task.ForcefieldUpdateTask;
|
||||
import org.bukkit.command.PluginCommand;
|
||||
@@ -35,6 +36,9 @@ public final class RegionForcefieldPlugin extends JavaPlugin {
|
||||
this.permissionChecker = new RegionPermissionChecker(this);
|
||||
this.forcefieldRenderer = new ForcefieldRenderer(this);
|
||||
|
||||
// Register listeners
|
||||
getServer().getPluginManager().registerEvents(new PlayerListener(this), this);
|
||||
|
||||
// Register commands
|
||||
ForcefieldCommand commandExecutor = new ForcefieldCommand(this);
|
||||
PluginCommand command = getCommand("forcefield");
|
||||
|
||||
@@ -5,15 +5,19 @@ import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedPolygonalRegion;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
import loganintech.regionforcefield.RegionForcefieldPlugin;
|
||||
import org.bukkit.Color;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Particle;
|
||||
import loganintech.regionforcefield.RegionForcefieldPlugin;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Renders particle forcefields around protected regions.
|
||||
@@ -23,6 +27,8 @@ public class ForcefieldRenderer {
|
||||
private final RegionForcefieldPlugin plugin;
|
||||
private final double particleSpacing;
|
||||
private final Particle.DustOptions dustOptions;
|
||||
private final PlayerBlockTracker blockTracker;
|
||||
private final BlockData glassBlockData;
|
||||
|
||||
/**
|
||||
* Creates a new forcefield renderer.
|
||||
@@ -32,6 +38,7 @@ public class ForcefieldRenderer {
|
||||
public ForcefieldRenderer(@NotNull RegionForcefieldPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
this.particleSpacing = plugin.getConfig().getDouble("particle-spacing", 0.5);
|
||||
this.blockTracker = new PlayerBlockTracker();
|
||||
|
||||
// Get color from config or use default (purple)
|
||||
int red = plugin.getConfig().getInt("particle-color.red", 147);
|
||||
@@ -40,6 +47,27 @@ public class ForcefieldRenderer {
|
||||
float size = (float) plugin.getConfig().getDouble("particle-size", 1.0);
|
||||
|
||||
this.dustOptions = new Particle.DustOptions(Color.fromRGB(red, green, blue), size);
|
||||
|
||||
// Get block material from config or use purple stained glass pane
|
||||
String materialName = plugin.getConfig().getString("block-material", "PURPLE_STAINED_GLASS_PANE");
|
||||
Material material;
|
||||
try {
|
||||
material = Material.valueOf(materialName.toUpperCase());
|
||||
} catch (IllegalArgumentException e) {
|
||||
plugin.getLogger().warning("Invalid block material '" + materialName + "', using PURPLE_STAINED_GLASS_PANE");
|
||||
material = Material.PURPLE_STAINED_GLASS_PANE;
|
||||
}
|
||||
this.glassBlockData = material.createBlockData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the block tracker for managing fake blocks.
|
||||
*
|
||||
* @return the block tracker
|
||||
*/
|
||||
@NotNull
|
||||
public PlayerBlockTracker getBlockTracker() {
|
||||
return blockTracker;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,49 +76,59 @@ public class ForcefieldRenderer {
|
||||
* @param player the player to show the forcefield to
|
||||
* @param region the region to render
|
||||
* @param world the world the region is in
|
||||
* @return set of block locations that were rendered
|
||||
*/
|
||||
public void renderForcefield(@NotNull Player player, @NotNull ProtectedRegion region, @NotNull World world) {
|
||||
@NotNull
|
||||
public Set<Location> renderForcefield(@NotNull Player player, @NotNull ProtectedRegion region, @NotNull World world) {
|
||||
Set<Location> newBlocks = new HashSet<>();
|
||||
|
||||
try {
|
||||
plugin.debug("Rendering forcefield for region " + region.getId() + " to player " + player.getName());
|
||||
|
||||
if (region instanceof ProtectedCuboidRegion) {
|
||||
renderCuboidForcefield(player, (ProtectedCuboidRegion) region, world);
|
||||
renderCuboidForcefield(player, (ProtectedCuboidRegion) region, world, newBlocks);
|
||||
} else if (region instanceof ProtectedPolygonalRegion) {
|
||||
renderPolygonalForcefield(player, (ProtectedPolygonalRegion) region, world);
|
||||
renderPolygonalForcefield(player, (ProtectedPolygonalRegion) region, world, newBlocks);
|
||||
} else {
|
||||
// For other region types, fall back to rendering a bounding box
|
||||
plugin.debug("Using bounding box for region type: " + region.getClass().getSimpleName());
|
||||
renderBoundingBoxForcefield(player, region, world);
|
||||
renderBoundingBoxForcefield(player, region, world, newBlocks);
|
||||
}
|
||||
|
||||
plugin.debug("Rendered " + newBlocks.size() + " blocks for region " + region.getId());
|
||||
} catch (Exception e) {
|
||||
plugin.getLogger().warning("Error rendering forcefield for region " + region.getId() + ": " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return newBlocks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a forcefield for a cuboid region.
|
||||
*/
|
||||
private void renderCuboidForcefield(@NotNull Player player, @NotNull ProtectedCuboidRegion region, @NotNull World world) {
|
||||
private void renderCuboidForcefield(@NotNull Player player, @NotNull ProtectedCuboidRegion region,
|
||||
@NotNull World world, @NotNull Set<Location> blocks) {
|
||||
BlockVector3 min = region.getMinimumPoint();
|
||||
BlockVector3 max = region.getMaximumPoint();
|
||||
|
||||
// Render vertical edges
|
||||
renderVerticalEdges(player, world, min, max);
|
||||
renderVerticalEdges(player, world, min, max, blocks);
|
||||
|
||||
// Render horizontal edges at top and bottom
|
||||
renderHorizontalEdges(player, world, min, max);
|
||||
renderHorizontalEdges(player, world, min, max, blocks);
|
||||
|
||||
// Optionally render faces (walls)
|
||||
if (plugin.getConfig().getBoolean("render-walls", true)) {
|
||||
renderWalls(player, world, min, max);
|
||||
renderWalls(player, world, min, max, blocks);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a forcefield for a polygonal region.
|
||||
*/
|
||||
private void renderPolygonalForcefield(@NotNull Player player, @NotNull ProtectedPolygonalRegion region, @NotNull World world) {
|
||||
private void renderPolygonalForcefield(@NotNull Player player, @NotNull ProtectedPolygonalRegion region,
|
||||
@NotNull World world, @NotNull Set<Location> blocks) {
|
||||
List<BlockVector2> points = region.getPoints();
|
||||
int minY = region.getMinimumPoint().y();
|
||||
int maxY = region.getMaximumPoint().y();
|
||||
@@ -100,64 +138,71 @@ public class ForcefieldRenderer {
|
||||
BlockVector2 point1 = points.get(i);
|
||||
BlockVector2 point2 = points.get((i + 1) % points.size());
|
||||
|
||||
renderVerticalWall(player, world, point1.x(), point1.z(), point2.x(), point2.z(), minY, maxY);
|
||||
renderVerticalWall(player, world, point1.x(), point1.z(), point2.x(), point2.z(), minY, maxY, blocks);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a bounding box forcefield for unsupported region types.
|
||||
*/
|
||||
private void renderBoundingBoxForcefield(@NotNull Player player, @NotNull ProtectedRegion region, @NotNull World world) {
|
||||
private void renderBoundingBoxForcefield(@NotNull Player player, @NotNull ProtectedRegion region,
|
||||
@NotNull World world, @NotNull Set<Location> blocks) {
|
||||
BlockVector3 min = region.getMinimumPoint();
|
||||
BlockVector3 max = region.getMaximumPoint();
|
||||
|
||||
renderVerticalEdges(player, world, min, max);
|
||||
renderHorizontalEdges(player, world, min, max);
|
||||
renderVerticalEdges(player, world, min, max, blocks);
|
||||
renderHorizontalEdges(player, world, min, max, blocks);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the vertical edges of a cuboid.
|
||||
*/
|
||||
private void renderVerticalEdges(@NotNull Player player, @NotNull World world, @NotNull BlockVector3 min, @NotNull BlockVector3 max) {
|
||||
private void renderVerticalEdges(@NotNull Player player, @NotNull World world,
|
||||
@NotNull BlockVector3 min, @NotNull BlockVector3 max,
|
||||
@NotNull Set<Location> blocks) {
|
||||
// Four vertical edges
|
||||
renderLine(player, world, min.x(), min.y(), min.z(), min.x(), max.y(), min.z());
|
||||
renderLine(player, world, max.x(), min.y(), min.z(), max.x(), max.y(), min.z());
|
||||
renderLine(player, world, min.x(), min.y(), max.z(), min.x(), max.y(), max.z());
|
||||
renderLine(player, world, max.x(), min.y(), max.z(), max.x(), max.y(), max.z());
|
||||
renderLine(player, world, min.x(), min.y(), min.z(), min.x(), max.y(), min.z(), blocks);
|
||||
renderLine(player, world, max.x(), min.y(), min.z(), max.x(), max.y(), min.z(), blocks);
|
||||
renderLine(player, world, min.x(), min.y(), max.z(), min.x(), max.y(), max.z(), blocks);
|
||||
renderLine(player, world, max.x(), min.y(), max.z(), max.x(), max.y(), max.z(), blocks);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the horizontal edges of a cuboid.
|
||||
*/
|
||||
private void renderHorizontalEdges(@NotNull Player player, @NotNull World world, @NotNull BlockVector3 min, @NotNull BlockVector3 max) {
|
||||
private void renderHorizontalEdges(@NotNull Player player, @NotNull World world,
|
||||
@NotNull BlockVector3 min, @NotNull BlockVector3 max,
|
||||
@NotNull Set<Location> blocks) {
|
||||
// Bottom edges
|
||||
renderLine(player, world, min.x(), min.y(), min.z(), max.x(), min.y(), min.z());
|
||||
renderLine(player, world, min.x(), min.y(), max.z(), max.x(), min.y(), max.z());
|
||||
renderLine(player, world, min.x(), min.y(), min.z(), min.x(), min.y(), max.z());
|
||||
renderLine(player, world, max.x(), min.y(), min.z(), max.x(), min.y(), max.z());
|
||||
renderLine(player, world, min.x(), min.y(), min.z(), max.x(), min.y(), min.z(), blocks);
|
||||
renderLine(player, world, min.x(), min.y(), max.z(), max.x(), min.y(), max.z(), blocks);
|
||||
renderLine(player, world, min.x(), min.y(), min.z(), min.x(), min.y(), max.z(), blocks);
|
||||
renderLine(player, world, max.x(), min.y(), min.z(), max.x(), min.y(), max.z(), blocks);
|
||||
|
||||
// Top edges
|
||||
renderLine(player, world, min.x(), max.y(), min.z(), max.x(), max.y(), min.z());
|
||||
renderLine(player, world, min.x(), max.y(), max.z(), max.x(), max.y(), max.z());
|
||||
renderLine(player, world, min.x(), max.y(), min.z(), min.x(), max.y(), max.z());
|
||||
renderLine(player, world, max.x(), max.y(), min.z(), max.x(), max.y(), max.z());
|
||||
renderLine(player, world, min.x(), max.y(), min.z(), max.x(), max.y(), min.z(), blocks);
|
||||
renderLine(player, world, min.x(), max.y(), max.z(), max.x(), max.y(), max.z(), blocks);
|
||||
renderLine(player, world, min.x(), max.y(), min.z(), min.x(), max.y(), max.z(), blocks);
|
||||
renderLine(player, world, max.x(), max.y(), min.z(), max.x(), max.y(), max.z(), blocks);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the walls (faces) of a cuboid.
|
||||
*/
|
||||
private void renderWalls(@NotNull Player player, @NotNull World world, @NotNull BlockVector3 min, @NotNull BlockVector3 max) {
|
||||
private void renderWalls(@NotNull Player player, @NotNull World world,
|
||||
@NotNull BlockVector3 min, @NotNull BlockVector3 max,
|
||||
@NotNull Set<Location> blocks) {
|
||||
// North wall (min Z)
|
||||
renderVerticalWall(player, world, min.x(), min.z(), max.x(), min.z(), min.y(), max.y());
|
||||
renderVerticalWall(player, world, min.x(), min.z(), max.x(), min.z(), min.y(), max.y(), blocks);
|
||||
|
||||
// South wall (max Z)
|
||||
renderVerticalWall(player, world, min.x(), max.z(), max.x(), max.z(), min.y(), max.y());
|
||||
renderVerticalWall(player, world, min.x(), max.z(), max.x(), max.z(), min.y(), max.y(), blocks);
|
||||
|
||||
// West wall (min X)
|
||||
renderVerticalWall(player, world, min.x(), min.z(), min.x(), max.z(), min.y(), max.y());
|
||||
renderVerticalWall(player, world, min.x(), min.z(), min.x(), max.z(), min.y(), max.y(), blocks);
|
||||
|
||||
// East wall (max X)
|
||||
renderVerticalWall(player, world, max.x(), min.z(), max.x(), max.z(), min.y(), max.y());
|
||||
renderVerticalWall(player, world, max.x(), min.z(), max.x(), max.z(), min.y(), max.y(), blocks);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -165,10 +210,11 @@ public class ForcefieldRenderer {
|
||||
*/
|
||||
private void renderVerticalWall(@NotNull Player player, @NotNull World world,
|
||||
double x1, double z1, double x2, double z2,
|
||||
double minY, double maxY) {
|
||||
double minY, double maxY, @NotNull Set<Location> blocks) {
|
||||
double distance = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(z2 - z1, 2));
|
||||
int horizontalSteps = (int) Math.ceil(distance / particleSpacing);
|
||||
int verticalSteps = (int) Math.ceil((maxY - minY) / particleSpacing);
|
||||
double blockSpacing = plugin.getConfig().getDouble("block-spacing", 1.0);
|
||||
|
||||
for (int i = 0; i <= horizontalSteps; i++) {
|
||||
double t = horizontalSteps > 0 ? (double) i / horizontalSteps : 0;
|
||||
@@ -178,6 +224,12 @@ public class ForcefieldRenderer {
|
||||
for (int j = 0; j <= verticalSteps; j++) {
|
||||
double y = minY + (maxY - minY) * ((double) j / verticalSteps);
|
||||
spawnParticle(player, world, x, y, z);
|
||||
|
||||
// Place blocks at intervals
|
||||
if (i % ((int) Math.max(1, blockSpacing / particleSpacing)) == 0 &&
|
||||
j % ((int) Math.max(1, blockSpacing / particleSpacing)) == 0) {
|
||||
placeBlock(player, world, x, y, z, blocks);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -187,7 +239,8 @@ public class ForcefieldRenderer {
|
||||
*/
|
||||
private void renderLine(@NotNull Player player, @NotNull World world,
|
||||
double x1, double y1, double z1,
|
||||
double x2, double y2, double z2) {
|
||||
double x2, double y2, double z2,
|
||||
@NotNull Set<Location> blocks) {
|
||||
double distance = Math.sqrt(
|
||||
Math.pow(x2 - x1, 2) +
|
||||
Math.pow(y2 - y1, 2) +
|
||||
@@ -195,6 +248,7 @@ public class ForcefieldRenderer {
|
||||
);
|
||||
|
||||
int steps = (int) Math.ceil(distance / particleSpacing);
|
||||
double blockSpacing = plugin.getConfig().getDouble("block-spacing", 1.0);
|
||||
|
||||
for (int i = 0; i <= steps; i++) {
|
||||
double t = steps > 0 ? (double) i / steps : 0;
|
||||
@@ -203,6 +257,11 @@ public class ForcefieldRenderer {
|
||||
double z = z1 + (z2 - z1) * t;
|
||||
|
||||
spawnParticle(player, world, x, y, z);
|
||||
|
||||
// Place blocks at intervals
|
||||
if (i % ((int) Math.max(1, blockSpacing / particleSpacing)) == 0) {
|
||||
placeBlock(player, world, x, y, z, blocks);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,4 +272,63 @@ public class ForcefieldRenderer {
|
||||
Location location = new Location(world, x, y, z);
|
||||
player.spawnParticle(Particle.DUST, location, 1, 0, 0, 0, 0, dustOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Places a fake block at the specified location if it's air.
|
||||
*
|
||||
* @param player the player to send the block to
|
||||
* @param world the world
|
||||
* @param x the x coordinate
|
||||
* @param y the y coordinate
|
||||
* @param z the z coordinate
|
||||
* @param blocks the set to add this block location to
|
||||
*/
|
||||
private void placeBlock(@NotNull Player player, @NotNull World world,
|
||||
double x, double y, double z, @NotNull Set<Location> blocks) {
|
||||
if (!plugin.getConfig().getBoolean("render-blocks", true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Location location = new Location(world, Math.floor(x), Math.floor(y), Math.floor(z));
|
||||
|
||||
// Only place blocks where there's currently air
|
||||
if (location.getBlock().getType() == Material.AIR) {
|
||||
player.sendBlockChange(location, glassBlockData);
|
||||
blocks.add(location);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all fake blocks for a player by restoring the real blocks.
|
||||
*
|
||||
* @param player the player
|
||||
*/
|
||||
public void clearBlocks(@NotNull Player player) {
|
||||
Set<Location> blocks = blockTracker.getBlocks(player);
|
||||
for (Location location : blocks) {
|
||||
// Send the real block data back to the player
|
||||
player.sendBlockChange(location, location.getBlock().getBlockData());
|
||||
}
|
||||
blockTracker.clearPlayer(player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates blocks for a player based on new blocks that should be visible.
|
||||
*
|
||||
* @param player the player
|
||||
* @param newBlocks the new set of blocks to show
|
||||
*/
|
||||
public void updateBlocks(@NotNull Player player, @NotNull Set<Location> newBlocks) {
|
||||
Set<Location> oldBlocks = blockTracker.getBlocks(player);
|
||||
|
||||
// Remove blocks that are no longer needed
|
||||
for (Location location : oldBlocks) {
|
||||
if (!newBlocks.contains(location)) {
|
||||
player.sendBlockChange(location, location.getBlock().getBlockData());
|
||||
}
|
||||
}
|
||||
|
||||
// Update the tracker
|
||||
blockTracker.setBlocks(player, newBlocks);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,21 +83,32 @@ public class RegionPermissionChecker {
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a player can enter a specific region.
|
||||
* Checks if a player can actually enter a region.
|
||||
* Takes into account entry deny flag, bypass permissions, and member/owner status.
|
||||
*
|
||||
* @param player the player to check
|
||||
* @param region the region to check
|
||||
* @return true if the player can enter, false otherwise
|
||||
* @return true if the player CAN enter (no forcefield), false if blocked (show forcefield)
|
||||
*/
|
||||
private boolean canEnterRegion(@NotNull LocalPlayer player, @NotNull ProtectedRegion region) {
|
||||
// Check the ENTRY flag
|
||||
// If ENTRY is set to DENY, the player cannot enter unless they have bypass permissions
|
||||
if (region.getFlag(Flags.ENTRY) == com.sk89q.worldguard.protection.flags.StateFlag.State.DENY) {
|
||||
// Check if player has bypass permission (includes ops)
|
||||
if (player.hasPermission("worldguard.region.bypass." + region.getId()) ||
|
||||
player.hasPermission("worldguard.region.bypass.*")) {
|
||||
return true; // Can enter (has bypass), no forcefield
|
||||
}
|
||||
|
||||
// Check if the player is a member or owner of the region
|
||||
return region.isMember(player) || region.isOwner(player);
|
||||
if (region.isMember(player) || region.isOwner(player)) {
|
||||
return true; // Can enter (is member/owner), no forcefield
|
||||
}
|
||||
|
||||
// Player cannot enter, show forcefield
|
||||
return false;
|
||||
}
|
||||
|
||||
// If ENTRY is not explicitly denied, the player can enter
|
||||
// If ENTRY is not explicitly denied, player can enter
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,10 +4,12 @@ import loganintech.regionforcefield.RegionForcefieldPlugin;
|
||||
import loganintech.regionforcefield.forcefield.ForcefieldRenderer;
|
||||
import loganintech.regionforcefield.region.RegionPermissionChecker;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
@@ -41,24 +43,30 @@ public class ForcefieldUpdateTask extends BukkitRunnable {
|
||||
try {
|
||||
// Iterate through all online players
|
||||
for (Player player : plugin.getServer().getOnlinePlayers()) {
|
||||
// Get all regions the player cannot enter in their current world
|
||||
// Get all regions the player should see forcefields for
|
||||
Set<ProtectedRegion> blockedRegions = permissionChecker.getBlockedRegions(player, player.getWorld());
|
||||
|
||||
if (!blockedRegions.isEmpty()) {
|
||||
plugin.debug("Processing " + blockedRegions.size() + " blocked regions for " + player.getName());
|
||||
}
|
||||
|
||||
// Render forcefields for nearby blocked regions
|
||||
// Collect all blocks that should be rendered for this player
|
||||
Set<Location> allBlocks = new HashSet<>();
|
||||
int rendered = 0;
|
||||
|
||||
for (ProtectedRegion region : blockedRegions) {
|
||||
if (isRegionNearPlayer(player, region)) {
|
||||
forcefieldRenderer.renderForcefield(player, region, player.getWorld());
|
||||
Set<Location> regionBlocks = forcefieldRenderer.renderForcefield(player, region, player.getWorld());
|
||||
allBlocks.addAll(regionBlocks);
|
||||
rendered++;
|
||||
}
|
||||
}
|
||||
|
||||
// Update the player's blocks (remove old ones, keep new ones)
|
||||
forcefieldRenderer.updateBlocks(player, allBlocks);
|
||||
|
||||
if (rendered > 0) {
|
||||
plugin.debug("Rendered " + rendered + " forcefields for " + player.getName());
|
||||
plugin.debug("Rendered " + rendered + " forcefields (" + allBlocks.size() + " blocks) for " + player.getName());
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
||||
@@ -26,3 +26,17 @@ particle-color:
|
||||
|
||||
# Particle size (recommended range: 0.5 to 2.0)
|
||||
particle-size: 1.0
|
||||
|
||||
# Block rendering settings
|
||||
# Whether to render actual blocks (glass panes) in addition to particles
|
||||
render-blocks: true
|
||||
|
||||
# Distance between blocks (in blocks)
|
||||
# Higher values = fewer blocks = better performance
|
||||
# Must be >= particle-spacing
|
||||
block-spacing: 1.0
|
||||
|
||||
# Block material to use for forcefields
|
||||
# Examples: PURPLE_STAINED_GLASS_PANE, BARRIER, GLASS, LIGHT_BLUE_STAINED_GLASS
|
||||
# See https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Material.html for all options
|
||||
block-material: PURPLE_STAINED_GLASS_PANE
|
||||
|
||||
Reference in New Issue
Block a user