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