package rabbitescape.ui.android;
import rabbitescape.engine.World;
import rabbitescape.engine.textworld.TextWorldManip;
/**
* Hairy synchronization of the game loop, and the UI/system thread to
* ensure the world saves correctly.
*
* Only the game loop can stop what it is doing to save the world, but
* it is the UI/system thread that asks for the saved world.
*/
public class WorldSaver
{
public static class Signal
{
public synchronized void listen( long wait_time )
{
try
{
wait( wait_time );
}
catch ( InterruptedException e )
{
// We have been notified that what we are waiting for
// might have arrived
}
}
public synchronized void speak()
{
notify();
}
}
private final World world;
private final AndroidGameLaunch gameLaunch;
private final Signal requestSave = new Signal();
private final Signal saved = new Signal();
private boolean saveWorld = false;
public String[] savedWorld = null;
public WorldSaver( World world, AndroidGameLaunch gameLaunch )
{
this.world = world;
this.gameLaunch = gameLaunch;
}
/**
* Game loop thread: checks whether we've been asked
* to save the world, and if so, blocks here while it does it.
*/
public void check()
{
if ( saveWorld )
{
saveWorld = false;
savedWorld = actuallySaveWorld();
saved.speak();
}
}
private String[] actuallySaveWorld()
{
world.changes.revert();
return TextWorldManip.renderCompleteWorld( world, true );
}
/**
* Game loop thread: pauses the time supplied, but will
* be interrupted if the UI/system thread wakes us up
* by calling calls waitUntilSaved().
*/
public void waitUnlessSaveSignal( long wait_time )
{
requestSave.listen( wait_time );
}
/**
* UI/system thread: requests a world save, wakes up the
* game loop if it is sleeping, then blocks until the game
* loop has saved the world, which it does by calling check().
*
* @return the saved model
*/
public String[] waitUntilSaved()
{
if ( !gameLaunch.isRunning() )
{
return actuallySaveWorld();
}
saveWorld = true;
requestSave.speak();
while ( savedWorld == null )
{
saved.listen( 0 );
}
String[] ret = savedWorld;
savedWorld = null;
return ret;
}
}