From e6903a733d6e1d20583f8ae50816bf5736931172 Mon Sep 17 00:00:00 2001 From: simibubi <31564874+simibubi@users.noreply.github.com> Date: Thu, 22 Sep 2022 18:03:15 +0200 Subject: [PATCH] Casualty Control - Attempted to reduce false positives for damage from carriage contraptions --- .../BlockBreakingMovementBehaviour.java | 2 + .../AbstractContraptionEntity.java | 4 + .../ContraptionCollider.java | 110 ++++++++++-------- .../EntityContraptionInteractionMixin.java | 41 ++++--- 4 files changed, 94 insertions(+), 63 deletions(-) diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/BlockBreakingMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/BlockBreakingMovementBehaviour.java index 65b099ea7..70771c429 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/BlockBreakingMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/BlockBreakingMovementBehaviour.java @@ -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 diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AbstractContraptionEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AbstractContraptionEntity.java index 58ccad24e..f36dda9b8 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AbstractContraptionEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AbstractContraptionEntity.java @@ -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()) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionCollider.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionCollider.java index a669f66b8..f8258f762 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionCollider.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionCollider.java @@ -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()) { diff --git a/src/main/java/com/simibubi/create/foundation/mixin/EntityContraptionInteractionMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/EntityContraptionInteractionMixin.java index 16892decd..efc48643b 100644 --- a/src/main/java/com/simibubi/create/foundation/mixin/EntityContraptionInteractionMixin.java +++ b/src/main/java/com/simibubi/create/foundation/mixin/EntityContraptionInteractionMixin.java @@ -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"))