Make config more like ARM
This commit is contained in:
1 parent
2c5928a3a0
commit
2fa49f9490
11 files changed
+354
-91
No files matched your search
@@ -27,6 +27,7 @@ import me.wiefferink.areashop.modules.BukkitModule;
|
||||
import me.wiefferink.areashop.modules.DependencyModule;
|
||||
import me.wiefferink.areashop.modules.PlatformModule;
|
||||
import me.wiefferink.areashop.platform.adapter.PlatformAdapter;
|
||||
import me.wiefferink.areashop.regions.GeneralRegion;
|
||||
import me.wiefferink.areashop.regions.RentRegion;
|
||||
import me.wiefferink.areashop.services.ServiceManager;
|
||||
import me.wiefferink.areashop.tools.GithubUpdateCheck;
|
||||
@@ -64,9 +65,11 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.logging.Level;
|
||||
@@ -102,6 +105,15 @@ public final class AreaShop extends JavaPlugin implements AreaShopApi {
|
||||
|
||||
private final ServiceManager serviceManager = new ServiceManager();
|
||||
|
||||
// Cached LuckPerms prefix colors so sign updates never block on storage
|
||||
private static final long PREFIX_COLOR_CACHE_MILLIS = TimeUnit.MINUTES.toMillis(5);
|
||||
|
||||
private record CachedPrefixColor(String color, long loadedAt) {
|
||||
}
|
||||
|
||||
private final Map<UUID, CachedPrefixColor> prefixColorCache = new ConcurrentHashMap<>();
|
||||
private final Set<UUID> prefixColorLoading = ConcurrentHashMap.newKeySet();
|
||||
|
||||
// Folders and file names
|
||||
public static final String languageFolder = "lang";
|
||||
public static final String schematicFolder = "schem";
|
||||
@@ -130,6 +142,7 @@ public final class AreaShop extends JavaPlugin implements AreaShopApi {
|
||||
public static final String tagPrice = "price";
|
||||
public static final String tagRawPrice = "rawprice";
|
||||
public static final String tagDuration = "duration";
|
||||
public static final String tagDurationShort = "durationshort";
|
||||
public static final String tagRentedUntil = "until";
|
||||
public static final String tagRentedUntilShort = "untilshort";
|
||||
public static final String tagWidth = "width"; // x-axis
|
||||
@@ -580,15 +593,18 @@ public final class AreaShop extends JavaPlugin implements AreaShopApi {
|
||||
|
||||
}
|
||||
|
||||
// Check if jubilee mode is enabled: only the first rent is charged and gets the maximum
|
||||
// rent time, extending/buying/reselling is free and there are no Diamond paybacks.
|
||||
// Check if jubilee mode is enabled: only the first rent is charged and gets the
|
||||
// maximum
|
||||
// rent time, extending/buying/reselling is free and there are no Diamond
|
||||
// paybacks.
|
||||
public boolean isJubilee() {
|
||||
|
||||
return getConfig().getBoolean("jubilee");
|
||||
|
||||
}
|
||||
|
||||
// Extend all currently rented regions to the maximum rent time, jubilee mode grants
|
||||
// Extend all currently rented regions to the maximum rent time, jubilee mode
|
||||
// grants
|
||||
// every renter the maximum duration.
|
||||
private void applyJubileeToRents() {
|
||||
|
||||
@@ -932,14 +948,10 @@ public final class AreaShop extends JavaPlugin implements AreaShopApi {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the color and formatting codes a player's name inherits from their
|
||||
* LuckPerms prefix.
|
||||
*
|
||||
* @param player UUID of the player, may be null
|
||||
* @return Legacy color codes (&-format) active at the end of the player's
|
||||
* prefix, empty string if unavailable
|
||||
*/
|
||||
// Get the color code a player's name inherits from their LuckPerms prefix,
|
||||
// in &-format, or an empty string if unavailable. Never blocks the calling
|
||||
// thread: uncached users are loaded asynchronously and the result is cached,
|
||||
// affected signs are repainted once the color is known.
|
||||
public String getPlayerPrefixColors(UUID player) {
|
||||
|
||||
if (player == null) {
|
||||
@@ -957,27 +969,79 @@ public final class AreaShop extends JavaPlugin implements AreaShopApi {
|
||||
|
||||
UserManager userManager = permissionProvider.getUserManager();
|
||||
User user = userManager.getUser(player);
|
||||
boolean loaded = user != null;
|
||||
if (user == null) {
|
||||
if (user != null) {
|
||||
|
||||
// Not cached, load it from storage (blocking)
|
||||
user = userManager.loadUser(player).join();
|
||||
String color = extractPrefixColor(user.getCachedData().getMetaData().getPrefix());
|
||||
prefixColorCache.put(player, new CachedPrefixColor(color, System.currentTimeMillis()));
|
||||
return color;
|
||||
|
||||
}
|
||||
|
||||
if (user == null) {
|
||||
CachedPrefixColor cached = prefixColorCache.get(player);
|
||||
boolean fresh = cached != null && (System.currentTimeMillis() - cached.loadedAt()) < PREFIX_COLOR_CACHE_MILLIS;
|
||||
if (!fresh && prefixColorLoading.add(player)) {
|
||||
|
||||
return "";
|
||||
// Not cached, load it from storage asynchronously and repaint the
|
||||
// signs of the regions the player owns when the color changed
|
||||
userManager.loadUser(player).whenComplete((loadedUser, error) -> {
|
||||
|
||||
try {
|
||||
|
||||
if (error != null || loadedUser == null) {
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
String color = extractPrefixColor(loadedUser.getCachedData().getMetaData().getPrefix());
|
||||
CachedPrefixColor previous = prefixColorCache.put(player,
|
||||
new CachedPrefixColor(color, System.currentTimeMillis()));
|
||||
userManager.cleanupUser(loadedUser);
|
||||
if ((previous == null || !previous.color().equals(color)) && isEnabled()) {
|
||||
|
||||
getServer().getScheduler().runTask(this, () -> updateRegionsOfPlayer(player));
|
||||
|
||||
}
|
||||
|
||||
} finally {
|
||||
|
||||
prefixColorLoading.remove(player);
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
String prefix = user.getCachedData().getMetaData().getPrefix();
|
||||
if (!loaded) {
|
||||
// Serve the cached color (possibly stale) until the async load finishes
|
||||
return cached == null ? "" : cached.color();
|
||||
|
||||
userManager.cleanupUser(user);
|
||||
}
|
||||
|
||||
// Repaint the signs and flags of all regions owned by the given player
|
||||
private void updateRegionsOfPlayer(UUID player) {
|
||||
|
||||
if (fileManager == null) {
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
for (GeneralRegion region : fileManager.getRegionsRef()) {
|
||||
|
||||
if (player.equals(region.getOwner())) {
|
||||
|
||||
region.update();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Extract the color a name inherits from a prefix as an &-code, or ""
|
||||
private static String extractPrefixColor(String prefix) {
|
||||
|
||||
if (prefix == null) {
|
||||
|
||||
return "";
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
package me.wiefferink.areashop.commands;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import me.wiefferink.areashop.AreaShop;
|
||||
import me.wiefferink.areashop.commands.util.AreaShopCommandException;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
|
||||
import me.wiefferink.areashop.commands.util.RegionParseUtil;
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.regions.RentRegion;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bean.CommandProperties;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.parser.flag.CommandFlag;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
@Singleton
|
||||
public class PayRentCommand extends AreashopCommandBean {
|
||||
|
||||
private final AreaShop plugin;
|
||||
private final CommandFlag<RentRegion> rentRegionFlag;
|
||||
|
||||
@Inject
|
||||
public PayRentCommand(@Nonnull AreaShop plugin, @Nonnull IFileManager fileManager) {
|
||||
|
||||
this.plugin = plugin;
|
||||
this.rentRegionFlag = RegionParseUtil.createDefaultRent(fileManager);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringDescription() {
|
||||
|
||||
return "Allows you to pay the rent of a region, your own or someone else's";
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpKey(CommandSender target) {
|
||||
|
||||
if (target.hasPermission("areashop.payrent")) {
|
||||
|
||||
return "help-payrent";
|
||||
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nonnull CommandProperties properties() {
|
||||
|
||||
return CommandProperties.of("payrent");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nonnull Command.Builder<? extends CommandSender> configureCommand(
|
||||
@Nonnull Command.Builder<CommandSender> builder)
|
||||
{
|
||||
|
||||
return builder.literal("payrent").flag(this.rentRegionFlag).senderType(Player.class)
|
||||
.handler(this::handleCommand);
|
||||
|
||||
}
|
||||
|
||||
private void handleCommand(@Nonnull CommandContext<Player> context) {
|
||||
|
||||
if (!context.hasPermission("areashop.payrent")) {
|
||||
|
||||
throw new AreaShopCommandException("payrent-noPermission");
|
||||
|
||||
}
|
||||
|
||||
RentRegion region = RegionParseUtil.getOrParseRentRegion(context, this.rentRegionFlag);
|
||||
if (!region.isRented()) {
|
||||
|
||||
throw new AreaShopCommandException("payrent-notRented", region.getName());
|
||||
|
||||
}
|
||||
|
||||
// During the jubilee only the first rent is ever charged, extends are
|
||||
// free and automatic, so there is no rent to pay
|
||||
if (plugin.isJubilee()) {
|
||||
|
||||
throw new AreaShopCommandException("payrent-jubilee", region.getName());
|
||||
|
||||
}
|
||||
|
||||
Player payer = context.sender();
|
||||
if (payer.getUniqueId().equals(region.getRenter())) {
|
||||
|
||||
region.rent(payer);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
region.rent(Bukkit.getOfflinePlayer(region.getRenter()), payer);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -25,6 +25,7 @@ import me.wiefferink.areashop.commands.InfoRegionCommand;
|
||||
import me.wiefferink.areashop.commands.LinkSignsCommand;
|
||||
import me.wiefferink.areashop.commands.MeCommand;
|
||||
import me.wiefferink.areashop.commands.MessageCommand;
|
||||
import me.wiefferink.areashop.commands.PayRentCommand;
|
||||
import me.wiefferink.areashop.commands.QuickBuyCommand;
|
||||
import me.wiefferink.areashop.commands.QuickDeleteCommand;
|
||||
import me.wiefferink.areashop.commands.QuickRentCommand;
|
||||
@@ -73,12 +74,12 @@ public class AreashopCommands {
|
||||
DelSignCommand.class, FindCommand.class, GroupAddCommand.class, GroupDelCommand.class,
|
||||
GroupInfoCommand.class, GroupListCommand.class, HelpCommand.class, InfoCommand.class, InfoBaseCommand.class,
|
||||
InfoPlayerCommand.class, InfoRegionCommand.class, LinkSignsCommand.class, MeCommand.class,
|
||||
MessageCommand.class, QuickBuyCommand.class, QuickDeleteCommand.class, QuickRentCommand.class,
|
||||
ReloadCommand.class, RentCommand.class, ResellCommand.class, SchematicEventCommand.class, SellCommand.class,
|
||||
SetDurationCommand.class, SetLandlordCommand.class, SetOwnerCommand.class, SetPriceCommand.class,
|
||||
SetRestoreCommand.class, SetTeleportCommand.class, SetTransferCommand.class, StackCommand.class,
|
||||
StopResellCommand.class, TeleportCommand.class, ToggleHomeCommand.class, TransferCommand.class,
|
||||
UnrentCommand.class);
|
||||
MessageCommand.class, PayRentCommand.class, QuickBuyCommand.class, QuickDeleteCommand.class,
|
||||
QuickRentCommand.class, ReloadCommand.class, RentCommand.class, ResellCommand.class,
|
||||
SchematicEventCommand.class, SellCommand.class, SetDurationCommand.class, SetLandlordCommand.class,
|
||||
SetOwnerCommand.class, SetPriceCommand.class, SetRestoreCommand.class, SetTeleportCommand.class,
|
||||
SetTransferCommand.class, StackCommand.class, StopResellCommand.class, TeleportCommand.class,
|
||||
ToggleHomeCommand.class, TransferCommand.class, UnrentCommand.class);
|
||||
|
||||
private final MessageBridge messageBridge;
|
||||
|
||||
|
||||
@@ -510,7 +510,8 @@ public class BuyRegion extends GeneralRegion {
|
||||
|
||||
}
|
||||
|
||||
// Buying and reselling are free during the jubilee, otherwise the price is charged
|
||||
// Buying and reselling are free during the jubilee, otherwise the price is
|
||||
// charged
|
||||
boolean jubilee = plugin.isJubilee();
|
||||
UUID oldOwner = getBuyer();
|
||||
if (isResell && oldOwner != null) {
|
||||
@@ -548,8 +549,8 @@ public class BuyRegion extends GeneralRegion {
|
||||
|
||||
try {
|
||||
|
||||
economy.playerPayPlayer(payingPlayer.getUniqueId(), oldOwner,
|
||||
Utils.diamondsToShards(resellPrice), "AreaShop resell: " + getName(), null);
|
||||
economy.playerPayPlayer(payingPlayer.getUniqueId(), oldOwner, Utils.diamondsToShards(resellPrice),
|
||||
"AreaShop resell: " + getName(), null);
|
||||
|
||||
} catch (DiamondBankException.InsufficientFundsException e) {
|
||||
|
||||
|
||||
@@ -253,6 +253,7 @@ public class RentRegion extends GeneralRegion {
|
||||
case AreaShop.tagPrice -> Message.fromString(getFormattedPrice());
|
||||
case AreaShop.tagRawPrice -> getPrice();
|
||||
case AreaShop.tagDuration -> getDurationString();
|
||||
case AreaShop.tagDurationShort -> Utils.millisToCompactFormat(getDuration());
|
||||
case AreaShop.tagPlayerName -> getPlayerName();
|
||||
case AreaShop.tagPlayerColor -> Message.fromString(plugin.getPlayerPrefixColors(getRenter()));
|
||||
case AreaShop.tagPlayerUUID -> getRenter();
|
||||
@@ -641,12 +642,26 @@ public class RentRegion extends GeneralRegion {
|
||||
|
||||
/**
|
||||
* Rent a region.
|
||||
*
|
||||
*
|
||||
* @param offlinePlayer The player that wants to rent the region
|
||||
* @return true if it succeeded and false if not
|
||||
*/
|
||||
public boolean rent(OfflinePlayer offlinePlayer) {
|
||||
|
||||
return rent(offlinePlayer, null);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Rent a region, optionally charged to another player.
|
||||
*
|
||||
* @param offlinePlayer The player the rent is for
|
||||
* @param payer The online player paying the Diamonds, or null to charge
|
||||
* the renter themselves
|
||||
* @return true if it succeeded and false if not
|
||||
*/
|
||||
public boolean rent(OfflinePlayer offlinePlayer, Player payer) {
|
||||
|
||||
if (economy == null) {
|
||||
|
||||
message(offlinePlayer, "general-noEconomy");
|
||||
@@ -818,14 +833,16 @@ public class RentRegion extends GeneralRegion {
|
||||
|
||||
}
|
||||
|
||||
// During the jubilee only the first rent is charged, otherwise every rent and extend
|
||||
// costs the (possibly prorated) price. Payment is taken from the renter's physical
|
||||
// diamonds through DiamondBank-OG, so the renter must be online.
|
||||
// During the jubilee only the first rent is charged, otherwise every rent and
|
||||
// extend
|
||||
// costs the (possibly prorated) price. Payment is taken from the paying
|
||||
// player's physical
|
||||
// diamonds through DiamondBank-OG, so the payer must be online.
|
||||
boolean charged = price > 0 && (!extend || !plugin.isJubilee());
|
||||
long priceShards = 0;
|
||||
if (charged) {
|
||||
|
||||
Player payingPlayer = offlinePlayer.getPlayer();
|
||||
Player payingPlayer = payer != null ? payer : offlinePlayer.getPlayer();
|
||||
if (payingPlayer == null) {
|
||||
|
||||
message(offlinePlayer, "rent-payError");
|
||||
@@ -839,7 +856,7 @@ public class RentRegion extends GeneralRegion {
|
||||
long balance = economy.getTotalShards(payingPlayer.getUniqueId());
|
||||
if (balance < priceShards) {
|
||||
|
||||
message(offlinePlayer, extend ? "rent-lowMoneyExtend" : "rent-lowMoneyRent",
|
||||
message(payingPlayer, extend ? "rent-lowMoneyExtend" : "rent-lowMoneyRent",
|
||||
economy.shardsToDiamonds(balance));
|
||||
return false;
|
||||
|
||||
@@ -847,7 +864,7 @@ public class RentRegion extends GeneralRegion {
|
||||
|
||||
} catch (DiamondBankException e) {
|
||||
|
||||
message(offlinePlayer, "rent-payError");
|
||||
message(payingPlayer, "rent-payError");
|
||||
return false;
|
||||
|
||||
}
|
||||
@@ -864,10 +881,10 @@ public class RentRegion extends GeneralRegion {
|
||||
|
||||
}
|
||||
|
||||
// Subtract the money from the player's balance (physical diamonds)
|
||||
// Subtract the money from the paying player's balance (physical diamonds)
|
||||
if (charged) {
|
||||
|
||||
Player payingPlayer = offlinePlayer.getPlayer();
|
||||
Player payingPlayer = payer != null ? payer : offlinePlayer.getPlayer();
|
||||
if (payingPlayer == null) {
|
||||
|
||||
message(offlinePlayer, "rent-payError");
|
||||
@@ -892,13 +909,13 @@ public class RentRegion extends GeneralRegion {
|
||||
|
||||
}
|
||||
|
||||
message(offlinePlayer, extend ? "rent-lowMoneyExtend" : "rent-lowMoneyRent", have);
|
||||
message(payingPlayer, extend ? "rent-lowMoneyExtend" : "rent-lowMoneyRent", have);
|
||||
return false;
|
||||
|
||||
} catch (DiamondBankException e) {
|
||||
|
||||
message(offlinePlayer, "rent-payError");
|
||||
AreaShop.debug("Something went wrong with getting money from " + offlinePlayer.getName()
|
||||
message(payingPlayer, "rent-payError");
|
||||
AreaShop.debug("Something went wrong with getting money from " + payingPlayer.getName()
|
||||
+ " while renting " + getName() + ": " + e.getMessage());
|
||||
return false;
|
||||
|
||||
@@ -963,6 +980,13 @@ public class RentRegion extends GeneralRegion {
|
||||
|
||||
}
|
||||
|
||||
// Confirm to the payer when they paid for someone else's rent
|
||||
if (payer != null && !payer.getUniqueId().equals(offlinePlayer.getUniqueId())) {
|
||||
|
||||
message(payer, "payrent-paidOther");
|
||||
|
||||
}
|
||||
|
||||
// Notify about updates
|
||||
this.notifyAndUpdate(new RentedRegionEvent(this, extend));
|
||||
return true;
|
||||
@@ -1016,7 +1040,8 @@ public class RentRegion extends GeneralRegion {
|
||||
|
||||
}
|
||||
|
||||
// Pay back (part of) the price for the unused time, jubilee mode pays nothing back.
|
||||
// Pay back (part of) the price for the unused time, jubilee mode pays nothing
|
||||
// back.
|
||||
// If the payback fails the unrent is cancelled completely.
|
||||
double moneyBack = getMoneyBackAmount();
|
||||
if (giveMoneyBack && !plugin.isJubilee() && moneyBack > 0) {
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
/*
|
||||
* Adapted from the ParticleBorder minifeature of AdvancedRegionMarket
|
||||
* (https://github.com/alex9849/advanced-region-market), Copyright alex9849,
|
||||
* licensed under the Apache License, Version 2.0:
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Modifications for AreaShop: takes a plugin instance instead of using the ARM
|
||||
* singleton, outlines cuboids only (polygonal regions use their bounding box),
|
||||
* always uses the purple witch particle effect and restarts cleanly when recreated.
|
||||
*/
|
||||
// Adapted from the ParticleBorder minifeature of AdvancedRegionMarket
|
||||
// (https://github.com/alex9849/advanced-region-market), Copyright alex9849,
|
||||
// licensed under the Apache License, Version 2.0:
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
// Modifications for AreaShop: takes a plugin instance instead of using the ARM
|
||||
// singleton, outlines cuboids only (polygonal regions use their bounding box),
|
||||
// always uses the purple witch particle effect and restarts cleanly when recreated.
|
||||
package me.wiefferink.areashop.tools;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
@@ -20,9 +18,7 @@ import org.bukkit.util.Vector;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Shows the edges of a cuboid region to a single player with purple particles.
|
||||
*/
|
||||
// Shows the edges of a cuboid region to a single player with purple particles.
|
||||
public class ParticleBorder {
|
||||
|
||||
private final Plugin plugin;
|
||||
@@ -33,15 +29,8 @@ public class ParticleBorder {
|
||||
private Integer taskID;
|
||||
private Integer cancelerID;
|
||||
|
||||
/**
|
||||
* Create a particle border for a cuboid volume.
|
||||
*
|
||||
* @param plugin Plugin to schedule the particle tasks with
|
||||
* @param player Player that should see the particles
|
||||
* @param world World the volume is in
|
||||
* @param pos1 First corner of the volume
|
||||
* @param pos2 Second corner of the volume
|
||||
*/
|
||||
// Create a particle border for a cuboid volume that only the given player will
|
||||
// see.
|
||||
public ParticleBorder(Plugin plugin, Player player, World world, Vector pos1, Vector pos2) {
|
||||
|
||||
this.plugin = plugin;
|
||||
@@ -87,11 +76,7 @@ public class ParticleBorder {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Start showing the border to the player.
|
||||
*
|
||||
* @param ticks How long the border should stay visible, in ticks
|
||||
*/
|
||||
// Start showing the border to the player for the given number of ticks.
|
||||
public void createParticleBorder(int ticks) {
|
||||
|
||||
removeBorder();
|
||||
@@ -128,9 +113,7 @@ public class ParticleBorder {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop showing the border.
|
||||
*/
|
||||
// Stop showing the border.
|
||||
public void removeBorder() {
|
||||
|
||||
if (taskID == null || cancelerID == null) {
|
||||
|
||||
@@ -409,6 +409,73 @@ public class Utils {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert milliseconds to the compact time format AdvancedRegionMarket uses on
|
||||
* signs, for example '30d', '1d 12h', '45min' or '30s'.
|
||||
*
|
||||
* @param milliseconds The amount of milliseconds to convert
|
||||
* @return A compact string with the non-zero day/hour/minute/second parts
|
||||
*/
|
||||
public static String millisToCompactFormat(long milliseconds) {
|
||||
|
||||
long seconds = (milliseconds + 500) / 1000;
|
||||
if (seconds <= 0) {
|
||||
|
||||
return "0s";
|
||||
|
||||
}
|
||||
|
||||
long days = seconds / 86400;
|
||||
long hours = (seconds % 86400) / 3600;
|
||||
long minutes = (seconds % 3600) / 60;
|
||||
long secs = seconds % 60;
|
||||
StringBuilder result = new StringBuilder();
|
||||
if (days > 0) {
|
||||
|
||||
result.append(days).append("d");
|
||||
|
||||
}
|
||||
|
||||
if (hours > 0) {
|
||||
|
||||
if (result.length() > 0) {
|
||||
|
||||
result.append(" ");
|
||||
|
||||
}
|
||||
|
||||
result.append(hours).append("h");
|
||||
|
||||
}
|
||||
|
||||
if (minutes > 0) {
|
||||
|
||||
if (result.length() > 0) {
|
||||
|
||||
result.append(" ");
|
||||
|
||||
}
|
||||
|
||||
result.append(minutes).append("min");
|
||||
|
||||
}
|
||||
|
||||
if (secs > 0) {
|
||||
|
||||
if (result.length() > 0) {
|
||||
|
||||
result.append(" ");
|
||||
|
||||
}
|
||||
|
||||
result.append(secs).append("s");
|
||||
|
||||
}
|
||||
|
||||
return result.toString();
|
||||
|
||||
}
|
||||
|
||||
private static final BlockFace[] facings = { BlockFace.NORTH, BlockFace.NORTH_EAST, BlockFace.EAST,
|
||||
BlockFace.SOUTH_EAST, BlockFace.SOUTH, BlockFace.SOUTH_WEST, BlockFace.WEST, BlockFace.NORTH_WEST };
|
||||
|
||||
@@ -724,7 +791,8 @@ public class Utils {
|
||||
|
||||
}
|
||||
|
||||
// Convert an amount of diamonds to DiamondBank-OG shards (9 shards = 1 diamond).
|
||||
// Convert an amount of diamonds to DiamondBank-OG shards (9 shards = 1
|
||||
// diamond).
|
||||
public static long diamondsToShards(double diamonds) {
|
||||
|
||||
return Math.round(diamonds * 9.0);
|
||||
|
||||
@@ -193,6 +193,7 @@ maximumTries: 50000
|
||||
# %price% The price of the region formatted with the configured characters before and after the number.
|
||||
# %rawprice% The price without formatting, like '10.0' or '7.77'.
|
||||
# %duration% The duration of a rent region, for example '1 d', '4 minutes' or '2 years'.
|
||||
# %durationshort% The duration in compact form for signs, for example '30d', '1d 12h' or '45min'.
|
||||
# %world% The name of the world that the region is in.
|
||||
# %type% The type of the region, 'rent' or 'buy'.
|
||||
# %until% The end time of a rent formatted as configured with 'timeFormatChat'.
|
||||
|
||||
@@ -44,10 +44,10 @@ general:
|
||||
# Sections with 'Player' at the end will be run by the player that clicks the sign and 'Console' ones from the console.
|
||||
signProfile:
|
||||
forrent:
|
||||
line1: '&0&lFor Rent:'
|
||||
line2: '&6%region%'
|
||||
line3: '&eDuration: %duration% (12x)'
|
||||
line4: '&b%price%'
|
||||
line1: '&2For Rent:'
|
||||
line2: '&0&l%region%'
|
||||
line3: '&e%durationshort% (12x)'
|
||||
line4: '%price%'
|
||||
rightClickPlayer:
|
||||
- 'areashop info region --region %region%'
|
||||
rightClickConsole:
|
||||
@@ -55,8 +55,8 @@ general:
|
||||
leftClickPlayer:
|
||||
- 'areashop info region --region %region%'
|
||||
rented:
|
||||
line1: '&0&lRented:'
|
||||
line2: '&6%region%'
|
||||
line1: '&2Rented:'
|
||||
line2: '&0&l%region%'
|
||||
line3: '&3&lShopkeeper:'
|
||||
line4: '&0%playercolor%%player%'
|
||||
rightClickPlayer:
|
||||
@@ -65,12 +65,14 @@ general:
|
||||
# - 'areashop message %clicker% %lang:confirm-extend|%region%|%' # Alternative to first ask for confirmation (remove rightClickPlayer section)
|
||||
leftClickPlayer:
|
||||
- 'areashop info region --region %region%'
|
||||
shiftRightClickConsole:
|
||||
- 'areashop message %clicker% %lang:confirm-unrent|%region%|%'
|
||||
shiftRightClickPlayer:
|
||||
- 'areashop payrent --region %region%'
|
||||
shiftLeftClickPlayer:
|
||||
- 'areashop payrent --region %region%'
|
||||
forsale:
|
||||
line1: '&0&lFor Sale:'
|
||||
line2: '&6%region%'
|
||||
line3: '&b%price%'
|
||||
line1: '&2For Sale:'
|
||||
line2: '&0&l%region%'
|
||||
line3: '%price%'
|
||||
line4: '&8%width%x%depth%x%height%'
|
||||
rightClickPlayer:
|
||||
- 'areashop info region --region %region%'
|
||||
@@ -79,9 +81,9 @@ general:
|
||||
leftClickPlayer:
|
||||
- 'areashop info region --region %region%'
|
||||
resell:
|
||||
line1: '&0&lFor Sale:'
|
||||
line2: '&6%region%'
|
||||
line3: '&b%resellprice%'
|
||||
line1: '&2For Sale:'
|
||||
line2: '&0&l%region%'
|
||||
line3: '%resellprice%'
|
||||
line4: '&8%width%x%depth%x%height%'
|
||||
rightClickPlayer:
|
||||
- 'areashop info region --region %region%'
|
||||
@@ -92,8 +94,8 @@ general:
|
||||
shiftRightClickPlayer:
|
||||
- 'areashop stopresell --region %region%'
|
||||
sold:
|
||||
line1: '&0&lSold:'
|
||||
line2: '&6%region%'
|
||||
line1: '&4Sold:'
|
||||
line2: '&0&l%region%'
|
||||
line3: '&0%playercolor%%player%'
|
||||
line4: '&2No Expiry'
|
||||
rightClickPlayer:
|
||||
@@ -122,14 +124,14 @@ general:
|
||||
block-place: 'allow g:members'
|
||||
chest-access: 'allow g:members'
|
||||
forrent:
|
||||
greeting: '%lang:wgPrefix%&6This shop can be rented for &b%price% &6per &2%duration%'
|
||||
greeting: '%lang:wgPrefix%&6This shop can be rented for %price% &6per &2%duration%'
|
||||
use: 'allow g:all'
|
||||
rented:
|
||||
members: '%uuid%, %friendsuuid%'
|
||||
greeting: ''
|
||||
use: 'allow g:members'
|
||||
forsale:
|
||||
greeting: '%lang:wgPrefix%&6This shop can be purchased for &b%price%'
|
||||
greeting: '%lang:wgPrefix%&6This shop can be purchased for %price%'
|
||||
use: 'allow g:all'
|
||||
sold:
|
||||
members: '%uuid%, %friendsuuid%'
|
||||
@@ -137,7 +139,7 @@ general:
|
||||
use: 'allow g:members'
|
||||
resell:
|
||||
members: '%uuid%, %friendsuuid%'
|
||||
greeting: '%lang:wgPrefix%&6This shop can be purchased for &b%resellprice%'
|
||||
greeting: '%lang:wgPrefix%&6This shop can be purchased for %resellprice%'
|
||||
use: 'allow g:all'
|
||||
|
||||
##### Save and restore schematics to clean up regions.
|
||||
|
||||
@@ -74,6 +74,7 @@ help-alias: "Command aliases: /areashop, /as."
|
||||
help-help: "%lang:helpCommand|/as help|% Shows this help page."
|
||||
help-info: "%lang:helpCommand|/as info|% Get info about current regions."
|
||||
help-rent: "%lang:helpCommand|/as rent|% Rent a region or extend your current rent."
|
||||
help-payrent: "%lang:helpCommand|/as payrent|% Pay the rent of a region, your own or someone else's."
|
||||
help-buy: "%lang:helpCommand|/as buy|% Buy a region."
|
||||
help-unrent: "%lang:helpCommand|/as unrent|% Unrent a region."
|
||||
help-sell: "%lang:helpCommand|/as sell|% Sell a region."
|
||||
@@ -131,6 +132,12 @@ rent-expireWarning: "Your region %lang:region% has %timeleft% left, be sure to e
|
||||
rent-expiringSoon: "Your region %lang:tRegion|%0%|% has %1% left, be sure to extend it if you want to keep it."
|
||||
rent-alreadyAtFull: "%lang:region% is already at or above the maximum rental time, you cannot extend it yet."
|
||||
|
||||
payrent-help: "/as payrent [region], pay the rent of a region for its current renter, the region you stand in will be used if not specified."
|
||||
payrent-noPermission: "You don't have permission to pay the rent of a region."
|
||||
payrent-notRented: "Region '%0%' is not rented, there is no rent to pay."
|
||||
payrent-jubilee: "There is no rent to pay for region '%0%', during the jubilee only the first rent is charged."
|
||||
payrent-paidOther: "You paid the rent of %lang:region%, it is now extended for %player%."
|
||||
|
||||
buy-help: "/as buy [region], the region you stand in will be used if not specified."
|
||||
buy-noPermission: "You don't have permission to buy a region."
|
||||
buy-noPermissionResell: "You don't have permission to buy a region in resell mode."
|
||||
|
||||
@@ -24,6 +24,7 @@ permissions:
|
||||
areashop.destroyrent: true
|
||||
areashop.destroybuy: true
|
||||
areashop.rent: true
|
||||
areashop.payrent: true
|
||||
areashop.buy: true
|
||||
areashop.buyresell: true
|
||||
areashop.buynormal: true
|
||||
@@ -76,6 +77,9 @@ permissions:
|
||||
areashop.rent:
|
||||
description: Allows you to rent a region
|
||||
default: true
|
||||
areashop.payrent:
|
||||
description: Allows you to pay the rent of a region, your own or someone else's
|
||||
default: true
|
||||
areashop.buy:
|
||||
description: Allows you to buy a region
|
||||
default: true
|
||||
|
||||
Reference in new issue
Block a user