public void onClientTick()

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();
                }
            }
        }