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