diff --git a/NMS/API/build.gradle b/NMS/API/build.gradle
deleted file mode 100644
index 4c4c6db8..00000000
--- a/NMS/API/build.gradle
+++ /dev/null
@@ -1,9 +0,0 @@
-dependencies {
- compileOnly 'org.spigotmc:spigot-api:1.15.2-R0.1-SNAPSHOT'
-}
-
-jar {
- archiveFileName = findProperty("Name") + " v" + findProperty("version") + ".jar"
-}
-
-description = 'EcoEnchants API'
diff --git a/NMS/API/src/main/java/com/willfp/ecoenchants/nms/api/BlockBreakWrapper.java b/NMS/API/src/main/java/com/willfp/ecoenchants/nms/api/BlockBreakWrapper.java
deleted file mode 100644
index ee746cdc..00000000
--- a/NMS/API/src/main/java/com/willfp/ecoenchants/nms/api/BlockBreakWrapper.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.willfp.ecoenchants.nms.api;
-
-import org.bukkit.block.Block;
-import org.bukkit.entity.Player;
-
-/**
- * NMS Interface for breaking blocks as player
- */
-public interface BlockBreakWrapper {
- void breakBlock(Player player, Block block);
-}
diff --git a/NMS/API/src/main/java/com/willfp/ecoenchants/nms/api/ChatComponentWrapper.java b/NMS/API/src/main/java/com/willfp/ecoenchants/nms/api/ChatComponentWrapper.java
deleted file mode 100644
index f01192fd..00000000
--- a/NMS/API/src/main/java/com/willfp/ecoenchants/nms/api/ChatComponentWrapper.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.willfp.ecoenchants.nms.api;
-
-public interface ChatComponentWrapper {
- Object modifyComponent(Object object);
-}
diff --git a/NMS/API/src/main/java/com/willfp/ecoenchants/nms/api/CooldownWrapper.java b/NMS/API/src/main/java/com/willfp/ecoenchants/nms/api/CooldownWrapper.java
deleted file mode 100644
index f4f55b26..00000000
--- a/NMS/API/src/main/java/com/willfp/ecoenchants/nms/api/CooldownWrapper.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.willfp.ecoenchants.nms.api;
-
-import org.bukkit.entity.Player;
-
-/**
- * NMS Interface for getting attack cooldown
- */
-public interface CooldownWrapper {
- double getAttackCooldown(Player player);
-}
diff --git a/NMS/API/src/main/java/com/willfp/ecoenchants/nms/api/OpenInventoryWrapper.java b/NMS/API/src/main/java/com/willfp/ecoenchants/nms/api/OpenInventoryWrapper.java
deleted file mode 100644
index f6bc7e80..00000000
--- a/NMS/API/src/main/java/com/willfp/ecoenchants/nms/api/OpenInventoryWrapper.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.willfp.ecoenchants.nms.api;
-
-import org.bukkit.entity.Player;
-
-public interface OpenInventoryWrapper {
- Object getOpenInventory(Player player);
-}
diff --git a/NMS/API/src/main/java/com/willfp/ecoenchants/nms/api/RepairCostWrapper.java b/NMS/API/src/main/java/com/willfp/ecoenchants/nms/api/RepairCostWrapper.java
deleted file mode 100644
index af8beeae..00000000
--- a/NMS/API/src/main/java/com/willfp/ecoenchants/nms/api/RepairCostWrapper.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.willfp.ecoenchants.nms.api;
-
-import org.bukkit.inventory.ItemStack;
-
-/**
- * NMS Interface for getting/setting anvil repair cost
- */
-public interface RepairCostWrapper {
- ItemStack setRepairCost(ItemStack itemStack, int cost);
-
- int getRepairCost(ItemStack itemStack);
-}
diff --git a/NMS/API/src/main/java/com/willfp/ecoenchants/nms/api/TridentStackWrapper.java b/NMS/API/src/main/java/com/willfp/ecoenchants/nms/api/TridentStackWrapper.java
deleted file mode 100644
index 13fee844..00000000
--- a/NMS/API/src/main/java/com/willfp/ecoenchants/nms/api/TridentStackWrapper.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.willfp.ecoenchants.nms.api;
-
-import org.bukkit.entity.Trident;
-import org.bukkit.inventory.ItemStack;
-
-/**
- * NMS Interface for getting an ItemStack from a Trident
- */
-public interface TridentStackWrapper {
- ItemStack getTridentStack(Trident trident);
-}
\ No newline at end of file
diff --git a/NMS/v1_15_R1/build.gradle b/NMS/v1_15_R1/build.gradle
deleted file mode 100644
index dbe87bd6..00000000
--- a/NMS/v1_15_R1/build.gradle
+++ /dev/null
@@ -1,10 +0,0 @@
-dependencies {
- compileOnly project(':API')
- compileOnly 'org.spigotmc:spigot:1.15.2-R0.1-SNAPSHOT'
-}
-
-jar {
- archiveFileName = project.name + " v" + findProperty("version") + ".jar"
-}
-
-description = 'v1_15_R1'
diff --git a/NMS/v1_15_R1/src/main/java/com/willfp/ecoenchants/nms/v1_15_R1/ChatComponent.java b/NMS/v1_15_R1/src/main/java/com/willfp/ecoenchants/nms/v1_15_R1/ChatComponent.java
deleted file mode 100644
index b7d4f9ec..00000000
--- a/NMS/v1_15_R1/src/main/java/com/willfp/ecoenchants/nms/v1_15_R1/ChatComponent.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.willfp.ecoenchants.nms.v1_15_R1;
-
-import com.willfp.ecoenchants.nms.api.ChatComponentWrapper;
-
-public class ChatComponent implements ChatComponentWrapper {
- @Override
- public Object modifyComponent(Object object) {
- return object;
- }
-}
diff --git a/NMS/v1_16_R1/build.gradle b/NMS/v1_16_R1/build.gradle
deleted file mode 100644
index 40e3958a..00000000
--- a/NMS/v1_16_R1/build.gradle
+++ /dev/null
@@ -1,10 +0,0 @@
-dependencies {
- compileOnly project(':API')
- compileOnly 'org.spigotmc:spigot:1.16.1-R0.1-SNAPSHOT'
-}
-
-jar {
- archiveFileName = project.name + " v" + findProperty("version") + ".jar"
-}
-
-description = 'v1_16_R1'
diff --git a/NMS/v1_16_R2/build.gradle b/NMS/v1_16_R2/build.gradle
deleted file mode 100644
index 1f6676f6..00000000
--- a/NMS/v1_16_R2/build.gradle
+++ /dev/null
@@ -1,10 +0,0 @@
-dependencies {
- compileOnly project(':API')
- compileOnly 'org.spigotmc:spigot:1.16.2-R0.1-SNAPSHOT'
-}
-
-jar {
- archiveFileName = project.name + " v" + findProperty("version") + ".jar"
-}
-
-description = 'v1_16_R2'
diff --git a/NMS/v1_16_R3/build.gradle b/NMS/v1_16_R3/build.gradle
deleted file mode 100644
index e71452b3..00000000
--- a/NMS/v1_16_R3/build.gradle
+++ /dev/null
@@ -1,10 +0,0 @@
-dependencies {
- compileOnly project(':API')
- compileOnly 'org.spigotmc:spigot:1.16.4-R0.1-SNAPSHOT'
-}
-
-jar {
- archiveFileName = project.name + " v" + findProperty("version") + ".jar"
-}
-
-description = 'v1_16_R3'
diff --git a/Plugin/build.gradle b/Plugin/build.gradle
index cd04c497..e69de29b 100644
--- a/Plugin/build.gradle
+++ b/Plugin/build.gradle
@@ -1,71 +0,0 @@
-plugins {
- id 'com.github.johnrengelman.shadow' version '5.2.0'
- id 'maven-publish'
- id 'maven'
-}
-
-dependencies {
- implementation project(':API')
- implementation project(':v1_15_R1')
- implementation project(':v1_16_R1')
- implementation project(':v1_16_R2')
- implementation project(':v1_16_R3')
- implementation 'org.apache.maven:maven-artifact:3.0.3'
- implementation 'org.bstats:bstats-bukkit:1.7'
- compileOnly 'org.spigotmc:spigot-api:1.16.3-R0.1-SNAPSHOT'
- compileOnly 'commons-io:commons-io:2.8.0'
- compileOnly 'com.sk89q.worldguard:worldguard-bukkit:7.0.4-SNAPSHOT'
- compileOnly 'com.github.TechFortress:GriefPrevention:16.14.0'
- compileOnly 'com.massivecraft:Factions:1.6.9.5-U0.5.10'
- compileOnly 'com.github.cryptomorin:kingdoms:1.10.3.1'
- shadow files('../lib/SpartanAPI.jar')
- shadow files('../lib/aac-api-5.0.0.jar')
- compileOnly 'com.github.TownyAdvanced:Towny:0.96.2.0'
- compileOnly 'com.github.angeschossen:LandsAPI:4.7.3'
- compileOnly 'fr.neatmonster:nocheatplus:3.16.1-SNAPSHOT'
- compileOnly 'com.github.jiangdashao:matrix-api-repo:317d4635fd'
- compileOnly 'com.comphenix.protocol:ProtocolLib:4.6.0-SNAPSHOT'
- compileOnly 'net.ess3:EssentialsX:2.18.1'
- compileOnly 'com.destroystokyo.paper:paper-api:1.16.3-R0.1-SNAPSHOT'
- compileOnly 'com.gmail.nossr50.mcMMO:mcMMO:2.1.157'
- compileOnly 'me.clip:placeholderapi:2.10.9'
- compileOnly 'org.jetbrains:annotations:19.0.0'
-}
-
-shadowJar {
- relocate('org.bstats.bukkit', 'com.willfp.ecoenchants.shaded.bstats')
- relocate('org.apache.maven', 'com.willfp.ecoenchants.shaded.maven')
- archiveFileName = findProperty("plugin-name") + " v" + findProperty("version") + ".jar"
-}
-
-processResources {
- filesNotMatching(["**/*.png", "**/models/**", "**/textures/**"]) {
- expand projectVersion: findProperty("version")
- }
-}
-
-jar {
- archiveFileName = findProperty("plugin-name") + " v" + findProperty("version") + " " + "unshaded" + ".jar"
-}
-
-tasks.withType(JavaCompile) {
- options.encoding = 'UTF-8'
-}
-
-tasks.withType(Jar) {
- destinationDirectory = file("$rootDir/bin/")
-}
-
-build.dependsOn shadowJar
-
-description = 'EcoEnchants'
-compileJava.options.encoding = 'UTF-8'
-
-
-publishing {
- publications {
- mavenJava(MavenPublication) {
- from components.java
- }
- }
-}
\ No newline at end of file
diff --git a/Plugin/src/main/java/com/willfp/ecoenchants/util/internal/updater/PlayerJoinListener.java b/Plugin/src/main/java/com/willfp/ecoenchants/util/internal/updater/PlayerJoinListener.java
deleted file mode 100644
index 87e418e4..00000000
--- a/Plugin/src/main/java/com/willfp/ecoenchants/util/internal/updater/PlayerJoinListener.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.willfp.ecoenchants.util.internal.updater;
-
-import com.willfp.ecoenchants.EcoEnchantsPlugin;
-import com.willfp.ecoenchants.config.ConfigManager;
-import org.bukkit.event.EventHandler;
-import org.bukkit.event.Listener;
-import org.bukkit.event.player.PlayerJoinEvent;
-
-public class PlayerJoinListener implements Listener {
- @EventHandler
- public void onPlayerJoin(PlayerJoinEvent event) {
- if (UpdateChecker.isOutdated()) {
- if (event.getPlayer().hasPermission("ecoenchants.updateannounce")) {
- event.getPlayer().sendMessage(ConfigManager.getLang().getMessage("outdated").replace("%ver%", EcoEnchantsPlugin.getInstance().getDescription().getVersion())
- .replace("%newver%", UpdateChecker.getNewVersion()));
- }
- }
- }
-}
diff --git a/build.gradle b/build.gradle
index 32c97984..54bcae82 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,45 +1,47 @@
plugins {
id 'java-library'
+ id 'com.github.johnrengelman.shadow' version '5.2.0'
id 'maven-publish'
id 'java'
}
+dependencies {
+ implementation getSubprojects()
+}
+
allprojects {
apply plugin: 'java'
apply plugin: 'maven-publish'
+ apply plugin: 'com.github.johnrengelman.shadow'
+
repositories {
mavenCentral()
jcenter()
mavenLocal()
-
- maven { url 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/' }
- maven { url 'https://repo.codemc.org/repository/maven-public' }
- maven { url 'https://repo.codemc.org/repository/nms/' }
- maven { url "https://oss.sonatype.org/content/repositories/snapshots" }
- maven { url 'https://oss.sonatype.org/content/groups/public/' }
- maven { url 'https://maven.enginehub.org/repo/' }
maven { url 'https://jitpack.io' }
- maven { url 'https://ci.ender.zone/plugin/repository/project/' }
- maven { url 'https://ci.ender.zone/plugin/repository/everything/' }
- maven { url 'https://repo.md-5.net/content/repositories/snapshots/' }
- maven { url 'https://repo.dmulloy2.net/nexus/repository/public/' }
- maven { url 'https://papermc.io/repo/repository/maven-public/' }
- maven { url 'https://repo.maven.apache.org/maven2/' }
- maven { url 'https://repo.dustplanet.de/artifactory/ext-release-local/' }
- maven { url 'https://maven.seyfahni.de/repository/snapshots/' }
- maven { url 'https://libraries.minecraft.net/' }
- maven { url 'https://repo.spongepowered.org/maven/' }
- maven { url 'https://org.kitteh.pastegg' }
- maven { url 'https://repo.mikeprimm.com/' }
- maven { url 'https://maven.sk89q.com/repo/' }
- maven { url 'https://github.com/factions-site/repo/raw/public/' }
- maven { url 'https://repo.extendedclip.com/content/repositories/placeholderapi/' }
+ maven { url 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/' }
+ maven { url 'https://repo.codemc.org/repository/nms/' }
+ }
+
+ dependencies {
+ compileOnly 'org.jetbrains:annotations:19.0.0'
}
tasks.withType(JavaCompile) {
options.deprecation = true
options.encoding = 'UTF-8'
}
+
+ tasks.withType(Jar) {
+ destinationDirectory = file("$rootDir/bin/")
+ }
+
+ processResources {
+ filesNotMatching(["**/*.png", "**/models/**", "**/textures/**"]) {
+ expand projectVersion: findProperty("version")
+ }
+ }
+
compileJava.options.encoding = 'UTF-8'
compileJava.dependsOn clean
}
@@ -48,11 +50,25 @@ clean.doLast {
file("${rootDir}/bin").deleteDir()
}
-group = 'com.willfp.ecoenchants'
+shadowJar {
+ relocate('org.bstats.bukkit', 'com.willfp.ecoenchants.shaded.bstats')
+ relocate('org.apache.maven', 'com.willfp.ecoenchants.shaded.maven')
+ archiveFileName = findProperty("plugin-name") + " v" + findProperty("version") + ".jar"
+}
+
+jar {
+ archiveFileName = findProperty("plugin-name") + " v" + findProperty("version") + " " + "unshaded" + ".jar"
+}
+
+group = 'com.willfp'
archivesBaseName = project.name
version = project.version
java.sourceCompatibility = JavaVersion.VERSION_1_8
+compileJava.options.encoding = 'UTF-8'
+
+build.dependsOn shadowJar
+
publishing {
publications {
maven(MavenPublication) {
diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml
new file mode 100644
index 00000000..e6a55441
--- /dev/null
+++ b/config/checkstyle/checkstyle.xml
@@ -0,0 +1,180 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/eco-core/build.gradle b/eco-core/build.gradle
new file mode 100644
index 00000000..eb65e048
--- /dev/null
+++ b/eco-core/build.gradle
@@ -0,0 +1,8 @@
+group 'com.willfp'
+version rootProject.version
+
+subprojects {
+ dependencies {
+ compileOnly project(":eco-util")
+ }
+}
\ No newline at end of file
diff --git a/eco-core/core-nms/build.gradle b/eco-core/core-nms/build.gradle
new file mode 100644
index 00000000..34b97e1c
--- /dev/null
+++ b/eco-core/core-nms/build.gradle
@@ -0,0 +1,8 @@
+group 'com.willfp'
+version rootProject.version
+
+subprojects {
+ dependencies {
+ compileOnly project(':eco-core:core-proxy')
+ }
+}
\ No newline at end of file
diff --git a/eco-core/core-nms/v1_15_R1/build.gradle b/eco-core/core-nms/v1_15_R1/build.gradle
new file mode 100644
index 00000000..52cdf754
--- /dev/null
+++ b/eco-core/core-nms/v1_15_R1/build.gradle
@@ -0,0 +1,6 @@
+group 'com.willfp'
+version rootProject.version
+
+dependencies {
+ compileOnly 'org.spigotmc:spigot:1.15.2-R0.1-SNAPSHOT'
+}
\ No newline at end of file
diff --git a/NMS/v1_15_R1/src/main/java/com/willfp/ecoenchants/nms/v1_15_R1/BlockBreak.java b/eco-core/core-nms/v1_15_R1/src/main/java/com/willfp/eco/core/proxy/v1_15_R1/BlockBreak.java
similarity index 71%
rename from NMS/v1_15_R1/src/main/java/com/willfp/ecoenchants/nms/v1_15_R1/BlockBreak.java
rename to eco-core/core-nms/v1_15_R1/src/main/java/com/willfp/eco/core/proxy/v1_15_R1/BlockBreak.java
index c23e65dc..e79b7de5 100644
--- a/NMS/v1_15_R1/src/main/java/com/willfp/ecoenchants/nms/v1_15_R1/BlockBreak.java
+++ b/eco-core/core-nms/v1_15_R1/src/main/java/com/willfp/eco/core/proxy/v1_15_R1/BlockBreak.java
@@ -1,12 +1,12 @@
-package com.willfp.ecoenchants.nms.v1_15_R1;
+package com.willfp.eco.core.proxy.v1_15_R1;
-import com.willfp.ecoenchants.nms.api.BlockBreakWrapper;
+import com.willfp.eco.core.proxy.proxies.BlockBreakProxy;
import net.minecraft.server.v1_15_R1.BlockPosition;
import org.bukkit.block.Block;
import org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer;
import org.bukkit.entity.Player;
-public class BlockBreak implements BlockBreakWrapper {
+public class BlockBreak implements BlockBreakProxy {
@Override
public void breakBlock(Player player, Block block) {
((CraftPlayer) player).getHandle().playerInteractManager.breakBlock(new BlockPosition(block.getX(), block.getY(), block.getZ()));
diff --git a/eco-core/core-nms/v1_15_R1/src/main/java/com/willfp/eco/core/proxy/v1_15_R1/ChatComponent.java b/eco-core/core-nms/v1_15_R1/src/main/java/com/willfp/eco/core/proxy/v1_15_R1/ChatComponent.java
new file mode 100644
index 00000000..a035ba78
--- /dev/null
+++ b/eco-core/core-nms/v1_15_R1/src/main/java/com/willfp/eco/core/proxy/v1_15_R1/ChatComponent.java
@@ -0,0 +1,10 @@
+package com.willfp.eco.core.proxy.v1_15_R1;
+
+import com.willfp.eco.core.proxy.proxies.ChatComponentProxy;
+
+public class ChatComponent implements ChatComponentProxy {
+ @Override
+ public Object modifyComponent(Object object) {
+ return object;
+ }
+}
diff --git a/NMS/v1_15_R1/src/main/java/com/willfp/ecoenchants/nms/v1_15_R1/Cooldown.java b/eco-core/core-nms/v1_15_R1/src/main/java/com/willfp/eco/core/proxy/v1_15_R1/Cooldown.java
similarity index 68%
rename from NMS/v1_15_R1/src/main/java/com/willfp/ecoenchants/nms/v1_15_R1/Cooldown.java
rename to eco-core/core-nms/v1_15_R1/src/main/java/com/willfp/eco/core/proxy/v1_15_R1/Cooldown.java
index 6cc7b9d0..1e34a70a 100644
--- a/NMS/v1_15_R1/src/main/java/com/willfp/ecoenchants/nms/v1_15_R1/Cooldown.java
+++ b/eco-core/core-nms/v1_15_R1/src/main/java/com/willfp/eco/core/proxy/v1_15_R1/Cooldown.java
@@ -1,11 +1,11 @@
-package com.willfp.ecoenchants.nms.v1_15_R1;
+package com.willfp.eco.core.proxy.v1_15_R1;
-import com.willfp.ecoenchants.nms.api.CooldownWrapper;
+import com.willfp.eco.core.proxy.proxies.CooldownProxy;
import net.minecraft.server.v1_15_R1.EntityHuman;
import org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer;
import org.bukkit.entity.Player;
-public class Cooldown implements CooldownWrapper {
+public class Cooldown implements CooldownProxy {
@Override
public double getAttackCooldown(Player player) {
EntityHuman entityHuman = ((CraftPlayer) player).getHandle();
diff --git a/NMS/v1_15_R1/src/main/java/com/willfp/ecoenchants/nms/v1_15_R1/FastGetEnchants.java b/eco-core/core-nms/v1_15_R1/src/main/java/com/willfp/eco/core/proxy/v1_15_R1/FastGetEnchants.java
similarity index 91%
rename from NMS/v1_15_R1/src/main/java/com/willfp/ecoenchants/nms/v1_15_R1/FastGetEnchants.java
rename to eco-core/core-nms/v1_15_R1/src/main/java/com/willfp/eco/core/proxy/v1_15_R1/FastGetEnchants.java
index 2f275e99..81985161 100644
--- a/NMS/v1_15_R1/src/main/java/com/willfp/ecoenchants/nms/v1_15_R1/FastGetEnchants.java
+++ b/eco-core/core-nms/v1_15_R1/src/main/java/com/willfp/eco/core/proxy/v1_15_R1/FastGetEnchants.java
@@ -1,6 +1,6 @@
-package com.willfp.ecoenchants.nms.v1_15_R1;
+package com.willfp.eco.core.proxy.v1_15_R1;
-import com.willfp.ecoenchants.nms.api.FastGetEnchantsWrapper;
+import com.willfp.eco.core.proxy.proxies.FastGetEnchantsProxy;
import net.minecraft.server.v1_15_R1.NBTBase;
import net.minecraft.server.v1_15_R1.NBTTagCompound;
import net.minecraft.server.v1_15_R1.NBTTagList;
@@ -12,7 +12,7 @@ import org.bukkit.inventory.ItemStack;
import java.util.HashMap;
import java.util.Map;
-public class FastGetEnchants implements FastGetEnchantsWrapper {
+public class FastGetEnchants implements FastGetEnchantsProxy {
@Override
public Map getEnchantmentsOnItem(ItemStack itemStack) {
net.minecraft.server.v1_15_R1.ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack);
diff --git a/NMS/v1_15_R1/src/main/java/com/willfp/ecoenchants/nms/v1_15_R1/OpenInventory.java b/eco-core/core-nms/v1_15_R1/src/main/java/com/willfp/eco/core/proxy/v1_15_R1/OpenInventory.java
similarity index 58%
rename from NMS/v1_15_R1/src/main/java/com/willfp/ecoenchants/nms/v1_15_R1/OpenInventory.java
rename to eco-core/core-nms/v1_15_R1/src/main/java/com/willfp/eco/core/proxy/v1_15_R1/OpenInventory.java
index 0fbc0188..2028c16a 100644
--- a/NMS/v1_15_R1/src/main/java/com/willfp/ecoenchants/nms/v1_15_R1/OpenInventory.java
+++ b/eco-core/core-nms/v1_15_R1/src/main/java/com/willfp/eco/core/proxy/v1_15_R1/OpenInventory.java
@@ -1,10 +1,10 @@
-package com.willfp.ecoenchants.nms.v1_15_R1;
+package com.willfp.eco.core.proxy.v1_15_R1;
-import com.willfp.ecoenchants.nms.api.OpenInventoryWrapper;
+import com.willfp.eco.core.proxy.proxies.OpenInventoryProxy;
import org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer;
import org.bukkit.entity.Player;
-public class OpenInventory implements OpenInventoryWrapper {
+public class OpenInventory implements OpenInventoryProxy {
@Override
public Object getOpenInventory(Player player) {
return ((CraftPlayer) player).getHandle().activeContainer;
diff --git a/NMS/v1_15_R1/src/main/java/com/willfp/ecoenchants/nms/v1_15_R1/RepairCost.java b/eco-core/core-nms/v1_15_R1/src/main/java/com/willfp/eco/core/proxy/v1_15_R1/RepairCost.java
similarity index 79%
rename from NMS/v1_15_R1/src/main/java/com/willfp/ecoenchants/nms/v1_15_R1/RepairCost.java
rename to eco-core/core-nms/v1_15_R1/src/main/java/com/willfp/eco/core/proxy/v1_15_R1/RepairCost.java
index 2f6b89d7..422e7aa8 100644
--- a/NMS/v1_15_R1/src/main/java/com/willfp/ecoenchants/nms/v1_15_R1/RepairCost.java
+++ b/eco-core/core-nms/v1_15_R1/src/main/java/com/willfp/eco/core/proxy/v1_15_R1/RepairCost.java
@@ -1,10 +1,10 @@
-package com.willfp.ecoenchants.nms.v1_15_R1;
+package com.willfp.eco.core.proxy.v1_15_R1;
-import com.willfp.ecoenchants.nms.api.RepairCostWrapper;
+import com.willfp.eco.core.proxy.proxies.RepairCostProxy;
import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftItemStack;
import org.bukkit.inventory.ItemStack;
-public class RepairCost implements RepairCostWrapper {
+public class RepairCost implements RepairCostProxy {
@Override
public ItemStack setRepairCost(ItemStack itemStack, int cost) {
net.minecraft.server.v1_15_R1.ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack);
diff --git a/NMS/v1_15_R1/src/main/java/com/willfp/ecoenchants/nms/v1_15_R1/TridentStack.java b/eco-core/core-nms/v1_15_R1/src/main/java/com/willfp/eco/core/proxy/v1_15_R1/TridentStack.java
similarity index 73%
rename from NMS/v1_15_R1/src/main/java/com/willfp/ecoenchants/nms/v1_15_R1/TridentStack.java
rename to eco-core/core-nms/v1_15_R1/src/main/java/com/willfp/eco/core/proxy/v1_15_R1/TridentStack.java
index 1a28aea8..84652e9b 100644
--- a/NMS/v1_15_R1/src/main/java/com/willfp/ecoenchants/nms/v1_15_R1/TridentStack.java
+++ b/eco-core/core-nms/v1_15_R1/src/main/java/com/willfp/eco/core/proxy/v1_15_R1/TridentStack.java
@@ -1,13 +1,13 @@
-package com.willfp.ecoenchants.nms.v1_15_R1;
+package com.willfp.eco.core.proxy.v1_15_R1;
-import com.willfp.ecoenchants.nms.api.TridentStackWrapper;
+import com.willfp.eco.core.proxy.proxies.TridentStackProxy;
import net.minecraft.server.v1_15_R1.EntityThrownTrident;
import org.bukkit.craftbukkit.v1_15_R1.entity.CraftTrident;
import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftItemStack;
import org.bukkit.entity.Trident;
import org.bukkit.inventory.ItemStack;
-public class TridentStack implements TridentStackWrapper {
+public class TridentStack implements TridentStackProxy {
@Override
public ItemStack getTridentStack(Trident trident) {
EntityThrownTrident t = ((CraftTrident) trident).getHandle();
diff --git a/eco-core/core-nms/v1_16_R1/build.gradle b/eco-core/core-nms/v1_16_R1/build.gradle
new file mode 100644
index 00000000..49623620
--- /dev/null
+++ b/eco-core/core-nms/v1_16_R1/build.gradle
@@ -0,0 +1,6 @@
+group 'com.willfp'
+version rootProject.version
+
+dependencies {
+ compileOnly 'org.spigotmc:spigot:1.16.1-R0.1-SNAPSHOT'
+}
\ No newline at end of file
diff --git a/NMS/v1_16_R1/src/main/java/com/willfp/ecoenchants/nms/v1_16_R1/BlockBreak.java b/eco-core/core-nms/v1_16_R1/src/main/java/com/willfp/eco/core/proxy/v1_16_R1/BlockBreak.java
similarity index 71%
rename from NMS/v1_16_R1/src/main/java/com/willfp/ecoenchants/nms/v1_16_R1/BlockBreak.java
rename to eco-core/core-nms/v1_16_R1/src/main/java/com/willfp/eco/core/proxy/v1_16_R1/BlockBreak.java
index 4ffc375a..9ea11b41 100644
--- a/NMS/v1_16_R1/src/main/java/com/willfp/ecoenchants/nms/v1_16_R1/BlockBreak.java
+++ b/eco-core/core-nms/v1_16_R1/src/main/java/com/willfp/eco/core/proxy/v1_16_R1/BlockBreak.java
@@ -1,12 +1,12 @@
-package com.willfp.ecoenchants.nms.v1_16_R1;
+package com.willfp.eco.core.proxy.v1_16_R1;
-import com.willfp.ecoenchants.nms.api.BlockBreakWrapper;
+import com.willfp.eco.core.proxy.proxies.BlockBreakProxy;
import net.minecraft.server.v1_16_R1.BlockPosition;
import org.bukkit.block.Block;
import org.bukkit.craftbukkit.v1_16_R1.entity.CraftPlayer;
import org.bukkit.entity.Player;
-public class BlockBreak implements BlockBreakWrapper {
+public class BlockBreak implements BlockBreakProxy {
@Override
public void breakBlock(Player player, Block block) {
((CraftPlayer) player).getHandle().playerInteractManager.breakBlock(new BlockPosition(block.getX(), block.getY(), block.getZ()));
diff --git a/NMS/v1_16_R1/src/main/java/com/willfp/ecoenchants/nms/v1_16_R1/ChatComponent.java b/eco-core/core-nms/v1_16_R1/src/main/java/com/willfp/eco/core/proxy/v1_16_R1/ChatComponent.java
similarity index 95%
rename from NMS/v1_16_R1/src/main/java/com/willfp/ecoenchants/nms/v1_16_R1/ChatComponent.java
rename to eco-core/core-nms/v1_16_R1/src/main/java/com/willfp/eco/core/proxy/v1_16_R1/ChatComponent.java
index 537c91f9..a88b5176 100644
--- a/NMS/v1_16_R1/src/main/java/com/willfp/ecoenchants/nms/v1_16_R1/ChatComponent.java
+++ b/eco-core/core-nms/v1_16_R1/src/main/java/com/willfp/eco/core/proxy/v1_16_R1/ChatComponent.java
@@ -1,10 +1,10 @@
-package com.willfp.ecoenchants.nms.v1_16_R1;
+package com.willfp.eco.core.proxy.v1_16_R1;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
-import com.willfp.ecoenchants.nms.api.ChatComponentWrapper;
+import com.willfp.eco.core.proxy.proxies.ChatComponentProxy;
import net.minecraft.server.v1_16_R1.ChatBaseComponent;
import net.minecraft.server.v1_16_R1.ChatHoverable;
import net.minecraft.server.v1_16_R1.ChatMessage;
@@ -18,7 +18,7 @@ import org.bukkit.inventory.ItemStack;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
-public class ChatComponent implements ChatComponentWrapper {
+public class ChatComponent implements ChatComponentProxy {
@Override
public Object modifyComponent(Object object) {
if (!(object instanceof IChatBaseComponent)) {
diff --git a/NMS/v1_16_R2/src/main/java/com/willfp/ecoenchants/nms/v1_16_R2/Cooldown.java b/eco-core/core-nms/v1_16_R1/src/main/java/com/willfp/eco/core/proxy/v1_16_R1/Cooldown.java
similarity index 50%
rename from NMS/v1_16_R2/src/main/java/com/willfp/ecoenchants/nms/v1_16_R2/Cooldown.java
rename to eco-core/core-nms/v1_16_R1/src/main/java/com/willfp/eco/core/proxy/v1_16_R1/Cooldown.java
index 42de97f1..c99ebe25 100644
--- a/NMS/v1_16_R2/src/main/java/com/willfp/ecoenchants/nms/v1_16_R2/Cooldown.java
+++ b/eco-core/core-nms/v1_16_R1/src/main/java/com/willfp/eco/core/proxy/v1_16_R1/Cooldown.java
@@ -1,9 +1,9 @@
-package com.willfp.ecoenchants.nms.v1_16_R2;
+package com.willfp.eco.core.proxy.v1_16_R1;
-import com.willfp.ecoenchants.nms.api.CooldownWrapper;
+import com.willfp.eco.core.proxy.proxies.CooldownProxy;
import org.bukkit.entity.Player;
-public class Cooldown implements CooldownWrapper {
+public class Cooldown implements CooldownProxy {
@Override
public double getAttackCooldown(Player player) {
return player.getAttackCooldown();
diff --git a/NMS/v1_16_R1/src/main/java/com/willfp/ecoenchants/nms/v1_16_R1/FastGetEnchants.java b/eco-core/core-nms/v1_16_R1/src/main/java/com/willfp/eco/core/proxy/v1_16_R1/FastGetEnchants.java
similarity index 91%
rename from NMS/v1_16_R1/src/main/java/com/willfp/ecoenchants/nms/v1_16_R1/FastGetEnchants.java
rename to eco-core/core-nms/v1_16_R1/src/main/java/com/willfp/eco/core/proxy/v1_16_R1/FastGetEnchants.java
index 6877a40d..b4ca7b6e 100644
--- a/NMS/v1_16_R1/src/main/java/com/willfp/ecoenchants/nms/v1_16_R1/FastGetEnchants.java
+++ b/eco-core/core-nms/v1_16_R1/src/main/java/com/willfp/eco/core/proxy/v1_16_R1/FastGetEnchants.java
@@ -1,6 +1,6 @@
-package com.willfp.ecoenchants.nms.v1_16_R1;
+package com.willfp.eco.core.proxy.v1_16_R1;
-import com.willfp.ecoenchants.nms.api.FastGetEnchantsWrapper;
+import com.willfp.eco.core.proxy.proxies.FastGetEnchantsProxy;
import net.minecraft.server.v1_16_R1.NBTBase;
import net.minecraft.server.v1_16_R1.NBTTagCompound;
import net.minecraft.server.v1_16_R1.NBTTagList;
@@ -12,7 +12,7 @@ import org.bukkit.inventory.ItemStack;
import java.util.HashMap;
import java.util.Map;
-public class FastGetEnchants implements FastGetEnchantsWrapper {
+public class FastGetEnchants implements FastGetEnchantsProxy {
@Override
public Map getEnchantmentsOnItem(ItemStack itemStack) {
net.minecraft.server.v1_16_R1.ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack);
diff --git a/NMS/v1_16_R1/src/main/java/com/willfp/ecoenchants/nms/v1_16_R1/OpenInventory.java b/eco-core/core-nms/v1_16_R1/src/main/java/com/willfp/eco/core/proxy/v1_16_R1/OpenInventory.java
similarity index 58%
rename from NMS/v1_16_R1/src/main/java/com/willfp/ecoenchants/nms/v1_16_R1/OpenInventory.java
rename to eco-core/core-nms/v1_16_R1/src/main/java/com/willfp/eco/core/proxy/v1_16_R1/OpenInventory.java
index 75a08d03..5fafbfc7 100644
--- a/NMS/v1_16_R1/src/main/java/com/willfp/ecoenchants/nms/v1_16_R1/OpenInventory.java
+++ b/eco-core/core-nms/v1_16_R1/src/main/java/com/willfp/eco/core/proxy/v1_16_R1/OpenInventory.java
@@ -1,10 +1,10 @@
-package com.willfp.ecoenchants.nms.v1_16_R1;
+package com.willfp.eco.core.proxy.v1_16_R1;
-import com.willfp.ecoenchants.nms.api.OpenInventoryWrapper;
+import com.willfp.eco.core.proxy.proxies.OpenInventoryProxy;
import org.bukkit.craftbukkit.v1_16_R1.entity.CraftPlayer;
import org.bukkit.entity.Player;
-public class OpenInventory implements OpenInventoryWrapper {
+public class OpenInventory implements OpenInventoryProxy {
@Override
public Object getOpenInventory(Player player) {
return ((CraftPlayer) player).getHandle().activeContainer;
diff --git a/NMS/v1_16_R1/src/main/java/com/willfp/ecoenchants/nms/v1_16_R1/RepairCost.java b/eco-core/core-nms/v1_16_R1/src/main/java/com/willfp/eco/core/proxy/v1_16_R1/RepairCost.java
similarity index 79%
rename from NMS/v1_16_R1/src/main/java/com/willfp/ecoenchants/nms/v1_16_R1/RepairCost.java
rename to eco-core/core-nms/v1_16_R1/src/main/java/com/willfp/eco/core/proxy/v1_16_R1/RepairCost.java
index 01e02d9c..a0503efc 100644
--- a/NMS/v1_16_R1/src/main/java/com/willfp/ecoenchants/nms/v1_16_R1/RepairCost.java
+++ b/eco-core/core-nms/v1_16_R1/src/main/java/com/willfp/eco/core/proxy/v1_16_R1/RepairCost.java
@@ -1,10 +1,10 @@
-package com.willfp.ecoenchants.nms.v1_16_R1;
+package com.willfp.eco.core.proxy.v1_16_R1;
-import com.willfp.ecoenchants.nms.api.RepairCostWrapper;
+import com.willfp.eco.core.proxy.proxies.RepairCostProxy;
import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftItemStack;
import org.bukkit.inventory.ItemStack;
-public class RepairCost implements RepairCostWrapper {
+public class RepairCost implements RepairCostProxy {
@Override
public ItemStack setRepairCost(ItemStack itemStack, int cost) {
net.minecraft.server.v1_16_R1.ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack);
diff --git a/NMS/v1_16_R1/src/main/java/com/willfp/ecoenchants/nms/v1_16_R1/TridentStack.java b/eco-core/core-nms/v1_16_R1/src/main/java/com/willfp/eco/core/proxy/v1_16_R1/TridentStack.java
similarity index 73%
rename from NMS/v1_16_R1/src/main/java/com/willfp/ecoenchants/nms/v1_16_R1/TridentStack.java
rename to eco-core/core-nms/v1_16_R1/src/main/java/com/willfp/eco/core/proxy/v1_16_R1/TridentStack.java
index e7fb04b0..13a5e3da 100644
--- a/NMS/v1_16_R1/src/main/java/com/willfp/ecoenchants/nms/v1_16_R1/TridentStack.java
+++ b/eco-core/core-nms/v1_16_R1/src/main/java/com/willfp/eco/core/proxy/v1_16_R1/TridentStack.java
@@ -1,13 +1,13 @@
-package com.willfp.ecoenchants.nms.v1_16_R1;
+package com.willfp.eco.core.proxy.v1_16_R1;
-import com.willfp.ecoenchants.nms.api.TridentStackWrapper;
+import com.willfp.eco.core.proxy.proxies.TridentStackProxy;
import net.minecraft.server.v1_16_R1.EntityThrownTrident;
import org.bukkit.craftbukkit.v1_16_R1.entity.CraftTrident;
import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftItemStack;
import org.bukkit.entity.Trident;
import org.bukkit.inventory.ItemStack;
-public class TridentStack implements TridentStackWrapper {
+public class TridentStack implements TridentStackProxy {
@Override
public ItemStack getTridentStack(Trident trident) {
EntityThrownTrident t = ((CraftTrident) trident).getHandle();
diff --git a/eco-core/core-nms/v1_16_R2/build.gradle b/eco-core/core-nms/v1_16_R2/build.gradle
new file mode 100644
index 00000000..3f4d50cf
--- /dev/null
+++ b/eco-core/core-nms/v1_16_R2/build.gradle
@@ -0,0 +1,6 @@
+group 'com.willfp'
+version rootProject.version
+
+dependencies {
+ compileOnly 'org.spigotmc:spigot:1.16.3-R0.1-SNAPSHOT'
+}
\ No newline at end of file
diff --git a/NMS/v1_16_R2/src/main/java/com/willfp/ecoenchants/nms/v1_16_R2/BlockBreak.java b/eco-core/core-nms/v1_16_R2/src/main/java/com/willfp/eco/core/proxy/v1_16_R2/BlockBreak.java
similarity index 71%
rename from NMS/v1_16_R2/src/main/java/com/willfp/ecoenchants/nms/v1_16_R2/BlockBreak.java
rename to eco-core/core-nms/v1_16_R2/src/main/java/com/willfp/eco/core/proxy/v1_16_R2/BlockBreak.java
index cf4893ff..0688d6fe 100644
--- a/NMS/v1_16_R2/src/main/java/com/willfp/ecoenchants/nms/v1_16_R2/BlockBreak.java
+++ b/eco-core/core-nms/v1_16_R2/src/main/java/com/willfp/eco/core/proxy/v1_16_R2/BlockBreak.java
@@ -1,12 +1,12 @@
-package com.willfp.ecoenchants.nms.v1_16_R2;
+package com.willfp.eco.core.proxy.v1_16_R2;
-import com.willfp.ecoenchants.nms.api.BlockBreakWrapper;
+import com.willfp.eco.core.proxy.proxies.BlockBreakProxy;
import net.minecraft.server.v1_16_R2.BlockPosition;
import org.bukkit.block.Block;
import org.bukkit.craftbukkit.v1_16_R2.entity.CraftPlayer;
import org.bukkit.entity.Player;
-public class BlockBreak implements BlockBreakWrapper {
+public class BlockBreak implements BlockBreakProxy {
@Override
public void breakBlock(Player player, Block block) {
((CraftPlayer) player).getHandle().playerInteractManager.breakBlock(new BlockPosition(block.getX(), block.getY(), block.getZ()));
diff --git a/NMS/v1_16_R2/src/main/java/com/willfp/ecoenchants/nms/v1_16_R2/ChatComponent.java b/eco-core/core-nms/v1_16_R2/src/main/java/com/willfp/eco/core/proxy/v1_16_R2/ChatComponent.java
similarity index 95%
rename from NMS/v1_16_R2/src/main/java/com/willfp/ecoenchants/nms/v1_16_R2/ChatComponent.java
rename to eco-core/core-nms/v1_16_R2/src/main/java/com/willfp/eco/core/proxy/v1_16_R2/ChatComponent.java
index 0baab3bd..8fb6ba5c 100644
--- a/NMS/v1_16_R2/src/main/java/com/willfp/ecoenchants/nms/v1_16_R2/ChatComponent.java
+++ b/eco-core/core-nms/v1_16_R2/src/main/java/com/willfp/eco/core/proxy/v1_16_R2/ChatComponent.java
@@ -1,10 +1,10 @@
-package com.willfp.ecoenchants.nms.v1_16_R2;
+package com.willfp.eco.core.proxy.v1_16_R2;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
-import com.willfp.ecoenchants.nms.api.ChatComponentWrapper;
+import com.willfp.eco.core.proxy.proxies.ChatComponentProxy;
import net.minecraft.server.v1_16_R2.ChatBaseComponent;
import net.minecraft.server.v1_16_R2.ChatHoverable;
import net.minecraft.server.v1_16_R2.ChatMessage;
@@ -18,7 +18,7 @@ import org.bukkit.inventory.ItemStack;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
-public class ChatComponent implements ChatComponentWrapper {
+public class ChatComponent implements ChatComponentProxy {
@Override
public Object modifyComponent(Object object) {
if (!(object instanceof IChatBaseComponent)) {
diff --git a/NMS/v1_16_R1/src/main/java/com/willfp/ecoenchants/nms/v1_16_R1/Cooldown.java b/eco-core/core-nms/v1_16_R2/src/main/java/com/willfp/eco/core/proxy/v1_16_R2/Cooldown.java
similarity index 50%
rename from NMS/v1_16_R1/src/main/java/com/willfp/ecoenchants/nms/v1_16_R1/Cooldown.java
rename to eco-core/core-nms/v1_16_R2/src/main/java/com/willfp/eco/core/proxy/v1_16_R2/Cooldown.java
index 03cb1530..33317269 100644
--- a/NMS/v1_16_R1/src/main/java/com/willfp/ecoenchants/nms/v1_16_R1/Cooldown.java
+++ b/eco-core/core-nms/v1_16_R2/src/main/java/com/willfp/eco/core/proxy/v1_16_R2/Cooldown.java
@@ -1,9 +1,9 @@
-package com.willfp.ecoenchants.nms.v1_16_R1;
+package com.willfp.eco.core.proxy.v1_16_R2;
-import com.willfp.ecoenchants.nms.api.CooldownWrapper;
+import com.willfp.eco.core.proxy.proxies.CooldownProxy;
import org.bukkit.entity.Player;
-public class Cooldown implements CooldownWrapper {
+public class Cooldown implements CooldownProxy {
@Override
public double getAttackCooldown(Player player) {
return player.getAttackCooldown();
diff --git a/NMS/v1_16_R2/src/main/java/com/willfp/ecoenchants/nms/v1_16_R2/FastGetEnchants.java b/eco-core/core-nms/v1_16_R2/src/main/java/com/willfp/eco/core/proxy/v1_16_R2/FastGetEnchants.java
similarity index 91%
rename from NMS/v1_16_R2/src/main/java/com/willfp/ecoenchants/nms/v1_16_R2/FastGetEnchants.java
rename to eco-core/core-nms/v1_16_R2/src/main/java/com/willfp/eco/core/proxy/v1_16_R2/FastGetEnchants.java
index ed725a6d..6de0819f 100644
--- a/NMS/v1_16_R2/src/main/java/com/willfp/ecoenchants/nms/v1_16_R2/FastGetEnchants.java
+++ b/eco-core/core-nms/v1_16_R2/src/main/java/com/willfp/eco/core/proxy/v1_16_R2/FastGetEnchants.java
@@ -1,6 +1,6 @@
-package com.willfp.ecoenchants.nms.v1_16_R2;
+package com.willfp.eco.core.proxy.v1_16_R2;
-import com.willfp.ecoenchants.nms.api.FastGetEnchantsWrapper;
+import com.willfp.eco.core.proxy.proxies.FastGetEnchantsProxy;
import net.minecraft.server.v1_16_R2.NBTBase;
import net.minecraft.server.v1_16_R2.NBTTagCompound;
import net.minecraft.server.v1_16_R2.NBTTagList;
@@ -12,7 +12,7 @@ import org.bukkit.inventory.ItemStack;
import java.util.HashMap;
import java.util.Map;
-public class FastGetEnchants implements FastGetEnchantsWrapper {
+public class FastGetEnchants implements FastGetEnchantsProxy {
@Override
public Map getEnchantmentsOnItem(ItemStack itemStack) {
net.minecraft.server.v1_16_R2.ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack);
diff --git a/NMS/v1_16_R2/src/main/java/com/willfp/ecoenchants/nms/v1_16_R2/OpenInventory.java b/eco-core/core-nms/v1_16_R2/src/main/java/com/willfp/eco/core/proxy/v1_16_R2/OpenInventory.java
similarity index 58%
rename from NMS/v1_16_R2/src/main/java/com/willfp/ecoenchants/nms/v1_16_R2/OpenInventory.java
rename to eco-core/core-nms/v1_16_R2/src/main/java/com/willfp/eco/core/proxy/v1_16_R2/OpenInventory.java
index e3877256..bae62130 100644
--- a/NMS/v1_16_R2/src/main/java/com/willfp/ecoenchants/nms/v1_16_R2/OpenInventory.java
+++ b/eco-core/core-nms/v1_16_R2/src/main/java/com/willfp/eco/core/proxy/v1_16_R2/OpenInventory.java
@@ -1,10 +1,10 @@
-package com.willfp.ecoenchants.nms.v1_16_R2;
+package com.willfp.eco.core.proxy.v1_16_R2;
-import com.willfp.ecoenchants.nms.api.OpenInventoryWrapper;
+import com.willfp.eco.core.proxy.proxies.OpenInventoryProxy;
import org.bukkit.craftbukkit.v1_16_R2.entity.CraftPlayer;
import org.bukkit.entity.Player;
-public class OpenInventory implements OpenInventoryWrapper {
+public class OpenInventory implements OpenInventoryProxy {
@Override
public Object getOpenInventory(Player player) {
return ((CraftPlayer) player).getHandle().activeContainer;
diff --git a/NMS/v1_16_R2/src/main/java/com/willfp/ecoenchants/nms/v1_16_R2/RepairCost.java b/eco-core/core-nms/v1_16_R2/src/main/java/com/willfp/eco/core/proxy/v1_16_R2/RepairCost.java
similarity index 79%
rename from NMS/v1_16_R2/src/main/java/com/willfp/ecoenchants/nms/v1_16_R2/RepairCost.java
rename to eco-core/core-nms/v1_16_R2/src/main/java/com/willfp/eco/core/proxy/v1_16_R2/RepairCost.java
index 051489d2..4a1ae3be 100644
--- a/NMS/v1_16_R2/src/main/java/com/willfp/ecoenchants/nms/v1_16_R2/RepairCost.java
+++ b/eco-core/core-nms/v1_16_R2/src/main/java/com/willfp/eco/core/proxy/v1_16_R2/RepairCost.java
@@ -1,10 +1,10 @@
-package com.willfp.ecoenchants.nms.v1_16_R2;
+package com.willfp.eco.core.proxy.v1_16_R2;
-import com.willfp.ecoenchants.nms.api.RepairCostWrapper;
+import com.willfp.eco.core.proxy.proxies.RepairCostProxy;
import org.bukkit.craftbukkit.v1_16_R2.inventory.CraftItemStack;
import org.bukkit.inventory.ItemStack;
-public class RepairCost implements RepairCostWrapper {
+public class RepairCost implements RepairCostProxy {
@Override
public ItemStack setRepairCost(ItemStack itemStack, int cost) {
net.minecraft.server.v1_16_R2.ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack);
diff --git a/NMS/v1_16_R2/src/main/java/com/willfp/ecoenchants/nms/v1_16_R2/TridentStack.java b/eco-core/core-nms/v1_16_R2/src/main/java/com/willfp/eco/core/proxy/v1_16_R2/TridentStack.java
similarity index 73%
rename from NMS/v1_16_R2/src/main/java/com/willfp/ecoenchants/nms/v1_16_R2/TridentStack.java
rename to eco-core/core-nms/v1_16_R2/src/main/java/com/willfp/eco/core/proxy/v1_16_R2/TridentStack.java
index e9f65bdf..dbe60d01 100644
--- a/NMS/v1_16_R2/src/main/java/com/willfp/ecoenchants/nms/v1_16_R2/TridentStack.java
+++ b/eco-core/core-nms/v1_16_R2/src/main/java/com/willfp/eco/core/proxy/v1_16_R2/TridentStack.java
@@ -1,13 +1,13 @@
-package com.willfp.ecoenchants.nms.v1_16_R2;
+package com.willfp.eco.core.proxy.v1_16_R2;
-import com.willfp.ecoenchants.nms.api.TridentStackWrapper;
+import com.willfp.eco.core.proxy.proxies.TridentStackProxy;
import net.minecraft.server.v1_16_R2.EntityThrownTrident;
import org.bukkit.craftbukkit.v1_16_R2.entity.CraftTrident;
import org.bukkit.craftbukkit.v1_16_R2.inventory.CraftItemStack;
import org.bukkit.entity.Trident;
import org.bukkit.inventory.ItemStack;
-public class TridentStack implements TridentStackWrapper {
+public class TridentStack implements TridentStackProxy {
@Override
public ItemStack getTridentStack(Trident trident) {
EntityThrownTrident t = ((CraftTrident) trident).getHandle();
diff --git a/eco-core/core-nms/v1_16_R3/build.gradle b/eco-core/core-nms/v1_16_R3/build.gradle
new file mode 100644
index 00000000..5930f17d
--- /dev/null
+++ b/eco-core/core-nms/v1_16_R3/build.gradle
@@ -0,0 +1,6 @@
+group 'com.willfp'
+version rootProject.version
+
+dependencies {
+ compileOnly 'org.spigotmc:spigot:1.16.4-R0.1-SNAPSHOT'
+}
\ No newline at end of file
diff --git a/NMS/v1_16_R3/src/main/java/com/willfp/ecoenchants/nms/v1_16_R3/BlockBreak.java b/eco-core/core-nms/v1_16_R3/src/main/java/com/willfp/eco/core/proxy/v1_16_R3/BlockBreak.java
similarity index 71%
rename from NMS/v1_16_R3/src/main/java/com/willfp/ecoenchants/nms/v1_16_R3/BlockBreak.java
rename to eco-core/core-nms/v1_16_R3/src/main/java/com/willfp/eco/core/proxy/v1_16_R3/BlockBreak.java
index 565b3089..d723119c 100644
--- a/NMS/v1_16_R3/src/main/java/com/willfp/ecoenchants/nms/v1_16_R3/BlockBreak.java
+++ b/eco-core/core-nms/v1_16_R3/src/main/java/com/willfp/eco/core/proxy/v1_16_R3/BlockBreak.java
@@ -1,12 +1,12 @@
-package com.willfp.ecoenchants.nms.v1_16_R3;
+package com.willfp.eco.core.proxy.v1_16_R3;
-import com.willfp.ecoenchants.nms.api.BlockBreakWrapper;
+import com.willfp.eco.core.proxy.proxies.BlockBreakProxy;
import net.minecraft.server.v1_16_R3.BlockPosition;
import org.bukkit.block.Block;
import org.bukkit.craftbukkit.v1_16_R3.entity.CraftPlayer;
import org.bukkit.entity.Player;
-public class BlockBreak implements BlockBreakWrapper {
+public class BlockBreak implements BlockBreakProxy {
@Override
public void breakBlock(Player player, Block block) {
((CraftPlayer) player).getHandle().playerInteractManager.breakBlock(new BlockPosition(block.getX(), block.getY(), block.getZ()));
diff --git a/NMS/v1_16_R3/src/main/java/com/willfp/ecoenchants/nms/v1_16_R3/ChatComponent.java b/eco-core/core-nms/v1_16_R3/src/main/java/com/willfp/eco/core/proxy/v1_16_R3/ChatComponent.java
similarity index 95%
rename from NMS/v1_16_R3/src/main/java/com/willfp/ecoenchants/nms/v1_16_R3/ChatComponent.java
rename to eco-core/core-nms/v1_16_R3/src/main/java/com/willfp/eco/core/proxy/v1_16_R3/ChatComponent.java
index a5dd45e3..f239d91e 100644
--- a/NMS/v1_16_R3/src/main/java/com/willfp/ecoenchants/nms/v1_16_R3/ChatComponent.java
+++ b/eco-core/core-nms/v1_16_R3/src/main/java/com/willfp/eco/core/proxy/v1_16_R3/ChatComponent.java
@@ -1,10 +1,10 @@
-package com.willfp.ecoenchants.nms.v1_16_R3;
+package com.willfp.eco.core.proxy.v1_16_R3;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
-import com.willfp.ecoenchants.nms.api.ChatComponentWrapper;
+import com.willfp.eco.core.proxy.proxies.ChatComponentProxy;
import net.minecraft.server.v1_16_R3.ChatBaseComponent;
import net.minecraft.server.v1_16_R3.ChatHoverable;
import net.minecraft.server.v1_16_R3.ChatMessage;
@@ -18,7 +18,7 @@ import org.bukkit.inventory.ItemStack;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
-public class ChatComponent implements ChatComponentWrapper {
+public class ChatComponent implements ChatComponentProxy {
@Override
public Object modifyComponent(Object object) {
if (!(object instanceof IChatBaseComponent)) {
diff --git a/NMS/v1_16_R3/src/main/java/com/willfp/ecoenchants/nms/v1_16_R3/Cooldown.java b/eco-core/core-nms/v1_16_R3/src/main/java/com/willfp/eco/core/proxy/v1_16_R3/Cooldown.java
similarity index 50%
rename from NMS/v1_16_R3/src/main/java/com/willfp/ecoenchants/nms/v1_16_R3/Cooldown.java
rename to eco-core/core-nms/v1_16_R3/src/main/java/com/willfp/eco/core/proxy/v1_16_R3/Cooldown.java
index 429c7cda..85486ddb 100644
--- a/NMS/v1_16_R3/src/main/java/com/willfp/ecoenchants/nms/v1_16_R3/Cooldown.java
+++ b/eco-core/core-nms/v1_16_R3/src/main/java/com/willfp/eco/core/proxy/v1_16_R3/Cooldown.java
@@ -1,9 +1,9 @@
-package com.willfp.ecoenchants.nms.v1_16_R3;
+package com.willfp.eco.core.proxy.v1_16_R3;
-import com.willfp.ecoenchants.nms.api.CooldownWrapper;
+import com.willfp.eco.core.proxy.proxies.CooldownProxy;
import org.bukkit.entity.Player;
-public class Cooldown implements CooldownWrapper {
+public class Cooldown implements CooldownProxy {
@Override
public double getAttackCooldown(Player player) {
return player.getAttackCooldown();
diff --git a/NMS/v1_16_R3/src/main/java/com/willfp/ecoenchants/nms/v1_16_R3/FastGetEnchants.java b/eco-core/core-nms/v1_16_R3/src/main/java/com/willfp/eco/core/proxy/v1_16_R3/FastGetEnchants.java
similarity index 91%
rename from NMS/v1_16_R3/src/main/java/com/willfp/ecoenchants/nms/v1_16_R3/FastGetEnchants.java
rename to eco-core/core-nms/v1_16_R3/src/main/java/com/willfp/eco/core/proxy/v1_16_R3/FastGetEnchants.java
index 74f5e374..7cee9430 100644
--- a/NMS/v1_16_R3/src/main/java/com/willfp/ecoenchants/nms/v1_16_R3/FastGetEnchants.java
+++ b/eco-core/core-nms/v1_16_R3/src/main/java/com/willfp/eco/core/proxy/v1_16_R3/FastGetEnchants.java
@@ -1,6 +1,6 @@
-package com.willfp.ecoenchants.nms.v1_16_R3;
+package com.willfp.eco.core.proxy.v1_16_R3;
-import com.willfp.ecoenchants.nms.api.FastGetEnchantsWrapper;
+import com.willfp.eco.core.proxy.proxies.FastGetEnchantsProxy;
import net.minecraft.server.v1_16_R3.NBTBase;
import net.minecraft.server.v1_16_R3.NBTTagCompound;
import net.minecraft.server.v1_16_R3.NBTTagList;
@@ -12,7 +12,7 @@ import org.bukkit.inventory.ItemStack;
import java.util.HashMap;
import java.util.Map;
-public class FastGetEnchants implements FastGetEnchantsWrapper {
+public class FastGetEnchants implements FastGetEnchantsProxy {
@Override
public Map getEnchantmentsOnItem(ItemStack itemStack) {
net.minecraft.server.v1_16_R3.ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack);
diff --git a/NMS/v1_16_R3/src/main/java/com/willfp/ecoenchants/nms/v1_16_R3/OpenInventory.java b/eco-core/core-nms/v1_16_R3/src/main/java/com/willfp/eco/core/proxy/v1_16_R3/OpenInventory.java
similarity index 58%
rename from NMS/v1_16_R3/src/main/java/com/willfp/ecoenchants/nms/v1_16_R3/OpenInventory.java
rename to eco-core/core-nms/v1_16_R3/src/main/java/com/willfp/eco/core/proxy/v1_16_R3/OpenInventory.java
index 1caa92c3..753628cf 100644
--- a/NMS/v1_16_R3/src/main/java/com/willfp/ecoenchants/nms/v1_16_R3/OpenInventory.java
+++ b/eco-core/core-nms/v1_16_R3/src/main/java/com/willfp/eco/core/proxy/v1_16_R3/OpenInventory.java
@@ -1,10 +1,10 @@
-package com.willfp.ecoenchants.nms.v1_16_R3;
+package com.willfp.eco.core.proxy.v1_16_R3;
-import com.willfp.ecoenchants.nms.api.OpenInventoryWrapper;
+import com.willfp.eco.core.proxy.proxies.OpenInventoryProxy;
import org.bukkit.craftbukkit.v1_16_R3.entity.CraftPlayer;
import org.bukkit.entity.Player;
-public class OpenInventory implements OpenInventoryWrapper {
+public class OpenInventory implements OpenInventoryProxy {
@Override
public Object getOpenInventory(Player player) {
return ((CraftPlayer) player).getHandle().activeContainer;
diff --git a/NMS/v1_16_R3/src/main/java/com/willfp/ecoenchants/nms/v1_16_R3/RepairCost.java b/eco-core/core-nms/v1_16_R3/src/main/java/com/willfp/eco/core/proxy/v1_16_R3/RepairCost.java
similarity index 79%
rename from NMS/v1_16_R3/src/main/java/com/willfp/ecoenchants/nms/v1_16_R3/RepairCost.java
rename to eco-core/core-nms/v1_16_R3/src/main/java/com/willfp/eco/core/proxy/v1_16_R3/RepairCost.java
index 3696dc53..772c91d5 100644
--- a/NMS/v1_16_R3/src/main/java/com/willfp/ecoenchants/nms/v1_16_R3/RepairCost.java
+++ b/eco-core/core-nms/v1_16_R3/src/main/java/com/willfp/eco/core/proxy/v1_16_R3/RepairCost.java
@@ -1,10 +1,10 @@
-package com.willfp.ecoenchants.nms.v1_16_R3;
+package com.willfp.eco.core.proxy.v1_16_R3;
-import com.willfp.ecoenchants.nms.api.RepairCostWrapper;
+import com.willfp.eco.core.proxy.proxies.RepairCostProxy;
import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack;
import org.bukkit.inventory.ItemStack;
-public class RepairCost implements RepairCostWrapper {
+public class RepairCost implements RepairCostProxy {
@Override
public ItemStack setRepairCost(ItemStack itemStack, int cost) {
net.minecraft.server.v1_16_R3.ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack);
diff --git a/NMS/v1_16_R3/src/main/java/com/willfp/ecoenchants/nms/v1_16_R3/TridentStack.java b/eco-core/core-nms/v1_16_R3/src/main/java/com/willfp/eco/core/proxy/v1_16_R3/TridentStack.java
similarity index 73%
rename from NMS/v1_16_R3/src/main/java/com/willfp/ecoenchants/nms/v1_16_R3/TridentStack.java
rename to eco-core/core-nms/v1_16_R3/src/main/java/com/willfp/eco/core/proxy/v1_16_R3/TridentStack.java
index 8cc79ac4..731a90e6 100644
--- a/NMS/v1_16_R3/src/main/java/com/willfp/ecoenchants/nms/v1_16_R3/TridentStack.java
+++ b/eco-core/core-nms/v1_16_R3/src/main/java/com/willfp/eco/core/proxy/v1_16_R3/TridentStack.java
@@ -1,13 +1,13 @@
-package com.willfp.ecoenchants.nms.v1_16_R3;
+package com.willfp.eco.core.proxy.v1_16_R3;
-import com.willfp.ecoenchants.nms.api.TridentStackWrapper;
+import com.willfp.eco.core.proxy.proxies.TridentStackProxy;
import net.minecraft.server.v1_16_R3.EntityThrownTrident;
import org.bukkit.craftbukkit.v1_16_R3.entity.CraftTrident;
import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack;
import org.bukkit.entity.Trident;
import org.bukkit.inventory.ItemStack;
-public class TridentStack implements TridentStackWrapper {
+public class TridentStack implements TridentStackProxy {
@Override
public ItemStack getTridentStack(Trident trident) {
EntityThrownTrident t = ((CraftTrident) trident).getHandle();
diff --git a/eco-core/core-plugin/build.gradle b/eco-core/core-plugin/build.gradle
new file mode 100644
index 00000000..4104d2cf
--- /dev/null
+++ b/eco-core/core-plugin/build.gradle
@@ -0,0 +1,46 @@
+group 'com.willfp'
+version rootProject.version
+
+
+repositories {
+ maven { url 'https://repo.codemc.org/repository/maven-public' }
+ maven { url "https://oss.sonatype.org/content/repositories/snapshots" }
+ maven { url 'https://oss.sonatype.org/content/groups/public/' }
+ maven { url 'https://maven.enginehub.org/repo/' }
+ maven { url 'https://ci.ender.zone/plugin/repository/project/' }
+ maven { url 'https://ci.ender.zone/plugin/repository/everything/' }
+ maven { url 'https://repo.md-5.net/content/repositories/snapshots/' }
+ maven { url 'https://repo.dmulloy2.net/nexus/repository/public/' }
+ maven { url 'https://papermc.io/repo/repository/maven-public/' }
+ maven { url 'https://repo.maven.apache.org/maven2/' }
+ maven { url 'https://repo.dustplanet.de/artifactory/ext-release-local/' }
+ maven { url 'https://maven.seyfahni.de/repository/snapshots/' }
+ maven { url 'https://libraries.minecraft.net/' }
+ maven { url 'https://repo.spongepowered.org/maven/' }
+ maven { url 'https://org.kitteh.pastegg' }
+ maven { url 'https://repo.mikeprimm.com/' }
+ maven { url 'https://maven.sk89q.com/repo/' }
+ maven { url 'https://github.com/factions-site/repo/raw/public/' }
+ maven { url 'https://repo.extendedclip.com/content/repositories/placeholderapi/' }
+}
+
+dependencies {
+ implementation 'org.bstats:bstats-bukkit:1.7'
+ compileOnly 'org.spigotmc:spigot-api:1.16.4-R0.1-SNAPSHOT'
+ compileOnly 'commons-io:commons-io:2.8.0'
+ compileOnly 'com.sk89q.worldguard:worldguard-bukkit:7.0.4-SNAPSHOT'
+ compileOnly 'com.github.TechFortress:GriefPrevention:16.14.0'
+ compileOnly 'com.massivecraft:Factions:1.6.9.5-U0.5.10'
+ compileOnly 'com.github.cryptomorin:kingdoms:1.10.3.1'
+ compileOnly 'com.github.TownyAdvanced:Towny:0.96.2.0'
+ compileOnly 'com.github.angeschossen:LandsAPI:4.7.3'
+ compileOnly 'fr.neatmonster:nocheatplus:3.16.1-SNAPSHOT'
+ compileOnly 'com.github.jiangdashao:matrix-api-repo:317d4635fd'
+ compileOnly 'com.comphenix.protocol:ProtocolLib:4.6.0-SNAPSHOT'
+ compileOnly 'net.ess3:EssentialsX:2.18.1'
+ compileOnly 'com.destroystokyo.paper:paper-api:1.16.3-R0.1-SNAPSHOT'
+ compileOnly 'com.gmail.nossr50.mcMMO:mcMMO:2.1.157'
+ compileOnly 'me.clip:placeholderapi:2.10.9'
+ shadow files('../lib/SpartanAPI.jar')
+ shadow files('../lib/aac-api-5.0.0.jar')
+}
\ No newline at end of file
diff --git a/Plugin/src/main/resources/config.yml b/eco-core/core-plugin/src/main/resources/config.yml
similarity index 100%
rename from Plugin/src/main/resources/config.yml
rename to eco-core/core-plugin/src/main/resources/config.yml
diff --git a/Plugin/src/main/resources/enchants/artifact/ashartifact.yml b/eco-core/core-plugin/src/main/resources/enchants/artifact/ashartifact.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/artifact/ashartifact.yml
rename to eco-core/core-plugin/src/main/resources/enchants/artifact/ashartifact.yml
diff --git a/Plugin/src/main/resources/enchants/artifact/cloudsartifact.yml b/eco-core/core-plugin/src/main/resources/enchants/artifact/cloudsartifact.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/artifact/cloudsartifact.yml
rename to eco-core/core-plugin/src/main/resources/enchants/artifact/cloudsartifact.yml
diff --git a/Plugin/src/main/resources/enchants/artifact/crimsonartifact.yml b/eco-core/core-plugin/src/main/resources/enchants/artifact/crimsonartifact.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/artifact/crimsonartifact.yml
rename to eco-core/core-plugin/src/main/resources/enchants/artifact/crimsonartifact.yml
diff --git a/Plugin/src/main/resources/enchants/artifact/damageartifact.yml b/eco-core/core-plugin/src/main/resources/enchants/artifact/damageartifact.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/artifact/damageartifact.yml
rename to eco-core/core-plugin/src/main/resources/enchants/artifact/damageartifact.yml
diff --git a/Plugin/src/main/resources/enchants/artifact/dragonartifact.yml b/eco-core/core-plugin/src/main/resources/enchants/artifact/dragonartifact.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/artifact/dragonartifact.yml
rename to eco-core/core-plugin/src/main/resources/enchants/artifact/dragonartifact.yml
diff --git a/Plugin/src/main/resources/enchants/artifact/dustartifact.yml b/eco-core/core-plugin/src/main/resources/enchants/artifact/dustartifact.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/artifact/dustartifact.yml
rename to eco-core/core-plugin/src/main/resources/enchants/artifact/dustartifact.yml
diff --git a/Plugin/src/main/resources/enchants/artifact/emeraldartifact.yml b/eco-core/core-plugin/src/main/resources/enchants/artifact/emeraldartifact.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/artifact/emeraldartifact.yml
rename to eco-core/core-plugin/src/main/resources/enchants/artifact/emeraldartifact.yml
diff --git a/Plugin/src/main/resources/enchants/artifact/enchantmentartifact.yml b/eco-core/core-plugin/src/main/resources/enchants/artifact/enchantmentartifact.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/artifact/enchantmentartifact.yml
rename to eco-core/core-plugin/src/main/resources/enchants/artifact/enchantmentartifact.yml
diff --git a/Plugin/src/main/resources/enchants/artifact/endartifact.yml b/eco-core/core-plugin/src/main/resources/enchants/artifact/endartifact.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/artifact/endartifact.yml
rename to eco-core/core-plugin/src/main/resources/enchants/artifact/endartifact.yml
diff --git a/Plugin/src/main/resources/enchants/artifact/fireartifact.yml b/eco-core/core-plugin/src/main/resources/enchants/artifact/fireartifact.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/artifact/fireartifact.yml
rename to eco-core/core-plugin/src/main/resources/enchants/artifact/fireartifact.yml
diff --git a/Plugin/src/main/resources/enchants/artifact/heartartifact.yml b/eco-core/core-plugin/src/main/resources/enchants/artifact/heartartifact.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/artifact/heartartifact.yml
rename to eco-core/core-plugin/src/main/resources/enchants/artifact/heartartifact.yml
diff --git a/Plugin/src/main/resources/enchants/artifact/honeyartifact.yml b/eco-core/core-plugin/src/main/resources/enchants/artifact/honeyartifact.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/artifact/honeyartifact.yml
rename to eco-core/core-plugin/src/main/resources/enchants/artifact/honeyartifact.yml
diff --git a/Plugin/src/main/resources/enchants/artifact/inkartifact.yml b/eco-core/core-plugin/src/main/resources/enchants/artifact/inkartifact.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/artifact/inkartifact.yml
rename to eco-core/core-plugin/src/main/resources/enchants/artifact/inkartifact.yml
diff --git a/Plugin/src/main/resources/enchants/artifact/lavaartifact.yml b/eco-core/core-plugin/src/main/resources/enchants/artifact/lavaartifact.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/artifact/lavaartifact.yml
rename to eco-core/core-plugin/src/main/resources/enchants/artifact/lavaartifact.yml
diff --git a/Plugin/src/main/resources/enchants/artifact/limeartifact.yml b/eco-core/core-plugin/src/main/resources/enchants/artifact/limeartifact.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/artifact/limeartifact.yml
rename to eco-core/core-plugin/src/main/resources/enchants/artifact/limeartifact.yml
diff --git a/Plugin/src/main/resources/enchants/artifact/magicartifact.yml b/eco-core/core-plugin/src/main/resources/enchants/artifact/magicartifact.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/artifact/magicartifact.yml
rename to eco-core/core-plugin/src/main/resources/enchants/artifact/magicartifact.yml
diff --git a/Plugin/src/main/resources/enchants/artifact/magmaartifact.yml b/eco-core/core-plugin/src/main/resources/enchants/artifact/magmaartifact.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/artifact/magmaartifact.yml
rename to eco-core/core-plugin/src/main/resources/enchants/artifact/magmaartifact.yml
diff --git a/Plugin/src/main/resources/enchants/artifact/musicartifact.yml b/eco-core/core-plugin/src/main/resources/enchants/artifact/musicartifact.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/artifact/musicartifact.yml
rename to eco-core/core-plugin/src/main/resources/enchants/artifact/musicartifact.yml
diff --git a/Plugin/src/main/resources/enchants/artifact/netherartifact.yml b/eco-core/core-plugin/src/main/resources/enchants/artifact/netherartifact.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/artifact/netherartifact.yml
rename to eco-core/core-plugin/src/main/resources/enchants/artifact/netherartifact.yml
diff --git a/Plugin/src/main/resources/enchants/artifact/redstoneartifact.yml b/eco-core/core-plugin/src/main/resources/enchants/artifact/redstoneartifact.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/artifact/redstoneartifact.yml
rename to eco-core/core-plugin/src/main/resources/enchants/artifact/redstoneartifact.yml
diff --git a/Plugin/src/main/resources/enchants/artifact/smokeartifact.yml b/eco-core/core-plugin/src/main/resources/enchants/artifact/smokeartifact.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/artifact/smokeartifact.yml
rename to eco-core/core-plugin/src/main/resources/enchants/artifact/smokeartifact.yml
diff --git a/Plugin/src/main/resources/enchants/artifact/snowartifact.yml b/eco-core/core-plugin/src/main/resources/enchants/artifact/snowartifact.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/artifact/snowartifact.yml
rename to eco-core/core-plugin/src/main/resources/enchants/artifact/snowartifact.yml
diff --git a/Plugin/src/main/resources/enchants/artifact/soulartifact.yml b/eco-core/core-plugin/src/main/resources/enchants/artifact/soulartifact.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/artifact/soulartifact.yml
rename to eco-core/core-plugin/src/main/resources/enchants/artifact/soulartifact.yml
diff --git a/Plugin/src/main/resources/enchants/artifact/soulfireartifact.yml b/eco-core/core-plugin/src/main/resources/enchants/artifact/soulfireartifact.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/artifact/soulfireartifact.yml
rename to eco-core/core-plugin/src/main/resources/enchants/artifact/soulfireartifact.yml
diff --git a/Plugin/src/main/resources/enchants/artifact/sparkleartifact.yml b/eco-core/core-plugin/src/main/resources/enchants/artifact/sparkleartifact.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/artifact/sparkleartifact.yml
rename to eco-core/core-plugin/src/main/resources/enchants/artifact/sparkleartifact.yml
diff --git a/Plugin/src/main/resources/enchants/artifact/tearartifact.yml b/eco-core/core-plugin/src/main/resources/enchants/artifact/tearartifact.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/artifact/tearartifact.yml
rename to eco-core/core-plugin/src/main/resources/enchants/artifact/tearartifact.yml
diff --git a/Plugin/src/main/resources/enchants/artifact/totemartifact.yml b/eco-core/core-plugin/src/main/resources/enchants/artifact/totemartifact.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/artifact/totemartifact.yml
rename to eco-core/core-plugin/src/main/resources/enchants/artifact/totemartifact.yml
diff --git a/Plugin/src/main/resources/enchants/artifact/warpedartifact.yml b/eco-core/core-plugin/src/main/resources/enchants/artifact/warpedartifact.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/artifact/warpedartifact.yml
rename to eco-core/core-plugin/src/main/resources/enchants/artifact/warpedartifact.yml
diff --git a/Plugin/src/main/resources/enchants/artifact/waterartifact.yml b/eco-core/core-plugin/src/main/resources/enchants/artifact/waterartifact.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/artifact/waterartifact.yml
rename to eco-core/core-plugin/src/main/resources/enchants/artifact/waterartifact.yml
diff --git a/Plugin/src/main/resources/enchants/artifact/witchartifact.yml b/eco-core/core-plugin/src/main/resources/enchants/artifact/witchartifact.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/artifact/witchartifact.yml
rename to eco-core/core-plugin/src/main/resources/enchants/artifact/witchartifact.yml
diff --git a/Plugin/src/main/resources/enchants/artifact/zapartifact.yml b/eco-core/core-plugin/src/main/resources/enchants/artifact/zapartifact.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/artifact/zapartifact.yml
rename to eco-core/core-plugin/src/main/resources/enchants/artifact/zapartifact.yml
diff --git a/Plugin/src/main/resources/enchants/curse/breaklessnesscurse.yml b/eco-core/core-plugin/src/main/resources/enchants/curse/breaklessnesscurse.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/curse/breaklessnesscurse.yml
rename to eco-core/core-plugin/src/main/resources/enchants/curse/breaklessnesscurse.yml
diff --git a/Plugin/src/main/resources/enchants/curse/callingcurse.yml b/eco-core/core-plugin/src/main/resources/enchants/curse/callingcurse.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/curse/callingcurse.yml
rename to eco-core/core-plugin/src/main/resources/enchants/curse/callingcurse.yml
diff --git a/Plugin/src/main/resources/enchants/curse/decaycurse.yml b/eco-core/core-plugin/src/main/resources/enchants/curse/decaycurse.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/curse/decaycurse.yml
rename to eco-core/core-plugin/src/main/resources/enchants/curse/decaycurse.yml
diff --git a/Plugin/src/main/resources/enchants/curse/fragilitycurse.yml b/eco-core/core-plugin/src/main/resources/enchants/curse/fragilitycurse.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/curse/fragilitycurse.yml
rename to eco-core/core-plugin/src/main/resources/enchants/curse/fragilitycurse.yml
diff --git a/Plugin/src/main/resources/enchants/curse/harmlessnesscurse.yml b/eco-core/core-plugin/src/main/resources/enchants/curse/harmlessnesscurse.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/curse/harmlessnesscurse.yml
rename to eco-core/core-plugin/src/main/resources/enchants/curse/harmlessnesscurse.yml
diff --git a/Plugin/src/main/resources/enchants/curse/hungercurse.yml b/eco-core/core-plugin/src/main/resources/enchants/curse/hungercurse.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/curse/hungercurse.yml
rename to eco-core/core-plugin/src/main/resources/enchants/curse/hungercurse.yml
diff --git a/Plugin/src/main/resources/enchants/curse/inaccuracycurse.yml b/eco-core/core-plugin/src/main/resources/enchants/curse/inaccuracycurse.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/curse/inaccuracycurse.yml
rename to eco-core/core-plugin/src/main/resources/enchants/curse/inaccuracycurse.yml
diff --git a/Plugin/src/main/resources/enchants/curse/misfortunecurse.yml b/eco-core/core-plugin/src/main/resources/enchants/curse/misfortunecurse.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/curse/misfortunecurse.yml
rename to eco-core/core-plugin/src/main/resources/enchants/curse/misfortunecurse.yml
diff --git a/Plugin/src/main/resources/enchants/curse/permanencecurse.yml b/eco-core/core-plugin/src/main/resources/enchants/curse/permanencecurse.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/curse/permanencecurse.yml
rename to eco-core/core-plugin/src/main/resources/enchants/curse/permanencecurse.yml
diff --git a/Plugin/src/main/resources/enchants/normal/abattoir.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/abattoir.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/abattoir.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/abattoir.yml
diff --git a/Plugin/src/main/resources/enchants/normal/abrasion.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/abrasion.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/abrasion.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/abrasion.yml
diff --git a/Plugin/src/main/resources/enchants/normal/aerial.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/aerial.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/aerial.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/aerial.yml
diff --git a/Plugin/src/main/resources/enchants/normal/aquatic.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/aquatic.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/aquatic.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/aquatic.yml
diff --git a/Plugin/src/main/resources/enchants/normal/arachnid.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/arachnid.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/arachnid.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/arachnid.yml
diff --git a/Plugin/src/main/resources/enchants/normal/arcanic.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/arcanic.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/arcanic.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/arcanic.yml
diff --git a/Plugin/src/main/resources/enchants/normal/atmospheric.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/atmospheric.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/atmospheric.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/atmospheric.yml
diff --git a/Plugin/src/main/resources/enchants/normal/backstab.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/backstab.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/backstab.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/backstab.yml
diff --git a/Plugin/src/main/resources/enchants/normal/beheading.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/beheading.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/beheading.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/beheading.yml
diff --git a/Plugin/src/main/resources/enchants/normal/blastmining.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/blastmining.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/blastmining.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/blastmining.yml
diff --git a/Plugin/src/main/resources/enchants/normal/bleed.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/bleed.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/bleed.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/bleed.yml
diff --git a/Plugin/src/main/resources/enchants/normal/blind.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/blind.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/blind.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/blind.yml
diff --git a/Plugin/src/main/resources/enchants/normal/blockbreather.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/blockbreather.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/blockbreather.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/blockbreather.yml
diff --git a/Plugin/src/main/resources/enchants/normal/bosshunter.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/bosshunter.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/bosshunter.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/bosshunter.yml
diff --git a/Plugin/src/main/resources/enchants/normal/buckshot.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/buckshot.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/buckshot.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/buckshot.yml
diff --git a/Plugin/src/main/resources/enchants/normal/butchering.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/butchering.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/butchering.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/butchering.yml
diff --git a/Plugin/src/main/resources/enchants/normal/cerebral.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/cerebral.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/cerebral.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/cerebral.yml
diff --git a/Plugin/src/main/resources/enchants/normal/chopless.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/chopless.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/chopless.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/chopless.yml
diff --git a/Plugin/src/main/resources/enchants/normal/cleave.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/cleave.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/cleave.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/cleave.yml
diff --git a/Plugin/src/main/resources/enchants/normal/collateral.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/collateral.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/collateral.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/collateral.yml
diff --git a/Plugin/src/main/resources/enchants/normal/conclude.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/conclude.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/conclude.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/conclude.yml
diff --git a/Plugin/src/main/resources/enchants/normal/corrosive.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/corrosive.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/corrosive.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/corrosive.yml
diff --git a/Plugin/src/main/resources/enchants/normal/cranial.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/cranial.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/cranial.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/cranial.yml
diff --git a/Plugin/src/main/resources/enchants/normal/criticals.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/criticals.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/criticals.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/criticals.yml
diff --git a/Plugin/src/main/resources/enchants/normal/cubism.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/cubism.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/cubism.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/cubism.yml
diff --git a/Plugin/src/main/resources/enchants/normal/defender.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/defender.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/defender.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/defender.yml
diff --git a/Plugin/src/main/resources/enchants/normal/deflection.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/deflection.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/deflection.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/deflection.yml
diff --git a/Plugin/src/main/resources/enchants/normal/defusion.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/defusion.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/defusion.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/defusion.yml
diff --git a/Plugin/src/main/resources/enchants/normal/dexterous.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/dexterous.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/dexterous.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/dexterous.yml
diff --git a/Plugin/src/main/resources/enchants/normal/disable.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/disable.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/disable.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/disable.yml
diff --git a/Plugin/src/main/resources/enchants/normal/disappear.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/disappear.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/disappear.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/disappear.yml
diff --git a/Plugin/src/main/resources/enchants/normal/diurnal.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/diurnal.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/diurnal.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/diurnal.yml
diff --git a/Plugin/src/main/resources/enchants/normal/diverse.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/diverse.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/diverse.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/diverse.yml
diff --git a/Plugin/src/main/resources/enchants/normal/drill.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/drill.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/drill.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/drill.yml
diff --git a/Plugin/src/main/resources/enchants/normal/dullness.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/dullness.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/dullness.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/dullness.yml
diff --git a/Plugin/src/main/resources/enchants/normal/dweller.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/dweller.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/dweller.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/dweller.yml
diff --git a/Plugin/src/main/resources/enchants/normal/economical.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/economical.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/economical.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/economical.yml
diff --git a/Plugin/src/main/resources/enchants/normal/electroshock.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/electroshock.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/electroshock.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/electroshock.yml
diff --git a/Plugin/src/main/resources/enchants/normal/enderism.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/enderism.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/enderism.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/enderism.yml
diff --git a/Plugin/src/main/resources/enchants/normal/enderslayer.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/enderslayer.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/enderslayer.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/enderslayer.yml
diff --git a/Plugin/src/main/resources/enchants/normal/endinfusion.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/endinfusion.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/endinfusion.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/endinfusion.yml
diff --git a/Plugin/src/main/resources/enchants/normal/evasion.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/evasion.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/evasion.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/evasion.yml
diff --git a/Plugin/src/main/resources/enchants/normal/extinguishing.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/extinguishing.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/extinguishing.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/extinguishing.yml
diff --git a/Plugin/src/main/resources/enchants/normal/extract.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/extract.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/extract.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/extract.yml
diff --git a/Plugin/src/main/resources/enchants/normal/famine.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/famine.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/famine.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/famine.yml
diff --git a/Plugin/src/main/resources/enchants/normal/farmhand.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/farmhand.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/farmhand.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/farmhand.yml
diff --git a/Plugin/src/main/resources/enchants/normal/fetching.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/fetching.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/fetching.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/fetching.yml
diff --git a/Plugin/src/main/resources/enchants/normal/finality.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/finality.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/finality.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/finality.yml
diff --git a/Plugin/src/main/resources/enchants/normal/finishing.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/finishing.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/finishing.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/finishing.yml
diff --git a/Plugin/src/main/resources/enchants/normal/fireaffinity.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/fireaffinity.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/fireaffinity.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/fireaffinity.yml
diff --git a/Plugin/src/main/resources/enchants/normal/firststrike.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/firststrike.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/firststrike.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/firststrike.yml
diff --git a/Plugin/src/main/resources/enchants/normal/flinch.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/flinch.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/flinch.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/flinch.yml
diff --git a/Plugin/src/main/resources/enchants/normal/forcefield.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/forcefield.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/forcefield.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/forcefield.yml
diff --git a/Plugin/src/main/resources/enchants/normal/freerunner.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/freerunner.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/freerunner.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/freerunner.yml
diff --git a/Plugin/src/main/resources/enchants/normal/frozen.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/frozen.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/frozen.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/frozen.yml
diff --git a/Plugin/src/main/resources/enchants/normal/fury.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/fury.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/fury.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/fury.yml
diff --git a/Plugin/src/main/resources/enchants/normal/goliath.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/goliath.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/goliath.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/goliath.yml
diff --git a/Plugin/src/main/resources/enchants/normal/graceful.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/graceful.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/graceful.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/graceful.yml
diff --git a/Plugin/src/main/resources/enchants/normal/grapple.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/grapple.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/grapple.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/grapple.yml
diff --git a/Plugin/src/main/resources/enchants/normal/greenthumb.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/greenthumb.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/greenthumb.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/greenthumb.yml
diff --git a/Plugin/src/main/resources/enchants/normal/grit.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/grit.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/grit.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/grit.yml
diff --git a/Plugin/src/main/resources/enchants/normal/hellish.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/hellish.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/hellish.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/hellish.yml
diff --git a/Plugin/src/main/resources/enchants/normal/hook.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/hook.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/hook.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/hook.yml
diff --git a/Plugin/src/main/resources/enchants/normal/horde.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/horde.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/horde.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/horde.yml
diff --git a/Plugin/src/main/resources/enchants/normal/iceshot.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/iceshot.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/iceshot.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/iceshot.yml
diff --git a/Plugin/src/main/resources/enchants/normal/identify.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/identify.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/identify.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/identify.yml
diff --git a/Plugin/src/main/resources/enchants/normal/ignite.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/ignite.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/ignite.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/ignite.yml
diff --git a/Plugin/src/main/resources/enchants/normal/illusionaspect.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/illusionaspect.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/illusionaspect.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/illusionaspect.yml
diff --git a/Plugin/src/main/resources/enchants/normal/impact.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/impact.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/impact.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/impact.yml
diff --git a/Plugin/src/main/resources/enchants/normal/incandescence.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/incandescence.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/incandescence.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/incandescence.yml
diff --git a/Plugin/src/main/resources/enchants/normal/infernaltouch.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/infernaltouch.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/infernaltouch.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/infernaltouch.yml
diff --git a/Plugin/src/main/resources/enchants/normal/inferno.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/inferno.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/inferno.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/inferno.yml
diff --git a/Plugin/src/main/resources/enchants/normal/infuriate.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/infuriate.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/infuriate.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/infuriate.yml
diff --git a/Plugin/src/main/resources/enchants/normal/insecticide.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/insecticide.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/insecticide.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/insecticide.yml
diff --git a/Plugin/src/main/resources/enchants/normal/instantaneous.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/instantaneous.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/instantaneous.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/instantaneous.yml
diff --git a/Plugin/src/main/resources/enchants/normal/invigoration.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/invigoration.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/invigoration.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/invigoration.yml
diff --git a/Plugin/src/main/resources/enchants/normal/kinetic.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/kinetic.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/kinetic.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/kinetic.yml
diff --git a/Plugin/src/main/resources/enchants/normal/launch.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/launch.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/launch.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/launch.yml
diff --git a/Plugin/src/main/resources/enchants/normal/leeching.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/leeching.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/leeching.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/leeching.yml
diff --git a/Plugin/src/main/resources/enchants/normal/lesion.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/lesion.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/lesion.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/lesion.yml
diff --git a/Plugin/src/main/resources/enchants/normal/levitate.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/levitate.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/levitate.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/levitate.yml
diff --git a/Plugin/src/main/resources/enchants/normal/liquidshot.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/liquidshot.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/liquidshot.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/liquidshot.yml
diff --git a/Plugin/src/main/resources/enchants/normal/lumberjack.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/lumberjack.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/lumberjack.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/lumberjack.yml
diff --git a/Plugin/src/main/resources/enchants/normal/magmawalker.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/magmawalker.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/magmawalker.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/magmawalker.yml
diff --git a/Plugin/src/main/resources/enchants/normal/magnetic.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/magnetic.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/magnetic.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/magnetic.yml
diff --git a/Plugin/src/main/resources/enchants/normal/marking.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/marking.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/marking.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/marking.yml
diff --git a/Plugin/src/main/resources/enchants/normal/marksman.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/marksman.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/marksman.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/marksman.yml
diff --git a/Plugin/src/main/resources/enchants/normal/necrotic.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/necrotic.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/necrotic.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/necrotic.yml
diff --git a/Plugin/src/main/resources/enchants/normal/netheric.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/netheric.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/netheric.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/netheric.yml
diff --git a/Plugin/src/main/resources/enchants/normal/netherinfusion.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/netherinfusion.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/netherinfusion.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/netherinfusion.yml
diff --git a/Plugin/src/main/resources/enchants/normal/nocturnal.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/nocturnal.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/nocturnal.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/nocturnal.yml
diff --git a/Plugin/src/main/resources/enchants/normal/optics.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/optics.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/optics.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/optics.yml
diff --git a/Plugin/src/main/resources/enchants/normal/oxygenate.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/oxygenate.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/oxygenate.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/oxygenate.yml
diff --git a/Plugin/src/main/resources/enchants/normal/pacify.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/pacify.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/pacify.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/pacify.yml
diff --git a/Plugin/src/main/resources/enchants/normal/paladin.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/paladin.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/paladin.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/paladin.yml
diff --git a/Plugin/src/main/resources/enchants/normal/paralyze.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/paralyze.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/paralyze.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/paralyze.yml
diff --git a/Plugin/src/main/resources/enchants/normal/parasitic.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/parasitic.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/parasitic.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/parasitic.yml
diff --git a/Plugin/src/main/resources/enchants/normal/parry.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/parry.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/parry.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/parry.yml
diff --git a/Plugin/src/main/resources/enchants/normal/phantasm.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/phantasm.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/phantasm.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/phantasm.yml
diff --git a/Plugin/src/main/resources/enchants/normal/plasmic.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/plasmic.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/plasmic.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/plasmic.yml
diff --git a/Plugin/src/main/resources/enchants/normal/protector.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/protector.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/protector.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/protector.yml
diff --git a/Plugin/src/main/resources/enchants/normal/proximity.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/proximity.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/proximity.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/proximity.yml
diff --git a/Plugin/src/main/resources/enchants/normal/puncture.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/puncture.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/puncture.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/puncture.yml
diff --git a/Plugin/src/main/resources/enchants/normal/quadrilateralism.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/quadrilateralism.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/quadrilateralism.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/quadrilateralism.yml
diff --git a/Plugin/src/main/resources/enchants/normal/radiance.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/radiance.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/radiance.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/radiance.yml
diff --git a/Plugin/src/main/resources/enchants/normal/rage.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/rage.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/rage.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/rage.yml
diff --git a/Plugin/src/main/resources/enchants/normal/rapid.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/rapid.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/rapid.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/rapid.yml
diff --git a/Plugin/src/main/resources/enchants/normal/reel.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/reel.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/reel.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/reel.yml
diff --git a/Plugin/src/main/resources/enchants/normal/reinforcement.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/reinforcement.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/reinforcement.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/reinforcement.yml
diff --git a/Plugin/src/main/resources/enchants/normal/rejuvenation.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/rejuvenation.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/rejuvenation.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/rejuvenation.yml
diff --git a/Plugin/src/main/resources/enchants/normal/replenish.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/replenish.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/replenish.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/replenish.yml
diff --git a/Plugin/src/main/resources/enchants/normal/respirator.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/respirator.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/respirator.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/respirator.yml
diff --git a/Plugin/src/main/resources/enchants/normal/revenant.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/revenant.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/revenant.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/revenant.yml
diff --git a/Plugin/src/main/resources/enchants/normal/sating.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/sating.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/sating.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/sating.yml
diff --git a/Plugin/src/main/resources/enchants/normal/serrated.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/serrated.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/serrated.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/serrated.yml
diff --git a/Plugin/src/main/resources/enchants/normal/settle.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/settle.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/settle.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/settle.yml
diff --git a/Plugin/src/main/resources/enchants/normal/shockwave.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/shockwave.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/shockwave.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/shockwave.yml
diff --git a/Plugin/src/main/resources/enchants/normal/shotassist.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/shotassist.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/shotassist.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/shotassist.yml
diff --git a/Plugin/src/main/resources/enchants/normal/sickening.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/sickening.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/sickening.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/sickening.yml
diff --git a/Plugin/src/main/resources/enchants/normal/slaughter.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/slaughter.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/slaughter.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/slaughter.yml
diff --git a/Plugin/src/main/resources/enchants/normal/slicing.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/slicing.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/slicing.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/slicing.yml
diff --git a/Plugin/src/main/resources/enchants/normal/spearfishing.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/spearfishing.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/spearfishing.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/spearfishing.yml
diff --git a/Plugin/src/main/resources/enchants/normal/spiked.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/spiked.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/spiked.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/spiked.yml
diff --git a/Plugin/src/main/resources/enchants/normal/splash.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/splash.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/splash.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/splash.yml
diff --git a/Plugin/src/main/resources/enchants/normal/stab.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/stab.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/stab.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/stab.yml
diff --git a/Plugin/src/main/resources/enchants/normal/stalwart.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/stalwart.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/stalwart.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/stalwart.yml
diff --git a/Plugin/src/main/resources/enchants/normal/stamina.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/stamina.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/stamina.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/stamina.yml
diff --git a/Plugin/src/main/resources/enchants/normal/stoneswitcher.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/stoneswitcher.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/stoneswitcher.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/stoneswitcher.yml
diff --git a/Plugin/src/main/resources/enchants/normal/strayaspect.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/strayaspect.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/strayaspect.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/strayaspect.yml
diff --git a/Plugin/src/main/resources/enchants/normal/succession.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/succession.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/succession.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/succession.yml
diff --git a/Plugin/src/main/resources/enchants/normal/supercritical.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/supercritical.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/supercritical.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/supercritical.yml
diff --git a/Plugin/src/main/resources/enchants/normal/sycophant.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/sycophant.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/sycophant.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/sycophant.yml
diff --git a/Plugin/src/main/resources/enchants/normal/tectonic.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/tectonic.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/tectonic.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/tectonic.yml
diff --git a/Plugin/src/main/resources/enchants/normal/telekinesis.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/telekinesis.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/telekinesis.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/telekinesis.yml
diff --git a/Plugin/src/main/resources/enchants/normal/thor.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/thor.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/thor.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/thor.yml
diff --git a/Plugin/src/main/resources/enchants/normal/thrive.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/thrive.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/thrive.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/thrive.yml
diff --git a/Plugin/src/main/resources/enchants/normal/tornado.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/tornado.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/tornado.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/tornado.yml
diff --git a/Plugin/src/main/resources/enchants/normal/toxic.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/toxic.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/toxic.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/toxic.yml
diff --git a/Plugin/src/main/resources/enchants/normal/transfuse.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/transfuse.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/transfuse.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/transfuse.yml
diff --git a/Plugin/src/main/resources/enchants/normal/tripleshot.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/tripleshot.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/tripleshot.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/tripleshot.yml
diff --git a/Plugin/src/main/resources/enchants/normal/vampireaspect.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/vampireaspect.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/vampireaspect.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/vampireaspect.yml
diff --git a/Plugin/src/main/resources/enchants/normal/vein.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/vein.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/vein.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/vein.yml
diff --git a/Plugin/src/main/resources/enchants/normal/venom.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/venom.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/venom.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/venom.yml
diff --git a/Plugin/src/main/resources/enchants/normal/voidaffinity.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/voidaffinity.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/voidaffinity.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/voidaffinity.yml
diff --git a/Plugin/src/main/resources/enchants/normal/voltage.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/voltage.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/voltage.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/voltage.yml
diff --git a/Plugin/src/main/resources/enchants/normal/wateraffinity.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/wateraffinity.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/wateraffinity.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/wateraffinity.yml
diff --git a/Plugin/src/main/resources/enchants/normal/wateraspect.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/wateraspect.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/wateraspect.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/wateraspect.yml
diff --git a/Plugin/src/main/resources/enchants/normal/weakening.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/weakening.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/weakening.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/weakening.yml
diff --git a/Plugin/src/main/resources/enchants/normal/wisdom.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/wisdom.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/wisdom.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/wisdom.yml
diff --git a/Plugin/src/main/resources/enchants/normal/wound.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/wound.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/wound.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/wound.yml
diff --git a/Plugin/src/main/resources/enchants/normal/zeus.yml b/eco-core/core-plugin/src/main/resources/enchants/normal/zeus.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/normal/zeus.yml
rename to eco-core/core-plugin/src/main/resources/enchants/normal/zeus.yml
diff --git a/Plugin/src/main/resources/enchants/special/aiming.yml b/eco-core/core-plugin/src/main/resources/enchants/special/aiming.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/special/aiming.yml
rename to eco-core/core-plugin/src/main/resources/enchants/special/aiming.yml
diff --git a/Plugin/src/main/resources/enchants/special/annihilate.yml b/eco-core/core-plugin/src/main/resources/enchants/special/annihilate.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/special/annihilate.yml
rename to eco-core/core-plugin/src/main/resources/enchants/special/annihilate.yml
diff --git a/Plugin/src/main/resources/enchants/special/bladed.yml b/eco-core/core-plugin/src/main/resources/enchants/special/bladed.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/special/bladed.yml
rename to eco-core/core-plugin/src/main/resources/enchants/special/bladed.yml
diff --git a/Plugin/src/main/resources/enchants/special/bolt.yml b/eco-core/core-plugin/src/main/resources/enchants/special/bolt.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/special/bolt.yml
rename to eco-core/core-plugin/src/main/resources/enchants/special/bolt.yml
diff --git a/Plugin/src/main/resources/enchants/special/carve.yml b/eco-core/core-plugin/src/main/resources/enchants/special/carve.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/special/carve.yml
rename to eco-core/core-plugin/src/main/resources/enchants/special/carve.yml
diff --git a/Plugin/src/main/resources/enchants/special/confusion.yml b/eco-core/core-plugin/src/main/resources/enchants/special/confusion.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/special/confusion.yml
rename to eco-core/core-plugin/src/main/resources/enchants/special/confusion.yml
diff --git a/Plugin/src/main/resources/enchants/special/energizing.yml b/eco-core/core-plugin/src/main/resources/enchants/special/energizing.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/special/energizing.yml
rename to eco-core/core-plugin/src/main/resources/enchants/special/energizing.yml
diff --git a/Plugin/src/main/resources/enchants/special/force.yml b/eco-core/core-plugin/src/main/resources/enchants/special/force.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/special/force.yml
rename to eco-core/core-plugin/src/main/resources/enchants/special/force.yml
diff --git a/Plugin/src/main/resources/enchants/special/frenzy.yml b/eco-core/core-plugin/src/main/resources/enchants/special/frenzy.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/special/frenzy.yml
rename to eco-core/core-plugin/src/main/resources/enchants/special/frenzy.yml
diff --git a/Plugin/src/main/resources/enchants/special/harpoon.yml b/eco-core/core-plugin/src/main/resources/enchants/special/harpoon.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/special/harpoon.yml
rename to eco-core/core-plugin/src/main/resources/enchants/special/harpoon.yml
diff --git a/Plugin/src/main/resources/enchants/special/indestructibility.yml b/eco-core/core-plugin/src/main/resources/enchants/special/indestructibility.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/special/indestructibility.yml
rename to eco-core/core-plugin/src/main/resources/enchants/special/indestructibility.yml
diff --git a/Plugin/src/main/resources/enchants/special/instability.yml b/eco-core/core-plugin/src/main/resources/enchants/special/instability.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/special/instability.yml
rename to eco-core/core-plugin/src/main/resources/enchants/special/instability.yml
diff --git a/Plugin/src/main/resources/enchants/special/intellect.yml b/eco-core/core-plugin/src/main/resources/enchants/special/intellect.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/special/intellect.yml
rename to eco-core/core-plugin/src/main/resources/enchants/special/intellect.yml
diff --git a/Plugin/src/main/resources/enchants/special/lifesteal.yml b/eco-core/core-plugin/src/main/resources/enchants/special/lifesteal.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/special/lifesteal.yml
rename to eco-core/core-plugin/src/main/resources/enchants/special/lifesteal.yml
diff --git a/Plugin/src/main/resources/enchants/special/pentashot.yml b/eco-core/core-plugin/src/main/resources/enchants/special/pentashot.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/special/pentashot.yml
rename to eco-core/core-plugin/src/main/resources/enchants/special/pentashot.yml
diff --git a/Plugin/src/main/resources/enchants/special/preservation.yml b/eco-core/core-plugin/src/main/resources/enchants/special/preservation.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/special/preservation.yml
rename to eco-core/core-plugin/src/main/resources/enchants/special/preservation.yml
diff --git a/Plugin/src/main/resources/enchants/special/prosperity.yml b/eco-core/core-plugin/src/main/resources/enchants/special/prosperity.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/special/prosperity.yml
rename to eco-core/core-plugin/src/main/resources/enchants/special/prosperity.yml
diff --git a/Plugin/src/main/resources/enchants/special/razor.yml b/eco-core/core-plugin/src/main/resources/enchants/special/razor.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/special/razor.yml
rename to eco-core/core-plugin/src/main/resources/enchants/special/razor.yml
diff --git a/Plugin/src/main/resources/enchants/special/repairing.yml b/eco-core/core-plugin/src/main/resources/enchants/special/repairing.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/special/repairing.yml
rename to eco-core/core-plugin/src/main/resources/enchants/special/repairing.yml
diff --git a/Plugin/src/main/resources/enchants/special/soulbound.yml b/eco-core/core-plugin/src/main/resources/enchants/special/soulbound.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/special/soulbound.yml
rename to eco-core/core-plugin/src/main/resources/enchants/special/soulbound.yml
diff --git a/Plugin/src/main/resources/enchants/special/spring.yml b/eco-core/core-plugin/src/main/resources/enchants/special/spring.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/special/spring.yml
rename to eco-core/core-plugin/src/main/resources/enchants/special/spring.yml
diff --git a/Plugin/src/main/resources/enchants/special/streamlining.yml b/eco-core/core-plugin/src/main/resources/enchants/special/streamlining.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/special/streamlining.yml
rename to eco-core/core-plugin/src/main/resources/enchants/special/streamlining.yml
diff --git a/Plugin/src/main/resources/enchants/special/volatile.yml b/eco-core/core-plugin/src/main/resources/enchants/special/volatile.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/special/volatile.yml
rename to eco-core/core-plugin/src/main/resources/enchants/special/volatile.yml
diff --git a/Plugin/src/main/resources/enchants/spell/ascend.yml b/eco-core/core-plugin/src/main/resources/enchants/spell/ascend.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/spell/ascend.yml
rename to eco-core/core-plugin/src/main/resources/enchants/spell/ascend.yml
diff --git a/Plugin/src/main/resources/enchants/spell/charge.yml b/eco-core/core-plugin/src/main/resources/enchants/spell/charge.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/spell/charge.yml
rename to eco-core/core-plugin/src/main/resources/enchants/spell/charge.yml
diff --git a/Plugin/src/main/resources/enchants/spell/dynamite.yml b/eco-core/core-plugin/src/main/resources/enchants/spell/dynamite.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/spell/dynamite.yml
rename to eco-core/core-plugin/src/main/resources/enchants/spell/dynamite.yml
diff --git a/Plugin/src/main/resources/enchants/spell/missile.yml b/eco-core/core-plugin/src/main/resources/enchants/spell/missile.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/spell/missile.yml
rename to eco-core/core-plugin/src/main/resources/enchants/spell/missile.yml
diff --git a/Plugin/src/main/resources/enchants/spell/quake.yml b/eco-core/core-plugin/src/main/resources/enchants/spell/quake.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/spell/quake.yml
rename to eco-core/core-plugin/src/main/resources/enchants/spell/quake.yml
diff --git a/Plugin/src/main/resources/enchants/spell/vitalize.yml b/eco-core/core-plugin/src/main/resources/enchants/spell/vitalize.yml
similarity index 100%
rename from Plugin/src/main/resources/enchants/spell/vitalize.yml
rename to eco-core/core-plugin/src/main/resources/enchants/spell/vitalize.yml
diff --git a/Plugin/src/main/resources/lang.yml b/eco-core/core-plugin/src/main/resources/lang.yml
similarity index 100%
rename from Plugin/src/main/resources/lang.yml
rename to eco-core/core-plugin/src/main/resources/lang.yml
diff --git a/Plugin/src/main/resources/plugin.yml b/eco-core/core-plugin/src/main/resources/plugin.yml
similarity index 100%
rename from Plugin/src/main/resources/plugin.yml
rename to eco-core/core-plugin/src/main/resources/plugin.yml
diff --git a/Plugin/src/main/resources/rarity.yml b/eco-core/core-plugin/src/main/resources/rarity.yml
similarity index 100%
rename from Plugin/src/main/resources/rarity.yml
rename to eco-core/core-plugin/src/main/resources/rarity.yml
diff --git a/Plugin/src/main/resources/target.yml b/eco-core/core-plugin/src/main/resources/target.yml
similarity index 100%
rename from Plugin/src/main/resources/target.yml
rename to eco-core/core-plugin/src/main/resources/target.yml
diff --git a/eco-core/core-proxy/build.gradle b/eco-core/core-proxy/build.gradle
new file mode 100644
index 00000000..3f90b631
--- /dev/null
+++ b/eco-core/core-proxy/build.gradle
@@ -0,0 +1,6 @@
+group 'com.willfp'
+version rootProject.version
+
+dependencies {
+ compileOnly 'org.spigotmc:spigot-api:1.16.4-R0.1-SNAPSHOT'
+}
\ No newline at end of file
diff --git a/eco-core/core-proxy/src/main/java/com/willfp/eco/core/proxy/AbstractProxy.java b/eco-core/core-proxy/src/main/java/com/willfp/eco/core/proxy/AbstractProxy.java
new file mode 100644
index 00000000..dddcddc2
--- /dev/null
+++ b/eco-core/core-proxy/src/main/java/com/willfp/eco/core/proxy/AbstractProxy.java
@@ -0,0 +1,5 @@
+package com.willfp.eco.core.proxy;
+
+public interface AbstractProxy {
+
+}
diff --git a/eco-core/core-proxy/src/main/java/com/willfp/eco/core/proxy/ProxyConstants.java b/eco-core/core-proxy/src/main/java/com/willfp/eco/core/proxy/ProxyConstants.java
new file mode 100644
index 00000000..d9af999e
--- /dev/null
+++ b/eco-core/core-proxy/src/main/java/com/willfp/eco/core/proxy/ProxyConstants.java
@@ -0,0 +1,7 @@
+package com.willfp.eco.core.proxy;
+
+import org.bukkit.Bukkit;
+
+public class ProxyConstants {
+ public static final String NMS_VERSION = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3];
+}
diff --git a/eco-core/core-proxy/src/main/java/com/willfp/eco/core/proxy/ProxyFactory.java b/eco-core/core-proxy/src/main/java/com/willfp/eco/core/proxy/ProxyFactory.java
new file mode 100644
index 00000000..5181f46b
--- /dev/null
+++ b/eco-core/core-proxy/src/main/java/com/willfp/eco/core/proxy/ProxyFactory.java
@@ -0,0 +1,42 @@
+package com.willfp.eco.core.proxy;
+
+import java.util.HashMap;
+
+public class ProxyFactory {
+ private static final HashMap, Object> CACHE = new HashMap<>();
+
+ private final Class proxyClass;
+
+ public ProxyFactory(Class proxyClass) {
+ this.proxyClass = proxyClass;
+ }
+
+ public T getProxy() {
+ try {
+ T cachedProxy = attemptCache();
+ if(cachedProxy != null) return cachedProxy;
+
+ final Class> class2 = Class.forName("com.willfp.eco.core.proxy." + ProxyConstants.NMS_VERSION + "." + proxyClass.getSimpleName().replace("Proxy", ""));
+ Object instance = class2.getConstructor().newInstance();
+ if (proxyClass.isAssignableFrom(class2) && proxyClass.isInstance(instance)) {
+ T proxy = proxyClass.cast(instance);
+ CACHE.put(proxyClass, proxy);
+ }
+ } catch (Exception e) {
+ // If not returned, then throw error
+ }
+
+ throw new UnsupportedVersionException("You're running an unsupported server version: " + ProxyConstants.NMS_VERSION);
+ }
+
+ private T attemptCache() {
+ Object proxy = CACHE.get(proxyClass);
+ if(proxy == null) return null;
+
+ if(proxyClass.isInstance(proxy)) {
+ return proxyClass.cast(proxy);
+ }
+
+ return null;
+ }
+}
diff --git a/eco-core/core-proxy/src/main/java/com/willfp/eco/core/proxy/UnsupportedVersionException.java b/eco-core/core-proxy/src/main/java/com/willfp/eco/core/proxy/UnsupportedVersionException.java
new file mode 100644
index 00000000..56a0d60d
--- /dev/null
+++ b/eco-core/core-proxy/src/main/java/com/willfp/eco/core/proxy/UnsupportedVersionException.java
@@ -0,0 +1,7 @@
+package com.willfp.eco.core.proxy;
+
+public class UnsupportedVersionException extends RuntimeException {
+ public UnsupportedVersionException(String message) {
+ super(message);
+ }
+}
diff --git a/eco-core/core-proxy/src/main/java/com/willfp/eco/core/proxy/proxies/BlockBreakProxy.java b/eco-core/core-proxy/src/main/java/com/willfp/eco/core/proxy/proxies/BlockBreakProxy.java
new file mode 100644
index 00000000..02ea104a
--- /dev/null
+++ b/eco-core/core-proxy/src/main/java/com/willfp/eco/core/proxy/proxies/BlockBreakProxy.java
@@ -0,0 +1,13 @@
+package com.willfp.eco.core.proxy.proxies;
+
+
+import com.willfp.eco.core.proxy.AbstractProxy;
+import org.bukkit.block.Block;
+import org.bukkit.entity.Player;
+
+/**
+ * Utility class to break a block as if the player had done it manually
+ */
+public interface BlockBreakProxy extends AbstractProxy {
+ void breakBlock(Player player, Block block);
+}
diff --git a/eco-core/core-proxy/src/main/java/com/willfp/eco/core/proxy/proxies/ChatComponentProxy.java b/eco-core/core-proxy/src/main/java/com/willfp/eco/core/proxy/proxies/ChatComponentProxy.java
new file mode 100644
index 00000000..dd8ff1c9
--- /dev/null
+++ b/eco-core/core-proxy/src/main/java/com/willfp/eco/core/proxy/proxies/ChatComponentProxy.java
@@ -0,0 +1,11 @@
+package com.willfp.eco.core.proxy.proxies;
+
+
+import com.willfp.eco.core.proxy.AbstractProxy;
+
+/**
+ * Utility class to manage chat components
+ */
+public interface ChatComponentProxy extends AbstractProxy {
+ Object modifyComponent(Object object);
+}
\ No newline at end of file
diff --git a/eco-core/core-proxy/src/main/java/com/willfp/eco/core/proxy/proxies/CooldownProxy.java b/eco-core/core-proxy/src/main/java/com/willfp/eco/core/proxy/proxies/CooldownProxy.java
new file mode 100644
index 00000000..82afecca
--- /dev/null
+++ b/eco-core/core-proxy/src/main/java/com/willfp/eco/core/proxy/proxies/CooldownProxy.java
@@ -0,0 +1,12 @@
+package com.willfp.eco.core.proxy.proxies;
+
+
+import com.willfp.eco.core.proxy.AbstractProxy;
+import org.bukkit.entity.Player;
+
+/**
+ * Utility class to get the attack cooldown of a player
+ */
+public interface CooldownProxy extends AbstractProxy {
+ double getAttackCooldown(Player player);
+}
\ No newline at end of file
diff --git a/NMS/API/src/main/java/com/willfp/ecoenchants/nms/api/FastGetEnchantsWrapper.java b/eco-core/core-proxy/src/main/java/com/willfp/eco/core/proxy/proxies/FastGetEnchantsProxy.java
similarity index 51%
rename from NMS/API/src/main/java/com/willfp/ecoenchants/nms/api/FastGetEnchantsWrapper.java
rename to eco-core/core-proxy/src/main/java/com/willfp/eco/core/proxy/proxies/FastGetEnchantsProxy.java
index bdea7273..42688391 100644
--- a/NMS/API/src/main/java/com/willfp/ecoenchants/nms/api/FastGetEnchantsWrapper.java
+++ b/eco-core/core-proxy/src/main/java/com/willfp/eco/core/proxy/proxies/FastGetEnchantsProxy.java
@@ -1,11 +1,15 @@
-package com.willfp.ecoenchants.nms.api;
+package com.willfp.eco.core.proxy.proxies;
+import com.willfp.eco.core.proxy.AbstractProxy;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack;
import java.util.Map;
-public interface FastGetEnchantsWrapper {
+/**
+ * Utility class to break a block as if the player had done it manually
+ */
+public interface FastGetEnchantsProxy extends AbstractProxy {
Map getEnchantmentsOnItem(ItemStack itemStack);
int getLevelOnItem(ItemStack itemStack, Enchantment enchantment);
-}
+}
\ No newline at end of file
diff --git a/eco-core/core-proxy/src/main/java/com/willfp/eco/core/proxy/proxies/OpenInventoryProxy.java b/eco-core/core-proxy/src/main/java/com/willfp/eco/core/proxy/proxies/OpenInventoryProxy.java
new file mode 100644
index 00000000..c3292b21
--- /dev/null
+++ b/eco-core/core-proxy/src/main/java/com/willfp/eco/core/proxy/proxies/OpenInventoryProxy.java
@@ -0,0 +1,11 @@
+package com.willfp.eco.core.proxy.proxies;
+
+import com.willfp.eco.core.proxy.AbstractProxy;
+import org.bukkit.entity.Player;
+
+/**
+ * Utility class to get the NMS implementation of a players' currently open inventory
+ */
+public interface OpenInventoryProxy extends AbstractProxy {
+ Object getOpenInventory(Player player);
+}
\ No newline at end of file
diff --git a/eco-core/core-proxy/src/main/java/com/willfp/eco/core/proxy/proxies/RepairCostProxy.java b/eco-core/core-proxy/src/main/java/com/willfp/eco/core/proxy/proxies/RepairCostProxy.java
new file mode 100644
index 00000000..1f67fc92
--- /dev/null
+++ b/eco-core/core-proxy/src/main/java/com/willfp/eco/core/proxy/proxies/RepairCostProxy.java
@@ -0,0 +1,12 @@
+package com.willfp.eco.core.proxy.proxies;
+
+import com.willfp.eco.core.proxy.AbstractProxy;
+import org.bukkit.inventory.ItemStack;
+
+/**
+ * Utility class to get and set the anvil rework penalty of an item
+ */
+public interface RepairCostProxy extends AbstractProxy {
+ ItemStack setRepairCost(ItemStack itemStack, int cost);
+ int getRepairCost(ItemStack itemStack);
+}
diff --git a/eco-core/core-proxy/src/main/java/com/willfp/eco/core/proxy/proxies/TridentStackProxy.java b/eco-core/core-proxy/src/main/java/com/willfp/eco/core/proxy/proxies/TridentStackProxy.java
new file mode 100644
index 00000000..1e136d80
--- /dev/null
+++ b/eco-core/core-proxy/src/main/java/com/willfp/eco/core/proxy/proxies/TridentStackProxy.java
@@ -0,0 +1,13 @@
+package com.willfp.eco.core.proxy.proxies;
+
+
+import com.willfp.eco.core.proxy.AbstractProxy;
+import org.bukkit.entity.Trident;
+import org.bukkit.inventory.ItemStack;
+
+/**
+ * Utility class to get the {@link ItemStack} of a given {@link Trident}
+ */
+public interface TridentStackProxy extends AbstractProxy {
+ ItemStack getTridentStack(Trident trident);
+}
\ No newline at end of file
diff --git a/eco-util/build.gradle b/eco-util/build.gradle
new file mode 100644
index 00000000..64cd737c
--- /dev/null
+++ b/eco-util/build.gradle
@@ -0,0 +1,12 @@
+group 'com.willfp'
+version rootProject.version
+
+repositories {
+ maven { url 'https://repo.dmulloy2.net/nexus/repository/public/' }
+}
+
+dependencies {
+ implementation 'org.apache.maven:maven-artifact:3.0.3'
+ compileOnly 'org.spigotmc:spigot-api:1.16.4-R0.1-SNAPSHOT'
+ compileOnly 'me.clip:placeholderapi:2.10.9'
+}
\ No newline at end of file
diff --git a/eco-util/src/main/java/com/willfp/eco/util/BlockUtils.java b/eco-util/src/main/java/com/willfp/eco/util/BlockUtils.java
new file mode 100644
index 00000000..0d1c042f
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/BlockUtils.java
@@ -0,0 +1,38 @@
+package com.willfp.eco.util;
+
+import org.bukkit.Material;
+import org.bukkit.block.Block;
+import org.bukkit.block.BlockFace;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class BlockUtils {
+ private static Set getNearbyBlocks(Block start, List allowedMaterials, HashSet blocks, int limit) {
+ for (BlockFace face : BlockFace.values()) {
+ Block block = start.getRelative(face);
+ if (!blocks.contains(block) && allowedMaterials.contains(block.getType())) {
+ blocks.add(block);
+ if (blocks.size() > limit) return blocks;
+ if (blocks.size() > 2500) return blocks; // anti stack overflow
+ blocks.addAll(getNearbyBlocks(block, allowedMaterials, blocks, limit));
+ }
+ }
+ return blocks;
+ }
+
+
+ /**
+ * Get a set of all blocks in contact with each other of a specific type
+ *
+ * @param start The initial block
+ * @param allowedMaterials A list of all valid {@link Material}s
+ * @param limit The maximum size of vein to return
+ *
+ * @return A set of all {@link Block}s
+ */
+ public static Set getVein(Block start, List allowedMaterials, int limit) {
+ return getNearbyBlocks(start, allowedMaterials, new HashSet<>(), limit);
+ }
+}
diff --git a/eco-util/src/main/java/com/willfp/eco/util/ClassUtils.java b/eco-util/src/main/java/com/willfp/eco/util/ClassUtils.java
new file mode 100644
index 00000000..0aa9094e
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/ClassUtils.java
@@ -0,0 +1,21 @@
+package com.willfp.eco.util;
+
+public class ClassUtils {
+ /**
+ * Get if a class exists
+ *
+ * @param className The class to check
+ *
+ * @return If the class exists
+ *
+ * @see Class#forName(String)
+ */
+ public static boolean exists(String className) {
+ try {
+ Class.forName(className);
+ return true;
+ } catch (ClassNotFoundException e) {
+ return false;
+ }
+ }
+}
diff --git a/eco-util/src/main/java/com/willfp/eco/util/DurabilityUtils.java b/eco-util/src/main/java/com/willfp/eco/util/DurabilityUtils.java
new file mode 100644
index 00000000..7ffe483b
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/DurabilityUtils.java
@@ -0,0 +1,112 @@
+package com.willfp.eco.util;
+
+import org.bukkit.Bukkit;
+import org.bukkit.Sound;
+import org.bukkit.SoundCategory;
+import org.bukkit.entity.Player;
+import org.bukkit.event.player.PlayerItemBreakEvent;
+import org.bukkit.event.player.PlayerItemDamageEvent;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.PlayerInventory;
+import org.bukkit.inventory.meta.Damageable;
+import org.bukkit.inventory.meta.ItemMeta;
+
+/**
+ * Contains methods for damaging/repairing items
+ */
+public class DurabilityUtils {
+ /**
+ * Damage an item in a player's inventory
+ * The slot of a held item can be obtained with {@link PlayerInventory#getHeldItemSlot()}
+ * Armor slots are 39 (helmet), 38 (chestplate), 37 (leggings), 36 (boots)
+ *
+ * @param player The player
+ * @param item The item to damage
+ * @param damage The amount of damage to deal
+ * @param slot The slot in the inventory of the item
+ */
+ public static void damageItem(Player player, ItemStack item, int damage, int slot) {
+ if (item == null) return;
+ if (item.getItemMeta() == null) return;
+
+ if (item.getItemMeta().isUnbreakable()) return;
+
+ PlayerItemDamageEvent event3 = new PlayerItemDamageEvent(player, item, damage);
+ Bukkit.getPluginManager().callEvent(event3);
+
+ if (!event3.isCancelled()) {
+ int damage2 = event3.getDamage();
+ if (item.getItemMeta() instanceof Damageable) {
+ Damageable meta = (Damageable) item.getItemMeta();
+ meta.setDamage(meta.getDamage() + damage2);
+
+ if (meta.getDamage() >= item.getType().getMaxDurability()) {
+ meta.setDamage(item.getType().getMaxDurability());
+ item.setItemMeta((ItemMeta) meta);
+ PlayerItemBreakEvent event = new PlayerItemBreakEvent(player, item);
+ Bukkit.getPluginManager().callEvent(event);
+ player.getInventory().clear(slot);
+ player.playSound(player.getLocation(), Sound.ENTITY_ITEM_BREAK, SoundCategory.BLOCKS, 1, 1);
+ } else {
+ item.setItemMeta((ItemMeta) meta);
+ }
+ }
+ }
+ }
+
+ /**
+ * Damage an item in a player's inventory without breaking it
+ * The slot of a held item can be obtained with {@link PlayerInventory#getHeldItemSlot()}
+ * Armor slots are 39 (helmet), 38 (chestplate), 37 (leggings), 36 (boots)
+ *
+ * @param item The item to damage
+ * @param damage The amount of damage to deal
+ * @param player The player
+ */
+ public static void damageItemNoBreak(ItemStack item, int damage, Player player) {
+ if (item == null) return;
+ if (item.getItemMeta() == null) return;
+
+ if (item.getItemMeta().isUnbreakable()) return;
+
+ PlayerItemDamageEvent event3 = new PlayerItemDamageEvent(player, item, damage);
+ Bukkit.getPluginManager().callEvent(event3);
+
+ if (!event3.isCancelled()) {
+ int damage2 = event3.getDamage();
+ if (item.getItemMeta() instanceof Damageable) {
+ Damageable meta = (Damageable) item.getItemMeta();
+ meta.setDamage(meta.getDamage() + damage2);
+
+ if (meta.getDamage() >= item.getType().getMaxDurability()) {
+ meta.setDamage(item.getType().getMaxDurability() - 1);
+ }
+ item.setItemMeta((ItemMeta) meta);
+ }
+ }
+ }
+
+ /**
+ * Repair an item in a player's inventory
+ * The slot of a held item can be obtained with {@link PlayerInventory#getHeldItemSlot()}
+ * Armor slots are 39 (helmet), 38 (chestplate), 37 (leggings), 36 (boots)
+ *
+ * @param item The item to damage
+ * @param repair The amount of damage to heal
+ */
+ public static void repairItem(ItemStack item, int repair) {
+ if (item == null) return;
+ if (item.getItemMeta() == null) return;
+
+ if (item.getItemMeta().isUnbreakable()) return;
+ if (item.getItemMeta() instanceof Damageable) {
+ Damageable meta = (Damageable) item.getItemMeta();
+ meta.setDamage(meta.getDamage() - repair);
+
+ if (meta.getDamage() < 0) {
+ meta.setDamage(0);
+ }
+ item.setItemMeta((ItemMeta) meta);
+ }
+ }
+}
diff --git a/eco-util/src/main/java/com/willfp/eco/util/LightningUtils.java b/eco-util/src/main/java/com/willfp/eco/util/LightningUtils.java
new file mode 100644
index 00000000..b75df107
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/LightningUtils.java
@@ -0,0 +1,26 @@
+package com.willfp.eco.util;
+
+import org.bukkit.Location;
+import org.bukkit.entity.LivingEntity;
+
+/**
+ * Class containing methods for striking lightning
+ */
+public class LightningUtils {
+
+ /**
+ * Strike lightning on player without fire
+ *
+ * @param victim The entity to smite
+ * @param damage The damage to deal
+ */
+ public static void strike(LivingEntity victim, double damage) {
+ if (victim == null) return;
+
+ Location loc = victim.getLocation();
+
+ victim.getWorld().strikeLightningEffect(loc);
+
+ victim.damage(damage);
+ }
+}
diff --git a/eco-util/src/main/java/com/willfp/eco/util/NumberUtils.java b/eco-util/src/main/java/com/willfp/eco/util/NumberUtils.java
new file mode 100644
index 00000000..2cd8ea3c
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/NumberUtils.java
@@ -0,0 +1,157 @@
+package com.willfp.eco.util;
+
+import java.text.DecimalFormat;
+import java.util.TreeMap;
+
+public class NumberUtils {
+
+ private final static TreeMap NUMERALS = new TreeMap<>();
+
+ static {
+
+ NUMERALS.put(1000, "M");
+ NUMERALS.put(900, "CM");
+ NUMERALS.put(500, "D");
+ NUMERALS.put(400, "CD");
+ NUMERALS.put(100, "C");
+ NUMERALS.put(90, "XC");
+ NUMERALS.put(50, "L");
+ NUMERALS.put(40, "XL");
+ NUMERALS.put(10, "X");
+ NUMERALS.put(9, "IX");
+ NUMERALS.put(5, "V");
+ NUMERALS.put(4, "IV");
+ NUMERALS.put(1, "I");
+
+ }
+
+ /**
+ * Bias the input value according to a curve
+ *
+ * @param input The input value
+ * @param bias The bias between -1 and 1, where higher values bias input values to lower output values
+ *
+ * @return The biased output
+ */
+ public static double bias(double input, double bias) {
+ double k = Math.pow(1 - bias, 3);
+
+ return (input * k) / (input * k - input + 1);
+ }
+
+ /**
+ * If value is above maximum, set it to maximum
+ *
+ * @param toChange The value to test
+ * @param limit The maximum
+ *
+ * @return The new value
+ */
+ public static int equalIfOver(int toChange, int limit) {
+ if (toChange > limit) {
+ toChange = limit;
+ }
+ return toChange;
+ }
+
+ /**
+ * If value is above maximum, set it to maximum
+ *
+ * @param toChange The value to test
+ * @param limit The maximum
+ *
+ * @return The new value
+ */
+ public static double equalIfOver(double toChange, double limit) {
+ if (toChange > limit) {
+ toChange = limit;
+ }
+ return toChange;
+ }
+
+ /**
+ * Get Roman Numeral from number
+ *
+ * @param number The number to convert
+ *
+ * @return The number, converted to a roman numeral
+ */
+ public static String toNumeral(int number) {
+ if (number >= 1 && number <= 4096) {
+ int l = NUMERALS.floorKey(number);
+ if (number == l) {
+ return NUMERALS.get(number);
+ }
+ return NUMERALS.get(l) + toNumeral(number - l);
+ } else return String.valueOf(number);
+ }
+
+ /**
+ * Generate random integer in range
+ *
+ * @param min Minimum
+ * @param max Maximum
+ *
+ * @return Random integer
+ */
+ public static int randInt(int min, int max) {
+ return (int) ((long) min + Math.random() * ((long) max - min + 1));
+ }
+
+ /**
+ * Generate random double in range
+ *
+ * @param min Minimum
+ * @param max Maximum
+ *
+ * @return Random double
+ */
+ public static double randFloat(double min, double max) {
+ java.util.Random rand = new java.util.Random();
+ return rand.nextFloat() * (max - min) + min;
+ }
+
+ /**
+ * Generate random double with a triangular distribution
+ *
+ * @param minimum Minimum
+ * @param maximum Maximum
+ * @param peak Peak
+ *
+ * @return Random double
+ */
+ public static double triangularDistribution(double minimum, double maximum, double peak) {
+ double F = (peak - minimum) / (maximum - minimum);
+ double rand = Math.random();
+ if (rand < F) {
+ return minimum + Math.sqrt(rand * (maximum - minimum) * (peak - minimum));
+ } else {
+ return maximum - Math.sqrt((1 - rand) * (maximum - minimum) * (maximum - peak));
+ }
+ }
+
+ /**
+ * Get Log base 2 of a number
+ *
+ * @param N The number
+ *
+ * @return The result
+ */
+ public static int log2(int N) {
+ return (int) (Math.log(N) / Math.log(2));
+ }
+
+ /**
+ * Format double to string
+ *
+ * @param toFormat The number to format
+ *
+ * @return Formatted
+ */
+ public static String format(double toFormat) {
+ DecimalFormat df = new DecimalFormat("0.00");
+ String formatted = df.format(toFormat);
+
+ return formatted.endsWith("00") ? String.valueOf((int) toFormat) : formatted;
+ }
+}
diff --git a/eco-util/src/main/java/com/willfp/eco/util/StringUtils.java b/eco-util/src/main/java/com/willfp/eco/util/StringUtils.java
new file mode 100644
index 00000000..c6031b31
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/StringUtils.java
@@ -0,0 +1,99 @@
+package com.willfp.eco.util;
+
+import com.willfp.eco.util.integrations.placeholder.PlaceholderManager;
+import net.md_5.bungee.api.ChatColor;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collection;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+import static net.md_5.bungee.api.ChatColor.COLOR_CHAR;
+
+public class StringUtils {
+ /**
+ * Translate a string - converts Placeholders and Color codes
+ *
+ * @param message The message to translate
+ * @param player The player to translate placeholders with respect to
+ *
+ * @return The message, translated
+ */
+ public static String translate(String message, @Nullable Player player) {
+ message = PlaceholderManager.translatePlaceholders(message, player);
+ message = translateHexColorCodes(message);
+ message = ChatColor.translateAlternateColorCodes('&', message);
+ return ChatColor.translateAlternateColorCodes('&', translateHexColorCodes(message));
+ }
+
+ /**
+ * Translate a string without respect to a player
+ *
+ * @param message The message to translate
+ *
+ * @return The message, translated
+ *
+ * @see StringUtils#translate(String, Player)
+ */
+ public static String translate(String message) {
+ message = PlaceholderManager.translatePlaceholders(message, null);
+ message = translateHexColorCodes(message);
+ message = ChatColor.translateAlternateColorCodes('&', message);
+ return ChatColor.translateAlternateColorCodes('&', translateHexColorCodes(message));
+ }
+
+ private static String translateHexColorCodes(String message) {
+ Pattern hexPattern = Pattern.compile("" + "([A-Fa-f0-9]{6})" + "");
+ Matcher matcher = hexPattern.matcher(message);
+ StringBuffer buffer = new StringBuffer(message.length() + 4 * 8);
+ while (matcher.find()) {
+ String group = matcher.group(1);
+ matcher.appendReplacement(buffer, COLOR_CHAR + "x"
+ + COLOR_CHAR + group.charAt(0) + COLOR_CHAR + group.charAt(1)
+ + COLOR_CHAR + group.charAt(2) + COLOR_CHAR + group.charAt(3)
+ + COLOR_CHAR + group.charAt(4) + COLOR_CHAR + group.charAt(5));
+ }
+
+ return matcher.appendTail(buffer).toString();
+ }
+
+ /**
+ * Internal implementation of {@link String#valueOf}
+ * Formats collections and doubles better
+ *
+ * @param object The object to convert to string
+ *
+ * @return The object stringified
+ */
+ public static String internalToString(@Nullable Object object) {
+ if (object == null) return "null";
+
+ if (object instanceof Integer) {
+ return ((Integer) object).toString();
+ } else if (object instanceof String) {
+ return (String) object;
+ } else if (object instanceof Double) {
+ return NumberUtils.format((Double) object);
+ } else if (object instanceof Collection>) {
+ Collection> c = (Collection>) object;
+ return c.stream().map(StringUtils::internalToString).collect(Collectors.joining(", "));
+ } else return String.valueOf(object);
+ }
+
+ /**
+ * Remove a string of characters from the start of a string
+ *
+ * @param s The string to remove the prefix from
+ * @param prefix The substring to remove
+ *
+ * @return The string with the prefix removed
+ */
+ public static String removePrefix(String s, String prefix) {
+ if (s != null && prefix != null && s.startsWith(prefix)) {
+ return s.substring(prefix.length());
+ }
+ return s;
+ }
+}
diff --git a/eco-util/src/main/java/com/willfp/eco/util/VectorUtils.java b/eco-util/src/main/java/com/willfp/eco/util/VectorUtils.java
new file mode 100644
index 00000000..387aa7fa
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/VectorUtils.java
@@ -0,0 +1,146 @@
+package com.willfp.eco.util;
+
+import org.bukkit.util.NumberConversions;
+import org.bukkit.util.Vector;
+
+import java.util.ArrayList;
+
+public class VectorUtils {
+ /**
+ * If vector has all components as finite
+ *
+ * @param vector The vector to check
+ *
+ * @return If the vector is finite
+ */
+ public static boolean isFinite(Vector vector) {
+ try {
+ NumberConversions.checkFinite(vector.getX(), "x not finite");
+ NumberConversions.checkFinite(vector.getY(), "y not finite");
+ NumberConversions.checkFinite(vector.getZ(), "z not finite");
+ } catch (IllegalArgumentException e) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Only keep largest part of normalised vector.
+ * For example: -0.8, 0.01, -0.2 would become -1, 0, 0
+ *
+ * @param vec The vector to simplify
+ *
+ * @return The vector, simplified
+ */
+ public static Vector simplifyVector(Vector vec) {
+ double x = Math.abs(vec.getX());
+ double y = Math.abs(vec.getY());
+ double z = Math.abs(vec.getZ());
+ double max = Math.max(x, Math.max(y, z));
+ if (x > 1 || z > 1) {
+ max = y;
+ }
+ if (max == x) {
+ if (vec.getX() < 0) {
+ return new Vector(-1, 0, 0);
+ }
+ return new Vector(1, 0, 0);
+ } else if (max == y) {
+ if (vec.getY() < 0) {
+ return new Vector(0, -1, 0);
+ }
+ return new Vector(0, 1, 0);
+ } else {
+ if (vec.getZ() < 0) {
+ return new Vector(0, 0, -1);
+ }
+ return new Vector(0, 0, 1);
+ }
+ }
+
+ /**
+ * Get circle as relative vectors
+ *
+ * @param radius The radius
+ *
+ * @return An array of {@link Vector}s
+ */
+ public static Vector[] getCircle(int radius) {
+ ArrayList circleVecs = new ArrayList<>();
+
+ int xoffset = -radius;
+ int zoffset = -radius;
+
+ while (zoffset <= radius) {
+ while (xoffset <= radius) {
+ if (Math.round(Math.sqrt((xoffset * xoffset) + (zoffset * zoffset))) <= radius) {
+ circleVecs.add(new Vector(xoffset, 0, zoffset));
+ } else {
+ xoffset++;
+ continue;
+ }
+ xoffset++;
+ }
+ xoffset = -radius;
+ zoffset++;
+ }
+
+ return circleVecs.toArray(new Vector[0]);
+ }
+
+ /**
+ * Get square as relative vectors
+ *
+ * @param radius The radius of the square
+ *
+ * @return An array of {@link Vector}s
+ */
+ public static Vector[] getSquare(int radius) {
+ ArrayList circleVecs = new ArrayList<>();
+
+ int xoffset = -radius;
+ int zoffset = -radius;
+
+ while (zoffset <= radius) {
+ while (xoffset <= radius) {
+ circleVecs.add(new Vector(xoffset, 0, zoffset));
+ xoffset++;
+ }
+ xoffset = -radius;
+ zoffset++;
+ }
+
+ return circleVecs.toArray(new Vector[0]);
+ }
+
+ /**
+ * Get cube as relative vectors
+ *
+ * @param radius The radius of the cube
+ *
+ * @return An array of {@link Vector}s
+ */
+ public static Vector[] getCube(int radius) {
+ ArrayList cubeVecs = new ArrayList<>();
+
+ int xoffset = -radius;
+ int zoffset = -radius;
+ int yoffset = -radius;
+
+ while (yoffset <= radius) {
+ while (zoffset <= radius) {
+ while (xoffset <= radius) {
+ cubeVecs.add(new Vector(xoffset, yoffset, zoffset));
+ xoffset++;
+ }
+ xoffset = -radius;
+ zoffset++;
+ }
+ zoffset = -radius;
+ yoffset++;
+ }
+
+ return cubeVecs.toArray(new Vector[0]);
+ }
+}
diff --git a/eco-util/src/main/java/com/willfp/eco/util/arrows/ArrowDataListener.java b/eco-util/src/main/java/com/willfp/eco/util/arrows/ArrowDataListener.java
new file mode 100644
index 00000000..da6fea50
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/arrows/ArrowDataListener.java
@@ -0,0 +1,44 @@
+package com.willfp.eco.util.arrows;
+
+import com.willfp.eco.util.injection.PluginDependent;
+import com.willfp.eco.util.plugin.AbstractEcoPlugin;
+import org.bukkit.Material;
+import org.bukkit.enchantments.Enchantment;
+import org.bukkit.entity.Arrow;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.event.entity.ProjectileLaunchEvent;
+import org.bukkit.inventory.ItemStack;
+
+import java.util.Map;
+
+public class ArrowDataListener extends PluginDependent implements Listener {
+ public ArrowDataListener(AbstractEcoPlugin plugin) {
+ super(plugin);
+ }
+
+ @EventHandler(priority = EventPriority.LOWEST)
+ public void onLaunch(ProjectileLaunchEvent event) {
+ if (!(event.getEntity() instanceof Arrow))
+ return;
+ if (!(event.getEntity().getShooter() instanceof LivingEntity))
+ return;
+
+ Arrow arrow = (Arrow) event.getEntity();
+ LivingEntity entity = (LivingEntity) arrow.getShooter();
+
+ if (entity.getEquipment() == null)
+ return;
+
+ ItemStack item = entity.getEquipment().getItemInMainHand();
+
+ if (item.getType().equals(Material.AIR)) return;
+ if (!item.hasItemMeta()) return;
+ if (item.getItemMeta() == null) return;
+
+ Map enchantments = item.getItemMeta().getEnchants();
+ arrow.setMetadata("enchantments", plugin.getMetadataValueFactory().create(enchantments));
+ }
+}
diff --git a/eco-util/src/main/java/com/willfp/eco/util/bukkit/events/EcoEventManager.java b/eco-util/src/main/java/com/willfp/eco/util/bukkit/events/EcoEventManager.java
new file mode 100644
index 00000000..21ca0a7c
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/bukkit/events/EcoEventManager.java
@@ -0,0 +1,28 @@
+package com.willfp.eco.util.bukkit.events;
+
+import com.willfp.eco.util.injection.PluginDependent;
+import com.willfp.eco.util.plugin.AbstractEcoPlugin;
+import org.bukkit.Bukkit;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.Listener;
+
+public class EcoEventManager extends PluginDependent implements EventManager {
+ public EcoEventManager(AbstractEcoPlugin plugin) {
+ super(plugin);
+ }
+
+ @Override
+ public void registerEvents(Listener listener) {
+ Bukkit.getPluginManager().registerEvents(listener, this.plugin);
+ }
+
+ @Override
+ public void unregisterEvents(Listener listener) {
+ HandlerList.unregisterAll(listener);
+ }
+
+ @Override
+ public void unregisterAllEvents() {
+ HandlerList.unregisterAll(this.plugin);
+ }
+}
diff --git a/eco-util/src/main/java/com/willfp/eco/util/bukkit/events/EventManager.java b/eco-util/src/main/java/com/willfp/eco/util/bukkit/events/EventManager.java
new file mode 100644
index 00000000..c504d24e
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/bukkit/events/EventManager.java
@@ -0,0 +1,9 @@
+package com.willfp.eco.util.bukkit.events;
+
+import org.bukkit.event.Listener;
+
+public interface EventManager {
+ void registerEvents(Listener listener);
+ void unregisterEvents(Listener listener);
+ void unregisterAllEvents();
+}
diff --git a/eco-util/src/main/java/com/willfp/eco/util/bukkit/keys/NamespacedKeyFactory.java b/eco-util/src/main/java/com/willfp/eco/util/bukkit/keys/NamespacedKeyFactory.java
new file mode 100644
index 00000000..586bc1da
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/bukkit/keys/NamespacedKeyFactory.java
@@ -0,0 +1,15 @@
+package com.willfp.eco.util.bukkit.keys;
+
+import com.willfp.eco.util.factory.PluginDependentFactory;
+import com.willfp.eco.util.plugin.AbstractEcoPlugin;
+import org.bukkit.NamespacedKey;
+
+public class NamespacedKeyFactory extends PluginDependentFactory {
+ public NamespacedKeyFactory(AbstractEcoPlugin plugin) {
+ super(plugin);
+ }
+
+ public NamespacedKey create(String key) {
+ return new NamespacedKey(this.plugin, key);
+ }
+}
diff --git a/eco-util/src/main/java/com/willfp/eco/util/bukkit/logging/EcoLogger.java b/eco-util/src/main/java/com/willfp/eco/util/bukkit/logging/EcoLogger.java
new file mode 100644
index 00000000..19b24821
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/bukkit/logging/EcoLogger.java
@@ -0,0 +1,25 @@
+package com.willfp.eco.util.bukkit.logging;
+
+import com.willfp.eco.util.injection.PluginDependent;
+import com.willfp.eco.util.plugin.AbstractEcoPlugin;
+
+public class EcoLogger extends PluginDependent implements Logger {
+ public EcoLogger(AbstractEcoPlugin plugin) {
+ super(plugin);
+ }
+
+ @Override
+ public void info(String message) {
+ this.plugin.getLogger().info(message);
+ }
+
+ @Override
+ public void warn(String message) {
+ this.plugin.getLogger().warning(message);
+ }
+
+ @Override
+ public void error(String message) {
+ this.plugin.getLogger().severe(message);
+ }
+}
diff --git a/eco-util/src/main/java/com/willfp/eco/util/bukkit/logging/Logger.java b/eco-util/src/main/java/com/willfp/eco/util/bukkit/logging/Logger.java
new file mode 100644
index 00000000..ba32ce29
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/bukkit/logging/Logger.java
@@ -0,0 +1,7 @@
+package com.willfp.eco.util.bukkit.logging;
+
+public interface Logger {
+ void info(String message);
+ void warn(String message);
+ void error(String message);
+}
diff --git a/eco-util/src/main/java/com/willfp/eco/util/bukkit/meta/MetadataValueFactory.java b/eco-util/src/main/java/com/willfp/eco/util/bukkit/meta/MetadataValueFactory.java
new file mode 100644
index 00000000..c5dcd0d2
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/bukkit/meta/MetadataValueFactory.java
@@ -0,0 +1,15 @@
+package com.willfp.eco.util.bukkit.meta;
+
+import com.willfp.eco.util.factory.PluginDependentFactory;
+import com.willfp.eco.util.plugin.AbstractEcoPlugin;
+import org.bukkit.metadata.FixedMetadataValue;
+
+public class MetadataValueFactory extends PluginDependentFactory {
+ public MetadataValueFactory(AbstractEcoPlugin plugin) {
+ super(plugin);
+ }
+
+ public FixedMetadataValue create(Object value) {
+ return new FixedMetadataValue(this.plugin, value);
+ }
+}
diff --git a/eco-util/src/main/java/com/willfp/eco/util/bukkit/scheduling/EcoScheduler.java b/eco-util/src/main/java/com/willfp/eco/util/bukkit/scheduling/EcoScheduler.java
new file mode 100644
index 00000000..ae8e8d9a
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/bukkit/scheduling/EcoScheduler.java
@@ -0,0 +1,38 @@
+package com.willfp.eco.util.bukkit.scheduling;
+
+import com.willfp.eco.util.injection.PluginDependent;
+import com.willfp.eco.util.lambda.Callable;
+import com.willfp.eco.util.plugin.AbstractEcoPlugin;
+import org.bukkit.Bukkit;
+import org.bukkit.scheduler.BukkitTask;
+
+public class EcoScheduler extends PluginDependent implements Scheduler {
+ public EcoScheduler(AbstractEcoPlugin plugin) {
+ super(plugin);
+ }
+
+ @Override
+ public BukkitTask runLater(Callable callable, long ticksLater) {
+ return Bukkit.getServer().getScheduler().runTaskLater(this.plugin, callable::call, ticksLater);
+ }
+
+ @Override
+ public BukkitTask runTimer(Callable callable, long delay, long repeat) {
+ return Bukkit.getServer().getScheduler().runTaskTimer(this.plugin, callable::call, delay, repeat);
+ }
+
+ @Override
+ public BukkitTask runAsyncTimer(Callable callable, long delay, long repeat) {
+ return Bukkit.getServer().getScheduler().runTaskTimerAsynchronously(this.plugin, callable::call, delay, repeat);
+ }
+
+ @Override
+ public BukkitTask run(Callable callable) {
+ return Bukkit.getServer().getScheduler().runTask(this.plugin, callable::call);
+ }
+
+ @Override
+ public void cancelAll() {
+ Bukkit.getScheduler().cancelTasks(this.plugin);
+ }
+}
diff --git a/eco-util/src/main/java/com/willfp/eco/util/bukkit/scheduling/Scheduler.java b/eco-util/src/main/java/com/willfp/eco/util/bukkit/scheduling/Scheduler.java
new file mode 100644
index 00000000..4438411e
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/bukkit/scheduling/Scheduler.java
@@ -0,0 +1,12 @@
+package com.willfp.eco.util.bukkit.scheduling;
+
+import com.willfp.eco.util.lambda.Callable;
+import org.bukkit.scheduler.BukkitTask;
+
+public interface Scheduler {
+ BukkitTask runLater(Callable callable, long ticksLater);
+ BukkitTask runTimer(Callable callable, long delay, long repeat);
+ BukkitTask runAsyncTimer(Callable callable, long delay, long repeat);
+ BukkitTask run(Callable callable);
+ void cancelAll();
+}
diff --git a/eco-util/src/main/java/com/willfp/eco/util/command/AbstractCommand.java b/eco-util/src/main/java/com/willfp/eco/util/command/AbstractCommand.java
new file mode 100644
index 00000000..83234d47
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/command/AbstractCommand.java
@@ -0,0 +1,71 @@
+package com.willfp.eco.util.command;
+
+import com.willfp.eco.util.config.Configs;
+import com.willfp.eco.util.interfaces.Registerable;
+import org.bukkit.Bukkit;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandExecutor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.command.PluginCommand;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Arrays;
+import java.util.List;
+
+public abstract class AbstractCommand implements CommandExecutor, Registerable {
+ private final String name;
+ private final String permission;
+ private final boolean playersOnly;
+
+ protected AbstractCommand(String name, String permission, boolean playersOnly) {
+ this.name = name;
+ this.permission = permission;
+ this.playersOnly = playersOnly;
+ }
+
+ public AbstractTabCompleter getTab() {
+ return null;
+ }
+
+ public String getPermission() {
+ return this.permission;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ @Override
+ public boolean onCommand(@NotNull CommandSender sender, Command command, @NotNull String label, String[] args) {
+ if (!command.getName().equalsIgnoreCase(name)) return false;
+
+ if (playersOnly && !(sender instanceof Player)) {
+ sender.sendMessage(Configs.LANG.getMessage("not-player"));
+ return true;
+ }
+
+ if (!sender.hasPermission(permission) && sender instanceof Player) {
+ sender.sendMessage(Configs.LANG.getNoPermission());
+ return true;
+ }
+
+ onExecute(sender, Arrays.asList(args));
+
+ return true;
+ }
+
+ @Override
+ public final void register() {
+ PluginCommand command = Bukkit.getPluginCommand(name);
+ assert command != null;
+ command.setExecutor(this);
+
+ AbstractTabCompleter tabCompleter = this.getTab();
+ if (tabCompleter != null) {
+ command.setTabCompleter(tabCompleter);
+ }
+ }
+
+ public abstract void onExecute(CommandSender sender, List args);
+}
diff --git a/eco-util/src/main/java/com/willfp/eco/util/command/AbstractTabCompleter.java b/eco-util/src/main/java/com/willfp/eco/util/command/AbstractTabCompleter.java
new file mode 100644
index 00000000..0c5257be
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/command/AbstractTabCompleter.java
@@ -0,0 +1,31 @@
+package com.willfp.eco.util.command;
+
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+import org.bukkit.command.TabCompleter;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Arrays;
+import java.util.List;
+
+public abstract class AbstractTabCompleter implements TabCompleter {
+ private final AbstractCommand command;
+
+ protected AbstractTabCompleter(AbstractCommand command) {
+ this.command = command;
+ }
+
+ @Override
+ public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
+ if (!command.getName().equalsIgnoreCase(this.command.getName()))
+ return null;
+
+ if (!sender.hasPermission(this.command.getPermission()))
+ return null;
+
+ return onTab(sender, Arrays.asList(args));
+ }
+
+ public abstract List onTab(CommandSender sender, List args);
+}
diff --git a/eco-util/src/main/java/com/willfp/eco/util/config/BaseConfig.java b/eco-util/src/main/java/com/willfp/eco/util/config/BaseConfig.java
new file mode 100644
index 00000000..21a1d1d6
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/config/BaseConfig.java
@@ -0,0 +1,77 @@
+package com.willfp.eco.util.config;
+
+import com.willfp.eco.util.injection.PluginDependent;
+import com.willfp.eco.util.plugin.AbstractEcoPlugin;
+import org.bukkit.configuration.InvalidConfigurationException;
+import org.bukkit.configuration.file.YamlConfiguration;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+
+public abstract class BaseConfig extends PluginDependent {
+ private static final AbstractEcoPlugin plugin = AbstractEcoPlugin.getInstance();
+
+ public final YamlConfiguration config;
+ private final File configFile;
+ private final String name;
+ private final boolean removeUnused;
+
+ protected BaseConfig(String name, boolean removeUnused) {
+ super(plugin);
+ this.name = name + ".yml";
+ this.removeUnused = removeUnused;
+
+ if (!new File(plugin.getDataFolder(), name).exists()) {
+ createFile();
+ }
+
+ this.configFile = new File(plugin.getDataFolder(), name);
+ this.config = YamlConfiguration.loadConfiguration(configFile);
+
+ update();
+ }
+
+ private void createFile() {
+ plugin.saveResource(name, false);
+ }
+
+ public void update() {
+ try {
+ config.load(configFile);
+
+ InputStream newIn = plugin.getResource(name);
+ if (newIn == null) {
+ plugin.getLog().error(name + " is null?");
+ return;
+ }
+ BufferedReader reader = new BufferedReader(new InputStreamReader(newIn, StandardCharsets.UTF_8));
+ YamlConfiguration newConfig = new YamlConfiguration();
+ newConfig.load(reader);
+
+ if (newConfig.getKeys(true).equals(config.getKeys(true)))
+ return;
+
+ newConfig.getKeys(true).forEach((s -> {
+ if (!config.getKeys(true).contains(s)) {
+ config.set(s, newConfig.get(s));
+ }
+ }));
+
+ if (this.removeUnused) {
+ config.getKeys(true).forEach((s -> {
+ if (!newConfig.getKeys(true).contains(s)) {
+ config.set(s, null);
+ }
+ }));
+ }
+
+ config.save(configFile);
+ } catch (IOException | InvalidConfigurationException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/eco-util/src/main/java/com/willfp/eco/util/config/Configs.java b/eco-util/src/main/java/com/willfp/eco/util/config/Configs.java
new file mode 100644
index 00000000..8ecd2dde
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/config/Configs.java
@@ -0,0 +1,10 @@
+package com.willfp.eco.util.config;
+
+
+import com.willfp.eco.util.config.configs.Config;
+import com.willfp.eco.util.config.configs.Lang;
+
+public class Configs {
+ public static final Lang LANG = new Lang();
+ public static final Config CONFIG = new Config();
+}
\ No newline at end of file
diff --git a/eco-util/src/main/java/com/willfp/eco/util/config/configs/Config.java b/eco-util/src/main/java/com/willfp/eco/util/config/configs/Config.java
new file mode 100644
index 00000000..1931183f
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/config/configs/Config.java
@@ -0,0 +1,55 @@
+package com.willfp.eco.util.config.configs;
+
+import com.willfp.eco.util.config.BaseConfig;
+import org.bukkit.inventory.ItemStack;
+
+import java.util.List;
+
+/**
+ * Wrapper for config.yml
+ */
+public class Config extends BaseConfig {
+ public Config() {
+ super("config", true);
+ }
+
+ public int getInt(String path) {
+ return config.getInt(path);
+ }
+
+ public int getInt(String path, int def) {
+ return config.getInt(path, def);
+ }
+
+ public List getInts(String path) {
+ return config.getIntegerList(path);
+ }
+
+ public boolean getBool(String path) {
+ return config.getBoolean(path);
+ }
+
+ public List getBools(String path) {
+ return config.getBooleanList(path);
+ }
+
+ public String getString(String path) {
+ return config.getString(path);
+ }
+
+ public List getStrings(String path) {
+ return config.getStringList(path);
+ }
+
+ public double getDouble(String path) {
+ return config.getDouble(path);
+ }
+
+ public List getDoubles(String path) {
+ return config.getDoubleList(path);
+ }
+
+ public ItemStack getItemStack(String path) {
+ return config.getItemStack(path);
+ }
+}
diff --git a/eco-util/src/main/java/com/willfp/eco/util/config/configs/Lang.java b/eco-util/src/main/java/com/willfp/eco/util/config/configs/Lang.java
new file mode 100644
index 00000000..7340ce3e
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/config/configs/Lang.java
@@ -0,0 +1,36 @@
+package com.willfp.eco.util.config.configs;
+
+import com.willfp.eco.util.StringUtils;
+import com.willfp.eco.util.config.BaseConfig;
+
+import java.util.List;
+
+/**
+ * Wrapper for lang.yml
+ */
+public class Lang extends BaseConfig {
+ public Lang() {
+ super("lang", false);
+ }
+
+ public String getString(String path) {
+ return StringUtils.translate(String.valueOf(config.getString(path)));
+ }
+
+ public List getStrings(String path) {
+ return config.getStringList(path);
+ }
+
+
+ public String getPrefix() {
+ return StringUtils.translate(config.getString("messages.prefix"));
+ }
+
+ public String getNoPermission() {
+ return getPrefix() + StringUtils.translate(config.getString("messages.no-permission"));
+ }
+
+ public String getMessage(String message) {
+ return getPrefix() + StringUtils.translate(config.getString("messages." + message));
+ }
+}
\ No newline at end of file
diff --git a/eco-util/src/main/java/com/willfp/eco/util/drops/DropQueue.java b/eco-util/src/main/java/com/willfp/eco/util/drops/DropQueue.java
new file mode 100644
index 00000000..6bfb51d8
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/drops/DropQueue.java
@@ -0,0 +1,101 @@
+package com.willfp.eco.util.drops;
+
+import com.willfp.eco.util.drops.internal.AbstractDropQueue;
+import com.willfp.eco.util.drops.internal.DropManager;
+import com.willfp.eco.util.drops.internal.DropQueueType;
+import com.willfp.eco.util.drops.internal.FastCollatedDropQueue;
+import com.willfp.eco.util.drops.internal.InternalDropQueue;
+import org.bukkit.Location;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.ItemStack;
+
+import java.util.Collection;
+
+/**
+ * All drops should be sent through a {@link DropQueue}
+ */
+public class DropQueue {
+ private final AbstractDropQueue handle;
+
+ /**
+ * Create {@link DropQueue} linked to player
+ *
+ * @param player The player
+ */
+ public DropQueue(Player player) {
+ handle = DropManager.getType() == DropQueueType.COLLATED ? new FastCollatedDropQueue(player) : new InternalDropQueue(player);
+ }
+
+ /**
+ * Add item to queue
+ *
+ * @param item The item to add
+ * @return The DropQueue
+ */
+ public DropQueue addItem(ItemStack item) {
+ handle.addItem(item);
+ return this;
+ }
+
+ /**
+ * Add multiple items to queue
+ *
+ * @param itemStacks The items to add
+ * @return The DropQueue
+ */
+ public DropQueue addItems(Collection itemStacks) {
+ handle.addItems(itemStacks);
+ return this;
+ }
+
+ /**
+ * Add xp to queue
+ *
+ * @param amount The amount to add
+ * @return The DropQueue
+ */
+ public DropQueue addXP(int amount) {
+ handle.addXP(amount);
+ return this;
+ }
+
+ /**
+ * Set location of the origin of the drops
+ *
+ * @param location The location
+ * @return The DropQueue
+ */
+ public DropQueue setLocation(Location location) {
+ handle.setLocation(location);
+ return this;
+ }
+
+ /**
+ * Force the queue to act as if player is telekinetic
+ *
+ * @return The DropQueue
+ */
+ public DropQueue forceTelekinesis() {
+ handle.forceTelekinesis();
+ return this;
+ }
+
+ /**
+ * Set the queue to test specific item for telekinesis
+ * Default item is the player's held item, however for this is required for Tridents.
+ *
+ * @param item The item to test
+ * @return The DropQueue
+ */
+ public DropQueue setItem(ItemStack item) {
+ handle.setItem(item);
+ return this;
+ }
+
+ /**
+ * Push the queue
+ */
+ public void push() {
+ handle.push();
+ }
+}
\ No newline at end of file
diff --git a/eco-util/src/main/java/com/willfp/eco/util/drops/internal/AbstractDropQueue.java b/eco-util/src/main/java/com/willfp/eco/util/drops/internal/AbstractDropQueue.java
new file mode 100644
index 00000000..a9cd779a
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/drops/internal/AbstractDropQueue.java
@@ -0,0 +1,61 @@
+package com.willfp.eco.util.drops.internal;
+
+import org.bukkit.Location;
+import org.bukkit.inventory.ItemStack;
+
+import java.util.Collection;
+
+public interface AbstractDropQueue {
+ /**
+ * Add item to queue
+ *
+ * @param item The item to add
+ * @return The DropQueue
+ */
+ AbstractDropQueue addItem(ItemStack item);
+
+ /**
+ * Add multiple items to queue
+ *
+ * @param itemStacks The items to add
+ * @return The DropQueue
+ */
+ AbstractDropQueue addItems(Collection itemStacks);
+
+ /**
+ * Add xp to queue
+ *
+ * @param amount The amount to add
+ * @return The DropQueue
+ */
+ AbstractDropQueue addXP(int amount);
+
+ /**
+ * Set location of the origin of the drops
+ *
+ * @param location The location
+ * @return The DropQueue
+ */
+ AbstractDropQueue setLocation(Location location);
+
+ /**
+ * Force the queue to act as if player is telekinetic
+ *
+ * @return The DropQueue
+ */
+ AbstractDropQueue forceTelekinesis();
+
+ /**
+ * Set the queue to test specific item for telekinesis
+ * Default item is the player's held item, however for this is required for Tridents.
+ *
+ * @param item The item to test
+ * @return The DropQueue
+ */
+ AbstractDropQueue setItem(ItemStack item);
+
+ /**
+ * Push the queue
+ */
+ void push();
+}
diff --git a/eco-util/src/main/java/com/willfp/eco/util/drops/internal/DropManager.java b/eco-util/src/main/java/com/willfp/eco/util/drops/internal/DropManager.java
new file mode 100644
index 00000000..c478fc60
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/drops/internal/DropManager.java
@@ -0,0 +1,19 @@
+package com.willfp.eco.util.drops.internal;
+
+import com.willfp.eco.util.config.Configs;
+
+public class DropManager {
+ private static DropQueueType type = DropQueueType.STANDARD;
+
+ public static DropQueueType getType() {
+ return type;
+ }
+
+ public static void update() {
+ type = Configs.CONFIG.getBool("drops.collate") ? DropQueueType.COLLATED : DropQueueType.STANDARD;
+ }
+
+ static {
+ update();
+ }
+}
diff --git a/eco-util/src/main/java/com/willfp/eco/util/drops/internal/DropQueueType.java b/eco-util/src/main/java/com/willfp/eco/util/drops/internal/DropQueueType.java
new file mode 100644
index 00000000..643cdfb0
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/drops/internal/DropQueueType.java
@@ -0,0 +1,6 @@
+package com.willfp.eco.util.drops.internal;
+
+public enum DropQueueType {
+ STANDARD,
+ COLLATED
+}
diff --git a/eco-util/src/main/java/com/willfp/eco/util/drops/internal/FastCollatedDropQueue.java b/eco-util/src/main/java/com/willfp/eco/util/drops/internal/FastCollatedDropQueue.java
new file mode 100644
index 00000000..cd0c7f3d
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/drops/internal/FastCollatedDropQueue.java
@@ -0,0 +1,109 @@
+package com.willfp.eco.util.drops.internal;
+
+import com.willfp.eco.util.drops.DropQueue;
+import com.willfp.eco.util.injection.PluginDependent;
+import com.willfp.eco.util.plugin.AbstractEcoPlugin;
+import org.bukkit.Location;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.scheduler.BukkitTask;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Backend implementation of {@link AbstractDropQueue}
+ * {@link this#push()} adds to a map that creates a new {@link InternalDropQueue} at the end of every tick
+ *
+ * The drops are not instantly pushed when called, instead the map is iterated over at the end of every tick. This massively improves performance.
+ */
+public class FastCollatedDropQueue extends InternalDropQueue {
+ private static final HashMap COLLATED_MAP = new HashMap<>();
+
+ /**
+ * Create {@link DropQueue} linked to player
+ *
+ * @param player The player
+ */
+ public FastCollatedDropQueue(Player player) {
+ super(player);
+ }
+
+ @Override
+ public void push() {
+ CollatedDrops fetched = COLLATED_MAP.get(player);
+ CollatedDrops collatedDrops = fetched == null ? new CollatedDrops(items, loc, xp) : fetched.addDrops(items).setLocation(loc).addXp(xp);
+ COLLATED_MAP.put(player, collatedDrops);
+ }
+
+ private static class CollatedDrops {
+ private final List drops;
+ private Location location;
+ private int xp;
+
+ private CollatedDrops(List drops, Location location, int xp) {
+ this.drops = drops;
+ this.location = location;
+ this.xp = xp;
+ }
+
+ public List getDrops() {
+ return drops;
+ }
+
+ public Location getLocation() {
+ return location;
+ }
+
+ public int getXp() {
+ return xp;
+ }
+
+ public CollatedDrops addDrops(List toAdd) {
+ drops.addAll(toAdd);
+ return this;
+ }
+
+ public CollatedDrops setLocation(Location loc) {
+ this.location = loc;
+ return this;
+ }
+
+ public CollatedDrops addXp(int xp) {
+ this.xp += xp;
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return "CollatedDrops{" +
+ "drops=" + drops +
+ ", location=" + location +
+ ", xp=" + xp +
+ '}';
+ }
+ }
+
+ public static class CollatedRunnable extends PluginDependent {
+ private final BukkitTask runnableTask;
+
+ public CollatedRunnable(AbstractEcoPlugin plugin) {
+ super(plugin);
+ runnableTask = plugin.getScheduler().runTimer(() -> {
+ for (Map.Entry entry : COLLATED_MAP.entrySet()) {
+ new InternalDropQueue(entry.getKey())
+ .setLocation(entry.getValue().getLocation())
+ .addItems(entry.getValue().getDrops())
+ .addXP(entry.getValue().getXp())
+ .push();
+ }
+ COLLATED_MAP.clear();
+ }, 0, 1);
+ }
+
+ public BukkitTask getRunnableTask() {
+ return runnableTask;
+ }
+ }
+}
\ No newline at end of file
diff --git a/eco-util/src/main/java/com/willfp/eco/util/drops/internal/InternalDropQueue.java b/eco-util/src/main/java/com/willfp/eco/util/drops/internal/InternalDropQueue.java
new file mode 100644
index 00000000..845c8b8f
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/drops/internal/InternalDropQueue.java
@@ -0,0 +1,149 @@
+package com.willfp.eco.util.drops.internal;
+
+import com.willfp.eco.util.drops.telekinesis.TelekineticTests;
+import org.bukkit.Bukkit;
+import org.bukkit.Location;
+import org.bukkit.World;
+import org.bukkit.entity.EntityType;
+import org.bukkit.entity.ExperienceOrb;
+import org.bukkit.entity.Player;
+import org.bukkit.event.player.PlayerExpChangeEvent;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.util.Vector;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+
+public class InternalDropQueue implements AbstractDropQueue {
+ protected final List items;
+ protected int xp;
+ protected final Player player;
+ protected Location loc;
+ protected boolean hasTelekinesis = false;
+ protected ItemStack item;
+
+ /**
+ * Create a DropQueue linked to player
+ *
+ * @param player The player
+ */
+ public InternalDropQueue(Player player) {
+ this.items = new ArrayList<>();
+ this.xp = 0;
+ this.player = player;
+ this.loc = player.getLocation();
+ this.item = player.getInventory().getItemInMainHand();
+ }
+
+ /**
+ * Add item to queue
+ *
+ * @param item The item to add
+ *
+ * @return The DropQueue
+ */
+ @Override
+ public AbstractDropQueue addItem(ItemStack item) {
+ this.items.add(item);
+ return this;
+ }
+
+ /**
+ * Add multiple items to queue
+ *
+ * @param itemStacks The items to add
+ *
+ * @return The DropQueue
+ */
+ @Override
+ public AbstractDropQueue addItems(Collection itemStacks) {
+ this.items.addAll(itemStacks);
+ return this;
+ }
+
+ /**
+ * Add xp to queue
+ *
+ * @param amount The amount to add
+ *
+ * @return The DropQueue
+ */
+ @Override
+ public AbstractDropQueue addXP(int amount) {
+ this.xp += amount;
+ return this;
+ }
+
+ /**
+ * Set location of the origin of the drops
+ *
+ * @param l The location
+ *
+ * @return The DropQueue
+ */
+ @Override
+ public AbstractDropQueue setLocation(Location l) {
+ this.loc = l;
+ return this;
+ }
+
+ /**
+ * Force the queue to act as if player has a telekinetic item
+ *
+ * @return The DropQueue
+ */
+ @Override
+ public AbstractDropQueue forceTelekinesis() {
+ this.hasTelekinesis = true;
+ return this;
+ }
+
+ /**
+ * Set the queue to test specific item for telekinesis
+ * Default item is the player's held item, however for this is required for Tridents.
+ *
+ * @param item The item to test
+ *
+ * @return The DropQueue
+ */
+ @Override
+ public AbstractDropQueue setItem(ItemStack item) {
+ this.item = item;
+ return this;
+ }
+
+ /**
+ * Push the queue
+ */
+ public void push() {
+ if(!hasTelekinesis) hasTelekinesis = TelekineticTests.testPlayer(player);
+
+ World world = loc.getWorld();
+ assert world != null;
+ loc = loc.add(0.5, 0.5, 0.5);
+
+ if(hasTelekinesis) {
+ HashMap leftover = player.getInventory().addItem(items.toArray(new ItemStack[0]));
+ for(ItemStack drop : leftover.values()) {
+ world.dropItem(loc, drop).setVelocity(new Vector());
+ }
+ if (xp > 0) {
+ PlayerExpChangeEvent event = new PlayerExpChangeEvent(player, xp);
+ Bukkit.getPluginManager().callEvent(event);
+ ExperienceOrb orb = (ExperienceOrb) world.spawnEntity(player.getLocation().add(0, 0.2, 0), EntityType.EXPERIENCE_ORB);
+ orb.setVelocity(new Vector(0, 0, 0));
+ orb.setExperience(event.getAmount());
+ }
+ } else {
+ for (ItemStack drop : items) {
+ world.dropItem(loc, drop).setVelocity(new Vector());
+ }
+ if (xp > 0) {
+ ExperienceOrb orb = (ExperienceOrb) world.spawnEntity(loc, EntityType.EXPERIENCE_ORB);
+ orb.setExperience(xp);
+ }
+ }
+ }
+}
diff --git a/eco-util/src/main/java/com/willfp/eco/util/drops/telekinesis/TelekineticTests.java b/eco-util/src/main/java/com/willfp/eco/util/drops/telekinesis/TelekineticTests.java
new file mode 100644
index 00000000..175239b1
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/drops/telekinesis/TelekineticTests.java
@@ -0,0 +1,23 @@
+package com.willfp.eco.util.drops.telekinesis;
+
+import com.willfp.eco.util.lambda.ObjectBiCallable;
+import org.bukkit.entity.Player;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class TelekineticTests {
+ private static final Set> tests = new HashSet<>();
+
+ public static void registerTest(ObjectBiCallable test) {
+ tests.add(test);
+ }
+
+ public static boolean testPlayer(Player player) {
+ for (ObjectBiCallable test : tests) {
+ if(test.call(player)) return true;
+ }
+
+ return false;
+ }
+}
diff --git a/eco-util/src/main/java/com/willfp/eco/util/events/armorequip/ArmorEquipEvent.java b/eco-util/src/main/java/com/willfp/eco/util/events/armorequip/ArmorEquipEvent.java
new file mode 100644
index 00000000..3f8f7d4f
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/events/armorequip/ArmorEquipEvent.java
@@ -0,0 +1,124 @@
+package com.willfp.eco.util.events.armorequip;
+
+
+import org.bukkit.entity.Player;
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.player.PlayerEvent;
+import org.bukkit.inventory.ItemStack;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Arnah
+ * @since Jul 30, 2015
+ */
+public class ArmorEquipEvent extends PlayerEvent implements Cancellable {
+
+ private static final HandlerList handlers = new HandlerList();
+ private boolean cancel = false;
+ private final EquipMethod equipType;
+ private final ArmorType type;
+ private ItemStack oldArmorPiece, newArmorPiece;
+
+ public ArmorEquipEvent(final Player player, final EquipMethod equipType, final ArmorType type, final ItemStack oldArmorPiece, final ItemStack newArmorPiece) {
+ super(player);
+ this.equipType = equipType;
+ this.type = type;
+ this.oldArmorPiece = oldArmorPiece;
+ this.newArmorPiece = newArmorPiece;
+ }
+
+ /**
+ * Gets a list of handlers handling this event.
+ *
+ * @return A list of handlers handling this event.
+ */
+
+ @Override
+ public @NotNull HandlerList getHandlers() {
+ return handlers;
+ }
+
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ /**
+ * Sets if this event should be cancelled.
+ *
+ * @param cancel If this event should be cancelled.
+ */
+ public final void setCancelled(final boolean cancel) {
+ this.cancel = cancel;
+ }
+
+ /**
+ * Gets if this event is cancelled.
+ *
+ * @return If this event is cancelled
+ */
+ public final boolean isCancelled() {
+ return cancel;
+ }
+
+ public final ArmorType getType() {
+ return type;
+ }
+
+ public final ItemStack getOldArmorPiece() {
+ return oldArmorPiece;
+ }
+
+ public final void setOldArmorPiece(final ItemStack oldArmorPiece) {
+ this.oldArmorPiece = oldArmorPiece;
+ }
+
+ public final ItemStack getNewArmorPiece() {
+ return newArmorPiece;
+ }
+
+ public final void setNewArmorPiece(final ItemStack newArmorPiece) {
+ this.newArmorPiece = newArmorPiece;
+ }
+
+ public EquipMethod getMethod() {
+ return equipType;
+ }
+
+ public enum EquipMethod {// These have got to be the worst documentations ever.
+ /**
+ * When you shift click an armor piece to equip or unequip
+ */
+ SHIFT_CLICK,
+ /**
+ * When you drag and drop the item to equip or unequip
+ */
+ DRAG,
+ /**
+ * When you manually equip or unequip the item. Use to be DRAG
+ */
+ PICK_DROP,
+ /**
+ * When you right click an armor piece in the hotbar without the inventory open to equip.
+ */
+ HOTBAR,
+ /**
+ * When you press the hotbar slot number while hovering over the armor slot to equip or unequip
+ */
+ HOTBAR_SWAP,
+ /**
+ * When in range of a dispenser that shoots an armor piece to equip.
+ * Requires the spigot version to have {@link org.bukkit.event.block.BlockDispenseArmorEvent} implemented.
+ */
+ DISPENSER,
+ /**
+ * When an armor piece is removed due to it losing all durability.
+ */
+ BROKE,
+ /**
+ * When you die causing all armor to unequip
+ */
+ DEATH,
+ ;
+ }
+}
\ No newline at end of file
diff --git a/eco-util/src/main/java/com/willfp/eco/util/events/armorequip/ArmorListener.java b/eco-util/src/main/java/com/willfp/eco/util/events/armorequip/ArmorListener.java
new file mode 100644
index 00000000..f52bf0f5
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/events/armorequip/ArmorListener.java
@@ -0,0 +1,206 @@
+package com.willfp.eco.util.events.armorequip;
+
+import org.bukkit.Bukkit;
+import org.bukkit.Material;
+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.bukkit.event.block.Action;
+import org.bukkit.event.entity.PlayerDeathEvent;
+import org.bukkit.event.inventory.ClickType;
+import org.bukkit.event.inventory.InventoryAction;
+import org.bukkit.event.inventory.InventoryClickEvent;
+import org.bukkit.event.inventory.InventoryDragEvent;
+import org.bukkit.event.inventory.InventoryType;
+import org.bukkit.event.inventory.InventoryType.SlotType;
+import org.bukkit.event.player.PlayerInteractEvent;
+import org.bukkit.event.player.PlayerItemBreakEvent;
+import org.bukkit.event.player.PlayerJoinEvent;
+import org.bukkit.event.player.PlayerRespawnEvent;
+import org.bukkit.inventory.ItemStack;
+
+import static com.willfp.eco.util.events.armorequip.ArmorEquipEvent.EquipMethod;
+
+/**
+ * @author Arnah
+ * @since Jul 30, 2015
+ */
+@SuppressWarnings("deprecation")
+public class ArmorListener implements Listener {
+ //Event Priority is highest because other plugins might cancel the events before we check.
+
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
+ public final void inventoryClick(final InventoryClickEvent e) {
+ boolean shift = false, numberkey = false;
+ if (e.isCancelled()) return;
+ if (e.getAction() == InventoryAction.NOTHING) return;// Why does this get called if nothing happens??
+ if (e.getClick().equals(ClickType.SHIFT_LEFT) || e.getClick().equals(ClickType.SHIFT_RIGHT)) {
+ shift = true;
+ }
+ if (e.getClick().equals(ClickType.NUMBER_KEY)) {
+ numberkey = true;
+ }
+ if (e.getSlotType() != SlotType.ARMOR && e.getSlotType() != SlotType.QUICKBAR && e.getSlotType() != SlotType.CONTAINER)
+ return;
+ if (e.getClickedInventory() != null && !e.getClickedInventory().getType().equals(InventoryType.PLAYER)) return;
+ if (!e.getInventory().getType().equals(InventoryType.CRAFTING) && !e.getInventory().getType().equals(InventoryType.PLAYER))
+ return;
+ if (!(e.getWhoClicked() instanceof Player)) return;
+ ArmorType newArmorType = ArmorType.matchType(shift ? e.getCurrentItem() : e.getCursor());
+ if (!shift && newArmorType != null && e.getRawSlot() != newArmorType.getSlot()) {
+ // Used for drag and drop checking to make sure you aren't trying to place a helmet in the boots slot.
+ return;
+ }
+ if (shift) {
+ newArmorType = ArmorType.matchType(e.getCurrentItem());
+ if (newArmorType != null) {
+ boolean equipping = true;
+ if (e.getRawSlot() == newArmorType.getSlot()) {
+ equipping = false;
+ }
+ if (newArmorType.equals(ArmorType.HELMET) && (equipping == isAirOrNull(e.getWhoClicked().getInventory().getHelmet())) || newArmorType.equals(ArmorType.CHESTPLATE) && (equipping == isAirOrNull(e.getWhoClicked().getInventory().getChestplate())) || newArmorType.equals(ArmorType.LEGGINGS) && (equipping == isAirOrNull(e.getWhoClicked().getInventory().getLeggings())) || newArmorType.equals(ArmorType.BOOTS) && (equipping == isAirOrNull(e.getWhoClicked().getInventory().getBoots()))) {
+ ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent((Player) e.getWhoClicked(), EquipMethod.SHIFT_CLICK, newArmorType, equipping ? null : e.getCurrentItem(), equipping ? e.getCurrentItem() : null);
+ Bukkit.getPluginManager().callEvent(armorEquipEvent);
+ if (armorEquipEvent.isCancelled()) {
+ e.setCancelled(true);
+ }
+ }
+ }
+ } else {
+ ItemStack newArmorPiece = e.getCursor();
+ ItemStack oldArmorPiece = e.getCurrentItem();
+ if (numberkey) {
+ if (e.getClickedInventory().getType().equals(InventoryType.PLAYER)) {// Prevents shit in the 2by2 crafting
+ // e.getClickedInventory() == The players inventory
+ // e.getHotBarButton() == key people are pressing to equip or unequip the item to or from.
+ // e.getRawSlot() == The slot the item is going to.
+ // e.getSlot() == Armor slot, can't use e.getRawSlot() as that gives a hotbar slot ;-;
+ ItemStack hotbarItem = e.getClickedInventory().getItem(e.getHotbarButton());
+ if (!isAirOrNull(hotbarItem)) {// Equipping
+ newArmorType = ArmorType.matchType(hotbarItem);
+ newArmorPiece = hotbarItem;
+ oldArmorPiece = e.getClickedInventory().getItem(e.getSlot());
+ } else {// Unequipping
+ newArmorType = ArmorType.matchType(!isAirOrNull(e.getCurrentItem()) ? e.getCurrentItem() : e.getCursor());
+ }
+ }
+ } else {
+ if (isAirOrNull(e.getCursor()) && !isAirOrNull(e.getCurrentItem())) {// unequip with no new item going into the slot.
+ newArmorType = ArmorType.matchType(e.getCurrentItem());
+ }
+ // e.getCurrentItem() == Unequip
+ // e.getCursor() == Equip
+ // newArmorType = ArmorType.matchType(!isAirOrNull(e.getCurrentItem()) ? e.getCurrentItem() : e.getCursor());
+ }
+ if (newArmorType != null && e.getRawSlot() == newArmorType.getSlot()) {
+ ArmorEquipEvent.EquipMethod method = ArmorEquipEvent.EquipMethod.PICK_DROP;
+ if (e.getAction().equals(InventoryAction.HOTBAR_SWAP) || numberkey) method = ArmorEquipEvent.EquipMethod.HOTBAR_SWAP;
+ ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent((Player) e.getWhoClicked(), method, newArmorType, oldArmorPiece, newArmorPiece);
+ Bukkit.getPluginManager().callEvent(armorEquipEvent);
+ if (armorEquipEvent.isCancelled()) {
+ e.setCancelled(true);
+ }
+ }
+ }
+ }
+
+ @EventHandler(priority = EventPriority.HIGHEST)
+ public void playerInteractEvent(PlayerInteractEvent e) {
+ if (e.useItemInHand().equals(Result.DENY)) return;
+ //
+ if (e.getAction() == Action.PHYSICAL) return;
+ if (e.getAction() == Action.RIGHT_CLICK_AIR || e.getAction() == Action.RIGHT_CLICK_BLOCK) {
+ Player player = e.getPlayer();
+ if (!e.useInteractedBlock().equals(Result.DENY)) {
+ if (e.getClickedBlock() != null && e.getAction() == Action.RIGHT_CLICK_BLOCK && !player.isSneaking()) {// Having both of these checks is useless, might as well do it though.
+ // Some blocks have actions when you right click them which stops the client from equipping the armor in hand.
+ Material mat = e.getClickedBlock().getType();
+ }
+ }
+ ArmorType newArmorType = ArmorType.matchType(e.getItem());
+ if (newArmorType != null) {
+ if (newArmorType.equals(ArmorType.HELMET) && isAirOrNull(e.getPlayer().getInventory().getHelmet()) || newArmorType.equals(ArmorType.CHESTPLATE) && isAirOrNull(e.getPlayer().getInventory().getChestplate()) || newArmorType.equals(ArmorType.LEGGINGS) && isAirOrNull(e.getPlayer().getInventory().getLeggings()) || newArmorType.equals(ArmorType.BOOTS) && isAirOrNull(e.getPlayer().getInventory().getBoots())) {
+ ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent(e.getPlayer(), ArmorEquipEvent.EquipMethod.HOTBAR, ArmorType.matchType(e.getItem()), null, e.getItem());
+ Bukkit.getPluginManager().callEvent(armorEquipEvent);
+ if (armorEquipEvent.isCancelled()) {
+ e.setCancelled(true);
+ player.updateInventory();
+ }
+ }
+ }
+ }
+ }
+
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
+ public void inventoryDrag(InventoryDragEvent event) {
+ // getType() seems to always be even.
+ // Old Cursor gives the item you are equipping
+ // Raw slot is the ArmorType slot
+ // Can't replace armor using this method making getCursor() useless.
+ ArmorType type = ArmorType.matchType(event.getOldCursor());
+ if (event.getRawSlots().isEmpty()) return;// Idk if this will ever happen
+ if (type != null && type.getSlot() == event.getRawSlots().stream().findFirst().orElse(0)) {
+ ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent((Player) event.getWhoClicked(), EquipMethod.DRAG, type, null, event.getOldCursor());
+ Bukkit.getPluginManager().callEvent(armorEquipEvent);
+ if (armorEquipEvent.isCancelled()) {
+ event.setResult(Result.DENY);
+ event.setCancelled(true);
+ }
+ }
+ // Debug shit
+ }
+
+ @EventHandler
+ public void playerJoinEvent(PlayerJoinEvent e) {
+ ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent(e.getPlayer(), null, null, null, null);
+ Bukkit.getPluginManager().callEvent(armorEquipEvent);
+ }
+
+ @EventHandler
+ public void playerRespawnEvent(PlayerRespawnEvent e) {
+ ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent(e.getPlayer(), null, null, null, null);
+ Bukkit.getPluginManager().callEvent(armorEquipEvent);
+ }
+
+ @EventHandler
+ public void itemBreakEvent(PlayerItemBreakEvent e) {
+ ArmorType type = ArmorType.matchType(e.getBrokenItem());
+ if (type != null) {
+ Player p = e.getPlayer();
+ ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent(p, EquipMethod.BROKE, type, e.getBrokenItem(), null);
+ Bukkit.getPluginManager().callEvent(armorEquipEvent);
+ if (armorEquipEvent.isCancelled()) {
+ ItemStack i = e.getBrokenItem().clone();
+ i.setAmount(1);
+ i.setDurability((short) (i.getDurability() - 1));
+ if (type.equals(ArmorType.HELMET)) {
+ p.getInventory().setHelmet(i);
+ } else if (type.equals(ArmorType.CHESTPLATE)) {
+ p.getInventory().setChestplate(i);
+ } else if (type.equals(ArmorType.LEGGINGS)) {
+ p.getInventory().setLeggings(i);
+ } else if (type.equals(ArmorType.BOOTS)) {
+ p.getInventory().setBoots(i);
+ }
+ }
+ }
+ }
+
+ @EventHandler
+ public void playerDeathEvent(PlayerDeathEvent e) {
+ Player p = e.getEntity();
+ if (e.getKeepInventory()) return;
+ for (ItemStack i : p.getInventory().getArmorContents()) {
+ if (!isAirOrNull(i)) {
+ Bukkit.getPluginManager().callEvent(new ArmorEquipEvent(p, EquipMethod.DEATH, ArmorType.matchType(i), i, null));
+ // No way to cancel a death event.
+ }
+ }
+ }
+
+ public static boolean isAirOrNull(ItemStack item) {
+ return item == null || item.getType().equals(Material.AIR);
+ }
+}
\ No newline at end of file
diff --git a/eco-util/src/main/java/com/willfp/eco/util/events/armorequip/ArmorType.java b/eco-util/src/main/java/com/willfp/eco/util/events/armorequip/ArmorType.java
new file mode 100644
index 00000000..a4c889d3
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/events/armorequip/ArmorType.java
@@ -0,0 +1,38 @@
+package com.willfp.eco.util.events.armorequip;
+
+import org.bukkit.inventory.ItemStack;
+
+/**
+ * @author Arnah
+ * @since Jul 30, 2015
+ */
+public enum ArmorType {
+ HELMET(5), CHESTPLATE(6), LEGGINGS(7), BOOTS(8);
+
+ private final int slot;
+
+ ArmorType(int slot) {
+ this.slot = slot;
+ }
+
+ /**
+ * Attempts to match the ArmorType for the specified ItemStack.
+ *
+ * @param itemStack The ItemStack to parse the type of.
+ *
+ * @return The parsed ArmorType, or null if not found.
+ */
+ public static ArmorType matchType(final ItemStack itemStack) {
+ if (ArmorListener.isAirOrNull(itemStack)) return null;
+ String type = itemStack.getType().name();
+ if (type.endsWith("_HELMET") || type.endsWith("_SKULL") || type.endsWith("PLAYER_HEAD")) return HELMET;
+ else if (type.endsWith("_CHESTPLATE") || type.endsWith("ELYTRA")) return CHESTPLATE;
+ else if (type.endsWith("_LEGGINGS")) return LEGGINGS;
+ else if (type.endsWith("_BOOTS")) return BOOTS;
+ else return null;
+ }
+
+ public int getSlot() {
+ return slot;
+ }
+}
\ No newline at end of file
diff --git a/eco-util/src/main/java/com/willfp/eco/util/events/armorequip/DispenserArmorListener.java b/eco-util/src/main/java/com/willfp/eco/util/events/armorequip/DispenserArmorListener.java
new file mode 100644
index 00000000..0cd0797b
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/events/armorequip/DispenserArmorListener.java
@@ -0,0 +1,28 @@
+package com.willfp.eco.util.events.armorequip;
+
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.block.BlockDispenseArmorEvent;
+
+/**
+ * @author Arnah
+ * @since Feb 08, 2019
+ */
+public class DispenserArmorListener implements Listener {
+ @EventHandler
+ public void dispenseArmorEvent(BlockDispenseArmorEvent event) {
+ ArmorType type = ArmorType.matchType(event.getItem());
+ if (type != null) {
+ if (event.getTargetEntity() instanceof Player) {
+ Player p = (Player) event.getTargetEntity();
+ ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent(p, ArmorEquipEvent.EquipMethod.DISPENSER, type, null, event.getItem());
+ Bukkit.getPluginManager().callEvent(armorEquipEvent);
+ if (armorEquipEvent.isCancelled()) {
+ event.setCancelled(true);
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/eco-util/src/main/java/com/willfp/eco/util/events/entitydeathbyentity/EntityDeathByEntityBuilder.java b/eco-util/src/main/java/com/willfp/eco/util/events/entitydeathbyentity/EntityDeathByEntityBuilder.java
new file mode 100644
index 00000000..90283225
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/events/entitydeathbyentity/EntityDeathByEntityBuilder.java
@@ -0,0 +1,58 @@
+package com.willfp.eco.util.events.entitydeathbyentity;
+
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.event.entity.EntityDeathEvent;
+import org.bukkit.inventory.ItemStack;
+
+import java.util.List;
+
+class EntityDeathByEntityBuilder {
+ private LivingEntity victim = null;
+ private Entity damager;
+ private EntityDeathEvent deathEvent;
+
+ private List drops;
+ private int xp = 0;
+ private boolean dropItems;
+
+ public EntityDeathByEntityBuilder() {
+
+ }
+
+ public LivingEntity getVictim() {
+ return this.victim;
+ }
+
+ public void setDeathEvent(EntityDeathEvent deathEvent) {
+ this.deathEvent = deathEvent;
+ }
+
+ public void setVictim(LivingEntity victim) {
+ this.victim = victim;
+ }
+
+ public void setDamager(Entity damager) {
+ this.damager = damager;
+ }
+
+ public void setDrops(List drops) {
+ this.drops = drops;
+ }
+
+ public void setXp(int xp) {
+ this.xp = xp;
+ }
+
+ public void push() {
+ if (this.victim == null) return;
+ if (this.damager == null) return;
+ if (this.drops == null) return;
+ if (this.deathEvent == null) return;
+
+ EntityDeathByEntityEvent event = new EntityDeathByEntityEvent(victim, damager, drops, xp, deathEvent);
+
+ Bukkit.getPluginManager().callEvent(event);
+ }
+}
diff --git a/eco-util/src/main/java/com/willfp/eco/util/events/entitydeathbyentity/EntityDeathByEntityEvent.java b/eco-util/src/main/java/com/willfp/eco/util/events/entitydeathbyentity/EntityDeathByEntityEvent.java
new file mode 100644
index 00000000..2f320d47
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/events/entitydeathbyentity/EntityDeathByEntityEvent.java
@@ -0,0 +1,115 @@
+package com.willfp.eco.util.events.entitydeathbyentity;
+
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.entity.EntityDeathEvent;
+import org.bukkit.inventory.ItemStack;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+/**
+ * Event triggered when entity is killed by entity.
+ */
+public class EntityDeathByEntityEvent extends Event {
+ private static final HandlerList HANDLERS = new HandlerList();
+
+ /**
+ * The {@link LivingEntity} killed
+ */
+ private final LivingEntity victim;
+
+ /**
+ * The {@link Entity} that killed;
+ */
+ private final Entity damager;
+
+ /**
+ * The associated {@link EntityDeathEvent}
+ */
+ private final EntityDeathEvent deathEvent;
+
+ /**
+ * The entity drops
+ */
+ private final List drops;
+
+ /**
+ * The xp to drop
+ */
+ private final int xp;
+
+ /**
+ * Create event based off parameters
+ *
+ * @param victim The killed entity
+ * @param damager The killer
+ * @param drops The item drops
+ * @param xp The amount of xp to drop
+ * @param deathEvent The associated {@link EntityDeathEvent}
+ */
+ public EntityDeathByEntityEvent(@NotNull LivingEntity victim, @NotNull Entity damager, @NotNull List drops, int xp, @NotNull EntityDeathEvent deathEvent) {
+ this.victim = victim;
+ this.damager = damager;
+ this.drops = drops;
+ this.xp = xp;
+ this.deathEvent = deathEvent;
+ }
+
+ /**
+ * Get victim
+ *
+ * @return The victim
+ */
+ public LivingEntity getVictim() {
+ return this.victim;
+ }
+
+ /**
+ * Get killer
+ *
+ * @return The killer
+ */
+ public Entity getKiller() {
+ return this.damager;
+ }
+
+ /**
+ * Get xp amount
+ *
+ * @return The xp
+ */
+ public int getDroppedExp() {
+ return this.xp;
+ }
+
+ /**
+ * Get drops
+ *
+ * @return {@link List} of drops
+ */
+ public List getDrops() {
+ return this.drops;
+ }
+
+ /**
+ * Get associated {@link EntityDeathEvent}
+ * Use this to modify event parameters.
+ *
+ * @return The associated {@link EntityDeathEvent}
+ */
+ public EntityDeathEvent getDeathEvent() {
+ return this.deathEvent;
+ }
+
+ @Override
+ public @NotNull HandlerList getHandlers() {
+ return HANDLERS;
+ }
+
+ public static HandlerList getHandlerList() {
+ return HANDLERS;
+ }
+}
diff --git a/eco-util/src/main/java/com/willfp/eco/util/events/entitydeathbyentity/EntityDeathByEntityListeners.java b/eco-util/src/main/java/com/willfp/eco/util/events/entitydeathbyentity/EntityDeathByEntityListeners.java
new file mode 100644
index 00000000..8590bb05
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/events/entitydeathbyentity/EntityDeathByEntityListeners.java
@@ -0,0 +1,73 @@
+package com.willfp.eco.util.events.entitydeathbyentity;
+
+import com.willfp.eco.util.injection.PluginDependent;
+import com.willfp.eco.util.plugin.AbstractEcoPlugin;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.event.entity.EntityDamageByEntityEvent;
+import org.bukkit.event.entity.EntityDeathEvent;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.scheduler.BukkitRunnable;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
+
+public class EntityDeathByEntityListeners extends PluginDependent implements Listener {
+ final Set events = new HashSet<>();
+
+ public EntityDeathByEntityListeners(AbstractEcoPlugin plugin) {
+ super(plugin);
+ }
+
+ @EventHandler(priority = EventPriority.HIGH)
+ public void onEntityDamage(EntityDamageByEntityEvent event) {
+ if (!(event.getEntity() instanceof LivingEntity)) return;
+
+ LivingEntity victim = (LivingEntity) event.getEntity();
+
+ if (victim.getHealth() > event.getFinalDamage()) return;
+
+ EntityDeathByEntityBuilder builtEvent = new EntityDeathByEntityBuilder();
+ builtEvent.setVictim(victim);
+ builtEvent.setDamager(event.getDamager());
+ events.add(builtEvent);
+
+ new BukkitRunnable() {
+ @Override
+ public void run() {
+ events.remove(builtEvent);
+ }
+ }.runTaskLater(this.plugin, 1);
+ }
+
+ @EventHandler
+ public void onEntityDeath(EntityDeathEvent event) {
+ LivingEntity victim = event.getEntity();
+
+ List drops = event.getDrops();
+ int xp = event.getDroppedExp();
+
+ AtomicReference atomicBuiltEvent = new AtomicReference<>(null);
+ EntityDeathByEntityBuilder builtEvent;
+
+ events.forEach((deathByEntityEvent) -> {
+ if (deathByEntityEvent.getVictim().equals(victim)) {
+ atomicBuiltEvent.set(deathByEntityEvent);
+ }
+ });
+
+ if (atomicBuiltEvent.get() == null) return;
+
+ builtEvent = atomicBuiltEvent.get();
+ events.remove(builtEvent);
+ builtEvent.setDrops(drops);
+ builtEvent.setXp(xp);
+ builtEvent.setDeathEvent(event);
+
+ builtEvent.push();
+ }
+}
diff --git a/eco-util/src/main/java/com/willfp/eco/util/events/naturalexpgainevent/NaturalExpGainBuilder.java b/eco-util/src/main/java/com/willfp/eco/util/events/naturalexpgainevent/NaturalExpGainBuilder.java
new file mode 100644
index 00000000..344602c3
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/events/naturalexpgainevent/NaturalExpGainBuilder.java
@@ -0,0 +1,56 @@
+package com.willfp.eco.util.events.naturalexpgainevent;
+
+import org.bukkit.Bukkit;
+import org.bukkit.Location;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.event.player.PlayerExpChangeEvent;
+
+class NaturalExpGainBuilder {
+ private final LivingEntity victim = null;
+ private boolean cancelled = false;
+ private PlayerExpChangeEvent event;
+ private Location loc;
+ private BuildReason reason;
+
+ public NaturalExpGainBuilder(BuildReason reason) {
+ this.reason = reason;
+ }
+
+ public LivingEntity getVictim() {
+ return this.victim;
+ }
+
+ public void setEvent(PlayerExpChangeEvent event) {
+ this.event = event;
+ }
+
+ public void setCancelled(boolean cancel) {
+ this.cancelled = cancel;
+ }
+
+ public void setLoc(Location location) {
+ this.loc = location;
+ }
+
+ public Location getLoc() {
+ return this.loc;
+ }
+
+ public BuildReason getReason() {
+ return reason;
+ }
+
+ public void push() {
+ if (this.event == null) return;
+ if (this.cancelled) return;
+
+ NaturalExpGainEvent naturalExpGainEvent = new NaturalExpGainEvent(event);
+
+ Bukkit.getPluginManager().callEvent(naturalExpGainEvent);
+ }
+
+ public enum BuildReason {
+ BOTTLE,
+ PLAYER
+ }
+}
diff --git a/eco-util/src/main/java/com/willfp/eco/util/events/naturalexpgainevent/NaturalExpGainEvent.java b/eco-util/src/main/java/com/willfp/eco/util/events/naturalexpgainevent/NaturalExpGainEvent.java
new file mode 100644
index 00000000..f2e62905
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/events/naturalexpgainevent/NaturalExpGainEvent.java
@@ -0,0 +1,46 @@
+package com.willfp.eco.util.events.naturalexpgainevent;
+
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.player.PlayerExpChangeEvent;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Event triggered when player receives experience not from bottle
+ */
+public class NaturalExpGainEvent extends Event {
+ private static final HandlerList HANDLERS = new HandlerList();
+
+ /**
+ * The associated {@link PlayerExpChangeEvent}
+ */
+ private final PlayerExpChangeEvent event;
+
+ /**
+ * Create event based off parameters
+ *
+ * @param event The associate PlayerExpChangeEvent
+ */
+ public NaturalExpGainEvent(@NotNull PlayerExpChangeEvent event) {
+ this.event = event;
+ }
+
+ /**
+ * Get associated {@link PlayerExpChangeEvent}
+ * Use this to modify event parameters.
+ *
+ * @return The associated {@link PlayerExpChangeEvent}
+ */
+ public PlayerExpChangeEvent getExpChangeEvent() {
+ return this.event;
+ }
+
+ @Override
+ public @NotNull HandlerList getHandlers() {
+ return HANDLERS;
+ }
+
+ public static HandlerList getHandlerList() {
+ return HANDLERS;
+ }
+}
diff --git a/eco-util/src/main/java/com/willfp/eco/util/events/naturalexpgainevent/NaturalExpGainListeners.java b/eco-util/src/main/java/com/willfp/eco/util/events/naturalexpgainevent/NaturalExpGainListeners.java
new file mode 100644
index 00000000..f4ac582d
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/events/naturalexpgainevent/NaturalExpGainListeners.java
@@ -0,0 +1,44 @@
+package com.willfp.eco.util.events.naturalexpgainevent;
+
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.entity.ExpBottleEvent;
+import org.bukkit.event.player.PlayerExpChangeEvent;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class NaturalExpGainListeners implements Listener {
+ private final Set events = new HashSet<>();
+
+ @EventHandler
+ public void playerChange(PlayerExpChangeEvent event) {
+ NaturalExpGainBuilder builder = new NaturalExpGainBuilder(NaturalExpGainBuilder.BuildReason.PLAYER);
+ builder.setEvent(event);
+
+ NaturalExpGainBuilder toRemove = null;
+ for (NaturalExpGainBuilder searchBuilder : events) {
+ if(!searchBuilder.getLoc().getWorld().equals(event.getPlayer().getLocation().getWorld())) continue;
+ if(searchBuilder.getReason().equals(NaturalExpGainBuilder.BuildReason.BOTTLE) && searchBuilder.getLoc().distanceSquared(event.getPlayer().getLocation()) > 52)
+ toRemove = searchBuilder;
+ }
+
+ if(toRemove != null) {
+ events.remove(toRemove);
+ return;
+ }
+
+ builder.setEvent(event);
+ builder.push();
+
+ events.remove(builder);
+ }
+
+ @EventHandler
+ public void onExpBottle(ExpBottleEvent event) {
+ NaturalExpGainBuilder builtEvent = new NaturalExpGainBuilder(NaturalExpGainBuilder.BuildReason.BOTTLE);
+ builtEvent.setLoc(event.getEntity().getLocation());
+
+ events.add(builtEvent);
+ }
+}
diff --git a/Plugin/src/main/java/com/willfp/ecoenchants/extensions/Extension.java b/eco-util/src/main/java/com/willfp/eco/util/extensions/Extension.java
similarity index 98%
rename from Plugin/src/main/java/com/willfp/ecoenchants/extensions/Extension.java
rename to eco-util/src/main/java/com/willfp/eco/util/extensions/Extension.java
index 7ed90289..73bc8ae8 100644
--- a/Plugin/src/main/java/com/willfp/ecoenchants/extensions/Extension.java
+++ b/eco-util/src/main/java/com/willfp/eco/util/extensions/Extension.java
@@ -1,4 +1,4 @@
-package com.willfp.ecoenchants.extensions;
+package com.willfp.eco.util.extensions;
import org.apache.commons.lang.Validate;
import org.jetbrains.annotations.ApiStatus;
diff --git a/Plugin/src/main/java/com/willfp/ecoenchants/extensions/MalformedExtensionException.java b/eco-util/src/main/java/com/willfp/eco/util/extensions/MalformedExtensionException.java
similarity index 89%
rename from Plugin/src/main/java/com/willfp/ecoenchants/extensions/MalformedExtensionException.java
rename to eco-util/src/main/java/com/willfp/eco/util/extensions/MalformedExtensionException.java
index 1f8e370e..7127c4f1 100644
--- a/Plugin/src/main/java/com/willfp/ecoenchants/extensions/MalformedExtensionException.java
+++ b/eco-util/src/main/java/com/willfp/eco/util/extensions/MalformedExtensionException.java
@@ -1,4 +1,4 @@
-package com.willfp.ecoenchants.extensions;
+package com.willfp.eco.util.extensions;
/**
* Called when the extension is made incorrectly
diff --git a/Plugin/src/main/java/com/willfp/ecoenchants/extensions/loader/EcoExtensionLoader.java b/eco-util/src/main/java/com/willfp/eco/util/extensions/loader/EcoExtensionLoader.java
similarity index 80%
rename from Plugin/src/main/java/com/willfp/ecoenchants/extensions/loader/EcoExtensionLoader.java
rename to eco-util/src/main/java/com/willfp/eco/util/extensions/loader/EcoExtensionLoader.java
index e066bfdc..9b3cb3e6 100644
--- a/Plugin/src/main/java/com/willfp/ecoenchants/extensions/loader/EcoExtensionLoader.java
+++ b/eco-util/src/main/java/com/willfp/eco/util/extensions/loader/EcoExtensionLoader.java
@@ -1,9 +1,10 @@
-package com.willfp.ecoenchants.extensions.loader;
+package com.willfp.eco.util.extensions.loader;
-import com.willfp.ecoenchants.EcoEnchantsPlugin;
-import com.willfp.ecoenchants.extensions.Extension;
-import com.willfp.ecoenchants.extensions.MalformedExtensionException;
-import com.willfp.ecoenchants.util.internal.Logger;
+
+import com.willfp.eco.util.extensions.Extension;
+import com.willfp.eco.util.extensions.MalformedExtensionException;
+import com.willfp.eco.util.injection.PluginDependent;
+import com.willfp.eco.util.plugin.AbstractEcoPlugin;
import org.bukkit.configuration.file.YamlConfiguration;
import java.io.File;
@@ -20,12 +21,16 @@ import java.util.Set;
/**
* Concrete implementation of {@link ExtensionLoader}
*/
-public class EcoExtensionLoader implements ExtensionLoader {
+public class EcoExtensionLoader extends PluginDependent implements ExtensionLoader {
private final Set extensions = new HashSet<>();
+ public EcoExtensionLoader(AbstractEcoPlugin plugin) {
+ super(plugin);
+ }
+
@Override
public void loadExtensions() {
- File dir = new File(EcoEnchantsPlugin.getInstance().getDataFolder(), "/extensions");
+ File dir = new File(this.plugin.getDataFolder(), "/extensions");
if (!dir.exists()) {
dir.mkdirs();
}
@@ -41,7 +46,7 @@ public class EcoExtensionLoader implements ExtensionLoader {
try {
loadExtension(extensionJar);
} catch (MalformedExtensionException e) {
- Logger.error(extensionJar.getName() + " caused MalformedExtensionException: " + e.getMessage());
+ plugin.getLog().error(extensionJar.getName() + " caused MalformedExtensionException: " + e.getMessage());
}
}
}
@@ -54,7 +59,7 @@ public class EcoExtensionLoader implements ExtensionLoader {
e.printStackTrace();
}
- ClassLoader cl = new URLClassLoader(new URL[]{url}, EcoEnchantsPlugin.class.getClassLoader());
+ ClassLoader cl = new URLClassLoader(new URL[]{url}, this.plugin.getClass().getClassLoader());
InputStream ymlIn = cl.getResourceAsStream("extension.yml");
diff --git a/Plugin/src/main/java/com/willfp/ecoenchants/extensions/loader/ExtensionLoader.java b/eco-util/src/main/java/com/willfp/eco/util/extensions/loader/ExtensionLoader.java
similarity index 85%
rename from Plugin/src/main/java/com/willfp/ecoenchants/extensions/loader/ExtensionLoader.java
rename to eco-util/src/main/java/com/willfp/eco/util/extensions/loader/ExtensionLoader.java
index fbfb7dbe..34f73da8 100644
--- a/Plugin/src/main/java/com/willfp/ecoenchants/extensions/loader/ExtensionLoader.java
+++ b/eco-util/src/main/java/com/willfp/eco/util/extensions/loader/ExtensionLoader.java
@@ -1,6 +1,6 @@
-package com.willfp.ecoenchants.extensions.loader;
+package com.willfp.eco.util.extensions.loader;
-import com.willfp.ecoenchants.extensions.Extension;
+import com.willfp.eco.util.extensions.Extension;
import java.util.Set;
diff --git a/eco-util/src/main/java/com/willfp/eco/util/factory/AbstractFactory.java b/eco-util/src/main/java/com/willfp/eco/util/factory/AbstractFactory.java
new file mode 100644
index 00000000..f58d7dee
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/factory/AbstractFactory.java
@@ -0,0 +1,4 @@
+package com.willfp.eco.util.factory;
+
+public interface AbstractFactory {
+}
diff --git a/eco-util/src/main/java/com/willfp/eco/util/factory/PluginDependentFactory.java b/eco-util/src/main/java/com/willfp/eco/util/factory/PluginDependentFactory.java
new file mode 100644
index 00000000..8872ce48
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/factory/PluginDependentFactory.java
@@ -0,0 +1,10 @@
+package com.willfp.eco.util.factory;
+
+import com.willfp.eco.util.injection.PluginDependent;
+import com.willfp.eco.util.plugin.AbstractEcoPlugin;
+
+public abstract class PluginDependentFactory extends PluginDependent implements AbstractFactory {
+ protected PluginDependentFactory(AbstractEcoPlugin plugin) {
+ super(plugin);
+ }
+}
diff --git a/eco-util/src/main/java/com/willfp/eco/util/injection/PluginDependent.java b/eco-util/src/main/java/com/willfp/eco/util/injection/PluginDependent.java
new file mode 100644
index 00000000..f8de5565
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/injection/PluginDependent.java
@@ -0,0 +1,11 @@
+package com.willfp.eco.util.injection;
+
+import com.willfp.eco.util.plugin.AbstractEcoPlugin;
+
+public abstract class PluginDependent {
+ protected final AbstractEcoPlugin plugin;
+
+ protected PluginDependent(AbstractEcoPlugin plugin) {
+ this.plugin = plugin;
+ }
+}
diff --git a/eco-util/src/main/java/com/willfp/eco/util/integrations/Integration.java b/eco-util/src/main/java/com/willfp/eco/util/integrations/Integration.java
new file mode 100644
index 00000000..f821a48c
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/integrations/Integration.java
@@ -0,0 +1,12 @@
+package com.willfp.eco.util.integrations;
+
+/**
+ * Interface for all integrations with optional dependencies
+ */
+public interface Integration {
+ /**
+ * Get the name of integration
+ * @return The name
+ */
+ String getPluginName();
+}
diff --git a/eco-util/src/main/java/com/willfp/eco/util/integrations/placeholder/PlaceholderEntry.java b/eco-util/src/main/java/com/willfp/eco/util/integrations/placeholder/PlaceholderEntry.java
new file mode 100644
index 00000000..2a3543c1
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/integrations/placeholder/PlaceholderEntry.java
@@ -0,0 +1,65 @@
+package com.willfp.eco.util.integrations.placeholder;
+
+import com.willfp.eco.util.lambda.ObjectBiCallable;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * A placeholder entry consists of an identifier and an {@link ObjectBiCallable} to fetch the result
+ */
+public class PlaceholderEntry {
+ private final String identifier;
+ private final ObjectBiCallable function;
+ private final boolean requiresPlayer;
+
+ /**
+ * Create a placeholder entry that doesn't require a player
+ *
+ * @param identifier The identifier of the placeholder
+ * @param function A lambda to get the result of the placeholder
+ */
+ public PlaceholderEntry(String identifier, ObjectBiCallable function) {
+ this(identifier, function, false);
+ }
+
+ /**
+ * Create a placeholder entry that may require a player
+ *
+ * @param identifier The identifier of the placeholder
+ * @param function A lambda to get the result of the placeholder
+ * @param requiresPlayer If the placeholder requires a player
+ */
+ public PlaceholderEntry(String identifier, ObjectBiCallable function, boolean requiresPlayer) {
+ this.identifier = identifier;
+ this.function = function;
+ this.requiresPlayer = requiresPlayer;
+ }
+
+ /**
+ * Get the identifier of the placeholder
+ *
+ * @return The identifier
+ */
+ public String getIdentifier() {
+ return this.identifier;
+ }
+
+ /**
+ * Get the result of the placeholder with respect to a player
+ *
+ * @param player The player to translate with respect to
+ * @return The result of the placeholder
+ */
+ public String getResult(@Nullable Player player) {
+ return this.function.call(player);
+ }
+
+ /**
+ * Get if the placeholder requires a player to get a result
+ *
+ * @return If the placeholder requires a player
+ */
+ public boolean requiresPlayer() {
+ return requiresPlayer;
+ }
+}
diff --git a/eco-util/src/main/java/com/willfp/eco/util/integrations/placeholder/PlaceholderIntegration.java b/eco-util/src/main/java/com/willfp/eco/util/integrations/placeholder/PlaceholderIntegration.java
new file mode 100644
index 00000000..d69cae9b
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/integrations/placeholder/PlaceholderIntegration.java
@@ -0,0 +1,24 @@
+package com.willfp.eco.util.integrations.placeholder;
+
+import com.willfp.eco.util.integrations.Integration;
+import org.bukkit.entity.Player;
+
+/**
+ * Interface for Placeholder integrations
+ */
+public interface PlaceholderIntegration extends Integration {
+ /**
+ * Register the integration with the specified plugin
+ * Not to be confused with internal registration in {@link PlaceholderManager#addIntegration(PlaceholderIntegration)}
+ */
+ void registerIntegration();
+
+ /**
+ * Translate all the placeholders in a string with respect to a player
+ *
+ * @param text The text to translate
+ * @param player The player to translate with respect to
+ * @return The string, translated
+ */
+ String translate(String text, Player player);
+}
diff --git a/eco-util/src/main/java/com/willfp/eco/util/integrations/placeholder/PlaceholderManager.java b/eco-util/src/main/java/com/willfp/eco/util/integrations/placeholder/PlaceholderManager.java
new file mode 100644
index 00000000..ac25df36
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/integrations/placeholder/PlaceholderManager.java
@@ -0,0 +1,67 @@
+package com.willfp.eco.util.integrations.placeholder;
+
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.HashSet;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * Utility class for placeholders
+ */
+public class PlaceholderManager {
+ private static final Set placeholders = new HashSet<>();
+ private static final Set integrations = new HashSet<>();
+
+ /**
+ * Register a new placeholder integration
+ *
+ * @param integration The {@link PlaceholderIntegration} to register
+ */
+ public static void addIntegration(PlaceholderIntegration integration) {
+ integration.registerIntegration();
+ integrations.add(integration);
+ }
+
+ /**
+ * Register a placeholder
+ *
+ * @param expansion The {@link PlaceholderEntry} to register
+ */
+ public static void registerPlaceholder(PlaceholderEntry expansion) {
+ placeholders.removeIf(placeholderEntry -> placeholderEntry.getIdentifier().equalsIgnoreCase(expansion.getIdentifier()));
+ placeholders.add(expansion);
+ }
+
+ /**
+ * Get the result of a placeholder with respect to a player
+ *
+ * @param player The player to get the result from
+ * @param identifier The placeholder identifier
+ * @return The value of the placeholder
+ */
+ public static String getResult(@Nullable Player player, String identifier) {
+ Optional matching = placeholders.stream().filter(expansion -> expansion.getIdentifier().equalsIgnoreCase(identifier)).findFirst();
+ if (!matching.isPresent())
+ return null;
+ PlaceholderEntry entry = matching.get();
+ if (player == null && entry.requiresPlayer())
+ return "";
+ return entry.getResult(player);
+ }
+
+ /**
+ * Translate all placeholders with respect to a player
+ *
+ * @param text The text that may contain placeholders to translate
+ * @param player The player to translate the placeholders with respect to
+ * @return The text, translated
+ */
+ public static String translatePlaceholders(String text, @Nullable Player player) {
+ AtomicReference translatedReference = new AtomicReference<>(text);
+ integrations.forEach(placeholderIntegration -> translatedReference.set(placeholderIntegration.translate(translatedReference.get(), player)));
+ return translatedReference.get();
+ }
+}
diff --git a/eco-util/src/main/java/com/willfp/eco/util/integrations/placeholder/plugins/PlaceholderIntegrationPAPI.java b/eco-util/src/main/java/com/willfp/eco/util/integrations/placeholder/plugins/PlaceholderIntegrationPAPI.java
new file mode 100644
index 00000000..09406337
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/integrations/placeholder/plugins/PlaceholderIntegrationPAPI.java
@@ -0,0 +1,65 @@
+package com.willfp.eco.util.integrations.placeholder.plugins;
+
+import com.willfp.eco.util.integrations.placeholder.PlaceholderIntegration;
+import com.willfp.eco.util.integrations.placeholder.PlaceholderManager;
+import com.willfp.eco.util.plugin.AbstractEcoPlugin;
+import me.clip.placeholderapi.PlaceholderAPI;
+import me.clip.placeholderapi.expansion.PlaceholderExpansion;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * PlaceholderAPI integration
+ */
+public class PlaceholderIntegrationPAPI extends PlaceholderExpansion implements PlaceholderIntegration {
+ private final AbstractEcoPlugin plugin;
+
+ public PlaceholderIntegrationPAPI(AbstractEcoPlugin plugin) {
+ this.plugin = plugin;
+ }
+
+ @Override
+ public boolean persist() {
+ return true;
+ }
+
+ @Override
+ public boolean canRegister() {
+ return true;
+ }
+
+ @Override
+ public @NotNull String getAuthor() {
+ return "Auxilor";
+ }
+
+ @Override
+ public @NotNull String getIdentifier() {
+ return plugin.getDescription().getName().toLowerCase();
+ }
+
+ @Override
+ public @NotNull String getVersion() {
+ return plugin.getDescription().getVersion();
+ }
+
+ @Override
+ public String onPlaceholderRequest(Player player, @NotNull String identifier) {
+ return PlaceholderManager.getResult(player, identifier);
+ }
+
+ @Override
+ public void registerIntegration() {
+ this.register();
+ }
+
+ @Override
+ public String getPluginName() {
+ return "PlaceholderAPI";
+ }
+
+ @Override
+ public String translate(String text, Player player) {
+ return PlaceholderAPI.setPlaceholders(player, text);
+ }
+}
diff --git a/Plugin/src/main/java/com/willfp/ecoenchants/util/interfaces/Registerable.java b/eco-util/src/main/java/com/willfp/eco/util/interfaces/Registerable.java
similarity index 71%
rename from Plugin/src/main/java/com/willfp/ecoenchants/util/interfaces/Registerable.java
rename to eco-util/src/main/java/com/willfp/eco/util/interfaces/Registerable.java
index 1e8b3fc2..a1b81658 100644
--- a/Plugin/src/main/java/com/willfp/ecoenchants/util/interfaces/Registerable.java
+++ b/eco-util/src/main/java/com/willfp/eco/util/interfaces/Registerable.java
@@ -1,4 +1,4 @@
-package com.willfp.ecoenchants.util.interfaces;
+package com.willfp.eco.util.interfaces;
/**
* Interface for objects that can be internally registered
diff --git a/eco-util/src/main/java/com/willfp/eco/util/lambda/Callable.java b/eco-util/src/main/java/com/willfp/eco/util/lambda/Callable.java
new file mode 100644
index 00000000..1efc0862
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/lambda/Callable.java
@@ -0,0 +1,9 @@
+package com.willfp.eco.util.lambda;
+
+/**
+ * Simple functional interface to run some code on demand
+ */
+@FunctionalInterface
+public interface Callable {
+ void call();
+}
diff --git a/eco-util/src/main/java/com/willfp/eco/util/lambda/ObjectBiCallable.java b/eco-util/src/main/java/com/willfp/eco/util/lambda/ObjectBiCallable.java
new file mode 100644
index 00000000..b26f346c
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/lambda/ObjectBiCallable.java
@@ -0,0 +1,12 @@
+package com.willfp.eco.util.lambda;
+
+/**
+ * Functional Interface to return a value of a specified type given a certain parameter
+ *
+ * @param The type of object to return
+ * @param The type of object for the parameter
+ */
+@FunctionalInterface
+public interface ObjectBiCallable {
+ A call(B object);
+}
diff --git a/eco-util/src/main/java/com/willfp/eco/util/lambda/ObjectCallable.java b/eco-util/src/main/java/com/willfp/eco/util/lambda/ObjectCallable.java
new file mode 100644
index 00000000..7abdf9fe
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/lambda/ObjectCallable.java
@@ -0,0 +1,11 @@
+package com.willfp.eco.util.lambda;
+
+/**
+ * Functional Interface to return a value of a given type
+ *
+ * @param The type to return
+ */
+@FunctionalInterface
+public interface ObjectCallable {
+ A call();
+}
diff --git a/eco-util/src/main/java/com/willfp/eco/util/optional/Prerequisite.java b/eco-util/src/main/java/com/willfp/eco/util/optional/Prerequisite.java
new file mode 100644
index 00000000..775fd0a6
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/optional/Prerequisite.java
@@ -0,0 +1,91 @@
+package com.willfp.eco.util.optional;
+
+import com.willfp.eco.util.ClassUtils;
+import com.willfp.eco.util.lambda.ObjectCallable;
+import org.bukkit.Bukkit;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class Prerequisite {
+ private static final List values = new ArrayList<>();
+
+ /**
+ * Requires the server to be running minecraft version 1.16 or higher
+ */
+ public static final Prerequisite MinVer1_16 = new Prerequisite(
+ () -> !Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3].contains("15"),
+ "Requires minimum server version of 1.16"
+ );
+
+ /**
+ * Requires the server to be running an implementation of paper
+ */
+ public static final Prerequisite HasPaper = new Prerequisite(
+ () -> ClassUtils.exists("com.destroystokyo.paper.event.player.PlayerElytraBoostEvent"),
+ "Requires server to be running paper (or a fork)"
+ );
+
+ private boolean isMet;
+ private final ObjectCallable isMetCallable;
+ private final String description;
+
+ /**
+ * Create a prerequisite
+ *
+ * @param isMetCallable An {@link ObjectCallable} that returns if the prerequisite is met
+ * @param description The description of the prerequisite, shown to the user if it isn't
+ */
+ public Prerequisite(ObjectCallable isMetCallable, String description) {
+ this.isMetCallable = isMetCallable;
+ this.isMet = isMetCallable.call();
+ this.description = description;
+ values.add(this);
+ }
+
+ /**
+ * Get the description of the prerequisite
+ *
+ * @return The description
+ */
+ public String getDescription() {
+ return description;
+ }
+
+ /**
+ * Get if the prerequisite has been met
+ *
+ * @return If the prerequisite is met
+ */
+ public boolean isMet() {
+ return isMet;
+ }
+
+ private void refresh() {
+ this.isMet = this.isMetCallable.call();
+ }
+
+ /**
+ * Update all prerequisites' {@link Prerequisite#isMet}
+ */
+ public static void update() {
+ values.forEach(Prerequisite::refresh);
+ }
+
+ /**
+ * Check if all prerequisites in array are met
+ *
+ * @param prerequisites A primitive array of prerequisites to check
+ *
+ * @return If all the prerequisites are met
+ */
+ public static boolean areMet(Prerequisite[] prerequisites) {
+ update();
+ return Arrays.stream(prerequisites).allMatch(Prerequisite::isMet);
+ }
+
+ static {
+ update();
+ }
+}
diff --git a/eco-util/src/main/java/com/willfp/eco/util/plugin/AbstractEcoPlugin.java b/eco-util/src/main/java/com/willfp/eco/util/plugin/AbstractEcoPlugin.java
new file mode 100644
index 00000000..4e9b3deb
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/plugin/AbstractEcoPlugin.java
@@ -0,0 +1,167 @@
+package com.willfp.eco.util.plugin;
+
+import com.willfp.eco.util.arrows.ArrowDataListener;
+import com.willfp.eco.util.bukkit.events.EcoEventManager;
+import com.willfp.eco.util.bukkit.events.EventManager;
+import com.willfp.eco.util.bukkit.keys.NamespacedKeyFactory;
+import com.willfp.eco.util.bukkit.logging.EcoLogger;
+import com.willfp.eco.util.bukkit.logging.Logger;
+import com.willfp.eco.util.bukkit.meta.MetadataValueFactory;
+import com.willfp.eco.util.bukkit.scheduling.EcoScheduler;
+import com.willfp.eco.util.bukkit.scheduling.Scheduler;
+import com.willfp.eco.util.drops.internal.FastCollatedDropQueue;
+import com.willfp.eco.util.events.armorequip.ArmorListener;
+import com.willfp.eco.util.events.armorequip.DispenserArmorListener;
+import com.willfp.eco.util.events.entitydeathbyentity.EntityDeathByEntityListeners;
+import com.willfp.eco.util.events.naturalexpgainevent.NaturalExpGainListeners;
+import com.willfp.eco.util.extensions.loader.EcoExtensionLoader;
+import com.willfp.eco.util.extensions.loader.ExtensionLoader;
+import com.willfp.eco.util.integrations.placeholder.PlaceholderManager;
+import com.willfp.eco.util.integrations.placeholder.plugins.PlaceholderIntegrationPAPI;
+import com.willfp.eco.util.lambda.Callable;
+import com.willfp.eco.util.updater.UpdateChecker;
+import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
+import org.bukkit.Bukkit;
+import org.bukkit.plugin.Plugin;
+import org.bukkit.plugin.java.JavaPlugin;
+import org.bukkit.scheduler.BukkitTask;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public abstract class AbstractEcoPlugin extends JavaPlugin {
+ protected static AbstractEcoPlugin instance;
+
+ protected final String pluginName;
+ protected final int resourceId;
+
+ private final Map integrations = new HashMap<>();
+
+ private final Logger log;
+ private final Scheduler scheduler;
+ private final EventManager eventManager;
+ private final NamespacedKeyFactory namespacedKeyFactory;
+ private final MetadataValueFactory metadataValueFactory;
+ private final ExtensionLoader extensionLoader;
+
+ private final BukkitTask dropQueueCollationTask;
+
+ protected boolean outdated = false;
+
+ protected AbstractEcoPlugin(String pluginName, int resourceId) {
+ this.pluginName = pluginName;
+ this.resourceId = resourceId;
+
+ this.log = new EcoLogger(this);
+ this.scheduler = new EcoScheduler(this);
+ this.eventManager = new EcoEventManager(this);
+ this.namespacedKeyFactory = new NamespacedKeyFactory(this);
+ this.metadataValueFactory = new MetadataValueFactory(this);
+ this.extensionLoader = new EcoExtensionLoader(this);
+
+ this.dropQueueCollationTask = new FastCollatedDropQueue.CollatedRunnable(this).getRunnableTask();
+ }
+
+ @Override
+ public final void onEnable() {
+ super.onLoad();
+
+ this.getEventManager().registerEvents(new ArrowDataListener(this));
+ this.getEventManager().registerEvents(new NaturalExpGainListeners());
+ this.getEventManager().registerEvents(new ArmorListener());
+ this.getEventManager().registerEvents(new DispenserArmorListener());
+ this.getEventManager().registerEvents(new EntityDeathByEntityListeners(this));
+
+ new UpdateChecker(this, resourceId).getVersion(version -> {
+ DefaultArtifactVersion currentVersion = new DefaultArtifactVersion(this.getDescription().getVersion());
+ DefaultArtifactVersion mostRecentVersion = new DefaultArtifactVersion(version);
+ if (!(currentVersion.compareTo(mostRecentVersion) > 0 || currentVersion.equals(mostRecentVersion))) {
+ this.getScheduler().runTimer(() -> {
+ this.getLog().info("&c " + this.pluginName + " is out of date! (Version " + this.getDescription().getVersion() + ")");
+ this.getLog().info("&cThe newest version is &f" + version);
+ this.getLog().info("&cDownload the new version!");
+ }, 0, 864000);
+ }
+ });
+
+ Set enabledPlugins = Arrays.stream(Bukkit.getPluginManager().getPlugins()).map(Plugin::getName).collect(Collectors.toSet());
+
+ this.getDefaultIntegrations().forEach(((s, callable) -> {
+ StringBuilder log = new StringBuilder();
+ log.append(s).append(": ");
+ if (enabledPlugins.contains(s)) {
+ callable.call();
+ log.append("&aENABLED");
+ } else {
+ log.append("&9DISABLED");
+ }
+ this.getLog().info(log.toString());
+ }));
+
+ this.enable();
+ }
+
+ @Override
+ public final void onDisable() {
+ super.onDisable();
+ this.disable();
+ }
+
+ @Override
+ public final void onLoad() {
+ super.onLoad();
+
+ instance = this;
+
+ this.load();
+ }
+
+ public final Map getDefaultIntegrations() {
+ integrations.put("PlaceholderAPI", () -> PlaceholderManager.addIntegration(new PlaceholderIntegrationPAPI(this)));
+ integrations.putAll(this.getIntegrations());
+ return integrations;
+ }
+
+ public abstract void enable();
+
+ public abstract void disable();
+
+ public abstract void load();
+
+ public abstract Map getIntegrations();
+
+ public final Logger getLog() {
+ return log;
+ }
+
+ public final Scheduler getScheduler() {
+ return scheduler;
+ }
+
+ public final EventManager getEventManager() {
+ return eventManager;
+ }
+
+ public final NamespacedKeyFactory getNamespacedKeyFactory() {
+ return namespacedKeyFactory;
+ }
+
+ public final MetadataValueFactory getMetadataValueFactory() {
+ return metadataValueFactory;
+ }
+
+ public ExtensionLoader getExtensionLoader() {
+ return extensionLoader;
+ }
+
+ public boolean isOutdated() {
+ return outdated;
+ }
+
+ public static AbstractEcoPlugin getInstance() {
+ return instance;
+ }
+}
diff --git a/eco-util/src/main/java/com/willfp/eco/util/tuplets/Pair.java b/eco-util/src/main/java/com/willfp/eco/util/tuplets/Pair.java
new file mode 100644
index 00000000..21c5dc6d
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/tuplets/Pair.java
@@ -0,0 +1,64 @@
+package com.willfp.eco.util.tuplets;
+
+/**
+ * Spigot doesn't include javafx
+ */
+public class Pair {
+ private A first;
+ private B second;
+
+ /**
+ * Create a pair
+ *
+ * @param first The first item in the tuplet
+ * @param second The second item in the tuplet
+ */
+ public Pair(A first, B second) {
+ this.first = first;
+ this.second = second;
+ }
+
+ /**
+ * Get the first item in the tuplet
+ *
+ * @return The first item
+ */
+ public A getFirst() {
+ return first;
+ }
+
+ /**
+ * Get the second item in the tuplet
+ *
+ * @return The second item
+ */
+ public B getSecond() {
+ return second;
+ }
+
+ /**
+ * Set the first item in the tuplet
+ *
+ * @param first The value to set the first item to
+ */
+ public void setFirst(A first) {
+ this.first = first;
+ }
+
+ /**
+ * Set the second item in the tuplet
+ *
+ * @param second The value to set the second item to
+ */
+ public void setSecond(B second) {
+ this.second = second;
+ }
+
+ @Override
+ public String toString() {
+ return "Pair{" +
+ "first=" + first +
+ ", second=" + second +
+ '}';
+ }
+}
diff --git a/eco-util/src/main/java/com/willfp/eco/util/tuplets/Triplet.java b/eco-util/src/main/java/com/willfp/eco/util/tuplets/Triplet.java
new file mode 100644
index 00000000..8a12f8c1
--- /dev/null
+++ b/eco-util/src/main/java/com/willfp/eco/util/tuplets/Triplet.java
@@ -0,0 +1,86 @@
+package com.willfp.eco.util.tuplets;
+
+/**
+ * Spigot doesn't include javafx
+ */
+public class Triplet {
+ private A first;
+ private B second;
+ private C third;
+
+ /**
+ * Create a triplet
+ *
+ * @param first The first item in the tuplet
+ * @param second The second item in the tuplet
+ * @param third The third item in the tuplet
+ */
+ public Triplet(A first, B second, C third) {
+ this.first = first;
+ this.second = second;
+ this.third = third;
+ }
+
+ /**
+ * Get the first item in the tuplet
+ *
+ * @return The first item
+ */
+ public A getFirst() {
+ return first;
+ }
+
+ /**
+ * Get the second item in the tuplet
+ *
+ * @return The second item
+ */
+ public B getSecond() {
+ return second;
+ }
+
+ /**
+ * Get the third item in the tuplet
+ *
+ * @return The third item
+ */
+ public C getThird() {
+ return third;
+ }
+
+ /**
+ * Set the first item in the tuplet
+ *
+ * @param first The value to set
+ */
+ public void setFirst(A first) {
+ this.first = first;
+ }
+
+ /**
+ * Set the second item in the tuplet
+ *
+ * @param second The value to set
+ */
+ public void setSecond(B second) {
+ this.second = second;
+ }
+
+ /**
+ * Set the third item in the tuplet
+ *
+ * @param third The value to set
+ */
+ public void setThird(C third) {
+ this.third = third;
+ }
+
+ @Override
+ public String toString() {
+ return "Triplet{" +
+ "first=" + first +
+ ", second=" + second +
+ ", third=" + third +
+ '}';
+ }
+}
diff --git a/Plugin/src/main/java/com/willfp/ecoenchants/util/internal/updater/UpdateChecker.java b/eco-util/src/main/java/com/willfp/eco/util/updater/UpdateChecker.java
similarity index 55%
rename from Plugin/src/main/java/com/willfp/ecoenchants/util/internal/updater/UpdateChecker.java
rename to eco-util/src/main/java/com/willfp/eco/util/updater/UpdateChecker.java
index 563f4418..dba46a78 100644
--- a/Plugin/src/main/java/com/willfp/ecoenchants/util/internal/updater/UpdateChecker.java
+++ b/eco-util/src/main/java/com/willfp/eco/util/updater/UpdateChecker.java
@@ -1,4 +1,4 @@
-package com.willfp.ecoenchants.util.internal.updater;
+package com.willfp.eco.util.updater;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
@@ -10,12 +10,9 @@ import java.net.URL;
import java.util.Scanner;
/**
- * Checks spigot if EcoEnchants is out of date
+ * Checks spigot if a plugin is out of date
*/
public class UpdateChecker {
- private static boolean outdated;
- private static String newVersion;
-
private final Plugin plugin;
private final int resourceId;
@@ -42,45 +39,9 @@ public class UpdateChecker {
consumer.accept(scanner.next());
}
} catch (IOException exception) {
- this.plugin.getLogger().warning("Failed to check for EcoEnchants updates: " + exception.getMessage());
+ this.plugin.getLogger().warning("Failed to check for updates: " + exception.getMessage());
}
});
}
-
- /**
- * Get if the plugin is outdated
- *
- * @return If the plugin is outdated
- */
- public static boolean isOutdated() {
- return outdated;
- }
-
- /**
- * Get the newest available version of the plugin
- *
- * @return The latest version
- */
- public static String getNewVersion() {
- return newVersion;
- }
-
- /**
- * Mark the plugin as outdated or not
- *
- * @param outdated Whether the plugin is outdated
- */
- public static void setOutdated(boolean outdated) {
- UpdateChecker.outdated = outdated;
- }
-
- /**
- * Set the newest available version of the plugin
- *
- * @param newVersion The newest version
- */
- public static void setNewVersion(String newVersion) {
- UpdateChecker.newVersion = newVersion;
- }
}
\ No newline at end of file
diff --git a/settings.gradle b/settings.gradle
index ea679092..8c6e99b5 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,44 +1,13 @@
rootProject.name = 'parent'
-include('v1_15_R1')
-include('plugin')
-include('API')
-include('v1_16_R1')
-include('v1_16_R2')
-include('v1_16_R3')
-project(":v1_15_R1").projectDir = file('NMS/v1_15_R1')
-project(":plugin").projectDir = file('Plugin')
-project(":API").projectDir = file('NMS/API')
-project(":v1_16_R1").projectDir = file('NMS/v1_16_R1')
-project(":v1_16_R2").projectDir = file('NMS/v1_16_R2')
-project(":v1_16_R3").projectDir = file('NMS/v1_16_R3')
+include ':eco-util'
-// Extensions
-include('Firewand')
-project(":Firewand").projectDir = file('Extensions/Firewand')
-
-include('Precision')
-project(":Precision").projectDir = file('Extensions/Precision')
-
-include('Effects')
-findProject(':Effects').projectDir = file('Extensions/Effects')
-
-include('Summoning')
-findProject(':Summoning').projectDir = file('Extensions/Summoning')
-
-include('Endershot')
-findProject(':Endershot').projectDir = file('Extensions/Endershot')
-
-include('Biomes')
-findProject(':Biomes').projectDir = file('Extensions/Biomes')
-
-include('SprintArtifacts')
-findProject(':SprintArtifacts').projectDir = file('Extensions/SprintArtifacts')
-
-include('Alchemy')
-findProject(':Alchemy').projectDir = file('Extensions/Alchemy')
-
-/*
-include('MMO')
-findProject(':MMO').projectDir = file('Extensions/MMO')
- */
\ No newline at end of file
+// Core
+include ':eco-core'
+include ':eco-core:core-nms'
+include ':eco-core:core-nms:v1_15_R1'
+include ':eco-core:core-nms:v1_16_R1'
+include ':eco-core:core-nms:v1_16_R2'
+include ':eco-core:core-nms:v1_16_R3'
+include ':eco-core:core-proxy'
+include ':eco-core:core-plugin'
\ No newline at end of file