add cross-play options

This commit is contained in:
Martin Michelsen
2023-10-07 20:39:30 -07:00
parent 07b1e9cde3
commit abd87054ac
12 changed files with 143 additions and 85 deletions
+5 -7
View File
@@ -359,11 +359,9 @@ static void server_command_exit(shared_ptr<Client> c, const std::u16string&) {
send_message_box(c, u"");
}
const auto& port_name = version_to_login_port_name.at(
static_cast<size_t>(c->version()));
const auto& port_name = version_to_login_port_name.at(static_cast<size_t>(c->version()));
auto s = c->require_server_state();
send_reconnect(c, s->connect_address_for_client(c),
s->name_to_port_config.at(port_name)->port);
send_reconnect(c, s->connect_address_for_client(c), s->name_to_port_config.at(port_name)->port);
}
}
@@ -597,7 +595,7 @@ static void server_command_playrec(shared_ptr<Client> c, const std::u16string& a
string file_path = file_path_for_recording(args, c->license->serial_number);
auto s = c->require_server_state();
uint32_t flags = Lobby::Flag::NON_V1_ONLY | Lobby::Flag::IS_SPECTATOR_TEAM;
uint32_t flags = Lobby::Flag::IS_SPECTATOR_TEAM;
string filename = encode_sjis(args);
if (filename[0] == '!') {
flags |= Lobby::Flag::START_BATTLE_PLAYER_IMMEDIATELY;
@@ -614,8 +612,8 @@ static void server_command_playrec(shared_ptr<Client> c, const std::u16string& a
shared_ptr<Episode3::BattleRecord> record(new Episode3::BattleRecord(data));
shared_ptr<Episode3::BattleRecordPlayer> battle_player(
new Episode3::BattleRecordPlayer(record, s->game_server->get_base()));
auto game = create_game_generic(s, c, args.c_str(), u"", Episode::EP3, GameMode::NORMAL,
0, flags, nullptr, battle_player);
auto game = create_game_generic(
s, c, args, u"", Episode::EP3, GameMode::NORMAL, 0, flags, false, nullptr, battle_player);
if (game) {
s->change_client_lobby(c, game);
c->flags |= Client::Flag::LOADING;
+2 -1
View File
@@ -17,7 +17,8 @@ Lobby::Lobby(shared_ptr<ServerState> s, uint32_t id)
min_level(0),
max_level(0xFFFFFFFF),
next_game_item_id(0x00810000),
version(GameVersion::GC),
base_version(GameVersion::GC),
allowed_versions(0xFFFF),
section_id(0),
episode(Episode::NONE),
mode(GameMode::NORMAL),
+14 -3
View File
@@ -27,8 +27,7 @@ struct ServerState;
struct Lobby : public std::enable_shared_from_this<Lobby> {
enum Flag {
GAME = 0x00000001,
NON_V1_ONLY = 0x00000002, // DC NTE and DCv1 not allowed
PERSISTENT = 0x00000004,
PERSISTENT = 0x00000002,
// Flags used only for games
CHEATS_ENABLED = 0x00000100,
@@ -45,6 +44,7 @@ struct Lobby : public std::enable_shared_from_this<Lobby> {
// Flags used only for lobbies
PUBLIC = 0x01000000,
DEFAULT = 0x02000000,
V2_AND_LATER = 0x04000000, // Lobby does not appear on v1
};
std::weak_ptr<ServerState> server_state;
@@ -69,7 +69,11 @@ struct Lobby : public std::enable_shared_from_this<Lobby> {
parray<le_uint32_t, 0x20> variations;
// Game config
GameVersion version;
GameVersion base_version;
// Bits in allowed_versions specify who is allowed to join this game. The
// bits are indexed as (1 << version), where version is a value from the
// QuestScriptVersion enum.
uint16_t allowed_versions;
uint8_t section_id;
Episode episode;
GameMode mode;
@@ -127,6 +131,13 @@ struct Lobby : public std::enable_shared_from_this<Lobby> {
return this->episode == Episode::EP3;
}
inline bool version_is_allowed(QuestScriptVersion v) const {
return this->allowed_versions & (1 << static_cast<size_t>(v));
}
inline void allow_version(QuestScriptVersion v) {
this->allowed_versions |= (1 << static_cast<size_t>(v));
}
void reassign_leader_on_client_departure(size_t leaving_client_id);
size_t count_clients() const;
bool any_client_loading() const;
+1 -1
View File
@@ -1895,7 +1895,7 @@ int main(int argc, char** argv) {
shared_ptr<DNSServer> dns_server;
if (state->dns_server_port && (behavior != Behavior::REPLAY_LOG)) {
config_log.info("Starting DNS server");
config_log.info("Starting DNS server on port %hu", state->dns_server_port);
dns_server.reset(new DNSServer(base, state->local_address,
state->external_address));
dns_server->listen("", state->dns_server_port);
+3
View File
@@ -27,6 +27,9 @@ void PlayerDispDataDCPCV3::enforce_v2_limits() {
this->visual.char_class = 5; // HUcaseal -> RAcaseal
}
// V1/V2 has fewer costumes, so substitute them here too
this->visual.costume %= 9;
// If the player is somehow still not a valid class, make them appear as the
// "ninja" NPC
if (this->visual.char_class > 8) {
+64 -29
View File
@@ -185,7 +185,7 @@ static void send_main_menu(shared_ptr<Client> c) {
const auto& l = it.second;
if (l->is_game()) {
num_games++;
if (l->version == c->version() &&
if (l->version_is_allowed(c->quest_version()) &&
(!l->is_ep3() == !(c->flags & Client::Flag::IS_EPISODE_3))) {
num_compatible_games++;
}
@@ -1119,11 +1119,8 @@ static bool start_ep3_battle_table_game_if_ready(shared_ptr<Lobby> l, int16_t ta
auto c = game_clients.begin()->second;
auto s = c->require_server_state();
uint32_t flags = Lobby::Flag::NON_V1_ONLY;
u16string name = tourn ? decode_sjis(tourn->get_name()) : u"<BattleTable>";
auto game = create_game_generic(
s, c, name, u"", Episode::EP3,
GameMode::NORMAL, 0, flags);
auto game = create_game_generic(s, c, name, u"", Episode::EP3);
if (!game) {
return false;
}
@@ -1914,10 +1911,9 @@ static void on_10(shared_ptr<Client> c, uint16_t, uint32_t, const string& data)
send_lobby_message_box(c, u"$C6You cannot join this\ngame because it is\nfull.");
break;
}
if ((game->version != c->version()) ||
if (!game->version_is_allowed(c->quest_version()) ||
(!game->is_ep3() != !(c->flags & Client::Flag::IS_EPISODE_3)) ||
(!(game->flags & Lobby::Flag::IS_EP3_TRIAL) != !(c->flags & Client::Flag::IS_EP3_TRIAL_EDITION)) ||
((game->flags & Lobby::Flag::NON_V1_ONLY) && (c->flags & Client::Flag::IS_DC_V1))) {
(!(game->flags & Lobby::Flag::IS_EP3_TRIAL) != !(c->flags & Client::Flag::IS_EP3_TRIAL_EDITION))) {
send_lobby_message_box(c, u"$C6You cannot join this\ngame because it is\nfor a different\nversion of PSO.");
break;
}
@@ -2375,7 +2371,7 @@ static void on_AC_V3_BB(shared_ptr<Client> c, uint16_t, uint32_t, const string&
if (c->flags & Client::Flag::LOADING_RUNNING_QUEST) {
c->flags &= ~Client::Flag::LOADING_RUNNING_QUEST;
if (l->version != GameVersion::BB) {
if (l->base_version != GameVersion::BB) {
throw logic_error("joinable quest started on non-BB version");
}
@@ -2395,7 +2391,7 @@ static void on_AC_V3_BB(shared_ptr<Client> c, uint16_t, uint32_t, const string&
}
if (send_quest_barrier_if_all_clients_ready(l) &&
(l->version == GameVersion::BB) &&
(l->base_version == GameVersion::BB) &&
l->map &&
l->quest) {
auto dat_contents = prs_decompress(*l->quest->dat_contents());
@@ -3203,6 +3199,7 @@ shared_ptr<Lobby> create_game_generic(
GameMode mode,
uint8_t difficulty,
uint32_t flags,
bool allow_v1,
shared_ptr<Lobby> watched_lobby,
shared_ptr<Episode3::BattleRecordPlayer> battle_player) {
@@ -3276,7 +3273,54 @@ shared_ptr<Lobby> create_game_generic(
(is_ep3_trial ? Lobby::Flag::IS_EP3_TRIAL : 0) |
((s->cheat_mode_behavior == ServerState::CheatModeBehavior::ON_BY_DEFAULT) ? Lobby::Flag::CHEATS_ENABLED : 0);
game->password = password;
game->version = c->version();
game->allowed_versions = 0;
switch (c->quest_version()) {
case QuestScriptVersion::DC_NTE:
game->allow_version(QuestScriptVersion::DC_NTE);
break;
case QuestScriptVersion::DC_V1:
game->allow_version(QuestScriptVersion::DC_V1);
game->allow_version(QuestScriptVersion::DC_V2);
if (s->allow_dc_pc_games) {
game->allow_version(QuestScriptVersion::PC_V2);
}
break;
case QuestScriptVersion::DC_V2:
case QuestScriptVersion::PC_V2:
if (allow_v1 && (difficulty <= 2)) {
game->allow_version(QuestScriptVersion::DC_V1);
}
game->allow_version(QuestScriptVersion::DC_V2);
if (s->allow_dc_pc_games) {
game->allow_version(QuestScriptVersion::PC_V2);
}
break;
case QuestScriptVersion::GC_NTE:
game->allow_version(QuestScriptVersion::GC_NTE);
break;
case QuestScriptVersion::GC_V3:
game->allow_version(QuestScriptVersion::GC_V3);
if (s->allow_gc_xb_games) {
game->allow_version(QuestScriptVersion::XB_V3);
}
break;
case QuestScriptVersion::XB_V3:
game->allow_version(QuestScriptVersion::XB_V3);
if (s->allow_gc_xb_games) {
game->allow_version(QuestScriptVersion::GC_V3);
}
break;
case QuestScriptVersion::GC_EP3:
game->allow_version(QuestScriptVersion::GC_EP3);
break;
case QuestScriptVersion::BB_V4:
game->allow_version(QuestScriptVersion::BB_V4);
break;
default:
throw logic_error("invalid quest script version");
}
game->section_id = c->options.override_section_id >= 0
? c->options.override_section_id
: c->game_data.player()->disp.visual.section_id;
@@ -3291,7 +3335,7 @@ shared_ptr<Lobby> create_game_generic(
game->battle_player = battle_player;
battle_player->set_lobby(game);
}
if (game->version == GameVersion::BB) {
if (game->base_version == GameVersion::BB) {
// TODO: Use appropriate restrictions here if in battle mode
game->item_creator.reset(new ItemCreator(
s->common_item_set,
@@ -3326,7 +3370,7 @@ shared_ptr<Lobby> create_game_generic(
generate_variations(game->variations, game->random_crypt, game->episode, is_solo);
}
if (game->version == GameVersion::BB) {
if (game->base_version == GameVersion::BB) {
for (size_t x = 0; x < 4; x++) {
game->next_item_id[x] = (0x00200000 * x) + 0x00010000;
}
@@ -3382,15 +3426,13 @@ static void on_C1_PC(shared_ptr<Client> c, uint16_t, uint32_t, const string& dat
const auto& cmd = check_size_t<C_CreateGame_PC_C1>(data);
auto s = c->require_server_state();
uint32_t flags = Lobby::Flag::NON_V1_ONLY;
GameMode mode = GameMode::NORMAL;
if (cmd.battle_mode) {
mode = GameMode::BATTLE;
} else if (cmd.challenge_mode) {
mode = GameMode::CHALLENGE;
}
auto game = create_game_generic(
s, c, cmd.name, cmd.password, Episode::EP1, mode, cmd.difficulty, flags);
auto game = create_game_generic(s, c, cmd.name, cmd.password, Episode::EP1, mode, cmd.difficulty);
if (game) {
s->change_client_lobby(c, game);
c->flags |= Client::Flag::LOADING;
@@ -3405,8 +3447,7 @@ static void on_0C_C1_E7_EC(shared_ptr<Client> c, uint16_t command, uint32_t, con
const auto& cmd = check_size_t<C_CreateGame_DCNTE<char>>(data);
u16string name = decode_sjis(cmd.name);
u16string password = decode_sjis(cmd.password);
game = create_game_generic(
s, c, name.c_str(), password.c_str(), Episode::EP1, GameMode::NORMAL, 0, 0);
game = create_game_generic(s, c, name, password);
} else {
const auto& cmd = check_size_t<C_CreateGame_DC_V3_0C_C1_Ep3_EC>(data);
@@ -3419,16 +3460,13 @@ static void on_0C_C1_E7_EC(shared_ptr<Client> c, uint16_t command, uint32_t, con
Episode episode = Episode::NONE;
uint32_t flags = 0;
bool allow_v1 = false;
if (c->version() == GameVersion::DC) {
if (cmd.episode) {
flags |= Lobby::Flag::NON_V1_ONLY;
}
allow_v1 = (cmd.episode == 0);
episode = Episode::EP1;
} else if (client_is_ep3) {
flags |= Lobby::Flag::NON_V1_ONLY;
episode = Episode::EP3;
} else { // XB/GC non-Ep3
flags |= Lobby::Flag::NON_V1_ONLY;
episode = cmd.episode == 2 ? Episode::EP2 : Episode::EP1;
}
@@ -3464,8 +3502,7 @@ static void on_0C_C1_E7_EC(shared_ptr<Client> c, uint16_t command, uint32_t, con
flags |= Lobby::Flag::IS_SPECTATOR_TEAM;
}
game = create_game_generic(
s, c, name.c_str(), password.c_str(), episode, mode, cmd.difficulty, flags, watched_lobby);
game = create_game_generic(s, c, name, password, episode, mode, cmd.difficulty, flags, allow_v1, watched_lobby);
if (game && (game->episode == Episode::EP3)) {
game->ep3_ex_result_values = s->ep3_default_ex_values;
}
@@ -3481,7 +3518,6 @@ static void on_C1_BB(shared_ptr<Client> c, uint16_t, uint32_t, const string& dat
const auto& cmd = check_size_t<C_CreateGame_BB_C1>(data);
auto s = c->require_server_state();
uint32_t flags = Lobby::Flag::NON_V1_ONLY;
GameMode mode = GameMode::NORMAL;
if (cmd.battle_mode) {
mode = GameMode::BATTLE;
@@ -3508,8 +3544,7 @@ static void on_C1_BB(shared_ptr<Client> c, uint16_t, uint32_t, const string& dat
throw runtime_error("invalid episode number");
}
auto game = create_game_generic(
s, c, cmd.name, cmd.password, episode, mode, cmd.difficulty, flags);
auto game = create_game_generic(s, c, cmd.name, cmd.password, episode, mode, cmd.difficulty);
if (game) {
s->change_client_lobby(c, game);
c->flags |= Client::Flag::LOADING;
@@ -3539,7 +3574,7 @@ static void on_6F(shared_ptr<Client> c, uint16_t, uint32_t, const string& data)
c->flags &= (~Client::Flag::LOADING);
send_resume_game(l, c);
if (l->version == GameVersion::BB) {
if (l->base_version == GameVersion::BB) {
send_set_exp_multiplier(l);
}
send_server_time(c);
+6 -5
View File
@@ -8,11 +8,12 @@ std::shared_ptr<Lobby> create_game_generic(
std::shared_ptr<ServerState> s,
std::shared_ptr<Client> c,
const std::u16string& name,
const std::u16string& password,
Episode episode,
GameMode mode,
uint8_t difficulty,
uint32_t flags,
const std::u16string& password = u"",
Episode episode = Episode::EP1,
GameMode mode = GameMode::NORMAL,
uint8_t difficulty = 0,
uint32_t flags = 0,
bool allow_v1 = false,
std::shared_ptr<Lobby> watched_lobby = nullptr,
std::shared_ptr<Episode3::BattleRecordPlayer> battle_player = nullptr);
+23 -23
View File
@@ -697,7 +697,7 @@ static void on_drop_partial_stack_t(shared_ptr<Client> c, uint8_t command, uint8
if (!l->is_game()) {
return;
}
if (l->version == GameVersion::BB) {
if (l->base_version == GameVersion::BB) {
return;
}
@@ -738,7 +738,7 @@ static void on_drop_partial_stack(shared_ptr<Client> c, uint8_t command, uint8_t
static void on_drop_partial_stack_bb(shared_ptr<Client> c, uint8_t command, uint8_t flag, const void* data, size_t size) {
auto l = c->require_lobby();
if (l->version == GameVersion::BB) {
if (l->base_version == GameVersion::BB) {
const auto& cmd = check_size_t<G_SplitStackedItem_BB_6xC3>(data, size);
if (!l->is_game() || (cmd.header.client_id != c->lobby_client_id)) {
@@ -791,7 +791,7 @@ static void on_buy_shop_item(shared_ptr<Client> c, uint8_t command, uint8_t flag
if (!l->is_game() || (cmd.header.client_id != c->lobby_client_id)) {
return;
}
if (l->version == GameVersion::BB) {
if (l->base_version == GameVersion::BB) {
return;
}
@@ -828,7 +828,7 @@ static void on_box_or_enemy_item_drop_t(shared_ptr<Client> c, uint8_t command, u
if (!l->is_game() || (c->lobby_client_id != l->leader_id)) {
return;
}
if (l->version == GameVersion::BB) {
if (l->base_version == GameVersion::BB) {
return;
}
@@ -870,7 +870,7 @@ static void on_pick_up_item(shared_ptr<Client> c, uint8_t command, uint8_t flag,
if (!l->is_game()) {
return;
}
if (l->version == GameVersion::BB) {
if (l->base_version == GameVersion::BB) {
// BB clients should never send this; only the server should send this
return;
}
@@ -900,7 +900,7 @@ static void on_pick_up_item(shared_ptr<Client> c, uint8_t command, uint8_t flag,
static void on_pick_up_item_request(shared_ptr<Client> c, uint8_t command, uint8_t flag, const void* data, size_t size) {
// This is handled by the server on BB, and by the leader on other versions
auto l = c->require_lobby();
if (l->version == GameVersion::BB) {
if (l->base_version == GameVersion::BB) {
auto& cmd = check_size_t<G_PickUpItemRequest_6x5A>(data, size);
if (!l->is_game() || (cmd.header.client_id != c->lobby_client_id)) {
@@ -946,7 +946,7 @@ static void on_equip_unequip_item(shared_ptr<Client> c, uint8_t command, uint8_t
} else { // Unequip
c->game_data.player()->inventory.items[index].flags &= 0xFFFFFFF7;
}
} else if (l->version == GameVersion::BB) {
} else if (l->base_version == GameVersion::BB) {
throw logic_error("item tracking not enabled in BB game");
}
@@ -1021,7 +1021,7 @@ static void on_feed_mag(
// a 6x29 immediately after to destroy the fed item. So on BB, we should
// remove the fed item here, but on other versions, we allow the following
// 6x29 command to do that.
if (l->version == GameVersion::BB) {
if (l->base_version == GameVersion::BB) {
c->game_data.player()->remove_item(cmd.fed_item_id, 1, false);
}
@@ -1049,7 +1049,7 @@ static void on_open_shop_bb_or_ep3_battle_subs(shared_ptr<Client> c, uint8_t com
} else {
const auto& cmd = check_size_t<G_ShopContentsRequest_BB_6xB5>(data, size);
if ((l->version == GameVersion::BB) && l->is_game()) {
if ((l->base_version == GameVersion::BB) && l->is_game()) {
if (!l->item_creator) {
throw logic_error("item creator missing from BB game");
}
@@ -1081,16 +1081,16 @@ static void on_open_shop_bb_or_ep3_battle_subs(shared_ptr<Client> c, uint8_t com
static void on_open_bank_bb_or_card_trade_counter_ep3(shared_ptr<Client> c, uint8_t command, uint8_t flag, const void* data, size_t size) {
auto l = c->require_lobby();
if ((l->version == GameVersion::BB) && l->is_game()) {
if ((l->base_version == GameVersion::BB) && l->is_game()) {
send_bank(c);
} else if ((l->version == GameVersion::GC) && l->is_ep3()) {
} else if ((l->base_version == GameVersion::GC) && l->is_ep3()) {
forward_subcommand(c, command, flag, data, size);
}
}
static void on_ep3_private_word_select_bb_bank_action(shared_ptr<Client> c, uint8_t command, uint8_t flag, const void* data, size_t size) {
auto l = c->require_lobby();
if (l->version == GameVersion::BB) {
if (l->base_version == GameVersion::BB) {
const auto& cmd = check_size_t<G_BankAction_BB_6xBD>(data, size);
if (!l->is_game()) {
@@ -1141,7 +1141,7 @@ static void on_ep3_private_word_select_bb_bank_action(shared_ptr<Client> c, uint
static void on_sort_inventory_bb(shared_ptr<Client> c, uint8_t, uint8_t, const void* data, size_t size) {
auto l = c->require_lobby();
if (l->version == GameVersion::BB) {
if (l->base_version == GameVersion::BB) {
const auto& cmd = check_size_t<G_SortInventory_BB_6xC4>(data, size);
if (!(l->flags & Lobby::Flag::ITEM_TRACKING_ENABLED)) {
@@ -1178,7 +1178,7 @@ static void on_entity_drop_item_request(shared_ptr<Client> c, uint8_t command, u
// If the game is not BB, forward the request to the leader (if drops are
// enabled, or just ignore it) instead of generating the item drop command
if (l->version != GameVersion::BB) {
if (l->base_version != GameVersion::BB) {
if (l->flags & Lobby::Flag::DROPS_ENABLED) {
forward_subcommand(c, command, flag, data, size);
}
@@ -1304,7 +1304,7 @@ static void on_set_quest_flag(shared_ptr<Client> c, uint8_t command, uint8_t fla
static void on_enemy_hit(shared_ptr<Client> c, uint8_t command, uint8_t flag, const void* data, size_t size) {
auto l = c->require_lobby();
if (l->version == GameVersion::BB) {
if (l->base_version == GameVersion::BB) {
const auto& cmd = check_size_t<G_EnemyHitByPlayer_6x0A>(data, size);
if (!l->is_game()) {
@@ -1333,7 +1333,7 @@ static void on_enemy_hit(shared_ptr<Client> c, uint8_t command, uint8_t flag, co
static void on_charge_attack_bb(shared_ptr<Client> c, uint8_t command, uint8_t flag, const void* data, size_t size) {
auto l = c->require_lobby();
if (l->version != GameVersion::BB) {
if (l->base_version != GameVersion::BB) {
throw runtime_error("BB-only command sent in non-BB game");
}
@@ -1375,7 +1375,7 @@ static void on_steal_exp_bb(shared_ptr<Client> c, uint8_t, uint8_t, const void*
auto s = c->require_server_state();
auto l = c->require_lobby();
if (l->version != GameVersion::BB) {
if (l->base_version != GameVersion::BB) {
throw runtime_error("BB-only command sent in non-BB game");
}
if (!l->map) {
@@ -1413,7 +1413,7 @@ static void on_enemy_killed_bb(shared_ptr<Client> c, uint8_t command, uint8_t fl
auto s = c->require_server_state();
auto l = c->require_lobby();
if (l->version != GameVersion::BB) {
if (l->base_version != GameVersion::BB) {
throw runtime_error("BB-only command sent in non-BB game");
}
@@ -1574,7 +1574,7 @@ static void on_destroy_ground_item(shared_ptr<Client> c, uint8_t command, uint8_
static void on_identify_item_bb(shared_ptr<Client> c, uint8_t command, uint8_t flag, const void* data, size_t size) {
auto l = c->require_lobby();
if (l->version == GameVersion::BB) {
if (l->base_version == GameVersion::BB) {
const auto& cmd = check_size_t<G_IdentifyItemRequest_6xB8>(data, size);
if (!l->is_game()) {
return;
@@ -1605,7 +1605,7 @@ static void on_identify_item_bb(shared_ptr<Client> c, uint8_t command, uint8_t f
static void on_accept_identify_item_bb(shared_ptr<Client> c, uint8_t command, uint8_t flag, const void* data, size_t size) {
auto l = c->require_lobby();
if (l->version == GameVersion::BB) {
if (l->base_version == GameVersion::BB) {
const auto& cmd = check_size_t<G_AcceptItemIdentification_BB_6xBA>(data, size);
if (!(l->flags & Lobby::Flag::ITEM_TRACKING_ENABLED)) {
@@ -1630,7 +1630,7 @@ static void on_accept_identify_item_bb(shared_ptr<Client> c, uint8_t command, ui
static void on_sell_item_at_shop_bb(shared_ptr<Client> c, uint8_t command, uint8_t flag, const void* data, size_t size) {
auto s = c->require_server_state();
auto l = c->require_lobby();
if (l->version == GameVersion::BB) {
if (l->base_version == GameVersion::BB) {
const auto& cmd = check_size_t<G_SellItemAtShop_BB_6xC0>(data, size);
if (!(l->flags & Lobby::Flag::ITEM_TRACKING_ENABLED)) {
@@ -1658,7 +1658,7 @@ static void on_sell_item_at_shop_bb(shared_ptr<Client> c, uint8_t command, uint8
static void on_buy_shop_item_bb(shared_ptr<Client> c, uint8_t, uint8_t, const void* data, size_t size) {
auto l = c->require_lobby();
if (l->version == GameVersion::BB) {
if (l->base_version == GameVersion::BB) {
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");
@@ -1695,7 +1695,7 @@ static void on_buy_shop_item_bb(shared_ptr<Client> c, uint8_t, uint8_t, const vo
static void on_medical_center_bb(shared_ptr<Client> c, uint8_t, uint8_t, const void*, size_t) {
auto l = c->require_lobby();
if (l->is_game() && (l->version == GameVersion::BB)) {
if (l->is_game() && (l->base_version == GameVersion::BB)) {
c->game_data.player()->remove_meseta(10, false);
}
}
+5 -13
View File
@@ -1188,15 +1188,7 @@ void send_game_menu_t(
if (!l->is_game()) {
continue;
}
if (l->version != c->version()) {
continue;
}
bool l_is_ep3 = l->is_ep3();
bool c_is_ep3 = !!(c->flags & Client::Flag::IS_EPISODE_3);
if (l_is_ep3 != c_is_ep3) {
continue;
}
if ((c->flags & Client::Flag::IS_DC_V1) && (l->flags & Lobby::Flag::NON_V1_ONLY)) {
if (!l->version_is_allowed(c->quest_version())) {
continue;
}
bool l_is_spectator_team = !!(l->flags & Lobby::Flag::IS_SPECTATOR_TEAM);
@@ -1228,10 +1220,10 @@ void send_game_menu_t(
auto& e = entries.emplace_back();
e.menu_id = MenuID::GAME;
e.game_id = l->lobby_id;
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();
if (c->version() == GameVersion::DC) {
e.episode = (l->flags & Lobby::Flag::NON_V1_ONLY) ? 1 : 0;
e.episode = l->version_is_allowed(QuestScriptVersion::DC_V1) ? 1 : 0;
} else {
e.episode = ((c->version() == GameVersion::BB) ? (l->max_clients << 4) : 0) | episode_num;
}
@@ -1367,7 +1359,7 @@ void send_lobby_list(shared_ptr<Client> c) {
if (!(l->flags & Lobby::Flag::DEFAULT)) {
continue;
}
if ((l->flags & Lobby::Flag::NON_V1_ONLY) && (c->flags & Client::Flag::IS_DC_V1)) {
if ((l->flags & Lobby::Flag::V2_AND_LATER) && (c->flags & Client::Flag::IS_DC_V1)) {
continue;
}
if (l->is_ep3() && !(c->flags & Client::Flag::IS_EPISODE_3)) {
@@ -2182,7 +2174,7 @@ void send_give_experience(shared_ptr<Client> c, uint32_t amount) {
}
void send_set_exp_multiplier(std::shared_ptr<Lobby> l) {
if (l->version != GameVersion::BB) {
if (l->base_version != GameVersion::BB) {
throw logic_error("6xDD can only be sent to BB clients");
}
if (!l->is_game()) {
+8 -3
View File
@@ -24,6 +24,8 @@ ServerState::ServerState(const char* config_filename, bool is_replay)
ip_stack_debug(false),
allow_unregistered_users(false),
allow_saving(true),
allow_dc_pc_games(false),
allow_gc_xb_games(true),
item_tracking_enabled(true),
drops_enabled(true),
ep3_send_function_call_enabled(false),
@@ -53,7 +55,7 @@ void ServerState::init() {
for (size_t x = 0; x < 20; x++) {
auto lobby_name = decode_sjis(string_printf("LOBBY%zu", x + 1));
bool is_non_v1_only = (x > 9);
bool v2_and_later_only = (x > 9);
bool is_ep3_only = (x > 14);
shared_ptr<Lobby> l = this->create_lobby();
@@ -61,7 +63,7 @@ void ServerState::init() {
Lobby::Flag::PUBLIC |
Lobby::Flag::DEFAULT |
Lobby::Flag::PERSISTENT |
(is_non_v1_only ? Lobby::Flag::NON_V1_ONLY : 0);
(v2_and_later_only ? Lobby::Flag::V2_AND_LATER : 0);
l->block = x + 1;
l->name = lobby_name;
l->max_clients = 12;
@@ -69,7 +71,7 @@ void ServerState::init() {
l->episode = Episode::EP3;
}
if (!is_non_v1_only) {
if (!v2_and_later_only) {
this->public_lobby_search_order_v1.emplace_back(l);
}
if (!is_ep3_only) {
@@ -655,6 +657,9 @@ void ServerState::parse_config(const JSON& json, bool is_reload) {
} catch (const out_of_range&) {
}
this->allow_dc_pc_games = json.get_bool("AllowDCPCGames", this->allow_dc_pc_games);
this->allow_gc_xb_games = json.get_bool("AllowGCXBGames", this->allow_gc_xb_games);
try {
auto v = json.at("LobbyEvent");
uint8_t event = v.is_int() ? v.as_int() : event_for_name(v.as_string());
+2
View File
@@ -57,6 +57,8 @@ struct ServerState : public std::enable_shared_from_this<ServerState> {
bool ip_stack_debug;
bool allow_unregistered_users;
bool allow_saving;
bool allow_dc_pc_games;
bool allow_gc_xb_games;
bool item_tracking_enabled;
bool drops_enabled;
bool ep3_send_function_call_enabled;