diff --git a/src/main/java/com/minelittlepony/unicopia/ability/UnicornCastingAbility.java b/src/main/java/com/minelittlepony/unicopia/ability/UnicornCastingAbility.java index 3dbc104a..9caff0d3 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/UnicornCastingAbility.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/UnicornCastingAbility.java @@ -1,9 +1,11 @@ package com.minelittlepony.unicopia.ability; +import com.google.common.collect.Streams; import com.minelittlepony.unicopia.Race; import com.minelittlepony.unicopia.ability.data.Hit; import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.magic.spell.ShieldSpell; +import com.minelittlepony.unicopia.magic.spell.SpellRegistry; import com.minelittlepony.unicopia.particles.MagicParticleEffect; /** @@ -39,16 +41,28 @@ public class UnicornCastingAbility implements Ability { @Override public void apply(Pony player, Hit data) { - // XXX: A way for the player to select which effect they want - if (player.getEffect() instanceof ShieldSpell) { - player.setEffect(null); + + if (player.hasEffect()) { + String current = player.getEffect().getName(); + player.setEffect(Streams.stream(player.getOwner().getItemsHand()) + .map(SpellRegistry::getKeyFromStack) + .filter(i -> i != null && !current.equals(i)) + .map(SpellRegistry.instance()::getSpellFromName) + .filter(i -> i != null) + .findFirst() + .orElse(null)); } else { - player.setEffect(new ShieldSpell()); + player.setEffect(Streams.stream(player.getOwner().getItemsHand()) + .map(SpellRegistry.instance()::getSpellFrom) + .filter(i -> i != null) + .findFirst() + .orElseGet(ShieldSpell::new)); } } @Override public void preApply(Pony player, AbilitySlot slot) { + player.getMagicalReserves().addEnergy(3); player.spawnParticles(MagicParticleEffect.UNICORN, 5); } diff --git a/src/main/java/com/minelittlepony/unicopia/client/particle/SphereParticle.java b/src/main/java/com/minelittlepony/unicopia/client/particle/SphereParticle.java index 67f0d930..e36a1b15 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/particle/SphereParticle.java +++ b/src/main/java/com/minelittlepony/unicopia/client/particle/SphereParticle.java @@ -7,7 +7,6 @@ import net.minecraft.client.render.Camera; import net.minecraft.client.render.VertexConsumer; import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.entity.Entity; import net.minecraft.util.math.MathHelper; import net.minecraft.world.World; @@ -15,6 +14,7 @@ import com.minelittlepony.client.render.MagicGlow; import com.minelittlepony.unicopia.client.render.model.SphereModel; import com.minelittlepony.unicopia.magic.Caster; import com.minelittlepony.unicopia.particles.ParticleHandle.Attachment; +import com.minelittlepony.unicopia.particles.ParticleHandle.Link; import com.minelittlepony.unicopia.particles.SphereParticleEffect; import com.minelittlepony.util.Color; @@ -32,7 +32,7 @@ public class SphereParticle extends Particle implements Attachment { protected float lerpIncrement; protected float toRadius; - private Caster caster; + private final Link link = new Link(); private static final SphereModel model = new SphereModel(); @@ -64,7 +64,7 @@ public class SphereParticle extends Particle implements Attachment { @Override public void attach(Caster caster) { setMaxAge(50000); - this.caster = caster; + this.link.attach(caster); } @Override @@ -91,22 +91,14 @@ public class SphereParticle extends Particle implements Attachment { public void tick() { super.tick(); - if (caster != null) { - if (!caster.hasEffect() || caster.getEffect().isDead() || caster.getEntity().removed) { - markDead(); - } else { - Entity e = caster.getEntity(); - - if (caster.getWorld().getEntityById(e.getEntityId()) == null) { - markDead(); - } - + if (link.linked()) { + link.ifAbsent(this::markDead).map(Caster::getEntity).ifPresent(e -> { setPos(e.getX(), e.getY(), e.getZ()); prevPosX = e.lastRenderX; prevPosY = e.lastRenderY; prevPosZ = e.lastRenderZ; - } + }); if (steps-- > 0) { radius += lerpIncrement; diff --git a/src/main/java/com/minelittlepony/unicopia/entity/SpellcastEntity.java b/src/main/java/com/minelittlepony/unicopia/entity/SpellcastEntity.java index fa30f726..9299210b 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/SpellcastEntity.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/SpellcastEntity.java @@ -51,8 +51,6 @@ public class SpellcastEntity extends MobEntityWithAi implements IMagicals, Caste private static final TrackedData EFFECT = DataTracker.registerData(SpellcastEntity.class, TrackedDataHandlerRegistry.TAG_COMPOUND); private static final TrackedData AFFINITY = DataTracker.registerData(SpellcastEntity.class, TrackedDataHandlerRegistry.INTEGER); - private LivingEntity owner = null; - public float hoverStart; private final EffectSync effectDelegate = new EffectSync(this, EFFECT); @@ -151,32 +149,21 @@ public class SpellcastEntity extends MobEntityWithAi implements IMagicals, Caste @Override public void setOwner(LivingEntity owner) { - this.owner = owner; setOwner(owner.getUuid()); } - protected void setOwner(UUID ownerId) { + protected void setOwner(@Nullable UUID ownerId) { dataTracker.set(OWNER, Optional.ofNullable(ownerId)); } - protected String getOwnerName() { - LivingEntity owner = getOwner(); - - if (owner != null) { - return owner.getEntityName(); - } - - return ""; + protected Optional getOwnerId() { + return dataTracker.get(OWNER); } @Nullable @Override public LivingEntity getOwner() { - if (owner == null) { - owner = dataTracker.get(OWNER).map(world::getPlayerByUuid).orElse(null); - } - - return owner; + return getOwnerId().map(world::getPlayerByUuid).orElse(null); } protected void displayTick() { @@ -353,7 +340,9 @@ public class SpellcastEntity extends MobEntityWithAi implements IMagicals, Caste setAffinity(Affinity.of(compound.getString("affinity"))); } - setOwner(compound.getUuid("owner")); + if (compound.containsUuid("owner")) { + setOwner(compound.getUuid("owner")); + } setCurrentLevel(compound.getInt("level")); if (compound.contains("effect")) { @@ -366,8 +355,8 @@ public class SpellcastEntity extends MobEntityWithAi implements IMagicals, Caste super.writeCustomDataToTag(compound); compound.putString("affinity", getAffinity().name()); - compound.putString("owner", getOwnerName()); compound.putInt("level", getCurrentLevel()); + getOwnerId().ifPresent(id -> compound.putUuid("owner", id)); if (hasEffect()) { compound.put("effect", SpellRegistry.instance().serializeEffectToNBT(getEffect())); diff --git a/src/main/java/com/minelittlepony/unicopia/magic/spell/ShieldSpell.java b/src/main/java/com/minelittlepony/unicopia/magic/spell/ShieldSpell.java index 29a98c15..65129332 100644 --- a/src/main/java/com/minelittlepony/unicopia/magic/spell/ShieldSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/magic/spell/ShieldSpell.java @@ -94,7 +94,9 @@ public class ShieldSpell extends AbstractRangedAreaSpell implements AttachedMagi Vec3d origin = source.getOriginVector(); List targets = source.findAllEntitiesInRange(radius) - .filter(entity -> !(ownerIsValid && entity.equals(owner))) + .filter(entity -> !(ownerIsValid && ( + entity.equals(owner) + || (entity instanceof PlayerEntity && owner instanceof PlayerEntity && Pony.equal((PlayerEntity)entity, (PlayerEntity)owner))))) .collect(Collectors.toList()); targets.forEach(i -> { diff --git a/src/main/java/com/minelittlepony/unicopia/particles/ParticleHandle.java b/src/main/java/com/minelittlepony/unicopia/particles/ParticleHandle.java index fbec074a..6d3e5074 100644 --- a/src/main/java/com/minelittlepony/unicopia/particles/ParticleHandle.java +++ b/src/main/java/com/minelittlepony/unicopia/particles/ParticleHandle.java @@ -2,12 +2,13 @@ package com.minelittlepony.unicopia.particles; import java.util.Optional; import java.util.function.Consumer; -import com.minelittlepony.unicopia.magic.Caster; +import com.minelittlepony.unicopia.magic.Caster; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.MinecraftClient; import net.minecraft.client.particle.Particle; +import net.minecraft.entity.Entity; import net.minecraft.particle.ParticleEffect; import net.minecraft.util.math.Vec3d; @@ -34,7 +35,7 @@ public class ParticleHandle { Particle p = MinecraftClient.getInstance().particleManager.addParticle(effect, pos.x, pos.y, pos.z, vel.x, vel.y, vel.z); if (p instanceof Attachment) { - particleEffect = Optional.ofNullable((Attachment)p); + particleEffect = Optional.of((Attachment)p); } } @@ -46,4 +47,34 @@ public class ParticleHandle { void setAttribute(int key, Object value); } + + public static final class Link { + + private Optional> caster = Optional.empty(); + private String effect; + private boolean linked; + + public void attach(Caster caster) { + this.linked = true; + this.caster = Optional.of(caster); + effect = caster.getEffect(false).getName(); + } + + public boolean linked() { + return linked; + } + + public Optional> ifAbsent(Runnable action) { + caster = caster.filter(c -> { + Entity e = c.getEntity(); + + return c.hasEffect() && c.getEffect(false).getName().equals(effect) && e != null && c.getWorld().getEntityById(e.getEntityId()) != null; + }); + if (!caster.isPresent()) { + action.run(); + } + + return caster; + } + } }