Implement event system

- 'ask' type events that can be cancelled, broadcasted before the action happens
- 'notify' type events that cannot be cancelled, but only let you know that it has happened
- Events for renting (with extending flag), unrenting, buying, selling, reselling
- General 'RegionUpdateEvent' to listen to as display service (update signs, update regions flags, etc)

All messages in the GeneralRegion, RentRegion and BuyRegion classes can now use all region variables (in the future all other messages will also be worked through)

Closes #84
Closes #86
This commit is contained in:
Thijs Wiefferink 2015-12-11 20:54:12 +01:00
parent 5403472476
commit 05fd8c0156
24 changed files with 852 additions and 162 deletions

View File

@ -5,6 +5,8 @@ import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import net.milkbowl.vault.economy.Economy;
import nl.evolutioncoding.areashop.Updater.UpdateResult;
import nl.evolutioncoding.areashop.Updater.UpdateType;
import nl.evolutioncoding.areashop.features.DebugFeature;
import nl.evolutioncoding.areashop.features.Feature;
import nl.evolutioncoding.areashop.interfaces.AreaShopInterface;
import nl.evolutioncoding.areashop.interfaces.WorldEditInterface;
import nl.evolutioncoding.areashop.interfaces.WorldGuardInterface;
@ -23,6 +25,7 @@ import org.bukkit.command.CommandSender;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.event.Listener;
import org.bukkit.permissions.Permission;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.RegisteredServiceProvider;
@ -31,9 +34,7 @@ import org.bukkit.scheduler.BukkitRunnable;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.UUID;
import java.util.*;
import java.util.logging.Logger;
/**
@ -211,7 +212,8 @@ public final class AreaShop extends JavaPlugin implements AreaShopInterface {
this.getServer().getPluginManager().registerEvents(new SignBreakListener(this), this);
this.getServer().getPluginManager().registerEvents(new SignClickListener(this), this);
this.getServer().getPluginManager().registerEvents(new PlayerLoginLogoutListener(this), this);
setupFeatures();
setupTasks();
// Startup the CommandManager (registers itself for the command)
@ -284,7 +286,23 @@ public final class AreaShop extends JavaPlugin implements AreaShopInterface {
debug = false;
ready = false;
updater = null;
}
}
/**
* Instanciate and register all Feature classes
*/
public void setupFeatures() {
Set<Feature> features = new HashSet<>();
features.add(new DebugFeature(this));
// Register as listener when necessary
for(Feature feature : features) {
if(feature instanceof Listener) {
this.getServer().getPluginManager().registerEvents((Listener)feature, this);
}
}
}
/**
* Indicates if the plugin is ready to be used
@ -537,6 +555,9 @@ public final class AreaShop extends JavaPlugin implements AreaShopInterface {
* @param params The parameters to inject into the message string
*/
public void configurableMessage(Object target, String key, boolean prefix, Object... params) {
if(target == null) {
return;
}
String langString = this.fixColors(languageManager.getLang(key, params));
if(langString == null || langString.equals("")) {
// Do nothing, message is not available or disabled

View File

@ -46,7 +46,7 @@ public class SchematiceventCommand extends CommandAreaShop {
return;
}
if(region.getRegion() == null) {
plugin.message(sender, "general-noRegion", region.getName());
plugin.message(sender, "general-noRegion", region);
return;
}
RegionEvent event = null;

View File

@ -65,21 +65,7 @@ public class SellCommand extends CommandAreaShop {
plugin.message(sender, "sell-notBought");
return;
}
if(sender.hasPermission("areashop.sell")) {
plugin.message(sender, "sell-sold", buy.getPlayerName());
buy.sell(true);
} else {
if(sender.hasPermission("areashop.sellown") && sender instanceof Player) {
if(buy.getBuyer().equals(((Player)sender).getUniqueId())) {
plugin.message(sender, "sell-soldYours");
buy.sell(true);
} else {
plugin.message(sender, "sell-noPermissionOther");
}
} else {
plugin.message(sender, "sell-noPermission");
}
}
buy.sell(true, sender);
}
@Override

View File

@ -64,22 +64,8 @@ public class UnrentCommand extends CommandAreaShop {
if(!rent.isRented()) {
plugin.message(sender, "unrent-notRented");
return;
}
if(sender.hasPermission("areashop.unrent")) {
plugin.message(sender, "unrent-other", rent.getPlayerName());
rent.unRent(true);
} else {
if(sender.hasPermission("areashop.unrentown") && sender instanceof Player) {
if(rent.getRenter().equals(((Player)sender).getUniqueId())) {
plugin.message(sender, "unrent-unrented");
rent.unRent(true);
} else {
plugin.message(sender, "unrent-noPermissionOther");
}
} else {
plugin.message(sender, "unrent-noPermission");
}
}
}
rent.unRent(true, sender);
}
@Override

View File

@ -0,0 +1,53 @@
package nl.evolutioncoding.areashop.events;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
public class CancellableAreaShopEvent extends Event {
private static final HandlerList handlers = new HandlerList();
private boolean cancelled;
private String reason;
@Override
public HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
/**
* Cancel the event from happening
* @param reason The reason of cancelling, used for display to the user, should end with a dot
*/
public void cancel(String reason) {
this.cancelled = true;
this.reason = reason;
}
/**
* Let the event continue, possible overwriting a cancel() call from another plugin
*/
public void allow() {
this.cancelled = false;
this.reason = null;
}
/**
* Check if the event has been cancelled
* @return true if the event has been cancelled, otherwise false
*/
public boolean isCancelled() {
return cancelled;
}
/**
* Get the reason why this event is cancelled
* @return null if there is no reason or the event is not cancelled, otherwise a string
*/
public String getReason() {
return reason;
}
}

View File

@ -0,0 +1,18 @@
package nl.evolutioncoding.areashop.events;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
public class NotifyAreaShopEvent extends Event {
private static final HandlerList handlers = new HandlerList();
@Override
public HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
}

View File

@ -0,0 +1,40 @@
package nl.evolutioncoding.areashop.events.ask;
import nl.evolutioncoding.areashop.events.CancellableAreaShopEvent;
import nl.evolutioncoding.areashop.regions.BuyRegion;
import org.bukkit.entity.Player;
/**
* Broadcasted when a player tries to buy a region.
*/
public class BuyingRegionEvent extends CancellableAreaShopEvent {
private BuyRegion region;
private Player player;
/**
* Constructor
* @param region The region that is about to get bought
* @param player The player that tries to buy the region
*/
public BuyingRegionEvent(BuyRegion region, Player player) {
this.region = region;
this.player = player;
}
/**
* Get the region that is about to be bought
* @return the region that is about to be bought
*/
public BuyRegion getRegion() {
return region;
}
/**
* Get the player that is trying to buy the region
* @return The player that is trying to buy the region
*/
public Player getPlayer() {
return player;
}
}

View File

@ -0,0 +1,51 @@
package nl.evolutioncoding.areashop.events.ask;
import nl.evolutioncoding.areashop.events.CancellableAreaShopEvent;
import nl.evolutioncoding.areashop.regions.RentRegion;
import org.bukkit.entity.Player;
/**
* Broadcasted when a player tries to rent a region
*/
public class RentingRegionEvent extends CancellableAreaShopEvent {
private RentRegion region;
private Player player;
private boolean extending;
/**
* Constructor
* @param region The region that is about to be rented
* @param player The player that tries to rent the region
* @param extending true if the player is extending the rental of the region, otherwise false
*/
public RentingRegionEvent(RentRegion region, Player player, boolean extending) {
this.region = region;
this.player = player;
this.extending = extending;
}
/**
* Get the region that is about to be rented
* @return the region that is about to be rented
*/
public RentRegion getRegion() {
return region;
}
/**
* Get the player that is trying to rent the region
* @return The player that is trying to rent the region
*/
public Player getPlayer() {
return player;
}
/**
* Check if the player is extending the region or renting it for the first time
* @return true if the player tries to extend the region, false if he tries to rent it the first time
*/
public boolean isExtending() {
return extending;
}
}

View File

@ -0,0 +1,40 @@
package nl.evolutioncoding.areashop.events.ask;
import nl.evolutioncoding.areashop.events.CancellableAreaShopEvent;
import nl.evolutioncoding.areashop.regions.BuyRegion;
import org.bukkit.entity.Player;
/**
* Broadcasted when a player tries to resell a region
*/
public class ResellingRegionEvent extends CancellableAreaShopEvent {
private BuyRegion region;
private Player player;
/**
* Contructor
* @param region The region that the player is trying to resell
* @param player The player that is trying to buy this region from the current owner
*/
public ResellingRegionEvent(BuyRegion region, Player player) {
this.region = region;
this.player = player;
}
/**
* Get the region that is about to be bought
* @return the region that is about to be bought
*/
public BuyRegion getRegion() {
return region;
}
/**
* Get the player that is trying to buy the region
* @return The player that is trying to buy the region
*/
public Player getBuyer() {
return player;
}
}

View File

@ -0,0 +1,28 @@
package nl.evolutioncoding.areashop.events.ask;
import nl.evolutioncoding.areashop.events.CancellableAreaShopEvent;
import nl.evolutioncoding.areashop.regions.BuyRegion;
/**
* Broadcasted when a region is about to get sold
*/
public class SellingRegionEvent extends CancellableAreaShopEvent {
private BuyRegion region;
/**
* Constructor
* @param region The region that is about to get sold
*/
public SellingRegionEvent(BuyRegion region) {
this.region = region;
}
/**
* Get the region that is about to be sold
* @return the region that is about to be sold
*/
public BuyRegion getRegion() {
return region;
}
}

View File

@ -0,0 +1,28 @@
package nl.evolutioncoding.areashop.events.ask;
import nl.evolutioncoding.areashop.events.CancellableAreaShopEvent;
import nl.evolutioncoding.areashop.regions.RentRegion;
/**
* Broadcasted when a region is about to be unrented
*/
public class UnrentingRegionEvent extends CancellableAreaShopEvent {
private RentRegion region;
/**
* Constructor
* @param region The region that is about to be unrented
*/
public UnrentingRegionEvent(RentRegion region) {
this.region = region;
}
/**
* Get the region that is about to be rented
* @return the region that is about to be rented
*/
public RentRegion getRegion() {
return region;
}
}

View File

@ -0,0 +1,28 @@
package nl.evolutioncoding.areashop.events.notify;
import nl.evolutioncoding.areashop.events.NotifyAreaShopEvent;
import nl.evolutioncoding.areashop.regions.BuyRegion;
/**
* Broadcasted when a region has been bought
*/
public class BoughtRegionEvent extends NotifyAreaShopEvent {
private BuyRegion region;
/**
* Constructor
* @param region The region that has been bought
*/
public BoughtRegionEvent(BuyRegion region) {
this.region = region;
}
/**
* Get the region that has been bought
* @return the region that has been bought
*/
public BuyRegion getRegion() {
return region;
}
}

View File

@ -0,0 +1,29 @@
package nl.evolutioncoding.areashop.events.notify;
import nl.evolutioncoding.areashop.events.NotifyAreaShopEvent;
import nl.evolutioncoding.areashop.regions.GeneralRegion;
/**
* Broadcasted when the data of a region changes.
* Should be used for updating displays that use region data.
*/
public class RegionUpdateEvent extends NotifyAreaShopEvent {
private GeneralRegion region;
/**
* Contructor
* @param region The region that has been updated
*/
public RegionUpdateEvent(GeneralRegion region) {
this.region = region;
}
/**
* The region that has been updated
* @return The GeneralRegion that has been updated
*/
public GeneralRegion getRegion() {
return region;
}
}

View File

@ -0,0 +1,39 @@
package nl.evolutioncoding.areashop.events.notify;
import nl.evolutioncoding.areashop.events.NotifyAreaShopEvent;
import nl.evolutioncoding.areashop.regions.RentRegion;
/**
* Broadcasted when a region has been rented
*/
public class RentedRegionEvent extends NotifyAreaShopEvent {
private RentRegion region;
private boolean extended;
/**
* Constructor
* @param region The region that has been rented
* @param extended true if the region has been extended, false if this is the first time buying the region
*/
public RentedRegionEvent(RentRegion region, boolean extended) {
this.region = region;
this.extended = extended;
}
/**
* Get the region that has been rented
* @return the region that has been rented
*/
public RentRegion getRegion() {
return region;
}
/**
* Check if the region was extended or rented for the first time
* @return true if the region was extended, false when rented for the first time
*/
public boolean hasExtended() {
return extended;
}
}

View File

@ -0,0 +1,41 @@
package nl.evolutioncoding.areashop.events.notify;
import nl.evolutioncoding.areashop.events.NotifyAreaShopEvent;
import nl.evolutioncoding.areashop.regions.BuyRegion;
import java.util.UUID;
/**
* Broadcasted when a region has been resold
*/
public class ResoldRegionEvent extends NotifyAreaShopEvent {
private BuyRegion region;
private UUID from;
/**
* Constructor
* @param region The region that has been resold
* @param from The player from who the region has been resold to the current owner
*/
public ResoldRegionEvent(BuyRegion region, UUID from) {
this.region = region;
this.from = from;
}
/**
* Get the region that has been bought
* @return the region that has been bought
*/
public BuyRegion getRegion() {
return region;
}
/**
* Get the player that the region has been bought from
* @return The UUID of the player that the region has been bought from
*/
public UUID getFromPlayer() {
return from;
}
}

View File

@ -0,0 +1,33 @@
package nl.evolutioncoding.areashop.events.notify;
import nl.evolutioncoding.areashop.events.NotifyAreaShopEvent;
import nl.evolutioncoding.areashop.regions.BuyRegion;
import java.util.UUID;
public class SoldRegionEvent extends NotifyAreaShopEvent {
private BuyRegion region;
private UUID oldBuyer;
public SoldRegionEvent(BuyRegion region, UUID oldBuyer) {
this.region = region;
this.oldBuyer = oldBuyer;
}
/**
* Get the region that has been sold
* @return the region that has been sold
*/
public BuyRegion getRegion() {
return region;
}
/**
* Get the player that the region is sold for
* @return The UUID of the player that the region is sold for
*/
public UUID getOldBuyer() {
return oldBuyer;
}
}

View File

@ -0,0 +1,41 @@
package nl.evolutioncoding.areashop.events.notify;
import nl.evolutioncoding.areashop.events.NotifyAreaShopEvent;
import nl.evolutioncoding.areashop.regions.RentRegion;
import java.util.UUID;
/**
* Broadcasted when a region has been unrented
*/
public class UnrentedRegionEvent extends NotifyAreaShopEvent {
private RentRegion region;
private UUID oldRenter;
/**
* Constructor
* @param region The region that has been unrented
* @param oldRenter The player that rented the region before it was unrented
*/
public UnrentedRegionEvent(RentRegion region, UUID oldRenter) {
this.region = region;
this.oldRenter = oldRenter;
}
/**
* Get the region that has been unrented
* @return the region that has been unrented
*/
public RentRegion getRegion() {
return region;
}
/**
* Get the player that the region was unrented for
* @return The UUID of the player that the region was unrented for
*/
public UUID getOldRenter() {
return oldRenter;
}
}

View File

@ -0,0 +1,69 @@
package nl.evolutioncoding.areashop.features;
import nl.evolutioncoding.areashop.AreaShop;
import nl.evolutioncoding.areashop.events.ask.*;
import nl.evolutioncoding.areashop.events.notify.*;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
public class DebugFeature extends Feature implements Listener {
public DebugFeature(AreaShop plugin) {
super(plugin);
}
@EventHandler
public void buyingRegion(BuyingRegionEvent event) {
AreaShop.debug(event.getPlayer().getName() + " is trying to buy " + event.getRegion().getName());
}
@EventHandler
public void boughtRegion(BoughtRegionEvent event) {
AreaShop.debug(event.getRegion().getPlayerName() + " bought " + event.getRegion().getName());
}
@EventHandler
public void sellingRegion(SellingRegionEvent event) {
AreaShop.debug(event.getRegion().getName() + " is trying to sell " + event.getRegion().getName());
}
@EventHandler
public void soldRegion(SoldRegionEvent event) {
AreaShop.debug(event.getRegion().getName() + " sold " + event.getRegion().getName());
}
@EventHandler
public void resellingRegion(ResellingRegionEvent event) {
AreaShop.debug(event.getRegion().getName() + " is trying to resell " + event.getRegion().getName());
}
@EventHandler
public void resoldRegion(ResoldRegionEvent event) {
AreaShop.debug(event.getRegion().getName() + " resold " + event.getRegion().getName());
}
@EventHandler
public void rentingRegion(RentingRegionEvent event) {
AreaShop.debug(event.getPlayer().getName() + " is trying to rent " + event.getRegion().getName() + ", extending=" + event.isExtending());
}
@EventHandler
public void rentedRegion(RentedRegionEvent event) {
AreaShop.debug(event.getRegion().getPlayerName() + " rented " + event.getRegion().getName() + ", extending=" + event.hasExtended());
}
@EventHandler
public void unrentingRegion(UnrentingRegionEvent event) {
AreaShop.debug(event.getRegion().getPlayerName() + " is trying to unrent " + event.getRegion().getName());
}
@EventHandler
public void unrentedRegion(UnrentedRegionEvent event) {
AreaShop.debug(event.getRegion().getPlayerName() + " unrented " + event.getRegion().getName());
}
@EventHandler
public void regionUpdate(RegionUpdateEvent event) {
AreaShop.debug(event.getRegion().getName() + " updated");
}
}

View File

@ -0,0 +1,12 @@
package nl.evolutioncoding.areashop.features;
import nl.evolutioncoding.areashop.AreaShop;
public class Feature {
AreaShop plugin;
public Feature(AreaShop plugin) {
this.plugin = plugin;
}
}

View File

@ -296,7 +296,7 @@ public class FileManager {
if(rent != null) {
rent.setDeleted();
if(rent.isRented()) {
rent.unRent(giveMoneyBack);
rent.unRent(giveMoneyBack, null);
}
// Handle schematics and run commands
rent.handleSchematicEvent(RegionEvent.DELETED);
@ -359,7 +359,7 @@ public class FileManager {
if(buy != null) {
buy.setDeleted();
if(buy.isSold()) {
buy.sell(giveMoneyBack);
buy.sell(giveMoneyBack, null);
}
// Handle schematics and run commands
buy.handleSchematicEvent(RegionEvent.DELETED);

View File

@ -2,9 +2,16 @@ package nl.evolutioncoding.areashop.regions;
import net.milkbowl.vault.economy.EconomyResponse;
import nl.evolutioncoding.areashop.AreaShop;
import nl.evolutioncoding.areashop.events.ask.BuyingRegionEvent;
import nl.evolutioncoding.areashop.events.ask.ResellingRegionEvent;
import nl.evolutioncoding.areashop.events.ask.SellingRegionEvent;
import nl.evolutioncoding.areashop.events.notify.BoughtRegionEvent;
import nl.evolutioncoding.areashop.events.notify.ResoldRegionEvent;
import nl.evolutioncoding.areashop.events.notify.SoldRegionEvent;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
@ -248,26 +255,26 @@ public class BuyRegion extends GeneralRegion {
// Check if the player has permission
if(player.hasPermission("areashop.buy")) {
if(plugin.getEconomy() == null) {
plugin.message(player, "general-noEconomy");
message(player, "general-noEconomy");
return false;
}
if(isInResellingMode()) {
if(!player.hasPermission("areashop.buyresell")) {
plugin.message(player, "buy-noPermissionResell");
message(player, "buy-noPermissionResell");
return false;
}
} else {
if(!player.hasPermission("areashop.buynormal")) {
plugin.message(player, "buy-noPermissionNoResell");
message(player, "buy-noPermissionNoResell");
return false;
}
}
if(getWorld() == null) {
plugin.message(player, "general-noWorld", getWorldName());
message(player, "general-noWorld");
return false;
}
if(getRegion() == null) {
plugin.message(player, "general-noRegion", getName());
message(player, "general-noRegion");
return false;
}
if(!isSold() || (isInResellingMode() && !isBuyer(player))) {
@ -275,11 +282,11 @@ public class BuyRegion extends GeneralRegion {
// Check if the players needs to be in the world or region for buying
if(restrictedToRegion() && (!player.getWorld().getName().equals(getWorldName())
|| !getRegion().contains(player.getLocation().getBlockX(), player.getLocation().getBlockY(), player.getLocation().getBlockZ()))) {
plugin.message(player, "buy-restrictedToRegion", getName());
message(player, "buy-restrictedToRegion");
return false;
}
if(restrictedToWorld() && !player.getWorld().getName().equals(getWorldName())) {
plugin.message(player, "buy-restrictedToWorld", getWorldName(), player.getWorld().getName());
message(player, "buy-restrictedToWorld", player.getWorld().getName());
return false;
}
// Check region limits
@ -287,11 +294,11 @@ public class BuyRegion extends GeneralRegion {
AreaShop.debug("LimitResult: " + limitResult.toString());
if(!limitResult.actionAllowed()) {
if(limitResult.getLimitingFactor() == LimitType.TOTAL) {
plugin.message(player, "total-maximum", limitResult.getMaximum(), limitResult.getCurrent(), limitResult.getLimitingGroup());
message(player, "total-maximum", limitResult.getMaximum(), limitResult.getCurrent(), limitResult.getLimitingGroup());
return false;
}
if(limitResult.getLimitingFactor() == LimitType.BUYS) {
plugin.message(player, "buy-maximum", limitResult.getMaximum(), limitResult.getCurrent(), limitResult.getLimitingGroup());
message(player, "buy-maximum", limitResult.getMaximum(), limitResult.getCurrent(), limitResult.getLimitingGroup());
return false;
}
// Should not be reached, but is safe like this
@ -302,12 +309,21 @@ public class BuyRegion extends GeneralRegion {
if((!isResell && plugin.getEconomy().has(player, getWorldName(), getPrice())) || (isResell && plugin.getEconomy().has(player, getWorldName(), getResellPrice()))) {
UUID oldOwner = getBuyer();
if(isResell && oldOwner != null) {
// Broadcast and check event
ResellingRegionEvent event = new ResellingRegionEvent(this, player);
Bukkit.getPluginManager().callEvent(event);
if(event.isCancelled()) {
message(player, "general-cancelled", event.getReason());
return false;
}
clearFriends();
double resellPrice = getResellPrice();
// Transfer the money to the previous owner
EconomyResponse r = plugin.getEconomy().withdrawPlayer(player, getWorldName(), getResellPrice());
if(!r.transactionSuccess()) {
plugin.message(player, "buy-payError");
message(player, "buy-payError");
AreaShop.debug("Something went wrong with getting money from " + player.getName() + " while buying " + getName() + ": " + r.errorMessage);
return false;
}
r = null;
@ -329,26 +345,35 @@ public class BuyRegion extends GeneralRegion {
// Set the owner
setBuyer(player.getUniqueId());
updateLastActiveTime();
// Update everything
handleSchematicEvent(RegionEvent.RESELL);
updateSigns();
updateRegionFlags();
// Send message to the player
plugin.message(player, "buy-successResale", getName(), oldOwnerName);
message(player, "buy-successResale", oldOwnerName);
Player seller = Bukkit.getPlayer(oldOwner);
if(seller != null) {
plugin.message(player, "buy-successSeller", getName(), getPlayerName(), resellPrice);
message(player, "buy-successSeller", resellPrice);
}
AreaShop.debug(player.getName() + " has bought region " + getName() + " for " + getFormattedPrice() + " from " + oldOwnerName);
// Notify about updates
this.notifyAndUpdate(new ResoldRegionEvent(this, oldOwner));
// Run commands
this.runEventCommands(RegionEvent.RESELL, false);
} else {
// Broadcast and check event
BuyingRegionEvent event = new BuyingRegionEvent(this, player);
Bukkit.getPluginManager().callEvent(event);
if(event.isCancelled()) {
message(player, "general-cancelled", event.getReason());
return false;
}
// Substract the money from the players balance
EconomyResponse r = plugin.getEconomy().withdrawPlayer(player, getWorldName(), getPrice());
if(!r.transactionSuccess()) {
plugin.message(player, "buy-payError");
message(player, "buy-payError");
return false;
}
// Optionally give money to the landlord
@ -367,44 +392,44 @@ public class BuyRegion extends GeneralRegion {
plugin.getLogger().warning("Something went wrong with paying '" + landlordName + "' " + getFormattedPrice() + " for his sell of region " + getName() + " to " + player.getName());
}
}
AreaShop.debug(player.getName() + " has bought region " + getName() + " for " + getFormattedPrice());
// Run commands
this.runEventCommands(RegionEvent.BOUGHT, true);
// Set the owner
setBuyer(player.getUniqueId());
updateLastActiveTime();
// Notify about updates
this.notifyAndUpdate(new BoughtRegionEvent(this));
// Update everything
handleSchematicEvent(RegionEvent.BOUGHT);
updateSigns();
updateRegionFlags();
// Send message to the player
plugin.message(player, "buy-succes", getName());
message(player, "buy-succes");
// Run commands
this.runEventCommands(RegionEvent.BOUGHT, false);
}
return true;
} else {
// Player has not enough money
String requiredMoney;
if(isResell) {
requiredMoney = getFormattedResellPrice();
message(player, "buy-lowMoneyResell", plugin.formatCurrency(plugin.getEconomy().getBalance(player, getWorldName())));
} else {
requiredMoney = getFormattedPrice();
}
plugin.message(player, "buy-lowMoney", plugin.formatCurrency(plugin.getEconomy().getBalance(player, getWorldName())), requiredMoney);
message(player, "buy-lowMoney", plugin.formatCurrency(plugin.getEconomy().getBalance(player, getWorldName())));
}
}
} else {
if(isBuyer(player)) {
plugin.message(player, "buy-yours");
message(player, "buy-yours");
} else {
plugin.message(player, "buy-someoneElse");
message(player, "buy-someoneElse");
}
}
} else {
plugin.message(player, "buy-noPermission");
message(player, "buy-noPermission");
}
return false;
}
@ -412,12 +437,34 @@ public class BuyRegion extends GeneralRegion {
/**
* Sell a buyed region, get part of the money back
* @param giveMoneyBack true if the player should be given money back, otherwise false
* @param executor CommandSender to receive a message when the sell fails, or null
*/
@SuppressWarnings("deprecation")
public void sell(boolean giveMoneyBack) {
if(plugin.getEconomy() == null) {
return;
public boolean sell(boolean giveMoneyBack, CommandSender executor) {
boolean own = executor != null && executor instanceof Player && this.isBuyer((Player)executor);
if(executor != null) {
if(!executor.hasPermission("areashop.sell") && !own) {
message(executor, "sell-noPermissionOther");
return false;
}
if(!executor.hasPermission("areashop.sell") && !executor.hasPermission("areashop.sellown") && own) {
message(executor, "sell-noPermission");
return false;
}
}
if(plugin.getEconomy() == null) {
return false;
}
// Broadcast and check event
SellingRegionEvent event = new SellingRegionEvent(this);
Bukkit.getPluginManager().callEvent(event);
if(event.isCancelled()) {
message(executor, "general-cancelled", event.getReason());
return false;
}
// Run commands
this.runEventCommands(RegionEvent.SOLD, true);
@ -462,22 +509,30 @@ public class BuyRegion extends GeneralRegion {
}
}
}
AreaShop.debug(getPlayerName() + " has sold " + getName() + ", got " + plugin.formatCurrency(moneyBack) + " money back");
if(own) {
plugin.message(executor, "sell-soldYours");
} else {
plugin.message(executor, "sell-sold");
}
// Remove friends and the owner
clearFriends();
UUID oldBuyer = getBuyer();
setBuyer(null);
removeLastActiveTime();
// Notify about updates
this.notifyAndUpdate(new SoldRegionEvent(this, oldBuyer));
// Update everything
handleSchematicEvent(RegionEvent.SOLD);
AreaShop.debug("friends before sell: " + getFriendNames().toString());
// Remove friends and the owner
clearFriends();
setBuyer(null);
removeLastActiveTime();
updateRegionFlags(RegionState.FORSALE);
updateSigns();
// Run commands
this.runEventCommands(RegionEvent.SOLD, false);
return true;
}
@Override
@ -491,12 +546,11 @@ public class BuyRegion extends GeneralRegion {
return false;
}
long lastPlayed = getLastActiveTime();
AreaShop.debug("currentTime=" + Calendar.getInstance().getTimeInMillis() + ", getLastPlayed()=" + lastPlayed + ", timeInactive=" + (Calendar.getInstance().getTimeInMillis()-player.getLastPlayed()) + ", inactiveSetting=" + inactiveSetting);
//AreaShop.debug("currentTime=" + Calendar.getInstance().getTimeInMillis() + ", getLastPlayed()=" + lastPlayed + ", timeInactive=" + (Calendar.getInstance().getTimeInMillis()-player.getLastPlayed()) + ", inactiveSetting=" + inactiveSetting);
if(Calendar.getInstance().getTimeInMillis() > (lastPlayed + inactiveSetting)) {
plugin.getLogger().info("Region " + getName() + " unrented because of inactivity for player " + getPlayerName());
AreaShop.debug("currentTime=" + Calendar.getInstance().getTimeInMillis() + ", getLastPlayed()=" + lastPlayed + ", timeInactive=" + (Calendar.getInstance().getTimeInMillis()-player.getLastPlayed()) + ", inactiveSetting=" + inactiveSetting);
this.sell(true);
return true;
return this.sell(true, null);
}
return false;
}

View File

@ -10,6 +10,8 @@ import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import com.sk89q.worldguard.protection.regions.ProtectedRegion.CircularInheritanceException;
import nl.evolutioncoding.areashop.AreaShop;
import nl.evolutioncoding.areashop.Utils;
import nl.evolutioncoding.areashop.events.NotifyAreaShopEvent;
import nl.evolutioncoding.areashop.events.notify.RegionUpdateEvent;
import nl.evolutioncoding.areashop.interfaces.GeneralRegionInterface;
import nl.evolutioncoding.areashop.managers.FileManager;
import org.apache.commons.lang.exception.ExceptionUtils;
@ -173,7 +175,25 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
public boolean equals(Object region) {
return region instanceof GeneralRegion && ((GeneralRegion)region).getName().equals(getName());
}
/**
* Broadcast an event to indicate that region settings have been changed.
* This will update region flags, signs, etc.
*/
public void update() {
Bukkit.getServer().getPluginManager().callEvent(new RegionUpdateEvent(this));
}
/**
* Broadcast the given event and update the region status
* @param event The update event that should be broadcasted
*/
public void notifyAndUpdate(NotifyAreaShopEvent event) {
Bukkit.getPluginManager().callEvent(event);
update();
}
/**
* Update the region flags according the region data
*/
@ -780,6 +800,29 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
}
return false;
}
/**
* Method to send a message to a CommandSender, using chatprefix if it is a player
* Automatically includes the region in the message, enabling the use of all variables
* @param target The CommandSender you wan't to send the message to (e.g. a player)
* @param key The key to get the translation
* @param prefix Specify if the message should have a prefix
* @param params The parameters to inject into the message string
*/
public void configurableMessage(Object target, String key, boolean prefix, Object... params) {
Object[] newParams = new Object[params.length + 1];
newParams[0] = this;
System.arraycopy(params, 0, newParams, 1, params.length);
plugin.configurableMessage(target, key, prefix, newParams);
}
public void messageNoPrefix(Object target, String key, Object... params) {
configurableMessage(target, key, false, params);
}
public void message(Object target, String key, Object... params) {
configurableMessage(target, key, true, params);
}
/**
* Check if a sign needs periodic updating
@ -1251,11 +1294,11 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
Location startLocation = null;
ProtectedRegion region = getRegion();
if(getWorld() == null) {
plugin.message(player, "general-noWorld", getWorldName());
message(player, "general-noWorld");
return false;
}
if(getRegion() == null) {
plugin.message(player, "general-noRegion", getName());
message(player, "general-noRegion");
return false;
}
if(isRentRegion()) {
@ -1269,27 +1312,27 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
if( (!toSign && owner && !player.hasPermission("areashop.teleport") && player.hasPermission("areashop.teleportsign")
|| !toSign && !owner && !friend && !player.hasPermission("areashop.teleportall") && player.hasPermission("areashop.teleportsignall")
|| !toSign && !owner && friend && !player.hasPermission("areashop.teleportfriend") && player.hasPermission("areashop.teleportfriendsign"))) {
plugin.message(player, "teleport-changedToSign");
message(player, "teleport-changedToSign");
toSign = true;
}
// Check permissions
if(owner && !player.hasPermission("areashop.teleport") && !toSign) {
plugin.message(player, "teleport-noPermission");
message(player, "teleport-noPermission");
return false;
} else if(!owner && !player.hasPermission("areashop.teleportall") && !toSign && !friend) {
plugin.message(player, "teleport-noPermissionOther");
message(player, "teleport-noPermissionOther");
return false;
} else if(!owner && !player.hasPermission("areashop.teleportfriend") && !toSign && friend) {
plugin.message(player, "teleport-noPermissionFriend");
message(player, "teleport-noPermissionFriend");
return false;
} else if(owner && !player.hasPermission("areashop.teleportsign") && toSign) {
plugin.message(player, "teleport-noPermissionSign");
message(player, "teleport-noPermissionSign");
return false;
} else if(!owner && !player.hasPermission("areashop.teleportsignall") && toSign && !friend) {
plugin.message(player, "teleport-noPermissionOtherSign");
message(player, "teleport-noPermissionOtherSign");
return false;
} else if(!owner && !player.hasPermission("areashop.teleportfriendsign") && toSign && friend) {
plugin.message(player, "teleport-noPermissionFriendSign");
message(player, "teleport-noPermissionFriendSign");
return false;
}
}
@ -1304,7 +1347,7 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
startLocation.setYaw(player.getLocation().getYaw());
} else {
// No sign available
plugin.message(player, "teleport-changedToNoSign");
message(player, "teleport-changedToNoSign");
toSign = false;
}
}
@ -1347,7 +1390,7 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
int radius = 1;
boolean blocksInRegion = region.contains(startLocation.getBlockX(), startLocation.getBlockY(), startLocation.getBlockZ());
if(!blocksInRegion && insideRegion) {
plugin.message(player, "teleport-blocked", getName());
message(player, "teleport-blocked");
return false;
}
boolean done = isSafe(safeLocation) && ((blocksInRegion && insideRegion) || (!insideRegion));
@ -1550,15 +1593,15 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
}
if(done && isSafe(safeLocation)) {
if(toSign) {
plugin.message(player, "teleport-successSign", getName());
message(player, "teleport-successSign");
} else {
plugin.message(player, "teleport-success", getName());
message(player, "teleport-success");
}
player.teleport(safeLocation);
AreaShop.debug("Found location: " + safeLocation.toString() + " Tries: " + (checked-1));
return true;
} else {
plugin.message(player, "teleport-noSafe", getName(), checked-1, maxTries);
message(player, "teleport-noSafe", checked-1, maxTries);
AreaShop.debug("No location found, checked " + (checked-1) + " spots of max " + maxTries);
return false;
}

View File

@ -2,9 +2,14 @@ package nl.evolutioncoding.areashop.regions;
import net.milkbowl.vault.economy.EconomyResponse;
import nl.evolutioncoding.areashop.AreaShop;
import nl.evolutioncoding.areashop.events.ask.RentingRegionEvent;
import nl.evolutioncoding.areashop.events.ask.UnrentingRegionEvent;
import nl.evolutioncoding.areashop.events.notify.RentedRegionEvent;
import nl.evolutioncoding.areashop.events.notify.UnrentedRegionEvent;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
@ -333,11 +338,12 @@ public class RentRegion extends GeneralRegion {
if(!isDeleted() && isRented() && now > getRentedUntil()) {
// Send message to the player if online
Player player = Bukkit.getPlayer(getRenter());
if(player != null) {
plugin.message(player, "unrent-expired", getName());
if(unRent(false, player)) {
if(player != null) {
message(player, "unrent-expired");
}
return true;
}
unRent(false);
return true;
}
return false;
}
@ -369,7 +375,7 @@ public class RentRegion extends GeneralRegion {
if(checkTime > warningsDoneUntil && checkTime <= sendUntil) {
if(plugin.getConfig().getBoolean(configPath + "." + timeBefore + ".warnPlayer")) {
plugin.message(player, "rent-expireWarning", this);
message(player, "rent-expireWarning");
}
this.runCommands(Bukkit.getConsoleSender(), plugin.getConfig().getStringList(configPath + "." + timeBefore + ".commands"));
}
@ -386,17 +392,17 @@ public class RentRegion extends GeneralRegion {
@SuppressWarnings("deprecation")
public boolean rent(Player player) {
if(plugin.getEconomy() == null) {
plugin.message(player, "general-noEconomy");
message(player, "general-noEconomy");
return false;
}
//Check if the player has permission
if(player.hasPermission("areashop.rent")) {
if(getWorld() == null) {
plugin.message(player, "general-noWorld", getWorldName());
message(player, "general-noWorld");
return false;
}
if(getRegion() == null) {
plugin.message(player, "general-noRegion", getName());
message(player, "general-noRegion");
return false;
}
boolean extend = false;
@ -408,11 +414,11 @@ public class RentRegion extends GeneralRegion {
// Check if the players needs to be in the world or region for buying
if(restrictedToRegion() && (!player.getWorld().getName().equals(getWorldName())
|| !getRegion().contains(player.getLocation().getBlockX(), player.getLocation().getBlockY(), player.getLocation().getBlockZ()))) {
plugin.message(player, "rent-restrictedToRegion", getName());
message(player, "rent-restrictedToRegion");
return false;
}
if(restrictedToWorld() && !player.getWorld().getName().equals(getWorldName())) {
plugin.message(player, "rent-restrictedToWorld", getWorldName(), player.getWorld().getName());
message(player, "rent-restrictedToWorld", player.getWorld().getName());
return false;
}
// Check region limits if this is not extending
@ -427,15 +433,15 @@ public class RentRegion extends GeneralRegion {
AreaShop.debug("LimitResult: " + limitResult.toString());
if(!limitResult.actionAllowed()) {
if(limitResult.getLimitingFactor() == LimitType.TOTAL) {
plugin.message(player, "total-maximum", limitResult.getMaximum(), limitResult.getCurrent(), limitResult.getLimitingGroup());
message(player, "total-maximum", limitResult.getMaximum(), limitResult.getCurrent(), limitResult.getLimitingGroup());
return false;
}
if(limitResult.getLimitingFactor() == LimitType.RENTS) {
plugin.message(player, "rent-maximum", limitResult.getMaximum(), limitResult.getCurrent(), limitResult.getLimitingGroup());
message(player, "rent-maximum", limitResult.getMaximum(), limitResult.getCurrent(), limitResult.getLimitingGroup());
return false;
}
if(limitResult.getLimitingFactor() == LimitType.EXTEND) {
plugin.message(player, "rent-maximumExtend", limitResult.getMaximum(), limitResult.getCurrent()+1, limitResult.getLimitingGroup());
message(player, "rent-maximumExtend", limitResult.getMaximum(), limitResult.getCurrent() + 1, limitResult.getLimitingGroup());
return false;
}
return false;
@ -445,7 +451,7 @@ public class RentRegion extends GeneralRegion {
// Check if the player can still extend this rent
if(extend && !player.hasPermission("areashop.rentextendbypass")) {
if(getMaxExtends() >= 0 && getTimesExtended() >= getMaxExtends()) {
plugin.message(player, "rent-maxExtends", getMaxExtends());
message(player, "rent-maxExtends");
return false;
}
}
@ -464,24 +470,35 @@ public class RentRegion extends GeneralRegion {
&& maxRentTime != -1) {
// Extend to the maximum instead of adding a full period
if(getBooleanSetting("rent.extendToFullWhenAboveMaxRentTime")) {
if(timeRented >= timeNow) {
plugin.message(player, "rent-alreadyAtFull", this);
if(timeRented >= maxRentTime) {
message(player, "rent-alreadyAtFull");
return false;
} else {
extendToMax = true;
long toRentPart = maxRentTime - timeRented;
extendToMax = true;
price = ((double)toRentPart)/getDuration()*price;
}
} else {
plugin.message(player, "rent-maxRentTime", this.millisToHumanFormat(maxRentTime), this.millisToHumanFormat(timeRented));
message(player, "rent-maxRentTime");
return false;
}
}
if(plugin.getEconomy().has(player, getWorldName(), price)) {
// Broadcast and check event
RentingRegionEvent event = new RentingRegionEvent(this, player, extend);
Bukkit.getPluginManager().callEvent(event);
if(event.isCancelled()) {
message(player, "general-cancelled", event.getReason());
return false;
}
// Substract the money from the players balance
EconomyResponse r = plugin.getEconomy().withdrawPlayer(player, getWorldName(), price);
AreaShop.debug("price: " + price);
if(!r.transactionSuccess()) {
plugin.message(player, "rent-payError");
message(player, "rent-payError");
AreaShop.debug("Something went wrong with getting money from " + player.getName() + " while renting " + getName() + ": " + r.errorMessage);
return false;
}
// Optionally give money to the landlord
@ -519,13 +536,15 @@ public class RentRegion extends GeneralRegion {
calendar.setTimeInMillis(calendar.getTimeInMillis() + getDuration());
}
SimpleDateFormat dateFull = new SimpleDateFormat(plugin.getConfig().getString("timeFormatChat"));
AreaShop.debug(player.getName() + " has rented region " + getName() + " for " + getFormattedPrice() + " until " + dateFull.format(calendar.getTime()));
// Add values to the rent and send it to FileManager
setRentedUntil(calendar.getTimeInMillis());
setRenter(player.getUniqueId());
updateLastActiveTime();
// Notify about updates
this.notifyAndUpdate(new RentedRegionEvent(this, extend));
// Fire schematic event and updated times extended
if(!extend) {
this.handleSchematicEvent(RegionEvent.RENTED);
@ -533,19 +552,18 @@ public class RentRegion extends GeneralRegion {
} else {
setTimesExtended(getTimesExtended() + 1);
}
// Change the sign and the region flags
updateSigns();
updateRegionFlags(RegionState.RENTED);
// Send message to the player
if(extendToMax) {
plugin.message(player, "rent-extendedToMax", this);
message(player, "rent-extendedToMax");
} else if(extend) {
plugin.message(player, "rent-extended", getName(), dateFull.format(calendar.getTime()));
message(player, "rent-extended");
} else {
plugin.message(player, "rent-rented", getName(), dateFull.format(calendar.getTime()));
plugin.message(player, "rent-extend");
message(player, "rent-rented");
message(player, "rent-extend");
}
if(!extend) {
// Run commands
@ -558,16 +576,16 @@ public class RentRegion extends GeneralRegion {
} else {
// Player has not enough money
if(extend) {
plugin.message(player, "rent-lowMoneyExtend", plugin.formatCurrency(plugin.getEconomy().getBalance(player, getWorldName())), getFormattedPrice());
message(player, "rent-lowMoneyExtend", plugin.formatCurrency(plugin.getEconomy().getBalance(player, getWorldName())));
} else {
plugin.message(player, "rent-lowMoneyRent", plugin.formatCurrency(plugin.getEconomy().getBalance(player, getWorldName())), getFormattedPrice());
message(player, "rent-lowMoneyRent", plugin.formatCurrency(plugin.getEconomy().getBalance(player, getWorldName())));
}
}
} else {
plugin.message(player, "rent-someoneElse");
message(player, "rent-someoneElse");
}
} else {
plugin.message(player, "rent-noPermission");
message(player, "rent-noPermission");
}
return false;
}
@ -575,12 +593,34 @@ public class RentRegion extends GeneralRegion {
/**
* Unrent a region, reset to unrented
* @param giveMoneyBack true if money should be given back to the player, false otherwise
* @param executor The CommandSender that should get the cancelled message if there is any, or null
*/
@SuppressWarnings("deprecation")
public void unRent(boolean giveMoneyBack) {
if(plugin.getEconomy() == null) {
return;
public boolean unRent(boolean giveMoneyBack, CommandSender executor) {
boolean own = executor != null && executor instanceof Player && this.isRenter((Player)executor);
if(executor != null) {
if(!executor.hasPermission("areashop.unrent") && !own) {
message(executor, "unrent-noPermissionOther");
return false;
}
if(!executor.hasPermission("areashop.unrent") && !executor.hasPermission("areashop.unrentown") && own) {
message(executor, "unrent-noPermission");
return false;
}
}
if(plugin.getEconomy() == null) {
return false;
}
// Broadcast and check event
UnrentingRegionEvent event = new UnrentingRegionEvent(this);
Bukkit.getPluginManager().callEvent(event);
if(event.isCancelled()) {
message(executor, "general-cancelled", event.getReason());
return false;
}
// Run commands
this.runEventCommands(RegionEvent.UNRENTED, true);
double moneyBack = getMoneyBackAmount();
@ -622,24 +662,33 @@ public class RentRegion extends GeneralRegion {
}
}
}
// Debug message
AreaShop.debug(getPlayerName() + " has unrented " + getName() + ", got " + plugin.formatCurrency(moneyBack) + " money back");
// Update the signs and region flags
handleSchematicEvent(RegionEvent.UNRENTED);
// Send messages
if(!own) {
message(executor, "unrent-other");
} else {
message(executor, "unrent-unrented");
}
// Remove friends, the owner and renteduntil values
clearFriends();
UUID oldRenter = getRenter();
setRenter(null);
setRentedUntil(null);
setTimesExtended(-1);
removeLastActiveTime();
// Notify about updates
this.notifyAndUpdate(new UnrentedRegionEvent(this, oldRenter));
updateRegionFlags(RegionState.FORRENT);
updateSigns();
// Run commands
this.runEventCommands(RegionEvent.UNRENTED, false);
return true;
}
@Override
@ -653,12 +702,11 @@ public class RentRegion extends GeneralRegion {
return false;
}
long lastPlayed = getLastActiveTime();
AreaShop.debug("currentTime=" + Calendar.getInstance().getTimeInMillis() + ", getLastPlayed()=" + lastPlayed + ", timeInactive=" + (Calendar.getInstance().getTimeInMillis()-player.getLastPlayed()) + ", inactiveSetting=" + inactiveSetting);
//AreaShop.debug("currentTime=" + Calendar.getInstance().getTimeInMillis() + ", getLastPlayed()=" + lastPlayed + ", timeInactive=" + (Calendar.getInstance().getTimeInMillis()-player.getLastPlayed()) + ", inactiveSetting=" + inactiveSetting);
if(Calendar.getInstance().getTimeInMillis() > (lastPlayed + inactiveSetting)) {
plugin.getLogger().info("Region " + getName() + " unrented because of inactivity for player " + getPlayerName());
AreaShop.debug("currentTime=" + Calendar.getInstance().getTimeInMillis() + ", getLastPlayed()=" + lastPlayed + ", timeInactive=" + (Calendar.getInstance().getTimeInMillis()-player.getLastPlayed()) + ", inactiveSetting=" + inactiveSetting);
this.unRent(true);
return true;
return this.unRent(true, null);
}
return false;
}

View File

@ -11,9 +11,10 @@
total-maximum: "You can't rent and buy more than %0% region(s) in total (you already have %1% in group '%2%')."
general-notReady: "AreaShop has not fully loaded yet, please wait."
general-noWorld: "You cannot do that, the world of this region is currently unavailable (world '%0%')."
general-noRegion: "You cannot do that, the WorldGuard region is currently unavailable (region '%0%')."
general-noWorld: "You cannot do that, the world of this region is currently unavailable (world '%world%')."
general-noRegion: "You cannot do that, the WorldGuard region is currently unavailable (region '%region%')."
general-noEconomy: "There is no Economy plugin installed or it is not setup correctly, notify the server owner about this."
general-cancelled: "%0%"
cmd-notValid: "That command is not valid, use '/as help' for info."
cmd-onlyByPlayer: "This command can only be run by a player."
@ -73,18 +74,18 @@ rent-noPermission: "You don't have permission to rent a region."
rent-maximum: "You can't rent more than %0% region(s) (you already have %1% in group '%2%')."
rent-maximumExtend: "You can't extend this rent because you have more than %0% region(s) (you already have %1% in group '%2%')."
rent-payError: "Something went wrong with paying, try again later."
rent-rented: "You rented %0% until %1%."
rent-extended: "You extended your rent of %0% until %1%."
rent-rented: "You rented %region% until %until%."
rent-extended: "You extended your rent of %region% until %until%."
rent-extendedToMax: "You extended your rent of %region% until %until% (which is the maximum rental time of %maxrenttime%)."
rent-extend: "You can extend your rent by rightclicking the sign again or using /as rent."
rent-lowMoneyExtend: "You don't have enough money to extend the rent (you have %0% and you need %1%)."
rent-lowMoneyRent: "You don't have enough money to rent this region (you have %0% and you need %1%)."
rent-lowMoneyExtend: "You don't have enough money to extend the rent (you have %0% and you need %price%)."
rent-lowMoneyRent: "You don't have enough money to rent this region (you have %0% and you need %price%)."
rent-someoneElse: "Someone else already rented this region."
rent-notRentable: "That region is not available for renting."
rent-maxExtends: "You cannot extend this rent anymore (the maximum is %0% times), however after the rent is over you can rent this region again."
rent-maxRentTime: "You cannot rent this region more time in advance, the maximum time is %0% and you have currently rented it for %1%."
rent-restrictedToWorld: "You need to be in the '%0%' world to rent this region (you are in '%1%')."
rent-restrictedToRegion: "You need to be inside '%0%' to rent it."
rent-maxExtends: "You cannot extend this rent anymore (the maximum is %maxextends% times), however after the rent is over you can rent this region again."
rent-maxRentTime: "You cannot rent this region more time in advance, the maximum time is %maxrenttime% and you have currently rented it for %timeleft%."
rent-restrictedToWorld: "You need to be in the '%world%' world to rent this region (you are in '%0%')."
rent-restrictedToRegion: "You need to be inside %region% to rent it."
rent-expireWarning: "Your region %region% has %timeleft% left, be sure to extend it if you want to keep it."
rent-alreadyAtFull: "%region% is already at or above the maximum rental time, you cannot extend it yet."
@ -95,29 +96,30 @@ buy-noPermissionNoResell: "You don't have permission to buy a region that is not
buy-notBuyable: "That region is not available for buying."
buy-maximum: "You can't buy more than %0% region(s) (you already have %1% in group '%2%')."
buy-payError: "Something went wrong with paying, try again later."
buy-succes: "You successfully bought %0%."
buy-successResale: "You successfully bought %0% from %1%."
buy-successSeller: "Your region %0% has been sold to %1% for %2%."
buy-lowMoney: "You don't have enough money to buy this region (you have %0% and you need %1%)."
buy-succes: "You successfully bought %region%."
buy-successResale: "You successfully bought %region% from %0%."
buy-successSeller: "Your region %region% has been sold to %player% for %0%."
buy-lowMoney: "You don't have enough money to buy this region (you have %0% and you need %price%)."
buy-lowMoneyResell: "You don't have enough money to buy this region (you have %0% and you need %resellprice%)."
buy-yours: "You already own this region."
buy-someoneElse: "Someone else already bought this region."
buy-restrictedToWorld: "You need to be in the '%0%' world to buy this region (you are in '%1%')."
buy-restrictedToRegion: "You need to be inside '%0%' to buy it."
buy-restrictedToWorld: "You need to be in the '%world%' world to buy this region (you are in '%0%')."
buy-restrictedToRegion: "You need to be inside '%region%' to buy it."
unrent-help: "/as unrent [regionname], the region you stand in will be used if not specified."
unrent-noPermission: "You don't have permission to unrent a region."
unrent-noPermissionOther: "You don't have permission to unrent another region."
unrent-notRegistered: "The region can't be unrented because it is not registered for renting."
unrent-notRented: "The region can't be unrented because it is not rented."
unrent-unrented: "Your region has been unrented."
unrent-other: "The region has been unrented for player %0%."
unrent-expired: "Your rent of %0% has expired."
unrent-unrented: "You have unrented %region%."
unrent-other: "%region% has been unrented for %player%."
unrent-expired: "Your rent of %region% has expired."
sell-help: "/as sell [regionname], the region you stand in will be used if not specified."
sell-notRegistered: "The region can't be sold because it is not registered for buying."
sell-notBought: "The region can't be sold because it is not someone's property."
sell-sold: "The region has been sold for player %0%."
sell-soldYours: "Your region has been sold."
sell-sold: "%region% has been sold for %player%."
sell-soldYours: "You have sold %region%."
sell-noPermission: "You don't have permission to sell a region."
sell-noPermissionOther: "You don't have permission to sell another region."
@ -242,9 +244,9 @@ teleport-noPermissionSign: "You don't have permission to teleport to the sign of
teleport-noPermissionOtherSign: "You don't have permission to teleport to signs of regions you do not own."
teleport-noPermissionFriend: "You don't have permission to teleport to regions you are added to as a friend."
teleport-noPermissionFriendSign: "You don't have permission to teleport to the sign of regions you are added to as a friend."
teleport-success: "You teleported to %0%."
teleport-successSign: "You teleported to the sign of %0%."
teleport-noSafe: "No safe position found in region %0%, no spots in region left or maximum tries exceeded (%1%/%2%)."
teleport-success: "You teleported to %region%."
teleport-successSign: "You teleported to the sign of %region%."
teleport-noSafe: "No safe position found in %region%, no spots in the region left or maximum tries exceeded (%0%/%1%)."
teleport-blocked: "You can't teleport because the position is outside the region, and you are forced to teleport inside."
teleport-changedToSign: "You only have permission to teleport to the sign and not inside the region, teleporting to sign."
teleport-changedToNoSign: "No sign available to teleport to, trying to teleport inside the region instead."