mirror of
https://github.com/Sollace/Unicopia.git
synced 2024-11-30 16:28:00 +01:00
Pigs love muffins
This commit is contained in:
parent
2c77cfb4c3
commit
d9d56c634c
8 changed files with 183 additions and 6 deletions
|
@ -0,0 +1,36 @@
|
||||||
|
package com.minelittlepony.unicopia.client.render;
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.entity.Creature;
|
||||||
|
import com.minelittlepony.unicopia.entity.Equine;
|
||||||
|
import com.minelittlepony.unicopia.mixin.client.MixinAnimalModel;
|
||||||
|
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.client.render.entity.model.EntityModel;
|
||||||
|
import net.minecraft.client.render.entity.model.QuadrupedEntityModel;
|
||||||
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
|
import net.minecraft.entity.LivingEntity;
|
||||||
|
import net.minecraft.entity.mob.MobEntity;
|
||||||
|
import net.minecraft.entity.passive.PigEntity;
|
||||||
|
|
||||||
|
public class AnimalPoser {
|
||||||
|
public static final AnimalPoser INSTANCE = new AnimalPoser();
|
||||||
|
|
||||||
|
public void applyPosing(MatrixStack matrices, MobEntity entity, EntityModel<?> model) {
|
||||||
|
|
||||||
|
if (entity instanceof PigEntity && model instanceof QuadrupedEntityModel<?> quad) {
|
||||||
|
Equine.of((LivingEntity)entity)
|
||||||
|
.filter(eq -> eq instanceof Creature)
|
||||||
|
.map(Creature.class::cast)
|
||||||
|
.ifPresent(creature -> {
|
||||||
|
float tickDelta = MinecraftClient.getInstance().getTickDelta();
|
||||||
|
float headAngle = creature.getHeadAngle(tickDelta);
|
||||||
|
float neckAngle = 12;
|
||||||
|
|
||||||
|
((MixinAnimalModel)quad).invokeGetHeadParts().forEach(part -> {
|
||||||
|
part.pivotY = neckAngle;
|
||||||
|
part.pitch = headAngle;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,6 +15,7 @@ import com.minelittlepony.unicopia.ability.magic.spell.Spell;
|
||||||
import com.minelittlepony.unicopia.ability.magic.spell.effect.TargetSelecter;
|
import com.minelittlepony.unicopia.ability.magic.spell.effect.TargetSelecter;
|
||||||
import com.minelittlepony.unicopia.entity.ai.BreakHeartGoal;
|
import com.minelittlepony.unicopia.entity.ai.BreakHeartGoal;
|
||||||
import com.minelittlepony.unicopia.entity.ai.DynamicTargetGoal;
|
import com.minelittlepony.unicopia.entity.ai.DynamicTargetGoal;
|
||||||
|
import com.minelittlepony.unicopia.entity.ai.EatMuffinGoal;
|
||||||
import com.minelittlepony.unicopia.entity.ai.WantItTakeItGoal;
|
import com.minelittlepony.unicopia.entity.ai.WantItTakeItGoal;
|
||||||
import com.minelittlepony.unicopia.entity.player.PlayerAttributes;
|
import com.minelittlepony.unicopia.entity.player.PlayerAttributes;
|
||||||
|
|
||||||
|
@ -32,15 +33,18 @@ import net.minecraft.entity.data.TrackedDataHandlerRegistry;
|
||||||
import net.minecraft.entity.mob.HostileEntity;
|
import net.minecraft.entity.mob.HostileEntity;
|
||||||
import net.minecraft.entity.mob.MobEntity;
|
import net.minecraft.entity.mob.MobEntity;
|
||||||
import net.minecraft.entity.mob.SlimeEntity;
|
import net.minecraft.entity.mob.SlimeEntity;
|
||||||
|
import net.minecraft.entity.passive.PigEntity;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.nbt.NbtCompound;
|
import net.minecraft.nbt.NbtCompound;
|
||||||
import net.minecraft.nbt.NbtElement;
|
import net.minecraft.nbt.NbtElement;
|
||||||
|
import net.minecraft.util.math.MathHelper;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
public class Creature extends Living<LivingEntity> implements WeaklyOwned<LivingEntity> {
|
public class Creature extends Living<LivingEntity> implements WeaklyOwned<LivingEntity> {
|
||||||
private static final TrackedData<NbtCompound> EFFECT = DataTracker.registerData(LivingEntity.class, TrackedDataHandlerRegistry.NBT_COMPOUND);
|
private static final TrackedData<NbtCompound> EFFECT = DataTracker.registerData(LivingEntity.class, TrackedDataHandlerRegistry.NBT_COMPOUND);
|
||||||
private static final TrackedData<NbtCompound> MASTER = DataTracker.registerData(LivingEntity.class, TrackedDataHandlerRegistry.NBT_COMPOUND);
|
private static final TrackedData<NbtCompound> MASTER = DataTracker.registerData(LivingEntity.class, TrackedDataHandlerRegistry.NBT_COMPOUND);
|
||||||
public static final TrackedData<Float> GRAVITY = DataTracker.registerData(LivingEntity.class, TrackedDataHandlerRegistry.FLOAT);
|
public static final TrackedData<Float> GRAVITY = DataTracker.registerData(LivingEntity.class, TrackedDataHandlerRegistry.FLOAT);
|
||||||
|
private static final TrackedData<Integer> EATING = DataTracker.registerData(LivingEntity.class, TrackedDataHandlerRegistry.INTEGER);
|
||||||
|
|
||||||
private static final LevelStore LEVELS = Levelled.fixed(0);
|
private static final LevelStore LEVELS = Levelled.fixed(0);
|
||||||
|
|
||||||
|
@ -55,10 +59,15 @@ public class Creature extends Living<LivingEntity> implements WeaklyOwned<Living
|
||||||
@Nullable
|
@Nullable
|
||||||
private GoalSelector targets;
|
private GoalSelector targets;
|
||||||
|
|
||||||
|
private int eatTimer;
|
||||||
|
@Nullable
|
||||||
|
private EatMuffinGoal eatMuffinGoal;
|
||||||
|
|
||||||
public Creature(LivingEntity entity) {
|
public Creature(LivingEntity entity) {
|
||||||
super(entity, EFFECT);
|
super(entity, EFFECT);
|
||||||
physics = new EntityPhysics<>(entity, GRAVITY);
|
physics = new EntityPhysics<>(entity, GRAVITY);
|
||||||
entity.getDataTracker().startTracking(MASTER, master.toNBT());
|
entity.getDataTracker().startTracking(MASTER, master.toNBT());
|
||||||
|
entity.getDataTracker().startTracking(EATING, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -115,6 +124,10 @@ public class Creature extends Living<LivingEntity> implements WeaklyOwned<Living
|
||||||
if (entity.getType().getSpawnGroup() == SpawnGroup.MONSTER) {
|
if (entity.getType().getSpawnGroup() == SpawnGroup.MONSTER) {
|
||||||
goals.add(3, new BreakHeartGoal((MobEntity)entity, targetter));
|
goals.add(3, new BreakHeartGoal((MobEntity)entity, targetter));
|
||||||
}
|
}
|
||||||
|
if (entity instanceof PigEntity) {
|
||||||
|
eatMuffinGoal = new EatMuffinGoal((MobEntity)entity, targetter);
|
||||||
|
goals.add(3, eatMuffinGoal);
|
||||||
|
}
|
||||||
|
|
||||||
if (master.isPresent(getWorld())) {
|
if (master.isPresent(getWorld())) {
|
||||||
initMinionAi();
|
initMinionAi();
|
||||||
|
@ -145,6 +158,37 @@ public class Creature extends Living<LivingEntity> implements WeaklyOwned<Living
|
||||||
public void tick() {
|
public void tick() {
|
||||||
super.tick();
|
super.tick();
|
||||||
physics.tick();
|
physics.tick();
|
||||||
|
|
||||||
|
if (isClient()) {
|
||||||
|
eatTimer = entity.getDataTracker().get(EATING);
|
||||||
|
} else if (eatMuffinGoal != null) {
|
||||||
|
eatTimer = eatMuffinGoal.getTimer();
|
||||||
|
entity.getDataTracker().set(EATING, eatTimer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getNeckAngle(float delta) {
|
||||||
|
if (eatTimer <= 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (eatTimer >= 4 && eatTimer <= 36) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (eatTimer < 4) {
|
||||||
|
return (eatTimer - delta) / 4F;
|
||||||
|
}
|
||||||
|
return -(eatTimer - 40 - delta) / 4F;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getHeadAngle(float delta) {
|
||||||
|
if (eatTimer > 4 && eatTimer <= 36) {
|
||||||
|
float f = (eatTimer - 4 - delta) / 32F;
|
||||||
|
return 0.62831855f + 0.21991149f * MathHelper.sin(f * 28.7F);
|
||||||
|
}
|
||||||
|
if (eatTimer > 0) {
|
||||||
|
return 0.62831855f;
|
||||||
|
}
|
||||||
|
return entity.getPitch() * ((float)Math.PI / 180);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -22,7 +22,7 @@ public class BreakHeartGoal extends Goal {
|
||||||
public BreakHeartGoal(MobEntity mob, DynamicTargetGoal targetter) {
|
public BreakHeartGoal(MobEntity mob, DynamicTargetGoal targetter) {
|
||||||
this.mob = mob;
|
this.mob = mob;
|
||||||
this.targetter = targetter;
|
this.targetter = targetter;
|
||||||
this.setControls(EnumSet.of(Goal.Control.MOVE, Goal.Control.LOOK));
|
this.setControls(EnumSet.of(Goal.Control.MOVE, Goal.Control.LOOK, Goal.Control.JUMP));
|
||||||
|
|
||||||
target = targetter.addPredicate(this::canTarget);
|
target = targetter.addPredicate(this::canTarget);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
package com.minelittlepony.unicopia.entity.ai;
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.entity.PhysicsBodyProjectileEntity;
|
||||||
|
import com.minelittlepony.unicopia.item.UItems;
|
||||||
|
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.mob.MobEntity;
|
||||||
|
import net.minecraft.entity.passive.AnimalEntity;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
|
||||||
|
public class EatMuffinGoal extends BreakHeartGoal {
|
||||||
|
|
||||||
|
private int timer;
|
||||||
|
|
||||||
|
private boolean eatingStarted;
|
||||||
|
|
||||||
|
public EatMuffinGoal(MobEntity mob, DynamicTargetGoal targetter) {
|
||||||
|
super(mob, targetter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTimer() {
|
||||||
|
return eatingStarted ? timer : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start() {
|
||||||
|
eatingStarted = false;
|
||||||
|
timer = getTickCount(10);
|
||||||
|
mob.getNavigation().stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stop() {
|
||||||
|
super.stop();
|
||||||
|
eatingStarted = false;
|
||||||
|
timer = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldContinue() {
|
||||||
|
return timer > 0 && super.shouldContinue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean canTarget(Entity e) {
|
||||||
|
return !e.isRemoved()
|
||||||
|
&& e instanceof PhysicsBodyProjectileEntity
|
||||||
|
&& ((PhysicsBodyProjectileEntity)e).getStack().getItem() == UItems.MUFFIN
|
||||||
|
&& mob.getVisibilityCache().canSee(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void attackTarget(Entity target, double reach, double distance) {
|
||||||
|
double speed = 1D;
|
||||||
|
|
||||||
|
if (distance > 5) {
|
||||||
|
speed += 0.5;
|
||||||
|
}
|
||||||
|
if (distance < 2) {
|
||||||
|
speed += 0.1D;
|
||||||
|
}
|
||||||
|
|
||||||
|
mob.getNavigation().startMovingTo(target, speed);
|
||||||
|
|
||||||
|
if (distance <= reach + 0.5) {
|
||||||
|
eatingStarted = true;
|
||||||
|
|
||||||
|
if (target instanceof PhysicsBodyProjectileEntity projectile) {
|
||||||
|
mob.eatFood(mob.world, projectile.getStack());
|
||||||
|
projectile.discard();
|
||||||
|
|
||||||
|
if (mob instanceof AnimalEntity animal) {
|
||||||
|
if (mob.world.random.nextInt(12) == 0) {
|
||||||
|
Entity player = ((PhysicsBodyProjectileEntity) target).getOwner();
|
||||||
|
|
||||||
|
animal.lovePlayer(player instanceof PlayerEntity ? (PlayerEntity)player : null);
|
||||||
|
animal.setLoveTicks(1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -29,11 +29,7 @@ abstract class ProjectileItem extends Item implements ProjectileDelegate<Project
|
||||||
public TypedActionResult<ItemStack> use(World world, PlayerEntity player, Hand hand) {
|
public TypedActionResult<ItemStack> use(World world, PlayerEntity player, Hand hand) {
|
||||||
|
|
||||||
if (isFood() && !player.isSneaking()) {
|
if (isFood() && !player.isSneaking()) {
|
||||||
TypedActionResult<ItemStack> eaten = super.use(world, player, hand);
|
return super.use(world, player, hand);
|
||||||
|
|
||||||
if (eaten.getResult().isAccepted()) {
|
|
||||||
return eaten;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemStack stack = player.getStackInHand(hand);
|
ItemStack stack = player.getStackInHand(hand);
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
package com.minelittlepony.unicopia.mixin.client;
|
||||||
|
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||||
|
import net.minecraft.client.model.ModelPart;
|
||||||
|
import net.minecraft.client.render.entity.model.AnimalModel;
|
||||||
|
|
||||||
|
@Mixin(AnimalModel.class)
|
||||||
|
public interface MixinAnimalModel {
|
||||||
|
@Invoker("getHeadParts")
|
||||||
|
Iterable<ModelPart> invokeGetHeadParts();
|
||||||
|
}
|
|
@ -6,6 +6,7 @@ import org.spongepowered.asm.mixin.injection.At.Shift;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.client.render.AnimalPoser;
|
||||||
import com.minelittlepony.unicopia.client.render.PlayerPoser;
|
import com.minelittlepony.unicopia.client.render.PlayerPoser;
|
||||||
|
|
||||||
import net.minecraft.client.render.VertexConsumerProvider;
|
import net.minecraft.client.render.VertexConsumerProvider;
|
||||||
|
@ -16,6 +17,7 @@ import net.minecraft.client.render.entity.model.BipedEntityModel;
|
||||||
import net.minecraft.client.render.entity.model.EntityModel;
|
import net.minecraft.client.render.entity.model.EntityModel;
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
import net.minecraft.entity.LivingEntity;
|
import net.minecraft.entity.LivingEntity;
|
||||||
|
import net.minecraft.entity.mob.MobEntity;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
|
||||||
@Mixin(LivingEntityRenderer.class)
|
@Mixin(LivingEntityRenderer.class)
|
||||||
|
@ -37,5 +39,8 @@ abstract class MixinLivingEntityRenderer<T extends LivingEntity, M extends Entit
|
||||||
if (entity instanceof PlayerEntity player) {
|
if (entity instanceof PlayerEntity player) {
|
||||||
PlayerPoser.INSTANCE.applyPosing(matrices, player, (BipedEntityModel<?>)getModel());
|
PlayerPoser.INSTANCE.applyPosing(matrices, player, (BipedEntityModel<?>)getModel());
|
||||||
}
|
}
|
||||||
|
if (entity instanceof MobEntity mob) {
|
||||||
|
AnimalPoser.INSTANCE.applyPosing(matrices, mob, getModel());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
"MixinWorldChunk"
|
"MixinWorldChunk"
|
||||||
],
|
],
|
||||||
"client": [
|
"client": [
|
||||||
|
"client.MixinAnimalModel",
|
||||||
"client.MixinArmorFeatureRenderer",
|
"client.MixinArmorFeatureRenderer",
|
||||||
"client.MixinCamera",
|
"client.MixinCamera",
|
||||||
"client.MixinClientPlayerInteractionManager",
|
"client.MixinClientPlayerInteractionManager",
|
||||||
|
|
Loading…
Reference in a new issue