thaumic-machinery/src/main/java/net/anvilcraft/thaummach/entities/EntitySingularity.java

522 lines
19 KiB
Java

package net.anvilcraft.thaummach.entities;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import dev.tilera.auracore.aura.AuraManager;
import net.minecraft.block.Block;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.DamageSource;
import net.minecraft.util.MathHelper;
import net.minecraft.util.Vec3;
import net.minecraft.world.ChunkPosition;
import net.minecraft.world.World;
import thaumcraft.api.aspects.Aspect;
import thaumcraft.api.aspects.AspectList;
public class EntitySingularity extends Entity {
public float rotation;
double bounceFactor;
public int fuse;
int fusemax;
boolean exploded;
public double explosionX;
public double explosionY;
public double explosionZ;
public float explosionSize;
public Set<ChunkPosition> destroyedBlockPositions;
private float currentVis;
public EntitySingularity(World world) {
super(world);
this.setSize(0.5F, 0.5F);
super.yOffset = super.height / 2.0F;
this.bounceFactor = 0.25;
this.exploded = false;
this.destroyedBlockPositions = new HashSet<>();
super.worldObj = world;
}
public EntitySingularity(World world, Entity entity) {
this(world);
this.setRotation(entity.rotationYaw, 0.0F);
double xHeading
= (double) (-MathHelper.sin(entity.rotationYaw * 3.141593F / 180.0F));
double zHeading
= (double) MathHelper.cos(entity.rotationYaw * 3.141593F / 180.0F);
super.motionX = 0.75 * xHeading
* (double) MathHelper.cos(entity.rotationPitch / 180.0F * 3.141593F);
super.motionY
= -0.5 * (double) MathHelper.sin(entity.rotationPitch / 180.0F * 3.141593F);
super.motionZ = 0.75 * zHeading
* (double) MathHelper.cos(entity.rotationPitch / 180.0F * 3.141593F);
this.setPosition(
entity.posX + xHeading * 0.8, entity.posY, entity.posZ + zHeading * 0.8
);
super.prevPosX = super.posX;
super.prevPosY = super.posY;
super.prevPosZ = super.posZ;
this.explosionSize = 4.0F;
this.fuse = 60;
}
@Override
protected boolean canTriggerWalking() {
return false;
}
@Override
public void onUpdate() {
if (this.fuse-- == 0) {
this.explode();
}
if (this.fuse > 0) {
double prevVelX = super.motionX;
double prevVelY = super.motionY;
double prevVelZ = super.motionZ;
super.prevPosX = super.posX;
super.prevPosY = super.posY;
super.prevPosZ = super.posZ;
this.moveEntity(super.motionX, super.motionY, super.motionZ);
if (super.motionX != prevVelX) {
super.motionX = -this.bounceFactor * prevVelX;
}
if (super.motionY != prevVelY) {
super.motionY = -this.bounceFactor * prevVelY;
} else {
super.motionY -= 0.04;
}
if (super.motionZ != prevVelZ) {
super.motionZ = -this.bounceFactor * prevVelZ;
}
super.motionX *= 0.98;
super.motionY *= 0.98;
super.motionZ *= 0.98;
// TODO: FX
//FXWisp ef = new FXWisp(
// super.worldObj,
// (double) ((float) super.posX),
// (double) ((float) super.posY + 0.1F),
// (double) ((float) super.posZ),
// 0.4F,
// 0
//);
//ef.shrink = true;
//Minecraft.getMinecraft().effectRenderer.addEffect(ef);
} else {
++this.rotation;
if (this.rotation > 360.0F) {
this.rotation -= 360.0F;
}
this.doSuckage();
}
if (this.fuse < -170) {
this.doSpawnResult();
this.setDead();
}
}
@SuppressWarnings("unchecked")
public void doExplosion() {
super.worldObj.playSoundEffect(
this.explosionX,
this.explosionY,
this.explosionZ,
"random.explode",
4.0F,
(1.0F
+ (super.worldObj.rand.nextFloat() - super.worldObj.rand.nextFloat()) * 0.2F)
* 0.7F
);
super.worldObj.spawnParticle(
"largeexplode",
this.explosionX,
this.explosionY,
this.explosionZ,
0.0,
0.0,
0.0
);
float f = this.explosionSize;
int i = 16;
int j;
int l;
int j1;
double d5;
double d7;
double d9;
for (j = 0; j < i; ++j) {
for (l = 0; l < i; ++l) {
for (j1 = 0; j1 < i; ++j1) {
if (j == 0 || j == i - 1 || l == 0 || l == i - 1 || j1 == 0
|| j1 == i - 1) {
double d
= (double) ((float) j / ((float) i - 1.0F) * 2.0F - 1.0F);
double d1
= (double) ((float) l / ((float) i - 1.0F) * 2.0F - 1.0F);
double d2
= (double) ((float) j1 / ((float) i - 1.0F) * 2.0F - 1.0F);
double d3 = Math.sqrt(d * d + d1 * d1 + d2 * d2);
d /= d3;
d1 /= d3;
d2 /= d3;
float f1 = this.explosionSize
* (0.7F + super.worldObj.rand.nextFloat() * 0.6F);
d5 = this.explosionX;
d7 = this.explosionY;
d9 = this.explosionZ;
for (float f2 = 0.3F; !(f1 <= 0.0F); f1 -= f2 * 0.75F) {
int j4 = MathHelper.floor_double(d5);
int k4 = MathHelper.floor_double(d7);
int l4 = MathHelper.floor_double(d9);
Block i5 = super.worldObj.getBlock(j4, k4, l4);
if (i5 != Blocks.air) {
f1 -= (i5.getExplosionResistance(this) + 0.3F) * f2;
}
if (f1 > 0.0F) {
this.destroyedBlockPositions.add(
new ChunkPosition(j4, k4, l4)
);
}
d5 += d * (double) f2;
d7 += d1 * (double) f2;
d9 += d2 * (double) f2;
}
}
}
}
}
this.explosionSize *= 2.0F;
j = MathHelper.floor_double(this.explosionX - (double) this.explosionSize - 1.0);
l = MathHelper.floor_double(this.explosionX + (double) this.explosionSize + 1.0);
j1 = MathHelper.floor_double(this.explosionY - (double) this.explosionSize - 1.0);
int l1 = MathHelper.floor_double(
this.explosionY + (double) this.explosionSize + 1.0
);
int i2 = MathHelper.floor_double(
this.explosionZ - (double) this.explosionSize - 1.0
);
int j2 = MathHelper.floor_double(
this.explosionZ + (double) this.explosionSize + 1.0
);
List<Entity> list = super.worldObj.getEntitiesWithinAABBExcludingEntity(
this,
AxisAlignedBB.getBoundingBox(
(double) j, (double) j1, (double) i2, (double) l, (double) l1, (double) j2
)
);
Vec3 vec3d
= Vec3.createVectorHelper(this.explosionX, this.explosionY, this.explosionZ);
for (int k2 = 0; k2 < list.size(); ++k2) {
Entity entity = (Entity) list.get(k2);
double d4
= entity.getDistance(this.explosionX, this.explosionY, this.explosionZ)
/ (double) this.explosionSize;
if (d4 <= 1.0) {
d5 = entity.posX - this.explosionX;
d7 = entity.posY - this.explosionY;
d9 = entity.posZ - this.explosionZ;
double d11 = (double) MathHelper.sqrt_double(d5 * d5 + d7 * d7 + d9 * d9);
d5 /= d11;
d7 /= d11;
d9 /= d11;
double d12
= (double) super.worldObj.getBlockDensity(vec3d, entity.boundingBox);
double d13 = (1.0 - d4) * d12;
entity.attackEntityFrom(
// TODO: WTF
//DamageSource.explosion,
DamageSource.magic,
(int
) ((d13 * d13 + d13) / 2.0 * 8.0 * (double) this.explosionSize + 1.0)
);
entity.motionX += d5 * d13;
entity.motionY += d7 * d13;
entity.motionZ += d9 * d13;
}
}
this.explosionSize = f;
ArrayList<ChunkPosition> arraylist = new ArrayList<>();
arraylist.addAll(this.destroyedBlockPositions);
for (int ii = arraylist.size() - 1; ii >= 0; --ii) {
ChunkPosition chunkposition = (ChunkPosition) arraylist.get(ii);
int jj = chunkposition.chunkPosX;
int kk = chunkposition.chunkPosY;
int ll = chunkposition.chunkPosZ;
Block id = super.worldObj.getBlock(jj, kk, ll);
double d = (double) ((float) jj + super.worldObj.rand.nextFloat());
double d1 = (double) ((float) kk + super.worldObj.rand.nextFloat());
double d2 = (double) ((float) ll + super.worldObj.rand.nextFloat());
double d3 = d - this.explosionX;
double d4 = d1 - this.explosionY;
double d10 = d2 - this.explosionZ;
double d6 = (double) MathHelper.sqrt_double(d3 * d3 + d4 * d4 + d10 * d10);
d3 /= d6;
d4 /= d6;
d10 /= d6;
double d11 = 0.5 / (d6 / (double) this.explosionSize + 0.1);
d11 *= (double
) (super.worldObj.rand.nextFloat() * super.worldObj.rand.nextFloat() + 0.3F);
d3 *= -d11;
d4 *= -d11;
d10 *= -d11;
super.worldObj.spawnParticle("smoke", d, d1, d2, d3, d4, d10);
if (id != Blocks.air) {
id.dropBlockAsItemWithChance(
super.worldObj,
jj,
kk,
ll,
super.worldObj.getBlockMetadata(jj, kk, ll),
0.9F,
0
);
super.worldObj.setBlockToAir(jj, kk, ll);
// TODO: need `Explosion` for this
//id.onBlockDestroyedByExplosion(
// super.worldObj, jj, kk, ll
//);
}
}
}
private void explode() {
if (!this.exploded) {
this.exploded = true;
this.explosionX = super.posX;
this.explosionY = super.posY;
this.explosionZ = super.posZ;
this.doExplosion();
super.worldObj.playSoundEffect(
super.posX, super.posY, super.posZ, "thaumcraft.singularity", 2.0F, 1.0F
);
}
}
@SuppressWarnings("unchecked")
private void doSuckage() {
int auraSize = 10;
int lastdistance = 999;
int lastx = 0;
int lasty = 0;
int lastz = 0;
int mx = super.worldObj.rand.nextBoolean() ? 1 : -1;
int my = super.worldObj.rand.nextBoolean() ? 1 : -1;
int mz = super.worldObj.rand.nextBoolean() ? 1 : -1;
int a;
int b;
int c;
int distance;
for (a = -auraSize; a < auraSize + 1; ++a) {
for (b = -auraSize; b < auraSize + 1; ++b) {
for (c = -auraSize; c < auraSize + 1; ++c) {
if (super.worldObj.getBlock(
(int) super.posX + a * mx,
(int) super.posY + b * my,
(int) super.posZ + c * mz
)
!= Blocks.air) {
distance = (int) this.getDistance(
super.posX + (double) (a * mx) + 0.5,
super.posY + (double) (b * my) + 0.5,
super.posZ + (double) (c * mz) + 0.5
);
if (distance < lastdistance && distance <= auraSize) {
lastdistance = distance;
lastx = (int) super.posX + a * mx;
lasty = (int) super.posY + b * my;
lastz = (int) super.posZ + c * mz;
}
}
}
}
}
int zm;
if (lastdistance < 999) {
Block block = super.worldObj.getBlock(lastx, lasty, lastz);
zm = super.worldObj.getBlockMetadata(lastx, lasty, lastz);
if (block != Blocks.bedrock && block.getExplosionResistance(this) < 100.0F
&& block.getBlockHardness(this.worldObj, lastx, lasty, lastz) != -1.0F) {
block.dropBlockAsItemWithChance(
super.worldObj,
lastx,
lasty,
lastz,
super.worldObj.getBlockMetadata(lastx, lasty, lastz),
0.9F,
0
);
super.worldObj.setBlockToAir(lastx, lasty, lastz);
}
}
a = MathHelper.floor_double(super.posX - (double) auraSize - 1.0);
b = MathHelper.floor_double(super.posX + (double) auraSize + 1.0);
c = MathHelper.floor_double(super.posY - (double) auraSize - 1.0);
distance = MathHelper.floor_double(super.posY + (double) auraSize + 1.0);
zm = MathHelper.floor_double(super.posZ - (double) auraSize - 1.0);
int zp = MathHelper.floor_double(super.posZ + (double) auraSize + 1.0);
List<Entity> list = super.worldObj.getEntitiesWithinAABB(
Entity.class,
AxisAlignedBB.getBoundingBox(
(double) a,
(double) c,
(double) zm,
(double) b,
(double) distance,
(double) zp
)
);
Entity entity;
for (a = 0; a < list.size(); ++a) {
entity = (Entity) list.get(a);
double d4 = entity.getDistance(super.posX, super.posY, super.posZ)
/ (double) auraSize;
double dx = entity.posX - super.posX;
double dy = entity.posY - super.posY;
double dz = entity.posZ - super.posZ;
double d11 = (double) MathHelper.sqrt_double(dx * dx + dy * dy + dz * dz);
dx /= d11;
dy /= d11;
dz /= d11;
double d13 = (1.0 - d4) * 0.1;
if (d13 < 0.0) {
d13 = 0.0;
}
entity.motionX -= dx * d13;
entity.motionY -= dy * d13;
entity.motionZ -= dz * d13;
if (!(entity instanceof EntityLiving)) {
// TODO: FX
//FXWisp ef = new FXWisp(
// super.worldObj,
// (double) ((float) entity.prevPosX),
// (double) ((float) entity.prevPosY + 0.1F),
// (double) ((float) entity.prevPosZ),
// 0.4F,
// 5
//);
//ef.shrink = true;
//Minecraft.getMinecraft().effectRenderer.addEffect(ef);
}
}
a = MathHelper.floor_double(super.posX - 0.75);
b = MathHelper.floor_double(super.posX + 0.75);
c = MathHelper.floor_double(super.posY - 0.75);
distance = MathHelper.floor_double(super.posY + 0.75);
zm = MathHelper.floor_double(super.posZ - 0.75);
zp = MathHelper.floor_double(super.posZ + 0.75);
list = super.worldObj.getEntitiesWithinAABB(
Entity.class,
AxisAlignedBB.getBoundingBox(
(double) a,
(double) c,
(double) zm,
(double) b,
(double) distance,
(double) zp
)
);
for (a = 0; a < list.size(); ++a) {
entity = (Entity) list.get(a);
if (!(entity instanceof EntitySingularity)) {
if (entity instanceof EntityItem) {
// TODO: crucible recipes
//int val = (int) RecipesCrucible.smelting().getSmeltingResult(
// ((EntityItem) entity).item, true, true
//);
//this.currentVis += (float) val;
entity.setDead();
// TODO: FX
//FXWisp ef = new FXWisp(
// super.worldObj,
// (double) ((float) super.posX),
// (double) ((float) super.posY + 0.1F),
// (double) ((float) super.posZ),
// 1.0F,
// 5
//);
//ef.shrink = true;
//Minecraft.getMinecraft().effectRenderer.addEffect(ef);
} else {
entity.attackEntityFrom(DamageSource.magic, 3);
if (entity instanceof EntityLiving) {
++this.currentVis;
}
}
}
}
}
private void doSpawnResult() {
AuraManager.addFluxToClosest(
this.worldObj,
(float) this.posX,
(float) this.posY,
(float) this.posZ,
new AspectList().add(Aspect.DARKNESS, (int) (this.currentVis / 4.0))
);
}
@Override
public boolean attackEntityFrom(DamageSource entity, float i) {
super.attackEntityFrom(entity, i);
this.explode();
return false;
}
@Override
public void onCollideWithPlayer(EntityPlayer entityplayer) {}
@Override
public boolean canBeCollidedWith() {
return !super.isDead;
}
@Override
public float getShadowSize() {
return 0.1F;
}
@Override
protected void entityInit() {}
@Override
protected void readEntityFromNBT(NBTTagCompound var1) {
var1.setByte("Fuse", (byte) this.fuse);
}
@Override
protected void writeEntityToNBT(NBTTagCompound var1) {
this.fuse = var1.getByte("Fuse");
}
}