All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.minecraft.server.Explosion Maven / Gradle / Ivy

package net.minecraft.server;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.bukkit.Location;
import org.bukkit.craftbukkit.event.CraftEventFactory;
import org.bukkit.entity.FallingBlock;
import org.bukkit.event.block.BlockExplodeEvent;
import org.bukkit.event.entity.EntityExplodeEvent;
import walkmc.extensions.numbers.MathsKt;

import java.util.*;
// CraftBukkit end

public class Explosion {
	
	public final Entity source;
	private final boolean a;
	private final boolean b;
	private final Random c = new Random();
	private final World world;
	private final double posX;
	private final double posY;
	private final double posZ;
	private final float size;
	private final List blocks = Lists.newArrayList();
	private final Map k = Maps.newHashMap();
	
	//
	//    From CraftBukkit section:
	//
	
	public boolean wasCanceled = false; // CraftBukkit - add field
	
	//
	//    From WalkMC section:
	//
	
	public Random random = new Random();
	public boolean blockEffects = false;
	
	//
	//    End of all sections.
	//
	
	public Explosion(World world, Entity entity, double d0, double d1, double d2, float f, boolean flag, boolean flag1) {
		this.world = world;
		this.source = entity;
		this.size = (float) Math.max(f, 0.0); // CraftBukkit - clamp bad values
		this.posX = d0;
		this.posY = d1;
		this.posZ = d2;
		this.a = flag;
		this.b = flag1;
	}
	
	public void a() {
		// CraftBukkit start
		if (this.size < 0.1F) {
			return;
		}
		// CraftBukkit end
		HashSet hashset = Sets.newHashSet();
		boolean flag = true;
		
		int i;
		int j;
		
		for (int k = 0; k < 16; ++k) {
			for (i = 0; i < 16; ++i) {
				for (j = 0; j < 16; ++j) {
					if (k == 0 || k == 15 || i == 0 || i == 15 || j == 0 || j == 15) {
						double d0 = (float) k / 15.0F * 2.0F - 1.0F;
						double d1 = (float) i / 15.0F * 2.0F - 1.0F;
						double d2 = (float) j / 15.0F * 2.0F - 1.0F;
						double d3 = Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2);
						
						d0 /= d3;
						d1 /= d3;
						d2 /= d3;
						float f = this.size * (0.7F + this.world.random.nextFloat() * 0.6F);
						double d4 = this.posX;
						double d5 = this.posY;
						double d6 = this.posZ;
						
						for (float f1 = 0.3F; f > 0.0F; f -= 0.22500001F) {
							BlockPosition blockposition = new BlockPosition(d4, d5, d6);
							IBlockData iblockdata = this.world.getType(blockposition);
							
							if (iblockdata.getBlock().getMaterial() != Material.AIR) {
								float f2 = this.source != null ? this.source.getExplosionResistance(this, this.world, blockposition, iblockdata) : iblockdata.getBlock().a((Entity) null);
								
								f -= (f2 + 0.3F) * 0.3F;
							}
							
							if (f > 0.0F && (this.source == null || this.source.verifyExplosion(this, this.world, blockposition, iblockdata, f)) && blockposition.getY() < 256 && blockposition.getY() >= 0) { // CraftBukkit - don't wrap explosions
								hashset.add(blockposition);
							}
							
							d4 += d0 * 0.30000001192092896D;
							d5 += d1 * 0.30000001192092896D;
							d6 += d2 * 0.30000001192092896D;
						}
					}
				}
			}
		}
		
		this.blocks.addAll(hashset);
		float f3 = this.size * 2.0F;
		
		i = MathHelper.floor(this.posX - (double) f3 - 1.0D);
		j = MathHelper.floor(this.posX + (double) f3 + 1.0D);
		int l = MathHelper.floor(this.posY - (double) f3 - 1.0D);
		int i1 = MathHelper.floor(this.posY + (double) f3 + 1.0D);
		int j1 = MathHelper.floor(this.posZ - (double) f3 - 1.0D);
		int k1 = MathHelper.floor(this.posZ + (double) f3 + 1.0D);
		
		List list = this.world.getEntities(this.source, new AxisAlignedBB(i, l, j1, j, i1, k1), entity -> !entity.isAlive());
		
		Vec3D vec3d = new Vec3D(this.posX, this.posY, this.posZ);
		
		for (Entity o : list) {
			
			if (!o.isImmuneToExplosions()) {
				double d7 = o.getDistance(this.posX, this.posY, this.posZ) / (double) f3;
				
				if (d7 <= 1.0D) {
					double d8 = o.locX - this.posX;
					double d9 = o.locY + (double) o.getHeadHeight() - this.posY;
					double d10 = o.locZ - this.posZ;
					double d11 = MathHelper.sqrt(d8 * d8 + d9 * d9 + d10 * d10);
					
					if (d11 != 0.0D) {
						d8 /= d11;
						d9 /= d11;
						d10 /= d11;
						double d12 = this.world.a(vec3d, o.getBoundingBox());
						double d13 = (1.0D - d7) * d12;
						
						// entity.damageEntity(DamageSource.explosion(this), (float) ((int) ((d13 * d13 + d13) / 2.0D * 8.0D * (double) f3 + 1.0D)));+                        // CraftBukkit start
						CraftEventFactory.entityDamage = source;
						o.forceExplosionKnockback = false;
						boolean wasDamaged = o.damageEntity(DamageSource.explosion(this), (float) ((int) ((d13 * d13 + d13) / 2.0D * 8.0D * (double) f3 + 1.0D)));
						CraftEventFactory.entityDamage = null;
						if (!wasDamaged && !(o instanceof EntityTNTPrimed || o instanceof EntityFallingBlock) && !o.forceExplosionKnockback) {
							continue;
						}
						// CraftBukkit end
						double d14 = EnchantmentProtection.a(o, d13);
						
						o.motX += d8 * d14;
						o.motY += d9 * d14;
						o.motZ += d10 * d14;
						if (o instanceof EntityHuman && !((EntityHuman) o).abilities.isInvulnerable) {
							this.k.put((EntityHuman) o, new Vec3D(d8 * d13, d9 * d13, d10 * d13));
						}
					}
				}
			}
		}
		
	}
	
	public void a(boolean flag) {
		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);
		if (this.size >= 2.0F && this.b) {
			this.world.addParticle(EnumParticle.EXPLOSION_HUGE, this.posX, this.posY, this.posZ, 1.0D, 0.0D, 0.0D);
		} else {
			this.world.addParticle(EnumParticle.EXPLOSION_LARGE, this.posX, this.posY, this.posZ, 1.0D, 0.0D, 0.0D);
		}
		
		Iterator iterator;
		BlockPosition blockposition;
		
		if (this.b) {
			// CraftBukkit start
			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);
			
			List blockList = Lists.newArrayList();
			for (int i1 = this.blocks.size() - 1; i1 >= 0; i1--) {
				BlockPosition cpos = this.blocks.get(i1);
				org.bukkit.block.Block bblock = bworld.getBlockAt(cpos.getX(), cpos.getY(), cpos.getZ());
				if (bblock.getType() != org.bukkit.Material.AIR) {
					blockList.add(bblock);
				}
			}
			
			boolean cancelled;
			List bukkitBlocks;
			float yield;
			
			if (explode != null) {
				EntityExplodeEvent event = new EntityExplodeEvent(explode, location, blockList, 0.3F);
				this.world.getServer().getPluginManager().callEvent(event);
				cancelled = event.isCancelled();
				bukkitBlocks = event.blockList();
				yield = event.getYield();
			} else {
				BlockExplodeEvent event = new BlockExplodeEvent(location.getBlock(), blockList, 0.3F);
				this.world.getServer().getPluginManager().callEvent(event);
				cancelled = event.isCancelled();
				bukkitBlocks = event.blockList();
				yield = event.getYield();
			}
			
			this.blocks.clear();
			
			for (org.bukkit.block.Block bblock : bukkitBlocks) {
				BlockPosition coords = new BlockPosition(bblock.getX(), bblock.getY(), bblock.getZ());
				blocks.add(coords);
			}
			
			if (cancelled) {
				this.wasCanceled = true;
				return;
			}
			// CraftBukkit end
			iterator = this.blocks.iterator();
			
			while (iterator.hasNext()) {
				blockposition = (BlockPosition) iterator.next();
				Block block = this.world.getType(blockposition).getBlock();
				
				if (flag) {
					double d0 = (float) blockposition.getX() + this.world.random.nextFloat();
					double d1 = (float) blockposition.getY() + this.world.random.nextFloat();
					double d2 = (float) blockposition.getZ() + this.world.random.nextFloat();
					double d3 = d0 - this.posX;
					double d4 = d1 - this.posY;
					double d5 = d2 - this.posZ;
					double d6 = MathHelper.sqrt(d3 * d3 + d4 * d4 + d5 * d5);
					
					d3 /= d6;
					d4 /= d6;
					d5 /= d6;
					double d7 = 0.5D / (d6 / (double) this.size + 0.1D);
					
					d7 *= this.world.random.nextFloat() * this.world.random.nextFloat() + 0.3F;
					d3 *= d7;
					d4 *= d7;
					d5 *= d7;
					this.world.addParticle(EnumParticle.EXPLOSION_NORMAL, (d0 + this.posX) / 2.0D, (d1 + this.posY) / 2.0D, (d2 + this.posZ) / 2.0D, d3, d4, d5);
					this.world.addParticle(EnumParticle.SMOKE_NORMAL, d0, d1, d2, d3, d4, d5);
				}
				
				if (block.getMaterial() != Material.AIR) {
					
					// walkmc start
					if (blockEffects) {
						org.bukkit.block.Block bblock = world.world.getBlockAt(blockposition);
						FallingBlock falling = world.world.spawnFallingBlock(bblock.getLocation(), bblock.getMaterial());
						falling.push(
							MathsKt.randomBetween(-1.5, 1.5),
							MathsKt.randomBetween(0.8, 1.5),
							MathsKt.randomBetween(-1.5, 1.5)
						);
					}
					// walkmc end
					
					if (block.a(this)) {
						// CraftBukkit - add yield
						block.dropNaturally(this.world, blockposition, this.world.getType(blockposition), yield, 0);
					}
					
					this.world.setTypeAndData(blockposition, Blocks.AIR.getBlockData(), 3);
					block.wasExploded(this.world, blockposition, this);
				}
			}
		}
		
		if (this.a) {
			iterator = this.blocks.iterator();
			
			while (iterator.hasNext()) {
				blockposition = (BlockPosition) iterator.next();
				if (this.world.getType(blockposition).getBlock().getMaterial() == Material.AIR && this.world.getType(blockposition.down()).getBlock().o() && this.c.nextInt(3) == 0) {
					// CraftBukkit start - Ignition by explosion
					if (!org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(this.world, blockposition.getX(), blockposition.getY(), blockposition.getZ(), this).isCancelled()) {
						this.world.setTypeUpdate(blockposition, Blocks.FIRE.getBlockData());
					}
					// CraftBukkit end
				}
			}
		}
		
	}
	
	public Map b() {
		return this.k;
	}
	
	public EntityLiving getSource() {
		// CraftBukkit start - obtain Fireball shooter for explosion tracking
		return this.source == null ? null : (this.source instanceof EntityTNTPrimed ? ((EntityTNTPrimed) this.source).getSource() : (this.source instanceof EntityLiving ? (EntityLiving) this.source : (this.source instanceof EntityFireball ? ((EntityFireball) this.source).shooter : null)));
		// CraftBukkit end
	}
	
	public void clearBlocks() {
		this.blocks.clear();
	}
	
	public List getBlocks() {
		return this.blocks;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy