clean up check_size
This commit is contained in:
+2
-4
@@ -75,8 +75,7 @@ void CatSession::on_channel_input(
|
||||
uint16_t command, uint32_t flag, std::string& data) {
|
||||
if (this->channel.version != GameVersion::BB) {
|
||||
if (command == 0x02 || command == 0x17 || command == 0x91 || command == 0x9B) {
|
||||
const auto& cmd = check_size_t<S_ServerInitDefault_DC_PC_V3_02_17_91_9B>(data,
|
||||
sizeof(S_ServerInitDefault_DC_PC_V3_02_17_91_9B), 0xFFFF);
|
||||
const auto& cmd = check_size_t<S_ServerInitDefault_DC_PC_V3_02_17_91_9B>(data, 0xFFFF);
|
||||
if ((this->channel.version == GameVersion::GC) ||
|
||||
(this->channel.version == GameVersion::XB)) {
|
||||
this->channel.crypt_in.reset(new PSOV3Encryption(cmd.server_key));
|
||||
@@ -95,8 +94,7 @@ void CatSession::on_channel_input(
|
||||
if (!this->bb_key_file) {
|
||||
throw runtime_error("BB encryption requires a key file");
|
||||
}
|
||||
const auto& cmd = check_size_t<S_ServerInitDefault_BB_03_9B>(data,
|
||||
sizeof(S_ServerInitDefault_BB_03_9B), 0xFFFF);
|
||||
const auto& cmd = check_size_t<S_ServerInitDefault_BB_03_9B>(data, 0xFFFF);
|
||||
this->channel.crypt_in.reset(new PSOBBEncryption(*this->bb_key_file, &cmd.server_key[0], sizeof(cmd.server_key)));
|
||||
this->channel.crypt_out.reset(new PSOBBEncryption(*this->bb_key_file, &cmd.client_key[0], sizeof(cmd.client_key)));
|
||||
this->log.info("Enabled BB encryption");
|
||||
|
||||
@@ -187,11 +187,9 @@ void BattleRecord::add_chat_message(
|
||||
|
||||
bool BattleRecord::is_map_definition_event(const Event& ev) {
|
||||
if (ev.type == Event::Type::BATTLE_COMMAND) {
|
||||
auto& header = check_size_t<G_CardBattleCommandHeader>(
|
||||
ev.data, sizeof(G_CardBattleCommandHeader), 0xFFFF);
|
||||
auto& header = check_size_t<G_CardBattleCommandHeader>(ev.data, 0xFFFF);
|
||||
if (header.subcommand == 0xB6) {
|
||||
auto& header = check_size_t<G_MapSubsubcommand_GC_Ep3_6xB6>(
|
||||
ev.data, sizeof(G_MapSubsubcommand_GC_Ep3_6xB6), 0xFFFF);
|
||||
auto& header = check_size_t<G_MapSubsubcommand_GC_Ep3_6xB6>(ev.data, 0xFFFF);
|
||||
if (header.subsubcommand == 0x41) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1532,8 +1532,7 @@ const unordered_map<uint8_t, Server::handler_t> Server::subcommand_handlers({
|
||||
});
|
||||
|
||||
void Server::on_server_data_input(const string& data) {
|
||||
auto header = check_size_t<G_CardBattleCommandHeader>(
|
||||
data, sizeof(G_CardBattleCommandHeader), 0xFFFF);
|
||||
auto header = check_size_t<G_CardBattleCommandHeader>(data, 0xFFFF);
|
||||
if (header.size * 4 < data.size()) {
|
||||
throw runtime_error("command is incomplete");
|
||||
}
|
||||
|
||||
+52
-32
@@ -49,12 +49,12 @@ union PSOCommandHeader {
|
||||
|
||||
// This function is used in a lot of places to check received command sizes and
|
||||
// cast them to the appropriate type
|
||||
template <typename T>
|
||||
const T& check_size_t(
|
||||
const void* data,
|
||||
template <typename RetT, typename PtrT>
|
||||
RetT& check_size_generic(
|
||||
PtrT data,
|
||||
size_t size,
|
||||
size_t min_size = sizeof(T),
|
||||
size_t max_size = sizeof(T)) {
|
||||
size_t min_size,
|
||||
size_t max_size) {
|
||||
if (size < min_size) {
|
||||
throw std::runtime_error(string_printf(
|
||||
"command too small (expected at least 0x%zX bytes, received 0x%zX bytes)",
|
||||
@@ -65,39 +65,59 @@ const T& check_size_t(
|
||||
"command too large (expected at most 0x%zX bytes, received 0x%zX bytes)",
|
||||
max_size, size));
|
||||
}
|
||||
return *reinterpret_cast<const T*>(data);
|
||||
return *reinterpret_cast<RetT*>(data);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
const T& check_size_t(const std::string& data, size_t min_size, size_t max_size) {
|
||||
return check_size_generic<const T, const void*>(data.data(), data.size(), min_size, max_size);
|
||||
}
|
||||
template <typename T>
|
||||
const T& check_size_t(
|
||||
const std::string& data,
|
||||
size_t min_size = sizeof(T),
|
||||
size_t max_size = sizeof(T)) {
|
||||
return check_size_t<T>(data.data(), data.size(), min_size, max_size);
|
||||
const T& check_size_t(const std::string& data, size_t max_size) {
|
||||
return check_size_generic<const T, const void*>(data.data(), data.size(), sizeof(T), max_size);
|
||||
}
|
||||
template <typename T>
|
||||
T& check_size_t(
|
||||
void* data,
|
||||
size_t size,
|
||||
size_t min_size = sizeof(T),
|
||||
size_t max_size = sizeof(T)) {
|
||||
if (size < min_size) {
|
||||
throw std::runtime_error(string_printf(
|
||||
"command too small (expected at least 0x%zX bytes, received 0x%zX bytes)",
|
||||
min_size, size));
|
||||
}
|
||||
if (size > max_size) {
|
||||
throw std::runtime_error(string_printf(
|
||||
"command too large (expected at most 0x%zX bytes, received 0x%zX bytes)",
|
||||
max_size, size));
|
||||
}
|
||||
return *reinterpret_cast<T*>(data);
|
||||
const T& check_size_t(const std::string& data) {
|
||||
return check_size_generic<const T, const void*>(data.data(), data.size(), sizeof(T), sizeof(T));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T& check_size_t(std::string& data, size_t min_size, size_t max_size) {
|
||||
return check_size_generic<T, void*>(data.data(), data.size(), min_size, max_size);
|
||||
}
|
||||
template <typename T>
|
||||
T& check_size_t(
|
||||
std::string& data,
|
||||
size_t min_size = sizeof(T),
|
||||
size_t max_size = sizeof(T)) {
|
||||
return check_size_t<T>(data.data(), data.size(), min_size, max_size);
|
||||
T& check_size_t(std::string& data, size_t max_size) {
|
||||
return check_size_generic<T, void*>(data.data(), data.size(), sizeof(T), max_size);
|
||||
}
|
||||
template <typename T>
|
||||
T& check_size_t(std::string& data) {
|
||||
return check_size_generic<T, void*>(data.data(), data.size(), sizeof(T), sizeof(T));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
const T& check_size_t(const void* data, size_t size, size_t min_size, size_t max_size) {
|
||||
return check_size_generic<const T, const void*>(data, size, min_size, max_size);
|
||||
}
|
||||
template <typename T>
|
||||
const T& check_size_t(const void* data, size_t size, size_t max_size) {
|
||||
return check_size_generic<const T, const void*>(data, size, sizeof(T), max_size);
|
||||
}
|
||||
template <typename T>
|
||||
const T& check_size_t(const void* data, size_t size) {
|
||||
return check_size_generic<const T, const void*>(data, size, sizeof(T), sizeof(T));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T& check_size_t(void* data, size_t size, size_t min_size, size_t max_size) {
|
||||
return check_size_generic<T, void*>(data, size, min_size, max_size);
|
||||
}
|
||||
template <typename T>
|
||||
T& check_size_t(void* data, size_t size, size_t max_size) {
|
||||
return check_size_generic<T, void*>(data, size, sizeof(T), max_size);
|
||||
}
|
||||
template <typename T>
|
||||
T& check_size_t(void* data, size_t size) {
|
||||
return check_size_generic<T, void*>(data, size, sizeof(T), sizeof(T));
|
||||
}
|
||||
|
||||
void check_size_v(size_t size, size_t min_size, size_t max_size = 0);
|
||||
|
||||
+28
-32
@@ -224,8 +224,7 @@ static HandlerResult S_V123P_02_17(
|
||||
|
||||
// Most servers don't include after_message or have a shorter
|
||||
// after_message than newserv does, so don't require it
|
||||
const auto& cmd = check_size_t<S_ServerInitDefault_DC_PC_V3_02_17_91_9B>(data,
|
||||
sizeof(S_ServerInitDefault_DC_PC_V3_02_17_91_9B), 0xFFFF);
|
||||
const auto& cmd = check_size_t<S_ServerInitDefault_DC_PC_V3_02_17_91_9B>(data, 0xFFFF);
|
||||
|
||||
if (!session.license) {
|
||||
session.log.info("No license in linked session");
|
||||
@@ -431,8 +430,7 @@ static HandlerResult S_B_03(shared_ptr<ServerState> s,
|
||||
ProxyServer::LinkedSession& session, uint16_t, uint32_t, string& data) {
|
||||
// Most servers don't include after_message or have a shorter after_message
|
||||
// than newserv does, so don't require it
|
||||
const auto& cmd = check_size_t<S_ServerInitDefault_BB_03_9B>(data,
|
||||
sizeof(S_ServerInitDefault_BB_03_9B), 0xFFFF);
|
||||
const auto& cmd = check_size_t<S_ServerInitDefault_BB_03_9B>(data, 0xFFFF);
|
||||
|
||||
// If the session has a detector crypt, then it was resumed from an unlinked
|
||||
// session, during which we already sent an 03 command.
|
||||
@@ -545,8 +543,7 @@ static HandlerResult S_V123_04(shared_ptr<ServerState>,
|
||||
static HandlerResult S_V123_06(shared_ptr<ServerState>,
|
||||
ProxyServer::LinkedSession& session, uint16_t, uint32_t, string& data) {
|
||||
if (session.license) {
|
||||
auto& cmd = check_size_t<SC_TextHeader_01_06_11_B0_EE>(data,
|
||||
sizeof(SC_TextHeader_01_06_11_B0_EE), 0xFFFF);
|
||||
auto& cmd = check_size_t<SC_TextHeader_01_06_11_B0_EE>(data, 0xFFFF);
|
||||
if (cmd.guild_card_number == session.remote_guild_card_number) {
|
||||
cmd.guild_card_number = session.license->serial_number;
|
||||
return HandlerResult::Type::MODIFIED;
|
||||
@@ -604,8 +601,8 @@ static HandlerResult S_88(shared_ptr<ServerState>,
|
||||
bool modified = false;
|
||||
if (session.license) {
|
||||
size_t expected_size = sizeof(S_ArrowUpdateEntry_88) * flag;
|
||||
auto* entries = &check_size_t<S_ArrowUpdateEntry_88>(data,
|
||||
expected_size, expected_size);
|
||||
auto* entries = &check_size_t<S_ArrowUpdateEntry_88>(
|
||||
data, expected_size, expected_size);
|
||||
for (size_t x = 0; x < flag; x++) {
|
||||
if (entries[x].guild_card_number == session.remote_guild_card_number) {
|
||||
entries[x].guild_card_number = session.license->serial_number;
|
||||
@@ -626,7 +623,7 @@ static HandlerResult S_B1(shared_ptr<ServerState>,
|
||||
|
||||
static HandlerResult S_B2(shared_ptr<ServerState>,
|
||||
ProxyServer::LinkedSession& session, uint16_t, uint32_t flag, string& data) {
|
||||
const auto& cmd = check_size_t<S_ExecuteCode_B2>(data, sizeof(S_ExecuteCode_B2), 0xFFFF);
|
||||
const auto& cmd = check_size_t<S_ExecuteCode_B2>(data, 0xFFFF);
|
||||
|
||||
if (cmd.code_size && session.options.save_files) {
|
||||
uint64_t filename_timestamp = now();
|
||||
@@ -843,7 +840,7 @@ static HandlerResult S_19_P_14(shared_ptr<ServerState>,
|
||||
} else {
|
||||
// This weird maximum size is here to properly handle the version-split
|
||||
// command that some servers (including newserv) use on port 9100
|
||||
auto& cmd = check_size_t<S_Reconnect_19>(data, sizeof(S_Reconnect_19), 0xFFFF);
|
||||
auto& cmd = check_size_t<S_Reconnect_19>(data, 0xFFFF);
|
||||
sin->sin_addr.s_addr = cmd.address.load_raw(); // Already big-endian
|
||||
sin->sin_port = htons(cmd.port);
|
||||
}
|
||||
@@ -869,7 +866,7 @@ static HandlerResult S_19_P_14(shared_ptr<ServerState>,
|
||||
if (sin->sin_family != AF_INET) {
|
||||
throw logic_error("existing connection is not ipv4");
|
||||
}
|
||||
auto& cmd = check_size_t<S_Reconnect_19>(data, sizeof(S_Reconnect_19), 0xFFFF);
|
||||
auto& cmd = check_size_t<S_Reconnect_19>(data, 0xFFFF);
|
||||
cmd.address.store_raw(sin->sin_addr.s_addr);
|
||||
cmd.port = ntohs(sin->sin_port);
|
||||
return HandlerResult::Type::MODIFIED;
|
||||
@@ -906,11 +903,9 @@ static HandlerResult S_6x(shared_ptr<ServerState>,
|
||||
if (session.options.save_files) {
|
||||
if ((session.version == GameVersion::GC) && (data.size() >= 0x14)) {
|
||||
if (static_cast<uint8_t>(data[0]) == 0xB6) {
|
||||
const auto& header = check_size_t<G_MapSubsubcommand_GC_Ep3_6xB6>(
|
||||
data, sizeof(G_MapSubsubcommand_GC_Ep3_6xB6), 0xFFFF);
|
||||
const auto& header = check_size_t<G_MapSubsubcommand_GC_Ep3_6xB6>(data, 0xFFFF);
|
||||
if (header.subsubcommand == 0x00000041) {
|
||||
const auto& cmd = check_size_t<G_MapData_GC_Ep3_6xB6x41>(
|
||||
data, sizeof(G_MapData_GC_Ep3_6xB6x41), 0xFFFF);
|
||||
const auto& cmd = check_size_t<G_MapData_GC_Ep3_6xB6x41>(data, 0xFFFF);
|
||||
string filename = string_printf("map%08" PRIX32 ".%" PRIu64 ".mnmd",
|
||||
cmd.map_number.load(), now());
|
||||
string map_data = prs_decompress(
|
||||
@@ -934,8 +929,7 @@ static HandlerResult S_6x(shared_ptr<ServerState>,
|
||||
((static_cast<uint8_t>(data[0]) == 0xB3) ||
|
||||
(static_cast<uint8_t>(data[0]) == 0xB4) ||
|
||||
(static_cast<uint8_t>(data[0]) == 0xB5))) {
|
||||
const auto& header = check_size_t<G_CardBattleCommandHeader>(
|
||||
data, sizeof(G_CardBattleCommandHeader), 0xFFFF);
|
||||
const auto& header = check_size_t<G_CardBattleCommandHeader>(data, 0xFFFF);
|
||||
if (header.mask_key) {
|
||||
set_mask_for_ep3_game_command(data.data(), data.size(), 0);
|
||||
modified = true;
|
||||
@@ -944,7 +938,7 @@ static HandlerResult S_6x(shared_ptr<ServerState>,
|
||||
|
||||
if (data[0] == 0x46) {
|
||||
const auto& cmd = check_size_t<G_AttackFinished_6x46>(data,
|
||||
offsetof(G_AttackFinished_6x46, entries),
|
||||
offsetof(G_AttackFinished_6x46, targets),
|
||||
sizeof(G_AttackFinished_6x46));
|
||||
size_t allowed_count = min<size_t>(cmd.header.size - 2, 11);
|
||||
if (cmd.count > allowed_count) {
|
||||
@@ -973,14 +967,13 @@ static HandlerResult S_6x(shared_ptr<ServerState>,
|
||||
} else if ((data[0] == 0x60) &&
|
||||
session.next_drop_item.data.data1d[0] &&
|
||||
(session.version != GameVersion::BB)) {
|
||||
const auto& cmd = check_size_t<G_EnemyDropItemRequest_DC_6x60>(data,
|
||||
sizeof(G_EnemyDropItemRequest_DC_6x60),
|
||||
sizeof(G_EnemyDropItemRequest_PC_V3_BB_6x60));
|
||||
const auto& cmd = check_size_t<G_StandardDropItemRequest_DC_6x60>(
|
||||
data, sizeof(G_StandardDropItemRequest_PC_V3_BB_6x60));
|
||||
session.next_drop_item.data.id = session.next_item_id++;
|
||||
send_drop_item(session.server_channel, session.next_drop_item.data,
|
||||
true, cmd.area, cmd.x, cmd.z, cmd.enemy_id);
|
||||
true, cmd.area, cmd.x, cmd.z, cmd.entity_id);
|
||||
send_drop_item(session.client_channel, session.next_drop_item.data,
|
||||
true, cmd.area, cmd.x, cmd.z, cmd.enemy_id);
|
||||
true, cmd.area, cmd.x, cmd.z, cmd.entity_id);
|
||||
session.next_drop_item.clear();
|
||||
return HandlerResult::Type::SUPPRESS;
|
||||
|
||||
@@ -991,12 +984,12 @@ static HandlerResult S_6x(shared_ptr<ServerState>,
|
||||
} else if ((static_cast<uint8_t>(data[0]) == 0xA2) &&
|
||||
session.next_drop_item.data.data1d[0] &&
|
||||
(session.version != GameVersion::BB)) {
|
||||
const auto& cmd = check_size_t<G_BoxItemDropRequest_6xA2>(data);
|
||||
const auto& cmd = check_size_t<G_SpecializableItemDropRequest_6xA2>(data);
|
||||
session.next_drop_item.data.id = session.next_item_id++;
|
||||
send_drop_item(session.server_channel, session.next_drop_item.data,
|
||||
false, cmd.area, cmd.x, cmd.z, cmd.request_id);
|
||||
false, cmd.area, cmd.x, cmd.z, cmd.entity_id);
|
||||
send_drop_item(session.client_channel, session.next_drop_item.data,
|
||||
false, cmd.area, cmd.x, cmd.z, cmd.request_id);
|
||||
false, cmd.area, cmd.x, cmd.z, cmd.entity_id);
|
||||
session.next_drop_item.clear();
|
||||
return HandlerResult::Type::SUPPRESS;
|
||||
|
||||
@@ -1024,7 +1017,7 @@ static HandlerResult C_GXB_61(shared_ptr<ServerState>,
|
||||
// return MODIFIED if so.
|
||||
|
||||
if (session.version == GameVersion::BB) {
|
||||
auto& pd = check_size_t<PSOPlayerDataBB>(data, sizeof(PSOPlayerDataBB), 0xFFFF);
|
||||
auto& pd = check_size_t<PSOPlayerDataBB>(data, 0xFFFF);
|
||||
if (session.options.enable_chat_filter) {
|
||||
add_color_inplace(pd.info_board.data(), pd.info_board.size());
|
||||
}
|
||||
@@ -1055,7 +1048,7 @@ static HandlerResult C_GXB_61(shared_ptr<ServerState>,
|
||||
}
|
||||
pd = reinterpret_cast<PSOPlayerDataV3*>(&ep3_pd);
|
||||
} else {
|
||||
pd = &check_size_t<PSOPlayerDataV3>(data, sizeof(PSOPlayerDataV3), 0xFFFF);
|
||||
pd = &check_size_t<PSOPlayerDataV3>(data, 0xFFFF);
|
||||
}
|
||||
if (session.options.enable_chat_filter) {
|
||||
add_color_inplace(pd->info_board.data(), pd->info_board.size());
|
||||
@@ -1242,8 +1235,7 @@ static HandlerResult S_G_B9(shared_ptr<ServerState>,
|
||||
|
||||
if (session.options.save_files) {
|
||||
try {
|
||||
const auto& header = check_size_t<S_UpdateMediaHeader_GC_Ep3_B9>(data,
|
||||
sizeof(S_UpdateMediaHeader_GC_Ep3_B9), 0xFFFF);
|
||||
const auto& header = check_size_t<S_UpdateMediaHeader_GC_Ep3_B9>(data, 0xFFFF);
|
||||
|
||||
if (data.size() - sizeof(header) < header.size) {
|
||||
throw runtime_error("Media data size extends beyond end of command; not saving file");
|
||||
@@ -1394,7 +1386,7 @@ static HandlerResult S_64(shared_ptr<ServerState>,
|
||||
CmdT* cmd;
|
||||
S_JoinGame_GC_Ep3_64* cmd_ep3 = nullptr;
|
||||
if (session.sub_version >= 0x40) {
|
||||
cmd = &check_size_t<CmdT>(data, sizeof(S_JoinGame_GC_Ep3_64), sizeof(S_JoinGame_GC_Ep3_64));
|
||||
cmd = &check_size_t<CmdT>(data, sizeof(S_JoinGame_GC_Ep3_64));
|
||||
cmd_ep3 = &check_size_t<S_JoinGame_GC_Ep3_64>(data);
|
||||
} else {
|
||||
cmd = &check_size_t<CmdT>(data);
|
||||
@@ -1549,7 +1541,7 @@ static HandlerResult C_98(shared_ptr<ServerState> s,
|
||||
static HandlerResult C_06(shared_ptr<ServerState> s,
|
||||
ProxyServer::LinkedSession& session, uint16_t, uint32_t, string& data) {
|
||||
if (data.size() >= 12) {
|
||||
const auto& cmd = check_size_t<C_Chat_06>(data, sizeof(C_Chat_06), 0xFFFF);
|
||||
const auto& cmd = check_size_t<C_Chat_06>(data, 0xFFFF);
|
||||
|
||||
u16string text;
|
||||
uint8_t private_flags = 0;
|
||||
@@ -1668,6 +1660,8 @@ static HandlerResult C_6x(shared_ptr<ServerState> s,
|
||||
if (session.options.infinite_hp) {
|
||||
send_player_stats_change(session.client_channel,
|
||||
session.lobby_client_id, PlayerStatsChange::ADD_HP, 2550);
|
||||
send_player_stats_change(session.server_channel,
|
||||
session.lobby_client_id, PlayerStatsChange::ADD_HP, 2550);
|
||||
}
|
||||
} else if (data[0] == 0x3E) {
|
||||
C_6x_movement<G_StopAtPosition_6x3E>(session, data);
|
||||
@@ -1681,6 +1675,8 @@ static HandlerResult C_6x(shared_ptr<ServerState> s,
|
||||
if (session.options.infinite_tp) {
|
||||
send_player_stats_change(session.client_channel,
|
||||
session.lobby_client_id, PlayerStatsChange::ADD_TP, 255);
|
||||
send_player_stats_change(session.server_channel,
|
||||
session.lobby_client_id, PlayerStatsChange::ADD_TP, 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-6
@@ -266,8 +266,7 @@ void ProxyServer::UnlinkedSession::on_input(Channel& ch, uint16_t command, uint3
|
||||
hardware_id = cmd.hardware_id;
|
||||
client_config.cfg.flags |= Client::Flag::IS_DC_V1;
|
||||
} else if (command == 0x9D) {
|
||||
const auto& cmd = check_size_t<C_Login_DC_PC_GC_9D>(
|
||||
data, sizeof(C_Login_DC_PC_GC_9D), sizeof(C_LoginExtended_DC_GC_9D));
|
||||
const auto& cmd = check_size_t<C_Login_DC_PC_GC_9D>(data, sizeof(C_LoginExtended_DC_GC_9D));
|
||||
license = session->server->state->license_manager->verify_pc(
|
||||
stoul(cmd.serial_number, nullptr, 16), cmd.access_key);
|
||||
sub_version = cmd.sub_version;
|
||||
@@ -283,8 +282,7 @@ void ProxyServer::UnlinkedSession::on_input(Channel& ch, uint16_t command, uint3
|
||||
if (command != 0x9D) {
|
||||
throw runtime_error("command is not 9D");
|
||||
}
|
||||
const auto& cmd = check_size_t<C_Login_DC_PC_GC_9D>(
|
||||
data, sizeof(C_Login_DC_PC_GC_9D), sizeof(C_LoginExtended_PC_9D));
|
||||
const auto& cmd = check_size_t<C_Login_DC_PC_GC_9D>(data, sizeof(C_LoginExtended_PC_9D));
|
||||
license = session->server->state->license_manager->verify_pc(
|
||||
stoul(cmd.serial_number, nullptr, 16), cmd.access_key);
|
||||
sub_version = cmd.sub_version;
|
||||
@@ -298,8 +296,7 @@ void ProxyServer::UnlinkedSession::on_input(Channel& ch, uint16_t command, uint3
|
||||
if (command != 0x9E) {
|
||||
throw runtime_error("command is not 9E");
|
||||
}
|
||||
const auto& cmd = check_size_t<C_Login_GC_9E>(
|
||||
data, sizeof(C_Login_GC_9E), sizeof(C_LoginExtended_GC_9E));
|
||||
const auto& cmd = check_size_t<C_Login_GC_9E>(data, sizeof(C_LoginExtended_GC_9E));
|
||||
license = session->server->state->license_manager->verify_gc(
|
||||
stoul(cmd.serial_number, nullptr, 16), cmd.access_key);
|
||||
sub_version = cmd.sub_version;
|
||||
|
||||
+14
-23
@@ -391,8 +391,7 @@ static void on_88_DCNTE(shared_ptr<ServerState> s, shared_ptr<Client> c,
|
||||
|
||||
static void on_8B_DCNTE(shared_ptr<ServerState> s, shared_ptr<Client> c,
|
||||
uint16_t, uint32_t, const string& data) {
|
||||
const auto& cmd = check_size_t<C_Login_DCNTE_8B>(data,
|
||||
sizeof(C_Login_DCNTE_8B), sizeof(C_LoginExtended_DCNTE_8B));
|
||||
const auto& cmd = check_size_t<C_Login_DCNTE_8B>(data, sizeof(C_LoginExtended_DCNTE_8B));
|
||||
c->channel.version = GameVersion::DC;
|
||||
c->flags |= flags_for_version(c->version(), -1);
|
||||
c->flags |= Client::Flag::IS_DC_V1 | Client::Flag::IS_TRIAL_EDITION;
|
||||
@@ -436,7 +435,7 @@ static void on_8B_DCNTE(shared_ptr<ServerState> s, shared_ptr<Client> c,
|
||||
|
||||
static void on_90_DC(shared_ptr<ServerState> s, shared_ptr<Client> c,
|
||||
uint16_t, uint32_t, const string& data) {
|
||||
const auto& cmd = check_size_t<C_LoginV1_DC_PC_V3_90>(data, sizeof(C_LoginV1_DC_PC_V3_90), 0xFFFF);
|
||||
const auto& cmd = check_size_t<C_LoginV1_DC_PC_V3_90>(data, 0xFFFF);
|
||||
c->channel.version = GameVersion::DC;
|
||||
c->flags |= flags_for_version(c->version(), -1);
|
||||
c->flags |= Client::Flag::IS_DC_V1;
|
||||
@@ -478,8 +477,7 @@ static void on_92_DC(shared_ptr<ServerState>, shared_ptr<Client> c,
|
||||
|
||||
static void on_93_DC(shared_ptr<ServerState> s, shared_ptr<Client> c,
|
||||
uint16_t, uint32_t, const string& data) {
|
||||
const auto& cmd = check_size_t<C_LoginV1_DC_93>(data,
|
||||
sizeof(C_LoginV1_DC_93), sizeof(C_LoginExtendedV1_DC_93));
|
||||
const auto& cmd = check_size_t<C_LoginV1_DC_93>(data, sizeof(C_LoginExtendedV1_DC_93));
|
||||
set_console_client_flags(c, cmd.sub_version);
|
||||
|
||||
uint32_t serial_number = stoul(cmd.serial_number, nullptr, 16);
|
||||
@@ -650,8 +648,7 @@ static void on_9D_9E(shared_ptr<ServerState> s, shared_ptr<Client> c,
|
||||
uint16_t command, uint32_t, const string& data) {
|
||||
const C_Login_DC_PC_GC_9D* base_cmd;
|
||||
if (command == 0x9D) {
|
||||
base_cmd = &check_size_t<C_Login_DC_PC_GC_9D>(data,
|
||||
sizeof(C_Login_DC_PC_GC_9D), sizeof(C_LoginExtended_PC_9D));
|
||||
base_cmd = &check_size_t<C_Login_DC_PC_GC_9D>(data, sizeof(C_LoginExtended_PC_9D));
|
||||
if (base_cmd->is_extended) {
|
||||
if (c->version() == GameVersion::PC) {
|
||||
const auto& cmd = check_size_t<C_LoginExtended_PC_9D>(data);
|
||||
@@ -669,8 +666,7 @@ static void on_9D_9E(shared_ptr<ServerState> s, shared_ptr<Client> c,
|
||||
} else if (command == 0x9E) {
|
||||
// GC and XB send different amounts of data in this command. This is how
|
||||
// newserv determines if a V3 client is GC or XB.
|
||||
const auto& cmd = check_size_t<C_Login_GC_9E>(data,
|
||||
sizeof(C_Login_GC_9E), sizeof(C_LoginExtended_XB_9E));
|
||||
const auto& cmd = check_size_t<C_Login_GC_9E>(data, sizeof(C_LoginExtended_XB_9E));
|
||||
switch (data.size()) {
|
||||
case sizeof(C_Login_GC_9E):
|
||||
case sizeof(C_LoginExtended_GC_9E):
|
||||
@@ -1310,8 +1306,7 @@ static void on_CA_Ep3(shared_ptr<ServerState> s, shared_ptr<Client> c,
|
||||
throw runtime_error("Episode 3 server data request sent outside of Episode 3 game");
|
||||
}
|
||||
|
||||
const auto& header = check_size_t<G_CardServerDataCommandHeader>(
|
||||
data, sizeof(G_CardServerDataCommandHeader), 0xFFFF);
|
||||
const auto& header = check_size_t<G_CardServerDataCommandHeader>(data, 0xFFFF);
|
||||
if (header.subcommand != 0xB3) {
|
||||
throw runtime_error("unknown Episode 3 server data request");
|
||||
}
|
||||
@@ -2448,8 +2443,7 @@ static void on_61_98(shared_ptr<ServerState> s, shared_ptr<Client> c,
|
||||
switch (c->version()) {
|
||||
case GameVersion::DC:
|
||||
case GameVersion::PC: {
|
||||
const auto& pd = check_size_t<PSOPlayerDataDCPC>(data,
|
||||
sizeof(PSOPlayerDataDCPC), 0xFFFF);
|
||||
const auto& pd = check_size_t<PSOPlayerDataDCPC>(data, 0xFFFF);
|
||||
c->game_data.import_player(pd);
|
||||
break;
|
||||
}
|
||||
@@ -2464,14 +2458,14 @@ static void on_61_98(shared_ptr<ServerState> s, shared_ptr<Client> c,
|
||||
c->game_data.ep3_config.reset(new Episode3::PlayerConfig(pd3->ep3_config));
|
||||
pd = reinterpret_cast<const PSOPlayerDataV3*>(pd3);
|
||||
} else {
|
||||
pd = &check_size_t<PSOPlayerDataV3>(data, sizeof(PSOPlayerDataV3),
|
||||
pd = &check_size_t<PSOPlayerDataV3>(data,
|
||||
sizeof(PSOPlayerDataV3) + c->game_data.player()->auto_reply.bytes());
|
||||
}
|
||||
c->game_data.import_player(*pd);
|
||||
break;
|
||||
}
|
||||
case GameVersion::BB: {
|
||||
const auto& pd = check_size_t<PSOPlayerDataBB>(data, sizeof(PSOPlayerDataBB),
|
||||
const auto& pd = check_size_t<PSOPlayerDataBB>(data,
|
||||
sizeof(PSOPlayerDataBB) + c->game_data.player()->auto_reply.bytes());
|
||||
c->game_data.import_player(pd);
|
||||
break;
|
||||
@@ -2599,7 +2593,7 @@ static void on_chat_generic(shared_ptr<ServerState> s, shared_ptr<Client> c,
|
||||
|
||||
static void on_06_PC_BB(shared_ptr<ServerState> s, shared_ptr<Client> c,
|
||||
uint16_t, uint32_t, const string& data) {
|
||||
const auto& cmd = check_size_t<C_Chat_06>(data, sizeof(C_Chat_06), 0xFFFF);
|
||||
const auto& cmd = check_size_t<C_Chat_06>(data, 0xFFFF);
|
||||
u16string text(cmd.text.pcbb, (data.size() - sizeof(C_Chat_06)) / sizeof(char16_t));
|
||||
strip_trailing_zeroes(text);
|
||||
on_chat_generic(s, c, text);
|
||||
@@ -2607,7 +2601,7 @@ static void on_06_PC_BB(shared_ptr<ServerState> s, shared_ptr<Client> c,
|
||||
|
||||
static void on_06_DC_V3(shared_ptr<ServerState> s, shared_ptr<Client> c,
|
||||
uint16_t, uint32_t, const string& data) {
|
||||
const auto& cmd = check_size_t<C_Chat_06>(data, sizeof(C_Chat_06), 0xFFFF);
|
||||
const auto& cmd = check_size_t<C_Chat_06>(data, 0xFFFF);
|
||||
u16string decoded_s = decode_sjis(cmd.text.dcv3, data.size() - sizeof(C_Chat_06));
|
||||
on_chat_generic(s, c, decoded_s);
|
||||
}
|
||||
@@ -4197,21 +4191,18 @@ void on_command_with_header(shared_ptr<ServerState> s, shared_ptr<Client> c,
|
||||
case GameVersion::DC:
|
||||
case GameVersion::GC:
|
||||
case GameVersion::XB: {
|
||||
auto& header = check_size_t<PSOCommandHeaderDCV3>(data,
|
||||
sizeof(PSOCommandHeaderDCV3), 0xFFFF);
|
||||
auto& header = check_size_t<PSOCommandHeaderDCV3>(data, 0xFFFF);
|
||||
on_command(s, c, header.command, header.flag, data.substr(sizeof(header)));
|
||||
break;
|
||||
}
|
||||
case GameVersion::PC:
|
||||
case GameVersion::PATCH: {
|
||||
auto& header = check_size_t<PSOCommandHeaderPC>(data,
|
||||
sizeof(PSOCommandHeaderPC), 0xFFFF);
|
||||
auto& header = check_size_t<PSOCommandHeaderPC>(data, 0xFFFF);
|
||||
on_command(s, c, header.command, header.flag, data.substr(sizeof(header)));
|
||||
break;
|
||||
}
|
||||
case GameVersion::BB: {
|
||||
auto& header = check_size_t<PSOCommandHeaderBB>(data,
|
||||
sizeof(PSOCommandHeaderBB), 0xFFFF);
|
||||
auto& header = check_size_t<PSOCommandHeaderBB>(data, 0xFFFF);
|
||||
on_command(s, c, header.command, header.flag, data.substr(sizeof(header)));
|
||||
break;
|
||||
}
|
||||
|
||||
+164
-191
@@ -27,38 +27,6 @@ bool command_is_private(uint8_t command) {
|
||||
return (command == 0x62) || (command == 0x6D);
|
||||
}
|
||||
|
||||
template <typename CmdT>
|
||||
const CmdT& check_size_sc(
|
||||
const string& data,
|
||||
size_t min_size = sizeof(CmdT),
|
||||
size_t max_size = sizeof(CmdT),
|
||||
bool check_size_field = true) {
|
||||
if (max_size < min_size) {
|
||||
max_size = min_size;
|
||||
}
|
||||
const auto& cmd = check_size_t<CmdT>(data, min_size, max_size);
|
||||
if (check_size_field) {
|
||||
if (data.size() < 4) {
|
||||
throw runtime_error("subcommand is too short for header");
|
||||
}
|
||||
const auto* header = reinterpret_cast<const G_UnusedHeader*>(data.data());
|
||||
if (header->size == 0) {
|
||||
if (data.size() < 8) {
|
||||
throw runtime_error("subcommand has extended size but is shorter than 8 bytes");
|
||||
}
|
||||
const auto* ext_header = reinterpret_cast<const G_ExtendedHeader<G_UnusedHeader>*>(data.data());
|
||||
if (ext_header->size != data.size()) {
|
||||
throw runtime_error("invalid subcommand extended size field");
|
||||
}
|
||||
} else {
|
||||
if ((header->size * 4) != data.size()) {
|
||||
throw runtime_error("invalid subcommand size field");
|
||||
}
|
||||
}
|
||||
}
|
||||
return cmd;
|
||||
}
|
||||
|
||||
static const unordered_set<uint8_t> watcher_subcommands({
|
||||
0x07, // Symbol chat
|
||||
0x74, // Word select
|
||||
@@ -120,16 +88,10 @@ static void forward_subcommand(shared_ptr<Lobby> l, shared_ptr<Client> c,
|
||||
}
|
||||
}
|
||||
|
||||
static void forward_subcommand(shared_ptr<Lobby> l, shared_ptr<Client> c,
|
||||
uint8_t command, uint8_t flag, const string& data) {
|
||||
forward_subcommand(l, c, command, flag, data.data(), data.size());
|
||||
}
|
||||
|
||||
static void on_invalid(shared_ptr<ServerState>,
|
||||
shared_ptr<Lobby>, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
||||
const string& data) {
|
||||
const auto& cmd = check_size_sc<G_UnusedHeader>(
|
||||
data, sizeof(G_UnusedHeader), 0xFFFF);
|
||||
const void* data, size_t size) {
|
||||
const auto& cmd = check_size_t<G_UnusedHeader>(data, size, 0xFFFF);
|
||||
if (command_is_private(command)) {
|
||||
c->log.error("Invalid subcommand: %02hhX (private to %hhu)",
|
||||
cmd.subcommand, flag);
|
||||
@@ -140,9 +102,8 @@ static void on_invalid(shared_ptr<ServerState>,
|
||||
|
||||
static void on_unimplemented(shared_ptr<ServerState>,
|
||||
shared_ptr<Lobby>, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
||||
const string& data) {
|
||||
const auto& cmd = check_size_sc<G_UnusedHeader>(
|
||||
data, sizeof(G_UnusedHeader), 0xFFFF);
|
||||
const void* data, size_t size) {
|
||||
const auto& cmd = check_size_t<G_UnusedHeader>(data, size, 0xFFFF);
|
||||
if (command_is_private(command)) {
|
||||
c->log.warning("Unknown subcommand: %02hhX (private to %hhu)",
|
||||
cmd.subcommand, flag);
|
||||
@@ -156,30 +117,29 @@ static void on_unimplemented(shared_ptr<ServerState>,
|
||||
|
||||
static void on_forward_check_size(shared_ptr<ServerState>,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
||||
const string& data) {
|
||||
check_size_sc<G_UnusedHeader>(data, sizeof(G_UnusedHeader), 0xFFFF);
|
||||
forward_subcommand(l, c, command, flag, data);
|
||||
const void* data, size_t size) {
|
||||
check_size_t<G_UnusedHeader>(data, size, 0xFFFF);
|
||||
forward_subcommand(l, c, command, flag, data, size);
|
||||
}
|
||||
|
||||
static void on_forward_check_game(shared_ptr<ServerState>,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
||||
const string& data) {
|
||||
const void* data, size_t size) {
|
||||
if (!l->is_game()) {
|
||||
return;
|
||||
}
|
||||
forward_subcommand(l, c, command, flag, data);
|
||||
forward_subcommand(l, c, command, flag, data, size);
|
||||
}
|
||||
|
||||
static void on_forward_sync_game_state(shared_ptr<ServerState>,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
||||
const string& data) {
|
||||
const void* data, size_t size) {
|
||||
if (!l->is_game() || !l->any_client_loading()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& cmd = check_size_sc<G_SyncGameStateHeader_6x6B_6x6C_6x6D_6x6E>(
|
||||
data, sizeof(G_SyncGameStateHeader_6x6B_6x6C_6x6D_6x6E), 0xFFFF);
|
||||
if (cmd.compressed_size > data.size() - sizeof(cmd)) {
|
||||
const auto& cmd = check_size_t<G_SyncGameStateHeader_6x6B_6x6C_6x6D_6x6E>(data, size, 0xFFFF);
|
||||
if (cmd.compressed_size > size - sizeof(cmd)) {
|
||||
throw runtime_error("compressed end offset is beyond end of command");
|
||||
}
|
||||
|
||||
@@ -190,57 +150,56 @@ static void on_forward_sync_game_state(shared_ptr<ServerState>,
|
||||
print_data(stderr, decompressed);
|
||||
}
|
||||
|
||||
forward_subcommand(l, c, command, flag, data);
|
||||
forward_subcommand(l, c, command, flag, data, size);
|
||||
}
|
||||
|
||||
static void on_forward_check_game_loading(shared_ptr<ServerState>,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
||||
const string& data) {
|
||||
const void* data, size_t size) {
|
||||
if (!l->is_game() || !l->any_client_loading()) {
|
||||
return;
|
||||
}
|
||||
forward_subcommand(l, c, command, flag, data);
|
||||
forward_subcommand(l, c, command, flag, data, size);
|
||||
}
|
||||
|
||||
static void on_forward_check_size_client(shared_ptr<ServerState>,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
||||
const string& data) {
|
||||
const auto& cmd = check_size_sc<G_ClientIDHeader>(
|
||||
data, sizeof(G_ClientIDHeader), 0xFFFF);
|
||||
const void* data, size_t size) {
|
||||
const auto& cmd = check_size_t<G_ClientIDHeader>(data, size, 0xFFFF);
|
||||
if (cmd.client_id != c->lobby_client_id) {
|
||||
return;
|
||||
}
|
||||
forward_subcommand(l, c, command, flag, data);
|
||||
forward_subcommand(l, c, command, flag, data, size);
|
||||
}
|
||||
|
||||
static void on_forward_check_size_game(shared_ptr<ServerState>,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
||||
const string& data) {
|
||||
check_size_sc<G_UnusedHeader>(data, sizeof(G_UnusedHeader), 0xFFFF);
|
||||
const void* data, size_t size) {
|
||||
check_size_t<G_UnusedHeader>(data, size, 0xFFFF);
|
||||
if (!l->is_game()) {
|
||||
return;
|
||||
}
|
||||
forward_subcommand(l, c, command, flag, data);
|
||||
forward_subcommand(l, c, command, flag, data, size);
|
||||
}
|
||||
|
||||
static void on_forward_check_size_ep3_lobby(shared_ptr<ServerState>,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
||||
const string& data) {
|
||||
check_size_sc<G_UnusedHeader>(data, sizeof(G_UnusedHeader), 0xFFFF);
|
||||
const void* data, size_t size) {
|
||||
check_size_t<G_UnusedHeader>(data, size, 0xFFFF);
|
||||
if (l->is_game() || !l->is_ep3()) {
|
||||
return;
|
||||
}
|
||||
forward_subcommand(l, c, command, flag, data);
|
||||
forward_subcommand(l, c, command, flag, data, size);
|
||||
}
|
||||
|
||||
static void on_forward_check_size_ep3_game(shared_ptr<ServerState>,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
||||
const string& data) {
|
||||
check_size_sc<G_UnusedHeader>(data, sizeof(G_UnusedHeader), 0xFFFF);
|
||||
const void* data, size_t size) {
|
||||
check_size_t<G_UnusedHeader>(data, size, 0xFFFF);
|
||||
if (!l->is_game() || !l->is_ep3()) {
|
||||
return;
|
||||
}
|
||||
forward_subcommand(l, c, command, flag, data);
|
||||
forward_subcommand(l, c, command, flag, data, size);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -248,21 +207,20 @@ static void on_forward_check_size_ep3_game(shared_ptr<ServerState>,
|
||||
|
||||
static void on_ep3_battle_subs(shared_ptr<ServerState> s,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
||||
const string& orig_data) {
|
||||
const auto& header = check_size_sc<G_CardBattleCommandHeader>(
|
||||
orig_data, sizeof(G_CardBattleCommandHeader), 0xFFFF);
|
||||
const void* orig_data, size_t size) {
|
||||
const auto& header = check_size_t<G_CardBattleCommandHeader>(orig_data, size, 0xFFFF);
|
||||
if (!l->is_game() || !l->is_ep3()) {
|
||||
return;
|
||||
}
|
||||
|
||||
string data = orig_data;
|
||||
string data(reinterpret_cast<const char*>(orig_data), size);
|
||||
set_mask_for_ep3_game_command(data.data(), data.size(), 0);
|
||||
|
||||
if (header.subcommand == 0xB5) {
|
||||
if (header.subsubcommand == 0x1A) {
|
||||
return;
|
||||
} else if (header.subsubcommand == 0x36) {
|
||||
const auto& cmd = check_size_t<G_Unknown_GC_Ep3_6xB5x36>(data);
|
||||
const auto& cmd = check_size_t<G_Unknown_GC_Ep3_6xB5x36>(data, size);
|
||||
if (l->is_game() && (cmd.unknown_a1 >= 4)) {
|
||||
return;
|
||||
}
|
||||
@@ -277,7 +235,7 @@ static void on_ep3_battle_subs(shared_ptr<ServerState> s,
|
||||
set_mask_for_ep3_game_command(data.data(), data.size(), mask_key);
|
||||
}
|
||||
|
||||
forward_subcommand(l, c, command, flag, data);
|
||||
forward_subcommand(l, c, command, flag, data.data(), data.size());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -285,7 +243,7 @@ static void on_ep3_battle_subs(shared_ptr<ServerState> s,
|
||||
|
||||
static void on_send_guild_card(shared_ptr<ServerState>,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
||||
const string& data) {
|
||||
const void* data, size_t size) {
|
||||
if (!command_is_private(command) || !l || (flag >= l->max_clients) ||
|
||||
(!l->clients[flag])) {
|
||||
return;
|
||||
@@ -293,18 +251,18 @@ static void on_send_guild_card(shared_ptr<ServerState>,
|
||||
|
||||
switch (c->version()) {
|
||||
case GameVersion::DC: {
|
||||
const auto& cmd = check_size_sc<G_SendGuildCard_DC_6x06>(data);
|
||||
const auto& cmd = check_size_t<G_SendGuildCard_DC_6x06>(data, size);
|
||||
c->game_data.player()->guild_card_description = cmd.description;
|
||||
break;
|
||||
}
|
||||
case GameVersion::PC: {
|
||||
const auto& cmd = check_size_sc<G_SendGuildCard_PC_6x06>(data);
|
||||
const auto& cmd = check_size_t<G_SendGuildCard_PC_6x06>(data, size);
|
||||
c->game_data.player()->guild_card_description = cmd.description;
|
||||
break;
|
||||
}
|
||||
case GameVersion::GC:
|
||||
case GameVersion::XB: {
|
||||
const auto& cmd = check_size_sc<G_SendGuildCard_V3_6x06>(data);
|
||||
const auto& cmd = check_size_t<G_SendGuildCard_V3_6x06>(data, size);
|
||||
c->game_data.player()->guild_card_description = cmd.description;
|
||||
break;
|
||||
}
|
||||
@@ -322,39 +280,39 @@ static void on_send_guild_card(shared_ptr<ServerState>,
|
||||
// client sends a symbol chat
|
||||
static void on_symbol_chat(shared_ptr<ServerState>,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
||||
const string& data) {
|
||||
const auto& cmd = check_size_sc<G_SymbolChat_6x07>(data);
|
||||
const void* data, size_t size) {
|
||||
const auto& cmd = check_size_t<G_SymbolChat_6x07>(data, size);
|
||||
|
||||
if (!c->can_chat || (cmd.client_id != c->lobby_client_id)) {
|
||||
return;
|
||||
}
|
||||
forward_subcommand(l, c, command, flag, data);
|
||||
forward_subcommand(l, c, command, flag, data, size);
|
||||
}
|
||||
|
||||
// client sends a word select chat
|
||||
static void on_word_select(shared_ptr<ServerState>,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
||||
const string& data) {
|
||||
const auto& cmd = check_size_sc<G_WordSelect_6x74>(data);
|
||||
const void* data, size_t size) {
|
||||
const auto& cmd = check_size_t<G_WordSelect_6x74>(data, size);
|
||||
|
||||
if (!c->can_chat || (cmd.header.client_id != c->lobby_client_id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
forward_subcommand(l, c, command, flag, data);
|
||||
forward_subcommand(l, c, command, flag, data, size);
|
||||
}
|
||||
|
||||
// client is done loading into a lobby (we use this to trigger arrow updates)
|
||||
static void on_set_player_visibility(shared_ptr<ServerState>,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
||||
const string& data) {
|
||||
const auto& cmd = check_size_sc<G_SetPlayerVisibility_6x22_6x23>(data);
|
||||
const void* data, size_t size) {
|
||||
const auto& cmd = check_size_t<G_SetPlayerVisibility_6x22_6x23>(data, size);
|
||||
|
||||
if (cmd.header.client_id != c->lobby_client_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
forward_subcommand(l, c, command, flag, data);
|
||||
forward_subcommand(l, c, command, flag, data, size);
|
||||
|
||||
if (!l->is_game() && !(c->flags & Client::Flag::IS_DC_V1)) {
|
||||
send_arrow_update(l);
|
||||
@@ -366,38 +324,38 @@ static void on_set_player_visibility(shared_ptr<ServerState>,
|
||||
|
||||
static void on_change_area(shared_ptr<ServerState>,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
||||
const string& data) {
|
||||
const auto& cmd = check_size_sc<G_InterLevelWarp_6x21>(data);
|
||||
const void* data, size_t size) {
|
||||
const auto& cmd = check_size_t<CmdT>(data, size);
|
||||
if (!l->is_game()) {
|
||||
return;
|
||||
}
|
||||
c->area = cmd.area;
|
||||
forward_subcommand(l, c, command, flag, data);
|
||||
forward_subcommand(l, c, command, flag, data, size);
|
||||
}
|
||||
|
||||
// when a player is hit by an enemy, heal them if infinite HP is enabled
|
||||
static void on_hit_by_enemy(shared_ptr<ServerState>,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
||||
const string& data) {
|
||||
const auto& cmd = check_size_sc<G_ClientIDHeader>(data, sizeof(G_ClientIDHeader), 0xFFFF);
|
||||
const void* data, size_t size) {
|
||||
const auto& cmd = check_size_t<G_ClientIDHeader>(data, size, 0xFFFF);
|
||||
if (!l->is_game() || (cmd.client_id != c->lobby_client_id)) {
|
||||
return;
|
||||
}
|
||||
forward_subcommand(l, c, command, flag, data);
|
||||
forward_subcommand(l, c, command, flag, data, size);
|
||||
if ((l->flags & Lobby::Flag::CHEATS_ENABLED) && c->options.infinite_hp) {
|
||||
send_player_stats_change(l, c, PlayerStatsChange::ADD_HP, 2550);
|
||||
}
|
||||
}
|
||||
|
||||
// when a player casts a tech, restore TP if infinite TP is enabled
|
||||
// When a player casts a tech, restore TP if infinite TP is enabled
|
||||
static void on_cast_technique_finished(shared_ptr<ServerState>,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
||||
const string& data) {
|
||||
const auto& cmd = check_size_sc<G_CastTechniqueComplete_6x48>(data);
|
||||
const void* data, size_t size) {
|
||||
const auto& cmd = check_size_t<G_CastTechniqueComplete_6x48>(data, size);
|
||||
if (!l->is_game() || (cmd.header.client_id != c->lobby_client_id)) {
|
||||
return;
|
||||
}
|
||||
forward_subcommand(l, c, command, flag, data);
|
||||
forward_subcommand(l, c, command, flag, data, size);
|
||||
if ((l->flags & Lobby::Flag::CHEATS_ENABLED) && c->options.infinite_tp) {
|
||||
send_player_stats_change(l, c, PlayerStatsChange::ADD_TP, 255);
|
||||
}
|
||||
@@ -405,48 +363,48 @@ static void on_cast_technique_finished(shared_ptr<ServerState>,
|
||||
|
||||
static void on_attack_finished(shared_ptr<ServerState> s,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
||||
const string& data) {
|
||||
const auto& cmd = check_size_sc<G_AttackFinished_6x46>(data,
|
||||
offsetof(G_AttackFinished_6x46, entries), sizeof(G_AttackFinished_6x46));
|
||||
const void* data, size_t size) {
|
||||
const auto& cmd = check_size_t<G_AttackFinished_6x46>(data, size,
|
||||
offsetof(G_AttackFinished_6x46, targets), sizeof(G_AttackFinished_6x46));
|
||||
size_t allowed_count = min<size_t>(cmd.header.size - 2, 11);
|
||||
if (cmd.count > allowed_count) {
|
||||
throw runtime_error("invalid attack finished command");
|
||||
}
|
||||
on_forward_check_size_client(s, l, c, command, flag, data);
|
||||
on_forward_check_size_client(s, l, c, command, flag, data, size);
|
||||
}
|
||||
|
||||
static void on_cast_technique(shared_ptr<ServerState> s,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
||||
const string& data) {
|
||||
const auto& cmd = check_size_sc<G_CastTechnique_6x47>(data,
|
||||
const void* data, size_t size) {
|
||||
const auto& cmd = check_size_t<G_CastTechnique_6x47>(data, size,
|
||||
offsetof(G_CastTechnique_6x47, targets), sizeof(G_CastTechnique_6x47));
|
||||
size_t allowed_count = min<size_t>(cmd.header.size - 2, 10);
|
||||
if (cmd.target_count > allowed_count) {
|
||||
throw runtime_error("invalid cast technique command");
|
||||
}
|
||||
on_forward_check_size_client(s, l, c, command, flag, data);
|
||||
on_forward_check_size_client(s, l, c, command, flag, data, size);
|
||||
}
|
||||
|
||||
static void on_subtract_pb_energy(shared_ptr<ServerState> s,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
||||
const string& data) {
|
||||
const auto& cmd = check_size_sc<G_SubtractPBEnergy_6x49>(data,
|
||||
const void* data, size_t size) {
|
||||
const auto& cmd = check_size_t<G_SubtractPBEnergy_6x49>(data, size,
|
||||
offsetof(G_SubtractPBEnergy_6x49, entries), sizeof(G_SubtractPBEnergy_6x49));
|
||||
size_t allowed_count = min<size_t>(cmd.header.size - 3, 14);
|
||||
if (cmd.entry_count > allowed_count) {
|
||||
throw runtime_error("invalid subtract PB energy command");
|
||||
}
|
||||
on_forward_check_size_client(s, l, c, command, flag, data);
|
||||
on_forward_check_size_client(s, l, c, command, flag, data, size);
|
||||
}
|
||||
|
||||
static void on_switch_state_changed(shared_ptr<ServerState>,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
||||
const string& data) {
|
||||
auto& cmd = check_size_t<G_SwitchStateChanged_6x05>(data);
|
||||
const void* data, size_t size) {
|
||||
auto& cmd = check_size_t<G_SwitchStateChanged_6x05>(data, size);
|
||||
if (!l->is_game()) {
|
||||
return;
|
||||
}
|
||||
forward_subcommand(l, c, command, flag, data);
|
||||
forward_subcommand(l, c, command, flag, data, size);
|
||||
if (cmd.flags && cmd.header.object_id != 0xFFFF) {
|
||||
if ((l->flags & Lobby::Flag::CHEATS_ENABLED) && c->options.switch_assist &&
|
||||
(c->last_switch_enabled_command.header.subcommand == 0x05)) {
|
||||
@@ -467,9 +425,8 @@ static void on_switch_state_changed(shared_ptr<ServerState>,
|
||||
template <typename CmdT>
|
||||
void on_movement(shared_ptr<ServerState>,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
||||
const string& data) {
|
||||
const auto& cmd = check_size_sc<CmdT>(data);
|
||||
|
||||
const void* data, size_t size) {
|
||||
const auto& cmd = check_size_t<CmdT>(data, size);
|
||||
if (cmd.header.client_id != c->lobby_client_id) {
|
||||
return;
|
||||
}
|
||||
@@ -477,7 +434,23 @@ void on_movement(shared_ptr<ServerState>,
|
||||
c->x = cmd.x;
|
||||
c->z = cmd.z;
|
||||
|
||||
forward_subcommand(l, c, command, flag, data);
|
||||
forward_subcommand(l, c, command, flag, data, size);
|
||||
}
|
||||
|
||||
template <typename CmdT>
|
||||
void on_movement_with_area(shared_ptr<ServerState>,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
||||
const void* data, size_t size) {
|
||||
const auto& cmd = check_size_t<CmdT>(data, size);
|
||||
if (cmd.header.client_id != c->lobby_client_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
c->x = cmd.x;
|
||||
c->z = cmd.z;
|
||||
c->area = cmd.area;
|
||||
|
||||
forward_subcommand(l, c, command, flag, data, size);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -485,8 +458,8 @@ void on_movement(shared_ptr<ServerState>,
|
||||
|
||||
static void on_player_drop_item(shared_ptr<ServerState>,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
||||
const string& data) {
|
||||
const auto& cmd = check_size_sc<G_DropItem_6x2A>(data);
|
||||
const void* data, size_t size) {
|
||||
const auto& cmd = check_size_t<G_DropItem_6x2A>(data, size);
|
||||
|
||||
if ((cmd.header.client_id != c->lobby_client_id)) {
|
||||
return;
|
||||
@@ -508,14 +481,14 @@ static void on_player_drop_item(shared_ptr<ServerState>,
|
||||
c->game_data.player()->print_inventory(stderr);
|
||||
}
|
||||
|
||||
forward_subcommand(l, c, command, flag, data);
|
||||
forward_subcommand(l, c, command, flag, data, size);
|
||||
}
|
||||
|
||||
static void on_create_inventory_item(shared_ptr<ServerState>,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
||||
const string& data) {
|
||||
const auto& cmd = check_size_sc<G_CreateInventoryItem_DC_6x2B>(data,
|
||||
sizeof(G_CreateInventoryItem_DC_6x2B), sizeof(G_CreateInventoryItem_PC_V3_BB_6x2B));
|
||||
const void* data, size_t size) {
|
||||
const auto& cmd = check_size_t<G_CreateInventoryItem_DC_6x2B>(
|
||||
data, size, sizeof(G_CreateInventoryItem_PC_V3_BB_6x2B));
|
||||
|
||||
if ((cmd.header.client_id != c->lobby_client_id)) {
|
||||
return;
|
||||
@@ -544,14 +517,14 @@ static void on_create_inventory_item(shared_ptr<ServerState>,
|
||||
c->game_data.player()->print_inventory(stderr);
|
||||
}
|
||||
|
||||
forward_subcommand(l, c, command, flag, data);
|
||||
forward_subcommand(l, c, command, flag, data, size);
|
||||
}
|
||||
|
||||
static void on_drop_partial_stack(shared_ptr<ServerState>,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
||||
const string& data) {
|
||||
const auto& cmd = check_size_sc<G_DropStackedItem_DC_6x5D>(data,
|
||||
sizeof(G_DropStackedItem_DC_6x5D), sizeof(G_DropStackedItem_PC_V3_BB_6x5D));
|
||||
const void* data, size_t size) {
|
||||
const auto& cmd = check_size_t<G_DropStackedItem_DC_6x5D>(
|
||||
data, size, sizeof(G_DropStackedItem_PC_V3_BB_6x5D));
|
||||
|
||||
// TODO: Should we check the client ID here too?
|
||||
if (!l->is_game()) {
|
||||
@@ -582,14 +555,14 @@ static void on_drop_partial_stack(shared_ptr<ServerState>,
|
||||
c->game_data.player()->print_inventory(stderr);
|
||||
}
|
||||
|
||||
forward_subcommand(l, c, command, flag, data);
|
||||
forward_subcommand(l, c, command, flag, data, size);
|
||||
}
|
||||
|
||||
static void on_drop_partial_stack_bb(shared_ptr<ServerState>,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
||||
const string& data) {
|
||||
const void* data, size_t size) {
|
||||
if (l->version == GameVersion::BB) {
|
||||
const auto& cmd = check_size_sc<G_SplitStackedItem_6xC3>(data);
|
||||
const auto& cmd = check_size_t<G_SplitStackedItem_BB_6xC3>(data, size);
|
||||
|
||||
if (!l->is_game() || (cmd.header.client_id != c->lobby_client_id)) {
|
||||
return;
|
||||
@@ -629,14 +602,14 @@ static void on_drop_partial_stack_bb(shared_ptr<ServerState>,
|
||||
send_drop_stacked_item(l, item.data, cmd.area, cmd.x, cmd.z);
|
||||
|
||||
} else {
|
||||
forward_subcommand(l, c, command, flag, data);
|
||||
forward_subcommand(l, c, command, flag, data, size);
|
||||
}
|
||||
}
|
||||
|
||||
static void on_buy_shop_item(shared_ptr<ServerState>,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
||||
const string& data) {
|
||||
const auto& cmd = check_size_sc<G_BuyShopItem_6x5E>(data);
|
||||
const void* data, size_t size) {
|
||||
const auto& cmd = check_size_t<G_BuyShopItem_6x5E>(data, size);
|
||||
|
||||
if (!l->is_game() || (cmd.header.client_id != c->lobby_client_id)) {
|
||||
return;
|
||||
@@ -663,14 +636,14 @@ static void on_buy_shop_item(shared_ptr<ServerState>,
|
||||
c->game_data.player()->print_inventory(stderr);
|
||||
}
|
||||
|
||||
forward_subcommand(l, c, command, flag, data);
|
||||
forward_subcommand(l, c, command, flag, data, size);
|
||||
}
|
||||
|
||||
static void on_box_or_enemy_item_drop(shared_ptr<ServerState>,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
||||
const string& data) {
|
||||
const auto& cmd = check_size_sc<G_DropItem_DC_6x5F>(data,
|
||||
sizeof(G_DropItem_DC_6x5F), sizeof(G_DropItem_PC_V3_BB_6x5F));
|
||||
const void* data, size_t size) {
|
||||
const auto& cmd = check_size_t<G_DropItem_DC_6x5F>(
|
||||
data, size, sizeof(G_DropItem_PC_V3_BB_6x5F));
|
||||
|
||||
if (!l->is_game() || (c->lobby_client_id != l->leader_id)) {
|
||||
return;
|
||||
@@ -696,13 +669,13 @@ static void on_box_or_enemy_item_drop(shared_ptr<ServerState>,
|
||||
}
|
||||
}
|
||||
|
||||
forward_subcommand(l, c, command, flag, data);
|
||||
forward_subcommand(l, c, command, flag, data, size);
|
||||
}
|
||||
|
||||
static void on_pick_up_item(shared_ptr<ServerState>,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
||||
const string& data) {
|
||||
auto& cmd = check_size_sc<G_PickUpItem_6x59>(data);
|
||||
const void* data, size_t size) {
|
||||
auto& cmd = check_size_t<G_PickUpItem_6x59>(data, size);
|
||||
|
||||
if (!l->is_game()) {
|
||||
return;
|
||||
@@ -732,15 +705,15 @@ static void on_pick_up_item(shared_ptr<ServerState>,
|
||||
effective_c->game_data.player()->print_inventory(stderr);
|
||||
}
|
||||
|
||||
forward_subcommand(l, c, command, flag, data);
|
||||
forward_subcommand(l, c, command, flag, data, size);
|
||||
}
|
||||
|
||||
static void on_pick_up_item_request(shared_ptr<ServerState>,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
||||
const string& data) {
|
||||
const void* data, size_t size) {
|
||||
// This is handled by the server on BB, and by the leader on other versions
|
||||
if (l->version == GameVersion::BB) {
|
||||
auto& cmd = check_size_sc<G_PickUpItemRequest_6x5A>(data);
|
||||
auto& cmd = check_size_t<G_PickUpItemRequest_6x5A>(data, size);
|
||||
|
||||
if (!l->is_game() || (cmd.header.client_id != c->lobby_client_id)) {
|
||||
return;
|
||||
@@ -766,14 +739,14 @@ static void on_pick_up_item_request(shared_ptr<ServerState>,
|
||||
send_pick_up_item(l, c, cmd.item_id, cmd.area);
|
||||
|
||||
} else {
|
||||
forward_subcommand(l, c, command, flag, data);
|
||||
forward_subcommand(l, c, command, flag, data, size);
|
||||
}
|
||||
}
|
||||
|
||||
static void on_equip_unequip_item(shared_ptr<ServerState>,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
||||
const string& data) {
|
||||
const auto& cmd = check_size_sc<G_EquipOrUnequipItem_6x25_6x26>(data);
|
||||
const void* data, size_t size) {
|
||||
const auto& cmd = check_size_t<G_EquipOrUnequipItem_6x25_6x26>(data, size);
|
||||
|
||||
if (cmd.header.client_id != c->lobby_client_id) {
|
||||
return;
|
||||
@@ -792,7 +765,7 @@ static void on_equip_unequip_item(shared_ptr<ServerState>,
|
||||
|
||||
// TODO: Should we forward this command on BB? The old version of newserv
|
||||
// didn't, but that seems wrong.
|
||||
forward_subcommand(l, c, command, flag, data);
|
||||
forward_subcommand(l, c, command, flag, data, size);
|
||||
}
|
||||
|
||||
static void on_use_item(
|
||||
@@ -801,8 +774,8 @@ static void on_use_item(
|
||||
shared_ptr<Client> c,
|
||||
uint8_t command,
|
||||
uint8_t flag,
|
||||
const string& data) {
|
||||
const auto& cmd = check_size_sc<G_UseItem_6x27>(data);
|
||||
const void* data, size_t size) {
|
||||
const auto& cmd = check_size_t<G_UseItem_6x27>(data, size);
|
||||
|
||||
if (cmd.header.client_id != c->lobby_client_id) {
|
||||
return;
|
||||
@@ -829,7 +802,7 @@ static void on_use_item(
|
||||
c->game_data.player()->print_inventory(stderr);
|
||||
}
|
||||
|
||||
forward_subcommand(l, c, command, flag, data);
|
||||
forward_subcommand(l, c, command, flag, data, size);
|
||||
}
|
||||
|
||||
static void on_feed_mag(
|
||||
@@ -838,8 +811,8 @@ static void on_feed_mag(
|
||||
shared_ptr<Client> c,
|
||||
uint8_t command,
|
||||
uint8_t flag,
|
||||
const string& data) {
|
||||
const auto& cmd = check_size_sc<G_FeedMAG_6x28>(data);
|
||||
const void* data, size_t size) {
|
||||
const auto& cmd = check_size_t<G_FeedMAG_6x28>(data, size);
|
||||
|
||||
if (cmd.header.client_id != c->lobby_client_id) {
|
||||
return;
|
||||
@@ -880,20 +853,20 @@ static void on_feed_mag(
|
||||
c->game_data.player()->print_inventory(stderr);
|
||||
}
|
||||
|
||||
forward_subcommand(l, c, command, flag, data);
|
||||
forward_subcommand(l, c, command, flag, data, size);
|
||||
}
|
||||
|
||||
static void on_open_shop_bb_or_ep3_battle_subs(shared_ptr<ServerState> s,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
||||
const string& data) {
|
||||
const void* data, size_t size) {
|
||||
if (l->is_ep3()) {
|
||||
on_ep3_battle_subs(s, l, c, command, flag, data);
|
||||
on_ep3_battle_subs(s, l, c, command, flag, data, size);
|
||||
|
||||
} else if (!l->item_creator.get()) {
|
||||
throw runtime_error("received shop subcommand without item creator present");
|
||||
|
||||
} else {
|
||||
const auto& cmd = check_size_sc<G_ShopContentsRequest_BB_6xB5>(data, 0x08);
|
||||
const auto& cmd = check_size_t<G_ShopContentsRequest_BB_6xB5>(data, size);
|
||||
if ((l->version == GameVersion::BB) && l->is_game()) {
|
||||
if (!l->item_creator) {
|
||||
throw logic_error("item creator missing from BB game");
|
||||
@@ -924,18 +897,18 @@ static void on_open_shop_bb_or_ep3_battle_subs(shared_ptr<ServerState> s,
|
||||
}
|
||||
|
||||
static void on_open_bank_bb_or_card_trade_counter_ep3(shared_ptr<ServerState>,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag, const string& data) {
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag, const void* data, size_t size) {
|
||||
if ((l->version == GameVersion::BB) && l->is_game()) {
|
||||
send_bank(c);
|
||||
} else if ((l->version == GameVersion::GC) && l->is_ep3()) {
|
||||
forward_subcommand(l, c, command, flag, data);
|
||||
forward_subcommand(l, c, command, flag, data, size);
|
||||
}
|
||||
}
|
||||
|
||||
static void on_bank_action_bb(shared_ptr<ServerState>,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t, uint8_t, const string& data) {
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t, uint8_t, const void* data, size_t size) {
|
||||
if (l->version == GameVersion::BB) {
|
||||
const auto& cmd = check_size_sc<G_BankAction_BB_6xBD>(data);
|
||||
const auto& cmd = check_size_t<G_BankAction_BB_6xBD>(data, size);
|
||||
|
||||
if (!l->is_game()) {
|
||||
return;
|
||||
@@ -984,9 +957,9 @@ static void on_bank_action_bb(shared_ptr<ServerState>,
|
||||
|
||||
static void on_sort_inventory_bb(shared_ptr<ServerState>,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t, uint8_t,
|
||||
const string& data) {
|
||||
const void* data, size_t size) {
|
||||
if (l->version == GameVersion::BB) {
|
||||
const auto& cmd = check_size_sc<G_SortInventory_6xC4>(data);
|
||||
const auto& cmd = check_size_t<G_SortInventory_BB_6xC4>(data, size);
|
||||
|
||||
if (!(l->flags & Lobby::Flag::ITEM_TRACKING_ENABLED)) {
|
||||
throw logic_error("item tracking not enabled in BB game");
|
||||
@@ -1016,7 +989,7 @@ static void on_sort_inventory_bb(shared_ptr<ServerState>,
|
||||
|
||||
static void on_entity_drop_item_request(
|
||||
shared_ptr<ServerState>, shared_ptr<Lobby> l, shared_ptr<Client> c,
|
||||
uint8_t command, uint8_t flag, const string& data) {
|
||||
uint8_t command, uint8_t flag, const void* data, size_t size) {
|
||||
if (!l->is_game()) {
|
||||
return;
|
||||
}
|
||||
@@ -1025,17 +998,17 @@ static void on_entity_drop_item_request(
|
||||
// enabled, or just ignore it) instead of generating the item drop command
|
||||
if (l->version != GameVersion::BB) {
|
||||
if (l->flags & Lobby::Flag::DROPS_ENABLED) {
|
||||
forward_subcommand(l, c, command, flag, data);
|
||||
forward_subcommand(l, c, command, flag, data, size);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
G_SpecializableItemDropRequest_6xA2 cmd;
|
||||
if (data.size() == sizeof(G_SpecializableItemDropRequest_6xA2)) {
|
||||
cmd = check_size_sc<G_SpecializableItemDropRequest_6xA2>(data);
|
||||
if (size == sizeof(G_SpecializableItemDropRequest_6xA2)) {
|
||||
cmd = check_size_t<G_SpecializableItemDropRequest_6xA2>(data, size);
|
||||
} else {
|
||||
const auto& in_cmd = check_size_sc<G_StandardDropItemRequest_DC_6x60>(
|
||||
data, sizeof(G_StandardDropItemRequest_DC_6x60), 0xFFFF);
|
||||
const auto& in_cmd = check_size_t<G_StandardDropItemRequest_DC_6x60>(
|
||||
data, size, 0xFFFF);
|
||||
cmd.entity_id = in_cmd.entity_id;
|
||||
cmd.area = in_cmd.area;
|
||||
cmd.rt_index = in_cmd.rt_index;
|
||||
@@ -1074,19 +1047,19 @@ static void on_entity_drop_item_request(
|
||||
|
||||
static void on_set_quest_flag(shared_ptr<ServerState>,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
||||
const string& data) {
|
||||
const void* data, size_t size) {
|
||||
if (!l->is_game()) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t flag_index, difficulty, action;
|
||||
if (c->version() == GameVersion::DC || c->version() == GameVersion::PC) {
|
||||
const auto& cmd = check_size_sc<G_SetQuestFlag_DC_PC_6x75>(data);
|
||||
const auto& cmd = check_size_t<G_SetQuestFlag_DC_PC_6x75>(data, size);
|
||||
flag_index = cmd.flag;
|
||||
action = cmd.action;
|
||||
difficulty = l->difficulty;
|
||||
} else {
|
||||
const auto& cmd = check_size_sc<G_SetQuestFlag_V3_BB_6x75>(data);
|
||||
const auto& cmd = check_size_t<G_SetQuestFlag_V3_BB_6x75>(data, size);
|
||||
flag_index = cmd.basic_cmd.flag;
|
||||
action = cmd.basic_cmd.action;
|
||||
difficulty = cmd.difficulty;
|
||||
@@ -1097,7 +1070,7 @@ static void on_set_quest_flag(shared_ptr<ServerState>,
|
||||
}
|
||||
// The client explicitly checks for both 0 and 1 - any other value means no
|
||||
// operation is performed.
|
||||
size_t bit_index = (l->difficulty << 10) + flag_index;
|
||||
size_t bit_index = (difficulty << 10) + flag_index;
|
||||
size_t byte_index = bit_index >> 3;
|
||||
uint8_t mask = 0x80 >> (bit_index & 7);
|
||||
if (action == 0) {
|
||||
@@ -1106,7 +1079,7 @@ static void on_set_quest_flag(shared_ptr<ServerState>,
|
||||
c->game_data.player()->quest_data1[byte_index] &= (~mask);
|
||||
}
|
||||
|
||||
forward_subcommand(l, c, command, flag, data);
|
||||
forward_subcommand(l, c, command, flag, data, size);
|
||||
|
||||
if (c->version() == GameVersion::GC) {
|
||||
bool should_send_boss_drop_req = false;
|
||||
@@ -1115,8 +1088,8 @@ static void on_set_quest_flag(shared_ptr<ServerState>,
|
||||
// On Normal, Dark Falz does not have a third phase, so send the drop
|
||||
// request after the end of the second phase. On all other difficulty
|
||||
// levels, send it after the third phase.
|
||||
if (((l->difficulty == 0) && (flag_index == 0x0035)) ||
|
||||
((l->difficulty != 0) && (flag_index == 0x0037))) {
|
||||
if (((difficulty == 0) && (flag_index == 0x0035)) ||
|
||||
((difficulty != 0) && (flag_index == 0x0037))) {
|
||||
should_send_boss_drop_req = true;
|
||||
}
|
||||
} else if (is_ep2 && (flag_index == 0x0057) && (c->area == 0x0D)) {
|
||||
@@ -1253,8 +1226,8 @@ static void on_enemy_killed(shared_ptr<ServerState> s,
|
||||
|
||||
static void on_destroy_inventory_item(shared_ptr<ServerState>,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
||||
const string& data) {
|
||||
const auto& cmd = check_size_sc<G_DeleteInventoryItem_6x29>(data);
|
||||
const void* data, size_t size) {
|
||||
const auto& cmd = check_size_t<G_DeleteInventoryItem_6x29>(data, size);
|
||||
if (!l->is_game()) {
|
||||
return;
|
||||
}
|
||||
@@ -1273,14 +1246,14 @@ static void on_destroy_inventory_item(shared_ptr<ServerState>,
|
||||
cmd.item_id.load(), name.c_str());
|
||||
}
|
||||
c->game_data.player()->print_inventory(stderr);
|
||||
forward_subcommand(l, c, command, flag, data);
|
||||
forward_subcommand(l, c, command, flag, data, size);
|
||||
}
|
||||
}
|
||||
|
||||
static void on_destroy_ground_item(shared_ptr<ServerState>,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
||||
const string& data) {
|
||||
const auto& cmd = check_size_sc<G_DestroyGroundItem_6x63>(data);
|
||||
const void* data, size_t size) {
|
||||
const auto& cmd = check_size_t<G_DestroyGroundItem_6x63>(data, size);
|
||||
if (!l->is_game()) {
|
||||
return;
|
||||
}
|
||||
@@ -1294,15 +1267,15 @@ static void on_destroy_ground_item(shared_ptr<ServerState>,
|
||||
send_text_message_printf(c, "$C5DESTROY/GND %08" PRIX32 "\n%s",
|
||||
cmd.item_id.load(), name.c_str());
|
||||
}
|
||||
forward_subcommand(l, c, command, flag, data);
|
||||
forward_subcommand(l, c, command, flag, data, size);
|
||||
}
|
||||
}
|
||||
|
||||
static void on_identify_item_bb(shared_ptr<ServerState>,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
||||
const string& data) {
|
||||
const void* data, size_t size) {
|
||||
if (l->version == GameVersion::BB) {
|
||||
const auto& cmd = check_size_sc<G_AcceptItemIdentification_BB_6xB8>(data);
|
||||
const auto& cmd = check_size_t<G_AcceptItemIdentification_BB_6xB8>(data, size);
|
||||
if (!l->is_game()) {
|
||||
return;
|
||||
}
|
||||
@@ -1328,16 +1301,16 @@ static void on_identify_item_bb(shared_ptr<ServerState>,
|
||||
send_command_t(l, 0x60, 0x00, res);
|
||||
|
||||
} else {
|
||||
forward_subcommand(l, c, command, flag, data);
|
||||
forward_subcommand(l, c, command, flag, data, size);
|
||||
}
|
||||
}
|
||||
|
||||
static void on_accept_identify_item_bb(shared_ptr<ServerState>,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
||||
const string& data) {
|
||||
const void* data, size_t size) {
|
||||
|
||||
if (l->version == GameVersion::BB) {
|
||||
const auto& cmd = check_size_sc<G_AcceptItemIdentification_BB_6xBA>(data);
|
||||
const auto& cmd = check_size_t<G_AcceptItemIdentification_BB_6xBA>(data, size);
|
||||
|
||||
if (!(l->flags & Lobby::Flag::ITEM_TRACKING_ENABLED)) {
|
||||
throw logic_error("item tracking not enabled in BB game");
|
||||
@@ -1354,15 +1327,15 @@ static void on_accept_identify_item_bb(shared_ptr<ServerState>,
|
||||
c->game_data.identify_result.clear();
|
||||
|
||||
} else {
|
||||
forward_subcommand(l, c, command, flag, data);
|
||||
forward_subcommand(l, c, command, flag, data, size);
|
||||
}
|
||||
}
|
||||
|
||||
static void on_sell_item_at_shop_bb(shared_ptr<ServerState> s,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag, const string& data) {
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag, const void* data, size_t size) {
|
||||
|
||||
if (l->version == GameVersion::BB) {
|
||||
const auto& cmd = check_size_sc<G_SellItemAtShop_BB_6xC0>(data);
|
||||
const auto& cmd = check_size_t<G_SellItemAtShop_BB_6xC0>(data, size);
|
||||
|
||||
if (!(l->flags & Lobby::Flag::ITEM_TRACKING_ENABLED)) {
|
||||
throw logic_error("item tracking not enabled in BB game");
|
||||
@@ -1384,14 +1357,14 @@ static void on_sell_item_at_shop_bb(shared_ptr<ServerState> s,
|
||||
cmd.item_id.load(), price, name.c_str());
|
||||
}
|
||||
|
||||
forward_subcommand(l, c, command, flag, data);
|
||||
forward_subcommand(l, c, command, flag, data, size);
|
||||
}
|
||||
}
|
||||
|
||||
static void on_buy_shop_item_bb(shared_ptr<ServerState>,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t, uint8_t, const string& data) {
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t, uint8_t, const void* data, size_t size) {
|
||||
if (l->version == GameVersion::BB) {
|
||||
const auto& cmd = check_size_sc<G_BuyShopItem_BB_6xB7>(data);
|
||||
const auto& cmd = check_size_t<G_BuyShopItem_BB_6xB7>(data, size);
|
||||
if (!(l->flags & Lobby::Flag::ITEM_TRACKING_ENABLED)) {
|
||||
throw logic_error("item tracking not enabled in BB game");
|
||||
}
|
||||
@@ -1428,7 +1401,7 @@ static void on_buy_shop_item_bb(shared_ptr<ServerState>,
|
||||
}
|
||||
|
||||
static void on_medical_center_bb(shared_ptr<ServerState>,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t, uint8_t, const string&) {
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t, uint8_t, const void*, size_t) {
|
||||
|
||||
if (l->version == GameVersion::BB) {
|
||||
if (c->game_data.player()->disp.meseta < 10) {
|
||||
@@ -1445,7 +1418,7 @@ static void on_medical_center_bb(shared_ptr<ServerState>,
|
||||
// for more information on flags. The maximum size is not enforced if it's zero.
|
||||
typedef void (*subcommand_handler_t)(shared_ptr<ServerState> s,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
||||
const string& data);
|
||||
const void* data, size_t size);
|
||||
|
||||
subcommand_handler_t subcommand_handlers[0x100] = {
|
||||
/* 6x00 */ on_invalid,
|
||||
|
||||
+28
-44
@@ -107,16 +107,14 @@ void ReplaySession::check_for_password(shared_ptr<const Event> ev) const {
|
||||
|
||||
switch (version) {
|
||||
case GameVersion::PATCH: {
|
||||
const auto& header = check_size_t<PSOCommandHeaderPC>(
|
||||
ev->data, sizeof(PSOCommandHeaderPC), 0xFFFF);
|
||||
const auto& header = check_size_t<PSOCommandHeaderPC>(ev->data, 0xFFFF);
|
||||
if (header.command == 0x04) {
|
||||
check_either(check_size_t<C_Login_Patch_04>(cmd_data, cmd_size).password);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GameVersion::PC: {
|
||||
const auto& header = check_size_t<PSOCommandHeaderPC>(
|
||||
ev->data, sizeof(PSOCommandHeaderPC), 0xFFFF);
|
||||
const auto& header = check_size_t<PSOCommandHeaderPC>(ev->data, 0xFFFF);
|
||||
if (header.command == 0x03) {
|
||||
check_ak(check_size_t<C_LegacyLogin_PC_V3_03>(cmd_data, cmd_size).access_key2);
|
||||
} else if (header.command == 0x04) {
|
||||
@@ -131,8 +129,8 @@ void ReplaySession::check_for_password(shared_ptr<const Event> ev) const {
|
||||
check_ak(cmd.access_key);
|
||||
check_pw(cmd.password);
|
||||
} else if (header.command == 0x9D) {
|
||||
const auto& cmd = check_size_t<C_Login_DC_PC_GC_9D>(cmd_data, cmd_size,
|
||||
sizeof(C_Login_DC_PC_GC_9D), sizeof(C_LoginExtended_PC_9D));
|
||||
const auto& cmd = check_size_t<C_Login_DC_PC_GC_9D>(
|
||||
cmd_data, cmd_size, sizeof(C_LoginExtended_PC_9D));
|
||||
check_ak(cmd.v1_access_key);
|
||||
check_ak(cmd.access_key);
|
||||
check_ak(cmd.access_key2);
|
||||
@@ -142,17 +140,16 @@ void ReplaySession::check_for_password(shared_ptr<const Event> ev) const {
|
||||
case GameVersion::DC:
|
||||
case GameVersion::GC:
|
||||
case GameVersion::XB: {
|
||||
const auto& header = check_size_t<PSOCommandHeaderDCV3>(
|
||||
ev->data, sizeof(PSOCommandHeaderDCV3), 0xFFFF);
|
||||
const auto& header = check_size_t<PSOCommandHeaderDCV3>(ev->data, 0xFFFF);
|
||||
if (header.command == 0x03) {
|
||||
check_ak(check_size_t<C_LegacyLogin_PC_V3_03>(cmd_data, cmd_size).access_key2);
|
||||
} else if (header.command == 0x04) {
|
||||
check_ak(check_size_t<C_LegacyLogin_PC_V3_04>(cmd_data, cmd_size).access_key);
|
||||
} else if (header.command == 0x90) {
|
||||
check_ak(check_size_t<C_LoginV1_DC_PC_V3_90>(cmd_data, cmd_size, sizeof(C_LoginV1_DC_PC_V3_90), 0xFFFF).access_key);
|
||||
check_ak(check_size_t<C_LoginV1_DC_PC_V3_90>(cmd_data, cmd_size, 0xFFFF).access_key);
|
||||
} else if (header.command == 0x93) {
|
||||
const auto& cmd = check_size_t<C_LoginV1_DC_93>(cmd_data, cmd_size,
|
||||
sizeof(C_LoginV1_DC_93), sizeof(C_LoginExtendedV1_DC_93));
|
||||
const auto& cmd = check_size_t<C_LoginV1_DC_93>(
|
||||
cmd_data, cmd_size, sizeof(C_LoginExtendedV1_DC_93));
|
||||
check_ak(cmd.access_key);
|
||||
} else if (header.command == 0x9A) {
|
||||
const auto& cmd = check_size_t<C_Login_DC_PC_V3_9A>(cmd_data, cmd_size);
|
||||
@@ -164,20 +161,20 @@ void ReplaySession::check_for_password(shared_ptr<const Event> ev) const {
|
||||
check_ak(cmd.access_key);
|
||||
check_pw(cmd.password);
|
||||
} else if (header.command == 0x9D) {
|
||||
const auto& cmd = check_size_t<C_Login_DC_PC_GC_9D>(cmd_data, cmd_size,
|
||||
sizeof(C_Login_DC_PC_GC_9D), sizeof(C_LoginExtended_DC_GC_9D));
|
||||
const auto& cmd = check_size_t<C_Login_DC_PC_GC_9D>(
|
||||
cmd_data, cmd_size, sizeof(C_LoginExtended_DC_GC_9D));
|
||||
check_ak(cmd.v1_access_key);
|
||||
check_ak(cmd.access_key);
|
||||
check_ak(cmd.access_key2);
|
||||
} else if (header.command == 0x9E) {
|
||||
if (version == GameVersion::GC) {
|
||||
const auto& cmd = check_size_t<C_Login_GC_9E>(cmd_data, cmd_size,
|
||||
sizeof(C_Login_GC_9E), sizeof(C_LoginExtended_GC_9E));
|
||||
const auto& cmd = check_size_t<C_Login_GC_9E>(
|
||||
cmd_data, cmd_size, sizeof(C_LoginExtended_GC_9E));
|
||||
check_ak(cmd.access_key);
|
||||
check_ak(cmd.access_key2);
|
||||
} else { // XB
|
||||
const auto& cmd = check_size_t<C_Login_XB_9E>(cmd_data, cmd_size,
|
||||
sizeof(C_Login_XB_9E), sizeof(C_LoginExtended_XB_9E));
|
||||
const auto& cmd = check_size_t<C_Login_XB_9E>(
|
||||
cmd_data, cmd_size, sizeof(C_LoginExtended_XB_9E));
|
||||
check_ak(cmd.access_key);
|
||||
check_ak(cmd.access_key2);
|
||||
}
|
||||
@@ -190,8 +187,7 @@ void ReplaySession::check_for_password(shared_ptr<const Event> ev) const {
|
||||
break;
|
||||
}
|
||||
case GameVersion::BB: {
|
||||
const auto& header = check_size_t<PSOCommandHeaderBB>(
|
||||
ev->data, sizeof(PSOCommandHeaderBB), 0xFFFF);
|
||||
const auto& header = check_size_t<PSOCommandHeaderBB>(ev->data, 0xFFFF);
|
||||
if (header.command == 0x04) {
|
||||
check_pw(check_size_t<C_LegacyLogin_BB_04>(cmd_data, cmd_size).password);
|
||||
} else if (header.command == 0x93) {
|
||||
@@ -220,8 +216,7 @@ void ReplaySession::apply_default_mask(shared_ptr<Event> ev) {
|
||||
|
||||
switch (version) {
|
||||
case GameVersion::PATCH: {
|
||||
const auto& header = check_size_t<PSOCommandHeaderPC>(
|
||||
ev->data, sizeof(PSOCommandHeaderPC), 0xFFFF);
|
||||
const auto& header = check_size_t<PSOCommandHeaderPC>(ev->data, 0xFFFF);
|
||||
if (header.command == 0x02) {
|
||||
auto& cmd_mask = check_size_t<S_ServerInit_Patch_02>(mask_data, mask_size);
|
||||
cmd_mask.server_key = 0;
|
||||
@@ -235,13 +230,9 @@ void ReplaySession::apply_default_mask(shared_ptr<Event> ev) {
|
||||
case GameVersion::XB: {
|
||||
uint8_t command;
|
||||
if (version == GameVersion::PC) {
|
||||
command = check_size_t<PSOCommandHeaderPC>(
|
||||
ev->data, sizeof(PSOCommandHeaderPC), 0xFFFF)
|
||||
.command;
|
||||
command = check_size_t<PSOCommandHeaderPC>(ev->data, 0xFFFF).command;
|
||||
} else { // V3
|
||||
command = check_size_t<PSOCommandHeaderDCV3>(
|
||||
ev->data, sizeof(PSOCommandHeaderDCV3), 0xFFFF)
|
||||
.command;
|
||||
command = check_size_t<PSOCommandHeaderDCV3>(ev->data, 0xFFFF).command;
|
||||
}
|
||||
switch (command) {
|
||||
case 0x02:
|
||||
@@ -249,7 +240,7 @@ void ReplaySession::apply_default_mask(shared_ptr<Event> ev) {
|
||||
case 0x91:
|
||||
case 0x9B: {
|
||||
auto& mask = check_size_t<S_ServerInitDefault_DC_PC_V3_02_17_91_9B>(
|
||||
mask_data, mask_size, sizeof(S_ServerInitDefault_DC_PC_V3_02_17_91_9B), 0xFFFF);
|
||||
mask_data, mask_size, 0xFFFF);
|
||||
mask.server_key = 0;
|
||||
mask.client_key = 0;
|
||||
break;
|
||||
@@ -284,8 +275,8 @@ void ReplaySession::apply_default_mask(shared_ptr<Event> ev) {
|
||||
mask.variations.clear(0);
|
||||
mask.rare_seed = 0;
|
||||
} else { // V3
|
||||
auto& mask = check_size_t<S_JoinGame_DC_GC_64>(mask_data, mask_size,
|
||||
sizeof(S_JoinGame_DC_GC_64), sizeof(S_JoinGame_GC_Ep3_64));
|
||||
auto& mask = check_size_t<S_JoinGame_DC_GC_64>(
|
||||
mask_data, mask_size, sizeof(S_JoinGame_GC_Ep3_64));
|
||||
mask.variations.clear(0);
|
||||
mask.rare_seed = 0;
|
||||
}
|
||||
@@ -309,13 +300,11 @@ void ReplaySession::apply_default_mask(shared_ptr<Event> ev) {
|
||||
}
|
||||
case 0x6C: {
|
||||
if (version == GameVersion::GC && mask_size >= 0x14) {
|
||||
const auto& cmd = check_size_t<G_MapList_GC_Ep3_6xB6x40>(
|
||||
cmd_data, cmd_size, sizeof(G_MapList_GC_Ep3_6xB6x40), 0xFFFF);
|
||||
const auto& cmd = check_size_t<G_MapList_GC_Ep3_6xB6x40>(cmd_data, cmd_size, 0xFFFF);
|
||||
if ((cmd.header.header.basic_header.subcommand == 0xB6) &&
|
||||
(cmd.header.subsubcommand == 0x40)) {
|
||||
check_size_t<PSOCommandHeaderDCV3>(ev->mask, sizeof(PSOCommandHeaderDCV3), 0xFFFF).size = 0;
|
||||
auto& mask = check_size_t<G_MapList_GC_Ep3_6xB6x40>(
|
||||
mask_data, mask_size, sizeof(G_MapList_GC_Ep3_6xB6x40), 0xFFFF);
|
||||
check_size_t<PSOCommandHeaderDCV3>(ev->mask, 0xFFFF).size = 0;
|
||||
auto& mask = check_size_t<G_MapList_GC_Ep3_6xB6x40>(mask_data, mask_size, 0xFFFF);
|
||||
mask.header.header.size = 0;
|
||||
mask.compressed_data_size = 0;
|
||||
ev->allow_size_disparity = true;
|
||||
@@ -330,13 +319,10 @@ void ReplaySession::apply_default_mask(shared_ptr<Event> ev) {
|
||||
break;
|
||||
}
|
||||
case GameVersion::BB: {
|
||||
uint16_t command = check_size_t<PSOCommandHeaderBB>(
|
||||
ev->data, sizeof(PSOCommandHeaderBB), 0xFFFF)
|
||||
.command;
|
||||
uint16_t command = check_size_t<PSOCommandHeaderBB>(ev->data, 0xFFFF).command;
|
||||
switch (command) {
|
||||
case 0x0003: {
|
||||
auto& mask = check_size_t<S_ServerInitDefault_BB_03_9B>(
|
||||
mask_data, mask_size, sizeof(S_ServerInitDefault_BB_03_9B), 0xFFFF);
|
||||
auto& mask = check_size_t<S_ServerInitDefault_BB_03_9B>(mask_data, mask_size, 0xFFFF);
|
||||
mask.server_key.clear(0);
|
||||
mask.client_key.clear(0);
|
||||
break;
|
||||
@@ -675,8 +661,7 @@ void ReplaySession::on_command_received(
|
||||
case GameVersion::GC:
|
||||
case GameVersion::XB:
|
||||
if (command == 0x02 || command == 0x17 || command == 0x91 || command == 0x9B) {
|
||||
auto& cmd = check_size_t<S_ServerInitDefault_DC_PC_V3_02_17_91_9B>(data,
|
||||
sizeof(S_ServerInitDefault_DC_PC_V3_02_17_91_9B), 0xFFFF);
|
||||
auto& cmd = check_size_t<S_ServerInitDefault_DC_PC_V3_02_17_91_9B>(data, 0xFFFF);
|
||||
if ((c->version == GameVersion::DC) || (c->version == GameVersion::PC)) {
|
||||
c->channel.crypt_in.reset(new PSOV2Encryption(cmd.server_key));
|
||||
c->channel.crypt_out.reset(new PSOV2Encryption(cmd.client_key));
|
||||
@@ -688,8 +673,7 @@ void ReplaySession::on_command_received(
|
||||
break;
|
||||
case GameVersion::BB:
|
||||
if (command == 0x03 || command == 0x9B) {
|
||||
auto& cmd = check_size_t<S_ServerInitDefault_BB_03_9B>(data,
|
||||
sizeof(S_ServerInitDefault_BB_03_9B), 0xFFFF);
|
||||
auto& cmd = check_size_t<S_ServerInitDefault_BB_03_9B>(data, 0xFFFF);
|
||||
// TODO: At some point it may matter which BB private key file we use.
|
||||
// Don't just blindly use the first one here.
|
||||
c->channel.crypt_in.reset(new PSOBBEncryption(
|
||||
|
||||
Reference in New Issue
Block a user