diff --git a/.forgejo/workflows/build.yml b/.forgejo/workflows/build.yml deleted file mode 100644 index 149d2f5..0000000 --- a/.forgejo/workflows/build.yml +++ /dev/null @@ -1,43 +0,0 @@ -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 deleted file mode 100644 index 392e32e..0000000 --- a/.forgejo/workflows/release-build.yml +++ /dev/null @@ -1,40 +0,0 @@ -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/workflows/build.yml b/.github/workflows/build.yml index 0e8199d..f5d4ddb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,7 +12,7 @@ on: jobs: build: - runs-on: ubuntu-latest + runs-on: "arch-linux" env: NEMESIS_VERSION_NAME: "autobuild-${{ github.sha }}" NEMESIS_BUILD_CHANNEL: "autobuild" diff --git a/.github/workflows/release-build.yml b/.github/workflows/release-build.yml index 9570712..c038796 100644 --- a/.github/workflows/release-build.yml +++ b/.github/workflows/release-build.yml @@ -6,7 +6,7 @@ on: jobs: build-and-release: - runs-on: ubuntu-latest + runs-on: "arch-linux" env: NEMESIS_VERSION_NAME: "${{ github.ref_name }}" NEMESIS_BUILD_CHANNEL: "production" @@ -32,10 +32,9 @@ jobs: - 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 + - 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 }} \ No newline at end of file diff --git a/README.md b/README.md index 0871654..6751543 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -eye_of_nemesis_social_cover +eye_of_nemesis_social_cover [![Modrinth Badge](https://img.shields.io/badge/Modrinth-Black?style=social&logo=Modrinth&logoColor=green)](https://modrinth.com/plugin/eye-of-nemesis) [![English Wiki Badge](https://img.shields.io/badge/English-White?style=flat-square&label=Wiki&color=black)](https://github.com/adrianvic/NemesisEye/wiki) @@ -17,8 +17,8 @@ I made this plugin as an effort to preserve a village from my private server. Or 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.X, 26.1.X, 26.2` -- **Project Poseidon/Bukkit** `b1.7.3 (CB1060)` +- **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.kts b/build.gradle.kts index e2d9a2e..488a93d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -59,24 +59,9 @@ mcVersions.forEach { ver -> /* ----------------------------------------- */ 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("compileOnly", "io.papermc.paper:paper-api:1.21.10-R0.1-SNAPSHOT") + add("r1_21CompileOnly", "io.papermc.paper:paper-api:1.21.10-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() } /* ----------------------------------------- */ diff --git a/docs/Nodes.md b/docs/Nodes.md index d5b475b..57cff1d 100644 --- a/docs/Nodes.md +++ b/docs/Nodes.md @@ -1,5 +1,5 @@ # 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. +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]: @@ -31,13 +31,4 @@ Triggered on `InventoryClickEvent` and `PlayerInteractEvent` (only if item is an Triggered on `PlayerMoveEvent`, returns true if player is gliding. ### USE_ENCHANTMENT -Triggered on `BlockBreakEvent` and `onEntityDamageByEntityEvent`, returns true when the used item has an enchantment matching the provided mapping of enchantment-level. - -### FORMBLOCK -Triggered on `BlockFormEvent` (ex. triggers when snow is formed from rain), returns true when the block being formed is in the provided list of materials. - -### ENDERMAN_ATTACK_PLAYER -Triggered on `EndermanAttackPlayerEvent` (from actions other than hitting the Enderman), returns true. - -### TAKE_LECTURN_BOOK -Triggered on `PlayerTakeLecturnBookEvent`, returns true. \ No newline at end of file +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/src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/v1_7_3/events/BlockEventListener.java b/src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/BlockEventListener.java similarity index 88% rename from src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/v1_7_3/events/BlockEventListener.java rename to src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/BlockEventListener.java index b09458f..76fd2d1 100644 --- a/src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/v1_7_3/events/BlockEventListener.java +++ b/src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/BlockEventListener.java @@ -1,4 +1,4 @@ -package io.github.adrianvic.nemesiseye.impl.v1_7_3.events; +package io.github.adrianvic.nemesiseye.impl; import io.github.adrianvic.nemesiseye.Events; import org.bukkit.event.block.BlockBreakEvent; diff --git a/src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/v1_7_3/ConfigurationEx.java b/src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/ConfigurationEx.java similarity index 98% rename from src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/v1_7_3/ConfigurationEx.java rename to src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/ConfigurationEx.java index 6fc8e27..a4b3327 100644 --- a/src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/v1_7_3/ConfigurationEx.java +++ b/src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/ConfigurationEx.java @@ -1,4 +1,4 @@ -package io.github.adrianvic.nemesiseye.impl.v1_7_3; +package io.github.adrianvic.nemesiseye.impl; import io.github.adrianvic.nemesiseye.Nemesis; import org.bukkit.plugin.java.JavaPlugin; diff --git a/src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/v1_7_3/events/EntityEventListener.java b/src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/EntityEventListener.java similarity index 88% rename from src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/v1_7_3/events/EntityEventListener.java rename to src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/EntityEventListener.java index e342969..cf49da1 100644 --- a/src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/v1_7_3/events/EntityEventListener.java +++ b/src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/EntityEventListener.java @@ -1,4 +1,4 @@ -package io.github.adrianvic.nemesiseye.impl.v1_7_3.events; +package io.github.adrianvic.nemesiseye.impl; import io.github.adrianvic.nemesiseye.Events; import org.bukkit.event.entity.EntityDamageByEntityEvent; diff --git a/src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/v1_7_3/Log.java b/src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/Log.java similarity index 95% rename from src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/v1_7_3/Log.java rename to src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/Log.java index e06b33c..ccba8b1 100644 --- a/src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/v1_7_3/Log.java +++ b/src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/Log.java @@ -1,4 +1,4 @@ -package io.github.adrianvic.nemesiseye.impl.v1_7_3; +package io.github.adrianvic.nemesiseye.impl; import static org.bukkit.Bukkit.getServer; diff --git a/src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/v1_7_3/events/PlayerEventListener.java b/src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/PlayerEventListener.java similarity index 84% rename from src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/v1_7_3/events/PlayerEventListener.java rename to src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/PlayerEventListener.java index 2ec8343..b77a56a 100644 --- a/src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/v1_7_3/events/PlayerEventListener.java +++ b/src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/PlayerEventListener.java @@ -1,4 +1,4 @@ -package io.github.adrianvic.nemesiseye.impl.v1_7_3.events; +package io.github.adrianvic.nemesiseye.impl; import io.github.adrianvic.nemesiseye.Events; import org.bukkit.event.player.PlayerInteractEvent; diff --git a/src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/v1_7_3/b1_7_3.java b/src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/b1_7_3.java similarity index 60% rename from src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/v1_7_3/b1_7_3.java rename to src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/b1_7_3.java index 97ad260..19d08fb 100644 --- a/src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/v1_7_3/b1_7_3.java +++ b/src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/b1_7_3.java @@ -1,16 +1,10 @@ -package io.github.adrianvic.nemesiseye.impl.v1_7_3; +package io.github.adrianvic.nemesiseye.impl; import io.github.adrianvic.nemesiseye.Nemesis; -import io.github.adrianvic.nemesiseye.impl.v1_7_3.commands.Eye; -import io.github.adrianvic.nemesiseye.impl.v1_7_3.events.BlockEventListener; -import io.github.adrianvic.nemesiseye.impl.v1_7_3.events.EntityEventListener; -import io.github.adrianvic.nemesiseye.impl.v1_7_3.events.PlayerEventListener; -import io.github.adrianvic.nemesiseye.policy.Action; -import io.github.adrianvic.nemesiseye.policy.NodeHandler; +import io.github.adrianvic.nemesiseye.impl.commands.Eye; 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; @@ -21,7 +15,6 @@ import org.bukkit.plugin.java.JavaPlugin; import java.io.File; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; @@ -70,7 +63,6 @@ public class b1_7_3 implements Glimmer { pm = Nemesis.getInstance().getPluginManager(); pm.registerEvent(Event.Type.ENTITY_DAMAGE, new EntityEventListener(), Event.Priority.Normal, plugin); pm.registerEvent(Event.Type.BLOCK_BREAK, new BlockEventListener(), Event.Priority.Normal, plugin); - pm.registerEvent(Event.Type.BLOCK_PLACE, new BlockEventListener(), Event.Priority.Normal, plugin); pm.registerEvent(Event.Type.PLAYER_INTERACT, new PlayerEventListener(), Event.Priority.Normal, plugin); plugin.getCommand("eye").setExecutor(new Eye()); } @@ -80,43 +72,6 @@ public class b1_7_3 implements Glimmer { return entity.getItemInHand(); } - @Override - public boolean isAir(ItemStack item) { - return item == null || item.getType() == Material.AIR; - } - - @Override - public boolean isGliding(org.bukkit.entity.Player player) { - return false; - } - - @Override - public void setGliding(org.bukkit.entity.Player player, boolean gliding) { - } - - @Override - public boolean hasPermission(org.bukkit.command.CommandSender sender, String permission) { - if (sender instanceof org.bukkit.entity.Player p) { - return p.isOp(); - } - return true; // Console always has permission - } - - @Override - public boolean isArmorEquipAttempt(org.bukkit.event.Event event) { - return false; - } - - @Override - public ItemStack getEquippedItem(org.bukkit.event.Event event) { - return null; - } - - @Override - public Map getExtraHandlers() { - return new HashMap<>(); - } - @Override public void sendMessage(CommandSender commandSender, String text) { String[] lines = text.split("\\r?\\n"); @@ -144,18 +99,4 @@ public class b1_7_3 implements Glimmer { public boolean hasAnyEnchantment(ItemStack itemStack) { return false; } - - @Override - public boolean isArmor(ItemStack item) { - if (item == null || item.getType() == Material.AIR) { - return false; - } - - String name = item.getType().name(); - - return name.endsWith("_HELMET") - || name.endsWith("_CHESTPLATE") - || name.endsWith("_LEGGINGS") - || name.endsWith("_BOOTS"); - } } diff --git a/src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/v1_7_3/commands/Eye.java b/src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/commands/Eye.java similarity index 89% rename from src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/v1_7_3/commands/Eye.java rename to src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/commands/Eye.java index c547c8f..b3db3e5 100644 --- a/src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/v1_7_3/commands/Eye.java +++ b/src/b1_7_3/java/io/github/adrianvic/nemesiseye/impl/commands/Eye.java @@ -1,4 +1,4 @@ -package io.github.adrianvic.nemesiseye.impl.v1_7_3.commands; +package io.github.adrianvic.nemesiseye.impl.commands; import io.github.adrianvic.nemesiseye.commands.EyeCore; import org.bukkit.command.Command; diff --git a/src/main/java/io/github/adrianvic/nemesiseye/DataShifter.java b/src/main/java/io/github/adrianvic/nemesiseye/DataShifter.java index 45ec7b5..ceb0e36 100644 --- a/src/main/java/io/github/adrianvic/nemesiseye/DataShifter.java +++ b/src/main/java/io/github/adrianvic/nemesiseye/DataShifter.java @@ -7,22 +7,13 @@ import java.util.Map; import java.util.regex.Pattern; public class DataShifter { + public static boolean safeMatches(String expression, String against) { String cleanPattern = expression.trim(); Pattern pattern = Pattern.compile(cleanPattern, Pattern.CASE_INSENSITIVE); return pattern.matcher(against).matches(); } - public static boolean safeMatches(List expressions, String against) { - for (String s : expressions) { - if (DataShifter.safeMatches(s, against)) { - return true; - } - } - - return false; - } - public static List parseValueToStringList(List values) { List result = new ArrayList<>(); for (Object o : values) { diff --git a/src/main/java/io/github/adrianvic/nemesiseye/Events.java b/src/main/java/io/github/adrianvic/nemesiseye/Events.java index c452cd6..442bbdc 100644 --- a/src/main/java/io/github/adrianvic/nemesiseye/Events.java +++ b/src/main/java/io/github/adrianvic/nemesiseye/Events.java @@ -1,12 +1,15 @@ package io.github.adrianvic.nemesiseye; import io.github.adrianvic.nemesiseye.policy.Action; -import io.github.adrianvic.nemesiseye.reflection.Glimmer; +import org.bukkit.Material; +import org.bukkit.entity.HumanEntity; import org.bukkit.entity.Player; import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.block.BlockPlaceEvent; -import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryType; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerMoveEvent; import org.bukkit.inventory.ItemStack; @@ -15,10 +18,6 @@ import java.util.List; public class Events { - private static Glimmer g() { - return Nemesis.getInstance().getGlimmer(); - } - public static void onBlockBreak(BlockBreakEvent event) { event.setCancelled( !Validator.can( @@ -32,12 +31,12 @@ public class Events { public static void onInteractionEvent(PlayerInteractEvent event) { ItemStack item = event.getItem(); - if (g().isAir(item)) { + if (item == null || item.getType().isAir()) { return; } // Right-click armor equipping - if (g().isArmor(item) + if (isArmor(item) && !Validator.can(event.getPlayer(), Action.EQUIP, event)) { event.setCancelled(true); return; @@ -45,7 +44,7 @@ public class Events { // Normal item interaction event.setCancelled( - !Validator.can(event.getPlayer(), List.of(Action.INTERACT, Action.INTERACTWITH), event) + !Validator.can(event.getPlayer(), Action.INTERACT, event) ); } @@ -68,17 +67,60 @@ public class Events { } public static void onPlayerMoveEvent(PlayerMoveEvent event) { - if (g().isGliding(event.getPlayer()) + if (event.getPlayer().isGliding() && !Validator.can( event.getPlayer(), List.of(Action.GLYDE), event )) { - g().setGliding(event.getPlayer(), false); + event.getPlayer().setGliding(false); } } - public static void onCreatureSpawnEvent(CreatureSpawnEvent event) { - event.setCancelled(!Validator.can(event.getEntity(), Action.SPAWN, event)); + public static void onInventoryClickEvent(InventoryClickEvent event) { + if (!isArmorEquipAttempt(event)) { + return; + } + + HumanEntity entity = event.getWhoClicked(); + + if (!Validator.can(entity, Action.EQUIP, event)) { + event.setCancelled(true); + } + } + + private static boolean isArmorEquipAttempt(InventoryClickEvent event) { + if (event.getSlotType() == InventoryType.SlotType.ARMOR) { + return true; + } + + if (event.isShiftClick()) { + return isArmor(event.getCurrentItem()); + } + + if (event.getClick() == ClickType.NUMBER_KEY + && event.getSlotType() == InventoryType.SlotType.ARMOR + && event.getWhoClicked() instanceof Player player) { + return isArmor( + player.getInventory().getItem(event.getHotbarButton()) + ); + } + + return false; + } + + private static boolean isArmor(ItemStack item) { + if (item == null || item.getType().isAir()) { + return false; + } + + Material type = item.getType(); + String name = type.name(); + + return name.endsWith("_HELMET") + || name.endsWith("_CHESTPLATE") + || name.endsWith("_LEGGINGS") + || name.endsWith("_BOOTS") + || type == Material.ELYTRA; } } \ No newline at end of file diff --git a/src/main/java/io/github/adrianvic/nemesiseye/ModernEvents.java b/src/main/java/io/github/adrianvic/nemesiseye/ModernEvents.java deleted file mode 100644 index e93f7c8..0000000 --- a/src/main/java/io/github/adrianvic/nemesiseye/ModernEvents.java +++ /dev/null @@ -1,39 +0,0 @@ -package io.github.adrianvic.nemesiseye; - -import com.destroystokyo.paper.event.entity.EndermanAttackPlayerEvent; -import io.github.adrianvic.nemesiseye.policy.Action; -import org.bukkit.entity.HumanEntity; -import org.bukkit.event.block.BlockFormEvent; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.event.player.PlayerTakeLecternBookEvent; - -public class ModernEvents { - public static void onInventoryClickEvent(InventoryClickEvent event) { - if (!Nemesis.getInstance().getGlimmer().isArmorEquipAttempt(event)) { - return; - } - - HumanEntity entity = event.getWhoClicked(); - - if (!Validator.can(entity, Action.EQUIP, event)) { - event.setCancelled(true); - } - } - - public static void onEndermanAttackPlayerEvent(EndermanAttackPlayerEvent event) { - if (!Validator.can(event.getEntity(), Action.ENDERMAN_ATTACK_PLAYER, event)) { - event.setCancelled(true); - } - } - - public static void onBlockFormEvent(BlockFormEvent event) { - boolean canceled = !Validator.can(event.getBlock().getWorld(), Action.FORMBLOCK, event); - event.setCancelled(canceled); - } - - public static void onPlayerTakeLecternBookEvent(PlayerTakeLecternBookEvent event) { - if (!Validator.can(event.getPlayer().getWorld(), Action.TAKE_LECTERN_BOOK, event)) { - event.setCancelled(true); - } - } -} diff --git a/src/main/java/io/github/adrianvic/nemesiseye/Validator.java b/src/main/java/io/github/adrianvic/nemesiseye/Validator.java index 41c1531..9222de5 100644 --- a/src/main/java/io/github/adrianvic/nemesiseye/Validator.java +++ b/src/main/java/io/github/adrianvic/nemesiseye/Validator.java @@ -2,10 +2,7 @@ package io.github.adrianvic.nemesiseye; import io.github.adrianvic.nemesiseye.policy.Action; import io.github.adrianvic.nemesiseye.policy.Policy; -import io.github.adrianvic.nemesiseye.policy.policies.GlobalPolicy; -import org.bukkit.World; import org.bukkit.entity.HumanEntity; -import org.bukkit.entity.LivingEntity; import org.bukkit.event.Event; import java.util.ArrayList; @@ -22,9 +19,12 @@ public class Validator { return true; } - public static boolean can(LivingEntity entity, Action action, Event event) { + public static boolean can(HumanEntity entity, Action action, Event event) { + boolean restricted = false; + boolean allowed = false; + for (Policy policy : getPoliciesForEntity(entity)) { - boolean matches = policy.matches(entity.getWorld(), action, event); + boolean matches = policy.matches(entity, action, event); switch (policy.effect()) { case ALLOW: @@ -40,38 +40,8 @@ public class Validator { return true; } - public static boolean can(World world, Action action, Event event) { - boolean allowed = true; - for (GlobalPolicy policy : getGlobalPolicies()) { - boolean matches = policy.matches(world, action, event); - - switch (policy.effect()) { - case ALLOW: - if (matches) return true; - break; - - case DENY: - if (matches) return false; - break; - } - } - - return allowed; - } - - public static List getGlobalPolicies() { - List ps = Config.getInstance().getPolicies(); - List result = new ArrayList<>(); - - for (Policy policy : ps) { - if (policy instanceof GlobalPolicy p) result.add(p); - } - - return result; - } - - public static List getPoliciesForEntity(LivingEntity entity) { + public static List getPoliciesForEntity(HumanEntity entity) { List ps = Config.getInstance().getPolicies(); List result = new ArrayList<>(); diff --git a/src/main/java/io/github/adrianvic/nemesiseye/commands/EyeCore.java b/src/main/java/io/github/adrianvic/nemesiseye/commands/EyeCore.java index fafdb24..e6583db 100644 --- a/src/main/java/io/github/adrianvic/nemesiseye/commands/EyeCore.java +++ b/src/main/java/io/github/adrianvic/nemesiseye/commands/EyeCore.java @@ -26,9 +26,10 @@ public class EyeCore { commandSender.sendMessage("Unknown command, try '/eye help' to list available commands."); return true; } - else if (glim.hasPermission(commandSender, sub.permission())) { + else if (commandSender.hasPermission(sub.permission())) { return sub.execute(commandSender, Arrays.copyOfRange(strings, 1, strings.length)); } else { + // Nemesis.getInstance().getLogger().info("does not have %s".formatted(sub.permission())); Commands.sendNoPermissionError(commandSender); return true; } @@ -40,15 +41,15 @@ public class EyeCore { if (strings.length == 1) { Map cmds = new HashMap<>(); for (Map.Entry e : Commands.getAll().entrySet()) { - if (glim.hasPermission(commandSender, e.getValue().permission())) { + if (e.getValue().hasPermission(commandSender)) { + cmds.put(e.getKey(), e.getValue()); cmds.put(e.getKey(), e.getValue()); } } return new ArrayList<>(cmds.keySet()); } - Subcommand sub = Commands.get(strings[0].toLowerCase()); - if (sub != null && glim.hasPermission(commandSender, sub.permission())) { + if (sub != null && commandSender.hasPermission(sub.permission())) { return sub.onTabComplete(commandSender, Arrays.copyOfRange(strings, 1, strings.length)); } return List.of(); diff --git a/src/main/java/io/github/adrianvic/nemesiseye/commands/sub/Subcommand.java b/src/main/java/io/github/adrianvic/nemesiseye/commands/sub/Subcommand.java index 00e0c56..3678494 100644 --- a/src/main/java/io/github/adrianvic/nemesiseye/commands/sub/Subcommand.java +++ b/src/main/java/io/github/adrianvic/nemesiseye/commands/sub/Subcommand.java @@ -1,6 +1,5 @@ package io.github.adrianvic.nemesiseye.commands.sub; -import io.github.adrianvic.nemesiseye.Nemesis; import org.bukkit.command.CommandSender; import org.bukkit.permissions.Permission; @@ -14,6 +13,6 @@ public interface Subcommand { List onTabComplete(CommandSender sender, String[] strings); String permission(); default boolean hasPermission(CommandSender sender) { - return Nemesis.getInstance().getGlimmer().hasPermission(sender, permission()); + return sender.hasPermission(permission()); } } \ No newline at end of file diff --git a/src/main/java/io/github/adrianvic/nemesiseye/policy/Action.java b/src/main/java/io/github/adrianvic/nemesiseye/policy/Action.java index ca63c96..b80f6a9 100644 --- a/src/main/java/io/github/adrianvic/nemesiseye/policy/Action.java +++ b/src/main/java/io/github/adrianvic/nemesiseye/policy/Action.java @@ -2,16 +2,11 @@ package io.github.adrianvic.nemesiseye.policy; public enum Action { INTERACT, - INTERACTWITH, BREAK, HIT, // TODO CRAFT, EQUIP, PLACE, USE_ENCHANTMENT, - GLYDE, - SPAWN, - ENDERMAN_ATTACK_PLAYER, - FORMBLOCK, - TAKE_LECTERN_BOOK + GLYDE } diff --git a/src/main/java/io/github/adrianvic/nemesiseye/policy/NodeHandler.java b/src/main/java/io/github/adrianvic/nemesiseye/policy/NodeHandler.java index e2a6f7a..31fa568 100644 --- a/src/main/java/io/github/adrianvic/nemesiseye/policy/NodeHandler.java +++ b/src/main/java/io/github/adrianvic/nemesiseye/policy/NodeHandler.java @@ -1,8 +1,8 @@ package io.github.adrianvic.nemesiseye.policy; -import org.bukkit.World; +import org.bukkit.entity.HumanEntity; import org.bukkit.event.Event; public interface NodeHandler { - boolean check(World world, PolicyNode node, Action action, Event event); + boolean check(HumanEntity entity, PolicyNode node, Action action, Event event); } \ No newline at end of file diff --git a/src/main/java/io/github/adrianvic/nemesiseye/policy/NodeHandlers.java b/src/main/java/io/github/adrianvic/nemesiseye/policy/NodeHandlers.java index 2bc4f0d..465747e 100644 --- a/src/main/java/io/github/adrianvic/nemesiseye/policy/NodeHandlers.java +++ b/src/main/java/io/github/adrianvic/nemesiseye/policy/NodeHandlers.java @@ -1,36 +1,24 @@ package io.github.adrianvic.nemesiseye.policy; -import io.github.adrianvic.nemesiseye.Nemesis; import io.github.adrianvic.nemesiseye.policy.handlers.*; -import io.github.adrianvic.nemesiseye.policy.handlers.generic.Boolean; import java.util.HashMap; import java.util.Map; public class NodeHandlers { private static final Map handlers = new HashMap<>(); - + static { - handlers.put(Action.HIT, new UseItem()); - handlers.put(Action.PLACE, new BePlaced()); - handlers.put(Action.INTERACT, new UseItem()); - handlers.put(Action.USE_ENCHANTMENT, new UseEnchantment()); - handlers.put(Action.GLYDE, new Boolean()); - handlers.put(Action.EQUIP, new Equip()); - handlers.put(Action.SPAWN, new Spawn()); - handlers.put(Action.BREAK, new UseItem()); // TODO: implement place handler - handlers.put(Action.INTERACTWITH, new InteractWith()); - handlers.put(Action.ENDERMAN_ATTACK_PLAYER, new Boolean()); - handlers.put(Action.TAKE_LECTERN_BOOK, new Boolean()); + handlers.put(Action.HIT, new useItem()); + handlers.put(Action.PLACE, new bePlaced()); + handlers.put(Action.INTERACT, new useItem()); + handlers.put(Action.USE_ENCHANTMENT, new useEnchantment()); + handlers.put(Action.GLYDE, new glyde()); + handlers.put(Action.EQUIP, new equip()); + handlers.put(Action.BREAK, new useItem()); // TODO: implement place handler } - + public static NodeHandler get(Action type) { - NodeHandler handler = handlers.get(type); - - if (handler == null) { - handler = Nemesis.getInstance().getGlimmer().getExtraHandlers().get(type); - } - - return handler; + return handlers.get(type); } } diff --git a/src/main/java/io/github/adrianvic/nemesiseye/policy/Policy.java b/src/main/java/io/github/adrianvic/nemesiseye/policy/Policy.java index eba8457..5992433 100644 --- a/src/main/java/io/github/adrianvic/nemesiseye/policy/Policy.java +++ b/src/main/java/io/github/adrianvic/nemesiseye/policy/Policy.java @@ -1,7 +1,6 @@ package io.github.adrianvic.nemesiseye.policy; -import org.bukkit.World; -import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.HumanEntity; import org.bukkit.event.Event; import java.util.List; @@ -10,7 +9,7 @@ public interface Policy { String name(); List nodes(); boolean policyAllowList(); - boolean applies(LivingEntity entity); + boolean applies(HumanEntity entity); Effect effect(); int weight(); List worlds(); @@ -19,13 +18,13 @@ public interface Policy { nodes().add(node); } - default boolean matches(World world, Action action, Event event) { - if (!worlds().contains(world.getName())) { + default boolean matches(HumanEntity entity, Action action, Event event) { + if (!worlds().contains(entity.getWorld().getName())) { return false; } for (PolicyNode node : nodes()) { - if (node.matches(world, action, event)) { + if (node.matches(entity, action, event)) { return true; } } diff --git a/src/main/java/io/github/adrianvic/nemesiseye/policy/PolicyNode.java b/src/main/java/io/github/adrianvic/nemesiseye/policy/PolicyNode.java index 0b9e77d..c87f916 100644 --- a/src/main/java/io/github/adrianvic/nemesiseye/policy/PolicyNode.java +++ b/src/main/java/io/github/adrianvic/nemesiseye/policy/PolicyNode.java @@ -1,7 +1,7 @@ package io.github.adrianvic.nemesiseye.policy; import io.github.adrianvic.nemesiseye.DataShifter; -import org.bukkit.World; +import org.bukkit.entity.HumanEntity; import org.bukkit.event.Event; import java.util.ArrayList; @@ -18,28 +18,27 @@ public record PolicyNode(List actions, List values) { List nodeActions = new ArrayList<>(); List nodeValues = new ArrayList<>(); - if (rawNode.getKey() instanceof List rawTypes && (rawNode.getValue() == null || rawNode.getValue() instanceof Map)) { + if (rawNode.getKey() instanceof List rawTypes && rawNode.getValue() instanceof Map rawNodeValues) { for (Object rawType : rawTypes) { - if (rawType instanceof String rts && !rts.isEmpty() && DataShifter.enumOrDefault(Action.class, rts, null) != null) { + if (rawType instanceof String rts && !rts.isEmpty() && !(rts == null) && DataShifter.enumOrDefault(Action.class, rts, null) != null) { nodeActions.add(DataShifter.enumOrDefault(Action.class, rts, null)); } } - - if (rawNode.getValue() instanceof Map rawNodeValues) { - Map semiParsedNodeValue = new HashMap<>(); - for (Map.Entry rawNodeValueEntries : rawNodeValues.entrySet()) { - if (rawNodeValueEntries.getKey() instanceof String stringKey) { - semiParsedNodeValue.put(stringKey, rawNodeValueEntries.getValue()); - } + Map semiParsedNodeValue = new HashMap<>(); + for (Map.Entry rawNodeValueEntries : rawNodeValues.entrySet()) { + if (rawNodeValueEntries.getKey() instanceof String stringKey) { + semiParsedNodeValue.put(stringKey, rawNodeValueEntries.getValue()); } + } - if (semiParsedNodeValue.get("values") instanceof List l) { - nodeValues.addAll(l); + if (semiParsedNodeValue.get("values") instanceof List l) { + for (Object v : l) { + nodeValues.add(v); } } } - if (!nodeActions.isEmpty()) { + if (!nodeActions.isEmpty() && !nodeValues.isEmpty()) { PolicyNode newNode = new PolicyNode(nodeActions, nodeValues); nodes.add(newNode); } @@ -56,7 +55,7 @@ public record PolicyNode(List actions, List values) { return handlers; } - public boolean matches(World world, Action action, Event event) { + public boolean matches(HumanEntity entity, Action action, Event event) { if (!actions.contains(action)) { return false; } @@ -67,6 +66,7 @@ public record PolicyNode(List actions, List values) { return false; } - return handler.check(world, this, action, event); + boolean result = handler.check(entity, this, action, event); + return result; } } \ No newline at end of file diff --git a/src/main/java/io/github/adrianvic/nemesiseye/policy/PolicyParser.java b/src/main/java/io/github/adrianvic/nemesiseye/policy/PolicyParser.java index 4e29e18..8050873 100644 --- a/src/main/java/io/github/adrianvic/nemesiseye/policy/PolicyParser.java +++ b/src/main/java/io/github/adrianvic/nemesiseye/policy/PolicyParser.java @@ -34,11 +34,8 @@ public interface PolicyParser { if (rawNodes instanceof List list) { for (Object o : list) { - if (o instanceof Map map) { + if (o instanceof Map map) nodeList.add((Map) map); - } else if (o instanceof List actions) { - nodeList.add(Map.of(actions, Map.of())); - } } } diff --git a/src/main/java/io/github/adrianvic/nemesiseye/policy/handlers/FormBlock.java b/src/main/java/io/github/adrianvic/nemesiseye/policy/handlers/FormBlock.java deleted file mode 100644 index 56bfc45..0000000 --- a/src/main/java/io/github/adrianvic/nemesiseye/policy/handlers/FormBlock.java +++ /dev/null @@ -1,28 +0,0 @@ -package io.github.adrianvic.nemesiseye.policy.handlers; - -import io.github.adrianvic.nemesiseye.DataShifter; -import io.github.adrianvic.nemesiseye.policy.Action; -import io.github.adrianvic.nemesiseye.policy.NodeHandler; -import io.github.adrianvic.nemesiseye.policy.PolicyNode; -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.event.Event; -import org.bukkit.event.block.BlockFormEvent; - -import java.util.List; - -public class FormBlock implements NodeHandler { - @Override - public boolean check(World world, PolicyNode node, Action action, Event event) { - if (event instanceof BlockFormEvent e) { - Material material = e.getNewState().getType(); - - String type = material.toString(); - List parsedValue = DataShifter.parseValueToStringList(node.values()); - - return DataShifter.safeMatches(parsedValue, type); - } - - return false; - } -} diff --git a/src/main/java/io/github/adrianvic/nemesiseye/policy/handlers/InteractWith.java b/src/main/java/io/github/adrianvic/nemesiseye/policy/handlers/InteractWith.java deleted file mode 100644 index 33d35eb..0000000 --- a/src/main/java/io/github/adrianvic/nemesiseye/policy/handlers/InteractWith.java +++ /dev/null @@ -1,30 +0,0 @@ -package io.github.adrianvic.nemesiseye.policy.handlers; - -import io.github.adrianvic.nemesiseye.DataShifter; -import io.github.adrianvic.nemesiseye.Nemesis; -import io.github.adrianvic.nemesiseye.policy.Action; -import io.github.adrianvic.nemesiseye.policy.NodeHandler; -import io.github.adrianvic.nemesiseye.policy.PolicyNode; -import io.github.adrianvic.nemesiseye.reflection.Glimmer; -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.event.Event; -import org.bukkit.event.player.PlayerInteractEvent; - -import java.util.List; - -public class InteractWith implements NodeHandler { - @Override - public boolean check(World world, PolicyNode node, Action action, Event event) { - if (event instanceof PlayerInteractEvent e) { - Material material = e.getMaterial(); - - String type = material.toString(); - List parsedValue = DataShifter.parseValueToStringList(node.values()); - - return DataShifter.safeMatches(parsedValue, type); - } - - return false; - } -} diff --git a/src/main/java/io/github/adrianvic/nemesiseye/policy/handlers/Spawn.java b/src/main/java/io/github/adrianvic/nemesiseye/policy/handlers/Spawn.java deleted file mode 100644 index cde4d9d..0000000 --- a/src/main/java/io/github/adrianvic/nemesiseye/policy/handlers/Spawn.java +++ /dev/null @@ -1,26 +0,0 @@ -package io.github.adrianvic.nemesiseye.policy.handlers; - -import io.github.adrianvic.nemesiseye.DataShifter; -import io.github.adrianvic.nemesiseye.policy.Action; -import io.github.adrianvic.nemesiseye.policy.NodeHandler; -import io.github.adrianvic.nemesiseye.policy.PolicyNode; -import org.bukkit.World; -import org.bukkit.event.Event; -import org.bukkit.event.entity.EntityEvent; - -import java.util.List; - -public class Spawn implements NodeHandler { - - @Override - public boolean check(World world, PolicyNode node, Action action, Event event) { - if (event instanceof EntityEvent e) { - String type = e.getEntity().getType().name(); - List parsedValue = DataShifter.parseValueToStringList(node.values()); - - return DataShifter.safeMatches(parsedValue, type); - } - - return false; - } -} diff --git a/src/main/java/io/github/adrianvic/nemesiseye/policy/handlers/UseEnchantment.java b/src/main/java/io/github/adrianvic/nemesiseye/policy/handlers/UseEnchantment.java deleted file mode 100644 index f329e48..0000000 --- a/src/main/java/io/github/adrianvic/nemesiseye/policy/handlers/UseEnchantment.java +++ /dev/null @@ -1,33 +0,0 @@ -package io.github.adrianvic.nemesiseye.policy.handlers; - -import io.github.adrianvic.nemesiseye.DataShifter; -import io.github.adrianvic.nemesiseye.Nemesis; -import io.github.adrianvic.nemesiseye.policy.Action; -import io.github.adrianvic.nemesiseye.policy.NodeHandler; -import io.github.adrianvic.nemesiseye.policy.PolicyNode; -import io.github.adrianvic.nemesiseye.reflection.Glimmer; -import org.bukkit.World; -import org.bukkit.entity.HumanEntity; -import org.bukkit.event.Event; -import org.bukkit.event.entity.EntityEvent; -import org.bukkit.inventory.ItemStack; - -public class UseEnchantment implements NodeHandler { - private final Glimmer glim = Nemesis.getInstance().getGlimmer(); - - @Override - public boolean check(World world, PolicyNode node, Action action, Event event) { - if (event instanceof EntityEvent entityEvent && entityEvent.getEntity() instanceof HumanEntity e) { - ItemStack item = glim.getItemInMainHandHumanEntity(e); - - if (glim.isAir(item)) return false; - if (!glim.hasItemMeta(item)) return false; - if (!glim.hasAnyEnchantment(item)) return false; - - return glim.hasEnchantment(item, - DataShifter.parseValueToStringMap(node.values())); - } - - return false; - } -} diff --git a/src/main/java/io/github/adrianvic/nemesiseye/policy/handlers/UseItem.java b/src/main/java/io/github/adrianvic/nemesiseye/policy/handlers/UseItem.java deleted file mode 100644 index 545adfe..0000000 --- a/src/main/java/io/github/adrianvic/nemesiseye/policy/handlers/UseItem.java +++ /dev/null @@ -1,34 +0,0 @@ -package io.github.adrianvic.nemesiseye.policy.handlers; - -import io.github.adrianvic.nemesiseye.DataShifter; -import io.github.adrianvic.nemesiseye.Nemesis; -import io.github.adrianvic.nemesiseye.policy.Action; -import io.github.adrianvic.nemesiseye.policy.NodeHandler; -import io.github.adrianvic.nemesiseye.policy.PolicyNode; -import io.github.adrianvic.nemesiseye.reflection.Glimmer; -import org.bukkit.World; -import org.bukkit.entity.HumanEntity; -import org.bukkit.event.Event; -import org.bukkit.event.entity.EntityEvent; - -import java.util.List; - -public class UseItem implements NodeHandler { - - private final Glimmer glim = Nemesis.getInstance().getGlimmer(); - - @Override - public boolean check(World world, PolicyNode node, Action action, Event event) { - if (event instanceof EntityEvent entityEvent && entityEvent.getEntity() instanceof HumanEntity e) { - org.bukkit.inventory.ItemStack item = glim.getItemInMainHandHumanEntity(e); - if (glim.isAir(item)) return false; - - String type = item.getType().toString(); - List parsedValue = DataShifter.parseValueToStringList(node.values()); - - return DataShifter.safeMatches(parsedValue, type); - } - - return false; - } -} diff --git a/src/main/java/io/github/adrianvic/nemesiseye/policy/handlers/BePlaced.java b/src/main/java/io/github/adrianvic/nemesiseye/policy/handlers/bePlaced.java similarity index 58% rename from src/main/java/io/github/adrianvic/nemesiseye/policy/handlers/BePlaced.java rename to src/main/java/io/github/adrianvic/nemesiseye/policy/handlers/bePlaced.java index f892302..edf5d7c 100644 --- a/src/main/java/io/github/adrianvic/nemesiseye/policy/handlers/BePlaced.java +++ b/src/main/java/io/github/adrianvic/nemesiseye/policy/handlers/bePlaced.java @@ -4,22 +4,22 @@ import io.github.adrianvic.nemesiseye.DataShifter; import io.github.adrianvic.nemesiseye.policy.Action; import io.github.adrianvic.nemesiseye.policy.NodeHandler; import io.github.adrianvic.nemesiseye.policy.PolicyNode; -import org.bukkit.World; +import org.bukkit.entity.HumanEntity; import org.bukkit.event.Event; import org.bukkit.event.block.BlockPlaceEvent; -import java.util.List; - -public class BePlaced implements NodeHandler { +public class bePlaced implements NodeHandler { @Override - public boolean check(World world, PolicyNode node, Action action, Event event) { + public boolean check(HumanEntity entity, PolicyNode node, Action action, Event event) { if (event instanceof BlockPlaceEvent bpe) { String type = bpe.getBlock().getType().toString(); - List parsedValue = DataShifter.parseValueToStringList(node.values()); - return DataShifter.safeMatches(parsedValue, type); + for (String s : DataShifter.parseValueToStringList(node.values())) { + if (DataShifter.safeMatches(s, type)) { + return true; + } + } } - return false; } } diff --git a/src/main/java/io/github/adrianvic/nemesiseye/policy/handlers/equip.java b/src/main/java/io/github/adrianvic/nemesiseye/policy/handlers/equip.java new file mode 100644 index 0000000..88bb6b6 --- /dev/null +++ b/src/main/java/io/github/adrianvic/nemesiseye/policy/handlers/equip.java @@ -0,0 +1,84 @@ +package io.github.adrianvic.nemesiseye.policy.handlers; + +import com.destroystokyo.paper.event.player.PlayerArmorChangeEvent; +import io.github.adrianvic.nemesiseye.DataShifter; +import io.github.adrianvic.nemesiseye.policy.Action; +import io.github.adrianvic.nemesiseye.policy.NodeHandler; +import io.github.adrianvic.nemesiseye.policy.PolicyNode; +import org.bukkit.entity.HumanEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryType; +import org.bukkit.inventory.ItemStack; + +public class equip implements NodeHandler { + + @Override + public boolean check(HumanEntity entity, PolicyNode node, Action action, Event event) { + ItemStack item = null; + + if (event instanceof PlayerArmorChangeEvent e) { + // Right click equip, dispenser equip, etc... + item = e.getNewItem(); + } + + else if (event instanceof InventoryClickEvent e) { + InventoryType.SlotType slotType = e.getSlotType(); + + // Number key swap into armor slot + if (e.getClick() == ClickType.NUMBER_KEY + && slotType == InventoryType.SlotType.ARMOR + && entity instanceof Player player) { + item = player.getInventory().getItem(e.getHotbarButton()); + } + + // Shift click armor from inventory + else if (e.isShiftClick()) { + ItemStack current = e.getCurrentItem(); + + if (isArmor(current)) { + item = current; + } + } + + // Cursor click onto armor slot + else if (slotType == InventoryType.SlotType.ARMOR) { + ItemStack cursor = e.getCursor(); + + if (isArmor(cursor)) { + item = cursor; + } + } + } + + if (!isArmor(item)) { + return false; + } + + String type = item.getType().name(); + + for (String s : DataShifter.parseValueToStringList(node.values())) { + if (DataShifter.safeMatches(s, type)) { + return true; + } + } + + return false; + } + + private boolean isArmor(ItemStack item) { + if (item == null || item.getType().isAir()) { + return false; + } + + String name = item.getType().name(); + + return name.endsWith("_HELMET") + || name.endsWith("_CHESTPLATE") + || name.endsWith("_LEGGINGS") + || name.endsWith("_BOOTS") + || item.getType() == org.bukkit.Material.ELYTRA; + } +} \ No newline at end of file diff --git a/src/main/java/io/github/adrianvic/nemesiseye/policy/handlers/generic/Boolean.java b/src/main/java/io/github/adrianvic/nemesiseye/policy/handlers/glyde.java similarity index 51% rename from src/main/java/io/github/adrianvic/nemesiseye/policy/handlers/generic/Boolean.java rename to src/main/java/io/github/adrianvic/nemesiseye/policy/handlers/glyde.java index 2b09322..dcce855 100644 --- a/src/main/java/io/github/adrianvic/nemesiseye/policy/handlers/generic/Boolean.java +++ b/src/main/java/io/github/adrianvic/nemesiseye/policy/handlers/glyde.java @@ -1,14 +1,14 @@ -package io.github.adrianvic.nemesiseye.policy.handlers.generic; +package io.github.adrianvic.nemesiseye.policy.handlers; import io.github.adrianvic.nemesiseye.policy.Action; import io.github.adrianvic.nemesiseye.policy.NodeHandler; import io.github.adrianvic.nemesiseye.policy.PolicyNode; -import org.bukkit.World; +import org.bukkit.entity.HumanEntity; import org.bukkit.event.Event; -public class Boolean implements NodeHandler { +public class glyde implements NodeHandler { @Override - public boolean check(World world, PolicyNode node, Action action, Event event) { + public boolean check(HumanEntity entity, PolicyNode node, Action action, Event event) { return true; } } diff --git a/src/main/java/io/github/adrianvic/nemesiseye/policy/handlers/Equip.java b/src/main/java/io/github/adrianvic/nemesiseye/policy/handlers/useEnchantment.java similarity index 51% rename from src/main/java/io/github/adrianvic/nemesiseye/policy/handlers/Equip.java rename to src/main/java/io/github/adrianvic/nemesiseye/policy/handlers/useEnchantment.java index 9b95756..5fe3ae0 100644 --- a/src/main/java/io/github/adrianvic/nemesiseye/policy/handlers/Equip.java +++ b/src/main/java/io/github/adrianvic/nemesiseye/policy/handlers/useEnchantment.java @@ -6,26 +6,23 @@ import io.github.adrianvic.nemesiseye.policy.Action; import io.github.adrianvic.nemesiseye.policy.NodeHandler; import io.github.adrianvic.nemesiseye.policy.PolicyNode; import io.github.adrianvic.nemesiseye.reflection.Glimmer; -import org.bukkit.World; +import org.bukkit.entity.HumanEntity; import org.bukkit.event.Event; import org.bukkit.inventory.ItemStack; -import java.util.List; - -public class Equip implements NodeHandler { +public class useEnchantment implements NodeHandler { private final Glimmer glim = Nemesis.getInstance().getGlimmer(); @Override - public boolean check(World world, PolicyNode node, Action action, Event event) { - ItemStack item = glim.getEquippedItem(event); + public boolean check(HumanEntity entity, PolicyNode node, Action action, Event event) { + ItemStack item = glim.getItemInMainHandHumanEntity(entity); - if (!glim.isArmor(item)) { - return false; - } + if (!glim.hasItemMeta(item)) return false; + if (!glim.hasAnyEnchantment(item)) return false; - String type = item.getType().name(); - List parsedValue = DataShifter.parseValueToStringList(node.values()); + boolean matches = glim.hasEnchantment(item, + DataShifter.parseValueToStringMap(node.values())); - return DataShifter.safeMatches(parsedValue, type); + return matches; } -} \ No newline at end of file +} diff --git a/src/main/java/io/github/adrianvic/nemesiseye/policy/handlers/useItem.java b/src/main/java/io/github/adrianvic/nemesiseye/policy/handlers/useItem.java new file mode 100644 index 0000000..6009407 --- /dev/null +++ b/src/main/java/io/github/adrianvic/nemesiseye/policy/handlers/useItem.java @@ -0,0 +1,28 @@ +package io.github.adrianvic.nemesiseye.policy.handlers; + +import io.github.adrianvic.nemesiseye.DataShifter; +import io.github.adrianvic.nemesiseye.Nemesis; +import io.github.adrianvic.nemesiseye.policy.Action; +import io.github.adrianvic.nemesiseye.policy.NodeHandler; +import io.github.adrianvic.nemesiseye.policy.PolicyNode; +import io.github.adrianvic.nemesiseye.reflection.Glimmer; +import org.bukkit.entity.HumanEntity; +import org.bukkit.event.Event; + +public class useItem implements NodeHandler { + + private final Glimmer glim = Nemesis.getInstance().getGlimmer(); + + @Override + public boolean check(HumanEntity entity, PolicyNode node, Action action, Event event) { + String type = glim.getItemInMainHandHumanEntity(entity).getType().toString(); + + for (String s : DataShifter.parseValueToStringList(node.values())) { + if (DataShifter.safeMatches(s, type)) { + return true; + } + } + + return false; + } +} diff --git a/src/main/java/io/github/adrianvic/nemesiseye/policy/policies/Core.java b/src/main/java/io/github/adrianvic/nemesiseye/policy/policies/Core.java index 7e85467..8476fda 100644 --- a/src/main/java/io/github/adrianvic/nemesiseye/policy/policies/Core.java +++ b/src/main/java/io/github/adrianvic/nemesiseye/policy/policies/Core.java @@ -4,13 +4,12 @@ import io.github.adrianvic.nemesiseye.policy.Effect; import io.github.adrianvic.nemesiseye.policy.Policy; import io.github.adrianvic.nemesiseye.policy.PolicyNode; import org.bukkit.entity.HumanEntity; -import org.bukkit.entity.LivingEntity; import java.util.List; public record Core(String name, List worlds, List nodes, boolean nodeAllowlist, boolean policyAllowList, Effect effect, int weight) implements Policy { @Override - public boolean applies(LivingEntity entity) { + public boolean applies(HumanEntity entity) { return false; } } \ No newline at end of file diff --git a/src/main/java/io/github/adrianvic/nemesiseye/policy/policies/GlobalPolicy.java b/src/main/java/io/github/adrianvic/nemesiseye/policy/policies/GlobalPolicy.java index 127430c..7080ea8 100644 --- a/src/main/java/io/github/adrianvic/nemesiseye/policy/policies/GlobalPolicy.java +++ b/src/main/java/io/github/adrianvic/nemesiseye/policy/policies/GlobalPolicy.java @@ -4,12 +4,11 @@ import io.github.adrianvic.nemesiseye.policy.Effect; import io.github.adrianvic.nemesiseye.policy.Policy; import io.github.adrianvic.nemesiseye.policy.PolicyNode; import org.bukkit.entity.HumanEntity; -import org.bukkit.entity.LivingEntity; import java.util.List; public record GlobalPolicy(String name, List worlds, List nodes, boolean policyAllowList, Effect effect, int weight) implements Policy { - public boolean applies(LivingEntity entity) { + public boolean applies(HumanEntity entity) { return true; } } diff --git a/src/main/java/io/github/adrianvic/nemesiseye/policy/policies/LocationPolicy.java b/src/main/java/io/github/adrianvic/nemesiseye/policy/policies/LocationPolicy.java index 255e433..5765535 100644 --- a/src/main/java/io/github/adrianvic/nemesiseye/policy/policies/LocationPolicy.java +++ b/src/main/java/io/github/adrianvic/nemesiseye/policy/policies/LocationPolicy.java @@ -5,13 +5,12 @@ import io.github.adrianvic.nemesiseye.policy.Policy; import io.github.adrianvic.nemesiseye.policy.PolicyNode; import io.github.adrianvic.nemesiseye.reflection.Glimmer; import org.bukkit.entity.HumanEntity; -import org.bukkit.entity.LivingEntity; import java.util.List; public record LocationPolicy(String name, List worlds, List locations, List nodes, boolean nodeAllowlist, boolean policyAllowList, Effect effect, int weight) implements Policy { @Override - public boolean applies(LivingEntity entity) { + public boolean applies(HumanEntity entity) { for (Glimmer.Box box : locations) { if (box.contains(entity.getLocation().toVector(), entity.getWorld())) { return !policyAllowList; diff --git a/src/main/java/io/github/adrianvic/nemesiseye/policy/policies/PermissionPolicy.java b/src/main/java/io/github/adrianvic/nemesiseye/policy/policies/PermissionPolicy.java index 309ce07..1c952ac 100644 --- a/src/main/java/io/github/adrianvic/nemesiseye/policy/policies/PermissionPolicy.java +++ b/src/main/java/io/github/adrianvic/nemesiseye/policy/policies/PermissionPolicy.java @@ -1,20 +1,18 @@ package io.github.adrianvic.nemesiseye.policy.policies; -import io.github.adrianvic.nemesiseye.Nemesis; import io.github.adrianvic.nemesiseye.policy.Effect; import io.github.adrianvic.nemesiseye.policy.Policy; import io.github.adrianvic.nemesiseye.policy.PolicyNode; import org.bukkit.entity.HumanEntity; -import org.bukkit.entity.LivingEntity; import java.util.List; public record PermissionPolicy(String name, List worlds, List permissions, List nodes, boolean policyAllowList, Effect effect, int weight) implements Policy { @Override - public boolean applies(LivingEntity entity) { + public boolean applies(HumanEntity entity) { for (String perm : permissions) { - if (Nemesis.getInstance().getGlimmer().hasPermission(entity, perm)) { + if (entity.hasPermission(perm)) { return true; } } diff --git a/src/main/java/io/github/adrianvic/nemesiseye/policy/policies/PlayerNamePolicy.java b/src/main/java/io/github/adrianvic/nemesiseye/policy/policies/PlayerNamePolicy.java index ba40e4b..8eeae4b 100644 --- a/src/main/java/io/github/adrianvic/nemesiseye/policy/policies/PlayerNamePolicy.java +++ b/src/main/java/io/github/adrianvic/nemesiseye/policy/policies/PlayerNamePolicy.java @@ -4,14 +4,13 @@ import io.github.adrianvic.nemesiseye.policy.Effect; import io.github.adrianvic.nemesiseye.policy.Policy; import io.github.adrianvic.nemesiseye.policy.PolicyNode; import org.bukkit.entity.HumanEntity; -import org.bukkit.entity.LivingEntity; import java.util.List; public record PlayerNamePolicy(String name, List worlds, List playerName, List nodes, Effect effect, boolean policyAllowList, int weight) implements Policy { @Override - public boolean applies(LivingEntity entity) { + public boolean applies(HumanEntity entity) { if (playerName.contains(entity.getName())) { return !policyAllowList(); } else { diff --git a/src/main/java/io/github/adrianvic/nemesiseye/reflection/Glimmer.java b/src/main/java/io/github/adrianvic/nemesiseye/reflection/Glimmer.java index a8ba767..dec3092 100644 --- a/src/main/java/io/github/adrianvic/nemesiseye/reflection/Glimmer.java +++ b/src/main/java/io/github/adrianvic/nemesiseye/reflection/Glimmer.java @@ -1,7 +1,5 @@ package io.github.adrianvic.nemesiseye.reflection; -import io.github.adrianvic.nemesiseye.policy.Action; -import io.github.adrianvic.nemesiseye.policy.NodeHandler; import io.github.adrianvic.nemesiseye.policy.Policy; import org.bukkit.Location; import org.bukkit.World; @@ -28,22 +26,8 @@ public interface Glimmer { boolean hasItemMeta(ItemStack item); boolean hasEnchantment(ItemStack item, Map valuesmap); boolean hasAnyEnchantment(ItemStack itemStack); - boolean isArmor(ItemStack item); - boolean isAir(ItemStack item); ItemStack getItemInMainHandHumanEntity(HumanEntity entity); - // Players - boolean isGliding(org.bukkit.entity.Player player); - void setGliding(org.bukkit.entity.Player player, boolean gliding); - boolean hasPermission(org.bukkit.command.CommandSender sender, String permission); - - // Events - boolean isArmorEquipAttempt(org.bukkit.event.Event event); - ItemStack getEquippedItem(org.bukkit.event.Event event); - - // Handlers - Map getExtraHandlers(); - // Commands void sendMessage(CommandSender commandSender, String text); diff --git a/src/main/java/io/github/adrianvic/nemesiseye/reflection/VersionMatcher.java b/src/main/java/io/github/adrianvic/nemesiseye/reflection/VersionMatcher.java index 1e83f2c..7852cd5 100644 --- a/src/main/java/io/github/adrianvic/nemesiseye/reflection/VersionMatcher.java +++ b/src/main/java/io/github/adrianvic/nemesiseye/reflection/VersionMatcher.java @@ -3,39 +3,145 @@ package io.github.adrianvic.nemesiseye.reflection; import io.github.adrianvic.nemesiseye.DataShifter; import org.bukkit.Bukkit; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + public class VersionMatcher { public VersionMatcher() {} - public Glimmer loadGlim() { - String rawVersion = null; - try { - rawVersion = Bukkit.getMinecraftVersion(); - } catch (NoSuchMethodError ignored) {} + private record Entry(String pattern, String classSuffix) {} - if (rawVersion == null || rawVersion.isEmpty()) { - String v = Bukkit.getVersion(); // e.g. "git-Bukkit-0.0.0-1060-... (MC: 1.7.3)" - int start = v.lastIndexOf("MC: "); - if (start != -1) { - rawVersion = v.substring(start + 4, v.length() - 1); - } else { - rawVersion = "unknown"; + public String getVersion(String type, String serverVersion) { + if (type == null || serverVersion == null) { + return ""; + } + + Map> map = populateMap(); + List entries = map.get(type.toLowerCase()); + if (entries == null || entries.isEmpty()) { + return ""; + } + + for (Entry e : entries) { + if (DataShifter.safeMatches(e.pattern, serverVersion)) { + return e.pattern + "|" + e.classSuffix; } } - String impl = DataShifter.safeMatches("^1\\.7\\.3$", rawVersion) - ? "b1_7_3" - : "r1_21"; + List sorted = new ArrayList<>(entries); + Collections.sort(sorted, (a, b) -> compareVersions(a.pattern, b.pattern)); - String subPkg = impl.equals("b1_7_3") ? "v1_7_3" : "v1_21"; - Glimmer glim = tryInstantiate( - "io.github.adrianvic.nemesiseye.impl." + subPkg + "." + impl); + Entry oldest = sorted.get(0); + Entry newest = sorted.get(sorted.size() - 1); - if (glim == null) { - throw new IllegalStateException("Missing implementation: " + impl); + int cmpOldest = compareVersions(serverVersion, oldest.pattern); + int cmpNewest = compareVersions(serverVersion, newest.pattern); + + if (cmpOldest < 0) { + return oldest.pattern + "|" + oldest.classSuffix; + } else if (cmpNewest > 0) { + return newest.pattern + "|" + newest.classSuffix; } - return glim; + // should not happen because we already tried all patterns + return newest.pattern + "|" + newest.classSuffix; + } + + private Map> populateMap() { + Map> map = new HashMap<>(); + + // RELEASE patterns, newest first (order does not matter for matching) + map.put("release", List.of( + new Entry("^1\\.21\\..*$", "r1_21") + )); + + // BETA patterns + map.put("beta", List.of( + new Entry("^1\\.7\\.3$", "b1_7_3") + )); + + return map; + } + + private int compareVersions(String v1, String v2) { + String clean1 = v1.replaceAll("[^0-9.]", ""); + String clean2 = v2.replaceAll("[^0-9.]", ""); + + String[] a1 = clean1.split("\\."); + String[] a2 = clean2.split("\\."); + + int len = Math.max(a1.length, a2.length); + for (int i = 0; i < len; i++) { + int n1 = i < a1.length ? parseInt(a1[i]) : 0; + int n2 = i < a2.length ? parseInt(a2[i]) : 0; + if (n1 != n2) { + return n1 - n2; + } + } + return 0; + } + + private int parseInt(String s) { + try { + return Integer.parseInt(s); + } catch (NumberFormatException e) { + return 0; + } + } + + public Glimmer loadGlim() { + String rawVersion; + try { + rawVersion = Bukkit.getMinecraftVersion(); // returns something like "1.21.10" + } catch (NoSuchMethodError e) { + return betaLoadGlim(); + } + + String matchInfo = getVersion("release", rawVersion); + if (matchInfo.isEmpty()) { + // TODO: Should change to something more robust, it's not beta since we have Bukkit.getMinecraftVersion() + return betaLoadGlim(); + } + + // split the returned string: "pattern|classSuffix" + String[] partsInfo = matchInfo.split("\\|"); + String classSuffix = partsInfo[1]; // e.g. "r1_21" + + String[] versionParts = rawVersion.split("\\."); + int major = parseInt(versionParts[0]); + int minor = parseInt(versionParts[1]); + int patch = versionParts.length > 2 ? parseInt(versionParts[2]) : 0; + + while (true) { + String className = "io.github.adrianvic.nemesiseye.impl." + classSuffix; + Glimmer glimmer = tryInstantiate(className); + if (glimmer != null) return glimmer; + + if (patch > 0) { + patch--; + continue; + } + if (minor > 0) { + minor--; + patch = 20; + continue; + } + className = "io.github.adrianvic.nemesiseye.impl.r" + major + "_" + minor; + glimmer = tryInstantiate(className); + if (glimmer != null) return glimmer; + + throw new IllegalStateException( + "No suitable implementation found for version " + rawVersion); + } + } + + private Glimmer betaLoadGlim() { + // Bukkit.getVersion() // returns something like "1.1.10 (MC: 1.7.3)" WEIRD + return tryInstantiate("io.github.adrianvic.nemesiseye.impl.b1_7_3"); // only supported beta version for now } private Glimmer tryInstantiate(String className) { diff --git a/src/main/resources/settings.yml b/src/main/resources/settings.yml index 0611c04..a94dd2f 100644 --- a/src/main/resources/settings.yml +++ b/src/main/resources/settings.yml @@ -5,19 +5,18 @@ # \_\ \_____ / /_/ /_______ /\_______ /\____|__ / # \/ \/ \/ \/ # EYE OF NEMESIS - Example config file. -# Documentation in our repository's /docs +# Documentation in our wiki: https://github.com/adrianvic/NemesisEye Policies: - # This example blocks the usage of bedrock without the server.usebedrock permissin - - name: "Bedrock-allow-admins" # No spaces here or else commands which need the name as argument will not work - type: "permission" # global | location | permission | playerName + - name: "Bedrock-allow-admins" + type: "permission" worlds: [world] - effect: ALLOW # DENY | ALLOW (overrides deny) | ALLOWONLY (allow only if met) - weight: 3 # Greater weight overrides lower + effect: ALLOW + weight: 3 permissions: - "server.usebedrock" nodes: - - [PLACE]: + - [BREAK, PLACE, HIT, INTERACT]: values: - BEDROCK @@ -27,16 +26,15 @@ Policies: effect: DENY weight: 2 nodes: - - [PLACE]: + - [BREAK, PLACE, HIT, INTERACT]: values: - BEDROCK - # This example blocks all non-beta (b1.7.3) items, blocks, mobs, enchantments in a rectangular area - - name: "Block-non-beta-items" - type: "location" - effect: DENY + - name: "Block-non-beta-items" # No spaces here or else commands which need the name as argument will not work + type: "location" # global | location | permission | playerName + effect: DENY # DENY | ALLOW (overrides deny) | ALLOWONLY (allow only if met) worlds: [world] - weight: 0 + weight: 0 # Greater weight overrides lower policyAllowList: false # Inverts the policy validation logic, for example a location policy will affect all players NOT inside it's location locations: worlds: [world] @@ -44,7 +42,7 @@ Policies: - corner1: { x: 2100, y: 256, z: 1400 } corner2: { x: 1000, y: -64, z: 2200 } nodes: - - [INTERACT, BREAK, HIT, PLACE, GLYDE, EQUIP, SPAWN]: + - [INTERACT, BREAK, HIT, PLACE]: values: - '.*' - [USE_ENCHANTMENT]: @@ -61,7 +59,7 @@ Policies: - corner1: { x: 2100, y: 256, z: 1400 } corner2: { x: 1000, y: -64, z: 2200 } nodes: - - [INTERACT, BREAK, HIT, PLACE, SPAWN]: + - [INTERACT, BREAK, HIT, PLACE]: values: - AIR - STONE @@ -170,16 +168,4 @@ Policies: - MUSIC_DISK_CAT - MUSIC_DISK_13 - DIRT - - BREAD - - ZOMBIE - - SKELETON - - CHICKEN - - PIG - - SHEEP - - COW - - SQUID - - WOLF - - PIGZOMBIE - - SPIDER - - GHAST - - CREEPER \ No newline at end of file + - BREAD \ No newline at end of file diff --git a/src/r1_21/java/io/github/adrianvic/nemesiseye/impl/v1_21/EventListener.java b/src/r1_21/java/io/github/adrianvic/nemesiseye/impl/EventListener.java similarity index 58% rename from src/r1_21/java/io/github/adrianvic/nemesiseye/impl/v1_21/EventListener.java rename to src/r1_21/java/io/github/adrianvic/nemesiseye/impl/EventListener.java index e7a7d8e..f7bf288 100644 --- a/src/r1_21/java/io/github/adrianvic/nemesiseye/impl/v1_21/EventListener.java +++ b/src/r1_21/java/io/github/adrianvic/nemesiseye/impl/EventListener.java @@ -1,19 +1,15 @@ -package io.github.adrianvic.nemesiseye.impl.v1_21; +package io.github.adrianvic.nemesiseye.impl; import io.github.adrianvic.nemesiseye.Events; -import io.github.adrianvic.nemesiseye.ModernEvents; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.block.BlockBreakEvent; -import org.bukkit.event.block.BlockFormEvent; import org.bukkit.event.block.BlockPlaceEvent; -import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerMoveEvent; -import org.bukkit.event.player.PlayerTakeLecternBookEvent; public class EventListener implements Listener { @EventHandler @@ -40,21 +36,5 @@ public class EventListener implements Listener { public void onPlayerMoveEvent(PlayerMoveEvent event) { Events.onPlayerMoveEvent(event); } @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onInventoryClickEvent(InventoryClickEvent event) { ModernEvents.onInventoryClickEvent(event); } - - @EventHandler - public void onCreatureSpawnEvent(CreatureSpawnEvent event) { Events.onCreatureSpawnEvent(event); } - - @EventHandler - public void onEndermanAttackPlayerEvent(com.destroystokyo.paper.event.entity.EndermanAttackPlayerEvent event) { - ModernEvents.onEndermanAttackPlayerEvent(event); - } - - @EventHandler - public void onBlockFormEvent(BlockFormEvent event) { - ModernEvents.onBlockFormEvent(event); - } - - @EventHandler - public void onPlayerTakeLecternBook(PlayerTakeLecternBookEvent event) { ModernEvents.onPlayerTakeLecternBookEvent(event); } + public void onInventoryClickEvent(InventoryClickEvent event) { Events.onInventoryClickEvent(event);} } \ No newline at end of file diff --git a/src/r1_21/java/io/github/adrianvic/nemesiseye/impl/v1_21/commands/Eye.java b/src/r1_21/java/io/github/adrianvic/nemesiseye/impl/commands/Eye.java similarity index 94% rename from src/r1_21/java/io/github/adrianvic/nemesiseye/impl/v1_21/commands/Eye.java rename to src/r1_21/java/io/github/adrianvic/nemesiseye/impl/commands/Eye.java index 30e81f5..e28b412 100644 --- a/src/r1_21/java/io/github/adrianvic/nemesiseye/impl/v1_21/commands/Eye.java +++ b/src/r1_21/java/io/github/adrianvic/nemesiseye/impl/commands/Eye.java @@ -1,4 +1,4 @@ -package io.github.adrianvic.nemesiseye.impl.v1_21.commands; +package io.github.adrianvic.nemesiseye.impl.commands; import io.github.adrianvic.nemesiseye.commands.EyeCore; import org.bukkit.command.Command; diff --git a/src/r1_21/java/io/github/adrianvic/nemesiseye/impl/r1_21.java b/src/r1_21/java/io/github/adrianvic/nemesiseye/impl/r1_21.java new file mode 100644 index 0000000..b929d0b --- /dev/null +++ b/src/r1_21/java/io/github/adrianvic/nemesiseye/impl/r1_21.java @@ -0,0 +1,108 @@ +package io.github.adrianvic.nemesiseye.impl; + +import io.github.adrianvic.nemesiseye.DataShifter; +import io.github.adrianvic.nemesiseye.Nemesis; +import io.github.adrianvic.nemesiseye.impl.commands.Eye; +import io.github.adrianvic.nemesiseye.policy.Policy; +import io.github.adrianvic.nemesiseye.policy.PolicyParsers; +import io.github.adrianvic.nemesiseye.reflection.Glimmer; +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.bukkit.command.CommandSender; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.entity.HumanEntity; +import org.bukkit.inventory.ItemStack; +import org.bukkit.plugin.PluginManager; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +@SuppressWarnings("unused") +public class r1_21 implements Glimmer { + @Override + public File loadConfigFile() { + File file = new File(Nemesis.getInstance().getDataFolder(), "settings.yml"); + + if (!file.exists()) + Nemesis.getInstance().saveResource("settings.yml", false); + + return file; + } + + @Override + public List loadPoliciesFromFile(File file) { + YamlConfiguration config = new YamlConfiguration(); + config.options().parseComments(true); + + try { + config.load(file); + } catch (Exception e) { + e.printStackTrace(); + } + + List> rawPolicies = config.getMapList("Policies"); + List allPolicies = new ArrayList<>(); + + for (Map policyMap : rawPolicies) { + if (policyMap.get("type") != null && policyMap.get("type") instanceof String type) { + allPolicies.add(PolicyParsers.get(type).parse(policyMap)); + } + } + + return allPolicies; + } + + @Override + public void onLoad() { + PluginManager pm = Nemesis.getInstance().getPluginManager(); + Nemesis.getInstance().getCommand("eye").setExecutor(new Eye()); + pm.registerEvents(new EventListener(), Nemesis.getInstance()); + } + + @Override + public ItemStack getItemInMainHandHumanEntity(HumanEntity entity) { + return entity.getInventory().getItemInMainHand(); + } + + @Override + public void sendMessage(CommandSender commandSender, String text) { + commandSender.sendMessage(text); + } + + @Override + public boolean hasItemMeta(ItemStack item) { + return item.getItemMeta() != null; + } + + @Override + public List getWorlds() { + return Bukkit.getWorlds(); + } + + @Override + public boolean hasEnchantment(ItemStack item, Map valuesmap) { + Map enchantments = item.getEnchantments(); + + for (Map.Entry ench : enchantments.entrySet()) { + String enchKey = ench.getKey().getKey().getKey(); + String enchLevel = ench.getValue().toString(); + + for (Map.Entry rule : valuesmap.entrySet()) { + if ( + DataShifter.safeMatches(rule.getKey(), enchKey) && + DataShifter.safeMatches(rule.getValue(), enchLevel) + ) { + return true; + } + } + } + return false; + } + + public boolean hasAnyEnchantment(ItemStack item) { + return !(item.getItemMeta().getEnchants().isEmpty()); + } +} diff --git a/src/r1_21/java/io/github/adrianvic/nemesiseye/impl/v1_21/r1_21.java b/src/r1_21/java/io/github/adrianvic/nemesiseye/impl/v1_21/r1_21.java deleted file mode 100644 index edd5a60..0000000 --- a/src/r1_21/java/io/github/adrianvic/nemesiseye/impl/v1_21/r1_21.java +++ /dev/null @@ -1,215 +0,0 @@ -package io.github.adrianvic.nemesiseye.impl.v1_21; - -import io.github.adrianvic.nemesiseye.DataShifter; -import io.github.adrianvic.nemesiseye.Nemesis; -import io.github.adrianvic.nemesiseye.impl.v1_21.commands.Eye; -import io.github.adrianvic.nemesiseye.policy.Action; -import io.github.adrianvic.nemesiseye.policy.NodeHandler; -import io.github.adrianvic.nemesiseye.policy.Policy; -import io.github.adrianvic.nemesiseye.policy.PolicyParsers; -import io.github.adrianvic.nemesiseye.policy.handlers.FormBlock; -import io.github.adrianvic.nemesiseye.reflection.Glimmer; -import org.bukkit.Bukkit; -import org.bukkit.World; -import org.bukkit.command.CommandSender; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.enchantments.Enchantment; -import org.bukkit.entity.HumanEntity; -import org.bukkit.inventory.ItemStack; -import org.bukkit.plugin.PluginManager; - -import java.io.File; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -@SuppressWarnings("unused") -public class r1_21 implements Glimmer { - @Override - public File loadConfigFile() { - File file = new File(Nemesis.getInstance().getDataFolder(), "settings.yml"); - - if (!file.exists()) - Nemesis.getInstance().saveResource("settings.yml", false); - - return file; - } - - @Override - public List loadPoliciesFromFile(File file) { - YamlConfiguration config = new YamlConfiguration(); - config.options().parseComments(true); - - try { - config.load(file); - } catch (Exception e) { - e.printStackTrace(); - } - - List> rawPolicies = config.getMapList("Policies"); - List allPolicies = new ArrayList<>(); - - for (Map policyMap : rawPolicies) { - if (policyMap.get("type") != null && policyMap.get("type") instanceof String type) { - allPolicies.add(PolicyParsers.get(type).parse(policyMap)); - } - } - - return allPolicies; - } - - @Override - public void onLoad() { - PluginManager pm = Nemesis.getInstance().getPluginManager(); - Eye eye = new Eye(); - Nemesis.getInstance().getCommand("eye").setExecutor(eye); - Nemesis.getInstance().getCommand("eye").setTabCompleter(eye); - pm.registerEvents(new EventListener(), Nemesis.getInstance()); - } - - @Override - public ItemStack getItemInMainHandHumanEntity(HumanEntity entity) { - return entity.getInventory().getItemInMainHand(); - } - - @Override - public boolean isAir(ItemStack item) { - return item == null || item.getType().isAir(); - } - - @Override - public boolean isGliding(org.bukkit.entity.Player player) { - return player.isGliding(); - } - - @Override - public void setGliding(org.bukkit.entity.Player player, boolean gliding) { - player.setGliding(gliding); - } - - @Override - public boolean hasPermission(org.bukkit.command.CommandSender sender, String permission) { - return sender.hasPermission(permission); - } - - @Override - public boolean isArmorEquipAttempt(org.bukkit.event.Event event) { - if (!(event instanceof org.bukkit.event.inventory.InventoryClickEvent e)) { - return false; - } - - if (e.getSlotType() == org.bukkit.event.inventory.InventoryType.SlotType.ARMOR) { - return true; - } - - if (e.isShiftClick()) { - return isArmor(e.getCurrentItem()); - } - - if (e.getClick() == org.bukkit.event.inventory.ClickType.NUMBER_KEY - && e.getSlotType() == org.bukkit.event.inventory.InventoryType.SlotType.ARMOR - && e.getWhoClicked() instanceof org.bukkit.entity.Player player) { - return isArmor( - player.getInventory().getItem(e.getHotbarButton()) - ); - } - - return false; - } - - @Override - public ItemStack getEquippedItem(org.bukkit.event.Event event) { - if (event instanceof org.bukkit.event.inventory.InventoryClickEvent e) { - org.bukkit.event.inventory.InventoryType.SlotType slotType = e.getSlotType(); - - if (e.getClick() == org.bukkit.event.inventory.ClickType.NUMBER_KEY // hotbar key swap - && slotType == org.bukkit.event.inventory.InventoryType.SlotType.ARMOR - && e.getWhoClicked() instanceof org.bukkit.entity.Player player) { - return player.getInventory().getItem(e.getHotbarButton()); - } - - if (e.isShiftClick()) { - ItemStack current = e.getCurrentItem(); - if (isArmor(current)) return current; - } - - // regular click - if (slotType == org.bukkit.event.inventory.InventoryType.SlotType.ARMOR) { - ItemStack cursor = e.getCursor(); - if (isArmor(cursor)) return cursor; - } - } - - // Try Paper's PlayerArmorChangeEvent via reflection or just check if class exists - try { - if (event instanceof com.destroystokyo.paper.event.player.PlayerArmorChangeEvent e) { - return e.getNewItem(); - } - } catch (NoClassDefFoundError | Exception ignored) {} - - return null; - } - - @Override - public Map getExtraHandlers() { - Map handlers = new HashMap<>(); - handlers.put(Action.FORMBLOCK, new FormBlock()); - return handlers; - } - - @Override - public void sendMessage(CommandSender commandSender, String text) { - commandSender.sendMessage(text); - } - - @Override - public boolean hasItemMeta(ItemStack item) { - return item.getItemMeta() != null; - } - - @Override - public List getWorlds() { - return Bukkit.getWorlds(); - } - - @Override - public boolean hasEnchantment(ItemStack item, Map valuesmap) { - Map enchantments = item.getEnchantments(); - - for (Map.Entry ench : enchantments.entrySet()) { - String enchKey = ench.getKey().getKey().getKey(); - String enchLevel = ench.getValue().toString(); - - for (Map.Entry rule : valuesmap.entrySet()) { - if ( - DataShifter.safeMatches(rule.getKey(), enchKey) && - DataShifter.safeMatches(rule.getValue(), enchLevel) - ) { - return true; - } - } - } - return false; - } - - @Override - public boolean hasAnyEnchantment(ItemStack item) { - return !(item.getItemMeta().getEnchants().isEmpty()); - } - - @Override - public boolean isArmor(ItemStack item) { - if (item == null || item.getType().isAir()) { - return false; - } - - String name = item.getType().name(); - - return name.endsWith("_HELMET") - || name.endsWith("_CHESTPLATE") - || name.endsWith("_LEGGINGS") - || name.endsWith("_BOOTS") - || item.getType() == org.bukkit.Material.ELYTRA; - } -} diff --git a/src/test/java/io/github/adrianvic/nemesiseye/ValidatorTest.java b/src/test/java/io/github/adrianvic/nemesiseye/ValidatorTest.java deleted file mode 100644 index bd00215..0000000 --- a/src/test/java/io/github/adrianvic/nemesiseye/ValidatorTest.java +++ /dev/null @@ -1,38 +0,0 @@ -package io.github.adrianvic.nemesiseye; - -import io.github.adrianvic.nemesiseye.policy.Action; -import io.github.adrianvic.nemesiseye.policy.Effect; -import io.github.adrianvic.nemesiseye.policy.Policy; -import io.github.adrianvic.nemesiseye.reflection.Glimmer; -import org.bukkit.World; -import org.bukkit.event.Event; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import static org.mockito.Mockito.*; - -public class ValidatorTest { - - private Glimmer mockGlim; - private Config mockConfig; - - @BeforeEach - void setUp() { - mockGlim = mock(Glimmer.class); - } - - @Test - void testValidatorCanDeny() { - World world = mock(World.class); - Event event = mock(Event.class); - Policy policy = mock(Policy.class); - -// when(policy.applies(world)).thenReturn(true); - when(policy.matches(world, Action.BREAK, event)).thenReturn(true); - when(policy.effect()).thenReturn(Effect.DENY); - - // We need to handle the static Config.getInstance() - // This is tricky without refactoring or Mockito-inline - // For now, let's just demonstrate the concept if Validator was more testable - } -} diff --git a/src/test/java/io/github/adrianvic/nemesiseye/impl/ImplementationContractTest.java b/src/test/java/io/github/adrianvic/nemesiseye/impl/ImplementationContractTest.java deleted file mode 100644 index 74379c8..0000000 --- a/src/test/java/io/github/adrianvic/nemesiseye/impl/ImplementationContractTest.java +++ /dev/null @@ -1,66 +0,0 @@ -package io.github.adrianvic.nemesiseye.impl; - -import be.seeseemelk.mockbukkit.MockBukkit; -import be.seeseemelk.mockbukkit.ServerMock; -import io.github.adrianvic.nemesiseye.impl.v1_21.r1_21; -import io.github.adrianvic.nemesiseye.impl.v1_7_3.b1_7_3; -import io.github.adrianvic.nemesiseye.reflection.Glimmer; -import org.bukkit.Material; -import org.bukkit.inventory.ItemStack; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; - -import java.util.stream.Stream; - -import static org.junit.jupiter.api.Assertions.*; - -public class ImplementationContractTest { - - private ServerMock server; - - @BeforeEach - void setUp() { - server = MockBukkit.mock(); - } - - @AfterEach - void tearDown() { - MockBukkit.unmock(); - } - - static Stream implementations() { - return Stream.of( - new b1_7_3(), - new r1_21() - ); - } - - @ParameterizedTest - @MethodSource("implementations") - void testIsArmor(Glimmer glim) { - // Helmets - assertTrue(glim.isArmor(new ItemStack(Material.IRON_HELMET))); - assertTrue(glim.isArmor(new ItemStack(Material.DIAMOND_HELMET))); - - // Chestplates - assertTrue(glim.isArmor(new ItemStack(Material.GOLDEN_CHESTPLATE))); - - // Non-armor - assertFalse(glim.isArmor(new ItemStack(Material.STICK))); - assertFalse(glim.isArmor(new ItemStack(Material.DIRT))); - - // Null/Air - assertFalse(glim.isArmor(null)); - assertFalse(glim.isArmor(new ItemStack(Material.AIR))); - } - - @ParameterizedTest - @MethodSource("implementations") - void testIsAir(Glimmer glim) { - assertTrue(glim.isAir(null)); - assertTrue(glim.isAir(new ItemStack(Material.AIR))); - assertFalse(glim.isAir(new ItemStack(Material.STONE))); - } -}