diff --git a/MIGRATION.md b/MIGRATION.md index c495e94..3cdb0b9 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -23,7 +23,7 @@ plugins/ ```text plugins/ -├─ MagicGem-Reforged-1.0.0.jar +├─ MagicGem-Reforged-1.0.1.jar ├─ MagicGem/ └─ MagicGem-Reforged/ ``` diff --git a/README.md b/README.md index 8c31c06..eedf4c1 100644 --- a/README.md +++ b/README.md @@ -39,4 +39,4 @@ plugins/MagicGem → plugins/MagicGem-Reforged mvn clean package ``` -产物位于 `target/MagicGem-Reforged-1.0.0.jar`。 +产物位于 `target/MagicGem-Reforged-1.0.1.jar`。 diff --git a/pom.xml b/pom.xml index 83024c5..85d20d5 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ cn.infstar magicgem-reforged - 1.0.0 + 1.0.1 jar MagicGem-Reforged diff --git a/src/main/java/cn/infstar/magicgem/skill/SkillEngine.java b/src/main/java/cn/infstar/magicgem/skill/SkillEngine.java index b0ee503..b3530ba 100644 --- a/src/main/java/cn/infstar/magicgem/skill/SkillEngine.java +++ b/src/main/java/cn/infstar/magicgem/skill/SkillEngine.java @@ -217,10 +217,10 @@ public final class SkillEngine implements Listener { switch (normalize(mechanic.type())) { case "reward" -> { ItemStack changed = applyReward(player, item, mechanic, false); - if (changed != item) replaceMatchingItem(player, item, changed); + if (changed != item) replaceMatchingItem(player, slot, item, changed); } case "rewardswitch" -> { } - case "switch" -> switchSkill(player, item, skill, mechanic); + case "switch" -> switchSkill(player, item, slot, mechanic); case "potionbuff" -> potionBuff(player, item, mechanic, action.target(), target, action.worldLimits()); case "blink" -> blink(player, item, mechanic, action.target(), target, context.location()); case "timestart" -> timeStart(player, item, skill, mechanic); @@ -251,7 +251,7 @@ public final class SkillEngine implements Listener { return rewardContext.item(); } - private void switchSkill(Player player, ItemStack item, SkillDefinition source, Directive mechanic) + private void switchSkill(Player player, ItemStack item, String slot, Directive mechanic) throws RewardException { List cycle = new ArrayList<>(); String first = mechanic.argument("", "skills", "list", "s"); @@ -277,7 +277,7 @@ public final class SkillEngine implements Listener { if (newSkill != null) for (SkillAction action : newSkill.actions()) if (normalize(action.mechanic().type()).equals("rewardswitch")) changed = applyReward(player, changed, action.mechanic(), false); - replaceMatchingItem(player, item, changed); + replaceItemInSlot(player, slot, item, changed); } private void potionBuff(Player player, ItemStack item, Directive mechanic, String selector, Entity target, @@ -525,16 +525,46 @@ public final class SkillEngine implements Listener { return value.toLowerCase(Locale.ROOT).replace("_", "").replace("-", ""); } - private void replaceMatchingItem(Player player, ItemStack original, ItemStack changed) { + private void replaceMatchingItem(Player player, String configuredSlot, ItemStack original, ItemStack changed) { + EquipmentSlot expected = equipmentSlot(configuredSlot); + if (expected != null) { + ItemStack equipped = player.getInventory().getItem(expected); + if (equipped == original || equipped != null && original != null && equipped.isSimilar(original)) { + player.getInventory().setItem(expected, changed); + return; + } + } for (EquipmentSlot slot : EquipmentSlot.values()) { ItemStack equipped = player.getInventory().getItem(slot); - if (equipped == original) { + if (equipped == original || equipped != null && original != null && equipped.isSimilar(original)) { player.getInventory().setItem(slot, changed); return; } } } + private void replaceItemInSlot(Player player, String configuredSlot, ItemStack original, ItemStack changed) { + EquipmentSlot expected = equipmentSlot(configuredSlot); + if (expected != null) { + player.getInventory().setItem(expected, changed); + return; + } + replaceMatchingItem(player, configuredSlot, original, changed); + } + + private EquipmentSlot equipmentSlot(String configuredSlot) { + if (configuredSlot == null) return null; + return switch (configuredSlot.toLowerCase(Locale.ROOT)) { + case "mainhand", "hand" -> EquipmentSlot.HAND; + case "offhand" -> EquipmentSlot.OFF_HAND; + case "head", "helmet" -> EquipmentSlot.HEAD; + case "chest", "chestplate" -> EquipmentSlot.CHEST; + case "legs", "leggings" -> EquipmentSlot.LEGS; + case "feet", "boots" -> EquipmentSlot.FEET; + default -> null; + }; + } + private Player attackingPlayer(Entity damager) { if (damager instanceof Player player) return player; if (damager instanceof Projectile projectile && projectile.getShooter() instanceof Player player) return player; diff --git a/src/main/resources/skills/DefaultSkills.yml b/src/main/resources/skills/DefaultSkills.yml index 9413f7d..552c258 100644 --- a/src/main/resources/skills/DefaultSkills.yml +++ b/src/main/resources/skills/DefaultSkills.yml @@ -38,12 +38,12 @@ - Switch{s=精准;时运} ~onShiftUse 精准: Skills: - - RewardSwitch{Enchant{name=SILK_TOUCH;limit=1}} + - RewardSwitch{Enchant{name=SILK_TOUCH;level=1;limit=1}} - RewardSwitch{ActionBar{m=&b&l切换为精准模式}} 时运: Skills: - - RewardSwitch{Enchant{name=LOOT_BONUS_BLOCKS;level=0}} + - RewardSwitch{Enchant{name=LOOT_BONUS_BLOCKS;level=1;limit=1}} - RewardSwitch{ActionBar{m=&a&l切换为时运模式}} 忠诚/激流切换: @@ -55,12 +55,13 @@ 激流: Skills: - - RewardSwitch{Enchant{name=RIPTIDE;level=0}} + - RewardSwitch{Enchant{name=RIPTIDE;level=1;limit=1}} - RewardSwitch{ActionBar{m=&b&l切换为激流模式}} 忠诚: Skills: - - RewardSwitch{ActionBar{m=&a&l切换为时忠诚模式}} + - RewardSwitch{Enchant{name=LOYALTY;level=1;limit=1}} + - RewardSwitch{ActionBar{m=&a&l切换为忠诚模式}} 禁飞DEBUFF: Cooldown: 5.0 diff --git a/src/test/java/cn/infstar/magicgem/skill/BundledConfigurationTest.java b/src/test/java/cn/infstar/magicgem/skill/BundledConfigurationTest.java index 9c435a6..50c273e 100644 --- a/src/test/java/cn/infstar/magicgem/skill/BundledConfigurationTest.java +++ b/src/test/java/cn/infstar/magicgem/skill/BundledConfigurationTest.java @@ -12,8 +12,10 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.LinkedHashSet; import java.util.Locale; +import java.util.Map; import java.util.Set; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; @@ -94,4 +96,34 @@ class BundledConfigurationTest { } } } + + @Test + void enchantmentSwitchModesDefineSymmetricPositiveLevels() { + YamlConfiguration yaml = YamlConfiguration.loadConfiguration( + new File("src/main/resources/skills/DefaultSkills.yml")); + Map expected = Map.of( + "精准", "SILK_TOUCH", + "时运", "LOOT_BONUS_BLOCKS", + "激流", "RIPTIDE", + "忠诚", "LOYALTY"); + + for (Map.Entry entry : expected.entrySet()) { + String path = entry.getKey() + ".Skills"; + String source = yaml.getStringList(path).stream() + .filter(line -> line.trim().startsWith("RewardSwitch{Enchant{")) + .findFirst() + .orElse(null); + assertNotNull(source, path + " must contain an enchantment RewardSwitch"); + + Directive rewardSwitch = parser.parse(source); + String nestedSource = rewardSwitch.positional().isEmpty() + ? rewardSwitch.argument("", "reward", "r") + : rewardSwitch.positional().getFirst(); + Directive enchant = parser.parse(nestedSource); + assertEquals("Enchant", enchant.type(), path); + assertEquals(entry.getValue(), enchant.argument("", "name"), path); + assertEquals(1, enchant.intArgument(1, "level", "l"), path); + assertEquals(1, enchant.intArgument(0, "limit"), path); + } + } }