void wotreplay::show_map_boundaries(const game_t &game, const std::vector<packet_t> &packets) { float min_x = 0.f, min_y = 0.f, max_x = 0.f, max_y = 0.f; for (const packet_t &packet : packets) { if (packet.type() != 0xa) { continue; } uint32_t player_id = packet.player_id(); // only take into account positions of 'valid' players. if (game.get_team_id(player_id) != -1) { // update the boundaries auto position = packet.position(); min_x = std::min(min_x, std::get<0>(position)); min_y = std::min(min_y, std::get<2>(position)); max_x = std::max(max_x, std::get<0>(position)); max_y = std::max(max_y, std::get<2>(position)); break; } } printf("The boundaries of used positions in this replay are: min_x = %f max_x = %f min_y = %f max_y = %f\n", min_x, max_x, min_y, max_y); }
int wotreplay::get_start_packet (const game_t &game, double skip) { std::unordered_map<int, packet_t> last_packets; int i = 0; for (const auto &packet : game.get_packets()) { i++; if (!packet.has_property(property_t::position)) { continue; } int player_id = packet.player_id(), team_id = game.get_team_id(player_id); if (team_id < 0) { continue; // belongs to no team } auto last = last_packets.find(player_id); if (last != last_packets.end()) { int distance = dist(last->second.position(), packet.position()); if (distance > 0.01) { break; } } last_packets[player_id] = packet; } const auto &packets = game.get_packets(); if (i < packets.size()) { float clock = packets[i].clock(), offset = skip; for (auto it = packets.begin() + i; it != packets.end(); ++it) { if (it->has_property(property_t::clock) && it->clock() >= clock + offset) { break; } ++i; } } return i; }
void image_writer_t::draw_death(const packet_t &packet, const game_t &game) { uint32_t killer, killed; std::tie(killed, killer) = packet.tank_destroyed(); packet_t position_packet; bool found = game.find_property(packet.clock(), killed, property_t::position, position_packet); if (found) { draw_position(position_packet, game, this->deaths); } }
std::tuple<float, float> wotreplay::get_2d_coord(const std::tuple<float, float, float> &position, const game_t &game, int width, int height) { float x,y,z; const std::array<int, 4> &map_boundaries = game.get_map_boundaries(); int min_x = map_boundaries[0], max_x = map_boundaries[1], min_y = map_boundaries[2], max_y = map_boundaries[3]; // std::tie(min_x, max_x, min_y, max_y) = game.get_map_boundaries(); std::tie(x,z,y) = position; x = (x - min_x) * (static_cast<float>(width) / (max_x - min_x + 1)); y = (max_y - y) * (static_cast<float>(height) / (max_y - min_y + 1)); return std::make_tuple(x,y); }
void image_writer_t::draw_position(const packet_t &packet, const game_t &game, boost::multi_array<float, 3> &image) { uint32_t player_id = packet.player_id(); int team_id = game.get_team_id(player_id); if (team_id < 0) return; auto shape = image.shape(); int width = static_cast<int>(shape[2]); int height = static_cast<int>(shape[1]); float x,y; std::tie(x,y) = get_2d_coord( packet.position(), game, width, height); if (x >= 0 && y >= 0 && x <= (width - 1) && y <= (height - 1)) { image[team_id][y][x] = 1; if (player_id == game.get_recorder_id()) { image[2][y][x] = 1; } } }
void image_writer_t::update(const game_t &game) { std::set<int> dead_players; for (const packet_t &packet : game.get_packets()) { if (packet.has_property(property_t::position) && dead_players.find(packet.player_id()) == dead_players.end()) { draw_position(packet, game, this->positions); } else if (packet.has_property(property_t::tank_destroyed)) { uint32_t target, killer; std::tie(target, killer) = packet.tank_destroyed(); dead_players.insert(target); draw_death(packet, game); } } }
void wotreplay::write_parts_to_file(const game_t &game) { std::ofstream game_begin("game_begin.json", std::ios::binary | std::ios::ate); std::copy(game.get_game_begin().begin(), game.get_game_begin().end(), std::ostream_iterator<char>(game_begin)); game_begin.close(); std::ofstream game_end("game_end.json", std::ios::binary | std::ios::ate); std::copy(game.get_game_end().begin(), game.get_game_end().end(), std::ostream_iterator<char>(game_end)); game_end.close(); std::ofstream replay_content("replay.dat", std::ios::binary | std::ios::ate); std::copy(game.get_raw_replay().begin(), game.get_raw_replay().end(), std::ostream_iterator<char>(replay_content)); }
void json_writer_t::update(const game_t &game) { auto &packets = root["packets"]; bounding_box_t bounding_box = game.get_arena().bounding_box; // copy boundary values Json::Value coordinate(Json::arrayValue); coordinate.append(std::get<0>(bounding_box.bottom_left)); coordinate.append(std::get<1>(bounding_box.bottom_left)); root["map_boundaries"].append(coordinate); coordinate.clear(); coordinate.append(std::get<0>(bounding_box.upper_right)); coordinate.append(std::get<1>(bounding_box.upper_right)); root["map_boundaries"].append(coordinate); root["recorder_id"] = game.get_recorder_id(); Json::Value summary; Json::Reader reader; const buffer_t &buffer = game.get_game_begin(); std::string summary_str(buffer.begin(), buffer.end()); reader.parse(summary_str, summary); root["summary"] = summary; for (auto &packet : game.get_packets()) { Json::Value value(Json::objectValue); if (packet.has_property(property_t::type)) { value["type"] = packet.type(); } if (packet.has_property(property_t::clock)) { value["clock"] = packet.clock(); } if (packet.has_property(property_t::player_id)) { value["player_id"] = packet.player_id(); int team_id = game.get_team_id(packet.player_id()); if (team_id != -1) { value["team"] = team_id; } } if (packet.has_property(property_t::position)) { Json::Value positionValue(Json::arrayValue); const auto &position = packet.position(); positionValue.append(std::get<0>(position)); positionValue.append(std::get<1>(position)); positionValue.append(std::get<2>(position)); value["position"] = positionValue; } if (packet.has_property(property_t::hull_orientation)) { Json::Value orientationValue(Json::arrayValue); const auto &orientation = packet.hull_orientation(); orientationValue.append(std::get<0>(orientation)); orientationValue.append(std::get<1>(orientation)); orientationValue.append(std::get<2>(orientation)); value["hull_orientation"] = orientationValue; } if (packet.has_property(property_t::tank_destroyed)) { uint32_t target, destroyed_by; std::tie(target, destroyed_by) = packet.tank_destroyed(); value["target"] = target; value["destroyed_by"] = destroyed_by; } if (packet.has_property(property_t::health)) { value["health"] = packet.health(); } if (packet.has_property(property_t::source)) { value["source"] = packet.source(); } if (packet.has_property(property_t::message)) { value["message"] = packet.message(); } if (packet.has_property(property_t::sub_type)) { value["sub_type"] = packet.sub_type(); } if (packet.has_property(property_t::target)) { value["target"] = packet.target(); } if (packet.has_property(property_t::destroyed_track_id)) { value["destroyed_track_id"] = packet.destroyed_track_id(); } if (packet.has_property(property_t::alt_track_state)) { value["alt_track_state"] = packet.alt_track_state(); } packets.append(value); } }