package me.gtacraft.util;
import com.google.common.collect.Lists;
import me.gtacraft.GTAGuns;
import me.gtacraft.event.BulletHitBlockEvent;
import me.gtacraft.event.WeaponDamageEntityEvent;
import me.gtacraft.gun.BulletData;
import me.gtacraft.gun.GunData;
import me.vaqxine.VNPC.tasks.CrimeResponseTask;
import me.vaqxine.WorldRegeneration.RegenerationAPI;
import net.minecraft.server.v1_7_R3.Packet;
import net.minecraft.server.v1_7_R3.PacketPlayOutWorldEvent;
import org.bukkit.Bukkit;
import org.bukkit.Effect;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.craftbukkit.v1_7_R3.CraftServer;
import org.bukkit.craftbukkit.v1_7_R3.CraftWorld;
import org.bukkit.entity.Item;
import org.bukkit.entity.LivingEntity;
import org.bukkit.inventory.ItemStack;
import org.bukkit.util.Vector;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Connor on 5/3/14. Designed for the GTA-Guns project.
*/
public class ExplosionUtil {
public static List<Item> deny_pickup = new ArrayList<Item>();
public static void explode(final BulletData bullet) {
if (bullet == null)
return;
final GunData gun = bullet.getGunData();
boolean boom = gun.getDefaultAttribute("explosion.enabled", false).getBooleanValue();
if (boom == false)
return;
final double dist = gun.getDefaultAttribute("explosion.radius", 1.0).getDoubleValue();
Location origin = bullet.getProjectile().getLocation();
boolean isScatter = gun.getDefaultAttribute("explosion.scatter.enabled", false).getBooleanValue();
if (isScatter) {
int amount = gun.getAttribute("explosion.scatter.amount").getIntValue();
ItemStack drop = new ItemStack(Material.getMaterial(gun.getAttribute("explosion.scatter.id").getIntValue()), 1, (short)0, (byte)gun.getAttribute("explosion.scatter.data").getIntValue());
drop.setAmount(Short.MAX_VALUE);
double expRadius = gun.getDefaultAttribute("explosion.scatter.radius", 1.0).getDoubleValue();
for (int i = 0; i < amount; i++) {
final Item dropped = origin.getWorld().dropItem(origin, drop.clone());
dropped.setVelocity(new Vector((Math.random()*expRadius)-(expRadius/2), (Math.random()*expRadius), (Math.random()*expRadius)-(expRadius/2)));
Runnable explode = new Runnable() {
public void run() {
Location hit = dropped.getLocation();
destroyBlocks(dist, hit, 15);
ParticleEffects.sendToLocation(ParticleEffects.LARGE_EXPLODE, hit, 0.5f, 0.5f, 0.5f, 0, 5);
SoundUtil.playSound(dropped.getLocation(), "EXPLODE-10-1-0", Bukkit.getOnlinePlayers());
for (LivingEntity e : hit.getWorld().getLivingEntities()) {
if (e.getLocation().distance(hit) <= dist && !e.isDead() && e.isValid()) {
WeaponDamageEntityEvent wdee = new WeaponDamageEntityEvent(bullet, e);
Bukkit.getPluginManager().callEvent(wdee);
if (!wdee.isCancelled())
e.damage(ArmorUtil.recomputeDamage(e, gun.getDefaultAttribute("explosion.scatter.damage", 1.0).getDoubleValue()));
}
}
dropped.remove();
}
};
Bukkit.getScheduler().scheduleSyncDelayedTask(GTAGuns.getInstnace(), explode, (long) ((gun.getAttribute("explosion.scatter.timeout").getIntValue()*20)+Math.random()*20));
CrimeResponseTask.addCrimeLocation(dropped.getLocation(), bullet.getProjectile().getShooter());
deny_pickup.add(dropped);
}
return;
} else {
Location projHit = bullet.getProjectile().getLocation();
SoundUtil.playSound(projHit, "EXPLODE-10-1-0", Bukkit.getOnlinePlayers());
ParticleEffects.sendToLocation(ParticleEffects.HUGE_EXPLOSION, projHit, 0f, 0f, 0f, 0, 1);
destroyBlocks(dist, projHit, 15);
CrimeResponseTask.addCrimeLocation(projHit, bullet.getProjectile().getShooter());
for (LivingEntity close : projHit.getWorld().getLivingEntities()) {
Location at = close.getLocation();
if (at.distance(projHit) <= dist) {
WeaponDamageEntityEvent wdee = new WeaponDamageEntityEvent(bullet, close);
Bukkit.getPluginManager().callEvent(wdee);
if (!wdee.isCancelled())
close.damage(ArmorUtil.recomputeDamage(close, gun.getDefaultAttribute("explosion.damage", 1.0).getDoubleValue()));
}
}
bullet.getProjectile().remove();
}
}
/*static List<Material> state_blocks = Lists.newArrayList();
static {
state_blocks.add(Material.SAPLING);
state_blocks.add(Material.RAILS);
state_blocks.add(Material.ACTIVATOR_RAIL);
state_blocks.add(Material.DETECTOR_RAIL);
state_blocks.add(Material.POWERED_RAIL);
state_blocks.add(Material.DEAD_BUSH);
state_blocks.add(Material.getMaterial(31));
state_blocks.add(Material.YELLOW_FLOWER);
state_blocks.add(Material.RED_ROSE);
state_blocks.add(Material.BROWN_MUSHROOM);
state_blocks.add(Material.RED_MUSHROOM);
state_blocks.add(Material.TORCH);
state_blocks.add(Material.LADDER);
state_blocks.add(Material.LEVER);
state_blocks.add(Material.STONE_PLATE);
state_blocks.add(Material.WOOD_PLATE);
state_blocks.add(Material.REDSTONE_TORCH_OFF);
state_blocks.add(Material.REDSTONE_TORCH_ON);
state_blocks.add(Material.STONE_BUTTON);
state_blocks.add(Material.WOOD_BUTTON);
state_blocks.add(Material.SNOW);
state_blocks.add(Material.CACTUS);
state_blocks.add(Material.VINE);
state_blocks.add(Material.WATER_LILY);
state_blocks.add(Material.TRIPWIRE_HOOK);
state_blocks.add(Material.BED_BLOCK);
state_blocks.add(Material.getMaterial(141));
state_blocks.add(Material.getMaterial(142));
state_blocks.add(Material.GOLD_PLATE);
state_blocks.add(Material.IRON_PLATE);
state_blocks.add(Material.CARPET);
state_blocks.add(Material.getMaterial(175));
state_blocks.add(Material.FLOWER_POT);
}*/
public static void destroyBlocks(final double radius, final Location current, final int regenTime) {
BulletHitBlockEvent bhbe = new BulletHitBlockEvent(current);
Bukkit.getPluginManager().callEvent(bhbe);
if (bhbe.isCancelled())
return;
Runnable async = new Runnable() {
public void run() {
List<Block> blocks = Lists.newArrayList();
int xMin = (int)(current.getX()-radius);
int yMin = (int)(current.getY()-radius);
int zMin = (int)(current.getZ()-radius);
for (int x = xMin; x < xMin+(radius*2); x++) {
for (int y = yMin; y < yMin+(radius*2); y++) {
for (int z = zMin; z < zMin+(radius*2); z++) {
Location hit = new Location(current.getWorld(), x, y, z);
if (hit.getBlock().getType().equals(Material.AIR))
continue;
if (hit.toVector().isInSphere(current.toVector(), radius)) {
if (hit.getY() <= 10)
continue;
if (hit.getBlock().getType().equals(Material.WOODEN_DOOR) || hit.getBlock().getType().equals(Material.IRON_DOOR_BLOCK)) {
Location up = hit.clone().add(0, 1, 0);
Location down = hit.clone().add(0, -1, 0);
if (up.getBlock().getType().equals(Material.WOODEN_DOOR) || up.getBlock().getType().equals(Material.IRON_DOOR_BLOCK)) {
blocks.add(up.getBlock());
} else if (down.getBlock().getType().equals(Material.WOODEN_DOOR) || down.getBlock().getType().equals(Material.IRON_DOOR_BLOCK)) {
blocks.add(down.getBlock());
}
}
blocks.add(hit.getBlock());
}
}
}
}
final List<Block> fblocks = blocks;
Runnable destroy = new Runnable() {
public void run() {
for (final Block b : fblocks) {
RegenerationAPI.queueBlockForRegeneration(b, regenTime);
final int id = b.getTypeId();
if (Math.random()*10 < 8) {
Runnable async = new Runnable() {
public void run() {
sendPacket(b, id);
}
};
Bukkit.getScheduler().scheduleAsyncDelayedTask(GTAGuns.getInstnace(), async);
}
b.getWorld().playEffect(b.getLocation(), Effect.STEP_SOUND, b.getTypeId(), b.getData());
b.setType(Material.AIR);
}
}
void sendPacket(Block b, int id) {
Packet particles = new PacketPlayOutWorldEvent(2001, Math.round(b.getX()), Math.round(b.getY()), Math.round(b.getZ()), id, false);
((CraftServer) Bukkit.getServer()).getServer().getPlayerList().sendPacketNearby(b.getX(), b.getY(), b.getZ(), 16, ((CraftWorld) b.getWorld()).getHandle().dimension, particles);
}
};
Bukkit.getScheduler().scheduleSyncDelayedTask(GTAGuns.getInstnace(), destroy);
}
};
Bukkit.getScheduler().scheduleAsyncDelayedTask(GTAGuns.getInstnace(), async);
}
public static List<Item> getDeniedItems() {
return deny_pickup;
}
}