diff --git a/src/main/java/appeng/services/CompassService.java b/src/main/java/appeng/services/CompassService.java index 93bede4d2..8ae10d9d0 100644 --- a/src/main/java/appeng/services/CompassService.java +++ b/src/main/java/appeng/services/CompassService.java @@ -35,11 +35,15 @@ import com.google.common.base.Preconditions; import net.minecraft.block.Block; import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; +import net.minecraftforge.event.world.WorldEvent; + +import cpw.mods.fml.common.eventhandler.SubscribeEvent; import appeng.api.AEApi; import appeng.api.util.DimensionalCoord; import appeng.services.compass.CompassReader; import appeng.services.compass.ICompassCallback; +import appeng.util.Platform; public final class CompassService @@ -71,6 +75,22 @@ public final class CompassService return this.executor.submit( new CMDirectionRequest( coord, maxRange, cc ) ); } + /** + * Ensure the a compass service is removed once a world gets unloaded by forge. + * + * @param event the event containing the unloaded world. + */ + @SubscribeEvent + public void unloadWorld( WorldEvent.Unload event ) + { + if( Platform.isServer() && this.worldSet.containsKey( event.world ) ) + { + final CompassReader compassReader = this.worldSet.remove( event.world ); + + compassReader.close(); + } + } + public int jobSize() { return this.jobSize; @@ -78,7 +98,7 @@ public final class CompassService public void cleanUp() { - for( CompassReader cr : this.worldSet.values() ) + for( final CompassReader cr : this.worldSet.values() ) { cr.close(); } @@ -86,8 +106,8 @@ public final class CompassService public void updateArea( World w, int chunkX, int chunkZ ) { - int x = chunkX << 4; - int z = chunkZ << 4; + final int x = chunkX << 4; + final int z = chunkZ << 4; this.updateArea( w, x, CHUNK_SIZE, z ); this.updateArea( w, x, CHUNK_SIZE + 32, z ); @@ -104,17 +124,17 @@ public final class CompassService { this.jobSize++; - int cx = x >> 4; - int cdy = y >> 5; - int cz = z >> 4; + final int cx = x >> 4; + final int cdy = y >> 5; + final int cz = z >> 4; - int low_y = cdy << 5; - int hi_y = low_y + 32; + final int low_y = cdy << 5; + final int hi_y = low_y + 32; // lower level... - Chunk c = w.getChunkFromBlockCoords( x, z ); + final Chunk c = w.getChunkFromBlockCoords( x, z ); - for( Block skyStoneBlock : AEApi.instance().definitions().blocks().skyStone().maybeBlock().asSet() ) + for( final Block skyStoneBlock : AEApi.instance().definitions().blocks().skyStone().maybeBlock().asSet() ) { for( int i = 0; i < CHUNK_SIZE; i++ ) { @@ -122,7 +142,7 @@ public final class CompassService { for( int k = low_y; k < hi_y; k++ ) { - Block blk = c.getBlock( i, k, j ); + final Block blk = c.getBlock( i, k, j ); if( blk == skyStoneBlock && c.getBlockMetadata( i, k, j ) == 0 ) { return this.executor.submit( new CMUpdatePost( w, cx, cz, cdy, true ) ); @@ -135,6 +155,28 @@ public final class CompassService return this.executor.submit( new CMUpdatePost( w, cx, cz, cdy, false ) ); } + public void kill() + { + this.executor.shutdown(); + + try + { + this.executor.awaitTermination( 6, TimeUnit.MINUTES ); + this.jobSize = 0; + + for( final CompassReader cr : this.worldSet.values() ) + { + cr.close(); + } + + this.worldSet.clear(); + } + catch( final InterruptedException e ) + { + // wrap this up.. + } + } + private CompassReader getReader( World w ) { CompassReader cr = this.worldSet.get( w ); @@ -150,42 +192,20 @@ public final class CompassService private int dist( int ax, int az, int bx, int bz ) { - int up = ( bz - az ) * CHUNK_SIZE; - int side = ( bx - ax ) * CHUNK_SIZE; + final int up = ( bz - az ) * CHUNK_SIZE; + final int side = ( bx - ax ) * CHUNK_SIZE; return up * up + side * side; } private double rad( int ax, int az, int bx, int bz ) { - int up = bz - az; - int side = bx - ax; + final int up = bz - az; + final int side = bx - ax; return Math.atan2( -up, side ) - Math.PI / 2.0; } - public void kill() - { - this.executor.shutdown(); - - try - { - this.executor.awaitTermination( 6, TimeUnit.MINUTES ); - this.jobSize = 0; - - for( CompassReader cr : this.worldSet.values() ) - { - cr.close(); - } - - this.worldSet.clear(); - } - catch( InterruptedException e ) - { - // wrap this up.. - } - } - private class CMUpdatePost implements Runnable { @@ -210,7 +230,7 @@ public final class CompassService { CompassService.this.jobSize--; - CompassReader cr = CompassService.this.getReader( this.world ); + final CompassReader cr = CompassService.this.getReader( this.world ); cr.setHasBeacon( this.chunkX, this.chunkZ, this.doubleChunkY, this.value ); if( CompassService.this.jobSize() < 2 ) @@ -239,10 +259,10 @@ public final class CompassService { CompassService.this.jobSize--; - int cx = this.coord.x >> 4; - int cz = this.coord.z >> 4; + final int cx = this.coord.x >> 4; + final int cz = this.coord.z >> 4; - CompassReader cr = CompassService.this.getReader( this.coord.getWorld() ); + final CompassReader cr = CompassService.this.getReader( this.coord.getWorld() ); // Am I standing on it? if( cr.hasBeacon( cx, cz ) ) @@ -260,10 +280,10 @@ public final class CompassService // spiral outward... for( int offset = 1; offset < this.maxRange; offset++ ) { - int minX = cx - offset; - int minZ = cz - offset; - int maxX = cx + offset; - int maxZ = cz + offset; + final int minX = cx - offset; + final int minZ = cz - offset; + final int maxX = cx + offset; + final int maxZ = cz + offset; int closest = Integer.MAX_VALUE; int chosen_x = cx; @@ -273,7 +293,7 @@ public final class CompassService { if( cr.hasBeacon( minX, z ) ) { - int closeness = CompassService.this.dist( cx, cz, minX, z ); + final int closeness = CompassService.this.dist( cx, cz, minX, z ); if( closeness < closest ) { closest = closeness; @@ -284,7 +304,7 @@ public final class CompassService if( cr.hasBeacon( maxX, z ) ) { - int closeness = CompassService.this.dist( cx, cz, maxX, z ); + final int closeness = CompassService.this.dist( cx, cz, maxX, z ); if( closeness < closest ) { closest = closeness; @@ -298,7 +318,7 @@ public final class CompassService { if( cr.hasBeacon( x, minZ ) ) { - int closeness = CompassService.this.dist( cx, cz, x, minZ ); + final int closeness = CompassService.this.dist( cx, cz, x, minZ ); if( closeness < closest ) { closest = closeness; @@ -309,7 +329,7 @@ public final class CompassService if( cr.hasBeacon( x, maxZ ) ) { - int closeness = CompassService.this.dist( cx, cz, x, maxZ ); + final int closeness = CompassService.this.dist( cx, cz, x, maxZ ); if( closeness < closest ) { closest = closeness; diff --git a/src/main/java/appeng/services/compass/CompassReader.java b/src/main/java/appeng/services/compass/CompassReader.java index 70b01c65d..a74ed740b 100644 --- a/src/main/java/appeng/services/compass/CompassReader.java +++ b/src/main/java/appeng/services/compass/CompassReader.java @@ -55,10 +55,18 @@ public final class CompassReader public void setHasBeacon( int cx, int cz, int cdy, boolean hasBeacon ) { - CompassRegion r = this.getRegion( cx, cz ); + final CompassRegion r = this.getRegion( cx, cz ); + r.setHasBeacon( cx, cz, cdy, hasBeacon ); } + public boolean hasBeacon( int cx, int cz ) + { + final CompassRegion r = this.getRegion( cx, cz ); + + return r.hasBeacon( cx, cz ); + } + private CompassRegion getRegion( int cx, int cz ) { long pos = cx >> 10; @@ -66,6 +74,7 @@ public final class CompassReader pos |= ( cz >> 10 ); CompassRegion cr = this.regions.get( pos ); + if( cr == null ) { cr = new CompassRegion( cx, cz, this.dimensionId, this.worldCompassFolder ); @@ -74,10 +83,4 @@ public final class CompassReader return cr; } - - public boolean hasBeacon( int cx, int cz ) - { - CompassRegion r = this.getRegion( cx, cz ); - return r.hasBeacon( cx, cz ); - } } diff --git a/src/main/java/appeng/services/compass/CompassRegion.java b/src/main/java/appeng/services/compass/CompassRegion.java index bfbf7b290..086b34c9f 100644 --- a/src/main/java/appeng/services/compass/CompassRegion.java +++ b/src/main/java/appeng/services/compass/CompassRegion.java @@ -52,8 +52,8 @@ public final class CompassRegion this.worldCompassFolder = worldCompassFolder; this.encoder = new MeteorDataNameEncoder( 0 ); - int region_x = cx >> 10; - int region_z = cz >> 10; + final int region_x = cx >> 10; + final int region_z = cz >> 10; this.lowX = region_x << 10; this.lowZ = region_z << 10; @@ -61,42 +61,6 @@ public final class CompassRegion this.openFile( false ); } - private void openFile( boolean create ) - { - if( this.hasFile ) - { - return; - } - - final File file = this.getFile(); - if( create || this.isFileExistent( file ) ) - { - try - { - this.raf = new RandomAccessFile( file, "rw" ); - FileChannel fc = this.raf.getChannel(); - this.buffer = fc.map( FileChannel.MapMode.READ_WRITE, 0, 0x400 * 0x400 );// fc.size() ); - this.hasFile = true; - } - catch( Throwable t ) - { - throw new CompassException( t ); - } - } - } - - private File getFile() - { - final String fileName = this.encoder.encode( this.world, this.lowX, this.lowZ ); - - return new File( this.worldCompassFolder, fileName ); - } - - private boolean isFileExistent( File file ) - { - return file.exists() && file.isFile(); - } - public void close() { try @@ -122,7 +86,7 @@ public final class CompassRegion cx &= 0x3FF; cz &= 0x3FF; - int val = this.read( cx, cz ); + final int val = this.read( cx, cz ); if( val != 0 ) { return true; @@ -132,6 +96,87 @@ public final class CompassRegion return false; } + public void setHasBeacon( int cx, int cz, int cdy, boolean hasBeacon ) + { + cx &= 0x3FF; + cz &= 0x3FF; + + this.openFile( hasBeacon ); + + if( this.hasFile ) + { + int val = this.read( cx, cz ); + final int originalVal = val; + + if( hasBeacon ) + { + val |= 1 << cdy; + } + else + { + val &= ~( 1 << cdy ); + } + + if( originalVal != val ) + { + this.write( cx, cz, val ); + } + } + } + + @Override + protected void finalize() throws Throwable + { + try + { + if( this.raf != null ) + { + this.raf.close(); + } + } + finally + { + super.finalize(); + } + + } + + private void openFile( boolean create ) + { + if( this.hasFile ) + { + return; + } + + final File file = this.getFile(); + if( create || this.isFileExistent( file ) ) + { + try + { + this.raf = new RandomAccessFile( file, "rw" ); + final FileChannel fc = this.raf.getChannel(); + this.buffer = fc.map( FileChannel.MapMode.READ_WRITE, 0, 0x400 * 0x400 );// fc.size() ); + this.hasFile = true; + } + catch( final Throwable t ) + { + throw new CompassException( t ); + } + } + } + + private File getFile() + { + final String fileName = this.encoder.encode( this.world, this.lowX, this.lowZ ); + + return new File( this.worldCompassFolder, fileName ); + } + + private boolean isFileExistent( File file ) + { + return file.exists() && file.isFile(); + } + private int read( int cx, int cz ) { try @@ -150,34 +195,6 @@ public final class CompassRegion } } - public void setHasBeacon( int cx, int cz, int cdy, boolean hasBeacon ) - { - cx &= 0x3FF; - cz &= 0x3FF; - - this.openFile( hasBeacon ); - - if( this.hasFile ) - { - int val = this.read( cx, cz ); - int originalVal = val; - - if( hasBeacon ) - { - val |= 1 << cdy; - } - else - { - val &= ~( 1 << cdy ); - } - - if( originalVal != val ) - { - this.write( cx, cz, val ); - } - } - } - private void write( int cx, int cz, int val ) { try