From 28af30cc309711930e9349dd301d9d238a0417a4 Mon Sep 17 00:00:00 2001 From: Jascha Starke Date: Thu, 19 Jan 2012 22:47:41 +0100 Subject: [PATCH] Added region support Separated Features (optional disable): - Store inventories - Limit creative - Region support other details --- README.md | 8 +- config.yml | 27 ++- lang/default.yml | 13 +- plugin.yml | 9 +- .../minecraft/limitedcreative/Commands.java | 25 ++- .../limitedcreative/Configuration.java | 14 +- .../minecraft/limitedcreative/LCPlayer.java | 115 +++++++++-- .../limitedcreative/LimitedCreativeCore.java | 11 +- .../minecraft/limitedcreative/Listener.java | 18 +- .../WorldGuardIntegration.java | 181 +++++++++++++++++- .../minecraft/regions/ApplicableRegions.java | 55 ++++++ .../minecraft/regions/CRegion.java | 71 +++++++ .../minecraft/regions/CRegionManager.java | 121 ++++++++++++ .../minecraft/regions/FlagList.java | 62 ++++++ .../minecraft/regions/FlagValue.java | 35 ++++ .../minecraft/regions/IRestrictedFlag.java | 24 +++ src/de/jaschastarke/minecraft/utils/Util.java | 15 ++ 17 files changed, 767 insertions(+), 37 deletions(-) create mode 100644 src/de/jaschastarke/minecraft/regions/ApplicableRegions.java create mode 100644 src/de/jaschastarke/minecraft/regions/CRegion.java create mode 100644 src/de/jaschastarke/minecraft/regions/CRegionManager.java create mode 100644 src/de/jaschastarke/minecraft/regions/FlagList.java create mode 100644 src/de/jaschastarke/minecraft/regions/FlagValue.java create mode 100644 src/de/jaschastarke/minecraft/regions/IRestrictedFlag.java diff --git a/README.md b/README.md index f6ed56f..e629f25 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,10 @@ # Limited Creative http://dev.bukkit.org/server-mods/limited-creative/ -There is no automated building yet, so just use "Export..." -> "JAR file" in Eclipse \ No newline at end of file +There is no automated building yet, so just use "Export..." -> "JAR file" in Eclipse + +Dependencies: +* [Craftbukkit](https://github.com/Bukkit/CraftBukkit) + * which implies [Bukkit](https://github.com/Bukkit/Bukkit) +* Optional: [WorldGuard](https://github.com/sk89q/worldguard) + * which depends on [WorldEdit](https://github.com/sk89q/worldedit) \ No newline at end of file diff --git a/config.yml b/config.yml index ff80e72..5e5b853 100644 --- a/config.yml +++ b/config.yml @@ -5,6 +5,12 @@ # -------------------------------- store: + # SeparatedInventoryEnabled + # Use this option to disable the separated inventories feature, for the case you only need the other features. + # This option can only changed by reloading the plugin (not via ingame commands). + # default: true + enabled: true + # StoreCreative # Should the creative-inventory also be stored on disk, when switching to survival? # If disabled, the inventory gets cleared every time on switching to creative. @@ -13,15 +19,22 @@ store: # InventoryFolder # The folder inside the datadir-folder (plugin/LimitedCreative) where the inventories are saved to. - # By default the inventories are saved to plugin/LimitedCreative/inventories. + # By default the inventories are saved to "plugin/LimitedCreative/inventories". # default: "inventories" folder: "inventories" limit: + # LimitsEnabled + # Use this option to disable all drop/pvp/etc. preventions while in creative mode. While you also can get this + # by giving the "nolimit" permissions, using this option can save you CPU performance. This option can only changed + # by reloading the plugin (not via ingame commands). + # default: true + enabled: true + # BlockPickup # Prevents the pickup of items while in creative mode - # default: true - pickup: true + # default: false + pickup: false # BlockSign # Prevents interacting with signs (right-click), while in creative mode, so trading becomes more difficult. @@ -29,6 +42,14 @@ limit: # default: true sign: true +region: + # RegionsEnabled + # Enables the Feature for "creative-regions". This Feature is automatically disabled, if the required plugin + # "WorldGuard" (http://dev.bukkit.org/server-mods/worldguard/) isn't found. + # This option can only changed by reloading the plugin (not via ingame commands). + # default: true + enabled: true + permissions: # PermissionsEnabled # When enabled, the Permissions will allow selected users to ignore limitations like PvP, Chest-Block, etc. diff --git a/lang/default.yml b/lang/default.yml index 43ee228..1284ad9 100644 --- a/lang/default.yml +++ b/lang/default.yml @@ -9,6 +9,16 @@ command: changed: "{0}'s game mode has been changed" option: done: Option changed. + worldguard: + alias: Alias for //region-command + unknown_flag: Unknown flag specified + available_flags: Available flags + region_not_found: Could not find a region by that ID + world_not_found: Could not find a world by that name + no_flag_given: You need to specify a flag to set + no_integration: The worldguard-commands are not available, because worldguard wasn't found + flag_set: "The flag {0} was set" + additional_flags: Additional flags exception: command: lackingpermission: You do not have access to this command @@ -20,4 +30,5 @@ exception: savefail: Failed to write modified configuration to disk blocked: chest: Access to chests is not allowed in creative mode - sign: To interact with signs is not allowed in creative mode \ No newline at end of file + sign: To interact with signs is not allowed in creative mode + survival_flying: You should stay on ground, when leaving a creative-area \ No newline at end of file diff --git a/plugin.yml b/plugin.yml index 3fe156f..80297da 100644 --- a/plugin.yml +++ b/plugin.yml @@ -1,16 +1,23 @@ name: LimitedCreative main: de.jaschastarke.minecraft.limitedcreative.LimitedCreativeCore -version: 0.2-beta +version: 0.5-beta softdepend: [WorldGuard] commands: limitedcreative: description: Main LimitedCreative-Controlling-Commands aliases: lc usage: / - displays LimitedCreative-Help + /region: + description: Alternate region command, to use for WorldGuard-Integration + aliases: lcregion + usage: / info|flag [#] - set/get region options permissions: limitedcreative.config: description: Allows enabling/disabling of config options ingame default: op + limitedcreative.regions: + description: Allows usage of the //region commands + default: op limitedcreative.switch_gamemode: description: Allows switching of own game mode to creative and back default: op diff --git a/src/de/jaschastarke/minecraft/limitedcreative/Commands.java b/src/de/jaschastarke/minecraft/limitedcreative/Commands.java index bcdf51b..1568b39 100644 --- a/src/de/jaschastarke/minecraft/limitedcreative/Commands.java +++ b/src/de/jaschastarke/minecraft/limitedcreative/Commands.java @@ -17,6 +17,8 @@ */ package de.jaschastarke.minecraft.limitedcreative; +import java.util.Arrays; + import org.bukkit.ChatColor; import org.bukkit.GameMode; import org.bukkit.command.Command; @@ -34,6 +36,7 @@ public class Commands { S, SURVIVAL, E, ENABLE, D, DISABLE, + R, REGION, }; @Override @@ -62,6 +65,11 @@ public class Commands { case DISABLE: this.setOption(sender, args, false); return true; + case R: + case REGION: + args = Arrays.copyOfRange(args, 1, args.length); + plugin.getCommand("/region").execute(sender, "/region", args); + return true; } } catch (CommandException e) { sender.sendMessage(ChatColor.DARK_RED + e.getLocalizedMessage()); @@ -80,6 +88,8 @@ public class Commands { message += "/"+c+" e[nable] "+L("command.config.overview")+"\n"; if (sender.hasPermission("limitedcreative.config")) message += "/"+c+" d[isable] "+L("command.config.overview")+"\n"; + if (sender.hasPermission("limitedcreative.config")) + message += "/"+c+" r[egion] "+L("command.worldguard.alias")+"\n"; if (message.length() > 0) { sender.sendMessage("Usage:"); for (String m : message.split("\n")) { @@ -167,10 +177,23 @@ public class Commands { } + public static class NotAvailableCommandExecutor implements CommandExecutor { + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + sender.sendMessage(ChatColor.DARK_RED + L("command.worldguard.no_integration")); + return true; + } + + } + public static void register(LimitedCreativeCore pplugin) { plugin = pplugin; - plugin.getCommand("limitedcreative").setExecutor(new MainCommandExecutor()); + if (plugin.worldguard != null) { + plugin.getCommand("/region").setExecutor(plugin.worldguard.new WGICommandExecutor()); // very odd syntax, but i liiiikey internal classes :D + } else { + plugin.getCommand("/region").setExecutor(new NotAvailableCommandExecutor()); + } } abstract static public class CommandException extends Exception { diff --git a/src/de/jaschastarke/minecraft/limitedcreative/Configuration.java b/src/de/jaschastarke/minecraft/limitedcreative/Configuration.java index b315df5..20cd17a 100644 --- a/src/de/jaschastarke/minecraft/limitedcreative/Configuration.java +++ b/src/de/jaschastarke/minecraft/limitedcreative/Configuration.java @@ -18,12 +18,10 @@ package de.jaschastarke.minecraft.limitedcreative; import java.io.File; -//import java.io.IOException; import org.bukkit.configuration.file.FileConfiguration; import static de.jaschastarke.minecraft.utils.Util.copyFile; -//import static de.jaschastarke.minecraft.utils.Locale.L; public class Configuration { private FileConfiguration c; @@ -40,6 +38,17 @@ public class Configuration { c = plugin.getConfig(); } + + public boolean getStoreEnabled() { + return c.getBoolean("store.enabled", true); + } + public boolean getLimitEnabled() { + return c.getBoolean("limit.enabled", true); + } + public boolean getRegionEnabled() { + return c.getBoolean("region.enabled", true); + } + public boolean getStoreCreative() { return c.getBoolean("store.creative", true); } @@ -59,6 +68,7 @@ public class Configuration { return this.getPermissionsEnabled() && c.getBoolean("permissions.keepinventory", false); } + public void setStoreCreative(boolean value) { this.reload(); c.set("store.creative", value); diff --git a/src/de/jaschastarke/minecraft/limitedcreative/LCPlayer.java b/src/de/jaschastarke/minecraft/limitedcreative/LCPlayer.java index 74f559f..37f42c7 100644 --- a/src/de/jaschastarke/minecraft/limitedcreative/LCPlayer.java +++ b/src/de/jaschastarke/minecraft/limitedcreative/LCPlayer.java @@ -19,16 +19,24 @@ package de.jaschastarke.minecraft.limitedcreative; import static de.jaschastarke.minecraft.utils.Locale.L; +import java.io.File; +import java.io.IOException; import java.util.HashMap; import java.util.Map; import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.entity.EntityDeathEvent; import org.bukkit.event.player.PlayerDropItemEvent; import org.bukkit.event.player.PlayerInteractEntityEvent; import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerMoveEvent; import org.bukkit.event.player.PlayerPickupItemEvent; import org.bukkit.event.player.PlayerRespawnEvent; import org.bukkit.inventory.ItemStack; @@ -40,9 +48,22 @@ public class LCPlayer { private static Map players = new HashMap(); private Player player; private Map tempinv = null; + + private static File _store_file = new File(plugin.getDataFolder(), "players.yml"); + public static YamlConfiguration store = YamlConfiguration.loadConfiguration(_store_file); + + private boolean isPermanentCreative = false; + private boolean _isRegionCreative = false; private LCPlayer(Player pplayer) { player = pplayer; + _isRegionCreative = store.getBoolean(player.getName()+".region_creative", false); + if (player.getGameMode() == GameMode.CREATIVE && !this.getRegionCreative()) + isPermanentCreative = true; + } + + public Player getRaw() { + return player; } public static LCPlayer get(Player pplayer) { @@ -55,26 +76,52 @@ public class LCPlayer { } } - public void onSetCreative() { - if (plugin.config.getPermissionToKeepInventory() && player.hasPermission("limitedcreative.keepinventory")) - return; - Inventory inv = new Inventory(player); - inv.save(); - if (plugin.config.getStoreCreative() && inv.isStored(GameMode.CREATIVE)) { - inv.load(GameMode.CREATIVE); + public boolean getRegionCreative() { + return _isRegionCreative; + } + public void setRegionCreative(boolean b) { + if (b) { + store.set(player.getName()+".region_creative", true); } else { - inv.clear(); + store.set(player.getName(), null); + } + try { + store.save(_store_file); + } catch (IOException e) { + plugin.logger.severe("Failed to save players.yml"); + e.printStackTrace(); + } + _isRegionCreative = b; + } + + public void onSetCreative() { + if (!this.getRegionCreative()) + isPermanentCreative = true; + if (plugin.config.getStoreEnabled()) { + if (plugin.config.getPermissionToKeepInventory() && player.hasPermission("limitedcreative.keepinventory")) + return; + Inventory inv = new Inventory(player); + inv.save(); + if (plugin.config.getStoreCreative() && inv.isStored(GameMode.CREATIVE)) { + inv.load(GameMode.CREATIVE); + } else { + inv.clear(); + } } } public void onSetSurvival() { - if (plugin.config.getPermissionToKeepInventory() && player.hasPermission("limitedcreative.keepinventory")) - return; - Inventory inv = new Inventory(player); - if (plugin.config.getStoreCreative()) { - inv.save(); + isPermanentCreative = false; + setRegionCreative(false); + if (plugin.config.getStoreEnabled()) { + if (plugin.config.getPermissionToKeepInventory() && player.hasPermission("limitedcreative.keepinventory")) + return; + Inventory inv = new Inventory(player); + if (plugin.config.getStoreCreative()) { + inv.save(); + } + if (inv.isStored(GameMode.SURVIVAL)) + inv.load(GameMode.SURVIVAL); } - if (inv.isStored(GameMode.SURVIVAL)) - inv.load(GameMode.SURVIVAL); } public void onDropItem(PlayerDropItemEvent event) { if (player.getGameMode() == GameMode.CREATIVE) { @@ -150,5 +197,43 @@ public class LCPlayer { event.getPlayer().sendMessage(L("blocked.sign")); event.setCancelled(true); } + + public void setRegionCreativeAllowed(boolean rcreative, PlayerMoveEvent event) { + if (rcreative && player.getGameMode() == GameMode.SURVIVAL) { + setRegionCreative(true); // have to be set, before setGameMode + player.setGameMode(GameMode.CREATIVE); + } else if (!rcreative && player.getGameMode() == GameMode.CREATIVE && !isPermanentCreative) { + if (getFloatingHeight() > 3) { + player.sendMessage(L("blocked.survival_flying")); + event.setTo(event.getFrom()); + } else { + player.setGameMode(GameMode.SURVIVAL); // also unsets isRegionCreative; + } + } + } + public int getFloatingHeight() { + Block b = player.getLocation().getBlock(); + int steps = 0; + while (b.getType() == Material.AIR) { + steps++; + b = b.getRelative(BlockFace.DOWN); + } + return steps; + } + + public void goToFloor() { + Block b = player.getLocation().getBlock(); + int steps = 0; + while (b.getType() == Material.AIR) { + steps++; + b = b.getRelative(BlockFace.DOWN); + } + if (steps > 2) { + player.teleport(new Location(player.getWorld(), + player.getLocation().getX(), + b.getY()+1, + player.getLocation().getZ())); + } + } } diff --git a/src/de/jaschastarke/minecraft/limitedcreative/LimitedCreativeCore.java b/src/de/jaschastarke/minecraft/limitedcreative/LimitedCreativeCore.java index 437d397..6d0fcc0 100644 --- a/src/de/jaschastarke/minecraft/limitedcreative/LimitedCreativeCore.java +++ b/src/de/jaschastarke/minecraft/limitedcreative/LimitedCreativeCore.java @@ -22,6 +22,7 @@ import org.bukkit.plugin.PluginDescriptionFile; import org.bukkit.plugin.java.JavaPlugin; import static de.jaschastarke.minecraft.utils.Util.versionCompare; +import static de.jaschastarke.minecraft.utils.Locale.L; import de.jaschastarke.minecraft.utils.Locale; @@ -48,13 +49,15 @@ public class LimitedCreativeCore extends JavaPlugin { new Locale(this); Listener.register(this); - Commands.register(this); - try { - Class.forName("com.sk89q.worldguard.bukkit.WorldGuardPlugin", false, null); + if (config.getRegionEnabled() && WorldGuardIntegration.available()) { worldguard = new WorldGuardIntegration(this); worldguard.init(); - } catch (ClassNotFoundException e) {} + } else { + logger.info("["+this.getDescription().getName()+"] "+L("warning.no_worldguard_found")); + } + + Commands.register(this); PluginDescriptionFile df = this.getDescription(); logger.info("["+df.getName() + " v" + df.getVersion() + "] done loading."); diff --git a/src/de/jaschastarke/minecraft/limitedcreative/Listener.java b/src/de/jaschastarke/minecraft/limitedcreative/Listener.java index a1df001..02c7ab2 100644 --- a/src/de/jaschastarke/minecraft/limitedcreative/Listener.java +++ b/src/de/jaschastarke/minecraft/limitedcreative/Listener.java @@ -100,11 +100,13 @@ public final class Listener { private void register() { pm.registerEvent(Event.Type.PLAYER_GAME_MODE_CHANGE, this, Priority.Normal, plugin); - pm.registerEvent(Event.Type.PLAYER_DROP_ITEM, this, Priority.Normal, plugin); - pm.registerEvent(Event.Type.PLAYER_PICKUP_ITEM, this, Priority.Normal, plugin); - pm.registerEvent(Event.Type.PLAYER_INTERACT, this, Priority.Lowest, plugin); - pm.registerEvent(Event.Type.PLAYER_INTERACT_ENTITY, this, Priority.Lowest, plugin); - pm.registerEvent(Event.Type.PLAYER_RESPAWN, this, Priority.Normal, plugin); + if (plugin.config.getLimitEnabled()) { + pm.registerEvent(Event.Type.PLAYER_DROP_ITEM, this, Priority.Normal, plugin); + pm.registerEvent(Event.Type.PLAYER_PICKUP_ITEM, this, Priority.Normal, plugin); + pm.registerEvent(Event.Type.PLAYER_INTERACT, this, Priority.Lowest, plugin); + pm.registerEvent(Event.Type.PLAYER_INTERACT_ENTITY, this, Priority.Lowest, plugin); + pm.registerEvent(Event.Type.PLAYER_RESPAWN, this, Priority.Normal, plugin); + } } } @@ -128,8 +130,10 @@ public final class Listener { } private void register() { - pm.registerEvent(Event.Type.ENTITY_DAMAGE, this, Priority.Normal, plugin); - pm.registerEvent(Event.Type.ENTITY_DEATH, this, Priority.Low, plugin); + if (plugin.config.getLimitEnabled()) { + pm.registerEvent(Event.Type.ENTITY_DAMAGE, this, Priority.Normal, plugin); + pm.registerEvent(Event.Type.ENTITY_DEATH, this, Priority.Low, plugin); + } } } diff --git a/src/de/jaschastarke/minecraft/limitedcreative/WorldGuardIntegration.java b/src/de/jaschastarke/minecraft/limitedcreative/WorldGuardIntegration.java index 98ed071..a6a27a7 100644 --- a/src/de/jaschastarke/minecraft/limitedcreative/WorldGuardIntegration.java +++ b/src/de/jaschastarke/minecraft/limitedcreative/WorldGuardIntegration.java @@ -17,23 +17,200 @@ */ package de.jaschastarke.minecraft.limitedcreative; +import java.io.File; + +import org.bukkit.ChatColor; +import org.bukkit.World; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.Event.Priority; +import org.bukkit.event.player.PlayerListener; +import org.bukkit.event.player.PlayerMoveEvent; + +import static de.jaschastarke.minecraft.utils.Locale.L; + +import com.sk89q.worldedit.Vector; import com.sk89q.worldguard.bukkit.WorldGuardPlugin; -//import com.sk89q.worldguard.protection.flags.DefaultFlag; +import com.sk89q.worldguard.protection.flags.Flag; +import com.sk89q.worldguard.protection.flags.InvalidFlagFormat; +import com.sk89q.worldguard.protection.flags.RegionGroupFlag; import com.sk89q.worldguard.protection.flags.StateFlag; +import com.sk89q.worldguard.protection.managers.RegionManager; +import com.sk89q.worldguard.protection.regions.GlobalProtectedRegion; +import com.sk89q.worldguard.protection.regions.ProtectedRegion; + +import de.jaschastarke.minecraft.regions.ApplicableRegions; +import de.jaschastarke.minecraft.regions.CRegion; +import de.jaschastarke.minecraft.regions.CRegionManager; +import de.jaschastarke.minecraft.regions.FlagList; +import de.jaschastarke.minecraft.regions.FlagValue; +import de.jaschastarke.minecraft.utils.Util; public class WorldGuardIntegration { public static LimitedCreativeCore plugin; public static WorldGuardPlugin wg; + private CRegionManager rm; public WorldGuardIntegration(LimitedCreativeCore pplugin) { plugin = pplugin; wg = (WorldGuardPlugin) plugin.getServer().getPluginManager().getPlugin("WorldGuard"); } + public static boolean available() { + return LimitedCreativeCore.plugin.getServer().getPluginManager().getPlugin("WorldGuard") != null; + } + - public static final StateFlag CREATIVE_MEMBER = new StateFlag("creative-member", false); + public static final StateFlag CREATIVE = new StateFlag("creative", false); + public static final RegionGroupFlag CREATIVE_GROUP = new RegionGroupFlag("creative-group", RegionGroupFlag.RegionGroup.MEMBERS); + static { + CREATIVE.setGroupFlag(CREATIVE_GROUP); + } public void init() { + rm = new CRegionManager(new File(plugin.getDataFolder(), "regions.yml")); + FlagList.addFlag(CREATIVE); + FlagList.addFlag(CREATIVE_GROUP); + new WGIPlayerListen().register(); + } + + public enum Action { + FLAG, + INFO + } + + public class WGIPlayerListen extends PlayerListener { + @Override + public void onPlayerMove(PlayerMoveEvent event) { + if (event.isCancelled()) + return; + if (event.getFrom().getBlockX() != event.getTo().getBlockX() + || event.getFrom().getBlockY() != event.getTo().getBlockY() + || event.getFrom().getBlockZ() != event.getTo().getBlockZ()) { + + LCPlayer player = LCPlayer.get(event.getPlayer()); + RegionManager mgr = wg.getGlobalRegionManager().get(event.getPlayer().getWorld()); + Vector pt = new Vector(event.getTo().getBlockX(), event.getTo().getBlockY(), event.getTo().getBlockZ()); + ApplicableRegions set = new ApplicableRegions(mgr.getApplicableRegions(pt), rm.world(event.getPlayer().getWorld())); + + player.setRegionCreativeAllowed(set.allows(CREATIVE, player), event); + } + } + + private void register() { + plugin.getServer().getPluginManager().registerEvent(Event.Type.PLAYER_MOVE, this, Priority.Normal, plugin); + } + } + + /** + * @TODO: Move "generic" region command to .regions-NS + */ + public class WGICommandExecutor implements CommandExecutor { + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (args.length < 2) { + return false; + } + if (!sender.hasPermission("limitedcreative.regions")) { + sender.sendMessage(ChatColor.DARK_RED + "exception.command.lackingpermission"); + return true; + } + Player player = sender instanceof Player ? (Player) sender : null; + World world = null; + Action act; + String rid; + try { + act = Action.valueOf(args[0].toUpperCase()); + } catch (IllegalArgumentException e) { + return false; + } + String[] wr = args[1].split("#"); + if (wr.length == 2) { + world = plugin.getServer().getWorld(wr[0]); + rid = wr[1]; + } else { + rid = args[1]; + if (player != null) { + world = player.getWorld(); + } else { + sender.sendMessage(ChatColor.DARK_RED + L("command.worldguard.world_not_found")); + return true; + } + } + + + RegionManager mgr = wg.getGlobalRegionManager().get(world); + ProtectedRegion region = mgr.getRegion(rid); + if (region == null) { + if (rid.equalsIgnoreCase("__global__")) { + region = new GlobalProtectedRegion(rid); + mgr.addRegion(region); + } else { + sender.sendMessage(ChatColor.DARK_RED + L("command.worldguard.region_not_found")); + return true; + } + } + + CRegion reg = rm.world(world).region(region); + + switch (act) { + case INFO: + onInfo(sender, player, reg); + return true; + case FLAG: + onFlag(sender, player, reg, args); + return true; + } + return false; + } + + private void onInfo(CommandSender sender, Player player, CRegion region) { + String[] args = new String[]{"info", region.getWorld().getName(), region.getProtectedRegion().getId()}; + wg.onCommand(sender, wg.getCommand("region"), "/region", args); + + StringBuilder list = new StringBuilder(); + for (FlagValue data : region.getFlags()) { + if (list.length() > 0) + list.append(", "); + list.append(data.getFlag().getName()); + list.append(": "); + list.append(data.getValue().toString()); + } + + sender.sendMessage(ChatColor.GREEN + L("command.worldguard.additional_flags") + ": " + list.toString()); + } + private void onFlag(CommandSender sender, Player player, CRegion region, String[] args) { + if (args.length < 3) { + sender.sendMessage(ChatColor.DARK_RED + L("command.worldguard.no_flag_given")); + sender.sendMessage(ChatColor.DARK_RED + L("command.worldguard.available_flags") + ": " + FlagList.getStringListAvailableFlags(sender)); + return; + } + String flagName = args[2]; + Flag flag = FlagList.getFlag(flagName); + if (flag == null) { + sender.sendMessage(ChatColor.DARK_RED + L("command.worldguard.unknown_flag") + ": " + flagName); + sender.sendMessage(ChatColor.DARK_RED + L("command.worldguard.available_flags") + ": " + FlagList.getStringListAvailableFlags(sender)); + return; + } + String value = null; + if (args.length > 3) + value = Util.join(args, 3); + + try { + if (value != null) { + region.setFlag(flag, flag.parseInput(wg, sender, value)); + } else { + region.setFlag(flag, null); + } + } catch (InvalidFlagFormat e) { + sender.sendMessage(ChatColor.DARK_RED + e.getLocalizedMessage()); + return; + } + sender.sendMessage(L("command.worldguard.flag_set", flag.getName())); + } } } diff --git a/src/de/jaschastarke/minecraft/regions/ApplicableRegions.java b/src/de/jaschastarke/minecraft/regions/ApplicableRegions.java new file mode 100644 index 0000000..fbb65d9 --- /dev/null +++ b/src/de/jaschastarke/minecraft/regions/ApplicableRegions.java @@ -0,0 +1,55 @@ +package de.jaschastarke.minecraft.regions; + +import com.sk89q.worldguard.protection.ApplicableRegionSet; +import com.sk89q.worldguard.protection.flags.Flag; +import com.sk89q.worldguard.protection.flags.StateFlag; +import com.sk89q.worldguard.protection.regions.ProtectedRegion; + +import de.jaschastarke.minecraft.limitedcreative.LCPlayer; +import de.jaschastarke.minecraft.limitedcreative.WorldGuardIntegration; + +public class ApplicableRegions { + private ApplicableRegionSet regions; + private CRegionManager.CWorld mgr; + + public ApplicableRegions(ApplicableRegionSet regions, CRegionManager.CWorld rm) { + this.regions = regions; + this.mgr = rm; + } + + + public boolean allows(StateFlag flag) { + extendRegionFlags(); + boolean r = regions.allows(flag); + contractRegionFlags(); + return r; + } + + public boolean allows(StateFlag flag, LCPlayer player) { + extendRegionFlags(); + boolean r = regions.allows(flag, WorldGuardIntegration.wg.wrapPlayer(player.getRaw())); + contractRegionFlags(); + return r; + } + + @SuppressWarnings("unchecked") + private , V> void extendRegionFlags() { + for (ProtectedRegion pr : regions) { + for (FlagValue data : mgr.region(pr).getFlags()) { + T flag = (T) data.getFlag(); + V value = (V) data.getValue(); + pr.setFlag(flag, value); + } + } + } + @SuppressWarnings("unchecked") + private , V> void contractRegionFlags() { + for (ProtectedRegion pr : regions) { + for (FlagValue data : mgr.region(pr).getFlags()) { + T flag = (T) data.getFlag(); + pr.setFlag(flag, null); + } + } + } + +} diff --git a/src/de/jaschastarke/minecraft/regions/CRegion.java b/src/de/jaschastarke/minecraft/regions/CRegion.java new file mode 100644 index 0000000..54749da --- /dev/null +++ b/src/de/jaschastarke/minecraft/regions/CRegion.java @@ -0,0 +1,71 @@ +/* + * Limited Creative - (Bukkit Plugin) + * Copyright (C) 2012 jascha@ja-s.de + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package de.jaschastarke.minecraft.regions; + +import java.util.Iterator; +import java.util.List; + +import org.bukkit.World; + +import com.sk89q.worldguard.protection.flags.Flag; +import com.sk89q.worldguard.protection.regions.ProtectedRegion; +import de.jaschastarke.minecraft.regions.CRegionManager.CWorld; + +public class CRegion { + private ProtectedRegion region; + private CWorld mgr; + private List flags = null; + + protected CRegion(CWorld w, ProtectedRegion reg) { + mgr = w; + region = reg; + } + + public void removeFlag(Flag flag) { + if (flags != null) { + Iterator i = flags.iterator(); + while (i.hasNext()) { + if (i.next().getFlag() == flag) + i.remove(); + } + } + mgr.storeFlag(this, flag, null); + } + + public void setFlag(Flag flag, Object value) { + if (value == null) { + removeFlag(flag); + } else { + if (flags != null) + flags.add(new FlagValue(flag, value)); + mgr.storeFlag(this, flag, value); + } + } + public ProtectedRegion getProtectedRegion() { + return region; + } + public World getWorld() { + return mgr.getWorld(); + } + public List getFlags() { + if (flags == null) { + flags = mgr.getFlags(this); + } + return flags; + } +} diff --git a/src/de/jaschastarke/minecraft/regions/CRegionManager.java b/src/de/jaschastarke/minecraft/regions/CRegionManager.java new file mode 100644 index 0000000..fa6cf08 --- /dev/null +++ b/src/de/jaschastarke/minecraft/regions/CRegionManager.java @@ -0,0 +1,121 @@ +/* + * Limited Creative - (Bukkit Plugin) + * Copyright (C) 2012 jascha@ja-s.de + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package de.jaschastarke.minecraft.regions; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.bukkit.World; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.YamlConfiguration; + +import com.sk89q.worldguard.protection.flags.Flag; +import com.sk89q.worldguard.protection.regions.ProtectedRegion; + +public class CRegionManager { + protected YamlConfiguration c; + protected File file; + private Map worlds = new HashMap(); + public CRegionManager(File f) { + file = f; + c = YamlConfiguration.loadConfiguration(file); + } + + + public CWorld world(World w) { + if (worlds.containsKey(w)) { + return worlds.get(w); + } else { + CWorld r = new CWorld(w); + worlds.put(w, r); + return r; + } + } + + public class CWorld { + private World world; + private ConfigurationSection wc = null; + public CWorld(World w) { + world = w; + } + public CRegionManager getManager() { + return CRegionManager.this; + } + private Map regions = new HashMap(); + public CRegion region(ProtectedRegion pr) { + if (regions.containsKey(pr)) { + return regions.get(pr); + } else { + CRegion r = new CRegion(this, pr); + regions.put(pr, r); + return r; + } + } + public World getWorld() { + return world; + } + @SuppressWarnings("unchecked") + public void storeFlag(CRegion region, Flag flag, Object value) { + if (wc == null) { + if (c.contains(world.getName().toLowerCase())) + wc = c.getConfigurationSection(world.getName().toLowerCase()); + else + wc = c.createSection(world.getName().toLowerCase()); + } + + ConfigurationSection rs; + if (wc.contains(region.getProtectedRegion().getId())) + rs = wc.getConfigurationSection(region.getProtectedRegion().getId()); + else + rs = wc.createSection(region.getProtectedRegion().getId()); + + ConfigurationSection fs = rs.contains("flags") ? rs.getConfigurationSection("flags") : rs.createSection("flags"); + + fs.set(flag.getName(), flag.marshal((V) value)); + + try { + c.save(file); + } catch (IOException e) { + e.printStackTrace(); + } + } + public List getFlags(CRegion region) { + List list = new ArrayList(); + + if (c.contains(world.getName().toLowerCase())) { + ConfigurationSection wc = c.getConfigurationSection(world.getName().toLowerCase()); + if (wc.contains(region.getProtectedRegion().getId())) { + ConfigurationSection rs = wc.getConfigurationSection(region.getProtectedRegion().getId()); + if (rs.contains("flags")) { + ConfigurationSection fs = rs.getConfigurationSection("flags"); + for (Map.Entry data : fs.getValues(false).entrySet()) { + Flag flag = FlagList.getFlag(data.getKey()); + Object value = flag.unmarshal(data.getValue()); + list.add(new FlagValue(flag, value)); + } + } + } + } + return list; + } + } +} diff --git a/src/de/jaschastarke/minecraft/regions/FlagList.java b/src/de/jaschastarke/minecraft/regions/FlagList.java new file mode 100644 index 0000000..b4abf32 --- /dev/null +++ b/src/de/jaschastarke/minecraft/regions/FlagList.java @@ -0,0 +1,62 @@ +/* + * Limited Creative - (Bukkit Plugin) + * Copyright (C) 2012 jascha@ja-s.de + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package de.jaschastarke.minecraft.regions; + +import java.util.ArrayList; +import java.util.List; + +import org.bukkit.command.CommandSender; + +import com.sk89q.worldguard.protection.flags.Flag; + +public class FlagList { + protected static List> list = new ArrayList>(); + + public static List> getFlags() { + return list; + } + public static void addFlag(Flag flag) { + list.add(flag); + } + public static Flag getFlag(String flag) { + for (Flag f : list) { + if (f.getName().replace("-", "").equalsIgnoreCase(flag.replace("-", ""))) { + return f; + } + } + return null; + } + public static List> getAvailableFlags(CommandSender sender) { + List> result = new ArrayList>(); + for (Flag f : list) { + if (!(f instanceof IRestrictedFlag) || ((IRestrictedFlag) f).isAllowed(sender)) { + result.add(f); + } + } + return result; + } + public static String getStringListAvailableFlags(CommandSender sender) { + String result = ""; + for (Flag f : getAvailableFlags(sender)) { + if (result.length() > 0) + result += ", "; + result += f.getName(); + } + return result; + } +} diff --git a/src/de/jaschastarke/minecraft/regions/FlagValue.java b/src/de/jaschastarke/minecraft/regions/FlagValue.java new file mode 100644 index 0000000..cbd31ae --- /dev/null +++ b/src/de/jaschastarke/minecraft/regions/FlagValue.java @@ -0,0 +1,35 @@ +/* + * Limited Creative - (Bukkit Plugin) + * Copyright (C) 2012 jascha@ja-s.de + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package de.jaschastarke.minecraft.regions; + +import com.sk89q.worldguard.protection.flags.Flag; + +public class FlagValue { + private Flag flag; + private Object value; + public FlagValue(Flag flag, Object value) { + this.flag = flag; + this.value = value; + } + public Flag getFlag() { + return flag; + } + public Object getValue() { + return value; + } +} diff --git a/src/de/jaschastarke/minecraft/regions/IRestrictedFlag.java b/src/de/jaschastarke/minecraft/regions/IRestrictedFlag.java new file mode 100644 index 0000000..21cd9ea --- /dev/null +++ b/src/de/jaschastarke/minecraft/regions/IRestrictedFlag.java @@ -0,0 +1,24 @@ +/* + * Limited Creative - (Bukkit Plugin) + * Copyright (C) 2012 jascha@ja-s.de + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package de.jaschastarke.minecraft.regions; + +import org.bukkit.command.CommandSender; + +public interface IRestrictedFlag { + public boolean isAllowed(CommandSender sender); +} diff --git a/src/de/jaschastarke/minecraft/utils/Util.java b/src/de/jaschastarke/minecraft/utils/Util.java index 7cb44c2..e0ae596 100644 --- a/src/de/jaschastarke/minecraft/utils/Util.java +++ b/src/de/jaschastarke/minecraft/utils/Util.java @@ -63,4 +63,19 @@ final public class Util { e.printStackTrace(); } } + public static String join(String[] list, String sep, int from, int range) { + StringBuilder result = new StringBuilder(); + for (int i = from; i >= 0 && i < from + range && i < list.length; i++) { + if (result.length() > 0) + result.append(sep); + result.append(list[i]); + } + return result.toString(); + } + public static String join(String[] list, int from, int range) { + return join(list, " ", from, range); + } + public static String join(String[] list, int from) { + return join(list, " ", from, from); + } }