From aef2396adc92dd52649c938a3ef0731069ff430a Mon Sep 17 00:00:00 2001 From: AlgorithmX2 Date: Thu, 7 Aug 2014 01:47:42 -0500 Subject: [PATCH] Scary Meteorite Re-write. --- core/WorldSettings.java | 127 +++++++++++ debug/ToolMeteoritePlacer.java | 2 +- helpers/MeteoritePlacer.java | 383 +++++++++++++++++++++++++++++---- hooks/MeteoriteWorldGen.java | 133 +++++++++--- hooks/TickHandler.java | 11 + services/CompassService.java | 37 +++- spatial/CachedPlane.java | 45 +--- util/Platform.java | 48 +++++ 8 files changed, 663 insertions(+), 123 deletions(-) diff --git a/core/WorldSettings.java b/core/WorldSettings.java index 364d206f..45a3fc5b 100644 --- a/core/WorldSettings.java +++ b/core/WorldSettings.java @@ -1,13 +1,19 @@ package appeng.core; import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; import java.io.IOException; import java.lang.ref.WeakReference; import java.util.ArrayList; +import java.util.Collection; +import java.util.LinkedList; import java.util.List; import java.util.WeakHashMap; import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.nbt.CompressedStreamTools; +import net.minecraft.nbt.NBTTagCompound; import net.minecraftforge.common.DimensionManager; import net.minecraftforge.common.config.ConfigCategory; import net.minecraftforge.common.config.Configuration; @@ -41,6 +47,10 @@ public class WorldSettings extends Configuration compass = new CompassService( AEFolder ); + File spawnData = new File( AEFolder, "spawndata" ); + if ( !spawnData.exists() || !spawnData.isDirectory() ) + spawnData.mkdir(); + for (int dimID : get( "DimensionManager", "StorageCells", new int[0] ).getIntList()) { storageCellDims.add( dimID ); @@ -59,6 +69,123 @@ public class WorldSettings extends Configuration } } + NBTTagCompound loadSpawnData(int dim, int chunkX, int chunkZ) + { + if ( !Thread.holdsLock( WorldSettings.class ) ) + throw new RuntimeException( "Invalid Request" ); + + File f = new File( AEFolder, "spawndata" + File.separatorChar + dim + "_" + (chunkX >> 4) + "_" + (chunkZ >> 4) + ".dat" ); + + if ( f.isFile() && f.exists() ) + { + // open + FileInputStream fis; + try + { + fis = new FileInputStream( f ); + NBTTagCompound data = CompressedStreamTools.readCompressed( fis ); + fis.close(); + + return data; + } + catch (Throwable e) + { + + } + + } + + return new NBTTagCompound(); + } + + void writeSpawnData(int dim, int chunkX, int chunkZ, NBTTagCompound data) + { + if ( !Thread.holdsLock( WorldSettings.class ) ) + throw new RuntimeException( "Invalid Request" ); + + File f = new File( AEFolder, "spawndata" + File.separatorChar + dim + "_" + (chunkX >> 4) + "_" + (chunkZ >> 4) + ".dat" ); + + try + { + // save + FileOutputStream fos = new FileOutputStream( f ); + CompressedStreamTools.writeCompressed( data, fos ); + fos.close(); + } + catch (Throwable e) + { + + } + } + + public Collection getNearByMetetorites(int dim, int chunkX, int chunkZ) + { + LinkedList ll = new LinkedList(); + + synchronized (WorldSettings.class) + { + for (int x = -1; x <= 1; x++) + { + for (int z = -1; z <= 1; z++) + { + int cx = x + (chunkX >> 4); + int cz = z + (chunkZ >> 4); + + NBTTagCompound data = loadSpawnData( dim, cx << 4, cz << 4 ); + + if ( data != null ) + { + // edit. + int size = data.getInteger( "num" ); + for (int s = 0; s < size; s++) + ll.add( data.getCompoundTag( "" + s ) ); + } + } + } + } + + return ll; + } + + public boolean hasGenerated(int dim, int chunkX, int chunkZ) + { + synchronized (WorldSettings.class) + { + NBTTagCompound data = loadSpawnData( dim, chunkX, chunkZ ); + return data.getBoolean( chunkX + "," + chunkZ ); + } + } + + public void setGenerated(int dim, int chunkX, int chunkZ) + { + synchronized (WorldSettings.class) + { + NBTTagCompound data = loadSpawnData( dim, chunkX, chunkZ ); + + // edit. + data.setBoolean( chunkX + "," + chunkZ, true ); + + writeSpawnData( dim, chunkX, chunkZ, data ); + } + } + + public boolean addNearByMetetorites(int dim, int chunkX, int chunkZ, NBTTagCompound newData) + { + synchronized (WorldSettings.class) + { + NBTTagCompound data = loadSpawnData( dim, chunkX, chunkZ ); + + // edit. + int size = data.getInteger( "num" ); + data.setTag( "" + size, newData ); + data.setInteger( "num", size + 1 ); + + writeSpawnData( dim, chunkX, chunkZ, data ); + + return true; + } + } + public void shutdown() { save(); diff --git a/debug/ToolMeteoritePlacer.java b/debug/ToolMeteoritePlacer.java index 1dbe65b3..d3c3f5e0 100644 --- a/debug/ToolMeteoritePlacer.java +++ b/debug/ToolMeteoritePlacer.java @@ -28,7 +28,7 @@ public class ToolMeteoritePlacer extends AEBaseItem return false; MeteoritePlacer mp = new MeteoritePlacer(); - boolean worked = mp.spawnMeteorite( world, x, y, z ); + boolean worked = mp.spawnMeteorite( new MeteoritePlacer.StandardWorld( world ), x, y, z ); if ( !worked ) player.addChatMessage( new ChatComponentText( "Un-suiteable Location." ) ); diff --git a/helpers/MeteoritePlacer.java b/helpers/MeteoritePlacer.java index 7bd6a241..016e87ae 100644 --- a/helpers/MeteoritePlacer.java +++ b/helpers/MeteoritePlacer.java @@ -10,9 +10,11 @@ import net.minecraft.entity.item.EntityItem; import net.minecraft.init.Blocks; import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.AxisAlignedBB; import net.minecraft.world.World; +import net.minecraft.world.chunk.Chunk; import net.minecraftforge.common.util.ForgeDirection; import net.minecraftforge.oredict.OreDictionary; import appeng.api.AEApi; @@ -31,7 +33,7 @@ public class MeteoritePlacer return 0; } - public void getRandomFall(World w, int x, int y, int z) + public void getRandomFall(IMetroiteWorld w, int x, int y, int z) { double a = Math.random(); if ( a > 0.9 ) @@ -44,7 +46,7 @@ public class MeteoritePlacer put( w, x, y, z, Blocks.gravel ); } - public void getRandomInset(World w, int x, int y, int z) + public void getRandomInset(IMetroiteWorld w, int x, int y, int z) { double a = Math.random(); if ( a > 0.9 ) @@ -69,17 +71,17 @@ public class MeteoritePlacer Block blk; int meta; - public FalloutCopy(World w, int x, int y, int z) { + public FalloutCopy(IMetroiteWorld w, int x, int y, int z) { blk = w.getBlock( x, y, z ); meta = w.getBlockMetadata( x, y, z ); } - public void getOther(World w, int x, int y, int z, double a) + public void getOther(IMetroiteWorld w, int x, int y, int z, double a) { } - public void getRandomFall(World w, int x, int y, int z) + public void getRandomFall(IMetroiteWorld w, int x, int y, int z) { double a = Math.random(); if ( a > 0.9 ) @@ -88,7 +90,7 @@ public class MeteoritePlacer getOther( w, x, y, z, a ); } - public void getRandomInset(World w, int x, int y, int z) + public void getRandomInset(IMetroiteWorld w, int x, int y, int z) { double a = Math.random(); if ( a > 0.9 ) @@ -103,7 +105,7 @@ public class MeteoritePlacer private class FalloutSand extends FalloutCopy { - public FalloutSand(World w, int x, int y, int z) { + public FalloutSand(IMetroiteWorld w, int x, int y, int z) { super( w, x, y, z ); } @@ -112,7 +114,7 @@ public class MeteoritePlacer return 2; } - public void getOther(World w, int x, int y, int z, double a) + public void getOther(IMetroiteWorld w, int x, int y, int z, double a) { if ( a > 0.66 ) put( w, x, y, z, Blocks.glass ); @@ -123,7 +125,7 @@ public class MeteoritePlacer private class FalloutSnow extends FalloutCopy { - public FalloutSnow(World w, int x, int y, int z) { + public FalloutSnow(IMetroiteWorld w, int x, int y, int z) { super( w, x, y, z ); } @@ -132,7 +134,7 @@ public class MeteoritePlacer return 2; } - public void getOther(World w, int x, int y, int z, double a) + public void getOther(IMetroiteWorld w, int x, int y, int z, double a) { if ( a > 0.7 ) put( w, x, y, z, Blocks.snow ); @@ -142,6 +144,231 @@ public class MeteoritePlacer }; + public interface IMetroiteWorld + { + + int minX(int in); + + int minZ(int in); + + int maxX(int in); + + int maxZ(int in); + + boolean hasNoSky(); + + int getBlockMetadata(int x, int y, int z); + + Block getBlock(int x, int y, int z); + + boolean canBlockSeeTheSky(int i, int j, int k); + + TileEntity getTileEntity(int x, int y, int z); + + World getWorld(); + + void setBlock(int i, int j, int k, Block blk); + + void setBlock(int i, int j, int k, Block blk_b, int meta_b, int l); + + void done(); + + }; + + static public class StandardWorld implements IMetroiteWorld + { + + protected World w; + + public StandardWorld(World w) { + this.w = w; + } + + @Override + public boolean hasNoSky() + { + return !w.provider.hasNoSky; + } + + @Override + public int getBlockMetadata(int x, int y, int z) + { + if ( range( x, y, z ) ) + return w.getBlockMetadata( x, y, z ); + return 0; + } + + @Override + public Block getBlock(int x, int y, int z) + { + if ( range( x, y, z ) ) + return w.getBlock( x, y, z ); + return Platform.air; + } + + @Override + public boolean canBlockSeeTheSky(int x, int y, int z) + { + if ( range( x, y, z ) ) + return w.canBlockSeeTheSky( x, y, z ); + return false; + } + + @Override + public TileEntity getTileEntity(int x, int y, int z) + { + if ( range( x, y, z ) ) + return w.getTileEntity( x, y, z ); + return null; + } + + @Override + public World getWorld() + { + return w; + } + + @Override + public void setBlock(int x, int y, int z, Block blk) + { + if ( range( x, y, z ) ) + w.setBlock( x, y, z, blk ); + } + + @Override + public void setBlock(int x, int y, int z, Block blk, int metadata, int flags) + { + if ( range( x, y, z ) ) + w.setBlock( x, y, z, blk, metadata, flags ); + } + + public boolean range(int x, int y, int z) + { + return true; + } + + @Override + public int minX(int in) + { + return in; + } + + @Override + public int minZ(int in) + { + return in; + } + + @Override + public int maxX(int in) + { + return in; + } + + @Override + public int maxZ(int in) + { + return in; + } + + @Override + public void done() + { + + } + + } + + static public class ChunkOnly extends StandardWorld + { + + Chunk target; + + int verticalBits = 0; + + final int cx, cz; + + public ChunkOnly(World w, int cx, int cz) { + super( w ); + target = w.getChunkFromChunkCoords( cx, cz ); + this.cx = cx; + this.cz = cz; + } + + @Override + public void done() + { + if ( verticalBits != 0 ) + Platform.sendChunk( target, verticalBits ); + } + + @Override + public void setBlock(int x, int y, int z, Block blk) + { + if ( range( x, y, z ) ) + { + verticalBits |= 1 << (y >> 4); + w.setBlock( x, y, z, blk, 0, 1 ); + } + } + + @Override + public void setBlock(int x, int y, int z, Block blk, int metadata, int flags) + { + if ( range( x, y, z ) ) + { + verticalBits |= 1 << (y >> 4); + w.setBlock( x, y, z, blk, metadata, flags & (~2) ); + } + } + + @Override + public Block getBlock(int x, int y, int z) + { + if ( range( x, y, z ) ) + return target.getBlock( x & 0xF, y, z & 0xF ); + return Platform.air; + } + + @Override + public int getBlockMetadata(int x, int y, int z) + { + if ( range( x, y, z ) ) + return target.getBlockMetadata( x & 0xF, y, z & 0xF ); + return 0; + } + + @Override + public boolean range(int x, int y, int z) + { + return cx == (x >> 4) && cz == (z >> 4); + } + + @Override + public int minX(int in) + { + return Math.max( in, cx << 4 ); + } + + @Override + public int minZ(int in) + { + return Math.max( in, cz << 4 ); + } + + @Override + public int maxX(int in) + { + return Math.min( in, (cx + 1) << 4 ); + } + + @Override + public int maxZ(int in) + { + return Math.min( in, (cz + 1) << 4 ); + } + }; + int minBLocks = 200; HashSet validSpawn = new HashSet(); HashSet invalidSpawn = new HashSet(); @@ -191,17 +418,78 @@ public class MeteoritePlacer invalidSpawn.add( Blocks.log2 ); } - public boolean spawnMeteorite(World w, int x, int y, int z) + NBTTagCompound settings; + + public boolean spawnMeteorite(IMetroiteWorld w, NBTTagCompound metoriteBlob) + { + settings = metoriteBlob; + + int x = settings.getInteger( "x" ); + int y = settings.getInteger( "y" ); + int z = settings.getInteger( "z" ); + + real_sizeOfMetorite = settings.getDouble( "real_sizeOfMetorite" ); + real_crator = settings.getDouble( "real_crator" ); + sizeOfMetorite = settings.getDouble( "sizeOfMetorite" ); + crator = settings.getDouble( "crator" ); + + Block blk = Block.getBlockById( settings.getInteger( "blk" ) ); + + if ( blk == Blocks.sand ) + type = new FalloutSand( w, x, y, z ); + else if ( blk == Blocks.hardened_clay ) + type = new FalloutCopy( w, x, y, z ); + else if ( blk == Blocks.ice || blk == Blocks.snow ) + type = new FalloutSnow( w, x, y, z ); + + int skyMode = settings.getInteger( "skyMode" ); + + // creator + if ( skyMode > 10 ) + placeCrator( w, x, y, z ); + + placeMetor( w, x, y, z ); + + // collapse blocks... + if ( skyMode > 3 ) + Decay( w, x, y, z ); + + w.done(); + return true; + } + + public double getSqDistance(int x, int z) + { + int Cx = settings.getInteger( "x" ) - x; + int Cz = settings.getInteger( "z" ) - z; + + return Cx * Cx + Cz * Cz; + } + + public boolean spawnMeteorite(IMetroiteWorld w, int x, int y, int z) { int validBlocks = 0; - if ( w.provider.hasNoSky ) + if ( !w.hasNoSky() ) return false; Block blk = w.getBlock( x, y, z ); if ( !validSpawn.contains( blk ) ) return false; // must spawn on a valid block.. + settings = new NBTTagCompound(); + settings.setInteger( "x", x ); + settings.setInteger( "y", y ); + settings.setInteger( "z", z ); + settings.setInteger( "blk", Block.getIdFromBlock( blk ) ); + + settings.setDouble( "real_sizeOfMetorite", real_sizeOfMetorite ); + settings.setDouble( "real_crator", real_crator ); + settings.setDouble( "sizeOfMetorite", sizeOfMetorite ); + settings.setDouble( "crator", crator ); + + settings.setBoolean( "lava", Math.random() > 0.9 ); + if ( blk == Blocks.sand ) type = new FalloutSand( w, x, y, z ); else if ( blk == Blocks.hardened_clay ) @@ -265,20 +553,24 @@ public class MeteoritePlacer if ( skyMode > 3 ) Decay( w, x, y, z ); + settings.setInteger( "skyMode", skyMode ); + w.done(); + + WorldSettings.getInstance().addNearByMetetorites( w.getWorld().provider.dimensionId, x >> 4, z >> 4, settings ); return true; } return false; } - private void placeCrator(World w, int x, int y, int z) + private void placeCrator(IMetroiteWorld w, int x, int y, int z) { - boolean lava = Math.random() > 0.9; + boolean lava = settings.getBoolean( "lava" ); - int maxY = Math.min( y + 20, 255 ); - int minX = x - 40; - int maxX = x + 40; - int minZ = z - 40; - int maxZ = z + 40; + int maxY = 255; + int minX = w.minX( x - 200 ); + int maxX = w.maxX( x + 200 ); + int minZ = w.minZ( z - 200 ); + int maxZ = w.maxZ( z + 200 ); for (int j = y - 5; j < maxY; j++) { @@ -295,7 +587,7 @@ public class MeteoritePlacer if ( j > h + distanceFrom * 0.02 ) { - if ( lava && j < y && w.getBlock( x, y - 1, z ).isBlockSolid( w, i, j, k, 0 ) ) + if ( lava && j < y && w.getBlock( x, y - 1, z ).isBlockSolid( w.getWorld(), i, j, k, 0 ) ) { if ( j > h + distanceFrom * 0.02 ) put( w, i, j, k, Blocks.lava ); @@ -304,32 +596,27 @@ public class MeteoritePlacer changed = put( w, i, j, k, Platform.air ) || changed; } } - - if ( changed && j > maxY - 5 ) - { - maxY = Math.min( maxY + 5, 255 ); - - minX -= 7; - maxX += 7; - - minZ -= 7; - maxZ += 7; - } } - for (Object o : w.getEntitiesWithinAABB( EntityItem.class, AxisAlignedBB.getBoundingBox( x - 30, y - 5, z - 30, x + 30, y + 30, z + 30 ) )) + for (Object o : w.getWorld().getEntitiesWithinAABB( EntityItem.class, + AxisAlignedBB.getBoundingBox( w.minX( x - 30 ), y - 5, w.minZ( z - 30 ), w.maxX( x + 30 ), y + 30, w.maxZ( z + 30 ) ) )) { Entity e = (Entity) o; e.setDead(); } } - private void placeMetor(World w, int x, int y, int z) + private void placeMetor(IMetroiteWorld w, int x, int y, int z) { + int Xmeteor_l = w.minX( x - 8 ); + int Xmeteor_h = w.maxX( x + 8 ); + int Zmeteor_l = w.minZ( z - 8 ); + int Zmeteor_h = w.maxZ( z + 8 ); + // spawn metor - for (int i = x - 8; i < x + 8; i++) + for (int i = Xmeteor_l; i < Xmeteor_h; i++) for (int j = y - 8; j < y + 8; j++) - for (int k = z - 8; k < z + 8; k++) + for (int k = Zmeteor_l; k < Zmeteor_h; k++) { double dx = i - x; double dy = j - y; @@ -341,7 +628,7 @@ public class MeteoritePlacer put( w, x, y, z, skychest ); TileEntity te = w.getTileEntity( x, y, z ); - if ( te instanceof IInventory ) + if ( te != null && te instanceof IInventory ) { InventoryAdaptor ap = InventoryAdaptor.getAdaptor( te, ForgeDirection.UP ); @@ -428,19 +715,24 @@ public class MeteoritePlacer } } - private void Decay(World w, int x, int y, int z) + private void Decay(IMetroiteWorld w, int x, int y, int z) { double randomShit = 0; - for (int i = x - 30; i < x + 30; i++) - for (int k = z - 30; k < z + 30; k++) + int Xmeteor_l = w.minX( x - 30 ); + int Xmeteor_h = w.maxX( x + 30 ); + int Zmeteor_l = w.minZ( z - 30 ); + int Zmeteor_h = w.maxZ( z + 30 ); + + for (int i = Xmeteor_l; i < Xmeteor_h; i++) + for (int k = Zmeteor_l; k < Zmeteor_h; k++) for (int j = y - 9; j < y + 30; j++) { Block blk = w.getBlock( i, j, k ); if ( blk == Blocks.lava ) continue; - if ( blk.isReplaceable( w, i, j, k ) ) + if ( blk.isReplaceable( w.getWorld(), i, j, k ) ) { blk = Platform.air; Block blk_b = w.getBlock( i, j + 1, k ); @@ -460,7 +752,7 @@ public class MeteoritePlacer double dist = dx * dx + dy * dy + dz * dz; Block xf = w.getBlock( i, j - 1, k ); - if ( !xf.isReplaceable( w, i, j - 1, k ) ) + if ( !xf.isReplaceable( w.getWorld(), i, j - 1, k ) ) { double extrRange = Math.random() * 0.6; double height = crator * (extrRange + 0.2) - Math.abs( dist - crator * 1.7 ); @@ -497,7 +789,7 @@ public class MeteoritePlacer } } - private boolean put(World w, int i, int j, int k, Block blk) + private boolean put(IMetroiteWorld w, int i, int j, int k, Block blk) { Block original = w.getBlock( i, j, k ); @@ -508,11 +800,16 @@ public class MeteoritePlacer return true; } - private void put(World w, int i, int j, int k, Block blk, int meta) + private void put(IMetroiteWorld w, int i, int j, int k, Block blk, int meta) { if ( w.getBlock( i, j, k ) == Blocks.bedrock ) return; w.setBlock( i, j, k, blk, meta, 3 ); } + + public NBTTagCompound getSettings() + { + return settings; + } } diff --git a/hooks/MeteoriteWorldGen.java b/hooks/MeteoriteWorldGen.java index ddb83d9c..3f5a48c1 100644 --- a/hooks/MeteoriteWorldGen.java +++ b/hooks/MeteoriteWorldGen.java @@ -1,18 +1,19 @@ package appeng.hooks; +import java.util.Collection; import java.util.Random; -import java.util.concurrent.Future; +import java.util.concurrent.Callable; +import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; import net.minecraft.world.chunk.IChunkProvider; import appeng.api.features.IWorldGen.WorldGenType; -import appeng.api.util.DimensionalCoord; import appeng.core.AEConfig; -import appeng.core.AELog; import appeng.core.WorldSettings; import appeng.core.features.registries.WorldGenRegistry; import appeng.helpers.MeteoritePlacer; import appeng.services.helpers.ICompassCallback; +import appeng.util.Platform; import cpw.mods.fml.common.IWorldGenerator; final public class MeteoriteWorldGen implements IWorldGenerator @@ -37,41 +38,105 @@ final public class MeteoriteWorldGen implements IWorldGenerator @Override public void generate(Random r, int chunkX, int chunkZ, World w, IChunkProvider chunkGenerator, IChunkProvider chunkProvider) { - if ( WorldGenRegistry.instance.isWorldGenEnabled( WorldGenType.Metorites, w ) && r.nextFloat() > 0.9 ) + if ( WorldGenRegistry.instance.isWorldGenEnabled( WorldGenType.Metorites, w ) ) { - int x = r.nextInt( 16 ) + (chunkX << 4); - int z = r.nextInt( 16 ) + (chunkZ << 4); - - myGen obj = new myGen(); - Future future = WorldSettings.getInstance().getCompass().getCompassDirection( new DimensionalCoord( w, x, 128, z ), 70, obj ); - - try + // add new metorites? + if ( r.nextFloat() > 0.7 ) { - future.get(); - - if ( obj.distance > AEConfig.instance.minMeteoriteDistanceSq ) - { - int depth = 180 + r.nextInt( 20 ); - for (int trys = 0; trys < 20; trys++) - { - MeteoritePlacer mp = new MeteoritePlacer(); - - if ( mp.spawnMeteorite( w, x, depth, z ) ) - return; - - depth -= 15; - if ( depth < 40 ) - return; - - } - } + int x = r.nextInt( 16 ) + (chunkX << 4); + int z = r.nextInt( 16 ) + (chunkZ << 4); + int depth = 180 + r.nextInt( 20 ); + TickHandler.instance.addCallable( w, new MetoriteSpawn( x, depth, z, w ) ); } - catch (Throwable e) - { - AELog.error( e ); - } - + else + TickHandler.instance.addCallable( w, new MetoriteSpawn( chunkX << 4, 128, chunkZ << 4, w ) ); } } + + class MetoriteSpawn implements Callable + { + + final int x; + final int z; + final World w; + int depth; + + public MetoriteSpawn(int x, int depth, int z, World w) { + this.x = x; + this.z = z; + this.w = w; + this.depth = depth; + } + + @Override + public Object call() throws Exception + { + int chunkX = x >> 4; + int chunkZ = z >> 4; + + double minSqDist = Double.MAX_VALUE; + + // near by meteorites! + for (NBTTagCompound data : getNearByMetetorites( w, chunkX, chunkZ )) + { + MeteoritePlacer mp = new MeteoritePlacer(); + mp.spawnMeteorite( new MeteoritePlacer.ChunkOnly( w, chunkX, chunkZ ), data ); + + minSqDist = Math.min( minSqDist, mp.getSqDistance( x, z ) ); + } + + boolean isCluster = (minSqDist < 30 * 30) && Platform.getRandomFloat() > 0.8; + + if ( minSqDist > AEConfig.instance.minMeteoriteDistanceSq || isCluster ) + tryMetroite( w, depth, x, z ); + + WorldSettings.getInstance().setGenerated( w.provider.dimensionId, chunkX, chunkZ ); + return null; + } + } + + private boolean tryMetroite(World w, int depth, int x, int z) + { + for (int trys = 0; trys < 20; trys++) + { + MeteoritePlacer mp = new MeteoritePlacer(); + + if ( mp.spawnMeteorite( new MeteoritePlacer.ChunkOnly( w, x >> 4, z >> 4 ), x, depth, z ) ) + { + int px = x >> 4; + int pz = z >> 4; + + for (int cx = px - 6; cx < px + 6; cx++) + for (int cz = pz - 6; cz < pz + 6; cz++) + { + if ( w.getChunkProvider().chunkExists( cx, cz ) ) + { + if ( px == cx && pz == cz ) + continue; + + if ( WorldSettings.getInstance().hasGenerated( w.provider.dimensionId, cx, cz ) ) + { + MeteoritePlacer mp2 = new MeteoritePlacer(); + mp2.spawnMeteorite( new MeteoritePlacer.ChunkOnly( w, cx, cz ), mp.getSettings() ); + } + } + } + + return true; + } + + depth -= 15; + if ( depth < 40 ) + return false; + } + + return false; + } + + private Collection getNearByMetetorites(World w, int chunkX, int chunkZ) + { + return WorldSettings.getInstance().getNearByMetetorites( w.provider.dimensionId, chunkX, chunkZ ); + } + } diff --git a/hooks/TickHandler.java b/hooks/TickHandler.java index da3ed37a..87161927 100644 --- a/hooks/TickHandler.java +++ b/hooks/TickHandler.java @@ -7,6 +7,7 @@ import java.util.LinkedList; import java.util.Queue; import java.util.WeakHashMap; import java.util.concurrent.Callable; +import java.util.concurrent.TimeUnit; import net.minecraft.world.World; import net.minecraftforge.event.world.ChunkEvent; @@ -25,6 +26,7 @@ import appeng.me.NetworkList; import appeng.tile.AEBaseTile; import appeng.util.Platform; +import com.google.common.base.Stopwatch; import com.google.common.collect.LinkedListMultimap; import com.google.common.collect.Multimap; @@ -251,18 +253,27 @@ public class TickHandler if ( queue == null ) return; + Stopwatch sw = Stopwatch.createStarted(); + Callable c = null; while ((c = queue.poll()) != null) { try { c.call(); + + if ( sw.elapsed( TimeUnit.MILLISECONDS ) > 50 ) + break; } catch (Exception e) { AELog.error( e ); } } + + // long time = sw.elapsed( TimeUnit.MILLISECONDS ); + // if ( time > 0 ) + // AELog.info( "processQueue Time: " + time + "ms" ); } Multimap craftingJobs = LinkedListMultimap.create(); diff --git a/services/CompassService.java b/services/CompassService.java index 1de9c8a4..ab00e14d 100644 --- a/services/CompassService.java +++ b/services/CompassService.java @@ -18,6 +18,8 @@ import appeng.services.helpers.ICompassCallback; public class CompassService implements ThreadFactory { + int jobSize = 0; + private class CMUpdatePost implements Runnable { @@ -38,9 +40,13 @@ public class CompassService implements ThreadFactory @Override public void run() { + jobSize--; + CompassReader cr = getReader( world ); cr.setHasBeacon( chunkX, chunkZ, doubleChunkY, value ); - cr.close(); + + if ( jobSize() < 2 ) + cleanUp(); } }; @@ -61,6 +67,8 @@ public class CompassService implements ThreadFactory @Override public void run() { + jobSize--; + int cx = coord.x >> 4; int cz = coord.z >> 4; @@ -70,6 +78,10 @@ public class CompassService implements ThreadFactory if ( cr.hasBeacon( cx, cz ) ) { callback.calculatedDirection( true, true, -999, 0 ); + + if ( jobSize() < 2 ) + cleanUp(); + return; } @@ -138,22 +150,43 @@ public class CompassService implements ThreadFactory if ( closest < Integer.MAX_VALUE ) { callback.calculatedDirection( true, false, rad( cx, cz, chosen_x, chosen_z ), dist( cx, cz, chosen_x, chosen_z ) ); + + if ( jobSize() < 2 ) + cleanUp(); + return; } } // didn't find shit... callback.calculatedDirection( false, true, -999, 999 ); + + if ( jobSize() < 2 ) + cleanUp(); } }; public Future getCompassDirection(DimensionalCoord coord, int maxRange, ICompassCallback cc) { + jobSize++; return executor.submit( new CMDirectionRequest( coord, maxRange, cc ) ); } + public int jobSize() + { + return jobSize; + } + + public void cleanUp() + { + for (CompassReader cr : worldSet.values()) + cr.close(); + } + public Future updateArea(World w, int x, int y, int z) { + jobSize++; + int cx = x >> 4; int cdy = y >> 5; int cz = z >> 4; @@ -194,6 +227,7 @@ public class CompassService implements ThreadFactory public CompassService(File aEFolder) { rootFolder = aEFolder; executor = Executors.newSingleThreadExecutor( this ); + jobSize = 0; } private CompassReader getReader(World w) @@ -232,6 +266,7 @@ public class CompassService implements ThreadFactory try { executor.awaitTermination( 6, TimeUnit.MINUTES ); + jobSize = 0; for (CompassReader cr : worldSet.values()) { diff --git a/spatial/CachedPlane.java b/spatial/CachedPlane.java index 10c81f04..d8892b39 100644 --- a/spatial/CachedPlane.java +++ b/spatial/CachedPlane.java @@ -1,20 +1,15 @@ package appeng.spatial; -import java.lang.reflect.Method; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map.Entry; import net.minecraft.block.Block; -import net.minecraft.network.Packet; -import net.minecraft.network.play.server.S21PacketChunkData; -import net.minecraft.server.management.PlayerManager; import net.minecraft.tileentity.TileEntity; import net.minecraft.world.ChunkPosition; import net.minecraft.world.NextTickListEntry; import net.minecraft.world.World; -import net.minecraft.world.WorldServer; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.storage.ExtendedBlockStorage; import net.minecraftforge.common.util.ForgeDirection; @@ -25,7 +20,6 @@ import appeng.api.util.WorldCoord; import appeng.core.AELog; import appeng.core.WorldSettings; import appeng.util.Platform; -import cpw.mods.fml.relauncher.ReflectionHelper; public class CachedPlane { @@ -400,47 +394,10 @@ public class CachedPlane for (int y = 1; y < 255; y += 32) WorldSettings.getInstance().getCompass().updateArea( wrld, c.xPosition << 4, y, c.zPosition << 4 ); - try - { - WorldServer ws = (WorldServer) c.worldObj; - PlayerManager pm = ws.getPlayerManager(); - - if ( getOrCreateChunkWatcher == null ) - { - getOrCreateChunkWatcher = ReflectionHelper.findMethod( PlayerManager.class, pm, new String[] { "getOrCreateChunkWatcher", - "func_72690_a" }, int.class, int.class, boolean.class ); - } - - if ( getOrCreateChunkWatcher != null ) - { - Object playerinstance = getOrCreateChunkWatcher.invoke( pm, c.xPosition, c.zPosition, false ); - if ( playerinstance != null ) - { - Playerinstance = playerinstance.getClass(); - - if ( sendToAllPlayersWatchingChunk == null ) - { - sendToAllPlayersWatchingChunk = ReflectionHelper.findMethod( Playerinstance, playerinstance, new String[] { - "sendToAllPlayersWatchingChunk", "func_151251_a" }, Packet.class ); - } - - if ( sendToAllPlayersWatchingChunk != null ) - sendToAllPlayersWatchingChunk.invoke( playerinstance, new S21PacketChunkData( c, false, verticalBits ) ); - } - } - - } - catch (Throwable t) - { - AELog.error( t ); - } + Platform.sendChunk( c, verticalBits ); } } - Class Playerinstance; - Method getOrCreateChunkWatcher; - Method sendToAllPlayersWatchingChunk; - } diff --git a/util/Platform.java b/util/Platform.java index cbe784c0..5f06feac 100644 --- a/util/Platform.java +++ b/util/Platform.java @@ -1,6 +1,7 @@ package appeng.util; import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Collection; @@ -37,6 +38,9 @@ import net.minecraft.nbt.NBTTagInt; import net.minecraft.nbt.NBTTagList; import net.minecraft.nbt.NBTTagLong; import net.minecraft.nbt.NBTTagString; +import net.minecraft.network.Packet; +import net.minecraft.network.play.server.S21PacketChunkData; +import net.minecraft.server.management.PlayerManager; import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntityChest; import net.minecraft.util.AxisAlignedBB; @@ -47,6 +51,7 @@ import net.minecraft.util.Vec3; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; import net.minecraft.world.WorldServer; +import net.minecraft.world.chunk.Chunk; import net.minecraftforge.common.util.FakePlayerFactory; import net.minecraftforge.common.util.ForgeDirection; import appeng.api.AEApi; @@ -101,6 +106,7 @@ import buildcraft.api.tools.IToolWrench; import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.Loader; import cpw.mods.fml.common.ModContainer; +import cpw.mods.fml.relauncher.ReflectionHelper; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; @@ -1720,4 +1726,46 @@ public class Platform return is; } + + private static Class Playerinstance; + private static Method getOrCreateChunkWatcher; + private static Method sendToAllPlayersWatchingChunk; + + public static void sendChunk(Chunk c, int verticalBits) + { + try + { + WorldServer ws = (WorldServer) c.worldObj; + PlayerManager pm = ws.getPlayerManager(); + + if ( getOrCreateChunkWatcher == null ) + { + getOrCreateChunkWatcher = ReflectionHelper.findMethod( PlayerManager.class, pm, new String[] { "getOrCreateChunkWatcher", "func_72690_a" }, + int.class, int.class, boolean.class ); + } + + if ( getOrCreateChunkWatcher != null ) + { + Object playerinstance = getOrCreateChunkWatcher.invoke( pm, c.xPosition, c.zPosition, false ); + if ( playerinstance != null ) + { + Playerinstance = playerinstance.getClass(); + + if ( sendToAllPlayersWatchingChunk == null ) + { + sendToAllPlayersWatchingChunk = ReflectionHelper.findMethod( Playerinstance, playerinstance, new String[] { + "sendToAllPlayersWatchingChunk", "func_151251_a" }, Packet.class ); + } + + if ( sendToAllPlayersWatchingChunk != null ) + sendToAllPlayersWatchingChunk.invoke( playerinstance, new S21PacketChunkData( c, false, verticalBits ) ); + } + } + + } + catch (Throwable t) + { + AELog.error( t ); + } + } }