package com.hbm.explosion; import java.util.ArrayList; import java.util.List; import net.minecraft.init.Blocks; import net.minecraft.util.Vec3; import net.minecraft.world.World; public class ExplosionNukeRay { List affectedBlocks = new ArrayList<>(); int posX; int posY; int posZ; World world; int strength; int length; int processed; int gspNumMax; int gspNum; double gspX; double gspY; public boolean isAusf3Complete = false; /*[[unused]] int count; int speed; int startY; int startCir; Random rand = new Random(); private double overrideRange = 0; */ public ExplosionNukeRay(World world, int x, int y, int z, int strength, int count, int speed, int length) { this.world = world; this.posX = x; this.posY = y; this.posZ = z; this.strength = strength; this.length = length; //Ausf3, must be double //Mk 4.5, must be int32 // Total number of points this.gspNumMax = (int)(2.5 * Math.PI * Math.pow(this.strength,2)); this.gspNum = 1; // The beginning of the generalized spiral points this.gspX = Math.PI; this.gspY = 0.0; /*[[unused]] // this.startY = strength; this.startY = 0; this.startCir = 0; this.count = count; this.speed = speed; //starts at around 80, becomes 8 at length 500 this.overrideRange = Math.max((Math.log(length) * 4 - 2.5D) * 10, 0); */ } // Raise one generalized spiral points private void generateGspUp(){ if (this.gspNum < this.gspNumMax) { int k = this.gspNum + 1; double hk = -1.0 + 2.0 * (k - 1.0) / (this.gspNumMax - 1.0); this.gspX = Math.acos(hk); double prev_lon = this.gspY; double lon = prev_lon + 3.6 / Math.sqrt(this.gspNumMax) / Math.sqrt(1.0 - hk * hk); this.gspY = lon % (Math.PI * 2); } else { this.gspX = 0.0; this.gspY = 0.0; } this.gspNum++; } // Get Cartesian coordinates for spherical coordinates private Vec3 getSpherical2cartesian(){ double dx = Math.sin(this.gspX) * Math.cos(this.gspY); double dz = Math.sin(this.gspX) * Math.sin(this.gspY); double dy = Math.cos(this.gspX); return Vec3.createVectorHelper(dx, dy, dz); } //currently used by mk4 public void collectTipMk4_5(int count) { int amountProcessed = 0; while (this.gspNumMax >= this.gspNum){ // Get Cartesian coordinates for spherical coordinates Vec3 vec = this.getSpherical2cartesian(); int length = (int)Math.ceil(strength); float res = strength; FloatTriplet lastPos = null; for(int i = 0; i < length; i ++) { if(i > this.length) break; float x0 = (float) (posX + (vec.xCoord * i)); float y0 = (float) (posY + (vec.yCoord * i)); float z0 = (float) (posZ + (vec.zCoord * i)); double fac = 100 - ((double) i) / ((double) length) * 100; fac *= 0.07D; if(!world.getBlock((int)x0, (int)y0, (int)z0).getMaterial().isLiquid()) res -= Math.pow(world.getBlock((int)x0, (int)y0, (int)z0).getExplosionResistance(null), 7.5D - fac); else res -= Math.pow(Blocks.air.getExplosionResistance(null), 7.5D - fac); if(res > 0 && world.getBlock((int)x0, (int)y0, (int)z0) != Blocks.air) { lastPos = new FloatTriplet(x0, y0, z0); } if(res <= 0 || i + 1 >= this.length) { if(affectedBlocks.size() < Integer.MAX_VALUE - 100 && lastPos != null) { affectedBlocks.add(lastPos); } break; } } // Raise one generalized spiral points this.generateGspUp(); amountProcessed++; if(amountProcessed >= count) { return; } } isAusf3Complete = true; } public void processTip(int count) { int processedBlocks = 0; int braker = 0; for(int l = 0; l < Integer.MAX_VALUE; l++) { if(processedBlocks >= count) return; if(braker >= count * 50) return; if(l > affectedBlocks.size() - 1) break; if(affectedBlocks.isEmpty()) return; int in = affectedBlocks.size() - 1; float x = affectedBlocks.get(in).xCoord; float y = affectedBlocks.get(in).yCoord; float z = affectedBlocks.get(in).zCoord; world.setBlock((int)x, (int)y, (int)z, Blocks.air); Vec3 vec = Vec3.createVectorHelper(x - this.posX, y - this.posY, z - this.posZ); double pX = vec.xCoord / vec.lengthVector(); double pY = vec.yCoord / vec.lengthVector(); double pZ = vec.zCoord / vec.lengthVector(); for(int i = 0; i < vec.lengthVector(); i ++) { int x0 = (int)(posX + pX * i); int y0 = (int)(posY + pY * i); int z0 = (int)(posZ + pZ * i); if(!world.isAirBlock(x0, y0, z0)) { world.setBlock(x0, y0, z0, Blocks.air); processedBlocks++; } braker++; } affectedBlocks.remove(in); } processed += count; } /*public void processBunch(int count) { for(int l = processed; l < processed + count; l++) { if(l > affectedBlocks.size() - 1) break; int x = affectedBlocks.get(l).chunkPosX; int y = affectedBlocks.get(l).chunkPosY; int z = affectedBlocks.get(l).chunkPosZ; if(world.getBlock(x, y, z) != Blocks.air) { world.setBlock(x, y, z, Blocks.air); } } processed += count; } public void collectBunch(int count) { for(int k = 0; k < count; k++) { double phi = rand.nextDouble() * (Math.PI * 2); double costheta = rand.nextDouble() * 2 - 1; double theta = Math.acos(costheta); double x = Math.sin( theta) * Math.cos( phi ); double y = Math.sin( theta) * Math.sin( phi ); double z = Math.cos( theta ); Vec3 vec = Vec3.createVectorHelper(x, y, z); int length = (int)Math.ceil(strength); float res = strength; for(int i = 0; i < length; i ++) { if(i > this.length) break; int x0 = (int)(posX + (vec.xCoord * i)); int y0 = (int)(posY + (vec.yCoord * i)); int z0 = (int)(posZ + (vec.zCoord * i)); if(!world.getBlock(x0, y0, z0).getMaterial().isLiquid()) res -= Math.pow(world.getBlock(x0, y0, z0).getExplosionResistance(null), 1.25); else res -= Math.pow(Blocks.air.getExplosionResistance(null), 1.25); if(res > 0 && world.getBlock(x0, y0, z0) != Blocks.air) { if(affectedBlocks.size() < Integer.MAX_VALUE - 100) affectedBlocks.add(new ChunkPosition(x0, y0, z0)); } } } }*/ /* @Untested //override range public void collectTip(int count) { for(int k = 0; k < count; k++) { double phi = rand.nextDouble() * (Math.PI * 2); double costheta = rand.nextDouble() * 2 - 1; double theta = Math.acos(costheta); double x = Math.sin(theta) * Math.cos(phi); double y = Math.sin(theta) * Math.sin(phi); double z = Math.cos(theta); Vec3 vec = Vec3.createVectorHelper(x, y, z); int length = (int)Math.ceil(strength); float res = strength; FloatTriplet lastPos = null; for(int i = 0; i < length; i ++) { if(i > this.length) break; float x0 = (float) (posX + (vec.xCoord * i)); float y0 = (float) (posY + (vec.yCoord * i)); float z0 = (float) (posZ + (vec.zCoord * i)); if(!world.getBlock((int)x0, (int)y0, (int)z0).getMaterial().isLiquid()) res -= Math.pow(world.getBlock((int)x0, (int)y0, (int)z0).getExplosionResistance(null), 1.25); else res -= Math.pow(Blocks.air.getExplosionResistance(null), 1.25); //Blast resistance calculations are still done to preserve the general shape, //but if the blast were to be stopped within this range we go through with it anyway. //There is currently no blast resistance limit on this, could change in the future. boolean inOverrideRange = this.overrideRange >= length; if((res > 0 || inOverrideRange) && world.getBlock((int)x0, (int)y0, (int)z0) != Blocks.air) { lastPos = new FloatTriplet(x0, y0, z0); } // Only stop if we are either out of range or if the remaining strength is 0 while being outside the override range if((res <= 0 && !inOverrideRange) || i + 1 >= this.length) { if(affectedBlocks.size() < Integer.MAX_VALUE - 100 && lastPos != null) affectedBlocks.add(new FloatTriplet(lastPos.xCoord, lastPos.yCoord, lastPos.zCoord)); break; } } } } */ /* public void collectTipExperimental(int count) { for(int k = 0; k < count; k++) { double phi = rand.nextDouble() * (Math.PI * 2); double costheta = rand.nextDouble() * 2 - 1; double theta = Math.acos(costheta); double x = Math.sin(theta) * Math.cos(phi); double y = Math.sin(theta) * Math.sin(phi); double z = Math.cos(theta); Vec3 vec = Vec3.createVectorHelper(x, y, z); int length = (int)Math.ceil(strength); float res = strength; FloatTriplet lastPos = null; for(int i = 0; i < length; i ++) { if(i > this.length) break; float x0 = (float) (posX + (vec.xCoord * i)); float y0 = (float) (posY + (vec.yCoord * i)); float z0 = (float) (posZ + (vec.zCoord * i)); double fac = 100 - ((double) i) / ((double) length) * 100; fac *= 0.07D; if(!world.getBlock((int)x0, (int)y0, (int)z0).getMaterial().isLiquid()) res -= Math.pow(world.getBlock((int)x0, (int)y0, (int)z0).getExplosionResistance(null), 7.5D - fac); else res -= Math.pow(Blocks.air.getExplosionResistance(null), 7.5D - fac); if(res > 0 && world.getBlock((int)x0, (int)y0, (int)z0) != Blocks.air) { lastPos = new FloatTriplet(x0, y0, z0); } if(res <= 0 || i + 1 >= this.length) { if(affectedBlocks.size() < Integer.MAX_VALUE - 100 && lastPos != null) affectedBlocks.add(new FloatTriplet(lastPos.xCoord, lastPos.yCoord, lastPos.zCoord)); break; } } } } */ /*public void collectTipAusf3(int count) { int amountProcessed = 0; //Axial //StartY starts at this.length for(double y = startY; y >= -strength; y -= (0.35D + ( Math.pow((strength - Math.abs(y)) / strength, 1.5D) * 0.3D))) { double sectionRad = Math.sqrt(Math.pow(strength, 2) - Math.pow(y, 2)); double circumference = (1.5 * Math.PI * sectionRad + rand.nextDouble()) * (sectionRad / strength + 0.1D); //circumference = Math.ceil(circumference); //Radial //StartCir starts at circumference for(int r = startCir; r < circumference; r ++) { Vec3 vec = Vec3.createVectorHelper(sectionRad, y, 0); vec = vec.normalize(); if(y > 0) vec.rotateAroundZ((float) (y / sectionRad) * 0.15F); if(y < 0) vec.rotateAroundZ((float) (y / sectionRad) * -0.15F); vec.rotateAroundY((float) (360 / circumference * r)); int length = (int)Math.ceil(strength); float res = strength; FloatTriplet lastPos = null; for(int i = 0; i < length; i ++) { if(i > this.length) break; float x0 = (float) (posX + (vec.xCoord * i)); float y0 = (float) (posY + (vec.yCoord * i)); float z0 = (float) (posZ + (vec.zCoord * i)); double fac = 100 - ((double) i) / ((double) length) * 100; fac *= 0.07D; if(!world.getBlock((int)x0, (int)y0, (int)z0).getMaterial().isLiquid()) res -= Math.pow(world.getBlock((int)x0, (int)y0, (int)z0).getExplosionResistance(null), 7.5D - fac); else res -= Math.pow(Blocks.air.getExplosionResistance(null), 7.5D - fac); if(res > 0 && world.getBlock((int)x0, (int)y0, (int)z0) != Blocks.air) { lastPos = new FloatTriplet(x0, y0, z0); } if(res <= 0 || i + 1 >= this.length) { if(affectedBlocks.size() < Integer.MAX_VALUE - 100 && lastPos != null) { affectedBlocks.add(new FloatTriplet(lastPos.xCoord, lastPos.yCoord, lastPos.zCoord)); } break; } } amountProcessed++; if(amountProcessed >= count) { startY = y + 1; startCir = startCir + 1; return; } } } isAusf3Complete = true; }*/ //Dysfunctional, punches hole into ground /*public void collectTipAusf3(int count) { int amountProcessed = 0; //Axial //StartY starts at this.length for(int y = startY; y >= -length; y--) { double circumference = 2 * Math.PI * Math.sqrt(Math.pow(y, 2) + Math.pow(length, 2)); circumference = Math.ceil(circumference); //Radial //StartCir starts at circumference for(int r = startCir; r < circumference; r ++) { Vec3 vec = Vec3.createVectorHelper(1, y, 0); vec.normalize(); vec.rotateAroundY((float) (360 / circumference * r)); int length = (int)Math.ceil(strength); float res = strength; FloatTriplet lastPos = null; for(int i = 0; i < length; i ++) { if(i > this.length) break; float x0 = (float) (posX + (vec.xCoord * i)); float y0 = (float) (posY + (vec.yCoord * i)); float z0 = (float) (posZ + (vec.zCoord * i)); double fac = 100 - ((double) i) / ((double) length) * 100; fac *= 0.07D; if(!world.getBlock((int)x0, (int)y0, (int)z0).getMaterial().isLiquid()) res -= Math.pow(world.getBlock((int)x0, (int)y0, (int)z0).getExplosionResistance(null), 7.5D - fac); else res -= Math.pow(Blocks.air.getExplosionResistance(null), 7.5D - fac); if(res > 0 && world.getBlock((int)x0, (int)y0, (int)z0) != Blocks.air) { lastPos = new FloatTriplet(x0, y0, z0); } if(res <= 0 || i + 1 >= this.length) { if(affectedBlocks.size() < Integer.MAX_VALUE - 100 && lastPos != null) affectedBlocks.add(new FloatTriplet(lastPos.xCoord, lastPos.yCoord, lastPos.zCoord)); break; } } amountProcessed++; if(amountProcessed >= count) { startY = y + 1; startCir = startCir + 1; return; } } } isAusf3Complete = true; }*/ public void deleteStorage() { this.affectedBlocks.clear(); } public int getStoredSize() { return this.affectedBlocks.size(); } public int getProgress() { return this.processed; } public class FloatTriplet { public float xCoord; public float yCoord; public float zCoord; public FloatTriplet(float x, float y, float z) { xCoord = x; yCoord = y; zCoord = z; } } }