in Minecraft/src/main/java/com/microsoft/Malmo/Client/ClientStateMachine.java [1876:1987]
public void onClientTick(ClientTickEvent event)
{
// Check to see whether anything has caused us to abort - if so, go to the abort state.
if (inAbortState())
onMissionEnded(ClientState.MISSION_ABORTED, "Mission was aborted by server: " + ClientStateMachine.this.getErrorDetails());
// Check to see whether we've been kicked from the server.
NetworkManager netman = Minecraft.getMinecraft().getConnection().getNetworkManager();
if (netman != null && !netman.hasNoChannel() && !netman.isChannelOpen())
{
// Connection has been lost.
onMissionEnded(ClientState.ERROR_LOST_NETWORK_CONNECTION, "Client was kicked from server - " + netman.getExitMessage().getUnformattedText());
}
// Check we are still in touch with the agent:
if (System.currentTimeMillis() > this.lastPingSent + this.pingFrequencyMs)
{
this.lastPingSent = System.currentTimeMillis();
// Ping the agent - if serverHasFiredStartingPistol is true, we don't need to abort -
// we can simply set the wantsToQuit flag and end the mission cleanly.
// If serverHasFiredStartingPistol is false, then the mission isn't yet running, and
// setting the quit flag will do nothing - so we need to abort.
if (!pingAgent(false))
{
if (!this.serverHasFiredStartingPistol)
onMissionEnded(ClientState.ERROR_LOST_AGENT, "Lost contact with the agent");
else
{
System.out.println("Error - agent is not responding to pings.");
this.wantsToQuit = true;
this.quitCode = MalmoMod.AGENT_UNRESPONSIVE_CODE;
}
}
}
if (this.frameTimestamp != 0 && (System.currentTimeMillis() - this.frameTimestamp > VIDEO_MAX_WAIT)) {
System.out.println("No video produced recently. Aborting mission.");
if (!this.serverHasFiredStartingPistol)
onMissionEnded(ClientState.ERROR_LOST_VIDEO, "No video produced recently.");
else
{
System.out.println("Error - not receiving video.");
this.wantsToQuit = true;
this.quitCode = MalmoMod.VIDEO_UNRESPONSIVE_CODE;
}
}
// Check here to see whether the player has died or not:
if (!this.playerDied && Minecraft.getMinecraft().player.isDead)
{
this.playerDied = true;
this.quitCode = MalmoMod.AGENT_DEAD_QUIT_CODE;
}
// Although we only arrive in this episode once the server has determined that all clients are ready to go,
// the server itself waits for all clients to begin running before it enters the running state itself.
// This creates a small vulnerability, since a running client could theoretically *finish* its mission
// before the server manages to *start*.
// (This has potentially disastrous effects for the state machine, and is easy to reproduce by,
// for example, setting the start point and goal of the mission to the same coordinates.)
// To guard against this happening, although we are running, we don't act on anything -
// we don't check for commands, or send observations or rewards - until we get the SERVER_GO signal,
// which is sent once the server's running episode has started.
if (!this.serverHasFiredStartingPistol)
return;
if (event.phase == Phase.END)
{
// Check whether or not we want to quit:
IWantToQuit quitHandler = (currentMissionBehaviour() != null) ? currentMissionBehaviour().quitProducer : null;
boolean quitHandlerFired = (quitHandler != null && quitHandler.doIWantToQuit(currentMissionInit()));
if (quitHandlerFired || this.wantsToQuit || this.playerDied)
{
if (quitHandlerFired)
{
this.quitCode = quitHandler.getOutcome();
}
try
{
// Save the quit code for anything that needs it:
MalmoMod.getPropertiesForCurrentThread().put("QuitCode", this.quitCode);
}
catch (Exception e)
{
System.out.println("Failed to get properties - final reward may go missing.");
}
// Get the final reward data:
ClientAgentConnection cac = currentMissionInit().getClientAgentConnection();
if (currentMissionBehaviour() != null && currentMissionBehaviour().rewardProducer != null && cac != null)
currentMissionBehaviour().rewardProducer.getReward(currentMissionInit(), ClientStateMachine.this.finalReward);
// Now send a message to the server saying that we have finished our mission:
List<AgentSection> agents = currentMissionInit().getMission().getAgentSection();
String agentName = agents.get(currentMissionInit().getClientRole()).getName();
HashMap<String, String> map = new HashMap<String, String>();
map.put("agentname", agentName);
map.put("username", Minecraft.getMinecraft().player.getName());
map.put("quitcode", this.quitCode);
MalmoMod.network.sendToServer(new MalmoMod.MalmoMessage(MalmoMessageType.CLIENT_AGENTFINISHEDMISSION, 0, map));
onMissionEnded(ClientState.IDLING, null);
}
else
{
// Send off observation and reward data:
sendData();
// And see if we have any incoming commands to act upon:
checkForControlCommand();
}
}
}