允许使用数据包定义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;
import com.atsuishio.superbwarfare.config.server.VehicleConfig;
import com.atsuishio.superbwarfare.entity.vehicle.damage.DamageModify;
import com.google.gson.annotations.SerializedName;
import java.util.List;
public class DefaultVehicleData {
@SerializedName("ID")
public String id = "";
@ -25,7 +28,9 @@ public class DefaultVehicleData {
@SerializedName("AllowFreeCam")
public boolean allowFreeCam = false;
// TODO damage modifier
// @SerializedName("DamageModifier")
// private List<DamageModify> damageModifier;
@SerializedName("ApplyDefaultDamageModifiers")
public boolean applyDefaultDamageModifiers = true;
@SerializedName("DamageModifiers")
public List<DamageModify> damageModifiers = List.of();
}

View file

@ -1,9 +1,12 @@
package com.atsuishio.superbwarfare.data.vehicle;
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.CacheLoader;
import com.google.common.cache.LoadingCache;
import net.minecraft.world.damagesource.DamageTypes;
import net.minecraft.world.entity.EntityType;
import org.jetbrains.annotations.NotNull;
@ -53,4 +56,21 @@ public class VehicleData {
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.vehicle.base.MobileVehicleEntity;
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.ModSounds;
import com.atsuishio.superbwarfare.tools.CustomExplosion;
@ -93,12 +92,6 @@ public class Tom6Entity extends MobileVehicleEntity implements GeoEntity {
return false;
}
@Override
public DamageModifier getDamageModifier() {
return super.getDamageModifier()
.multiply(2, ModDamageTypes.VEHICLE_STRIKE);
}
@Override
public @NotNull InteractionResult interact(Player player, @NotNull InteractionHand hand) {
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.damagesource.DamageSource;
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.projectile.AbstractArrow;
import net.minecraft.world.entity.projectile.ThrownPotion;
import net.minecraft.world.entity.vehicle.DismountHelper;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
@ -450,14 +452,7 @@ public abstract class VehicleEntity extends Entity {
* @return DamageModifier
*/
public DamageModifier getDamageModifier() {
return new 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);
return data().damageModifier();
}
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.world.damagesource.DamageSource;
import net.minecraft.world.damagesource.DamageType;
import net.minecraft.world.entity.EntityType;
import java.util.ArrayList;
import java.util.List;
@ -55,6 +56,23 @@ public class DamageModifier {
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;
}
/**
* 固定减少指定类型的伤害一定数值
* @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;
}
/**
* 将指定类型的伤害值乘以指定数值
* @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;
}
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<>();
/**

View file

@ -1,10 +1,13 @@
package com.atsuishio.superbwarfare.entity.vehicle.damage;
import com.google.gson.annotations.SerializedName;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.TagKey;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.damagesource.DamageType;
import net.minecraft.world.entity.EntityType;
import java.util.function.Function;
@ -19,20 +22,41 @@ public class DamageModify {
}
@SerializedName("Value")
private float value;
private float value = 0;
@SerializedName("Type")
private ModifyType type;
private ModifyType type = ModifyType.IMMUNITY;
public ModifyType getType() {
return type;
}
@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 ResourceKey<DamageType> sourceKey = null;
private transient Function<DamageSource, Boolean> condition = null;
public DamageModify() {
}
public DamageModify(ModifyType type, float value) {
this.type = type;
this.value = value;
this.sourceType = SourceType.ALL;
}
@ -40,18 +64,43 @@ public class DamageModify {
this.type = type;
this.value = value;
this.sourceTagKey = sourceTagKey;
this.sourceType = SourceType.TAG_KEY;
}
public DamageModify(ModifyType type, float value, ResourceKey<DamageType> sourceKey) {
this.type = type;
this.value = value;
this.sourceKey = sourceKey;
this.sourceType = SourceType.RESOURCE_KEY;
}
public DamageModify(ModifyType type, float value, Function<DamageSource, Boolean> condition) {
this.type = type;
this.value = value;
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 伤害来源是否符合条件
*/
public boolean match(DamageSource source) {
if (condition != null) {
return condition.apply(source);
} else if (sourceTagKey != null) {
return source.is(sourceTagKey);
} else if (sourceKey != null) {
return source.is(sourceKey);
if (sourceType == null) {
generateSourceType();
}
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,
"MaxEnergy": 100000,
"UpStep": 0.5,
"allowFreeCam": true
"allowFreeCam": true,
"DamageModifiers": [
{
"Type": "Multiply",
"Value": 2,
"Source": "superbwarfare:vehicle_strike"
}
]
}