make ticked explosions less laggy

This commit is contained in:
Sen 2025-07-01 17:43:31 +02:00
parent f241158cc1
commit 9cefe7602b
Signed by: sen
GPG key ID: 3AC50A6F47D1B722
3 changed files with 66 additions and 26 deletions

View file

@ -3,6 +3,7 @@ package common.entity.item;
import common.entity.Entity;
import common.entity.EntityType;
import common.tags.TagObject;
import common.vars.Vars;
import common.world.Explosion;
import common.world.World;
@ -10,13 +11,13 @@ public class EntityExplosion extends Entity
{
private int progress;
private int radius;
private int iteration;
public EntityExplosion(World worldIn)
{
super(worldIn);
this.preventSpawning = true;
this.setSize(0.1F, 0.1F);
// this.setInvisible(true);
}
public EntityExplosion(World worldIn, double x, double y, double z)
@ -49,29 +50,34 @@ public class EntityExplosion extends Entity
this.prevY = this.posY;
this.prevZ = this.posZ;
this.motionX = this.motionY = this.motionZ = 0.0D;
if(this.progress++ >= this.radius) {
if(this.worldObj.client)
return;
if(this.progress >= this.radius) {
this.setDead();
return;
}
else if(!this.worldObj.client) {
this.explode(this.progress - 1);
}
if(this.explode(this.progress - 1))
++this.progress;
}
private void explode(double min)
private boolean explode(double min)
{
Explosion.doExplosionAlgo3(this.worldObj, this.posX, this.posY + (double)(this.height / 2.0F), this.posZ, this.rand, min + 6.0d, min);
this.iteration = Explosion.doExplosionAlgo3(this.worldObj, this.posX, this.posY, this.posZ, this.rand, min + 6.0d, min, this.iteration, Vars.maxExplosionIters);
return this.iteration == 0;
}
protected void writeEntity(TagObject tagCompound)
{
tagCompound.setInt("Progress", this.progress);
tagCompound.setInt("Radius", this.radius);
tagCompound.setInt("Iteration", this.iteration);
}
protected void readEntity(TagObject tagCompund)
{
this.progress = tagCompund.getInt("Progress");
this.radius = tagCompund.getInt("Radius");
this.iteration = tagCompund.getInt("Iteration");
}
public float getEyeHeight()

View file

@ -253,6 +253,8 @@ public abstract class Vars {
public static int eggTimer = 6000;
@Var(name = "spawnMoreZombies")
public static int spawnMoreZombie = 25;
@Var(name = "explosionBlocksPerTick", min = 100, max = 100000)
public static int maxExplosionIters = 1024;
@Var(name = "knockback")
public static float knockback = 1.0f;

View file

@ -26,6 +26,32 @@ import common.vars.Vars;
public class Explosion
{
private static final int[][] TABLES = new int[1024][];
private static int[] shuffle(int size) {
int[] table = new int[size];
Random rand = new Random(8236737136521L);
for(int z = 0; z < size; z++) {
table[z] = z;
}
for(int z = 0; z < size; z++) {
int r = rand.zrange(size);
int n = table[z];
table[z] = table[r];
table[r] = n;
}
return table;
}
private static int[] getTable(int size) {
if(size < 0 || size >= TABLES.length)
return null;
int[] table = TABLES[size];
if(table == null)
TABLES[size] = table = shuffle(size);
return table;
}
/** whether or not the explosion sets fire to blocks around it */
private final boolean isFlaming;
@ -151,32 +177,36 @@ public class Explosion
}
}
public static void doExplosionAlgo3(World worldObj, double explosionX, double explosionY, double explosionZ, Random rand, double explosionSize, double minDist)
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;
for (int x = -d; x <= d; ++x)
int lmt = div * div * div;
int cnt = 0;
for(; iter < lmt && cnt < max; iter++)
{
for (int y = -d; y <= d; ++y)
{
for (int z = -d; z <= d; ++z)
{
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);
if(iblockstate.getBlock() != Blocks.air && iblockstate.getBlock().getExplosionResistance(null) < 60000.0f) {
worldObj.setState(blockpos, Blocks.air.getState(), 3);
if(rand.chance(1000)) {
worldObj.playSound(SoundEvent.EXPLODE, explosionX + x, explosionY + y, explosionZ + z, 4.0F);
((AWorldServer)worldObj).spawnParticle(ParticleType.EXPLOSION_HUGE, explosionX + x, explosionY + y, explosionZ + z, 0, rand.gaussian() * 0.02D, rand.gaussian() * 0.02D, rand.gaussian() * 0.02D, 1.0, 0);
}
}
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);
if(iblockstate.getBlock() != Blocks.air && iblockstate.getBlock().getExplosionResistance(null) < 60000.0f) {
worldObj.setState(blockpos, Blocks.air.getState(), 3);
if(rand.chance(1000)) {
worldObj.playSound(SoundEvent.EXPLODE, explosionX + x, explosionY + y, explosionZ + z, 4.0F);
((AWorldServer)worldObj).spawnParticle(ParticleType.EXPLOSION_HUGE, explosionX + x, explosionY + y, explosionZ + z, 0, rand.gaussian() * 0.02D, rand.gaussian() * 0.02D, rand.gaussian() * 0.02D, 1.0, 0);
}
}
}
cnt++;
}
}
if(worldObj.client || Vars.damageExplosion) {
@ -195,6 +225,8 @@ public class Explosion
}
}
}
return iter >= lmt ? 0 : iter;
}
/**