Skip to content

Commit

Permalink
Poses, size and animation
Browse files Browse the repository at this point in the history
  • Loading branch information
N1nn1 committed May 6, 2024
1 parent 7708473 commit aa53cb5
Show file tree
Hide file tree
Showing 19 changed files with 447 additions and 44 deletions.
263 changes: 263 additions & 0 deletions src/main/java/com/ninni/spawn/client/animation/SunfishAnimation.java

Large diffs are not rendered by default.

38 changes: 36 additions & 2 deletions src/main/java/com/ninni/spawn/client/model/SunfishModel.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package com.ninni.spawn.client.model;

import com.ninni.spawn.client.animation.SunfishAnimation;
import com.ninni.spawn.entity.Sunfish;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.model.HierarchicalModel;
import net.minecraft.client.model.geom.ModelPart;
import net.minecraft.client.model.geom.PartPose;
import net.minecraft.client.model.geom.builders.*;
import net.minecraft.util.Mth;

@Environment(value= EnvType.CLIENT)
@SuppressWarnings("FieldCanBeLocal, unused")
Expand Down Expand Up @@ -34,8 +36,40 @@ public SunfishModel(ModelPart root) {


@Override
public void setupAnim(Sunfish entity, float f, float g, float h, float i, float j) {

public void setupAnim(Sunfish entity, float limbSwing, float limbSwingAmount, float animationProgress, float headYaw, float headPitch) {
float pi = (float)Math.PI;
this.root.getAllParts().forEach(ModelPart::resetPose);


if (!entity.isBaby()) {
this.all.y = 11.0F;
this.all.yRot = 0;
this.all.zRot = 0;
this.tailFin.yRot = 0;
this.leftFin.yRot = 0;
this.rightFin.yRot = 0;
this.topFin.zRot = 0;
this.bottomFin.zRot = 0;

if (entity.isInWaterOrBubble()) {
this.animateWalk(SunfishAnimation.SWIM, limbSwing, limbSwingAmount, 1.5f, 8.0f);
this.animate(entity.idleAnimationState, SunfishAnimation.IDLE, animationProgress, 1.0f);
this.animate(entity.flopAnimationState, SunfishAnimation.FLOP, animationProgress, 1.0f);
}
else this.animate(entity.landAnimationState, SunfishAnimation.LAND, animationProgress, 1.0f);
} else {
this.all.zRot = pi/2;
this.all.y = Mth.cos(animationProgress * 0.2F) * 1.5F * 0.25F + (entity.getSunfishAge() == -2 ? 22.5F : 19.0F);
this.all.yRot = Mth.cos(animationProgress * 0.2F) * 0.4F * 0.25F;
this.tailFin.yRot = Mth.cos(animationProgress * 0.4F) * 0.8F * 0.25F;
this.leftFin.yRot = Mth.cos(animationProgress * 0.4F) * 0.8F * 0.25F + 0.8F;
this.rightFin.yRot = Mth.cos(animationProgress * 0.4F + pi) * 0.8F * 0.25F - 0.8F;
this.topFin.zRot = Mth.cos(animationProgress * 0.4F) * 1.6F * 0.25F;
this.bottomFin.zRot = Mth.cos(animationProgress * 0.4F + pi) * 1.6F * 0.25F;

this.all.xRot += headPitch * (float) (Math.PI / 180);
this.all.yRot += headYaw * (float) (Math.PI / 180);
}
}

@Override
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/com/ninni/spawn/entity/AnglerFish.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
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.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.damagesource.DamageSource;
Expand Down Expand Up @@ -157,7 +158,7 @@ protected SoundEvent getSwimSound() {
@Nullable
@Override
protected SoundEvent getAmbientSound() {
return SpawnSoundEvents.FISH_AMBIENT;
return SoundEvents.EMPTY;
}

@Nullable
Expand Down
1 change: 0 additions & 1 deletion src/main/java/com/ninni/spawn/entity/Clam.java
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ public SpawnGroupData finalizeSpawn(ServerLevelAccessor serverLevelAccessor, Dif
protected InteractionResult mobInteract(Player player, InteractionHand interactionHand) {
ItemStack itemStack = player.getItemInHand(interactionHand);
if ((itemStack.isEmpty() || itemStack.getItem() instanceof ClamCaseItem) && this.isAlive()) {
//TODO sound
this.playSound(SoundEvents.EMPTY, 1.0f, 1.0f);
ItemStack itemStack2 = this.getItemStack();
saveToBucketTag(itemStack2);
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/ninni/spawn/entity/Herring.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public ItemStack getBucketItemStack() {

@Override
protected SoundEvent getAmbientSound() {
return SpawnSoundEvents.FISH_AMBIENT;
return SoundEvents.EMPTY;
}

@Override
Expand Down
17 changes: 1 addition & 16 deletions src/main/java/com/ninni/spawn/entity/Octopus.java
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,7 @@ public boolean canBeLeashed(Player player) {
return false;
}

//TODO replace with hashmap
public static int getId(Item item) {
if (item == Items.BUCKET) return 0;
else if (item == Items.GLASS_BOTTLE) return 1;
Expand Down Expand Up @@ -373,22 +374,6 @@ public void tick() {
}
}

static class OctopusLookControl extends GoodAmphibiousMovement.GoodAmphibiousLookControl {
private final Octopus octopus;

public OctopusLookControl(Octopus octopus) {
super(octopus);
this.octopus = octopus;
}

@Override
public void tick() {
if (!this.octopus.isLocking()) {
super.tick();
}
}
}

public class OctopusRandomSwim extends RandomSwimmingGoal {

public OctopusRandomSwim(PathfinderMob pathfinderMob) {
Expand Down
5 changes: 3 additions & 2 deletions src/main/java/com/ninni/spawn/entity/SeaCow.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.ninni.spawn.SpawnTags;
import com.ninni.spawn.entity.ai.goal.EatSeagrassGoal;
import com.ninni.spawn.entity.common.DeepLurker;
import com.ninni.spawn.registry.SpawnBlocks;
import com.ninni.spawn.registry.SpawnParticleTypes;
import com.ninni.spawn.registry.SpawnSoundEvents;
Expand Down Expand Up @@ -55,7 +56,7 @@

import static com.ninni.spawn.Spawn.MOD_ID;

public class SeaCow extends WaterAnimal implements Shearable {
public class SeaCow extends WaterAnimal implements Shearable, DeepLurker {
public static final ResourceLocation LOOT_COMMON = new ResourceLocation(MOD_ID, "archaeology/sea_cow_common");
public static final ResourceLocation LOOT_RARE = new ResourceLocation(MOD_ID, "archaeology/sea_cow_rare");
private static final EntityDataAccessor<Integer> ALGAE = SynchedEntityData.defineId(SeaCow.class, EntityDataSerializers.INT);
Expand All @@ -80,9 +81,9 @@ protected void registerGoals() {
this.goalSelector.addGoal(0, this.eatBlockGoal);
this.goalSelector.addGoal(1, new AvoidEntityGoal<>(this, Guardian.class, 8.0f, 1.0, 1.0));
this.goalSelector.addGoal(2, new RandomSwimmingGoal(this, 1.0, 10));
this.goalSelector.addGoal(3, new MoveToSeagrassGoal(1.2f, 12, 1));
this.goalSelector.addGoal(3, new RandomLookAroundGoal(this));
this.goalSelector.addGoal(4, new LookAtPlayerGoal(this, Player.class, 6.0f));
this.goalSelector.addGoal(5, new MoveToSeagrassGoal(1.2f, 12, 1));
}

public static AttributeSupplier.Builder createAttributes() {
Expand Down
72 changes: 70 additions & 2 deletions src/main/java/com/ninni/spawn/entity/Sunfish.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.ninni.spawn.SpawnTags;
import com.ninni.spawn.registry.SpawnItems;
import com.ninni.spawn.registry.SpawnPose;
import com.ninni.spawn.registry.SpawnSoundEvents;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
Expand All @@ -10,14 +11,17 @@
import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.tags.FluidTags;
import net.minecraft.util.RandomSource;
import net.minecraft.world.DifficultyInstance;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.damagesource.DamageSource;
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.ai.control.SmoothSwimmingLookControl;
import net.minecraft.world.entity.ai.control.SmoothSwimmingMoveControl;
import net.minecraft.world.entity.ai.goal.*;
import net.minecraft.world.entity.ai.navigation.PathNavigation;
Expand All @@ -35,14 +39,21 @@
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.Nullable;


public class Sunfish extends PathfinderMob implements Bucketable {
private static final EntityDataAccessor<Integer> AGE = SynchedEntityData.defineId(Sunfish.class, EntityDataSerializers.INT);
private static final EntityDataAccessor<Boolean> FROM_BUCKET = SynchedEntityData.defineId(Sunfish.class, EntityDataSerializers.BOOLEAN);
public final AnimationState idleAnimationState = new AnimationState();
public final AnimationState landAnimationState = new AnimationState();
public final AnimationState flopAnimationState = new AnimationState();
private int idleAnimationTimeout = 0;
private int landAnimationTimeout = 0;

public Sunfish(EntityType<? extends PathfinderMob> entityType, Level level) {
super(entityType, level);
this.setPathfindingMalus(BlockPathTypes.WATER, 0.0f);
this.moveControl = new SmoothSwimmingMoveControl(this, 85, 10, 0.02f, 0.1f, true);
this.lookControl = new SmoothSwimmingLookControl(this, 10);
}

@Override
Expand All @@ -56,7 +67,7 @@ protected void registerGoals() {
}

public static AttributeSupplier.Builder createAttributes() {
return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 30.0).add(Attributes.MOVEMENT_SPEED, 0.2f);
return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 30.0).add(Attributes.MOVEMENT_SPEED, 0.8f);
}

//@Override
Expand All @@ -65,6 +76,13 @@ public static AttributeSupplier.Builder createAttributes() {
//}


@Nullable
@Override
public SpawnGroupData finalizeSpawn(ServerLevelAccessor serverLevelAccessor, DifficultyInstance difficultyInstance, MobSpawnType mobSpawnType, @Nullable SpawnGroupData spawnGroupData, @Nullable CompoundTag compoundTag) {

return super.finalizeSpawn(serverLevelAccessor, difficultyInstance, mobSpawnType, spawnGroupData, compoundTag);
}

@Override
protected InteractionResult mobInteract(Player player, InteractionHand interactionHand) {
if (this.isBaby() && Bucketable.bucketMobPickup(player, interactionHand, this).isPresent()) {
Expand All @@ -73,6 +91,56 @@ protected InteractionResult mobInteract(Player player, InteractionHand interacti
return super.mobInteract(player, interactionHand);
}

@Override
public void tick() {
super.tick();
if (!this.isBaby()) {
if (!this.isInWaterOrBubble()) {
if (this.getPose() != Pose.STANDING) this.setPose(Pose.STANDING);
} else {
if (this.getPose() != Pose.SWIMMING) this.setPose(Pose.SWIMMING);
}
} else {
SpawnPose pose = this.getSunfishAge() == -2 ? SpawnPose.NEWBORN : SpawnPose.BABY;
if (this.getPose() != pose.get()) this.setPose(pose.get());
}

if (this.level().isClientSide()) {
this.setupAnimationStates();
}
}

@Override
public EntityDimensions getDimensions(Pose pose) {
if (this.isBaby()) {
return pose == SpawnPose.NEWBORN.get() ? EntityDimensions.scalable(0.2F, 0.2F) : EntityDimensions.scalable(0.6F, 0.6F);
} else {
if (pose == Pose.STANDING) return EntityDimensions.scalable(2.2F, 0.5F);
else return EntityDimensions.scalable(1.5F, 2.2F);
}
}

private void setupAnimationStates() {
if (!this.isBaby()) {
if (this.isInWaterOrBubble()) {
if (this.idleAnimationTimeout <= 0) {
this.idleAnimationTimeout = 20 * 4;
this.idleAnimationState.start(this.tickCount);
} else {
--this.idleAnimationTimeout;
}
} else {
if (this.landAnimationTimeout <= 0) {
this.landAnimationTimeout = 20 * 2;
this.landAnimationState.start(this.tickCount);
} else {
--this.landAnimationTimeout;
}

}
}
}

public int getSunfishAge() {
if (this.isBaby()) return this.getAge() < -12000 ? -2 : -1;
return 0;
Expand Down Expand Up @@ -233,7 +301,7 @@ protected SoundEvent getSwimSound() {
@Nullable
@Override
protected SoundEvent getAmbientSound() {
return SpawnSoundEvents.FISH_AMBIENT;
return SoundEvents.EMPTY;
}

@Nullable
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/com/ninni/spawn/entity/Tuna.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
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.stats.Stats;
import net.minecraft.tags.FluidTags;
import net.minecraft.util.Mth;
Expand Down Expand Up @@ -208,7 +209,7 @@ protected SoundEvent getSwimSound() {
@Nullable
@Override
protected SoundEvent getAmbientSound() {
return SpawnSoundEvents.FISH_AMBIENT;
return SoundEvents.EMPTY;
}

@Nullable
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/com/ninni/spawn/entity/Whale.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import net.minecraft.network.protocol.game.ClientboundAddEntityPacket;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.tags.DamageTypeTags;
import net.minecraft.tags.FluidTags;
import net.minecraft.util.Mth;
Expand Down Expand Up @@ -105,7 +106,7 @@ protected SoundEvent getSwimSound() {
@Nullable
@Override
protected SoundEvent getAmbientSound() {
return SpawnSoundEvents.FISH_AMBIENT;
return SoundEvents.EMPTY;
}

@Nullable
Expand Down
41 changes: 41 additions & 0 deletions src/main/java/com/ninni/spawn/mixin/PoseMixin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.ninni.spawn.mixin;

import com.ninni.spawn.registry.SpawnPose;
import net.minecraft.world.entity.Pose;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.gen.Invoker;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@Mixin(Pose.class)
public class PoseMixin {
@Shadow
@Mutable
@Final
private static Pose[] $VALUES;

@Invoker("<init>")
public static Pose newPose(String name, int id) {
throw new AssertionError();
}

@Inject(method = "<clinit>", at = @At(value = "FIELD", target = "Lnet/minecraft/world/entity/Pose;$VALUES:[Lnet/minecraft/world/entity/Pose;", shift = At.Shift.AFTER))
private static void US$addCustomPose(CallbackInfo ci) {
List<Pose> poses = new ArrayList<>(Arrays.asList($VALUES));
Pose last = poses.get(poses.size() - 1);
int i = 1;
for (SpawnPose pose : SpawnPose.values()) {
poses.add(newPose(pose.name(), last.ordinal() + i));
i++;
}
$VALUES = poses.toArray(new Pose[0]);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public class SpawnFish{
.defaultAttributes(Sunfish::createAttributes)
.spawnGroup(MobCategory.WATER_CREATURE)
.spawnRestriction(SpawnPlacements.Type.IN_WATER, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, Sunfish::checkSurfaceWaterAnimalSpawnRules)
.dimensions(EntityDimensions.scalable(0.8F, 2F))
.dimensions(EntityDimensions.scalable(1.5F, 2.2F))
);
public static final EntityType<AnglerFish> ANGLER_FISH = register(
"angler_fish",
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/com/ninni/spawn/registry/SpawnPose.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.ninni.spawn.registry;

import net.minecraft.world.entity.Pose;

public enum SpawnPose {
NEWBORN,
BABY;

public Pose get() {
return Pose.valueOf(this.name());
}
}
Loading

0 comments on commit aa53cb5

Please sign in to comment.