mirror of
https://github.com/Sollace/Unicopia.git
synced 2024-11-27 15:17:59 +01:00
Reimplement placed spell rendering to no longer require a particle
This commit is contained in:
parent
81070be4b3
commit
b3a7d338d2
12 changed files with 125 additions and 76 deletions
|
@ -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<World> 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<Vec3d> position = Optional.empty();
|
||||
|
||||
public PlaceableSpell(CustomisedSpellType<?> type) {
|
||||
|
@ -75,15 +70,13 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Spell> 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<Spell> 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<Attachment> 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<World> 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 -> {
|
||||
|
|
|
@ -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<Entity> 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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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()));
|
||||
}
|
||||
|
|
|
@ -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[] {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,8 +11,6 @@ import net.minecraft.screen.PlayerScreenHandler;
|
|||
import net.minecraft.util.Identifier;
|
||||
|
||||
public class CastSpellEntityRenderer extends EntityRenderer<CastSpellEntity> {
|
||||
private final SpellEffectsRenderDispatcher spellRenderDispatcher = new SpellEffectsRenderDispatcher();
|
||||
|
||||
public CastSpellEntityRenderer(EntityRendererFactory.Context ctx) {
|
||||
super(ctx);
|
||||
}
|
||||
|
@ -24,7 +22,7 @@ public class CastSpellEntityRenderer extends EntityRenderer<CastSpellEntity> {
|
|||
|
||||
@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) {
|
||||
|
|
|
@ -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<PlaceableSpell> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -43,10 +43,16 @@ public class SpellEffectsRenderDispatcher implements SynchronousResourceReloader
|
|||
REGISTRY.put(type, rendererFactory);
|
||||
}
|
||||
|
||||
static {
|
||||
register(SpellType.PLACED_SPELL, PlacedSpellRenderer::new);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Map<SpellType<?>, SpellRenderer<?>> renderers = Map.of();
|
||||
private final MinecraftClient client = MinecraftClient.getInstance();
|
||||
|
||||
private SpellEffectsRenderDispatcher() {}
|
||||
|
||||
@Override
|
||||
public Identifier getFabricId() {
|
||||
return ID;
|
||||
|
|
|
@ -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<String, Attachment> loadedEffects = new WeakHashMap<>();
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ public interface UParticles {
|
|||
ParticleType<OrientedBillboardParticleEffect> RAINBOOM_RING = register("rainboom_ring", FabricParticleTypes.complex(OrientedBillboardParticleEffect.FACTORY));
|
||||
DefaultParticleType RAINBOOM_TRAIL = register("rainboom_trail", FabricParticleTypes.simple());
|
||||
|
||||
@Deprecated
|
||||
ParticleType<OrientedBillboardParticleEffect> MAGIC_RUNES = register("magic_runes", FabricParticleTypes.complex(OrientedBillboardParticleEffect.FACTORY));
|
||||
|
||||
DefaultParticleType RAIN_DROPS = register("rain_drops", FabricParticleTypes.simple());
|
||||
|
|
Loading…
Reference in a new issue