mirror of
https://github.com/md5sha256/AreaShop.git
synced 2026-11-06 17:32:43 -05:00
Compare commits
7
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d7907498c9 | ||
|
|
afbdc6c009 | ||
|
|
cc3a0b32a4 | ||
|
|
aca6103b1c | ||
|
|
02c02dad8d | ||
|
|
822f300e65 | ||
|
|
1671dc8c26 |
No files matched your search
+22
-24
@@ -14,10 +14,11 @@ description = "AreaShop"
|
||||
dependencies {
|
||||
// Platform
|
||||
compileOnlyApi(libs.spigot)
|
||||
compileOnlyApi(libs.worldeditCore)
|
||||
compileOnlyApi(libs.worldeditBukkit)
|
||||
compileOnlyApi(libs.worldguardCore)
|
||||
compileOnlyApi(libs.worldguardBukkit)
|
||||
compileOnlyApi("com.github.MilkBowl:VaultAPI:1.7")
|
||||
compileOnlyApi("me.clip:placeholderapi:2.11.6")
|
||||
|
||||
// 3rd party libraries
|
||||
api("io.papermc:paperlib:1.0.8")
|
||||
@@ -30,7 +31,7 @@ dependencies {
|
||||
api("com.google.inject.extensions:guice-assistedinject:7.0.0") {
|
||||
exclude("com.google.guava")
|
||||
}
|
||||
implementation("org.incendo:cloud-paper:2.0.0-beta.9") {
|
||||
implementation("org.incendo:cloud-paper:2.0.0-beta.10") {
|
||||
exclude("com.google.guava")
|
||||
}
|
||||
implementation("org.incendo:cloud-processors-confirmation:1.0.0-beta.3") {
|
||||
@@ -40,8 +41,6 @@ dependencies {
|
||||
implementation("net.kyori:adventure-platform-bukkit:4.3.2")
|
||||
implementation("org.spongepowered:configurate-yaml:4.1.2")
|
||||
|
||||
implementation("org.jetbrains:annotations:23.0.0")
|
||||
|
||||
// Project submodules
|
||||
api(projects.areashopInterface)
|
||||
api(projects.adapters.platform.platformInterface)
|
||||
@@ -54,18 +53,18 @@ dependencies {
|
||||
runtimeOnly(projects.adapters.plugins.fastasyncworldedit)
|
||||
runtimeOnly(projects.adapters.plugins.essentials)
|
||||
}
|
||||
|
||||
testImplementation("com.github.MilkBowl:VaultAPI:1.7")
|
||||
testImplementation("com.github.MilkBowl:VaultAPI:1.7")
|
||||
testImplementation("me.clip:placeholderapi:2.11.6")
|
||||
testImplementation(libs.worldeditBukkit)
|
||||
testImplementation(libs.worldguardBukkit)
|
||||
testImplementation("io.papermc.paper:paper-api:1.21.1-R0.1-SNAPSHOT")
|
||||
testImplementation("com.github.seeseemelk:MockBukkit-v1.21:3.131.0")
|
||||
testImplementation("org.junit.jupiter:junit-jupiter-api:5.10.1")
|
||||
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.10.1")
|
||||
}
|
||||
|
||||
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
tasks {
|
||||
processResources {
|
||||
filesMatching("plugin.yml") {
|
||||
@@ -118,29 +117,28 @@ tasks {
|
||||
relocate("com.google.errorprone", "${base}.errorprone")
|
||||
relocate("org.aopalliance", "${base}.aopalliance")
|
||||
relocate("javax.annotation", "${base}.javax.annotation")
|
||||
relocate("javax.inject", "${base}.javax.inject")
|
||||
relocate("org.jetbrains.annotation", "${base}.jetbrains.annotations")
|
||||
}
|
||||
|
||||
test {
|
||||
useJUnitPlatform()
|
||||
testLogging {
|
||||
events("passed", "skipped", "failed")
|
||||
}
|
||||
relocate("jakarta.inject", "${base}.jakarta.inject")
|
||||
relocate("org.jetbrains.annotations", "${base}.jetbrains.annotations")
|
||||
relocate("io.leangen.geantyref", "${base}.geantyref")
|
||||
relocate("net.kyori", "${base}.kyori")
|
||||
relocate("org.checkerframework", "${base}.checkerframework")
|
||||
relocate("org.intellij", "${base}.intellij")
|
||||
relocate("org.spongepowered", "${base}.spongepowered")
|
||||
relocate("org.yaml.snakeyaml", "${base}.snakeyaml")
|
||||
}
|
||||
runServer {
|
||||
// Configure the Minecraft version for our task.
|
||||
// This is the only required configuration besides applying the plugin.
|
||||
// Your plugin's jar (or shadowJar if present) will be used automatically.
|
||||
minecraftVersion("1.21")
|
||||
minecraftVersion("1.21.1")
|
||||
|
||||
downloadPlugins {
|
||||
github("EssentialsX", "essentials", "2.20.1", "EssentialsX-2.20.1.jar")
|
||||
github("MilkBowl", "Vault", "1.7.3", "Vault.jar")
|
||||
// WorldEdit 7.3.3
|
||||
url("https://mediafilez.forgecdn.net/files/5400/331/worldedit-bukkit-7.3.3.jar")
|
||||
// WorldGuard 7.0.10
|
||||
url("https://mediafilez.forgecdn.net/files/5344/377/worldguard-bukkit-7.0.10-dist.jar")
|
||||
// WorldEdit 7.3.9
|
||||
url("https://mediafilez.forgecdn.net/files/5935/693/worldedit-bukkit-7.3.9.jar")
|
||||
// WorldGuard 7.0.12
|
||||
url("https://mediafilez.forgecdn.net/files/5719/698/worldguard-bukkit-7.0.12-dist.jar")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,14 +12,14 @@ import me.wiefferink.areashop.adapters.platform.paper.PaperPlatform;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommands;
|
||||
import me.wiefferink.areashop.extensions.AreashopExtension;
|
||||
import me.wiefferink.areashop.features.signs.SignManager;
|
||||
import me.wiefferink.areashop.hook.placeholders.PlaceholderHook;
|
||||
import me.wiefferink.areashop.interfaces.AreaShopInterface;
|
||||
import me.wiefferink.areashop.interfaces.WorldEditInterface;
|
||||
import me.wiefferink.areashop.interfaces.WorldGuardInterface;
|
||||
import me.wiefferink.areashop.listeners.PlayerLoginLogoutListener;
|
||||
import me.wiefferink.areashop.managers.CacheManager;
|
||||
import me.wiefferink.areashop.managers.FeatureManager;
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.managers.FileManager;
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.managers.Manager;
|
||||
import me.wiefferink.areashop.managers.SignErrorLogger;
|
||||
import me.wiefferink.areashop.managers.SignLinkerManager;
|
||||
@@ -57,6 +57,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.time.Duration;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
@@ -82,6 +83,7 @@ public final class AreaShop extends JavaPlugin implements AreaShopApi {
|
||||
private MessageBridge messageBridge;
|
||||
private IFileManager fileManager = null;
|
||||
private LanguageManager languageManager = null;
|
||||
private CacheManager cacheManager = null;
|
||||
private SignLinkerManager signLinkerManager = null;
|
||||
private FeatureManager featureManager = null;
|
||||
private SignManager signManager;
|
||||
@@ -286,11 +288,17 @@ public final class AreaShop extends JavaPlugin implements AreaShopApi {
|
||||
managers.add(featureManager);
|
||||
signManager = injector.getInstance(SignManager.class);
|
||||
managers.add(signManager);
|
||||
cacheManager = injector.getInstance(CacheManager.class);
|
||||
String rawExpiryDuration = fileManager.getConfig().getString("cacheExpiryDuration", "7d");
|
||||
long millis = Utils.durationStringToLong(rawExpiryDuration);
|
||||
cacheManager.initialize(new File(getDataFolder(), "uuid-cache.bin"), Duration.ofMillis(millis));
|
||||
cacheManager.loadCache();
|
||||
managers.add(cacheManager);
|
||||
|
||||
loadExtensions();
|
||||
|
||||
// Register the event listeners
|
||||
getServer().getPluginManager().registerEvents(new PlayerLoginLogoutListener(this, messageBridge), this);
|
||||
getServer().getPluginManager().registerEvents(new PlayerLoginLogoutListener(this, messageBridge, this.cacheManager), this);
|
||||
|
||||
setupTasks();
|
||||
|
||||
@@ -302,12 +310,6 @@ public final class AreaShop extends JavaPlugin implements AreaShopApi {
|
||||
signLinkerManager = injector.getInstance(SignLinkerManager.class);
|
||||
managers.add(signLinkerManager);
|
||||
|
||||
PlaceholderHook hook = new PlaceholderHook();
|
||||
if (hook.tryEnable(this)) {
|
||||
// PlaceholderAPI is present so we should register the hook
|
||||
managers.add(hook);
|
||||
}
|
||||
|
||||
// Register dynamic permission (things declared in config)
|
||||
registerDynamicPermissions();
|
||||
|
||||
@@ -391,6 +393,10 @@ public final class AreaShop extends JavaPlugin implements AreaShopApi {
|
||||
return version;
|
||||
}
|
||||
|
||||
public CacheManager getCacheManager() {
|
||||
return cacheManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called on shutdown or reload of the server.
|
||||
*/
|
||||
|
||||
@@ -75,7 +75,7 @@ public class GroupInfoCommand extends AreashopCommandBean {
|
||||
throw new AreaShopCommandException("groupinfo-noMembers", group.getName());
|
||||
}
|
||||
String seperatedMembers = Utils.createCommaSeparatedList(members);
|
||||
this.messageBridge.message(context.sender(), "groupinfo-members", group.getName(), seperatedMembers);
|
||||
this.messageBridge.message(context.sender().sender(), "groupinfo-members", group.getName(), seperatedMembers);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
package me.wiefferink.areashop.commands;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import me.wiefferink.areashop.MessageBridge;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
|
||||
import me.wiefferink.areashop.commands.util.RegionParseUtil;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.regions.RentRegion;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bean.CommandProperties;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.key.CloudKey;
|
||||
import org.incendo.cloud.parser.flag.CommandFlag;
|
||||
import org.incendo.cloud.parser.standard.IntegerParser;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
@Singleton
|
||||
public class SetMaxExtends extends AreashopCommandBean {
|
||||
|
||||
private static final CloudKey<Integer> KEY_EXTENDS = CloudKey.of("extends", Integer.class);
|
||||
private final MessageBridge messageBridge;
|
||||
private final CommandFlag<RentRegion> regionFlag;
|
||||
|
||||
@Inject
|
||||
public SetMaxExtends(
|
||||
@Nonnull MessageBridge messageBridge,
|
||||
@Nonnull IFileManager fileManager
|
||||
) {
|
||||
this.messageBridge = messageBridge;
|
||||
this.regionFlag = RegionParseUtil.createDefaultRent(fileManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpKey(@NotNull CommandSender target) {
|
||||
if (target.hasPermission("areashop.setmaxextends")) {
|
||||
return "help-setmaxextends";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringDescription() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Command.Builder<? extends CommandSource<?>> configureCommand(Command.@NotNull Builder<CommandSource<?>> builder) {
|
||||
return builder.literal("setmaxextends")
|
||||
.required(KEY_EXTENDS, IntegerParser.integerParser(0))
|
||||
.flag(this.regionFlag)
|
||||
.handler(this::handleCommand);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull CommandProperties properties() {
|
||||
return CommandProperties.of("setmaxextends");
|
||||
}
|
||||
|
||||
private void handleCommand(@Nonnull CommandContext<CommandSource<?>> context) {
|
||||
CommandSender sender = context.sender().sender();
|
||||
if (!sender.hasPermission("areashop.setmaxextends") && (!sender.hasPermission("areashop.setmaxextends.landlord") && sender instanceof Player)) {
|
||||
this.messageBridge.message(sender, "setmaxextends-noPermission");
|
||||
return;
|
||||
}
|
||||
RentRegion rent = RegionParseUtil.getOrParseRentRegion(context, sender, this.regionFlag);
|
||||
if (!sender.hasPermission("areashop.setmaxextends")
|
||||
&& !(sender instanceof Player player
|
||||
&& rent.isLandlord(player.getUniqueId()))
|
||||
) {
|
||||
this.messageBridge.message(sender, "setmaxextends-noLandlord", rent);
|
||||
return;
|
||||
}
|
||||
int extend = context.get(KEY_EXTENDS);
|
||||
|
||||
sender.sendMessage();
|
||||
rent.setMaxExtends(extend);
|
||||
rent.update();
|
||||
this.messageBridge.message(sender, "setmaxextends-success", rent);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -46,6 +46,7 @@ import me.wiefferink.areashop.commands.TeleportCommand;
|
||||
import me.wiefferink.areashop.commands.ToggleHomeCommand;
|
||||
import me.wiefferink.areashop.commands.TransferCommand;
|
||||
import me.wiefferink.areashop.commands.UnrentCommand;
|
||||
import me.wiefferink.areashop.commands.SetMaxExtends;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSourceMapper;
|
||||
import org.bukkit.command.CommandSender;
|
||||
@@ -109,7 +110,8 @@ public class AreashopCommands {
|
||||
TeleportCommand.class,
|
||||
ToggleHomeCommand.class,
|
||||
TransferCommand.class,
|
||||
UnrentCommand.class
|
||||
UnrentCommand.class,
|
||||
SetMaxExtends.class
|
||||
);
|
||||
|
||||
private final MessageBridge messageBridge;
|
||||
@@ -147,14 +149,14 @@ public class AreashopCommands {
|
||||
private void initCommandManager() {
|
||||
ExceptionController<CommandSource<?>> exceptionController = this.commandManager.exceptionController();
|
||||
// We need to unwrap ArgumentParseException because they wrap the custom exception messages
|
||||
exceptionController.registerHandler(ArgumentParseException.class,
|
||||
ExceptionHandler.unwrappingHandler(AreaShopCommandException.class));
|
||||
exceptionController.registerHandler(CommandExecutionException.class,
|
||||
ExceptionHandler.unwrappingHandler(AreaShopCommandException.class));
|
||||
exceptionController.registerHandler(InvalidCommandSenderException.class,
|
||||
new InvalidCommandSenderHandler(this.messageBridge));
|
||||
exceptionController.registerHandler(AreaShopCommandException.class,
|
||||
new ArgumentParseExceptionHandler<>(this.messageBridge));
|
||||
exceptionController.registerHandler(ArgumentParseException.class,
|
||||
ExceptionHandler.unwrappingHandler(AreaShopCommandException.class));
|
||||
exceptionController.registerHandler(CommandExecutionException.class,
|
||||
ExceptionHandler.unwrappingHandler(AreaShopCommandException.class));
|
||||
var confirmationConfiguration = ConfirmationConfiguration.<CommandSource<?>>builder()
|
||||
.cache(GuavaCache.of(CacheBuilder.newBuilder().build()))
|
||||
.noPendingCommandNotifier(x -> {
|
||||
|
||||
-68
@@ -1,68 +0,0 @@
|
||||
package me.wiefferink.areashop.hook.placeholders;
|
||||
|
||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||
import me.wiefferink.areashop.interfaces.GeneralRegionInterface;
|
||||
import me.wiefferink.areashop.regions.IRegionContainer;
|
||||
import me.wiefferink.interactivemessenger.processing.ReplacementProvider;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class BuiltinRegionExpansion extends PlaceholderExpansion {
|
||||
|
||||
private final Pattern pattern = Pattern.compile("_");
|
||||
private final IRegionContainer regionContainer;
|
||||
|
||||
public BuiltinRegionExpansion(@NotNull IRegionContainer regionContainer) {
|
||||
this.regionContainer = regionContainer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getIdentifier() {
|
||||
return "region";
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getAuthor() {
|
||||
return "md5sha256";
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getVersion() {
|
||||
return "1.0";
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String onRequest(OfflinePlayer player, @NotNull String params) {
|
||||
final String[] split = pattern.split(params);
|
||||
if (split.length < 2) {
|
||||
return null;
|
||||
}
|
||||
final String regionId = split[0];
|
||||
final GeneralRegionInterface region = regionContainer.getRegionInterface(regionId);
|
||||
if (!(region instanceof ReplacementProvider provider)) {
|
||||
return null;
|
||||
}
|
||||
final String replacementKey = split[1];
|
||||
final Object replacement = provider.provideReplacement(replacementKey);
|
||||
return handleReplacement(replacement);
|
||||
}
|
||||
|
||||
@Nullable String handleReplacement(@Nullable Object repl) {
|
||||
if (repl instanceof String s) {
|
||||
return s;
|
||||
} else if (repl instanceof Number number) {
|
||||
return formatNumber(number);
|
||||
} else if (repl != null) {
|
||||
return repl.toString();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private @NotNull String formatNumber(@NotNull Number number) {
|
||||
return NumberFormat.getInstance().format(number);
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package me.wiefferink.areashop.hook.placeholders;
|
||||
|
||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||
import me.wiefferink.areashop.AreaShop;
|
||||
import me.wiefferink.areashop.managers.Manager;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
public class PlaceholderHook extends Manager {
|
||||
|
||||
private boolean enabled;
|
||||
|
||||
private final Collection<PlaceholderExpansion> expansions = new ArrayList<>();
|
||||
|
||||
public final boolean enabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public boolean tryEnable(AreaShop plugin) {
|
||||
if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") == null) {
|
||||
return false;
|
||||
}
|
||||
if (enabled) {
|
||||
return true;
|
||||
}
|
||||
plugin.getLogger().info(() -> "Detected PlaceHolderAPI; registering placeholders");
|
||||
PlaceholderExpansion generalRegionExp = new BuiltinRegionExpansion(plugin.getFileManager());
|
||||
plugin.debugI(() -> "Initialized the GeneralRegionExpansion");
|
||||
expansions.add(generalRegionExp);
|
||||
expansions.forEach(PlaceholderExpansion::register);
|
||||
enabled = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
if (!enabled) {
|
||||
return;
|
||||
}
|
||||
expansions.forEach(PlaceholderExpansion::unregister);
|
||||
expansions.clear();
|
||||
enabled = false;
|
||||
}
|
||||
|
||||
}
|
||||
+11
-1
@@ -2,10 +2,12 @@ package me.wiefferink.areashop.listeners;
|
||||
|
||||
import me.wiefferink.areashop.AreaShop;
|
||||
import me.wiefferink.areashop.MessageBridge;
|
||||
import me.wiefferink.areashop.managers.CacheManager;
|
||||
import me.wiefferink.areashop.regions.BuyRegion;
|
||||
import me.wiefferink.areashop.regions.GeneralRegion;
|
||||
import me.wiefferink.areashop.regions.RentRegion;
|
||||
import me.wiefferink.areashop.tools.Utils;
|
||||
import me.wiefferink.areashop.tools.CacheWrapper;
|
||||
import me.wiefferink.bukkitdo.Do;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
@@ -27,14 +29,20 @@ public final class PlayerLoginLogoutListener implements Listener {
|
||||
|
||||
private final AreaShop plugin;
|
||||
private final MessageBridge messageBridge;
|
||||
private final CacheManager cacheManager;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param plugin The AreaShop plugin
|
||||
*/
|
||||
public PlayerLoginLogoutListener(@Nonnull AreaShop plugin, @Nonnull MessageBridge messageBridge) {
|
||||
public PlayerLoginLogoutListener(
|
||||
@Nonnull AreaShop plugin,
|
||||
@Nonnull MessageBridge messageBridge,
|
||||
@Nonnull CacheManager cacheManager
|
||||
) {
|
||||
this.plugin = plugin;
|
||||
this.messageBridge = messageBridge;
|
||||
this.cacheManager = cacheManager;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,6 +56,8 @@ public final class PlayerLoginLogoutListener implements Listener {
|
||||
}
|
||||
final Player player = event.getPlayer();
|
||||
|
||||
this.cacheManager.computeIfAbsent(player.getUniqueId(), uuid -> new CacheWrapper(uuid, player.getName()));
|
||||
|
||||
// Schedule task to check for notifications, prevents a lag spike at login
|
||||
Do.syncTimerLater(25, 25, () -> {
|
||||
// Delay until all regions are loaded
|
||||
|
||||
@@ -0,0 +1,247 @@
|
||||
package me.wiefferink.areashop.managers;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import me.wiefferink.areashop.tools.CacheWrapper;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.time.Duration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Function;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class CacheManager extends Manager {
|
||||
|
||||
private final Plugin plugin;
|
||||
private final Map<UUID, CacheWrapper> cache;
|
||||
|
||||
private File cacheFile;
|
||||
private Duration expiryDuration;
|
||||
|
||||
@Inject
|
||||
CacheManager(@Nonnull Plugin plugin) {
|
||||
this.plugin = plugin;
|
||||
this.cache = new HashMap<>();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
if (this.expiryDuration != null) {
|
||||
trimCache(expiryDuration);
|
||||
}
|
||||
if (this.cacheFile != null) {
|
||||
saveCache(cacheFile);
|
||||
}
|
||||
}
|
||||
|
||||
public void initialize(@Nonnull File cacheFile, @Nonnull Duration expiryDuration) {
|
||||
this.cacheFile = cacheFile;
|
||||
this.expiryDuration = expiryDuration;
|
||||
}
|
||||
|
||||
public void loadCache() {
|
||||
if (this.cacheFile != null) {
|
||||
loadCache(this.cacheFile);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the cache from the file
|
||||
*/
|
||||
public void loadCache(@Nonnull File cacheFile) {
|
||||
if (Files.notExists(cacheFile.toPath())) {
|
||||
this.plugin.getLogger().info("uuid cache file does not exist, loaded 0 entries");
|
||||
return;
|
||||
}
|
||||
this.cache.clear();
|
||||
|
||||
try (FileInputStream input = new FileInputStream(cacheFile)) {
|
||||
byte[] bytes = input.readAllBytes();
|
||||
ByteBuffer buffer = ByteBuffer.wrap(bytes).asReadOnlyBuffer();
|
||||
while (buffer.hasRemaining()) {
|
||||
long lastUsed = buffer.getLong();
|
||||
long lsb = buffer.getLong();
|
||||
long msb = buffer.getLong();
|
||||
int stringLen = buffer.getInt();
|
||||
byte[] stringBytes = new byte[stringLen];
|
||||
buffer.get(stringBytes);
|
||||
String name = new String(stringBytes, StandardCharsets.UTF_8);
|
||||
UUID uuid = new UUID(msb, lsb);
|
||||
CacheWrapper wrapper = new CacheWrapper(uuid, name, lastUsed);
|
||||
this.cache.put(wrapper.getUuid(), wrapper);
|
||||
}
|
||||
this.plugin.getLogger()
|
||||
.info(String.format("Loaded %d cached uuid name entries", this.cache.size()));
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
this.plugin.getLogger().warning("Failed to load the uuid cache!");
|
||||
}
|
||||
}
|
||||
|
||||
public void saveCache() {
|
||||
if (this.cacheFile != null) {
|
||||
saveCache(this.cacheFile);
|
||||
}
|
||||
}
|
||||
|
||||
public void saveCacheAsync() {
|
||||
if (this.cacheFile != null) {
|
||||
saveCacheAsync(this.cacheFile);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Save the cache to the file
|
||||
*/
|
||||
public void saveCache(@Nonnull File cacheFile) {
|
||||
List<CacheWrapper> copy = this.cache.values().stream().map(CacheWrapper::new).toList();
|
||||
try {
|
||||
// Ensure parent directory exists
|
||||
Path parentDir = cacheFile.toPath().getParent();
|
||||
if (parentDir != null) { // parent might be null if cacheFile is relative with no parent
|
||||
Files.createDirectories(parentDir);
|
||||
}
|
||||
byte[] bytes = serialize(copy);
|
||||
try (FileOutputStream fos = new FileOutputStream(cacheFile)) {
|
||||
fos.write(bytes);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
plugin.getLogger().log(Level.SEVERE, "Failed to save cache.json", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void saveCacheAsync(@Nonnull File cacheFile) {
|
||||
List<CacheWrapper> copy = this.cache.values().stream().map(CacheWrapper::new).toList();
|
||||
CompletableFuture.runAsync(() -> {
|
||||
try {
|
||||
// Ensure parent directory exists
|
||||
Path parentDir = cacheFile.toPath().getParent();
|
||||
if (parentDir != null) { // parent might be null if cacheFile is relative with no parent
|
||||
Files.createDirectories(parentDir);
|
||||
}
|
||||
byte[] bytes = serialize(copy);
|
||||
try (FileOutputStream fos = new FileOutputStream(cacheFile)) {
|
||||
fos.write(bytes);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
plugin.getLogger().log(Level.SEVERE, "Failed to save cache.json", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private byte[] serialize(List<CacheWrapper> wrappers) {
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream(256 * wrappers.size());
|
||||
for (CacheWrapper wrapper : wrappers) {
|
||||
ByteBuffer buffer = ByteBuffer.allocate(256);
|
||||
byte[] stringBytes = wrapper.getName().getBytes(StandardCharsets.UTF_8);
|
||||
int stringLen = stringBytes.length;
|
||||
long lsb = wrapper.getUuid().getLeastSignificantBits();
|
||||
long msb = wrapper.getUuid().getMostSignificantBits();
|
||||
long lastUsed = wrapper.getLastUsed();
|
||||
buffer.putLong(lastUsed);
|
||||
buffer.putLong(lsb);
|
||||
buffer.putLong(msb);
|
||||
buffer.putInt(stringLen);
|
||||
buffer.put(stringBytes);
|
||||
|
||||
buffer.flip();
|
||||
|
||||
bos.write(buffer.array(), buffer.position(), buffer.remaining());
|
||||
}
|
||||
return bos.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a cache entry
|
||||
*/
|
||||
public CacheWrapper get(UUID uuid) {
|
||||
return cache.get(uuid);
|
||||
}
|
||||
|
||||
public CacheWrapper computeIfAbsent(@Nonnull UUID uuid, Function<UUID, CacheWrapper> function) {
|
||||
return this.cache.computeIfAbsent(uuid, function);
|
||||
}
|
||||
|
||||
/**
|
||||
* Put a cache entry
|
||||
*/
|
||||
public void put(UUID uuid, CacheWrapper wrapper) {
|
||||
cache.put(uuid, wrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a cache entry
|
||||
*/
|
||||
public CacheWrapper remove(UUID uuid) {
|
||||
return cache.remove(uuid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if cache contains a UUID
|
||||
*/
|
||||
public boolean contains(UUID uuid) {
|
||||
return cache.containsKey(uuid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all cache entries
|
||||
*/
|
||||
public Map<UUID, CacheWrapper> getAllEntries() {
|
||||
return new HashMap<>(cache);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all cache entries
|
||||
*/
|
||||
public void clear() {
|
||||
cache.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the size of the cache
|
||||
*/
|
||||
public int size() {
|
||||
return cache.size();
|
||||
}
|
||||
|
||||
public void trimCache() {
|
||||
if (this.expiryDuration != null) {
|
||||
trimCache(this.expiryDuration);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Trim the cache by removing entries older than 1 week
|
||||
*/
|
||||
public void trimCache(@Nonnull Duration expiryDuration) {
|
||||
long expiryMillis = expiryDuration.toMillis();
|
||||
long currentTime = System.currentTimeMillis();
|
||||
|
||||
Iterator<Map.Entry<UUID, CacheWrapper>> iterator = cache.entrySet().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry<UUID, CacheWrapper> entry = iterator.next();
|
||||
CacheWrapper wrapper = entry.getValue();
|
||||
|
||||
if (wrapper.getLastUsed() != -1 && (currentTime - wrapper.getLastUsed()) >= expiryMillis) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -12,18 +12,15 @@ import me.wiefferink.areashop.events.ask.AddingRegionEvent;
|
||||
import me.wiefferink.areashop.events.ask.DeletingRegionEvent;
|
||||
import me.wiefferink.areashop.events.notify.AddedRegionEvent;
|
||||
import me.wiefferink.areashop.events.notify.DeletedRegionEvent;
|
||||
import me.wiefferink.areashop.interfaces.GeneralRegionInterface;
|
||||
import me.wiefferink.areashop.features.signs.SignManager;
|
||||
import me.wiefferink.areashop.interfaces.WorldGuardInterface;
|
||||
import me.wiefferink.areashop.regions.BuyRegion;
|
||||
import me.wiefferink.areashop.regions.GeneralRegion;
|
||||
import me.wiefferink.areashop.regions.GeneralRegion.RegionEvent;
|
||||
import me.wiefferink.areashop.regions.GeneralRegion.RegionType;
|
||||
import me.wiefferink.areashop.regions.IRegionContainer;
|
||||
import me.wiefferink.areashop.regions.RegionFactory;
|
||||
import me.wiefferink.areashop.regions.RegionGroup;
|
||||
import me.wiefferink.areashop.regions.RentRegion;
|
||||
import me.wiefferink.areashop.regions.SimpleRegionContainer;
|
||||
import me.wiefferink.areashop.tools.Utils;
|
||||
import me.wiefferink.bukkitdo.Do;
|
||||
import org.bukkit.Bukkit;
|
||||
@@ -34,7 +31,6 @@ import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
@@ -50,9 +46,11 @@ import java.io.OutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
@@ -63,8 +61,9 @@ import java.util.regex.Pattern;
|
||||
public class FileManager extends Manager implements IFileManager {
|
||||
|
||||
private final AreaShop plugin;
|
||||
|
||||
private final IRegionContainer regionContainer = new SimpleRegionContainer();
|
||||
private final Map<String, GeneralRegion> regions;
|
||||
private final Map<String, BuyRegion> buys;
|
||||
private final Map<String, RentRegion> rents;
|
||||
private final String regionsPath;
|
||||
private final Map<String, RegionGroup> groups;
|
||||
private final String configPath;
|
||||
@@ -102,6 +101,9 @@ public class FileManager extends Manager implements IFileManager {
|
||||
this.messageBridge = messageBridge;
|
||||
this.regionFactory = regionFactory;
|
||||
this.signManager = signManager;
|
||||
regions = new HashMap<>();
|
||||
buys = new HashMap<>();
|
||||
rents = new HashMap<>();
|
||||
regionsPath = plugin.getDataFolder() + File.separator + AreaShop.regionsFolder;
|
||||
configPath = plugin.getDataFolder() + File.separator + "config.yml";
|
||||
groups = new HashMap<>();
|
||||
@@ -120,7 +122,7 @@ public class FileManager extends Manager implements IFileManager {
|
||||
@Override
|
||||
public void shutdown() {
|
||||
// Update lastactive time for players that are online now
|
||||
for(GeneralRegion region : this.regionContainer.getRegionsRef()) {
|
||||
for(GeneralRegion region : this.regions.values()) {
|
||||
UUID ownerUuid = region.getOwner();
|
||||
if (ownerUuid == null) {
|
||||
continue;
|
||||
@@ -194,22 +196,6 @@ public class FileManager extends Manager implements IFileManager {
|
||||
return config;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public GeneralRegionInterface getRegionInterface(String name) {
|
||||
return this.regionContainer.getRegionInterface(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GeneralRegionInterface> getRegionInterfaces() {
|
||||
return this.regionContainer.getRegionInterfaces();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<GeneralRegionInterface> getRegionInterfacesRef() {
|
||||
return this.regionContainer.getRegionInterfacesRef();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a region.
|
||||
* @param name The name of the region to get (will be normalized)
|
||||
@@ -217,7 +203,7 @@ public class FileManager extends Manager implements IFileManager {
|
||||
*/
|
||||
@Override
|
||||
public @Nullable GeneralRegion getRegion(String name) {
|
||||
return this.regionContainer.getRegion(name);
|
||||
return regions.get(name.toLowerCase());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -227,7 +213,7 @@ public class FileManager extends Manager implements IFileManager {
|
||||
*/
|
||||
@Override
|
||||
public @Nullable RentRegion getRent(String name) {
|
||||
return this.regionContainer.getRent(name);
|
||||
return rents.get(name.toLowerCase(Locale.ENGLISH));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -237,7 +223,7 @@ public class FileManager extends Manager implements IFileManager {
|
||||
*/
|
||||
@Override
|
||||
public @Nullable BuyRegion getBuy(String name) {
|
||||
return this.regionContainer.getBuy(name);
|
||||
return buys.get(name.toLowerCase(Locale.ENGLISH));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -245,8 +231,8 @@ public class FileManager extends Manager implements IFileManager {
|
||||
* @return List of all rental regions
|
||||
*/
|
||||
@Override
|
||||
public List<RentRegion> getRents() {
|
||||
return this.regionContainer.getRents();
|
||||
public Collection<RentRegion> getRents() {
|
||||
return new ArrayList<>(rents.values());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -255,7 +241,7 @@ public class FileManager extends Manager implements IFileManager {
|
||||
*/
|
||||
@Override
|
||||
public Collection<RentRegion> getRentsRef() {
|
||||
return this.regionContainer.getRentsRef();
|
||||
return Collections.unmodifiableCollection(rents.values());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -264,12 +250,12 @@ public class FileManager extends Manager implements IFileManager {
|
||||
*/
|
||||
@Override
|
||||
public List<BuyRegion> getBuys() {
|
||||
return this.regionContainer.getBuys();
|
||||
return new ArrayList<>(buys.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<BuyRegion> getBuysRef() {
|
||||
return this.regionContainer.getBuysRef();
|
||||
return Collections.unmodifiableCollection(buys.values());
|
||||
}
|
||||
|
||||
|
||||
@@ -279,7 +265,7 @@ public class FileManager extends Manager implements IFileManager {
|
||||
*/
|
||||
@Override
|
||||
public List<GeneralRegion> getRegions() {
|
||||
return this.regionContainer.getRegions();
|
||||
return new ArrayList<>(regions.values());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -288,7 +274,7 @@ public class FileManager extends Manager implements IFileManager {
|
||||
*/
|
||||
@Override
|
||||
public Collection<GeneralRegion> getRegionsRef() {
|
||||
return this.regionContainer.getRegionsRef();
|
||||
return Collections.unmodifiableCollection(regions.values());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -297,7 +283,11 @@ public class FileManager extends Manager implements IFileManager {
|
||||
*/
|
||||
@Override
|
||||
public List<String> getBuyNames() {
|
||||
return this.regionContainer.getBuyNames();
|
||||
ArrayList<String> result = new ArrayList<>(buys.size());
|
||||
for(BuyRegion region : buys.values()) {
|
||||
result.add(region.getName());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -306,7 +296,11 @@ public class FileManager extends Manager implements IFileManager {
|
||||
*/
|
||||
@Override
|
||||
public List<String> getRentNames() {
|
||||
return this.regionContainer.getRentNames();
|
||||
ArrayList<String> result = new ArrayList<>(rents.size());
|
||||
for(RentRegion region : rents.values()) {
|
||||
result.add(region.getName());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -315,12 +309,11 @@ public class FileManager extends Manager implements IFileManager {
|
||||
*/
|
||||
@Override
|
||||
public List<String> getRegionNames() {
|
||||
return this.regionContainer.getRegionNames();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getRegionInterfaceNames() {
|
||||
return this.regionContainer.getRegionInterfaceNames();
|
||||
ArrayList<String> result = new ArrayList<>(regions.size());
|
||||
for(GeneralRegion region : regions.values()) {
|
||||
result.add(region.getName());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -369,7 +362,13 @@ public class FileManager extends Manager implements IFileManager {
|
||||
if (event.isCancelled()) {
|
||||
return event;
|
||||
}
|
||||
this.regionContainer.addRegionInterface(region);
|
||||
final String key = region.getName().toLowerCase(Locale.ENGLISH);
|
||||
regions.put(key, region);
|
||||
if (region instanceof BuyRegion buyRegion) {
|
||||
buys.put(key, buyRegion);
|
||||
} else if (region instanceof RentRegion rentRegion) {
|
||||
rents.put(key, rentRegion);
|
||||
}
|
||||
Bukkit.getPluginManager().callEvent(new AddedRegionEvent(region));
|
||||
return event;
|
||||
}
|
||||
@@ -492,7 +491,9 @@ public class FileManager extends Manager implements IFileManager {
|
||||
|
||||
region.resetRegionFlags();
|
||||
String name = region.getLowerCaseName();
|
||||
this.regionContainer.removeRegion(name);
|
||||
regions.remove(name);
|
||||
buys.remove(name);
|
||||
rents.remove(name);
|
||||
|
||||
// Remove file
|
||||
File file = new File(plugin.getDataFolder() + File.separator + AreaShop.regionsFolder + File.separator + region.getLowerCaseName() + ".yml");
|
||||
@@ -620,21 +621,6 @@ public class FileManager extends Manager implements IFileManager {
|
||||
return saveGroupsRequired;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addRegionInterface(@NotNull GeneralRegionInterface region) {
|
||||
this.regionContainer.addRegionInterface(region);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeRegion(@NotNull String region) {
|
||||
this.regionContainer.removeRegion(region);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeRegion(@NotNull GeneralRegionInterface region) {
|
||||
this.regionContainer.removeRegion(region);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the groups file to disk synchronously.
|
||||
*/
|
||||
@@ -966,7 +952,9 @@ public class FileManager extends Manager implements IFileManager {
|
||||
*/
|
||||
@Override
|
||||
public void loadRegionFiles() {
|
||||
this.regionContainer.clearRegions();
|
||||
this.regions.clear();
|
||||
this.buys.clear();
|
||||
this.rents.clear();
|
||||
final File file = new File(regionsPath);
|
||||
if(!file.exists()) {
|
||||
if(!file.mkdirs()) {
|
||||
@@ -1031,7 +1019,7 @@ public class FileManager extends Manager implements IFileManager {
|
||||
noWorld.add(region);
|
||||
} else if(region.getRegion() == null) {
|
||||
noRegion.put(region, regionFile);
|
||||
} else if(region instanceof RentRegion rentRegion && !Utils.checkTimeFormat(rentRegion.getDurationString())) {
|
||||
} else if(region instanceof RentRegion && !Utils.checkTimeFormat(((RentRegion)region).getDurationString())) {
|
||||
incorrectDuration.add(region);
|
||||
} else {
|
||||
added = true;
|
||||
@@ -1424,11 +1412,6 @@ public class FileManager extends Manager implements IFileManager {
|
||||
public void setGroupSetting(RegionGroup group, String path, Object setting) {
|
||||
groupsConfig.set(group.getName().toLowerCase() + "." + path, setting);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearRegions() {
|
||||
this.regionContainer.clearRegions();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -3,18 +3,20 @@ package me.wiefferink.areashop.managers;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
import me.wiefferink.areashop.events.ask.AddingRegionEvent;
|
||||
import me.wiefferink.areashop.events.ask.DeletingRegionEvent;
|
||||
import me.wiefferink.areashop.regions.BuyRegion;
|
||||
import me.wiefferink.areashop.regions.GeneralRegion;
|
||||
import me.wiefferink.areashop.regions.IRegionContainer;
|
||||
import me.wiefferink.areashop.regions.RegionGroup;
|
||||
import me.wiefferink.areashop.regions.RentRegion;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public interface IFileManager extends IRegionContainer {
|
||||
public interface IFileManager {
|
||||
|
||||
/**
|
||||
* Get the folder where schematics are stored.
|
||||
@@ -59,6 +61,95 @@ public interface IFileManager extends IRegionContainer {
|
||||
*/
|
||||
YamlConfiguration getConfig();
|
||||
|
||||
/**
|
||||
* Get a region.
|
||||
*
|
||||
* @param name The name of the region to get (will be normalized)
|
||||
* @return The region if found, otherwise null
|
||||
*/
|
||||
@Nullable
|
||||
GeneralRegion getRegion(String name);
|
||||
|
||||
/**
|
||||
* Get a rental region.
|
||||
*
|
||||
* @param name The name of the rental region (will be normalized)
|
||||
* @return RentRegion if it could be found, otherwise null
|
||||
*/
|
||||
@Nullable
|
||||
RentRegion getRent(String name);
|
||||
|
||||
/**
|
||||
* Get a buy region.
|
||||
*
|
||||
* @param name The name of the buy region (will be normalized)
|
||||
* @return BuyRegion if it could be found, otherwise null
|
||||
*/
|
||||
@Nullable
|
||||
BuyRegion getBuy(String name);
|
||||
|
||||
/**
|
||||
* Get all rental regions.
|
||||
*
|
||||
* @return List of all rental regions
|
||||
*/
|
||||
Collection<RentRegion> getRents();
|
||||
|
||||
/**
|
||||
* Get all rental regions (readonly)
|
||||
*
|
||||
* @return Unmodifiable collection of all rental regions
|
||||
*/
|
||||
Collection<RentRegion> getRentsRef();
|
||||
|
||||
/**
|
||||
* Get all buy regions.
|
||||
*
|
||||
* @return List of all buy regions
|
||||
*/
|
||||
List<BuyRegion> getBuys();
|
||||
|
||||
/**
|
||||
* Get all buy regions (readonly)
|
||||
* @return Unmodifiable collection of all buy regions
|
||||
*/
|
||||
Collection<BuyRegion> getBuysRef();
|
||||
|
||||
/**
|
||||
* Get all regions.
|
||||
*
|
||||
* @return List of all regions (it is safe to modify the list)
|
||||
*/
|
||||
List<GeneralRegion> getRegions();
|
||||
|
||||
/**
|
||||
* Get all regions (readonly)
|
||||
*
|
||||
* @return Unmodifiable collection of all regions
|
||||
*/
|
||||
Collection<GeneralRegion> getRegionsRef();
|
||||
|
||||
/**
|
||||
* Get a list of names of all buy regions.
|
||||
*
|
||||
* @return A String list with all the names
|
||||
*/
|
||||
List<String> getBuyNames();
|
||||
|
||||
/**
|
||||
* Get a list of names of all rent regions.
|
||||
*
|
||||
* @return A String list with all the names
|
||||
*/
|
||||
List<String> getRentNames();
|
||||
|
||||
/**
|
||||
* Get a list of names of all regions.
|
||||
*
|
||||
* @return A String list with all the names
|
||||
*/
|
||||
List<String> getRegionNames();
|
||||
|
||||
/**
|
||||
* Get a list of names of all groups.
|
||||
*
|
||||
|
||||
@@ -13,7 +13,6 @@ import me.wiefferink.areashop.interfaces.WorldEditInterface;
|
||||
import me.wiefferink.areashop.interfaces.WorldGuardInterface;
|
||||
import me.wiefferink.areashop.managers.FeatureManager;
|
||||
import me.wiefferink.areashop.managers.FileManager;
|
||||
import me.wiefferink.areashop.regions.IRegionContainer;
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.managers.SignErrorLogger;
|
||||
import me.wiefferink.areashop.managers.SignLinkerManager;
|
||||
@@ -67,7 +66,6 @@ public class AreaShopModule extends AbstractModule {
|
||||
bind(SignErrorLogger.class).toInstance(this.signErrorLogger);
|
||||
// Setup managers
|
||||
bind(IFileManager.class).to(FileManager.class).asEagerSingleton();
|
||||
bind(IRegionContainer.class).to(FileManager.class).asEagerSingleton();
|
||||
bind(FeatureManager.class).in(Singleton.class);
|
||||
// bind(CommandManager.class).in(Singleton.class);
|
||||
bind(SignLinkerManager.class).in(Singleton.class);
|
||||
|
||||
@@ -635,7 +635,7 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
|
||||
return getName();
|
||||
}
|
||||
case AreaShop.tagRegionType -> {
|
||||
return getType().getValue().toLowerCase(Locale.ENGLISH);
|
||||
return getType().getValue().toLowerCase();
|
||||
}
|
||||
case AreaShop.tagWorldName -> {
|
||||
return getWorldName();
|
||||
|
||||
@@ -1,149 +0,0 @@
|
||||
package me.wiefferink.areashop.regions;
|
||||
|
||||
import me.wiefferink.areashop.interfaces.GeneralRegionInterface;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public interface IRegionContainer {
|
||||
|
||||
@Nullable
|
||||
GeneralRegionInterface getRegionInterface(String name);
|
||||
|
||||
/**
|
||||
* Get a region.
|
||||
*
|
||||
* @param name The name of the region to get (will be normalized)
|
||||
* @return The region if found, otherwise null
|
||||
*/
|
||||
@Nullable
|
||||
GeneralRegion getRegion(String name);
|
||||
|
||||
/**
|
||||
* Get a rental region.
|
||||
*
|
||||
* @param name The name of the rental region (will be normalized)
|
||||
* @return RentRegion if it could be found, otherwise null
|
||||
*/
|
||||
@Nullable
|
||||
RentRegion getRent(String name);
|
||||
|
||||
/**
|
||||
* Get a buy region.
|
||||
*
|
||||
* @param name The name of the buy region (will be normalized)
|
||||
* @return BuyRegion if it could be found, otherwise null
|
||||
*/
|
||||
@Nullable
|
||||
BuyRegion getBuy(String name);
|
||||
|
||||
/**
|
||||
* Get a copy of all registered {@link RentRegion} instances
|
||||
*
|
||||
* @return List of regions (it is safe to modify the list)
|
||||
*/
|
||||
List<RentRegion> getRents();
|
||||
|
||||
/**
|
||||
* Get a readonly view of all registered {@link RentRegion} instances.
|
||||
*
|
||||
* @return Readonly collection of all regions
|
||||
*/
|
||||
Collection<RentRegion> getRentsRef();
|
||||
|
||||
/**
|
||||
* Get a copy of all registered {@link BuyRegion} instances
|
||||
*
|
||||
* @return List of regions (it is safe to modify the list)
|
||||
*/
|
||||
List<BuyRegion> getBuys();
|
||||
|
||||
/**
|
||||
* Get a readonly view of all registered {@link BuyRegion} instances.
|
||||
*
|
||||
* @return Readonly collection of all regions
|
||||
*/
|
||||
Collection<BuyRegion> getBuysRef();
|
||||
|
||||
/**
|
||||
* Get copy of all registered {@link GeneralRegion}s.
|
||||
*
|
||||
* @return List of regions (it is safe to modify the list)
|
||||
*/
|
||||
List<GeneralRegion> getRegions();
|
||||
|
||||
/**
|
||||
* Get a readonly view of all registered {@link GeneralRegion} instances.
|
||||
*
|
||||
* @return Readonly collection of all regions
|
||||
*/
|
||||
Collection<GeneralRegion> getRegionsRef();
|
||||
|
||||
/**
|
||||
* Get copy of all registered {@link GeneralRegionInterface}s.
|
||||
*
|
||||
* @return List of regions (it is safe to modify the list)
|
||||
*/
|
||||
List<GeneralRegionInterface> getRegionInterfaces();
|
||||
|
||||
/**
|
||||
* Get a readonly view of all registered {@link GeneralRegionInterface} instances.
|
||||
*
|
||||
* @return Readonly collection of all regions
|
||||
*/
|
||||
Collection<GeneralRegionInterface> getRegionInterfacesRef();
|
||||
|
||||
/**
|
||||
* Get a list of names of all {@link BuyRegion}s
|
||||
*
|
||||
* @return A String list with all the names
|
||||
*/
|
||||
List<String> getBuyNames();
|
||||
|
||||
/**
|
||||
* Get a list of names of all {@link RentRegion}s
|
||||
*
|
||||
* @return A String list with all the names
|
||||
*/
|
||||
List<String> getRentNames();
|
||||
|
||||
/**
|
||||
* Get a list of names of all {@link GeneralRegion}
|
||||
*
|
||||
* @return A String list with all the names
|
||||
*/
|
||||
List<String> getRegionNames();
|
||||
|
||||
/**
|
||||
* Get a list of names of all {@link GeneralRegionInterface}s
|
||||
* @return A string list with all the names
|
||||
*/
|
||||
List<String> getRegionInterfaceNames();
|
||||
|
||||
/**
|
||||
* Register a {@link GeneralRegionInterface}
|
||||
* @param region The region to register
|
||||
*/
|
||||
void addRegionInterface(@NotNull GeneralRegionInterface region);
|
||||
|
||||
/**
|
||||
* Deregister a region by its name
|
||||
* @param region The name of the region to deregister
|
||||
* @see GeneralRegionInterface#getName()
|
||||
*/
|
||||
void removeRegion(@NotNull String region);
|
||||
|
||||
/**
|
||||
* Deregister a {@link GeneralRegionInterface}
|
||||
* @param region The region to deregister
|
||||
*/
|
||||
void removeRegion(@NotNull GeneralRegionInterface region);
|
||||
|
||||
/**
|
||||
* Clear all registered regions
|
||||
*/
|
||||
void clearRegions();
|
||||
|
||||
}
|
||||
@@ -190,6 +190,9 @@ public class RentRegion extends GeneralRegion {
|
||||
}
|
||||
}
|
||||
|
||||
public void setMaxExtends(int times) {
|
||||
setSetting("rent.maxExtends", times); }
|
||||
|
||||
@Override
|
||||
public Object provideReplacement(String variable) {
|
||||
return switch (variable) {
|
||||
|
||||
@@ -1,153 +0,0 @@
|
||||
package me.wiefferink.areashop.regions;
|
||||
|
||||
import me.wiefferink.areashop.interfaces.GeneralRegionInterface;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
public class SimpleRegionContainer implements IRegionContainer {
|
||||
|
||||
private final Map<String, GeneralRegionInterface> regions = new HashMap<>();
|
||||
private final Map<String, GeneralRegion> general = new HashMap<>();
|
||||
private final Map<String, BuyRegion> buys = new HashMap<>();
|
||||
private final Map<String, RentRegion> rents = new HashMap<>();
|
||||
|
||||
private static @NotNull String sanitize(@NotNull String s) {
|
||||
return s.toLowerCase(Locale.ENGLISH);
|
||||
}
|
||||
|
||||
private static @NotNull List<String> getTrueNames(@NotNull Collection<? extends GeneralRegionInterface> regions) {
|
||||
List<String> trueNames = new ArrayList<>(regions.size());
|
||||
for (GeneralRegionInterface region : regions) {
|
||||
trueNames.add(region.getName());
|
||||
}
|
||||
return trueNames;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public GeneralRegionInterface getRegionInterface(String name) {
|
||||
return this.regions.get(sanitize(name));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public GeneralRegion getRegion(String name) {
|
||||
return this.general.get(sanitize(name));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public RentRegion getRent(String name) {
|
||||
return this.rents.get(sanitize(name));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BuyRegion getBuy(String name) {
|
||||
return this.buys.get(sanitize(name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RentRegion> getRents() {
|
||||
return new ArrayList<>(this.rents.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<RentRegion> getRentsRef() {
|
||||
return Collections.unmodifiableCollection(this.rents.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BuyRegion> getBuys() {
|
||||
return new ArrayList<>(this.buys.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<BuyRegion> getBuysRef() {
|
||||
return Collections.unmodifiableCollection(this.buys.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GeneralRegion> getRegions() {
|
||||
return new ArrayList<>(this.general.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<GeneralRegion> getRegionsRef() {
|
||||
return Collections.unmodifiableCollection(this.general.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GeneralRegionInterface> getRegionInterfaces() {
|
||||
return new ArrayList<>(this.regions.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<GeneralRegionInterface> getRegionInterfacesRef() {
|
||||
return Collections.unmodifiableCollection(this.regions.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getBuyNames() {
|
||||
return getTrueNames(this.buys.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getRentNames() {
|
||||
return getTrueNames(this.rents.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getRegionNames() {
|
||||
return getTrueNames(this.rents.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getRegionInterfaceNames() {
|
||||
return getTrueNames(this.regions.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addRegionInterface(@NotNull GeneralRegionInterface region) {
|
||||
final String name = sanitize(region.getName());
|
||||
this.regions.put(name, region);
|
||||
if (region instanceof GeneralRegion generalRegion) {
|
||||
this.general.put(name, generalRegion);
|
||||
if (region instanceof BuyRegion buyRegion) {
|
||||
this.buys.put(name, buyRegion);
|
||||
} else if (region instanceof RentRegion rentRegion) {
|
||||
this.rents.put(name, rentRegion);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeRegion(@NotNull String region) {
|
||||
final String sanitized = sanitize(region);
|
||||
this.regions.remove(sanitized);
|
||||
this.general.remove(sanitized);
|
||||
this.buys.remove(sanitized);
|
||||
this.rents.remove(sanitized);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeRegion(@NotNull GeneralRegionInterface region) {
|
||||
removeRegion(region.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearRegions() {
|
||||
this.regions.clear();
|
||||
this.general.clear();
|
||||
this.rents.clear();
|
||||
this.buys.clear();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package me.wiefferink.areashop.tools;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
public class CacheWrapper {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(CacheWrapper.class);
|
||||
private final UUID uuid;
|
||||
private final String name;
|
||||
private long lastUsed;
|
||||
|
||||
public CacheWrapper(CacheWrapper other) {
|
||||
this.uuid = other.uuid;
|
||||
this.name = other.name;
|
||||
this.lastUsed = other.lastUsed;
|
||||
}
|
||||
|
||||
public CacheWrapper(@Nonnull UUID uuid, @Nonnull String name) {
|
||||
this(uuid, name, -1);
|
||||
}
|
||||
|
||||
public CacheWrapper(@Nonnull UUID uuid, @Nonnull String name, long lastUsed) {
|
||||
this.uuid = uuid;
|
||||
this.name = name;
|
||||
this.lastUsed = lastUsed;
|
||||
}
|
||||
|
||||
public UUID getUuid() {
|
||||
return this.uuid;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
this.lastUsed = System.currentTimeMillis();
|
||||
return name;
|
||||
}
|
||||
|
||||
public long getLastUsed() {
|
||||
return lastUsed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
CacheWrapper that = (CacheWrapper) o;
|
||||
return lastUsed == that.lastUsed && Objects.equals(uuid,
|
||||
that.uuid) && Objects.equals(name, that.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(uuid, name, lastUsed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CacheWrapper{" +
|
||||
"uuid=" + uuid +
|
||||
", name='" + name + '\'' +
|
||||
", lastUsed=" + lastUsed +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import jakarta.inject.Inject;
|
||||
import me.wiefferink.areashop.AreaShop;
|
||||
import me.wiefferink.areashop.interfaces.WorldEditSelection;
|
||||
import me.wiefferink.areashop.interfaces.WorldGuardInterface;
|
||||
import me.wiefferink.areashop.managers.CacheManager;
|
||||
import me.wiefferink.areashop.regions.BuyRegion;
|
||||
import me.wiefferink.areashop.regions.GeneralRegion;
|
||||
import me.wiefferink.areashop.regions.RentRegion;
|
||||
@@ -805,10 +806,20 @@ public class Utils {
|
||||
if (uuid == null) {
|
||||
return "";
|
||||
}
|
||||
String name = Bukkit.getOfflinePlayer(uuid).getName();
|
||||
|
||||
final CacheManager cacheManager = plugin.getCacheManager();
|
||||
|
||||
if (cacheManager.contains(uuid))
|
||||
return cacheManager.get(uuid).getName();
|
||||
|
||||
|
||||
final String name = Bukkit.getOfflinePlayer(uuid).getName();
|
||||
|
||||
if (name != null) {
|
||||
cacheManager.put(uuid, new CacheWrapper(uuid, name, System.currentTimeMillis()));
|
||||
return name;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
@@ -150,6 +150,7 @@ forceClearEntities: false
|
||||
# Maximum number of locations the teleport function should check to find a safe spot.
|
||||
maximumTries: 50000
|
||||
|
||||
cacheExpiryDuration: '7d'
|
||||
|
||||
# ┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
||||
# │ VARIABLES: Variables that can be used in messages and settings where a region is available. │
|
||||
|
||||
@@ -374,6 +374,11 @@ setduration-noLandlord: You don't have permission to change the duration because
|
||||
setduration-successRemoved: 'Duration of %lang:region% has been removed, it will now
|
||||
use the duration from a group or the default.yml file, new duration: %duration%.'
|
||||
|
||||
setmaxextends-noPermission: You don't have permission to change the amount of times a region can have rent extended.
|
||||
setmaxextends-help: /as setmaxextends \<amount> [region], the region you stand in will be used if not specified.
|
||||
setmaxextends-noLandlord: You don't have permission to change the duration because you are not the landlord of %lang:region%.
|
||||
setmaxextends-success: Max extensions of %lang:region% changed to %maxextends%
|
||||
|
||||
setup-noRegion: You did not specify a region on the second line.
|
||||
setup-alreadyRentSign: The region you specified is already added to AreaShop as a
|
||||
rent region, add signs with [as] on the first line or '/as addsign'.
|
||||
|
||||
@@ -81,6 +81,7 @@ help-reload: "%lang:helpCommand|/as reload|% Reload all files and update the reg
|
||||
help-setrestore: "%lang:helpCommand|/as setrestore|% Set restoring on/off and choose profile."
|
||||
help-setprice: "%lang:helpCommand|/as setprice|% Change the price of a region."
|
||||
help-setduration: "%lang:helpCommand|/as setduration|% Change the duration of a rent region."
|
||||
help-setmaxextends: "%lang:helpCommand|/as setmaxextends|% Change the amount of times a renter can extend their rent by."
|
||||
help-settransfer: "%lang:helpCommand|/as settransfer|% Set transfer on/off."
|
||||
help-teleport: "%lang:helpCommand|/as tp|% Teleport to a rent/buy region."
|
||||
help-setteleport: "%lang:helpCommand|/as settp|% Set teleport position for a region."
|
||||
@@ -350,6 +351,11 @@ setduration-success: "Duration of region %lang:region% changed to '%duration%'."
|
||||
setduration-noLandlord: "You don't have permission to change the duration because you are not the landlord of %lang:region%."
|
||||
setduration-successRemoved: "Duration of %lang:region% has been removed, it will now use the duration from a group or the default.yml file, new duration: %duration%."
|
||||
|
||||
setmaxextends-noPermission: "You don't have permission to change the amount of times a region can have rent extended."
|
||||
setmaxextends-help: "/as setmaxextends <amount> [region], the region you stand in will be used if not specified."
|
||||
setmaxextends-noLandlord: "You don't have permission to change the duration because you are not the landlord of %lang:region%."
|
||||
setmaxextends-success: "Max extensions of %lang:region% changed to %maxextends%"
|
||||
|
||||
setup-noRegion: "You did not specify a region on the second line."
|
||||
setup-alreadyRentSign: "The region you specified is already added to AreaShop as a rent region, add signs with [as] on the first line or '/as addsign'."
|
||||
setup-alreadyOtherWorld: "The region you specified is already added to AreaShop in another world, regions from different worlds still need different names."
|
||||
|
||||
@@ -3,7 +3,7 @@ main: me.wiefferink.areashop.AreaShop
|
||||
version: "${version}"
|
||||
description: "Selling and renting WorldGuard regions to your players, highly configurable."
|
||||
depend: [Vault, WorldGuard, WorldEdit]
|
||||
softdepend: [Multiverse-Core, FastAsyncWorldEdit, Essentials, PlaceholderAPI]
|
||||
softdepend: [Multiverse-Core, FastAsyncWorldEdit, Essentials]
|
||||
authors: [NLThijs48, md5sha256, Dartanman]
|
||||
website: https://github.com/md5sha256/AreaShop
|
||||
#commands:
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
package me.wiefferink.areashop.hook.placeholders;
|
||||
|
||||
import be.seeseemelk.mockbukkit.MockBukkit;
|
||||
import be.seeseemelk.mockbukkit.ServerMock;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||
import me.wiefferink.areashop.AreaShop;
|
||||
import me.wiefferink.areashop.interfaces.GeneralRegionInterface;
|
||||
import me.wiefferink.areashop.regions.IRegionContainer;
|
||||
import me.wiefferink.areashop.regions.SimpleRegionContainer;
|
||||
import me.wiefferink.areashop.regions.MockRegionInterface;
|
||||
import org.bukkit.World;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.NumberFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
|
||||
class TestPlaceholders {
|
||||
|
||||
private static ServerMock server;
|
||||
|
||||
@BeforeAll
|
||||
static void init() {
|
||||
server = MockBukkit.mock();
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
static void teardown() {
|
||||
server = null;
|
||||
MockBukkit.unmock();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPlaceholder() {
|
||||
// Setup mock regions
|
||||
IRegionContainer regionContainer = new SimpleRegionContainer();
|
||||
final World world = server.addSimpleWorld("test");
|
||||
final String regionId = "test-region";
|
||||
final BlockVector3 location = BlockVector3.ZERO;
|
||||
ProtectedRegion protectedRegion = new ProtectedCuboidRegion(regionId, location, location);
|
||||
final Calendar calendar = Calendar.getInstance();
|
||||
final DateFormat dateFormat = new SimpleDateFormat();
|
||||
final NumberFormat numberFormat = NumberFormat.getInstance();
|
||||
final GeneralRegionInterface region = new MockRegionInterface(protectedRegion, regionId, world, calendar, dateFormat);
|
||||
regionContainer.addRegionInterface(region);
|
||||
// Test the expansion
|
||||
PlaceholderExpansion expansion = new BuiltinRegionExpansion(regionContainer);
|
||||
final String actualRegionName = expansion.onRequest(null, String.format("%s_%s", regionId, AreaShop.tagRegionName));
|
||||
Assertions.assertEquals(regionId, actualRegionName);
|
||||
final String actualWorldName = expansion.onRequest(null, String.format("%s_%s", regionId, AreaShop.tagWorldName));
|
||||
Assertions.assertEquals(world.getName(), actualWorldName);
|
||||
final String zero = "0";
|
||||
for (String tag : new String[]{AreaShop.tagWidth, AreaShop.tagHeight, AreaShop.tagWidth}) {
|
||||
final String actual = expansion.onRequest(null, String.format("%s_%s", regionId, tag));
|
||||
Assertions.assertEquals(zero, actual);
|
||||
}
|
||||
final String actualEpoch = expansion.onRequest(null, String.format("%s_%s", regionId, AreaShop.tagEpoch));
|
||||
Assertions.assertEquals(numberFormat.format(calendar.getTimeInMillis()), actualEpoch);
|
||||
final String actualMillis = expansion.onRequest(null, String.format("%s_%s", regionId, AreaShop.tagMillisecond));
|
||||
Assertions.assertEquals(numberFormat.format(calendar.get(Calendar.MILLISECOND)), actualMillis);
|
||||
final String actualSecond = expansion.onRequest(null, String.format("%s_%s", regionId, AreaShop.tagSecond));
|
||||
Assertions.assertEquals(numberFormat.format(calendar.get(Calendar.SECOND)), actualSecond);
|
||||
final String actualMinute = expansion.onRequest(null, String.format("%s_%s", regionId, AreaShop.tagMinute));
|
||||
Assertions.assertEquals(numberFormat.format(calendar.get(Calendar.MINUTE)), actualMinute);
|
||||
final String actualHour = expansion.onRequest(null, String.format("%s_%s", regionId, AreaShop.tagHour));
|
||||
Assertions.assertEquals(numberFormat.format(calendar.get(Calendar.HOUR_OF_DAY)), actualHour);
|
||||
final String actualDay = expansion.onRequest(null, String.format("%s_%s", regionId, AreaShop.tagDay));
|
||||
Assertions.assertEquals(numberFormat.format(calendar.get(Calendar.DAY_OF_MONTH)), actualDay);
|
||||
final String actualMonth = expansion.onRequest(null, String.format("%s_%s", regionId, AreaShop.tagMonth));
|
||||
Assertions.assertEquals(numberFormat.format(calendar.get(Calendar.MONTH) + 1), actualMonth);
|
||||
final String actualYear = expansion.onRequest(null, String.format("%s_%s", regionId, AreaShop.tagYear));
|
||||
Assertions.assertEquals(numberFormat.format(calendar.get(Calendar.YEAR)), actualYear);
|
||||
final String actualDate = expansion.onRequest(null, String.format("%s_%s", regionId, AreaShop.tagDateTime));
|
||||
Assertions.assertEquals(dateFormat.format(calendar.getTime()), actualDate);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
package me.wiefferink.areashop.regions;
|
||||
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
import me.wiefferink.areashop.AreaShop;
|
||||
import me.wiefferink.areashop.interfaces.GeneralRegionInterface;
|
||||
import me.wiefferink.interactivemessenger.processing.ReplacementProvider;
|
||||
import org.bukkit.World;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.util.Calendar;
|
||||
|
||||
public record MockRegionInterface(ProtectedRegion region, String name, World world, Calendar calendar, DateFormat dateFormat) implements GeneralRegionInterface, ReplacementProvider {
|
||||
|
||||
@Override
|
||||
public ProtectedRegion getRegion() {
|
||||
return this.region;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public World getWorld() {
|
||||
return this.world;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWorldName() {
|
||||
return this.world.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWidth() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDepth() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeight() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object provideReplacement(String variable) {
|
||||
return switch (variable) {
|
||||
case AreaShop.tagRegionName -> this.region.getId();
|
||||
case AreaShop.tagWorldName -> this.world.getName();
|
||||
case AreaShop.tagWidth -> getWidth();
|
||||
case AreaShop.tagDepth -> getDepth();
|
||||
case AreaShop.tagHeight -> getHeight();
|
||||
// Date/time
|
||||
case AreaShop.tagEpoch -> this.calendar.getTimeInMillis();
|
||||
case AreaShop.tagMillisecond -> this.calendar.get(Calendar.MILLISECOND);
|
||||
case AreaShop.tagSecond -> this.calendar.get(Calendar.SECOND);
|
||||
case AreaShop.tagMinute -> this.calendar.get(Calendar.MINUTE);
|
||||
case AreaShop.tagHour -> this.calendar.get(Calendar.HOUR_OF_DAY);
|
||||
case AreaShop.tagDay -> this.calendar.get(Calendar.DAY_OF_MONTH);
|
||||
case AreaShop.tagMonth -> this.calendar.get(Calendar.MONTH) + 1;
|
||||
case AreaShop.tagYear -> this.calendar.get(Calendar.YEAR);
|
||||
case AreaShop.tagDateTime, AreaShop.tagDateTimeShort -> this.dateFormat.format(this.calendar.getTime());
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
package me.wiefferink.areashop.regions;
|
||||
|
||||
import be.seeseemelk.mockbukkit.MockBukkit;
|
||||
import be.seeseemelk.mockbukkit.ServerMock;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
import me.wiefferink.areashop.interfaces.GeneralRegionInterface;
|
||||
import org.bukkit.World;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
class TestSimpleRegionContainer {
|
||||
|
||||
private static ServerMock server;
|
||||
|
||||
@BeforeAll
|
||||
static void init() {
|
||||
server = MockBukkit.mock();
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
static void teardown() {
|
||||
MockBukkit.unmock();
|
||||
}
|
||||
|
||||
static GeneralRegionInterface generateRegion(@NotNull String name) {
|
||||
final ProtectedRegion region = new ProtectedCuboidRegion("null", BlockVector3.ZERO, BlockVector3.ZERO);
|
||||
final World world = server.addSimpleWorld("world");
|
||||
final Calendar calendar = Calendar.getInstance();
|
||||
final DateFormat dateFormat = new SimpleDateFormat();
|
||||
return new MockRegionInterface(region, name, world, calendar, dateFormat);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRegionAddRemove() {
|
||||
final IRegionContainer regionContainer = new SimpleRegionContainer();
|
||||
final String sanitizedName = "test";
|
||||
final String dirtyName = "TEST";
|
||||
final GeneralRegionInterface regionInterface = generateRegion(sanitizedName);
|
||||
Assertions.assertNull(regionContainer.getRegion(sanitizedName));
|
||||
Assertions.assertNull(regionContainer.getRegion(dirtyName));
|
||||
regionContainer.addRegionInterface(regionInterface);
|
||||
Assertions.assertSame(regionInterface, regionContainer.getRegionInterface(sanitizedName));
|
||||
Assertions.assertSame(regionInterface, regionContainer.getRegionInterface(dirtyName));
|
||||
final List<String> actualNames = regionContainer.getRegionInterfaceNames();
|
||||
Assertions.assertEquals(1, actualNames.size());
|
||||
Assertions.assertEquals(sanitizedName, actualNames.get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCollectionGetters() {
|
||||
final IRegionContainer regionContainer = new SimpleRegionContainer();
|
||||
final String sanitizedName = "test";
|
||||
final GeneralRegionInterface regionInterface = generateRegion(sanitizedName);
|
||||
regionContainer.addRegionInterface(regionInterface);
|
||||
testCollectionAndRef(1, regionContainer.getRegionInterfacesRef(), regionContainer.getRegionInterfaces());
|
||||
final Collection<GeneralRegionInterface> regionInterfaces = regionContainer.getRegionInterfaces();
|
||||
Assertions.assertTrue(regionInterfaces.contains(regionInterface));
|
||||
testCollectionAndRef(0, regionContainer.getRegionsRef(), regionContainer.getRegions());
|
||||
testCollectionAndRef(0, regionContainer.getBuysRef(), regionContainer.getBuys());
|
||||
testCollectionAndRef(0, regionContainer.getRentsRef(), regionContainer.getRents());
|
||||
|
||||
}
|
||||
|
||||
private static <T> void testCollectionAndRef(int expectedSize, Collection<T> ref, Collection<T> copy) {
|
||||
Assertions.assertEquals(expectedSize, ref.size());
|
||||
Assertions.assertEquals(ref.size(), copy.size());
|
||||
try {
|
||||
copy.clear();
|
||||
} catch (Throwable ex) {
|
||||
Assertions.fail("Failed to modify the copy", ex);
|
||||
return;
|
||||
}
|
||||
Assertions.assertThrows(UnsupportedOperationException.class, ref::clear);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,3 +1,8 @@
|
||||
<h1>
|
||||
The project is no longer maintained. See this alternative <a href="https://github.com/MCCitiesNetwork/realty">realty</a>
|
||||
</h1>
|
||||
<br>
|
||||
|
||||
<br/>
|
||||
[](https://jitpack.io/#md5sha256/AreaShop)
|
||||
<br>
|
||||
@@ -74,4 +79,4 @@ For a preview join 'mc.go-craft.com' and go to the Survival server, the shops ar
|
||||
**Made by [PerkulatorTime](https://www.youtube.com/user/PerkulatorTime)**<br/>
|
||||
[](https://www.youtube.com/watch?v=OQOsOG-EdNc)
|
||||
|
||||
Old video for AreaShop v1.0: [Tutorial by VariationVault](https://www.youtube.com/watch?v=k2HMCxCCOYo)
|
||||
Old video for AreaShop v1.0: [Tutorial by VariationVault](https://www.youtube.com/watch?v=k2HMCxCCOYo)
|
||||
@@ -53,10 +53,6 @@ subprojects {
|
||||
}
|
||||
maven("https://repo.aikar.co/content/groups/aikar/")
|
||||
maven("https://maven.enginehub.org/repo/")
|
||||
maven {
|
||||
name = "extendedclip-repo"
|
||||
url = uri("https://repo.extendedclip.com/content/repositories/placeholderapi/")
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[versions]
|
||||
# Platforms
|
||||
minecraft = "1.21-R0.1-SNAPSHOT"
|
||||
minecraft = "1.21.1-R0.1-SNAPSHOT"
|
||||
|
||||
# Minecraft Plugins
|
||||
worldedit = "7.3.3"
|
||||
|
||||
Reference in new issue
Block a user