Compare commits

...
Author SHA1 Message Date
Andrew Wong 3d6acba83e Merge branch 'dev/bleeding' into feature/papi 2025-01-12 14:35:53 +08:00
Andrew Wong 72c4a76c6c Save regions async 2025-01-12 14:00:31 +08:00
Andrew Wong c9e7e3cdbb Bump gradle verstion to 8.11.1 2025-01-12 10:17:48 +08:00
Andrew Wong f283f8b33c Merge branch 'dev/bleeding' into feature/papi 2024-10-07 16:51:13 +11:00
Andrew Wong 4ceff1b80e Update mockbukkit 2024-10-07 16:31:55 +11:00
Andrew Wong 8e88dc7b6b Update gradle wrapper 2024-10-07 16:23:41 +11:00
Andrew Wong 2762ebae1d Supplement OfflinePlayer#hasPlayedBefore checks with #isOnline checks 2024-08-08 20:34:49 +10:00
Andrew Wong 5742dd623e Fix as me command to have the player arg be properly optional 2024-08-04 21:51:44 +10:00
Andrew Wong e5d190d81e Revert "Remove argument from me command"
This reverts commit b631cfc89d.
2024-08-04 21:50:39 +10:00
Andrew Wong b631cfc89d Remove argument from me command 2024-08-04 21:10:04 +10:00
Andrew Wong 399b166339 Sync back to main after looking up offline player async 2024-08-03 18:10:17 +10:00
Andrew Wong b556cb1bce Refactor commands to avoid main thread offline player lookup 2024-08-01 11:12:19 +10:00
Andrew Wong 105274b633 Snapshot 2.9.2 2024-08-01 11:11:54 +10:00
Andrew Wong 9b036dad93 Release 2.9.1 2024-07-24 14:47:35 +10:00
Andrew Wong 628aa83089 Update cloud to beta.9 2024-07-24 14:45:59 +10:00
Andrew Wong 11da15454d Enforce min version to 1.21 2024-07-24 14:45:59 +10:00
Andrew Wong ff2e4e235d Compile against 1.21, bump version to 2.9.1-SNAPSHOT 2024-07-24 14:45:59 +10:00
Andrew Wong 88c7b7a4bd Release 2.9.0 2024-07-24 14:04:44 +10:00
Andrew Wong cd3a7e97a7 Remove extra listener for SignChangeEvent in SignListener 2024-07-24 14:04:13 +10:00
Andrew Wong d33739491a Revert "Release 2.9.0"
This reverts commit ff59fa7f70.
2024-07-24 13:35:27 +10:00
Andrew Wong 5488deb0d7 Fix message sending errors in the ArgumentParseHandler, fix issue with quickbuy and quickrent where newly joined playes are treated as invalid 2024-07-24 13:35:09 +10:00
Andrew Wong ff59fa7f70 Release 2.9.0 2024-07-24 13:21:03 +10:00
Andrew Wong 219ba0335e Remove paperweight userdev, update cloud to 2.0.0-beta.8 2024-07-24 13:15:08 +10:00
Andrew Wong 724439da7d Remove BukkitInterface 2024-06-30 17:43:23 +10:00
Andrew Wong 7bebca5dca Inline BlockBehaviourHelper, remove areashop-nms and areashop-platform-modern 2024-06-30 17:37:45 +10:00
Andrew Wong 5989ecbcbc Handle new SignChangeEvent in the sign listener 2024-06-28 21:39:15 +10:00
Andrew Wong 386487c8a4 Refactor the file manager to delegate to a IRegionContainer and add tests for SimpleRegionContainer 2022-09-18 15:31:36 +08:00
Andrew Wong 10b33a49cc Refactor the FileManager and add placeholder support 2022-09-18 03:21:26 +08:00
50 changed files with 1161 additions and 557 deletions

No files matched your search

+22 -22
View File
@@ -14,11 +14,10 @@ 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")
@@ -31,7 +30,7 @@ dependencies {
api("com.google.inject.extensions:guice-assistedinject:7.0.0") {
exclude("com.google.guava")
}
implementation("org.incendo:cloud-paper:2.0.0-SNAPSHOT") {
implementation("org.incendo:cloud-paper:2.0.0-beta.9") {
exclude("com.google.guava")
}
implementation("org.incendo:cloud-processors-confirmation:1.0.0-beta.3") {
@@ -41,9 +40,10 @@ 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.areashopNms)
api(projects.adapters.platform.platformInterface)
api(projects.adapters.platform.paper)
@@ -53,20 +53,19 @@ dependencies {
runtimeOnly(projects.adapters.plugins.worldguard)
runtimeOnly(projects.adapters.plugins.fastasyncworldedit)
runtimeOnly(projects.adapters.plugins.essentials)
runtimeOnly(projects.adapters.platform.bukkitModern)
}
testImplementation("io.papermc.paper:paper-api:1.20.4-R0.1-SNAPSHOT")
testImplementation("com.github.seeseemelk:MockBukkit-v1.20:3.86.1")
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") {
@@ -119,20 +118,21 @@ tasks {
relocate("com.google.errorprone", "${base}.errorprone")
relocate("org.aopalliance", "${base}.aopalliance")
relocate("javax.annotation", "${base}.javax.annotation")
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")
relocate("javax.inject", "${base}.javax.inject")
relocate("org.jetbrains.annotation", "${base}.jetbrains.annotations")
}
test {
useJUnitPlatform()
testLogging {
events("passed", "skipped", "failed")
}
}
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.20.6")
minecraftVersion("1.21")
downloadPlugins {
github("EssentialsX", "essentials", "2.20.1", "EssentialsX-2.20.1.jar")
@@ -12,6 +12,7 @@ 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;
@@ -26,7 +27,6 @@ import me.wiefferink.areashop.modules.AreaShopModule;
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.services.ServiceManager;
import me.wiefferink.areashop.tools.GithubUpdateCheck;
import me.wiefferink.areashop.tools.LanguageConverter;
@@ -79,7 +79,6 @@ public final class AreaShop extends JavaPlugin implements AreaShopApi {
private WorldGuardInterface worldGuardInterface = null;
private WorldEditPlugin worldEdit = null;
private WorldEditInterface worldEditInterface = null;
private PlatformAdapter platformAdapter;
private MessageBridge messageBridge;
private IFileManager fileManager = null;
private LanguageManager languageManager = null;
@@ -183,18 +182,8 @@ public final class AreaShop extends JavaPlugin implements AreaShopApi {
// Setup NMS Impl
Version currentServerVersion = VersionUtil.parseMinecraftVersion(Bukkit.getBukkitVersion());
if (currentServerVersion.versionData().isOlderThan(VersionUtil.MC_1_20_6)) {
error("Unsupported minecraft version: " + currentServerVersion + "! Minimum is 1.20.6");
shutdownOnError();
return;
}
try {
Class<?> adapterImpl = Class.forName("me.wiefferink.areashop.adapters.platform.modern.ModernPlatformAdapter");
this.platformAdapter = adapterImpl.asSubclass(PlatformAdapter.class).getConstructor().newInstance();
} catch (ReflectiveOperationException ex) {
ex.printStackTrace();
error("Failed to initialize modern PlatformAdapter implementation!");
if (currentServerVersion.versionData().isOlderThan(VersionUtil.MC_1_21)) {
error("Unsupported minecraft version: " + currentServerVersion + "! Minimum is 1.21");
shutdownOnError();
return;
}
@@ -207,7 +196,7 @@ public final class AreaShop extends JavaPlugin implements AreaShopApi {
platform = new SpigotPlatform(this);
info("Detected Spigot; using the SpigotPlatform impl");
}
final PlatformModule platformModule = new PlatformModule(platform, this.platformAdapter);
final PlatformModule platformModule = new PlatformModule(platform);
// Check if Vault is present
if(getServer().getPluginManager().getPlugin("Vault") == null) {
@@ -313,6 +302,12 @@ 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();
@@ -502,10 +497,6 @@ public final class AreaShop extends JavaPlugin implements AreaShopApi {
this.chatprefix = chatprefix;
}
public PlatformAdapter getPlatformAdapter() {
return platformAdapter;
}
public SignErrorLogger getSignErrorLogger() {
return signErrorLogger;
}
@@ -3,15 +3,17 @@ package me.wiefferink.areashop.commands;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.adapters.platform.OfflinePlayerHelper;
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
import me.wiefferink.areashop.commands.util.OfflinePlayerParser;
import me.wiefferink.areashop.commands.util.RegionParseUtil;
import me.wiefferink.areashop.commands.util.ValidatedOfflinePlayerParser;
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
import me.wiefferink.areashop.commands.util.commandsource.PlayerCommandSource;
import me.wiefferink.areashop.managers.IFileManager;
import me.wiefferink.areashop.regions.BuyRegion;
import me.wiefferink.areashop.regions.GeneralRegion;
import me.wiefferink.areashop.regions.RentRegion;
import me.wiefferink.areashop.tools.BukkitSchedulerExecutor;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@@ -28,20 +30,26 @@ import javax.annotation.Nonnull;
@Singleton
public class AddFriendCommand extends AreashopCommandBean {
private static final CloudKey<OfflinePlayer> KEY_FRIEND = CloudKey.of("friend", OfflinePlayer.class);
private static final CloudKey<String> KEY_FRIEND = CloudKey.of("friend", String.class);
private final CommandFlag<GeneralRegion> regionFlag;
private final MessageBridge messageBridge;
private final Plugin plugin;
private final BukkitSchedulerExecutor executor;
private final OfflinePlayerHelper offlinePlayerHelper;
@Inject
public AddFriendCommand(
@Nonnull MessageBridge messageBridge,
@Nonnull IFileManager fileManager,
@Nonnull Plugin plugin
@Nonnull Plugin plugin,
@Nonnull BukkitSchedulerExecutor executor,
@Nonnull OfflinePlayerHelper offlinePlayerHelper
) {
this.messageBridge = messageBridge;
this.plugin = plugin;
this.regionFlag = RegionParseUtil.createDefault(fileManager);
this.executor = executor;
this.offlinePlayerHelper = offlinePlayerHelper;
}
@Override
@@ -61,7 +69,7 @@ public class AddFriendCommand extends AreashopCommandBean {
protected @Nonnull Command.Builder<? extends CommandSource<?>> configureCommand(@Nonnull Command.Builder<CommandSource<?>> builder) {
return builder.literal("addfriend")
.senderType(PlayerCommandSource.class)
.required(KEY_FRIEND, ValidatedOfflinePlayerParser.validatedOfflinePlayerParser())
.required(KEY_FRIEND, OfflinePlayerParser.parser())
.flag(this.regionFlag)
.handler(this::handleCommand);
}
@@ -73,31 +81,49 @@ public class AddFriendCommand extends AreashopCommandBean {
return;
}
GeneralRegion region = RegionParseUtil.getOrParseRegion(context, sender, this.regionFlag);
OfflinePlayer friend = context.get(KEY_FRIEND);
this.offlinePlayerHelper.lookupOfflinePlayerAsync(context.get(KEY_FRIEND))
.whenCompleteAsync((offlinePlayer, exception) -> {
if (exception != null) {
sender.sendMessage("failed to lookup offline player!");
exception.printStackTrace();
return;
}
if (!offlinePlayer.hasPlayedBefore() && !offlinePlayer.isOnline()) {
this.messageBridge.message(sender, "cmd-invalidPlayer", offlinePlayer.getName());
return;
}
processWithFriend(sender, region, offlinePlayer);
}, this.executor);
}
private void processWithFriend(@Nonnull Player sender,
@Nonnull GeneralRegion region,
@Nonnull OfflinePlayer friend
) {
if (sender.hasPermission("areashop.addfriendall") && ((region instanceof RentRegion rentRegion && !rentRegion.isRented())
|| (region instanceof BuyRegion buyRegion && !buyRegion.isSold()))) {
this.messageBridge.message(sender, "addfriend-noOwner", region);
this.messageBridge.message(sender, "addfriend-noOwner", region);
return;
}
if (!sender.hasPermission("areashop.addfriend")) {
this.messageBridge.message(sender, "addfriend-noPermission", region);
this.messageBridge.message(sender, "addfriend-noPermission", region);
return;
}
if (!region.isOwner(sender)) {
this.messageBridge.message(sender, "addfriend-noPermissionOther", region);
this.messageBridge.message(sender, "addfriend-noPermissionOther", region);
return;
}
if (!friend.hasPlayedBefore() && !friend.isOnline() && !plugin.getConfig()
.getBoolean("addFriendNotExistingPlayers")) {
this.messageBridge.message(sender, "addfriend-notVisited", friend.getName(), region);
this.messageBridge.message(sender, "addfriend-notVisited", friend.getName(), region);
} else if (region.getFriendsFeature().getFriends().contains(friend.getUniqueId())) {
this.messageBridge.message(sender, "addfriend-alreadyAdded", friend.getName(), region);
this.messageBridge.message(sender, "addfriend-alreadyAdded", friend.getName(), region);
} else if (region.isOwner(friend.getUniqueId())) {
this.messageBridge.message(sender, "addfriend-self", friend.getName(), region);
this.messageBridge.message(sender, "addfriend-self", friend.getName(), region);
} else if (region.getFriendsFeature().addFriend(friend.getUniqueId(), sender)) {
region.update();
this.messageBridge.message(sender, "addfriend-success", friend.getName(), region);
this.messageBridge.message(sender, "addfriend-success", friend.getName(), region);
}
}
@@ -3,16 +3,18 @@ package me.wiefferink.areashop.commands;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.adapters.platform.OfflinePlayerHelper;
import me.wiefferink.areashop.commands.util.AreaShopCommandException;
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
import me.wiefferink.areashop.commands.util.OfflinePlayerParser;
import me.wiefferink.areashop.commands.util.RegionParseUtil;
import me.wiefferink.areashop.commands.util.ValidatedOfflinePlayerParser;
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
import me.wiefferink.areashop.features.FriendsFeature;
import me.wiefferink.areashop.managers.IFileManager;
import me.wiefferink.areashop.regions.BuyRegion;
import me.wiefferink.areashop.regions.GeneralRegion;
import me.wiefferink.areashop.regions.RentRegion;
import me.wiefferink.areashop.tools.BukkitSchedulerExecutor;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@@ -34,17 +36,23 @@ import java.util.concurrent.CompletableFuture;
public class DelFriendCommand extends AreashopCommandBean {
private static final CloudKey<OfflinePlayer> KEY_PLAYER = CloudKey.of("player", OfflinePlayer.class);
private static final CloudKey<String> KEY_PLAYER = CloudKey.of("player", String.class);
private final MessageBridge messageBridge;
private final CommandFlag<GeneralRegion> regionFlag;
private final OfflinePlayerHelper offlinePlayerHelper;
private final BukkitSchedulerExecutor executor;
@Inject
public DelFriendCommand(
@Nonnull MessageBridge messageBridge,
@Nonnull IFileManager fileManager
@Nonnull IFileManager fileManager,
@Nonnull OfflinePlayerHelper offlinePlayerHelper,
@Nonnull BukkitSchedulerExecutor executor
) {
this.messageBridge = messageBridge;
this.regionFlag = RegionParseUtil.createDefault(fileManager);
this.offlinePlayerHelper = offlinePlayerHelper;
this.executor = executor;
}
/**
@@ -85,7 +93,7 @@ public class DelFriendCommand extends AreashopCommandBean {
@Override
protected @Nonnull Command.Builder<? extends CommandSource<?>> configureCommand(@Nonnull Command.Builder<CommandSource<?>> builder) {
return builder.literal("delfriend", "deletefriend")
.required(KEY_PLAYER, ValidatedOfflinePlayerParser.validatedOfflinePlayerParser(), this::suggestFriends)
.required(KEY_PLAYER, OfflinePlayerParser.parser(), this::suggestFriends)
.flag(this.regionFlag)
.handler(this::handleCommand);
}
@@ -96,7 +104,24 @@ public class DelFriendCommand extends AreashopCommandBean {
throw new AreaShopCommandException("delfriend-noPermission");
}
GeneralRegion region = RegionParseUtil.getOrParseRegion(context, sender, this.regionFlag);
OfflinePlayer friend = context.get(KEY_PLAYER);
this.offlinePlayerHelper.lookupOfflinePlayerAsync(context.get(KEY_PLAYER))
.whenCompleteAsync((offlinePlayer, exception) -> {
if (exception != null) {
sender.sendMessage("failed to lookup offline player!");
exception.printStackTrace();
return;
}
if (!offlinePlayer.hasPlayedBefore() && !offlinePlayer.isOnline()) {
this.messageBridge.message(sender, "cmd-invalidPlayer", offlinePlayer.getName());
return;
}
processWithSender(sender, region, offlinePlayer);
}, this.executor);
}
private void processWithSender(@Nonnull CommandSender sender,
@Nonnull GeneralRegion region,
@Nonnull OfflinePlayer friend) {
FriendsFeature friendsFeature = region.getFriendsFeature();
if (sender.hasPermission("areashop.delfriendall")) {
if ((region instanceof RentRegion rentRegion && !rentRegion.isRented())
@@ -3,12 +3,13 @@ package me.wiefferink.areashop.commands;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.adapters.platform.OfflinePlayerHelper;
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
import me.wiefferink.areashop.commands.util.OfflinePlayerParser;
import me.wiefferink.areashop.commands.util.RegionInfoUtil;
import me.wiefferink.areashop.commands.util.ValidatedOfflinePlayerParser;
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
import me.wiefferink.areashop.managers.IFileManager;
import org.bukkit.OfflinePlayer;
import me.wiefferink.areashop.tools.BukkitSchedulerExecutor;
import org.bukkit.command.CommandSender;
import org.incendo.cloud.Command;
import org.incendo.cloud.bean.CommandProperties;
@@ -20,18 +21,24 @@ import javax.annotation.Nonnull;
@Singleton
public class InfoPlayerCommand extends AreashopCommandBean {
private static final CloudKey<OfflinePlayer> KEY_PLAYER = CloudKey.of("player", OfflinePlayer.class);
private static final CloudKey<String> KEY_PLAYER = CloudKey.of("player", String.class);
private final MessageBridge messageBridge;
private final IFileManager fileManager;
private final OfflinePlayerHelper offlinePlayerHelper;
private final BukkitSchedulerExecutor executor;
@Inject
public InfoPlayerCommand(
@Nonnull MessageBridge messageBridge,
@Nonnull IFileManager fileManager
@Nonnull IFileManager fileManager,
@Nonnull OfflinePlayerHelper offlinePlayerHelper,
@Nonnull BukkitSchedulerExecutor executor
) {
this.messageBridge = messageBridge;
this.fileManager = fileManager;
this.offlinePlayerHelper = offlinePlayerHelper;
this.executor = executor;
}
@Override
@@ -47,7 +54,7 @@ public class InfoPlayerCommand extends AreashopCommandBean {
@Override
protected @Nonnull Command.Builder<? extends CommandSource<?>> configureCommand(@Nonnull Command.Builder<CommandSource<?>> builder) {
return builder.literal("info").literal("player")
.required(KEY_PLAYER, ValidatedOfflinePlayerParser.validatedOfflinePlayerParser())
.required(KEY_PLAYER, OfflinePlayerParser.parser())
.handler(this::handleCommand);
}
@@ -62,8 +69,19 @@ public class InfoPlayerCommand extends AreashopCommandBean {
messageBridge.message(sender, "info-noPermission");
return;
}
OfflinePlayer offlinePlayer = context.get(KEY_PLAYER);
RegionInfoUtil.showRegionInfo(this.messageBridge, this.fileManager, sender, offlinePlayer);
this.offlinePlayerHelper.lookupOfflinePlayerAsync(context.get(KEY_PLAYER))
.whenCompleteAsync((offlinePlayer, exception) -> {
if (exception != null) {
sender.sendMessage("failed to lookup offline player!");
exception.printStackTrace();
return;
}
if (!offlinePlayer.hasPlayedBefore() && !offlinePlayer.isOnline()) {
this.messageBridge.message(sender, "cmd-invalidPlayer", offlinePlayer.getName());
return;
}
RegionInfoUtil.showRegionInfo(this.messageBridge, this.fileManager, sender, offlinePlayer);
}, this.executor);
}
}
@@ -3,14 +3,15 @@ package me.wiefferink.areashop.commands;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.adapters.platform.OfflinePlayerHelper;
import me.wiefferink.areashop.commands.util.AreaShopCommandException;
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
import me.wiefferink.areashop.commands.util.OfflinePlayerParser;
import me.wiefferink.areashop.commands.util.RegionInfoUtil;
import me.wiefferink.areashop.commands.util.ValidatedOfflinePlayerParser;
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
import me.wiefferink.areashop.commands.util.commandsource.PlayerCommandSource;
import me.wiefferink.areashop.managers.IFileManager;
import org.bukkit.OfflinePlayer;
import me.wiefferink.areashop.tools.BukkitSchedulerExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -25,17 +26,23 @@ import javax.annotation.Nonnull;
@Singleton
public class MeCommand extends AreashopCommandBean {
private static final CloudKey<OfflinePlayer> KEY_PLAYER = CloudKey.of("player", OfflinePlayer.class);
private static final CloudKey<String> KEY_PLAYER = CloudKey.of("player", String.class);
private final IFileManager fileManager;
private final MessageBridge messageBridge;
private final OfflinePlayerHelper offlinePlayerHelper;
private final BukkitSchedulerExecutor executor;
@Inject
public MeCommand(
@Nonnull MessageBridge messageBridge,
@Nonnull IFileManager fileManager
@Nonnull IFileManager fileManager,
@Nonnull OfflinePlayerHelper offlinePlayerHelper,
@Nonnull BukkitSchedulerExecutor executor
) {
this.messageBridge = messageBridge;
this.fileManager = fileManager;
this.offlinePlayerHelper = offlinePlayerHelper;
this.executor = executor;
}
@Override
@@ -47,7 +54,7 @@ public class MeCommand extends AreashopCommandBean {
protected Command.Builder<? extends CommandSource<?>> configureCommand(Command.@NotNull Builder<CommandSource<?>> builder) {
return builder.literal("me")
.senderType(PlayerCommandSource.class)
.optional(KEY_PLAYER, ValidatedOfflinePlayerParser.validatedOfflinePlayerParser())
.optional(KEY_PLAYER, OfflinePlayerParser.parser())
.handler(this::handleCommand);
}
@@ -69,8 +76,23 @@ public class MeCommand extends AreashopCommandBean {
if (!sender.hasPermission("areashop.me")) {
throw new AreaShopCommandException("me-noPermission");
}
OfflinePlayer player = context.getOrDefault(KEY_PLAYER, sender);
RegionInfoUtil.showRegionInfo(this.messageBridge, this.fileManager, sender, player);
if (!context.contains(KEY_PLAYER)) {
RegionInfoUtil.showRegionInfo(this.messageBridge, this.fileManager, sender, sender);
return;
}
this.offlinePlayerHelper.lookupOfflinePlayerAsync(context.get(KEY_PLAYER))
.whenCompleteAsync((offlinePlayer, exception) -> {
if (exception != null) {
sender.sendMessage("failed to lookup offline player!");
exception.printStackTrace();
return;
}
if (!offlinePlayer.hasPlayedBefore() && !offlinePlayer.isOnline()) {
this.messageBridge.message(sender, "cmd-invalidPlayer", offlinePlayer.getName());
return;
}
RegionInfoUtil.showRegionInfo(this.messageBridge, this.fileManager, sender, offlinePlayer);
}, this.executor);
}
}
@@ -3,18 +3,18 @@ package me.wiefferink.areashop.commands;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.adapters.platform.OfflinePlayerHelper;
import me.wiefferink.areashop.commands.util.AreaShopCommandException;
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
import me.wiefferink.areashop.commands.util.ArgumentParseExceptionHandler;
import me.wiefferink.areashop.commands.util.OfflinePlayerParser;
import me.wiefferink.areashop.commands.util.RegionCreationUtil;
import me.wiefferink.areashop.commands.util.ValidatedOfflinePlayerParser;
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
import me.wiefferink.areashop.commands.util.commandsource.PlayerCommandSource;
import me.wiefferink.areashop.managers.IFileManager;
import me.wiefferink.areashop.regions.BuyRegion;
import me.wiefferink.areashop.regions.RegionFactory;
import me.wiefferink.areashop.tools.BukkitSchedulerExecutor;
import org.bukkit.OfflinePlayer;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@@ -34,12 +34,13 @@ public class QuickBuyCommand extends AreashopCommandBean {
private static final CloudKey<String> KEY_REGION = CloudKey.of("region", String.class);
private static final CloudKey<Double> KEY_PRICE = CloudKey.of("price", Double.class);
private static final CloudKey<OfflinePlayer> KEY_LANDLORD = CloudKey.of("landlord", OfflinePlayer.class);
private static final CloudKey<String> KEY_LANDLORD = CloudKey.of("landlord", String.class);
private final RegionFactory regionFactory;
private final IFileManager fileManager;
private final MessageBridge messageBridge;
private final RegionCreationUtil regionCreationUtil;
private final BukkitSchedulerExecutor executor;
private final OfflinePlayerHelper offlinePlayerHelper;
@Inject
public QuickBuyCommand(
@@ -47,13 +48,15 @@ public class QuickBuyCommand extends AreashopCommandBean {
@Nonnull RegionFactory regionFactory,
@Nonnull IFileManager fileManager,
@Nonnull RegionCreationUtil regionCreationUtil,
@Nonnull BukkitSchedulerExecutor executor
@Nonnull BukkitSchedulerExecutor executor,
@Nonnull OfflinePlayerHelper offlinePlayerHelper
) {
this.messageBridge = messageBridge;
this.regionFactory = regionFactory;
this.fileManager = fileManager;
this.regionCreationUtil = regionCreationUtil;
this.executor = executor;
this.offlinePlayerHelper = offlinePlayerHelper;
}
@Override
@@ -69,7 +72,7 @@ public class QuickBuyCommand extends AreashopCommandBean {
.senderType(PlayerCommandSource.class)
.required(KEY_REGION, StringParser.stringParser())
.required(KEY_PRICE, DoubleParser.doubleParser(0))
.required(KEY_LANDLORD, ValidatedOfflinePlayerParser.validatedOfflinePlayerParser())
.required(KEY_LANDLORD, OfflinePlayerParser.parser())
.handler(this::handleCommand);
}
@@ -96,20 +99,26 @@ public class QuickBuyCommand extends AreashopCommandBean {
return;
}
double price = context.get(KEY_PRICE);
this.offlinePlayerHelper.lookupOfflinePlayerAsync(context.get(KEY_LANDLORD))
.whenCompleteAsync((landlord, exception) -> {
if (exception != null) {
player.sendMessage("failed to lookup offline player!");
exception.printStackTrace();
return;
}
if (!landlord.isOnline() && !landlord.hasPlayedBefore()) {
this.messageBridge.message(player, "me-noPlayer", landlord.getName());
return;
}
String regionName = region.getId();
World world = player.getWorld();
OfflinePlayer landlord = context.get(KEY_LANDLORD);
if (!landlord.hasPlayedBefore()) {
this.messageBridge.message(player, "me-noPlayer");
return;
}
String regionName = region.getId();
World world = player.getWorld();
BuyRegion buyRegion = this.regionFactory.createBuyRegion(regionName, world);
buyRegion.setPrice(price);
buyRegion.setLandlord(landlord.getUniqueId(), landlord.getName());
this.fileManager.addRegion(buyRegion);
this.messageBridge.message(player, "add-success", "buy", regionName);
BuyRegion buyRegion = this.regionFactory.createBuyRegion(regionName, world);
buyRegion.setPrice(price);
buyRegion.setLandlord(landlord.getUniqueId(), landlord.getName());
this.fileManager.addRegion(buyRegion);
this.messageBridge.message(player, "add-success", "buy", regionName);
}, this.executor);
}, this.executor);
}
@@ -126,4 +135,4 @@ public class QuickBuyCommand extends AreashopCommandBean {
protected @Nonnull CommandProperties properties() {
return CommandProperties.of("quickbuy");
}
}
}
@@ -3,12 +3,13 @@ package me.wiefferink.areashop.commands;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.adapters.platform.OfflinePlayerHelper;
import me.wiefferink.areashop.commands.util.AreaShopCommandException;
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
import me.wiefferink.areashop.commands.util.ArgumentParseExceptionHandler;
import me.wiefferink.areashop.commands.util.DurationInputParser;
import me.wiefferink.areashop.commands.util.OfflinePlayerParser;
import me.wiefferink.areashop.commands.util.RegionCreationUtil;
import me.wiefferink.areashop.commands.util.ValidatedOfflinePlayerParser;
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
import me.wiefferink.areashop.commands.util.commandsource.PlayerCommandSource;
import me.wiefferink.areashop.managers.IFileManager;
@@ -16,7 +17,6 @@ import me.wiefferink.areashop.regions.RegionFactory;
import me.wiefferink.areashop.regions.RentRegion;
import me.wiefferink.areashop.tools.BukkitSchedulerExecutor;
import me.wiefferink.areashop.tools.DurationInput;
import org.bukkit.OfflinePlayer;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@@ -38,12 +38,13 @@ public class QuickRentCommand extends AreashopCommandBean {
private static final CloudKey<Double> KEY_PRICE = CloudKey.of("price", Double.class);
private static final CloudKey<DurationInput> KEY_DURATION = CloudKey.of("duration", DurationInput.class);
private static final CloudKey<OfflinePlayer> KEY_LANDLORD = CloudKey.of("landlord", OfflinePlayer.class);
private static final CloudKey<String> KEY_LANDLORD = CloudKey.of("landlord", String.class);
private final RegionFactory regionFactory;
private final IFileManager fileManager;
private final MessageBridge messageBridge;
private final RegionCreationUtil regionCreationUtil;
private final BukkitSchedulerExecutor executor;
private final OfflinePlayerHelper offlinePlayerHelper;
@Inject
public QuickRentCommand(
@@ -51,13 +52,15 @@ public class QuickRentCommand extends AreashopCommandBean {
@Nonnull RegionFactory regionFactory,
@Nonnull IFileManager fileManager,
@Nonnull RegionCreationUtil regionCreationUtil,
@Nonnull BukkitSchedulerExecutor executor
@Nonnull BukkitSchedulerExecutor executor,
@Nonnull OfflinePlayerHelper offlinePlayerHelper
) {
this.messageBridge = messageBridge;
this.regionFactory = regionFactory;
this.fileManager = fileManager;
this.regionCreationUtil = regionCreationUtil;
this.executor = executor;
this.offlinePlayerHelper = offlinePlayerHelper;
}
@Override
@@ -74,7 +77,7 @@ public class QuickRentCommand extends AreashopCommandBean {
.required(KEY_REGION, StringParser.stringParser())
.required(KEY_PRICE, DoubleParser.doubleParser(0))
.required(KEY_DURATION, DurationInputParser.durationInputParser())
.required(KEY_LANDLORD, ValidatedOfflinePlayerParser.validatedOfflinePlayerParser())
.required(KEY_LANDLORD, OfflinePlayerParser.parser())
.handler(this::handleCommand);
}
@@ -103,20 +106,27 @@ public class QuickRentCommand extends AreashopCommandBean {
double price = context.get(KEY_PRICE);
DurationInput duration = context.get(KEY_DURATION);
OfflinePlayer landlord = context.get(KEY_LANDLORD);
if (!landlord.hasPlayedBefore()) {
this.messageBridge.message(player, "me-noPlayer");
return;
}
String regionName = region.getId();
World world = player.getWorld();
this.offlinePlayerHelper.lookupOfflinePlayerAsync(context.get(KEY_LANDLORD))
.whenCompleteAsync((landlord, exception) -> {
if (exception != null) {
player.sendMessage("failed to lookup offline player!");
exception.printStackTrace();
return;
}
if (!landlord.hasPlayedBefore() && !landlord.isOnline()) {
this.messageBridge.message(player, "cmd-invalidPlayer", landlord.getName());
return;
}
String regionName = region.getId();
World world = player.getWorld();
RentRegion rentRegion = this.regionFactory.createRentRegion(regionName, world);
rentRegion.setPrice(price);
rentRegion.setLandlord(landlord.getUniqueId(), landlord.getName());
rentRegion.setDuration(duration.toTinySpacedString());
this.fileManager.addRegion(rentRegion);
this.messageBridge.message(player, "add-success", "rent", regionName);
RentRegion rentRegion = this.regionFactory.createRentRegion(regionName, world);
rentRegion.setPrice(price);
rentRegion.setLandlord(landlord.getUniqueId(), landlord.getName());
rentRegion.setDuration(duration.toTinySpacedString());
this.fileManager.addRegion(rentRegion);
this.messageBridge.message(player, "add-success", "rent", regionName);
}, this.executor);
}, this.executor);
}
@@ -133,4 +143,4 @@ public class QuickRentCommand extends AreashopCommandBean {
protected @Nonnull CommandProperties properties() {
return CommandProperties.of("quickrent");
}
}
}
@@ -3,14 +3,15 @@ package me.wiefferink.areashop.commands;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.adapters.platform.OfflinePlayerHelper;
import me.wiefferink.areashop.commands.util.AreaShopCommandException;
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
import me.wiefferink.areashop.commands.util.OfflinePlayerParser;
import me.wiefferink.areashop.commands.util.RegionParseUtil;
import me.wiefferink.areashop.commands.util.ValidatedOfflinePlayerParser;
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
import me.wiefferink.areashop.managers.IFileManager;
import me.wiefferink.areashop.regions.GeneralRegion;
import org.bukkit.OfflinePlayer;
import me.wiefferink.areashop.tools.BukkitSchedulerExecutor;
import org.bukkit.command.CommandSender;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.incendo.cloud.Command;
@@ -25,18 +26,24 @@ import javax.annotation.Nonnull;
@Singleton
public class SetLandlordCommand extends AreashopCommandBean {
private static final CloudKey<OfflinePlayer> KEY_PLAYER = CloudKey.of("player", OfflinePlayer.class);
private static final CloudKey<String> KEY_PLAYER = CloudKey.of("player", String.class);
private final MessageBridge messageBridge;
private final CommandFlag<GeneralRegion> regionFlag;
private final OfflinePlayerHelper offlinePlayerHelper;
private final BukkitSchedulerExecutor executor;
@Inject
public SetLandlordCommand(
@Nonnull MessageBridge messageBridge,
@Nonnull IFileManager fileManager
@Nonnull IFileManager fileManager,
@Nonnull OfflinePlayerHelper offlinePlayerHelper,
@Nonnull BukkitSchedulerExecutor executor
) {
this.messageBridge = messageBridge;
this.regionFlag = RegionParseUtil.createDefault(fileManager);
this.offlinePlayerHelper = offlinePlayerHelper;
this.executor = executor;
}
@@ -56,7 +63,7 @@ public class SetLandlordCommand extends AreashopCommandBean {
@Override
protected Command.Builder<? extends CommandSource<?>> configureCommand(Command.@NotNull Builder<CommandSource<?>> builder) {
return builder.literal("setlandlord")
.required(KEY_PLAYER, ValidatedOfflinePlayerParser.validatedOfflinePlayerParser())
.required(KEY_PLAYER, OfflinePlayerParser.parser())
.flag(this.regionFlag)
.handler(this::handleCommand);
}
@@ -72,11 +79,22 @@ public class SetLandlordCommand extends AreashopCommandBean {
throw new AreaShopCommandException("setlandlord-noPermission");
}
GeneralRegion region = RegionParseUtil.getOrParseRegion(context, sender, this.regionFlag);
OfflinePlayer player = context.get(KEY_PLAYER);
String playerName = player.getName();
region.setLandlord(player.getUniqueId(), playerName);
region.update();
this.messageBridge.message(sender, "setlandlord-success", playerName, region);
this.offlinePlayerHelper.lookupOfflinePlayerAsync(context.get(KEY_PLAYER))
.whenCompleteAsync((landlord, exception) -> {
if (exception != null) {
sender.sendMessage("failed to lookup offline player!");
exception.printStackTrace();
return;
}
if (!landlord.hasPlayedBefore() && !landlord.isOnline()) {
this.messageBridge.message(sender, "cmd-invalidPlayer", landlord.getName());
return;
}
String playerName = landlord.getName();
region.setLandlord(landlord.getUniqueId(), playerName);
region.update();
this.messageBridge.message(sender, "setlandlord-success", playerName, region);
}, this.executor);
}
}
@@ -3,14 +3,16 @@ package me.wiefferink.areashop.commands;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.adapters.platform.OfflinePlayerHelper;
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
import me.wiefferink.areashop.commands.util.OfflinePlayerParser;
import me.wiefferink.areashop.commands.util.RegionParseUtil;
import me.wiefferink.areashop.commands.util.ValidatedOfflinePlayerParser;
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
import me.wiefferink.areashop.managers.IFileManager;
import me.wiefferink.areashop.regions.BuyRegion;
import me.wiefferink.areashop.regions.GeneralRegion;
import me.wiefferink.areashop.regions.RentRegion;
import me.wiefferink.areashop.tools.BukkitSchedulerExecutor;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.CommandSender;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -28,18 +30,24 @@ import java.util.UUID;
@Singleton
public class SetOwnerCommand extends AreashopCommandBean {
private static final CloudKey<OfflinePlayer> KEY_PLAYER = CloudKey.of("player", OfflinePlayer.class);
private static final CloudKey<String> KEY_PLAYER = CloudKey.of("player", String.class);
private final CommandFlag<GeneralRegion> regionFlag;
private final MessageBridge messageBridge;
private final OfflinePlayerHelper offlinePlayerHelper;
private final BukkitSchedulerExecutor executor;
@Inject
public SetOwnerCommand(
@Nonnull MessageBridge messageBridge,
@Nonnull IFileManager fileManager
) {
@Nonnull IFileManager fileManager,
@Nonnull OfflinePlayerHelper offlinePlayerHelper,
@Nonnull BukkitSchedulerExecutor executor
) {
this.messageBridge = messageBridge;
this.regionFlag = RegionParseUtil.createDefault(fileManager);
this.offlinePlayerHelper = offlinePlayerHelper;
this.executor = executor;
}
@Override
@@ -58,7 +66,7 @@ public class SetOwnerCommand extends AreashopCommandBean {
@Override
protected Command.Builder<? extends CommandSource<?>> configureCommand(Command.@NotNull Builder<CommandSource<?>> builder) {
return builder.literal("setowner")
.required(KEY_PLAYER, ValidatedOfflinePlayerParser.validatedOfflinePlayerParser())
.required(KEY_PLAYER, OfflinePlayerParser.parser())
.flag(this.regionFlag)
.handler(this::handleCommand);
}
@@ -83,11 +91,22 @@ public class SetOwnerCommand extends AreashopCommandBean {
this.messageBridge.message(sender, "setowner-noPermissionBuy", region);
return;
}
OfflinePlayer player = context.get(KEY_PLAYER);
if (!player.hasPlayedBefore()) {
this.messageBridge.message(sender, "setowner-noPlayer", player.getName(), region);
return;
}
this.offlinePlayerHelper.lookupOfflinePlayerAsync(context.get(KEY_PLAYER))
.whenCompleteAsync((offlinePlayer, exception) -> {
if (exception != null) {
sender.sendMessage("failed to lookup offline player!");
exception.printStackTrace();
return;
}
if (!offlinePlayer.hasPlayedBefore() && !offlinePlayer.isOnline()) {
this.messageBridge.message(sender, "cmd-invalidPlayer", offlinePlayer.getName());
return;
}
setOwner(sender, offlinePlayer, region);
}, this.executor);
}
private void setOwner(@Nonnull CommandSender sender, @Nonnull OfflinePlayer player, GeneralRegion region) {
final UUID uuid = player.getUniqueId();
if (region instanceof RentRegion rent) {
if (rent.isRenter(uuid)) {
@@ -3,11 +3,12 @@ package me.wiefferink.areashop.commands;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.adapters.platform.OfflinePlayerHelper;
import me.wiefferink.areashop.commands.util.AreaShopCommandException;
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
import me.wiefferink.areashop.commands.util.GeneralRegionParser;
import me.wiefferink.areashop.commands.util.OfflinePlayerParser;
import me.wiefferink.areashop.commands.util.RegionParseUtil;
import me.wiefferink.areashop.commands.util.ValidatedOfflinePlayerParser;
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
import me.wiefferink.areashop.commands.util.commandsource.PlayerCommandSource;
import me.wiefferink.areashop.managers.IFileManager;
@@ -35,15 +36,17 @@ import java.util.concurrent.CompletableFuture;
@Singleton
public class TransferCommand extends AreashopCommandBean {
private static final CloudKey<OfflinePlayer> KEY_PLAYER = CloudKey.of("player", OfflinePlayer.class);
private static final CloudKey<String> KEY_PLAYER = CloudKey.of("player", String.class);
private final MessageBridge messageBridge;
private final IFileManager fileManager;
private final CommandFlag<GeneralRegion> regionFlag;
private final OfflinePlayerHelper offlinePlayerHelper;
@Inject
public TransferCommand(
@Nonnull MessageBridge messageBridge,
@Nonnull IFileManager fileManager
@Nonnull IFileManager fileManager,
@Nonnull OfflinePlayerHelper offlinePlayerHelper
) {
ParserDescriptor<PlayerCommandSource, GeneralRegion> regionParser =
ParserDescriptor.of(new GeneralRegionParser<>(fileManager, this::suggestRegions), GeneralRegion.class);
@@ -52,6 +55,7 @@ public class TransferCommand extends AreashopCommandBean {
this.regionFlag = CommandFlag.<PlayerCommandSource>builder("region")
.withComponent(regionParser)
.build();
this.offlinePlayerHelper = offlinePlayerHelper;
}
@Override
@@ -71,7 +75,7 @@ public class TransferCommand extends AreashopCommandBean {
protected Command.Builder<? extends CommandSource<?>> configureCommand(Command.@NotNull Builder<CommandSource<?>> builder) {
return builder.literal("transfer")
.senderType(PlayerCommandSource.class)
.required(KEY_PLAYER, ValidatedOfflinePlayerParser.validatedOfflinePlayerParser())
.required(KEY_PLAYER, OfflinePlayerParser.parser())
.flag(this.regionFlag)
.handler(this::handleCommand);
}
@@ -90,12 +94,32 @@ public class TransferCommand extends AreashopCommandBean {
if (!region.isTransferEnabled()) {
throw new AreaShopCommandException("transfer-disabled");
}
OfflinePlayer targetPlayer = context.get(KEY_PLAYER);
this.offlinePlayerHelper.lookupOfflinePlayerAsync(context.get(KEY_PLAYER))
.whenComplete((offlinePlayer, exception) -> {
if (exception != null) {
sender.sendMessage("failed to lookup offline player!");
exception.printStackTrace();
return;
}
if (!offlinePlayer.hasPlayedBefore() &&!offlinePlayer.isOnline()) {
this.messageBridge.message(sender, "cmd-invalidPlayer", offlinePlayer.getName());
return;
}
performTransfer(sender, offlinePlayer, region);
});
}
private void performTransfer(
@Nonnull Player sender,
@Nonnull OfflinePlayer targetPlayer,
@Nonnull GeneralRegion region
) {
String targetPlayerName = targetPlayer.getName();
if (Objects.equals(sender, targetPlayer)) {
throw new AreaShopCommandException("transfer-transferSelf");
}
if (!targetPlayer.hasPlayedBefore()) {
if (!targetPlayer.hasPlayedBefore() && !targetPlayer.isOnline()) {
// Unknown player
throw new AreaShopCommandException("transfer-noPlayer", targetPlayerName);
}
@@ -23,11 +23,11 @@ public class ArgumentParseExceptionHandler<C extends CommandSource<?>> implement
String key = exception.messageKey();
Object[] replacements = exception.replacements();
if (replacements.length == 0) {
messageBridge.message(sender, key);
messageBridge.message(sender.sender(), key);
return;
}
// Pass the values as a var-args and not as a string[]
messageBridge.message(sender, key, replacements);
messageBridge.message(sender.sender(), key, replacements);
}
@Override
@@ -0,0 +1,38 @@
package me.wiefferink.areashop.commands.util;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.incendo.cloud.context.CommandContext;
import org.incendo.cloud.context.CommandInput;
import org.incendo.cloud.parser.ArgumentParseResult;
import org.incendo.cloud.parser.ArgumentParser;
import org.incendo.cloud.parser.ParserDescriptor;
import org.incendo.cloud.suggestion.BlockingSuggestionProvider;
public class OfflinePlayerParser<C> implements ArgumentParser<C, String>, BlockingSuggestionProvider.Strings<C> {
public static <C> ParserDescriptor<C, String> parser() {
return ParserDescriptor.of(new OfflinePlayerParser<>(), String.class);
}
@Override
public @NonNull ArgumentParseResult<@NonNull String> parse(@NonNull CommandContext<@NonNull C> commandContext,
@NonNull CommandInput commandInput) {
final String input = commandInput.readString();
if (input.length() > 16) {
return ArgumentParseResult.failure(new AreaShopCommandException("cmd-invalidPlayer", input));
}
return ArgumentParseResult.success(input);
}
@Override
public @NonNull Iterable<@NonNull String> stringSuggestions(@NonNull CommandContext<C> commandContext,
@NonNull CommandInput input) {
return Bukkit.getServer().getOnlinePlayers().stream()
.map(Player::getName)
.toList();
}
}
@@ -1,64 +0,0 @@
package me.wiefferink.areashop.commands.util;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.incendo.cloud.bukkit.BukkitCommandContextKeys;
import org.incendo.cloud.context.CommandContext;
import org.incendo.cloud.context.CommandInput;
import org.incendo.cloud.parser.ArgumentParseResult;
import org.incendo.cloud.parser.ArgumentParser;
import org.incendo.cloud.parser.ParserDescriptor;
import org.incendo.cloud.suggestion.BlockingSuggestionProvider;
import java.util.Collections;
public class ValidatedOfflinePlayerParser<C> implements ArgumentParser<C, OfflinePlayer>, BlockingSuggestionProvider.Strings<C> {
public static <C> ParserDescriptor<C, OfflinePlayer> validatedOfflinePlayerParser() {
return ParserDescriptor.of(new ValidatedOfflinePlayerParser<>(), OfflinePlayer.class);
}
@Override
@SuppressWarnings("deprecation")
public @NonNull ArgumentParseResult<OfflinePlayer> parse(
final @NonNull CommandContext<C> commandContext,
final @NonNull CommandInput commandInput
) {
final String input = commandInput.readString();
if (input.length() > 16) {
return ArgumentParseResult.failure(new AreaShopCommandException("cmd-invalidPlayer", input));
}
final Player onlinePlayer = Bukkit.getPlayerExact(input);
if (onlinePlayer != null) {
return ArgumentParseResult.success(onlinePlayer);
}
final OfflinePlayer player;
try {
player = Bukkit.getOfflinePlayer(input);
} catch (final Exception e) {
return ArgumentParseResult.failure(new AreaShopCommandException("cmd-invalidPlayer", input));
}
if (!player.hasPlayedBefore()) {
return ArgumentParseResult.failure(new AreaShopCommandException("cmd-invalidPlayer", input));
}
return ArgumentParseResult.success(player);
}
@Override
public @NonNull Iterable<@NonNull String> stringSuggestions(
final @NonNull CommandContext<C> commandContext,
final @NonNull CommandInput input
) {
if (!commandContext.contains(BukkitCommandContextKeys.BUKKIT_COMMAND_SENDER)) {
return Collections.emptyList();
}
final CommandSender sender = commandContext.get(BukkitCommandContextKeys.BUKKIT_COMMAND_SENDER);
return Bukkit.getOnlinePlayers().stream()
.filter(onlinePlayer -> !(sender instanceof Player player && !((Player) sender).canSee(player)))
.map(Player::getName)
.toList();
}
}
@@ -7,7 +7,6 @@ import io.github.bakedlibs.dough.blocks.BlockPosition;
import io.papermc.lib.PaperLib;
import me.wiefferink.areashop.AreaShop;
import me.wiefferink.areashop.managers.SignErrorLogger;
import me.wiefferink.areashop.platform.adapter.BlockBehaviourHelper;
import me.wiefferink.areashop.regions.GeneralRegion;
import me.wiefferink.areashop.tools.Materials;
import me.wiefferink.areashop.tools.SignUtils;
@@ -16,6 +15,7 @@ import me.wiefferink.interactivemessenger.processing.Message;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Server;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
@@ -35,8 +35,8 @@ import java.util.List;
*/
public class RegionSign {
private final BlockBehaviourHelper blockHelper;
private final SignErrorLogger errorLogger;
private final Server server;
private final SignsFeature signsFeature;
private final String key;
@@ -44,13 +44,13 @@ public class RegionSign {
@AssistedInject
RegionSign(
@Nonnull BlockBehaviourHelper blockBehaviourHelper,
@Nonnull SignErrorLogger signErrorLogger,
@Nonnull Server server,
@Assisted @Nonnull SignsFeature signsFeature,
@Assisted @Nonnull String key
) {
this.blockHelper = blockBehaviourHelper;
this.errorLogger = signErrorLogger;
this.server = server;
this.signsFeature = signsFeature;
this.key = key;
}
@@ -176,7 +176,7 @@ public class RegionSign {
// Place the sign back (with proper rotation and type) after it has been hidden or (indirectly) destroyed
if(!Materials.isSign(block.getType())) {
Material signType = getMaterial();
if (!blockHelper.canPlace(block.getLocation(), Bukkit.createBlockData(signType))) {
if (!block.canPlace(this.server.createBlockData(signType))) {
errorLogger.submitWarning("Setting sign" + key + "of region" + getRegion().getName() + "failed, could not set sign block back");
this.remove();
return false;
@@ -278,7 +278,7 @@ public class RegionSign {
for(String command : stateConfig.getStringList(clickType.getValue() + "Console")) {
consoleCommands.add(command.replace(Message.VARIABLE_START + AreaShop.tagClicker + Message.VARIABLE_END, clicker.getName()));
}
getRegion().runCommands(Bukkit.getConsoleSender(), consoleCommands);
getRegion().runCommands(this.server.getConsoleSender(), consoleCommands);
return !playerCommands.isEmpty() || !consoleCommands.isEmpty();
}
@@ -10,7 +10,6 @@ import me.wiefferink.areashop.events.notify.UpdateRegionEvent;
import me.wiefferink.areashop.interfaces.WorldGuardInterface;
import me.wiefferink.areashop.managers.IFileManager;
import me.wiefferink.areashop.managers.SignLinkerManager;
import me.wiefferink.areashop.platform.adapter.BlockBehaviourHelper;
import me.wiefferink.areashop.regions.BuyRegion;
import me.wiefferink.areashop.regions.GeneralRegion;
import me.wiefferink.areashop.regions.RegionFactory;
@@ -42,7 +41,6 @@ import java.util.Set;
public class SignListener implements Listener {
private final BlockBehaviourHelper behaviourHelper;
private final AreaShop plugin;
private final MessageBridge messageBridge;
private final SignManager signManager;
@@ -53,7 +51,6 @@ public class SignListener implements Listener {
public SignListener(
@Nonnull AreaShop plugin,
@Nonnull BlockBehaviourHelper behaviourHelper,
@Nonnull RegionFactory regionFactory,
@Nonnull MessageBridge messageBridge,
@Nonnull SignLinkerManager signLinkerManager,
@@ -64,7 +61,6 @@ public class SignListener implements Listener {
this.signManager = signManager;
this.signLinkerManager = signLinkerManager;
this.regionFactory = regionFactory;
this.behaviourHelper = behaviourHelper;
this.plugin = plugin;
this.worldGuardInterface = worldGuardInterface;
this.messageBridge = messageBridge;
@@ -96,8 +92,9 @@ public class SignListener implements Listener {
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onIndirectSignBreak(BlockPhysicsEvent event) {
Block block = event.getBlock();
// Check if the block is a sign
if(!Materials.isSign(event.getBlock().getType()) || behaviourHelper.isBlockValid(event.getBlock())) {
if(!Materials.isSign(block.getType()) || block.canPlace(block.getBlockData())) {
return;
}
@@ -152,24 +149,13 @@ public class SignListener implements Listener {
if (!(event.getAction() == Action.RIGHT_CLICK_BLOCK || event.getAction() == Action.LEFT_CLICK_BLOCK)) {
return;
}
// Only care about clicking blocks
if(!Materials.isSign(block.getType())) {
Optional<RegionSign> optionalRegionSign = getRegionSign(block, event.getPlayer());
if (optionalRegionSign.isEmpty()) {
return;
}
RegionSign regionSign = optionalRegionSign.get();
// Check if this sign belongs to a region
Optional<RegionSign> optional = signManager.signFromLocation(block.getLocation());
if(optional.isEmpty()) {
return;
}
RegionSign regionSign = optional.get();
// Ignore players that are in sign link mode (which will handle the event itself)
Player player = event.getPlayer();
if(signLinkerManager.isInSignLinkMode(player)) {
return;
}
// Get the clicktype
GeneralRegion.ClickType clickType = null;
@@ -189,6 +175,21 @@ public class SignListener implements Listener {
event.setCancelled(ran);
}
private Optional<RegionSign> getRegionSign(@Nonnull Block block, @Nonnull Player player) {
// Only care about clicking blocks
if(!Materials.isSign(block.getType())) {
return Optional.empty();
}
// Ignore players that are in sign link mode (which will handle the event itself)
if(signLinkerManager.isInSignLinkMode(player)) {
return Optional.empty();
}
// Check if this sign belongs to a region
return signManager.signFromLocation(block.getLocation());
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onSignChange(SignChangeEvent event) {
Player player = event.getPlayer();
@@ -9,7 +9,6 @@ import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.interfaces.WorldGuardInterface;
import me.wiefferink.areashop.managers.IFileManager;
import me.wiefferink.areashop.managers.SignLinkerManager;
import me.wiefferink.areashop.platform.adapter.BlockBehaviourHelper;
import me.wiefferink.areashop.regions.RegionFactory;
import javax.annotation.Nonnull;
@@ -25,7 +24,6 @@ public class SignsModule extends AbstractModule {
@Provides
@Singleton
public SignListener provideSignListener(@Nonnull AreaShop plugin,
@Nonnull BlockBehaviourHelper behaviourHelper,
@Nonnull RegionFactory regionFactory,
@Nonnull MessageBridge messageBridge,
@Nonnull SignLinkerManager signLinkerManager,
@@ -35,7 +33,6 @@ public class SignsModule extends AbstractModule {
) {
final SignListener signListener = new SignListener(
plugin,
behaviourHelper,
regionFactory,
messageBridge,
signLinkerManager,
@@ -0,0 +1,68 @@
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);
}
}
@@ -0,0 +1,47 @@
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;
}
}
@@ -12,15 +12,18 @@ 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;
@@ -31,6 +34,7 @@ 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;
@@ -46,11 +50,9 @@ 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;
@@ -61,9 +63,8 @@ import java.util.regex.Pattern;
public class FileManager extends Manager implements IFileManager {
private final AreaShop plugin;
private final Map<String, GeneralRegion> regions;
private final Map<String, BuyRegion> buys;
private final Map<String, RentRegion> rents;
private final IRegionContainer regionContainer = new SimpleRegionContainer();
private final String regionsPath;
private final Map<String, RegionGroup> groups;
private final String configPath;
@@ -101,9 +102,6 @@ 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<>();
@@ -122,7 +120,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.regions.values()) {
for(GeneralRegion region : this.regionContainer.getRegionsRef()) {
UUID ownerUuid = region.getOwner();
if (ownerUuid == null) {
continue;
@@ -196,6 +194,22 @@ 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)
@@ -203,7 +217,7 @@ public class FileManager extends Manager implements IFileManager {
*/
@Override
public @Nullable GeneralRegion getRegion(String name) {
return regions.get(name.toLowerCase());
return this.regionContainer.getRegion(name);
}
/**
@@ -213,7 +227,7 @@ public class FileManager extends Manager implements IFileManager {
*/
@Override
public @Nullable RentRegion getRent(String name) {
return rents.get(name.toLowerCase(Locale.ENGLISH));
return this.regionContainer.getRent(name);
}
/**
@@ -223,7 +237,7 @@ public class FileManager extends Manager implements IFileManager {
*/
@Override
public @Nullable BuyRegion getBuy(String name) {
return buys.get(name.toLowerCase(Locale.ENGLISH));
return this.regionContainer.getBuy(name);
}
/**
@@ -231,8 +245,8 @@ public class FileManager extends Manager implements IFileManager {
* @return List of all rental regions
*/
@Override
public Collection<RentRegion> getRents() {
return new ArrayList<>(rents.values());
public List<RentRegion> getRents() {
return this.regionContainer.getRents();
}
/**
@@ -241,7 +255,7 @@ public class FileManager extends Manager implements IFileManager {
*/
@Override
public Collection<RentRegion> getRentsRef() {
return Collections.unmodifiableCollection(rents.values());
return this.regionContainer.getRentsRef();
}
/**
@@ -250,12 +264,12 @@ public class FileManager extends Manager implements IFileManager {
*/
@Override
public List<BuyRegion> getBuys() {
return new ArrayList<>(buys.values());
return this.regionContainer.getBuys();
}
@Override
public Collection<BuyRegion> getBuysRef() {
return Collections.unmodifiableCollection(buys.values());
return this.regionContainer.getBuysRef();
}
@@ -265,7 +279,7 @@ public class FileManager extends Manager implements IFileManager {
*/
@Override
public List<GeneralRegion> getRegions() {
return new ArrayList<>(regions.values());
return this.regionContainer.getRegions();
}
/**
@@ -274,7 +288,7 @@ public class FileManager extends Manager implements IFileManager {
*/
@Override
public Collection<GeneralRegion> getRegionsRef() {
return Collections.unmodifiableCollection(regions.values());
return this.regionContainer.getRegionsRef();
}
/**
@@ -283,11 +297,7 @@ public class FileManager extends Manager implements IFileManager {
*/
@Override
public List<String> getBuyNames() {
ArrayList<String> result = new ArrayList<>(buys.size());
for(BuyRegion region : buys.values()) {
result.add(region.getName());
}
return result;
return this.regionContainer.getBuyNames();
}
/**
@@ -296,11 +306,7 @@ public class FileManager extends Manager implements IFileManager {
*/
@Override
public List<String> getRentNames() {
ArrayList<String> result = new ArrayList<>(rents.size());
for(RentRegion region : rents.values()) {
result.add(region.getName());
}
return result;
return this.regionContainer.getRentNames();
}
/**
@@ -309,11 +315,12 @@ public class FileManager extends Manager implements IFileManager {
*/
@Override
public List<String> getRegionNames() {
ArrayList<String> result = new ArrayList<>(regions.size());
for(GeneralRegion region : regions.values()) {
result.add(region.getName());
}
return result;
return this.regionContainer.getRegionNames();
}
@Override
public List<String> getRegionInterfaceNames() {
return this.regionContainer.getRegionInterfaceNames();
}
/**
@@ -362,13 +369,7 @@ public class FileManager extends Manager implements IFileManager {
if (event.isCancelled()) {
return event;
}
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);
}
this.regionContainer.addRegionInterface(region);
Bukkit.getPluginManager().callEvent(new AddedRegionEvent(region));
return event;
}
@@ -491,9 +492,7 @@ public class FileManager extends Manager implements IFileManager {
region.resetRegionFlags();
String name = region.getLowerCaseName();
regions.remove(name);
buys.remove(name);
rents.remove(name);
this.regionContainer.removeRegion(name);
// Remove file
File file = new File(plugin.getDataFolder() + File.separator + AreaShop.regionsFolder + File.separator + region.getLowerCaseName() + ".yml");
@@ -621,6 +620,21 @@ 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.
*/
@@ -651,7 +665,7 @@ public class FileManager extends Manager implements IFileManager {
getRegionsRef(),
region -> {
if(region.isSaveRequired()) {
region.saveNow();
region.saveNowAsync();
}
}
);
@@ -952,9 +966,7 @@ public class FileManager extends Manager implements IFileManager {
*/
@Override
public void loadRegionFiles() {
this.regions.clear();
this.buys.clear();
this.rents.clear();
this.regionContainer.clearRegions();
final File file = new File(regionsPath);
if(!file.exists()) {
if(!file.mkdirs()) {
@@ -1019,7 +1031,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 && !Utils.checkTimeFormat(((RentRegion)region).getDurationString())) {
} else if(region instanceof RentRegion rentRegion && !Utils.checkTimeFormat(rentRegion.getDurationString())) {
incorrectDuration.add(region);
} else {
added = true;
@@ -1412,6 +1424,11 @@ 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,20 +3,18 @@ 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 {
public interface IFileManager extends IRegionContainer {
/**
* Get the folder where schematics are stored.
@@ -61,95 +59,6 @@ public interface IFileManager {
*/
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,6 +13,7 @@ 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;
@@ -66,6 +67,7 @@ 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);
@@ -3,27 +3,20 @@ package me.wiefferink.areashop.modules;
import com.google.inject.AbstractModule;
import me.wiefferink.areashop.adapters.platform.MinecraftPlatform;
import me.wiefferink.areashop.adapters.platform.OfflinePlayerHelper;
import me.wiefferink.areashop.platform.adapter.BlockBehaviourHelper;
import me.wiefferink.areashop.platform.adapter.PlatformAdapter;
import me.wiefferink.areashop.tools.BukkitSchedulerExecutor;
import org.jetbrains.annotations.NotNull;
public class PlatformModule extends AbstractModule {
private final MinecraftPlatform minecraftPlatform;
private final PlatformAdapter platformAdapter;
public PlatformModule(@NotNull MinecraftPlatform platform,
@NotNull PlatformAdapter platformAdapter) {
public PlatformModule(@NotNull MinecraftPlatform platform) {
this.minecraftPlatform = platform;
this.platformAdapter = platformAdapter;
}
@Override
protected void configure() {
bind(MinecraftPlatform.class).toInstance(this.minecraftPlatform);
bind(OfflinePlayerHelper.class).toInstance(this.minecraftPlatform.offlinePlayerHelper());
bind(PlatformAdapter.class).toInstance(this.platformAdapter);
bind(BlockBehaviourHelper.class).toInstance(this.platformAdapter.blockBehaviourHelper());
bind(BukkitSchedulerExecutor.class).asEagerSingleton();
}
}
@@ -31,7 +31,7 @@ import java.util.UUID;
public class BuyRegion extends GeneralRegion {
private final Economy economy;
@AssistedInject
BuyRegion(
@Nonnull AreaShop plugin,
@@ -424,7 +424,7 @@ public class BuyRegion extends GeneralRegion {
// Resell is done, disable that now
disableReselling();
// Send message to the player
message(offlinePlayer, "buy-successResale", oldOwnerName);
Player seller = Bukkit.getPlayer(oldOwner);
@@ -542,7 +542,7 @@ public class BuyRegion extends GeneralRegion {
// Give back the money
OfflinePlayer player = Bukkit.getOfflinePlayer(getBuyer());
if(player.hasPlayedBefore() && !noPayBack) {
if((player.hasPlayedBefore() || player.isOnline()) && !noPayBack) {
EconomyResponse response = null;
boolean error = false;
try {
@@ -1,5 +1,6 @@
package me.wiefferink.areashop.regions;
import com.google.common.base.Charsets;
import com.sk89q.worldguard.protection.regions.ProtectedPolygonalRegion;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import me.wiefferink.areashop.AreaShop;
@@ -29,11 +30,15 @@ import org.bukkit.command.CommandSender;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitScheduler;
import org.bukkit.util.Vector;
import javax.annotation.Nonnull;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
@@ -472,7 +477,7 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
if(landlordName != null && !landlordName.isEmpty()) {
@SuppressWarnings("deprecation")
OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(landlordName);
if(offlinePlayer.hasPlayedBefore()) {
if(offlinePlayer.hasPlayedBefore() || offlinePlayer.isOnline()) {
return offlinePlayer.getUniqueId();
}
}
@@ -630,7 +635,7 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
return getName();
}
case AreaShop.tagRegionType -> {
return getType().getValue().toLowerCase();
return getType().getValue().toLowerCase(Locale.ENGLISH);
}
case AreaShop.tagWorldName -> {
return getWorldName();
@@ -958,6 +963,27 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
}
}
@Nonnull
public CompletableFuture<Boolean> saveNowAsync() {
if(isDeleted()) {
return CompletableFuture.completedFuture(false);
}
String data = config.saveToString();
saveRequired = false;
File file = new File(plugin.getFileManager().getRegionFolder() + File.separator + getName().toLowerCase() + ".yml");
BukkitScheduler scheduler = this.plugin.getServer().getScheduler();
CompletableFuture<Boolean> future = new CompletableFuture<>();
scheduler.runTaskAsynchronously(this.plugin, () -> {
try(Writer writer = new OutputStreamWriter(new FileOutputStream(file), Charsets.UTF_8);){
writer.write(data);
future.complete(true);
} catch (IOException ex) {
future.complete(false);
}
});
return future;
}
// CONFIG
@@ -0,0 +1,149 @@
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();
}
@@ -279,7 +279,7 @@ public class ImportJob {
if(owner != null) {
@SuppressWarnings("deprecation")
OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(owner);
if(offlinePlayer.hasPlayedBefore()) {
if(offlinePlayer.hasPlayedBefore() || offlinePlayer.isOnline()) {
existing.add(offlinePlayer.getUniqueId());
}
}
@@ -0,0 +1,153 @@
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();
}
}
@@ -21,7 +21,7 @@ public class SpigotOfflinePlayerHelper implements OfflinePlayerHelper {
@Override
public CompletableFuture<Optional<UUID>> lookupUuidAsync(String username) {
return lookupOfflinePlayerAsync(username).thenApply(player -> {
if (player.hasPlayedBefore()) {
if (player.hasPlayedBefore() || player.isOnline()) {
return Optional.of(player.getUniqueId());
}
return Optional.empty();
@@ -31,6 +31,11 @@ public class SpigotOfflinePlayerHelper implements OfflinePlayerHelper {
@Override
public CompletableFuture<OfflinePlayer> lookupOfflinePlayerAsync(String username) {
final CompletableFuture<OfflinePlayer> future = new CompletableFuture<>();
OfflinePlayer onlinePlayer = this.plugin.getServer().getPlayerExact(username);
if (onlinePlayer != null) {
future.complete(onlinePlayer);
return future;
}
final Server server = this.plugin.getServer();
server.getScheduler().runTaskAsynchronously(this.plugin, () -> {
@SuppressWarnings("deprecation")
@@ -5,7 +5,7 @@ import java.util.StringJoiner;
public class VersionUtil {
public static final VersionData MC_1_20_6 = new VersionData(1, 20, 6);
public static final VersionData MC_1_21 = new VersionData(1, 21);
@Nonnull
public static String padTrailingZero(@Nonnull String minecraftVersion) {
+1 -1
View File
@@ -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]
softdepend: [Multiverse-Core, FastAsyncWorldEdit, Essentials, PlaceholderAPI]
authors: [NLThijs48, md5sha256, Dartanman]
website: https://github.com/md5sha256/AreaShop
#commands:
@@ -0,0 +1,85 @@
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);
}
}
@@ -0,0 +1,70 @@
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;
};
}
}
@@ -0,0 +1,89 @@
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,10 +0,0 @@
dependencies {
compileOnly("io.papermc.paper:paper-api:1.20.6-R0.1-SNAPSHOT")
compileOnly(projects.areashopNms)
}
description = "AreaShop NMS Helper 1-18"
tasks {
}
@@ -1,28 +0,0 @@
package me.wiefferink.areashop.adapters.platform.modern;
import me.wiefferink.areashop.platform.adapter.BlockBehaviourHelper;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.data.BlockData;
import java.util.Objects;
public class BlockBehaviourImpl implements BlockBehaviourHelper {
@Override
public boolean canPlace(Location location, BlockData blockData) {
Objects.requireNonNull(location.getWorld(), "Null World!");
return location.getBlock().canPlace(blockData);
}
@Override
public boolean isBlockValid(Block block) {
return block.canPlace(block.getBlockData());
}
@Override
public boolean isBlockStateValid(BlockState blockState) {
return blockState.getBlock().canPlace(blockState.getBlockData());
}
}
@@ -1,15 +0,0 @@
package me.wiefferink.areashop.adapters.platform.modern;
import me.wiefferink.areashop.platform.adapter.BlockBehaviourHelper;
import me.wiefferink.areashop.platform.adapter.PlatformAdapter;
public class ModernPlatformAdapter implements PlatformAdapter {
private final BlockBehaviourImpl blockBehaviourHelper = new BlockBehaviourImpl();
@Override
public BlockBehaviourHelper blockBehaviourHelper() {
return this.blockBehaviourHelper;
}
}
@@ -29,6 +29,15 @@ public class PaperOfflinePlayerHelper implements OfflinePlayerHelper {
@Override
public CompletableFuture<OfflinePlayer> lookupOfflinePlayerAsync(String username) {
final CompletableFuture<OfflinePlayer> future = new CompletableFuture<>();
OfflinePlayer onlinePlayer = this.server.getPlayerExact(username);
if (onlinePlayer != null) {
future.complete(onlinePlayer);
return future;
}
OfflinePlayer cachedPlayer = this.server.getOfflinePlayerIfCached(username);
if (cachedPlayer != null) {
return CompletableFuture.completedFuture(cachedPlayer);
}
this.server.getScheduler().runTaskAsynchronously(this.plugin, () -> {
OfflinePlayer offlinePlayer = plugin.getServer().getOfflinePlayer(username);
future.complete(offlinePlayer);
@@ -1,76 +0,0 @@
package me.wiefferink.areashop.interfaces;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.type.Sign;
import org.bukkit.block.data.type.WallSign;
/**
* Sign handler for 1.13+
* @deprecated Obsolete as we don't support pre-1.13 versions anyway
*/
@Deprecated(forRemoval = true)
public class BukkitInterface {
public BukkitInterface(AreaShopInterface pluginInterface) {
}
// Uses BlockData, which does not yet exist in 1.12-
public BlockFace getSignFacing(Block block) {
if (block == null) {
return null;
}
BlockState blockState = block.getState();
BlockData blockData = blockState.getBlockData();
if(blockData instanceof WallSign) {
return ((WallSign) blockData).getFacing();
} else if(blockData instanceof Sign) {
return ((Sign) blockData).getRotation();
}
return null;
}
// Uses BlockData, WallSign and Sign which don't exist in 1.12-
public boolean setSignFacing(Block block, BlockFace facing) {
if (block == null || facing == null) {
return false;
}
BlockState blockState = block.getState();
BlockData blockData = blockState.getBlockData();
if(blockData instanceof WallSign) {
((WallSign) blockData).setFacing(facing);
} else if(blockData instanceof Sign) {
((Sign) blockData).setRotation(facing);
} else {
return false;
}
block.setBlockData(blockData);
return true;
}
public Block getSignAttachedTo(Block block) {
if (block == null) {
return null;
}
BlockState blockState = block.getState();
BlockData blockData = blockState.getBlockData();
if(blockData instanceof WallSign) {
return block.getRelative(((WallSign) blockData).getFacing().getOppositeFace());
} else if(blockData instanceof Sign) {
return block.getRelative(BlockFace.DOWN);
}
return null;
}
}
@@ -56,7 +56,7 @@ public class RegionAccessSet {
for(String playerName : playerNames) {
@SuppressWarnings("deprecation")
OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(playerName);
if(offlinePlayer.hasPlayedBefore()) {
if(offlinePlayer.hasPlayedBefore() || offlinePlayer.isOnline()) {
result.add(offlinePlayer.getUniqueId());
}
}
-5
View File
@@ -1,5 +0,0 @@
dependencies {
compileOnly(libs.spigot)
}
description = "AreaShop NMS Interface"
@@ -1,16 +0,0 @@
package me.wiefferink.areashop.platform.adapter;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.data.BlockData;
public interface BlockBehaviourHelper {
boolean canPlace(Location location, BlockData blockData);
boolean isBlockValid(Block block);
boolean isBlockStateValid(BlockState blockState);
}
@@ -1,7 +0,0 @@
package me.wiefferink.areashop.platform.adapter;
public interface PlatformAdapter {
BlockBehaviourHelper blockBehaviourHelper();
}
+6 -3
View File
@@ -5,14 +5,13 @@ plugins {
java
`java-library`
`maven-publish`
id("io.papermc.paperweight.userdev") version "1.7.0" apply false
id("com.github.spotbugs") version "5.1.3"
idea
eclipse
}
group = "me.wiefferink"
version = "2.9.0-SNAPSHOT"
version = "2.9.2-SNAPSHOT"
val targetJavaVersion = 21
val encoding = Charsets.UTF_8
@@ -33,7 +32,7 @@ subprojects {
plugin<MavenPublishPlugin>()
// plugin<SpotBugsPlugin>()
}
repositories {
mavenCentral()
maven("https://oss.sonatype.org/content/groups/public/")
@@ -54,6 +53,10 @@ 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 -1
View File
@@ -1,6 +1,6 @@
[versions]
# Platforms
minecraft = "1.20.6-R0.1-SNAPSHOT"
minecraft = "1.21-R0.1-SNAPSHOT"
# Minecraft Plugins
worldedit = "7.3.3"
Binary file not shown.
+1 -1
View File
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Vendored
+5 -2
View File
@@ -15,6 +15,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#
##############################################################################
#
@@ -55,7 +57,7 @@
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
@@ -84,7 +86,8 @@ done
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
Vendored
+2
View File
@@ -13,6 +13,8 @@
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@rem SPDX-License-Identifier: Apache-2.0
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
-3
View File
@@ -15,7 +15,6 @@ rootProject.name = "areashop-parent"
// Interfaces
include(":areashop-interface")
include(":areashop-nms")
// Adapters
include(":adapters:platform:paper")
@@ -27,8 +26,6 @@ include(":adapters:plugins:fastasyncworldedit")
include(":adapters:plugins:essentials")
include(":adapters:platform:bukkit-modern")
// Main project
include(":areashop")