rename client and lobby flags

This commit is contained in:
Martin Michelsen
2022-09-22 22:50:14 -07:00
parent 7bcb040e8d
commit 29fc74470d
9 changed files with 106 additions and 94 deletions
+2 -2
View File
@@ -69,7 +69,7 @@ static void check_is_game(shared_ptr<Lobby> l, bool is_game) {
} }
static void check_is_ep3(shared_ptr<Client> c, bool is_ep3) { static void check_is_ep3(shared_ptr<Client> c, bool is_ep3) {
if (!!(c->flags & Client::Flag::EPISODE_3) != is_ep3) { if (!!(c->flags & Client::Flag::IS_EPISODE_3) != is_ep3) {
throw precondition_failed(is_ep3 ? throw precondition_failed(is_ep3 ?
u"$C6This command can only\nbe used in Episode 3." : u"$C6This command can only\nbe used in Episode 3." :
u"$C6This command cannot\nbe used in Episode 3."); u"$C6This command cannot\nbe used in Episode 3.");
@@ -270,7 +270,7 @@ static void proxy_command_lobby_event(shared_ptr<ServerState>,
if (((session.version == GameVersion::GC) || if (((session.version == GameVersion::GC) ||
(session.version == GameVersion::XB) || (session.version == GameVersion::XB) ||
(session.version == GameVersion::BB)) && (session.version == GameVersion::BB)) &&
!(session.newserv_client_config.cfg.flags & Client::Flag::GC_TRIAL_EDITION)) { !(session.newserv_client_config.cfg.flags & Client::Flag::IS_TRIAL_EDITION)) {
session.client_channel.send(0xDA, session.override_lobby_event); session.client_channel.send(0xDA, session.override_lobby_event);
} }
} }
+31 -23
View File
@@ -22,38 +22,46 @@ extern const uint64_t CLIENT_CONFIG_MAGIC;
struct Client { struct Client {
enum Flag { enum Flag {
// This flag has two meanings. If set on a client with GameVersion::DC, then
// IS_DC_V1 is also set. In this case, the client is DC Network Trial
// Edition, which uses several commands that no other version uses. If this
// flag is set without IS_DC_V1, then the client is GC Episodes 1 & 2 Trial
// Edition, and therefore uses V2 encryption instead of V3 encryption, and
// doesn't support some commands.
// Note that this flag is NOT set for Episode 3 Trial Edition clients, since
// that version is similar enough to the release version of Episode 3 that
// newserv does not have to change its behavior at all.
IS_TRIAL_EDITION = 0x2000,
// Client is DC v1
IS_DC_V1 = 0x0010,
// For patch server clients, client is Blue Burst rather than PC // For patch server clients, client is Blue Burst rather than PC
BB_PATCH = 0x0001, IS_BB_PATCH = 0x0001,
// After joining a lobby, client will no longer send D6 commands when they // After joining a lobby, client will no longer send D6 commands when they
// close message boxes // close message boxes
NO_MESSAGE_BOX_CLOSE_CONFIRMATION_AFTER_LOBBY_JOIN = 0x0002, NO_D6_AFTER_LOBBY = 0x0002,
// Client has the above flag and has already joined a lobby, or is not GC // Client has the above flag and has already joined a lobby, or is not GC
NO_MESSAGE_BOX_CLOSE_CONFIRMATION = 0x0004, NO_D6 = 0x0004,
// Client is Episode 3, should be able to see CARD lobbies, and should only // Client is Episode 3, should be able to see CARD lobbies, and should only
// be able to see/join games with the IS_EPISODE_3 flag // be able to see/join games with the EPISODE_3_ONLY flag
EPISODE_3 = 0x0008, IS_EPISODE_3 = 0x0008,
// Client is DC v1 (disables some features)
DCV1 = 0x0010,
// Client is loading into a game
LOADING = 0x0020,
// Client is loading a quest
LOADING_QUEST = 0x0040,
// Client is in the information menu (login server only)
IN_INFORMATION_MENU = 0x0080,
// Client is at the welcome message (login server only)
AT_WELCOME_MESSAGE = 0x0100,
// Client disconnects if it receives B2 (send_function_call) // Client disconnects if it receives B2 (send_function_call)
DOES_NOT_SUPPORT_SEND_FUNCTION_CALL = 0x0200, NO_SEND_FUNCTION_CALL = 0x0200,
// Client has already received a 97 (enable saves) command, so don't show
// the programs menu anymore
SAVE_ENABLED = 0x0400,
// Client requires doubly-encrypted code section in send_function_call // Client requires doubly-encrypted code section in send_function_call
ENCRYPTED_SEND_FUNCTION_CALL = 0x0800, ENCRYPTED_SEND_FUNCTION_CALL = 0x0800,
// Client supports send_function_call but does not actually run the code // Client supports send_function_call but does not actually run the code
SEND_FUNCTION_CALL_CHECKSUM_ONLY = 0x1000, SEND_FUNCTION_CALL_CHECKSUM_ONLY = 0x1000,
// Client is GC Trial Edition, and therefore uses V2 encryption instead of
// V3, and doesn't support some commands // Client is loading into a game
GC_TRIAL_EDITION = 0x2000, LOADING = 0x0020,
// Client is loading a quest
LOADING_QUEST = 0x0040,
// Client is in the information menu (login server only)
IN_INFORMATION_MENU = 0x0080,
// Client is at the welcome message (login server only)
AT_WELCOME_MESSAGE = 0x0100,
// Client has already received a 97 (enable saves) command, so don't show
// the programs menu anymore
SAVE_ENABLED = 0x0400,
}; };
uint64_t id; uint64_t id;
+1 -1
View File
@@ -22,13 +22,13 @@ struct Lobby {
enum Flag { enum Flag {
GAME = 0x00000001, GAME = 0x00000001,
EPISODE_3_ONLY = 0x00000002, EPISODE_3_ONLY = 0x00000002,
NON_V1_ONLY = 0x00000004, // DC NTE and DCv1 not allowed
// Flags used only for games // Flags used only for games
CHEATS_ENABLED = 0x00000100, CHEATS_ENABLED = 0x00000100,
QUEST_IN_PROGRESS = 0x00000200, QUEST_IN_PROGRESS = 0x00000200,
JOINABLE_QUEST_IN_PROGRESS = 0x00000400, JOINABLE_QUEST_IN_PROGRESS = 0x00000400,
ITEM_TRACKING_ENABLED = 0x00000800, ITEM_TRACKING_ENABLED = 0x00000800,
DC_V2_ONLY = 0x00001000,
BATTLE_MODE = 0x00002000, BATTLE_MODE = 0x00002000,
CHALLENGE_MODE = 0x00004000, CHALLENGE_MODE = 0x00004000,
SOLO_MODE = 0x00008000, SOLO_MODE = 0x00008000,
+4 -4
View File
@@ -226,7 +226,7 @@ static HandlerResult on_server_dc_pc_v3_patch_02_17(
} else if ((session.version == GameVersion::DC) || } else if ((session.version == GameVersion::DC) ||
(session.version == GameVersion::PC)) { (session.version == GameVersion::PC)) {
if (session.newserv_client_config.cfg.flags & Client::Flag::DCV1) { if (session.newserv_client_config.cfg.flags & Client::Flag::IS_DC_V1) {
if (command == 0x17) { if (command == 0x17) {
C_LoginV1_DC_PC_V3_90 cmd; C_LoginV1_DC_PC_V3_90 cmd;
cmd.serial_number = string_printf("%08" PRIX32 "", cmd.serial_number = string_printf("%08" PRIX32 "",
@@ -742,7 +742,7 @@ static HandlerResult on_server_v3_1A_D5(shared_ptr<ServerState>,
// has the no-close-confirmation flag set in its newserv client config, send a // has the no-close-confirmation flag set in its newserv client config, send a
// fake confirmation to the remote server immediately. // fake confirmation to the remote server immediately.
if (((session.version == GameVersion::GC) || (session.version == GameVersion::XB)) && if (((session.version == GameVersion::GC) || (session.version == GameVersion::XB)) &&
(session.newserv_client_config.cfg.flags & Client::Flag::NO_MESSAGE_BOX_CLOSE_CONFIRMATION)) { (session.newserv_client_config.cfg.flags & Client::Flag::NO_D6)) {
session.server_channel.send(0xD6); session.server_channel.send(0xD6);
} }
return HandlerResult::Type::FORWARD; return HandlerResult::Type::FORWARD;
@@ -909,8 +909,8 @@ static HandlerResult on_server_65_67_68(shared_ptr<ServerState>,
// behavior in the client config, so if it happens during a proxy session, // behavior in the client config, so if it happens during a proxy session,
// update the client config that we'll restore if the client uses the change // update the client config that we'll restore if the client uses the change
// ship or change block command. // ship or change block command.
if (session.newserv_client_config.cfg.flags & Client::Flag::NO_MESSAGE_BOX_CLOSE_CONFIRMATION_AFTER_LOBBY_JOIN) { if (session.newserv_client_config.cfg.flags & Client::Flag::NO_D6_AFTER_LOBBY) {
session.newserv_client_config.cfg.flags |= Client::Flag::NO_MESSAGE_BOX_CLOSE_CONFIRMATION; session.newserv_client_config.cfg.flags |= Client::Flag::NO_D6;
} }
} }
+1 -1
View File
@@ -274,7 +274,7 @@ void ProxyServer::UnlinkedSession::on_input(Channel& ch, uint16_t command, uint3
language = cmd.language; language = cmd.language;
character_name = cmd.name; character_name = cmd.name;
hardware_id = cmd.hardware_id; hardware_id = cmd.hardware_id;
client_config.cfg.flags |= Client::Flag::DCV1; client_config.cfg.flags |= Client::Flag::IS_DC_V1;
} else if (command == 0x9D) { } else if (command == 0x9D) {
const auto& cmd = check_size_t<C_Login_DC_PC_GC_9D>( 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)); data, sizeof(C_Login_DC_PC_GC_9D), sizeof(C_LoginExtended_DC_GC_9D));
+27 -25
View File
@@ -81,7 +81,7 @@ void on_connect(std::shared_ptr<ServerState> s, std::shared_ptr<Client> c) {
break; break;
case ServerBehavior::PATCH_SERVER_BB: case ServerBehavior::PATCH_SERVER_BB:
c->flags |= Client::Flag::BB_PATCH; c->flags |= Client::Flag::IS_BB_PATCH;
send_server_init(s, c, 0); send_server_init(s, c, 0);
break; break;
@@ -104,7 +104,7 @@ void on_login_complete(shared_ptr<ServerState> s, shared_ptr<Client> c) {
(c->server_behavior == ServerBehavior::DATA_SERVER_BB)) { (c->server_behavior == ServerBehavior::DATA_SERVER_BB)) {
// On the login server, send the events/songs, ep3 updates, and the main // On the login server, send the events/songs, ep3 updates, and the main
// menu or welcome message // menu or welcome message
if (c->flags & Client::Flag::EPISODE_3) { if (c->flags & Client::Flag::IS_EPISODE_3) {
if (s->ep3_menu_song >= 0) { if (s->ep3_menu_song >= 0) {
send_ep3_change_music(c, s->ep3_menu_song); send_ep3_change_music(c, s->ep3_menu_song);
} else if (s->pre_lobby_event) { } else if (s->pre_lobby_event) {
@@ -117,7 +117,7 @@ void on_login_complete(shared_ptr<ServerState> s, shared_ptr<Client> c) {
} }
if (s->welcome_message.empty() || if (s->welcome_message.empty() ||
(c->flags & Client::Flag::NO_MESSAGE_BOX_CLOSE_CONFIRMATION) || (c->flags & Client::Flag::NO_D6) ||
!(c->flags & Client::Flag::AT_WELCOME_MESSAGE)) { !(c->flags & Client::Flag::AT_WELCOME_MESSAGE)) {
c->flags &= ~Client::Flag::AT_WELCOME_MESSAGE; c->flags &= ~Client::Flag::AT_WELCOME_MESSAGE;
send_menu(c, s->name.c_str(), MenuID::MAIN, s->main_menu); send_menu(c, s->name.c_str(), MenuID::MAIN, s->main_menu);
@@ -164,7 +164,7 @@ static void set_console_client_flags(
c->channel.version = GameVersion::DC; c->channel.version = GameVersion::DC;
c->log.info("Game version changed to DC"); c->log.info("Game version changed to DC");
} else if (c->version() == GameVersion::GC) { } else if (c->version() == GameVersion::GC) {
c->flags |= Client::Flag::GC_TRIAL_EDITION; c->flags |= Client::Flag::IS_TRIAL_EDITION;
c->log.info("Trial edition flag set"); c->log.info("Trial edition flag set");
} }
} }
@@ -217,7 +217,7 @@ static void on_login_0_dc_pc_v3(shared_ptr<ServerState> s, shared_ptr<Client> c,
const auto& cmd = check_size_t<C_LoginV1_DC_PC_V3_90>(data); const auto& cmd = check_size_t<C_LoginV1_DC_PC_V3_90>(data);
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::DCV1; c->flags |= Client::Flag::IS_DC_V1;
uint32_t serial_number = stoul(cmd.serial_number, nullptr, 16); uint32_t serial_number = stoul(cmd.serial_number, nullptr, 16);
try { try {
@@ -1005,10 +1005,10 @@ static void on_menu_selection(shared_ptr<ServerState> s, shared_ptr<Client> c,
break; break;
case MainMenuItemID::DOWNLOAD_QUESTS: case MainMenuItemID::DOWNLOAD_QUESTS:
if (c->flags & Client::Flag::EPISODE_3) { if (c->flags & Client::Flag::IS_EPISODE_3) {
shared_ptr<Lobby> l = c->lobby_id ? s->find_lobby(c->lobby_id) : nullptr; shared_ptr<Lobby> l = c->lobby_id ? s->find_lobby(c->lobby_id) : nullptr;
auto quests = s->quest_index->filter( auto quests = s->quest_index->filter(
c->version(), c->flags & Client::Flag::DCV1, QuestCategory::EPISODE_3); c->version(), c->flags & Client::Flag::IS_DC_V1, QuestCategory::EPISODE_3);
if (quests.empty()) { if (quests.empty()) {
send_lobby_message_box(c, u"$C6There are no quests\navailable."); send_lobby_message_box(c, u"$C6There are no quests\navailable.");
} else { } else {
@@ -1116,8 +1116,8 @@ static void on_menu_selection(shared_ptr<ServerState> s, shared_ptr<Client> c,
break; break;
} }
if ((game->version != c->version()) || if ((game->version != c->version()) ||
(!(game->flags & Lobby::Flag::EPISODE_3_ONLY) != !(c->flags & Client::Flag::EPISODE_3)) || (!(game->flags & Lobby::Flag::EPISODE_3_ONLY) != !(c->flags & Client::Flag::IS_EPISODE_3)) ||
((game->flags & Lobby::Flag::DC_V2_ONLY) && (c->flags & Client::Flag::DCV1))) { ((game->flags & Lobby::Flag::NON_V1_ONLY) && (c->flags & Client::Flag::IS_DC_V1))) {
send_lobby_message_box(c, u"$C6You cannot join this\ngame because it is\nfor a different\nversion of PSO."); send_lobby_message_box(c, u"$C6You cannot join this\ngame because it is\nfor a different\nversion of PSO.");
break; break;
} }
@@ -1163,7 +1163,7 @@ static void on_menu_selection(shared_ptr<ServerState> s, shared_ptr<Client> c,
} }
shared_ptr<Lobby> l = c->lobby_id ? s->find_lobby(c->lobby_id) : nullptr; shared_ptr<Lobby> l = c->lobby_id ? s->find_lobby(c->lobby_id) : nullptr;
auto quests = s->quest_index->filter(c->version(), auto quests = s->quest_index->filter(c->version(),
c->flags & Client::Flag::DCV1, c->flags & Client::Flag::IS_DC_V1,
static_cast<QuestCategory>(item_id & 0xFF)); static_cast<QuestCategory>(item_id & 0xFF));
if (quests.empty()) { if (quests.empty()) {
send_lobby_message_box(c, u"$C6There are no quests\navailable in that\ncategory."); send_lobby_message_box(c, u"$C6There are no quests\navailable in that\ncategory.");
@@ -1240,7 +1240,7 @@ static void on_menu_selection(shared_ptr<ServerState> s, shared_ptr<Client> c,
// check/clear it later. // check/clear it later.
if ((l->clients[x]->version() != GameVersion::DC) && if ((l->clients[x]->version() != GameVersion::DC) &&
(l->clients[x]->version() != GameVersion::PC) && (l->clients[x]->version() != GameVersion::PC) &&
!(l->clients[x]->flags & Client::Flag::GC_TRIAL_EDITION)) { !(l->clients[x]->flags & Client::Flag::IS_TRIAL_EDITION)) {
l->clients[x]->flags |= Client::Flag::LOADING_QUEST; l->clients[x]->flags |= Client::Flag::LOADING_QUEST;
} }
} }
@@ -1268,7 +1268,7 @@ static void on_menu_selection(shared_ptr<ServerState> s, shared_ptr<Client> c,
send_menu(c, s->name.c_str(), MenuID::MAIN, s->main_menu); send_menu(c, s->name.c_str(), MenuID::MAIN, s->main_menu);
} else { } else {
if (c->flags & Client::Flag::DOES_NOT_SUPPORT_SEND_FUNCTION_CALL) { if (c->flags & Client::Flag::NO_SEND_FUNCTION_CALL) {
throw runtime_error("client does not support send_function_call"); throw runtime_error("client does not support send_function_call");
} }
@@ -1283,7 +1283,7 @@ static void on_menu_selection(shared_ptr<ServerState> s, shared_ptr<Client> c,
send_menu(c, s->name.c_str(), MenuID::MAIN, s->main_menu); send_menu(c, s->name.c_str(), MenuID::MAIN, s->main_menu);
} else { } else {
if (c->flags & Client::Flag::DOES_NOT_SUPPORT_SEND_FUNCTION_CALL) { if (c->flags & Client::Flag::NO_SEND_FUNCTION_CALL) {
throw runtime_error("client does not support send_function_call"); throw runtime_error("client does not support send_function_call");
} }
@@ -1331,7 +1331,7 @@ static void on_change_lobby(shared_ptr<ServerState> s, shared_ptr<Client> c,
return; return;
} }
if ((new_lobby->flags & Lobby::Flag::EPISODE_3_ONLY) && !(c->flags & Client::Flag::EPISODE_3)) { if ((new_lobby->flags & Lobby::Flag::EPISODE_3_ONLY) && !(c->flags & Client::Flag::IS_EPISODE_3)) {
send_lobby_message_box(c, u"$C6Can't change lobby\n\n$C7The lobby is for\nEpisode 3 only."); send_lobby_message_box(c, u"$C6Can't change lobby\n\n$C7The lobby is for\nEpisode 3 only.");
return; return;
} }
@@ -1453,7 +1453,7 @@ static void on_quest_list_request(shared_ptr<ServerState> s, shared_ptr<Client>
// In Episode 3, there are no quest categories, so skip directly to the quest // In Episode 3, there are no quest categories, so skip directly to the quest
// filter menu. // filter menu.
if (c->flags & Client::Flag::EPISODE_3) { if (c->flags & Client::Flag::IS_EPISODE_3) {
send_lobby_message_box(c, u"$C6Episode 3 does not\nprovide online quests\nvia this interface."); send_lobby_message_box(c, u"$C6Episode 3 does not\nprovide online quests\nvia this interface.");
} else { } else {
@@ -1516,7 +1516,7 @@ static void on_update_quest_statistics(shared_ptr<ServerState> s,
shared_ptr<Client> c, uint16_t, uint32_t, const string& data) { // AA shared_ptr<Client> c, uint16_t, uint32_t, const string& data) { // AA
const auto& cmd = check_size_t<C_UpdateQuestStatistics_V3_BB_AA>(data); const auto& cmd = check_size_t<C_UpdateQuestStatistics_V3_BB_AA>(data);
if (c->flags & Client::Flag::GC_TRIAL_EDITION) { if (c->flags & Client::Flag::IS_TRIAL_EDITION) {
throw runtime_error("trial edition client sent update quest stats command"); throw runtime_error("trial edition client sent update quest stats command");
} }
@@ -1562,7 +1562,7 @@ static void on_player_data(shared_ptr<ServerState> s, shared_ptr<Client> c,
case GameVersion::XB: { case GameVersion::XB: {
const PSOPlayerDataV3* pd; const PSOPlayerDataV3* pd;
if (flag == 4) { // Episode 3 if (flag == 4) { // Episode 3
if (!(c->flags & Client::Flag::EPISODE_3)) { if (!(c->flags & Client::Flag::IS_EPISODE_3)) {
throw runtime_error("non-Episode 3 client sent Episode 3 player data"); throw runtime_error("non-Episode 3 client sent Episode 3 player data");
} }
const auto* pd3 = &check_size_t<PSOPlayerDataGCEp3>(data); const auto* pd3 = &check_size_t<PSOPlayerDataGCEp3>(data);
@@ -2297,7 +2297,7 @@ static void on_create_game_pc(shared_ptr<ServerState> s, shared_ptr<Client> c,
uint16_t, uint32_t, const string& data) { // C1 uint16_t, uint32_t, const string& data) { // C1
const auto& cmd = check_size_t<C_CreateGame_PC_C1>(data); const auto& cmd = check_size_t<C_CreateGame_PC_C1>(data);
uint32_t flags = 0; uint32_t flags = Lobby::Flag::NON_V1_ONLY;
if (cmd.battle_mode) { if (cmd.battle_mode) {
flags |= Lobby::Flag::BATTLE_MODE; flags |= Lobby::Flag::BATTLE_MODE;
} }
@@ -2312,21 +2312,23 @@ static void on_create_game_dc_v3(shared_ptr<ServerState> s, shared_ptr<Client> c
const auto& cmd = check_size_t<C_CreateGame_DC_V3_0C_C1_Ep3_EC>(data); const auto& cmd = check_size_t<C_CreateGame_DC_V3_0C_C1_Ep3_EC>(data);
// Only allow EC from Ep3 clients // Only allow EC from Ep3 clients
bool client_is_ep3 = c->flags & Client::Flag::EPISODE_3; bool client_is_ep3 = c->flags & Client::Flag::IS_EPISODE_3;
if ((command == 0xEC) && !client_is_ep3) { if ((command == 0xEC) && !client_is_ep3) {
return; return;
} }
uint8_t episode = cmd.episode; uint8_t episode = cmd.episode;
uint32_t flags = 0; uint32_t flags = 0;
if ((c->version() == GameVersion::DC) || (c->version() == GameVersion::PC)) { if (c->version() == GameVersion::DC) {
if (episode) { if (episode) {
flags |= Lobby::Flag::DC_V2_ONLY; flags |= Lobby::Flag::NON_V1_ONLY;
} }
episode = 1; episode = 1;
} else if (client_is_ep3) { } else if (client_is_ep3) {
flags |= Lobby::Flag::EPISODE_3_ONLY; flags |= (Lobby::Flag::NON_V1_ONLY | Lobby::Flag::EPISODE_3_ONLY);
episode = 0xFF; episode = 0xFF;
} else { // XB/GC non-Ep3
flags |= Lobby::Flag::NON_V1_ONLY;
} }
u16string name = decode_sjis(cmd.name); u16string name = decode_sjis(cmd.name);
@@ -2346,7 +2348,7 @@ static void on_create_game_bb(shared_ptr<ServerState> s, shared_ptr<Client> c,
uint16_t, uint32_t, const string& data) { // C1 uint16_t, uint32_t, const string& data) { // C1
const auto& cmd = check_size_t<C_CreateGame_BB_C1>(data); const auto& cmd = check_size_t<C_CreateGame_BB_C1>(data);
uint32_t flags = 0; uint32_t flags = Lobby::Flag::NON_V1_ONLY;
if (cmd.battle_mode) { if (cmd.battle_mode) {
flags |= Lobby::Flag::BATTLE_MODE; flags |= Lobby::Flag::BATTLE_MODE;
} }
@@ -2579,13 +2581,13 @@ static void on_login_patch(shared_ptr<ServerState> s, shared_ptr<Client> c,
// On BB we can use colors and newlines should be \n; on PC we can't use // On BB we can use colors and newlines should be \n; on PC we can't use
// colors, the text is auto-word-wrapped, and newlines should be \r\n. // colors, the text is auto-word-wrapped, and newlines should be \r\n.
const u16string& message = (c->flags & Client::Flag::BB_PATCH) const u16string& message = (c->flags & Client::Flag::IS_BB_PATCH)
? s->bb_patch_server_message : s->pc_patch_server_message; ? s->bb_patch_server_message : s->pc_patch_server_message;
if (!message.empty()) { if (!message.empty()) {
send_message_box(c, message.c_str()); send_message_box(c, message.c_str());
} }
auto index = (c->flags & Client::Flag::BB_PATCH) ? auto index = (c->flags & Client::Flag::IS_BB_PATCH) ?
s->bb_patch_file_index : s->pc_patch_file_index; s->bb_patch_file_index : s->pc_patch_file_index;
if (index.get()) { if (index.get()) {
send_command(c, 0x0B, 0x00); // Start patch session; go to root directory send_command(c, 0x0B, 0x00); // Start patch session; go to root directory
+4 -4
View File
@@ -65,7 +65,7 @@ static void forward_subcommand(shared_ptr<Lobby> l, shared_ptr<Client> c,
// if the command is an Ep3-only command, make sure an Ep3 client sent it // if the command is an Ep3-only command, make sure an Ep3 client sent it
bool command_is_ep3 = (command & 0xF0) == 0xC0; bool command_is_ep3 = (command & 0xF0) == 0xC0;
if (command_is_ep3 && !(c->flags & Client::Flag::EPISODE_3)) { if (command_is_ep3 && !(c->flags & Client::Flag::IS_EPISODE_3)) {
return; return;
} }
@@ -77,7 +77,7 @@ static void forward_subcommand(shared_ptr<Lobby> l, shared_ptr<Client> c,
if (!target) { if (!target) {
return; return;
} }
if (command_is_ep3 && !(target->flags & Client::Flag::EPISODE_3)) { if (command_is_ep3 && !(target->flags & Client::Flag::IS_EPISODE_3)) {
return; return;
} }
send_command(target, command, flag, data, size); send_command(target, command, flag, data, size);
@@ -85,7 +85,7 @@ static void forward_subcommand(shared_ptr<Lobby> l, shared_ptr<Client> c,
} else { } else {
if (command_is_ep3) { if (command_is_ep3) {
for (auto& target : l->clients) { for (auto& target : l->clients) {
if (!target || (target == c) || !(target->flags & Client::Flag::EPISODE_3)) { if (!target || (target == c) || !(target->flags & Client::Flag::IS_EPISODE_3)) {
continue; continue;
} }
send_command(target, command, flag, data, size); send_command(target, command, flag, data, size);
@@ -191,7 +191,7 @@ static void on_subcommand_set_player_visibility(shared_ptr<ServerState>,
forward_subcommand(l, c, command, flag, data); forward_subcommand(l, c, command, flag, data);
if (!l->is_game() && !(c->flags & Client::Flag::DCV1)) { if (!l->is_game() && !(c->flags & Client::Flag::IS_DC_V1)) {
send_arrow_update(l); send_arrow_update(l);
} }
} }
+15 -13
View File
@@ -247,7 +247,7 @@ void send_function_call(
const std::string& suffix, const std::string& suffix,
uint32_t checksum_addr, uint32_t checksum_addr,
uint32_t checksum_size) { uint32_t checksum_size) {
if (c->flags & Client::Flag::DOES_NOT_SUPPORT_SEND_FUNCTION_CALL) { if (c->flags & Client::Flag::NO_SEND_FUNCTION_CALL) {
throw logic_error("client does not support function calls"); throw logic_error("client does not support function calls");
} }
if (code.get() && (c->flags & Client::Flag::SEND_FUNCTION_CALL_CHECKSUM_ONLY)) { if (code.get() && (c->flags & Client::Flag::SEND_FUNCTION_CALL_CHECKSUM_ONLY)) {
@@ -846,8 +846,8 @@ void send_menu_t(
((c->version() == GameVersion::GC) && (item.flags & MenuItem::Flag::INVISIBLE_ON_GC)) || ((c->version() == GameVersion::GC) && (item.flags & MenuItem::Flag::INVISIBLE_ON_GC)) ||
((c->version() == GameVersion::XB) && (item.flags & MenuItem::Flag::INVISIBLE_ON_XB)) || ((c->version() == GameVersion::XB) && (item.flags & MenuItem::Flag::INVISIBLE_ON_XB)) ||
((c->version() == GameVersion::BB) && (item.flags & MenuItem::Flag::INVISIBLE_ON_BB)) || ((c->version() == GameVersion::BB) && (item.flags & MenuItem::Flag::INVISIBLE_ON_BB)) ||
((item.flags & MenuItem::Flag::REQUIRES_MESSAGE_BOXES) && (c->flags & Client::Flag::NO_MESSAGE_BOX_CLOSE_CONFIRMATION)) || ((item.flags & MenuItem::Flag::REQUIRES_MESSAGE_BOXES) && (c->flags & Client::Flag::NO_D6)) ||
((item.flags & MenuItem::Flag::REQUIRES_SEND_FUNCTION_CALL) && (c->flags & Client::Flag::DOES_NOT_SUPPORT_SEND_FUNCTION_CALL)) || ((item.flags & MenuItem::Flag::REQUIRES_SEND_FUNCTION_CALL) && (c->flags & Client::Flag::NO_SEND_FUNCTION_CALL)) ||
((item.flags & MenuItem::Flag::REQUIRES_SAVE_DISABLED) && (c->flags & Client::Flag::SAVE_ENABLED))) { ((item.flags & MenuItem::Flag::REQUIRES_SAVE_DISABLED) && (c->flags & Client::Flag::SAVE_ENABLED))) {
continue; continue;
} }
@@ -892,11 +892,11 @@ void send_game_menu_t(shared_ptr<Client> c, shared_ptr<ServerState> s) {
continue; continue;
} }
bool l_is_ep3 = !!(l->flags & Lobby::Flag::EPISODE_3_ONLY); bool l_is_ep3 = !!(l->flags & Lobby::Flag::EPISODE_3_ONLY);
bool c_is_ep3 = !!(c->flags & Client::Flag::EPISODE_3); bool c_is_ep3 = !!(c->flags & Client::Flag::IS_EPISODE_3);
if (l_is_ep3 != c_is_ep3) { if (l_is_ep3 != c_is_ep3) {
continue; continue;
} }
if ((c->flags & Client::Flag::DCV1) && (l->flags & Lobby::Flag::DC_V2_ONLY)) { if ((c->flags & Client::Flag::IS_DC_V1) && (l->flags & Lobby::Flag::NON_V1_ONLY)) {
continue; continue;
} }
@@ -906,7 +906,7 @@ void send_game_menu_t(shared_ptr<Client> c, shared_ptr<ServerState> s) {
e.difficulty_tag = (l_is_ep3 ? 0x0A : (l->difficulty + 0x22)); e.difficulty_tag = (l_is_ep3 ? 0x0A : (l->difficulty + 0x22));
e.num_players = l->count_clients(); e.num_players = l->count_clients();
if (c->version() == GameVersion::DC) { if (c->version() == GameVersion::DC) {
e.episode = (l->flags & Lobby::Flag::DC_V2_ONLY) ? 1 : 0; e.episode = (l->flags & Lobby::Flag::NON_V1_ONLY) ? 1 : 0;
} else { } else {
e.episode = ((c->version() == GameVersion::BB) ? (l->max_clients << 4) : 0) | l->episode; e.episode = ((c->version() == GameVersion::BB) ? (l->max_clients << 4) : 0) | l->episode;
} }
@@ -1030,7 +1030,10 @@ void send_lobby_list(shared_ptr<Client> c, shared_ptr<ServerState> s) {
if (!(l->flags & Lobby::Flag::DEFAULT)) { if (!(l->flags & Lobby::Flag::DEFAULT)) {
continue; continue;
} }
if ((l->flags & Lobby::Flag::EPISODE_3_ONLY) && !(c->flags & Client::Flag::EPISODE_3)) { if ((l->flags & Lobby::Flag::NON_V1_ONLY) && (c->flags & Client::Flag::IS_DC_V1)) {
continue;
}
if ((l->flags & Lobby::Flag::EPISODE_3_ONLY) && !(c->flags & Client::Flag::IS_EPISODE_3)) {
continue; continue;
} }
auto& e = entries.emplace_back(); auto& e = entries.emplace_back();
@@ -1118,7 +1121,7 @@ void send_join_lobby_t(shared_ptr<Client> c, shared_ptr<Lobby> l,
// Allow non-canonical lobby types on GC. They may work on other versions too, // Allow non-canonical lobby types on GC. They may work on other versions too,
// but I haven't verified which values don't crash on each version. // but I haven't verified which values don't crash on each version.
if (c->version() == GameVersion::GC) { if (c->version() == GameVersion::GC) {
if (c->flags & Client::Flag::EPISODE_3) { if (c->flags & Client::Flag::IS_EPISODE_3) {
if ((l->type > 0x14) && (l->type < 0xE9)) { if ((l->type > 0x14) && (l->type < 0xE9)) {
lobby_type = l->block - 1; lobby_type = l->block - 1;
} }
@@ -1213,9 +1216,8 @@ void send_join_lobby(shared_ptr<Client> c, shared_ptr<Lobby> l) {
// If the client will stop sending message box close confirmations after // If the client will stop sending message box close confirmations after
// joining any lobby, set the appropriate flag and update the client config // joining any lobby, set the appropriate flag and update the client config
if ((c->flags & (Client::Flag::NO_MESSAGE_BOX_CLOSE_CONFIRMATION_AFTER_LOBBY_JOIN | Client::Flag::NO_MESSAGE_BOX_CLOSE_CONFIRMATION)) if ((c->flags & (Client::Flag::NO_D6_AFTER_LOBBY | Client::Flag::NO_D6)) == Client::Flag::NO_D6_AFTER_LOBBY) {
== Client::Flag::NO_MESSAGE_BOX_CLOSE_CONFIRMATION_AFTER_LOBBY_JOIN) { c->flags |= Client::Flag::NO_D6;
c->flags |= Client::Flag::NO_MESSAGE_BOX_CLOSE_CONFIRMATION;
send_update_client_config(c); send_update_client_config(c);
} }
} }
@@ -1293,7 +1295,7 @@ void send_arrow_update(shared_ptr<Lobby> l) {
} }
for (size_t x = 0; x < l->max_clients; x++) { for (size_t x = 0; x < l->max_clients; x++) {
if (!l->clients[x] || (l->clients[x]->flags & Client::Flag::DCV1)) { if (!l->clients[x] || (l->clients[x]->flags & Client::Flag::IS_DC_V1)) {
continue; continue;
} }
send_command_vt(l->clients[x], 0x88, entries.size(), entries); send_command_vt(l->clients[x], 0x88, entries.size(), entries);
@@ -1695,7 +1697,7 @@ void send_change_event(shared_ptr<Client> c, uint8_t new_event) {
// This command isn't supported on versions before V3, nor on Trial Edition. // This command isn't supported on versions before V3, nor on Trial Edition.
if ((c->version() == GameVersion::DC) || if ((c->version() == GameVersion::DC) ||
(c->version() == GameVersion::PC) || (c->version() == GameVersion::PC) ||
(c->flags & Client::Flag::GC_TRIAL_EDITION)) { (c->flags & Client::Flag::IS_TRIAL_EDITION)) {
return; return;
} }
send_command(c, 0xDA, new_event); send_command(c, 0xDA, new_event);
+21 -21
View File
@@ -15,33 +15,33 @@ uint16_t flags_for_version(GameVersion version, int64_t sub_version) {
case -1: // Initial check (before sub_version recognition) case -1: // Initial check (before sub_version recognition)
switch (version) { switch (version) {
case GameVersion::DC: case GameVersion::DC:
return Client::Flag::NO_MESSAGE_BOX_CLOSE_CONFIRMATION; return Client::Flag::NO_D6;
case GameVersion::GC: case GameVersion::GC:
case GameVersion::XB: case GameVersion::XB:
return 0; return 0;
case GameVersion::PC: case GameVersion::PC:
return Client::Flag::NO_MESSAGE_BOX_CLOSE_CONFIRMATION | return Client::Flag::NO_D6 |
Client::Flag::SEND_FUNCTION_CALL_CHECKSUM_ONLY; Client::Flag::SEND_FUNCTION_CALL_CHECKSUM_ONLY;
case GameVersion::PATCH: case GameVersion::PATCH:
return Client::Flag::NO_MESSAGE_BOX_CLOSE_CONFIRMATION | return Client::Flag::NO_D6 |
Client::Flag::DOES_NOT_SUPPORT_SEND_FUNCTION_CALL; Client::Flag::NO_SEND_FUNCTION_CALL;
case GameVersion::BB: case GameVersion::BB:
return Client::Flag::NO_MESSAGE_BOX_CLOSE_CONFIRMATION | return Client::Flag::NO_D6 |
Client::Flag::SAVE_ENABLED; Client::Flag::SAVE_ENABLED;
} }
break; break;
// TODO: Which other sub_versions of DC v1 and v2 exist? // TODO: Which other sub_versions of DC v1 and v2 exist?
case 0x21: // DCv1 US case 0x21: // DCv1 US
return Client::Flag::DCV1 | return Client::Flag::IS_DC_V1 |
Client::Flag::NO_MESSAGE_BOX_CLOSE_CONFIRMATION | Client::Flag::NO_D6 |
Client::Flag::DOES_NOT_SUPPORT_SEND_FUNCTION_CALL; Client::Flag::NO_SEND_FUNCTION_CALL;
case 0x26: // DCv2 US case 0x26: // DCv2 US
return Client::Flag::NO_MESSAGE_BOX_CLOSE_CONFIRMATION; return Client::Flag::NO_D6;
case 0x29: // PC case 0x29: // PC
return Client::Flag::NO_MESSAGE_BOX_CLOSE_CONFIRMATION | return Client::Flag::NO_D6 |
Client::Flag::SEND_FUNCTION_CALL_CHECKSUM_ONLY; Client::Flag::SEND_FUNCTION_CALL_CHECKSUM_ONLY;
case 0x30: // GC Ep1&2 JP v1.02, at least one version of PSO XB case 0x30: // GC Ep1&2 JP v1.02, at least one version of PSO XB
@@ -50,27 +50,27 @@ uint16_t flags_for_version(GameVersion version, int64_t sub_version) {
return 0; return 0;
case 0x32: // GC Ep1&2 EU 50Hz case 0x32: // GC Ep1&2 EU 50Hz
case 0x33: // GC Ep1&2 EU 60Hz case 0x33: // GC Ep1&2 EU 60Hz
return Client::Flag::NO_MESSAGE_BOX_CLOSE_CONFIRMATION_AFTER_LOBBY_JOIN; return Client::Flag::NO_D6_AFTER_LOBBY;
case 0x35: // GC Ep1&2 JP v1.04 (Plus) case 0x35: // GC Ep1&2 JP v1.04 (Plus)
return Client::Flag::NO_MESSAGE_BOX_CLOSE_CONFIRMATION_AFTER_LOBBY_JOIN | return Client::Flag::NO_D6_AFTER_LOBBY |
Client::Flag::ENCRYPTED_SEND_FUNCTION_CALL; Client::Flag::ENCRYPTED_SEND_FUNCTION_CALL;
case 0x36: // GC Ep1&2 US v1.02 (Plus) case 0x36: // GC Ep1&2 US v1.02 (Plus)
case 0x39: // GC Ep1&2 JP v1.05 (Plus) case 0x39: // GC Ep1&2 JP v1.05 (Plus)
return Client::Flag::NO_MESSAGE_BOX_CLOSE_CONFIRMATION_AFTER_LOBBY_JOIN | return Client::Flag::NO_D6_AFTER_LOBBY |
Client::Flag::DOES_NOT_SUPPORT_SEND_FUNCTION_CALL; Client::Flag::NO_SEND_FUNCTION_CALL;
case 0x40: // GC Ep3 trial case 0x40: // GC Ep3 trial
return Client::Flag::NO_MESSAGE_BOX_CLOSE_CONFIRMATION_AFTER_LOBBY_JOIN | return Client::Flag::NO_D6_AFTER_LOBBY |
Client::Flag::EPISODE_3; Client::Flag::IS_EPISODE_3;
case 0x42: // GC Ep3 JP case 0x42: // GC Ep3 JP
return Client::Flag::NO_MESSAGE_BOX_CLOSE_CONFIRMATION_AFTER_LOBBY_JOIN | return Client::Flag::NO_D6_AFTER_LOBBY |
Client::Flag::EPISODE_3 | Client::Flag::IS_EPISODE_3 |
Client::Flag::ENCRYPTED_SEND_FUNCTION_CALL; Client::Flag::ENCRYPTED_SEND_FUNCTION_CALL;
case 0x41: // GC Ep3 US case 0x41: // GC Ep3 US
case 0x43: // GC Ep3 EU case 0x43: // GC Ep3 EU
return Client::Flag::NO_MESSAGE_BOX_CLOSE_CONFIRMATION_AFTER_LOBBY_JOIN | return Client::Flag::NO_D6_AFTER_LOBBY |
Client::Flag::EPISODE_3 | Client::Flag::IS_EPISODE_3 |
Client::Flag::DOES_NOT_SUPPORT_SEND_FUNCTION_CALL; Client::Flag::NO_SEND_FUNCTION_CALL;
} }
throw runtime_error("unknown sub_version"); throw runtime_error("unknown sub_version");
} }