From 536fccb08caa46510ac15c7a4c1229085d2f7250 Mon Sep 17 00:00:00 2001
From: jhqwqmc <2110242767@qq.com>
Date: Thu, 12 Jun 2025 05:22:12 +0800
Subject: [PATCH] =?UTF-8?q?feat(item):=20=E6=B7=BB=E5=8A=A0=E7=89=A9?=
=?UTF-8?q?=E5=93=81invulnerable=E8=AE=BE=E7=BD=AE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 物品: hhh我无敌了
---
.../item/listener/ItemEventListener.java | 15 ++++
.../bukkit/util/DamageCauseUtils.java | 89 +++++++++++++++++++
.../src/main/resources/translations/en.yml | 1 +
.../src/main/resources/translations/zh_cn.yml | 1 +
.../craftengine/core/item/ItemSettings.java | 26 +++++-
.../craftengine/core/util/DamageCause.java | 58 ++++++++++++
gradle.properties | 2 +-
7 files changed, 187 insertions(+), 5 deletions(-)
create mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/DamageCauseUtils.java
create mode 100644 core/src/main/java/net/momirealms/craftengine/core/util/DamageCause.java
diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/listener/ItemEventListener.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/listener/ItemEventListener.java
index 0bec09f6b..2f037484f 100644
--- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/listener/ItemEventListener.java
+++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/listener/ItemEventListener.java
@@ -28,11 +28,13 @@ import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData;
+import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
+import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.FoodLevelChangeEvent;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.event.player.PlayerInteractEvent;
@@ -398,4 +400,17 @@ public class ItemEventListener implements Listener {
}
return false;
}
+
+ @EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
+ public void onEntityDamage(EntityDamageEvent event) {
+ if (event.getEntityType() == EntityType.ITEM && event.getEntity() instanceof org.bukkit.entity.Item item) {
+ Optional.ofNullable(this.plugin.itemManager().wrap(item.getItemStack()))
+ .flatMap(Item::getCustomItem)
+ .ifPresent(it -> {
+ if (it.settings().invulnerable().contains(DamageCauseUtils.fromBukkit(event.getCause()))) {
+ event.setCancelled(true);
+ }
+ });
+ }
+ }
}
diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/DamageCauseUtils.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/DamageCauseUtils.java
new file mode 100644
index 000000000..752c23915
--- /dev/null
+++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/DamageCauseUtils.java
@@ -0,0 +1,89 @@
+package net.momirealms.craftengine.bukkit.util;
+
+import net.momirealms.craftengine.core.util.DamageCause;
+import org.bukkit.event.entity.EntityDamageEvent;
+
+public class DamageCauseUtils {
+
+ private DamageCauseUtils() {}
+
+ @SuppressWarnings("deprecation")
+ public static EntityDamageEvent.DamageCause toBukkit(DamageCause cause) {
+ return switch (cause) {
+ case BLOCK_EXPLOSION -> EntityDamageEvent.DamageCause.BLOCK_EXPLOSION;
+ case CAMPFIRE -> EntityDamageEvent.DamageCause.CAMPFIRE;
+ case CONTACT -> EntityDamageEvent.DamageCause.CONTACT;
+ case CRAMMING -> EntityDamageEvent.DamageCause.CRAMMING;
+ case CUSTOM -> EntityDamageEvent.DamageCause.CUSTOM;
+ case DROWNING -> EntityDamageEvent.DamageCause.DROWNING;
+ case DRYOUT -> EntityDamageEvent.DamageCause.DRYOUT;
+ case ENTITY_ATTACK -> EntityDamageEvent.DamageCause.ENTITY_ATTACK;
+ case ENTITY_EXPLOSION -> EntityDamageEvent.DamageCause.ENTITY_EXPLOSION;
+ case ENTITY_SWEEP_ATTACK -> EntityDamageEvent.DamageCause.ENTITY_SWEEP_ATTACK;
+ case FALL -> EntityDamageEvent.DamageCause.FALL;
+ case FALLING_BLOCK -> EntityDamageEvent.DamageCause.FALLING_BLOCK;
+ case FIRE -> EntityDamageEvent.DamageCause.FIRE;
+ case FIRE_TICK -> EntityDamageEvent.DamageCause.FIRE_TICK;
+ case FLY_INTO_WALL -> EntityDamageEvent.DamageCause.FLY_INTO_WALL;
+ case FREEZE -> EntityDamageEvent.DamageCause.FREEZE;
+ case HOT_FLOOR -> EntityDamageEvent.DamageCause.HOT_FLOOR;
+ case KILL -> EntityDamageEvent.DamageCause.KILL;
+ case LAVA -> EntityDamageEvent.DamageCause.LAVA;
+ case LIGHTNING -> EntityDamageEvent.DamageCause.LIGHTNING;
+ case MAGIC -> EntityDamageEvent.DamageCause.MAGIC;
+ case MELTING -> EntityDamageEvent.DamageCause.MELTING;
+ case POISON -> EntityDamageEvent.DamageCause.POISON;
+ case PROJECTILE -> EntityDamageEvent.DamageCause.PROJECTILE;
+ case SONIC_BOOM -> EntityDamageEvent.DamageCause.SONIC_BOOM;
+ case STARVATION -> EntityDamageEvent.DamageCause.STARVATION;
+ case SUFFOCATION -> EntityDamageEvent.DamageCause.SUFFOCATION;
+ case SUICIDE -> EntityDamageEvent.DamageCause.SUICIDE;
+ case THORNS -> EntityDamageEvent.DamageCause.THORNS;
+ case VOID -> EntityDamageEvent.DamageCause.VOID;
+ case WITHER -> EntityDamageEvent.DamageCause.WITHER;
+ case WORLD_BORDER -> EntityDamageEvent.DamageCause.WORLD_BORDER;
+ case DRAGON_BREATH -> EntityDamageEvent.DamageCause.DRAGON_BREATH;
+ default -> throw new IllegalArgumentException("Unexpected value: " + cause);
+ };
+ }
+
+ @SuppressWarnings("deprecation")
+ public static DamageCause fromBukkit(EntityDamageEvent.DamageCause cause) {
+ return switch (cause) {
+ case BLOCK_EXPLOSION -> DamageCause.BLOCK_EXPLOSION;
+ case CAMPFIRE -> DamageCause.CAMPFIRE;
+ case CONTACT -> DamageCause.CONTACT;
+ case CRAMMING -> DamageCause.CRAMMING;
+ case CUSTOM -> DamageCause.CUSTOM;
+ case DROWNING -> DamageCause.DROWNING;
+ case DRYOUT -> DamageCause.DRYOUT;
+ case ENTITY_ATTACK -> DamageCause.ENTITY_ATTACK;
+ case ENTITY_EXPLOSION -> DamageCause.ENTITY_EXPLOSION;
+ case ENTITY_SWEEP_ATTACK -> DamageCause.ENTITY_SWEEP_ATTACK;
+ case FALL -> DamageCause.FALL;
+ case FALLING_BLOCK -> DamageCause.FALLING_BLOCK;
+ case FIRE -> DamageCause.FIRE;
+ case FIRE_TICK -> DamageCause.FIRE_TICK;
+ case FLY_INTO_WALL -> DamageCause.FLY_INTO_WALL;
+ case FREEZE -> DamageCause.FREEZE;
+ case HOT_FLOOR -> DamageCause.HOT_FLOOR;
+ case KILL -> DamageCause.KILL;
+ case LAVA -> DamageCause.LAVA;
+ case LIGHTNING -> DamageCause.LIGHTNING;
+ case MAGIC -> DamageCause.MAGIC;
+ case MELTING -> DamageCause.MELTING;
+ case POISON -> DamageCause.POISON;
+ case PROJECTILE -> DamageCause.PROJECTILE;
+ case SONIC_BOOM -> DamageCause.SONIC_BOOM;
+ case STARVATION -> DamageCause.STARVATION;
+ case SUFFOCATION -> DamageCause.SUFFOCATION;
+ case SUICIDE -> DamageCause.SUICIDE;
+ case THORNS -> DamageCause.THORNS;
+ case VOID -> DamageCause.VOID;
+ case WITHER -> DamageCause.WITHER;
+ case WORLD_BORDER -> DamageCause.WORLD_BORDER;
+ case DRAGON_BREATH -> DamageCause.DRAGON_BREATH;
+ default -> throw new IllegalArgumentException("Unexpected value: " + cause);
+ };
+ }
+}
diff --git a/common-files/src/main/resources/translations/en.yml b/common-files/src/main/resources/translations/en.yml
index a2b68568f..5e1ed8c99 100644
--- a/common-files/src/main/resources/translations/en.yml
+++ b/common-files/src/main/resources/translations/en.yml
@@ -153,6 +153,7 @@ warning.config.furniture.hitbox.invalid_type: "Issue found in file Issue found in file - The furniture '' is using a custom hitbox with invalid entity type ''."
warning.config.item.duplicate: "Issue found in file - Duplicated item ''. Please check if there is the same configuration in other files."
warning.config.item.settings.unknown: "Issue found in file - The item '' is using an unknown setting type ''."
+warning.config.item.settings.invulnerable-unknown: "Issue found in file - The item '' is using an unknown damage cause type ''."
warning.config.item.missing_material: "Issue found in file - The item '' is missing the required 'material' argument."
warning.config.item.invalid_material: "Issue found in file - The item '' is using an invalid material type ''."
warning.config.item.invalid_custom_model_data: "Issue found in file - The item '' is using a negative custom model data '' which is invalid."
diff --git a/common-files/src/main/resources/translations/zh_cn.yml b/common-files/src/main/resources/translations/zh_cn.yml
index 4f11d3878..5db0f709d 100644
--- a/common-files/src/main/resources/translations/zh_cn.yml
+++ b/common-files/src/main/resources/translations/zh_cn.yml
@@ -153,6 +153,7 @@ warning.config.furniture.hitbox.invalid_type: "在文件 发现
warning.config.furniture.hitbox.custom.invalid_entity: "在文件 发现问题 - 家具 '' 的自定义碰撞箱使用了无效的实体类型 ''"
warning.config.item.duplicate: "在文件 发现问题 - 重复的物品 '' 请检查其他文件中是否存在相同配置"
warning.config.item.settings.unknown: "在文件 发现问题 - 物品 '' 使用了未知的设置类型 ''"
+warning.config.item.settings.invulnerable-unknown: "在文件 发现问题 - 物品 '' 物品使用了未知的受伤害类型 ''"
warning.config.item.missing_material: "在文件 发现问题 - 物品 '' 缺少必需的 'material' 参数"
warning.config.item.invalid_material: "在文件 发现问题 - 物品 '' 使用了无效的材料类型 ''"
warning.config.item.invalid_custom_model_data: "在文件 发现问题 - 物品 '' 使用了无效的负数模型值 ''."
diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/ItemSettings.java b/core/src/main/java/net/momirealms/craftengine/core/item/ItemSettings.java
index bd621ea79..25d129b5a 100644
--- a/core/src/main/java/net/momirealms/craftengine/core/item/ItemSettings.java
+++ b/core/src/main/java/net/momirealms/craftengine/core/item/ItemSettings.java
@@ -12,10 +12,7 @@ import net.momirealms.craftengine.core.item.setting.Helmet;
import net.momirealms.craftengine.core.pack.misc.EquipmentGeneration;
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
import net.momirealms.craftengine.core.sound.SoundData;
-import net.momirealms.craftengine.core.util.Key;
-import net.momirealms.craftengine.core.util.MiscUtils;
-import net.momirealms.craftengine.core.util.ResourceConfigUtils;
-import net.momirealms.craftengine.core.util.VersionHelper;
+import net.momirealms.craftengine.core.util.*;
import org.jetbrains.annotations.Nullable;
import org.joml.Quaternionf;
import org.joml.Vector3f;
@@ -37,6 +34,7 @@ public class ItemSettings {
Helmet helmet = null;
FoodData foodData = null;
Key consumeReplacement = null;
+ List invulnerable = List.of();
private ItemSettings() {}
@@ -74,6 +72,7 @@ public class ItemSettings {
newSettings.helmet = settings.helmet;
newSettings.foodData = settings.foodData;
newSettings.consumeReplacement = settings.consumeReplacement;
+ newSettings.invulnerable = settings.invulnerable;
return newSettings;
}
@@ -141,6 +140,10 @@ public class ItemSettings {
return equipment;
}
+ public List invulnerable() {
+ return invulnerable;
+ }
+
public ItemSettings repairItems(List items) {
this.anvilRepairItems = items;
return this;
@@ -201,6 +204,11 @@ public class ItemSettings {
return this;
}
+ public ItemSettings invulnerable(List invulnerable) {
+ this.invulnerable = invulnerable;
+ return this;
+ }
+
@FunctionalInterface
public interface Modifier {
@@ -293,6 +301,16 @@ public class ItemSettings {
);
return settings -> settings.foodData(data);
}));
+ registerFactory("invulnerable", (value -> {
+ List list = MiscUtils.getAsStringList(value).stream().map(it -> {
+ try {
+ return DamageCause.byName(it);
+ } catch (IllegalArgumentException e) {
+ throw new LocalizedResourceConfigException("warning.config.item.settings.invulnerable-unknown", it);
+ }
+ }).toList();
+ return settings -> settings.invulnerable(list);
+ }));
}
private static void registerFactory(String id, ItemSettings.Modifier.Factory factory) {
diff --git a/core/src/main/java/net/momirealms/craftengine/core/util/DamageCause.java b/core/src/main/java/net/momirealms/craftengine/core/util/DamageCause.java
new file mode 100644
index 000000000..bf01e6833
--- /dev/null
+++ b/core/src/main/java/net/momirealms/craftengine/core/util/DamageCause.java
@@ -0,0 +1,58 @@
+package net.momirealms.craftengine.core.util;
+
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Optional;
+
+public enum DamageCause {
+ BLOCK_EXPLOSION,
+ CAMPFIRE,
+ CONTACT,
+ CRAMMING,
+ CUSTOM,
+ DROWNING,
+ DRYOUT,
+ ENTITY_ATTACK,
+ ENTITY_EXPLOSION,
+ ENTITY_SWEEP_ATTACK,
+ FALL,
+ FALLING_BLOCK,
+ FIRE,
+ FIRE_TICK,
+ FLY_INTO_WALL,
+ FREEZE,
+ HOT_FLOOR,
+ KILL,
+ LAVA,
+ LIGHTNING,
+ MAGIC,
+ MELTING,
+ POISON,
+ PROJECTILE,
+ SONIC_BOOM,
+ STARVATION,
+ SUFFOCATION,
+ SUICIDE,
+ THORNS,
+ VOID,
+ WITHER,
+ WORLD_BORDER,
+ @Deprecated
+ @SuppressWarnings("all")
+ DRAGON_BREATH;
+
+ public static final Map BY_NAME = new HashMap<>();
+
+ static {
+ for (DamageCause cause : values()) {
+ BY_NAME.put(cause.name().toLowerCase(Locale.ROOT), cause);
+ BY_NAME.put(cause.name(), cause);
+ }
+ }
+
+ public static DamageCause byName(String name) {
+ return Optional.ofNullable(BY_NAME.get(name)).orElseThrow(() -> new IllegalArgumentException("Unknown damage cause: " + name));
+ }
+
+}
diff --git a/gradle.properties b/gradle.properties
index 6e05db11f..d8bb1d53e 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -4,7 +4,7 @@ org.gradle.jvmargs=-Xmx1G
# Rule: [major update].[feature update].[bug fix]
project_version=0.0.56.5
config_version=36
-lang_version=15
+lang_version=16
project_group=net.momirealms
latest_supported_version=1.21.5