package sourcecoded.quantum.vacuum.instability;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.boss.EntityDragon;
import net.minecraft.entity.boss.EntityDragonPart;
import net.minecraft.entity.boss.EntityWither;
import net.minecraft.entity.effect.EntityLightningBolt;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.entity.projectile.EntityWitherSkull;
import net.minecraft.init.Blocks;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.Vec3;
import sourcecoded.core.util.RandomUtils;
import sourcecoded.quantum.api.discovery.DiscoveryManager;
import sourcecoded.quantum.api.vacuum.IVacuumRecipe;
import sourcecoded.quantum.api.vacuum.Instability;
import sourcecoded.quantum.discovery.QADiscoveries;
import sourcecoded.quantum.network.MessageSetPlayerVelocity;
import sourcecoded.quantum.network.NetworkHandler;
import sourcecoded.quantum.tile.TileRiftNode;
import sourcecoded.quantum.util.WorldUtils;
import sourcecoded.quantum.util.shapes.CircleCallback;
import sourcecoded.quantum.util.shapes.CircleUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class InstabilityHandler {
public Instability instabilityLevel;
TileRiftNode node;
public boolean isAlive = true;
public int ticker = 0;
public boolean cataSwitched = false;
public boolean watcher1 = false;
public boolean explosionWatcher = true;
IVacuumRecipe recipe;
public InstabilityHandler(IVacuumRecipe recipe, Instability instability, TileRiftNode node) {
this.instabilityLevel = instability;
this.recipe = recipe;
this.node = node;
if (instability == Instability.CATACLYSMIC_SWITCH)
cataSwitched = RandomUtils.rnd.nextInt(4) == 0;
explosionWatcher = true;
}
public Instability getInstability() {
return instabilityLevel;
}
public void tick() {
if (!isAlive()) return;
ticker++;
if (instabilityLevel == null) {
isAlive = false;
return;
}
Instability in = getInstability();
if (in != Instability.CATACLYSMIC_SWITCH)
handleInstabilityForTick(in);
else {
if (!cataSwitched)
handleInstabilityForTick(in);
else
handleCataclysmicSwitch(in);
}
if (ticker == 1) {
int search = 100;
List<EntityPlayer> players = (List<EntityPlayer>) node.getWorldObj().getEntitiesWithinAABB(EntityPlayer.class, AxisAlignedBB.getBoundingBox(node.xCoord - search, node.yCoord - search, node.zCoord - search, node.xCoord + search, node.yCoord + search, node.zCoord + search));
for (EntityPlayer player : players)
DiscoveryManager.unlockItem(QADiscoveries.Item.VACUUM_INSTABILITY.get().getKey(), player, false);
}
if (ticker == 600) isAlive = false;
}
@SuppressWarnings("unchecked")
public void handleInstabilityForTick(Instability in) {
Random rnd = RandomUtils.rnd;
if (in.doesExplosion() && rnd.nextInt(50) == 0 && explosionWatcher)
node.getWorldObj().createExplosion(null, node.xCoord, node.yCoord, node.zCoord, in.explosionSize(), in.explosionFiery);
if (in.doesDamage() && rnd.nextInt(20) == 0) {
List<EntityLivingBase> living = node.getWorldObj().getEntitiesWithinAABB(EntityLivingBase.class, AxisAlignedBB.getBoundingBox(node.xCoord - in.damageRadius, node.yCoord - in.damageRadius, node.zCoord - in.damageRadius, node.xCoord + in.damageRadius, node.yCoord + in.damageRadius, node.zCoord + in.damageRadius));
for (EntityLivingBase livingCurrent : living)
livingCurrent.attackEntityFrom(new DamageSourceInstability(in), in.getDamage());
}
if (in.doesLightning() && rnd.nextInt(30) == 0) {
EntityLightningBolt lightning = new EntityLightningBolt(node.getWorldObj(), node.xCoord + RandomUtils.nextInt(-30, 30), node.yCoord + RandomUtils.nextInt(-30, 30), node.zCoord + RandomUtils.nextInt(-30, 30));
node.getWorldObj().addWeatherEffect(lightning);
node.getWorldObj().setWorldTime(18000);
}
if (in.doesPull) {
List<Entity> living = node.getWorldObj().getEntitiesWithinAABB(Entity.class, AxisAlignedBB.getBoundingBox(node.xCoord - in.pullRange, node.yCoord - in.pullRange, node.zCoord - in.pullRange, node.xCoord + in.pullRange, node.yCoord + in.pullRange, node.zCoord + in.pullRange));
for (Entity entity : living) {
if (entity instanceof EntityDragon || entity instanceof EntityDragonPart || entity instanceof EntityWither || entity instanceof EntityWitherSkull)
continue;
if (entity instanceof EntityPlayer && ((EntityPlayer) entity).capabilities.isCreativeMode)
continue;
Vec3 direction = Vec3.createVectorHelper(entity.posX - node.xCoord, entity.posY - node.yCoord, entity.posZ - node.zCoord);
final double distToOrigin = direction.lengthVector();
double force = in.pullStrength();
if (force <= 0) continue;
Vec3 normal = direction.normalize();
double xV = -force * normal.xCoord;
double yV = -force * normal.yCoord;
double zV = -force * normal.zCoord;
if (entity instanceof EntityPlayer) {
NetworkHandler.wrapper.sendTo(new MessageSetPlayerVelocity(xV, yV, zV), (EntityPlayerMP) entity);
} else {
entity.motionX += xV;
entity.motionY += yV;
entity.motionZ += zV;
}
}
}
if (in == Instability.DIMENSIONAL_SHIFT || in == Instability.CATACLYSMIC_SWITCH)
handleDimensionalShiftForTick(in);
}
public void handleDimensionalShiftForTick(Instability in) {
if (!watcher1) {
watcher1 = true;
explosionWatcher = false;
node.getWorldObj().createExplosion(null, node.xCoord, node.yCoord, node.zCoord, in.explosionSize(), in.explosionFiery);
EntityDragon dragon = new EntityDragon(node.getWorldObj());
dragon.setPositionAndUpdate(node.xCoord, node.yCoord + 50, node.zCoord);
node.getWorldObj().spawnEntityInWorld(dragon);
}
if (RandomUtils.rnd.nextInt(40) == 0) {
EntityWither wither = new EntityWither(node.getWorldObj());
wither.setPositionAndUpdate(node.xCoord, node.yCoord + 30, node.zCoord);
node.getWorldObj().spawnEntityInWorld(wither);
}
if (RandomUtils.rnd.nextInt(60) == 0) {
int x = node.xCoord + RandomUtils.nextInt(-100, 100);
int z = node.zCoord + RandomUtils.nextInt(-100, 100);
int worldHoleRadius = RandomUtils.nextInt(3, 10);
CircleCallback callback = new CircleCallback() {
@Override
public void call(int x1, int z1) {
for (int i = 0; i < node.getWorldObj().provider.getActualHeight(); i++)
node.getWorldObj().setBlockToAir(x1, i, z1);
}
};
CircleUtils.generateFilled(x, z, worldHoleRadius, callback);
}
}
@SuppressWarnings("unchecked")
public void handleCataclysmicSwitch(Instability in) {
watcher1 = true;
ArrayList<ItemStack> stack = new ArrayList<ItemStack>(recipe.getOutputs());
for (ItemStack cStack : stack) {
cStack.stackSize *= 8;
}
stack.add(new ItemStack(Blocks.diamond_block, RandomUtils.nextInt(4, 43)));
stack.add(new ItemStack(Blocks.emerald_block, RandomUtils.nextInt(4, 43)));
IInventory inventory = null;
for (IInventory cInventory : node.getVacuumExports()) {
if (node.getItemsFromInventory(cInventory, true).contains(null)) {
inventory = cInventory;
break;
}
}
if (inventory != null) {
node.insertItems(stack, inventory);
}
List<EntityLivingBase> living = node.getWorldObj().getEntitiesWithinAABB(EntityLivingBase.class, AxisAlignedBB.getBoundingBox(node.xCoord - in.damageRadius, node.yCoord - in.damageRadius, node.zCoord - in.damageRadius, node.xCoord + in.damageRadius, node.yCoord + in.damageRadius, node.zCoord + in.damageRadius));
for (EntityLivingBase livingCurrent : living)
livingCurrent.heal(in.damageValue);
List<TileRiftNode> nodes = WorldUtils.searchForTile(node.getWorldObj(), node.xCoord, node.yCoord, node.zCoord, 1000, 1000, 1000, TileRiftNode.class);
for (TileRiftNode node : nodes)
node.giveRiftEnergy(node.getMaxRiftEnergy());
isAlive = false;
}
public boolean isAlive() {
return isAlive;
}
}