diff --git a/common/include/common/rfproto.h b/common/include/common/rfproto.h index d75d1422..853ec84b 100644 --- a/common/include/common/rfproto.h +++ b/common/include/common/rfproto.h @@ -338,7 +338,7 @@ enum RF_LeftReason RF_LR_KICKED = 0x02, RF_LR_DATA_INCOMPATIBLE = 0x04, // Note: received when PF wants to download map (?) RF_LR_BETWEEN_LEVELS = 0x05, - RF_LR_EMPTY = 0x06, // TODO: check if it's polish translation bug + RF_LR_TIMED_OUT_JOINING = 0x06, RF_LR_NO_LEVEL_FILE = 0x07, // Note: other reasons shows the same message as RF_LR_UNKNOWN }; diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 74242a2e..c7e5d6e2 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -10,6 +10,9 @@ Version 1.5.0 (TBD): Not yet released - Notify players in a server that is recording demos - Restore cut first person weapon aim sway, toggleable with `cl_weaponsway` +[@is-this-c](https://github.com/is-this-c) +- Do not kick a player, if they joined right before limbo + ### Bug fixes [@GooberRF](https://github.com/GooberRF) - Fix phantom visual flag mesh being visible after Salvage flag is picked up on rare occasions diff --git a/game_patch/multi/demo/demo_record.cpp b/game_patch/multi/demo/demo_record.cpp index 71681ab5..835239b2 100644 --- a/game_patch/multi/demo/demo_record.cpp +++ b/game_patch/multi/demo/demo_record.cpp @@ -337,12 +337,12 @@ namespace FunHook multi_io_send_reliable_hook{ 0x00479480, - [](rf::Player* player, const void* data, int len, int not_limbo) { + [](rf::Player* player, const void* data, int len, int require_in_game) { if (player && player->is_observer()) { capture_packet(data, len, DEMO_PKT_RELIABLE); return; } - multi_io_send_reliable_hook.call_target(player, data, len, not_limbo); + multi_io_send_reliable_hook.call_target(player, data, len, require_in_game); }, }; diff --git a/game_patch/multi/network.cpp b/game_patch/multi/network.cpp index d6535582..807ec4f4 100644 --- a/game_patch/multi/network.cpp +++ b/game_patch/multi/network.cpp @@ -3193,6 +3193,40 @@ CodeInjection send_state_info_injection{ }, }; +CodeInjection process_state_info_req_between_levels_patch{ + 0x00481C12, + [] (auto& regs) { + if (regs.al) { + rf::Player* const player = regs.ebx; + if (is_player_minimum_af_client_version(player, 1, 4, 0)) { + rf::send_state_info(player); + + // Set `NETPLAYER_STATE_WAITING` like `mp_change_level`. + constexpr int NETPLAYER_STATE_WAITING = 0x0; + player->net_data->state = NETPLAYER_STATE_WAITING; + + const RF_GamePacketHeader enter_limbo_packet = + {.type = RF_GPT_ENTER_LIMBO, .size = 0}; + rf::multi_io_send_reliable( + player, + &enter_limbo_packet, + enter_limbo_packet.size + sizeof(RF_GamePacketHeader), + FALSE + ); + + regs.eip = 0x00481C4B; + } else { + regs.eip = 0x00481C31; + } + } else { + regs.eip = 0x00481C53; + } + + regs.esp += 0x8; + }, + false +}; + FunHook send_players_packet_hook{ 0x00481C70, [](rf::Player *player) { @@ -3780,6 +3814,7 @@ void network_init() // print join_req denial reasons check_access_for_new_player_hook.install(); + process_state_info_req_between_levels_patch.install(); // Move our limbo check to `check_join_request_restrict_status`. AsmWriter{0x0047AE64}.nop(6); diff --git a/game_patch/rf/multi.h b/game_patch/rf/multi.h index 5e4fadb7..0c78691f 100644 --- a/game_patch/rf/multi.h +++ b/game_patch/rf/multi.h @@ -263,7 +263,7 @@ namespace rf static auto& multi_get_game_type = addr_as_ref(0x00470770); static auto& multi_io_send = addr_as_ref(0x00479370); static auto& multi_io_send_reliable = - addr_as_ref(0x00479480); + addr_as_ref(0x00479480); static auto& multi_io_send_reliable_to_all = addr_as_ref(0x004795A0); static auto& multi_io_send_buffered_reliable_packets = addr_as_ref(0x004796C0);