From 308cb721cd077210736314b3ad362cfdb36c5477 Mon Sep 17 00:00:00 2001 From: Sollace Date: Sun, 3 Mar 2024 14:07:36 +0000 Subject: [PATCH] Separate the magic beam into its own entity --- .../ability/magic/spell/ThrowableSpell.java | 32 +--- .../magic/spell/effect/CatapultSpell.java | 9 +- .../magic/spell/effect/DarkVortexSpell.java | 5 +- .../magic/spell/effect/DispellEvilSpell.java | 5 +- .../magic/spell/effect/FireBoltSpell.java | 6 +- .../magic/spell/effect/NecromancySpell.java | 8 +- .../entity/MagicBeamEntityRenderer.java | 15 +- .../unicopia/entity/mob/UEntities.java | 3 +- .../unicopia/network/Channel.java | 1 - .../handler/ClientNetworkHandlerImpl.java | 30 --- .../unicopia/projectile/MagicBeamEntity.java | 171 ++++++++++++++++++ .../projectile/MagicProjectileEntity.java | 138 ++------------ 12 files changed, 220 insertions(+), 203 deletions(-) create mode 100644 src/main/java/com/minelittlepony/unicopia/projectile/MagicBeamEntity.java diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/ThrowableSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/ThrowableSpell.java index ddb3a43f..3e60cba0 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/ThrowableSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/ThrowableSpell.java @@ -7,11 +7,7 @@ import java.util.Optional; import com.minelittlepony.unicopia.USounds; import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.spell.effect.CustomisedSpellType; -import com.minelittlepony.unicopia.entity.mob.UEntities; -import com.minelittlepony.unicopia.item.UItems; -import com.minelittlepony.unicopia.projectile.MagicProjectileEntity; - -import net.minecraft.entity.Entity; +import com.minelittlepony.unicopia.projectile.MagicBeamEntity; import net.minecraft.nbt.NbtCompound; import net.minecraft.world.World; @@ -43,7 +39,7 @@ public final class ThrowableSpell extends AbstractDelegatingSpell { * * Returns the resulting projectile entity for customization (or null if on the client). */ - public Optional throwProjectile(Caster caster) { + public Optional throwProjectile(Caster caster) { return throwProjectile(caster, 1); } @@ -52,33 +48,23 @@ public final class ThrowableSpell extends AbstractDelegatingSpell { * * Returns the resulting projectile entity for customization (or null if on the client). */ - public Optional throwProjectile(Caster caster, float divergance) { + public Optional throwProjectile(Caster caster, float divergance) { World world = caster.asWorld(); - Entity entity = caster.asEntity(); - caster.playSound(USounds.SPELL_CAST_SHOOT, 0.7F, 0.4F / (world.random.nextFloat() * 0.4F + 0.8F)); if (caster.isClient()) { return Optional.empty(); } - Spell s = spell.get().prepareForCast(caster, CastingMethod.STORED); - if (s == null) { - return Optional.empty(); - } + return Optional.ofNullable(spell.get().prepareForCast(caster, CastingMethod.STORED)).map(s -> { + MagicBeamEntity projectile = new MagicBeamEntity(world, caster.asEntity(), divergance, s); - MagicProjectileEntity projectile = UEntities.MAGIC_BEAM.create(world); - projectile.setPosition(entity.getX(), entity.getEyeY() - 0.1F, entity.getZ()); - projectile.setOwner(entity); - projectile.setItem(UItems.GEMSTONE.getDefaultStack(spell.get().getType())); - s.apply(projectile); - projectile.setVelocity(entity, entity.getPitch(), entity.getYaw(), 0, 1.5F, divergance); - projectile.setNoGravity(true); - configureProjectile(projectile, caster); - world.spawnEntity(projectile); + configureProjectile(projectile, caster); + world.spawnEntity(projectile); - return Optional.of(projectile); + return projectile; + }); } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/CatapultSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/CatapultSpell.java index c72a69d1..ec5cbf3e 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/CatapultSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/CatapultSpell.java @@ -10,6 +10,7 @@ import com.minelittlepony.unicopia.ability.magic.spell.Situation; import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits; import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait; import com.minelittlepony.unicopia.mixin.MixinFallingBlockEntity; +import com.minelittlepony.unicopia.projectile.MagicBeamEntity; import com.minelittlepony.unicopia.projectile.MagicProjectileEntity; import com.minelittlepony.unicopia.projectile.ProjectileDelegate; @@ -42,15 +43,15 @@ public class CatapultSpell extends AbstractSpell implements ProjectileDelegate.B @Override public void onImpact(MagicProjectileEntity projectile, BlockHitResult hit) { - if (!projectile.isClient() && projectile.canModifyAt(hit.getBlockPos())) { - createBlockEntity(projectile.getWorld(), hit.getBlockPos(), e -> apply(projectile, e)); + if (!projectile.isClient() && projectile instanceof MagicBeamEntity source && source.canModifyAt(hit.getBlockPos())) { + createBlockEntity(projectile.getWorld(), hit.getBlockPos(), e -> apply(source, e)); } } @Override public void onImpact(MagicProjectileEntity projectile, EntityHitResult hit) { - if (!projectile.isClient()) { - apply(projectile, hit.getEntity()); + if (!projectile.isClient() && projectile instanceof MagicBeamEntity source) { + apply(source, hit.getEntity()); } } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DarkVortexSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DarkVortexSpell.java index d21a9c3e..ea5f8462 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DarkVortexSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DarkVortexSpell.java @@ -16,6 +16,7 @@ import com.minelittlepony.unicopia.particle.FollowingParticleEffect; import com.minelittlepony.unicopia.particle.LightningBoltParticleEffect; import com.minelittlepony.unicopia.particle.ParticleUtils; import com.minelittlepony.unicopia.particle.UParticles; +import com.minelittlepony.unicopia.projectile.MagicBeamEntity; import com.minelittlepony.unicopia.projectile.MagicProjectileEntity; import com.minelittlepony.unicopia.projectile.ProjectileDelegate; import com.minelittlepony.unicopia.util.shape.Sphere; @@ -55,10 +56,10 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileDelega @Override public void onImpact(MagicProjectileEntity projectile, BlockHitResult hit) { - if (!projectile.isClient()) { + if (!projectile.isClient() && projectile instanceof MagicBeamEntity source) { BlockPos pos = hit.getBlockPos(); projectile.getWorld().createExplosion(projectile, pos.getX(), pos.getY(), pos.getZ(), 3, ExplosionSourceType.NONE); - toPlaceable().tick(projectile, Situation.BODY); + toPlaceable().tick(source, Situation.BODY); } } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DispellEvilSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DispellEvilSpell.java index 4a488942..869ef51d 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DispellEvilSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DispellEvilSpell.java @@ -5,6 +5,7 @@ import com.minelittlepony.unicopia.ability.magic.spell.*; import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits; import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait; import com.minelittlepony.unicopia.particle.LightningBoltParticleEffect; +import com.minelittlepony.unicopia.projectile.MagicBeamEntity; import com.minelittlepony.unicopia.projectile.MagicProjectileEntity; import com.minelittlepony.unicopia.projectile.ProjectileDelegate; @@ -48,6 +49,8 @@ public class DispellEvilSpell extends AbstractSpell implements ProjectileDelegat @Override public void onImpact(MagicProjectileEntity projectile) { - tick(projectile, Situation.GROUND); + if (projectile instanceof MagicBeamEntity source) { + tick(source, Situation.GROUND); + } } } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/FireBoltSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/FireBoltSpell.java index a76ef43b..db63eaf4 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/FireBoltSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/FireBoltSpell.java @@ -45,13 +45,11 @@ public class FireBoltSpell extends AbstractSpell implements HomingSpell, @Override public boolean tick(Caster caster, Situation situation) { if (situation == Situation.PROJECTILE) { - if (caster instanceof MagicProjectileEntity && getTraits().get(Trait.FOCUS) >= 50) { + if (caster instanceof MagicProjectileEntity projectile && getTraits().get(Trait.FOCUS) >= 50) { caster.findAllEntitiesInRange( getTraits().get(Trait.FOCUS) - 49, EntityPredicates.VALID_LIVING_ENTITY.and(TargetSelecter.validTarget(this, caster)) - ).findFirst().ifPresent(target -> { - ((MagicProjectileEntity)caster).setHomingTarget(target); - }); + ).findFirst().ifPresent(target -> projectile.setHomingTarget(target)); } return true; diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/NecromancySpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/NecromancySpell.java index 56e16c10..1e4243a6 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/NecromancySpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/NecromancySpell.java @@ -12,6 +12,7 @@ import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait; import com.minelittlepony.unicopia.entity.Creature; import com.minelittlepony.unicopia.entity.EntityReference; import com.minelittlepony.unicopia.entity.Equine; +import com.minelittlepony.unicopia.projectile.MagicBeamEntity; import com.minelittlepony.unicopia.projectile.MagicProjectileEntity; import com.minelittlepony.unicopia.projectile.ProjectileDelegate; import com.minelittlepony.unicopia.util.Weighted; @@ -231,9 +232,10 @@ public class NecromancySpell extends AbstractAreaEffectSpell implements Projecti } @Override - public void onImpact(MagicProjectileEntity source, BlockHitResult hit) { - - // source.asWorld().createExplosion(source, hit.getPos().x, hit.getPos().y, hit.getPos().z, 3, ExplosionSourceType.MOB); + public void onImpact(MagicProjectileEntity projectile, BlockHitResult hit) { + if (!(projectile instanceof MagicBeamEntity source)) { + return; + } Shape affectRegion = new Sphere(false, 3); diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/entity/MagicBeamEntityRenderer.java b/src/main/java/com/minelittlepony/unicopia/client/render/entity/MagicBeamEntityRenderer.java index baf37053..26e2297a 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/render/entity/MagicBeamEntityRenderer.java +++ b/src/main/java/com/minelittlepony/unicopia/client/render/entity/MagicBeamEntityRenderer.java @@ -1,8 +1,7 @@ package com.minelittlepony.unicopia.client.render.entity; import com.minelittlepony.unicopia.client.render.RenderLayers; -import com.minelittlepony.unicopia.projectile.MagicProjectileEntity; - +import com.minelittlepony.unicopia.projectile.MagicBeamEntity; import net.minecraft.client.model.Dilation; import net.minecraft.client.model.ModelData; import net.minecraft.client.model.ModelPart; @@ -23,7 +22,7 @@ import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; -public class MagicBeamEntityRenderer extends EntityRenderer { +public class MagicBeamEntityRenderer extends EntityRenderer { private final Model model; public MagicBeamEntityRenderer(EntityRendererFactory.Context ctx) { @@ -32,17 +31,17 @@ public class MagicBeamEntityRenderer extends EntityRenderer { + public class Model extends EntityModel { private final ModelPart part; @@ -89,7 +88,7 @@ public class MagicBeamEntityRenderer extends EntityRenderer MAGIC_BEAM = register("magic_beam", FabricEntityTypeBuilder.create(SpawnGroup.MISC, MagicProjectileEntity::new) + EntityType MAGIC_BEAM = register("magic_beam", FabricEntityTypeBuilder.create(SpawnGroup.MISC, MagicBeamEntity::new) .trackRangeBlocks(100) .trackedUpdateRate(2) .dimensions(EntityDimensions.fixed(0.25F, 0.25F))); diff --git a/src/main/java/com/minelittlepony/unicopia/network/Channel.java b/src/main/java/com/minelittlepony/unicopia/network/Channel.java index d1a6bc19..3f65e69c 100644 --- a/src/main/java/com/minelittlepony/unicopia/network/Channel.java +++ b/src/main/java/com/minelittlepony/unicopia/network/Channel.java @@ -19,7 +19,6 @@ public interface Channel { C2SPacketType FLIGHT_CONTROLS_INPUT = SimpleNetworking.clientToServer(Unicopia.id("flight_controls"), MsgPlayerFlightControlsInput::new); S2CPacketType SERVER_PLAYER_CAPABILITIES = SimpleNetworking.serverToClient(Unicopia.id("player_capabilities"), MsgPlayerCapabilities::new); - S2CPacketType SERVER_SPAWN_PROJECTILE = SimpleNetworking.serverToClient(Unicopia.id("projectile_entity"), MsgSpawnProjectile::new); S2CPacketType SERVER_BLOCK_DESTRUCTION = SimpleNetworking.serverToClient(Unicopia.id("block_destruction"), MsgBlockDestruction::new); S2CPacketType CANCEL_PLAYER_ABILITY = SimpleNetworking.serverToClient(Unicopia.id("player_ability_cancel"), MsgCancelPlayerAbility::read); S2CPacketType SERVER_REQUEST_PLAYER_LOOK = SimpleNetworking.serverToClient(Unicopia.id("request_player_look"), MsgCasterLookRequest::new); diff --git a/src/main/java/com/minelittlepony/unicopia/network/handler/ClientNetworkHandlerImpl.java b/src/main/java/com/minelittlepony/unicopia/network/handler/ClientNetworkHandlerImpl.java index d9b9e07f..e4c97d2e 100644 --- a/src/main/java/com/minelittlepony/unicopia/network/handler/ClientNetworkHandlerImpl.java +++ b/src/main/java/com/minelittlepony/unicopia/network/handler/ClientNetworkHandlerImpl.java @@ -2,8 +2,6 @@ package com.minelittlepony.unicopia.network.handler; import java.util.Map; -import com.minelittlepony.unicopia.InteractionManager; -import com.minelittlepony.unicopia.Owned; import com.minelittlepony.unicopia.USounds; import com.minelittlepony.unicopia.ability.data.Rot; import com.minelittlepony.unicopia.ability.data.tree.TreeTypes; @@ -16,14 +14,11 @@ import com.minelittlepony.unicopia.client.gui.TribeSelectionScreen; import com.minelittlepony.unicopia.client.gui.spellbook.ClientChapters; import com.minelittlepony.unicopia.client.gui.spellbook.SpellbookChapterList.Chapter; import com.minelittlepony.unicopia.diet.PonyDiets; -import com.minelittlepony.unicopia.entity.mob.UEntities; import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.network.*; import com.minelittlepony.unicopia.network.MsgCasterLookRequest.Reply; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.world.ClientWorld; -import net.minecraft.entity.Entity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.util.Identifier; @@ -32,7 +27,6 @@ public class ClientNetworkHandlerImpl { public ClientNetworkHandlerImpl() { Channel.SERVER_SELECT_TRIBE.receiver().addPersistentListener(this::handleTribeScreen); - Channel.SERVER_SPAWN_PROJECTILE.receiver().addPersistentListener(this::handleSpawnProjectile); Channel.SERVER_BLOCK_DESTRUCTION.receiver().addPersistentListener(this::handleBlockDestruction); Channel.CANCEL_PLAYER_ABILITY.receiver().addPersistentListener(this::handleCancelAbility); Channel.UNLOCK_TRAITS.receiver().addPersistentListener(this::handleUnlockTraits); @@ -47,30 +41,6 @@ public class ClientNetworkHandlerImpl { client.setScreen(new TribeSelectionScreen(packet.availableRaces(), packet.serverMessage())); } - @SuppressWarnings("unchecked") - private void handleSpawnProjectile(PlayerEntity sender, MsgSpawnProjectile packet) { - ClientWorld world = client.world; - Entity entity = packet.getEntityType().create(world); - - entity.updateTrackedPosition(packet.getX(), packet.getY(), packet.getZ()); - entity.refreshPositionAfterTeleport(packet.getX(), packet.getY(), packet.getZ()); - entity.setVelocity(packet.getVelocityX(), packet.getVelocityY(), packet.getVelocityZ()); - entity.setPitch(packet.getPitch() * 360 / 256F); - entity.setYaw(packet.getYaw() * 360 / 256F); - entity.setId(packet.getId()); - entity.setUuid(packet.getUuid()); - - if (entity instanceof Owned.Mutable) { - ((Owned.Mutable) entity).setMaster(world.getEntityById(packet.getEntityData())); - } - - if (entity.getType() == UEntities.MAGIC_BEAM) { - InteractionManager.instance().playLoopingSound(entity, InteractionManager.SOUND_MAGIC_BEAM, entity.getId()); - } - - world.addEntity(packet.getId(), entity); - } - private void handleBlockDestruction(PlayerEntity sender, MsgBlockDestruction packet) { ClientBlockDestructionManager destr = ((ClientBlockDestructionManager.Source)client.worldRenderer).getDestructionManager(); diff --git a/src/main/java/com/minelittlepony/unicopia/projectile/MagicBeamEntity.java b/src/main/java/com/minelittlepony/unicopia/projectile/MagicBeamEntity.java new file mode 100644 index 00000000..2de94b7f --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/projectile/MagicBeamEntity.java @@ -0,0 +1,171 @@ +package com.minelittlepony.unicopia.projectile; + +import java.util.Optional; +import java.util.function.Consumer; +import java.util.function.Function; + +import com.minelittlepony.unicopia.Affinity; +import com.minelittlepony.unicopia.InteractionManager; +import com.minelittlepony.unicopia.ability.magic.Affine; +import com.minelittlepony.unicopia.ability.magic.Caster; +import com.minelittlepony.unicopia.ability.magic.Levelled; +import com.minelittlepony.unicopia.ability.magic.SpellContainer; +import com.minelittlepony.unicopia.ability.magic.SpellContainer.Operation; +import com.minelittlepony.unicopia.ability.magic.spell.Situation; +import com.minelittlepony.unicopia.ability.magic.spell.Spell; +import com.minelittlepony.unicopia.block.state.StatePredicate; +import com.minelittlepony.unicopia.entity.EntityPhysics; +import com.minelittlepony.unicopia.entity.MagicImmune; +import com.minelittlepony.unicopia.entity.Physics; +import com.minelittlepony.unicopia.entity.mob.UEntities; +import com.minelittlepony.unicopia.network.datasync.EffectSync; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.data.DataTracker; +import net.minecraft.entity.data.TrackedData; +import net.minecraft.entity.data.TrackedDataHandlerRegistry; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.network.packet.s2c.play.EntitySpawnS2CPacket; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; + +public class MagicBeamEntity extends MagicProjectileEntity implements Caster, MagicImmune { + private static final TrackedData GRAVITY = DataTracker.registerData(MagicBeamEntity.class, TrackedDataHandlerRegistry.FLOAT); + private static final TrackedData HYDROPHOBIC = DataTracker.registerData(MagicBeamEntity.class, TrackedDataHandlerRegistry.BOOLEAN); + private static final TrackedData EFFECT = DataTracker.registerData(MagicBeamEntity.class, TrackedDataHandlerRegistry.NBT_COMPOUND); + + private final EffectSync effectDelegate = new EffectSync(this, EFFECT); + + private final EntityPhysics physics = new EntityPhysics<>(this, GRAVITY); + + public MagicBeamEntity(EntityType type, World world) { + super(type, world); + } + + public MagicBeamEntity(World world, Entity owner, float divergance, Spell spell) { + super(UEntities.MAGIC_BEAM, world); + setPosition(owner.getX(), owner.getEyeY() - 0.1F, owner.getZ()); + setOwner(owner); + setVelocity(owner, owner.getPitch(), owner.getYaw(), 0, 1.5F, divergance); + setNoGravity(true); + spell.apply(this); + } + + @Override + protected void initDataTracker() { + super.initDataTracker(); + getDataTracker().startTracking(GRAVITY, 1F); + getDataTracker().startTracking(HYDROPHOBIC, false); + getDataTracker().startTracking(EFFECT, new NbtCompound()); + } + @Override + public void tick() { + super.tick(); + + if (getOwner() != null) { + effectDelegate.tick(Situation.PROJECTILE); + } + + + if (getHydrophobic()) { + if (StatePredicate.isFluid(getWorld().getBlockState(getBlockPos()))) { + Vec3d vel = getVelocity(); + + double velY = vel.y; + + velY *= -1; + + if (!hasNoGravity()) { + velY += 0.16; + } + + setVelocity(new Vec3d(vel.x, velY, vel.z)); + } + } + } + + public void setHydrophobic() { + getDataTracker().set(HYDROPHOBIC, true); + } + + public boolean getHydrophobic() { + return getDataTracker().get(HYDROPHOBIC); + } + + @Override + public MagicBeamEntity asEntity() { + return this; + } + + @Override + public LevelStore getLevel() { + return getMasterReference().getTarget().map(target -> target.level()).orElse(Levelled.EMPTY); + } + + @Override + public LevelStore getCorruption() { + return getMasterReference().getTarget().map(target -> target.corruption()).orElse(Levelled.EMPTY); + } + + @Override + public Physics getPhysics() { + return physics; + } + + @Override + public Affinity getAffinity() { + return getSpellSlot().get(true).map(Affine::getAffinity).orElse(Affinity.NEUTRAL); + } + + @Override + public SpellContainer getSpellSlot() { + return effectDelegate; + } + + @Override + public boolean subtractEnergyCost(double amount) { + return Caster.of(getMaster()).filter(c -> c.subtractEnergyCost(amount)).isPresent(); + } + + @Override + public void onSpawnPacket(EntitySpawnS2CPacket packet) { + super.onSpawnPacket(packet); + InteractionManager.instance().playLoopingSound(this, InteractionManager.SOUND_MAGIC_BEAM, getId()); + } + + @Override + public void remove(RemovalReason reason) { + super.remove(reason); + getSpellSlot().clear(); + } + + @Override + protected void forEachDelegates(Consumer consumer, Function predicate) { + effectDelegate.tick(spell -> { + Optional.ofNullable(predicate.apply(spell)).ifPresent(consumer); + return Operation.SKIP; + }); + super.forEachDelegates(consumer, predicate); + } + + @Override + public void readCustomDataFromNbt(NbtCompound compound) { + super.readCustomDataFromNbt(compound); + getDataTracker().set(HYDROPHOBIC, compound.getBoolean("hydrophobic")); + physics.fromNBT(compound); + if (compound.contains("effect")) { + getSpellSlot().put(Spell.readNbt(compound.getCompound("effect"))); + } + } + + @Override + public void writeCustomDataToNbt(NbtCompound compound) { + super.writeCustomDataToNbt(compound); + compound.putBoolean("hydrophobic", getHydrophobic()); + physics.toNBT(compound); + getSpellSlot().get(true).ifPresent(effect -> { + compound.put("effect", Spell.writeNbt(effect)); + }); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/projectile/MagicProjectileEntity.java b/src/main/java/com/minelittlepony/unicopia/projectile/MagicProjectileEntity.java index 6ca4cb3c..23c7f67d 100644 --- a/src/main/java/com/minelittlepony/unicopia/projectile/MagicProjectileEntity.java +++ b/src/main/java/com/minelittlepony/unicopia/projectile/MagicProjectileEntity.java @@ -6,28 +6,12 @@ import java.util.function.Function; import org.jetbrains.annotations.Nullable; -import com.minelittlepony.unicopia.Affinity; import com.minelittlepony.unicopia.EquinePredicates; import com.minelittlepony.unicopia.Unicopia; import com.minelittlepony.unicopia.WeaklyOwned; -import com.minelittlepony.unicopia.ability.magic.Affine; -import com.minelittlepony.unicopia.ability.magic.Caster; -import com.minelittlepony.unicopia.ability.magic.Levelled; -import com.minelittlepony.unicopia.ability.magic.SpellContainer; -import com.minelittlepony.unicopia.ability.magic.SpellContainer.Operation; -import com.minelittlepony.unicopia.ability.magic.spell.Situation; -import com.minelittlepony.unicopia.ability.magic.spell.Spell; -import com.minelittlepony.unicopia.block.state.StatePredicate; -import com.minelittlepony.unicopia.entity.EntityPhysics; import com.minelittlepony.unicopia.entity.EntityReference; -import com.minelittlepony.unicopia.entity.MagicImmune; -import com.minelittlepony.unicopia.entity.Physics; import com.minelittlepony.unicopia.entity.mob.UEntities; import com.minelittlepony.unicopia.item.UItems; -import com.minelittlepony.unicopia.network.Channel; -import com.minelittlepony.unicopia.network.MsgSpawnProjectile; -import com.minelittlepony.unicopia.network.datasync.EffectSync; - import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; @@ -40,8 +24,6 @@ import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtElement; -import net.minecraft.network.packet.Packet; -import net.minecraft.network.listener.ClientPlayPacketListener; import net.minecraft.particle.ItemStackParticleEffect; import net.minecraft.particle.ParticleEffect; import net.minecraft.particle.ParticleTypes; @@ -49,32 +31,22 @@ import net.minecraft.predicate.entity.EntityPredicates; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.hit.EntityHitResult; import net.minecraft.util.hit.HitResult; -import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; /** * A generalised version of Mojang's projectile entity class with added support for a custom appearance and water phobia. - * - * Can also carry a spell if needed. */ -public class MagicProjectileEntity extends ThrownItemEntity implements Caster, WeaklyOwned.Mutable, MagicImmune { +public class MagicProjectileEntity extends ThrownItemEntity implements WeaklyOwned.Mutable { private static final TrackedData DAMAGE = DataTracker.registerData(MagicProjectileEntity.class, TrackedDataHandlerRegistry.FLOAT); - private static final TrackedData GRAVITY = DataTracker.registerData(MagicProjectileEntity.class, TrackedDataHandlerRegistry.FLOAT); - private static final TrackedData HYDROPHOBIC = DataTracker.registerData(MagicProjectileEntity.class, TrackedDataHandlerRegistry.BOOLEAN); - private static final TrackedData EFFECT = DataTracker.registerData(MagicProjectileEntity.class, TrackedDataHandlerRegistry.NBT_COMPOUND); public static final byte PROJECTILE_COLLISSION = 3; - private final EffectSync effectDelegate = new EffectSync(this, EFFECT); - - private final EntityPhysics physics = new EntityPhysics<>(this, GRAVITY); - private final EntityReference homingTarget = new EntityReference<>(); private EntityReference owner; private int maxAge = 90; - public MagicProjectileEntity(EntityType type, World world) { + public MagicProjectileEntity(EntityType type, World world) { super(type, world); } @@ -86,27 +58,24 @@ public class MagicProjectileEntity extends ThrownItemEntity implements Caster type, World world, LivingEntity thrower) { + super(type, thrower, world); + } + @Override protected void initDataTracker() { super.initDataTracker(); - getDataTracker().startTracking(GRAVITY, 1F); getDataTracker().startTracking(DAMAGE, 0F); - getDataTracker().startTracking(EFFECT, new NbtCompound()); - getDataTracker().startTracking(HYDROPHOBIC, false); + } + + @Override + public World asWorld() { + return getWorld(); } @Override protected Item getDefaultItem() { - switch (getSpellSlot().get(false).map(Spell::getAffinity).orElse(Affinity.NEUTRAL)) { - case GOOD: return Items.SNOWBALL; - case BAD: return Items.MAGMA_CREAM; - default: return Items.AIR; - } - } - - @Override - public MagicProjectileEntity asEntity() { - return this; + return Items.AIR; } @Override @@ -140,36 +109,6 @@ public class MagicProjectileEntity extends ThrownItemEntity implements Caster target.level()).orElse(Levelled.EMPTY); - } - - @Override - public LevelStore getCorruption() { - return getMasterReference().getTarget().map(target -> target.corruption()).orElse(Levelled.EMPTY); - } - - @Override - public Physics getPhysics() { - return physics; - } - - @Override - public Affinity getAffinity() { - return getSpellSlot().get(true).map(Affine::getAffinity).orElse(Affinity.NEUTRAL); - } - - @Override - public SpellContainer getSpellSlot() { - return effectDelegate; - } - - @Override - public boolean subtractEnergyCost(double amount) { - return Caster.of(getMaster()).filter(c -> c.subtractEnergyCost(amount)).isPresent(); - } - public void addThrowDamage(float damage) { setThrowDamage(getThrowDamage() + damage); } @@ -182,14 +121,6 @@ public class MagicProjectileEntity extends ThrownItemEntity implements Caster { setNoGravity(true); noClip = true; @@ -261,12 +170,8 @@ public class MagicProjectileEntity extends ThrownItemEntity implements Caster { - compound.put("effect", Spell.writeNbt(effect)); - }); } @Override @@ -296,12 +197,6 @@ public class MagicProjectileEntity extends ThrownItemEntity implements Caster void forEachDelegates(Consumer consumer, Function predicate) { - effectDelegate.tick(spell -> { - Optional.ofNullable(predicate.apply(spell)).ifPresent(consumer); - return Operation.SKIP; - }); try { Optional.ofNullable(predicate.apply(getItem().getItem())).ifPresent(consumer); } catch (Throwable t) { Unicopia.LOGGER.error("Error whilst ticking spell on entity {}", getMasterReference(), t); } } - - @Override - public Packet createSpawnPacket() { - return Channel.SERVER_SPAWN_PROJECTILE.toPacket(new MsgSpawnProjectile(this)); - } }