void AgentHost::onMissionControlMessage()

in Malmo/src/AgentHost.cpp [606:711]


    void AgentHost::onMissionControlMessage(TimestampedString xml)
    {
        boost::lock_guard<boost::mutex> scope_guard(this->world_state_mutex);

        std::stringstream ss( xml.text );
        boost::property_tree::ptree pt;
        try {
            boost::property_tree::read_xml( ss, pt);
        }
        catch( std::exception&e ) {
            TimestampedString error_message( xml );
            error_message.text = std::string("Error parsing mission control message as XML: ") + e.what() + ":\n" + xml.text.substr(0,20) + "...\n";
            this->world_state.errors.push_back( boost::make_shared<TimestampedString>( error_message ) );
            return;
        }

        if( pt.empty() )
        {
            TimestampedString error_message( xml );
            error_message.text = "Empty XML string in mission control message";
            this->world_state.errors.push_back( boost::make_shared<TimestampedString>( error_message ) );
            return;
        }
        std::string root_node_name(pt.front().first.data());

        if( !this->world_state.is_mission_running && root_node_name == "MissionInit" ) {
            const bool validate = true;
            this->current_mission_init = boost::make_shared<MissionInitSpec>(xml.text,validate);
            this->world_state.is_mission_running = true;
            this->world_state.has_mission_begun = true;
            this->openCommandsConnection();
        }
        else if( root_node_name == "MissionEnded" ) {
            
            try {
                MissionEndedXML mission_ended(xml.text);
                const std::string status = mission_ended.getStatus();

                if (status != MissionEndedXML::ENDED && status != MissionEndedXML::PLAYER_DIED) {
                    std::ostringstream oss;
                    oss << "Mission ended abnormally: " << mission_ended.getHumanReadableStatus();
                    TimestampedString error_message(xml);
                    error_message.text = oss.str();
                    this->world_state.errors.push_back(boost::make_shared<TimestampedString>(error_message));
                }
                
                if (this->world_state.is_mission_running) {
                    const RewardXML& reward = mission_ended.getReward();

                    if (reward.size() != 0) {
                        TimestampedReward final_reward(xml.timestamp, reward);
                        this->processReceivedReward(final_reward);
                        this->rewards_server->recordMessage(TimestampedString(xml.timestamp, final_reward.getAsSimpleString()));
                    }
                }

                // Close our servers now, before we finish writing the MissionEnded message.
                this->closeServers();

                // Add some diagnostics of our own before this gets to the agent:
                if (this->video_server || this->luminance_server || this->depth_server || this->colourmap_server) {
                    for (auto &vd : mission_ended.videoDataAttributes()) {
                        boost::shared_ptr<VideoServer> vs = 0;
                        if (vd.frame_type == "VIDEO")
                            vs = this->video_server;
                        else if (vd.frame_type == "DEPTH_MAP")
                            vs = this->depth_server;
                        else if (vd.frame_type == "LUMINANCE")
                            vs = this->luminance_server;
                        else if (vd.frame_type == "COLOUR_MAP")
                            vs = this->colourmap_server;
                        if (vs) {
                            vd.frames_received =  vs->receivedFrames();
                            vd.frames_written = vs->writtenFrames();
                        }
                    }

                    xml.text = mission_ended.toXml();
                }
            }
            catch (const std::exception& e) {
                std::ostringstream oss;
                oss << "Error processing MissionEnded message XML: " << e.what() << " : " << xml.text.substr(0, 20) << "...";
                TimestampedString error_message(xml);
                error_message.text = oss.str();
                this->world_state.errors.push_back( boost::make_shared<TimestampedString>( error_message ) );
                return;
            }
            if (this->current_mission_record->isRecording()){
                std::ofstream missionEndedXML(this->current_mission_record->getMissionEndedPath());
                missionEndedXML << xml.text;
            }
            this->close();
        }
        else if (root_node_name == "ping") {
            // The mod is pinging us to check we are still around - do nothing.
        }
        else {
            TimestampedString error_message( xml );
            error_message.text = "Unknown mission control message root node or at wrong time: " + root_node_name + " :" + xml.text.substr(0, 200) + "...";
            this->world_state.errors.push_back( boost::make_shared<TimestampedString>( error_message ) );
            return;
        }

        this->world_state.mission_control_messages.push_back( boost::make_shared<TimestampedString>( xml ) );
    }