Add region whitelist flag

This commit is contained in:
NotAlexNoyle committed 2026-05-13 08:10:01 -04:00
1 parent c422e555c7
commit 63acbc99d5
10 files changed
+356 -1

No files matched your search

@@ -10,6 +10,7 @@ import org.battleplugins.arena.spleef.action.GiveShovelAction;
import org.battleplugins.arena.spleef.action.PasteLayersAction;
import org.battleplugins.arena.spleef.api.SpleefApiListener;
import org.battleplugins.arena.spleef.arena.SpleefArena;
import org.battleplugins.arena.spleef.hook.GameModeInventoriesListener;
import org.battleplugins.arena.spleef.hook.PlayerBountiesListener;
import org.bukkit.Bukkit;
import org.bukkit.NamespacedKey;
@@ -34,9 +35,26 @@ public class ArenaSpleef extends JavaPlugin {
private static ArenaSpleef instance;
private SpleefConfig config;
private GameModeInventoriesListener gameModeInventoriesListener;
private final NamespacedKey spleefItemKey = new NamespacedKey(this, "spleef_item");
@Override
public void onLoad() {
if (Bukkit.getPluginManager().getPlugin("WorldGuard") != null) {
SpleefFlags.register(this);
} else {
this.getSLF4JLogger().warn(
"WorldGuard not present at load time; the 'allow-spleef' region flag will not be registered.");
}
}
@Override
public void onEnable() {
@@ -72,6 +90,14 @@ public class ArenaSpleef extends JavaPlugin {
this.getServer().getPluginManager().registerEvents(new SpleefApiListener(), this);
this.gameModeInventoriesListener = GameModeInventoriesListener.register(this);
if (this.gameModeInventoriesListener != null) {
this.getSLF4JLogger()
.info("Hooked into GameModeInventories-OG; Spleef will preserve gamemode-specific inventories.");
}
if (PlayerBountiesListener.register(this)) {
this.getSLF4JLogger().info(
@@ -84,6 +110,12 @@ public class ArenaSpleef extends JavaPlugin {
@Override
public void onDisable() {
if (this.gameModeInventoriesListener != null) {
this.gameModeInventoriesListener.releaseAll();
}
Bukkit.getScheduler().cancelTasks(this);
}
@@ -4,6 +4,8 @@ import org.battleplugins.arena.config.ArenaOption;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Locale;
import java.util.Map;
public class SpleefConfig {
@@ -14,6 +16,9 @@ public class SpleefConfig {
@ArenaOption(name = "shovels", description = "The shovels for this spleef game.", required = true)
private Map<String, ItemStack> shovels;
@ArenaOption(name = "world-whitelist", description = "Worlds where Spleef arenas may be created and run. Empty list = all worlds allowed.")
private List<String> worldWhitelist;
public boolean shouldProjectilesBreakBlocks() {
return this.projectilesBreakBlocks;
@@ -34,4 +39,39 @@ public class SpleefConfig {
}
public boolean isWorldAllowed(String worldName) {
if (this.worldWhitelist == null || this.worldWhitelist.isEmpty()) {
return true;
}
if (worldName == null) {
return false;
}
String target = worldName.toLowerCase(Locale.ROOT);
for (String allowed : this.worldWhitelist) {
if (allowed != null && allowed.toLowerCase(Locale.ROOT).equals(target)) {
return true;
}
}
return false;
}
public List<String> getWorldWhitelist() {
return this.worldWhitelist == null ? List.of() : List.copyOf(this.worldWhitelist);
}
}
@@ -18,6 +18,36 @@ public class SpleefExecutor extends ArenaCommandExecutor {
}
@Override
public void create(Player player) {
SpleefConfig config = ArenaSpleef.getInstance().getMainConfig();
String worldName = player.getWorld().getName();
if (config != null && !config.isWorldAllowed(worldName)) {
SpleefMessages.CREATE_WORLD_NOT_WHITELISTED.send(player, worldName);
return;
}
if (!WorldGuardSupport.isEnabled()) {
SpleefMessages.CREATE_WG_MISSING.send(player);
return;
}
if (!WorldGuardSupport.isSpleefAllowedAt(player)) {
SpleefMessages.CREATE_WG_FLAG_REQUIRED.send(player);
return;
}
super.create(player);
}
@ArenaCommand(commands = "layer", subCommands = "add", description = "Adds a layer to a spleef arena.", permissionNode = "layer.add")
public void layer(Player player, CompetitionMap map) {
@@ -0,0 +1,61 @@
package org.battleplugins.arena.spleef;
import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.protection.flags.Flag;
import com.sk89q.worldguard.protection.flags.StateFlag;
import com.sk89q.worldguard.protection.flags.registry.FlagConflictException;
import com.sk89q.worldguard.protection.flags.registry.FlagRegistry;
import org.bukkit.plugin.Plugin;
public final class SpleefFlags {
public static final String ALLOW_SPLEEF_FLAG_NAME = "allow-spleef";
private static StateFlag allowSpleefFlag;
private SpleefFlags() {
}
public static void register(Plugin plugin) {
FlagRegistry registry = WorldGuard.getInstance().getFlagRegistry();
try {
StateFlag flag = new StateFlag(ALLOW_SPLEEF_FLAG_NAME, false);
registry.register(flag);
allowSpleefFlag = flag;
} catch (FlagConflictException conflict) {
Flag<?> existing = registry.get(ALLOW_SPLEEF_FLAG_NAME);
if (existing instanceof StateFlag stateFlag) {
allowSpleefFlag = stateFlag;
plugin.getSLF4JLogger().info("Reusing existing WorldGuard flag '{}'.", ALLOW_SPLEEF_FLAG_NAME);
} else {
plugin.getSLF4JLogger().error(
"WorldGuard flag '{}' is already registered with an incompatible type; spleef will not enforce it.",
ALLOW_SPLEEF_FLAG_NAME);
}
} catch (IllegalStateException late) {
plugin.getSLF4JLogger().error(
"Failed to register WorldGuard flag '{}' — registry already locked. Ensure Spleef-OG loads before WorldGuard enables.",
ALLOW_SPLEEF_FLAG_NAME, late);
}
}
public static StateFlag getAllowSpleefFlag() {
return allowSpleefFlag;
}
}
@@ -34,4 +34,13 @@ public final class SpleefMessages {
public static final Message DEATH_REGION_SET = Messages.success("spleef-death-region-set",
"Death region set successfully!");
public static final Message CREATE_WORLD_NOT_WHITELISTED = Messages.error("spleef-create-world-not-whitelisted",
"Spleef arenas cannot be created in this world. World <secondary>{}</secondary> is not in the Spleef world whitelist.");
public static final Message CREATE_WG_FLAG_REQUIRED = Messages.error("spleef-create-wg-flag-required",
"You must stand inside a WorldGuard region that has the <secondary>allow-spleef</secondary> flag set to <secondary>allow</secondary> to create a Spleef arena here.");
public static final Message CREATE_WG_MISSING = Messages.error("spleef-create-wg-missing",
"WorldGuard is not loaded; Spleef arena creation is disabled.");
public static final Message WORLD_BLOCKED_AT_RUNTIME = Messages.error("spleef-world-blocked",
"Spleef matches are not permitted in world <secondary>{}</secondary>.");
}
@@ -2,11 +2,15 @@ package org.battleplugins.arena.spleef;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.protection.ApplicableRegionSet;
import com.sk89q.worldguard.protection.flags.StateFlag;
import com.sk89q.worldguard.protection.managers.RegionManager;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.Player;
public final class WorldGuardSupport {
@@ -36,4 +40,29 @@ public final class WorldGuardSupport {
}
public static boolean isSpleefAllowedAt(Player player) {
StateFlag flag = SpleefFlags.getAllowSpleefFlag();
if (flag == null) {
return false;
}
LocalPlayer localPlayer = WorldGuardPlugin.inst().wrapPlayer(player);
Location location = player.getLocation();
RegionManager regionManager = WorldGuard.getInstance().getPlatform().getRegionContainer()
.get(BukkitAdapter.adapt(location.getWorld()));
if (regionManager == null) {
return false;
}
BlockVector3 position = BlockVector3.at(location.getBlockX(), location.getBlockY(), location.getBlockZ());
ApplicableRegionSet regions = regionManager.getApplicableRegions(position);
return regions.testState(localPlayer, flag);
}
}
@@ -84,6 +84,17 @@ public class SpleefArena extends Arena {
if (event.getCompetition() instanceof SpleefCompetition spleefCompetition) {
org.bukkit.World mapWorld = spleefCompetition.getMap().getWorld();
String worldName = mapWorld == null ? null : mapWorld.getName();
if (!ArenaSpleef.getInstance().getMainConfig().isWorldAllowed(worldName)) {
ArenaSpleef.getInstance().getSLF4JLogger().warn(
"Refusing to start Spleef competition '{}' — world '{}' is not in the Spleef world whitelist.",
spleefCompetition.getMap().getName(), worldName);
return;
}
spleefCompetition.beginLayerDecay();
}
@@ -0,0 +1,139 @@
package org.battleplugins.arena.spleef.hook;
import org.battleplugins.arena.event.player.ArenaJoinEvent;
import org.battleplugins.arena.event.player.ArenaLeaveEvent;
import org.battleplugins.arena.event.player.ArenaSpectateEvent;
import org.battleplugins.arena.spleef.api.SpleefAPI;
import org.battleplugins.arena.spleef.arena.SpleefCompetition;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.permissions.PermissionAttachment;
import org.bukkit.plugin.Plugin;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public final class GameModeInventoriesListener implements Listener {
public static final String PLUGIN_NAME = "GameModeInventories-OG";
private static final String USE_PERMISSION = "gamemodeinventories.use";
private final Plugin owner;
private final Map<UUID, PermissionAttachment> attachments = new HashMap<>();
private GameModeInventoriesListener(Plugin owner) {
this.owner = owner;
}
public static GameModeInventoriesListener register(Plugin owner) {
final Plugin gameModeInventories = Bukkit.getPluginManager().getPlugin(PLUGIN_NAME);
if (gameModeInventories == null || !gameModeInventories.isEnabled()) {
return null;
}
final GameModeInventoriesListener listener = new GameModeInventoriesListener(owner);
Bukkit.getPluginManager().registerEvents(listener, owner);
return listener;
}
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void onArenaJoin(ArenaJoinEvent event) {
if (event.getArenaPlayer().getCompetition() instanceof SpleefCompetition) {
this.suspend(event.getPlayer());
}
}
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void onArenaSpectate(ArenaSpectateEvent event) {
if (event.getArenaPlayer().getCompetition() instanceof SpleefCompetition) {
this.suspend(event.getPlayer());
}
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onArenaLeave(ArenaLeaveEvent event) {
if (!(event.getArenaPlayer().getCompetition() instanceof SpleefCompetition)) {
return;
}
final Player player = event.getPlayer();
Bukkit.getScheduler().runTask(this.owner, () -> {
if (!SpleefAPI.isInSpleef(player)) {
this.release(player);
}
});
}
public void releaseAll() {
for (PermissionAttachment attachment : this.attachments.values()) {
try {
attachment.remove();
} catch (IllegalArgumentException ignored) {
}
}
this.attachments.clear();
}
private void suspend(Player player) {
// Keep GMI from saving arena-cleared contents over real inventories.
this.attachments.computeIfAbsent(player.getUniqueId(),
key -> player.addAttachment(this.owner, USE_PERMISSION, false));
}
private void release(Player player) {
final PermissionAttachment attachment = this.attachments.remove(player.getUniqueId());
if (attachment == null) {
return;
}
try {
attachment.remove();
} catch (IllegalArgumentException ignored) {
}
}
}
+4
View File
@@ -10,6 +10,10 @@ config-version: 2.0 # The config version, do not change!
# Whether projectiles (i.e. snowballs) should break blocks or not.
projectiles-break-blocks: false
# Worlds where Spleef arenas may be created and where matches may run.
# Leave empty to allow every world. Names are matched case-insensitively.
world-whitelist: []
# The shovels to use for Spleef.
shovels:
classic: diamond_shovel{display-name=<yellow>Spleef Shovel}
+1 -1
View File
@@ -6,4 +6,4 @@ author: BattlePlugins
website: https://battleplugins.org
api-version: ${apiVersion}
depend: [BattleArena, WorldGuard]
softdepend: [HorseTp-OG, PetTeleport-OG, PlayerBounties-OG, WorldEdit]
softdepend: [GameModeInventories-OG, HorseTp-OG, PetTeleport-OG, PlayerBounties-OG, WorldEdit]