diff --git a/common/src/main/java/dev/itsmeow/whisperwoods/client/renderer/entity/model/ModelZotzpyre.java b/common/src/main/java/dev/itsmeow/whisperwoods/client/renderer/entity/model/ModelZotzpyre.java index 669567a..64e00b6 100644 --- a/common/src/main/java/dev/itsmeow/whisperwoods/client/renderer/entity/model/ModelZotzpyre.java +++ b/common/src/main/java/dev/itsmeow/whisperwoods/client/renderer/entity/model/ModelZotzpyre.java @@ -3,7 +3,6 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import dev.itsmeow.whisperwoods.entity.EntityZotzpyre; -import net.minecraft.client.Minecraft; import net.minecraft.client.model.EntityModel; import net.minecraft.client.model.geom.ModelPart; import net.minecraft.util.Mth; @@ -65,6 +64,8 @@ public class ModelZotzpyre extends EntityModel { public ModelPart mane03; public ModelPart mane04; + private boolean wasHanging = false; + public ModelZotzpyre() { texWidth = 128; texHeight = 64; @@ -392,58 +393,112 @@ public void renderToBuffer(PoseStack matrixStackIn, VertexConsumer bufferIn, int public void setupAnim(T entity, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch) { if(entity instanceof EntityZotzpyre) { EntityZotzpyre zotz = (EntityZotzpyre) entity; - if((zotz.getDeltaMovement().x() > 0.05 || zotz.getDeltaMovement().z() > 0.05) && zotz.getVehicle() == null || (zotz.getVehicle() == null && zotz.hasImpulse)) { - this.setRotateAngle(lLeg01, 1.3962634015954636F, 0.08726646259971647F, 0.40142572795869574F); - this.setRotateAngle(lWing03, 0.0F, -0.9599310885968813F, 0.0F); - this.setRotateAngle(lWing02, 0.0F, 0.5235987755982988F, 0.0F); - this.setRotateAngle(rLeg01, 1.3962634015954636F, -0.08726646259971647F, -0.40142572795869574F); - this.setRotateAngle(rWing03, 0.0F, 0.9599310885968813F, 0.0F); - this.setRotateAngle(rWing02, 0.0F, -0.5235987755982988F, 0.0F); - - // - this.setRotateAngle(tail01, 0.0F, 0.0F, 0.0F); - this.setRotateAngle(tail02, 0.0F, 0.0F, 0.0F); - this.setRotateAngle(rWingMembrane02, 0.0F, 0.0F, 0.0F); - this.setRotateAngle(lWingMembrane02, 0.0F, 0.0F, 0.0F); - this.setRotateAngle(lWing01, 0.0F, 0.0F, 0.0F); - this.setRotateAngle(rWing01, 0.0F, 0.0F, 0.0F); - - // - this.setRotateAngle(head, -0.08726646259971647F, 0.0F, 0.0F); - } else { - this.setRotateAngle(lWing02, 0.3490658503988659F, 0.6981317007977318F, 0.7853981633974483F); - this.setRotateAngle(rWing03, 0.0F, 1.9547687622336491F, 0.0F); - this.setRotateAngle(rWing01, -0.13962634015954636F, 0.5759586531581287F, -0.40142572795869574F); - this.setRotateAngle(tail01, -0.6283185307179586F, 0.0F, 0.0F); - this.setRotateAngle(rWingMembrane02, 0.0F, 0.5759586531581287F, 0.0F); - this.setRotateAngle(lLeg01, 0.0F, 0.45378560551852565F, -0.03490658503988659F); - this.setRotateAngle(lWingMembrane02, 0.0F, -0.5759586531581287F, 0.0F); - this.setRotateAngle(tail02, -0.3141592653589793F, 0.0F, 0.0F); - this.setRotateAngle(rWing02, 0.3490658503988659F, -0.6981317007977318F, -0.7853981633974483F); - this.setRotateAngle(lWing01, -0.13962634015954636F, -0.5759586531581287F, 0.40142572795869574F); - this.setRotateAngle(lWing03, 0.0F, -1.9547687622336491F, 0.0F); - this.setRotateAngle(rLeg01, 0.0F, -0.45378560551852565F, 0.03490658503988659F); - this.lLeg01.xRot = Mth.sin(limbSwing * 0.8665F + (float) Math.PI) * limbSwingAmount; - this.rLeg01.xRot = Mth.cos(limbSwing * 0.8665F) * limbSwingAmount; - this.lWing01.xRot = Mth.sin(limbSwing * 0.8665F + (float) Math.PI) * limbSwingAmount - 0.13962634015954636F; - this.rWing01.xRot = Mth.cos(limbSwing * 0.8665F) * limbSwingAmount - 0.13962634015954636F; - } - if(entity.getVehicle() != null) { - this.lowerJaw.xRot = (float) Math.toRadians(45); + if(zotz.isHanging()) { + this.hangingPose(); + this.wasHanging = true; } else { - this.lowerJaw.xRot = 0F; + if(wasHanging) { + wasHanging = false; + this.resetHangingPose(); + } + if (zotz.isNoGravity()) { + this.setRotateAngle(lLeg01, 1.3962634015954636F, 0.08726646259971647F, 0.40142572795869574F); + this.setRotateAngle(lWing03, 0.0F, -0.9599310885968813F, 0.0F); + this.setRotateAngle(lWing02, 0.0F, 0.5235987755982988F, 0.0F); + this.setRotateAngle(rLeg01, 1.3962634015954636F, -0.08726646259971647F, -0.40142572795869574F); + this.setRotateAngle(rWing03, 0.0F, 0.9599310885968813F, 0.0F); + this.setRotateAngle(rWing02, 0.0F, -0.5235987755982988F, 0.0F); + this.setRotateAngle(tail01, 0.0F, 0.0F, 0.0F); + this.setRotateAngle(tail02, 0.0F, 0.0F, 0.0F); + this.setRotateAngle(rWingMembrane02, 0.0F, 0.0F, 0.0F); + this.setRotateAngle(lWingMembrane02, 0.0F, 0.0F, 0.0F); + this.setRotateAngle(lWing01, 0.0F, 0.0F, 0.0F); + this.setRotateAngle(rWing01, 0.0F, 0.0F, 0.0F); + this.setRotateAngle(head, -0.08726646259971647F, 0.0F, 0.0F); + float limbSwingAmountM = Math.max(limbSwingAmount, 0.5F); + this.lWing01.xRot = Mth.cos(ageInTicks * 0.1F) * 0.4F - 0.14F; + this.rWing01.xRot = this.lWing01.xRot; + this.lWing01.zRot = Mth.cos(ageInTicks) * limbSwingAmountM * 0.4F - 0.14F; + this.rWing01.zRot = -this.lWing01.zRot; + this.lWing03.zRot = Mth.cos(ageInTicks) * limbSwingAmountM - 0.14F; + this.rWing03.zRot = -this.lWing03.zRot; + this.chest.xRot = -Mth.cos(ageInTicks * 0.45F) * limbSwingAmountM * 0.02F; + this.chest.zRot = -Mth.cos(ageInTicks * 0.3F) * 0.1F * limbSwingAmountM; + this.stomach.zRot = -Mth.cos(ageInTicks * 0.3F) * 0.1F * limbSwingAmountM; + this.lLeg01.zRot = Mth.cos(ageInTicks * 0.6F) * 0.1F * limbSwingAmountM; + this.rLeg01.zRot = this.lLeg01.zRot; + this.lowerJaw.xRot = 0.9F + Mth.cos(ageInTicks * 0.2F) * 0.25F; + } else { + this.setRotateAngle(lWing02, 0.3490658503988659F, 0.6981317007977318F, 0.7853981633974483F); + this.setRotateAngle(rWing03, 0.0F, 1.9547687622336491F, 0.0F); + this.setRotateAngle(rWing01, -0.13962634015954636F, 0.5759586531581287F, -0.40142572795869574F); + this.setRotateAngle(tail01, -0.6283185307179586F, 0.0F, 0.0F); + this.setRotateAngle(rWingMembrane02, 0.0F, 0.5759586531581287F, 0.0F); + this.setRotateAngle(lLeg01, 0.0F, 0.45378560551852565F, -0.03490658503988659F); + this.setRotateAngle(lWingMembrane02, 0.0F, -0.5759586531581287F, 0.0F); + this.setRotateAngle(tail02, -0.3141592653589793F, 0.0F, 0.0F); + this.setRotateAngle(rWing02, 0.3490658503988659F, -0.6981317007977318F, -0.7853981633974483F); + this.setRotateAngle(lWing01, -0.13962634015954636F, -0.5759586531581287F, 0.40142572795869574F); + this.setRotateAngle(lWing03, 0.0F, -1.9547687622336491F, 0.0F); + this.setRotateAngle(rLeg01, 0.0F, -0.45378560551852565F, 0.03490658503988659F); + this.lLeg01.xRot = Mth.sin(limbSwing * 0.8665F + (float) Math.PI) * limbSwingAmount; + this.rLeg01.xRot = Mth.cos(limbSwing * 0.8665F) * limbSwingAmount; + this.lWing01.xRot = Mth.sin(limbSwing * 0.8665F + (float) Math.PI) * limbSwingAmount - 0.13962634015954636F; + this.rWing01.xRot = Mth.cos(limbSwing * 0.8665F) * limbSwingAmount - 0.13962634015954636F; + this.lowerJaw.xRot = 0F; + } + this.neck.xRot = headPitch * 0.017453292F; + this.neck.yRot = netHeadYaw * 0.017453292F; } - this.neck.xRot = (entity.xRotO + (entity.xRot - entity.xRotO) * Minecraft.getInstance().getFrameTime()) * 0.017453292F; - float yawOffset = interpolate(entity.yBodyRotO, entity.yBodyRot, Minecraft.getInstance().getFrameTime()); - float yawHead = interpolate(entity.yHeadRotO, entity.yHeadRot, Minecraft.getInstance().getFrameTime()); - this.neck.yRot = (yawHead - yawOffset) * 0.017453292F; } } - private static float interpolate(float a1, float a2, float p) { - float angle = a2 - a1; - angle = angle < -180F ? angle += 360F : angle; - return a1 + p * (angle = angle >= 180F ? angle -= 360F : angle); + public void hangingPose() { + this.setRotateAngle(chest, 1.5708F, 0.0F, 0.0F); + this.setRotateAngle(head, 0.0F, 0.0F, 0.0F); + this.setRotateAngle(lClawsRotator, 0.0873F, 0.0F, 1.6144F); + this.setRotateAngle(lFinger, -2.0944F, -0.7854F, 2.8798F); + this.setRotateAngle(lLeg01, 1.5708F, -1.3963F, 0.0F); + this.setRotateAngle(lLeg02, 0.0F, -0.2094F, -1.4399F); + this.setRotateAngle(lWing01, 0.2618F, -0.1309F, 1.309F); + this.setRotateAngle(lWing02, 0.0F, 0.829F, 1.3526F); + this.setRotateAngle(lWing03, 0.0F, -1.9199F, 0.0F); + this.setRotateAngle(lWingMembrane02, 0.6109F, -0.2182F, -1.309F); + this.setRotateAngle(neck, 0.0F, 0.0F, 0.0F); + this.setRotateAngle(rClawsRotator, 0.0873F, 0.0F, -1.6144F); + this.setRotateAngle(rFinger, -2.0944F, 0.7854F, -2.8798F); + this.setRotateAngle(rLeg01, 1.5708F, 1.4399F, 0.0F); + this.setRotateAngle(rLeg02, 0.0F, 0.2094F, 1.4399F); + this.setRotateAngle(rWing01, 0.2618F, 0.1309F, -1.5272F); + this.setRotateAngle(rWing02, 0.0F, -0.829F, -1.3526F); + this.setRotateAngle(rWing03, 0.0F, 1.9199F, 0.0F); + this.setRotateAngle(rWingMembrane02, 0.6109F, 0.2182F, 1.309F); + this.setRotateAngle(stomach, 0.0F, 0.0F, 0.0F); + this.setRotateAngle(tail01, 0.0F, 0.0F, 0.0F); + } + + public void resetHangingPose() { + this.setRotateAngle(chest, -0.2182F, 0.0F, 0.0F); + this.setRotateAngle(head, 0.0873F, 0.0F, 0.0F); + this.setRotateAngle(lClawsRotator, 0.0873F, 0.0F, -0.2618F); + this.setRotateAngle(lFinger, -0.6981F, -0.3054F, 0.6545F); + this.setRotateAngle(lLeg01, 0.3491F, 0.2182F, 0.2618F); + this.setRotateAngle(lLeg02, -0.2182F, 0.0F, 0.0F); + this.setRotateAngle(lWing01, 0.7418F, -0.1309F, 0.48F); + this.setRotateAngle(lWing02, 0.0F, 0.829F, 0.3491F); + this.setRotateAngle(lWing03, 0.0F, -2.1719F, 0.0F); + this.setRotateAngle(lWingMembrane02, 0.1745F, -0.6545F, -0.6981F); + this.setRotateAngle(neck, 0.1309F, 0.0F, 0.0F); + this.setRotateAngle(rClawsRotator, 0.0873F, 0.0F, 0.2618F); + this.setRotateAngle(rFinger, -0.6981F, 0.3054F, -0.6545F); + this.setRotateAngle(rLeg01, 0.3491F, -0.2182F, -0.2618F); + this.setRotateAngle(rLeg02, -0.2182F, 0.0F, 0.0F); + this.setRotateAngle(rWing01, 0.7418F, 0.1309F, -0.48F); + this.setRotateAngle(rWing02, 0.0F, -0.829F, -0.3491F); + this.setRotateAngle(rWing03, 0.0F, 2.1719F, 0.0F); + this.setRotateAngle(rWingMembrane02, 0.1745F, 0.6545F, 0.6981F); + this.setRotateAngle(stomach, 0.0785F, 0.0F, 0.0F); + this.setRotateAngle(tail01, -0.5473F, 0.0F, 0.0F); } public void setRotateAngle(ModelPart ModelPart, float x, float y, float z) { diff --git a/common/src/main/java/dev/itsmeow/whisperwoods/entity/EntityZotzpyre.java b/common/src/main/java/dev/itsmeow/whisperwoods/entity/EntityZotzpyre.java index 87e2da0..8c15a8a 100644 --- a/common/src/main/java/dev/itsmeow/whisperwoods/entity/EntityZotzpyre.java +++ b/common/src/main/java/dev/itsmeow/whisperwoods/entity/EntityZotzpyre.java @@ -4,14 +4,13 @@ import dev.itsmeow.imdlib.entity.util.BiomeTypes; import dev.itsmeow.whisperwoods.init.ModEntities; import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; import net.minecraft.core.Registry; -import net.minecraft.network.protocol.game.ClientboundSetPassengersPacket; import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.network.syncher.SynchedEntityData; import net.minecraft.resources.ResourceKey; import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundEvents; import net.minecraft.util.Mth; @@ -21,165 +20,66 @@ import net.minecraft.world.effect.MobEffects; import net.minecraft.world.entity.*; import net.minecraft.world.entity.ai.attributes.Attributes; -import net.minecraft.world.entity.ai.goal.FloatGoal; -import net.minecraft.world.entity.ai.goal.LeapAtTargetGoal; -import net.minecraft.world.entity.ai.goal.LookAtPlayerGoal; -import net.minecraft.world.entity.ai.goal.WaterAvoidingRandomStrollGoal; +import net.minecraft.world.entity.ai.control.FlyingMoveControl; +import net.minecraft.world.entity.ai.control.MoveControl; +import net.minecraft.world.entity.ai.goal.Goal; +import net.minecraft.world.entity.ai.goal.WaterAvoidingRandomFlyingGoal; import net.minecraft.world.entity.ai.goal.target.HurtByTargetGoal; import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal; +import net.minecraft.world.entity.ai.navigation.FlyingPathNavigation; import net.minecraft.world.entity.ai.navigation.PathNavigation; -import net.minecraft.world.entity.ai.navigation.WallClimberNavigation; -import net.minecraft.world.entity.ambient.AmbientCreature; +import net.minecraft.world.entity.ai.util.RandomPos; import net.minecraft.world.entity.animal.FlyingAnimal; -import net.minecraft.world.entity.animal.horse.AbstractHorse; -import net.minecraft.world.entity.monster.Enemy; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.enchantment.EnchantmentHelper; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.pathfinder.TurtleNodeEvaluator; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; +import net.minecraft.world.phys.shapes.VoxelShape; +import java.util.EnumSet; import java.util.Random; -public class EntityZotzpyre extends EntityMonsterWithTypes { +public class EntityZotzpyre extends EntityMonsterWithTypes implements FlyingAnimal { - private static final EntityDataAccessor CLIMBING = SynchedEntityData.defineId(EntityZotzpyre.class, EntityDataSerializers.BYTE); - protected int lastAttack = 0; - private boolean isFromZotz = false; + private static final EntityDataAccessor HANGING = SynchedEntityData.defineId(EntityZotzpyre.class, EntityDataSerializers.BOOLEAN); + private FastFlyingMoveControl moveSwoop; + private FlyingMoveControl moveNormal; public EntityZotzpyre(EntityType entityType, Level worldIn) { super(entityType, worldIn); + this.setNoGravity(true); + this.moveSwoop = new FastFlyingMoveControl(this); + this.moveNormal = new FlyingMoveControl(this, 20, false); + this.moveControl = moveNormal; } @Override protected void registerGoals() { - this.goalSelector.addGoal(0, new FloatGoal(this)); - this.goalSelector.addGoal(1, new LeapAtTargetGoal(this, 0.5F)); - this.goalSelector.addGoal(2, new WaterAvoidingRandomStrollGoal(this, 0.6D)); - this.goalSelector.addGoal(3, new LookAtPlayerGoal(this, Player.class, 8.0F)); + this.goalSelector.addGoal(0, new SwoopingAttackGoal(this)); + this.goalSelector.addGoal(1, new HangFromCeilingGoal(this)); + this.goalSelector.addGoal(2, new WaterAvoidingRandomFlyingGoal(this, 1D)); this.targetSelector.addGoal(0, new HurtByTargetGoal(this)); - this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Player.class, true)); - this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Mob.class, 0, true, true, entity -> !(entity instanceof EntityZotzpyre) && !(entity instanceof AbstractHorse) && !(entity instanceof AmbientCreature) && !(entity instanceof Enemy) && entity.getMobType() != MobType.UNDEAD)); + this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Player.class, 0, false, false, e -> true)); } protected PathNavigation createNavigation(Level worldIn) { - return new WallClimberNavigation(this, worldIn); + return new FlyingPathNavigation(this, worldIn); } @Override protected void defineSynchedData() { super.defineSynchedData(); - this.entityData.define(CLIMBING, (byte) 0); + this.getEntityData().define(HANGING, false); } - @Override - public boolean isPushable() { - return false; - } - - @Override - protected void doPush(Entity entityIn) { + public boolean isHanging() { + return this.getEntityData().get(HANGING); } - @Override - protected void pushEntities() { - } - - @Override - public void tick() { - if (this.isPassenger()) { - this.setNoAi(true); - // you'd think it wouldn't be null. except it is. on turtles in water? - // explain MINECRAFT. EXPLAIN. - if (this.getNavigation().getNodeEvaluator() == null) { - this.getNavigation().nodeEvaluator = new TurtleNodeEvaluator(); - } - } else if (this.isNoAi()) { - this.setNoAi(false); - } - super.tick(); - if (!this.level.isClientSide && !this.isAlive() && this.getVehicle() != null || (!this.level.isClientSide && this.getVehicle() != null && !this.getVehicle().isAlive())) { - this.dismountZotz(); - } - if (!this.level.isClientSide) { - this.setBesideClimbableBlock(this.horizontalCollision); - } - } - - /* prevent slowdown in air */ - @Override - public void travel(Vec3 vec) { - boolean flag = this.getDeltaMovement().y <= 0.0D; - double d0 = 0.08D; - double d1 = this.getY(); - float f = this.isSprinting() ? 0.9F : this.getWaterSlowDown(); - float f1 = 0.02F; - float f2 = (float) EnchantmentHelper.getDepthStrider(this); - if (f2 > 3.0F) { - f2 = 3.0F; - } - - if (f2 > 0.0F) { - f += (0.54600006F - f) * f2 / 3.0F; - f1 += (this.getSpeed() - f1) * f2 / 3.0F; - } - - if (this.hasEffect(MobEffects.DOLPHINS_GRACE)) { - f = 0.96F; - } - - this.moveRelative(f1, vec); - this.move(MoverType.SELF, this.getDeltaMovement()); - Vec3 vec3d1 = this.getDeltaMovement(); - if (this.horizontalCollision && this.onClimbable()) { - vec3d1 = new Vec3(vec3d1.x, 0.2D, vec3d1.z); - } - - this.setDeltaMovement(vec3d1.multiply(f, 0.8F, f)); - if (!this.isNoGravity() && !this.isSprinting()) { - Vec3 vec3d2 = this.getDeltaMovement(); - double d2; - if (flag && Math.abs(vec3d2.y - 0.005D) >= 0.003D && Math.abs(vec3d2.y - d0 / 16.0D) < 0.003D) { - d2 = -0.003D; - } else { - d2 = vec3d2.y - d0 / 16.0D; - } - - this.setDeltaMovement(vec3d2.x, d2, vec3d2.z); - } - - Vec3 vec3d6 = this.getDeltaMovement(); - if (this.horizontalCollision && this.isFree(vec3d6.x, vec3d6.y + (double) 0.6F - this.getY() + d1, vec3d6.z)) { - this.setDeltaMovement(vec3d6.x, 0.3F, vec3d6.z); - } - - - this.animationSpeedOld = this.animationSpeed; - double d5 = this.getX() - this.xo; - double d6 = this.getZ() - this.zo; - double d8 = this instanceof FlyingAnimal ? this.getY() - this.yo : 0.0D; - float f8 = Mth.sqrt(d5 * d5 + d8 * d8 + d6 * d6) * 4.0F; - if (f8 > 1.0F) { - f8 = 1.0F; - } - - this.animationSpeed += (f8 - this.animationSpeed) * 0.4F; - this.animationPosition += this.animationSpeed; - } - - @Override - public boolean onClimbable() { - return this.isBesideClimbableBlock(); - } - - public boolean isBesideClimbableBlock() { - return (this.entityData.get(CLIMBING) & 1) != 0; - } - - public void setBesideClimbableBlock(boolean climbing) { - byte b0 = this.entityData.get(CLIMBING); - this.entityData.set(CLIMBING, climbing ? (byte) (b0 | 1) : (byte) (b0 & -2)); + public void setHanging(boolean hanging) { + this.getEntityData().set(HANGING, hanging); } @Override @@ -207,83 +107,6 @@ protected SoundEvent getDeathSound() { return SoundEvents.BAT_DEATH; } - @Override - public void aiStep() { - super.aiStep(); - if (!this.level.isClientSide && this.getTarget() != null && this.getTarget().isAlive()) { - if (this.getVehicle() != null && this.getVehicle() == this.getTarget()) { - float time = 20F; - if (!this.wasTouchingWater) { - time *= 2F * (Math.random() + 1F); - } else { - time += Math.random() * Math.random() * 2 * ((Math.random() < 0.5) ? -1 : 1); - } - if (this.lastAttack + time < this.tickCount) { - this.doHurtTarget(this.getTarget()); - } - } else if (this.distanceToSqr(this.getTarget()) < 3) { - this.grabTarget(this.getTarget()); - } - } - } - - @Override - public boolean rideableUnderWater() { - return true; - } - - public void grabTarget(Entity entity) { - if (!level.isClientSide) { - if (this.getVehicle() == null) { - this.startRiding(entity, true); - for (ServerPlayer player : this.level.getServer().getPlayerList().getPlayers()) { - if (player.level == this.level && player.distanceTo(this) <= 128) { - player.connection.send(new ClientboundSetPassengersPacket(entity)); - } - } - } - } - } - - public void dismountZotz() { - Entity mount = this.getVehicle(); - this.isFromZotz = true; - this.stopRiding(); - this.isFromZotz = false; - if (!level.isClientSide && this.level.getServer() != null) { - for (ServerPlayer player : this.level.getServer().getPlayerList().getPlayers()) { - if (player.level == this.level && player.distanceTo(this) <= 128) { - player.connection.send(new ClientboundSetPassengersPacket(mount)); - } - } - } - } - - @Override - public void stopRiding() { - if (this.getVehicle() != null && !this.getVehicle().rideableUnderWater()) { - super.stopRiding(); - } else if (this.getTarget() == null || isFromZotz) { - super.stopRiding(); - } - } - - //@Override on Forge - public boolean canRiderInteract() { - return true; - } - - @Override - public double getMyRidingOffset() { - if (getVehicle() != null && getVehicle() instanceof Player) { - return getVehicle().getBbHeight() - 2.25F; - } else if (getVehicle() != null) { - return (getVehicle().getEyeHeight() / 2) - this.getBbHeight(); - } else { - return super.getMyRidingOffset(); - } - } - @SuppressWarnings("deprecation") public static boolean canSpawn(EntityType type, LevelAccessor world, MobSpawnType reason, BlockPos pos, Random rand) { if (pos.getY() >= world.getSeaLevel() && !BiomeTypes.getTypes(ResourceKey.create(Registry.BIOME_REGISTRY, ((ServerLevel)world).getServer().registryAccess().registryOrThrow(Registry.BIOME_REGISTRY).getKey(world.getBiome(pos)))).contains(BiomeTypes.JUNGLE)) { @@ -293,26 +116,12 @@ public static boolean canSpawn(EntityType type, LevelAccessor wo } } - @Override - public boolean hurt(DamageSource source, float amount) { - if (this.isInvulnerableTo(source)) { - return false; - } else { - if (amount > 3 && this.getVehicle() != null && !this.level.isClientSide) { - this.dismountZotz(); - } - - return super.hurt(source, amount); - } - } - @Override public boolean doHurtTarget(Entity entityIn) { float f = (float) this.getAttribute(Attributes.ATTACK_DAMAGE).getValue(); boolean flag = entityIn.hurt(DamageSource.mobAttack(this), f); if (flag) { - this.lastAttack = this.tickCount; - if (entityIn instanceof Player) { + if(entityIn instanceof Player) { Player player = (Player) entityIn; int slowTicks = 0; if (this.level.getDifficulty() == Difficulty.EASY) { @@ -322,23 +131,274 @@ public boolean doHurtTarget(Entity entityIn) { } else if (this.level.getDifficulty() == Difficulty.HARD) { slowTicks = 600; // 30s } - player.addEffect(new MobEffectInstance(MobEffects.MOVEMENT_SLOWDOWN, slowTicks, 1, false, false)); + if (slowTicks > 0) + player.addEffect(new MobEffectInstance(MobEffects.MOVEMENT_SLOWDOWN, slowTicks, 1, false, false)); } - } - if (!this.level.isClientSide && !entityIn.isAlive() && entityIn == this.getVehicle()) { - this.dismountZotz(); + this.setLastHurtMob(entityIn); } return flag; } + @Override + public boolean canCollideWith(Entity entity) { + return entity != this.getTarget() && super.canCollideWith(entity); + } + @Override public boolean causeFallDamage(float distance, float damageMultiplier) { return false; } + @Override + protected void checkFallDamage(double d, boolean bl, BlockState blockState, BlockPos blockPos) { + } + + @Override + public void travel(Vec3 vec3) { + if(this.isHanging() || this.moveControl == this.moveSwoop) { + if (this.isInWater()) { + this.moveRelative(0.02F, vec3); + this.move(MoverType.SELF, this.getDeltaMovement()); + this.setDeltaMovement(this.getDeltaMovement().scale(0.800000011920929D)); + } else if (this.isInLava()) { + this.moveRelative(0.02F, vec3); + this.move(MoverType.SELF, this.getDeltaMovement()); + this.setDeltaMovement(this.getDeltaMovement().scale(0.5D)); + } else { + float f = 0.91F; + if (this.onGround) { + f = this.level.getBlockState(new BlockPos(this.getX(), this.getY() - 1.0D, this.getZ())).getBlock().getFriction() * 0.91F; + } + float g = 0.16277137F / (f * f * f); + this.moveRelative(this.onGround ? 0.1F * g : 0.02F, vec3); + this.move(MoverType.SELF, this.getDeltaMovement()); + this.setDeltaMovement(this.getDeltaMovement().scale(f)); + } + this.calculateEntityAnimation(this, false); + } else { + super.travel(vec3); + } + } + + @Override + public boolean onClimbable() { + return !this.isHanging(); + } + @Override public EntityTypeContainer getContainer() { return ModEntities.ZOTZPYRE; } + public static class HangFromCeilingGoal extends Goal { + + protected T parentEntity; + + public HangFromCeilingGoal(T parentEntity) { + this.parentEntity = parentEntity; + this.setFlags(EnumSet.of(Flag.MOVE)); + } + + @Override + public boolean canUse() { + return this.parentEntity.getTarget() == null && this.parentEntity.level.getBlockState(this.parentEntity.blockPosition().above()).isFaceSturdy(this.parentEntity.level, this.parentEntity.blockPosition().above(), Direction.DOWN); + } + + @Override + public void tick() { + this.parentEntity.getNavigation().moveTo(this.parentEntity.getX(), this.parentEntity.blockPosition().getY(), this.parentEntity.getZ(), 1D); + } + + @Override + public void start() { + if(parentEntity instanceof EntityZotzpyre) { + ((EntityZotzpyre) this.parentEntity).setHanging(true); + } + } + + @Override + public void stop() { + ((EntityZotzpyre) this.parentEntity).setHanging(false); + } + } + + public static class SwoopingAttackGoal extends Goal { + + public enum MovementPhase { + SWOOP_TO, + HIT, + SWOOP_AWAY; + } + + protected MovementPhase phase; + protected T parentEntity; + private int phaseTicks; + private Vec3 startPos; + + private Vec3 targetPosition; + + public SwoopingAttackGoal(T parentEntity) { + this.parentEntity = parentEntity; + this.setFlags(EnumSet.of(Flag.MOVE, Flag.LOOK)); + this.phase = MovementPhase.SWOOP_TO; + this.phaseTicks = 0; + this.startPos = null; + this.targetPosition = null; + } + + @Override + public void stop() { + this.phase = MovementPhase.SWOOP_TO; + this.phaseTicks = 0; + this.startPos = null; + this.targetPosition = null; + if (this.parentEntity.getMoveControl() instanceof FastFlyingMoveControl) { + ((FastFlyingMoveControl) this.parentEntity.getMoveControl()).stop(); + } + if(this.parentEntity instanceof EntityZotzpyre) { + EntityZotzpyre zotzpyre = (EntityZotzpyre) this.parentEntity; + zotzpyre.moveControl = zotzpyre.moveNormal; + } + } + + @Override + public boolean canUse() { + return this.parentEntity.getTarget() != null && this.parentEntity.canAttack(this.parentEntity.getTarget()); + } + + @Override + public void start() { + if(this.parentEntity instanceof EntityZotzpyre) { + EntityZotzpyre zotzpyre = (EntityZotzpyre) this.parentEntity; + zotzpyre.moveControl = zotzpyre.moveSwoop; + } + this.startPos = this.parentEntity.position(); + this.phaseTicks = 0; + LivingEntity target = this.parentEntity.getTarget(); + if(this.parentEntity.distanceTo(target) < 1D) { + this.phase = MovementPhase.HIT; + this.startPos = null; + } + this.targetPosition = target.getEyePosition(1F); + } + + private boolean isAtPosition() { + return this.targetPosition != null ? this.parentEntity.position().distanceTo(this.targetPosition) < 1.5D : false; + } + + @Override + public void tick() { + LivingEntity target = this.parentEntity.getTarget(); + if(this.phase == MovementPhase.SWOOP_TO) { + this.targetPosition = target.getEyePosition(1F); + if(this.targetPosition != null && !this.isAtPosition() && this.phaseTicks++ > 20F && this.parentEntity.getDeltaMovement().length() < 0.01D) { + this.parentEntity.getNavigation().moveTo(targetPosition.x(), targetPosition.y(), targetPosition.z(), 1D); + } else { + this.parentEntity.getNavigation().stop(); + } + this.parentEntity.lookAt(target, 30F, 30F); + if(this.isAtPosition()) { + this.phase = MovementPhase.HIT; + this.phaseTicks = 0; + } + } else if(this.phase == MovementPhase.HIT) { + this.targetPosition = target.getEyePosition(1F); + this.parentEntity.lookAt(target, 30F, 30F); + if((this.parentEntity.tickCount - this.parentEntity.getLastHurtMobTimestamp() > 40 && this.parentEntity.doHurtTarget(target)) || this.phaseTicks++ > 45) { + this.phaseTicks = 0; + this.phase = MovementPhase.SWOOP_AWAY; + this.targetPosition = null; + } + } else if(this.phase == MovementPhase.SWOOP_AWAY) { + if(this.targetPosition != null) { + if(this.isAtPosition() || this.phaseTicks++ > 45 || this.parentEntity.getNavigation().createPath(targetPosition.x(), targetPosition.y(), targetPosition.z(), 1) == null) { + this.phase = MovementPhase.SWOOP_TO; + this.phaseTicks = 0; + this.startPos = this.parentEntity.position(); + this.targetPosition = null; + } + } else { + if (startPos != null) { + Vec3 oScale = startPos.subtract(target.position()).multiply(-2D, 1D, -2D); + if (oScale.length() > 10D) { + oScale = oScale.multiply(0.5D, 1D, 0.5D); + } + if(oScale.y() > 5) { + oScale = oScale.subtract(0, 2.5, 0); + } + Vec3 opposite = target.position().add(oScale); + this.targetPosition = opposite; + } else { + Vec3 newPos = RandomPos.getAirPos(this.parentEntity, 10, 10, 10, null, 1D); + this.targetPosition = newPos; + } + } + } else { + this.phase = MovementPhase.SWOOP_TO; + this.phaseTicks = 0; + this.startPos = null; + this.targetPosition = null; + } + if(this.targetPosition != null && !this.isAtPosition()) { + this.parentEntity.getMoveControl().setWantedPosition(this.targetPosition.x(), this.targetPosition.y(), this.targetPosition.z(), 1D); + } + } + } + + public static class FastFlyingMoveControl extends MoveControl { + + private boolean cantReach = false; + + public FastFlyingMoveControl(Mob mob) { + super(mob); + } + + @Override + public void setWantedPosition(double d, double e, double f, double g) { + super.setWantedPosition(d, e, f, g); + this.cantReach = false; + } + + @Override + public void tick() { + if (this.operation == Operation.MOVE_TO) { + this.mob.setNoGravity(true); + Vec3 diff = new Vec3(this.wantedX - this.mob.getX(), this.wantedY - this.mob.getY(), this.wantedZ - this.mob.getZ()); + Vec3 diffNorm = diff.normalize(); + if (this.canReach(diffNorm, Mth.ceil(diff.length()))) { + this.mob.setDeltaMovement(this.mob.getDeltaMovement().add(diffNorm.scale(0.1D))); + } else { + this.cantReach = true; + this.stop(); + } + + double yawAngle = Math.atan2(diff.z(), diff.x()) * (180D / Math.PI) - 90D; + this.mob.yRot = this.rotlerp(this.mob.yRot, (float) yawAngle, 35.0F); + + double pitchAngle = -Math.atan2(diff.y(), Math.sqrt(diff.x() * diff.x() + diff.z() * diff.z())) * (180D / Math.PI); + this.mob.xRot = this.rotlerp(this.mob.xRot, (float) pitchAngle, 35.0F); + } else { + this.mob.setNoGravity(false); + } + } + + public boolean cantReach() { + return this.cantReach; + } + + public void stop() { + this.operation = Operation.WAIT; + } + + private boolean canReach(Vec3 vec3, int i) { + AABB box = this.mob.getBoundingBox(); + for (int j = 1; j < i; ++j) { + box = box.move(vec3); + if (!this.mob.level.getBlockCollisions(this.mob, box).allMatch(VoxelShape::isEmpty)) { + return false; + } + } + return true; + } + } } diff --git a/common/src/main/java/dev/itsmeow/whisperwoods/init/ModEntities.java b/common/src/main/java/dev/itsmeow/whisperwoods/init/ModEntities.java index 0968112..4c17fbe 100644 --- a/common/src/main/java/dev/itsmeow/whisperwoods/init/ModEntities.java +++ b/common/src/main/java/dev/itsmeow/whisperwoods/init/ModEntities.java @@ -82,7 +82,10 @@ public class ModEntities { public static final EntityTypeContainer ZOTZPYRE = H.add(EntityZotzpyre.class, EntityZotzpyre::new, "zotzpyre", () -> Mob.createMobAttributes() .add(Attributes.MAX_HEALTH, 20.0D) - .add(Attributes.ATTACK_DAMAGE, 3.0D), b -> b + .add(Attributes.ATTACK_DAMAGE, 3.0D) + .add(Attributes.FLYING_SPEED) + .add(Attributes.FLYING_SPEED, 1D) + .add(Attributes.FOLLOW_RANGE, 32D), b -> b .spawn(MobCategory.MONSTER, 30, 1, 1) .defaultPlacement(EntityZotzpyre::canSpawn) .egg(0x321e13, 0x543a28).size(1F, 1F) diff --git a/fabric/src/main/java/dev/itsmeow/whisperwoods/mixin/ProjectileUtilMixin.java b/fabric/src/main/java/dev/itsmeow/whisperwoods/mixin/ProjectileUtilMixin.java deleted file mode 100644 index f1aa107..0000000 --- a/fabric/src/main/java/dev/itsmeow/whisperwoods/mixin/ProjectileUtilMixin.java +++ /dev/null @@ -1,34 +0,0 @@ -package dev.itsmeow.whisperwoods.mixin; - -import dev.itsmeow.whisperwoods.entity.EntityZotzpyre; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.entity.projectile.ProjectileUtil; -import net.minecraft.world.level.Level; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.EntityHitResult; -import net.minecraft.world.phys.Vec3; -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.CallbackInfoReturnable; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; - -import java.util.Iterator; -import java.util.Optional; -import java.util.function.Predicate; - -@Mixin(ProjectileUtil.class) -public class ProjectileUtilMixin { - - @Inject(at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/world/phys/Vec3;distanceToSqr(Lnet/minecraft/world/phys/Vec3;)D", ordinal = 0), method = "getEntityHitResult(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/phys/Vec3;Lnet/minecraft/world/phys/Vec3;Lnet/minecraft/world/phys/AABB;Ljava/util/function/Predicate;D)Lnet/minecraft/world/phys/EntityHitResult;", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD) - private static void getEntityHitResult(Entity entity, Vec3 vec3, Vec3 vec32, AABB aABB, Predicate predicate, double d, CallbackInfoReturnable callbackInfoReturnable, Level level, double e, Entity entity2, Vec3 vec33, Iterator var12, Entity entity3, AABB aABB2, Optional optional, Vec3 vec34, double f) { - if (f < e || e == 0.0D) { - if (entity3.getRootVehicle() == entity.getRootVehicle() && entity instanceof Player && entity3 instanceof EntityZotzpyre && ((EntityZotzpyre) entity3).canRiderInteract()) { - callbackInfoReturnable.setReturnValue(new EntityHitResult(entity3, vec34)); - callbackInfoReturnable.cancel(); - } - } - } - -} \ No newline at end of file diff --git a/fabric/src/main/resources/whisperwoods-fabric.mixins.json b/fabric/src/main/resources/whisperwoods-fabric.mixins.json index acf2c1a..64709bb 100644 --- a/fabric/src/main/resources/whisperwoods-fabric.mixins.json +++ b/fabric/src/main/resources/whisperwoods-fabric.mixins.json @@ -4,9 +4,7 @@ "compatibilityLevel": "JAVA_8", "minVersion": "0.8", "mixins": [], - "client": [ - "ProjectileUtilMixin" - ], + "client": [], "injectors": { "defaultRequire": 1 }