fix minor isses in battle replays

This commit is contained in:
Martin Michelsen
2023-09-24 23:17:22 -07:00
parent 9272feff8f
commit 949ad0d260
11 changed files with 56 additions and 34 deletions
+4 -5
View File
@@ -542,20 +542,19 @@ static void proxy_command_lobby_type(shared_ptr<ProxyServer::LinkedSession> ses,
}
static void server_command_saverec(shared_ptr<Client> c, const std::u16string& args) {
auto l = c->require_lobby();
if (args.find(u'/') != string::npos) {
send_text_message(c, u"$C4Recording names\ncannot include\nthe / character");
return;
}
if (!l->prev_battle_record) {
if (!c->ep3_prev_battle_record) {
send_text_message(c, u"$C4No finished\nrecording is\npresent");
return;
}
string filename = "system/ep3/battle-records/" + encode_sjis(args) + ".mzrd";
string data = l->prev_battle_record->serialize();
string data = c->ep3_prev_battle_record->serialize();
save_file(filename, data);
send_text_message(l, u"$C7Recording saved");
l->prev_battle_record.reset();
send_text_message(c, u"$C7Recording saved");
c->ep3_prev_battle_record.reset();
}
static void server_command_playrec(shared_ptr<Client> c, const std::u16string& args) {
+1
View File
@@ -162,6 +162,7 @@ struct Client : public std::enable_shared_from_this<Client> {
uint16_t card_battle_table_seat_number;
uint16_t card_battle_table_seat_state;
std::weak_ptr<Episode3::Tournament::Team> ep3_tournament_team;
std::shared_ptr<Episode3::BattleRecord> ep3_prev_battle_record;
std::shared_ptr<const Menu> last_menu_sent;
// Miscellaneous (used by chat commands)
+4 -2
View File
@@ -127,7 +127,8 @@ const BattleRecord::Event* BattleRecord::get_first_event() const {
void BattleRecord::add_player(
const PlayerLobbyDataDCGC& lobby_data,
const PlayerInventory& inventory,
const PlayerDispDataDCPCV3& disp) {
const PlayerDispDataDCPCV3& disp,
uint32_t level) {
if (!this->is_writable) {
throw logic_error("cannot write to battle record");
}
@@ -141,6 +142,7 @@ void BattleRecord::add_player(
player.lobby_data = lobby_data;
player.inventory = inventory;
player.disp = disp;
player.level = level;
}
void BattleRecord::delete_player(uint8_t client_id) {
@@ -349,7 +351,7 @@ void BattleRecordPlayer::schedule_events() {
send_command(l, (ev.data.size() >= 0x400) ? 0x6C : 0x60, 0x00, ev.data);
break;
case BattleRecord::Event::Type::EP3_GAME_COMMAND:
send_command(l, 0xCB, 0x00, ev.data);
send_command(l, 0xC9, 0x00, ev.data);
break;
case BattleRecord::Event::Type::CHAT_MESSAGE:
send_chat_message(l, ev.guild_card_number, decode_sjis(ev.data));
+4 -2
View File
@@ -23,6 +23,7 @@ public:
PlayerLobbyDataDCGC lobby_data;
PlayerInventory inventory;
PlayerDispDataDCPCV3 disp;
uint32_t level;
} __attribute__((packed));
struct Event {
@@ -65,7 +66,8 @@ public:
void add_player(
const PlayerLobbyDataDCGC& lobby_data,
const PlayerInventory& inventory,
const PlayerDispDataDCPCV3& disp);
const PlayerDispDataDCPCV3& disp,
uint32_t level);
void delete_player(uint8_t client_id);
void add_command(Event::Type type, const void* data, size_t size);
void add_command(Event::Type type, std::string&& data);
@@ -78,7 +80,7 @@ public:
void set_battle_end_timestamp();
private:
static constexpr uint64_t SIGNATURE = 0x14C946D56D1DAC5A;
static constexpr uint64_t SIGNATURE = 0x14C946D56D1DAC50;
static bool is_map_definition_event(const Event& ev);
+2 -1
View File
@@ -144,7 +144,8 @@ void Lobby::add_client(shared_ptr<Client> c, ssize_t required_client_id) {
this->battle_record->add_player(
lobby_data,
c->game_data.player()->inventory,
c->game_data.player()->disp.to_dcpcv3());
c->game_data.player()->disp.to_dcpcv3(),
c->game_data.ep3_config ? (c->game_data.ep3_config->online_clv_exp / 100) : 0);
}
// Send spectator count notifications if needed
-1
View File
@@ -97,7 +97,6 @@ struct Lobby : public std::enable_shared_from_this<Lobby> {
std::weak_ptr<Lobby> watched_lobby; // Only used in watcher games
std::unordered_set<shared_ptr<Lobby>> watcher_lobbies; // Only used in primary games
std::shared_ptr<Episode3::BattleRecord> battle_record; // Not used in watcher games
std::shared_ptr<Episode3::BattleRecord> prev_battle_record; // Only used in primary games
std::shared_ptr<Episode3::BattleRecordPlayer> battle_player; // Only used in replay games
std::shared_ptr<Episode3::Tournament::Match> tournament_match;
std::shared_ptr<const G_SetEXResultValues_GC_Ep3_6xB4x4B> ep3_ex_result_values;
+19 -5
View File
@@ -1278,6 +1278,11 @@ static void on_CA_Ep3(shared_ptr<Client> c, uint16_t, uint32_t, const string& da
if (!l->is_game() || !l->is_ep3()) {
throw runtime_error("Episode 3 server data request sent outside of Episode 3 game");
}
if (l->battle_player) {
return;
}
auto s = l->require_server_state();
const auto& header = check_size_t<G_CardServerDataCommandHeader>(data, 0xFFFF);
@@ -1314,8 +1319,11 @@ static void on_CA_Ep3(shared_ptr<Client> c, uint16_t, uint32_t, const string& da
if (s->ep3_behavior_flags & Episode3::BehaviorFlag::ENABLE_RECORDING) {
if (l->battle_record) {
l->prev_battle_record = l->battle_record;
l->prev_battle_record->set_battle_end_timestamp();
for (const auto& c : l->clients) {
if (c) {
c->ep3_prev_battle_record = l->battle_record;
}
}
}
l->battle_record.reset(new Episode3::BattleRecord(s->ep3_behavior_flags));
for (auto existing_c : l->clients) {
@@ -1324,18 +1332,24 @@ static void on_CA_Ep3(shared_ptr<Client> c, uint16_t, uint32_t, const string& da
lobby_data.name = encode_sjis(existing_c->game_data.player()->disp.name);
lobby_data.player_tag = 0x00010000;
lobby_data.guild_card = existing_c->license->serial_number;
l->battle_record->add_player(lobby_data,
l->battle_record->add_player(
lobby_data,
existing_c->game_data.player()->inventory,
existing_c->game_data.player()->disp.to_dcpcv3());
existing_c->game_data.player()->disp.to_dcpcv3(),
c->game_data.ep3_config ? (c->game_data.ep3_config->online_clv_exp / 100) : 0);
}
}
if (l->prev_battle_record) {
if (c->ep3_prev_battle_record) {
send_text_message(l, u"$C6Recording complete");
}
send_text_message(l, u"$C6Recording enabled");
}
}
bool battle_finished_before = l->ep3_server->battle_finished;
l->ep3_server->on_server_data_input(data);
if (!battle_finished_before && l->ep3_server->battle_finished && l->battle_record) {
l->battle_record->set_battle_end_timestamp();
}
if (l->tournament_match &&
l->ep3_server->setup_phase == Episode3::SetupPhase::BATTLE_ENDED &&
!l->ep3_server->tournament_match_result_sent) {
+4 -2
View File
@@ -1428,8 +1428,8 @@ static void send_join_spectator_team(shared_ptr<Client> c, shared_ptr<Lobby> l)
uint8_t player_count = 0;
auto watched_lobby = l->watched_lobby.lock();
if (watched_lobby) {
cmd.leader_id = watched_lobby->leader_id;
// Live spectating
cmd.leader_id = watched_lobby->leader_id;
for (size_t z = 0; z < 4; z++) {
auto& wc = watched_lobby->clients[z];
if (!wc) {
@@ -1480,7 +1480,6 @@ static void send_join_spectator_team(shared_ptr<Client> c, shared_ptr<Lobby> l)
throw runtime_error("invalid client id in battle record");
}
auto& p = cmd.players[client_id];
auto& e = cmd.entries[client_id];
p.lobby_data = entry.lobby_data;
remove_language_marker_inplace(p.lobby_data.name);
p.inventory = entry.inventory;
@@ -1489,12 +1488,15 @@ static void send_join_spectator_team(shared_ptr<Client> c, shared_ptr<Lobby> l)
}
p.disp = entry.disp;
remove_language_marker_inplace(p.disp.visual.name);
auto& e = cmd.entries[client_id];
e.player_tag = 0x00010000;
e.guild_card_number = entry.lobby_data.guild_card;
e.name = entry.disp.visual.name;
remove_language_marker_inplace(e.name);
e.present = 1;
e.level = entry.disp.stats.level.load();
player_count++;
}