diff --git a/src/Client.hh b/src/Client.hh index 985b8177..b78d2106 100644 --- a/src/Client.hh +++ b/src/Client.hh @@ -199,8 +199,9 @@ public: ItemData bb_identify_result; std::array, 3> bb_shop_contents; - // Miscellaneous (used by chat commands) - uint32_t next_exp_value = 0; // next EXP value to give + // Miscellaneous (used by chat commands / quest opcodes) + uint8_t schtserv_response_register = 0; + uint32_t next_exp_value = 0; bool can_chat = true; // NOTE: If you add any new optional promises here, make sure to also add // them to cancel_pending_promises. diff --git a/src/QuestMetadata.cc b/src/QuestMetadata.cc index 9c044e8f..6ce83484 100644 --- a/src/QuestMetadata.cc +++ b/src/QuestMetadata.cc @@ -62,6 +62,10 @@ void QuestMetadata::apply_json_overrides(const phosg::JSON& json) { this->default_drop_mode = phosg::enum_for_name(json.at("DefaultDropMode").as_string()); } catch (const out_of_range&) { } + try { + this->enable_schtserv_commands = json.at("EnableSchtservCommands").as_bool(); + } catch (const out_of_range&) { + } } void QuestMetadata::assign_default_floors() { @@ -219,6 +223,10 @@ void QuestMetadata::assert_compatible(const QuestMetadata& other) const { throw runtime_error(format("quest version has different default drop mode (existing: {}, new: {})", phosg::name_for_enum(this->default_drop_mode), phosg::name_for_enum(other.default_drop_mode))); } + if (this->enable_schtserv_commands != other.enable_schtserv_commands) { + throw runtime_error(format("quest version has different value for enable_schtserv_commands (existing: {}, new: {})", + this->enable_schtserv_commands ? "true" : "false", other.enable_schtserv_commands ? "true" : "false")); + } } phosg::JSON QuestMetadata::json() const { diff --git a/src/QuestMetadata.hh b/src/QuestMetadata.hh index b4bd9abd..167c5bf7 100644 --- a/src/QuestMetadata.hh +++ b/src/QuestMetadata.hh @@ -59,6 +59,7 @@ struct QuestMetadata { bool allow_start_from_chat_command = false; int16_t lock_status_register = -1; std::unordered_map enemy_exp_overrides; + bool enable_schtserv_commands = false; // Extra header fields (only used on BB) struct CreateItemMask { diff --git a/src/ReceiveSubcommands.cc b/src/ReceiveSubcommands.cc index b4910e60..2a1c4c02 100644 --- a/src/ReceiveSubcommands.cc +++ b/src/ReceiveSubcommands.cc @@ -3228,18 +3228,29 @@ static asio::awaitable on_sync_quest_register(shared_ptr c, Subcom } } - // NOCOMMIT: Add condition here for l->quest->meta.enable_schtserv_commands - if ((cmd.register_number == 0xF1) && (cmd.value.as_int == 0x52455650)) { - // PVER => respond with specific_version in schtserv's format - G_SyncQuestRegister_6x77 ret_cmd; - ret_cmd.header.subcommand = 0x77; - ret_cmd.header.size = sizeof(ret_cmd) / 4; - ret_cmd.header.unused = 0; - ret_cmd.register_number = 0xF2; - ret_cmd.value.as_int = is_v4(c->version()) ? 0x50 : c->sub_version; - send_command_t(c, 0x60, 0x00, ret_cmd); + bool should_forward = true; + if (l->quest->meta.enable_schtserv_commands) { + // We currently only implement one Schtserv server command here. There + // are likely many more which we don't support. - } else { + if (cmd.register_number == 0xF0) { + should_forward = false; + c->schtserv_response_register = cmd.value.as_int; + + } else if ((cmd.register_number == 0xF1) && (cmd.value.as_int == 0x52455650)) { + // PVER => respond with specific_version in schtserv's format + should_forward = false; + G_SyncQuestRegister_6x77 ret_cmd; + ret_cmd.header.subcommand = 0x77; + ret_cmd.header.size = sizeof(ret_cmd) / 4; + ret_cmd.header.unused = 0; + ret_cmd.register_number = c->schtserv_response_register; + ret_cmd.value.as_int = is_v4(c->version()) ? 0x50 : c->sub_version; + send_command_t(c, 0x60, 0x00, ret_cmd); + } + } + + if (should_forward) { forward_subcommand(c, msg); } } diff --git a/tests/nocommit.test.sh b/tests/nocommit.test.sh new file mode 100755 index 00000000..3a06c819 --- /dev/null +++ b/tests/nocommit.test.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +set -e + +grep -nHR NOCOMMIT src/ || exit 0 +echo "Failed: one or more NOCOMMIT comments were found" +exit 1