package com.minelittlepony.unicopia.particle; import java.util.EnumSet; import java.util.Random; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.entity.Entity; import net.minecraft.particle.BlockStateParticleEffect; import net.minecraft.particle.ParticleTypes; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.math.Direction; import net.minecraft.util.math.Direction.Axis; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; public class ParticleEmitter { static final ParticleEmitter INSTANCE = new ParticleEmitter(); public static ParticleEmitter instance() { return INSTANCE; } private static final Vec3d BUFFER = new Vec3d(0.25, 0.25, 0.25); private static final Vec3d HALF = new Vec3d(0.5, 0.5, 0.5); private static final EnumSet ALL_EXES = EnumSet.allOf(Axis.class); public void emitDestructionParticles(Entity entity, BlockState state) { float height = entity.getHeight(); float width = entity.getWidth(); Vec3d dim = new Vec3d(width, height, width).add(BUFFER); Vec3d origin = entity.getPos(); int total = (int)(32 * dim.length()); for (int i = 0; i < total; i++) { Vec3d pos = centeredRange(entity.world.random, origin, dim); Vec3d vel = pos.subtract(pos.floorAlongAxes(ALL_EXES).subtract(HALF)); spawnDiggingFX(entity.world, pos, vel, state, 1); } } public void emitDiggingParticles(Entity entity, Block block) { emitDiggingParticles(entity, block.getDefaultState()); } public void emitDiggingParticles(Entity entity, BlockState state) { Vec3d area = new Vec3d(entity.getWidth(), entity.getHeight(), entity.getWidth()).add(BUFFER); Vec3d origin = entity.getPos(); for (Direction side : Direction.values()) { Vec3d plane = Vec3d.of(side.getVector()); spawnDiggingFX(entity.getEntityWorld(), clampPlane(side.getAxis(), centeredRange(entity.world.random, origin, area), origin.add(area.multiply(plane)) ), plane.multiply(0.5), state, 0.6F); } } private Vec3d clampPlane(Axis axis, Vec3d vector, Vec3d plane) { return new Vec3d( axis == Axis.X ? plane.x : vector.x, axis == Axis.Y ? plane.y : vector.y, axis == Axis.Z ? plane.z : vector.z ); } private Vec3d centeredRange(Random rand, Vec3d center, Vec3d max) { return center .add(new Vec3d( rand.nextFloat(), rand.nextFloat(), rand.nextFloat() ).multiply(max)) .subtract(max.multiply(0.5D)); } protected void spawnDiggingFX(World w, Vec3d pos, Vec3d vel, BlockState blockState, float multVel) { if (w instanceof ServerWorld) { double speed = vel.length() * multVel; vel = vel.normalize(); ((ServerWorld)w).spawnParticles(new BlockStateParticleEffect(ParticleTypes.BLOCK, blockState), pos.x, pos.y, pos.z, 1, vel.x, vel.y, vel.z, speed ); } } }