diff --git a/src/main/java/com/minelittlepony/unicopia/entity/behaviour/BlazeBehaviour.java b/src/main/java/com/minelittlepony/unicopia/entity/behaviour/BlazeBehaviour.java new file mode 100644 index 00000000..11d27af7 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/entity/behaviour/BlazeBehaviour.java @@ -0,0 +1,93 @@ +package com.minelittlepony.unicopia.entity.behaviour; + +import com.minelittlepony.unicopia.ability.magic.Caster; +import com.minelittlepony.unicopia.ability.magic.spell.DisguiseSpell; +import com.minelittlepony.unicopia.entity.player.Pony; +import com.minelittlepony.unicopia.mixin.MixinBlazeEntity; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.mob.BlazeEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.projectile.SmallFireballEntity; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.WorldEvents; + +public class BlazeBehaviour extends EntityBehaviour { + @Override + public void update(Caster source, BlazeEntity entity, DisguiseSpell spell) { + super.update(source, entity, spell); + + Entity src = source.getEntity(); + + if (src.isOnGround() || src instanceof PlayerEntity && ((PlayerEntity)src).getAbilities().flying) { + return; + } + + Vec3d vel = src.getVelocity(); + + if (vel.y < 0) { + src.setVelocity(vel.multiply(1, 0.8, 1)); + } + } + + @Override + public void update(Pony player, BlazeEntity entity, DisguiseSpell spell) { + + NbtCompound tag = spell.getDisguise().getOrCreateTag(); + + boolean firing = tag.getBoolean("isFiring"); + int fireballCooldown = tag.getInt("fireballCooldown"); + int fireballsFired = tag.getInt("fireballsFired"); + + if (player.sneakingChanged()) { + boolean sneaking = player.getMaster().isSneaking(); + + if (sneaking) { + firing = true; + fireballCooldown = 60; + } else { + firing = false; + } + } + + if (firing && fireballCooldown <= 0) { + fireballsFired++; + + if (fireballsFired == 1) { + fireballCooldown = 60; + ((MixinBlazeEntity)entity).invokeSetFireActive(true); + } else if (fireballsFired <= 4) { + fireballCooldown = 6; + } else { + fireballCooldown = 100; + fireballsFired = 0; + ((MixinBlazeEntity)entity).invokeSetFireActive(false); + } + + if (fireballsFired > 0) { + if (!entity.isSilent()) { + entity.world.syncWorldEvent((PlayerEntity)null, WorldEvents.BLAZE_SHOOTS, entity.getBlockPos(), 0); + } + + Vec3d rot = player.getEntity().getRotationVec(1); + + for (int i = 0; i < 1; ++i) { + SmallFireballEntity proj = new SmallFireballEntity(entity.world, player.getMaster(), + rot.getX() + entity.getRandom().nextGaussian(), + rot.getY(), + rot.getZ() + entity.getRandom().nextGaussian() + ); + proj.setPosition(proj.getX(), entity.getBodyY(0.5D) + 0.5D, proj.getZ()); + entity.world.spawnEntity(proj); + } + } + } else if (!firing) { + ((MixinBlazeEntity)entity).invokeSetFireActive(false); + } + + tag.putBoolean("isFiring", firing); + tag.putInt("fireballCooldown", fireballCooldown); + tag.putInt("fireballsFired", fireballsFired); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/entity/behaviour/ChickenBehaviour.java b/src/main/java/com/minelittlepony/unicopia/entity/behaviour/ChickenBehaviour.java index 7db0a67b..f8962a87 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/behaviour/ChickenBehaviour.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/behaviour/ChickenBehaviour.java @@ -61,7 +61,7 @@ public class ChickenBehaviour extends EntityBehaviour { Vec3d vel = src.getVelocity(); if (vel.y < 0) { - src.setVelocity(vel.multiply(1, 0.6, 1)); + src.setVelocity(vel.multiply(1, 0.8, 1)); } } diff --git a/src/main/java/com/minelittlepony/unicopia/entity/behaviour/Disguise.java b/src/main/java/com/minelittlepony/unicopia/entity/behaviour/Disguise.java index f51b9233..e0fd8c3d 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/behaviour/Disguise.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/behaviour/Disguise.java @@ -63,6 +63,13 @@ public class Disguise implements NbtSerialisable { private Optional dimensions = Optional.empty(); + /** + * Tag that allows behaviours to store data between ticks. + * This is not serialized, so should only be used for server-side data. + */ + @Nullable + private NbtCompound tag; + @Nullable private NbtCompound entityNbt; @@ -99,6 +106,17 @@ public class Disguise implements NbtSerialisable { return entity != null; } + public NbtCompound getOrCreateTag() { + if (tag == null) { + tag = new NbtCompound(); + } + return tag; + } + + public boolean hasTag() { + return tag != null; + } + public void remove() { attachments.clear(); if (entity != null) { diff --git a/src/main/java/com/minelittlepony/unicopia/entity/behaviour/EntityBehaviour.java b/src/main/java/com/minelittlepony/unicopia/entity/behaviour/EntityBehaviour.java index a234344b..acd0f31f 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/behaviour/EntityBehaviour.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/behaviour/EntityBehaviour.java @@ -193,8 +193,12 @@ public class EntityBehaviour { l.stuckStingerTimer = from.stuckStingerTimer; l.stuckArrowTimer = from.stuckArrowTimer; + // disguise uses our health l.setHealth((from.getHealth() / from.getMaxHealth()) * l.getMaxHealth()); + // we use the disguise's air so changelings disguised as dolphin/axolotl/etc drown on land + from.setAir((l.getAir() / l.getMaxAir()) * from.getMaxAir()); + copyInventory(from, l); } @@ -278,6 +282,7 @@ public class EntityBehaviour { register(CreeperBehaviour::new, EntityType.CREEPER); register(SilverfishBehaviour::new, EntityType.SILVERFISH); register(ChickenBehaviour::new, EntityType.CHICKEN); + register(BlazeBehaviour::new, EntityType.BLAZE); register(MinecartBehaviour::new, EntityType.CHEST_MINECART, EntityType.COMMAND_BLOCK_MINECART, EntityType.FURNACE_MINECART, EntityType.HOPPER_MINECART, EntityType.MINECART, EntityType.SPAWNER_MINECART, EntityType.TNT_MINECART); } } diff --git a/src/main/java/com/minelittlepony/unicopia/entity/behaviour/WaterCreatureBehaviour.java b/src/main/java/com/minelittlepony/unicopia/entity/behaviour/WaterCreatureBehaviour.java new file mode 100644 index 00000000..784c35b2 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/entity/behaviour/WaterCreatureBehaviour.java @@ -0,0 +1,24 @@ +package com.minelittlepony.unicopia.entity.behaviour; + +import com.minelittlepony.unicopia.ability.magic.Caster; +import com.minelittlepony.unicopia.ability.magic.spell.DisguiseSpell; + +import net.minecraft.entity.damage.DamageSource; +import net.minecraft.entity.mob.WaterCreatureEntity; + +public class WaterCreatureBehaviour extends EntityBehaviour { + @Override + public void update(Caster source, WaterCreatureEntity entity, DisguiseSpell spell) { + + if (source.getEntity().isInsideWaterOrBubbleColumn()) { + source.getEntity().setAir(source.getEntity().getAir() - 1); + if (source.getEntity().getAir() == -20) { + source.getEntity().setAir(0); + source.getEntity().damage(DamageSource.DRYOUT, 2); + } + } else { + source.getEntity().setAir(300); + } + + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/MixinBlazeEntity.java b/src/main/java/com/minelittlepony/unicopia/mixin/MixinBlazeEntity.java new file mode 100644 index 00000000..0edf8893 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/mixin/MixinBlazeEntity.java @@ -0,0 +1,12 @@ +package com.minelittlepony.unicopia.mixin; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +import net.minecraft.entity.mob.BlazeEntity; + +@Mixin(BlazeEntity.class) +public interface MixinBlazeEntity { + @Invoker + void invokeSetFireActive(boolean active); +} diff --git a/src/main/resources/unicopia.mixin.json b/src/main/resources/unicopia.mixin.json index d367f811..1d63abe7 100644 --- a/src/main/resources/unicopia.mixin.json +++ b/src/main/resources/unicopia.mixin.json @@ -5,6 +5,7 @@ "refmap": "unicopia.mixin.refmap.json", "compatibilityLevel": "JAVA_16", "mixins": [ + "MixinBlazeEntity", "MixinBlockEntity", "MixinBlockItem", "MixinBrain",