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 082460cf..98095393 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 @@ -13,10 +13,6 @@ 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.particle.OrientedBillboardParticleEffect; -import com.minelittlepony.unicopia.particle.ParticleHandle; -import com.minelittlepony.unicopia.particle.UParticles; -import com.minelittlepony.unicopia.particle.ParticleHandle.Attachment; import com.minelittlepony.unicopia.server.world.Ether; import com.minelittlepony.unicopia.util.NbtSerialisable; @@ -24,6 +20,7 @@ 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; @@ -40,11 +37,6 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS @Nullable private RegistryKey dimension; - /** - * The visual effect - */ - private final ParticleHandle particlEffect = new ParticleHandle(); - /** * ID of the placed counterpart of this spell. */ @@ -64,6 +56,9 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS public float pitch; public float yaw; + private int prevAge; + private int age; + private Optional position = Optional.empty(); public PlaceableSpell(CustomisedSpellType type) { @@ -75,15 +70,13 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS return this; } - @Override - public Collection getDelegates() { - return List.of(spell); + public float getAge(float tickDelta) { + return MathHelper.lerp(tickDelta, prevAge, age); } @Override - public void setDead() { - super.setDead(); - particlEffect.destroy(); + public Collection getDelegates() { + return List.of(spell); } @Override @@ -113,16 +106,13 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS setDead(); return false; } + } else { + prevAge = age; + if (age < 25) { + age++; + } } - if (spell instanceof PlacementDelegate delegate) { - delegate.updatePlacement(source, this); - } - - getParticleEffectAttachment(source).ifPresent(p -> { - p.setAttribute(Attachment.ATTR_COLOR, spell.getType().getColor()); - }); - return super.tick(source, Situation.GROUND); } @@ -200,12 +190,6 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS return castEntity.getTarget().map(EntityValues::pos); } - public Optional getParticleEffectAttachment(Caster source) { - return particlEffect.update(getUuid(), source, spawner -> { - spawner.addParticle(new OrientedBillboardParticleEffect(UParticles.MAGIC_RUNES, pitch + 90, yaw), Vec3d.ZERO, Vec3d.ZERO); - }); - } - protected Optional getWorld(Caster source) { return Optional.ofNullable(dimension) .map(dim -> source.asWorld().getServer().getWorld(dim)); @@ -214,6 +198,7 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS @Override public void toNBT(NbtCompound compound) { super.toNBT(compound); + compound.putInt("age", age); compound.putFloat("pitch", pitch); compound.putFloat("yaw", yaw); position.ifPresent(pos -> { @@ -232,6 +217,7 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS @Override public void fromNBT(NbtCompound compound) { super.fromNBT(compound); + age = compound.getInt("age"); pitch = compound.getFloat("pitch"); yaw = compound.getFloat("yaw"); position = compound.contains("position") ? Optional.of(NbtSerialisable.readVector(compound.getList("position", NbtElement.FLOAT_TYPE))) : Optional.empty(); @@ -264,9 +250,6 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS } public interface PlacementDelegate { - void onPlaced(Caster source, PlaceableSpell parent, CastSpellEntity entity); - - void updatePlacement(Caster source, PlaceableSpell parent); } } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/RainboomAbilitySpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/RainboomAbilitySpell.java index 4bf0d726..d7b7b562 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/RainboomAbilitySpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/RainboomAbilitySpell.java @@ -54,7 +54,7 @@ public class RainboomAbilitySpell extends AbstractSpell { }); if (source.isClient()) { - // source.addParticle(new OrientedBillboardParticleEffect(UParticles.RAINBOOM_RING, source.getPhysics().getMotionAngle()), source.getOriginVector(), Vec3d.ZERO); + //source.addParticle(new OrientedBillboardParticleEffect(UParticles.RAINBOOM_RING, source.getPhysics().getMotionAngle()), source.getOriginVector(), Vec3d.ZERO); } source.findAllEntitiesInRange(RADIUS).forEach(e -> { diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DisplacementSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DisplacementSpell.java index 14d3abf8..a58b77de 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DisplacementSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DisplacementSpell.java @@ -6,8 +6,6 @@ import com.minelittlepony.unicopia.ability.magic.spell.*; import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait; import com.minelittlepony.unicopia.entity.EntityReference; import com.minelittlepony.unicopia.entity.damage.UDamageTypes; -import com.minelittlepony.unicopia.entity.mob.CastSpellEntity; -import com.minelittlepony.unicopia.particle.ParticleHandle.Attachment; import com.minelittlepony.unicopia.projectile.MagicProjectileEntity; import com.minelittlepony.unicopia.projectile.ProjectileDelegate; @@ -16,7 +14,7 @@ import net.minecraft.nbt.NbtCompound; import net.minecraft.util.hit.EntityHitResult; import net.minecraft.util.math.Vec3d; -public class DisplacementSpell extends AbstractSpell implements HomingSpell, PlaceableSpell.PlacementDelegate, ProjectileDelegate.EntityHitListener { +public class DisplacementSpell extends AbstractSpell implements HomingSpell, ProjectileDelegate.EntityHitListener { private final EntityReference target = new EntityReference<>(); @@ -67,19 +65,6 @@ public class DisplacementSpell extends AbstractSpell implements HomingSpell, Pla originator.subtractEnergyCost(destinationPos.distanceTo(sourcePos) / 20F); } - @Override - public void onPlaced(Caster source, PlaceableSpell parent, CastSpellEntity entity) { - - } - - @Override - public void updatePlacement(Caster caster, PlaceableSpell parent) { - parent.getParticleEffectAttachment(caster).ifPresent(attachment -> { - float r = 3 - (1 - ((ticks + 10) / 20F)) * 3; - attachment.setAttribute(Attachment.ATTR_RADIUS, r); - }); - } - private void teleport(Caster source, Entity entity, Vec3d pos, Vec3d vel) { entity.teleport(pos.x, pos.y, pos.z); entity.setVelocity(vel); 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 8b25fbe9..e55f388c 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 @@ -14,7 +14,6 @@ import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait; import com.minelittlepony.unicopia.entity.EntityReference; import com.minelittlepony.unicopia.entity.mob.CastSpellEntity; import com.minelittlepony.unicopia.particle.*; -import com.minelittlepony.unicopia.particle.ParticleHandle.Attachment; import com.minelittlepony.unicopia.server.world.Ether; import com.minelittlepony.unicopia.util.shape.*; @@ -177,14 +176,6 @@ public class PortalSpell extends AbstractSpell implements PlaceableSpell.Placeme entity.setPos(targetPos.x, caster.getY() + 1.5, targetPos.z); } - @Override - public void updatePlacement(Caster source, PlaceableSpell parent) { - parent.getParticleEffectAttachment(source).ifPresent(attachment -> { - attachment.setAttribute(Attachment.ATTR_RADIUS, 2); - attachment.setAttribute(Attachment.ATTR_OPACITY, 0.92F); - }); - } - @Override protected void onDestroyed(Caster caster) { particleEffect.destroy(); diff --git a/src/main/java/com/minelittlepony/unicopia/client/particle/OrientedBillboardParticle.java b/src/main/java/com/minelittlepony/unicopia/client/particle/OrientedBillboardParticle.java index f3f04b23..4c25b465 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/particle/OrientedBillboardParticle.java +++ b/src/main/java/com/minelittlepony/unicopia/client/particle/OrientedBillboardParticle.java @@ -22,7 +22,6 @@ public abstract class OrientedBillboardParticle extends AbstractBillboardParticl fixed = effect.fixed(); if (fixed) { - // Was hamiltonianProduct (CHECK THIS!!) rotation.mul(RotationAxis.POSITIVE_Y.rotationDegrees(effect.pitch())); rotation.mul(RotationAxis.POSITIVE_X.rotationDegrees(180 - effect.yaw())); } diff --git a/src/main/java/com/minelittlepony/unicopia/client/particle/RunesParticle.java b/src/main/java/com/minelittlepony/unicopia/client/particle/RunesParticle.java index 58a8d453..87ee30c2 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/particle/RunesParticle.java +++ b/src/main/java/com/minelittlepony/unicopia/client/particle/RunesParticle.java @@ -20,6 +20,7 @@ import net.minecraft.entity.Entity; import net.minecraft.util.Identifier; import net.minecraft.util.math.*; +@Deprecated public class RunesParticle extends OrientedBillboardParticle implements Attachment { private static final Identifier[] TEXTURES = new Identifier[] { diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/RenderUtil.java b/src/main/java/com/minelittlepony/unicopia/client/render/RenderUtil.java index a126ee28..fc981555 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/render/RenderUtil.java +++ b/src/main/java/com/minelittlepony/unicopia/client/render/RenderUtil.java @@ -1,6 +1,5 @@ package com.minelittlepony.unicopia.client.render; -import org.joml.Matrix4f; import org.joml.Vector3f; import org.joml.Vector4f; @@ -11,7 +10,7 @@ import net.minecraft.client.render.VertexFormats; import net.minecraft.client.util.math.MatrixStack; public class RenderUtil { - private static final Vector4f TEMP_VECTOR = new Vector4f(); + public static final Vector4f TEMP_VECTOR = new Vector4f(); public static final Vertex[] UNIT_FACE = new Vertex[] { new Vertex(new Vector3f(0, 0, 0), 1, 1), new Vertex(new Vector3f(0, 1, 0), 1, 0), @@ -21,21 +20,18 @@ public class RenderUtil { public static void renderFace(MatrixStack matrices, Tessellator te, BufferBuilder buffer, float r, float g, float b, float a, int light) { buffer.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE_COLOR_LIGHT); - - Vertex[] UNIT_FACE = new Vertex[] { - new Vertex(new Vector3f(0, 0, 0), 1, 1), - new Vertex(new Vector3f(0, 1, 0), 1, 0), - new Vertex(new Vector3f(1, 1, 0), 0, 0), - new Vertex(new Vector3f(1, 0, 0), 0, 1) - }; - - Matrix4f transformation = matrices.peek().getPositionMatrix(); for (Vertex vertex : UNIT_FACE) { - transformation.transform(TEMP_VECTOR.set(vertex.position(), 1)); - buffer.vertex(TEMP_VECTOR.x, TEMP_VECTOR.y, TEMP_VECTOR.z).texture(vertex.u(), vertex.v()).color(r, g, b, a).light(light).next(); + Vector4f position = vertex.position(matrices); + buffer.vertex(position.x, position.y, position.z).texture(vertex.u(), vertex.v()).color(r, g, b, a).light(light).next(); } te.draw(); } - record Vertex(Vector3f position, float u, float v) {} + public record Vertex(Vector3f position, float u, float v) { + + public Vector4f position(MatrixStack matrices) { + matrices.peek().getPositionMatrix().transform(TEMP_VECTOR.set(position, 1)); + return TEMP_VECTOR; + } + } } diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/entity/CastSpellEntityRenderer.java b/src/main/java/com/minelittlepony/unicopia/client/render/entity/CastSpellEntityRenderer.java index 7b4fae4e..ece6638b 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/render/entity/CastSpellEntityRenderer.java +++ b/src/main/java/com/minelittlepony/unicopia/client/render/entity/CastSpellEntityRenderer.java @@ -11,8 +11,6 @@ import net.minecraft.screen.PlayerScreenHandler; import net.minecraft.util.Identifier; public class CastSpellEntityRenderer extends EntityRenderer { - private final SpellEffectsRenderDispatcher spellRenderDispatcher = new SpellEffectsRenderDispatcher(); - public CastSpellEntityRenderer(EntityRendererFactory.Context ctx) { super(ctx); } @@ -24,7 +22,7 @@ public class CastSpellEntityRenderer extends EntityRenderer { @Override public void render(CastSpellEntity entity, float yaw, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light) { - spellRenderDispatcher.render(matrices, vertexConsumers, light, entity, 0, 0, tickDelta, getAnimationProgress(entity, tickDelta), yaw, 0); + SpellEffectsRenderDispatcher.INSTANCE.render(matrices, vertexConsumers, light, entity, 0, 0, tickDelta, getAnimationProgress(entity, tickDelta), yaw, 0); } protected float getAnimationProgress(CastSpellEntity entity, float tickDelta) { 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 new file mode 100644 index 00000000..4e293248 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/client/render/spell/PlacedSpellRenderer.java @@ -0,0 +1,88 @@ +package com.minelittlepony.unicopia.client.render.spell; + +import org.joml.Vector3f; +import org.joml.Vector4f; + +import com.minelittlepony.common.util.Color; +import com.minelittlepony.unicopia.Unicopia; +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.RenderUtil; + +import net.minecraft.client.render.RenderLayer; +import net.minecraft.client.render.VertexConsumer; +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.RotationAxis; + +public class PlacedSpellRenderer implements SpellRenderer { + private static final Identifier[] TEXTURES = new Identifier[] { + Unicopia.id("textures/particles/runes_0.png"), + Unicopia.id("textures/particles/runes_1.png"), + Unicopia.id("textures/particles/runes_2.png"), + Unicopia.id("textures/particles/runes_3.png"), + Unicopia.id("textures/particles/runes_4.png"), + Unicopia.id("textures/particles/runes_5.png") + }; + private static final RenderUtil.Vertex[] CORNERS = new RenderUtil.Vertex[]{ + new RenderUtil.Vertex(new Vector3f(-1, -1, 0), 0, 0), + new RenderUtil.Vertex(new Vector3f(-1, 1, 0), 1, 0), + new RenderUtil.Vertex(new Vector3f( 1, 1, 0), 1, 1), + new RenderUtil.Vertex(new Vector3f( 1, -1, 0), 0, 1) + }; + + @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) { + + for (Spell delegate : spell.getDelegates()) { + + matrices.push(); + matrices.translate(0, 0.001, 0); + matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(spell.pitch)); + matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(90 - spell.yaw)); + float scale = (spell.getAge(tickDelta) / 25F) * 3; + matrices.scale(scale, scale, scale); + + float alpha = scale; + + float angle = (animationProgress / 9F) % 360; + + int color = delegate.getType().getColor(); + + float red = Color.r(color); + float green = Color.g(color); + float blue = Color.b(color); + + for (int i = 0; i < TEXTURES.length; i++) { + VertexConsumer buffer = vertices.getBuffer(RenderLayer.getEntityTranslucent(TEXTURES[i])); + + for (int dim = 0; dim < 3; dim++) { + float ringSpeed = (i % 2 == 0 ? i : -1) * i; + + matrices.push(); + matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(angle * ringSpeed)); + matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(angle * ringSpeed * dim)); + matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(angle * ringSpeed * dim)); + renderQuad(buffer, matrices, red, green, blue, alpha / ((float)(dim * 3) + 1), light); + matrices.pop(); + } + } + + matrices.pop(); + + var renderer = SpellEffectsRenderDispatcher.INSTANCE.getRenderer(delegate); + if (renderer != null) { + renderer.render(matrices, vertices, spell, caster, light, limbAngle, limbDistance, tickDelta, animationProgress, headYaw, headPitch); + } + } + } + + protected final void renderQuad(VertexConsumer buffer, MatrixStack matrices, float red, float green, float blue, float alpha, int light) { + for (var corner : CORNERS) { + Vector4f pos = corner.position(matrices); + buffer.vertex(pos.x, pos.y, pos.z, red, green, blue, alpha, corner.u(), corner.v(), 0, light, 1, 1, 1); + } + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/spell/SpellEffectsRenderDispatcher.java b/src/main/java/com/minelittlepony/unicopia/client/render/spell/SpellEffectsRenderDispatcher.java index 7f5d26a8..f44aad5f 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/render/spell/SpellEffectsRenderDispatcher.java +++ b/src/main/java/com/minelittlepony/unicopia/client/render/spell/SpellEffectsRenderDispatcher.java @@ -43,10 +43,16 @@ public class SpellEffectsRenderDispatcher implements SynchronousResourceReloader REGISTRY.put(type, rendererFactory); } + static { + register(SpellType.PLACED_SPELL, PlacedSpellRenderer::new); + } + @Nullable private Map, SpellRenderer> renderers = Map.of(); private final MinecraftClient client = MinecraftClient.getInstance(); + private SpellEffectsRenderDispatcher() {} + @Override public Identifier getFabricId() { return ID; diff --git a/src/main/java/com/minelittlepony/unicopia/particle/ParticleHandle.java b/src/main/java/com/minelittlepony/unicopia/particle/ParticleHandle.java index 1fc12c06..b099f347 100644 --- a/src/main/java/com/minelittlepony/unicopia/particle/ParticleHandle.java +++ b/src/main/java/com/minelittlepony/unicopia/particle/ParticleHandle.java @@ -20,6 +20,7 @@ import net.minecraft.world.World; /** * A connection class for updating and persisting an attached particle effect. */ +@Deprecated public class ParticleHandle { private final Map loadedEffects = new WeakHashMap<>(); diff --git a/src/main/java/com/minelittlepony/unicopia/particle/UParticles.java b/src/main/java/com/minelittlepony/unicopia/particle/UParticles.java index 8d5208f0..186be3e0 100644 --- a/src/main/java/com/minelittlepony/unicopia/particle/UParticles.java +++ b/src/main/java/com/minelittlepony/unicopia/particle/UParticles.java @@ -16,6 +16,7 @@ public interface UParticles { ParticleType RAINBOOM_RING = register("rainboom_ring", FabricParticleTypes.complex(OrientedBillboardParticleEffect.FACTORY)); DefaultParticleType RAINBOOM_TRAIL = register("rainboom_trail", FabricParticleTypes.simple()); + @Deprecated ParticleType MAGIC_RUNES = register("magic_runes", FabricParticleTypes.complex(OrientedBillboardParticleEffect.FACTORY)); DefaultParticleType RAIN_DROPS = register("rain_drops", FabricParticleTypes.simple());