From 8642e803549981c644679534dcafeb30fe00023a Mon Sep 17 00:00:00 2001 From: Atsuihsio <842960157@qq.com> Date: Wed, 1 Jan 2025 06:26:48 +0800 Subject: [PATCH] =?UTF-8?q?=E7=9B=B4=E5=8D=87=E6=9C=BA=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../client/model/entity/Ah6Model.java | 25 ++ .../client/renderer/entity/Ah6Renderer.java | 52 ++++ .../superbwarfare/entity/Ah6Entity.java | 251 ++++++++++++++++++ .../entity/MobileVehicleEntity.java | 19 +- .../superbwarfare/entity/VehicleEntity.java | 18 ++ .../superbwarfare/init/ModEntities.java | 2 + .../init/ModEntityRenderers.java | 1 + .../atsuishio/superbwarfare/init/ModTabs.java | 1 + .../item/ContainerBlockItem.java | 4 + .../mixins/GameRendererMixin.java | 46 +++- .../mixins/LivingEntityRendererMixin.java | 23 ++ .../mixins/MouseHandlerMixin.java | 7 +- src/main/resources/mixins.superbwarfare.json | 9 +- 13 files changed, 451 insertions(+), 7 deletions(-) create mode 100644 src/main/java/com/atsuishio/superbwarfare/client/model/entity/Ah6Model.java create mode 100644 src/main/java/com/atsuishio/superbwarfare/client/renderer/entity/Ah6Renderer.java create mode 100644 src/main/java/com/atsuishio/superbwarfare/entity/Ah6Entity.java create mode 100644 src/main/java/com/atsuishio/superbwarfare/mixins/LivingEntityRendererMixin.java diff --git a/src/main/java/com/atsuishio/superbwarfare/client/model/entity/Ah6Model.java b/src/main/java/com/atsuishio/superbwarfare/client/model/entity/Ah6Model.java new file mode 100644 index 000000000..a8a1b647a --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/client/model/entity/Ah6Model.java @@ -0,0 +1,25 @@ +package com.atsuishio.superbwarfare.client.model.entity; + +import com.atsuishio.superbwarfare.ModUtils; +import com.atsuishio.superbwarfare.entity.Ah6Entity; +import net.minecraft.resources.ResourceLocation; +import software.bernie.geckolib.model.GeoModel; + +public class Ah6Model extends GeoModel { + + @Override + public ResourceLocation getAnimationResource(Ah6Entity entity) { + return null; +// return ModUtils.loc("animations/wheel_chair.animation.json"); + } + + @Override + public ResourceLocation getModelResource(Ah6Entity entity) { + return new ResourceLocation(ModUtils.MODID, "geo/wheel_chair.geo.json"); + } + + @Override + public ResourceLocation getTextureResource(Ah6Entity entity) { + return ModUtils.loc("textures/entity/wheel_chair.png"); + } +} 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 new file mode 100644 index 000000000..40b91018d --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/client/renderer/entity/Ah6Renderer.java @@ -0,0 +1,52 @@ +package com.atsuishio.superbwarfare.client.renderer.entity; + +import com.atsuishio.superbwarfare.client.model.entity.Ah6Model; +import com.atsuishio.superbwarfare.entity.Ah6Entity; +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.renderer.GeoEntityRenderer; + +public class Ah6Renderer extends GeoEntityRenderer { + + public Ah6Renderer(EntityRendererProvider.Context renderManager) { + super(renderManager, new Ah6Model()); + this.shadowRadius = 0.5f; + } + + @Override + public RenderType getRenderType(Ah6Entity animatable, ResourceLocation texture, MultiBufferSource bufferSource, float partialTick) { + return RenderType.entityTranslucent(getTextureLocation(animatable)); + } + + @Override + public void preRender(PoseStack poseStack, Ah6Entity entity, BakedGeoModel model, MultiBufferSource bufferSource, VertexConsumer buffer, boolean isReRender, float partialTick, int packedLight, int packedOverlay, float red, float green, + float blue, float alpha) { + float scale = 1f; + this.scaleHeight = scale; + this.scaleWidth = scale; + super.preRender(poseStack, entity, model, bufferSource, buffer, isReRender, partialTick, packedLight, packedOverlay, red, green, blue, alpha); + } + + @Override + public void render(Ah6Entity entityIn, float entityYaw, float partialTicks, PoseStack poseStack, MultiBufferSource bufferIn, int packedLightIn) { + 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))); + super.render(entityIn, entityYaw, partialTicks, poseStack, bufferIn, packedLightIn); + poseStack.popPose(); + } + +// @Override +// public void renderRecursively(PoseStack poseStack, Ah6Entity 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(); +// 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/Ah6Entity.java b/src/main/java/com/atsuishio/superbwarfare/entity/Ah6Entity.java new file mode 100644 index 000000000..8b2b3b8ce --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/entity/Ah6Entity.java @@ -0,0 +1,251 @@ +package com.atsuishio.superbwarfare.entity; + +import com.atsuishio.superbwarfare.config.server.ExplosionDestroyConfig; +import com.atsuishio.superbwarfare.init.ModDamageTypes; +import com.atsuishio.superbwarfare.init.ModEntities; +import com.atsuishio.superbwarfare.init.ModSounds; +import com.atsuishio.superbwarfare.tools.CustomExplosion; +import com.atsuishio.superbwarfare.tools.EntityFindUtil; +import com.atsuishio.superbwarfare.tools.ParticleTool; +import com.mojang.math.Axis; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.game.ClientGamePacketListener; +import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.network.syncher.EntityDataSerializers; +import net.minecraft.network.syncher.SynchedEntityData; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.sounds.SoundSource; +import net.minecraft.util.Mth; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Explosion; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.network.NetworkHooks; +import net.minecraftforge.network.PlayMessages; +import org.jetbrains.annotations.NotNull; +import org.joml.Math; +import org.joml.Matrix4f; +import org.joml.Vector3f; +import org.joml.Vector4f; +import software.bernie.geckolib.animatable.GeoEntity; +import software.bernie.geckolib.core.animatable.instance.AnimatableInstanceCache; +import software.bernie.geckolib.core.animation.AnimatableManager; +import software.bernie.geckolib.util.GeckoLibUtil; + +public class Ah6Entity extends MobileVehicleEntity implements GeoEntity { + + private final AnimatableInstanceCache cache = GeckoLibUtil.createInstanceCache(this); + public static final float MAX_HEALTH = 200; + public static final int MAX_ENERGY = 4000000; + public static final EntityDataAccessor DELTA_ROT = SynchedEntityData.defineId(Ah6Entity.class, EntityDataSerializers.FLOAT); + + public Ah6Entity(PlayMessages.SpawnEntity packet, Level world) { + this(ModEntities.AH_6.get(), world); + } + + public Ah6Entity(EntityType type, Level world) { + super(type, world); + this.setMaxUpStep(1.1f); + } + + @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(DELTA_ROT, 0f); + } + + @Override + public void addAdditionalSaveData(CompoundTag compound) { + super.addAdditionalSaveData(compound); + } + + @Override + public void readAdditionalSaveData(CompoundTag compound) { + super.readAdditionalSaveData(compound); + } + + @Override + public Packet getAddEntityPacket() { + return NetworkHooks.getEntitySpawningPacket(this); + } + + @Override + public boolean hurt(DamageSource source, float amount) { + super.hurt(source, amount); + this.level().playSound(null, this.getOnPos(), ModSounds.HIT.get(), SoundSource.PLAYERS, 1, 1); + this.hurt(amount); + return true; + } + + @Override + public void baseTick() { + super.baseTick(); + + this.setDeltaMovement(this.getDeltaMovement().add(0.0, -0.06, 0.0)); + if (this.onGround()) { + this.setDeltaMovement(this.getDeltaMovement().multiply(0.6, 0.95, 0.6)); + this.setZRot(this.roll * 0.4f); + this.setXRot(this.getXRot() * 0.4f); + } else { + float f = (float) Mth.clamp(0.93f + 0.03f * Mth.abs(90 - (float) calculateAngle(this.getDeltaMovement(), this.getViewVector(1))) / 90, 0.01, 0.99); + this.setDeltaMovement(this.getDeltaMovement().add(this.getViewVector(1).scale(0.03 * this.getDeltaMovement().length()))); + this.setDeltaMovement(this.getDeltaMovement().multiply(f, 0.95, f)); + } + this.refreshDimensions(); + } + + @Override + public void travel() { + Entity passenger = this.getPassengers().isEmpty() ? null : this.getPassengers().get(0); + float diffX; + float diffY; + + if (passenger == null) { + this.leftInputDown = false; + this.rightInputDown = false; + this.forwardInputDown = false; + this.backInputDown = false; + } else if (passenger instanceof Player player) { + if (level().isClientSide && this.getEnergy() > 0) { + level().playLocalSound(this.getX(), this.getY() + this.getBbHeight() * 0.5, this.getZ(), this.getEngineSound(), this.getSoundSource(), Math.min((this.forwardInputDown || this.backInputDown ? 7.5f : 5f) * 2 * Mth.abs(this.entityData.get(POWER)), 0.25f), (random.nextFloat() * 0.1f + 1f), false); + } + + if (!this.onGround()) { + diffY = Math.clamp(-90f, 90f, Mth.wrapDegrees(passenger.getYHeadRot() - this.getYRot())); + diffX = Math.clamp(-60f, 60f, Mth.wrapDegrees(passenger.getXRot() - this.getXRot())); + + if (rightInputDown) { + this.entityData.set(DELTA_ROT, this.entityData.get(DELTA_ROT) - 0.8f); + } else if (this.leftInputDown) { + this.entityData.set(DELTA_ROT, this.entityData.get(DELTA_ROT) + 0.8f); + } + + this.setYRot(this.getYRot() + 0.75f * diffY); + this.setXRot(Mth.clamp(this.getXRot() + 0.5f * diffX, -85, 85)); + this.setZRot(Mth.clamp(this.getRoll() - this.entityData.get(DELTA_ROT) + 0.2f * diffY, -85, 85)); + } + + if (this.upInputDown || this.forwardInputDown) { + this.entityData.set(POWER, Math.min(this.entityData.get(POWER) + 0.005f, 0.12f)); + } + + if (this.downInputDown || this.backInputDown) { + this.entityData.set(POWER, Math.max(this.entityData.get(POWER) - 0.005f, 0)); + } + +// player.displayClientMessage(Component.literal("Power:" + new java.text.DecimalFormat("##.####").format(this.entityData.get(POWER))), true); + } + + this.entityData.set(DELTA_ROT, this.entityData.get(DELTA_ROT) * 0.9f); + this.entityData.set(POWER, this.entityData.get(POWER) * 0.9998f); + + + setDeltaMovement(getDeltaMovement().add(0.0f, Math.sin((90 - this.getXRot()) * Mth.DEG_TO_RAD) * this.entityData.get(POWER), 0.0f)); + + Vector3f direction = getRightDirection().mul(Math.cos((this.getRoll() + 90) * Mth.DEG_TO_RAD) * this.entityData.get(POWER)); + setDeltaMovement(getDeltaMovement().add(new Vec3(direction.x, direction.y, direction.z).scale(0.8))); + + Vector3f directionZ = getForwardDirection().mul(-Math.cos((this.getXRot() + 90) * Mth.DEG_TO_RAD) * this.entityData.get(POWER)); + setDeltaMovement(getDeltaMovement().add(new Vec3(directionZ.x, directionZ.y, directionZ.z).scale(0.5))); + } + + @Override + public SoundEvent getEngineSound() { + return ModSounds.WHEEL_CHAIR_ENGINE.get(); + } + + protected void clampRotation(Entity entity) { + float f = Mth.wrapDegrees(entity.getXRot()); + float f1 = Mth.clamp(f, -80.0F, 80F); + entity.xRotO += f1 - f; + entity.setXRot(entity.getXRot() + f1 - f); + + entity.setYBodyRot(this.getYRot()); + float f2 = Mth.wrapDegrees(entity.getYRot() - this.getYRot()); + float f3 = Mth.clamp(f2, -10.0F, 10.0F); + entity.yRotO += f3 - f2; + entity.setYRot(entity.getYRot() + f3 - f2); + entity.setYHeadRot(entity.getYRot()); + } + + @Override + public void onPassengerTurned(Entity entity) { + this.clampRotation(entity); + } + + @Override + public void positionRider(@NotNull Entity passenger, @NotNull MoveFunction positionUpdater) { + // From Immersive_Aircraft + if (!hasPassenger(passenger)) { + return; + } + + Matrix4f transform = getVehicleTransform(); + + float x = 0; + float y = 0.8f; + float z = 0; + + + y += (float) passenger.getMyRidingOffset(); + + Vector4f worldPosition = transformPosition(transform, x, y, z); + + passenger.setPos(worldPosition.x, worldPosition.y, worldPosition.z); + + positionUpdater.accept(passenger, worldPosition.x, worldPosition.y, worldPosition.z); + } + + // From Immersive_Aircraft + public Matrix4f getVehicleTransform() { + Matrix4f transform = new Matrix4f(); + transform.translate((float) getX(), (float) getY(), (float) getZ()); + transform.rotate(Axis.YP.rotationDegrees(-getYRot())); + transform.rotate(Axis.XP.rotationDegrees(getXRot())); + transform.rotate(Axis.ZP.rotationDegrees(getRoll())); + return transform; + } + + protected Vector4f transformPosition(Matrix4f transform, float x, float y, float z) { + return transform.transform(new Vector4f(x, y, z, 1)); + } + + @Override + public void destroy() { + if (level() instanceof ServerLevel) { + Entity attacker = EntityFindUtil.findEntity(this.level(), this.entityData.get(LAST_ATTACKER_UUID)); + CustomExplosion explosion = new CustomExplosion(this.level(), attacker == null ? this : attacker, + ModDamageTypes.causeCustomExplosionDamage(this.level().registryAccess(), attacker == null ? this : attacker, attacker == null ? this : attacker), 25.0f, + this.getX(), this.getY(), this.getZ(), 5f, ExplosionDestroyConfig.EXPLOSION_DESTROY.get() ? Explosion.BlockInteraction.DESTROY : Explosion.BlockInteraction.KEEP).setDamageMultiplier(1); + explosion.explode(); + net.minecraftforge.event.ForgeEventFactory.onExplosionStart(this.level(), explosion); + explosion.finalizeExplosion(false); + ParticleTool.spawnMediumExplosionParticles(this.level(), this.position()); + this.discard(); + } + } + + @Override + public void registerControllers(AnimatableManager.ControllerRegistrar data) { + } + + @Override + public AnimatableInstanceCache getAnimatableInstanceCache() { + return this.cache; + } + + @Override + public float getMaxHealth() { + return MAX_HEALTH; + } + + @Override + public int getMaxEnergy() { + return MAX_ENERGY; + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/entity/MobileVehicleEntity.java b/src/main/java/com/atsuishio/superbwarfare/entity/MobileVehicleEntity.java index 827d3d8a9..39796c90f 100644 --- a/src/main/java/com/atsuishio/superbwarfare/entity/MobileVehicleEntity.java +++ b/src/main/java/com/atsuishio/superbwarfare/entity/MobileVehicleEntity.java @@ -9,6 +9,7 @@ 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.Entity; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.MoverType; @@ -19,6 +20,7 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.entity.EntityTypeTest; import net.minecraft.world.phys.Vec3; import org.joml.Math; +import org.joml.Vector3f; public class MobileVehicleEntity extends EnergyVehicleEntity { @@ -30,7 +32,6 @@ public class MobileVehicleEntity extends EnergyVehicleEntity { public boolean backInputDown; public boolean upInputDown; public boolean downInputDown; - public float roll; public MobileVehicleEntity(EntityType pEntityType, Level pLevel) { super(pEntityType, pLevel); @@ -87,6 +88,22 @@ public class MobileVehicleEntity extends EnergyVehicleEntity { } } + 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; } diff --git a/src/main/java/com/atsuishio/superbwarfare/entity/VehicleEntity.java b/src/main/java/com/atsuishio/superbwarfare/entity/VehicleEntity.java index e51f6fb2d..ac4668db0 100644 --- a/src/main/java/com/atsuishio/superbwarfare/entity/VehicleEntity.java +++ b/src/main/java/com/atsuishio/superbwarfare/entity/VehicleEntity.java @@ -35,6 +35,21 @@ public class VehicleEntity extends Entity { protected double serverYRot; protected double serverXRot; + public float roll; + public float prevRoll; + + public float getRoll() { + return roll; + } + + public float getRoll(float tickDelta) { + return Mth.lerp(0.6f * tickDelta, prevRoll, getRoll()); + } + + public void setZRot(float rot) { + roll = rot; + } + public VehicleEntity(EntityType pEntityType, Level pLevel) { super(pEntityType, pLevel); this.setHealth(this.getMaxHealth()); @@ -174,6 +189,9 @@ public class VehicleEntity extends Entity { public void baseTick() { super.baseTick(); + prevRoll = this.getRoll(); + setZRot(roll * 0.8f); + float delta = Math.abs(getYRot() - yRotO); while (getYRot() > 180F) { setYRot(getYRot() - 360F); diff --git a/src/main/java/com/atsuishio/superbwarfare/init/ModEntities.java b/src/main/java/com/atsuishio/superbwarfare/init/ModEntities.java index 9b7e51f60..1ebad9e89 100644 --- a/src/main/java/com/atsuishio/superbwarfare/init/ModEntities.java +++ b/src/main/java/com/atsuishio/superbwarfare/init/ModEntities.java @@ -65,6 +65,8 @@ public class ModEntities { EntityType.Builder.of(SpeedboatEntity::new, MobCategory.MISC).setShouldReceiveVelocityUpdates(true).setTrackingRange(512).setUpdateInterval(3).setCustomClientFactory(SpeedboatEntity::new).fireImmune().sized(3.0f, 2.0f)); public static final RegistryObject> WHEEL_CHAIR = register("wheel_chair", EntityType.Builder.of(WheelChairEntity::new, MobCategory.MISC).setShouldReceiveVelocityUpdates(true).setTrackingRange(512).setUpdateInterval(3).setCustomClientFactory(WheelChairEntity::new).fireImmune().sized(1.0f, 1.0f)); + public static final RegistryObject> AH_6 = register("ah_6", + EntityType.Builder.of(Ah6Entity::new, MobCategory.MISC).setShouldReceiveVelocityUpdates(true).setTrackingRange(512).setUpdateInterval(3).setCustomClientFactory(Ah6Entity::new).fireImmune().sized(1.0f, 1.0f)); private static RegistryObject> register(String name, EntityType.Builder entityTypeBuilder) { return REGISTRY.register(name, () -> entityTypeBuilder.build(name)); diff --git a/src/main/java/com/atsuishio/superbwarfare/init/ModEntityRenderers.java b/src/main/java/com/atsuishio/superbwarfare/init/ModEntityRenderers.java index bbc70a1e8..34bff6796 100644 --- a/src/main/java/com/atsuishio/superbwarfare/init/ModEntityRenderers.java +++ b/src/main/java/com/atsuishio/superbwarfare/init/ModEntityRenderers.java @@ -31,5 +31,6 @@ public class ModEntityRenderers { event.registerEntityRenderer(ModEntities.ANNIHILATOR.get(), AnnihilatorRenderer::new); event.registerEntityRenderer(ModEntities.SPEEDBOAT.get(), SpeedboatRenderer::new); event.registerEntityRenderer(ModEntities.WHEEL_CHAIR.get(), WheelChairRenderer::new); + event.registerEntityRenderer(ModEntities.AH_6.get(), Ah6Renderer::new); } } diff --git a/src/main/java/com/atsuishio/superbwarfare/init/ModTabs.java b/src/main/java/com/atsuishio/superbwarfare/init/ModTabs.java index 7e15593f2..5f610fa11 100644 --- a/src/main/java/com/atsuishio/superbwarfare/init/ModTabs.java +++ b/src/main/java/com/atsuishio/superbwarfare/init/ModTabs.java @@ -108,6 +108,7 @@ public class ModTabs { output.accept(ContainerBlockItem.createAnnihilatorInstance()); output.accept(ContainerBlockItem.createSpeedboatInstance()); output.accept(ContainerBlockItem.createWheelChairInstance()); + output.accept(ContainerBlockItem.createAh6Instance()); } else { output.accept(registryObject.get()); if (registryObject.get() == ModItems.ARMOR_PLATE.get()) { diff --git a/src/main/java/com/atsuishio/superbwarfare/item/ContainerBlockItem.java b/src/main/java/com/atsuishio/superbwarfare/item/ContainerBlockItem.java index f96d69fbc..3edfb44b3 100644 --- a/src/main/java/com/atsuishio/superbwarfare/item/ContainerBlockItem.java +++ b/src/main/java/com/atsuishio/superbwarfare/item/ContainerBlockItem.java @@ -109,4 +109,8 @@ public class ContainerBlockItem extends BlockItem implements GeoItem { public static ItemStack createWheelChairInstance() { return createInstance(ModEntities.WHEEL_CHAIR.get()); } + + public static ItemStack createAh6Instance() { + return createInstance(ModEntities.AH_6.get()); + } } diff --git a/src/main/java/com/atsuishio/superbwarfare/mixins/GameRendererMixin.java b/src/main/java/com/atsuishio/superbwarfare/mixins/GameRendererMixin.java index e8048f99a..f01f8a6d6 100644 --- a/src/main/java/com/atsuishio/superbwarfare/mixins/GameRendererMixin.java +++ b/src/main/java/com/atsuishio/superbwarfare/mixins/GameRendererMixin.java @@ -1,13 +1,21 @@ package com.atsuishio.superbwarfare.mixins; -import com.mojang.blaze3d.vertex.PoseStack; +import com.atsuishio.superbwarfare.entity.Ah6Entity; import com.atsuishio.superbwarfare.init.ModTags; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.math.Axis; +import net.minecraft.client.Camera; import net.minecraft.client.CameraType; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; +import org.joml.Quaternionf; +import org.joml.Vector3f; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @@ -26,4 +34,40 @@ public class GameRendererMixin { } } } + + // From Immersive_Aircraft + + @Shadow + @Final + private Camera mainCamera; + + @Inject(method = "renderLevel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Camera;setup(Lnet/minecraft/world/level/BlockGetter;Lnet/minecraft/world/entity/Entity;ZZF)V")) + public void immersiveAircraft$renderWorld(float tickDelta, long limitTime, PoseStack matrices, CallbackInfo ci) { + Entity entity = mainCamera.getEntity(); + //noinspection ConstantValue + if (entity != null && !mainCamera.isDetached() && entity.getRootVehicle() instanceof Ah6Entity vehicle) { + // rotate camera + + matrices.mulPose(Axis.ZP.rotationDegrees(vehicle.getRoll(tickDelta))); +// matrices.mulPose(Axis.XP.rotationDegrees(vehicle.getViewXRot(tickDelta))); + + // fetch eye offset + float eye = entity.getEyeHeight(); + + // transform eye offset to match aircraft rotation + Vector3f offset = new Vector3f(0, -eye, 0); + Quaternionf quaternion = Axis.XP.rotationDegrees(0.0f); + quaternion.mul(Axis.YP.rotationDegrees(-vehicle.getViewYRot(tickDelta))); + quaternion.mul(Axis.XP.rotationDegrees(vehicle.getViewXRot(tickDelta))); + quaternion.mul(Axis.ZP.rotationDegrees(vehicle.getRoll(tickDelta))); + offset.rotate(quaternion); + + // apply camera offset + matrices.mulPose(Axis.XP.rotationDegrees(mainCamera.getXRot())); + matrices.mulPose(Axis.YP.rotationDegrees(mainCamera.getYRot() + 180.0f)); + matrices.translate(offset.x(), offset.y() + eye, offset.z()); + matrices.mulPose(Axis.YP.rotationDegrees(-mainCamera.getYRot() - 180.0f)); + matrices.mulPose(Axis.XP.rotationDegrees(-mainCamera.getXRot())); + } + } } diff --git a/src/main/java/com/atsuishio/superbwarfare/mixins/LivingEntityRendererMixin.java b/src/main/java/com/atsuishio/superbwarfare/mixins/LivingEntityRendererMixin.java new file mode 100644 index 000000000..fad1f90e1 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/mixins/LivingEntityRendererMixin.java @@ -0,0 +1,23 @@ +package com.atsuishio.superbwarfare.mixins; + +import com.atsuishio.superbwarfare.entity.Ah6Entity; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.math.Axis; +import net.minecraft.client.renderer.entity.LivingEntityRenderer; +import net.minecraft.world.entity.LivingEntity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +// From Immersive_Aircraft +@Mixin(LivingEntityRenderer.class) +public class LivingEntityRendererMixin { + @Inject(method = "setupRotations", at = @At("TAIL")) + public void render(T entity, PoseStack matrices, float animationProgress, float bodyYaw, float tickDelta, CallbackInfo ci) { + if (entity.getRootVehicle() != entity && entity.getRootVehicle() instanceof Ah6Entity ah6Entity) { + matrices.mulPose(Axis.XP.rotationDegrees(-ah6Entity.getViewXRot(tickDelta))); + matrices.mulPose(Axis.ZP.rotationDegrees(-ah6Entity.getRoll(tickDelta))); + } + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/mixins/MouseHandlerMixin.java b/src/main/java/com/atsuishio/superbwarfare/mixins/MouseHandlerMixin.java index 97d454f8b..32e5be714 100644 --- a/src/main/java/com/atsuishio/superbwarfare/mixins/MouseHandlerMixin.java +++ b/src/main/java/com/atsuishio/superbwarfare/mixins/MouseHandlerMixin.java @@ -1,5 +1,6 @@ package com.atsuishio.superbwarfare.mixins; +import com.atsuishio.superbwarfare.entity.Ah6Entity; import com.atsuishio.superbwarfare.entity.IArmedVehicleEntity; import com.atsuishio.superbwarfare.entity.ICannonEntity; import com.atsuishio.superbwarfare.event.ClientEventHandler; @@ -41,7 +42,7 @@ public class MouseHandlerMixin { ItemStack stack = mc.player.getMainHandItem(); - if (player.getVehicle() != null && player.getVehicle() instanceof ICannonEntity) { + if (player.getVehicle() instanceof ICannonEntity) { if (ClientEventHandler.zoom) { return 0.15; } else { @@ -49,6 +50,10 @@ public class MouseHandlerMixin { } } + if (player.getVehicle() instanceof Ah6Entity) { + return 0.25; + } + if (stack.is(ModItems.MONITOR.get()) && stack.getOrCreateTag().getBoolean("Using") && stack.getOrCreateTag().getBoolean("Linked")) { return 0.33 / (1 + 0.08 * (droneFovLerp - 1)); } diff --git a/src/main/resources/mixins.superbwarfare.json b/src/main/resources/mixins.superbwarfare.json index 1036800ef..f502ef740 100644 --- a/src/main/resources/mixins.superbwarfare.json +++ b/src/main/resources/mixins.superbwarfare.json @@ -4,14 +4,15 @@ "compatibilityLevel": "JAVA_17", "refmap": "mixins.superbwarfare.refmap.json", "mixins": [ - "LivingEntityMixin", - "ClientboundSetEntityMotionPacketMixin" + "ClientboundSetEntityMotionPacketMixin", + "LivingEntityMixin" ], "client": [ - "ItemInHandLayerMixin", "CameraMixin", - "KeyMappingMixin", "GameRendererMixin", + "ItemInHandLayerMixin", + "KeyMappingMixin", + "LivingEntityRendererMixin", "MouseHandlerMixin" ], "minVersion": "0.8",