diff --git a/core/WorldSettings.java b/core/WorldSettings.java index 426ae2aa..99cfd21e 100644 --- a/core/WorldSettings.java +++ b/core/WorldSettings.java @@ -37,7 +37,6 @@ public class WorldSettings extends Configuration AEFolder = aeFolder; compass = new CompassService( AEFolder ); - (new Thread( compass, "AE Compass Service" )).start(); for (int dimID : get( "DimensionManager", "StorageCells", new int[0] ).getIntList()) { diff --git a/hooks/MeteoriteWorldGen.java b/hooks/MeteoriteWorldGen.java index b88b0cd0..4c2c2472 100644 --- a/hooks/MeteoriteWorldGen.java +++ b/hooks/MeteoriteWorldGen.java @@ -1,10 +1,13 @@ package appeng.hooks; import java.util.Random; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; import net.minecraft.world.World; import net.minecraft.world.chunk.IChunkProvider; import appeng.api.util.DimensionalCoord; +import appeng.core.AELog; import appeng.core.WorldSettings; import appeng.helpers.MeteoritePlacer; import appeng.services.helpers.ICompassCallback; @@ -25,11 +28,6 @@ final public class MeteoriteWorldGen implements IWorldGenerator distance = dist; else distance = Double.MAX_VALUE; - - synchronized (this) - { - notify(); - } } }; @@ -43,37 +41,38 @@ final public class MeteoriteWorldGen implements IWorldGenerator int z = r.nextInt( 16 ) + (chunkZ << 4); myGen obj = new myGen(); - WorldSettings.getInstance().getCompass().getCompassDirection( new DimensionalCoord( w, x, 128, z ), 70, obj ); + Future future = WorldSettings.getInstance().getCompass().getCompassDirection( new DimensionalCoord( w, x, 128, z ), 70, obj ); - synchronized (obj) + try { - try - { - obj.wait(); - } - catch (InterruptedException e) + future.get(); + + if ( obj.distance > 1000 * 500 ) { - // meh - return; + 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; + + } } + } - - if ( obj.distance > 1000 * 500 ) + catch (InterruptedException e) { - 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; - - } + AELog.error( e ); + } + catch (ExecutionException e) + { + AELog.error( e ); } } diff --git a/services/CompassService.java b/services/CompassService.java index e7247faf..9e01502e 100644 --- a/services/CompassService.java +++ b/services/CompassService.java @@ -2,35 +2,23 @@ package appeng.services; import java.io.File; import java.util.HashMap; -import java.util.LinkedList; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; import net.minecraft.block.Block; import net.minecraft.world.World; import appeng.api.AEApi; import appeng.api.util.DimensionalCoord; -import appeng.services.helpers.CompassException; import appeng.services.helpers.CompassReader; import appeng.services.helpers.ICompassCallback; -public class CompassService implements Runnable +public class CompassService implements ThreadFactory { - private class CompassMessage - { - - public boolean isUpdate() - { - return false; - } - - public boolean isRequest() - { - return false; - } - - }; - - private class CMUpdatePost extends CompassMessage + private class CMUpdatePost implements Runnable { public final World world; @@ -39,12 +27,6 @@ public class CompassService implements Runnable public final int doubleChunkY; // 32 blocks instead of 16. public final boolean value; - @Override - public boolean isUpdate() - { - return true; - } - public CMUpdatePost(World w, int cx, int cz, int dcy, boolean val) { world = w; chunkX = cx; @@ -52,32 +34,125 @@ public class CompassService implements Runnable chunkZ = cz; value = val; } + + @Override + public void run() + { + CompassReader cr = getReader( world ); + cr.setHasBeacon( chunkX, chunkZ, doubleChunkY, value ); + cr.close(); + } + }; - private class CMDirectionRequest extends CompassMessage + private class CMDirectionRequest implements Runnable { public final int maxRange; public final DimensionalCoord coord; public final ICompassCallback callback; - @Override - public boolean isRequest() - { - return true; - } - public CMDirectionRequest(DimensionalCoord coord, int getMaxRange, ICompassCallback cc) { this.coord = coord; this.maxRange = getMaxRange; callback = cc; } + @Override + public void run() + { + int cx = coord.x >> 4; + int cz = coord.z >> 4; + + CompassReader cr = getReader( coord.getWorld() ); + + // Am I standing on it? + if ( cr.hasBeacon( cx, cz ) ) + { + callback.calculatedDirection( true, true, -999, 0 ); + return; + } + + // spiral outward... + for (int offset = 1; offset < maxRange; offset++) + { + int minx = cx - offset; + int minz = cz - offset; + int maxx = cx + offset; + int maxz = cz + offset; + + int closest = Integer.MAX_VALUE; + int chosen_x = cx; + int chosen_z = cz; + + for (int z = minz; z <= maxz; z++) + { + if ( cr.hasBeacon( minx, z ) ) + { + int closness = dist( cx, cz, minx, z ); + if ( closness < closest ) + { + closest = closness; + chosen_x = minx; + chosen_z = z; + } + } + + if ( cr.hasBeacon( maxx, z ) ) + { + int closness = dist( cx, cz, maxx, z ); + if ( closness < closest ) + { + closest = closness; + chosen_x = maxx; + chosen_z = z; + } + } + } + + for (int x = minx + 1; x < maxx; x++) + { + if ( cr.hasBeacon( x, minz ) ) + { + int closness = dist( cx, cz, x, minz ); + if ( closness < closest ) + { + closest = closness; + chosen_x = x; + chosen_z = minz; + } + } + + if ( cr.hasBeacon( x, maxz ) ) + { + int closness = dist( cx, cz, x, maxz ); + if ( closness < closest ) + { + closest = closness; + chosen_x = x; + chosen_z = maxz; + } + } + } + + if ( closest < Integer.MAX_VALUE ) + { + callback.calculatedDirection( true, false, rad( cx, cz, chosen_x, chosen_z ), dist( cx, cz, chosen_x, chosen_z ) ); + return; + } + } + + // didn't find shit... + callback.calculatedDirection( false, true, -999, 999 ); + } }; - private LinkedList jobList = new LinkedList(); + public Future getCompassDirection(DimensionalCoord coord, int maxRange, ICompassCallback cc) + { + return executor.submit( new CMDirectionRequest( coord, maxRange, cc ) ); + } - public void updateArea(World w, int x, int y, int z) + public Future updateArea(World w, int x, int y, int z) { int cx = x >> 4; int cdy = y >> 5; @@ -102,67 +177,26 @@ public class CompassService implements Runnable Block blk = w.getBlock( i, k, j ); if ( blk == skystone && w.getBlockMetadata( i, k, j ) == 0 ) { - postJob( new CMUpdatePost( w, cx, cz, cdy, true ) ); - return; + return executor.submit( new CMUpdatePost( w, cx, cz, cdy, true ) ); } } } } - postJob( new CMUpdatePost( w, cx, cz, cdy, false ) ); + return executor.submit( new CMUpdatePost( w, cx, cz, cdy, false ) ); } - public void getCompassDirection(DimensionalCoord coord, int maxRange, ICompassCallback cc) - { - postJob( new CMDirectionRequest( coord, maxRange, cc ) ); - } - - private void postJob(CompassMessage msg) - { - synchronized (jobList) - { - if ( msg != null ) - jobList.offer( msg ); - jobList.notify(); - } - } - - private CompassMessage getNextMessage() - { - CompassMessage myMsg = null; - - while (myMsg == null && run) - { - synchronized (jobList) - { - try - { - myMsg = jobList.poll(); - overOberdened = jobList.isEmpty(); - - if ( myMsg == null ) - jobList.wait(); - } - catch (InterruptedException e) - { - // :P - } - } - } - - return myMsg; - } - - boolean overOberdened = false; HashMap worldSet = new HashMap(); + ExecutorService executor; final File rootFolder; public CompassService(File aEFolder) { rootFolder = aEFolder; + executor = Executors.newSingleThreadExecutor( this ); } - public CompassReader getReader(World w) + private CompassReader getReader(World w) { CompassReader cr = worldSet.get( w ); @@ -175,97 +209,6 @@ public class CompassService implements Runnable return cr; } - private void processRequest(CMDirectionRequest req) - { - int cx = req.coord.x >> 4; - int cz = req.coord.z >> 4; - - CompassReader cr = getReader( req.coord.getWorld() ); - - // Am I standing on it? - if ( cr.hasBeacon( cx, cz ) ) - { - req.callback.calculatedDirection( true, true, -999, 0 ); - return; - } - - // spiral outward... - for (int offset = 1; offset < req.maxRange; offset++) - { - int minx = cx - offset; - int minz = cz - offset; - int maxx = cx + offset; - int maxz = cz + offset; - - int closest = Integer.MAX_VALUE; - int chosen_x = cx; - int chosen_z = cz; - - for (int z = minz; z <= maxz; z++) - { - if ( cr.hasBeacon( minx, z ) ) - { - int closness = dist( cx, cz, minx, z ); - if ( closness < closest ) - { - closest = closness; - chosen_x = minx; - chosen_z = z; - } - } - - if ( cr.hasBeacon( maxx, z ) ) - { - int closness = dist( cx, cz, maxx, z ); - if ( closness < closest ) - { - closest = closness; - chosen_x = maxx; - chosen_z = z; - } - } - } - - for (int x = minx + 1; x < maxx; x++) - { - if ( cr.hasBeacon( x, minz ) ) - { - int closness = dist( cx, cz, x, minz ); - if ( closness < closest ) - { - closest = closness; - chosen_x = x; - chosen_z = minz; - } - } - - if ( cr.hasBeacon( x, maxz ) ) - { - int closness = dist( cx, cz, x, maxz ); - if ( closness < closest ) - { - closest = closness; - chosen_x = x; - chosen_z = maxz; - } - } - } - - if ( closest < Integer.MAX_VALUE ) - { - req.callback.calculatedDirection( true, false, rad( cx, cz, chosen_x, chosen_z ), dist( cx, cz, chosen_x, chosen_z ) ); - if ( !overOberdened ) - cr.close(); - return; - } - } - - // didn't find shit... - req.callback.calculatedDirection( false, true, -999, 999 ); - if ( !overOberdened ) - cr.close(); - } - private int dist(int ax, int az, int bx, int bz) { int up = (bz - az) * 16; @@ -282,58 +225,23 @@ public class CompassService implements Runnable return Math.atan2( -up, side ) - Math.PI / 2.0; } - private void processUpdate(CMUpdatePost req) - { - CompassReader cr = getReader( req.world ); - cr.setHasBeacon( req.chunkX, req.chunkZ, req.doubleChunkY, req.value ); - cr.close(); - } - - boolean run = true; - boolean stopped = false; - - @Override - public void run() - { - - while (run) - { - CompassMessage myMsg = getNextMessage(); - - try - { - if ( myMsg != null ) - { - if ( myMsg.isRequest() ) - processRequest( (CMDirectionRequest) myMsg ); - else if ( myMsg.isUpdate() ) - processUpdate( (CMUpdatePost) myMsg ); - } - } - catch (CompassException ce) - { - ce.inner.printStackTrace(); - } - } - - stopped = true; - } - public void kill() { - run = false; - postJob( null ); + executor.shutdown(); - while (!stopped) + try { - try - { - Thread.sleep( 100 ); - } - catch (InterruptedException e) - { - // :P - } + executor.awaitTermination( 6, TimeUnit.MINUTES ); + } + catch (InterruptedException e) + { + // wrap this up.. } } + + @Override + public Thread newThread(Runnable job) + { + return new Thread( job, "AE Compass Service" ); + } }