[READ-ONLY] Mirror of https://github.com/aaronateataco/pets-and-pals. Pets & Pals — client-side companion pets with real presence. Fork/redesign of downloadableduck's Pets Mod.
0

Configure Feed

Select the types of activity you want to include in your feed.

0.15.1: smooth every transition - star grow/shrink, raft rise-in, ferry hull turning

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

aaronateataco (Jul 12, 2026, 10:15 AM +0100) b00e57da 632f28b5

+50 -7
+6
CHANGELOG.md
··· 1 1 # Changelog 2 2 3 + ## 0.15.1 4 + - Animation polish pass: the nether star now grows in when the pet tucks away and shrinks out before the pet reforms, instead of popping 5 + - The raft floats up out of the water when it appears instead of blinking into place 6 + - The pet on a ferry raft turns smoothly with the hull instead of snapping toward the destination 7 + - Hopping onto the boat raft now gets the same sparkle transition as the ferry 8 + 3 9 ## 0.15.0 4 10 - Land pets no longer float behind your shoulder during combat - they tuck into the nether star instead, and it stays a star until the fight is over. Flyers keep the shoulder hover 5 11 - Flying pets no longer get a raft when you board a boat - they just fly along
+1 -1
gradle.properties
··· 12 12 loom_version=1.14-SNAPSHOT 13 13 14 14 # Mod Properties 15 - mod_version=0.15.0 15 + mod_version=0.15.1 16 16 maven_group=io.github.aaronateataco.petsandpals 17 17 archives_base_name=pets-and-pals 18 18
+6
src/client/java/io/github/aaronateataco/petsandpals/rendering/PetOrbRenderer.java
··· 28 28 29 29 public static class PetOrbRenderState extends EntityRenderState { 30 30 public float spin; 31 + public float scale = 1.0F; 31 32 } 32 33 33 34 @Override ··· 39 40 public void extractRenderState(@NotNull PetOrb orb, @NotNull PetOrbRenderState state, float partialTick) { 40 41 super.extractRenderState(orb, state, partialTick); 41 42 state.spin = (orb.tickCount + partialTick) * 6.0F; 43 + state.scale = orb.renderScale(partialTick); 42 44 } 43 45 44 46 @Override ··· 47 49 super.submit(state, poseStack, collector, camera); 48 50 RenderType renderType = RenderTypes.entityTranslucentEmissive(TEXTURE); 49 51 52 + if (state.scale <= 0.0F) { 53 + return; 54 + } 50 55 poseStack.pushPose(); 51 56 poseStack.translate(0.0F, 0.25F, 0.0F); 57 + poseStack.scale(state.scale, state.scale, state.scale); 52 58 poseStack.mulPose(Axis.YP.rotationDegrees(state.spin)); 53 59 54 60 // vertical plane
+1
src/main/java/io/github/aaronateataco/petsandpals/mob/AbstractPet.java
··· 232 232 && boatOwner.getVehicle() instanceof net.minecraft.world.entity.vehicle.boat.AbstractBoat boat 233 233 && boatOwner.level() == this.level()) { 234 234 this.setRafted(true); 235 + this.transitionEffects(); 235 236 clientEntitySpawner.accept(PetRaft.create(this.level(), this, boat)); 236 237 } 237 238
+23 -1
src/main/java/io/github/aaronateataco/petsandpals/mob/PetOrb.java
··· 27 27 public class PetOrb extends Entity { 28 28 29 29 private AbstractPet pet; 30 + // countdown for the shrink-out before the pet reforms; -1 = not shrinking 31 + private int shrinkTicks = -1; 32 + private Vec3 pendingSpot; 30 33 31 34 public PetOrb(EntityType<? extends @NotNull PetOrb> type, Level level) { 32 35 super(type, level); ··· 90 93 this.getX(), this.getY() + 0.25, this.getZ(), 0.0, 0.0, 0.0); 91 94 } 92 95 96 + // already shrinking toward reform 97 + if (this.shrinkTicks >= 0) { 98 + if (--this.shrinkTicks < 0) { 99 + this.materializeAt(this.pendingSpot); 100 + } 101 + return; 102 + } 103 + 93 104 // near the owner: look for a spot to reform (never mid-fight) 94 105 if (this.tickCount > 15 && this.tickCount % 8 == 0 && distance < 5.0 95 106 && !this.pet.isCombatTucked()) { 96 107 Vec3 spot = this.findMaterializeSpot(owner); 97 108 if (spot != null) { 98 - this.materializeAt(spot); 109 + // shrink out over a few ticks instead of vanishing on the spot 110 + this.pendingSpot = spot; 111 + this.shrinkTicks = 4; 99 112 } 100 113 } 114 + } 115 + 116 + /** Star size for the renderer: grows in on spawn, shrinks out before reforming. */ 117 + public float renderScale(float partialTick) { 118 + float appear = Mth.clamp((this.tickCount + partialTick) / 5.0F, 0.0F, 1.0F); 119 + if (this.shrinkTicks >= 0) { 120 + return appear * Mth.clamp((this.shrinkTicks - partialTick) / 4.0F, 0.0F, 1.0F); 121 + } 122 + return appear; 101 123 } 102 124 103 125 private void materializeAt(Vec3 spot) {
+13 -5
src/main/java/io/github/aaronateataco/petsandpals/mob/PetRaft.java
··· 146 146 this.velocity = this.velocity.scale(0.3); 147 147 } else { 148 148 double bob = 0.02 * Math.sin(this.tickCount * 0.09); 149 - this.setPos(nextX, surface - 0.01 + bob, nextZ); 149 + this.setPos(nextX, surface - 0.01 + bob + this.riseIn(), nextZ); 150 150 } 151 151 // hull swings like a towed boat: the leashed bow leads toward the rope 152 152 // when it's taut, otherwise the hull drifts around to face its motion ··· 188 188 }; 189 189 // ease the head toward its target so glances look natural 190 190 this.pet.setYHeadRot(Mth.approachDegrees(this.pet.getYHeadRot(), headYaw, 4.0F)); 191 + } 192 + 193 + // spawn entrance: the raft floats up out of the water instead of popping in 194 + private double riseIn() { 195 + if (this.tickCount >= 8) return 0.0; 196 + double t = this.tickCount / 8.0; 197 + return -0.35 * (1.0 - t) * (1.0 - t); 191 198 } 192 199 193 200 // actual water surface at this column; MIN_VALUE when there's no water (land) ··· 220 227 surface = this.waterSurfaceY(nextX, this.getY(), nextZ); 221 228 if (surface == Double.MIN_VALUE) { this.release(); return; } 222 229 } 223 - this.setPos(nextX, surface - 0.01 + 0.02 * Math.sin(this.tickCount * 0.09), nextZ); 230 + this.setPos(nextX, surface - 0.01 + 0.02 * Math.sin(this.tickCount * 0.09) + this.riseIn(), nextZ); 224 231 this.pet.setPos(this.getX(), this.getY() + 0.07, this.getZ()); 225 232 this.pet.setDeltaMovement(Vec3.ZERO); 226 233 this.pet.fallDistance = 0; 227 234 float yaw = (float) (Math.toDegrees(Mth.atan2(toOwner.z, toOwner.x))) - 90.0F; 228 235 this.setYRot(Mth.approachDegrees(this.getYRot(), yaw, 6.0F)); 229 - this.pet.setYRot(yaw); 230 - this.pet.yBodyRot = yaw; 231 - this.pet.setYHeadRot(yaw); 236 + // pet turns with the hull, not straight at the target 237 + this.pet.setYRot(this.getYRot()); 238 + this.pet.yBodyRot = this.getYRot(); 239 + this.pet.setYHeadRot(this.getYRot()); 232 240 } 233 241 234 242 private void release() {