mirror of
https://github.com/NLthijs48/AreaShop.git
synced 2024-11-16 07:15:23 +01:00
Add RegionForSale import, rental auto-extend and other things
- `/as import RegionForSale`, as requested in #98: - Imports all regions from RegionForSale - Converts almost all settings to their AreaShop equivalent - Handles parent regions - Add `rent.autoExtend` for use with rental regions to automatically extend the rent when the time is out, start of #29, still need the command - Vault compatible permissions plugin is required to let this work while the player is offline - All permissions, limits and the player balance are checked as during a normal rent - Add option to region groups to automatically add all regions of a certain world - BREAKING: Region events now use OfflinePlayer instead of Player - Automatically import existing region owners/members when adding a region to AreaShop There are still a couple of things missing in the import and it needs to be tested a lot.
This commit is contained in:
parent
0bf2314f2a
commit
b1dfe93088
@ -24,6 +24,7 @@ import net.milkbowl.vault.economy.Economy;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.lang.exception.ExceptionUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
@ -34,6 +35,7 @@ import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.RegisteredServiceProvider;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
@ -521,15 +523,37 @@ public final class AreaShop extends JavaPlugin implements AreaShopInterface {
|
||||
* Get the Vault permissions provider.
|
||||
* @return Vault permissions provider
|
||||
*/
|
||||
public net.milkbowl.vault.permission.Permission getPermissionProvider() {
|
||||
public @Nullable net.milkbowl.vault.permission.Permission getPermissionProvider() {
|
||||
RegisteredServiceProvider<net.milkbowl.vault.permission.Permission> permissionProvider = getServer().getServicesManager().getRegistration(net.milkbowl.vault.permission.Permission.class);
|
||||
if (permissionProvider == null || permissionProvider.getProvider() == null) {
|
||||
error("There is no permission plugin that supports Vault, make sure you have a Vault-compatible permissions plugin installed");
|
||||
return null;
|
||||
}
|
||||
return permissionProvider.getProvider();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for a permission of a (possibly offline) player.
|
||||
* @param offlinePlayer OfflinePlayer to check
|
||||
* @param permission Permission to check
|
||||
* @return true if the player has the permission, false if the player does not have permission or, is offline and there is not Vault-compatible permission plugin
|
||||
*/
|
||||
public boolean hasPermission(OfflinePlayer offlinePlayer, String permission) {
|
||||
// Online, return through Bukkit
|
||||
if(offlinePlayer.getPlayer() != null) {
|
||||
return offlinePlayer.getPlayer().hasPermission(permission);
|
||||
}
|
||||
|
||||
// Resolve while offline if possible
|
||||
net.milkbowl.vault.permission.Permission permissionProvider = getPermissionProvider();
|
||||
if(permissionProvider != null) {
|
||||
// TODO: Should we provide a world here?
|
||||
return permissionProvider.playerHas(null, offlinePlayer, permission);
|
||||
}
|
||||
|
||||
// Player offline and no offline permission provider available, safely say that there is no permission
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the FileManager (loads/save regions and can be used to get regions).
|
||||
* @return The fileManager
|
||||
|
@ -15,8 +15,10 @@ import org.bukkit.entity.Player;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
import java.util.TreeSet;
|
||||
import java.util.UUID;
|
||||
|
||||
public class AddCommand extends CommandAreaShop {
|
||||
|
||||
@ -140,6 +142,9 @@ public class AddCommand extends CommandAreaShop {
|
||||
boolean landlord = (!sender.hasPermission("areashop.create" + type)
|
||||
&& ((sender.hasPermission("areashop.create" + type + ".owner") && isOwner)
|
||||
|| (sender.hasPermission("areashop.create" + type + ".member") && isMember)));
|
||||
List<UUID> existing = new ArrayList<>();
|
||||
existing.addAll(plugin.getWorldGuardHandler().getOwners(region).asUniqueIdList());
|
||||
existing.addAll(plugin.getWorldGuardHandler().getMembers(region).asUniqueIdList());
|
||||
if(isRent) {
|
||||
RentRegion rent = new RentRegion(region.getId(), finalWorld);
|
||||
// Set landlord
|
||||
@ -155,6 +160,33 @@ public class AddCommand extends CommandAreaShop {
|
||||
|
||||
// Run commands
|
||||
rent.runEventCommands(GeneralRegion.RegionEvent.CREATED, false);
|
||||
|
||||
// Add existing owners/members if any
|
||||
if(!landlord && !existing.isEmpty()) {
|
||||
// TODO also execute rent events to notify other plugins?
|
||||
|
||||
// Run commands
|
||||
rent.runEventCommands(GeneralRegion.RegionEvent.RENTED, true);
|
||||
|
||||
// Add values to the rent and send it to FileManager
|
||||
rent.setRentedUntil(Calendar.getInstance().getTimeInMillis() + rent.getDuration());
|
||||
rent.setRenter(existing.remove(0));
|
||||
rent.updateLastActiveTime();
|
||||
|
||||
// Add others as friends
|
||||
for(UUID friend : existing) {
|
||||
rent.getFriendsFeature().addFriend(friend, null);
|
||||
}
|
||||
|
||||
// Fire schematic event and updated times extended
|
||||
rent.handleSchematicEvent(GeneralRegion.RegionEvent.RENTED);
|
||||
|
||||
// Notify about updates
|
||||
rent.update();
|
||||
|
||||
rent.runEventCommands(GeneralRegion.RegionEvent.RENTED, false);
|
||||
}
|
||||
|
||||
regionsSuccess.add(rent);
|
||||
} else {
|
||||
BuyRegion buy = new BuyRegion(region.getId(), finalWorld);
|
||||
@ -172,6 +204,32 @@ public class AddCommand extends CommandAreaShop {
|
||||
|
||||
// Run commands
|
||||
buy.runEventCommands(GeneralRegion.RegionEvent.CREATED, false);
|
||||
|
||||
// Add existing owners/members if any
|
||||
if(!landlord && !existing.isEmpty()) {
|
||||
// TODO also execute buy events to notify for other plugins?
|
||||
|
||||
// Run commands
|
||||
buy.runEventCommands(GeneralRegion.RegionEvent.BOUGHT, true);
|
||||
|
||||
// Set the owner
|
||||
buy.setBuyer(existing.remove(0));
|
||||
buy.updateLastActiveTime();
|
||||
// Add others as friends
|
||||
for(UUID friend : existing) {
|
||||
buy.getFriendsFeature().addFriend(friend, null);
|
||||
}
|
||||
|
||||
// Notify about updates
|
||||
buy.update();
|
||||
|
||||
// Update everything
|
||||
buy.handleSchematicEvent(GeneralRegion.RegionEvent.BOUGHT);
|
||||
|
||||
// Run commands
|
||||
buy.runEventCommands(GeneralRegion.RegionEvent.BOUGHT, false);
|
||||
}
|
||||
|
||||
regionsSuccess.add(buy);
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import org.bukkit.command.CommandSender;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class GroupinfoCommand extends CommandAreaShop {
|
||||
|
||||
@ -38,7 +39,7 @@ public class GroupinfoCommand extends CommandAreaShop {
|
||||
plugin.message(sender, "groupinfo-noGroup", args[1]);
|
||||
return;
|
||||
}
|
||||
List<String> members = group.getMembers();
|
||||
Set<String> members = group.getMembers();
|
||||
if(members.size() == 0) {
|
||||
plugin.message(sender, "groupinfo-noMembers", group.getName());
|
||||
} else {
|
||||
|
@ -0,0 +1,74 @@
|
||||
package me.wiefferink.areashop.commands;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ImportCommand extends CommandAreaShop {
|
||||
|
||||
/* RegionGroup priority usage:
|
||||
0: Settings from /config.yml
|
||||
1: Settings from /worlds/<world>/config.yml
|
||||
2: Settings from /worlds/<world>/parent-regions.yml (if their priority is set it is added to this value)
|
||||
*/
|
||||
|
||||
@Override
|
||||
public String getCommandStart() {
|
||||
return "areashop import";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelp(CommandSender target) {
|
||||
if(target.hasPermission("areashop.import")) {
|
||||
return "help-import";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// TODO
|
||||
// - Landlord?
|
||||
// - Friends
|
||||
// - Region flags?
|
||||
// - Settings from the 'permissions' section in RegionForSale/config.yml?
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender sender, String[] args) {
|
||||
if(!sender.hasPermission("areashop.import")) {
|
||||
plugin.message(sender, "import-noPermission");
|
||||
return;
|
||||
}
|
||||
|
||||
if(args.length < 2) {
|
||||
plugin.message(sender, "import-help");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!"RegionForSale".equalsIgnoreCase(args[1])) {
|
||||
plugin.message(sender, "import-wrongSource");
|
||||
return;
|
||||
}
|
||||
|
||||
ImportJob importJob = new ImportJob(sender);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTabCompleteList(int toComplete, String[] start, CommandSender sender) {
|
||||
List<String> result = new ArrayList<>();
|
||||
if(toComplete == 2) {
|
||||
result.add("RegionForSale");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,456 @@
|
||||
package me.wiefferink.areashop.commands;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import com.sk89q.worldguard.protection.managers.RegionManager;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
import javafx.util.Pair;
|
||||
import me.wiefferink.areashop.AreaShop;
|
||||
import me.wiefferink.areashop.features.SignsFeature;
|
||||
import me.wiefferink.areashop.regions.BuyRegion;
|
||||
import me.wiefferink.areashop.regions.GeneralRegion;
|
||||
import me.wiefferink.areashop.regions.RegionGroup;
|
||||
import me.wiefferink.areashop.regions.RentRegion;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class ImportJob {
|
||||
|
||||
private AreaShop plugin;
|
||||
private CommandSender sender;
|
||||
|
||||
/**
|
||||
* Create and execute the import.
|
||||
* @param sender CommandSender that should receive progress updates
|
||||
*/
|
||||
public ImportJob(CommandSender sender) {
|
||||
this.sender = sender;
|
||||
this.plugin = AreaShop.getInstance();
|
||||
execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*/
|
||||
private void execute() {
|
||||
// Check for RegionForSale data
|
||||
File regionForSaleFolder = new File(plugin.getDataFolder().getParentFile().getAbsolutePath(), "RegionForSale");
|
||||
if(!regionForSaleFolder.exists()) {
|
||||
message("import-noPluginFolder", regionForSaleFolder.getName());
|
||||
return;
|
||||
}
|
||||
|
||||
File worldsFolder = new File(regionForSaleFolder.getAbsolutePath(), "worlds");
|
||||
if(!worldsFolder.exists()) {
|
||||
message("import-noWorldsFolder");
|
||||
return;
|
||||
}
|
||||
|
||||
File[] worldFolders = worldsFolder.listFiles();
|
||||
if(worldFolders == null) {
|
||||
message("import-noWorldsFolder");
|
||||
return;
|
||||
}
|
||||
|
||||
// Import data for each world
|
||||
message("import-start");
|
||||
|
||||
// Group with settings for all imported regions
|
||||
RegionGroup regionForSaleGroup = new RegionGroup(plugin, "RegionForSale");
|
||||
plugin.getFileManager().addGroup(regionForSaleGroup);
|
||||
|
||||
// Import /RegionForSale/config.yml settings
|
||||
File regionForSaleConfigFile = new File(regionForSaleFolder.getAbsolutePath(), "config.yml");
|
||||
YamlConfiguration regionForSaleConfig = loadConfiguration(regionForSaleConfigFile);
|
||||
if(regionForSaleConfig == null) {
|
||||
messageNoPrefix("import-loadConfigFailed", regionForSaleConfigFile.getAbsolutePath());
|
||||
} else {
|
||||
importRegionSettings(regionForSaleConfig, regionForSaleGroup.getSettings(), null);
|
||||
regionForSaleGroup.setSetting("priority", 0);
|
||||
}
|
||||
|
||||
// Import /RegionForSale/general.yml settings
|
||||
File regionForSaleGeneralFile = new File(regionForSaleFolder.getAbsolutePath(), "config.yml");
|
||||
YamlConfiguration regionForSaleGeneral = loadConfiguration(regionForSaleConfigFile);
|
||||
if(regionForSaleGeneral == null) {
|
||||
messageNoPrefix("import-loadConfigFailed", regionForSaleGeneralFile.getAbsolutePath());
|
||||
} else {
|
||||
// Collection interval of RegionForSale maps to rent duration
|
||||
String duration = "1 day";
|
||||
if(regionForSaleGeneral.isLong("interval.collect_money")) {
|
||||
duration = minutesToString(regionForSaleGeneral.getLong("interval.collect_money"));
|
||||
}
|
||||
regionForSaleGroup.setSetting("rent.duration", duration);
|
||||
|
||||
// Global economy account has an effect close to landlord in AreaShop
|
||||
if(regionForSaleGeneral.isString("global_econ_account")) {
|
||||
regionForSaleGroup.setSetting("general.landlordName", regionForSaleGeneral.getString("global_econ_account"));
|
||||
}
|
||||
}
|
||||
regionForSaleGroup.saveRequired();
|
||||
|
||||
////////// Handle defaults of RegionForSale
|
||||
|
||||
// Set autoExtend, to keep the same behavior as RegionForSale had
|
||||
regionForSaleGroup.setSetting("rent.autoExtend", true);
|
||||
|
||||
// Import regions from each world
|
||||
for(File worldFolder : worldFolders) {
|
||||
// Skip files
|
||||
if(!worldFolder.isDirectory()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
messageNoPrefix("import-doWorld", worldFolder.getName());
|
||||
|
||||
// Get the Bukkit world
|
||||
World world = Bukkit.getWorld(worldFolder.getName());
|
||||
if(world == null) {
|
||||
messageNoPrefix("import-noBukkitWorld");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get the WorldGuard RegionManager
|
||||
RegionManager regionManager = plugin.getWorldGuard().getRegionManager(world);
|
||||
if(regionManager == null) {
|
||||
messageNoPrefix("import-noRegionManger");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Load the /worlds/<world>/regions.yml file
|
||||
File regionsFile = new File(worldFolder.getAbsolutePath(), "regions.yml");
|
||||
YamlConfiguration regions = loadConfiguration(regionsFile);
|
||||
if(regions == null) {
|
||||
messageNoPrefix("import-loadRegionsFailed", regionsFile.getAbsolutePath());
|
||||
continue;
|
||||
}
|
||||
|
||||
// Load /worlds/<world>/config.yml file
|
||||
File worldConfigFile = new File(worldFolder.getAbsolutePath(), "config.yml");
|
||||
YamlConfiguration worldConfig = loadConfiguration(worldConfigFile);
|
||||
if(worldConfig == null) {
|
||||
messageNoPrefix("import-loadWorldConfigFailed", worldConfigFile.getAbsolutePath());
|
||||
// Simply skip importing the settings, since this is not really fatal
|
||||
} else {
|
||||
// RegionGroup with all world settings
|
||||
RegionGroup worldGroup = new RegionGroup(plugin, "RegionForSale-" + worldFolder.getName());
|
||||
importRegionSettings(worldConfig, worldGroup.getSettings(), null);
|
||||
worldGroup.setSetting("priority", 1);
|
||||
worldGroup.addWorld(worldFolder.getName());
|
||||
plugin.getFileManager().addGroup(regionForSaleGroup);
|
||||
worldGroup.saveRequired();
|
||||
}
|
||||
|
||||
// Create groups to hold settings of /worlds/<world>/parent-regions.yml
|
||||
File parentRegionsFile = new File(worldFolder.getAbsolutePath(), "parent-regions.yml");
|
||||
YamlConfiguration parentRegions = loadConfiguration(parentRegionsFile);
|
||||
if(parentRegions == null) {
|
||||
messageNoPrefix("import-loadParentRegionsFailed", parentRegionsFile.getAbsolutePath());
|
||||
// Non-fatal, so just continue
|
||||
} else {
|
||||
for(String parentRegionName : parentRegions.getKeys(false)) {
|
||||
// Get WorldGuard region
|
||||
ProtectedRegion worldGuardRegion = regionManager.getRegion(parentRegionName);
|
||||
if(worldGuardRegion == null) {
|
||||
messageNoPrefix("import-noWorldGuardRegionParent", parentRegionName);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get settings section
|
||||
ConfigurationSection parentRegionSection = parentRegions.getConfigurationSection(parentRegionName);
|
||||
if(parentRegionSection == null) {
|
||||
messageNoPrefix("import-improperParentRegion", parentRegionName);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip if it does not have any settings
|
||||
if(parentRegionSection.getKeys(false).isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Import parent region settings into a RegionGroup
|
||||
RegionGroup parentRegionGroup = new RegionGroup(plugin, "RegionForSale-" + worldFolder.getName() + "-" + parentRegionName);
|
||||
importRegionSettings(parentRegionSection, parentRegionGroup.getSettings(), null);
|
||||
parentRegionGroup.setSetting("priority", 2 + parentRegionSection.getLong("info.priority", 0));
|
||||
parentRegionGroup.saveRequired();
|
||||
|
||||
// TODO add all regions that are contained in this parent region
|
||||
// Utils.getWorldEditRegionsInSelection()
|
||||
}
|
||||
}
|
||||
|
||||
// Read and import regions
|
||||
for(String regionKey : regions.getKeys(false)) {
|
||||
GeneralRegion existingRegion = plugin.getFileManager().getRegion(regionKey);
|
||||
if(existingRegion != null) {
|
||||
if(world.getName().equalsIgnoreCase(existingRegion.getWorldName())) {
|
||||
messageNoPrefix("import-alreadyAdded", regionKey);
|
||||
} else {
|
||||
messageNoPrefix("import-alreadyAddedOtherWorld", regionKey, existingRegion.getWorldName(), world.getName());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
ConfigurationSection regionSection = regions.getConfigurationSection(regionKey);
|
||||
if(regionSection == null) {
|
||||
messageNoPrefix("import-invalidRegionSection", regionKey);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get WorldGuard region
|
||||
ProtectedRegion worldGuardRegion = regionManager.getRegion(regionKey);
|
||||
if(worldGuardRegion == null) {
|
||||
messageNoPrefix("import-noWorldGuardRegion", regionKey);
|
||||
continue;
|
||||
}
|
||||
|
||||
String owner = regionSection.getString("info.owner", null);
|
||||
boolean isBought = regionSection.getBoolean("info.is-bought");
|
||||
boolean rentable = regionSection.getBoolean("economic-settings.rentable");
|
||||
boolean buyable = regionSection.getBoolean("economic-settings.buyable");
|
||||
|
||||
// Can be bought and rented, import as buy
|
||||
if(buyable && rentable) {
|
||||
messageNoPrefix("import-buyAndRent", regionKey);
|
||||
}
|
||||
|
||||
// Cannot be bought or rented, skip
|
||||
if(!buyable && !rentable && owner == null) {
|
||||
messageNoPrefix("import-noBuyAndNoRent", regionKey);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Create region
|
||||
GeneralRegion region;
|
||||
if(rentable || (owner != null && !isBought)) {
|
||||
region = new RentRegion(regionKey, world);
|
||||
plugin.getFileManager().addRent((RentRegion)region);
|
||||
} else {
|
||||
region = new BuyRegion(regionKey, world);
|
||||
plugin.getFileManager().addBuy((BuyRegion)region);
|
||||
}
|
||||
|
||||
// Import settings
|
||||
importRegionSettings(regionSection, region.getConfig(), region);
|
||||
region.getConfig().set("general.importedFrom", "RegionForSale");
|
||||
|
||||
// Get existing owners and members
|
||||
List<UUID> existing = new ArrayList<>();
|
||||
if(owner != null) {
|
||||
OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(owner);
|
||||
if(offlinePlayer != null) {
|
||||
existing.add(offlinePlayer.getUniqueId());
|
||||
}
|
||||
}
|
||||
for(UUID uuid : plugin.getWorldGuardHandler().getOwners(worldGuardRegion).asUniqueIdList()) {
|
||||
if(!existing.contains(uuid)) {
|
||||
existing.add(uuid);
|
||||
}
|
||||
}
|
||||
for(UUID uuid : plugin.getWorldGuardHandler().getMembers(worldGuardRegion).asUniqueIdList()) {
|
||||
if(!existing.contains(uuid)) {
|
||||
existing.add(uuid);
|
||||
}
|
||||
}
|
||||
|
||||
// First owner (or if none, the first member) will be the renter/buyer
|
||||
if(!existing.isEmpty()) {
|
||||
region.setOwner(existing.remove(0));
|
||||
}
|
||||
// Add others as friends
|
||||
for(UUID friend : existing) {
|
||||
region.getFriendsFeature().addFriend(friend, null);
|
||||
}
|
||||
|
||||
region.saveRequired();
|
||||
|
||||
messageNoPrefix("import-imported", regionKey);
|
||||
}
|
||||
}
|
||||
|
||||
// Update all regions
|
||||
plugin.getFileManager().updateAllRegions(sender);
|
||||
// Write all imported regions and settings to disk
|
||||
plugin.getFileManager().saveRequiredFiles();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a YamlConfiguration from disk using UTF-8 encoding.
|
||||
* @param from File to read the configuration from
|
||||
* @return YamlConfiguration if the file exists and got read wihout problems, otherwise null
|
||||
*/
|
||||
private YamlConfiguration loadConfiguration(File from) {
|
||||
try(
|
||||
InputStreamReader reader = new InputStreamReader(new FileInputStream(from), Charsets.UTF_8)
|
||||
) {
|
||||
return YamlConfiguration.loadConfiguration(reader);
|
||||
} catch(IOException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Import region specific settings from a RegionForSale source to an AreaShop target ConfigurationSection.
|
||||
* @param from RegionForSale config section that specifies region settings
|
||||
* @param to AreaShop config section that specifies region settings
|
||||
* @param region GeneralRegion to copy settings to, or null if doing generic settings
|
||||
*/
|
||||
private void importRegionSettings(ConfigurationSection from, ConfigurationSection to, GeneralRegion region) {
|
||||
// Maximum rental time, TODO check if this is actually the same
|
||||
if(from.isLong("permissions.max-rent-time")) {
|
||||
to.set("rent.maxRentTime", minutesToString(from.getLong("permissions.max-rent-time")));
|
||||
}
|
||||
|
||||
// Region rebuild
|
||||
if(from.getBoolean("region-rebuilding.auto-rebuild")) {
|
||||
to.set("general.enableRestore", true);
|
||||
}
|
||||
|
||||
// Get price settings
|
||||
String unit = from.getString("economic-settings.unit-type");
|
||||
String rentPrice = from.getString("economic-settings.cost-per-unit.rent");
|
||||
String buyPrice = from.getString("economic-settings.cost-per-unit.buy");
|
||||
String sellPrice = from.getString("economic-settings.cost-per-unit.selling-price");
|
||||
// TODO: There is no easy way to import this, setup eventCommandsProfile?
|
||||
String taxes = from.getString("economic-settings.cost-per-unit.taxes");
|
||||
|
||||
// Determine unit and add that to the price
|
||||
String unitSuffix = "";
|
||||
if("region".equalsIgnoreCase(unit)) {
|
||||
// add nothing
|
||||
} else if("m3".equalsIgnoreCase(unit)) {
|
||||
unitSuffix = "*%volume%";
|
||||
} else { // m2 or nothing (in case not set, we should actually look in parent files to correctly set this...)
|
||||
unitSuffix = "*(%volume%/%height%)"; // This is better than width*depth because of polygon regions
|
||||
}
|
||||
|
||||
// Apply settings
|
||||
if(rentPrice != null) {
|
||||
to.set("rent.price", rentPrice + unitSuffix);
|
||||
}
|
||||
if(buyPrice != null) {
|
||||
to.set("buy.price", buyPrice + unitSuffix);
|
||||
if(sellPrice != null) {
|
||||
try {
|
||||
double buyPriceAmount = Double.parseDouble(buyPrice);
|
||||
double sellPriceAmount = Double.parseDouble(sellPrice);
|
||||
to.set("buy.moneyBack", sellPriceAmount / buyPriceAmount * 100);
|
||||
} catch(NumberFormatException e) {
|
||||
// There is not always a region here for the message, should probably indicate something though
|
||||
message("import-moneyBackFailed", buyPrice, sellPrice);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set rented until
|
||||
if(from.isLong("info.last-withdrawal")
|
||||
&& region != null
|
||||
&& region instanceof RentRegion) {
|
||||
RentRegion rentRegion = (RentRegion)region;
|
||||
long lastWithdrawal = from.getLong("info.last-withdrawal");
|
||||
// Because the rental duration is already imported into the region and its parents this should be correct
|
||||
rentRegion.setRentedUntil(lastWithdrawal + rentRegion.getDuration());
|
||||
}
|
||||
|
||||
// Import signs (list of strings like "297, 71, -22")
|
||||
if(from.isList("info.signs") && region != null) {
|
||||
for(String signLocation : from.getStringList("info.signs")) {
|
||||
String[] locationParts = signLocation.split(", ");
|
||||
if(locationParts.length != 3) {
|
||||
message("import-invalidSignLocation", region.getName(), signLocation);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Parse the location
|
||||
Location location;
|
||||
try {
|
||||
location = new Location(region.getWorld(), Double.parseDouble(locationParts[0]), Double.parseDouble(locationParts[1]), Double.parseDouble(locationParts[2]));
|
||||
} catch(NumberFormatException e) {
|
||||
message("import-invalidSignLocation", region.getName(), signLocation);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if this location is already added to a region
|
||||
SignsFeature.RegionSign regionSign = SignsFeature.getSignByLocation(location);
|
||||
if(regionSign != null) {
|
||||
if(!regionSign.getRegion().equals(region)) {
|
||||
message("import-signAlreadyAdded", region.getName(), signLocation, regionSign.getRegion().getName());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// SignType and Facing will be written when the sign is updated later
|
||||
region.getSignsFeature().addSign(location, null, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static List<Pair<Integer, String>> timeUnitLookup = new ArrayList<Pair<Integer, String>>() {
|
||||
{
|
||||
add(new Pair<>(60 * 24 * 30 * 12, "year"));
|
||||
add(new Pair<>(60 * 24 * 30, "month"));
|
||||
add(new Pair<>(60 * 24, "day"));
|
||||
add(new Pair<>(60, "hour"));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert minutes to a human-readable string.
|
||||
* @param minutes Value to convert
|
||||
* @return String that represents the same length of time in a readable format, like "1 day", "5 minutes", "3 months"
|
||||
*/
|
||||
private String minutesToString(long minutes) {
|
||||
// If the specified number of minutes can map nicely to a higher unit, use that one
|
||||
String resultUnit = "minute";
|
||||
long resultValue = minutes;
|
||||
for(Pair<Integer, String> unit : timeUnitLookup) {
|
||||
long result = minutes / unit.getKey();
|
||||
if(resultValue * unit.getKey() == minutes) {
|
||||
resultUnit = unit.getValue();
|
||||
resultValue = result;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return resultValue + " " + resultUnit + (resultValue == 1 ? "" : "s");
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message to a target without a prefix.
|
||||
* @param key The key of the language string
|
||||
* @param replacements The replacements to insert in the message
|
||||
*/
|
||||
public void messageNoPrefix(String key, Object... replacements) {
|
||||
plugin.messageNoPrefix(sender, key, replacements);
|
||||
|
||||
if(!(sender instanceof ConsoleCommandSender)) {
|
||||
plugin.messageNoPrefix(Bukkit.getConsoleSender(), key, replacements);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message to a target, prefixed by the default chat prefix.
|
||||
* @param key The key of the language string
|
||||
* @param replacements The replacements to insert in the message
|
||||
*/
|
||||
public void message(String key, Object... replacements) {
|
||||
plugin.message(sender, key, replacements);
|
||||
|
||||
if(!(sender instanceof ConsoleCommandSender)) {
|
||||
plugin.message(Bukkit.getConsoleSender(), key, replacements);
|
||||
}
|
||||
}
|
||||
}
|
@ -18,6 +18,8 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
// TODO fix '/as info' help message hitting replacement limit (improve depth tracking?)
|
||||
// TODO add info about autoExtend
|
||||
public class InfoCommand extends CommandAreaShop {
|
||||
|
||||
@Override
|
||||
|
@ -71,7 +71,7 @@ public class MeCommand extends CommandAreaShop {
|
||||
// Get the regions the player is added as friend
|
||||
Set<GeneralRegion> friendRegions = new HashSet<>();
|
||||
for(GeneralRegion region : plugin.getFileManager().getRegions()) {
|
||||
if(region.getFriendsFeature().getFriends() != null && region.getFriendsFeature().getFriends().contains(player.getUniqueId())) {
|
||||
if(region.getFriendsFeature().getFriends().contains(player.getUniqueId())) {
|
||||
friendRegions.add(region);
|
||||
}
|
||||
}
|
||||
|
@ -66,9 +66,9 @@ public class SetpriceCommand extends CommandAreaShop {
|
||||
}
|
||||
if("default".equalsIgnoreCase(args[1]) || "reset".equalsIgnoreCase(args[1])) {
|
||||
if(region instanceof RentRegion) {
|
||||
((RentRegion)region).removePrice();
|
||||
((RentRegion)region).setPrice(null);
|
||||
} else if(region instanceof BuyRegion) {
|
||||
((BuyRegion)region).removePrice();
|
||||
((BuyRegion)region).setPrice(null);
|
||||
}
|
||||
region.update();
|
||||
plugin.message(sender, "setprice-successRemoved", region);
|
||||
|
@ -2,21 +2,21 @@ package me.wiefferink.areashop.events.ask;
|
||||
|
||||
import me.wiefferink.areashop.events.CancellableRegionEvent;
|
||||
import me.wiefferink.areashop.regions.BuyRegion;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
|
||||
/**
|
||||
* Broadcasted when a player tries to buy a region.
|
||||
*/
|
||||
public class BuyingRegionEvent extends CancellableRegionEvent<BuyRegion> {
|
||||
|
||||
private Player player;
|
||||
private OfflinePlayer 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) {
|
||||
public BuyingRegionEvent(BuyRegion region, OfflinePlayer player) {
|
||||
super(region);
|
||||
this.player = player;
|
||||
}
|
||||
@ -25,7 +25,7 @@ public class BuyingRegionEvent extends CancellableRegionEvent<BuyRegion> {
|
||||
* Get the player that is trying to buy the region.
|
||||
* @return The player that is trying to buy the region
|
||||
*/
|
||||
public Player getPlayer() {
|
||||
public OfflinePlayer getPlayer() {
|
||||
return player;
|
||||
}
|
||||
}
|
||||
|
@ -2,14 +2,14 @@ package me.wiefferink.areashop.events.ask;
|
||||
|
||||
import me.wiefferink.areashop.events.CancellableRegionEvent;
|
||||
import me.wiefferink.areashop.regions.RentRegion;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
|
||||
/**
|
||||
* Broadcasted when a player tries to rent a region.
|
||||
*/
|
||||
public class RentingRegionEvent extends CancellableRegionEvent<RentRegion> {
|
||||
|
||||
private Player player;
|
||||
private OfflinePlayer player;
|
||||
private boolean extending;
|
||||
|
||||
/**
|
||||
@ -18,7 +18,7 @@ public class RentingRegionEvent extends CancellableRegionEvent<RentRegion> {
|
||||
* @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) {
|
||||
public RentingRegionEvent(RentRegion region, OfflinePlayer player, boolean extending) {
|
||||
super(region);
|
||||
this.player = player;
|
||||
this.extending = extending;
|
||||
@ -28,7 +28,7 @@ public class RentingRegionEvent extends CancellableRegionEvent<RentRegion> {
|
||||
* Get the player that is trying to rent the region.
|
||||
* @return The player that is trying to rent the region
|
||||
*/
|
||||
public Player getPlayer() {
|
||||
public OfflinePlayer getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
|
@ -2,21 +2,21 @@ package me.wiefferink.areashop.events.ask;
|
||||
|
||||
import me.wiefferink.areashop.events.CancellableRegionEvent;
|
||||
import me.wiefferink.areashop.regions.BuyRegion;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
|
||||
/**
|
||||
* Broadcasted when a player tries to resell a region.
|
||||
*/
|
||||
public class ResellingRegionEvent extends CancellableRegionEvent<BuyRegion> {
|
||||
|
||||
private Player player;
|
||||
private OfflinePlayer 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) {
|
||||
public ResellingRegionEvent(BuyRegion region, OfflinePlayer player) {
|
||||
super(region);
|
||||
this.player = player;
|
||||
}
|
||||
@ -25,7 +25,7 @@ public class ResellingRegionEvent extends CancellableRegionEvent<BuyRegion> {
|
||||
* Get the player that is trying to buy the region.
|
||||
* @return The player that is trying to buy the region
|
||||
*/
|
||||
public Player getBuyer() {
|
||||
public OfflinePlayer getBuyer() {
|
||||
return player;
|
||||
}
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ public class FriendsFeature extends RegionFeature {
|
||||
HashSet<String> result = new HashSet<>();
|
||||
for(UUID friend : getFriends()) {
|
||||
OfflinePlayer player = Bukkit.getOfflinePlayer(friend);
|
||||
if(player != null) {
|
||||
if(player != null && player.getName() != null) {
|
||||
result.add(player.getName());
|
||||
}
|
||||
}
|
||||
|
@ -138,8 +138,8 @@ public class SignsFeature extends RegionFeature {
|
||||
}
|
||||
String signPath = "general.signs." + i + ".";
|
||||
region.setSetting(signPath + "location", Utils.locationToConfig(location));
|
||||
region.setSetting(signPath + "facing", facing.name());
|
||||
region.setSetting(signPath + "signType", signType.name());
|
||||
region.setSetting(signPath + "facing", facing != null ? facing.name() : null);
|
||||
region.setSetting(signPath + "signType", signType != null ? signType.name() : null);
|
||||
if(profile != null && profile.length() != 0) {
|
||||
region.setSetting(signPath + "profile", profile);
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import me.wiefferink.areashop.commands.GroupdelCommand;
|
||||
import me.wiefferink.areashop.commands.GroupinfoCommand;
|
||||
import me.wiefferink.areashop.commands.GrouplistCommand;
|
||||
import me.wiefferink.areashop.commands.HelpCommand;
|
||||
import me.wiefferink.areashop.commands.ImportCommand;
|
||||
import me.wiefferink.areashop.commands.InfoCommand;
|
||||
import me.wiefferink.areashop.commands.LinksignsCommand;
|
||||
import me.wiefferink.areashop.commands.MeCommand;
|
||||
@ -83,6 +84,7 @@ public class CommandManager extends Manager implements CommandExecutor, TabCompl
|
||||
commands.add(new StackCommand());
|
||||
commands.add(new SetlandlordCommand());
|
||||
commands.add(new MessageCommand());
|
||||
commands.add(new ImportCommand());
|
||||
|
||||
// Register commands in bukkit
|
||||
plugin.getCommand("AreaShop").setExecutor(this);
|
||||
|
@ -307,10 +307,20 @@ public class FileManager extends Manager {
|
||||
public void addRent(RentRegion rent) {
|
||||
addRentNoSave(rent);
|
||||
rent.saveRequired();
|
||||
markGroupsAutoDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a buy to the list without saving it to disk (useful for laoding at startup).
|
||||
* Mark all RegionGroups that they should regenerate regions.
|
||||
*/
|
||||
public void markGroupsAutoDirty() {
|
||||
for(RegionGroup group : getGroups()) {
|
||||
group.autoDirty();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a buy to the list without saving it to disk (useful for loading at startup).
|
||||
* @param buy The buy region to add
|
||||
*/
|
||||
public void addBuyNoSave(BuyRegion buy) {
|
||||
@ -329,6 +339,7 @@ public class FileManager extends Manager {
|
||||
public void addBuy(BuyRegion buy) {
|
||||
addBuyNoSave(buy);
|
||||
buy.saveRequired();
|
||||
markGroupsAutoDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -71,7 +71,7 @@ public class BuyRegion extends GeneralRegion {
|
||||
* @param player Player to check
|
||||
* @return true if this player owns this region, otherwise false
|
||||
*/
|
||||
public boolean isBuyer(Player player) {
|
||||
public boolean isBuyer(OfflinePlayer player) {
|
||||
return player != null && isBuyer(player.getUniqueId());
|
||||
}
|
||||
|
||||
@ -161,17 +161,10 @@ public class BuyRegion extends GeneralRegion {
|
||||
* Change the price of the region.
|
||||
* @param price The price to set this region to
|
||||
*/
|
||||
public void setPrice(double price) {
|
||||
public void setPrice(Double price) {
|
||||
setSetting("buy.price", price);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the price so that the price will be taken from a group or the default.yml file
|
||||
*/
|
||||
public void removePrice() {
|
||||
setSetting("buy.price", null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the region into resell mode with the given price.
|
||||
* @param price The price this region should be put up for sale
|
||||
@ -260,58 +253,65 @@ public class BuyRegion extends GeneralRegion {
|
||||
|
||||
/**
|
||||
* Buy a region.
|
||||
* @param player The player that wants to buy the region
|
||||
* @param offlinePlayer The player that wants to buy the region
|
||||
* @return true if it succeeded and false if not
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public boolean buy(Player player) {
|
||||
public boolean buy(OfflinePlayer offlinePlayer) {
|
||||
// Check if the player has permission
|
||||
if(player.hasPermission("areashop.buy")) {
|
||||
if(plugin.hasPermission(offlinePlayer, "areashop.buy")) {
|
||||
if(plugin.getEconomy() == null) {
|
||||
message(player, "general-noEconomy");
|
||||
message(offlinePlayer, "general-noEconomy");
|
||||
return false;
|
||||
}
|
||||
if(isInResellingMode()) {
|
||||
if(!player.hasPermission("areashop.buyresell")) {
|
||||
message(player, "buy-noPermissionResell");
|
||||
if(!plugin.hasPermission(offlinePlayer, "areashop.buyresell")) {
|
||||
message(offlinePlayer, "buy-noPermissionResell");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if(!player.hasPermission("areashop.buynormal")) {
|
||||
message(player, "buy-noPermissionNoResell");
|
||||
if(!plugin.hasPermission(offlinePlayer, "areashop.buynormal")) {
|
||||
message(offlinePlayer, "buy-noPermissionNoResell");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(getWorld() == null) {
|
||||
message(player, "general-noWorld");
|
||||
message(offlinePlayer, "general-noWorld");
|
||||
return false;
|
||||
}
|
||||
if(getRegion() == null) {
|
||||
message(player, "general-noRegion");
|
||||
message(offlinePlayer, "general-noRegion");
|
||||
return false;
|
||||
}
|
||||
if(!isSold() || (isInResellingMode() && !isBuyer(player))) {
|
||||
if(!isSold() || (isInResellingMode() && !isBuyer(offlinePlayer))) {
|
||||
boolean isResell = isInResellingMode();
|
||||
// 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()))) {
|
||||
message(player, "buy-restrictedToRegion");
|
||||
return false;
|
||||
}
|
||||
if(restrictedToWorld() && !player.getWorld().getName().equals(getWorldName())) {
|
||||
message(player, "buy-restrictedToWorld", player.getWorld().getName());
|
||||
return false;
|
||||
|
||||
// Only relevant if the player is online
|
||||
Player player = offlinePlayer.getPlayer();
|
||||
if(player != null) {
|
||||
// Check if the players needs to be in the region for buying
|
||||
if(restrictedToRegion() && (!player.getWorld().getName().equals(getWorldName())
|
||||
|| !getRegion().contains(player.getLocation().getBlockX(), player.getLocation().getBlockY(), player.getLocation().getBlockZ()))) {
|
||||
message(offlinePlayer, "buy-restrictedToRegion");
|
||||
return false;
|
||||
}
|
||||
// Check if the players needs to be in the world for buying
|
||||
if(restrictedToWorld() && !player.getWorld().getName().equals(getWorldName())) {
|
||||
message(offlinePlayer, "buy-restrictedToWorld", player.getWorld().getName());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check region limits
|
||||
LimitResult limitResult = this.limitsAllow(RegionType.BUY, player);
|
||||
LimitResult limitResult = this.limitsAllow(RegionType.BUY, offlinePlayer);
|
||||
AreaShop.debug("LimitResult: " + limitResult.toString());
|
||||
if(!limitResult.actionAllowed()) {
|
||||
if(limitResult.getLimitingFactor() == LimitType.TOTAL) {
|
||||
message(player, "total-maximum", limitResult.getMaximum(), limitResult.getCurrent(), limitResult.getLimitingGroup());
|
||||
message(offlinePlayer, "total-maximum", limitResult.getMaximum(), limitResult.getCurrent(), limitResult.getLimitingGroup());
|
||||
return false;
|
||||
}
|
||||
if(limitResult.getLimitingFactor() == LimitType.BUYS) {
|
||||
message(player, "buy-maximum", limitResult.getMaximum(), limitResult.getCurrent(), limitResult.getLimitingGroup());
|
||||
message(offlinePlayer, "buy-maximum", limitResult.getMaximum(), limitResult.getCurrent(), limitResult.getLimitingGroup());
|
||||
return false;
|
||||
}
|
||||
// Should not be reached, but is safe like this
|
||||
@ -319,24 +319,24 @@ public class BuyRegion extends GeneralRegion {
|
||||
}
|
||||
|
||||
// Check if the player has enough money
|
||||
if((!isResell && plugin.getEconomy().has(player, getWorldName(), getPrice())) || (isResell && plugin.getEconomy().has(player, getWorldName(), getResellPrice()))) {
|
||||
if((!isResell && plugin.getEconomy().has(offlinePlayer, getWorldName(), getPrice())) || (isResell && plugin.getEconomy().has(offlinePlayer, getWorldName(), getResellPrice()))) {
|
||||
UUID oldOwner = getBuyer();
|
||||
if(isResell && oldOwner != null) {
|
||||
// Broadcast and check event
|
||||
ResellingRegionEvent event = new ResellingRegionEvent(this, player);
|
||||
ResellingRegionEvent event = new ResellingRegionEvent(this, offlinePlayer);
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
if(event.isCancelled()) {
|
||||
message(player, "general-cancelled", event.getReason());
|
||||
message(offlinePlayer, "general-cancelled", event.getReason());
|
||||
return false;
|
||||
}
|
||||
|
||||
getFriendsFeature().clearFriends();
|
||||
double resellPrice = getResellPrice();
|
||||
// Transfer the money to the previous owner
|
||||
EconomyResponse r = plugin.getEconomy().withdrawPlayer(player, getWorldName(), getResellPrice());
|
||||
EconomyResponse r = plugin.getEconomy().withdrawPlayer(offlinePlayer, getWorldName(), getResellPrice());
|
||||
if(!r.transactionSuccess()) {
|
||||
message(player, "buy-payError");
|
||||
AreaShop.debug("Something went wrong with getting money from " + player.getName() + " while buying " + getName() + ": " + r.errorMessage);
|
||||
message(offlinePlayer, "buy-payError");
|
||||
AreaShop.debug("Something went wrong with getting money from " + offlinePlayer.getName() + " while buying " + getName() + ": " + r.errorMessage);
|
||||
return false;
|
||||
}
|
||||
r = null;
|
||||
@ -349,14 +349,14 @@ public class BuyRegion extends GeneralRegion {
|
||||
r = plugin.getEconomy().depositPlayer(oldOwnerName, getWorldName(), getResellPrice());
|
||||
}
|
||||
if(r == null || !r.transactionSuccess()) {
|
||||
AreaShop.warn("Something went wrong with paying '" + oldOwnerName + "' " + getFormattedPrice() + " for his resell of region " + getName() + " to " + player.getName());
|
||||
AreaShop.warn("Something went wrong with paying '" + oldOwnerName + "' " + getFormattedPrice() + " for his resell of region " + getName() + " to " + offlinePlayer.getName());
|
||||
}
|
||||
// Resell is done, disable that now
|
||||
disableReselling();
|
||||
// Run commands
|
||||
this.runEventCommands(RegionEvent.RESELL, true);
|
||||
// Set the owner
|
||||
setBuyer(player.getUniqueId());
|
||||
setBuyer(offlinePlayer.getUniqueId());
|
||||
updateLastActiveTime();
|
||||
|
||||
// Update everything
|
||||
@ -366,7 +366,7 @@ public class BuyRegion extends GeneralRegion {
|
||||
this.notifyAndUpdate(new ResoldRegionEvent(this, oldOwner));
|
||||
|
||||
// Send message to the player
|
||||
message(player, "buy-successResale", oldOwnerName);
|
||||
message(offlinePlayer, "buy-successResale", oldOwnerName);
|
||||
Player seller = Bukkit.getPlayer(oldOwner);
|
||||
if(seller != null) {
|
||||
message(seller, "buy-successSeller", resellPrice);
|
||||
@ -375,17 +375,17 @@ public class BuyRegion extends GeneralRegion {
|
||||
this.runEventCommands(RegionEvent.RESELL, false);
|
||||
} else {
|
||||
// Broadcast and check event
|
||||
BuyingRegionEvent event = new BuyingRegionEvent(this, player);
|
||||
BuyingRegionEvent event = new BuyingRegionEvent(this, offlinePlayer);
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
if(event.isCancelled()) {
|
||||
message(player, "general-cancelled", event.getReason());
|
||||
message(offlinePlayer, "general-cancelled", event.getReason());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Substract the money from the players balance
|
||||
EconomyResponse r = plugin.getEconomy().withdrawPlayer(player, getWorldName(), getPrice());
|
||||
EconomyResponse r = plugin.getEconomy().withdrawPlayer(offlinePlayer, getWorldName(), getPrice());
|
||||
if(!r.transactionSuccess()) {
|
||||
message(player, "buy-payError");
|
||||
message(offlinePlayer, "buy-payError");
|
||||
return false;
|
||||
}
|
||||
// Optionally give money to the landlord
|
||||
@ -401,14 +401,14 @@ public class BuyRegion extends GeneralRegion {
|
||||
r = plugin.getEconomy().depositPlayer(landlordName, getWorldName(), getPrice());
|
||||
}
|
||||
if(r != null && !r.transactionSuccess()) {
|
||||
AreaShop.warn("Something went wrong with paying '" + landlordName + "' " + getFormattedPrice() + " for his sell of region " + getName() + " to " + player.getName());
|
||||
AreaShop.warn("Something went wrong with paying '" + landlordName + "' " + getFormattedPrice() + " for his sell of region " + getName() + " to " + offlinePlayer.getName());
|
||||
}
|
||||
}
|
||||
|
||||
// Run commands
|
||||
this.runEventCommands(RegionEvent.BOUGHT, true);
|
||||
// Set the owner
|
||||
setBuyer(player.getUniqueId());
|
||||
setBuyer(offlinePlayer.getUniqueId());
|
||||
updateLastActiveTime();
|
||||
|
||||
// Notify about updates
|
||||
@ -418,7 +418,7 @@ public class BuyRegion extends GeneralRegion {
|
||||
handleSchematicEvent(RegionEvent.BOUGHT);
|
||||
|
||||
// Send message to the player
|
||||
message(player, "buy-succes");
|
||||
message(offlinePlayer, "buy-succes");
|
||||
// Run commands
|
||||
this.runEventCommands(RegionEvent.BOUGHT, false);
|
||||
}
|
||||
@ -426,20 +426,20 @@ public class BuyRegion extends GeneralRegion {
|
||||
} else {
|
||||
// Player has not enough money
|
||||
if(isResell) {
|
||||
message(player, "buy-lowMoneyResell", Utils.formatCurrency(plugin.getEconomy().getBalance(player, getWorldName())));
|
||||
message(offlinePlayer, "buy-lowMoneyResell", Utils.formatCurrency(plugin.getEconomy().getBalance(offlinePlayer, getWorldName())));
|
||||
} else {
|
||||
message(player, "buy-lowMoney", Utils.formatCurrency(plugin.getEconomy().getBalance(player, getWorldName())));
|
||||
message(offlinePlayer, "buy-lowMoney", Utils.formatCurrency(plugin.getEconomy().getBalance(offlinePlayer, getWorldName())));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(isBuyer(player)) {
|
||||
message(player, "buy-yours");
|
||||
if(isBuyer(offlinePlayer)) {
|
||||
message(offlinePlayer, "buy-yours");
|
||||
} else {
|
||||
message(player, "buy-someoneElse");
|
||||
message(offlinePlayer, "buy-someoneElse");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
message(player, "buy-noPermission");
|
||||
message(offlinePlayer, "buy-noPermission");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -413,6 +413,18 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the owner of the region.
|
||||
* @param player The player that should be the owner
|
||||
*/
|
||||
public void setOwner(UUID player) {
|
||||
if(this instanceof RentRegion) {
|
||||
((RentRegion)this).setRenter(player);
|
||||
} else {
|
||||
((BuyRegion)this).setBuyer(player);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the landlord of this region (the player that receives any revenue from this region).
|
||||
* @return The UUID of the landlord of this region
|
||||
@ -1137,19 +1149,19 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
|
||||
* @param player The player to check it for
|
||||
* @return LimitResult containing if it is allowed, why and limiting factor
|
||||
*/
|
||||
public LimitResult limitsAllow(RegionType type, Player player) {
|
||||
public LimitResult limitsAllow(RegionType type, OfflinePlayer player) {
|
||||
return limitsAllow(type, player, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the player can buy/rent this region, detailed info in the result object.
|
||||
* @param type The type of region to check
|
||||
* @param player The player to check it for
|
||||
* @param offlinePlayer The player to check it for
|
||||
* @param extend Check for extending of rental regions
|
||||
* @return LimitResult containing if it is allowed, why and limiting factor
|
||||
*/
|
||||
public LimitResult limitsAllow(RegionType type, Player player, boolean extend) {
|
||||
if(player.hasPermission("areashop.limitbypass")) {
|
||||
public LimitResult limitsAllow(RegionType type, OfflinePlayer offlinePlayer, boolean extend) {
|
||||
if(plugin.hasPermission(offlinePlayer, "areashop.limitbypass")) {
|
||||
return new LimitResult(true, null, 0, 0, null);
|
||||
}
|
||||
GeneralRegion exclude = null;
|
||||
@ -1166,7 +1178,7 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
|
||||
List<String> groups = new ArrayList<>(plugin.getConfig().getConfigurationSection("limitGroups").getKeys(false));
|
||||
while(!groups.isEmpty()) {
|
||||
String group = groups.get(0);
|
||||
if(player.hasPermission("areashop.limits." + group) && this.matchesLimitGroup(group)) {
|
||||
if(plugin.hasPermission(offlinePlayer, "areashop.limits." + group) && this.matchesLimitGroup(group)) {
|
||||
String pathPrefix = "limitGroups." + group + ".";
|
||||
if(!plugin.getConfig().isInt(pathPrefix + "total")) {
|
||||
AreaShop.warn("Limit group " + group + " in the config.yml file does not correctly specify the number of total regions (should be specified as total: <number>)");
|
||||
@ -1177,12 +1189,12 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
|
||||
int totalLimit = plugin.getConfig().getInt("limitGroups." + group + ".total");
|
||||
int typeLimit = plugin.getConfig().getInt("limitGroups." + group + "." + typePath);
|
||||
//AreaShop.debug("typeLimitOther="+typeLimit+", typePath="+typePath);
|
||||
int totalCurrent = hasRegionsInLimitGroup(player, group, plugin.getFileManager().getRegions(), exclude);
|
||||
int totalCurrent = hasRegionsInLimitGroup(offlinePlayer, group, plugin.getFileManager().getRegions(), exclude);
|
||||
int typeCurrent;
|
||||
if(type == RegionType.RENT) {
|
||||
typeCurrent = hasRegionsInLimitGroup(player, group, plugin.getFileManager().getRents(), exclude);
|
||||
typeCurrent = hasRegionsInLimitGroup(offlinePlayer, group, plugin.getFileManager().getRents(), exclude);
|
||||
} else {
|
||||
typeCurrent = hasRegionsInLimitGroup(player, group, plugin.getFileManager().getBuys(), exclude);
|
||||
typeCurrent = hasRegionsInLimitGroup(offlinePlayer, group, plugin.getFileManager().getBuys(), exclude);
|
||||
}
|
||||
if(totalLimit == -1) {
|
||||
totalLimit = Integer.MAX_VALUE;
|
||||
@ -1196,7 +1208,7 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
|
||||
// Get the highest number from the groups of the same category
|
||||
List<String> groupsCopy = new ArrayList<>(groups);
|
||||
for(String checkGroup : groupsCopy) {
|
||||
if(player.hasPermission("areashop.limits." + checkGroup) && this.matchesLimitGroup(checkGroup)) {
|
||||
if(plugin.hasPermission(offlinePlayer, "areashop.limits." + checkGroup) && this.matchesLimitGroup(checkGroup)) {
|
||||
if(limitGroupsOfSameCategory(group, checkGroup)) {
|
||||
groups.remove(checkGroup);
|
||||
int totalLimitOther = plugin.getConfig().getInt("limitGroups." + checkGroup + ".total");
|
||||
@ -1338,7 +1350,7 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
|
||||
* @param exclude Exclude this region from the count
|
||||
* @return The number of regions that the player has bought or rented matching the limit group (worlds and groups filters)
|
||||
*/
|
||||
public int hasRegionsInLimitGroup(Player player, String limitGroup, List<? extends GeneralRegion> regions, GeneralRegion exclude) {
|
||||
public int hasRegionsInLimitGroup(OfflinePlayer player, String limitGroup, List<? extends GeneralRegion> regions, GeneralRegion exclude) {
|
||||
int result = 0;
|
||||
for(GeneralRegion region : regions) {
|
||||
if(region.isOwner(player) && region.matchesLimitGroup(limitGroup) && (exclude == null || !exclude.getName().equals(region.getName()))) {
|
||||
|
@ -2,10 +2,10 @@ package me.wiefferink.areashop.regions;
|
||||
|
||||
import me.wiefferink.areashop.AreaShop;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
// TODO consider switching to saving lowercase regions
|
||||
@ -13,35 +13,86 @@ public class RegionGroup {
|
||||
|
||||
private AreaShop plugin;
|
||||
private String name;
|
||||
private Set<String> regions;
|
||||
private Set<String> autoRegions;
|
||||
private boolean autoDirty;
|
||||
private Set<String> worlds;
|
||||
|
||||
/**
|
||||
* Constructor, used when creating new groups or restoring them from groups.yml at server boot
|
||||
* Constructor, used when creating new groups or restoring them from groups.yml at server boot.
|
||||
* @param plugin The AreaShop plugin
|
||||
* @param name Name of the group, has to be unique
|
||||
*/
|
||||
public RegionGroup(AreaShop plugin, String name) {
|
||||
this.plugin = plugin;
|
||||
this.name = name;
|
||||
this.autoDirty = true;
|
||||
setSetting("name", name);
|
||||
// Delete duplicates
|
||||
List<String> members = getMembers();
|
||||
int previousCount = members.size();
|
||||
List<String> newMembers = new ArrayList<>();
|
||||
while(!members.isEmpty()) {
|
||||
String member = members.remove(0);
|
||||
// If the region has been deleted also clean it from the group
|
||||
if(plugin.getFileManager().getRegion(member) != null) {
|
||||
newMembers.add(member);
|
||||
}
|
||||
while(members.contains(member)) {
|
||||
members.remove(member);
|
||||
|
||||
// Load regions and worlds
|
||||
regions = new HashSet<>(getSettings().getStringList("regions"));
|
||||
worlds = new HashSet<>(getSettings().getStringList("worlds"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get automatically added regions.
|
||||
*/
|
||||
public Set<String> getAutoRegions() {
|
||||
if(autoDirty) {
|
||||
autoRegions = new HashSet<>();
|
||||
for(GeneralRegion region : plugin.getFileManager().getRegions()) {
|
||||
if(worlds.contains(region.getWorldName())) {
|
||||
autoRegions.add(region.getName());
|
||||
}
|
||||
}
|
||||
autoDirty = false;
|
||||
}
|
||||
if(newMembers.size() != previousCount) {
|
||||
setSetting("regions", newMembers);
|
||||
AreaShop.debug("group save required because of changed member size", newMembers);
|
||||
return autoRegions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark that automatically added regions should be regenerated.
|
||||
*/
|
||||
public void autoDirty() {
|
||||
autoDirty = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a world from which all regions should be added to the group.
|
||||
* @param world World from which all regions should be added
|
||||
* @return true if the region was not already added, otherwise false
|
||||
*/
|
||||
public boolean addWorld(String world) {
|
||||
if(worlds.add(world)) {
|
||||
setSetting("regionsFromWorlds", new ArrayList<>(worlds));
|
||||
saveRequired();
|
||||
autoDirty();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a member from the group.
|
||||
* @param world World to remove
|
||||
* @return true if the region was in the group before, otherwise false
|
||||
*/
|
||||
public boolean removeWorld(String world) {
|
||||
if(worlds.remove(world)) {
|
||||
setSetting("regionsFromWorlds", new ArrayList<>(worlds));
|
||||
saveRequired();
|
||||
autoDirty();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all worlds from which regions are added automatically.
|
||||
* @return A list with the names of all worlds (immutable)
|
||||
*/
|
||||
public Set<String> getWorlds() {
|
||||
return new HashSet<>(worlds);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -50,15 +101,12 @@ public class RegionGroup {
|
||||
* @return true if the region was not already added, otherwise false
|
||||
*/
|
||||
public boolean addMember(GeneralRegion region) {
|
||||
List<String> members = getMembers();
|
||||
if(members.contains(region.getName())) {
|
||||
return false;
|
||||
} else {
|
||||
members.add(region.getName());
|
||||
setSetting("regions", members);
|
||||
this.saveRequired();
|
||||
if(regions.add(region.getName())) {
|
||||
setSetting("regions", new ArrayList<>(regions));
|
||||
saveRequired();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -67,26 +115,30 @@ public class RegionGroup {
|
||||
* @return true if the region was in the group before, otherwise false
|
||||
*/
|
||||
public boolean removeMember(GeneralRegion region) {
|
||||
if(!isMember(region)) {
|
||||
return false;
|
||||
if(regions.remove(region.getName())) {
|
||||
setSetting("regions", new ArrayList<>(regions));
|
||||
saveRequired();
|
||||
return true;
|
||||
}
|
||||
|
||||
List<String> members = getMembers();
|
||||
members.remove(region.getName());
|
||||
setSetting("regions", members);
|
||||
this.saveRequired();
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all members of the group.
|
||||
* @return A list with the names of all members of the group
|
||||
* @return A list with the names of all members of the group (immutable)
|
||||
*/
|
||||
public List<String> getMembers() {
|
||||
if(getSettings() == null || getSettings().getStringList("regions") == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return getSettings().getStringList("regions");
|
||||
public Set<String> getMembers() {
|
||||
HashSet<String> result = new HashSet<>(regions);
|
||||
result.addAll(getAutoRegions());
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all manually added members of the group.
|
||||
* @return A list with the names of all members of the group (immutable)
|
||||
*/
|
||||
public Set<String> getManualMembers() {
|
||||
return new HashSet<>(regions);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -139,7 +191,12 @@ public class RegionGroup {
|
||||
* @return The ConfigurationSection with the settings of the group
|
||||
*/
|
||||
public ConfigurationSection getSettings() {
|
||||
return plugin.getFileManager().getGroupSettings(name);
|
||||
ConfigurationSection result = plugin.getFileManager().getGroupSettings(name);
|
||||
if(result != null) {
|
||||
return result;
|
||||
} else {
|
||||
return new YamlConfiguration();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -158,7 +158,7 @@ public class RentRegion extends GeneralRegion {
|
||||
case AreaShop.tagRawMoneyBackAmount:
|
||||
return getMoneyBackAmount();
|
||||
case AreaShop.tagMoneyBackPercentage:
|
||||
return getMoneyBackPercentage() % 1.0 == 0.0 ? (int)getMoneyBackPercentage() : getMoneyBackPercentage();
|
||||
return (getMoneyBackPercentage() % 1.0) == 0.0 ? (int)getMoneyBackPercentage() : getMoneyBackPercentage();
|
||||
case AreaShop.tagTimesExtended:
|
||||
return this.getTimesExtended();
|
||||
case AreaShop.tagMaxExtends:
|
||||
@ -290,17 +290,10 @@ public class RentRegion extends GeneralRegion {
|
||||
* Change the price of the region.
|
||||
* @param price The price of the region
|
||||
*/
|
||||
public void setPrice(double price) {
|
||||
public void setPrice(Double price) {
|
||||
setSetting("rent.price", price);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the price so that the price will be taken from a group or the default.yml file
|
||||
*/
|
||||
public void removePrice() {
|
||||
setSetting("rent.price", null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the duration of the rent.
|
||||
* @param duration The duration of the rent (as specified on the documentation pages)
|
||||
@ -353,6 +346,13 @@ public class RentRegion extends GeneralRegion {
|
||||
public boolean checkExpiration() {
|
||||
long now = Calendar.getInstance().getTimeInMillis();
|
||||
if(!isDeleted() && isRented() && now > getRentedUntil()) {
|
||||
// Extend rent if configured for that
|
||||
if(getBooleanSetting("rent.autoExtend")) {
|
||||
if(extend()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Send message to the player if online
|
||||
Player player = Bukkit.getPlayer(getRenter());
|
||||
if(unRent(false, null)) {
|
||||
@ -411,64 +411,83 @@ public class RentRegion extends GeneralRegion {
|
||||
warningsDoneUntil = sendUntil;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to extend the rent for the current owner, respecting all restrictions.
|
||||
* @return true if successful, otherwise false
|
||||
*/
|
||||
public boolean extend() {
|
||||
if(!isRented()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(getRenter());
|
||||
return offlinePlayer != null && rent(offlinePlayer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rent a region.
|
||||
* @param player The player that wants to rent the region
|
||||
* @param offlinePlayer The player that wants to rent the region
|
||||
* @return true if it succeeded and false if not
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public boolean rent(Player player) {
|
||||
public boolean rent(OfflinePlayer offlinePlayer) {
|
||||
if(plugin.getEconomy() == null) {
|
||||
message(player, "general-noEconomy");
|
||||
message(offlinePlayer, "general-noEconomy");
|
||||
return false;
|
||||
}
|
||||
//Check if the player has permission
|
||||
if(player.hasPermission("areashop.rent")) {
|
||||
if(plugin.hasPermission(offlinePlayer, "areashop.rent")) {
|
||||
if(getWorld() == null) {
|
||||
message(player, "general-noWorld");
|
||||
message(offlinePlayer, "general-noWorld");
|
||||
return false;
|
||||
}
|
||||
if(getRegion() == null) {
|
||||
message(player, "general-noRegion");
|
||||
message(offlinePlayer, "general-noRegion");
|
||||
return false;
|
||||
}
|
||||
boolean extend = false;
|
||||
if(getRenter() != null && player.getUniqueId().equals(getRenter())) {
|
||||
if(getRenter() != null && offlinePlayer.getUniqueId().equals(getRenter())) {
|
||||
extend = true;
|
||||
}
|
||||
// Check if the region is available for renting or if the player wants to extend the rent
|
||||
if(!isRented() || extend) {
|
||||
// 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()))) {
|
||||
message(player, "rent-restrictedToRegion");
|
||||
return false;
|
||||
}
|
||||
if(restrictedToWorld() && !player.getWorld().getName().equals(getWorldName())) {
|
||||
message(player, "rent-restrictedToWorld", player.getWorld().getName());
|
||||
return false;
|
||||
// These checks are only relevant for online players doing the renting/buying themselves
|
||||
Player player = offlinePlayer.getPlayer();
|
||||
if(player != null) {
|
||||
// Check if the players needs to be in the region for renting
|
||||
if(restrictedToRegion() && (!player.getWorld().getName().equals(getWorldName())
|
||||
|| !getRegion().contains(player.getLocation().getBlockX(), player.getLocation().getBlockY(), player.getLocation().getBlockZ()))) {
|
||||
message(offlinePlayer, "rent-restrictedToRegion");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the players needs to be in the world for renting
|
||||
if(restrictedToWorld() && !player.getWorld().getName().equals(getWorldName())) {
|
||||
message(offlinePlayer, "rent-restrictedToWorld", player.getWorld().getName());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check region limits if this is not extending
|
||||
if(!(extend && config.getBoolean("allowRegionExtendsWhenAboveLimits"))) {
|
||||
|
||||
LimitResult limitResult;
|
||||
if(extend) {
|
||||
limitResult = this.limitsAllow(RegionType.RENT, player, true);
|
||||
limitResult = this.limitsAllow(RegionType.RENT, offlinePlayer, true);
|
||||
} else {
|
||||
limitResult = this.limitsAllow(RegionType.RENT, player);
|
||||
limitResult = this.limitsAllow(RegionType.RENT, offlinePlayer);
|
||||
}
|
||||
AreaShop.debug("LimitResult: " + limitResult.toString());
|
||||
if(!limitResult.actionAllowed()) {
|
||||
if(limitResult.getLimitingFactor() == LimitType.TOTAL) {
|
||||
message(player, "total-maximum", limitResult.getMaximum(), limitResult.getCurrent(), limitResult.getLimitingGroup());
|
||||
message(offlinePlayer, "total-maximum", limitResult.getMaximum(), limitResult.getCurrent(), limitResult.getLimitingGroup());
|
||||
return false;
|
||||
}
|
||||
if(limitResult.getLimitingFactor() == LimitType.RENTS) {
|
||||
message(player, "rent-maximum", limitResult.getMaximum(), limitResult.getCurrent(), limitResult.getLimitingGroup());
|
||||
message(offlinePlayer, "rent-maximum", limitResult.getMaximum(), limitResult.getCurrent(), limitResult.getLimitingGroup());
|
||||
return false;
|
||||
}
|
||||
if(limitResult.getLimitingFactor() == LimitType.EXTEND) {
|
||||
message(player, "rent-maximumExtend", limitResult.getMaximum(), limitResult.getCurrent() + 1, limitResult.getLimitingGroup());
|
||||
message(offlinePlayer, "rent-maximumExtend", limitResult.getMaximum(), limitResult.getCurrent() + 1, limitResult.getLimitingGroup());
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
@ -476,9 +495,9 @@ public class RentRegion extends GeneralRegion {
|
||||
}
|
||||
|
||||
// Check if the player can still extend this rent
|
||||
if(extend && !player.hasPermission("areashop.rentextendbypass")) {
|
||||
if(extend && !plugin.hasPermission(offlinePlayer, "areashop.rentextendbypass")) {
|
||||
if(getMaxExtends() >= 0 && getTimesExtended() >= getMaxExtends()) {
|
||||
message(player, "rent-maxExtends");
|
||||
message(offlinePlayer, "rent-maxExtends");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -493,12 +512,12 @@ public class RentRegion extends GeneralRegion {
|
||||
timeRented = getRentedUntil() - timeNow;
|
||||
}
|
||||
if((timeRented + getDuration()) > (maxRentTime)
|
||||
&& !player.hasPermission("areashop.renttimebypass")
|
||||
&& !plugin.hasPermission(offlinePlayer, "areashop.renttimebypass")
|
||||
&& maxRentTime != -1) {
|
||||
// Extend to the maximum instead of adding a full period
|
||||
if(getBooleanSetting("rent.extendToFullWhenAboveMaxRentTime")) {
|
||||
if(timeRented >= maxRentTime) {
|
||||
message(player, "rent-alreadyAtFull");
|
||||
message(offlinePlayer, "rent-alreadyAtFull");
|
||||
return false;
|
||||
} else {
|
||||
long toRentPart = maxRentTime - timeRented;
|
||||
@ -506,25 +525,25 @@ public class RentRegion extends GeneralRegion {
|
||||
price = ((double)toRentPart) / getDuration() * price;
|
||||
}
|
||||
} else {
|
||||
message(player, "rent-maxRentTime");
|
||||
message(offlinePlayer, "rent-maxRentTime");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(plugin.getEconomy().has(player, getWorldName(), price)) {
|
||||
if(plugin.getEconomy().has(offlinePlayer, getWorldName(), price)) {
|
||||
// Broadcast and check event
|
||||
RentingRegionEvent event = new RentingRegionEvent(this, player, extend);
|
||||
RentingRegionEvent event = new RentingRegionEvent(this, offlinePlayer, extend);
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
if(event.isCancelled()) {
|
||||
message(player, "general-cancelled", event.getReason());
|
||||
message(offlinePlayer, "general-cancelled", event.getReason());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Substract the money from the players balance
|
||||
EconomyResponse r = plugin.getEconomy().withdrawPlayer(player, getWorldName(), price);
|
||||
EconomyResponse r = plugin.getEconomy().withdrawPlayer(offlinePlayer, getWorldName(), price);
|
||||
if(!r.transactionSuccess()) {
|
||||
message(player, "rent-payError");
|
||||
AreaShop.debug("Something went wrong with getting money from " + player.getName() + " while renting " + getName() + ": " + r.errorMessage);
|
||||
message(offlinePlayer, "rent-payError");
|
||||
AreaShop.debug("Something went wrong with getting money from " + offlinePlayer.getName() + " while renting " + getName() + ": " + r.errorMessage);
|
||||
return false;
|
||||
}
|
||||
// Optionally give money to the landlord
|
||||
@ -540,7 +559,7 @@ public class RentRegion extends GeneralRegion {
|
||||
r = plugin.getEconomy().depositPlayer(landlordName, getWorldName(), price);
|
||||
}
|
||||
if(r == null || !r.transactionSuccess()) {
|
||||
AreaShop.warn("Something went wrong with paying '" + landlordName + "' " + Utils.formatCurrency(price) + " for his rent of region " + getName() + " to " + player.getName());
|
||||
AreaShop.warn("Something went wrong with paying '" + landlordName + "' " + Utils.formatCurrency(price) + " for his rent of region " + getName() + " to " + offlinePlayer.getName());
|
||||
}
|
||||
}
|
||||
|
||||
@ -564,7 +583,7 @@ public class RentRegion extends GeneralRegion {
|
||||
|
||||
// Add values to the rent and send it to FileManager
|
||||
setRentedUntil(calendar.getTimeInMillis());
|
||||
setRenter(player.getUniqueId());
|
||||
setRenter(offlinePlayer.getUniqueId());
|
||||
updateLastActiveTime();
|
||||
|
||||
// Fire schematic event and updated times extended
|
||||
@ -580,11 +599,11 @@ public class RentRegion extends GeneralRegion {
|
||||
|
||||
// Send message to the player
|
||||
if(extendToMax) {
|
||||
message(player, "rent-extendedToMax");
|
||||
message(offlinePlayer, "rent-extendedToMax");
|
||||
} else if(extend) {
|
||||
message(player, "rent-extended");
|
||||
message(offlinePlayer, "rent-extended");
|
||||
} else {
|
||||
message(player, "rent-rented");
|
||||
message(offlinePlayer, "rent-rented");
|
||||
}
|
||||
if(!extend) {
|
||||
// Run commands
|
||||
@ -597,16 +616,16 @@ public class RentRegion extends GeneralRegion {
|
||||
} else {
|
||||
// Player has not enough money
|
||||
if(extend) {
|
||||
message(player, "rent-lowMoneyExtend", Utils.formatCurrency(plugin.getEconomy().getBalance(player, getWorldName())));
|
||||
message(offlinePlayer, "rent-lowMoneyExtend", Utils.formatCurrency(plugin.getEconomy().getBalance(offlinePlayer, getWorldName())));
|
||||
} else {
|
||||
message(player, "rent-lowMoneyRent", Utils.formatCurrency(plugin.getEconomy().getBalance(player, getWorldName())));
|
||||
message(offlinePlayer, "rent-lowMoneyRent", Utils.formatCurrency(plugin.getEconomy().getBalance(offlinePlayer, getWorldName())));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
message(player, "rent-someoneElse");
|
||||
message(offlinePlayer, "rent-someoneElse");
|
||||
}
|
||||
} else {
|
||||
message(player, "rent-noPermission");
|
||||
message(offlinePlayer, "rent-noPermission");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -104,6 +104,8 @@ public class Analytics {
|
||||
}
|
||||
});
|
||||
|
||||
// TODO track rent/buy/unrent/sell/resell actions (so that it can be reported per collection interval)
|
||||
|
||||
AreaShop.debug("Started bstats.org statistics service");
|
||||
} catch(Exception e) {
|
||||
AreaShop.debug("Could not start bstats.org statistics service");
|
||||
|
@ -108,6 +108,7 @@ general:
|
||||
flagProfile:
|
||||
ALL: # Flags that should always be applied
|
||||
priority: 10
|
||||
owners: ''
|
||||
members: ''
|
||||
interact: 'deny g:non_members' # Only allow region members/owners to use things in the region (chests, furnace, animals, etc.)
|
||||
use: 'deny g:non_members'
|
||||
@ -196,6 +197,8 @@ rent:
|
||||
price: 1000
|
||||
# The default duration of a rental region, you can find all time indicators in config.yml below the RENTING header.
|
||||
duration: '1 day'
|
||||
# Automatically extend the rental when it is running out (if the player meets the criteria)
|
||||
autoExtend: false
|
||||
# The percentage of the rent price you get back if you unrent the region (only the time that is unused is given back).
|
||||
# (variables, mathematical expressions and JavaScript can be used)
|
||||
moneyBack: 100
|
||||
|
@ -98,6 +98,7 @@ help-delFriend: "%lang:helpCommand|/as delfriend|% Delete a friend from a region
|
||||
help-linksigns: "%lang:helpCommand|/as linksigns|% Use bulk sign linking mode."
|
||||
help-stack: "%lang:helpCommand|/as stack|% Create multiple regions and add them."
|
||||
help-setlandlord: "%lang:helpCommand|/as setlandlord|% Set the landlord of a region."
|
||||
help-import: "%lang:helpCommand|/as import|% Import region from RegionForSale.%"
|
||||
|
||||
rent-help: "/as rent [region], the region you stand in will be used if not specified."
|
||||
rent-noPermission: "You don't have permission to rent a region."
|
||||
@ -538,6 +539,30 @@ message-help: "/as message <player> <message...>"
|
||||
message-noPermission: "You do not have permission to send AreaShop messages."
|
||||
message-notOnline: "%0% is not online."
|
||||
|
||||
import-help: "/as import RegionForSale"
|
||||
import-wrongSource: "Specify from where you want to import data, options: RegionForSale."
|
||||
import-noPluginFolder: "Could not find the %0% folder, are you sure you are importing from the correct source?"
|
||||
import-noWorldsFolder: "There is no 'plugins/RegionForSale/worlds' folder, therefore nothing could be imported."
|
||||
import-start: "Starting import of RegionForSale data:"
|
||||
import-doWorld: "[darkgreen][bold]► World %0%:"
|
||||
import-noBukkitWorld: "[red]Could not find world in Bukkit."
|
||||
import-noRegionManager: "[red]Could not get RegionManager from WorldGuard, are regions enabled in this world?"
|
||||
import-noRegions: "[red]No regions.yml file found."
|
||||
import-loadRegionsFailed: "[red]Could not load regions.yml at: %0%"
|
||||
import-invalidRegionSection: "[red]Invalid section in regions.yml: %0%."
|
||||
import-noWorldGuardRegion: "[red]WorldGuard region not found: %0%."
|
||||
import-noWorldGuardRegionParent: "[red]WorldGuard region for parent region not found: %0%."
|
||||
import-buyAndRent: "[gold]%0% can be bought and rented, only adding as buy in AreaShop (cannot be both)."
|
||||
import-noBuyAndNoRent: "[red]%0% cannot be bought and cannot be rented, skipping import."
|
||||
import-imported: "[green]%lang:tRegion|%0%|% imported."
|
||||
import-loadWorldConfigFailed: "[red]Loading world-specific config.yml failed: %0%."
|
||||
import-improperParentRegion: "[red]Parent region %0% does not have readable settings."
|
||||
import-alreadyAdded: "[red]Region '%0%' has already been added."
|
||||
import-alreadyAddedOtherWorld: "[red]Region '%0%' has already been added in world %1%, regions in different worlds cannot have the same name in AreaShop."
|
||||
import-invalidSignLocation: "[red]Failed to import a sign of region '%0%', invalid location: '%1%'."
|
||||
import-signAlreadyAdded: "[red]Skipped adding sign at location '%1%' to region '%0%', it is already added to region '%2%'."
|
||||
import-moneyBackFailed: "[red]Failed to parse buy price '%0%' and sell price '%1%' to set the money back percentage."
|
||||
|
||||
confirm-rent:
|
||||
- "%lang:prefix%Are you sure you want to rent %lang:tRegion|%0%|%?[break]"
|
||||
- "[darkgreen][bold]►[reset] %lang:button|Click to rent %0%|%"
|
||||
|
@ -57,6 +57,7 @@ permissions:
|
||||
areashop.setlandlord: true
|
||||
areashop.linksigns: true
|
||||
areashop.message: true
|
||||
areashop.import: true
|
||||
areashop.landlord.*:
|
||||
description: Give access to all landlord features
|
||||
children:
|
||||
@ -263,4 +264,7 @@ permissions:
|
||||
default: op
|
||||
areashop.message:
|
||||
description: Allows you to send AreaShop messages to players
|
||||
default: op
|
||||
default: op
|
||||
areashop.import:
|
||||
description: Allows importing regions from other plugins
|
||||
default: op
|
||||
|
@ -1,6 +1,11 @@
|
||||
package me.wiefferink.areashop.interfaces;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
@ -36,9 +41,25 @@ public class RegionAccessSet {
|
||||
|
||||
/**
|
||||
* Get the groups.
|
||||
* @return Set with groups added to this RegionAccessSet
|
||||
* @return Set with groups added to this RegionAccessSet.
|
||||
*/
|
||||
public Set<String> getGroupNames() {
|
||||
return groupNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get this access set as a list of player UUIDs.
|
||||
* @return List of player UUIDs, first players already added by UUID, then players added by name, groups are not in the list
|
||||
*/
|
||||
public List<UUID> asUniqueIdList() {
|
||||
List<UUID> result = new ArrayList<>();
|
||||
result.addAll(playerUniqueIds);
|
||||
for(String playerName : playerNames) {
|
||||
OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(playerName);
|
||||
if(offlinePlayer != null && offlinePlayer.getUniqueId() != null) {
|
||||
result.add(offlinePlayer.getUniqueId());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -28,14 +28,14 @@ public abstract class WorldGuardInterface {
|
||||
/**
|
||||
* Parse an owner(s) string and set the players as owner of the WorldGuard region (set by UUID or name depending on implementation).
|
||||
* @param region The WorldGuard region to set the owners of
|
||||
* @param regionAccessSet The owner(s) string to set
|
||||
* @param regionAccessSet The owner(s) to set
|
||||
*/
|
||||
public abstract void setOwners(ProtectedRegion region, RegionAccessSet regionAccessSet);
|
||||
|
||||
/**
|
||||
* Parse a member(s) string and set the players as member of the WorldGuard region (set by UUID or name depending on implementation).
|
||||
* @param region The WorldGuard region to set the members of
|
||||
* @param regionAccessSet The member(s) string to set
|
||||
* @param regionAccessSet The member(s) to set
|
||||
*/
|
||||
public abstract void setMembers(ProtectedRegion region, RegionAccessSet regionAccessSet);
|
||||
|
||||
@ -55,6 +55,20 @@ public abstract class WorldGuardInterface {
|
||||
*/
|
||||
public abstract boolean containsOwner(ProtectedRegion region, UUID player);
|
||||
|
||||
/**
|
||||
* Get the members of a region.
|
||||
* @param region to get the members of
|
||||
* @return RegionAccessSet with all members (by uuid and name) and groups of the given region
|
||||
*/
|
||||
public abstract RegionAccessSet getMembers(ProtectedRegion region);
|
||||
|
||||
/**
|
||||
* Get the owners of a region.
|
||||
* @param region to get the owners of
|
||||
* @return RegionAccessSet with all owners (by uuid and name) and groups of the given region
|
||||
*/
|
||||
public abstract RegionAccessSet getOwners(ProtectedRegion region);
|
||||
|
||||
// New flag system was introcuded in version 6.1.3, requiring different flag parsing
|
||||
/**
|
||||
* Get a flag from the name of a flag.
|
||||
@ -78,4 +92,4 @@ public abstract class WorldGuardInterface {
|
||||
* @return The RegionGroup denoted by the input
|
||||
*/
|
||||
public abstract RegionGroup parseFlagGroupInput(RegionGroupFlag flag, String input) throws InvalidFlagFormat;
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ import com.sk89q.worldedit.session.ClipboardHolder;
|
||||
import com.sk89q.worldedit.util.io.Closer;
|
||||
import com.sk89q.worldedit.world.registry.WorldData;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
import com.sk89q.worldguard.protection.regions.RegionType;
|
||||
import me.wiefferink.areashop.interfaces.AreaShopInterface;
|
||||
import me.wiefferink.areashop.interfaces.GeneralRegionInterface;
|
||||
import me.wiefferink.areashop.interfaces.WorldEditInterface;
|
||||
@ -80,19 +81,22 @@ public class WorldEditHandler6 extends WorldEditInterface {
|
||||
BlockTransformExtent extent = new BlockTransformExtent(clipboardHolder.getClipboard(), clipboardHolder.getTransform(), editSession.getWorld().getWorldData().getBlockRegistry());
|
||||
ForwardExtentCopy copy = new ForwardExtentCopy(extent, clipboard.getRegion(), clipboard.getOrigin(), editSession, origin);
|
||||
copy.setTransform(clipboardHolder.getTransform());
|
||||
// Mask to region (for polygon regions)
|
||||
copy.setSourceMask(new Mask() {
|
||||
@Override
|
||||
public boolean test(Vector vector) {
|
||||
return region.contains(vector);
|
||||
}
|
||||
// Mask to region (for polygon and other weird shaped regions)
|
||||
// TODO make this more efficient (especially for polygon regions)
|
||||
if(region.getType() != RegionType.CUBOID) {
|
||||
copy.setSourceMask(new Mask() {
|
||||
@Override
|
||||
public boolean test(Vector vector) {
|
||||
return region.contains(vector);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Mask2D toMask2D() {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
@Nullable
|
||||
@Override
|
||||
public Mask2D toMask2D() {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
Operations.completeLegacy(copy);
|
||||
} catch(MaxChangedBlocksException e) {
|
||||
pluginInterface.getLogger().warning("Exeeded the block limit while restoring schematic of " + regionInterface.getName() + ", limit in exception: " + e.getBlockLimit() + ", limit passed by AreaShop: " + pluginInterface.getConfig().getInt("maximumBlocks"));
|
||||
|
@ -34,4 +34,4 @@
|
||||
<type>jar</type>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
</project>
|
||||
|
@ -54,6 +54,22 @@ public class WorldGuardHandler5 extends WorldGuardInterface {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegionAccessSet getMembers(ProtectedRegion region) {
|
||||
RegionAccessSet result = new RegionAccessSet();
|
||||
result.getGroupNames().addAll(region.getMembers().getGroups());
|
||||
result.getPlayerNames().addAll(region.getMembers().getPlayers());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegionAccessSet getOwners(ProtectedRegion region) {
|
||||
RegionAccessSet result = new RegionAccessSet();
|
||||
result.getGroupNames().addAll(region.getOwners().getGroups());
|
||||
result.getPlayerNames().addAll(region.getOwners().getPlayers());
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a DefaultDomain from a RegionAccessSet.
|
||||
* @param regionAccessSet RegionAccessSet to read
|
||||
|
@ -52,6 +52,24 @@ public class WorldGuardHandler6 extends WorldGuardInterface {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegionAccessSet getMembers(ProtectedRegion region) {
|
||||
RegionAccessSet result = new RegionAccessSet();
|
||||
result.getGroupNames().addAll(region.getMembers().getGroups());
|
||||
result.getPlayerNames().addAll(region.getMembers().getPlayers());
|
||||
result.getPlayerUniqueIds().addAll(region.getMembers().getUniqueIds());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegionAccessSet getOwners(ProtectedRegion region) {
|
||||
RegionAccessSet result = new RegionAccessSet();
|
||||
result.getGroupNames().addAll(region.getOwners().getGroups());
|
||||
result.getPlayerNames().addAll(region.getOwners().getPlayers());
|
||||
result.getPlayerUniqueIds().addAll(region.getOwners().getUniqueIds());
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a DefaultDomain from a RegionAccessSet.
|
||||
* @param regionAccessSet RegionAccessSet to read
|
||||
|
Loading…
Reference in New Issue
Block a user