get client language from login command instead of player data

This commit is contained in:
Martin Michelsen
2023-10-22 08:55:09 -07:00
parent ba7a3fc4c6
commit d2d96d9c0a
5 changed files with 29 additions and 25 deletions
+1
View File
@@ -61,6 +61,7 @@ Client::Client(
should_send_to_proxy_server(false), should_send_to_proxy_server(false),
proxy_destination_address(0), proxy_destination_address(0),
proxy_destination_port(0), proxy_destination_port(0),
language(1),
x(0.0f), x(0.0f),
z(0.0f), z(0.0f),
area(0), area(0),
+1 -4
View File
@@ -150,6 +150,7 @@ struct Client : public std::enable_shared_from_this<Client> {
// Lobby/positioning // Lobby/positioning
ClientOptions options; ClientOptions options;
uint8_t language;
float x; float x;
float z; float z;
uint32_t area; uint32_t area;
@@ -191,10 +192,6 @@ struct Client : public std::enable_shared_from_this<Client> {
void reschedule_ping_and_timeout_events(); void reschedule_ping_and_timeout_events();
inline uint8_t language() const {
auto p = this->game_data.player(true, false);
return p ? p->inventory.language : 1; // English by default
}
inline GameVersion version() const { inline GameVersion version() const {
return this->channel.version; return this->channel.version;
} }
+8 -9
View File
@@ -2318,7 +2318,7 @@ void Server::handle_CAx40_map_list_request(shared_ptr<Client> sender_c, const st
} }
const auto& list_data = this->options.map_index->get_compressed_list( const auto& list_data = this->options.map_index->get_compressed_list(
l->count_clients(), sender_c->language()); l->count_clients(), sender_c->language);
StringWriter w; StringWriter w;
uint32_t subcommand_size = (list_data.size() + sizeof(G_MapList_GC_Ep3_6xB6x40) + 3) & (~3); uint32_t subcommand_size = (list_data.size() + sizeof(G_MapList_GC_Ep3_6xB6x40) + 3) & (~3);
@@ -2347,16 +2347,15 @@ void Server::send_6xB6x41_to_all_clients() const {
if (!c) { if (!c) {
return; return;
} }
uint8_t language = c->language(); if (map_commands_by_language.size() <= c->language) {
if (map_commands_by_language.size() <= language) { map_commands_by_language.resize(c->language + 1);
map_commands_by_language.resize(language + 1);
} }
if (map_commands_by_language[language].empty()) { if (map_commands_by_language[c->language].empty()) {
map_commands_by_language[language] = this->prepare_6xB6x41_map_definition( map_commands_by_language[c->language] = this->prepare_6xB6x41_map_definition(
this->last_chosen_map, language, l->flags & Lobby::Flag::IS_EP3_TRIAL); this->last_chosen_map, c->language, l->flags & Lobby::Flag::IS_EP3_TRIAL);
} }
this->log().info("Sending %c version of map %08" PRIX32, char_for_language_code(language), this->last_chosen_map->map_number); this->log().info("Sending %c version of map %08" PRIX32, char_for_language_code(c->language), this->last_chosen_map->map_number);
send_command(c, 0x6C, 0x00, map_commands_by_language[language]); send_command(c, 0x6C, 0x00, map_commands_by_language[c->language]);
}; };
for (const auto& c : l->clients) { for (const auto& c : l->clients) {
send_to_client(c); send_to_client(c);
+16 -9
View File
@@ -430,6 +430,7 @@ static void on_8B_DCNTE(shared_ptr<Client> c, uint16_t, uint32_t, const string&
c->channel.version = GameVersion::DC; c->channel.version = GameVersion::DC;
c->flags |= flags_for_version(c->version(), -1); c->flags |= flags_for_version(c->version(), -1);
c->flags |= Client::Flag::IS_DC_V1 | Client::Flag::IS_DC_TRIAL_EDITION; c->flags |= Client::Flag::IS_DC_V1 | Client::Flag::IS_DC_TRIAL_EDITION;
c->language = cmd.language;
uint32_t serial_number = stoul(cmd.serial_number, nullptr, 16); uint32_t serial_number = stoul(cmd.serial_number, nullptr, 16);
try { try {
@@ -505,7 +506,8 @@ static void on_90_DC(shared_ptr<Client> c, uint16_t, uint32_t, const string& dat
} }
static void on_92_DC(shared_ptr<Client> c, uint16_t, uint32_t, const string& data) { static void on_92_DC(shared_ptr<Client> c, uint16_t, uint32_t, const string& data) {
check_size_t<C_RegisterV1_DC_92>(data); const auto& cmd = check_size_t<C_RegisterV1_DC_92>(data);
c->language = cmd.language;
// It appears that in response to 90 01, the DCv1 prototype sends 93 rather // It appears that in response to 90 01, the DCv1 prototype sends 93 rather
// than 92, so we use the presence of a 92 command to determine that the // than 92, so we use the presence of a 92 command to determine that the
// client is actually DCv1 and not the prototype. // client is actually DCv1 and not the prototype.
@@ -518,6 +520,7 @@ static void on_93_DC(shared_ptr<Client> c, uint16_t, uint32_t, const string& dat
auto s = c->require_server_state(); auto s = c->require_server_state();
set_console_client_flags(c, cmd.sub_version); set_console_client_flags(c, cmd.sub_version);
c->language = cmd.language;
uint32_t serial_number = stoul(cmd.serial_number, nullptr, 16); uint32_t serial_number = stoul(cmd.serial_number, nullptr, 16);
try { try {
@@ -633,6 +636,7 @@ static void on_9C(shared_ptr<Client> c, uint16_t, uint32_t, const string& data)
auto s = c->require_server_state(); auto s = c->require_server_state();
set_console_client_flags(c, cmd.sub_version); set_console_client_flags(c, cmd.sub_version);
c->language = cmd.language;
uint32_t serial_number = stoul(cmd.serial_number, nullptr, 16); uint32_t serial_number = stoul(cmd.serial_number, nullptr, 16);
try { try {
@@ -740,6 +744,8 @@ static void on_9D_9E(shared_ptr<Client> c, uint16_t command, uint32_t, const str
} }
set_console_client_flags(c, base_cmd->sub_version); set_console_client_flags(c, base_cmd->sub_version);
c->language = base_cmd->language;
// See system/ppc/Episode3USAQuestBufferOverflow.s for where this value gets // See system/ppc/Episode3USAQuestBufferOverflow.s for where this value gets
// set. We use this to determine if the client has already run the code or // set. We use this to determine if the client has already run the code or
// not; sending it again when the client has already run it will likely cause // not; sending it again when the client has already run it will likely cause
@@ -1494,7 +1500,7 @@ static void on_09(shared_ptr<Client> c, uint16_t, uint32_t, const string& data)
if (!q) { if (!q) {
send_quest_info(c, u"$C4Quest does not\nexist.", is_download_quest); send_quest_info(c, u"$C4Quest does not\nexist.", is_download_quest);
} else { } else {
auto vq = q->version(c->quest_version(), c->language()); auto vq = q->version(c->quest_version(), c->language);
if (!vq) { if (!vq) {
send_quest_info(c, u"$C4Quest does not\nexist for this game\nversion.", is_download_quest); send_quest_info(c, u"$C4Quest does not\nexist for this game\nversion.", is_download_quest);
} else { } else {
@@ -1747,7 +1753,7 @@ static void on_10(shared_ptr<Client> c, uint16_t, uint32_t, const string& data)
if (num_ep3_categories == 1) { if (num_ep3_categories == 1) {
auto quest_index = s->quest_index_for_client(c); auto quest_index = s->quest_index_for_client(c);
if (quest_index) { if (quest_index) {
auto quests = quest_index->filter(ep3_category_id, c->quest_version(), c->language()); auto quests = quest_index->filter(ep3_category_id, c->quest_version(), c->language);
send_quest_menu(c, MenuID::QUEST, quests, true); send_quest_menu(c, MenuID::QUEST, quests, true);
} else { } else {
send_lobby_message_box(c, u"$C6Quests are not available."); send_lobby_message_box(c, u"$C6Quests are not available.");
@@ -2033,7 +2039,7 @@ static void on_10(shared_ptr<Client> c, uint16_t, uint32_t, const string& data)
break; break;
} }
shared_ptr<Lobby> l = c->lobby.lock(); shared_ptr<Lobby> l = c->lobby.lock();
auto quests = quest_index->filter(item_id, c->quest_version(), c->language()); auto quests = quest_index->filter(item_id, c->quest_version(), c->language);
// Hack: Assume the menu to be sent is the download quest menu if the // Hack: Assume the menu to be sent is the download quest menu if the
// client is not in any lobby // client is not in any lobby
@@ -2089,7 +2095,7 @@ static void on_10(shared_ptr<Client> c, uint16_t, uint32_t, const string& data)
continue; continue;
} }
auto vq = q->version(lc->quest_version(), lc->language()); auto vq = q->version(lc->quest_version(), lc->language);
if (!vq) { if (!vq) {
send_lobby_message_box(lc, u"$C6Quest does not exist\nfor this game version."); send_lobby_message_box(lc, u"$C6Quest does not exist\nfor this game version.");
lc->should_disconnect = true; lc->should_disconnect = true;
@@ -2137,7 +2143,7 @@ static void on_10(shared_ptr<Client> c, uint16_t, uint32_t, const string& data)
} else { } else {
string quest_name = encode_sjis(q->name); string quest_name = encode_sjis(q->name);
auto vq = q->version(c->quest_version(), c->language()); auto vq = q->version(c->quest_version(), c->language);
if (!vq) { if (!vq) {
send_lobby_message_box(c, u"$C6Quest does not exist\nfor this game version."); send_lobby_message_box(c, u"$C6Quest does not exist\nfor this game version.");
break; break;
@@ -2491,7 +2497,7 @@ static void on_AC_V3_BB(shared_ptr<Client> c, uint16_t, uint32_t, const string&
(l->base_version == GameVersion::BB) && (l->base_version == GameVersion::BB) &&
l->map && l->map &&
l->quest) { l->quest) {
auto dat_contents = prs_decompress(*l->quest->version(QuestScriptVersion::BB_V4, c->language())->dat_contents); auto dat_contents = prs_decompress(*l->quest->version(QuestScriptVersion::BB_V4, c->language)->dat_contents);
l->map->clear(); l->map->clear();
l->map->add_enemies_from_quest_data(l->episode, l->difficulty, l->event, dat_contents.data(), dat_contents.size()); l->map->add_enemies_from_quest_data(l->episode, l->difficulty, l->event, dat_contents.data(), dat_contents.size());
c->log.info("Replaced enemies list with quest layout (%zu entries)", c->log.info("Replaced enemies list with quest layout (%zu entries)",
@@ -2689,6 +2695,7 @@ static void on_61_98(shared_ptr<Client> c, uint16_t command, uint32_t flag, cons
throw logic_error("player data command not implemented for version"); throw logic_error("player data command not implemented for version");
} }
player->inventory.decode_mags(c->version()); player->inventory.decode_mags(c->version());
c->language = player->inventory.language;
string name_str = remove_language_marker(encode_sjis(player->disp.name)); string name_str = remove_language_marker(encode_sjis(player->disp.name));
c->channel.name = string_printf("C-%" PRIX64 " (%s)", c->id, name_str.c_str()); c->channel.name = string_printf("C-%" PRIX64 " (%s)", c->id, name_str.c_str());
@@ -3663,7 +3670,7 @@ static void on_6F(shared_ptr<Client> c, uint16_t, uint32_t, const string& data)
if (!l->quest) { if (!l->quest) {
throw runtime_error("JOINABLE_QUEST_IN_PROGRESS is set, but lobby has no quest"); throw runtime_error("JOINABLE_QUEST_IN_PROGRESS is set, but lobby has no quest");
} }
auto vq = l->quest->version(c->quest_version(), c->language()); auto vq = l->quest->version(c->quest_version(), c->language);
if (!vq) { if (!vq) {
throw runtime_error("JOINABLE_QUEST_IN_PROGRESS is set, but lobby has no quest for client version"); throw runtime_error("JOINABLE_QUEST_IN_PROGRESS is set, but lobby has no quest for client version");
} }
@@ -3685,7 +3692,7 @@ static void on_6F(shared_ptr<Client> c, uint16_t, uint32_t, const string& data)
} else if (watched_lobby && watched_lobby->ep3_server) { } else if (watched_lobby && watched_lobby->ep3_server) {
if (!watched_lobby->ep3_server->battle_finished) { if (!watched_lobby->ep3_server->battle_finished) {
watched_lobby->ep3_server->send_commands_for_joining_spectator( watched_lobby->ep3_server->send_commands_for_joining_spectator(
c->channel, c->language(), c->flags & Client::Flag::IS_EP3_TRIAL_EDITION); c->channel, c->language, c->flags & Client::Flag::IS_EP3_TRIAL_EDITION);
} }
send_ep3_update_game_metadata(watched_lobby); send_ep3_update_game_metadata(watched_lobby);
} }
+3 -3
View File
@@ -1279,7 +1279,7 @@ void send_quest_menu_t(
auto v = c->quest_version(); auto v = c->quest_version();
vector<EntryT> entries; vector<EntryT> entries;
for (const auto& quest : quests) { for (const auto& quest : quests) {
auto vq = quest->version(v, c->language()); auto vq = quest->version(v, c->language);
if (!vq) { if (!vq) {
continue; continue;
} }
@@ -2390,7 +2390,7 @@ void send_ep3_tournament_details(
shared_ptr<const Episode3::Tournament> tourn) { shared_ptr<const Episode3::Tournament> tourn) {
S_TournamentGameDetails_GC_Ep3_E3 cmd; S_TournamentGameDetails_GC_Ep3_E3 cmd;
cmd.name = tourn->get_name(); cmd.name = tourn->get_name();
cmd.map_name = tourn->get_map()->version(c->language())->map->name; cmd.map_name = tourn->get_map()->version(c->language)->map->name;
cmd.rules = tourn->get_rules(); cmd.rules = tourn->get_rules();
const auto& teams = tourn->all_teams(); const auto& teams = tourn->all_teams();
for (size_t z = 0; z < min<size_t>(teams.size(), 0x20); z++) { for (size_t z = 0; z < min<size_t>(teams.size(), 0x20); z++) {
@@ -2431,7 +2431,7 @@ void send_ep3_game_details(shared_ptr<Client> c, shared_ptr<Lobby> l) {
S_TournamentGameDetails_GC_Ep3_E3 cmd; S_TournamentGameDetails_GC_Ep3_E3 cmd;
cmd.name = encode_sjis(l->name); cmd.name = encode_sjis(l->name);
cmd.map_name = tourn->get_map()->version(c->language())->map->name; cmd.map_name = tourn->get_map()->version(c->language)->map->name;
cmd.rules = tourn->get_rules(); cmd.rules = tourn->get_rules();
const auto& teams = tourn->all_teams(); const auto& teams = tourn->all_teams();