make $debug allow all cross-version games

This commit is contained in:
Martin Michelsen
2023-12-28 19:40:08 -08:00
parent 1058998550
commit 60f6b609da
6 changed files with 84 additions and 29 deletions
+1
View File
@@ -294,6 +294,7 @@ Some commands only work on the game server and not on the proxy server. The chat
* You'll see in-game messages from the server when you take certain actions, like killing an enemy in BB. * You'll see in-game messages from the server when you take certain actions, like killing an enemy in BB.
* You'll see the rare seed value and floor variations when you join a game. * You'll see the rare seed value and floor variations when you join a game.
* You'll be placed into the highest available slot in lobbies and games instead of the lowest, unless you're joining a BB solo-mode game. * You'll be placed into the highest available slot in lobbies and games instead of the lowest, unless you're joining a BB solo-mode game.
* You'll be able to join games with any PSO version, not only those for which crossplay is normally supported. Be prepared for client crashes and other client-side brokenness if you do this. Please do not submit any issues for broken behaviors in crossplay, unless the situation is explicitly supported (see the "Cross-version play" section above).
* The rest of the commands in this section are enabled on the game server. (They are always enabled on the proxy server.) * The rest of the commands in this section are enabled on the game server. (They are always enabled on the proxy server.)
* `$quest <number>` (game server only): Load a quest by quest number. Can be used to load battle or challenge quests with only one player present. * `$quest <number>` (game server only): Load a quest by quest number. Can be used to load battle or challenge quests with only one player present.
* `$qcall <function-id>`: Call a quest function on your client. * `$qcall <function-id>`: Call a quest function on your client.
+60 -24
View File
@@ -1831,32 +1831,68 @@ static void on_09(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
abbreviation_for_episode(game->episode), abbreviation_for_episode(game->episode),
abbreviation_for_difficulty(game->difficulty), abbreviation_for_difficulty(game->difficulty),
abbreviation_for_mode(game->mode), abbreviation_for_mode(game->mode),
name_for_section_id(game->section_id)); abbreviation_for_section_id(game->section_id));
bool cheats_enabled = game->check_flag(Lobby::Flag::CHEATS_ENABLED); if (c->config.check_flag(Client::Flag::DEBUG_ENABLED)) {
bool locked = !game->password.empty(); vector<const char*> flags_tokens;
if (cheats_enabled && locked) { string quest_name;
info += "$C4Locked$C7, $C6cheats on$C7\n"; if (game->check_flag(Lobby::Flag::CHEATS_ENABLED)) {
} else if (cheats_enabled) { flags_tokens.emplace_back("$C6C$C7");
info += "$C6Cheats on$C7\n"; }
} else if (locked) { if (game->check_flag(Lobby::Flag::PERSISTENT)) {
info += "$C4Locked$C7\n"; flags_tokens.emplace_back("$C6P$C7");
} }
if (!game->password.empty()) {
flags_tokens.emplace_back("$C4L$C7");
}
if (game->check_flag(Lobby::Flag::IS_SPECTATOR_TEAM)) {
flags_tokens.emplace_back("$C8ST$C7");
}
if (game->check_flag(Lobby::Flag::SPECTATORS_FORBIDDEN)) {
flags_tokens.emplace_back("$C8NS$C7");
}
if (game->quest) {
flags_tokens.emplace_back(game->check_flag(Lobby::Flag::JOINABLE_QUEST_IN_PROGRESS) ? "$C3JQ$C7" : "$C3Q$C7");
quest_name = remove_color(game->quest->name);
} else if (game->check_flag(Lobby::Flag::JOINABLE_QUEST_IN_PROGRESS)) {
flags_tokens.emplace_back("$C3JQ$C7");
} else if (game->check_flag(Lobby::Flag::QUEST_IN_PROGRESS)) {
flags_tokens.emplace_back("$C3Q$C7");
} else if (game->check_flag(Lobby::Flag::BATTLE_IN_PROGRESS)) {
flags_tokens.emplace_back("$C3B$C7");
}
info += ("Flags: " + join(flags_tokens, ",") + "\n");
if (!quest_name.empty()) {
info += ("Q: $C6" + quest_name + "$C7\n");
}
info += string_printf("Version: %s\n", name_for_enum(game->base_version));
if (game->quest) { } else {
info += (game->check_flag(Lobby::Flag::JOINABLE_QUEST_IN_PROGRESS)) ? "$C6Quest: " : "$C4Quest: "; bool cheats_enabled = game->check_flag(Lobby::Flag::CHEATS_ENABLED);
info += remove_color(game->quest->name); bool locked = !game->password.empty();
info += "\n"; if (cheats_enabled && locked) {
} else if (game->check_flag(Lobby::Flag::JOINABLE_QUEST_IN_PROGRESS)) { info += "$C4Locked$C7, $C6cheats on$C7\n";
info += "$C6Quest in progress\n"; } else if (cheats_enabled) {
} else if (game->check_flag(Lobby::Flag::QUEST_IN_PROGRESS)) { info += "$C6Cheats on$C7\n";
info += "$C4Quest in progress\n"; } else if (locked) {
} else if (game->check_flag(Lobby::Flag::BATTLE_IN_PROGRESS)) { info += "$C4Locked$C7\n";
info += "$C4Battle in progress\n"; }
}
if (game->check_flag(Lobby::Flag::SPECTATORS_FORBIDDEN)) { if (game->quest) {
info += "$C4View Battle forbidden\n"; info += (game->check_flag(Lobby::Flag::JOINABLE_QUEST_IN_PROGRESS)) ? "$C6Quest: " : "$C4Quest: ";
info += remove_color(game->quest->name);
info += "\n";
} else if (game->check_flag(Lobby::Flag::JOINABLE_QUEST_IN_PROGRESS)) {
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::BATTLE_IN_PROGRESS)) {
info += "$C4Battle in progress\n";
}
if (game->check_flag(Lobby::Flag::SPECTATORS_FORBIDDEN)) {
info += "$C4View Battle forbidden\n";
}
} }
strip_trailing_whitespace(info); strip_trailing_whitespace(info);
@@ -2349,7 +2385,7 @@ static void on_10(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
send_lobby_message_box(c, "$C6You cannot join this\ngame because it is\nfull."); send_lobby_message_box(c, "$C6You cannot join this\ngame because it is\nfull.");
break; break;
} }
if (!game->version_is_allowed(c->version())) { if (!game->version_is_allowed(c->version()) && !c->config.check_flag(Client::Flag::DEBUG_ENABLED)) {
send_lobby_message_box(c, "$C6You cannot join this\ngame because it is\nfor a different\nversion of PSO."); send_lobby_message_box(c, "$C6You cannot join this\ngame because it is\nfor a different\nversion of PSO.");
break; break;
} }
+4
View File
@@ -530,6 +530,7 @@ static void on_sync_joining_player_disp_and_inventory(
out_cmd.num_items = xb_cmd->num_items; out_cmd.num_items = xb_cmd->num_items;
out_cmd.items = xb_cmd->items; out_cmd.items = xb_cmd->items;
} else if (bb_cmd) { } else if (bb_cmd) {
out_cmd.base.visual.name.encode(bb_cmd->name.decode(c->language()), target->language());
out_cmd.stats = bb_cmd->stats; out_cmd.stats = bb_cmd->stats;
out_cmd.num_items = bb_cmd->num_items; out_cmd.num_items = bb_cmd->num_items;
out_cmd.items = bb_cmd->items; out_cmd.items = bb_cmd->items;
@@ -562,6 +563,7 @@ static void on_sync_joining_player_disp_and_inventory(
out_cmd.items = xb_cmd->items; out_cmd.items = xb_cmd->items;
out_cmd.floor = xb_cmd->floor; out_cmd.floor = xb_cmd->floor;
} else if (bb_cmd) { } else if (bb_cmd) {
out_cmd.base.visual.name.encode(bb_cmd->name.decode(c->language()), target->language());
out_cmd.stats = bb_cmd->stats; out_cmd.stats = bb_cmd->stats;
out_cmd.num_items = bb_cmd->num_items; out_cmd.num_items = bb_cmd->num_items;
out_cmd.items = bb_cmd->items; out_cmd.items = bb_cmd->items;
@@ -597,6 +599,7 @@ static void on_sync_joining_player_disp_and_inventory(
out_cmd.items = gc_cmd->items; out_cmd.items = gc_cmd->items;
out_cmd.floor = gc_cmd->floor; out_cmd.floor = gc_cmd->floor;
} else if (bb_cmd) { } else if (bb_cmd) {
out_cmd.base.visual.name.encode(bb_cmd->name.decode(c->language()), target->language());
out_cmd.stats = bb_cmd->stats; out_cmd.stats = bb_cmd->stats;
out_cmd.num_items = bb_cmd->num_items; out_cmd.num_items = bb_cmd->num_items;
out_cmd.items = bb_cmd->items; out_cmd.items = bb_cmd->items;
@@ -616,6 +619,7 @@ static void on_sync_joining_player_disp_and_inventory(
} else { } else {
G_SyncPlayerDispAndInventory_BB_6x70 out_cmd; G_SyncPlayerDispAndInventory_BB_6x70 out_cmd;
out_cmd.base = *base; out_cmd.base = *base;
out_cmd.base.visual.name.encode(string_printf("%10" PRIu32, c->license->serial_number), target->language());
out_cmd.name.encode(base->visual.name.decode(c->language()), target->language()); out_cmd.name.encode(base->visual.name.decode(c->language()), target->language());
if (v2_cmd) { if (v2_cmd) {
out_cmd.stats = v2_cmd->stats; out_cmd.stats = v2_cmd->stats;
+7 -5
View File
@@ -1354,9 +1354,10 @@ void send_game_menu_t(
} }
set<shared_ptr<const Lobby>, bool (*)(const shared_ptr<const Lobby>&, const shared_ptr<const Lobby>&)> games(Lobby::compare_shared); set<shared_ptr<const Lobby>, bool (*)(const shared_ptr<const Lobby>&, const shared_ptr<const Lobby>&)> games(Lobby::compare_shared);
bool client_has_debug = c->config.check_flag(Client::Flag::DEBUG_ENABLED);
for (shared_ptr<Lobby> l : s->all_lobbies()) { for (shared_ptr<Lobby> l : s->all_lobbies()) {
if (l->is_game() && if (l->is_game() &&
l->version_is_allowed(c->version()) && (client_has_debug || l->version_is_allowed(c->version())) &&
(l->check_flag(Lobby::Flag::IS_SPECTATOR_TEAM) == is_spectator_team_list) && (l->check_flag(Lobby::Flag::IS_SPECTATOR_TEAM) == is_spectator_team_list) &&
(!show_tournaments_only || l->tournament_match)) { (!show_tournaments_only || l->tournament_match)) {
games.emplace(l); games.emplace(l);
@@ -2667,14 +2668,15 @@ void send_give_experience(shared_ptr<Client> c, uint32_t amount) {
} }
void send_set_exp_multiplier(shared_ptr<Lobby> l) { void send_set_exp_multiplier(shared_ptr<Lobby> l) {
if (l->base_version != Version::BB_V4) {
throw logic_error("6xDD can only be sent to BB clients");
}
if (!l->is_game()) { if (!l->is_game()) {
throw logic_error("6xDD can only be sent in games (not in lobbies)"); throw logic_error("6xDD can only be sent in games (not in lobbies)");
} }
G_SetEXPMultiplier_BB_6xDD cmd = {{0xDD, sizeof(G_SetEXPMultiplier_BB_6xDD) / 4, (l->mode == GameMode::CHALLENGE) ? 1 : l->base_exp_multiplier}}; G_SetEXPMultiplier_BB_6xDD cmd = {{0xDD, sizeof(G_SetEXPMultiplier_BB_6xDD) / 4, (l->mode == GameMode::CHALLENGE) ? 1 : l->base_exp_multiplier}};
send_command_t(l, 0x60, 0x00, cmd); for (auto lc : l->clients) {
if (lc && (lc->version() == Version::BB_V4)) {
send_command_t(l, 0x60, 0x00, cmd);
}
}
} }
void send_rare_enemy_index_list(shared_ptr<Client> c, const vector<size_t>& indexes) { void send_rare_enemy_index_list(shared_ptr<Client> c, const vector<size_t>& indexes) {
+11
View File
@@ -109,6 +109,9 @@ static const array<const char*, 10> section_id_to_name = {
"Viridia", "Greennill", "Skyly", "Bluefull", "Purplenum", "Viridia", "Greennill", "Skyly", "Bluefull", "Purplenum",
"Pinkal", "Redria", "Oran", "Yellowboze", "Whitill"}; "Pinkal", "Redria", "Oran", "Yellowboze", "Whitill"};
static const array<const char*, 10> section_id_to_abbreviation = {
"Vir", "Grn", "Sky", "Blu", "Prp", "Pnk", "Red", "Orn", "Ylw", "Wht"};
const unordered_map<string, uint8_t> name_to_section_id({ const unordered_map<string, uint8_t> name_to_section_id({
{"viridia", 0}, {"viridia", 0},
{"greennill", 1}, {"greennill", 1},
@@ -221,6 +224,14 @@ const vector<string> npc_id_to_name({"ninja", "rico", "sonic", "knuckles", "tail
const unordered_map<string, uint8_t> name_to_npc_id = { const unordered_map<string, uint8_t> name_to_npc_id = {
{"ninja", 0}, {"rico", 1}, {"sonic", 2}, {"knuckles", 3}, {"tails", 4}, {"flowen", 5}, {"elly", 6}}; {"ninja", 0}, {"rico", 1}, {"sonic", 2}, {"knuckles", 3}, {"tails", 4}, {"flowen", 5}, {"elly", 6}};
const char* abbreviation_for_section_id(uint8_t section_id) {
if (section_id < section_id_to_abbreviation.size()) {
return section_id_to_abbreviation[section_id];
} else {
return "<Unknown>";
}
}
const char* name_for_section_id(uint8_t section_id) { const char* name_for_section_id(uint8_t section_id) {
if (section_id < section_id_to_name.size()) { if (section_id < section_id_to_name.size()) {
return section_id_to_name[section_id]; return section_id_to_name[section_id];
+1
View File
@@ -40,6 +40,7 @@ extern const std::unordered_map<std::string, uint8_t> name_to_tech_id;
const std::string& name_for_technique(uint8_t tech); const std::string& name_for_technique(uint8_t tech);
uint8_t technique_for_name(const std::string& name); uint8_t technique_for_name(const std::string& name);
const char* abbreviation_for_section_id(uint8_t section_id);
const char* name_for_section_id(uint8_t section_id); const char* name_for_section_id(uint8_t section_id);
uint8_t section_id_for_name(const std::string& name); uint8_t section_id_for_name(const std::string& name);