允许使用数据包定义DamageModifier,添加实体类型伤害免疫

This commit is contained in:
Light_Quanta 2025-05-20 08:35:25 +08:00
parent e3d0a2959f
commit cd6bc52270
No known key found for this signature in database
GPG key ID: 11A39A1B8C890959
7 changed files with 182 additions and 31 deletions

View file

@ -1,8 +1,11 @@
package com.atsuishio.superbwarfare.data.vehicle; package com.atsuishio.superbwarfare.data.vehicle;
import com.atsuishio.superbwarfare.config.server.VehicleConfig; import com.atsuishio.superbwarfare.config.server.VehicleConfig;
import com.atsuishio.superbwarfare.entity.vehicle.damage.DamageModify;
import com.google.gson.annotations.SerializedName; import com.google.gson.annotations.SerializedName;
import java.util.List;
public class DefaultVehicleData { public class DefaultVehicleData {
@SerializedName("ID") @SerializedName("ID")
public String id = ""; public String id = "";
@ -25,7 +28,9 @@ public class DefaultVehicleData {
@SerializedName("AllowFreeCam") @SerializedName("AllowFreeCam")
public boolean allowFreeCam = false; public boolean allowFreeCam = false;
// TODO damage modifier @SerializedName("ApplyDefaultDamageModifiers")
// @SerializedName("DamageModifier") public boolean applyDefaultDamageModifiers = true;
// private List<DamageModify> damageModifier;
@SerializedName("DamageModifiers")
public List<DamageModify> damageModifiers = List.of();
} }

View file

@ -1,9 +1,12 @@
package com.atsuishio.superbwarfare.data.vehicle; package com.atsuishio.superbwarfare.data.vehicle;
import com.atsuishio.superbwarfare.entity.vehicle.base.VehicleEntity; import com.atsuishio.superbwarfare.entity.vehicle.base.VehicleEntity;
import com.atsuishio.superbwarfare.entity.vehicle.damage.DamageModifier;
import com.atsuishio.superbwarfare.init.ModDamageTypes;
import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader; import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache; import com.google.common.cache.LoadingCache;
import net.minecraft.world.damagesource.DamageTypes;
import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.EntityType;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -53,4 +56,21 @@ public class VehicleData {
return data.allowFreeCam; return data.allowFreeCam;
} }
public DamageModifier damageModifier() {
var modifier = new DamageModifier();
if (data.applyDefaultDamageModifiers) {
modifier.immuneTo(EntityType.POTION)
.immuneTo(EntityType.AREA_EFFECT_CLOUD)
.immuneTo(DamageTypes.FALL)
.immuneTo(DamageTypes.DROWN)
.immuneTo(DamageTypes.DRAGON_BREATH)
.immuneTo(DamageTypes.WITHER)
.immuneTo(DamageTypes.WITHER_SKULL)
.reduce(5, ModDamageTypes.VEHICLE_STRIKE);
}
return modifier.addAll(data.damageModifiers);
}
} }

View file

@ -6,7 +6,6 @@ import com.atsuishio.superbwarfare.config.server.VehicleConfig;
import com.atsuishio.superbwarfare.entity.projectile.MelonBombEntity; import com.atsuishio.superbwarfare.entity.projectile.MelonBombEntity;
import com.atsuishio.superbwarfare.entity.vehicle.base.MobileVehicleEntity; import com.atsuishio.superbwarfare.entity.vehicle.base.MobileVehicleEntity;
import com.atsuishio.superbwarfare.entity.vehicle.base.ThirdPersonCameraPosition; import com.atsuishio.superbwarfare.entity.vehicle.base.ThirdPersonCameraPosition;
import com.atsuishio.superbwarfare.entity.vehicle.damage.DamageModifier;
import com.atsuishio.superbwarfare.init.ModDamageTypes; import com.atsuishio.superbwarfare.init.ModDamageTypes;
import com.atsuishio.superbwarfare.init.ModSounds; import com.atsuishio.superbwarfare.init.ModSounds;
import com.atsuishio.superbwarfare.tools.CustomExplosion; import com.atsuishio.superbwarfare.tools.CustomExplosion;
@ -93,12 +92,6 @@ public class Tom6Entity extends MobileVehicleEntity implements GeoEntity {
return false; return false;
} }
@Override
public DamageModifier getDamageModifier() {
return super.getDamageModifier()
.multiply(2, ModDamageTypes.VEHICLE_STRIKE);
}
@Override @Override
public @NotNull InteractionResult interact(Player player, @NotNull InteractionHand hand) { public @NotNull InteractionResult interact(Player player, @NotNull InteractionHand hand) {
if (player.getMainHandItem().is(Items.MELON) && !entityData.get(MELON)) { if (player.getMainHandItem().is(Items.MELON) && !entityData.get(MELON)) {

View file

@ -42,10 +42,12 @@ import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult; import net.minecraft.world.InteractionResult;
import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.damagesource.DamageTypes; import net.minecraft.world.damagesource.DamageTypes;
import net.minecraft.world.entity.*; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.Pose;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.projectile.AbstractArrow; import net.minecraft.world.entity.projectile.AbstractArrow;
import net.minecraft.world.entity.projectile.ThrownPotion;
import net.minecraft.world.entity.vehicle.DismountHelper; import net.minecraft.world.entity.vehicle.DismountHelper;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items; import net.minecraft.world.item.Items;
@ -450,14 +452,7 @@ public abstract class VehicleEntity extends Entity {
* @return DamageModifier * @return DamageModifier
*/ */
public DamageModifier getDamageModifier() { public DamageModifier getDamageModifier() {
return new DamageModifier() return data().damageModifier();
.immuneTo(source -> source.getDirectEntity() instanceof ThrownPotion || source.getDirectEntity() instanceof AreaEffectCloud)
.immuneTo(DamageTypes.FALL)
.immuneTo(DamageTypes.DROWN)
.immuneTo(DamageTypes.DRAGON_BREATH)
.immuneTo(DamageTypes.WITHER)
.immuneTo(DamageTypes.WITHER_SKULL)
.reduce(5, ModDamageTypes.VEHICLE_STRIKE);
} }
public float getSourceAngle(DamageSource source, float multiply) { public float getSourceAngle(DamageSource source, float multiply) {

View file

@ -4,6 +4,7 @@ import net.minecraft.resources.ResourceKey;
import net.minecraft.tags.TagKey; import net.minecraft.tags.TagKey;
import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.damagesource.DamageType; import net.minecraft.world.damagesource.DamageType;
import net.minecraft.world.entity.EntityType;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -55,6 +56,23 @@ public class DamageModifier {
return this; return this;
} }
/**
* 免疫指定类型的伤害
* @param entityId 伤害来源实体ID
*/
public DamageModifier immuneTo(String entityId) {
immuneList.add(new DamageModify(DamageModify.ModifyType.IMMUNITY, 0, entityId));
return this;
}
/**
* 免疫指定类型的伤害
* @param type 伤害来源实体类型
*/
public DamageModifier immuneTo(EntityType<?> type) {
return immuneTo(EntityType.getKey(type).toString());
}
/** /**
* 固定减少所有伤害一定数值 * 固定减少所有伤害一定数值
* *
@ -98,6 +116,25 @@ public class DamageModifier {
return this; return this;
} }
/**
* 固定减少指定类型的伤害一定数值
* @param value 要减少的数值
* @param entityId 伤害来源实体ID
*/
public DamageModifier reduce(float value, String entityId) {
reduceList.add(new DamageModify(DamageModify.ModifyType.REDUCE, value, entityId));
return this;
}
/**
* 固定减少指定类型的伤害一定数值
* @param value 要减少的数值
* @param type 伤害来源实体类型
*/
public DamageModifier reduce(float value, EntityType<?> type) {
return reduce(value, EntityType.getKey(type).toString());
}
/** /**
* 将所有类型的伤害值乘以指定数值 * 将所有类型的伤害值乘以指定数值
* *
@ -141,6 +178,25 @@ public class DamageModifier {
return this; return this;
} }
/**
* 将指定类型的伤害值乘以指定数值
* @param value 要乘以的数值
* @param entityId 伤害来源实体ID
*/
public DamageModifier multiply(float value, String entityId) {
multiplyList.add(new DamageModify(DamageModify.ModifyType.MULTIPLY, value, entityId));
return this;
}
/**
* 将指定类型的伤害值乘以指定数值
* @param value 要乘以的数值
* @param type 伤害来源实体类型
*/
public DamageModifier multiply(float value, EntityType<?> type) {
return multiply(value, EntityType.getKey(type).toString());
}
/** /**
* 自定义伤害值计算 * 自定义伤害值计算
* *
@ -151,6 +207,17 @@ public class DamageModifier {
return this; return this;
} }
public DamageModifier addAll(List<DamageModify> list) {
for (var damageModify : list) {
switch (damageModify.getType()) {
case IMMUNITY -> immuneList.add(damageModify);
case REDUCE -> reduceList.add(damageModify);
case MULTIPLY -> multiplyList.add(damageModify);
}
}
return this;
}
private final List<DamageModify> combinedList = new ArrayList<>(); private final List<DamageModify> combinedList = new ArrayList<>();
/** /**

View file

@ -1,10 +1,13 @@
package com.atsuishio.superbwarfare.entity.vehicle.damage; package com.atsuishio.superbwarfare.entity.vehicle.damage;
import com.google.gson.annotations.SerializedName; import com.google.gson.annotations.SerializedName;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.TagKey; import net.minecraft.tags.TagKey;
import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.damagesource.DamageType; import net.minecraft.world.damagesource.DamageType;
import net.minecraft.world.entity.EntityType;
import java.util.function.Function; import java.util.function.Function;
@ -19,20 +22,41 @@ public class DamageModify {
} }
@SerializedName("Value") @SerializedName("Value")
private float value; private float value = 0;
@SerializedName("Type") @SerializedName("Type")
private ModifyType type; private ModifyType type = ModifyType.IMMUNITY;
public ModifyType getType() {
return type;
}
@SerializedName("Source") @SerializedName("Source")
private String source; private String source = "All";
private transient String entityId = "";
// 必须默认为null否则无法处理JSON读取Source的情况
private transient SourceType sourceType = null;
private enum SourceType {
TAG_KEY,
RESOURCE_KEY,
FUNCTION,
ENTITY_ID,
ALL,
}
private transient TagKey<DamageType> sourceTagKey = null; private transient TagKey<DamageType> sourceTagKey = null;
private transient ResourceKey<DamageType> sourceKey = null; private transient ResourceKey<DamageType> sourceKey = null;
private transient Function<DamageSource, Boolean> condition = null; private transient Function<DamageSource, Boolean> condition = null;
public DamageModify() {
}
public DamageModify(ModifyType type, float value) { public DamageModify(ModifyType type, float value) {
this.type = type; this.type = type;
this.value = value; this.value = value;
this.sourceType = SourceType.ALL;
} }
@ -40,18 +64,43 @@ public class DamageModify {
this.type = type; this.type = type;
this.value = value; this.value = value;
this.sourceTagKey = sourceTagKey; this.sourceTagKey = sourceTagKey;
this.sourceType = SourceType.TAG_KEY;
} }
public DamageModify(ModifyType type, float value, ResourceKey<DamageType> sourceKey) { public DamageModify(ModifyType type, float value, ResourceKey<DamageType> sourceKey) {
this.type = type; this.type = type;
this.value = value; this.value = value;
this.sourceKey = sourceKey; this.sourceKey = sourceKey;
this.sourceType = SourceType.RESOURCE_KEY;
} }
public DamageModify(ModifyType type, float value, Function<DamageSource, Boolean> condition) { public DamageModify(ModifyType type, float value, Function<DamageSource, Boolean> condition) {
this.type = type; this.type = type;
this.value = value; this.value = value;
this.condition = condition; this.condition = condition;
this.sourceType = SourceType.FUNCTION;
}
public DamageModify(ModifyType type, float value, String entityId) {
this.type = type;
this.value = value;
this.entityId = entityId;
this.sourceType = SourceType.ENTITY_ID;
}
private void generateSourceType() {
if (source.startsWith("#")) {
sourceType = SourceType.TAG_KEY;
this.sourceTagKey = TagKey.create(Registries.DAMAGE_TYPE, ResourceLocation.parse(source.substring(1)));
} else if (source.startsWith("@")) {
sourceType = SourceType.ENTITY_ID;
this.entityId = source.substring(1);
} else if (!source.equals("All")) {
sourceType = SourceType.RESOURCE_KEY;
this.sourceKey = ResourceKey.create(Registries.DAMAGE_TYPE, ResourceLocation.parse(source));
} else {
sourceType = SourceType.ALL;
}
} }
/** /**
@ -61,14 +110,29 @@ public class DamageModify {
* @return 伤害来源是否符合条件 * @return 伤害来源是否符合条件
*/ */
public boolean match(DamageSource source) { public boolean match(DamageSource source) {
if (condition != null) { if (sourceType == null) {
return condition.apply(source); generateSourceType();
} else if (sourceTagKey != null) {
return source.is(sourceTagKey);
} else if (sourceKey != null) {
return source.is(sourceKey);
} }
return true;
return switch (sourceType) {
case TAG_KEY -> source.is(sourceTagKey);
case RESOURCE_KEY -> source.is(sourceKey);
case FUNCTION -> condition.apply(source);
case ENTITY_ID -> {
var directEntity = source.getDirectEntity();
var entity = source.getEntity();
// TODO 是否考虑优先处理Entity而不是DirectEntity
if (directEntity != null) {
yield EntityType.getKey(directEntity.getType()).toString().equals(this.entityId);
} else if (entity != null) {
yield EntityType.getKey(entity.getType()).toString().equals(this.entityId);
} else {
yield false;
}
}
case ALL -> true;
};
} }
/** /**

View file

@ -3,5 +3,12 @@
"MaxHealth": 40, "MaxHealth": 40,
"MaxEnergy": 100000, "MaxEnergy": 100000,
"UpStep": 0.5, "UpStep": 0.5,
"allowFreeCam": true "allowFreeCam": true,
"DamageModifiers": [
{
"Type": "Multiply",
"Value": 2,
"Source": "superbwarfare:vehicle_strike"
}
]
} }