From 2e3089cb103b43036382ea6365403eff3aa34f22 Mon Sep 17 00:00:00 2001 From: Martin Michelsen Date: Wed, 30 Nov 2022 23:23:17 -0800 Subject: [PATCH] make replay commands more usable --- src/ChatCommands.cc | 36 +++++++++++--------- src/Client.hh | 1 - src/Episode3/BattleRecord.cc | 18 ++++++---- src/Episode3/BattleRecord.hh | 5 +-- src/Lobby.hh | 33 +++++++++--------- src/ReceiveCommands.cc | 22 ++++++------ src/ReceiveCommands.hh | 10 ++++++ system/client-data/V2-SetDataTableOn-LE.rel | Bin 5856 -> 0 bytes system/client-data/V3-SetDataTableOn-BE.rel | Bin 9312 -> 0 bytes 9 files changed, 72 insertions(+), 53 deletions(-) delete mode 100644 system/client-data/V2-SetDataTableOn-LE.rel delete mode 100755 system/client-data/V3-SetDataTableOn-BE.rel diff --git a/src/ChatCommands.cc b/src/ChatCommands.cc index 3cee3ead..fa7fceeb 100644 --- a/src/ChatCommands.cc +++ b/src/ChatCommands.cc @@ -8,14 +8,15 @@ #include #include -#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, shared_ptr l, l->prev_battle_record.reset(); } -static void server_command_playrec(shared_ptr, shared_ptr l, +static void server_command_playrec(shared_ptr s, shared_ptr l, shared_ptr 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, shared_ptr 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 record(new Episode3::BattleRecord(data)); + shared_ptr 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); } } diff --git a/src/Client.hh b/src/Client.hh index e88d4d10..ca3d890c 100644 --- a/src/Client.hh +++ b/src/Client.hh @@ -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 next_game_battle_record; bool proxy_block_events; bool proxy_block_function_calls; diff --git a/src/Episode3/BattleRecord.cc b/src/Episode3/BattleRecord.cc index 759edb76..4d8d2c94 100644 --- a/src/Episode3/BattleRecord.cc +++ b/src/Episode3/BattleRecord.cc @@ -283,22 +283,26 @@ void BattleRecord::set_battle_end_timestamp() { BattleRecordPlayer::BattleRecordPlayer( shared_ptr rec, - shared_ptr base, - shared_ptr l) + shared_ptr 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 BattleRecordPlayer::get_record() const { return this->record; } +void BattleRecordPlayer::set_lobby(std::shared_ptr 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); diff --git a/src/Episode3/BattleRecord.hh b/src/Episode3/BattleRecord.hh index 5bfafd22..be7aa39b 100644 --- a/src/Episode3/BattleRecord.hh +++ b/src/Episode3/BattleRecord.hh @@ -98,11 +98,12 @@ class BattleRecordPlayer { public: BattleRecordPlayer( std::shared_ptr rec, - std::shared_ptr base, - std::shared_ptr l); + std::shared_ptr base); ~BattleRecordPlayer() = default; std::shared_ptr get_record() const; + + void set_lobby(std::shared_ptr l); void start(); private: diff --git a/src/Lobby.hh b/src/Lobby.hh index e27360f5..154bf49b 100644 --- a/src/Lobby.hh +++ b/src/Lobby.hh @@ -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; diff --git a/src/ReceiveCommands.cc b/src/ReceiveCommands.cc index 0fdcfae8..76c5a5aa 100644 --- a/src/ReceiveCommands.cc +++ b/src/ReceiveCommands.cc @@ -1931,9 +1931,7 @@ static void on_chat_generic(shared_ptr s, shared_ptr 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, shared_ptr create_game_generic(shared_ptr s, +shared_ptr create_game_generic( + shared_ptr s, shared_ptr c, const std::u16string& name, const std::u16string& password, uint8_t episode, uint8_t difficulty, - uint32_t flags) { + uint32_t flags, + shared_ptr 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 create_game_generic(shared_ptr 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 s, shared_ptr 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(); + } } diff --git a/src/ReceiveCommands.hh b/src/ReceiveCommands.hh index 61ccb6f2..dca4512b 100644 --- a/src/ReceiveCommands.hh +++ b/src/ReceiveCommands.hh @@ -6,6 +6,16 @@ +std::shared_ptr create_game_generic( + std::shared_ptr s, + std::shared_ptr c, + const std::u16string& name, + const std::u16string& password, + uint8_t episode, + uint8_t difficulty, + uint32_t flags, + std::shared_ptr battle_player = nullptr); + void on_connect(std::shared_ptr s, std::shared_ptr c); void on_disconnect(std::shared_ptr s, std::shared_ptr c); diff --git a/system/client-data/V2-SetDataTableOn-LE.rel b/system/client-data/V2-SetDataTableOn-LE.rel deleted file mode 100644 index 460e3a4c108f4022b930629ac519aba18bf02dde..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5856 zcmd^>El^}f6onszBqSl(O@crmR;)lE2AHivj6keFAP|TZQ^f)U1y%f2m{4rh2m}H# zA_9RxAP_4?AVx%tKp+qZ1Y*Sq1OkCTAP|V0(|!8Uultdtl8p+x-=5QV?(M$sPS3C_ zGwaiHOVtmB!gQgKB*{v;wtivlm-&rqVTiBtHMd4;W<6aP3f9BHdL&pE{q=CL|8THB zUeD~0b!LC8Gy7w0_n({DoHyOu$1`W9G55SrIYaJTmt!70$YYY3lj@KY)u927Gn2=M z^6QWj)s5uTjRbYbiRy|ub;Y0#IZ@r4oVqtb9dfdDe7LYq51c-q&57!wd1?rLT{KVR zX#1!6G3NJabE5O2c_J?}Pp)&GFPbOv7@J;OSirHFJ~DH*c~KvneN@Zl!a1tpbRIS* zyB{0Qsbi8~7tIlMXfJy&84K!=6P?F4GS7`bW{zCv)J1bdQf6LU=hQ{_5_y?>$+cIv zGBdZhwEFZ>=N$Z)>)nsBJjgR+4P!aAX0$<`8EqKLsWsyb^6)hF`_=1@;|=>mUevQ0 zaj+jp9M+mK2YF`9VJxTCjM~rR!-hSZ0R-pTyll@LKu&FX=iCfzUQ}z233^F?UwE}F z&&&XUXwHm<&ujCd+Gx(mi{{K&&biT?k;m&C_Lt6iW_509e%1csb+htguGWvabG=wP zXFrxxo8D(H4=vg|>Bn+vk!NS+<)w4>V>z|yefILwIs37k+H}q?j}3=Cn} z+cO^`r#8KlUTrih)S6?0GtxWh)$*9ImuOZEMnuE9*3rCZ@1c%=x zNe8rF3_?qSenQZf1^u$1Z(@%xp*2y59tiq|pl=EKb3y;0J=*Z(4w%N!9DOg841iHV zKOx>j*9HBK*oS@;^eu4#y%O~IqPsIm`UHKcCrKd5lyq6TBR!BdrGrQ&V_;IySHu={ zSI{4bW9W&XzZ5sn2SMNSMUuP%qhK7A-~YnSwJ4pCR-`rQo>SE9fsddi=r6=I z^g+<~bX#6Qi-LY!l%eZ_en;#>8-l*A^Y5iS`0~QXA$ct=Nl%bVF2RkUe-tmjL5-jv z6%)|+g1#ztp$CHgSe!yX3HqAO-;*|^r_#3c7P%z(7I#(94~PAq> zd|f1i_{?*CD{bKJay^B+z}N4kdzcm1XPQ}CdMEADxqVQ)l}R0nui)fNdIj}=ZaO>A zPX|69R-gO#-@g9bzHz)0y|_Q|tA9V@_V}yL|H+R3k3B!n1pk{|+&l2RKAr1a{7&0f Zo{PJ>Khy1>@%@SqG(Xe)S;yM{`2(r9J@Nnm diff --git a/system/client-data/V3-SetDataTableOn-BE.rel b/system/client-data/V3-SetDataTableOn-BE.rel deleted file mode 100755 index 79fa03ce8b941c57bb52c20e61bea27b758d8420..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9312 zcmd^CEl^xp7Jds1LqaDI(jg5rQ;3KNL?>Zp*eV2K1OkCTL{P&&OP6~@4kBH_lf5YJRc0v|M>6SLK?u5t^~bE6)P^d0@W?>^|Rq9@Kvx z)W`Kqeb|}$uru{xYyIiTKdWYXJ)Y_5eD=I)%ro29#+ZW#aS~+q#5}}Ac^E*}nTeA_ z`FV(m@?PZRy$JFU6Xo^g7xk&dK{Z$U{svPYxI6@xbnU8WZJ3`{WY*yl9_@ zVfl1_;`8U!n5bX0PsC;RDR$2JqJ1JxeB<-4UZHJfj?A7lE}BDjALYt$;T}1#+lR(v z>&d`5c@pI3MSDaZ#>+mJ;tTQ+6ZMlZGUtXPvq!OW@}fN=D6=oIbMm6+5^$&u!E_?8Oc6Q$<=|P-XYv{|#HLDHc%xXhlPOe#R5Qo#~`_-FI)*H@;xM*gx z;-H?aILtL`4&uz3Ltjp=S+yT0hYe>o3kdpZTy|zzKu)fE=IjnMF3L4+f?3@6g_kSo znH|6p?OA-`c{MJ|jrNSVXwTxy=^O1Caq>8a^SM1w&P~6r&gmDg-IedNxxUZ#^?Yv6 zzAq=&Jz+w3H`*0)O`D*HdnUbHX%o&8?FvEene=j_T_G;omH5J4XGc28|?~l7$^H&i7%X4a8Sm547FcXuEl7yBTP^_X6!-f_lFOc7I_1GiyI{-`iSmu{tw8 zRmB>;ncr4xwfTS3?fHLStXAi&+w(8YPfu4D?QXO#ecaKX*qpsrs`Y-T*5BQs-Ls(D z#lWvIwaKY@`%9A9v9WdbrG?4q^cz3)1-6+c^aZw=CiMBX1jwmEUtmYQkjLjpXO`pT z)Zy+H|9Cy8>q}!&pZ0RL*DLh}FB@*$|(p4_p7wp2q9{*_W!5Q`H&sw7ETdK66ITcKb?w>7G4bkeBW` zjY;?H`GP#e*w3=gDM{g+rjXn(*3pW=MrCNyE)DG74E*&H5zx) zY1}oZ%{PgBn#@mYlC%NIKY%jP3mzau4-=xt2+=hHy6p+{55Ow14&Ee0?-HW-3DL&{ zblWVn)Hoxqbu1Yz5nUvnf^iB1(Zj?9c!3bTMr?q02+`AyP(I~o1RKVzIAo?Xy1HU7nAFU@kC;FIq_sO5hSIX@T z%0GTYu3!g1tbyng;sX4IfNm-fJ>Wh<^bj!yULZuT5gXuL0=j*ebIg!e$(TjvZbz(e z(*f}rd`XD@s<_jdBzK+=qWcNdzcWFIUMAjyHwn>y5r^PY0=oT5`#)|Vm&tu()Rg(| zAWm=>=G`J8`YAC09w9`}5G&wyLi84~2Rf2aPyNCr9t{C@DZg^`Y>-ZQJST12tJFK&=$DfY=QGMTfB$1*nqa!fwuSr zZE*x`aSCm532pHenkW>L!~y3kSm0a*qO_{Bm)?^4cg)ZG|_RvoNF?6V)||(Mu2m5 z_Rxp36$Hls&SQYQd$?>+L~NhNb`Fw=V#kJE(`xa@PU*RJr8@F@kg8nt*P_Wr6t1O%Rx+6%Kx{~R$ycMU%5?ZH)w?sxQk zfsg1$KZ$E=NYRbH##bg!khhf|O20<@zIOq}FFwUhwI7Wsw@V(bw;$^D$1}>M1~T>_ z^-II#3G%XXM+Mx1chxZ%&qHSuxmT}uo~Yebp#LRV&Vu-^Au#H9v0m2}?Q6YWW}Whl z+TEk%6^-j&CvTDWl*@zUH89TIz2C5gKJurItXBN*_g;@H-sY*pEcVZBG2i01HU8V= z-%?9s(u)5dHPiEc`;Ows|4kKp2X5ndj_>!RC&^QBeU18izn$NY`j))!i}$lt=g$$x z#h%-zy}hzuCEca(y-nZNEspmi?df7pyMLd;3pM}er*nM8ZQ~l==koK@nX>--ALU@n AuK)l5