superb-warfare/src/main/java/com/atsuishio/superbwarfare/entity/vehicle/MobileVehicleEntity.java
2025-01-17 03:20:04 +08:00

207 lines
9.8 KiB
Java

package com.atsuishio.superbwarfare.entity.vehicle;
import com.atsuishio.superbwarfare.entity.DroneEntity;
import com.atsuishio.superbwarfare.entity.TargetEntity;
import com.atsuishio.superbwarfare.entity.projectile.FlareDecoyEntity;
import com.atsuishio.superbwarfare.entity.projectile.LaserEntity;
import com.atsuishio.superbwarfare.entity.projectile.ProjectileEntity;
import com.atsuishio.superbwarfare.init.ModDamageTypes;
import com.atsuishio.superbwarfare.init.ModSounds;
import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.EntityDataSerializers;
import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.AreaEffectCloud;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.MoverType;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.projectile.Projectile;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.entity.EntityTypeTest;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.NotNull;
import org.joml.Math;
import org.joml.Vector3f;
public class MobileVehicleEntity extends EnergyVehicleEntity {
public static final EntityDataAccessor<Float> POWER = SynchedEntityData.defineId(MobileVehicleEntity.class, EntityDataSerializers.FLOAT);
public boolean leftInputDown;
public boolean rightInputDown;
public boolean forwardInputDown;
public boolean backInputDown;
public boolean upInputDown;
public boolean downInputDown;
public boolean decoyInputDown;
public double lastTickSpeed;
public double lastTickVerticalSpeed;
public int collisionCoolDown;
public MobileVehicleEntity(EntityType<?> pEntityType, Level pLevel) {
super(pEntityType, pLevel);
}
@Override
public void playerTouch(Player pPlayer) {
if (pPlayer.isCrouching() && !this.level().isClientSide) {
double entitySize = pPlayer.getBbWidth() * pPlayer.getBbHeight();
double thisSize = this.getBbWidth() * this.getBbHeight();
double f = Math.min(entitySize / thisSize, 2);
double f1 = Math.min(thisSize / entitySize, 4);
this.setDeltaMovement(this.getDeltaMovement().add(new Vec3(pPlayer.position().vectorTo(this.position()).toVector3f()).scale(0.15 * f * pPlayer.getDeltaMovement().length())));
pPlayer.setDeltaMovement(pPlayer.getDeltaMovement().add(new Vec3(this.position().vectorTo(pPlayer.position()).toVector3f()).scale(0.1 * f1 * pPlayer.getDeltaMovement().length())));
}
}
@Override
public void baseTick() {
lastTickSpeed = new Vec3(this.getDeltaMovement().x, this.getDeltaMovement().y + 0.06, this.getDeltaMovement().z).length();
lastTickVerticalSpeed = this.getDeltaMovement().y + 0.06;
if (collisionCoolDown > 0) {
collisionCoolDown--;
}
super.baseTick();
crushEntities(this.getDeltaMovement());
this.setDeltaMovement(this.getDeltaMovement().add(0.0, -0.06, 0.0));
this.move(MoverType.SELF, this.getDeltaMovement());
this.refreshDimensions();
}
@Override
public void move(@NotNull MoverType movementType, @NotNull Vec3 movement) {
super.move(movementType, movement);
if (lastTickSpeed < 0.3 || collisionCoolDown > 0) return;
if ((verticalCollision)) {
if (this instanceof IHelicopterEntity) {
this.hurt(ModDamageTypes.causeVehicleStrikeDamage(this.level().registryAccess(), this, this.getFirstPassenger() == null ? this : this.getFirstPassenger()), (float) (100 * ((lastTickSpeed - 0.3) * (lastTickSpeed - 0.3))));
this.bounceVertical(Direction.getNearest(this.getDeltaMovement().x(), this.getDeltaMovement().y(), this.getDeltaMovement().z()).getOpposite());
} else if (Mth.abs((float) lastTickVerticalSpeed) > 0.6) {
this.hurt(ModDamageTypes.causeVehicleStrikeDamage(this.level().registryAccess(), this, this.getFirstPassenger() == null ? this : this.getFirstPassenger()), (float) (240 * ((Mth.abs((float) lastTickVerticalSpeed) - 0.6) * (lastTickSpeed - 0.4) * (lastTickSpeed - 0.4))));
if (!this.level().isClientSide) {
this.level().playSound(null, this, ModSounds.VEHICLE_STRIKE.get(), this.getSoundSource(), 1, 1);
}
this.bounceVertical(Direction.getNearest(this.getDeltaMovement().x(), this.getDeltaMovement().y(), this.getDeltaMovement().z()).getOpposite());
}
}
if (this.horizontalCollision) {
this.hurt(ModDamageTypes.causeVehicleStrikeDamage(this.level().registryAccess(), this, this.getFirstPassenger() == null ? this : this.getFirstPassenger()), (float) (180 * ((lastTickSpeed - 0.4) * (lastTickSpeed - 0.4))));
this.bounceHorizontal(Direction.getNearest(this.getDeltaMovement().x(), this.getDeltaMovement().y(), this.getDeltaMovement().z()).getOpposite());
if (!this.level().isClientSide) {
this.level().playSound(null, this, ModSounds.VEHICLE_STRIKE.get(), this.getSoundSource(), 1, 1);
}
collisionCoolDown = 4;
crash = true;
}
}
public void bounceHorizontal(Direction direction) {
switch (direction.getAxis()) {
case X:
this.setDeltaMovement(this.getDeltaMovement().multiply(-0.8, 0.99, 0.99));
break;
case Z:
this.setDeltaMovement(this.getDeltaMovement().multiply(0.99, 0.99, -0.8));
break;
}
}
public void bounceVertical(Direction direction) {
if (!this.level().isClientSide) {
this.level().playSound(null, this, ModSounds.VEHICLE_STRIKE.get(), this.getSoundSource(), 1, 1);
}
collisionCoolDown = 4;
crash = true;
if (direction.getAxis() == Direction.Axis.Y) {
this.setDeltaMovement(this.getDeltaMovement().multiply(0.9, -0.8, 0.9));
}
}
/**
* 撞击实体并造成伤害
* @param velocity 动量
*/
public void crushEntities(Vec3 velocity) {
if (this instanceof DroneEntity) return;
if (velocity.horizontalDistance() < 0.1) return;
if (isRemoved()) return;
var frontBox = getBoundingBox().move(velocity.scale(0.5));
var velAdd = velocity.add(0, 0, 0).scale(0.9);
var entities = level().getEntities(EntityTypeTest.forClass(Entity.class), frontBox,
entity -> entity != this && entity != getFirstPassenger() && entity.getVehicle() == null)
.stream().filter(entity -> entity.isAlive()
&& !(entity instanceof ItemEntity || entity instanceof Projectile || entity instanceof ProjectileEntity || entity instanceof LaserEntity || entity instanceof FlareDecoyEntity || entity instanceof AreaEffectCloud)
&& !(entity instanceof Player player && (player.isSpectator() || player.isCreative())))
.toList();
for (var entity : entities) {
double entitySize = entity.getBbWidth() * entity.getBbHeight();
double thisSize = this.getBbWidth() * this.getBbHeight();
double f = Math.min(entitySize / thisSize, 2);
double f1 = Math.min(thisSize / entitySize, 4);
if (velocity.length() > 0.3) {
if (!this.level().isClientSide) {
this.level().playSound(null, this, ModSounds.VEHICLE_STRIKE.get(), this.getSoundSource(), 1, 1);
}
if (!(entity instanceof TargetEntity)) {
this.push(-f * velAdd.x, -f * velAdd.y, -f * velAdd.z);
}
entity.push(f1 * velAdd.x, f1 * velAdd.y, f1 * velAdd.z);
entity.hurt(ModDamageTypes.causeVehicleStrikeDamage(this.level().registryAccess(), this, this.getFirstPassenger() == null ? this : this.getFirstPassenger()), (float) (thisSize * 20 * ((velocity.length() - 0.3) * (velocity.length() - 0.3))));
if (entities instanceof VehicleEntity) {
this.hurt(ModDamageTypes.causeVehicleStrikeDamage(this.level().registryAccess(), entity, entity.getFirstPassenger() == null ? entity : entity.getFirstPassenger()), (float) (entitySize * 10 * ((velocity.length() - 0.3) * (velocity.length() - 0.3))));
}
} else {
entity.push(0.3 * f1 * velAdd.x, 0.3 * f1 * velAdd.y, 0.3 * f1 * velAdd.z);
}
}
}
public Vector3f getForwardDirection() {
return new Vector3f(
Mth.sin(-getYRot() * ((float) java.lang.Math.PI / 180)),
0.0f,
Mth.cos(getYRot() * ((float) java.lang.Math.PI / 180))
).normalize();
}
public Vector3f getRightDirection() {
return new Vector3f(
Mth.cos(-getYRot() * ((float) java.lang.Math.PI / 180)),
0.0f,
Mth.sin(getYRot() * ((float) java.lang.Math.PI / 180))
).normalize();
}
public SoundEvent getEngineSound() {
return SoundEvents.EMPTY;
}
@Override
protected void defineSynchedData() {
super.defineSynchedData();
this.entityData.define(POWER, 0f);
}
@Override
protected void readAdditionalSaveData(CompoundTag compound) {
super.readAdditionalSaveData(compound);
this.entityData.set(POWER, compound.getFloat("Power"));
}
@Override
public void addAdditionalSaveData(CompoundTag compound) {
super.addAdditionalSaveData(compound);
compound.putFloat("Power", this.entityData.get(POWER));
}
}