diff --git a/.forgejo/workflows/build.yml b/.forgejo/workflows/build.yml
new file mode 100644
index 0000000..149d2f5
--- /dev/null
+++ b/.forgejo/workflows/build.yml
@@ -0,0 +1,43 @@
+name: Build
+
+on:
+ push:
+ paths:
+ - 'src/**'
+ - '.github/**'
+ - 'build.gradle.kts'
+ - 'gradle.properties'
+ - 'settings.gradle'
+
+jobs:
+ build:
+ runs-on: arch-linux
+ env:
+ NEMESIS_VERSION_NAME: "autobuild-${{ github.sha }}"
+ NEMESIS_BUILD_CHANNEL: "autobuild"
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v6.0.1
+
+ - name: Setup Java enviroment
+ uses: actions/setup-java@v5.1.0
+ with:
+ distribution: temurin
+ java-version: 21
+
+ - name: Setup Gradle
+ uses: gradle/actions/setup-gradle@v5
+
+ - name: Download CB1060
+ run: |
+ mkdir -p libs
+ curl -L -o libs/craftbukkit-1060.jar https://archive.org/download/craftbukkit1060/craftbukkit1-7-3%281060%29.jar
+
+ - name: Build with Gradle
+ run: ./gradlew buildAll
+
+
+ - name: Upload artifacts
+ uses: actions/upload-artifact@v6.0.0
+ with:
+ path: build/libs/*.jar
diff --git a/.forgejo/workflows/release-build.yml b/.forgejo/workflows/release-build.yml
new file mode 100644
index 0000000..392e32e
--- /dev/null
+++ b/.forgejo/workflows/release-build.yml
@@ -0,0 +1,40 @@
+name: Release Build
+
+on:
+ release:
+ types: [published]
+
+jobs:
+ build-and-release:
+ runs-on: arch-linux
+ env:
+ NEMESIS_VERSION_NAME: "${{ github.ref_name }}"
+ NEMESIS_BUILD_CHANNEL: "production"
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v6.0.1
+
+ - name: Set up Java
+ uses: actions/setup-java@v5.1.0
+ with:
+ distribution: temurin
+ java-version: 21
+
+ - name: Set up Gradle
+ uses: gradle/actions/setup-gradle@v5
+
+ - name: Download CB1060
+ run: |
+ mkdir -p libs
+ curl -L -o libs/craftbukkit-1060.jar \
+ https://archive.org/download/craftbukkit1060/craftbukkit1-7-3%281060%29.jar
+
+ - name: Build with Gradle
+ run: ./gradlew buildAll
+
+ - name: Upload JARs to release
+ uses: softprops/action-gh-release@v2.5.0
+ with:
+ files: build/libs/*.jar
+ tag_name: ${{ github.ref_name }}
+ name: ${{ github.ref_name }}
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 0000000..ac1941e
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1,15 @@
+# These are supported funding model platforms
+
+github: adrianvic
+patreon: # Replace with a single Patreon username
+open_collective: # Replace with a single Open Collective username
+ko_fi: # Replace with a single Ko-fi username
+tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
+community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
+liberapay: # Replace with a single Liberapay username
+issuehunt: # Replace with a single IssueHunt username
+lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
+polar: # Replace with a single Polar username
+buy_me_a_coffee: # Replace with a single Buy Me a Coffee username
+thanks_dev: # Replace with a single thanks.dev username
+custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
new file mode 100644
index 0000000..0e8199d
--- /dev/null
+++ b/.github/workflows/build.yml
@@ -0,0 +1,44 @@
+name: Build
+
+on:
+ workflow_dispatch:
+ push:
+ paths:
+ - 'src/**'
+ - '.github/**'
+ - 'build.gradle.kts'
+ - 'gradle.properties'
+ - 'settings.gradle'
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ env:
+ NEMESIS_VERSION_NAME: "autobuild-${{ github.sha }}"
+ NEMESIS_BUILD_CHANNEL: "autobuild"
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v6.0.1
+
+ - name: Setup Java enviroment
+ uses: actions/setup-java@v5.1.0
+ with:
+ distribution: temurin
+ java-version: 21
+
+ - name: Setup Gradle
+ uses: gradle/actions/setup-gradle@v5
+
+ - name: Download CB1060
+ run: |
+ mkdir -p libs
+ curl -L -o libs/craftbukkit-1060.jar https://archive.org/download/craftbukkit1060/craftbukkit1-7-3%281060%29.jar
+
+ - name: Build with Gradle
+ run: ./gradlew buildAll
+
+
+ - name: Upload artifacts
+ uses: actions/upload-artifact@v3
+ with:
+ path: build/libs/*.jar
diff --git a/.github/workflows/release-build.yml b/.github/workflows/release-build.yml
new file mode 100644
index 0000000..9570712
--- /dev/null
+++ b/.github/workflows/release-build.yml
@@ -0,0 +1,41 @@
+name: Release Build
+
+on:
+ release:
+ types: [published]
+
+jobs:
+ build-and-release:
+ runs-on: ubuntu-latest
+ env:
+ NEMESIS_VERSION_NAME: "${{ github.ref_name }}"
+ NEMESIS_BUILD_CHANNEL: "production"
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v6.0.1
+
+ - name: Set up Java
+ uses: actions/setup-java@v5.1.0
+ with:
+ distribution: temurin
+ java-version: 21
+
+ - name: Set up Gradle
+ uses: gradle/actions/setup-gradle@v5
+
+ - name: Download CB1060
+ run: |
+ mkdir -p libs
+ curl -L -o libs/craftbukkit-1060.jar \
+ https://archive.org/download/craftbukkit1060/craftbukkit1-7-3%281060%29.jar
+
+ - name: Build with Gradle
+ run: ./gradlew buildAll
+
+ - name: Upload artifacts to release
+ run: |
+ curl -X POST \
+ -H "Authorization: token ${{ secrets.FORGEJO_TOKEN }}" \
+ -H "Content-Type: application/octet-stream" \
+ https://inspiran.beetal-castor.ts.net/git/api/v1/repos/${{ github.repository }}/releases/tags/${{ github.ref_name }}/assets \
+ --data-binary @build/libs/your-artifact.jar
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 1ac6f97..1e3abdf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
.gradle/
build/
out/
-.idea/
\ No newline at end of file
+.idea/
+libs/
+run/
diff --git a/README.md b/README.md
index c4aceff..bf357cf 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,24 @@
-# Eye of Nemesis
-Eye of Nemesis is a Minecraft Paper plugin that allows server admins to write *policies* that will deny or allow (black/whitelist) players to do specific things.
+
-You can create policies based on player location, ~but other types of policies are available, like permission and player-name policy.~ (WIP)
+[](https://modrinth.com/plugin/eye-of-nemesis)
+[](https://github.com/adrianvic/NemesisEye/wiki)
+[](https://mgr.rf.gd/w/Eye_of_Nemesis)
+
+> [!IMPORTANT]
+> This project is in an early stage, please report any bug you find.
+
+# Eye of Nemesis
+Eye of Nemesis is a plugin that allows server admins to write policies that will deny or allow (black/whitelist) players to do specific things based on the value of nodes.
+
+## Motivations
+I made this plugin as an effort to preserve a village from my private server. Originally from beta 1.7.3 Betalands server, then transferred to RetroMC, and then finally we downloaded the chunks to merge into our server, I was afraid it would not have the same feeling after all the updates, so I had the idea to make a plugin that can block the newer features.
+
+## Game version and loaders
+Since version 1.0.3-SNAPSHOT, Eye of Nemesis has _reflection_, a technique that allows me to target multiple versions of the game while sharing the codebase across versions.
+
+Currently, we support the following Minecraft versions/loaders:
+- **PaperMC** `1.21, 1.21.1, 1.21.2, 1.21.3, 1.21.4, 1.21.5, 1.21.6, 1.21.7, 1.21.8, 1.21.9, 1.21.10`
+- **Bukkit** `b1.7.3 (CB1060)`
+
+## Performance
+This plugin is not scalable as it is and will end up running unoptimized checks when your players do things with policies in effect, I made it for a server with a few friends. I'll look forward into writing more performant code after all my other priorities are implemented.
diff --git a/build.gradle b/build.gradle
deleted file mode 100644
index a155746..0000000
--- a/build.gradle
+++ /dev/null
@@ -1,55 +0,0 @@
-plugins {
- id 'java'
- id("xyz.jpenilla.run-paper") version "2.3.1"
-}
-
-group = 'io.github.adrianvic'
-version = '1.0.1-SNAPSHOT'
-
-repositories {
- mavenCentral()
- maven {
- name = "papermc-repo"
- url = "https://repo.papermc.io/repository/maven-public/"
- }
-}
-
-dependencies {
- compileOnly("io.papermc.paper:paper-api:1.21.10-R0.1-SNAPSHOT")
-}
-
-tasks {
- runServer {
- // Configure the Minecraft version for our task.
- // This is the only required configuration besides applying the plugin.
- // Your plugin's jar (or shadowJar if present) will be used automatically.
- minecraftVersion("1.21")
- }
-}
-
-def targetJavaVersion = 21
-java {
- def javaVersion = JavaVersion.toVersion(targetJavaVersion)
- sourceCompatibility = javaVersion
- targetCompatibility = javaVersion
- if (JavaVersion.current() < javaVersion) {
- toolchain.languageVersion = JavaLanguageVersion.of(targetJavaVersion)
- }
-}
-
-tasks.withType(JavaCompile).configureEach {
- options.encoding = 'UTF-8'
-
- if (targetJavaVersion >= 10 || JavaVersion.current().isJava10Compatible()) {
- options.release.set(targetJavaVersion)
- }
-}
-
-processResources {
- def props = [version: version]
- inputs.properties props
- filteringCharset 'UTF-8'
- filesMatching('plugin.yml') {
- expand props
- }
-}
diff --git a/build.gradle.kts b/build.gradle.kts
new file mode 100644
index 0000000..e2d9a2e
--- /dev/null
+++ b/build.gradle.kts
@@ -0,0 +1,154 @@
+plugins {
+ java
+ id("xyz.jpenilla.run-paper") version "2.3.1"
+}
+
+group = "io.github.adrianvic"
+version = System.getenv("NEMESIS_VERSION_NAME") ?: "unknown"
+
+repositories {
+ mavenCentral()
+ maven("https://repo.papermc.io/repository/maven-public/")
+}
+
+/* ----------------------------------------- */
+/* SUPPORTED VERSIONS */
+/* ----------------------------------------- */
+
+val mcVersions = listOf(
+ "b1_7_3",
+ "r1_21"
+)
+
+/* ----------------------------------------- */
+/* CREATE SOURCE SET PER VERSION */
+/* ----------------------------------------- */
+
+tasks.withType {
+ inputs.property("version", project.version)
+
+ filesMatching("plugin.yml") {
+ expand("version" to project.version)
+ }
+}
+
+mcVersions.forEach { ver ->
+ val ss = sourceSets.create(ver) {
+ java.srcDir("src/$ver/java")
+
+ resources.setSrcDirs(listOf("src/$ver/resources", "src/main/resources"))
+
+ compileClasspath += sourceSets["main"].output
+ runtimeClasspath += output + compileClasspath
+ }
+
+ tasks.withType {
+ duplicatesStrategy = DuplicatesStrategy.EXCLUDE
+ }
+
+ configurations[ss.implementationConfigurationName]
+ .extendsFrom(configurations["implementation"])
+
+ configurations[ss.compileOnlyConfigurationName]
+ .extendsFrom(configurations["compileOnly"])
+
+}
+
+/* ----------------------------------------- */
+/* DEPENDENCIES */
+/* ----------------------------------------- */
+
+dependencies {
+ add("compileOnly", "io.papermc.paper:paper-api:1.21-R0.1-SNAPSHOT")
+ add("r1_21CompileOnly", "io.papermc.paper:paper-api:1.21-R0.1-SNAPSHOT")
+ add("b1_7_3CompileOnly", files("libs/craftbukkit-1060.jar"))
+
+ testImplementation("org.junit.jupiter:junit-jupiter:5.10.0")
+ testImplementation("org.mockito:mockito-core:5.5.0")
+ testRuntimeOnly("org.junit.platform:junit-platform-launcher")
+ testImplementation("io.papermc.paper:paper-api:1.21-R0.1-SNAPSHOT")
+ testImplementation("com.github.seeseemelk:MockBukkit-v1.21:3.102.0")
+
+ // Allow tests to see the versioned implementations
+ mcVersions.forEach { ver ->
+ testImplementation(sourceSets[ver].output)
+ }
+}
+
+tasks.test {
+ useJUnitPlatform()
+}
+
+/* ----------------------------------------- */
+/* BUILD TASKS */
+/* ----------------------------------------- */
+
+mcVersions.forEach { ver ->
+ tasks.register("jar${ver.replace(".", "_").replace("-", "_").replace("/", "_").capitalize()}") {
+ duplicatesStrategy = DuplicatesStrategy.EXCLUDE
+ from(sourceSets["main"].output)
+ from(sourceSets[ver].output)
+ archiveClassifier.set(ver)
+
+ manifest {
+ attributes(
+ "Nemesis-Impl-Version" to ver,
+ "Nemesis-Environment" to (System.getenv("NEMESIS_BUILD_CHANNEL") ?: "dev")
+ )
+ }
+
+ }
+}
+
+tasks.register("buildAll") {
+ dependsOn(tasks.withType())
+}
+
+tasks.register("shadowJar") {
+ from(sourceSets["main"].output)
+ mcVersions.forEach { ver ->
+ from(sourceSets[ver].output)
+ }
+
+ // This is kinda gross and, essentially, we shouldn't have it here...
+ duplicatesStrategy = DuplicatesStrategy.EXCLUDE
+
+ archiveClassifier.set("all-implementations")
+ archiveVersion.set(project.version.toString())
+
+ manifest {
+ attributes(
+ "Implemented-Versions" to mcVersions.joinToString(",")
+ )
+ }
+}
+
+/* ----------------------------------------- */
+/* JAVA SETTINGS */
+/* ----------------------------------------- */
+
+java {
+ toolchain.languageVersion.set(JavaLanguageVersion.of(21))
+}
+
+tasks.withType {
+ options.encoding = "UTF-8"
+}
+
+tasks.runServer {
+ minecraftVersion("1.21")
+ downloadPlugins {
+ modrinth("viaversion", "5.7.0")
+ modrinth("luckperms", "v5.5.17-bukkit")
+ }
+}
+
+tasks.register("runServerClean") {
+ doFirst {
+ exec {
+ commandLine("rm", "run/plugins/Eye-of-Nemesis/settings.yml")
+ }
+ }
+
+ dependsOn("runServer")
+}
\ No newline at end of file
diff --git a/docs/Nodes.md b/docs/Nodes.md
new file mode 100644
index 0000000..57cff1d
--- /dev/null
+++ b/docs/Nodes.md
@@ -0,0 +1,34 @@
+# Nodes
+Nodes narrow down even further if an action can be done or not. A node needs _properties_ to know what it should check against, for example, a HIT node needs a _list_ of blocks that it will check if the player is holding; while a USE_ENCHANTMENT node needs a mapping of enchantment to level. Some nodes like glyde don't need a value and will ignore if you provide one.
+```yaml
+nodes:
+ - [HIT]:
+ values:
+ - 'GOLD_SWORD'
+ - [USE_ENCHANTMENT]:
+ values:
+ - "UNBREAKING": "1"
+ - [GLYDE]
+```
+
+## Available nodes
+### INTERACT
+Triggered on `InteractionEvent`, returns true when the provided `list` contains the material used to interact.
+
+### HIT
+Triggered on `EntityDamageByEntityEvent`, returns true when the provided `list` contains the material used to hit.
+
+### PLACE
+Triggered on `BlockPlaceEvent`, returns true when the provided `list` contains the material being placed.
+
+### BREAK
+Triggered on `BlockBreakEvent`, returns true when the provided `list` contains the material used to break.
+
+### EQUIP
+Triggered on `InventoryClickEvent` and `PlayerInteractEvent` (only if item is an armor), returns true when the provided `list` contains the material being equipped.
+
+### GLYDE
+Triggered on `PlayerMoveEvent`, returns true if player is gliding.
+
+### USE_ENCHANTMENT
+Triggered on `BlockBreakEvent` and `onEntityDamageByEntityEvent`, returns true the used item has an enchantment matching the provided mapping of enchantment-level.
\ No newline at end of file
diff --git a/docs/Policies.md b/docs/Policies.md
new file mode 100644
index 0000000..21d468d
--- /dev/null
+++ b/docs/Policies.md
@@ -0,0 +1,89 @@
+# Policies
+Policies are a list of nodes with a specific condition to be met, they also determine what effect a node is going to have. Below is an example policy:
+```yaml
+ - name: "Allow example"
+ type: "location"
+ effect: ALLOW
+ weight: 1
+ worlds: [world]
+ locations:
+ coordinates:
+ - corner1: { x: 2100, y: 256, z: 1400 }
+ corner2: { x: 1000, y: -64, z: 2200 }
+ nodes:
+ - [INTERACT, BREAK, HIT, PLACE]:
+ values:
+ - AIR
+```
+
+## Properties
+### `name`
+Name of the policy, must not contain spaces or else commands that require you to type the policy name will not work.
+
+Example: `name: "disable-axe-damage"`
+
+### `type`
+One of the policy [types](#Types).
+
+Example: `type: location`
+
+### `effect`
+Can be `deny` to block the action if a node check returns true, `ALLOW` to revert `DENY` effects if the node check is true or `ALLOWONLY` to allow the action **only** if the node check returns true.
+
+Example: `effect: DENY`
+
+### `weight`
+A policy with greater weight will override a conflicting policy of lower weight.
+
+Example: `weight: 0`
+
+### `nodes`
+Must contain a list of node mappings to evaluate if the policy applies to a player.
+
+Example:
+```yaml
+nodes:
+ - [HIT]:
+ values:
+ - '.*_AXE$'
+```
+
+### `locations`
+Only used for `type: "location"`, is a list of mappings where corner1 and corner2 should map x, y and z to two corners of a rectangular area where the policy will take effect; `worlds` may be defined here.
+
+Example:
+
+```yaml
+locations:
+ worlds: [world]
+ coordinates:
+ - corner1: { x: 2100, y: 256, z: 1400 }
+ corner2: { x: 1000, y: -64, z: 2200 }
+```
+
+### `permissions`
+Only used for `type: "permission"`, is a list of permissions.
+
+Example:
+
+```yaml
+permissions:
+ - "server.axehit"
+```
+
+### `names`
+Only used for `type: "playerName"`, is a list of player names.
+
+## Types
+
+### `global`
+Always matches.
+
+### `location`
+Matches if the player location is inside any rectangle defined in the `locations` property.
+
+### `playerName`
+Matches if the player name is in the `names` property.
+
+### `permission`
+Matches if the player has a permission in the `permissions` property.
diff --git a/settings.gradle b/settings.gradle
index 52b1811..9a6526e 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1 +1 @@
-rootProject.name = 'regions'
+rootProject.name = 'eyeofnemesis'
diff --git a/src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/ConfigurationEx.java b/src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/ConfigurationEx.java
new file mode 100644
index 0000000..a4b3327
--- /dev/null
+++ b/src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/ConfigurationEx.java
@@ -0,0 +1,89 @@
+package io.github.adrianvic.nemesiseye.impl;
+
+import io.github.adrianvic.nemesiseye.Nemesis;
+import org.bukkit.plugin.java.JavaPlugin;
+import org.bukkit.util.config.Configuration;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+
+public class ConfigurationEx extends Configuration {
+ private final File configFile;
+ private final Log logger;
+ JavaPlugin plugin;
+
+ public ConfigurationEx(String fileName, Log _logger) {
+ super(new File(Nemesis.getInstance().getDataFolder(), fileName));
+ this.plugin = Nemesis.getInstance();
+ logger = _logger;
+ this.configFile = new File(plugin.getDataFolder(), fileName);
+ }
+
+ @Override
+ public void load() {
+ createParentDirectories();
+
+ if (!configFile.exists()) {
+ copyDefaultConfig();
+ }
+
+ try {
+ super.load();
+ } catch (Exception e) {
+ logger.severe(String.format("Failed to load config '%s': %s", configFile.getName(), e.getMessage()));
+ }
+ }
+
+ private void createParentDirectories() {
+ try {
+ Files.createDirectories(configFile.getParentFile().toPath());
+ } catch (IOException e) {
+ logger.severe(String.format("Failed to generate default config directory: %s", e.getMessage()));
+ }
+ }
+
+ private void copyDefaultConfig() {
+ // Load the config from the JAR directly (it is located at the root level)
+ String resourcePath = "/" + configFile.getName(); // Root path of JAR
+
+ try (InputStream input = plugin.getClass().getResourceAsStream(resourcePath)) {
+ if (input == null) {
+ logger.severe(String.format("Default config '%s' wasn't found in the JAR.", configFile.getName()));
+ return;
+ }
+
+ Files.copy(input, configFile.toPath());
+ if (Files.exists(configFile.toPath())) {
+ logger.info(String.format("Default config '%s' generated successfully.", configFile.getName()));
+ } else {
+ logger.warning("We tried to generate the default config file, but it was not found even after the creation. Maybe your permissions are broken?");
+ }
+ } catch (IOException e) {
+ logger.severe(String.format("Failed to generate default config '%s': %s", configFile.getName(), e.getMessage()));
+ }
+ }
+
+ public void loadConfig() {
+ try {
+ this.load();
+ logger.info(String.format("Config '%s' loaded successfully.", configFile.getName()));
+ } catch (Exception e) {
+ logger.severe(String.format("Failed to load config '%s': %s", configFile.getName(), e.getMessage()));
+ }
+ }
+
+ public void saveConfig() {
+ try {
+ this.save();
+ logger.info(String.format("Config '%s' saved successfully.", configFile.getName()));
+ } catch (Exception e) {
+ logger.severe(String.format("Failed to save config '%s': %s", configFile.getName(), e.getMessage()));
+ }
+ }
+
+ public File getConfig() {
+ return configFile;
+ }
+}
\ No newline at end of file
diff --git a/src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/Log.java b/src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/Log.java
new file mode 100644
index 0000000..ccba8b1
--- /dev/null
+++ b/src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/Log.java
@@ -0,0 +1,41 @@
+package io.github.adrianvic.nemesiseye.impl;
+
+import static org.bukkit.Bukkit.getServer;
+
+import io.github.adrianvic.nemesiseye.Nemesis;
+import org.bukkit.plugin.PluginDescriptionFile;
+import org.bukkit.plugin.java.JavaPlugin;
+
+public class Log {
+ JavaPlugin plugin;
+ PluginDescriptionFile pdf;
+
+ public Log() {
+ plugin = Nemesis.getInstance();
+ pdf = plugin.getDescription();
+ }
+
+ public void info(String message) {
+ getServer().getLogger().info("[" + pdf.getName() + "] " + message);
+ }
+
+ public void infoc(String message) {
+ getServer().getLogger().info("[" + pdf.getName() + "] " + message);
+ }
+
+ public void warning(String message) {
+ getServer().getLogger().warning("[" + pdf.getName() + "] " + message);
+ }
+
+ public void warningc(String message) {
+ getServer().getLogger().warning("[" + pdf.getName() + "] " + message);
+ }
+
+ public void severe(String message) {
+ getServer().getLogger().severe("[" + pdf.getName() + "] " + message);
+ }
+
+ public void severec(String message) {
+ getServer().getLogger().severe("[" + pdf.getName() + "] " + message);
+ }
+}
\ No newline at end of file
diff --git a/src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/b1_7_3.java b/src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/b1_7_3.java
new file mode 100644
index 0000000..0a86ce9
--- /dev/null
+++ b/src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/b1_7_3.java
@@ -0,0 +1,152 @@
+package io.github.adrianvic.nemesiseye.impl;
+
+import io.github.adrianvic.nemesiseye.Nemesis;
+import io.github.adrianvic.nemesiseye.impl.commands.Eye;
+import io.github.adrianvic.nemesiseye.impl.events.BlockEventListener;
+import io.github.adrianvic.nemesiseye.impl.events.EntityEventListener;
+import io.github.adrianvic.nemesiseye.impl.events.PlayerEventListener;
+import io.github.adrianvic.nemesiseye.policy.Policy;
+import io.github.adrianvic.nemesiseye.policy.PolicyParsers;
+import io.github.adrianvic.nemesiseye.reflection.Glimmer;
+import org.bukkit.Material;
+import org.bukkit.World;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.HumanEntity;
+import org.bukkit.event.Event;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.plugin.PluginManager;
+import org.bukkit.plugin.java.JavaPlugin;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+@SuppressWarnings("unused")
+public class b1_7_3 implements Glimmer {
+ JavaPlugin plugin;
+ PluginManager pm;
+ ConfigurationEx config;
+
+ @Override
+ public File loadConfigFile() {
+ config = new ConfigurationEx("settings.yml", new Log());
+ config.load();
+ return config.getConfig();
+ }
+
+ @Override
+ public List loadPoliciesFromFile(File file) {
+ List> rawPolicies = config.getList("Policies");
+
+ if (rawPolicies == null) {
+ return new ArrayList<>();
+ }
+
+ List