Compare commits

...
15 changed files with 761 additions and 159 deletions

No files matched your search

+18 -16
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")
@@ -41,6 +40,8 @@ dependencies {
implementation("net.kyori:adventure-platform-bukkit:4.3.2")
implementation("org.spongepowered:configurate-yaml:4.1.2")
implementation("org.jetbrains:annotations:23.0.0")
// Project submodules
api(projects.areashopInterface)
api(projects.adapters.platform.platformInterface)
@@ -53,18 +54,18 @@ dependencies {
runtimeOnly(projects.adapters.plugins.fastasyncworldedit)
runtimeOnly(projects.adapters.plugins.essentials)
}
testImplementation("com.github.MilkBowl:VaultAPI:1.7")
testImplementation("com.github.MilkBowl:VaultAPI:1.7")
testImplementation("me.clip:placeholderapi:2.11.6")
testImplementation(libs.worldeditBukkit)
testImplementation(libs.worldguardBukkit)
testImplementation("io.papermc.paper:paper-api:1.21.1-R0.1-SNAPSHOT")
testImplementation("com.github.seeseemelk:MockBukkit-v1.21:3.131.0")
testImplementation("org.junit.jupiter:junit-jupiter-api:5.10.1")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.10.1")
}
repositories {
mavenCentral()
}
tasks {
processResources {
filesMatching("plugin.yml") {
@@ -117,14 +118,15 @@ 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.
@@ -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;
@@ -301,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();
@@ -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.
*/
@@ -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);
@@ -635,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();
@@ -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();
}
@@ -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();
}
}
+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);
}
}
+4
View File
@@ -53,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 {