Skip to content

Commit

Permalink
Reanimated all fish
Browse files Browse the repository at this point in the history
  • Loading branch information
N1nn1 committed May 7, 2024
1 parent 58b3368 commit e353571
Show file tree
Hide file tree
Showing 17 changed files with 533 additions and 5 deletions.
18 changes: 18 additions & 0 deletions src/main/java/com/ninni/spawn/SpawnRPTweaks.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.ninni.spawn;

import net.minecraft.client.Minecraft;
import net.minecraft.client.model.geom.ModelPart;
import net.minecraft.resources.ResourceLocation;

public class SpawnRPTweaks {
Expand All @@ -9,6 +10,12 @@ public enum Tweaks {
PARROT_MODEL("parrot_remodel"),
RABBIT_REMODEL("rabbit_remodel"),
BAT_REMODEL("bat_remodel"),
SALMON_ANIMATIONS("salmon_animations"),
SALMON_TILTING("salmon_tilting"),
COD_ANIMATIONS("cod_animations"),
COD_TILTING("cod_tilting"),
TROPICAL_FISH_ANIMATIONS("tropical_fish_animations"),
TROPICAL_FISH_TILTING("tropical_fish_tilting"),
TURTLE_ANIMATIONS("turtle_animations"),
TURTLE_BABY_HEAD_SCALE("turtle_baby_head_scale");

Expand All @@ -26,4 +33,15 @@ public String getName() {
public static boolean isPresent(Tweaks tweak) {
return Minecraft.getInstance().getResourceManager().getResource(new ResourceLocation("tweaks/" + tweak.getName() +".txt")).isPresent();
}

public static void addTilting(Tweaks tweak, ModelPart all, float headYaw, float headPitch) {
float pi = ((float)Math.PI);
if (SpawnRPTweaks.isPresent(tweak)) {
all.xRot = headPitch * (pi / 180);
all.yRot = headYaw * (pi / 180);
} else {
all.xRot = 0;
all.yRot = 0;
}
}
}
2 changes: 0 additions & 2 deletions src/main/java/com/ninni/spawn/entity/AnglerFish.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,6 @@ public class AnglerFish extends AbstractFish implements Bucketable, PathFindingF

public AnglerFish(EntityType<? extends AnglerFish> type, Level world) {
super(type, world);
this.moveControl = new SmoothSwimmingMoveControl(this, 85, 10, 0.02F, 0.1F, true);
this.lookControl = new SmoothSwimmingLookControl(this, 10);
}

public boolean isDeflated() {
Expand Down
2 changes: 0 additions & 2 deletions src/main/java/com/ninni/spawn/entity/Herring.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@
public class Herring extends BoidFishEntity {
public Herring(EntityType<? extends BoidFishEntity> entityType, Level level) {
super(entityType, level);
this.moveControl = new SmoothSwimmingMoveControl(this, 85, 10, 0.02f, 0.1f, true);
this.lookControl = new SmoothSwimmingLookControl(this, 10);
}

public static AttributeSupplier.Builder createAttributes() {
Expand Down
42 changes: 42 additions & 0 deletions src/main/java/com/ninni/spawn/entity/Seahorse.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,18 @@
import net.minecraft.network.syncher.EntityDataSerializers;
import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.tags.FluidTags;
import net.minecraft.util.ByIdMap;
import net.minecraft.util.Mth;
import net.minecraft.util.RandomSource;
import net.minecraft.util.StringRepresentable;
import net.minecraft.world.DifficultyInstance;
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.LookControl;
import net.minecraft.world.entity.ai.control.MoveControl;
import net.minecraft.world.entity.ai.goal.LookAtPlayerGoal;
import net.minecraft.world.entity.ai.goal.RandomLookAroundGoal;
import net.minecraft.world.entity.ai.goal.RandomSwimmingGoal;
Expand All @@ -40,6 +44,8 @@ public class Seahorse extends AbstractFish implements VariantHolder<Seahorse.Pat

public Seahorse(EntityType<? extends Seahorse> type, Level world) {
super(type, world);
this.moveControl = new FishMoveControl(this);
this.lookControl = new LookControl(this);
}

@Nullable
Expand Down Expand Up @@ -123,6 +129,42 @@ protected SoundEvent getHurtSound(DamageSource damageSource) {
return SpawnSoundEvents.SEAHORSE_HURT;
}

private static class FishMoveControl extends MoveControl {
private final AbstractFish fish;

FishMoveControl(AbstractFish abstractFish) {
super(abstractFish);
this.fish = abstractFish;
}

public void tick() {
if (this.fish.isEyeInFluid(FluidTags.WATER)) {
this.fish.setDeltaMovement(this.fish.getDeltaMovement().add(0.0, 0.005, 0.0));
}

if (this.operation == Operation.MOVE_TO && !this.fish.getNavigation().isDone()) {
float f = (float)(this.speedModifier * this.fish.getAttributeValue(Attributes.MOVEMENT_SPEED));
this.fish.setSpeed(Mth.lerp(0.125F, this.fish.getSpeed(), f));
double d = this.wantedX - this.fish.getX();
double e = this.wantedY - this.fish.getY();
double g = this.wantedZ - this.fish.getZ();
if (e != 0.0) {
double h = Math.sqrt(d * d + e * e + g * g);
this.fish.setDeltaMovement(this.fish.getDeltaMovement().add(0.0, (double)this.fish.getSpeed() * (e / h) * 0.1, 0.0));
}

if (d != 0.0 || g != 0.0) {
float i = (float)(Mth.atan2(g, d) * 57.2957763671875) - 90.0F;
this.fish.setYRot(this.rotlerp(this.fish.getYRot(), i, 90.0F));
this.fish.yBodyRot = this.fish.getYRot();
}

} else {
this.fish.setSpeed(0.0F);
}
}
}

public static String getPredefinedName(int i) {
return "entity.spawn.seahorse.variant.predefined." + i;
}
Expand Down
11 changes: 10 additions & 1 deletion src/main/java/com/ninni/spawn/mixin/AbstractFishMixin.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import com.ninni.spawn.entity.common.FlopConditionable;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.ai.control.SmoothSwimmingLookControl;
import net.minecraft.world.entity.ai.control.SmoothSwimmingMoveControl;
import net.minecraft.world.entity.animal.AbstractFish;
import net.minecraft.world.entity.animal.Bucketable;
import net.minecraft.world.entity.animal.WaterAnimal;
Expand All @@ -17,8 +19,15 @@ private AbstractFishMixin(EntityType<? extends WaterAnimal> entityType, Level wo
super(entityType, world);
}


@Inject(method = "<init>", at = @At("TAIL"))
private void S$init(EntityType<? extends AbstractFish> entityType, Level level, CallbackInfo ci) {
this.moveControl = new SmoothSwimmingMoveControl(this, 85, 10, 0.02f, 0.1f, true);
this.lookControl = new SmoothSwimmingLookControl(this, 10);
}

@Inject(method = "aiStep", at = @At("HEAD"), cancellable = true)
private void onTickMovement(CallbackInfo ci) {
private void S$aiStep(CallbackInfo ci) {
AbstractFish that = AbstractFish.class.cast(this);
if (that instanceof FlopConditionable conditionable) {
if (!conditionable.doesFlopWhileOutOfWater()) {
Expand Down
98 changes: 98 additions & 0 deletions src/main/java/com/ninni/spawn/mixin/client/CodModelMixin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package com.ninni.spawn.mixin.client;

import com.ninni.spawn.SpawnRPTweaks;
import net.minecraft.client.model.CodModel;
import net.minecraft.client.model.HierarchicalModel;
import net.minecraft.client.model.SalmonModel;
import net.minecraft.client.model.geom.ModelPart;
import net.minecraft.client.model.geom.PartPose;
import net.minecraft.client.model.geom.builders.CubeListBuilder;
import net.minecraft.client.model.geom.builders.LayerDefinition;
import net.minecraft.client.model.geom.builders.MeshDefinition;
import net.minecraft.client.model.geom.builders.PartDefinition;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
import org.spongepowered.asm.mixin.Final;
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;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

@Mixin(CodModel.class)
public abstract class CodModelMixin<T extends Entity> extends HierarchicalModel<T> {

@Unique
private ModelPart body;
@Unique
private ModelPart leftFin;
@Unique
private ModelPart rightFin;
@Unique
private ModelPart tail;
@Unique
private ModelPart all;
@Shadow @Final private ModelPart root;
@Shadow @Final private ModelPart tailFin;

@Inject(method = "<init>", at = @At("TAIL"))
public void init(ModelPart modelPart, CallbackInfo ci) {
this.all = modelPart.getChild("all");
this.body = this.all.getChild("body");
this.tail = this.all.getChild("tail");
this.leftFin = this.body.getChild("left_fin");
this.rightFin = this.body.getChild("right_fin");
}

@Inject(method = "setupAnim", at = @At("HEAD"), cancellable = true)
private void setupAnim(T cod, float limbAngle, float limbDistance, float animationProgress, float headYaw, float headPitch, CallbackInfo ci) {
float pi = ((float)Math.PI);

if (SpawnRPTweaks.isPresent(SpawnRPTweaks.Tweaks.COD_ANIMATIONS)) {
ci.cancel();

float speed = cod.isInWater() ? 1 : 4;

SpawnRPTweaks.addTilting(SpawnRPTweaks.Tweaks.COD_TILTING, this.all, headYaw, headPitch);

this.all.y = Mth.cos(animationProgress * 0.3f + 3) * 2.4F * 0.25F + 22.0F;
this.all.z = -3.0F;
this.all.xRot += Mth.sin(animationProgress * 0.15f + 1) * 0.2F * -0.25F;
this.tail.yRot = Mth.cos(animationProgress * 0.15f * speed + 1) * 2.8F * 0.25F;
this.tail.yRot += Mth.cos(limbAngle * 2f + 1) * 2.8F * limbDistance;
this.rightFin.zRot = Mth.cos(animationProgress * 0.3f + 1f + pi) * 2 * 0.25F - 0.6F;
this.leftFin.zRot = Mth.cos(animationProgress * 0.3f + 1.5f) * 2F * 0.25F + 0.6F;
} else {
ci.cancel();
SpawnRPTweaks.addTilting(SpawnRPTweaks.Tweaks.COD_TILTING, this.all, headYaw, headPitch);
this.all.z = -3.0F;

float k = 1.0f;
if (!cod.isInWater()) {
k = 1.5f;
}
this.tail.yRot = -k * 0.45f * Mth.sin(0.6f * animationProgress);
}
}

@Inject(method = "createBodyLayer", at = @At("HEAD"), cancellable = true)
private static void createBodyLayer(CallbackInfoReturnable<LayerDefinition> cir) {
MeshDefinition meshdefinition = new MeshDefinition();
PartDefinition partdefinition = meshdefinition.getRoot();

PartDefinition tail_fin = partdefinition.addOrReplaceChild("tail_fin", CubeListBuilder.create(), PartPose.offset(0.0F, 24.0F, 0.0F));

PartDefinition all = partdefinition.addOrReplaceChild("all", CubeListBuilder.create(), PartPose.offset(0.0F, 22.0F, 2.0F));
PartDefinition tail = all.addOrReplaceChild("tail", CubeListBuilder.create().texOffs(22, 3).addBox(0.0F, -2.0F, 0.0F, 0.0F, 4.0F, 4.0F), PartPose.offset(0.0F, 0.0F, 5.0F));
PartDefinition top_fin = all.addOrReplaceChild("top_fin", CubeListBuilder.create().texOffs(20, -6).addBox(0.0F, -1.0F, -1.0F, 0.0F, 1.0F, 6.0F), PartPose.offset(0.0F, -2.0F, -2.0F));
PartDefinition head = all.addOrReplaceChild("head", CubeListBuilder.create().texOffs(11, 0).addBox(-1.0F, -2.0F, -3.0F, 2.0F, 4.0F, 3.0F), PartPose.offset(0.0F, 0.0F, -2.0F));
PartDefinition nose = head.addOrReplaceChild("nose", CubeListBuilder.create().texOffs(0, 0).addBox(-1.0F, -2.0F, -1.0F, 2.0F, 3.0F, 1.0F), PartPose.offset(0.0F, 0.0F, -3.0F));
PartDefinition body = all.addOrReplaceChild("body", CubeListBuilder.create().texOffs(0, 0).addBox(-1.0F, -2.0F, 0.0F, 2.0F, 4.0F, 7.0F), PartPose.offset(0.0F, 0.0F, -2.0F));
PartDefinition right_fin = body.addOrReplaceChild("right_fin", CubeListBuilder.create().texOffs(24, 1).addBox(-2.0F, 0.0F, -1.0F, 2.0F, 0.0F, 2.0F), PartPose.offsetAndRotation(-1.0F, 1.0F, 0.0F, 0.0F, 0.0F, -0.7854F));
PartDefinition left_fin = body.addOrReplaceChild("left_fin", CubeListBuilder.create().texOffs(24, 4).addBox(0.0F, 0.0F, -1.0F, 2.0F, 0.0F, 2.0F), PartPose.offsetAndRotation(1.0F, 1.0F, 0.0F, 0.0F, 0.0F, 0.7854F));

cir.setReturnValue(LayerDefinition.create(meshdefinition, 32, 32));
}
}
94 changes: 94 additions & 0 deletions src/main/java/com/ninni/spawn/mixin/client/SalmonModelMixin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package com.ninni.spawn.mixin.client;

import com.ninni.spawn.SpawnRPTweaks;
import net.minecraft.client.model.HierarchicalModel;
import net.minecraft.client.model.SalmonModel;
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;
import net.minecraft.world.entity.Entity;
import org.spongepowered.asm.mixin.*;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

@Mixin(SalmonModel.class)
public abstract class SalmonModelMixin<T extends Entity> extends HierarchicalModel<T> {

@Unique
private ModelPart backFin;
@Unique
private ModelPart leftFin;
@Unique
private ModelPart body;
@Unique
private ModelPart bodyFront;
@Unique
private ModelPart rightFin;
@Unique
private ModelPart all;

@Inject(method = "<init>", at = @At("TAIL"))
public void init(ModelPart modelPart, CallbackInfo ci) {
this.all = modelPart.getChild("all");
this.body = this.all.getChild("body");
this.bodyFront = this.all.getChild("body_front");
this.backFin = body.getChild("back_fin");
this.leftFin = this.bodyFront.getChild("left_fin");
this.rightFin = this.bodyFront.getChild("right_fin");
}

@Inject(method = "setupAnim", at = @At("HEAD"), cancellable = true)
private void setupAnim(T salmon, float limbAngle, float limbDistance, float animationProgress, float headYaw, float headPitch, CallbackInfo ci) {
float pi = ((float)Math.PI);

if (SpawnRPTweaks.isPresent(SpawnRPTweaks.Tweaks.SALMON_ANIMATIONS)) {
ci.cancel();

float speed = salmon.isInWater() ? 1 : 4;
SpawnRPTweaks.addTilting(SpawnRPTweaks.Tweaks.SALMON_TILTING, this.all, headYaw, headPitch);

this.all.y = Mth.cos(animationProgress * 0.3f + 3) * 2.4F * 0.25F + 21.0F;
this.all.z = 6.0F;
this.all.xRot += Mth.sin(animationProgress * 0.15f + 1) * 0.2F * -0.25F;
this.body.yRot = Mth.cos(animationProgress * 0.15f * speed + 2) * 0.8F * 0.25F;
this.backFin.yRot = Mth.cos(animationProgress * 0.15f * speed + 1) * 2.8F * 0.25F;
this.body.yRot += Mth.cos(limbAngle * 2f + 2) * 0.8F * limbDistance;
this.backFin.yRot += Mth.cos(limbAngle * 2f + 1) * 2.8F * limbDistance;
this.rightFin.zRot = Mth.cos(animationProgress * 0.3f + 1f + pi) * 2 * 0.25F - 0.6F;
this.leftFin.zRot = Mth.cos(animationProgress * 0.3f + 1.5f) * 2F * 0.25F + 0.6F;
} else {
ci.cancel();
SpawnRPTweaks.addTilting(SpawnRPTweaks.Tweaks.SALMON_TILTING, this.all, headYaw, headPitch);
this.all.z = 6.0F;

float k = 1.0f;
float l = 1.0f;
if (!salmon.isInWater()) {
k = 1.3f;
l = 1.7f;
}
this.body.yRot = -k * 0.25f * Mth.sin(l * 0.6f * animationProgress);
}
}
@Inject(method = "createBodyLayer", at = @At("HEAD"), cancellable = true)
private static void createBodyLayer(CallbackInfoReturnable<LayerDefinition> cir) {
MeshDefinition meshdefinition = new MeshDefinition();
PartDefinition partdefinition = meshdefinition.getRoot();

partdefinition.addOrReplaceChild("body_back", CubeListBuilder.create(), PartPose.offset(0, 0, 0));
PartDefinition all = partdefinition.addOrReplaceChild("all", CubeListBuilder.create(), PartPose.offset(0.0F, 21.0F, -1.0F));
all.addOrReplaceChild("tob_back_fin", CubeListBuilder.create().texOffs(0, 2).addBox(0.0F, -2.0F, -1.0F, 0.0F, 2.0F, 4.0F), PartPose.offset(0.0F, -2.5F, 0.0F));
all.addOrReplaceChild("top_front_fin", CubeListBuilder.create().texOffs(4, 2).addBox(0.0F, -4.0F, 6.0F, 0.0F, 2.0F, 2.0F), PartPose.offset(0.0F, -0.5F, -8.0F));
all.addOrReplaceChild("head", CubeListBuilder.create().texOffs(22, 0).addBox(-1.0F, -2.0F, -3.0F, 2.0F, 4.0F, 3.0F), PartPose.offset(0.0F, 0.0F, -8.0F));
PartDefinition body_back = all.addOrReplaceChild("body", CubeListBuilder.create().texOffs(0, 13).addBox(-1.5F, -2.5F, 0.0F, 3.0F, 5.0F, 8.0F), PartPose.offset(0.0F, 0.0F, 0.0F));
body_back.addOrReplaceChild("back_fin", CubeListBuilder.create().texOffs(20, 10).addBox(0.0F, -2.5F, 0.0F, 0.0F, 5.0F, 6.0F), PartPose.offset(0.0F, 0.0F, 8.0F));
PartDefinition body_front = all.addOrReplaceChild("body_front", CubeListBuilder.create().texOffs(0, 0).addBox(-1.5F, -2.5F, 0.0F, 3.0F, 5.0F, 8.0F), PartPose.offset(0.0F, 0.0F, -8.0F));
body_front.addOrReplaceChild("right_fin", CubeListBuilder.create().texOffs(0, 0).addBox(-2.0F, -1.0F, 0.0F, 2.0F, 2.0F, 0.0F), PartPose.offsetAndRotation(-1.5F, 1.5F, 1.0F, -1.5708F, 0.0F, -0.7854F));
body_front.addOrReplaceChild("left_fin", CubeListBuilder.create().texOffs(4, 0).addBox(0.0F, -1.0F, 0.0F, 2.0F, 2.0F, 0.0F), PartPose.offsetAndRotation(1.5F, 1.5F, 1.0F, -1.5708F, 0.0F, 0.7854F));

cir.setReturnValue(LayerDefinition.create(meshdefinition, 32, 32));
}
}
Loading

0 comments on commit e353571

Please sign in to comment.