Casualty Control

- Attempted to reduce false positives for damage from carriage contraptions
This commit is contained in:
simibubi 2022-09-22 18:03:15 +02:00
parent eee9c509e3
commit e6903a733d
4 changed files with 94 additions and 63 deletions

View File

@ -58,6 +58,8 @@ public class BlockBreakingMovementBehaviour implements MovementBehaviour {
continue;
if (entity instanceof AbstractContraptionEntity)
continue;
if (entity.isPassengerOfSameVehicle(context.contraption.entity))
continue;
if (entity instanceof AbstractMinecart)
for (Entity passenger : entity.getIndirectPassengers())
if (passenger instanceof AbstractContraptionEntity

View File

@ -139,6 +139,10 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit
public boolean collisionEnabled() {
return true;
}
public void registerColliding(Entity collidingEntity) {
collidingEntities.put(collidingEntity, new MutableInt());
}
public void addSittingPassenger(Entity passenger, int seatIndex) {
for (Entity entity : getPassengers()) {

View File

@ -7,7 +7,6 @@ import java.util.List;
import org.apache.commons.lang3.mutable.MutableBoolean;
import org.apache.commons.lang3.mutable.MutableFloat;
import org.apache.commons.lang3.mutable.MutableInt;
import org.apache.commons.lang3.mutable.MutableObject;
import com.google.common.base.Predicates;
@ -88,11 +87,12 @@ public class ContraptionCollider {
if (playerType == PlayerType.REMOTE)
continue;
entity.getSelfAndPassengers().forEach(e -> {
if (e instanceof ServerPlayer)
((ServerPlayer) e).connection.aboveGroundTickCount = 0;
});
entity.getSelfAndPassengers()
.forEach(e -> {
if (e instanceof ServerPlayer)
((ServerPlayer) e).connection.aboveGroundTickCount = 0;
});
if (playerType == PlayerType.SERVER)
continue;
@ -329,50 +329,15 @@ public class ContraptionCollider {
entityPosition.z + allowedMovement.z);
entityPosition = entity.position();
if (contraptionEntity instanceof CarriageContraptionEntity cce && entity.isOnGround()
&& !(entity instanceof ItemEntity) && cce.nonDamageTicks == 0
&& AllConfigs.SERVER.trains.trainsCauseDamage.get()) {
Vec3 diffMotion = contraptionMotion.subtract(entity.getDeltaMovement());
if (diffMotion.length() > 0.35f && contraptionMotion.length() > 0.35f) {
EntityDamageSource pSource = new EntityDamageSource("create.run_over", contraptionEntity);
double damage = diffMotion.length();
if (entity.getClassification(false) == MobCategory.MONSTER)
damage *= 2;
if (!(entity instanceof Player p) || !p.isCreative() && !p.isSpectator()) {
if (playerType == PlayerType.CLIENT) {
AllPackets.channel
.sendToServer(new TrainCollisionPacket((int) (damage * 16), contraptionEntity.getId()));
world.playSound((Player) entity, entity.blockPosition(), SoundEvents.PLAYER_ATTACK_CRIT,
SoundSource.NEUTRAL, 1, .75f);
} else {
entity.hurt(pSource, (int) (damage * 16));
world.playSound(null, entity.blockPosition(), SoundEvents.PLAYER_ATTACK_CRIT,
SoundSource.NEUTRAL, 1, .75f);
if (!entity.isAlive())
contraptionEntity.getControllingPlayer()
.map(world::getPlayerByUUID)
.ifPresent(AllAdvancements.TRAIN_ROADKILL::awardTo);
}
Vec3 added = entityMotion.add(contraptionMotion.multiply(1, 0, 1)
.normalize()
.add(0, .25, 0)
.scale(damage * 4))
.add(diffMotion);
entityMotion = VecHelper.clamp(added, 3);
}
}
}
entityMotion =
handleDamageFromTrain(world, contraptionEntity, contraptionMotion, entity, entityMotion, playerType);
entity.hurtMarked = true;
Vec3 contactPointMotion = Vec3.ZERO;
if (surfaceCollision.isTrue()) {
contraptionEntity.registerColliding(entity);
entity.fallDistance = 0;
contraptionEntity.collidingEntities.put(entity, new MutableInt(0));
boolean canWalk = bounce != 0 || slide == 0;
if (canWalk || !rotation.hasVerticalRotation()) {
if (canWalk)
@ -401,6 +366,57 @@ public class ContraptionCollider {
}
private static Vec3 handleDamageFromTrain(Level world, AbstractContraptionEntity contraptionEntity,
Vec3 contraptionMotion, Entity entity, Vec3 entityMotion, PlayerType playerType) {
if (!(contraptionEntity instanceof CarriageContraptionEntity cce))
return entityMotion;
if (!entity.isOnGround())
return entityMotion;
if (cce.collidingEntities.containsKey(entity))
return entityMotion;
if (entity instanceof ItemEntity)
return entityMotion;
if (cce.nonDamageTicks != 0)
return entityMotion;
if (!AllConfigs.SERVER.trains.trainsCauseDamage.get())
return entityMotion;
Vec3 diffMotion = contraptionMotion.subtract(entity.getDeltaMovement());
if (diffMotion.length() <= 0.35f || contraptionMotion.length() <= 0.35f)
return entityMotion;
EntityDamageSource pSource = new EntityDamageSource("create.run_over", contraptionEntity);
double damage = diffMotion.length();
if (entity.getClassification(false) == MobCategory.MONSTER)
damage *= 2;
if (entity instanceof Player p && (p.isCreative() || p.isSpectator()))
return entityMotion;
if (playerType == PlayerType.CLIENT) {
AllPackets.channel.sendToServer(new TrainCollisionPacket((int) (damage * 16), contraptionEntity.getId()));
world.playSound((Player) entity, entity.blockPosition(), SoundEvents.PLAYER_ATTACK_CRIT,
SoundSource.NEUTRAL, 1, .75f);
} else {
entity.hurt(pSource, (int) (damage * 16));
world.playSound(null, entity.blockPosition(), SoundEvents.PLAYER_ATTACK_CRIT, SoundSource.NEUTRAL, 1, .75f);
if (!entity.isAlive())
contraptionEntity.getControllingPlayer()
.map(world::getPlayerByUUID)
.ifPresent(AllAdvancements.TRAIN_ROADKILL::awardTo);
}
Vec3 added = entityMotion.add(contraptionMotion.multiply(1, 0, 1)
.normalize()
.add(0, .25, 0)
.scale(damage * 4))
.add(diffMotion);
return VecHelper.clamp(added, 3);
}
static boolean bounceEntity(Entity entity, Vec3 normal, AbstractContraptionEntity contraption, double factor) {
if (factor == 0)
return false;
@ -473,10 +489,10 @@ public class ContraptionCollider {
boolean flag = p_20273_.x != vec3.x;
boolean flag1 = p_20273_.y != vec3.y;
boolean flag2 = p_20273_.z != vec3.z;
boolean flag3 = e.isOnGround() || flag1 && p_20273_.y < 0.0D;
boolean flag3 = flag1 && p_20273_.y < 0.0D;
if (e.getStepHeight() > 0.0F && flag3 && (flag || flag2)) {
Vec3 vec31 =
collideBoundingBox(e, new Vec3(p_20273_.x, (double) e.getStepHeight(), p_20273_.z), aabb, e.level, list);
Vec3 vec31 = collideBoundingBox(e, new Vec3(p_20273_.x, (double) e.getStepHeight(), p_20273_.z), aabb,
e.level, list);
Vec3 vec32 = collideBoundingBox(e, new Vec3(0.0D, (double) e.getStepHeight(), 0.0D),
aabb.expandTowards(p_20273_.x, 0.0D, p_20273_.z), e.level, list);
if (vec32.y < (double) e.getStepHeight()) {

View File

@ -107,29 +107,38 @@ public abstract class EntityContraptionInteractionMixin extends CapabilityProvid
if (stepped.get())
this.nextStep = this.nextStep();
}
@Inject(at = @At(value = "TAIL"), method = "move")
private void movementMixin(MoverType mover, Vec3 movement, CallbackInfo ci) {
if (self.level.isClientSide && !self.isOnGround()) { // involves client-side view bobbing animation on contraptions
Vec3 worldPos = self.position()
.add(0, -0.2, 0);
// involves client-side view bobbing animation on contraptions
if (!self.level.isClientSide)
return;
if (self.isOnGround())
return;
boolean staysOnAtLeastOneContraption = getIntersectionContraptionsStream().anyMatch(cEntity -> {
Vec3 localPos = ContraptionCollider.getWorldToLocalTranslation(worldPos, cEntity);
Vec3 worldPos = self.position()
.add(0, -0.2, 0);
boolean onAtLeastOneContraption = getIntersectionContraptionsStream().anyMatch(cEntity -> {
Vec3 localPos = ContraptionCollider.getWorldToLocalTranslation(worldPos, cEntity);
localPos = worldPos.add(localPos);
localPos = worldPos.add(localPos);
BlockPos blockPos = new BlockPos(localPos);
Contraption contraption = cEntity.getContraption();
StructureTemplate.StructureBlockInfo info = contraption.getBlocks()
.get(blockPos);
BlockPos blockPos = new BlockPos(localPos);
Contraption contraption = cEntity.getContraption();
StructureTemplate.StructureBlockInfo info = contraption.getBlocks()
.get(blockPos);
return info != null;
});
if (info == null)
return false;
cEntity.registerColliding(self);
return true;
});
if (staysOnAtLeastOneContraption) {
self.setOnGround(true);
}
}
if (!onAtLeastOneContraption)
return;
self.setOnGround(true);
}
@Inject(method = { "spawnSprintParticle" }, at = @At(value = "TAIL"))