From 2db8e30b1d2151fdde5d08a6c06aef55f0c397d2 Mon Sep 17 00:00:00 2001 From: Foghrye4 Date: Fri, 27 Jan 2017 11:32:28 +0300 Subject: License, readme and stuff --- ihl/explosion/ExplosionVectorBlockV2.java | 552 ++++++++++++++++++++++++++++++ 1 file changed, 552 insertions(+) create mode 100644 ihl/explosion/ExplosionVectorBlockV2.java (limited to 'ihl/explosion/ExplosionVectorBlockV2.java') diff --git a/ihl/explosion/ExplosionVectorBlockV2.java b/ihl/explosion/ExplosionVectorBlockV2.java new file mode 100644 index 0000000..5d94609 --- /dev/null +++ b/ihl/explosion/ExplosionVectorBlockV2.java @@ -0,0 +1,552 @@ +package ihl.explosion; + +import ihl.IHLMod; +import ihl.utils.IHLUtils; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.Map.Entry; + +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.storage.ExtendedBlockStorage; + +public class ExplosionVectorBlockV2 +{ + public int[] startVectors = new int[1]; + private final int[][] directionMasks = new int[8][3]; + private final int bits = 8; + private final int maxValue = (1<> cachedBlockDrops = new HashMap>(128); + public final List dropBlocksPos = new ArrayList(64); + public Set chunksToUpdate=new HashSet(64); + public Map cachedDrops = new HashMap(128); + public Set dropBlocks = new HashSet(); + public Map blastWaveByDimensionId = new HashMap(); + private Entity[] cachedEntities = new Entity[maxArraySize]; + + public ExplosionVectorBlockV2() + { + this.precalculateExplosion(); + directionMasks[0] = new int[] {1,1,1}; + directionMasks[1] = new int[] {-1,1,1}; + directionMasks[2] = new int[] {1,-1,1}; + directionMasks[3] = new int[] {1,1,-1}; + directionMasks[4] = new int[] {-1,-1,1}; + directionMasks[5] = new int[] {1,-1,-1}; + directionMasks[6] = new int[] {-1,1,-1}; + directionMasks[7] = new int[] {-1,-1,-1}; + Arrays.fill(cachedBlockHardness,-1); + } + + private int encodeXYZ(int x, int y, int z) + { + return x<>bits*2,l>>bits&maxValue,l&maxValue}; + } + + public void precalculateExplosion() + { + startVectors[0]=0; + explosionPowerDampingFactor[0]=1f; + for(int levelRadius=1; levelRadiusMath.round(levelRadius*1.8f)) + { + pxyz[0]=IHLUtils.reduceVariableByAbsoluteValue(pxyz[0]); + pxyz[1]=IHLUtils.reduceVariableByAbsoluteValue(pxyz[1]); + pxyz[2]=IHLUtils.reduceVariableByAbsoluteValue(pxyz[2]); + } + else if(Math.abs(pxyz[0])<=Math.abs(pxyz[1]) && Math.abs(pxyz[0])<=Math.abs(pxyz[2])) + { + pxyz[1]=IHLUtils.reduceVariableByAbsoluteValue(pxyz[1]); + pxyz[2]=IHLUtils.reduceVariableByAbsoluteValue(pxyz[2]); + } + else if(Math.abs(pxyz[1])<=Math.abs(pxyz[0]) && Math.abs(pxyz[1])<=Math.abs(pxyz[2])) + { + pxyz[0]=IHLUtils.reduceVariableByAbsoluteValue(pxyz[0]); + pxyz[2]=IHLUtils.reduceVariableByAbsoluteValue(pxyz[2]); + } + else if(Math.abs(pxyz[2])<=Math.abs(pxyz[0]) && Math.abs(pxyz[2])<=Math.abs(pxyz[1])) + { + pxyz[1]=IHLUtils.reduceVariableByAbsoluteValue(pxyz[1]); + pxyz[0]=IHLUtils.reduceVariableByAbsoluteValue(pxyz[0]); + } + } + + public void setPower(int[] sv2, int power1) + { + for(int ev:sv2) + { + this.setPower(ev, power1); + } + } + + public void setPower(int ev, int power1) { + this.explosionPower[ev]=power1; + } + + public int[] breakBlocksAndGetDescendants(World world, int sourceX,int sourceY,int sourceZ, Explosion explosion, int ev, int[] directionMask) + { + int power1 = explosionPower[ev]; + power1 = this.getNewPowerAndProcessBlocks(world, ev, sourceX, sourceY, sourceZ, explosion, power1, directionMask); + power1 = (int)(power1*explosionPowerDampingFactor[ev])-1; + if(power1<=1 || this.vectors[ev][0]==0) + { + return null; + } + else + { + for(int d1:this.vectors[ev]) + { + if(d1!=0) + { + explosionPower[d1]=power1; + } + } + return this.vectors[ev]; + } + } + + private int getNewPowerAndProcessBlocks(World world, int ev, int sourceX, int sourceY, int sourceZ, Explosion explosion, int power2, int[] directionMask) + { + int power1=power2; + int[] xyz = decodeXYZ(ev); + int absX = xyz[0]*directionMask[0] + sourceX; + int absY = xyz[1]*directionMask[1] + sourceY; + int absZ = xyz[2]*directionMask[2] + sourceZ; + if(absY<0 || absY>=256) + { + return 0; + } + int absEBSX = absX>>4; + int absEBSZ = absZ>>4; + if(world.getChunkProvider().chunkExists(absEBSX, absEBSZ)) + { + if(world.getChunkProvider().provideChunk(absEBSX, absEBSZ).getTopFilledSegment()+24>=absY) + { + int explosionResistance = this.getBlockResistance(world, ev, absX, absY, absZ, sourceX, sourceY, sourceZ, explosion, directionMask); + if(explosionResistance>=power1) + { + if(this.cachedFluidBlocks[ev]!=0) + { + //IHLMod.log.info("Schleduling update for "+Block.getBlockById(this.cachedFluidBlocks[ev]).getUnlocalizedName()); + Block block = Block.getBlockById(this.cachedFluidBlocks[ev]); + block.onNeighborBlockChange(world, absX, absY, absZ, block); + } + else + { + this.dropBlocksPos.add(new int[] {absX, absY+1, absZ}); + } + return 0; + } + else + { + power1-=explosionResistance; + this.onBlockDestroy(world, ev, absX, absY, absZ, power1, explosion); + return power1; + } + } + else + { + return 0; + } + } + 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); + } + long chunkXZKey = ChunkCoordIntPair.chunkXZ2Int(absEBSX, absEBSZ); + blastWave.scheduleExplosionEffectsOnChunkLoad(chunkXZKey, ev, sourceX, sourceY, sourceZ, power1, directionMask); + return 0; + } + } + + public int getBlockResistance(World world, int ev, int absX, int absY, int absZ, int sourceX, int sourceY, int sourceZ, Explosion explosion, int[] directionMask) + { + if(this.cachedBlockHardness[ev]!=-1) + { + return this.cachedBlockHardness[ev]; + } + else + { + this.precacheEBSBlocks(world, absX, absY, absZ, sourceX, sourceY, sourceZ, explosion, directionMask); + return this.cachedBlockHardness[ev]; + } + } + + public void precacheEBSBlocks(World world, int absX, int absY, int absZ, int sourceX, int sourceY, int sourceZ, Explosion explosion, int[] directonMask) + { + Chunk chunk = world.getChunkProvider().provideChunk(absX>>4, absZ>>4); + List eList = this.getEntityList(chunk, absX, absY, absZ); + if(eList!=null) + { + Iterator eListI = eList.iterator(); + while(eListI.hasNext()) + { + Entity entity = eListI.next(); + int entityX = (int)entity.boundingBox.minX; + int entityY = (int)entity.boundingBox.minY; + int entityZ = (int)entity.boundingBox.minZ; + int rx = (entityX - sourceX) * directonMask[0]; + int ry = (entityY - sourceY) * directonMask[1]; + int rz = (entityZ - sourceZ) * directonMask[2]; + int ev = this.encodeXYZ(rx, ry, rz); + if(rx >= 0 && ry >= 0 && rz >= 0 && ev>=0 && ev>8) & 15)|(absY & 0xFFFFFFF0); + int blockWorldZ = ((i4>>4) & 15)|(absZ & 0xFFFFFFF0); + + int rx = (blockWorldX - sourceX) * directonMask[0]; + int ry = (blockWorldY - sourceY) * directonMask[1]; + int rz = (blockWorldZ - sourceZ) * directonMask[2]; + + int ev = this.encodeXYZ(rx, ry, rz); + if(rx >= 0 && ry >= 0 && rz >= 0 && ev>=0 && ev>8) & 15, (i4>>4) & 15) << 8; + } + int blockWorldX = (i4 & 15)|(absX & 0xFFFFFFF0); + int blockWorldY = ((i4>>8) & 15)|(absY & 0xFFFFFFF0); + int blockWorldZ = ((i4>>4) & 15)|(absZ & 0xFFFFFFF0); + int rx = (blockWorldX - sourceX) * directonMask[0]; + int ry = (blockWorldY - sourceY) * directonMask[1]; + int rz = (blockWorldZ - sourceZ) * directonMask[2]; + + int ev = this.encodeXYZ(rx, ry, rz); + if(rx >= 0 && ry >= 0 && rz >= 0 && ev>=0 && ev dropsList = (block.getDrops(world, blockWorldX, blockWorldY, blockWorldZ, ebs.getExtBlockMetadata(i4 & 15, (i4>>8) & 15, (i4>>4) & 15), 0)); + if(dropsList!=null) + { + this.cachedBlockDrops.put(ev, dropsList); + } + } + if(block.getBlockHardness(world, blockWorldX, blockWorldY, blockWorldZ)<0) + { + this.cachedBlockHardness[ev]=Integer.MAX_VALUE; + } + else if(ev==0 && directonMask[0]+directonMask[1]+directonMask[2]==3) + { + this.cachedBlockHardness[ev]=0; + } + else + { + int br=Math.round(block.getExplosionResistance(null, world, blockWorldX, blockWorldY, blockWorldZ, sourceX, sourceY, sourceZ)*10f); + this.cachedBlockHardness[ev]=br; + } + if(block.getMaterial().isLiquid()) + { + this.cachedFluidBlocks[ev]=var4; + } + } + } + } + } + + public ExtendedBlockStorage getEBS(Chunk chunk, int absX, int absY, int absZ) + { + ExtendedBlockStorage[] ebsA = chunk.getBlockStorageArray(); + ExtendedBlockStorage ebs = ebsA[absY>>4]; + if(ebs!=null) + { + this.chunksToUpdate.add(chunk); + } + return ebs; + } + + @SuppressWarnings("unchecked") + public List getEntityList(Chunk chunk, int absX, int absY, int absZ) + { + return chunk.entityLists[absY>>4]; + } + + + public void onBlockDestroy(World world, int ev, int absX,int absY,int absZ, int power, Explosion explosion) + { + Chunk chunk = world.getChunkProvider().provideChunk(absX>>4, absZ>>4); + ExtendedBlockStorage ebs = this.getEBS(chunk, absX, absY, absZ); + if(ebs==null || ebs.isEmpty()) + { + return; + } + int array_index = (absY & 15)<<8 | (absZ & 15)<<4 | (absX & 15); + if(ebs.getBlockLSBArray()[array_index] != 0 && + ebs.getBlockMSBArray()!=null && + ebs.getBlockMSBArray().get(absX & 15, absY & 15, absZ & 15) != 0) + { + ebs.blockRefCount--; + } + ebs.getBlockLSBArray()[array_index] = 0; + if(ebs.getBlockMSBArray()!=null){ + ebs.getBlockMSBArray().set(absX & 15, absY & 15, absZ & 15, 0); + } + if(this.cachedBlockDrops.containsKey(ev)) + { + Iterator drops = this.cachedBlockDrops.remove(ev).iterator(); + while(drops.hasNext()) + { + ItemStack drop = drops.next(); + int key = Item.getIdFromItem(drop.getItem())^(drop.getItemDamage()<<16); + if(this.cachedDrops.containsKey(key)) + { + this.cachedDrops.get(key).stackSize+=drop.stackSize; + } + else + { + this.cachedDrops.put(key, drop); + } + } + } + Entity victim = this.cachedEntities[ev]; + if(victim!=null) + { + victim.attackEntityFrom(DamageSource.setExplosionSource(explosion), power/10f); + this.cachedEntities[ev]=null; + } + this.dropBlocks.add(ev); + } + + private void addDrops(World world, int sourceX, int sourceY, int sourceZ, int[] directionMask) + { + Iterator> di = this.cachedDrops.entrySet().iterator(); + Entry cde = di.next(); + while(di.hasNext() && this.dropBlocksPos.size() > 0) + { + int[] xyz = this.dropBlocksPos.remove(this.dropBlocksPos.size()-1); + int x = xyz[0]; + int y = xyz[1]; + int z = xyz[2]; + int rx = (x - sourceX) * directionMask[0]; + int ry = (y - sourceY) * directionMask[1]; + int rz = (z - sourceZ) * directionMask[2]; + int ev = encodeXYZ(rx,ry,rz); + int ev2 = encodeXYZ(rx,ry-1,rz); + if(this.dropBlocks.contains(ev) && !this.dropBlocks.contains(ev2)) + { + ItemStack stack = cde.getValue(); + if(stack!=null && stack.getItem()!=null && stack.stackSize>0) + { + if(stack.stackSize <= stack.getMaxStackSize()) + { + if(stack.stackSize>0) + { + PileTileEntity pte = new PileTileEntity(); + pte.xCoord=x; + pte.yCoord=y; + pte.zCoord=z; + pte.setWorldObj(world); + pte.validate(); + pte.setContent(stack); + IHLUtils.setBlockAndTileEntityRaw(world, x, y, z, PileBlock.instance, pte); + } + di.remove(); + if(di.hasNext()) + { + cde = di.next(); + } + else + { + return; + } + } + else + { + ItemStack stack1=stack.copy(); + stack1.stackSize=stack.getMaxStackSize(); + PileTileEntity pte = new PileTileEntity(); + pte.content=stack1; + IHLUtils.setBlockAndTileEntityRaw(world, x, y, z, PileBlock.instance, pte); + stack.stackSize-=stack.getMaxStackSize(); + } + } + } + } + } + + public void sendChunkUpdateToPlayersInExplosionAffectedZone(World world, int sourceX, int sourceY, int sourceZ) + { +// Set clientSideChunkXZKeySet = new HashSet(); + Iterator ci = this.chunksToUpdate.iterator(); + while(ci.hasNext()) + { + Chunk chunk = ci.next(); + chunk.generateSkylightMap(); + Arrays.fill(chunk.updateSkylightColumns, true); + chunk.func_150804_b(false); +// long chunkXZKey = ChunkCoordIntPair.chunkXZ2Int(chunk.xPosition, chunk.zPosition); +// clientSideChunkXZKeySet.add(chunkXZKey); + } + List chunks = new ArrayList(); + chunks.addAll(this.chunksToUpdate); + for(Object player:world.playerEntities) + { + if(player instanceof EntityPlayerMP) + { + EntityPlayerMP playerMP = (EntityPlayerMP)player; + playerMP.playerNetServerHandler.sendPacket(new S26PacketMapChunkBulk(chunks)); + } + } +// IHLMod.proxy.sendChunksLightUpdateQuery(world, sourceX, sourceY, sourceZ, clientSideChunkXZKeySet); + this.chunksToUpdate.clear(); + } + + public void doExplosion(World world, int sourceX, int sourceY, int sourceZ, final int[] startVectors1, int[] directionMask, Explosion explosion) + { + boolean doExplosion=true; + int[] sv = null; + int svsize = 0; + while(doExplosion) + { + int[] sv2= new int[1<