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);
+ }
+ }
}