diff --git a/src/main/java/com/atsuishio/superbwarfare/client/model/entity/DroneModel.java b/src/main/java/com/atsuishio/superbwarfare/client/model/entity/DroneModel.java index 80bd34191..2580e608c 100644 --- a/src/main/java/com/atsuishio/superbwarfare/client/model/entity/DroneModel.java +++ b/src/main/java/com/atsuishio/superbwarfare/client/model/entity/DroneModel.java @@ -4,9 +4,7 @@ import com.atsuishio.superbwarfare.ModUtils; import com.atsuishio.superbwarfare.entity.DroneEntity; import com.atsuishio.superbwarfare.init.ModItems; import com.atsuishio.superbwarfare.tools.EntityFindUtil; -import net.minecraft.client.Minecraft; import net.minecraft.resources.ResourceLocation; -import net.minecraft.util.Mth; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import software.bernie.geckolib.core.animatable.model.CoreGeoBone; @@ -16,15 +14,8 @@ import software.bernie.geckolib.model.GeoModel; import java.util.UUID; import static com.atsuishio.superbwarfare.entity.DroneEntity.*; -import static com.atsuishio.superbwarfare.event.ClientEventHandler.droneBodyAngle; public class DroneModel extends GeoModel { - - public static float rotX = 0; - public static float rotZ = 0; - - public static float rotation = 0; - @Override public ResourceLocation getAnimationResource(DroneEntity entity) { return ModUtils.loc("animations/drone.animation.json"); @@ -49,7 +40,6 @@ public class DroneModel extends GeoModel { CoreGeoBone ammo5 = getAnimationProcessor().getBone("ammo5"); CoreGeoBone ammo6 = getAnimationProcessor().getBone("ammo6"); CoreGeoBone shell = getAnimationProcessor().getBone("shell"); - CoreGeoBone main = getAnimationProcessor().getBone("0"); ammo6.setHidden(animatable.getEntityData().get(AMMO) <= 5); ammo5.setHidden(animatable.getEntityData().get(AMMO) <= 4); @@ -59,33 +49,6 @@ public class DroneModel extends GeoModel { ammo1.setHidden(animatable.getEntityData().get(AMMO) <= 0); shell.setHidden(!animatable.getEntityData().get(KAMIKAZE)); - float times = Math.min(Minecraft.getInstance().getDeltaFrameTime(), 1); - - if (Minecraft.getInstance().options.keyRight.isDown()) { - rotZ = Mth.lerp(0.025f * times, rotZ, -0.25f); - } else if (Minecraft.getInstance().options.keyLeft.isDown()) { - rotZ = Mth.lerp(0.025f * times, rotZ, 0.25f); - } else { - rotZ = Mth.lerp(0.04f * times, rotZ, 0); - } - - main.setRotZ(rotZ); - - droneBodyAngle(rotZ); - - // 螺旋桨控制 - CoreGeoBone wingFL = getAnimationProcessor().getBone("wingFL"); - CoreGeoBone wingFR = getAnimationProcessor().getBone("wingFR"); - CoreGeoBone wingBL = getAnimationProcessor().getBone("wingBL"); - CoreGeoBone wingBR = getAnimationProcessor().getBone("wingBR"); - - rotation = (float) Mth.lerp(times, rotation, animatable.onGround() ? 0 : 0.2); - - wingFL.setRotY(wingFL.getRotY() - rotation); - wingFR.setRotY(wingFL.getRotY() - rotation); - wingBL.setRotY(wingFL.getRotY() - rotation); - wingBR.setRotY(wingFL.getRotY() - rotation); - CoreGeoBone weapon = getAnimationProcessor().getBone("Weapon"); String id = animatable.getEntityData().get(CONTROLLER); UUID uuid; diff --git a/src/main/java/com/atsuishio/superbwarfare/client/renderer/entity/Ah6Renderer.java b/src/main/java/com/atsuishio/superbwarfare/client/renderer/entity/Ah6Renderer.java index dbf89ea7b..ccdf22b93 100644 --- a/src/main/java/com/atsuishio/superbwarfare/client/renderer/entity/Ah6Renderer.java +++ b/src/main/java/com/atsuishio/superbwarfare/client/renderer/entity/Ah6Renderer.java @@ -40,7 +40,7 @@ public class Ah6Renderer extends GeoEntityRenderer { poseStack.pushPose(); poseStack.mulPose(Axis.YP.rotationDegrees(-entityYaw)); poseStack.mulPose(Axis.XP.rotationDegrees(Mth.lerp(partialTicks, entityIn.xRotO, entityIn.getXRot()))); - poseStack.mulPose(Axis.ZP.rotationDegrees(entityIn.getRoll(partialTicks))); + poseStack.mulPose(Axis.ZP.rotationDegrees(Mth.lerp(partialTicks, entityIn.prevRoll, entityIn.getRoll()))); super.render(entityIn, entityYaw, partialTicks, poseStack, bufferIn, packedLightIn); poseStack.popPose(); } diff --git a/src/main/java/com/atsuishio/superbwarfare/client/renderer/entity/DroneRenderer.java b/src/main/java/com/atsuishio/superbwarfare/client/renderer/entity/DroneRenderer.java index 313046363..54800881b 100644 --- a/src/main/java/com/atsuishio/superbwarfare/client/renderer/entity/DroneRenderer.java +++ b/src/main/java/com/atsuishio/superbwarfare/client/renderer/entity/DroneRenderer.java @@ -5,11 +5,14 @@ import com.atsuishio.superbwarfare.client.model.entity.DroneModel; import com.atsuishio.superbwarfare.entity.DroneEntity; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; +import com.mojang.math.Axis; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.entity.EntityRendererProvider; import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; import software.bernie.geckolib.cache.object.BakedGeoModel; +import software.bernie.geckolib.cache.object.GeoBone; import software.bernie.geckolib.renderer.GeoEntityRenderer; public class DroneRenderer extends GeoEntityRenderer { @@ -33,12 +36,30 @@ public class DroneRenderer extends GeoEntityRenderer { } @Override - protected float getDeathMaxRotation(DroneEntity entityLivingBaseIn) { - return 0.0F; + public void render(DroneEntity entityIn, float entityYaw, float partialTicks, PoseStack poseStack, MultiBufferSource bufferIn, int packedLightIn) { + poseStack.pushPose(); + poseStack.mulPose(Axis.YP.rotationDegrees(-entityIn.getYaw(partialTicks))); + poseStack.mulPose(Axis.XP.rotationDegrees(entityIn.getBodyPitch(partialTicks))); + poseStack.mulPose(Axis.ZP.rotationDegrees(entityIn.getRoll(partialTicks))); + super.render(entityIn, entityYaw, partialTicks, poseStack, bufferIn, packedLightIn); + poseStack.popPose(); } @Override - public boolean shouldShowName(DroneEntity animatable) { - return animatable.hasCustomName(); + public void renderRecursively(PoseStack poseStack, DroneEntity animatable, GeoBone bone, RenderType renderType, MultiBufferSource bufferSource, VertexConsumer buffer, boolean isReRender, float partialTick, int packedLight, int packedOverlay, float red, float green, float blue, float alpha) { + String name = bone.getName(); + if (name.equals("wingFL")) { + bone.setRotY(Mth.lerp(partialTick, animatable.propellerRotO, animatable.getPropellerRot())); + } + if (name.equals("wingFR")) { + bone.setRotY(Mth.lerp(partialTick, animatable.propellerRotO, animatable.getPropellerRot())); + } + if (name.equals("wingBL")) { + bone.setRotY(Mth.lerp(partialTick, animatable.propellerRotO, animatable.getPropellerRot())); + } + if (name.equals("wingBR")) { + bone.setRotY(Mth.lerp(partialTick, animatable.propellerRotO, animatable.getPropellerRot())); + } + super.renderRecursively(poseStack, animatable, bone, renderType, bufferSource, buffer, isReRender, partialTick, packedLight, packedOverlay, red, green, blue, alpha); } } diff --git a/src/main/java/com/atsuishio/superbwarfare/entity/DroneEntity.java b/src/main/java/com/atsuishio/superbwarfare/entity/DroneEntity.java index b2999a5b2..7a5b8b408 100644 --- a/src/main/java/com/atsuishio/superbwarfare/entity/DroneEntity.java +++ b/src/main/java/com/atsuishio/superbwarfare/entity/DroneEntity.java @@ -3,6 +3,7 @@ package com.atsuishio.superbwarfare.entity; import com.atsuishio.superbwarfare.config.server.ExplosionConfig; import com.atsuishio.superbwarfare.config.server.ExplosionDestroyConfig; import com.atsuishio.superbwarfare.entity.projectile.RgoGrenadeEntity; +import com.atsuishio.superbwarfare.entity.vehicle.MobileVehicleEntity; import com.atsuishio.superbwarfare.init.ModDamageTypes; import com.atsuishio.superbwarfare.init.ModEntities; import com.atsuishio.superbwarfare.init.ModItems; @@ -12,8 +13,6 @@ import com.atsuishio.superbwarfare.tools.CustomExplosion; import com.atsuishio.superbwarfare.tools.EntityFindUtil; import com.atsuishio.superbwarfare.tools.ParticleTool; import net.minecraft.ChatFormatting; -import net.minecraft.core.BlockPos; -import net.minecraft.core.NonNullList; import net.minecraft.core.registries.Registries; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; @@ -31,15 +30,14 @@ 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.ai.attributes.AttributeSupplier; -import net.minecraft.world.entity.ai.attributes.Attributes; +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.item.ItemStack; import net.minecraft.world.level.Explosion; import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; import net.minecraftforge.event.ForgeEventFactory; @@ -47,6 +45,7 @@ import net.minecraftforge.items.ItemHandlerHelper; import net.minecraftforge.network.NetworkHooks; import net.minecraftforge.network.PlayMessages; import org.jetbrains.annotations.NotNull; +import org.joml.Math; import org.joml.Vector3f; import software.bernie.geckolib.animatable.GeoEntity; import software.bernie.geckolib.core.animatable.instance.AnimatableInstanceCache; @@ -57,28 +56,26 @@ import java.util.Comparator; import java.util.Objects; import java.util.UUID; -public class DroneEntity extends LivingEntity implements GeoEntity { - +public class DroneEntity extends MobileVehicleEntity implements GeoEntity { public static final EntityDataAccessor LINKED = SynchedEntityData.defineId(DroneEntity.class, EntityDataSerializers.BOOLEAN); public static final EntityDataAccessor CONTROLLER = SynchedEntityData.defineId(DroneEntity.class, EntityDataSerializers.STRING); public static final EntityDataAccessor AMMO = SynchedEntityData.defineId(DroneEntity.class, EntityDataSerializers.INT); public static final EntityDataAccessor KAMIKAZE = SynchedEntityData.defineId(DroneEntity.class, EntityDataSerializers.BOOLEAN); - + public static final EntityDataAccessor DELTA_ROT = SynchedEntityData.defineId(DroneEntity.class, EntityDataSerializers.FLOAT); + public static final EntityDataAccessor DELTA_X_ROT = SynchedEntityData.defineId(DroneEntity.class, EntityDataSerializers.FLOAT); + public static final EntityDataAccessor PROPELLER_ROT = SynchedEntityData.defineId(DroneEntity.class, EntityDataSerializers.FLOAT); private final AnimatableInstanceCache cache = GeckoLibUtil.createInstanceCache(this); - public double moveX = 0; - public double moveY = 0; - public double moveZ = 0; - public boolean leftInputDown; - public boolean rightInputDown; - public boolean forwardInputDown; - public boolean backInputDown; - public boolean upInputDown; - public boolean downInputDown; + public static final float MAX_HEALTH = 5; + + public float propellerRot; + public float propellerRotO; + public boolean fire; public int collisionCoolDown; - public double lastTickSpeed; public double lastTickVerticalSpeed; + public float pitch; + public float pitchO; public DroneEntity(PlayMessages.SpawnEntity packet, Level world) { this(ModEntities.DRONE.get(), world); @@ -86,7 +83,30 @@ public class DroneEntity extends LivingEntity implements GeoEntity { public DroneEntity(EntityType type, Level world) { super(type, world); - this.noCulling = true; + } + + public float getBodyPitch() { + return pitch; + } + + public void setBodyXRot(float rot) { + pitch = rot; + } + + public float getBodyPitch(float tickDelta) { + return Mth.lerp(0.6f * tickDelta, pitchO, getBodyPitch()); + } + + @Override + public boolean hurt(DamageSource source, float amount) { + super.hurt(source, amount); + this.hurt(amount); + return true; + } + + @Override + public float getMaxHealth() { + return MAX_HEALTH; } public DroneEntity(EntityType type, Level world, float moveX, float moveY, float moveZ) { @@ -96,41 +116,20 @@ public class DroneEntity extends LivingEntity implements GeoEntity { @Override protected void defineSynchedData() { super.defineSynchedData(); + this.entityData.define(PROPELLER_ROT, 0f); + this.entityData.define(DELTA_ROT, 0f); + this.entityData.define(DELTA_X_ROT, 0f); this.entityData.define(CONTROLLER, "undefined"); this.entityData.define(LINKED, false); this.entityData.define(AMMO, 0); this.entityData.define(KAMIKAZE, false); } - @Override - protected float getStandingEyeHeight(Pose poseIn, EntityDimensions sizeIn) { - return 0.075F; - } - @Override public Packet getAddEntityPacket() { return NetworkHooks.getEntitySpawningPacket(this); } - @Override - public MobType getMobType() { - return super.getMobType(); - } - - @Override - public Iterable getArmorSlots() { - return NonNullList.withSize(1, ItemStack.EMPTY); - } - - @Override - public ItemStack getItemBySlot(EquipmentSlot pSlot) { - return ItemStack.EMPTY; - } - - @Override - public void setItemSlot(EquipmentSlot pSlot, ItemStack pStack) { - } - @Override public boolean causeFallDamage(float l, float d, DamageSource source) { return false; @@ -139,7 +138,6 @@ public class DroneEntity extends LivingEntity implements GeoEntity { @Override public void addAdditionalSaveData(CompoundTag compound) { super.addAdditionalSaveData(compound); - compound.putBoolean("Linked", this.entityData.get(LINKED)); compound.putString("Controller", this.entityData.get(CONTROLLER)); compound.putInt("Ammo", this.entityData.get(AMMO)); @@ -149,7 +147,6 @@ public class DroneEntity extends LivingEntity implements GeoEntity { @Override public void readAdditionalSaveData(CompoundTag compound) { super.readAdditionalSaveData(compound); - if (compound.contains("Linked")) this.entityData.set(LINKED, compound.getBoolean("Linked")); if (compound.contains("Controller")) @@ -160,25 +157,12 @@ public class DroneEntity extends LivingEntity implements GeoEntity { this.entityData.set(KAMIKAZE, compound.getBoolean("Kamikaze")); } - public Vector3f getForwardDirection() { - return new Vector3f( - Mth.sin(-getYRot() * ((float) Math.PI / 180)), - 0.0f, - Mth.cos(getYRot() * ((float) Math.PI / 180)) - ).normalize(); - } - - public Vector3f getRightDirection() { - return new Vector3f( - Mth.cos(-getYRot() * ((float) Math.PI / 180)), - 0.0f, - Mth.sin(getYRot() * ((float) Math.PI / 180)) - ).normalize(); - } - - @Override public void baseTick() { + pitchO = this.getBodyPitch(); + setBodyXRot(pitch * 0.9f); + propellerRotO = this.getPropellerRot(); + super.baseTick(); lastTickSpeed = this.getDeltaMovement().length(); @@ -188,49 +172,6 @@ public class DroneEntity extends LivingEntity implements GeoEntity { collisionCoolDown--; } - if (!this.onGround()) { - // left and right - if (leftInputDown) { - moveX = Mth.clamp(moveX + 0.3f, 0, 3); - } else if (rightInputDown) { - moveX = Mth.clamp(moveX - 0.3f, -3, 0); - } - - // forward and backward - if (forwardInputDown) { - moveZ = Mth.clamp(moveZ + 0.3f, 0, 3); - } else if (backInputDown) { - moveZ = Mth.clamp(moveZ - 0.3f, -3, 0); - } - - moveX *= 0.25; - moveZ *= 0.25; - - } else { - moveX = 0; - moveZ = 0; - } - - // up and down - if (upInputDown) { - moveY = Mth.clamp(moveY + 0.3f, 0, 3); - } else if (downInputDown) { - moveY = Mth.clamp(moveY - 0.15f, -2, 0); - } - - moveY *= 0.3; - - setDeltaMovement(getDeltaMovement().add(0.0f, (this.onGround() ? 0.059 : 0) + moveY, 0.0f)); - - Vector3f direction = getRightDirection().mul((float) moveX); - setDeltaMovement(getDeltaMovement().add(new Vec3(direction.x, direction.y, direction.z).scale(0.8))); - - Vector3f directionZ = getForwardDirection().mul((float) moveZ); - setDeltaMovement(getDeltaMovement().add(new Vec3(directionZ.x, directionZ.y, directionZ.z).scale(0.8))); - - Vec3 vec = this.getDeltaMovement(); - this.setDeltaMovement(vec.multiply(1.055, 0.9, 1.055)); - Player controller = EntityFindUtil.findPlayer(this.level(), this.entityData.get(CONTROLLER)); if (!this.onGround()) { @@ -257,12 +198,11 @@ public class DroneEntity extends LivingEntity implements GeoEntity { } } if (this.entityData.get(KAMIKAZE)) { - this.discard(); if (controller != null) { if (controller.getMainHandItem().is(ModItems.MONITOR.get())) { - Monitor.disLink(controller.getMainHandItem()); + Monitor.disLink(controller.getMainHandItem(), controller); } - kamikazeExplosion(controller); + this.hurt(new DamageSource(level().registryAccess().registryOrThrow(Registries.DAMAGE_TYPE).getHolderOrThrow(DamageTypes.EXPLOSION), controller), 10000); } } @@ -272,6 +212,14 @@ public class DroneEntity extends LivingEntity implements GeoEntity { this.refreshDimensions(); } + public float getPropellerRot() { + return this.propellerRot; + } + + public void setPropellerRot(float pPropellerRot) { + this.propellerRot = pPropellerRot; + } + private void droneDrop(Player player) { Level level = player.level(); if (!level.isClientSide()) { @@ -284,8 +232,6 @@ public class DroneEntity extends LivingEntity implements GeoEntity { @Override public InteractionResult interact(Player player, InteractionHand hand) { - super.interact(player, hand); - ItemStack stack = player.getMainHandItem(); if (stack.getItem() == ModItems.MONITOR.get()) { if (!player.isCrouching()) { @@ -317,7 +263,7 @@ public class DroneEntity extends LivingEntity implements GeoEntity { this.entityData.set(CONTROLLER, "none"); this.entityData.set(LINKED, false); - Monitor.disLink(stack); + Monitor.disLink(stack, player); player.displayClientMessage(Component.translatable("tips.superbwarfare.monitor.unlinked").withStyle(ChatFormatting.RED), true); if (player instanceof ServerPlayer serverPlayer) { @@ -339,7 +285,7 @@ public class DroneEntity extends LivingEntity implements GeoEntity { player.getInventory().items.stream().filter(stack_ -> stack_.getItem() == ModItems.MONITOR.get()) .forEach(stack_ -> { if (stack_.getOrCreateTag().getString(Monitor.LINKED_DRONE).equals(this.getStringUUID())) { - Monitor.disLink(stack_); + Monitor.disLink(stack_, player); } }); @@ -368,22 +314,86 @@ public class DroneEntity extends LivingEntity implements GeoEntity { } @Override - public void travel(Vec3 dir) { - Player controller = EntityFindUtil.findPlayer(this.level(), this.entityData.get(CONTROLLER)); + public void travel() { + float diffX; + float diffY; + if (!this.onGround()) { + // left and right + if (rightInputDown) { + this.entityData.set(DELTA_ROT, this.entityData.get(DELTA_ROT) - 0.3f); + } else if (this.leftInputDown) { + this.entityData.set(DELTA_ROT, this.entityData.get(DELTA_ROT) + 0.3f); + } - if (controller != null) { - ItemStack stack = controller.getMainHandItem(); - if (stack.is(ModItems.MONITOR.get()) && stack.getOrCreateTag().getBoolean("Using")) { - this.setYRot(controller.getYRot()); - this.yRotO = this.getYRot(); - this.setXRot(Mth.clamp(controller.getXRot(), -25, 90)); - this.setRot(this.getYRot(), this.getXRot()); - this.yBodyRot = controller.getYRot(); - this.yHeadRot = controller.getYRot(); + // forward and backward + if (forwardInputDown) { + this.entityData.set(DELTA_X_ROT, this.entityData.get(DELTA_X_ROT) - 0.3f); + } else if (backInputDown) { + this.entityData.set(DELTA_X_ROT, this.entityData.get(DELTA_X_ROT) + 0.3f); + } + + float f = (float) (0.97f - 0.02f * lastTickSpeed); + this.setDeltaMovement(this.getDeltaMovement().multiply(f, 0.9, f)); + + } else { + this.setDeltaMovement(this.getDeltaMovement().multiply(0.8, 1, 0.8)); + this.setZRot(this.roll * 0.9f); + this.setXRot(this.getXRot() * 0.9f); + this.setBodyXRot(this.getBodyPitch() * 0.9f); + } + + if (this.isInWater() && this.tickCount % 4 == 0) { + this.setDeltaMovement(this.getDeltaMovement().multiply(0.6, 0.6, 0.6)); + this.hurt(ModDamageTypes.causeVehicleStrikeDamage(this.level().registryAccess(), this, this.getFirstPassenger() == null ? this : this.getFirstPassenger()), 26 + (float) (60 * ((lastTickSpeed - 0.4) * (lastTickSpeed - 0.4)))); + } + + boolean up = this.upInputDown; + boolean down = this.downInputDown; + + if (up) { + this.entityData.set(POWER, Math.min(this.entityData.get(POWER) + 0.01f, 0.15f)); + } + + if (down) { + this.entityData.set(POWER, Math.max(this.entityData.get(POWER) - 0.01f, 0)); + } + + if (!(up || down)) { + if (this.getDeltaMovement().y() < 0) { + this.entityData.set(POWER, Math.min(this.entityData.get(POWER) + 0.001f, 0.15f)); + } else { + this.entityData.set(POWER, Math.max(this.entityData.get(POWER) - 0.001f, 0)); + } + } + + this.entityData.set(DELTA_ROT, this.entityData.get(DELTA_ROT) * 0.8f); + this.entityData.set(DELTA_X_ROT, this.entityData.get(DELTA_X_ROT) * 0.8f); + this.entityData.set(PROPELLER_ROT, Mth.lerp(0.08f, this.entityData.get(PROPELLER_ROT), this.entityData.get(POWER))); + this.setPropellerRot(this.getPropellerRot() + 30 * this.entityData.get(PROPELLER_ROT)); + this.entityData.set(PROPELLER_ROT, this.entityData.get(PROPELLER_ROT) * 0.9995f); + + this.setZRot(Mth.clamp(this.getRoll() - this.entityData.get(DELTA_ROT), -30, 30)); + this.setBodyXRot(Mth.clamp(this.getBodyPitch() - this.entityData.get(DELTA_X_ROT), -30, 30)); + + setDeltaMovement(getDeltaMovement().add(0.0f, Math.min(Math.sin((90 - this.getBodyPitch()) * Mth.DEG_TO_RAD), Math.sin((90 + this.getRoll()) * Mth.DEG_TO_RAD)) * this.entityData.get(POWER), 0.0f)); + + Vector3f direction = getRightDirection().mul(Math.cos((this.getRoll() + 90) * Mth.DEG_TO_RAD) * 0.1f); + setDeltaMovement(getDeltaMovement().add(new Vec3(direction.x, direction.y, direction.z).scale(4))); + + Vector3f directionZ = getForwardDirection().mul(-Math.cos((this.getBodyPitch() + 90) * Mth.DEG_TO_RAD) * 0.1f); + setDeltaMovement(getDeltaMovement().add(new Vec3(directionZ.x, directionZ.y, directionZ.z).scale(4))); + + Player controller = EntityFindUtil.findPlayer(this.level(), this.entityData.get(CONTROLLER)); + if (controller != null) { + ItemStack stack = controller.getMainHandItem(); + if (stack.is(ModItems.MONITOR.get()) && stack.getOrCreateTag().getBoolean("Using")) { + diffY = Math.clamp(-90f, 90f, Mth.wrapDegrees(controller.getYHeadRot() - this.getYRot())); + diffX = Math.clamp(-60f, 60f, Mth.wrapDegrees(controller.getXRot() - this.getXRot())); + this.setYRot(this.getYRot() + 0.5f * diffY); + this.setXRot(Mth.clamp(this.getXRot() + 0.5f * diffX, -10, 90)); } } - super.travel(dir); float f = 0.7f; AABB aabb = AABB.ofSize(this.getEyePosition(), f, 0.3, f); var level = this.level(); @@ -397,15 +407,16 @@ public class DroneEntity extends LivingEntity implements GeoEntity { } public void hitEntityCrash(Player controller, Entity target) { - if (lastTickSpeed > 0.2) { - if (this.entityData.get(KAMIKAZE) && 6 * lastTickSpeed > this.getHealth()) { + if (lastTickSpeed > 0.12) { + if (this.entityData.get(KAMIKAZE) && 20 * lastTickSpeed > this.getHealth()) { target.hurt(ModDamageTypes.causeCustomExplosionDamage(this.level().registryAccess(), this, controller), ExplosionConfig.DRONE_KAMIKAZE_HIT_DAMAGE.get()); + if (controller.getMainHandItem().is(ModItems.MONITOR.get())) { + Monitor.disLink(controller.getMainHandItem(), controller); + } } target.hurt(ModDamageTypes.causeDroneHitDamage(this.level().registryAccess(), this, controller), (float) (5 * lastTickSpeed)); - if (target instanceof Mob mobEntity) { - mobEntity.setTarget(this); - } - this.hurt(new DamageSource(level().registryAccess().registryOrThrow(Registries.DAMAGE_TYPE).getHolderOrThrow(DamageTypes.EXPLOSION), Objects.requireNonNullElse(controller, this)), (float) ((this.entityData.get(KAMIKAZE) ? 6 : 0.5) * lastTickSpeed)); + + this.hurt(new DamageSource(level().registryAccess().registryOrThrow(Registries.DAMAGE_TYPE).getHolderOrThrow(DamageTypes.EXPLOSION), Objects.requireNonNullElse(controller, this)), (float) ((this.entityData.get(KAMIKAZE) ? 20 : 4) * lastTickSpeed)); } } @@ -416,8 +427,9 @@ public class DroneEntity extends LivingEntity implements GeoEntity { if (lastTickSpeed < 0.2 || collisionCoolDown > 0) return; - if ((verticalCollision) && Mth.abs((float) lastTickVerticalSpeed) > 0.2) { + if ((verticalCollision) && Mth.abs((float) lastTickVerticalSpeed) > 0.3) { this.hurt(ModDamageTypes.causeCustomExplosionDamage(this.level().registryAccess(), this, controller == null ? this : controller), (float) (20 * ((Mth.abs((float) lastTickVerticalSpeed) - 0.3) * (lastTickSpeed - 0.2) * (lastTickSpeed - 0.2)))); + collisionCoolDown = 4; } if (this.horizontalCollision) { @@ -427,13 +439,7 @@ public class DroneEntity extends LivingEntity implements GeoEntity { } @Override - public boolean canBeCollidedWith() { - return super.canBeCollidedWith(); - } - - @Override - public void die(DamageSource source) { - super.die(source); + public void destroy() { String id = this.entityData.get(CONTROLLER); UUID uuid; @@ -448,22 +454,13 @@ public class DroneEntity extends LivingEntity implements GeoEntity { player.getInventory().items.stream().filter(stack -> stack.getItem() == ModItems.MONITOR.get()) .forEach(stack -> { if (stack.getOrCreateTag().getString(Monitor.LINKED_DRONE).equals(this.getStringUUID())) { - Monitor.disLink(stack); + Monitor.disLink(stack, player); } }); } - Player controller = EntityFindUtil.findPlayer(this.level(), this.entityData.get(CONTROLLER)); - if (this.entityData.get(KAMIKAZE)) { - this.discard(); - if (controller != null) { - if (controller.getMainHandItem().is(ModItems.MONITOR.get())) { - Monitor.disLink(controller.getMainHandItem()); - } - kamikazeExplosion(controller); - } - + kamikazeExplosion(); } ItemStack stack = new ItemStack(ModItems.RGO_GRENADE.get(), this.entityData.get(AMMO)); @@ -477,13 +474,23 @@ public class DroneEntity extends LivingEntity implements GeoEntity { if (level() instanceof ServerLevel) { level().explode(null, this.getX(), this.getY(), this.getZ(), 0, Level.ExplosionInteraction.NONE); } + + Player controller = EntityFindUtil.findPlayer(this.level(), this.entityData.get(CONTROLLER)); + if (controller != null) { + if (controller.getMainHandItem().is(ModItems.MONITOR.get())) { + Monitor.disLink(controller.getMainHandItem(), controller); + this.discard(); + } + } + this.discard(); } - private void kamikazeExplosion(Entity source) { + private void kamikazeExplosion() { + Entity attacker = EntityFindUtil.findEntity(this.level(), this.entityData.get(LAST_ATTACKER_UUID)); CustomExplosion explosion = new CustomExplosion(this.level(), this, - ModDamageTypes.causeProjectileBoomDamage(this.level().registryAccess(), source, source), ExplosionConfig.DRONE_KAMIKAZE_EXPLOSION_DAMAGE.get(), + ModDamageTypes.causeProjectileBoomDamage(this.level().registryAccess(), attacker, attacker), ExplosionConfig.DRONE_KAMIKAZE_EXPLOSION_DAMAGE.get(), this.getX(), this.getY(), this.getZ(), ExplosionConfig.DRONE_KAMIKAZE_EXPLOSION_RADIUS.get(), ExplosionDestroyConfig.EXPLOSION_DESTROY.get() ? Explosion.BlockInteraction.DESTROY : Explosion.BlockInteraction.KEEP).setDamageMultiplier(1); explosion.explode(); ForgeEventFactory.onExplosionStart(this.level(), explosion); @@ -491,35 +498,10 @@ public class DroneEntity extends LivingEntity implements GeoEntity { ParticleTool.spawnMediumExplosionParticles(this.level(), this.position()); } - @Override - protected void checkFallDamage(double y, boolean onGroundIn, BlockState state, BlockPos pos) { - } - - @Override - public boolean isNoGravity() { - return !this.onGround(); - } - - public static AttributeSupplier.Builder createAttributes() { - AttributeSupplier.Builder builder = Mob.createMobAttributes(); - builder = builder.add(Attributes.MOVEMENT_SPEED, 0); - builder = builder.add(Attributes.MAX_HEALTH, 4); - builder = builder.add(Attributes.ARMOR, 0); - builder = builder.add(Attributes.ATTACK_DAMAGE, 0); - builder = builder.add(Attributes.FOLLOW_RANGE, 64); - builder = builder.add(Attributes.FLYING_SPEED, 10); - return builder; - } - @Override public void registerControllers(AnimatableManager.ControllerRegistrar data) { } - @Override - public HumanoidArm getMainArm() { - return HumanoidArm.RIGHT; - } - @Override public AnimatableInstanceCache getAnimatableInstanceCache() { return this.cache; diff --git a/src/main/java/com/atsuishio/superbwarfare/entity/vehicle/MobileVehicleEntity.java b/src/main/java/com/atsuishio/superbwarfare/entity/vehicle/MobileVehicleEntity.java index 4281c075e..bc8b6c115 100644 --- a/src/main/java/com/atsuishio/superbwarfare/entity/vehicle/MobileVehicleEntity.java +++ b/src/main/java/com/atsuishio/superbwarfare/entity/vehicle/MobileVehicleEntity.java @@ -1,5 +1,6 @@ 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; @@ -128,6 +129,7 @@ public class MobileVehicleEntity extends EnergyVehicleEntity { * @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)); diff --git a/src/main/java/com/atsuishio/superbwarfare/entity/vehicle/VehicleEntity.java b/src/main/java/com/atsuishio/superbwarfare/entity/vehicle/VehicleEntity.java index 8c8ff8350..918e9ab27 100644 --- a/src/main/java/com/atsuishio/superbwarfare/entity/vehicle/VehicleEntity.java +++ b/src/main/java/com/atsuishio/superbwarfare/entity/vehicle/VehicleEntity.java @@ -1,5 +1,6 @@ package com.atsuishio.superbwarfare.entity.vehicle; +import com.atsuishio.superbwarfare.entity.DroneEntity; import com.atsuishio.superbwarfare.init.ModDamageTypes; import com.atsuishio.superbwarfare.init.ModItems; import com.atsuishio.superbwarfare.init.ModParticleTypes; @@ -58,15 +59,15 @@ public class VehicleEntity extends Entity { } public float getRoll(float tickDelta) { - return Mth.lerp(0.6f * tickDelta, prevRoll, getRoll()); + return Mth.lerp(tickDelta, prevRoll, getRoll()); } public float getYaw(float tickDelta) { - return Mth.lerp(0.6f * tickDelta, yRotO, getYRot()); + return Mth.lerp(tickDelta, yRotO, getYRot()); } public float getPitch(float tickDelta) { - return Mth.lerp(0.6f * tickDelta, xRotO, getXRot()); + return Mth.lerp(tickDelta, xRotO, getXRot()); } public void setZRot(float rot) { @@ -258,7 +259,9 @@ public class VehicleEntity extends Entity { if (this.getHealth() <= 0.1 * this.getMaxHealth()) { this.hurt(0.1f); } else { - this.heal(0.05f); + if (!(this instanceof DroneEntity)) { + this.heal(0.05f); + } } this.refreshDimensions(); diff --git a/src/main/java/com/atsuishio/superbwarfare/event/ClientEventHandler.java b/src/main/java/com/atsuishio/superbwarfare/event/ClientEventHandler.java index daddc3512..8871a603d 100644 --- a/src/main/java/com/atsuishio/superbwarfare/event/ClientEventHandler.java +++ b/src/main/java/com/atsuishio/superbwarfare/event/ClientEventHandler.java @@ -94,7 +94,6 @@ public class ClientEventHandler { public static double recoilHorizon = 0; public static double recoilY = 0; - public static double droneRotZ = 0; public static double droneFov = 1; public static double droneFovLerp = 1; @@ -795,22 +794,14 @@ public class ClientEventHandler { } } - public static void droneBodyAngle(float RotZ) { - LocalPlayer player = Minecraft.getInstance().player; - if (player != null) { - droneRotZ = RotZ; - - } - } - private static void handleDroneCamera(ViewportEvent.ComputeCameraAngles event, LivingEntity entity) { ItemStack stack = entity.getMainHandItem(); - double roll = event.getRoll(); + float yaw = event.getYaw(); DroneEntity drone = EntityFindUtil.findDrone(entity.level(), stack.getOrCreateTag().getString("LinkedDrone")); if (drone != null) { - event.setRoll((float) (roll - Mth.RAD_TO_DEG * droneRotZ)); + event.setRoll(drone.getRoll((float) event.getPartialTick()) * (1 - (drone.getPitch((float) event.getPartialTick()) / 90))); } if (drone != null && stack.getOrCreateTag().getBoolean("Using")) { diff --git a/src/main/java/com/atsuishio/superbwarfare/init/ModEntities.java b/src/main/java/com/atsuishio/superbwarfare/init/ModEntities.java index eb1d9f7e6..37f762529 100644 --- a/src/main/java/com/atsuishio/superbwarfare/init/ModEntities.java +++ b/src/main/java/com/atsuishio/superbwarfare/init/ModEntities.java @@ -39,7 +39,7 @@ public class ModEntities { EntityType.Builder.of(AnnihilatorEntity::new, MobCategory.MISC).setShouldReceiveVelocityUpdates(true).setTrackingRange(64).setUpdateInterval(3).setCustomClientFactory(AnnihilatorEntity::new).fireImmune().sized(13f, 4.2f)); public static final RegistryObject> DRONE = register("drone", - EntityType.Builder.of(DroneEntity::new, MobCategory.CREATURE).setShouldReceiveVelocityUpdates(true).setTrackingRange(64).setUpdateInterval(3).setCustomClientFactory(DroneEntity::new).sized(0.6f, 0.2f)); + EntityType.Builder.of(DroneEntity::new, MobCategory.MISC).setShouldReceiveVelocityUpdates(true).setTrackingRange(64).setUpdateInterval(3).setCustomClientFactory(DroneEntity::new).sized(0.6f, 0.2f)); public static final RegistryObject> TASER_BULLET_PROJECTILE = register("projectile_taser_bullet_projectile", EntityType.Builder.of(TaserBulletProjectileEntity::new, MobCategory.MISC).setCustomClientFactory(TaserBulletProjectileEntity::new).setShouldReceiveVelocityUpdates(true).setTrackingRange(64) @@ -89,6 +89,5 @@ public class ModEntities { public static void registerAttributes(EntityAttributeCreationEvent event) { event.put(TARGET.get(), TargetEntity.createAttributes().build()); event.put(SENPAI.get(), SenpaiEntity.createAttributes().build()); - event.put(DRONE.get(), DroneEntity.createAttributes().build()); } } diff --git a/src/main/java/com/atsuishio/superbwarfare/item/Monitor.java b/src/main/java/com/atsuishio/superbwarfare/item/Monitor.java index 520eeab55..330bdaa03 100644 --- a/src/main/java/com/atsuishio/superbwarfare/item/Monitor.java +++ b/src/main/java/com/atsuishio/superbwarfare/item/Monitor.java @@ -41,9 +41,14 @@ public class Monitor extends Item { itemstack.getOrCreateTag().putString(LINKED_DRONE, id); } - public static void disLink(ItemStack itemstack) { + public static void disLink(ItemStack itemstack, Player player) { ItemNBTTool.setBoolean(itemstack, LINKED, false); itemstack.getOrCreateTag().putString(LINKED_DRONE, "none"); + if (player.level().isClientSide) { + if (lastCameraType != null) { + Minecraft.getInstance().options.setCameraType(lastCameraType); + } + } } private void resetDroneData(DroneEntity drone) { diff --git a/src/main/java/com/atsuishio/superbwarfare/mixins/CameraMixin.java b/src/main/java/com/atsuishio/superbwarfare/mixins/CameraMixin.java index 99e75f6d2..6ee061ea0 100644 --- a/src/main/java/com/atsuishio/superbwarfare/mixins/CameraMixin.java +++ b/src/main/java/com/atsuishio/superbwarfare/mixins/CameraMixin.java @@ -6,6 +6,7 @@ import com.atsuishio.superbwarfare.event.ClientEventHandler; import com.atsuishio.superbwarfare.init.ModItems; import com.atsuishio.superbwarfare.init.ModTags; import com.atsuishio.superbwarfare.tools.EntityFindUtil; +import com.mojang.math.Axis; import net.minecraft.client.Camera; import net.minecraft.client.CameraType; import net.minecraft.client.Minecraft; @@ -15,9 +16,12 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.BlockGetter; +import org.joml.Matrix4f; import org.joml.Vector3d; +import org.joml.Vector4f; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @@ -60,25 +64,39 @@ public abstract class CameraMixin { if (stack.is(ModItems.MONITOR.get()) && stack.getOrCreateTag().getBoolean("Using") && stack.getOrCreateTag().getBoolean("Linked")) { DroneEntity drone = EntityFindUtil.findDrone(player.level(), stack.getOrCreateTag().getString("LinkedDrone")); - if (drone != null) { - float yRot = drone.getYRot(); - if (yRot < 0) { - yRot += 360; - } - yRot = yRot + 90 % 360; - var CameraPos = new Vector3d(0.22, 0.075, 0); - CameraPos.rotateZ(-drone.getXRot() * Mth.DEG_TO_RAD); - CameraPos.rotateY(-yRot * Mth.DEG_TO_RAD); + Matrix4f transform = superbWarfare$getVehicleTransform(drone, partialTicks); + float x0 = 0f; + float y0 = 0.075f; + float z0 = 0.18f; - setRotation(Mth.lerp(partialTicks, player.yBobO, player.yBob), drone.getViewXRot(partialTicks)); - setPosition(Mth.lerp(partialTicks, drone.xo + CameraPos.x, drone.getX() + CameraPos.x), Mth.lerp(partialTicks, drone.yo + 0.075, drone.getEyeY()), Mth.lerp(partialTicks, drone.zo + CameraPos.z, drone.getZ() + CameraPos.z)); + Vector4f worldPosition = superbWarfare$transformPosition(transform, x0, y0, z0); + + setRotation(drone.getYaw(partialTicks), drone.getPitch(partialTicks)); + setPosition(worldPosition.x, worldPosition.y, worldPosition.z); info.cancel(); } } } } + @Unique + private static Matrix4f superbWarfare$getVehicleTransform(DroneEntity vehicle, float ticks) { + Matrix4f transform = new Matrix4f(); + transform.translate((float) Mth.lerp(ticks, vehicle.xo, vehicle.getX()), (float) Mth.lerp(ticks, vehicle.yo, vehicle.getY()), (float) Mth.lerp(ticks, vehicle.zo, vehicle.getZ())); + transform.rotate(Axis.YP.rotationDegrees(-vehicle.getYaw(ticks))); + transform.rotate(Axis.XP.rotationDegrees(vehicle.getBodyPitch(ticks))); + transform.rotate(Axis.ZP.rotationDegrees(vehicle.getRoll(ticks))); + return transform; + } + + @Unique + private static Vector4f superbWarfare$transformPosition(Matrix4f transform, float x, float y, float z) { + return transform.transform(new Vector4f(x, y, z, 1)); + } + + + @Inject(method = "setup", at = @At("TAIL")) public void ia$setup(BlockGetter area, Entity entity, boolean thirdPerson, boolean inverseView, float tickDelta, CallbackInfo ci) { if (thirdPerson && entity.getVehicle() instanceof Mk42Entity) {