make replay commands more usable

This commit is contained in:
Martin Michelsen
2022-11-30 23:23:17 -08:00
parent f8da4ac7be
commit 2e3089cb10
9 changed files with 72 additions and 53 deletions
+19 -17
View File
@@ -8,14 +8,15 @@
#include <phosg/Strings.hh>
#include <phosg/Time.hh>
#include "Loggers.hh"
#include "Server.hh"
#include "ProxyServer.hh"
#include "Lobby.hh"
#include "Client.hh"
#include "Lobby.hh"
#include "Loggers.hh"
#include "ProxyServer.hh"
#include "ReceiveCommands.hh"
#include "SendCommands.hh"
#include "Text.hh"
#include "Server.hh"
#include "StaticGameData.hh"
#include "Text.hh"
using namespace std;
@@ -409,7 +410,7 @@ static void server_command_saverec(shared_ptr<ServerState>, shared_ptr<Lobby> l,
l->prev_battle_record.reset();
}
static void server_command_playrec(shared_ptr<ServerState>, shared_ptr<Lobby> l,
static void server_command_playrec(shared_ptr<ServerState> s, shared_ptr<Lobby> l,
shared_ptr<Client> c, const std::u16string& args) {
if (!(c->flags & Client::Flag::IS_EPISODE_3)) {
send_text_message(c, u"$C4This command can\nonly be used on\nEpisode 3");
@@ -420,19 +421,20 @@ static void server_command_playrec(shared_ptr<ServerState>, shared_ptr<Lobby> l,
return;
}
if (l->is_game() && (l->flags & Lobby::Flag::EPISODE_3_ONLY) && (l->flags & Lobby::Flag::IS_SPECTATOR_TEAM) && l->battle_player) {
l->flags |= Lobby::Flag::BATTLE_IN_PROGRESS;
if (l->battle_player) {
l->battle_player->start();
} else if (args.empty()) {
c->next_game_battle_record.reset();
send_text_message(c, u"$C6Replay state\ncleared");
} else {
string filename = "system/ep3/battle-records/" + encode_sjis(args) + ".mzrd";
string data = load_file(filename);
c->next_game_battle_record.reset(new Episode3::BattleRecord(data));
send_text_message(c, u"$C6Replay state set");
uint32_t flags = Lobby::Flag::NON_V1_ONLY | Lobby::Flag::EPISODE_3_ONLY | Lobby::Flag::IS_SPECTATOR_TEAM;
string filename = encode_sjis(args);
if (filename[0] == '!') {
flags |= Lobby::Flag::START_BATTLE_PLAYER_IMMEDIATELY;
filename = filename.substr(1);
}
string data = load_file("system/ep3/battle-records/" + filename + ".mzrd");
shared_ptr<Episode3::BattleRecord> record(new Episode3::BattleRecord(data));
shared_ptr<Episode3::BattleRecordPlayer> battle_player(
new Episode3::BattleRecordPlayer(record, s->game_server->get_base()));
auto game = create_game_generic(s, c, args.c_str(), u"", 0xFF, 0, flags, battle_player);
}
}
-1
View File
@@ -125,7 +125,6 @@ struct Client {
bool can_chat;
std::string pending_bb_save_username;
uint8_t pending_bb_save_player_index;
std::shared_ptr<const Episode3::BattleRecord> next_game_battle_record;
bool proxy_block_events;
bool proxy_block_function_calls;
+11 -7
View File
@@ -283,22 +283,26 @@ void BattleRecord::set_battle_end_timestamp() {
BattleRecordPlayer::BattleRecordPlayer(
shared_ptr<const BattleRecord> rec,
shared_ptr<struct event_base> base,
shared_ptr<Lobby> l)
shared_ptr<struct event_base> base)
: record(rec),
event_it(this->record->events.begin()),
play_start_timestamp(0),
base(base),
lobby(l),
next_command_ev(event_new(this->base.get(), -1, EV_TIMEOUT, &BattleRecordPlayer::dispatch_schedule_events, this), event_free) { }
shared_ptr<const BattleRecord> BattleRecordPlayer::get_record() const {
return this->record;
}
void BattleRecordPlayer::set_lobby(std::shared_ptr<Lobby> l) {
this->lobby = l;
}
void BattleRecordPlayer::start() {
this->play_start_timestamp = now();
this->schedule_events();
if (this->play_start_timestamp == 0) {
this->play_start_timestamp = now();
this->schedule_events();
}
}
void BattleRecordPlayer::dispatch_schedule_events(
@@ -348,10 +352,10 @@ void BattleRecordPlayer::schedule_events() {
// This should have been handled before the lobby was even created
break;
case BattleRecord::Event::Type::BATTLE_COMMAND:
send_command(l, 0xC9, 0x00, ev.data);
send_command(l, (ev.data.size() >= 0x400) ? 0x6C : 0xC9, 0x00, ev.data);
break;
case BattleRecord::Event::Type::GAME_COMMAND:
send_command(l, 0x60, 0x00, ev.data);
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);
+3 -2
View File
@@ -98,11 +98,12 @@ class BattleRecordPlayer {
public:
BattleRecordPlayer(
std::shared_ptr<const BattleRecord> rec,
std::shared_ptr<struct event_base> base,
std::shared_ptr<Lobby> l);
std::shared_ptr<struct event_base> base);
~BattleRecordPlayer() = default;
std::shared_ptr<const BattleRecord> get_record() const;
void set_lobby(std::shared_ptr<Lobby> l);
void start();
private:
+17 -16
View File
@@ -22,26 +22,27 @@
struct Lobby {
enum Flag {
GAME = 0x00000001,
EPISODE_3_ONLY = 0x00000002,
NON_V1_ONLY = 0x00000004, // DC NTE and DCv1 not allowed
PERSISTENT = 0x00000008,
GAME = 0x00000001,
EPISODE_3_ONLY = 0x00000002,
NON_V1_ONLY = 0x00000004, // DC NTE and DCv1 not allowed
PERSISTENT = 0x00000008,
// Flags used only for games
CHEATS_ENABLED = 0x00000100,
QUEST_IN_PROGRESS = 0x00000200,
BATTLE_IN_PROGRESS = 0x00000400,
JOINABLE_QUEST_IN_PROGRESS = 0x00000800,
ITEM_TRACKING_ENABLED = 0x00001000,
IS_SPECTATOR_TEAM = 0x00002000, // EPISODE_3_ONLY must also be set
SPECTATORS_FORBIDDEN = 0x00004000,
BATTLE_MODE = 0x00008000,
CHALLENGE_MODE = 0x00010000,
SOLO_MODE = 0x00020000,
CHEATS_ENABLED = 0x00000100,
QUEST_IN_PROGRESS = 0x00000200,
BATTLE_IN_PROGRESS = 0x00000400,
JOINABLE_QUEST_IN_PROGRESS = 0x00000800,
ITEM_TRACKING_ENABLED = 0x00001000,
IS_SPECTATOR_TEAM = 0x00002000, // EPISODE_3_ONLY must also be set
SPECTATORS_FORBIDDEN = 0x00004000,
BATTLE_MODE = 0x00008000,
CHALLENGE_MODE = 0x00010000,
SOLO_MODE = 0x00020000,
START_BATTLE_PLAYER_IMMEDIATELY = 0x00040000,
// Flags used only for lobbies
PUBLIC = 0x01000000,
DEFAULT = 0x02000000,
PUBLIC = 0x01000000,
DEFAULT = 0x02000000,
};
PrefixedLogger log;
+12 -10
View File
@@ -1931,9 +1931,7 @@ static void on_chat_generic(shared_ptr<ServerState> s, shared_ptr<Client> c,
char private_flags = 0;
u16string processed_text;
if ((text[0] != '\t') &&
(l->flags & Lobby::Flag::EPISODE_3_ONLY) &&
l->ep3_server_base) {
if ((text[0] != '\t') && (l->flags & Lobby::Flag::EPISODE_3_ONLY)) {
private_flags = text[0];
processed_text = remove_language_marker(text.substr(1));
} else {
@@ -2448,13 +2446,15 @@ static void on_set_blocked_senders_list(shared_ptr<ServerState>, shared_ptr<Clie
static shared_ptr<Lobby> create_game_generic(shared_ptr<ServerState> s,
shared_ptr<Lobby> create_game_generic(
shared_ptr<ServerState> s,
shared_ptr<Client> c,
const std::u16string& name,
const std::u16string& password,
uint8_t episode,
uint8_t difficulty,
uint32_t flags) {
uint32_t flags,
shared_ptr<Episode3::BattleRecordPlayer> battle_player) {
// A player's actual level is their displayed level - 1, so the minimums for
// Episode 1 (for example) are actually 1, 20, 40, 80.
@@ -2504,11 +2504,9 @@ static shared_ptr<Lobby> create_game_generic(shared_ptr<ServerState> s,
game->random_seed = c->override_random_seed;
game->random->seed(game->random_seed);
}
if (c->next_game_battle_record) {
game->battle_player.reset(new Episode3::BattleRecordPlayer(
c->next_game_battle_record, s->game_server->get_base(), game));
c->next_game_battle_record.reset();
game->flags |= Lobby::Flag::IS_SPECTATOR_TEAM;
if (battle_player) {
game->battle_player = battle_player;
battle_player->set_lobby(game);
}
game->common_item_creator.reset(new CommonItemCreator(
s->common_item_data, game->random));
@@ -2694,6 +2692,10 @@ static void on_client_ready(shared_ptr<ServerState> s, shared_ptr<Client> c,
if (c->version() == GameVersion::BB) {
send_get_player_info(c);
}
if (l->battle_player && (l->flags & Lobby::Flag::START_BATTLE_PLAYER_IMMEDIATELY)) {
l->battle_player->start();
}
}
+10
View File
@@ -6,6 +6,16 @@
std::shared_ptr<Lobby> create_game_generic(
std::shared_ptr<ServerState> s,
std::shared_ptr<Client> c,
const std::u16string& name,
const std::u16string& password,
uint8_t episode,
uint8_t difficulty,
uint32_t flags,
std::shared_ptr<Episode3::BattleRecordPlayer> battle_player = nullptr);
void on_connect(std::shared_ptr<ServerState> s, std::shared_ptr<Client> c);
void on_disconnect(std::shared_ptr<ServerState> s,
std::shared_ptr<Client> c);
Binary file not shown.
Binary file not shown.