From 05c78126859231a68e199dc34613689bd0978e2f Mon Sep 17 00:00:00 2001 From: Foghrye4 Date: Mon, 11 Apr 2016 19:44:54 +0300 Subject: Initial commit --- ihl/utils/ExplosionVector.java | 453 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 453 insertions(+) create mode 100644 ihl/utils/ExplosionVector.java (limited to 'ihl/utils/ExplosionVector.java') diff --git a/ihl/utils/ExplosionVector.java b/ihl/utils/ExplosionVector.java new file mode 100644 index 0000000..d341fd3 --- /dev/null +++ b/ihl/utils/ExplosionVector.java @@ -0,0 +1,453 @@ +package ihl.utils; + +import ihl.IHLMod; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.Set; + +import net.minecraft.block.Block; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.network.play.server.S26PacketMapChunkBulk; +import net.minecraft.util.DamageSource; +import net.minecraft.world.ChunkCoordIntPair; +import net.minecraft.world.Explosion; +import net.minecraft.world.World; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.chunk.NibbleArray; +import net.minecraft.world.chunk.storage.ExtendedBlockStorage; + +public class ExplosionVector +{ + public Set startVectors = new HashSet(); + private Set sv; + private Set chunksToUpdate=new HashSet(64); + public Map> vectors = new HashMap(32786); + public Map explosions = new HashMap(); + public Map explosionPower = new HashMap(); + public Map explosionPowerDampingFactor = new HashMap(32786); + public Map cachedEBS = new HashMap(128); + public Map cachedEBSHardness = new HashMap(128); + public Map> cachedEBSDrops = new HashMap(128); + public Map> cachedEBSEntity = new HashMap(128); + public Map blastWaveByDimensionId = new HashMap(); + + private Random random = new Random(); + + public ExplosionVector() + { + this.precalculateExplosion(); + } + + public void precalculateExplosion() + { + int maxExplosionRadius=32; + for(int levelRadius=1; levelRadiusMath.round(levelRadius*1.8f)) + { + prevX=IHLUtils.reduceVariableByAbsoluteValue(prevX); + prevY=IHLUtils.reduceVariableByAbsoluteValue(prevY); + prevZ=IHLUtils.reduceVariableByAbsoluteValue(prevZ); + } + else if(Math.abs(ix)<=Math.abs(iy) && Math.abs(ix)<=Math.abs(iz)) + { + prevY=IHLUtils.reduceVariableByAbsoluteValue(prevY); + prevZ=IHLUtils.reduceVariableByAbsoluteValue(prevZ); + } + else if(Math.abs(iy)<=Math.abs(ix) && Math.abs(iy)<=Math.abs(iz)) + { + prevX=IHLUtils.reduceVariableByAbsoluteValue(prevX); + prevZ=IHLUtils.reduceVariableByAbsoluteValue(prevZ); + } + else if(Math.abs(iz)<=Math.abs(ix) && Math.abs(iz)<=Math.abs(iy)) + { + prevY=IHLUtils.reduceVariableByAbsoluteValue(prevY); + prevX=IHLUtils.reduceVariableByAbsoluteValue(prevX); + } + long prevKey = IHLUtils.encodeXYZ(prevX,prevY,prevZ); + if(prevX==ix && prevY==iy && prevZ==iz && levelRadius>1) + { + IHLMod.log.error("Was:"+ix+"/" +iy+"/" +iz+"/"); + IHLMod.log.error("Now:"+prevX+"/" +prevY+"/" +prevZ+"/"); + throw new ArithmeticException("Variables are out of expected range. \n Expected are not equal: "+ix+"="+prevX+" "+iy+"="+prevY+" "+iz+"="+prevZ); + } + if(levelRadius==1) + { + startVectors.add(coordinateKey); + this.addElement(coordinateKey, prevX, prevY, prevZ, ix, iy, iz); + } + else if(vectors.containsKey(prevKey)) + { + //prevKey=this.getParentWithLowestDescendantsRate(prevKey, prevX, prevY, prevZ, levelRadius); + vectors.get(prevKey).add(coordinateKey); + this.addElement(coordinateKey, prevX, prevY, prevZ, ix, iy, iz); + } + else + { + IHLMod.log.error("Was:"+ix+"/" +iy+"/" +iz+"/"); + IHLMod.log.error("Now:"+prevX+"/" +prevY+"/" +prevZ+"/"); + IHLMod.log.info("ExplosionVector is missing parent! Help him!"); + } + } + } + } + } + } + } + } + + private void addElement(long coordinateKey, int prevX, int prevY, int prevZ, int ix, int iy, int iz) + { + vectors.put(coordinateKey, new HashSet()); + float df = (float)(prevX*prevX+prevY*prevY+prevZ*prevZ+1)/(float)(ix*ix+iy*iy+iz*iz+1); + explosionPowerDampingFactor.put(coordinateKey,df); + } + + public void setPower(Set sv2, int power1) + { + for(long ev:sv2) + { + this.setPower(ev, power1); + } + } + + public void setPower(Long ev, int power1) { + this.explosionPower.put(ev, power1); + } +/* + public Set breakBlocksAndGetDescendants(World world, EntityIHLExplosion exploder, Explosion explosion, long longNumber) + { + int multiplier = exploder.multiplier; + int[] xyz = IHLUtils.decodeXYZ(longNumber); + int power1 = explosionPower.get(longNumber); + int repeat=0; + //System.out.println("Power before " + power1); + if(Math.abs(xyz[0])>=Math.abs(xyz[1]) && Math.abs(xyz[0])>=Math.abs(xyz[2])) + { + for(int ix=xyz[0]>0?0:multiplier-1;ix=0;ix=xyz[0]>0?ix+1:ix-1) + { + for(int iy=xyz[1]>0?0:multiplier-1;iy=0;iy=xyz[1]>0?iy+1:iy-1) + { + for(int iz=xyz[2]>0?0:multiplier-1;iz=0;iz=xyz[2]>0?iz+1:iz-1) + { + power1 = this.getNewPowerAndProcessBlocks(world, exploder, explosion, xyz, multiplier, ix, iy, iz, power1); + } + } + } + } + else if(Math.abs(xyz[1])>=Math.abs(xyz[0]) && Math.abs(xyz[1])>=Math.abs(xyz[2])) + { + for(int iy=xyz[1]>0?0:multiplier-1;iy=0;iy=xyz[1]>0?iy+1:iy-1) + { + for(int ix=xyz[0]>0?0:multiplier-1;ix=0;ix=xyz[0]>0?ix+1:ix-1) + { + for(int iz=xyz[2]>0?0:multiplier-1;iz=0;iz=xyz[2]>0?iz+1:iz-1) + { + power1 = this.getNewPowerAndProcessBlocks(world, exploder, explosion, xyz, multiplier, ix, iy, iz, power1); + } + } + } + } + else + { + for(int iz=xyz[2]>0?0:multiplier-1;iz=0;iz=xyz[2]>0?iz+1:iz-1) + { + for(int ix=xyz[0]>0?0:multiplier-1;ix=0;ix=xyz[0]>0?ix+1:ix-1) + { + for(int iy=xyz[1]>0?0:multiplier-1;iy=0;iy=xyz[1]>0?iy+1:iy-1) + { + power1 = this.getNewPowerAndProcessBlocks(world, exploder, explosion, xyz, multiplier, ix, iy, iz, power1); + } + } + } + } + power1=Math.round(power1*explosionPowerDampingFactor.get(longNumber)-0.5f); + //System.out.println("Power after " + power1 + " \n repeats "+repeat); + if(power1<=1 || !vectors.containsKey(longNumber)|| vectors.get(longNumber).isEmpty()) + { + exploder.effectBorderBlocks.add(longNumber); + if(xyz[1]<0 || (exploder.y<=6 && xyz[1]<=6)) + { + exploder.effectBorderBlocksWithLowPosition.add(longNumber); + } + return null; + } + else + { + for(long d1:vectors.get(longNumber)) + { + explosionPower.put(d1, power1); + } + return vectors.get(longNumber); + } + } + */ + + public Set breakBlocksAndGetDescendantsForEBS(World world, int sourceX,int sourceY,int sourceZ, Explosion explosion, long longNumber) + { + int[] xyz = IHLUtils.decodeXYZ(longNumber); + int power1 = explosionPower.remove(longNumber); + power1 = this.getNewPowerAndProcessBlocksEBS(world, longNumber, sourceX, sourceY, sourceZ, explosion, xyz, power1); + power1=Math.round(power1*explosionPowerDampingFactor.get(longNumber)-0.5f); + if(power1<=1 || !vectors.containsKey(longNumber)|| vectors.get(longNumber).isEmpty()) + { + return null; + } + else + { + for(long d1:vectors.get(longNumber)) + { + explosionPower.put(d1, power1); + } + return vectors.get(longNumber); + } + + } +/* + private int getNewPowerAndProcessBlocks(World world, EntityIHLExplosion exploder, Explosion explosion, int xyz[], int multiplier, int ix, int iy, int iz, int power2) + { + int power1=power2; + int x = exploder.x+xyz[0]*multiplier+ix; + int y = exploder.y+xyz[1]*multiplier+iy; + int z = exploder.z+xyz[2]*multiplier+iz; + if(y<=4 || y>256) + { + return 0; + } + Block block = exploder.getBlock(x, y, z); + int explosionResistance = Math.round(block.getExplosionResistance(exploder, world, x, y, z, exploder.x, exploder.y, exploder.z)*10f); + if(explosionResistance>=power1) + { + power1=0; + } + else + { + power1-=Math.round(block.getExplosionResistance(exploder, world, x, y, z, exploder.x, exploder.y, exploder.z)*10f); + Entity entity = exploder.getEntity(x, y, z); + if(entity!=null) + { + entity.attackEntityFrom(exploder.damageSource, power1/10f); + } + block.onBlockDestroyedByExplosion(world, x, y, z, explosion); + exploder.setBlockToAir(x, y, z); + } + return power1; + } + */ + private int getNewPowerAndProcessBlocksEBS(World world, long longNumber, int sourceX, int sourceY, int sourceZ, Explosion explosion, int xyz[], int power2) + { + int power1=power2; + int absEBSX = xyz[0] + (sourceX>>4); + int absEBSY = xyz[1] + (sourceY>>4); + int absEBSZ = xyz[2] + (sourceZ>>4); + long chunkXZKey = ChunkCoordIntPair.chunkXZ2Int(absEBSX, absEBSZ); + if(absEBSY<0 || absEBSY>=16) + { + return 0; + } + if(world.getChunkProvider().chunkExists(absEBSX, absEBSZ)) + { + long absEBShash = IHLUtils.getXYZHash(absEBSX, absEBSY, absEBSZ); + int explosionResistance = this.getEBSResistance(world, absEBShash, absEBSX, absEBSY, absEBSZ, sourceX, sourceY, sourceZ); + if(explosionResistance>=power1) + { + power1=0; + } + else + { + power1-=explosionResistance; + if(this.cachedEBSEntity.containsKey(absEBShash)) + { + List entityList = this.cachedEBSEntity.get(absEBShash); + for(Object entity:entityList.toArray()) + { + if(entity!=null) + { + ((Entity) entity).attackEntityFrom(DamageSource.setExplosionSource(explosion), power1/10f); + } + } + } + this.onEBSDestroy(world, absEBShash, absEBSX, absEBSY, absEBSZ); + } + } + else + { + WorldSavedDataBlastWave blastWave = null; + int dimensionId = world.provider.dimensionId; + if(this.blastWaveByDimensionId.containsKey(dimensionId)) + { + blastWave=this.blastWaveByDimensionId.get(dimensionId); + } + else + { + blastWave=new WorldSavedDataBlastWave("blastWave"); + this.blastWaveByDimensionId.put(dimensionId, blastWave); + } + blastWave.scheduleExplosionEffectsOnChunkLoad(chunkXZKey, longNumber, sourceX, sourceY, sourceZ, power1, absEBSY); + } + return power1; + } + + public int getEBSResistance(World world, long absEBShash, int absEBSX, int absEBSY, int absEBSZ, int sourceX, int sourceY, int sourceZ) + { + + if(this.cachedEBSHardness.containsKey(absEBShash)) + { + return this.cachedEBSHardness.get(absEBShash); + } + else + { + this.precacheChunk(world, absEBSX,absEBSZ, sourceX, sourceY, sourceZ); + return this.cachedEBSHardness.containsKey(absEBShash)?this.cachedEBSHardness.get(absEBShash):0; + } + } + + public void precacheChunk(World world, int absEBSX, int absEBSZ, int sourceX, int sourceY, int sourceZ) + { + Chunk chunk = world.getChunkProvider().provideChunk(absEBSX, absEBSZ); + ExtendedBlockStorage[] ebsA = chunk.getBlockStorageArray(); + for(int y3=0;y3 drops = new HashMap(); + for(int i4=0;i4>8) & 15, (i4>>4) & 15) << 8; + } + int blockWorldX = (i4 & 15)+(absEBSX<<4); + int blockWorldY = ((i4>>8) & 15)+(y3<<4); + int blockWorldZ = ((i4>>4) & 15)+(absEBSZ<<4); + Block block = Block.getBlockById(var4); + List dropsList = (block.getDrops(world, blockWorldX, blockWorldY, blockWorldZ, ebs.getExtBlockMetadata(i4 & 15, (i4>>8) & 15, (i4>>4) & 15), 0)); + if(dropsList!=null) + { + for(ItemStack drop:dropsList) + { + long key = (Item.getIdFromItem(drop.getItem())<<16)|drop.getItemDamage(); + if(drops.containsKey(key)) + { + int ss = drops.get(key); + drops.put(key, drop.stackSize+ss); + } + else + { + drops.put(key, drop.stackSize); + } + } + } + if(block.getBlockHardness(world, blockWorldX, blockWorldY, blockWorldZ)<0) + { + ebsHardness=Integer.MAX_VALUE; + break; + } + else + { + ebsHardness+=Math.round(block.getExplosionResistance(null, world, blockWorldX, blockWorldY, blockWorldZ, sourceX, sourceY, sourceZ)*10f); + } + } + this.cachedEBSDrops.put(absEBShash1, drops); + this.cachedEBSEntity.put(absEBShash1, chunk.entityLists[y3]); + this.cachedEBSHardness.put(absEBShash1, ebsHardness); + this.cachedEBS.put(absEBShash1, ebs); + } + } + } + + public void onEBSDestroy(World world,long absEBShash,int absEBSX,int absEBSY,int absEBSZ) + { + if(this.cachedEBS.containsKey(absEBShash)) + { + ExtendedBlockStorage ebs = this.cachedEBS.get(absEBShash); + ebs.setBlockMSBArray(new NibbleArray(4096, 4)); + ebs.setBlockLSBArray(new byte[4096]); + this.cachedEBS.remove(absEBShash); + this.cachedEBSDrops.remove(absEBShash); + this.cachedEBSEntity.remove(absEBShash); + this.cachedEBSHardness.remove(absEBShash); + this.chunksToUpdate.add(world.getChunkProvider().provideChunk(absEBSX, absEBSZ)); + } + } + + public void sendChunkUpdateToPlayersInExplosionAffectedZone(World world) + { + for(Object player:world.playerEntities) + { + if(player instanceof EntityPlayerMP) + { + EntityPlayerMP playerMP = (EntityPlayerMP)player; + List chunks = new ArrayList(); + chunks.addAll(this.chunksToUpdate); + playerMP.playerNetServerHandler.sendPacket(new S26PacketMapChunkBulk(chunks)); + this.chunksToUpdate.clear(); + } + } + } + + public void doExplosion(World world, int sourceX, int sourceY, int sourceZ, Set startVectors1) + { + boolean doExplosion=true; + long sourceHash = IHLUtils.getXYZHash(sourceX, sourceY, sourceZ); + Explosion explosion = new Explosion(world, null, sourceX, sourceY, sourceZ, 100f); + explosions.put(sourceHash, explosion); + while(doExplosion) + { + Set sv2=new HashSet(); + if(sv==null) + { + sv = startVectors1; + } + for(long ev:sv) + { + Set sv3 = this.breakBlocksAndGetDescendantsForEBS(world, sourceX, sourceY, sourceZ, explosion, ev); + if(sv3!=null) + { + sv2.addAll(sv3); + } + } + if(sv2.isEmpty()) + { + doExplosion=false; + sv = null; + sendChunkUpdateToPlayersInExplosionAffectedZone(world); + break; + } + else + { + sv=sv2; + } + } + + + } + + +} -- cgit v1.2.3