Add a bulk sign linking mode for easier setup

When using '/as linksigns' you will get in sign linking mode. With
leftclick you can select a sign (max 100 blocks away) and with
rightclick you can select an AreaShop region (max 100 blocks away). If
you selected both then the sign will be linked to the region and then
you can select both again. This way you can easily link a lot of signs
to regions. Advice: Use WorldEdit or similar to get signs in front of
all regions (//stack), then use sign linking mode to link them all.
This commit is contained in:
Thijs Wiefferink 2015-01-30 12:12:00 +01:00
parent 75b752a235
commit 58680c8cc4
14 changed files with 393 additions and 42 deletions

View File

@ -61,6 +61,7 @@ help-addFriend: "&6/as addfriend &7-&r Add a friend to your region."
help-addFriendAll: "&6/as addfriend &7-&r Add a friend to a region."
help-delFriend: "&6/as delfriend &7-&r Delete a friend from your region."
help-delFriendAll: "&6/as delfriend &7-&r Delete a friend from a region."
help-linksigns: "&6/as linksigns &7-&r Use bulk sign linking mode."
rent-help: "/as rent [regionname], the region you stand in will be used if not specified."
rent-noPermission: "You don't have permission to rent a region."
@ -312,8 +313,8 @@ addsign-noRegions: "No region found around the sign position."
addsign-couldNotDetect: "Found multiple regions around the sign, specify region as extra argument (2 of the regions that were found: %0% and %1%)."
addsign-couldNotDetectSign: "Found multiple regions around the sign, specify region on the second line (2 of the regions that were found: %0% and %1%)."
addsign-wrongProfile: "The specified profile does not exist, use one of the following (check config): &7%0%."
addsign-success: "The sign has been added to %0%."
addsign-successProfile: "The sign has been added to %0% with profile %1%."
addsign-success: "The sign has been added to %region%."
addsign-successProfile: "The sign has been added to %region% with profile %0%."
addsign-alreadyRegistered: "That sign is already registered for region %0%."
addsign-noPermission: "You don't have permission to add a sign."
@ -379,6 +380,18 @@ delfriend-success: "%0% has been deleted as friend from your region %1%."
delfriend-notAdded: "%0% is not added as friend for this region."
delfriend-noOwner: "You cannot remove friends from a region without owner."
linksigns-multipleRegions: "Found multiple regions: &7%0%."
linksigns-multipleRegionsAdvice: "Click another time to try again or use '/as linksigns' to stop."
linksigns-noRegions: "No AreaShop regions found in the direction of your cursor, make sure the region is added to AreaShop &7(maximum range 100 blocks)."
linksigns-regionFound: "Region %region% has been found, now point to a sign and leftclick to link it."
linksigns-signFound: "Found a sign at (%0%, %1%, %2%), now point towards a region and rightclick to link it"
linksigns-noSign: "No sign found in the direction of your cursor, make sure you have a direct sight to a sign and click again &7(maximum range 100 blocks)."
linksigns-alreadyRegistered: "That sign is already registered for region %region%, click again to select another sign."
linksigns-first: "You have entered sign linking mode."
linksigns-next: "&7Leftclick to select a sign, rightclick to select a region, use /as linksigns to stop."
linksigns-noPermission: "You don't have permission to enter bulk sign linking mode."
linksigns-stopped: "Exited sign linking mode."
timeleft-years: "%0% years"
timeleft-months: "%0% months"
timeleft-days: "%0% days"

View File

@ -207,4 +207,7 @@ permissions:
default: op
areashop.notifyupdate:
description: Will notify this player when an update is available
default: op
areashop.linksigns:
description: Allows you to enter sign linking mode
default: op

View File

@ -9,6 +9,14 @@ import java.util.logging.Logger;
import net.milkbowl.vault.economy.Economy;
import nl.evolutioncoding.areashop.Updater.UpdateResult;
import nl.evolutioncoding.areashop.Updater.UpdateType;
import nl.evolutioncoding.areashop.listeners.PlayerLoginListener;
import nl.evolutioncoding.areashop.listeners.SignBreakListener;
import nl.evolutioncoding.areashop.listeners.SignChangeListener;
import nl.evolutioncoding.areashop.listeners.SignClickListener;
import nl.evolutioncoding.areashop.managers.CommandManager;
import nl.evolutioncoding.areashop.managers.FileManager;
import nl.evolutioncoding.areashop.managers.LanguageManager;
import nl.evolutioncoding.areashop.managers.SignLinkerManager;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
@ -38,6 +46,7 @@ public final class AreaShop extends JavaPlugin {
private FileManager fileManager = null;
private LanguageManager languageManager = null;
private CommandManager commandManager = null;
private SignLinkerManager signLinkerManager = null;
private boolean debug = false;
private String chatprefix = null;
private Updater updater = null;
@ -152,6 +161,9 @@ public final class AreaShop extends JavaPlugin {
// Startup the CommandManager (registers itself for the command)
commandManager = new CommandManager(this);
// Create a signLinkerManager
signLinkerManager = new SignLinkerManager(this);
// Enable Metrics if config allows it
if(this.getConfig().getBoolean("sendStats")) {
@ -230,6 +242,10 @@ public final class AreaShop extends JavaPlugin {
return commandManager;
}
public SignLinkerManager getSignlinkerManager() {
return signLinkerManager;
}
/**
* Function to get the Vault plugin
* @return Economy

View File

@ -101,9 +101,9 @@ public class AddsignCommand extends CommandAreaShop {
region.addSign(block.getLocation(), block.getType(), sign.getFacing(), profile);
if(profile == null) {
plugin.message(sender, "addsign-success", region.getName());
plugin.message(sender, "addsign-success", region);
} else {
plugin.message(sender, "addsign-successProfile", region.getName(), profile);
plugin.message(sender, "addsign-successProfile", region, profile);
}
region.updateSigns();
region.saveRequired();

View File

@ -0,0 +1,83 @@
package nl.evolutioncoding.areashop.commands;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import nl.evolutioncoding.areashop.AreaShop;
import nl.evolutioncoding.areashop.Utils;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
public class LinksignsCommand extends CommandAreaShop {
public LinksignsCommand(AreaShop plugin) {
super(plugin);
}
@Override
public String getCommandStart() {
return "areashop linksigns";
}
@Override
public String getHelp(CommandSender target) {
if(target.hasPermission("areashop.linksigns")) {
return plugin.getLanguageManager().getLang("help-linksigns");
}
return null;
}
@Override
public void execute(CommandSender sender, Command command, String[] args) {
if(!sender.hasPermission("areashop.linksigns")) {
plugin.message(sender, "linksigns-noPermission");
return;
}
if (!(sender instanceof Player)) {
plugin.message(sender, "cmd-onlyByPlayer");
return;
}
Player player = (Player)sender;
if(plugin.getSignlinkerManager().isInSignLinkMode(player)) {
plugin.getSignlinkerManager().exitSignLinkMode(player);
} else {
// Get the profile
String profile = null;
if(args.length > 1) {
profile = args[1];
Set<String> profiles = plugin.getConfig().getConfigurationSection("signProfiles").getKeys(false);
if(!profiles.contains(profile)) {
plugin.message(sender, "addsign-wrongProfile", Utils.createCommaSeparatedList(profiles));
return;
}
}
plugin.getSignlinkerManager().enterSignLinkMode(player, profile);
}
}
@Override
public List<String> getTabCompleteList(int toComplete, String[] start, CommandSender sender) {
List<String> result = new ArrayList<String>();
if(toComplete == 2) {
result.addAll(plugin.getFileManager().getRegionNames());
} else if(toComplete == 3) {
result.addAll(plugin.getConfig().getStringList("signProfiles"));
}
return result;
}
}

View File

@ -1,5 +1,6 @@
package nl.evolutioncoding.areashop;
package nl.evolutioncoding.areashop.listeners;
import nl.evolutioncoding.areashop.AreaShop;
import nl.evolutioncoding.areashop.regions.RentRegion;
import org.bukkit.entity.Player;

View File

@ -1,8 +1,7 @@
package nl.evolutioncoding.areashop;
package nl.evolutioncoding.areashop.listeners;
import nl.evolutioncoding.areashop.regions.BuyRegion;
import nl.evolutioncoding.areashop.AreaShop;
import nl.evolutioncoding.areashop.regions.GeneralRegion;
import nl.evolutioncoding.areashop.regions.RentRegion;
import org.bukkit.Material;
import org.bukkit.block.Block;
@ -46,24 +45,13 @@ public final class SignBreakListener implements Listener {
if(region == null) {
return;
}
if(region.isRentRegion()) {
/* Remove the rent if the player has permission */
if(event.getPlayer().hasPermission("areashop.destroyrent")) {
plugin.getFileManager().removeRent((RentRegion)region, true);
plugin.message(event.getPlayer(), "destroy-successRent", region.getName());
} else { /* Cancel the breaking of the sign */
event.setCancelled(true);
plugin.message(event.getPlayer(), "destroy-noPermissionRent");
}
} else if(region.isBuyRegion()) {
/* Remove the buy if the player has permission */
if(event.getPlayer().hasPermission("areashop.destroybuy")) {
plugin.getFileManager().removeBuy((BuyRegion)region, true);
plugin.message(event.getPlayer(), "destroy-successBuy", region.getName());
} else { /* Cancel the breaking of the sign */
event.setCancelled(true);
plugin.message(event.getPlayer(), "destroy-noPermissionBuy");
}
/* Remove the rent if the player has permission */
if(event.getPlayer().hasPermission("areashop.delsign")) {
region.removeSign(block.getLocation());
plugin.message(event.getPlayer(), "delsign-success", region.getName());
} else { /* Cancel the breaking of the sign */
event.setCancelled(true);
plugin.message(event.getPlayer(), "delsign-noPermission");
}
}
}

View File

@ -1,7 +1,8 @@
package nl.evolutioncoding.areashop;
package nl.evolutioncoding.areashop.listeners;
import java.util.List;
import nl.evolutioncoding.areashop.AreaShop;
import nl.evolutioncoding.areashop.regions.BuyRegion;
import nl.evolutioncoding.areashop.regions.GeneralRegion;
import nl.evolutioncoding.areashop.regions.RentRegion;
@ -278,10 +279,10 @@ public final class SignChangeListener implements Listener {
Sign sign = (Sign)event.getBlock().getState().getData();
if(thirdLine == null || thirdLine.length() == 0) {
region.addSign(event.getBlock().getLocation(), event.getBlock().getType(), sign.getFacing(), null);
plugin.message(player, "addsign-success", region.getName());
plugin.message(player, "addsign-success", region);
} else {
region.addSign(event.getBlock().getLocation(), event.getBlock().getType(), sign.getFacing(), thirdLine);
plugin.message(player, "addsign-successProfile", region.getName(), thirdLine);
plugin.message(player, "addsign-successProfile", region, thirdLine);
}
region.saveRequired();

View File

@ -1,5 +1,6 @@
package nl.evolutioncoding.areashop;
package nl.evolutioncoding.areashop.listeners;
import nl.evolutioncoding.areashop.AreaShop;
import nl.evolutioncoding.areashop.regions.GeneralRegion;
import nl.evolutioncoding.areashop.regions.GeneralRegion.ClickType;
@ -31,7 +32,7 @@ public class SignClickListener implements Listener {
public void onSignClick(PlayerInteractEvent event) {
Block block = event.getClickedBlock();
/* Check for clicking a sign and rightclicking */
if( (event.getAction() == Action.RIGHT_CLICK_BLOCK || event.getAction() == Action.LEFT_CLICK_BLOCK)
if((event.getAction() == Action.RIGHT_CLICK_BLOCK || event.getAction() == Action.LEFT_CLICK_BLOCK)
&& (block.getType() == Material.SIGN_POST || block.getType() == Material.WALL_SIGN)) {
/* Check if the rent sign is really the same as a saved rent */
GeneralRegion result = plugin.getFileManager().getRegionBySignLocation(block.getLocation());
@ -40,6 +41,9 @@ public class SignClickListener implements Listener {
}
String signName = result.getSignName(block.getLocation());
Player player = event.getPlayer();
if(plugin.getSignlinkerManager().isInSignLinkMode(player)) {
return;
}
// Get the clicktype
ClickType clickType = null;
if(player.isSneaking() && event.getAction() == Action.LEFT_CLICK_BLOCK) {

View File

@ -1,10 +1,11 @@
package nl.evolutioncoding.areashop;
package nl.evolutioncoding.areashop.managers;
import java.util.ArrayList;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;
import nl.evolutioncoding.areashop.AreaShop;
import nl.evolutioncoding.areashop.commands.AddCommand;
import nl.evolutioncoding.areashop.commands.AddfriendCommand;
import nl.evolutioncoding.areashop.commands.AddsignCommand;
@ -20,6 +21,7 @@ import nl.evolutioncoding.areashop.commands.GroupinfoCommand;
import nl.evolutioncoding.areashop.commands.GrouplistCommand;
import nl.evolutioncoding.areashop.commands.HelpCommand;
import nl.evolutioncoding.areashop.commands.InfoCommand;
import nl.evolutioncoding.areashop.commands.LinksignsCommand;
import nl.evolutioncoding.areashop.commands.MeCommand;
import nl.evolutioncoding.areashop.commands.ReloadCommand;
import nl.evolutioncoding.areashop.commands.RentCommand;
@ -85,6 +87,7 @@ public class CommandManager implements CommandExecutor, TabCompleter {
commands.add(new DelCommand(plugin));
commands.add(new AddsignCommand(plugin));
commands.add(new DelsignCommand(plugin));
commands.add(new LinksignsCommand(plugin));
/* Register commands in bukkit */
plugin.getCommand("AreaShop").setExecutor(this);

View File

@ -1,4 +1,4 @@
package nl.evolutioncoding.areashop;
package nl.evolutioncoding.areashop.managers;
import java.io.File;
import java.io.FileInputStream;
@ -19,6 +19,7 @@ import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import nl.evolutioncoding.areashop.AreaShop;
import nl.evolutioncoding.areashop.exceptions.RegionCreateException;
import nl.evolutioncoding.areashop.regions.BuyRegion;
import nl.evolutioncoding.areashop.regions.GeneralRegion;

View File

@ -1,4 +1,4 @@
package nl.evolutioncoding.areashop;
package nl.evolutioncoding.areashop.managers;
import java.io.File;
import java.io.FileInputStream;
@ -12,6 +12,7 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import nl.evolutioncoding.areashop.AreaShop;
import nl.evolutioncoding.areashop.regions.GeneralRegion;
import org.bukkit.configuration.file.YamlConfiguration;

View File

@ -0,0 +1,226 @@
package nl.evolutioncoding.areashop.managers;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import nl.evolutioncoding.areashop.AreaShop;
import nl.evolutioncoding.areashop.Utils;
import nl.evolutioncoding.areashop.regions.GeneralRegion;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.material.Sign;
import org.bukkit.util.BlockIterator;
public class SignLinkerManager implements Listener {
private AreaShop plugin = null;
private Map<UUID, SignLinker> signLinkers;
private boolean eventsRegistered;
public SignLinkerManager(AreaShop plugin) {
this.plugin = plugin;
signLinkers = new HashMap<UUID, SignLinker>();
eventsRegistered = false;
}
/**
* Let a player enter sign linking mode
* @param player The player that has to enter sign linking mode
* @param profile The profile to use for the signs (null for default)
*/
public void enterSignLinkMode(Player player, String profile) {
signLinkers.put(player.getUniqueId(), new SignLinker(player, profile));
plugin.message(player, "linksigns-first");
plugin.message(player, "linksigns-next");
if(!eventsRegistered) {
eventsRegistered = true;
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
}
/**
* Let a player exit sign linking mode
* @param player The player that has to exit sign linking mode
*/
public void exitSignLinkMode(Player player) {
signLinkers.remove(player.getUniqueId());
if(eventsRegistered && signLinkers.isEmpty()) {
eventsRegistered = false;
HandlerList.unregisterAll(this);
}
plugin.message(player, "linksigns-stopped");
}
/**
* Check if the player is in sign linking mode
* @param player The player to check
* @return true if the player is in sign linking mode, otherwise false
*/
public boolean isInSignLinkMode(Player player) {
return signLinkers.containsKey(player.getUniqueId());
}
@EventHandler(priority = EventPriority.HIGH)
public void onPlayerInteract(PlayerInteractEvent event) {
AreaShop.debug("PlayerInteractEvent of " + event.getPlayer().getName() + ", " + signLinkers.size() + " signlinkers");
if(isInSignLinkMode(event.getPlayer())) {
event.setCancelled(true);
Player player = event.getPlayer();
SignLinker linker = signLinkers.get(event.getPlayer().getUniqueId());
if(event.getAction() == Action.RIGHT_CLICK_AIR || event.getAction() == Action.RIGHT_CLICK_BLOCK) {
// Get the region
BlockIterator blockIterator = new BlockIterator(player, 100);
while(blockIterator.hasNext()) {
Block next = blockIterator.next();
List<GeneralRegion> regions = plugin.getFileManager().getASRegionsByLocation(next.getLocation());
if(regions.size() == 1) {
linker.setRegion(regions.get(0));
return;
} else if(regions.size() > 1) {
Set<String> names = new HashSet<String>();
for(GeneralRegion region : regions) {
names.add(region.getName());
}
plugin.message(player, "linksigns-multipleRegions", Utils.createCommaSeparatedList(names));
plugin.message(player, "linksigns-multipleRegionsAdvice");
return;
}
}
// No regions found within the maximum range
plugin.message(player, "linksigns-noRegions");
return;
} else if(event.getAction() == Action.LEFT_CLICK_AIR || event.getAction() == Action.LEFT_CLICK_BLOCK) {
Block block = null;
BlockIterator blockIterator = new BlockIterator(player, 100);
while(blockIterator.hasNext() && block == null) {
Block next = blockIterator.next();
if(next.getType() != Material.AIR) {
block = next;
}
}
if(block == null || !(block.getType() == Material.WALL_SIGN || block.getType() == Material.SIGN_POST)) {
plugin.message(player, "linksigns-noSign");
return;
}
GeneralRegion signRegion = plugin.getFileManager().getRegionBySignLocation(block.getLocation());
if(signRegion != null) {
plugin.message(player, "linksigns-alreadyRegistered", signRegion);
return;
}
Sign sign = (Sign)block.getState().getData();
linker.setSign(block.getLocation(), block.getType(), sign.getFacing());
return;
}
}
}
/**
* Handle disconnection players
*/
@EventHandler(priority = EventPriority.MONITOR)
public void onPlayerLeave(PlayerQuitEvent event) {
AreaShop.debug("PlayerQuitEvent of " + event.getPlayer().getName() + ", " + signLinkers.size() + " signlinkers");
signLinkers.remove(event.getPlayer().getUniqueId());
}
/**
* Class to keep track of the signlinking data
*/
private class SignLinker {
private boolean hasSign = false;
private boolean hasRegion = false;
public Player linker = null;
public String profile = null;
public GeneralRegion region = null;
public Location location = null;
public Material type = null;
public BlockFace facing = null;
public SignLinker(Player linker, String profile) {
this.linker = linker;
this.profile = profile;
}
public void setRegion(GeneralRegion region) {
this.region = region;
hasRegion = true;
if(!isComplete()) {
plugin.message(linker, "linksigns-regionFound", region);
}
finalize();
}
public void setSign(Location location, Material type, BlockFace facing) {
this.location = location;
this.type = type;
this.facing = facing;
hasSign = true;
if(!isComplete()) {
plugin.message(linker, "linksigns-signFound", location.getBlockX(), location.getBlockY(), location.getBlockZ());
}
finalize();
}
public void finalize() {
if(isComplete()) {
region.addSign(location, type, facing, profile);
if(profile == null) {
plugin.message(linker, "addsign-success", region);
} else {
plugin.message(linker, "addsign-successProfile", region, profile);
}
region.updateSigns();
region.saveRequired();
reset();
plugin.message(linker, "linksigns-next");
}
}
public void reset() {
hasSign = false;
hasRegion = false;
}
public boolean isComplete() {
return hasSign && hasRegion;
}
}
}

View File

@ -14,10 +14,11 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import nl.evolutioncoding.areashop.AreaShop;
import nl.evolutioncoding.areashop.FileManager;
import nl.evolutioncoding.areashop.Utils;
import nl.evolutioncoding.areashop.exceptions.RegionCreateException;
import nl.evolutioncoding.areashop.managers.FileManager;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
@ -2090,24 +2091,34 @@ public abstract class GeneralRegion {
boolean result = false;
String error = null;
String stacktrace = null;
try {
result = plugin.getServer().dispatchCommand(sender, command);
} catch(CommandException e) {
result = false;
error = e.getMessage();
}
if(error == null) {
AreaShop.debug("Command run, executor=" + sender.getName() + ", command=" + command + ", result=" + result);
} else {
AreaShop.debug("Command run, executor=" + sender.getName() + ", command=" + command + ", result=" + result + ", error=" + error);
error = e.getMessage();
stacktrace = ExceptionUtils.getStackTrace(e);
}
boolean printed = false;
if(!result && postCommandErrors) {
printed = true;
if(error != null) {
plugin.getLogger().warning("Command execution failed, command=" + command + ", error=" + error);
plugin.getLogger().warning("Command execution failed, command=" + command + ", error=" + error + ", stacktrace:");
plugin.getLogger().warning(stacktrace);
plugin.getLogger().warning("--- End of stacktrace ---");
} else {
plugin.getLogger().warning("Command execution failed, command=" + command);
}
}
if(!printed) {
if(error == null) {
AreaShop.debug("Command run, executor=" + sender.getName() + ", command=" + command + ", result=" + result);
} else {
AreaShop.debug("Command run, executor=" + sender.getName() + ", command=" + command + ", result=" + result + ", error=" + error + ", stacktrace:");
AreaShop.debug(stacktrace);
AreaShop.debug("--- End of stacktrace ---");
}
}
}
}