diff --git a/README.md b/README.md
index 3d6d2e0..a8544fd 100644
--- a/README.md
+++ b/README.md
@@ -21,7 +21,7 @@ How to include WorldEditWrapper into your maven project:
org.codemc.worldguardwrapper
worldguardwrapper
- 1.1.2-SNAPSHOT
+ 1.1.4-SNAPSHOT
```
diff --git a/api/pom.xml b/api/pom.xml
index 1d9e419..fa907b1 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -7,7 +7,7 @@
org.codemc.worldguardwrapper
worldguardwrapper-parent
- 1.1.3-SNAPSHOT
+ 1.1.4-SNAPSHOT
worldguardwrapper-api
diff --git a/implementation/legacy/pom.xml b/implementation/legacy/pom.xml
new file mode 100644
index 0000000..ffbac0a
--- /dev/null
+++ b/implementation/legacy/pom.xml
@@ -0,0 +1,41 @@
+
+
+ 4.0.0
+
+
+ org.codemc.worldguardwrapper
+ worldguardwrapper-implementation
+ 1.1.4-SNAPSHOT
+
+
+ worldguardwrapper-implementation-legacy
+
+ WorldGuardWrapper-Implementation-Legacy
+
+
+
+ sk89q-repo
+ http://maven.sk89q.com/repo/
+
+ always
+
+
+
+
+
+
+ ${project.groupId}
+ worldguardwrapper-api
+ 1.1.4-SNAPSHOT
+ provided
+
+
+ com.sk89q
+ worldguard
+ 6.1
+ provided
+
+
+
diff --git a/implementation/legacy/src/main/java/org/codemc/worldguardwrapper/implementation/legacy/WorldGuardImplementation.java b/implementation/legacy/src/main/java/org/codemc/worldguardwrapper/implementation/legacy/WorldGuardImplementation.java
new file mode 100644
index 0000000..ed6ac18
--- /dev/null
+++ b/implementation/legacy/src/main/java/org/codemc/worldguardwrapper/implementation/legacy/WorldGuardImplementation.java
@@ -0,0 +1,185 @@
+package org.codemc.worldguardwrapper.implementation.legacy;
+
+import com.sk89q.worldguard.LocalPlayer;
+import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
+import com.sk89q.worldguard.protection.ApplicableRegionSet;
+import com.sk89q.worldguard.protection.flags.DefaultFlag;
+import com.sk89q.worldguard.protection.flags.Flag;
+import com.sk89q.worldguard.protection.flags.StateFlag;
+import com.sk89q.worldguard.protection.managers.RegionManager;
+import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion;
+import com.sk89q.worldguard.protection.regions.ProtectedPolygonalRegion;
+import com.sk89q.worldguard.protection.regions.ProtectedRegion;
+import lombok.NoArgsConstructor;
+import lombok.NonNull;
+import org.bukkit.Location;
+import org.bukkit.World;
+import org.bukkit.entity.Player;
+import org.bukkit.plugin.java.JavaPlugin;
+import org.bukkit.util.Vector;
+import org.codemc.worldguardwrapper.flag.IWrappedFlag;
+import org.codemc.worldguardwrapper.flag.WrappedState;
+import org.codemc.worldguardwrapper.implementation.IWorldGuardImplementation;
+import org.codemc.worldguardwrapper.implementation.legacy.flag.AbstractWrappedFlag;
+import org.codemc.worldguardwrapper.implementation.legacy.flag.WrappedPrimitiveFlag;
+import org.codemc.worldguardwrapper.implementation.legacy.flag.WrappedStatusFlag;
+import org.codemc.worldguardwrapper.implementation.legacy.region.WrappedRegion;
+import org.codemc.worldguardwrapper.implementation.legacy.utility.WorldGuardVectorUtilities;
+import org.codemc.worldguardwrapper.region.IWrappedRegion;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+@NoArgsConstructor
+public class WorldGuardImplementation implements IWorldGuardImplementation {
+
+ private final WorldGuardPlugin plugin = WorldGuardPlugin.inst();
+
+ private Optional wrapPlayer(Player player) {
+ return Optional.ofNullable(player).map(bukkitPlayer -> plugin.wrapPlayer(player));
+ }
+
+ private Optional getWorldManager(@NonNull World world) {
+ return Optional.ofNullable(plugin.getRegionManager(world));
+ }
+
+ private Optional getApplicableRegions(@NonNull Location location) {
+ return getWorldManager(location.getWorld()).map(manager -> manager.getApplicableRegions(location));
+ }
+
+ private Optional getApplicableRegions(@NonNull Location minimum, @NonNull Location maximum) {
+ return getWorldManager(minimum.getWorld()).map(manager -> manager.getApplicableRegions(
+ new ProtectedCuboidRegion("temp", WorldGuardVectorUtilities.toBlockVector(minimum), WorldGuardVectorUtilities.toBlockVector(maximum))));
+ }
+
+ private Optional queryValue(Player player, @NonNull Location location, @NonNull Flag flag) {
+ return getApplicableRegions(location).map(applicableRegions -> applicableRegions.queryValue(wrapPlayer(player)
+ .orElse(null), flag));
+ }
+
+ // TODO: find a better way to define wrapper mappings and register mappings
+ @SuppressWarnings("unchecked")
+ private IWrappedFlag wrap(Flag> flag, Class type) {
+ final IWrappedFlag wrappedFlag;
+ if (type.equals(WrappedState.class)) {
+ wrappedFlag = (IWrappedFlag) new WrappedStatusFlag((Flag) flag);
+ } else if (type.equals(Boolean.class) || type.equals(boolean.class)) {
+ wrappedFlag = new WrappedPrimitiveFlag(flag);
+ } else if (type.equals(Double.class) || type.equals(double.class)) {
+ wrappedFlag = new WrappedPrimitiveFlag(flag);
+ } else if (type.equals(Enum.class)) {
+ wrappedFlag = new WrappedPrimitiveFlag(flag);
+ } else if (type.equals(Integer.class) || type.equals(int.class)) {
+ wrappedFlag = new WrappedPrimitiveFlag(flag);
+ } else if (type.equals(Location.class)) {
+ wrappedFlag = new WrappedPrimitiveFlag(flag);
+ } else if (type.equals(String.class)) {
+ wrappedFlag = new WrappedPrimitiveFlag(flag);
+ } else if (type.equals(Vector.class)) {
+ wrappedFlag = new WrappedPrimitiveFlag(flag);
+ } else {
+ throw new IllegalArgumentException("Unsupported flag type " + type.getName());
+ }
+ return wrappedFlag;
+ }
+
+ @Override
+ public JavaPlugin getWorldGuardPlugin() {
+ return WorldGuardPlugin.inst();
+ }
+
+ @Override
+ public int getApiVersion() {
+ return -6;
+ }
+
+ @Override
+ public Optional> getFlag(String name, Class type) {
+ for (Flag> currentFlag : DefaultFlag.getFlags()) {
+ if (currentFlag.getName().equalsIgnoreCase(name)) {
+ return Optional.of(wrap(currentFlag, type));
+ }
+ }
+ return Optional.empty();
+ }
+
+ @Override
+ public Optional queryFlag(Player player, Location location, IWrappedFlag flag) {
+ AbstractWrappedFlag wrappedFlag = (AbstractWrappedFlag) flag;
+ return wrappedFlag.fromWGValue(queryValue(player, location, wrappedFlag.getHandle()));
+ }
+
+ @Override
+ public Optional> registerFlag(String name, Class type, T defaultValue) {
+ throw new UnsupportedOperationException("Custom flags aren't supported in this version of WorldGuard!");
+ }
+
+ @Override
+ public Optional getRegion(World world, String id) {
+ return getWorldManager(world).map(regionManager -> new WrappedRegion(world, regionManager.getRegion(id)));
+ }
+
+ @Override
+ public Map getRegions(World world) {
+ RegionManager regionManager = plugin.getRegionManager(world);
+ Map regions = regionManager.getRegions();
+
+ Map map = new HashMap<>();
+ regions.forEach((name, region) -> map.put(name, new WrappedRegion(world, region)));
+
+ return map;
+ }
+
+ @Override
+ public Set getRegions(Location location) {
+ ApplicableRegionSet regionSet = getApplicableRegions(location).orElse(null);
+ Set set = new HashSet<>();
+
+ if (regionSet == null) {
+ return set;
+ }
+
+ regionSet.forEach(region -> set.add(new WrappedRegion(location.getWorld(), region)));
+ return set;
+ }
+
+ @Override
+ public Set getRegions(Location minimum, Location maximum) {
+ ApplicableRegionSet regionSet = getApplicableRegions(minimum, maximum).orElse(null);
+ Set set = new HashSet<>();
+
+ if (regionSet == null) {
+ return set;
+ }
+
+ regionSet.forEach(region -> set.add(new WrappedRegion(minimum.getWorld(), region)));
+ return set;
+ }
+
+ @Override
+ public Optional addRegion(String id, List points, int minY, int maxY) {
+ ProtectedRegion region;
+ World world = points.get(0).getWorld();
+ if (points.size() == 2) {
+ region = new ProtectedCuboidRegion(id, WorldGuardVectorUtilities.toBlockVector(points.get(0)), WorldGuardVectorUtilities.toBlockVector(points.get(1)));
+ } else {
+ region = new ProtectedPolygonalRegion(id, WorldGuardVectorUtilities.toBlockVector2DList(points), minY, maxY);
+ }
+
+ Optional manager = getWorldManager(world);
+ if (manager.isPresent()) {
+ manager.get().addRegion(region);
+ return Optional.of(new WrappedRegion(world, region));
+ } else {
+ return Optional.empty();
+ }
+ }
+
+ @Override
+ public Optional> removeRegion(World world, String id) {
+ Optional> set = getWorldManager(world).map(manager -> manager.removeRegion(id));
+ return set.map(protectedRegions -> protectedRegions.stream().map(region -> new WrappedRegion(world, region))
+ .collect(Collectors.toSet()));
+ }
+
+}
diff --git a/implementation/legacy/src/main/java/org/codemc/worldguardwrapper/implementation/legacy/event/EventListener.java b/implementation/legacy/src/main/java/org/codemc/worldguardwrapper/implementation/legacy/event/EventListener.java
new file mode 100644
index 0000000..c5642f7
--- /dev/null
+++ b/implementation/legacy/src/main/java/org/codemc/worldguardwrapper/implementation/legacy/event/EventListener.java
@@ -0,0 +1,100 @@
+package org.codemc.worldguardwrapper.implementation.legacy.event;
+
+import com.sk89q.worldguard.bukkit.event.block.UseBlockEvent;
+import com.sk89q.worldguard.bukkit.event.entity.DamageEntityEvent;
+import com.sk89q.worldguard.bukkit.event.entity.UseEntityEvent;
+import com.sk89q.worldguard.protection.events.DisallowedPVPEvent;
+import lombok.NoArgsConstructor;
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
+import org.bukkit.event.Event.Result;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.codemc.worldguardwrapper.event.*;
+
+@NoArgsConstructor
+public class EventListener implements Listener {
+
+ @EventHandler(priority = EventPriority.LOW)
+ public void onUseBlock(UseBlockEvent worldGuardEvent) {
+ Player player = worldGuardEvent.getCause().getFirstPlayer();
+ if (player == null) {
+ // Only forward player events for now
+ return;
+ }
+
+ AbstractWrappedEvent event = new WrappedUseBlockEvent(
+ worldGuardEvent.getOriginalEvent(),
+ player, worldGuardEvent.getWorld(),
+ worldGuardEvent.getBlocks(),
+ worldGuardEvent.getEffectiveMaterial());
+ Bukkit.getServer().getPluginManager().callEvent(event);
+
+ if (event.getResult() != Result.DEFAULT) {
+ // DEFAULT = Result probably has not been touched by the handler,
+ // so don't touch the original result either.
+ worldGuardEvent.setResult(event.getResult());
+ }
+ }
+
+ @EventHandler(priority = EventPriority.LOW)
+ public void onUseEntity(UseEntityEvent worldGuardEvent) {
+ Player player = worldGuardEvent.getCause().getFirstPlayer();
+ if (player == null) {
+ // Only forward player events for now
+ return;
+ }
+
+ AbstractWrappedEvent event = new WrappedUseEntityEvent(
+ worldGuardEvent.getOriginalEvent(),
+ player,
+ worldGuardEvent.getTarget(),
+ worldGuardEvent.getEntity());
+ Bukkit.getServer().getPluginManager().callEvent(event);
+
+ if (event.getResult() != Result.DEFAULT) {
+ // DEFAULT = Result probably has not been touched by the handler,
+ // so don't touch the original result either.
+ worldGuardEvent.setResult(event.getResult());
+ }
+ }
+
+ @EventHandler(priority = EventPriority.LOW)
+ public void onDamageEntity(DamageEntityEvent worldGuardEvent) {
+ Player player = worldGuardEvent.getCause().getFirstPlayer();
+ if (player == null) {
+ // Only forward player events for now
+ return;
+ }
+
+ AbstractWrappedEvent event = new WrappedDamageEntityEvent(
+ worldGuardEvent.getOriginalEvent(),
+ player,
+ worldGuardEvent.getTarget(),
+ worldGuardEvent.getEntity());
+ Bukkit.getServer().getPluginManager().callEvent(event);
+
+ if (event.getResult() != Result.DEFAULT) {
+ // DEFAULT = Result probably has not been touched by the handler,
+ // so don't touch the original result either.
+ worldGuardEvent.setResult(event.getResult());
+ }
+ }
+
+ @EventHandler(priority = EventPriority.LOW)
+ public void onDisallowedPVP(DisallowedPVPEvent worldGuardEvent) {
+ AbstractWrappedEvent event = new WrappedDisallowedPVPEvent(
+ worldGuardEvent.getAttacker(),
+ worldGuardEvent.getDefender(),
+ worldGuardEvent.getCause());
+ Bukkit.getServer().getPluginManager().callEvent(event);
+
+ if (event.getResult() != Result.DEFAULT) {
+ // DEFAULT = Result probably has not been touched by the handler,
+ // so don't touch the original result either.
+ worldGuardEvent.setCancelled(event.getResult() == Result.DENY);
+ }
+ }
+
+}
diff --git a/implementation/legacy/src/main/java/org/codemc/worldguardwrapper/implementation/legacy/flag/AbstractWrappedFlag.java b/implementation/legacy/src/main/java/org/codemc/worldguardwrapper/implementation/legacy/flag/AbstractWrappedFlag.java
new file mode 100644
index 0000000..af0080d
--- /dev/null
+++ b/implementation/legacy/src/main/java/org/codemc/worldguardwrapper/implementation/legacy/flag/AbstractWrappedFlag.java
@@ -0,0 +1,30 @@
+package org.codemc.worldguardwrapper.implementation.legacy.flag;
+
+import com.sk89q.worldguard.protection.flags.Flag;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import org.codemc.worldguardwrapper.flag.IWrappedFlag;
+
+import java.util.Optional;
+
+@AllArgsConstructor
+@Getter
+public abstract class AbstractWrappedFlag implements IWrappedFlag {
+
+ private final Flag> handle;
+
+ @Override
+ public String getName() {
+ return handle.getName();
+ }
+
+ public abstract Optional fromWGValue(Object value);
+
+ public abstract Optional