Skip to content
2 changes: 1 addition & 1 deletion common/include/common/rfproto.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
};
Expand Down
3 changes: 3 additions & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions game_patch/multi/demo/demo_record.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -337,12 +337,12 @@ namespace

FunHook<void(rf::Player*, const void*, int, int)> 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);
},
};

Expand Down
35 changes: 35 additions & 0 deletions game_patch/multi/network.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<void(rf::Player*)> send_players_packet_hook{
0x00481C70,
[](rf::Player *player) {
Expand Down Expand Up @@ -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);

Expand Down
2 changes: 1 addition & 1 deletion game_patch/rf/multi.h
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ namespace rf
static auto& multi_get_game_type = addr_as_ref<NetGameType()>(0x00470770);
static auto& multi_io_send = addr_as_ref<void(Player *player, const void *packet, int len)>(0x00479370);
static auto& multi_io_send_reliable =
addr_as_ref<void(Player *player, const void *data, int len, int not_limbo)>(0x00479480);
addr_as_ref<void(Player *player, const void *data, int len, int require_in_game)>(0x00479480);
static auto& multi_io_send_reliable_to_all =
addr_as_ref<void(const void *data, int len, int a4)>(0x004795A0);
static auto& multi_io_send_buffered_reliable_packets = addr_as_ref<void(Player *pp)>(0x004796C0);
Expand Down
Loading