Rewrote particles entirely

This commit is contained in:
Sollace 2019-01-28 19:42:18 +02:00
parent e044b5b5bd
commit 81b7693e34
21 changed files with 179 additions and 249 deletions

View file

@ -1,36 +0,0 @@
package com.minelittlepony.util.render;
import net.minecraft.client.model.ModelBox;
import net.minecraft.client.model.ModelRenderer;
public abstract class Box<T extends ModelRenderer> extends ModelBox {
protected final T parent;
public Box(T renderer, int texU, int texV, float x, float y, float z, int dx, int dy, int dz, float delta) {
super(renderer, texU, texV, x, y, z, dx, dy, dz, delta);
parent = renderer;
}
public Box(T renderer, int texU, int texV, float x, float y, float z, int dx, int dy, int dz, float delta, boolean mirror) {
super(renderer, texU, texV, x, y, z, dx, dy, dz, delta, mirror);
parent = renderer;
}
/**
* Creates a new vertex mapping the given (x, y, z) coordinates to a texture offset.
*/
protected Vertex vert(float x, float y, float z, int texX, int texY) {
return new Vertex(x, y, z, texX, texY);
}
/**
* Creates a new quad with the given spacial vertices.
*/
protected Quad quad(int startX, int width, int startY, int height, Vertex ...verts) {
return new Quad(verts,
startX, startY,
startX + width, startY + height,
parent.textureWidth, parent.textureHeight);
}
}

View file

@ -1,37 +0,0 @@
package com.minelittlepony.util.render;
import net.minecraft.client.model.TexturedQuad;
public class Quad extends TexturedQuad {
Quad(Vertex[] vertices, int texcoordU1, int texcoordV1, int texcoordU2, int texcoordV2, float textureWidth, float textureHeight) {
super(vertices, texcoordU1, texcoordV1, texcoordU2, texcoordV2, textureWidth, textureHeight);
}
/**
* Reverses the order of the vertices belonging to this quad.
* Positions of the vertices stay the same but the order of rendering is reversed to go counter-clockwise.
*
* Reversal also affects the cross-product used to calculate texture orientation.
* <pre>
* Normal:
* 0-----1
* |\ |
* | \ |
* | \|
* 3-----2
*
* After flipFace:
*
* 3-----2
* | /|
* | / |
* |/ |
* 0-----1
* </pre>
*/
@Override
public void flipFace() {
super.flipFace();
}
}

View file

@ -1,21 +0,0 @@
package com.minelittlepony.util.render;
import net.minecraft.client.model.PositionTextureVertex;
public class Vertex extends PositionTextureVertex {
public Vertex(float x, float y, float z, float texX, float texY) {
super(x, y, z, texX, texY);
}
private Vertex(Vertex old, float texX, float texY) {
super(old, texX, texY);
}
// The MCP name is misleading.
// This is meant to return a COPY with the given texture position
@Override
public Vertex setTexturePosition(float texX, float texY) {
return new Vertex(this, texX, texY);
}
}

View file

@ -0,0 +1,16 @@
package com.minelittlepony.unicopia;
import com.minelittlepony.unicopia.particle.Particles;
import com.minelittlepony.unicopia.particle.client.EntityMagicFX;
import com.minelittlepony.unicopia.particle.client.EntityRaindropFX;
public class UParticles {
public static int MAGIC_PARTICLE;
public static int RAIN_PARTICLE;
static void init() {
MAGIC_PARTICLE = Particles.instance().registerParticle(EntityMagicFX::new);
RAIN_PARTICLE = Particles.instance().registerParticle(EntityRaindropFX::new);
}
}

View file

@ -51,9 +51,6 @@ import com.minelittlepony.jumpingcastle.api.JumpingCastle;
import com.minelittlepony.jumpingcastle.api.Target;
import com.minelittlepony.unicopia.advancements.UAdvancements;
import com.minelittlepony.unicopia.block.ITillable;
import com.minelittlepony.unicopia.client.particle.EntityMagicFX;
import com.minelittlepony.unicopia.client.particle.EntityRaindropFX;
import com.minelittlepony.unicopia.client.particle.Particles;
import com.minelittlepony.unicopia.command.Commands;
import com.minelittlepony.unicopia.enchanting.SpellRecipe;
import com.minelittlepony.unicopia.forgebullshit.FBS;
@ -85,9 +82,6 @@ public class Unicopia implements IGuiHandler {
public static IChannel channel;
public static int MAGIC_PARTICLE;
public static int RAIN_PARTICLE;
/**
* The race preferred by the client - as determined by mine little pony.
* Human if minelp was not installed.
@ -106,6 +100,7 @@ public class Unicopia implements IGuiHandler {
if (UClient.isClientSide()) {
UEntities.preInit();
UParticles.init();
}
}
@ -131,11 +126,6 @@ public class Unicopia implements IGuiHandler {
.listenFor(MsgPlayerCapabilities.class)
.listenFor(MsgPlayerAbility.class);
if (event.getSide().isClient()) {
MAGIC_PARTICLE = Particles.instance().registerParticle(new EntityMagicFX.Factory());
RAIN_PARTICLE = Particles.instance().registerParticle(new EntityRaindropFX.Factory());
}
PowersRegistry.instance().init();
UAdvancements.init();

View file

@ -1,96 +0,0 @@
package com.minelittlepony.unicopia.client.particle;
import java.util.ArrayList;
import java.util.List;
import net.minecraft.client.Minecraft;
import net.minecraft.client.particle.IParticleFactory;
import net.minecraft.client.particle.Particle;
import net.minecraft.entity.Entity;
import net.minecraft.util.math.Vec3d;
public class Particles {
private static final Particles instance = new Particles();
public static Particles instance() {
return instance;
}
private final Minecraft mc = Minecraft.getMinecraft();
private final List<IParticleFactory> registeredParticles = new ArrayList<>();
private final EntityParticleEmitter entityEmitter = new EntityParticleEmitter();
public EntityParticleEmitter getEntityEmitter() {
return entityEmitter;
}
public int registerParticle(IParticleFactory factory) {
int id = registeredParticles.size();
registeredParticles.add(factory);
return -id - 1;
}
public Particle spawnParticle(int particleId, boolean ignoreDistance, Vec3d pos, double speedX, double speedY, double speedZ, int ...pars) {
return spawnParticle(particleId, ignoreDistance, pos.x, pos.y, pos.z, speedX, speedY, speedZ, pars);
}
public Particle spawnParticle(int particleId, boolean ignoreDistance, double posX, double posY, double posZ, double speedX, double speedY, double speedZ, int ...pars) {
Entity entity = mc.getRenderViewEntity();
if (entity == null && mc.effectRenderer == null) {
return null;
}
double dX = entity.posX - posX;
double dY = entity.posY - posY;
double dZ = entity.posZ - posZ;
double distance = dX * dX + dY * dY + dZ * dZ;
if (ignoreDistance || (distance <= 1024 && calculateParticleLevel(false) < 2)) {
return spawnEffectParticle(particleId, posX, posY, posZ, speedX, speedY, speedZ, pars);
}
return null;
}
private Particle spawnEffectParticle(int particleId, double posX, double posY, double posZ, double speedX, double speedY, double speedZ, int ...pars) {
if (particleId >= 0) {
// Not ours, delegate to mojang
return mc.effectRenderer.spawnEffectParticle(particleId, posX, posY, posZ, speedX, speedY, speedZ, pars);
}
particleId ++;
IParticleFactory iparticlefactory = registeredParticles.get(-particleId);
if (iparticlefactory == null) {
return null;
}
Particle particle = iparticlefactory.createParticle(particleId, mc.world, posX, posY, posZ, speedX, speedY, speedZ, pars);
if (particle == null) {
return null;
}
mc.effectRenderer.addEffect(particle);
return particle;
}
private int calculateParticleLevel(boolean minimiseLevel) {
int level = mc.gameSettings.particleSetting;
if (minimiseLevel && level == 2 && mc.world.rand.nextInt(10) == 0) {
level = 1;
}
if (level == 1 && mc.world.rand.nextInt(3) == 0) {
level = 2;
}
return level;
}
}

View file

@ -6,8 +6,8 @@ import java.util.Random;
import com.minelittlepony.unicopia.Predicates;
import com.minelittlepony.unicopia.UBlocks;
import com.minelittlepony.unicopia.UItems;
import com.minelittlepony.unicopia.Unicopia;
import com.minelittlepony.unicopia.client.particle.Particles;
import com.minelittlepony.unicopia.UParticles;
import com.minelittlepony.unicopia.particle.Particles;
import com.minelittlepony.unicopia.player.PlayerSpeciesList;
import net.minecraft.block.BlockCrops;
import net.minecraft.block.BlockFarmland;
@ -185,7 +185,7 @@ public class EntityCloud extends EntityFlying implements IAnimals {
double y = getEntityBoundingBox().minY + height/2;
double z = posZ + randomIn(rand, boundingbox.minX, boundingbox.maxX) - width / 2;
int particleId = canSnowHere(new BlockPos(x, y, z)) ? EnumParticleTypes.SNOW_SHOVEL.getParticleID() : Unicopia.RAIN_PARTICLE;
int particleId = canSnowHere(new BlockPos(x, y, z)) ? EnumParticleTypes.SNOW_SHOVEL.getParticleID() : UParticles.RAIN_PARTICLE;
Particles.instance().spawnParticle(particleId, false, x, y, z, 0, 0, 0);
}

View file

@ -1,4 +1,4 @@
package com.minelittlepony.unicopia.client.particle;
package com.minelittlepony.unicopia.particle;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
@ -17,7 +17,7 @@ public class EntityParticleEmitter {
double x = MathHelper.nextDouble(e.getEntityWorld().rand, e.posX - e.width/2 - f, e.posX + e.width/2 + f);
double y = MathHelper.nextDouble(e.getEntityWorld().rand, e.posY - f, e.posY + e.height + f);
double z = MathHelper.nextDouble(e.getEntityWorld().rand, e.posZ - e.width/2 - f, e.posZ + e.width/2 + f);
spawnDigginFX(e.getEntityWorld(), x, y, z, x - (int)x - 0.5, y - (int)y - 0.5, z - (int)z - 0.5, blockState, 1, 1);
spawnDiggingFX(e.getEntityWorld(), x, y, z, x - (int)x - 0.5, y - (int)y - 0.5, z - (int)z - 0.5, blockState, 1, 1);
}
}
@ -60,10 +60,10 @@ public class EntityParticleEmitter {
vX += 0.5;
}
spawnDigginFX(e.getEntityWorld(), x, y, z, vX, vY, vZ, blockState, 0.2F, 0.6F);
spawnDiggingFX(e.getEntityWorld(), x, y, z, vX, vY, vZ, blockState, 0.2F, 0.6F);
}
protected void spawnDigginFX(World w, double x, double y, double z, double vX, double vY, double vZ, IBlockState blockState, float multScale, float multVel) {
protected void spawnDiggingFX(World w, double x, double y, double z, double vX, double vY, double vZ, IBlockState blockState, float multScale, float multVel) {
if (w instanceof WorldServer) {
((WorldServer)w).spawnParticle(EnumParticleTypes.BLOCK_CRACK, false, x, y, z, 1, 0, 0, 0, Math.sqrt(vX * vX + vY * vY + vZ * vZ) * multVel, Block.getStateId(blockState));
}

View file

@ -0,0 +1,63 @@
package com.minelittlepony.unicopia.particle;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import com.minelittlepony.unicopia.UClient;
import com.minelittlepony.unicopia.particle.client.ParticlesClient;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
public class Particles<Particle> {
private static Particles<?> instance;
@SuppressWarnings("unchecked")
public static <T> Particles<T> instance() {
if (instance == null) {
if (UClient.isClientSide()) {
instance = new ParticlesClient();
} else {
instance = new Particles<>();
}
}
return (Particles<T>)instance;
}
protected final List<IFactory<Particle>> registeredParticles = new ArrayList<>();
private final EntityParticleEmitter entityEmitter = new EntityParticleEmitter();
public EntityParticleEmitter getEntityEmitter() {
return entityEmitter;
}
public int registerParticle(IFactory<Particle> factory) {
int id = registeredParticles.size();
registeredParticles.add(factory);
return -id - 1;
}
@Nullable
public void spawnParticle(int particleId, boolean ignoreDistance, Vec3d pos, double speedX, double speedY, double speedZ, int ...pars) {
spawnParticle(particleId, ignoreDistance, pos.x, pos.y, pos.z, speedX, speedY, speedZ, pars);
}
@Nullable
public void spawnParticle(int particleId, boolean ignoreDistance, double posX, double posY, double posZ, double speedX, double speedY, double speedZ, int ...pars) {
/* noop */
/* or network */
/* i don't know */
/* ... */
/* maybe later */
}
public static interface IFactory<T> {
@Nonnull
T createParticle(int id, World world, double x, double y, double z, double dx, double dy, double dz, int... args);
}
}

View file

@ -1,8 +1,7 @@
package com.minelittlepony.unicopia.client.particle;
package com.minelittlepony.unicopia.particle.client;
import net.minecraft.client.particle.Particle;
import net.minecraft.client.particle.IParticleFactory;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.entity.Entity;
import net.minecraft.world.World;
@ -13,6 +12,10 @@ public class EntityMagicFX extends Particle {
private double portalPosY;
private double portalPosZ;
public EntityMagicFX(int id, World w, double x, double y, double z, double vX, double vY, double vZ, int... args) {
this(w, x, y, z, vX, vY, vZ);
}
public EntityMagicFX(World w, double x, double y, double z, double vX, double vY, double vZ) {
super(w, x, y, z, vX, vY, vZ);
motionX = vX;
@ -70,11 +73,4 @@ public class EntityMagicFX extends Particle {
posZ = portalPosZ + motionZ * var1;
if (particleAge++ >= particleMaxAge) setExpired();
}
public static class Factory implements IParticleFactory {
@Override
public Particle createParticle(int id, World w, double x, double y, double z, double vX, double vY, double vZ, int... args) {
return new EntityMagicFX(w, x, y, z, vX, vY, vZ);
}
}
}

View file

@ -1,4 +1,4 @@
package com.minelittlepony.unicopia.client.particle;
package com.minelittlepony.unicopia.particle.client;
import net.minecraft.client.particle.IParticleFactory;
import net.minecraft.client.particle.Particle;
@ -7,6 +7,10 @@ import net.minecraft.world.World;
public class EntityRaindropFX extends ParticleRain {
public EntityRaindropFX(int id, World w, double x, double y, double z, double vX, double vY, double vZ, int... args) {
this(w, x, y, z);
}
public EntityRaindropFX(World w, double x, double y, double z) {
super(w, x, y, z);
motionY = -0.1;

View file

@ -0,0 +1,62 @@
package com.minelittlepony.unicopia.particle.client;
import javax.annotation.Nullable;
import com.minelittlepony.unicopia.particle.Particles;
import net.minecraft.client.Minecraft;
import net.minecraft.client.particle.Particle;
import net.minecraft.entity.Entity;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
@SideOnly(Side.CLIENT)
public class ParticlesClient extends Particles<Particle> {
static final int PARTICLES_ALL = 0;
static final int PARTICLES_DECREASED = 1;
static final int PARTICLES_MINIMAL = 2;
private final Minecraft mc = Minecraft.getMinecraft();
@Override
public void spawnParticle(int particleId, boolean ignoreDistance, double posX, double posY, double posZ, double speedX, double speedY, double speedZ, int ...pars) {
Entity entity = mc.getRenderViewEntity();
if (entity == null && mc.effectRenderer == null) {
return;
}
if (ignoreDistance || (entity.getDistanceSq(posX, posY, posZ) <= 1024 && calculateParticleLevel(false) < 2)) {
spawnEffectParticle(particleId, posX, posY, posZ, speedX, speedY, speedZ, pars);
}
}
@Nullable
private void spawnEffectParticle(int particleId, double posX, double posY, double posZ, double speedX, double speedY, double speedZ, int ...pars) {
if (particleId >= 0) {
// Not ours, delegate to mojang
mc.effectRenderer.spawnEffectParticle(particleId, posX, posY, posZ, speedX, speedY, speedZ, pars);
} else {
IFactory<Particle> factory = registeredParticles.get(-(particleId + 1));
if (factory != null) {
mc.effectRenderer.addEffect(factory.createParticle(particleId, mc.world, posX, posY, posZ, speedX, speedY, speedZ, pars));
}
}
}
private int calculateParticleLevel(boolean minimiseLevel) {
int level = mc.gameSettings.particleSetting;
if (minimiseLevel && level == PARTICLES_MINIMAL && mc.world.rand.nextInt(10) == PARTICLES_ALL) {
level = PARTICLES_DECREASED;
}
if (level == PARTICLES_DECREASED && mc.world.rand.nextInt(3) == PARTICLES_ALL) {
level = PARTICLES_MINIMAL;
}
return level;
}
}

View file

@ -1,8 +1,8 @@
package com.minelittlepony.unicopia.power;
import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.client.particle.Particles;
import com.minelittlepony.unicopia.input.IKeyBind;
import com.minelittlepony.unicopia.particle.Particles;
import com.minelittlepony.unicopia.player.IPlayer;
import com.minelittlepony.util.shape.IShape;
import com.minelittlepony.util.shape.Sphere;

View file

@ -5,7 +5,7 @@ import java.util.List;
import org.lwjgl.input.Keyboard;
import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.client.particle.Particles;
import com.minelittlepony.unicopia.particle.Particles;
import com.minelittlepony.unicopia.player.IPlayer;
import com.minelittlepony.unicopia.power.data.Hit;
import com.minelittlepony.util.MagicalDamageSource;

View file

@ -3,7 +3,7 @@ package com.minelittlepony.unicopia.power;
import org.lwjgl.input.Keyboard;
import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.Unicopia;
import com.minelittlepony.unicopia.UParticles;
import com.minelittlepony.unicopia.player.IPlayer;
import com.minelittlepony.unicopia.power.data.Location;
import com.minelittlepony.util.vector.VecHelper;
@ -104,7 +104,7 @@ public class PowerGrow implements IPower<Location> {
player.addExertion(3);
if (player.getWorld().isRemote) {
IPower.spawnParticles(Unicopia.MAGIC_PARTICLE, player, 1);
IPower.spawnParticles(UParticles.MAGIC_PARTICLE, player, 1);
}
}

View file

@ -9,7 +9,7 @@ import org.lwjgl.input.Keyboard;
import com.google.gson.annotations.Expose;
import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.UItems;
import com.minelittlepony.unicopia.client.particle.Particles;
import com.minelittlepony.unicopia.particle.Particles;
import com.minelittlepony.unicopia.player.IPlayer;
import com.minelittlepony.unicopia.player.PlayerSpeciesList;
import com.minelittlepony.unicopia.power.data.Location;

View file

@ -3,7 +3,7 @@ package com.minelittlepony.unicopia.power;
import org.lwjgl.input.Keyboard;
import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.Unicopia;
import com.minelittlepony.unicopia.UParticles;
import com.minelittlepony.unicopia.player.IPlayer;
import com.minelittlepony.unicopia.power.data.Location;
import com.minelittlepony.util.vector.VecHelper;
@ -157,15 +157,11 @@ public class PowerTeleport implements IPower<Location> {
public void preApply(IPlayer player) {
player.addExertion(3);
if (player.getWorld().isRemote) {
IPower.spawnParticles(Unicopia.MAGIC_PARTICLE, player, 5);
}
IPower.spawnParticles(UParticles.MAGIC_PARTICLE, player, 5);
}
@Override
public void postApply(IPlayer player) {
if (player.getWorld().isRemote) {
IPower.spawnParticles(Unicopia.MAGIC_PARTICLE, player, 5);
}
IPower.spawnParticles(UParticles.MAGIC_PARTICLE, player, 5);
}
}

View file

@ -1,13 +1,12 @@
package com.minelittlepony.unicopia.spell;
import java.util.List;
import java.util.Random;
import java.util.UUID;
import java.util.stream.Collectors;
import com.minelittlepony.unicopia.Unicopia;
import com.minelittlepony.unicopia.client.particle.Particles;
import com.minelittlepony.unicopia.UParticles;
import com.minelittlepony.unicopia.entity.EntitySpell;
import com.minelittlepony.unicopia.particle.Particles;
import com.minelittlepony.util.shape.IShape;
import com.minelittlepony.util.shape.Line;
@ -45,18 +44,12 @@ public class SpellCharge extends AbstractSpell {
if (target != null) {
Vec3d start = source.getEntity().getPositionVector();
Vec3d end = target.getPositionVector();
IShape line = new Line(start, end);
IShape line = new Line(start, target.getPositionVector());
Random rand = source.getWorld().rand;
for (int i = 0; i < line.getVolumeOfSpawnableSpace(); i++) {
Vec3d pos = line.computePoint(rand);
Particles.instance().spawnParticle(Unicopia.MAGIC_PARTICLE, false,
pos.x + start.x, pos.y + start.y, pos.z + start.z,
0, 0, 0);
}
source.spawnParticles(line, (int)line.getVolumeOfSpawnableSpace(), pos -> {
Particles.instance().spawnParticle(UParticles.MAGIC_PARTICLE, false, pos.add(start), 0, 0, 0);
});
}
}

View file

@ -7,10 +7,10 @@ import java.util.UUID;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import com.minelittlepony.unicopia.Unicopia;
import com.minelittlepony.unicopia.client.particle.Particles;
import com.minelittlepony.unicopia.UParticles;
import com.minelittlepony.unicopia.entity.EntitySpell;
import com.minelittlepony.unicopia.entity.IMagicals;
import com.minelittlepony.unicopia.particle.Particles;
import com.minelittlepony.unicopia.player.IPlayer;
import com.minelittlepony.unicopia.player.PlayerSpeciesList;
import com.minelittlepony.unicopia.util.serialisation.InbtSerialisable;
@ -156,7 +156,7 @@ public class SpellPortal extends AbstractSpell implements IUseAction {
@Override
public void render(ICaster<?> source, int level) {
source.spawnParticles(getPortalZone(), 10, pos -> {
Particles.instance().spawnParticle(Unicopia.MAGIC_PARTICLE, false, pos, 0, 0, 0);
Particles.instance().spawnParticle(UParticles.MAGIC_PARTICLE, false, pos, 0, 0, 0);
});
}

View file

@ -2,8 +2,8 @@ package com.minelittlepony.unicopia.spell;
import com.minelittlepony.unicopia.Predicates;
import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.Unicopia;
import com.minelittlepony.unicopia.client.particle.Particles;
import com.minelittlepony.unicopia.UParticles;
import com.minelittlepony.unicopia.particle.Particles;
import com.minelittlepony.unicopia.player.PlayerSpeciesList;
import com.minelittlepony.unicopia.power.IPower;
import com.minelittlepony.util.ProjectileUtil;
@ -53,7 +53,7 @@ public class SpellShield extends AbstractSpell {
protected void spawnParticles(ICaster<?> source, int strength) {
source.spawnParticles(new Sphere(true, strength), strength * 6, pos -> {
Particles.instance().spawnParticle(Unicopia.MAGIC_PARTICLE, false, pos.x, pos.y, pos.z, 0, 0, 0);
Particles.instance().spawnParticle(UParticles.MAGIC_PARTICLE, false, pos, 0, 0, 0);
});
}