prevent players from joining game when quest menu is open
This commit is contained in:
@@ -2105,14 +2105,11 @@ struct S_QuestMenuEntry_BB_A2_A4 {
|
||||
// A9 (C->S): Quest menu closed (canceled)
|
||||
// Internal name: SndQuestEnd
|
||||
// No arguments
|
||||
// This command is sent when the in-game quest menu (A2) is closed. When the
|
||||
// This command is sent when the in-game quest menu (A2) is closed. This is used
|
||||
// by the server to unlock the game if the players don't select a quest, since
|
||||
// players are forbidden from joining while the quest menu is open. When the
|
||||
// download quest menu is closed, either by downloading a quest or canceling,
|
||||
// the client sends A0 instead. The existence of the A0 response on the download
|
||||
// case makes sense, because the client may not be in a lobby and the server may
|
||||
// need to send another menu or redirect the client. But for the online quest
|
||||
// menu, the client is already in a game and can move normally after canceling
|
||||
// the quest menu, so it's not obvious why A9 is needed at all. newserv (and
|
||||
// probably all other private servers) ignores it.
|
||||
// the client sends A0 instead.
|
||||
// Curiously, PSO GC sends uninitialized data in header.flag.
|
||||
|
||||
// AA (C->S): Send quest statistic (V3/BB)
|
||||
|
||||
@@ -567,6 +567,7 @@ JSON HTTPServer::generate_lobby_json_st(shared_ptr<const Lobby> l, shared_ptr<co
|
||||
ret.emplace("Name", l->name);
|
||||
ret.emplace("RandomSeed", l->random_seed);
|
||||
if (l->episode != Episode::EP3) {
|
||||
ret.emplace("QuestSelectionInProgress", l->check_flag(Lobby::Flag::QUEST_SELECTION_IN_PROGRESS));
|
||||
ret.emplace("QuestInProgress", l->check_flag(Lobby::Flag::QUEST_IN_PROGRESS));
|
||||
ret.emplace("JoinableQuestInProgress", l->check_flag(Lobby::Flag::JOINABLE_QUEST_IN_PROGRESS));
|
||||
auto variations_json = JSON::list();
|
||||
@@ -846,6 +847,7 @@ JSON HTTPServer::generate_summary_json() const {
|
||||
game_json.emplace("MapNumber", (ep3s && ep3s->last_chosen_map) ? ep3s->last_chosen_map->map_number : JSON(nullptr));
|
||||
game_json.emplace("Rules", (ep3s && ep3s->map_and_rules) ? ep3s->map_and_rules->rules.json() : nullptr);
|
||||
} else {
|
||||
game_json.emplace("QuestSelectionInProgress", l->check_flag(Lobby::Flag::QUEST_SELECTION_IN_PROGRESS));
|
||||
game_json.emplace("QuestInProgress", l->check_flag(Lobby::Flag::QUEST_IN_PROGRESS));
|
||||
game_json.emplace("JoinableQuestInProgress", l->check_flag(Lobby::Flag::JOINABLE_QUEST_IN_PROGRESS));
|
||||
game_json.emplace("SectionID", name_for_section_id(l->effective_section_id()));
|
||||
|
||||
+6
-1
@@ -798,6 +798,9 @@ Lobby::JoinError Lobby::join_error_for_client(std::shared_ptr<Client> c, const s
|
||||
return JoinError::VERSION_CONFLICT;
|
||||
}
|
||||
if (this->is_game()) {
|
||||
if (this->check_flag(Flag::QUEST_SELECTION_IN_PROGRESS)) {
|
||||
return JoinError::QUEST_SELECTION_IN_PROGRESS;
|
||||
}
|
||||
if (this->check_flag(Flag::QUEST_IN_PROGRESS)) {
|
||||
return JoinError::QUEST_IN_PROGRESS;
|
||||
}
|
||||
@@ -973,7 +976,9 @@ bool Lobby::compare_shared(const shared_ptr<const Lobby>& a, const shared_ptr<co
|
||||
// 5. Difficulty: Normal < Hard < Very Hard < Ultimate
|
||||
// 6. Game name
|
||||
static auto get_priority = +[](const shared_ptr<const Lobby>& l) -> size_t {
|
||||
if (l->check_flag(Lobby::Flag::QUEST_IN_PROGRESS) || l->check_flag(Lobby::Flag::BATTLE_IN_PROGRESS)) {
|
||||
if (l->check_flag(Lobby::Flag::QUEST_SELECTION_IN_PROGRESS) ||
|
||||
l->check_flag(Lobby::Flag::QUEST_IN_PROGRESS) ||
|
||||
l->check_flag(Lobby::Flag::BATTLE_IN_PROGRESS)) {
|
||||
return 4;
|
||||
}
|
||||
size_t num_clients = l->count_clients();
|
||||
|
||||
+11
-9
@@ -67,15 +67,16 @@ struct Lobby : public std::enable_shared_from_this<Lobby> {
|
||||
PERSISTENT = 0x00000002,
|
||||
// Flags used only for games
|
||||
CHEATS_ENABLED = 0x00000100,
|
||||
QUEST_IN_PROGRESS = 0x00000200,
|
||||
BATTLE_IN_PROGRESS = 0x00000400,
|
||||
JOINABLE_QUEST_IN_PROGRESS = 0x00000800,
|
||||
IS_CLIENT_CUSTOMIZATION = 0x00001000,
|
||||
IS_SPECTATOR_TEAM = 0x00002000, // episode must be EP3 also
|
||||
SPECTATORS_FORBIDDEN = 0x00004000,
|
||||
START_BATTLE_PLAYER_IMMEDIATELY = 0x00008000,
|
||||
CANNOT_CHANGE_CHEAT_MODE = 0x00010000,
|
||||
USE_CREATOR_SECTION_ID = 0x00020000,
|
||||
QUEST_SELECTION_IN_PROGRESS = 0x00000200,
|
||||
QUEST_IN_PROGRESS = 0x00000400,
|
||||
BATTLE_IN_PROGRESS = 0x00000800,
|
||||
JOINABLE_QUEST_IN_PROGRESS = 0x00001000,
|
||||
IS_CLIENT_CUSTOMIZATION = 0x00002000,
|
||||
IS_SPECTATOR_TEAM = 0x00004000, // .episode must be EP3 also
|
||||
SPECTATORS_FORBIDDEN = 0x00008000,
|
||||
START_BATTLE_PLAYER_IMMEDIATELY = 0x00010000,
|
||||
CANNOT_CHANGE_CHEAT_MODE = 0x00020000,
|
||||
USE_CREATOR_SECTION_ID = 0x00040000,
|
||||
// Flags used only for lobbies
|
||||
PUBLIC = 0x01000000,
|
||||
DEFAULT = 0x02000000,
|
||||
@@ -282,6 +283,7 @@ struct Lobby : public std::enable_shared_from_this<Lobby> {
|
||||
ALLOWED = 0,
|
||||
FULL,
|
||||
VERSION_CONFLICT,
|
||||
QUEST_SELECTION_IN_PROGRESS,
|
||||
QUEST_IN_PROGRESS,
|
||||
BATTLE_IN_PROGRESS,
|
||||
LOADING,
|
||||
|
||||
+38
-24
@@ -1840,6 +1840,8 @@ static void on_09(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
|
||||
info += "$C6Quest in progress\n";
|
||||
} else if (game->check_flag(Lobby::Flag::QUEST_IN_PROGRESS)) {
|
||||
info += "$C4Quest in progress\n";
|
||||
} else if (game->check_flag(Lobby::Flag::QUEST_SELECTION_IN_PROGRESS)) {
|
||||
info += "$C4Selecting quest\n";
|
||||
}
|
||||
|
||||
switch (game->drop_mode) {
|
||||
@@ -2024,6 +2026,7 @@ void set_lobby_quest(shared_ptr<Lobby> l, shared_ptr<const Quest> q, bool substi
|
||||
} else {
|
||||
l->set_flag(Lobby::Flag::QUEST_IN_PROGRESS);
|
||||
}
|
||||
l->clear_flag(Lobby::Flag::QUEST_SELECTION_IN_PROGRESS);
|
||||
l->clear_flag(Lobby::Flag::PERSISTENT);
|
||||
|
||||
l->quest = q;
|
||||
@@ -2440,6 +2443,9 @@ static void on_10(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
|
||||
case Lobby::JoinError::VERSION_CONFLICT:
|
||||
send_lobby_message_box(c, "$C7You cannot join this\ngame because it is\nfor a different\nversion of PSO.");
|
||||
break;
|
||||
case Lobby::JoinError::QUEST_SELECTION_IN_PROGRESS:
|
||||
send_lobby_message_box(c, "$C7You cannot join this\ngame because the\nplayers are currently\nchoosing a quest.");
|
||||
break;
|
||||
case Lobby::JoinError::QUEST_IN_PROGRESS:
|
||||
send_lobby_message_box(c, "$C7You cannot join this\ngame because a\nquest is already\nin progress.");
|
||||
break;
|
||||
@@ -2843,33 +2849,41 @@ static void on_A2(shared_ptr<Client> c, uint16_t, uint32_t flag, string& data) {
|
||||
return;
|
||||
}
|
||||
|
||||
// In Episode 3, there are no quest categories, so skip directly to the quest
|
||||
// filter menu.
|
||||
if (is_ep3(c->version())) {
|
||||
send_lobby_message_box(c, "$C7Episode 3 does not\nprovide online quests\nvia this interface.");
|
||||
return;
|
||||
}
|
||||
|
||||
QuestMenuType menu_type;
|
||||
if ((c->version() == Version::BB_V4) && flag) {
|
||||
menu_type = QuestMenuType::GOVERNMENT;
|
||||
} else {
|
||||
QuestMenuType menu_type;
|
||||
if ((c->version() == Version::BB_V4) && flag) {
|
||||
menu_type = QuestMenuType::GOVERNMENT;
|
||||
} else {
|
||||
switch (l->mode) {
|
||||
case GameMode::NORMAL:
|
||||
menu_type = QuestMenuType::NORMAL;
|
||||
break;
|
||||
case GameMode::BATTLE:
|
||||
menu_type = QuestMenuType::BATTLE;
|
||||
break;
|
||||
case GameMode::CHALLENGE:
|
||||
menu_type = QuestMenuType::CHALLENGE;
|
||||
break;
|
||||
case GameMode::SOLO:
|
||||
menu_type = QuestMenuType::SOLO;
|
||||
break;
|
||||
default:
|
||||
throw logic_error("invalid game mode");
|
||||
}
|
||||
switch (l->mode) {
|
||||
case GameMode::NORMAL:
|
||||
menu_type = QuestMenuType::NORMAL;
|
||||
break;
|
||||
case GameMode::BATTLE:
|
||||
menu_type = QuestMenuType::BATTLE;
|
||||
break;
|
||||
case GameMode::CHALLENGE:
|
||||
menu_type = QuestMenuType::CHALLENGE;
|
||||
break;
|
||||
case GameMode::SOLO:
|
||||
menu_type = QuestMenuType::SOLO;
|
||||
break;
|
||||
default:
|
||||
throw logic_error("invalid game mode");
|
||||
}
|
||||
send_quest_categories_menu(c, s->quest_index(c->version()), menu_type, l->episode);
|
||||
}
|
||||
|
||||
send_quest_categories_menu(c, s->quest_index(c->version()), menu_type, l->episode);
|
||||
l->set_flag(Lobby::Flag::QUEST_SELECTION_IN_PROGRESS);
|
||||
}
|
||||
|
||||
static void on_A9(shared_ptr<Client> c, uint16_t, uint32_t, string&) {
|
||||
auto l = c->require_lobby();
|
||||
if (l->is_game() && (c->lobby_client_id == l->leader_id)) {
|
||||
l->clear_flag(Lobby::Flag::QUEST_SELECTION_IN_PROGRESS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5467,7 +5481,7 @@ static on_command_t handlers[0x100][NUM_NON_PATCH_VERSIONS] = {
|
||||
/* A6 */ {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, on_44_A6_V3_BB, on_44_A6_V3_BB, on_44_A6_V3_BB, on_44_A6_V3_BB, on_44_A6_V3_BB, nullptr},
|
||||
/* A7 */ {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, on_13_A7_V3_BB, on_13_A7_V3_BB, on_13_A7_V3_BB, on_13_A7_V3_BB, on_13_A7_V3_BB, nullptr},
|
||||
/* A8 */ {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
|
||||
/* A9 */ {on_ignored, on_ignored, on_ignored, on_ignored, on_ignored, on_ignored, on_ignored, on_ignored, on_ignored, on_ignored, on_ignored, on_ignored},
|
||||
/* A9 */ {on_A9, on_A9, on_A9, on_A9, on_A9, on_A9, on_A9, on_A9, on_A9, on_A9, on_A9, on_A9},
|
||||
/* AA */ {nullptr, nullptr, nullptr, nullptr, on_AA, on_AA, on_AA, on_AA, on_AA, on_AA, on_AA, on_AA},
|
||||
/* AB */ {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
|
||||
/* AC */ {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, on_AC_V3_BB, on_AC_V3_BB, on_AC_V3_BB, on_AC_V3_BB, on_AC_V3_BB, on_AC_V3_BB},
|
||||
|
||||
Reference in New Issue
Block a user