1
0
Fork 0

fix explosions

This commit is contained in:
Sen 2025-08-27 12:30:45 +02:00
parent 9dc0275e61
commit 3a77bb8551
Signed by: sen
GPG key ID: 3AC50A6F47D1B722
9 changed files with 106 additions and 136 deletions

View file

@ -791,8 +791,8 @@ public class Block {
return 10;
}
public float getResistance(Entity exploder) {
return this.resistance / 5.0F;
public final float getResistance() {
return this.resistance;
}
public boolean canPlace(World world, BlockPos pos, Facing side) {

View file

@ -59,7 +59,7 @@ public class BlockTNT extends Block
{
if (!worldIn.client)
{
EntityTnt entitytntprimed = new EntityTnt(worldIn, (double)((float)pos.getX() + 0.5F), (double)pos.getY(), (double)((float)pos.getZ() + 0.5F), explosionIn.getExplosivePlacedBy(), this.power);
EntityTnt entitytntprimed = new EntityTnt(worldIn, (double)((float)pos.getX() + 0.5F), (double)pos.getY(), (double)((float)pos.getZ() + 0.5F), explosionIn == null ? null : explosionIn.getExplosivePlacedBy(), this.power);
entitytntprimed.fuse = worldIn.rand.zrange(entitytntprimed.fuse / 4) + entitytntprimed.fuse / 8;
worldIn.spawnEntityInWorld(entitytntprimed);
}

View file

@ -2276,19 +2276,6 @@ public abstract class Entity
return this;
}
/**
* Explosion resistance of a block relative to this entity
*/
public float getExplosionResistance(Explosion explosionIn, World worldIn, BlockPos pos, State blockStateIn)
{
return blockStateIn.getBlock().getResistance(this);
}
public boolean verifyExplosion(Explosion explosionIn, World worldIn, BlockPos pos, State blockStateIn, float p_174816_5_)
{
return true;
}
/**
* The maximum height from where the entity is alowed to jump (used in pathfinder)
*/

View file

@ -62,7 +62,7 @@ public class EntityExplosion extends Entity
private boolean explode(double min)
{
this.iteration = Explosion.doExplosionAlgo3(this.worldObj, this.posX, this.posY, this.posZ, this.rand, min + 6.0d, min, this.iteration, Vars.maxExplosionIters);
this.iteration = Explosion.doPartial(this.worldObj, this.posX, this.posY, this.posZ, this.rand, min + 6.0d, min, this.iteration, Vars.maxExplosionIters);
return this.iteration == 0;
}

View file

@ -140,15 +140,6 @@ public class EntityTntCart extends EntityCart {
return this.minecartTNTFuse > -1;
}
public float getExplosionResistance(Explosion explosionIn, World worldIn, BlockPos pos, State blockStateIn) {
return !this.isIgnited() || !BlockRail.isRailBlock(blockStateIn) && !BlockRail.isRailBlock(worldIn, pos.up()) ? super.getExplosionResistance(explosionIn, worldIn, pos, blockStateIn) : 0.0F;
}
public boolean verifyExplosion(Explosion explosionIn, World worldIn, BlockPos pos, State blockStateIn, float p_174816_5_) {
return !this.isIgnited() || !BlockRail.isRailBlock(blockStateIn) && !BlockRail.isRailBlock(worldIn, pos.up()) ? super.verifyExplosion(explosionIn, worldIn, pos, blockStateIn, p_174816_5_)
: false;
}
protected void readEntity(TagObject tagCompund) {
super.readEntity(tagCompund);
this.minecartTNTFuse = tagCompund.getInt("TNTFuse");

View file

@ -53,10 +53,7 @@ public class Explosion
return table;
}
/** whether or not the explosion sets fire to blocks around it */
private final boolean isFlaming;
/** whether or not this explosion spawns smoke particles */
private final boolean isSmoking;
private final Random explosionRNG;
private final World worldObj;
@ -70,12 +67,7 @@ public class Explosion
public Explosion(World worldIn, Entity entityIn, double x, double y, double z, float size, List<BlockPos> affectedPositions)
{
this(worldIn, entityIn, x, y, z, size, false, true, affectedPositions);
}
public Explosion(World worldIn, Entity entityIn, double x, double y, double z, float size, boolean flaming, boolean smoking, List<BlockPos> affectedPositions)
{
this(worldIn, entityIn, x, y, z, size, flaming, smoking);
this(worldIn, entityIn, x, y, z, size, false, true);
this.affectedBlockPositions.addAll(affectedPositions);
}
@ -94,9 +86,65 @@ public class Explosion
this.isSmoking = smoking;
}
public void doExplosionAlgo2(Set<BlockPos> set)
public static int doPartial(World world, double explosionX, double explosionY, double explosionZ, Random rand, double radius, double minDist, int iter, int max)
{
int d = ((int)this.explosionSize) + 1;
int d = ((int)radius) + 1;
int div = d * 2 + 1;
int[] table = getTable(div);
if(table == null)
return 0;
double falloff = radius * 0.125d;
falloff = falloff > 4.0d ? 4.0d : falloff;
int lmt = div * div * div;
int cnt = 0;
for(; iter < lmt && cnt < max; iter++)
{
int x = table[(iter / div) % div] - d;
int y = table[iter % div] - d;
int z = table[(iter / div) / div] - d;
double dist = (double)ExtMath.sqrtd(((double)x) * ((double)x) + ((double)y) * ((double)y) + ((double)z) * ((double)z));
if(dist > minDist && (dist < radius - falloff ||
(dist < radius && rand.doublev() + ((dist - (radius - falloff)) / falloff) < 1.0d))) {
BlockPos pos = new BlockPos(explosionX + x, explosionY + y, explosionZ + z);
State state = world.getState(pos);
if(state.getBlock() != Blocks.air && (float)radius - (state.getBlock().getResistance() / 5.0F + 0.3F) * 0.3F > 0.0f) {
if(state.getBlock().canDrop(null))
state.getBlock().drop(world, pos, state, 1.0F / (float)radius, 0);
world.setState(pos, Blocks.air.getState(), radius < 40.0 ? 2 : 10);
state.getBlock().onDestroyedExplosion(world, pos, null, state);
if(rand.chance(1000)) {
world.sendSound(SoundEvent.EXPLODE, explosionX + x, explosionY + y, explosionZ + z, 4.0F);
((AWorldServer)world).spawnParticles(ParticleType.EXPLOSION_HUGE, explosionX + x, explosionY + y, explosionZ + z);
}
}
cnt++;
}
}
if(world.client || Vars.damageExplosion) {
List<Entity> list = world.getEntitiesWithinAABB(Entity.class, new BoundingBox(explosionX - (5.0 + (double)d), explosionY - (5.0 + (double)d),
explosionZ - (5.0 + (double)d), explosionX + 5.0 + (double)d, explosionY + 5.0 + (double)d, explosionZ + 5.0 + (double)d));
for (Entity entity : list)
{
if (!entity.isImmuneToExplosions())
{
double dist = (double)ExtMath.sqrtd((entity.posX - explosionX) * (entity.posX - explosionX) +
(entity.posY - explosionY) * (entity.posY - explosionY) + (entity.posZ - explosionZ) * (entity.posZ - explosionZ));
if((dist > minDist - 5.0) && (dist < radius + 5.0)) {
entity.attackEntityFrom(DamageSource.causeExplosionDamage(null), 10000);
}
}
}
}
return iter >= lmt ? 0 : iter;
}
public void doExplosionA()
{
Set<BlockPos> set = Sets.<BlockPos>newHashSet();
int d = ((int)this.explosionSize) + 1;
double falloff = this.explosionSize * 0.125d;
falloff = falloff > 4.0d ? 4.0d : falloff;
for (int x = -d; x <= d; ++x)
@ -108,93 +156,16 @@ public class Explosion
double dist = (double)ExtMath.sqrtd(((double)x) * ((double)x) + ((double)y) * ((double)y) + ((double)z) * ((double)z));
if(dist < this.explosionSize - falloff ||
(dist < this.explosionSize && this.explosionRNG.doublev() + ((dist - (this.explosionSize - falloff)) / falloff) < 1.0d)) {
BlockPos blockpos = new BlockPos(this.explosionX + x, this.explosionY + y, this.explosionZ + z);
State iblockstate = this.worldObj.getState(blockpos);
float f = this.explosionSize; // * (0.7F + this.worldObj.rand.nextFloat() * 0.6F);
if (iblockstate.getBlock() != Blocks.air)
{
float f2 = this.exploder != null ? this.exploder.getExplosionResistance(this, this.worldObj, blockpos, iblockstate) : iblockstate.getBlock().getResistance((Entity)null);
f -= (f2 + 0.3F) * 0.3F;
}
if (f > 0.0F && (this.exploder == null || this.exploder.verifyExplosion(this, this.worldObj, blockpos, iblockstate, f)))
{
set.add(blockpos);
}
BlockPos pos = new BlockPos(this.explosionX + x, this.explosionY + y, this.explosionZ + z);
State state = this.worldObj.getState(pos);
if(state.getBlock() != Blocks.air && this.explosionSize - (state.getBlock().getResistance() / 5.0F + 0.3F) * 0.3F > 0.0F)
set.add(pos);
}
}
}
}
}
public static int doExplosionAlgo3(World worldObj, double explosionX, double explosionY, double explosionZ, Random rand, double explosionSize, double minDist, int iter, int max)
{
int d = ((int)explosionSize) + 1;
int div = d * 2 + 1;
int[] table = getTable(div);
if(table == null)
return 0;
double falloff = explosionSize * 0.125d;
falloff = falloff > 4.0d ? 4.0d : falloff;
int lmt = div * div * div;
int cnt = 0;
for(; iter < lmt && cnt < max; iter++)
{
int x = table[(iter / div) % div] - d;
int y = table[iter % div] - d;
int z = table[(iter / div) / div] - d;
double dist = (double)ExtMath.sqrtd(((double)x) * ((double)x) + ((double)y) * ((double)y) + ((double)z) * ((double)z));
if(dist > minDist && (dist < explosionSize - falloff ||
(dist < explosionSize && rand.doublev() + ((dist - (explosionSize - falloff)) / falloff) < 1.0d))) {
BlockPos blockpos = new BlockPos(explosionX + x, explosionY + y, explosionZ + z);
State iblockstate = worldObj.getState(blockpos);
float f = (float)explosionSize;
if(iblockstate.getBlock() != Blocks.air) {
float f2 = iblockstate.getBlock().getResistance(null);
f -= (f2 + 0.3F) * 0.3F;
if(f > 0.0f) {
worldObj.setState(blockpos, Blocks.air.getState(), 10);
if(rand.chance(1000)) {
worldObj.sendSound(SoundEvent.EXPLODE, explosionX + x, explosionY + y, explosionZ + z, 4.0F);
((AWorldServer)worldObj).spawnParticles(ParticleType.EXPLOSION_HUGE, explosionX + x, explosionY + y, explosionZ + z);
}
}
}
cnt++;
}
}
if(worldObj.client || Vars.damageExplosion) {
List<Entity> list = worldObj.getEntitiesWithinAABB(Entity.class, new BoundingBox(explosionX - (5.0 + (double)d), explosionY - (5.0 + (double)d),
explosionZ - (5.0 + (double)d), explosionX + 5.0 + (double)d, explosionY + 5.0 + (double)d, explosionZ + 5.0 + (double)d));
for (Entity entity : list)
{
if (!entity.isImmuneToExplosions())
{
double dist = (double)ExtMath.sqrtd((entity.posX - explosionX) * (entity.posX - explosionX) +
(entity.posY - explosionY) * (entity.posY - explosionY) + (entity.posZ - explosionZ) * (entity.posZ - explosionZ));
if((dist > minDist - 5.0) && (dist < explosionSize + 5.0)) {
entity.attackEntityFrom(DamageSource.causeExplosionDamage(null), 10000);
}
}
}
}
return iter >= lmt ? 0 : iter;
}
/**
* Does the first part of the explosion (destroy blocks)
*/
public void doExplosionA()
{
Set<BlockPos> set = Sets.<BlockPos>newHashSet();
this.doExplosionAlgo2(set);
this.affectedBlockPositions.addAll(set);
set.clear();
float f3 = this.explosionSize * 2.0F;
int k1 = ExtMath.floord(this.explosionX - (double)f3 - 1.0D);
int l1 = ExtMath.floord(this.explosionX + (double)f3 + 1.0D);
@ -204,22 +175,18 @@ public class Explosion
int j1 = ExtMath.floord(this.explosionZ + (double)f3 + 1.0D);
List<Entity> list = this.worldObj.getEntitiesWithinAABBExcludingEntity(this.exploder, new BoundingBox((double)k1, (double)i2, (double)j2, (double)l1, (double)i1, (double)j1));
Vec3 vec3 = new Vec3(this.explosionX, this.explosionY, this.explosionZ);
for (int k2 = 0; k2 < list.size(); ++k2)
{
Entity entity = (Entity)list.get(k2);
if (!entity.isImmuneToExplosions())
{
double d12 = entity.getDistance(this.explosionX, this.explosionY, this.explosionZ) / (double)f3;
if (d12 <= 1.0D)
{
double d5 = entity.posX - this.explosionX;
double d7 = entity.posY + (double)entity.getEyeHeight() - this.explosionY;
double d9 = entity.posZ - this.explosionZ;
double d13 = (double)ExtMath.sqrtd(d5 * d5 + d7 * d7 + d9 * d9);
if (d13 != 0.0D)
{
d5 = d5 / d13;
@ -233,20 +200,14 @@ public class Explosion
entity.motionX += d5 * d11;
entity.motionY += d7 * d11;
entity.motionZ += d9 * d11;
if (entity.isPlayer()) // && !((EntityNPC)entity).creative)
{
if (entity.isPlayer())
this.playerKnockbackMap.put((EntityNPC)entity, new Vec3(d5 * d10, d7 * d10, d9 * d10));
}
}
}
}
}
}
/**
* Does the second part of the explosion (sound, particles, drop spawn)
*/
public void doExplosionB(boolean spawnParticles, boolean altSound)
{
this.worldObj.sendSound(altSound ? SoundEvent.EXPLODE_ALT : SoundEvent.EXPLODE, this.explosionX, this.explosionY, this.explosionZ, 4.0F);
@ -267,7 +228,7 @@ public class Explosion
State state = this.worldObj.getState(blockpos);
Block block = state.getBlock();
if (this.worldObj.client && spawnParticles /* && (this.explosionSize < 40.0F || this.worldObj.rand.chance(1000)) */)
if (this.worldObj.client && spawnParticles)
{
double d0 = (double)((float)blockpos.getX() + this.worldObj.rand.floatv());
double d1 = (double)((float)blockpos.getY() + this.worldObj.rand.floatv());
@ -279,9 +240,7 @@ public class Explosion
if (!this.worldObj.client && block != Blocks.air)
{
if (block.canDrop(this))
{
block.drop(this.worldObj, blockpos, this.worldObj.getState(blockpos), 1.0F / this.explosionSize, 0);
}
block.drop(this.worldObj, blockpos, state, 1.0F / this.explosionSize, 0);
this.worldObj.setState(blockpos, Blocks.air.getState(), this.explosionSize < 40.0F ? 2 : 10);
block.onDestroyedExplosion(this.worldObj, blockpos, this, state);

View file

@ -1242,11 +1242,11 @@ public abstract class World implements IWorldAccess {
return false;
}
public Explosion createExplosion(Entity entityIn, double x, double y, double z, float strength, boolean isSmoking) {
public final Explosion createExplosion(Entity entityIn, double x, double y, double z, float strength, boolean isSmoking) {
return this.newExplosion(entityIn, x, y, z, strength, false, isSmoking, false);
}
public Explosion createAltExplosion(Entity entityIn, double x, double y, double z, float strength, boolean isSmoking) {
public final Explosion createAltExplosion(Entity entityIn, double x, double y, double z, float strength, boolean isSmoking) {
return this.newExplosion(entityIn, x, y, z, strength, false, isSmoking, true);
}

View file

@ -285,6 +285,7 @@ public class CommandEnvironment {
this.registerExecutable(new CommandSeason());
this.registerExecutable(new CommandCamera());
this.registerExecutable(new CommandNocam());
this.registerExecutable(new CommandExplode());
this.registerExecutable(new CommandSet());
}

View file

@ -0,0 +1,32 @@
package server.command.commands;
import common.util.ExtMath;
import common.util.Vec3;
import server.command.Command;
import server.command.CommandEnvironment;
import server.command.Executor;
import server.world.WorldServer;
public class CommandExplode extends Command {
public CommandExplode() {
super("explode");
this.addVector("position", true, false);
this.addWorld("dim", true);
this.setParamsOptional();
this.addInt("radius", 'r', 1, 1024, 4);
this.addFlag("ticked", 't');
this.addFlag("fire", 'f');
this.addFlag("noblocks", 'n');
this.addFlag("altsound", 'a');
}
public void exec(CommandEnvironment env, Executor exec, Vec3 pos, WorldServer world, int radius, boolean ticked, boolean fire, boolean noblocks, boolean altsound) {
if(ticked)
world.newExplosion(pos.xCoord, pos.yCoord, pos.zCoord, radius);
else
world.newExplosion(null, pos.xCoord, pos.yCoord, pos.zCoord, radius, fire, !noblocks, altsound);
exec.log("Explosion bei %d, %d, %d in %s erzeugt", ExtMath.floord(pos.xCoord), ExtMath.floord(pos.yCoord), ExtMath.floord(pos.zCoord), world.dimension.getDisplay());
}
}