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 e55f388c..9eb227ca 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 @@ -42,8 +42,6 @@ public class PortalSpell extends AbstractSpell implements PlaceableSpell.Placeme private boolean publishedPosition; - private final ParticleHandle particleEffect = new ParticleHandle(); - private float pitch; private float yaw; @@ -53,6 +51,10 @@ public class PortalSpell extends AbstractSpell implements PlaceableSpell.Placeme super(type); } + public boolean isLinked() { + return teleportationTarget.getTarget().isPresent(); + } + @Override public boolean apply(Caster caster) { setOrientation(caster.asEntity().getPitch(), caster.asEntity().getYaw()); @@ -73,17 +75,9 @@ public class PortalSpell extends AbstractSpell implements PlaceableSpell.Placeme source.spawnParticles(origin, particleArea, 5, pos -> { source.addParticle(effect, pos, Vec3d.ZERO); }); - - teleportationTarget.getTarget().ifPresentOrElse(target -> { - particleEffect.update(getUuid(), source, spawner -> { - spawner.addParticle(new SphereParticleEffect(UParticles.DISK, getType().getColor(), 0.8F, 1.8F, new Vec3d(-pitch + 90, -yaw, 0)), source.getOriginVector(), Vec3d.ZERO); - }); - }, () -> { - particleEffect.destroy(); - }); } else { teleportationTarget.getTarget().ifPresent(target -> { - if (Ether.get(source.asWorld()).get(getType(), target, targetPortalId) != null) { + if (Ether.get(source.asWorld()).get(getType(), target, targetPortalId) == null) { Unicopia.LOGGER.debug("Lost sibling, breaking connection to " + target.uuid()); teleportationTarget.set(null); setDirty(); @@ -178,7 +172,6 @@ public class PortalSpell extends AbstractSpell implements PlaceableSpell.Placeme @Override protected void onDestroyed(Caster caster) { - particleEffect.destroy(); Ether ether = Ether.get(caster.asWorld()); ether.remove(getType(), caster); getTarget(caster).ifPresent(e -> e.setTaken(false)); diff --git a/src/main/java/com/minelittlepony/unicopia/client/URenderers.java b/src/main/java/com/minelittlepony/unicopia/client/URenderers.java index 1d91a1d5..dad19f19 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/URenderers.java +++ b/src/main/java/com/minelittlepony/unicopia/client/URenderers.java @@ -63,6 +63,7 @@ import net.minecraft.world.BlockRenderView; public interface URenderers { BlockEntity CHEST_RENDER_ENTITY = new CloudChestBlock.TileData(BlockPos.ORIGIN, UBlocks.CLOUD_CHEST.getDefaultState()); + @SuppressWarnings("unchecked") static void bootstrap() { ParticleFactoryRegistry.getInstance().register(UParticles.UNICORN_MAGIC, createFactory(MagicParticle::new)); ParticleFactoryRegistry.getInstance().register(UParticles.CHANGELING_MAGIC, createFactory(ChangelingMagicParticle::new)); diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/spell/BubbleSpellRenderer.java b/src/main/java/com/minelittlepony/unicopia/client/render/spell/BubbleSpellRenderer.java index d15863b7..48f0dbb9 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/render/spell/BubbleSpellRenderer.java +++ b/src/main/java/com/minelittlepony/unicopia/client/render/spell/BubbleSpellRenderer.java @@ -13,9 +13,11 @@ import net.minecraft.client.util.math.MatrixStack; import net.minecraft.entity.Entity; import net.minecraft.util.math.RotationAxis; -public class BubbleSpellRenderer implements SpellRenderer { +public class BubbleSpellRenderer extends SpellRenderer { @Override public void render(MatrixStack matrices, VertexConsumerProvider vertices, BubbleSpell spell, Caster caster, int light, float limbAngle, float limbDistance, float tickDelta, float animationProgress, float headYaw, float headPitch) { + super.render(matrices, vertices, spell, caster, light, limbAngle, limbDistance, tickDelta, animationProgress, headYaw, headPitch); + matrices.push(); double height = caster.asEntity().getEyeY() - caster.getOriginVector().y; matrices.translate(0, height * 0.5F, 0); diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/spell/DarkVortexSpellRenderer.java b/src/main/java/com/minelittlepony/unicopia/client/render/spell/DarkVortexSpellRenderer.java index 548854ae..2c03bc11 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/render/spell/DarkVortexSpellRenderer.java +++ b/src/main/java/com/minelittlepony/unicopia/client/render/spell/DarkVortexSpellRenderer.java @@ -2,6 +2,7 @@ package com.minelittlepony.unicopia.client.render.spell; import com.minelittlepony.unicopia.Unicopia; import com.minelittlepony.unicopia.ability.magic.Caster; +import com.minelittlepony.unicopia.ability.magic.spell.TimedSpell; import com.minelittlepony.unicopia.ability.magic.spell.effect.DarkVortexSpell; import com.minelittlepony.unicopia.client.render.RenderLayers; import com.minelittlepony.unicopia.client.render.model.PlaneModel; @@ -16,7 +17,7 @@ import net.minecraft.util.Identifier; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.RotationAxis; -public class DarkVortexSpellRenderer implements SpellRenderer { +public class DarkVortexSpellRenderer extends SpellRenderer { private static final Identifier ACCRETION_DISK_TEXTURE = Unicopia.id("textures/spells/dark_vortex/accretion_disk.png"); @@ -29,8 +30,13 @@ public class DarkVortexSpellRenderer implements SpellRenderer { } @Override - public void render(MatrixStack matrices, VertexConsumerProvider vertices, DarkVortexSpell spell, Caster caster, int light, float limbAngle, float limbDistance, float tickDelta, float animationProgress, float headYaw, float headPitch) { + public boolean shouldRenderEffectPass(int pass) { + return pass < 2; + } + @Override + public void render(MatrixStack matrices, VertexConsumerProvider vertices, DarkVortexSpell spell, Caster caster, int light, float limbAngle, float limbDistance, float tickDelta, float animationProgress, float headYaw, float headPitch) { + super.render(matrices, vertices, spell, caster, light, limbAngle, limbDistance, tickDelta, animationProgress, headYaw, headPitch); Entity cameraEntity = MinecraftClient.getInstance().getCameraEntity(); @@ -43,15 +49,12 @@ public class DarkVortexSpellRenderer implements SpellRenderer { SphereModel.SPHERE.render(matrices, vertices.getBuffer(RenderLayers.getSolid()), light, 1, Math.min(radius * 0.6F, absDistance * 0.1F), 0, 0, 0, 1); matrices.push(); - - matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(90)); matrices.multiply(RotationAxis.NEGATIVE_X.rotationDegrees(90 + cameraEntity.getYaw(tickDelta))); matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(-cameraEntity.getPitch(tickDelta))); matrices.scale(0.7F, 1, 1); - float distance = 1F / MathHelper.clamp((absDistance / (radius * 4)), 0.0000001F, 1); distance *= distance; if (absDistance < radius * 4) { @@ -97,4 +100,9 @@ public class DarkVortexSpellRenderer implements SpellRenderer { matrices.pop(); matrices.pop(); } + + @Override + protected void renderCountdown(MatrixStack matrices, TimedSpell spell, 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 index 4630912b..c833c5fd 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 @@ -15,7 +15,7 @@ import net.minecraft.client.util.math.MatrixStack; import net.minecraft.util.Identifier; import net.minecraft.util.math.RotationAxis; -public class PlacedSpellRenderer implements SpellRenderer { +public class PlacedSpellRenderer extends SpellRenderer { private static final Identifier[] TEXTURES = new Identifier[] { Unicopia.id("textures/particles/runes_0.png"), Unicopia.id("textures/particles/runes_1.png"), @@ -27,46 +27,65 @@ public class PlacedSpellRenderer implements 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)) { + if (!(caster.asEntity() instanceof CastSpellEntity castSpell)) { return; } + matrices.push(); + matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(-castSpell.getYaw())); + for (Spell delegate : spell.getDelegates()) { + renderAmbientEffects(matrices, vertices, spell, delegate, caster, light, animationProgress, tickDelta); 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 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)); - PlaneModel.INSTANCE.render(matrices, buffer, light, 0, 1, red, green, blue, scale / ((float)(dim * 3) + 1)); - matrices.pop(); - } - } - - matrices.pop(); - + 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, limbAngle, limbDistance, tickDelta, animationProgress, headYaw, headPitch); + matrices.pop(); } + + matrices.pop(); + } + + protected void renderAmbientEffects(MatrixStack matrices, VertexConsumerProvider vertices, PlaceableSpell spell, Spell delegate, Caster caster, int light, float animationProgress, float tickDelta) { + matrices.push(); + matrices.translate(0, 0.001, 0); + + 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.getAge(tickDelta) / 25F) * 3; + matrices.scale(scale, scale, 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); + + SpellRenderer renderer = SpellEffectsRenderDispatcher.INSTANCE.getRenderer(delegate); + + for (int i = 0; i < TEXTURES.length; i++) { + if (!renderer.shouldRenderEffectPass(i)) { + continue; + } + 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)); + PlaneModel.INSTANCE.render(matrices, buffer, light, 0, 1, red, green, blue, scale / ((float)(dim * 3) + 1)); + matrices.pop(); + } + } + + matrices.pop(); } } diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/spell/PortalSpellRenderer.java b/src/main/java/com/minelittlepony/unicopia/client/render/spell/PortalSpellRenderer.java new file mode 100644 index 00000000..4199c38d --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/client/render/spell/PortalSpellRenderer.java @@ -0,0 +1,51 @@ +package com.minelittlepony.unicopia.client.render.spell; + +import com.minelittlepony.common.util.Color; +import com.minelittlepony.unicopia.ability.magic.Caster; +import com.minelittlepony.unicopia.ability.magic.spell.effect.PortalSpell; +import com.minelittlepony.unicopia.client.render.RenderLayers; +import com.minelittlepony.unicopia.client.render.model.SphereModel; + +import net.minecraft.client.render.VertexConsumer; +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.util.math.RotationAxis; + +public class PortalSpellRenderer extends SpellRenderer { + + @Override + public boolean shouldRenderEffectPass(int pass) { + return pass == 0; + } + + @Override + public void render(MatrixStack matrices, VertexConsumerProvider vertices, PortalSpell spell, Caster caster, int light, float limbAngle, float limbDistance, float tickDelta, float animationProgress, float headYaw, float headPitch) { + super.render(matrices, vertices, spell, caster, light, limbAngle, limbDistance, tickDelta, animationProgress, headYaw, headPitch); + + if (!spell.isLinked()) { + return; + } + + int color = spell.getType().getColor(); + + float red = Color.r(color); + float green = Color.g(color); + float blue = Color.b(color); + + VertexConsumer buffer = vertices.getBuffer(RenderLayers.getEndGateway()); + + double thickness = 0.1; + + matrices.push(); + matrices.translate(0, thickness, 0); + SphereModel.DISK.render(matrices, buffer, light, 0, 2.5F, red, green, blue, 1); + matrices.pop(); + + matrices.push(); + matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(180)); + matrices.translate(0, thickness, 0); + SphereModel.DISK.render(matrices, buffer, light, 0, 2.5F, red, green, blue, 1); + + matrices.pop(); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/spell/ShieldSpellRenderer.java b/src/main/java/com/minelittlepony/unicopia/client/render/spell/ShieldSpellRenderer.java index 55844dd9..8ce41089 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/render/spell/ShieldSpellRenderer.java +++ b/src/main/java/com/minelittlepony/unicopia/client/render/spell/ShieldSpellRenderer.java @@ -12,9 +12,11 @@ import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.util.math.MathHelper; -public class ShieldSpellRenderer implements SpellRenderer { +public class ShieldSpellRenderer extends SpellRenderer { @Override public void render(MatrixStack matrices, VertexConsumerProvider vertices, ShieldSpell spell, Caster caster, int light, float limbAngle, float limbDistance, float tickDelta, float animationProgress, float headYaw, float headPitch) { + super.render(matrices, vertices, spell, caster, light, limbAngle, limbDistance, tickDelta, animationProgress, headYaw, headPitch); + matrices.push(); double height = caster.asEntity().getEyeY() - caster.getOriginVector().y; matrices.translate(0, height, 0); 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 341abe8a..04a7363e 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 @@ -8,19 +8,12 @@ import java.util.stream.Stream; import org.jetbrains.annotations.Nullable; -import com.minelittlepony.unicopia.EquinePredicates; import com.minelittlepony.unicopia.Unicopia; import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.SpellContainer.Operation; import com.minelittlepony.unicopia.ability.magic.spell.Spell; -import com.minelittlepony.unicopia.ability.magic.spell.TimedSpell; import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType; -import com.minelittlepony.unicopia.client.gui.DrawableUtil; import com.minelittlepony.unicopia.entity.Living; -import com.minelittlepony.unicopia.entity.mob.CastSpellEntity; -import com.minelittlepony.unicopia.projectile.MagicProjectileEntity; -import com.minelittlepony.unicopia.util.ColorHelper; - import net.fabricmc.fabric.api.resource.IdentifiableResourceReloadListener; import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer.TextLayerType; @@ -28,7 +21,6 @@ import net.minecraft.client.render.RenderLayer; import net.minecraft.client.render.VertexConsumer; import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.WorldRenderer; -import net.minecraft.client.render.model.json.ModelTransformationMode; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.registry.Registries; import net.minecraft.resource.ResourceManager; @@ -38,7 +30,6 @@ import net.minecraft.util.Colors; import net.minecraft.util.Formatting; import net.minecraft.util.Identifier; import net.minecraft.util.math.Box; -import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.RotationAxis; import net.minecraft.util.math.Vec3d; @@ -56,6 +47,7 @@ public class SpellEffectsRenderDispatcher implements SynchronousResourceReloader register(SpellType.SHIELD, ShieldSpellRenderer::new); register(SpellType.DARK_VORTEX, DarkVortexSpellRenderer::new); register(SpellType.BUBBLE, BubbleSpellRenderer::new); + register(SpellType.PORTAL, PortalSpellRenderer::new); } @Nullable @@ -71,20 +63,16 @@ public class SpellEffectsRenderDispatcher implements SynchronousResourceReloader @SuppressWarnings("unchecked") public SpellRenderer getRenderer(S spell) { - return (SpellRenderer)renderers.get(spell.getType()); + return (SpellRenderer)renderers.getOrDefault(spell.getType(), SpellRenderer.DEFAULT); } public void render(MatrixStack matrices, VertexConsumerProvider vertices, Spell spell, Caster caster, int light, float limbAngle, float limbDistance, float tickDelta, float animationProgress, float headYaw, float headPitch) { var renderer = getRenderer(spell); - if (renderer != null) { + if (renderer != SpellRenderer.DEFAULT) { client.getBufferBuilders().getEntityVertexConsumers().draw(); renderer.render(matrices, vertices, spell, caster, light, limbAngle, limbDistance, tickDelta, animationProgress, headYaw, headPitch); - - if (EquinePredicates.IS_CASTER.test(client.player)) { - renderGemstone(matrices, vertices, spell, caster, light, tickDelta, animationProgress); - } } } @@ -105,38 +93,6 @@ public class SpellEffectsRenderDispatcher implements SynchronousResourceReloader renderers = REGISTRY.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().create())); } - private void renderGemstone(MatrixStack matrices, VertexConsumerProvider vertices, Spell spell, Caster caster, int light, float tickDelta, float animationProgress) { - matrices.push(); - - if (!(caster.asEntity() instanceof MagicProjectileEntity)) { - - float y = -caster.asEntity().getHeight(); - if (caster.asEntity() instanceof CastSpellEntity) { - y = 1F; - } - - matrices.translate(0, y + MathHelper.sin(animationProgress / 3F) * 0.2F, 0); - matrices.push(); - matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(animationProgress)); - - client.getItemRenderer().renderItem(spell.getType().withTraits(spell.getTraits()).getDefaultStack(), ModelTransformationMode.FIXED, light, 0, matrices, vertices, caster.asWorld(), 0); - matrices.pop(); - - if (spell instanceof TimedSpell timed && spell.getType() != SpellType.DARK_VORTEX) { - matrices.multiply(client.getEntityRenderDispatcher().getRotation().invert()); - float radius = 0.6F; - float timeRemaining = timed.getTimer().getPercentTimeRemaining(tickDelta); - - DrawableUtil.drawArc(matrices, radius, radius + 0.3F, 0, DrawableUtil.TAU * timeRemaining, - ColorHelper.lerp(MathHelper.clamp(timeRemaining * 4, 0, 1), 0xFF0000FF, 0xFFFFFFFF), - false - ); - } - } - - matrices.pop(); - } - private void renderSpellDebugInfo(MatrixStack matrices, VertexConsumerProvider vertices, Caster caster, int light) { matrices.push(); matrices.multiply(client.getEntityRenderDispatcher().getRotation()); diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/spell/SpellRenderer.java b/src/main/java/com/minelittlepony/unicopia/client/render/spell/SpellRenderer.java index 8c7e6466..cdaf9f79 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/render/spell/SpellRenderer.java +++ b/src/main/java/com/minelittlepony/unicopia/client/render/spell/SpellRenderer.java @@ -1,11 +1,73 @@ package com.minelittlepony.unicopia.client.render.spell; +import com.minelittlepony.unicopia.EquinePredicates; import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.spell.Spell; +import com.minelittlepony.unicopia.ability.magic.spell.TimedSpell; +import com.minelittlepony.unicopia.client.gui.DrawableUtil; +import com.minelittlepony.unicopia.entity.mob.CastSpellEntity; +import com.minelittlepony.unicopia.projectile.MagicProjectileEntity; +import com.minelittlepony.unicopia.util.ColorHelper; +import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.render.model.json.ModelTransformationMode; import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.RotationAxis; -public interface SpellRenderer { - void render(MatrixStack matrices, VertexConsumerProvider vertices, T spell, Caster caster, int light, float limbAngle, float limbDistance, float tickDelta, float animationProgress, float headYaw, float headPitch); +public class SpellRenderer { + public static final SpellRenderer DEFAULT = new SpellRenderer<>(); + + protected final MinecraftClient client = MinecraftClient.getInstance(); + + public boolean shouldRenderEffectPass(int pass) { + return true; + } + + public void render(MatrixStack matrices, VertexConsumerProvider vertices, T spell, Caster caster, int light, float limbAngle, float limbDistance, float tickDelta, float animationProgress, float headYaw, float headPitch) { + if (caster.asEntity() == client.cameraEntity || (caster.asEntity() instanceof MagicProjectileEntity)) { + return; + } + + if (EquinePredicates.IS_CASTER.test(client.player)) { + renderGemstone(matrices, vertices, spell, caster, light, tickDelta, animationProgress); + } + } + + private void renderGemstone(MatrixStack matrices, VertexConsumerProvider vertices, T spell, Caster caster, int light, float tickDelta, float animationProgress) { + matrices.push(); + + transformGemstone(matrices, vertices, spell, caster, animationProgress); + matrices.push(); + matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(animationProgress)); + + client.getItemRenderer().renderItem(spell.getType().withTraits(spell.getTraits()).getDefaultStack(), ModelTransformationMode.FIXED, light, 0, matrices, vertices, caster.asWorld(), 0); + matrices.pop(); + + if (spell instanceof TimedSpell timed) { + renderCountdown(matrices, timed, tickDelta); + } + + matrices.pop(); + } + + protected void renderCountdown(MatrixStack matrices, TimedSpell spell, float tickDelta) { + matrices.multiply(client.getEntityRenderDispatcher().getRotation().invert()); + float radius = 0.6F; + float timeRemaining = spell.getTimer().getPercentTimeRemaining(tickDelta); + + DrawableUtil.drawArc(matrices, radius, radius + 0.3F, 0, DrawableUtil.TAU * timeRemaining, + ColorHelper.lerp(MathHelper.clamp(timeRemaining * 4, 0, 1), 0xFF0000FF, 0xFFFFFFFF), + false + ); + } + + protected void transformGemstone(MatrixStack matrices, VertexConsumerProvider vertices, T spell, Caster caster, float animationProgress) { + float y = -caster.asEntity().getHeight(); + if (caster.asEntity() instanceof CastSpellEntity) { + y = 1F; + } + matrices.translate(0, y + MathHelper.sin(animationProgress / 3F) * 0.2F, 0); + } } diff --git a/src/main/java/com/minelittlepony/unicopia/entity/mob/UEntities.java b/src/main/java/com/minelittlepony/unicopia/entity/mob/UEntities.java index 49904028..0aa7e069 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/mob/UEntities.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/mob/UEntities.java @@ -41,7 +41,7 @@ public interface UEntities { .dimensions(EntityDimensions.fixed(1, 1))); EntityType CAST_SPELL = register("cast_spell", FabricEntityTypeBuilder.create(SpawnGroup.MISC, CastSpellEntity::new) .trackRangeBlocks(200) - .dimensions(EntityDimensions.fixed(1, 0.4F))); + .dimensions(EntityDimensions.fixed(1, 1))); EntityType TWITTERMITE = register("twittermite", FabricEntityTypeBuilder.create(SpawnGroup.MISC, FairyEntity::new) .trackRangeBlocks(200) .dimensions(EntityDimensions.fixed(0.1F, 0.1F)));