From 77de42dd09d93511c4ae1a07a22affdc49aa7dc4 Mon Sep 17 00:00:00 2001 From: Sollace Date: Wed, 22 May 2024 21:21:34 +0100 Subject: [PATCH] Split the placed spell into separate types --- .../ability/magic/spell/OrientedSpell.java | 7 +- .../ability/magic/spell/PlaceableSpell.java | 230 +++++------------- .../magic/spell/PlacementControlSpell.java | 165 +++++++++++++ .../unicopia/ability/magic/spell/Spell.java | 4 +- .../magic/spell/effect/PortalSpell.java | 22 +- .../ability/magic/spell/effect/SpellType.java | 2 + .../client/gui/DismissSpellScreen.java | 4 +- .../render/spell/PlacedSpellRenderer.java | 10 +- .../unicopia/command/CastCommand.java | 8 +- .../unicopia/entity/mob/CastSpellEntity.java | 10 +- .../network/MsgCasterLookRequest.java | 7 +- .../unicopia/server/world/Ether.java | 2 +- .../unicopia/util/NbtSerialisable.java | 1 - 13 files changed, 261 insertions(+), 211 deletions(-) create mode 100644 src/main/java/com/minelittlepony/unicopia/ability/magic/spell/PlacementControlSpell.java diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/OrientedSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/OrientedSpell.java index 38d35171..59a05850 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/OrientedSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/OrientedSpell.java @@ -1,11 +1,12 @@ package com.minelittlepony.unicopia.ability.magic.spell; import com.minelittlepony.unicopia.ability.data.Rot; +import com.minelittlepony.unicopia.ability.magic.Caster; public interface OrientedSpell extends Spell { - void setOrientation(float pitch, float yaw); + void setOrientation(Caster caster, float pitch, float yaw); - default void setOrientation(Rot rotation) { - setOrientation(rotation.pitch(), rotation.yaw()); + default void setOrientation(Caster caster, Rot rotation) { + setOrientation(caster, rotation.pitch(), rotation.yaw()); } } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/PlaceableSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/PlaceableSpell.java index 3738f171..83c56ddf 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/PlaceableSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/PlaceableSpell.java @@ -1,28 +1,16 @@ package com.minelittlepony.unicopia.ability.magic.spell; -import java.util.*; - -import org.jetbrains.annotations.Nullable; +import java.util.UUID; import com.minelittlepony.unicopia.ability.magic.Caster; +import com.minelittlepony.unicopia.ability.magic.spell.PlacementControlSpell.PlacementDelegate; import com.minelittlepony.unicopia.ability.magic.spell.effect.CustomisedSpellType; -import com.minelittlepony.unicopia.entity.EntityReference; -import com.minelittlepony.unicopia.entity.EntityReference.EntityValues; -import com.minelittlepony.unicopia.entity.mob.CastSpellEntity; -import com.minelittlepony.unicopia.entity.mob.UEntities; -import com.minelittlepony.unicopia.entity.player.Pony; -import com.minelittlepony.unicopia.network.Channel; -import com.minelittlepony.unicopia.network.MsgCasterLookRequest; +import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType; import com.minelittlepony.unicopia.server.world.Ether; -import com.minelittlepony.unicopia.util.NbtSerialisable; +import net.minecraft.entity.Entity; import net.minecraft.nbt.*; -import net.minecraft.registry.*; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.util.Identifier; import net.minecraft.util.math.MathHelper; -import net.minecraft.util.math.Vec3d; -import net.minecraft.world.World; /** * A spell that can be attached to a specific location in the world. @@ -33,29 +21,8 @@ import net.minecraft.world.World; * When cast two copies of this spell are created. One is attached to the player and is the controlling spell, * the other is attached to a cast spell entity and placed in the world. * - * TODO: Split this up into separate classes. */ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedSpell { - /** - * Dimension the spell was originally cast in - */ - @Nullable - private RegistryKey dimension; - - /** - * ID of the placed counterpart of this spell. - */ - @Nullable - private UUID placedSpellId; - - /** - * The cast spell entity - */ - private final EntityReference castEntity = new EntityReference<>(); - - public float pitch; - public float yaw; - private int prevAge; private int age; @@ -63,15 +30,35 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS private int prevDeathTicks; private int deathTicks; - private Optional position = Optional.empty(); + private UUID controllingEntityUuid; + private UUID controllingSpellUuid; + + public float pitch; + public float yaw; public PlaceableSpell(CustomisedSpellType type) { super(type); } - public PlaceableSpell setSpell(Spell spell) { - delegate.set(spell); - return this; + PlaceableSpell(Caster caster, PlacementControlSpell control, Spell delegate) { + this(SpellType.PLACED_SPELL.withTraits()); + this.controllingEntityUuid = caster.asEntity().getUuid(); + this.controllingSpellUuid = control.getUuid(); + this.delegate.set(delegate); + + if (delegate instanceof PlacementDelegate s) { + s.onPlaced(caster, control); + } + } + + @Override + public boolean apply(Caster caster) { + boolean result = super.apply(caster); + if (result && !caster.isClient()) { + Ether.get(caster.asWorld()).getOrCreate(this, caster); + } + setDirty(); + return result; } public float getAge(float tickDelta) { @@ -86,7 +73,7 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS @Override public boolean isDying() { - return dead && deathTicks > 0; + return dead && deathTicks > 0 || super.isDying(); } @Override @@ -94,6 +81,7 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS super.setDead(); dead = true; deathTicks = 20; + setDirty(); } @Override @@ -103,126 +91,47 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS @Override public boolean tick(Caster source, Situation situation) { - if (situation == Situation.BODY) { - if (!source.isClient()) { - if (dimension == null) { - dimension = source.asWorld().getRegistryKey(); - if (source instanceof Pony) { - Channel.SERVER_REQUEST_PLAYER_LOOK.sendToPlayer(new MsgCasterLookRequest(getUuid()), (ServerPlayerEntity)source.asEntity()); - } - setDirty(); - } - - castEntity.getTarget().ifPresentOrElse( - target -> checkDetachment(source, target), - () -> spawnPlacedEntity(source) - ); - } - - return !isDead(); + if (!source.isClient() && !checkConnection(source)) { + setDead(); + return false; } - if (situation == Situation.GROUND_ENTITY) { - if (!source.isClient()) { - if (Ether.get(source.asWorld()).get(this, source) == null) { - setDead(); - return false; - } - } - - prevAge = age; - if (age < 25) { - age++; - } - - return super.tick(source, Situation.GROUND); + prevAge = age; + if (age < 25) { + age++; } - return !isDead(); + return super.tick(source, Situation.GROUND); + } + + private boolean checkConnection(Caster source) { + return Ether.get(source.asWorld()).get(SpellType.PLACE_CONTROL_SPELL, controllingEntityUuid, controllingSpellUuid) != null; } @Override public void tickDying(Caster caster) { + super.tickDying(caster); prevDeathTicks = deathTicks; deathTicks--; } - private void checkDetachment(Caster source, EntityValues target) { - if (getWorld(source).map(Ether::get).map(ether -> ether.get(getTypeAndTraits().type(), target, placedSpellId)).isEmpty()) { - setDead(); - } - } - - private void spawnPlacedEntity(Caster source) { - CastSpellEntity entity = UEntities.CAST_SPELL.create(source.asWorld()); - Vec3d pos = getPosition().orElse(position.orElse(source.asEntity().getPos())); - entity.updatePositionAndAngles(pos.x, pos.y, pos.z, source.asEntity().getYaw(), source.asEntity().getPitch()); - PlaceableSpell copy = delegate.get().toPlaceable(); - if (delegate.get() instanceof PlacementDelegate delegate) { - delegate.onPlaced(source, copy, entity); - } - entity.getSpellSlot().put(copy); - entity.setCaster(source); - entity.getWorld().spawnEntity(entity); - placedSpellId = copy.getUuid(); - Ether.get(entity.getWorld()).getOrCreate(copy, entity); - - castEntity.set(entity); - setDirty(); - } - - @Override - public void setOrientation(float pitch, float yaw) { - this.pitch = -90 - pitch; - this.yaw = -yaw; - if (delegate.get() instanceof OrientedSpell o) { - o.setOrientation(pitch, yaw); - } - setDirty(); - } - - public void setPosition(Caster source, Vec3d position) { - this.position = Optional.of(position); - this.dimension = source.asWorld().getRegistryKey(); - castEntity.ifPresent(source.asWorld(), entity -> { - entity.updatePositionAndAngles(position.x, position.y, position.z, entity.getYaw(), entity.getPitch()); - }); - if (delegate.get() instanceof PlaceableSpell o) { - o.setPosition(source, position); - } - setDirty(); - } - @Override protected void onDestroyed(Caster source) { if (!source.isClient()) { - castEntity.getTarget().ifPresent(target -> { - getWorld(source).map(Ether::get) - .ifPresent(ether -> ether.remove(getTypeAndTraits().type(), target.uuid())); - }); - castEntity.set(null); - getSpellEntity(source).ifPresent(e -> { - castEntity.set(null); - }); - - if (source.asEntity() instanceof CastSpellEntity) { - Ether.get(source.asWorld()).remove(this, source); - } + Ether.get(source.asWorld()).remove(this, source); } super.onDestroyed(source); } - public Optional getSpellEntity(Caster source) { - return getWorld(source).map(castEntity::get); - } - - public Optional getPosition() { - return castEntity.getTarget().map(EntityValues::pos); - } - - protected Optional getWorld(Caster source) { - return Optional.ofNullable(dimension) - .map(dim -> source.asWorld().getServer().getWorld(dim)); + @Override + public void setOrientation(Caster caster, float pitch, float yaw) { + this.pitch = -pitch - 90; + this.yaw = -yaw; + Entity entity = caster.asEntity(); + entity.updatePositionAndAngles(entity.getX(), entity.getY(), entity.getZ(), this.yaw, this.pitch); + entity.setYaw(this.yaw); + entity.setPitch(this.pitch); + setDirty(); } @Override @@ -233,17 +142,12 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS compound.putInt("age", age); compound.putFloat("pitch", pitch); compound.putFloat("yaw", yaw); - position.ifPresent(pos -> { - compound.put("position", NbtSerialisable.writeVector(pos)); - }); - if (placedSpellId != null) { - compound.putUuid("placedSpellId", placedSpellId); + if (controllingEntityUuid != null) { + compound.putUuid("owningEntity", controllingEntityUuid); } - if (dimension != null) { - compound.putString("dimension", dimension.getValue().toString()); + if (controllingSpellUuid != null) { + compound.putUuid("owningSpell", controllingSpellUuid); } - compound.put("castEntity", castEntity.toNBT()); - } @Override @@ -252,27 +156,9 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS dead = compound.getBoolean("dead"); deathTicks = compound.getInt("deathTicks"); age = compound.getInt("age"); + controllingEntityUuid = compound.containsUuid("owningEntity") ? compound.getUuid("owningEntity") : null; + controllingSpellUuid = compound.containsUuid("owningSpell") ? compound.getUuid("owningSpell") : null; pitch = compound.getFloat("pitch"); yaw = compound.getFloat("yaw"); - position = compound.contains("position") ? Optional.of(NbtSerialisable.readVector(compound.getList("position", NbtElement.FLOAT_TYPE))) : Optional.empty(); - placedSpellId = compound.containsUuid("placedSpellId") ? compound.getUuid("placedSpellId") : null; - if (compound.contains("dimension", NbtElement.STRING_TYPE)) { - Identifier id = Identifier.tryParse(compound.getString("dimension")); - if (id != null) { - dimension = RegistryKey.of(RegistryKeys.WORLD, id); - } - } - if (compound.contains("castEntity")) { - castEntity.fromNBT(compound.getCompound("castEntity")); - } - } - - @Override - public PlaceableSpell toPlaceable() { - return this; - } - - public interface PlacementDelegate { - void onPlaced(Caster source, PlaceableSpell parent, CastSpellEntity entity); } } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/PlacementControlSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/PlacementControlSpell.java new file mode 100644 index 00000000..d54b3e8f --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/PlacementControlSpell.java @@ -0,0 +1,165 @@ +package com.minelittlepony.unicopia.ability.magic.spell; + +import java.util.Optional; +import java.util.UUID; + +import org.jetbrains.annotations.Nullable; +import com.minelittlepony.unicopia.ability.magic.Caster; +import com.minelittlepony.unicopia.ability.magic.SpellPredicate; +import com.minelittlepony.unicopia.ability.magic.spell.effect.CustomisedSpellType; +import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType; +import com.minelittlepony.unicopia.entity.EntityReference; +import com.minelittlepony.unicopia.entity.EntityReference.EntityValues; +import com.minelittlepony.unicopia.entity.mob.CastSpellEntity; +import com.minelittlepony.unicopia.entity.mob.UEntities; +import com.minelittlepony.unicopia.server.world.Ether; +import com.minelittlepony.unicopia.util.NbtSerialisable; + +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtElement; +import net.minecraft.registry.RegistryKey; +import net.minecraft.registry.RegistryKeys; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; + +public class PlacementControlSpell extends AbstractDelegatingSpell implements OrientedSpell { + @Nullable + private UUID placedSpellId; + private final EntityReference castEntity = new EntityReference<>(); + + private Optional> dimension = Optional.empty(); + private Optional position = Optional.empty(); + private Optional orientation = Optional.empty(); + + public PlacementControlSpell(CustomisedSpellType type) { + super(type); + } + + PlacementControlSpell(CustomisedSpellType type, Spell delegate) { + super(type); + this.delegate.set(delegate); + } + + public Optional getPosition() { + return position; + } + + public void setDimension(RegistryKey dimension) { + this.dimension = Optional.of(dimension); + } + + public void setPosition(Vec3d position) { + this.position = Optional.of(position); + } + + @Override + public void setOrientation(Caster caster, float pitch, float yaw) { + this.orientation = Optional.of(new Vec3d(pitch, yaw, 0)); + castEntity.ifPresent(caster.asWorld(), entity -> { + entity.getSpellSlot().stream(SpellPredicate.IS_ORIENTED).forEach(spell -> { + if (!getTypeAndTraits().type().test(spell)) { + spell.setOrientation(caster, pitch, yaw); + } + }); + }); + setDirty(); + } + + @Override + public boolean apply(Caster caster) { + boolean result = super.apply(caster); + if (result) { + if (!caster.isClient()) { + Ether.get(caster.asWorld()).getOrCreate(this, caster); + } + if (dimension.isEmpty()) { + setDimension(caster.asWorld().getRegistryKey()); + } + if (position.isEmpty()) { + setPosition(caster.asEntity().getPos()); + } + } + return result; + } + + @Override + public boolean tick(Caster source, Situation situation) { + if (!source.isClient()) { + Ether.get(source.asWorld()).getOrCreate(this, source); + castEntity.getTarget().ifPresentOrElse(target -> { + if (!checkConnection(source, target)) { + setDead(); + } + }, () -> spawnPlacedEntity(source)); + } + return !isDead(); + } + + private void spawnPlacedEntity(Caster source) { + PlaceableSpell copy = new PlaceableSpell(source, this, getDelegate()); + + Vec3d pos = position.orElse(source.asEntity().getPos()); + Vec3d rot = orientation.orElse(Vec3d.ZERO); + + CastSpellEntity entity = UEntities.CAST_SPELL.create(source.asWorld()); + entity.setCaster(source); + entity.updatePositionAndAngles(pos.x, pos.y, pos.z, (float)rot.y, (float)rot.x); + entity.setYaw((float)rot.y); + entity.setPitch((float)rot.x); + copy.apply(entity); + entity.getWorld().spawnEntity(entity); + + placedSpellId = copy.getUuid(); + castEntity.set(entity); + setDirty(); + } + + private boolean checkConnection(Caster source, EntityValues target) { + return getWorld(source) + .map(Ether::get) + .map(ether -> ether.get(SpellType.PLACED_SPELL, target, placedSpellId)) + .isPresent(); + } + + private Optional getWorld(Caster source) { + return dimension.map(source.asWorld().getServer()::getWorld); + } + + @Override + protected void onDestroyed(Caster source) { + if (!source.isClient()) { + Ether.get(source.asWorld()).remove(this, source); + } + super.onDestroyed(source); + } + + @Override + public void toNBT(NbtCompound compound) { + super.toNBT(compound); + position.ifPresent(pos -> compound.put("position", NbtSerialisable.writeVector(pos))); + orientation.ifPresent(o -> compound.put("orientation", NbtSerialisable.writeVector(o))); + dimension.ifPresent(d -> compound.putString("dimension", d.getValue().toString())); + if (placedSpellId != null) { + compound.putUuid("placedSpellId", placedSpellId); + } + compound.put("castEntity", castEntity.toNBT()); + + } + + @Override + public void fromNBT(NbtCompound compound) { + super.fromNBT(compound); + placedSpellId = compound.containsUuid("placedSpellId") ? compound.getUuid("placedSpellId") : null; + position = compound.contains("position") ? Optional.of(NbtSerialisable.readVector(compound.getList("position", NbtElement.FLOAT_TYPE))) : Optional.empty(); + orientation = compound.contains("orientation") ? Optional.of(NbtSerialisable.readVector(compound.getList("orientation", NbtElement.FLOAT_TYPE))) : Optional.empty(); + if (compound.contains("dimension", NbtElement.STRING_TYPE)) { + dimension = Optional.ofNullable(Identifier.tryParse(compound.getString("dimension"))).map(id -> RegistryKey.of(RegistryKeys.WORLD, id)); + } + castEntity.fromNBT(compound.getCompound("castEntity")); + } + + public interface PlacementDelegate { + void onPlaced(Caster source, PlacementControlSpell parent); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/Spell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/Spell.java index 4258b079..8ede5a8b 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/Spell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/Spell.java @@ -123,8 +123,8 @@ public interface Spell extends NbtSerialisable, Affine { /** * Converts this spell into a placeable spell. */ - default PlaceableSpell toPlaceable() { - return SpellType.PLACED_SPELL.withTraits().create().setSpell(this); + default PlacementControlSpell toPlaceable() { + return new PlacementControlSpell(SpellType.PLACE_CONTROL_SPELL.withTraits(), this); } /** diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/PortalSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/PortalSpell.java index fea666b7..fff35722 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/PortalSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/PortalSpell.java @@ -13,7 +13,9 @@ import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits; import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait; import com.minelittlepony.unicopia.entity.EntityReference; import com.minelittlepony.unicopia.entity.Living; -import com.minelittlepony.unicopia.entity.mob.CastSpellEntity; +import com.minelittlepony.unicopia.entity.player.Pony; +import com.minelittlepony.unicopia.network.Channel; +import com.minelittlepony.unicopia.network.MsgCasterLookRequest; import com.minelittlepony.unicopia.particle.*; import com.minelittlepony.unicopia.server.world.Ether; import com.minelittlepony.unicopia.util.shape.*; @@ -25,13 +27,14 @@ import net.minecraft.entity.LivingEntity; import net.minecraft.nbt.NbtCompound; import net.minecraft.network.packet.s2c.play.PositionFlag; import net.minecraft.particle.ParticleTypes; +import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; import net.minecraft.world.WorldEvents; -public class PortalSpell extends AbstractSpell implements PlaceableSpell.PlacementDelegate, OrientedSpell { +public class PortalSpell extends AbstractSpell implements PlacementControlSpell.PlacementDelegate, OrientedSpell { public static final SpellTraits DEFAULT_TRAITS = new SpellTraits.Builder() .with(Trait.LIFE, 10) .with(Trait.KNOWLEDGE, 1) @@ -91,7 +94,7 @@ public class PortalSpell extends AbstractSpell implements PlaceableSpell.Placeme @Override public boolean apply(Caster caster) { - setOrientation(caster.asEntity().getPitch(), caster.asEntity().getYaw()); + setOrientation(caster, caster.asEntity().getPitch(), caster.asEntity().getYaw()); return toPlaceable().apply(caster); } @@ -195,22 +198,25 @@ public class PortalSpell extends AbstractSpell implements PlaceableSpell.Placeme } @Override - public void setOrientation(float pitch, float yaw) { + public void setOrientation(Caster caster, float pitch, float yaw) { this.pitch = pitch; this.yaw = yaw; particleArea = PARTICLE_AREA.rotate( pitch * MathHelper.RADIANS_PER_DEGREE, - (180 - yaw) * MathHelper.RADIANS_PER_DEGREE + yaw * MathHelper.RADIANS_PER_DEGREE ); setDirty(); } @Override - public void onPlaced(Caster source, PlaceableSpell parent, CastSpellEntity entity) { + public void onPlaced(Caster source, PlacementControlSpell parent) { + parent.setOrientation(source, source.asEntity().getPitch(), source.asEntity().getYaw()); LivingEntity caster = source.getMaster(); Vec3d targetPos = caster.getRotationVector().multiply(3).add(caster.getEyePos()); - parent.setOrientation(pitch, yaw); - entity.setPos(targetPos.x, Math.abs(pitch) > 15 ? targetPos.y : caster.getPos().y, targetPos.z); + parent.setPosition(new Vec3d(targetPos.x, caster.getPos().y, targetPos.z)); + if (source instanceof Pony pony) { + Channel.SERVER_REQUEST_PLAYER_LOOK.sendToPlayer(new MsgCasterLookRequest(parent.getUuid()), (ServerPlayerEntity)pony.asEntity()); + } } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/SpellType.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/SpellType.java index 6bbf0219..c35911d5 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/SpellType.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/SpellType.java @@ -12,6 +12,7 @@ import com.minelittlepony.unicopia.ability.magic.spell.ChangelingFeedingSpell; import com.minelittlepony.unicopia.ability.magic.spell.DispersableDisguiseSpell; import com.minelittlepony.unicopia.ability.magic.spell.RainboomAbilitySpell; import com.minelittlepony.unicopia.ability.magic.spell.PlaceableSpell; +import com.minelittlepony.unicopia.ability.magic.spell.PlacementControlSpell; import com.minelittlepony.unicopia.ability.magic.spell.RageAbilitySpell; import com.minelittlepony.unicopia.ability.magic.spell.Spell; import com.minelittlepony.unicopia.ability.magic.spell.ThrowableSpell; @@ -43,6 +44,7 @@ public final class SpellType implements Affine, SpellPredicate< private static final DynamicCommandExceptionType UNKNOWN_SPELL_TYPE_EXCEPTION = new DynamicCommandExceptionType(id -> Text.translatable("spell_type.unknown", id)); + public static final SpellType PLACE_CONTROL_SPELL = register("place_controller", SpellType.builder(PlacementControlSpell::new).affinity(Affinity.NEUTRAL).unobtainable().stackable().shape(GemstoneItem.Shape.DONUT)); public static final SpellType PLACED_SPELL = register("placed", builder(PlaceableSpell::new).affinity(Affinity.NEUTRAL).unobtainable().stackable().shape(GemstoneItem.Shape.DONUT)); public static final SpellType THROWN_SPELL = register("thrown", builder(ThrowableSpell::new).affinity(Affinity.NEUTRAL).unobtainable().shape(GemstoneItem.Shape.DONUT)); diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/DismissSpellScreen.java b/src/main/java/com/minelittlepony/unicopia/client/gui/DismissSpellScreen.java index 873f7d10..85a5bd85 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/gui/DismissSpellScreen.java +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/DismissSpellScreen.java @@ -40,11 +40,11 @@ public class DismissSpellScreen extends GameGui { double azimuth = 0; double ring = 2; - List placeableSpells = new ArrayList<>(); + List placeableSpells = new ArrayList<>(); for (Spell spell : pony.getSpellSlot().stream().filter(SpellPredicate.IS_VISIBLE).toList()) { - if (spell instanceof PlaceableSpell placeable) { + if (spell instanceof PlacementControlSpell placeable) { if (placeable.getPosition().isPresent()) { placeableSpells.add(placeable); continue; diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/spell/PlacedSpellRenderer.java b/src/main/java/com/minelittlepony/unicopia/client/render/spell/PlacedSpellRenderer.java index f0676140..856064d8 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/render/spell/PlacedSpellRenderer.java +++ b/src/main/java/com/minelittlepony/unicopia/client/render/spell/PlacedSpellRenderer.java @@ -6,7 +6,6 @@ import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.spell.PlaceableSpell; import com.minelittlepony.unicopia.ability.magic.spell.Spell; import com.minelittlepony.unicopia.client.render.model.PlaneModel; -import com.minelittlepony.unicopia.entity.mob.CastSpellEntity; import net.minecraft.client.render.RenderLayer; import net.minecraft.client.render.VertexConsumer; @@ -27,12 +26,7 @@ public class PlacedSpellRenderer extends SpellRenderer { @Override public void render(MatrixStack matrices, VertexConsumerProvider vertices, PlaceableSpell spell, Caster caster, int light, float limbAngle, float limbDistance, float tickDelta, float animationProgress, float headYaw, float headPitch) { - if (!(caster.asEntity() instanceof CastSpellEntity castSpell)) { - return; - } - matrices.push(); - matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(-castSpell.getYaw())); Spell delegate = spell.getDelegate(); @@ -42,8 +36,8 @@ public class PlacedSpellRenderer extends SpellRenderer { matrices.push(); float height = caster.asEntity().getHeight(); matrices.translate(0, (-spell.pitch / 90F) * height * 0.5F, 0); + matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(spell.yaw)); matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(-spell.pitch)); - matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(180 - spell.yaw)); SpellEffectsRenderDispatcher.INSTANCE.render(matrices, vertices, delegate, caster, light, spell.getScale(tickDelta), limbDistance, tickDelta, animationProgress, headYaw, headPitch); matrices.pop(); } @@ -58,8 +52,8 @@ public class PlacedSpellRenderer extends SpellRenderer { float height = caster.asEntity().getHeight(); matrices.translate(0, (-spell.pitch / 90F) * height * 0.5F, 0); + matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(spell.yaw)); matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(-spell.pitch)); - matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(180 - spell.yaw)); matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(90)); float scale = spell.getScale(tickDelta) * 3; diff --git a/src/main/java/com/minelittlepony/unicopia/command/CastCommand.java b/src/main/java/com/minelittlepony/unicopia/command/CastCommand.java index 1983c550..e3c63072 100644 --- a/src/main/java/com/minelittlepony/unicopia/command/CastCommand.java +++ b/src/main/java/com/minelittlepony/unicopia/command/CastCommand.java @@ -4,7 +4,7 @@ import java.util.Optional; import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.spell.CastingMethod; -import com.minelittlepony.unicopia.ability.magic.spell.PlaceableSpell; +import com.minelittlepony.unicopia.ability.magic.spell.PlacementControlSpell; import com.minelittlepony.unicopia.ability.magic.spell.effect.CustomisedSpellType; import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType; import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits; @@ -98,11 +98,11 @@ public class CastCommand { private static int placed(CommandContext source, TraitsFunc traits, Optional position, Vec2f rotation) throws CommandSyntaxException { ServerPlayerEntity player = source.getSource().getPlayerOrThrow(); - PlaceableSpell spell = getSpell(source, traits).create().toPlaceable(); + PlacementControlSpell spell = getSpell(source, traits).create().toPlaceable(); Caster caster = Caster.of(player).orElseThrow(); - spell.setOrientation(rotation.x, rotation.y); - position.ifPresent(pos -> spell.setPosition(caster, pos)); + spell.setOrientation(caster, rotation.x, rotation.y); + position.ifPresent(spell::setPosition); spell.apply(caster); return 0; diff --git a/src/main/java/com/minelittlepony/unicopia/entity/mob/CastSpellEntity.java b/src/main/java/com/minelittlepony/unicopia/entity/mob/CastSpellEntity.java index 01cbf06b..2ae93d61 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/mob/CastSpellEntity.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/mob/CastSpellEntity.java @@ -81,12 +81,10 @@ public class CastSpellEntity extends LightEmittingEntity implements Caster { - spell.setOrientation(rotation); - }); + .ifPresent(spell -> spell.setOrientation(pony, rotation)); } } } diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/Ether.java b/src/main/java/com/minelittlepony/unicopia/server/world/Ether.java index 10110d70..f0982276 100644 --- a/src/main/java/com/minelittlepony/unicopia/server/world/Ether.java +++ b/src/main/java/com/minelittlepony/unicopia/server/world/Ether.java @@ -113,7 +113,7 @@ public class Ether extends PersistentState { @SuppressWarnings("unchecked") @Nullable - private Entry get(SpellType spell, UUID entityId, @Nullable UUID spellId) { + public Entry get(SpellType spell, UUID entityId, @Nullable UUID spellId) { if (spellId == null) { return null; } diff --git a/src/main/java/com/minelittlepony/unicopia/util/NbtSerialisable.java b/src/main/java/com/minelittlepony/unicopia/util/NbtSerialisable.java index 54093f51..1dcf0bba 100644 --- a/src/main/java/com/minelittlepony/unicopia/util/NbtSerialisable.java +++ b/src/main/java/com/minelittlepony/unicopia/util/NbtSerialisable.java @@ -46,7 +46,6 @@ public interface NbtSerialisable { } static Vec3d readVector(NbtList list) { - return new Vec3d(list.getDouble(0), list.getDouble(1), list.getDouble(2)); }