2011-01-03 12:24:25 +01:00
|
|
|
package net.minecraft.server;
|
|
|
|
|
2011-01-29 22:50:29 +01:00
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.HashSet;
|
|
|
|
import java.util.List;
|
|
|
|
import java.util.Random;
|
|
|
|
import java.util.Set;
|
|
|
|
|
2011-01-11 09:25:13 +01:00
|
|
|
// CraftBukkit start
|
2011-01-15 21:26:05 +01:00
|
|
|
import org.bukkit.event.entity.EntityDamageByBlockEvent;
|
|
|
|
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
|
|
|
import org.bukkit.event.entity.EntityDamageEvent;
|
2011-01-17 21:11:06 +01:00
|
|
|
import org.bukkit.event.entity.EntityExplodeEvent;
|
2011-01-18 00:48:02 +01:00
|
|
|
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
|
2011-01-21 17:39:58 +01:00
|
|
|
import org.bukkit.Location;
|
2011-01-11 09:25:13 +01:00
|
|
|
// CraftBukkit end
|
2011-01-03 12:24:25 +01:00
|
|
|
|
|
|
|
public class Explosion {
|
|
|
|
|
2011-01-29 22:50:29 +01:00
|
|
|
public boolean a = false;
|
|
|
|
private Random h = new Random();
|
2011-04-20 19:05:14 +02:00
|
|
|
private World world;
|
|
|
|
public double posX;
|
|
|
|
public double posY;
|
|
|
|
public double posZ;
|
|
|
|
public Entity source;
|
|
|
|
public float size;
|
2011-06-27 00:25:01 +02:00
|
|
|
public Set blocks = new HashSet();
|
2011-02-20 17:40:40 +01:00
|
|
|
|
2011-02-23 13:56:36 +01:00
|
|
|
public boolean wasCanceled = false; // CraftBukkit
|
2011-01-29 22:50:29 +01:00
|
|
|
|
|
|
|
public Explosion(World world, Entity entity, double d0, double d1, double d2, float f) {
|
2011-04-20 19:05:14 +02:00
|
|
|
this.world = world;
|
|
|
|
this.source = entity;
|
|
|
|
this.size = f;
|
|
|
|
this.posX = d0;
|
|
|
|
this.posY = d1;
|
|
|
|
this.posZ = d2;
|
2011-01-03 12:24:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public void a() {
|
2011-04-20 19:05:14 +02:00
|
|
|
float f = this.size;
|
2011-01-29 22:50:29 +01:00
|
|
|
byte b0 = 16;
|
|
|
|
|
|
|
|
int i;
|
|
|
|
int j;
|
|
|
|
int k;
|
|
|
|
double d0;
|
|
|
|
double d1;
|
|
|
|
double d2;
|
|
|
|
|
|
|
|
for (i = 0; i < b0; ++i) {
|
|
|
|
for (j = 0; j < b0; ++j) {
|
|
|
|
for (k = 0; k < b0; ++k) {
|
|
|
|
if (i == 0 || i == b0 - 1 || j == 0 || j == b0 - 1 || k == 0 || k == b0 - 1) {
|
|
|
|
double d3 = (double) ((float) i / ((float) b0 - 1.0F) * 2.0F - 1.0F);
|
|
|
|
double d4 = (double) ((float) j / ((float) b0 - 1.0F) * 2.0F - 1.0F);
|
|
|
|
double d5 = (double) ((float) k / ((float) b0 - 1.0F) * 2.0F - 1.0F);
|
|
|
|
double d6 = Math.sqrt(d3 * d3 + d4 * d4 + d5 * d5);
|
|
|
|
|
|
|
|
d3 /= d6;
|
|
|
|
d4 /= d6;
|
|
|
|
d5 /= d6;
|
2011-04-20 19:05:14 +02:00
|
|
|
float f1 = this.size * (0.7F + this.world.random.nextFloat() * 0.6F);
|
2011-01-29 22:50:29 +01:00
|
|
|
|
2011-04-20 19:05:14 +02:00
|
|
|
d0 = this.posX;
|
|
|
|
d1 = this.posY;
|
|
|
|
d2 = this.posZ;
|
2011-01-29 22:50:29 +01:00
|
|
|
|
|
|
|
for (float f2 = 0.3F; f1 > 0.0F; f1 -= f2 * 0.75F) {
|
2011-04-20 19:05:14 +02:00
|
|
|
int l = MathHelper.floor(d0);
|
|
|
|
int i1 = MathHelper.floor(d1);
|
|
|
|
int j1 = MathHelper.floor(d2);
|
|
|
|
int k1 = this.world.getTypeId(l, i1, j1);
|
2011-01-29 22:50:29 +01:00
|
|
|
|
|
|
|
if (k1 > 0) {
|
2011-04-20 19:05:14 +02:00
|
|
|
f1 -= (Block.byId[k1].a(this.source) + 0.3F) * f2;
|
2011-01-29 22:50:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (f1 > 0.0F) {
|
2011-06-27 00:25:01 +02:00
|
|
|
this.blocks.add(new ChunkPosition(l, i1, j1));
|
2011-01-29 22:50:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
d0 += d3 * (double) f2;
|
|
|
|
d1 += d4 * (double) f2;
|
|
|
|
d2 += d5 * (double) f2;
|
2011-01-03 12:24:25 +01:00
|
|
|
}
|
2011-01-29 22:50:29 +01:00
|
|
|
}
|
2011-01-03 12:24:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-04-20 19:05:14 +02:00
|
|
|
this.size *= 2.0F;
|
|
|
|
i = MathHelper.floor(this.posX - (double) this.size - 1.0D);
|
|
|
|
j = MathHelper.floor(this.posX + (double) this.size + 1.0D);
|
|
|
|
k = MathHelper.floor(this.posY - (double) this.size - 1.0D);
|
|
|
|
int l1 = MathHelper.floor(this.posY + (double) this.size + 1.0D);
|
|
|
|
int i2 = MathHelper.floor(this.posZ - (double) this.size - 1.0D);
|
|
|
|
int j2 = MathHelper.floor(this.posZ + (double) this.size + 1.0D);
|
|
|
|
List list = this.world.b(this.source, AxisAlignedBB.b((double) i, (double) k, (double) i2, (double) j, (double) l1, (double) j2));
|
|
|
|
Vec3D vec3d = Vec3D.create(this.posX, this.posY, this.posZ);
|
2011-01-29 22:50:29 +01:00
|
|
|
|
|
|
|
for (int k2 = 0; k2 < list.size(); ++k2) {
|
|
|
|
Entity entity = (Entity) list.get(k2);
|
2011-04-20 19:05:14 +02:00
|
|
|
double d7 = entity.e(this.posX, this.posY, this.posZ) / (double) this.size;
|
2011-01-29 22:50:29 +01:00
|
|
|
|
|
|
|
if (d7 <= 1.0D) {
|
2011-04-20 19:05:14 +02:00
|
|
|
d0 = entity.locX - this.posX;
|
|
|
|
d1 = entity.locY - this.posY;
|
|
|
|
d2 = entity.locZ - this.posZ;
|
2011-01-29 22:50:29 +01:00
|
|
|
double d8 = (double) MathHelper.a(d0 * d0 + d1 * d1 + d2 * d2);
|
|
|
|
|
|
|
|
d0 /= d8;
|
|
|
|
d1 /= d8;
|
|
|
|
d2 /= d8;
|
2011-04-20 19:05:14 +02:00
|
|
|
double d9 = (double) this.world.a(vec3d, entity.boundingBox);
|
2011-01-29 22:50:29 +01:00
|
|
|
double d10 = (1.0D - d7) * d9;
|
2011-01-03 12:24:25 +01:00
|
|
|
|
2011-01-11 09:25:13 +01:00
|
|
|
// CraftBukkit start - explosion damage hook
|
2011-06-27 00:25:01 +02:00
|
|
|
org.bukkit.Server server = this.world.getServer();
|
2011-01-29 22:50:29 +01:00
|
|
|
org.bukkit.entity.Entity damagee = (entity == null) ? null : entity.getBukkitEntity();
|
2011-04-20 19:05:14 +02:00
|
|
|
int damageDone = (int) ((d10 * d10 + d10) / 2.0D * 8.0D * (double) this.size + 1.0D);
|
2011-01-11 09:25:13 +01:00
|
|
|
|
2011-02-23 13:56:36 +01:00
|
|
|
if (damagee == null) {
|
2011-01-19 09:07:56 +01:00
|
|
|
// nothing was hurt
|
2011-04-20 19:05:14 +02:00
|
|
|
} else if (this.source == null) { // Block explosion
|
2011-01-19 09:07:56 +01:00
|
|
|
// TODO: get the x/y/z of the tnt block?
|
|
|
|
// does this even get called ever? @see EntityTNTPrimed - not BlockTNT or whatever
|
2011-06-27 00:25:01 +02:00
|
|
|
EntityDamageByBlockEvent event = new EntityDamageByBlockEvent(null, damagee, EntityDamageEvent.DamageCause.BLOCK_EXPLOSION, damageDone);
|
2011-01-29 22:50:29 +01:00
|
|
|
server.getPluginManager().callEvent(event);
|
2011-02-23 13:56:36 +01:00
|
|
|
|
2011-01-29 22:50:29 +01:00
|
|
|
if (!event.isCancelled()) {
|
2011-04-20 19:05:14 +02:00
|
|
|
entity.damageEntity(this.source, event.getDamage());
|
2011-02-09 02:28:10 +01:00
|
|
|
entity.motX += d0 * d10;
|
|
|
|
entity.motY += d1 * d10;
|
|
|
|
entity.motZ += d2 * d10;
|
2011-01-17 21:11:06 +01:00
|
|
|
}
|
2011-01-03 12:24:25 +01:00
|
|
|
} else {
|
2011-06-27 00:25:01 +02:00
|
|
|
EntityDamageByEntityEvent event = new EntityDamageByEntityEvent(this.source.getBukkitEntity(), damagee, EntityDamageEvent.DamageCause.ENTITY_EXPLOSION, damageDone);
|
2011-01-29 22:50:29 +01:00
|
|
|
server.getPluginManager().callEvent(event);
|
|
|
|
|
|
|
|
if (!event.isCancelled()) {
|
2011-04-20 19:05:14 +02:00
|
|
|
entity.damageEntity(this.source, event.getDamage());
|
2011-01-19 09:07:56 +01:00
|
|
|
|
2011-01-29 22:50:29 +01:00
|
|
|
entity.motX += d0 * d10;
|
|
|
|
entity.motY += d1 * d10;
|
|
|
|
entity.motZ += d2 * d10;
|
2011-01-11 09:25:13 +01:00
|
|
|
}
|
2011-01-03 12:24:25 +01:00
|
|
|
}
|
2011-01-19 09:07:56 +01:00
|
|
|
// CraftBukkit end
|
2011-01-03 12:24:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-04-20 19:05:14 +02:00
|
|
|
this.size = f;
|
2011-01-03 12:24:25 +01:00
|
|
|
ArrayList arraylist = new ArrayList();
|
|
|
|
|
2011-06-27 00:25:01 +02:00
|
|
|
arraylist.addAll(this.blocks);
|
2011-01-29 22:50:29 +01:00
|
|
|
if (this.a) {
|
|
|
|
for (int l2 = arraylist.size() - 1; l2 >= 0; --l2) {
|
|
|
|
ChunkPosition chunkposition = (ChunkPosition) arraylist.get(l2);
|
2011-04-20 19:05:14 +02:00
|
|
|
int i3 = chunkposition.x;
|
|
|
|
int j3 = chunkposition.y;
|
|
|
|
int k3 = chunkposition.z;
|
|
|
|
int l3 = this.world.getTypeId(i3, j3, k3);
|
|
|
|
int i4 = this.world.getTypeId(i3, j3 - 1, k3);
|
2011-01-29 22:50:29 +01:00
|
|
|
|
|
|
|
if (l3 == 0 && Block.o[i4] && this.h.nextInt(3) == 0) {
|
2011-04-20 19:05:14 +02:00
|
|
|
this.world.setTypeId(i3, j3, k3, Block.FIRE.id);
|
2011-01-03 12:24:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-04-20 22:47:26 +02:00
|
|
|
public void a(boolean flag) {
|
2011-04-20 19:05:14 +02:00
|
|
|
this.world.makeSound(this.posX, this.posY, this.posZ, "random.explode", 4.0F, (1.0F + (this.world.random.nextFloat() - this.world.random.nextFloat()) * 0.2F) * 0.7F);
|
2011-01-03 12:24:25 +01:00
|
|
|
ArrayList arraylist = new ArrayList();
|
|
|
|
|
2011-06-27 00:25:01 +02:00
|
|
|
arraylist.addAll(this.blocks);
|
2011-01-17 21:11:06 +01:00
|
|
|
|
2011-01-19 09:07:56 +01:00
|
|
|
// CraftBukkit start
|
2011-06-27 00:25:01 +02:00
|
|
|
org.bukkit.World bworld = this.world.getWorld();
|
|
|
|
org.bukkit.entity.Entity explode = this.source == null ? null : this.source.getBukkitEntity();
|
|
|
|
Location location = new Location(bworld, this.posX, this.posY, this.posZ);
|
2011-01-19 09:07:56 +01:00
|
|
|
|
2011-02-23 13:56:36 +01:00
|
|
|
List<org.bukkit.block.Block> blockList = new ArrayList<org.bukkit.block.Block>();
|
2011-01-19 09:07:56 +01:00
|
|
|
for (int j = arraylist.size() - 1; j >= 0; j--) {
|
|
|
|
ChunkPosition cpos = (ChunkPosition) arraylist.get(j);
|
2011-06-27 00:25:01 +02:00
|
|
|
org.bukkit.block.Block block = bworld.getBlockAt(cpos.x, cpos.y, cpos.z);
|
2011-04-20 22:47:26 +02:00
|
|
|
if (block.getType() != org.bukkit.Material.AIR) {
|
2011-02-23 13:56:36 +01:00
|
|
|
blockList.add(block);
|
2011-01-03 12:24:25 +01:00
|
|
|
}
|
2011-01-17 21:11:06 +01:00
|
|
|
}
|
2011-01-29 22:50:29 +01:00
|
|
|
|
2011-03-26 22:32:56 +01:00
|
|
|
EntityExplodeEvent event = new EntityExplodeEvent(explode, location, blockList);
|
2011-06-27 00:25:01 +02:00
|
|
|
this.world.getServer().getPluginManager().callEvent(event);
|
2011-01-29 22:50:29 +01:00
|
|
|
|
|
|
|
if (event.isCancelled()) {
|
2011-06-27 00:25:01 +02:00
|
|
|
this.wasCanceled = true;
|
2011-01-19 09:07:56 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
// CraftBukkit end
|
2011-01-29 22:50:29 +01:00
|
|
|
|
|
|
|
for (int i = arraylist.size() - 1; i >= 0; --i) {
|
|
|
|
ChunkPosition chunkposition = (ChunkPosition) arraylist.get(i);
|
2011-04-20 19:05:14 +02:00
|
|
|
int j = chunkposition.x;
|
|
|
|
int k = chunkposition.y;
|
|
|
|
int l = chunkposition.z;
|
|
|
|
int i1 = this.world.getTypeId(j, k, l);
|
2011-01-29 22:50:29 +01:00
|
|
|
|
2011-04-20 22:47:26 +02:00
|
|
|
if (flag) {
|
2011-04-20 19:05:14 +02:00
|
|
|
double d0 = (double) ((float) j + this.world.random.nextFloat());
|
|
|
|
double d1 = (double) ((float) k + this.world.random.nextFloat());
|
|
|
|
double d2 = (double) ((float) l + this.world.random.nextFloat());
|
|
|
|
double d3 = d0 - this.posX;
|
|
|
|
double d4 = d1 - this.posY;
|
|
|
|
double d5 = d2 - this.posZ;
|
2011-01-29 22:50:29 +01:00
|
|
|
double d6 = (double) MathHelper.a(d3 * d3 + d4 * d4 + d5 * d5);
|
|
|
|
|
|
|
|
d3 /= d6;
|
|
|
|
d4 /= d6;
|
|
|
|
d5 /= d6;
|
2011-04-20 19:05:14 +02:00
|
|
|
double d7 = 0.5D / (d6 / (double) this.size + 0.1D);
|
2011-01-29 22:50:29 +01:00
|
|
|
|
2011-04-20 19:05:14 +02:00
|
|
|
d7 *= (double) (this.world.random.nextFloat() * this.world.random.nextFloat() + 0.3F);
|
2011-01-29 22:50:29 +01:00
|
|
|
d3 *= d7;
|
|
|
|
d4 *= d7;
|
|
|
|
d5 *= d7;
|
2011-04-20 19:05:14 +02:00
|
|
|
this.world.a("explode", (d0 + this.posX * 1.0D) / 2.0D, (d1 + this.posY * 1.0D) / 2.0D, (d2 + this.posZ * 1.0D) / 2.0D, d3, d4, d5);
|
|
|
|
this.world.a("smoke", d0, d1, d2, d3, d4, d5);
|
2011-01-19 09:07:56 +01:00
|
|
|
}
|
2011-01-03 12:24:25 +01:00
|
|
|
|
2011-06-11 00:34:12 +02:00
|
|
|
// CraftBukkit - stop explosions from putting out fire
|
|
|
|
if (i1 > 0 && i1 != Block.FIRE.id) {
|
2011-02-23 13:56:36 +01:00
|
|
|
// CraftBukkit
|
2011-04-20 19:05:14 +02:00
|
|
|
Block.byId[i1].dropNaturally(this.world, j, k, l, this.world.getData(j, k, l), event.getYield());
|
|
|
|
this.world.setTypeId(j, k, l, 0);
|
2011-06-30 00:02:25 +02:00
|
|
|
Block.byId[i1].d(this.world, j, k, l);
|
2011-01-03 12:24:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|