Add WorldGuard integration

This commit is contained in:
Flowsqy 2022-06-26 03:39:03 +02:00
parent b301c048a1
commit 543caae3a4
18 changed files with 502 additions and 4 deletions

15
external/README.md vendored Normal file
View File

@ -0,0 +1,15 @@
# External module
The external module contains all the integration to other plugins.
## WorldGuard
It adds three flags:
- **create-shop**:
Whether the player can create shop in the WorldGuard area
- **use-shop**:
Whether the player can use shop if he is not a member in the WorldGuard area
- **use-admin-shop**:
Whether the player can use admin shop if he is not a member in the WorldGuard area
You can define the default value of these flags in the configuration.

8
external/pom.xml vendored
View File

@ -17,6 +17,14 @@
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
</dependency>
<dependency>
<groupId>de.epiceric</groupId>
<artifactId>shopchest-common</artifactId>
</dependency>
<dependency>
<groupId>com.sk89q.worldguard</groupId>
<artifactId>worldguard-bukkit</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,31 @@
package de.epiceric.shopchest.external;
public class ExternalLoadData {
private int flags;
public ExternalLoadData() {
flags = 0;
}
public void setFlag(Flags flag) {
flags = flag.setFlag(flags);
}
public boolean isFlag(Flags flag) {
return flag.isFlag(flags);
}
public enum Flags {
CREATE, USE, USE_ADMIN;
private int setFlag(int data) {
return data | 1 << ordinal();
}
private boolean isFlag(int data) {
return (data >>> ordinal() & 1) == 1;
}
}
}

View File

@ -0,0 +1,52 @@
package de.epiceric.shopchest.external;
import de.epiceric.shopchest.hook.HookManager;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;
public abstract class ExternalLoader {
protected final HookManager hookManager;
protected final ExternalLoadData loadData;
private boolean stopped;
public ExternalLoader(HookManager hookManager, ExternalLoadData loadData) {
this.hookManager = hookManager;
this.loadData = loadData;
}
public boolean isStopped() {
return stopped;
}
public void setStopped(boolean stopped) {
this.stopped = stopped;
}
protected Plugin getPluginInstance(String pluginName) {
final Plugin plugin = Bukkit.getPluginManager().getPlugin(pluginName);
if (plugin == null) {
throw new IllegalStateException("'" + pluginName + "' plugin is not present");
}
return plugin;
}
protected <T extends JavaPlugin> T checkPluginInstanceType(Plugin plugin, Class<T> clazz) {
if (!clazz.isInstance(plugin)) {
throw new IllegalArgumentException("Wrong '" + plugin.getName() + "' plugin");
}
return clazz.cast(plugin);
}
public abstract String getName();
public abstract void check();
public void load() {
}
public void enable() {
}
}

View File

@ -0,0 +1,9 @@
package de.epiceric.shopchest.external;
public interface FlagHolder<T> {
T get();
void register();
}

View File

@ -0,0 +1,49 @@
package de.epiceric.shopchest.external;
public abstract class FlagRegistry<T> {
protected FlagHolder<T> create, use, useAdmin;
private boolean initialized, registered;
public FlagRegistry() {
}
public FlagHolder<T> getCreate() {
return create;
}
public FlagHolder<T> getUse() {
return use;
}
public FlagHolder<T> getUseAdmin() {
return useAdmin;
}
public void initialize(ExternalLoadData loadData) {
if (initialized) {
throw new IllegalStateException("Flags are already initialized");
}
initializeFlag(loadData);
initialized = true;
}
protected abstract void initializeFlag(ExternalLoadData loadData);
public void register() {
if (registered) {
throw new IllegalStateException("Flags are already registered");
}
if (!initialized) {
throw new IllegalStateException("Flags are not initialized");
}
create.register();
use.register();
useAdmin.register();
registered = true;
}
}

View File

@ -0,0 +1,32 @@
package de.epiceric.shopchest.external.worldguard;
import com.sk89q.worldguard.protection.flags.StateFlag;
// Custom class to use specificities of Flags.BUILD
// It's the cleanest way to allow use shop flags for member by default
class UseFlag extends StateFlag {
public UseFlag(String name, boolean def) {
super(name, def);
}
@Override
public boolean implicitlySetWithMembership() {
return true;
}
@Override
public boolean usesMembershipAsDefault() {
return true;
}
@Override
public boolean preventsAllowOnGlobal() {
return true;
}
@Override
public boolean requiresSubject() {
return true;
}
}

View File

@ -0,0 +1,34 @@
package de.epiceric.shopchest.external.worldguard;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.world.World;
import de.epiceric.shopchest.hook.CreateShopHook;
import de.epiceric.shopchest.hook.ExtendShopHook;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import java.util.List;
public class WGCreateHook extends WGHook implements CreateShopHook, ExtendShopHook {
public WGCreateHook(WGFlagRegistry registry) {
super(registry);
}
@Override
public boolean canCreate(Block clickedBlock, List<Block> shopBlocks, Player player) {
final World world = BukkitAdapter.adapt(clickedBlock.getWorld());
final List<Location> locations = getLocations(world, shopBlocks);
return test(locations, player, registry.getCreate().get());
}
@Override
public boolean canExtend(Block newestBlock, List<Block> currentShopBlocks, Player player) {
final World world = BukkitAdapter.adapt(newestBlock.getWorld());
final List<Location> locations = getLocations(world, currentShopBlocks);
locations.add(getLocation(world, newestBlock));
return test(locations, null, registry.getCreate().get());
}
}

View File

@ -0,0 +1,24 @@
package de.epiceric.shopchest.external.worldguard;
import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.protection.flags.StateFlag;
import de.epiceric.shopchest.external.FlagHolder;
public class WGFlagHolder implements FlagHolder<StateFlag> {
private final StateFlag flag;
public WGFlagHolder(StateFlag flag) {
this.flag = flag;
}
@Override
public StateFlag get() {
return flag;
}
@Override
public void register() {
WorldGuard.getInstance().getFlagRegistry().register(flag);
}
}

View File

@ -0,0 +1,29 @@
package de.epiceric.shopchest.external.worldguard;
import com.sk89q.worldguard.protection.flags.StateFlag;
import de.epiceric.shopchest.external.ExternalLoadData;
import de.epiceric.shopchest.external.FlagRegistry;
public class WGFlagRegistry extends FlagRegistry<StateFlag> {
@Override
protected void initializeFlag(ExternalLoadData loadData) {
create = new WGFlagHolder(
new StateFlag(
"create-shop",
loadData.isFlag(ExternalLoadData.Flags.CREATE)
)
);
use = new WGFlagHolder(
new UseFlag(
"use-shop",
loadData.isFlag(ExternalLoadData.Flags.USE)
)
);
useAdmin = new WGFlagHolder(
new UseFlag(
"use-admin-shop",
loadData.isFlag(ExternalLoadData.Flags.USE_ADMIN)
)
);
}
}

View File

@ -0,0 +1,51 @@
package de.epiceric.shopchest.external.worldguard;
import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.protection.ApplicableRegionSet;
import com.sk89q.worldguard.protection.flags.StateFlag;
import com.sk89q.worldguard.protection.regions.RegionQuery;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import java.util.LinkedList;
import java.util.List;
public abstract class WGHook {
protected final WGFlagRegistry registry;
public WGHook(WGFlagRegistry registry) {
this.registry = registry;
}
protected List<Location> getLocations(World world, List<Block> blocks) {
final List<Location> locations = new LinkedList<>();
for (Block block : blocks) {
locations.add(getLocation(world, block));
}
return locations;
}
protected Location getLocation(World world, Block block) {
return new Location(world, Vector3.at(block.getX(), block.getY(), block.getZ()));
}
protected boolean test(List<Location> locations, Player player, StateFlag... flag) {
final LocalPlayer wgPlayer = player == null ? null : WorldGuardPlugin.inst().wrapPlayer(player);
final RegionQuery query = WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery();
for (Location location : locations) {
final ApplicableRegionSet set = query.getApplicableRegions(location);
if (!set.testState(wgPlayer, flag)) {
return false;
}
}
return true;
}
}

View File

@ -0,0 +1,56 @@
package de.epiceric.shopchest.external.worldguard;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import de.epiceric.shopchest.external.ExternalLoadData;
import de.epiceric.shopchest.external.ExternalLoader;
import de.epiceric.shopchest.hook.HookManager;
import org.bukkit.plugin.Plugin;
public class WGLoader extends ExternalLoader {
// Maybe need to enable listener for deny message (see old listeners2)
private final WGFlagRegistry flagRegistry;
public WGLoader(HookManager hookManager, ExternalLoadData loadData) {
super(hookManager, loadData);
this.flagRegistry = new WGFlagRegistry();
}
@Override
public String getName() {
return "WorldGuard";
}
@Override
public void check() {
// Get WorldGuard instance
final Plugin plugin = getPluginInstance(getName());
// Check WorldGuard version and type
final String wgVersion = plugin.getDescription().getVersion();
final String majorVersion = wgVersion.split("\\.")[0];
// TODO Add v6 compatibility (maybe)
if (!"7".equals(majorVersion)) {
throw new IllegalArgumentException("Unsupported " + getName() + " version : " + wgVersion);
}
checkPluginInstanceType(plugin, WorldGuardPlugin.class);
}
@Override
public void load() {
// Register flags
flagRegistry.initialize(loadData);
flagRegistry.register();
}
@Override
public void enable() {
// Register hooks
final WGCreateHook createHook = new WGCreateHook(flagRegistry);
hookManager.registerCreateShopHook(createHook);
hookManager.registerExtendShopHook(createHook);
final WGUseHook useHook = new WGUseHook(flagRegistry);
hookManager.registerUseShopHook(useHook);
}
}

View File

@ -0,0 +1,27 @@
package de.epiceric.shopchest.external.worldguard;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.util.Location;
import de.epiceric.shopchest.hook.UseShopHook;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import java.util.Collections;
public class WGUseHook extends WGHook implements UseShopHook {
public WGUseHook(WGFlagRegistry registry) {
super(registry);
}
@Override
public boolean canUseShop(Block block, Player player, boolean admin) {
final Location location = getLocation(BukkitAdapter.adapt(block.getWorld()), block);
return test(
Collections.singletonList(location),
player,
admin ? registry.getUseAdmin().get() : registry.getUse().get()
);
}
}

View File

@ -45,6 +45,7 @@
<dependency>
<groupId>de.epiceric</groupId>
<artifactId>shopchest-common</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>de.epiceric</groupId>

View File

@ -117,8 +117,10 @@ public class ShopChest extends JavaPlugin {
debugLogger.debug("Loading ShopChest version " + getDescription().getVersion());
hookManager = new HookManager();
externalManager = new ExternalManager();
externalManager = new ExternalManager(hookManager, debugLogger);
externalManager.setup();
externalManager.check();
externalManager.load();
}

View File

@ -1,8 +1,66 @@
package de.epiceric.shopchest.external;
import de.epiceric.shopchest.config.Config;
import de.epiceric.shopchest.debug.DebugLogger;
import de.epiceric.shopchest.external.worldguard.WGLoader;
import de.epiceric.shopchest.hook.HookManager;
import java.util.LinkedList;
import java.util.List;
import java.util.function.Consumer;
public class ExternalManager {
private final HookManager hookManager;
private final DebugLogger logger;
private final List<ExternalLoader> loaders;
public ExternalManager(HookManager hookManager, DebugLogger logger) {
this.hookManager = hookManager;
this.logger = logger;
loaders = new LinkedList<>();
}
public void setup() {
// Add WorldGuard
if (Config.enableWorldGuardIntegration) {
final ExternalLoadData loadData = new ExternalLoadData();
if (Config.wgAllowCreateShopDefault) {
loadData.setFlag(ExternalLoadData.Flags.CREATE);
}
if (Config.wgAllowUseShopDefault) {
loadData.setFlag(ExternalLoadData.Flags.USE);
}
if (Config.wgAllowUseAdminShopDefault) {
loadData.setFlag(ExternalLoadData.Flags.USE_ADMIN);
}
loaders.add(new WGLoader(hookManager, loadData));
}
}
private void executePhase(Consumer<ExternalLoader> phase) {
for (ExternalLoader loader : loaders) {
if (loader.isStopped()) {
continue;
}
try {
phase.accept(loader);
} catch (Exception e) {
logger.debug("Can not load '" + loader.getName() + "' integration :");
logger.debug(e.getMessage());
loader.setStopped(true);
}
}
}
public void check() {
executePhase(ExternalLoader::check);
}
public void load() {
executePhase(ExternalLoader::load);
// TODO EXTERNAL : Register WorldGuard Flags
/*
@ -13,6 +71,10 @@ public class ExternalManager {
}
public void enable() {
executePhase(ExternalLoader::enable);
executePhase(loader -> logger.debug("Successfully loaded '" + loader.getName() + "' integration"));
// TODO EXTERNAL : Load Integrations
/*
@ -117,7 +179,6 @@ public class ExternalManager {
}
// TODO EXTERNAL Plugins supports
/*

View File

@ -7,6 +7,9 @@ author: EpicEric
website: "${project.url}"
description: Create your own nice-looking chest shops and sell your stuff to other players!
depend: [Vault]
softdepend:
- WorldEdit
- WorldGuard
api-version: "1.13"
permissions:

16
pom.xml
View File

@ -88,6 +88,11 @@
<id>jitpack-repo</id>
<url>https://jitpack.io</url>
</repository>
<!-- EngineHub repo (WorldEdit, WorldGuard) -->
<repository>
<id>enginehub-repo</id>
<url>https://maven.enginehub.org/repo/</url>
</repository>
</repositories>
<dependencyManagement>
@ -114,6 +119,14 @@
<scope>provided</scope>
</dependency>
<!-- External dependencies -->
<dependency>
<groupId>com.sk89q.worldguard</groupId>
<artifactId>worldguard-bukkit</artifactId>
<version>7.0.7</version>
<scope>provided</scope>
</dependency>
<!-- Only required for build to succeed ? -->
<dependency>
<groupId>org.projectlombok</groupId>
@ -145,6 +158,7 @@
<groupId>de.epiceric</groupId>
<artifactId>shopchest-common</artifactId>
<version>1.0.0</version>
<scope>provided</scope>
</dependency>
<!-- NMS -->
<dependency>
@ -182,7 +196,7 @@
<artifactId>shopchest-nms-v1_19_R1</artifactId>
<version>1.0.0</version>
</dependency>
<!-- External plugins -->
<!-- External plugins support -->
<dependency>
<groupId>de.epiceric</groupId>
<artifactId>shopchest-external</artifactId>