Added Sky Stone Tracking.

Added Meteorite Compass Block / Item.
Added Meteorite Spawner Debug Item.
Some Refactoring.
This commit is contained in:
AlgorithmX2
2014-03-02 02:35:11 -06:00
parent fb6bb1a964
commit 792249f8fd
62 changed files with 2472 additions and 754 deletions
+301
View File
@@ -0,0 +1,301 @@
package appeng.services;
import java.io.File;
import java.util.HashMap;
import java.util.LinkedList;
import net.minecraft.block.Block;
import net.minecraft.world.World;
import appeng.api.AEApi;
import appeng.api.util.DimensionalCoord;
import appeng.core.AELog;
import appeng.services.helpers.CompassException;
import appeng.services.helpers.CompassReader;
import appeng.services.helpers.ICompassCallback;
public class CompassService implements Runnable
{
private class CompassMessage
{
public boolean isUpdate()
{
return false;
}
public boolean isRequest()
{
return false;
}
};
private class CMUpdatePost extends CompassMessage
{
public final World world;
public final int chunkX, chunkZ;
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;
doubleChunkY = dcy;
chunkZ = cz;
value = val;
}
};
private class CMDirectionRequest extends CompassMessage
{
public final DimensionalCoord coord;
public final ICompassCallback callback;
@Override
public boolean isRequest()
{
return true;
}
public CMDirectionRequest(DimensionalCoord coord, ICompassCallback cc) {
this.coord = coord;
callback = cc;
}
};
private LinkedList<CompassMessage> jobList = new LinkedList();
public void updateArea(World w, int x, int y, int z)
{
int cx = x >> 4;
int cdy = y >> 5;
int cz = z >> 4;
int low_x = cx << 4;
int low_z = cz << 4;
int low_y = cdy << 5;
int hi_x = low_x + 16;
int hi_z = low_z + 16;
int hi_y = low_y + 32;
Block skystone = AEApi.instance().blocks().blockSkyStone.block();
for (int i = low_x; i < hi_x; i++)
{
for (int j = low_z; j < hi_z; j++)
{
for (int k = low_y; k < hi_y; k++)
{
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;
}
}
}
}
postJob( new CMUpdatePost( w, cx, cz, cdy, false ) );
}
public void getCompassDirection(DimensionalCoord coord, ICompassCallback cc)
{
postJob( new CMDirectionRequest( coord, 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();
if ( myMsg == null )
jobList.wait();
}
catch (InterruptedException e)
{
// :P
}
}
}
return myMsg;
}
HashMap<World, CompassReader> worldSet = new HashMap();
final File rootFolder;
public CompassService(File aEFolder) {
rootFolder = aEFolder;
}
public CompassReader getReader(World w)
{
CompassReader cr = worldSet.get( w );
if ( cr == null )
{
cr = new CompassReader( w, rootFolder );
worldSet.put( w, cr );
}
return cr;
}
private void processRequest(CMDirectionRequest req)
{
AELog.info( "CompassService.processRequest" );
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 );
cr.close();
return;
}
// spiral outward...
for (int offset = 1; offset < 174; offset++)
{
int minx = cx - offset;
int minz = cz - offset;
int maxx = cx + offset;
int maxz = cz + offset;
for (int z = minz; z <= maxz; z++)
{
if ( cr.hasBeacon( minx, z ) )
{
req.callback.calculatedDirection( true, false, rad( cx, cz, minx, z ) );
cr.close();
return;
}
if ( cr.hasBeacon( maxx, z ) )
{
req.callback.calculatedDirection( true, false, rad( cx, cz, maxx, z ) );
cr.close();
return;
}
}
for (int x = minx + 1; x < maxx; x++)
{
if ( cr.hasBeacon( x, minz ) )
{
req.callback.calculatedDirection( true, false, rad( cx, cz, x, minz ) );
cr.close();
return;
}
if ( cr.hasBeacon( x, maxz ) )
{
req.callback.calculatedDirection( true, false, rad( cx, cz, x, maxz ) );
cr.close();
return;
}
}
}
// didn't find shit...
req.callback.calculatedDirection( false, true, -999 );
cr.close();
}
private double rad(int ax, int az, int bx, int bz)
{
int up = bz - az;
int side = bx - ax;
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 );
while (!stopped)
{
try
{
Thread.sleep( 100 );
}
catch (InterruptedException e)
{
// :P
}
}
}
}
+14
View File
@@ -0,0 +1,14 @@
package appeng.services.helpers;
public class CompassException extends RuntimeException
{
private static final long serialVersionUID = 8825268683203860877L;
public final Throwable inner;
public CompassException(Throwable t) {
inner = t;
}
}
+56
View File
@@ -0,0 +1,56 @@
package appeng.services.helpers;
import java.io.File;
import java.util.HashMap;
import net.minecraft.world.World;
public class CompassReader
{
HashMap<Long, CompassRegion> regions = new HashMap();
final int id;
final File rootFolder;
public void close()
{
for (CompassRegion r : regions.values())
r.close();
regions.clear();
}
public CompassReader(World w, File rootFolder) {
id = w.provider.dimensionId;
this.rootFolder = rootFolder;
}
public void setHasBeacon(int cx, int cz, int cdy, boolean hasBeacon)
{
CompassRegion r = getRegion( cx, cz );
r.setHasBeacon( cx, cz, cdy, hasBeacon );
}
public boolean hasBeacon(int cx, int cz)
{
CompassRegion r = getRegion( cx, cz );
return r.hasBeacon( cx, cz );
}
private CompassRegion getRegion(int cx, int cz)
{
long pos = cx >> 10;
pos = pos << 32;
pos = pos | (cz >> 10);
CompassRegion cr = regions.get( pos );
if ( cr == null )
{
cr = new CompassRegion( cx, cz, id, rootFolder );
regions.put( pos, cr );
}
return cr;
}
}
+159
View File
@@ -0,0 +1,159 @@
package appeng.services.helpers;
import java.io.EOFException;
import java.io.File;
import java.io.RandomAccessFile;
public class CompassRegion
{
final int low_x;
final int low_z;
final int hi_x;
final int hi_z;
final int world;
boolean hasFile = false;
final File rootFolder;
RandomAccessFile raf = null;
public void close()
{
try
{
if ( hasFile )
{
raf.close();
raf = null;
hasFile = false;
}
}
catch (Throwable t)
{
throw new CompassException( t );
}
}
public CompassRegion(int cx, int cz, int worldID, File rootFolder) {
world = worldID;
this.rootFolder = rootFolder;
int region_x = cx >> 10;
int region_z = cz >> 10;
low_x = region_x << 10;
low_z = region_z << 10;
hi_x = low_x + 1024;
hi_z = low_z + 1024;
openFile( false );
}
public boolean hasBeacon(int cx, int cz)
{
if ( hasFile )
{
cx = cx & 0x3FF;
cz = cz & 0x3FF;
int val = read( cx, cz );
if ( val != 0 )
return true;
}
return false;
}
public void setHasBeacon(int cx, int cz, int cdy, boolean hasBeacon)
{
cx &= 0x3FF;
cz &= 0x3FF;
openFile( hasBeacon );
if ( hasFile )
{
int val = read( cx, cz );
int originalVal = val;
if ( hasBeacon )
val |= 1 << cdy;
else
val &= ~(1 << cdy);
if ( originalVal != val )
write( cx, cz, val );
}
}
private void write(int cx, int cz, int val)
{
try
{
raf.seek( cx + cz * 0x400 );
raf.writeByte( val );
}
catch (Throwable t)
{
throw new CompassException( t );
}
}
private int read(int cx, int cz)
{
try
{
raf.seek( cx + cz * 0x400 );
return raf.readByte();
}
catch (EOFException eof)
{
return 0;
}
catch (Throwable t)
{
throw new CompassException( t );
}
}
private void openFile(boolean create)
{
File fName = getFileName();
if ( hasFile )
return;
if ( create || fileExists( fName ) )
{
try
{
raf = new RandomAccessFile( fName, "rw" );
hasFile = true;
}
catch (Throwable t)
{
throw new CompassException( t );
}
}
}
private boolean fileExists(File name)
{
return name.exists() && name.isFile();
}
private File getFileName()
{
String folder = rootFolder.getPath() + File.separatorChar + "compass";
File folderFile = new File( folder );
if ( !folderFile.exists() || !folderFile.isDirectory() )
folderFile.mkdir();
return new File( folder + File.separatorChar + world + "_" + low_x + "_" + low_z + ".dat" );
}
}
+15
View File
@@ -0,0 +1,15 @@
package appeng.services.helpers;
public interface ICompassCallback
{
/**
* Called from another thread.
*
* @param hasResult
* @param spin
* @param radians
*/
public void calculatedDirection(boolean hasResult, boolean spin, double radians);
}