improve support for 11/2000 prototype
This commit is contained in:
@@ -58,8 +58,11 @@ newserv supports several versions of PSO. Specifically:
|
||||
| Version | Login | Lobbies | Games | Proxy |
|
||||
|----------------|--------------|--------------|--------------|--------------|
|
||||
| DC Trial | Yes | Yes | Yes | No |
|
||||
| DC Prototype | Yes (3) | Yes (3) | Yes (3) | No |
|
||||
| DC 11/2000 | Yes (3) | Yes (3) | Yes (3) | No |
|
||||
| DC 12/2000 | Untested (1) | Untested (1) | Untested (1) | No |
|
||||
| DC 01/2001 | Untested (1) | Untested (1) | Untested (1) | No |
|
||||
| DC V1 | Yes | Yes | Yes | Yes |
|
||||
| DC 08/2001 | Untested (1) | Untested (1) | Untested (1) | No |
|
||||
| DC V2 | Yes | Yes | Yes | Yes |
|
||||
| PC | Yes | Yes | Yes | Yes |
|
||||
| GC Ep1&2 Trial | Untested (1) | Untested (1) | Untested (1) | Untested (1) |
|
||||
@@ -74,8 +77,7 @@ newserv supports several versions of PSO. Specifically:
|
||||
*Notes:*
|
||||
1. *newserv's implementation of this version is based on disassembly of the client executable and has never been tested.*
|
||||
2. *BB games are mostly playable, but there are still some unimplemented features (for example, some quests that use rare commands may not work). Please submit a GitHub issue if you find something that doesn't work.*
|
||||
3. *Support for the December 2000 prototype is somewhat incomplete and probably never will be complete. This version is rather unstable and seems to crash often, but it's not obvious whether it's because it's a prototype or because newserv sends data it can't handle.*
|
||||
4. *Creating a game works and battle setup behaves mostly normally, but starting a battle doesn't work.*
|
||||
3. *Creating a game works and battle setup behaves mostly normally, but starting a battle doesn't work.*
|
||||
|
||||
## Setup
|
||||
|
||||
@@ -109,7 +111,7 @@ newserv automatically finds quests in the subdirectories of the system/quests/ d
|
||||
|
||||
Within the category directories, quest files should be named like `q###-VERSION-LANGUAGE.EXT` (although the `q` is ignored, and can be any letter). The fields in each filename are:
|
||||
- `###`: quest number (this doesn't really matter; it should just be unique across the PSO version)
|
||||
- `VERSION`: dn = Dreamcast NTE, d1 = Dreamcast v1, dc = Dreamcast v2, pc = PC, gcn = GameCube Trial Edition, gc = GameCube Episodes 1 & 2, gc3 = Episode 3 (see below), xb = Xbox, bb = Blue Burst
|
||||
- `VERSION`: dn = Dreamcast NTE, dp = Dreamcast 11/2000 prototype, d1 = Dreamcast v1, dc = Dreamcast v2, pc = PC, gcn = GameCube Trial Edition, gc = GameCube Episodes 1 & 2, gc3 = Episode 3 (see below), xb = Xbox, bb = Blue Burst
|
||||
- `LANGUAGE`: j = Japanese, e = English, g = German, f = French, s = Spanish
|
||||
- `EXT`: file extension (see table below)
|
||||
|
||||
|
||||
+2
-2
@@ -266,7 +266,7 @@ void Channel::send(uint16_t cmd, uint32_t flag, const std::vector<std::pair<cons
|
||||
size_t send_data_size = 0;
|
||||
switch (this->version) {
|
||||
case Version::DC_NTE:
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
case Version::DC_V2:
|
||||
case Version::GC_NTE:
|
||||
@@ -277,7 +277,7 @@ void Channel::send(uint16_t cmd, uint32_t flag, const std::vector<std::pair<cons
|
||||
PSOCommandHeaderDCV3 header;
|
||||
if (this->crypt_out.get() &&
|
||||
(this->version != Version::DC_NTE) &&
|
||||
(this->version != Version::DC_V1_12_2000_PROTOTYPE) &&
|
||||
(this->version != Version::DC_V1_11_2000_PROTOTYPE) &&
|
||||
(this->version != Version::DC_V1)) {
|
||||
send_data_size = (sizeof(header) + size + 3) & ~3;
|
||||
} else {
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ void Client::Config::set_flags_for_version(Version version, int64_t sub_version)
|
||||
this->set_flag(Flag::NO_SEND_FUNCTION_CALL);
|
||||
break;
|
||||
case Version::DC_NTE:
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
case Version::DC_V2:
|
||||
this->set_flag(Flag::NO_D6);
|
||||
|
||||
@@ -1637,10 +1637,9 @@ struct C_RegisterV1_DC_92 {
|
||||
uint8_t is_extended = 0; // TODO: This is a guess
|
||||
uint8_t language = 0; // TODO: This is a guess; verify it
|
||||
parray<uint8_t, 2> unknown_a3;
|
||||
pstring<TextEncoding::ASCII, 0x10> hardware_id;
|
||||
parray<uint8_t, 0x50> unused1;
|
||||
pstring<TextEncoding::ASCII, 0x20> email; // According to Sylverant documentation
|
||||
parray<uint8_t, 0x10> unused2;
|
||||
pstring<TextEncoding::ASCII, 0x30> hardware_id;
|
||||
pstring<TextEncoding::ASCII, 0x30> unknown_a4;
|
||||
pstring<TextEncoding::ASCII, 0x30> email; // According to Sylverant documentation
|
||||
} __packed__;
|
||||
|
||||
// 92 (S->C): Register result (non-BB)
|
||||
|
||||
+1
-1
@@ -794,7 +794,7 @@ void ItemCreator::generate_unit_stars_tables() {
|
||||
case Version::GC_EP3:
|
||||
throw logic_error("ItemCreator cannot be created for Episode 3 games");
|
||||
case Version::DC_NTE:
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
case Version::DC_V2:
|
||||
case Version::PC_V2:
|
||||
|
||||
+1
-1
@@ -63,7 +63,7 @@ void Lobby::create_item_creator() {
|
||||
case Version::GC_EP3:
|
||||
throw runtime_error("cannot create item creator for this base version");
|
||||
case Version::DC_NTE:
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
// TODO: We should probably have a v1 common item set at some point too
|
||||
common_item_set = s->common_item_set_v2;
|
||||
|
||||
+2
-2
@@ -95,7 +95,7 @@ Version get_cli_version(Arguments& args) {
|
||||
} else if (args.get<bool>("dc-nte")) {
|
||||
return Version::DC_NTE;
|
||||
} else if (args.get<bool>("dc-proto")) {
|
||||
return Version::DC_V1_12_2000_PROTOTYPE;
|
||||
return Version::DC_V1_11_2000_PROTOTYPE;
|
||||
} else if (args.get<bool>("dc-v1")) {
|
||||
return Version::DC_V1;
|
||||
} else if (args.get<bool>("dc-v2") || args.get<bool>("dc")) {
|
||||
@@ -358,7 +358,7 @@ static void a_encrypt_decrypt_fn(Arguments& args) {
|
||||
shared_ptr<PSOEncryption> crypt;
|
||||
switch (version) {
|
||||
case Version::DC_NTE:
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
case Version::DC_V2:
|
||||
case Version::PC_V2:
|
||||
|
||||
+7
-7
@@ -24,7 +24,7 @@ uint16_t PSOCommandHeader::command(Version version) const {
|
||||
case Version::PC_V2:
|
||||
return this->pc.command;
|
||||
case Version::DC_NTE:
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
case Version::DC_V2:
|
||||
return this->dc.command;
|
||||
@@ -50,7 +50,7 @@ void PSOCommandHeader::set_command(Version version, uint16_t command) {
|
||||
this->pc.command = command;
|
||||
break;
|
||||
case Version::DC_NTE:
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
case Version::DC_V2:
|
||||
this->dc.command = command;
|
||||
@@ -79,7 +79,7 @@ uint16_t PSOCommandHeader::size(Version version) const {
|
||||
case Version::PC_V2:
|
||||
return this->pc.size;
|
||||
case Version::DC_NTE:
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
case Version::DC_V2:
|
||||
return this->dc.size;
|
||||
@@ -105,7 +105,7 @@ void PSOCommandHeader::set_size(Version version, uint32_t size) {
|
||||
this->pc.size = size;
|
||||
break;
|
||||
case Version::DC_NTE:
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
case Version::DC_V2:
|
||||
this->dc.size = size;
|
||||
@@ -134,7 +134,7 @@ uint32_t PSOCommandHeader::flag(Version version) const {
|
||||
case Version::PC_V2:
|
||||
return this->pc.flag;
|
||||
case Version::DC_NTE:
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
case Version::DC_V2:
|
||||
return this->dc.flag;
|
||||
@@ -160,7 +160,7 @@ void PSOCommandHeader::set_flag(Version version, uint32_t flag) {
|
||||
this->pc.flag = flag;
|
||||
break;
|
||||
case Version::DC_NTE:
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
case Version::DC_V2:
|
||||
this->dc.flag = flag;
|
||||
@@ -207,7 +207,7 @@ std::string prepend_command_header(
|
||||
StringWriter ret;
|
||||
switch (version) {
|
||||
case Version::DC_NTE:
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
case Version::DC_V2:
|
||||
case Version::GC_NTE:
|
||||
|
||||
@@ -664,7 +664,8 @@ void PlayerInventory::encode_for_client(shared_ptr<Client> c) {
|
||||
// DC NTE has the item count as a 32-bit value here, whereas every other
|
||||
// version uses a single byte. To stop DC NTE from crashing by trying to
|
||||
// construct far more than 30 TItem objects, we clear the fields DC NTE
|
||||
// doesn't know about.
|
||||
// doesn't know about. Note that the 11/2000 prototype does not have this
|
||||
// issue - its inventory format matches the rest of the versions.
|
||||
this->hp_from_materials = 0;
|
||||
this->tp_from_materials = 0;
|
||||
this->language = 0;
|
||||
|
||||
@@ -72,8 +72,6 @@ struct PlayerInventory {
|
||||
/* 0004 */ parray<PlayerInventoryItem, 30> items;
|
||||
/* 034C */
|
||||
|
||||
void clear_dc_nte_unused_fields();
|
||||
|
||||
size_t find_item(uint32_t item_id) const;
|
||||
size_t find_item_by_primary_identifier(uint32_t primary_identifier) const;
|
||||
|
||||
|
||||
@@ -268,7 +268,7 @@ static HandlerResult S_V123P_02_17(
|
||||
// TODO
|
||||
throw runtime_error("DC NTE proxy is not implemented");
|
||||
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
if (command == 0x17) {
|
||||
C_LoginV1_DC_PC_V3_90 cmd;
|
||||
|
||||
+2
-2
@@ -175,7 +175,7 @@ void ProxyServer::on_client_connect(
|
||||
case Version::BB_PATCH:
|
||||
throw logic_error("cannot create unlinked patch session");
|
||||
case Version::DC_NTE:
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
case Version::DC_V2:
|
||||
case Version::PC_V2:
|
||||
@@ -281,7 +281,7 @@ void ProxyServer::UnlinkedSession::on_input(Channel& ch, uint16_t command, uint3
|
||||
break;
|
||||
}
|
||||
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
case Version::DC_V2:
|
||||
// We should only get a 93 or 9D while the session is unlinked
|
||||
|
||||
+4
-4
@@ -235,7 +235,7 @@ VersionedQuest::VersionedQuest(
|
||||
break;
|
||||
}
|
||||
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
case Version::DC_V2: {
|
||||
if (bin_decompressed.size() < sizeof(PSOQuestHeaderDC)) {
|
||||
@@ -570,7 +570,7 @@ QuestIndex::QuestIndex(
|
||||
// Get the version from the second token
|
||||
static const unordered_map<string, Version> name_to_version({
|
||||
{"dn", Version::DC_NTE},
|
||||
{"dp", Version::DC_V1_12_2000_PROTOTYPE},
|
||||
{"dp", Version::DC_V1_11_2000_PROTOTYPE},
|
||||
{"d1", Version::DC_V1},
|
||||
{"dc", Version::DC_V2},
|
||||
{"pc", Version::PC_V2},
|
||||
@@ -807,7 +807,7 @@ shared_ptr<VersionedQuest> VersionedQuest::create_download_quest(uint8_t overrid
|
||||
// There's no known language field in this version, so we don't write
|
||||
// anything here
|
||||
break;
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
case Version::DC_V2:
|
||||
if (decompressed_bin.size() < sizeof(PSOQuestHeaderDC)) {
|
||||
@@ -1222,7 +1222,7 @@ string encode_qst_file(
|
||||
// unfortunate abstraction-breaking.
|
||||
switch (version) {
|
||||
case Version::DC_NTE: // DC NTE doesn't support quests, but we support encoding QST files anyway
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
case Version::DC_V2:
|
||||
for (const auto& it : files) {
|
||||
|
||||
+2
-2
@@ -861,7 +861,7 @@ std::string disassemble_quest_script(const void* data, size_t size, Version vers
|
||||
lines.emplace_back(".name " + escape_string(header.name.decode(0)));
|
||||
break;
|
||||
}
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
case Version::DC_V2: {
|
||||
const auto& header = r.get<PSOQuestHeaderDC>();
|
||||
@@ -1527,7 +1527,7 @@ Episode find_quest_episode_from_script(const void* data, size_t size, Version ve
|
||||
Episode header_episode = Episode::NONE;
|
||||
switch (version) {
|
||||
case Version::DC_NTE:
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
case Version::DC_V2:
|
||||
case Version::PC_V2:
|
||||
|
||||
+15
-11
@@ -576,6 +576,7 @@ static void on_92_DC(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
|
||||
// than 92, so we use the presence of a 92 command to determine that the
|
||||
// client is actually DCv1 and not the prototype.
|
||||
c->config.set_flag(Client::Flag::CHECKED_FOR_DC_V1_PROTOTYPE);
|
||||
c->channel.version = Version::DC_V1;
|
||||
c->log.info("Game version changed to DC_V1");
|
||||
send_command(c, 0x92, 0x01);
|
||||
}
|
||||
@@ -585,7 +586,9 @@ static void on_93_DC(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
|
||||
auto s = c->require_server_state();
|
||||
|
||||
c->channel.language = cmd.language;
|
||||
set_console_client_flags(c, cmd.sub_version);
|
||||
if (!c->config.check_flag(Client::Flag::CHECKED_FOR_DC_V1_PROTOTYPE)) {
|
||||
set_console_client_flags(c, cmd.sub_version);
|
||||
}
|
||||
|
||||
uint32_t serial_number = stoul(cmd.serial_number.decode(), nullptr, 16);
|
||||
try {
|
||||
@@ -639,7 +642,8 @@ static void on_93_DC(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
|
||||
if (!c->config.check_flag(Client::Flag::CHECKED_FOR_DC_V1_PROTOTYPE)) {
|
||||
send_command(c, 0x90, 0x01);
|
||||
c->config.set_flag(Client::Flag::CHECKED_FOR_DC_V1_PROTOTYPE);
|
||||
c->log.info("Game version changed to DC_V1_12_2000_PROTOTYPE (will be changed to V1 if 92 is received)");
|
||||
c->channel.version = Version::DC_V1_11_2000_PROTOTYPE;
|
||||
c->log.info("Game version changed to DC_V1_11_2000_PROTOTYPE (will be changed to V1 if 92 is received)");
|
||||
} else {
|
||||
on_login_complete(c);
|
||||
}
|
||||
@@ -2015,7 +2019,7 @@ static void on_10(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
|
||||
c->config.set_flag(Client::Flag::SAVE_ENABLED);
|
||||
// DC NTE and the v1 prototype crash if they receive a 97 command,
|
||||
// so we instead do the redirect immediately
|
||||
if ((c->version() == Version::DC_NTE) || (c->version() == Version::DC_V1_12_2000_PROTOTYPE)) {
|
||||
if ((c->version() == Version::DC_NTE) || (c->version() == Version::DC_V1_11_2000_PROTOTYPE)) {
|
||||
send_client_to_lobby_server(c);
|
||||
} else {
|
||||
send_command(c, 0x97, 0x01);
|
||||
@@ -2777,7 +2781,7 @@ static void on_61_98(shared_ptr<Client> c, uint16_t command, uint32_t flag, stri
|
||||
|
||||
switch (c->version()) {
|
||||
case Version::DC_NTE:
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
case Version::DC_V1: {
|
||||
const auto& cmd = check_size_t<C_CharacterData_DCv1_61_98>(data);
|
||||
c->game_data.last_reported_disp_v1_v2.reset(new PlayerDispDataDCPCV3(cmd.disp));
|
||||
@@ -3490,7 +3494,7 @@ static void on_81(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
|
||||
uint32_t to_guild_card_number;
|
||||
switch (c->version()) {
|
||||
case Version::DC_NTE:
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
case Version::DC_V2:
|
||||
case Version::GC_NTE:
|
||||
@@ -3677,8 +3681,8 @@ shared_ptr<Lobby> create_game_generic(
|
||||
case Version::DC_NTE:
|
||||
game->allow_version(Version::DC_NTE);
|
||||
break;
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
game->allow_version(Version::DC_V1_12_2000_PROTOTYPE);
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
game->allow_version(Version::DC_V1_11_2000_PROTOTYPE);
|
||||
break;
|
||||
case Version::DC_V1:
|
||||
game->allow_version(Version::DC_V1);
|
||||
@@ -3803,7 +3807,7 @@ shared_ptr<Lobby> create_game_generic(
|
||||
// Generate the map variations
|
||||
if (game->is_ep3()) {
|
||||
game->variations.clear(0);
|
||||
} else if ((c->version() == Version::DC_NTE) || (c->version() == Version::DC_V1_12_2000_PROTOTYPE)) {
|
||||
} else if ((c->version() == Version::DC_NTE) || (c->version() == Version::DC_V1_11_2000_PROTOTYPE)) {
|
||||
generate_variations_dc_nte(game->variations, game->random_crypt);
|
||||
} else {
|
||||
generate_variations(game->variations, game->random_crypt, game->episode, is_solo);
|
||||
@@ -3910,7 +3914,7 @@ static void on_0C_C1_E7_EC(shared_ptr<Client> c, uint16_t command, uint32_t, str
|
||||
auto s = c->require_server_state();
|
||||
|
||||
shared_ptr<Lobby> game;
|
||||
if ((c->version() == Version::DC_NTE) || (c->version() == Version::DC_V1_12_2000_PROTOTYPE)) {
|
||||
if ((c->version() == Version::DC_NTE) || (c->version() == Version::DC_V1_11_2000_PROTOTYPE)) {
|
||||
const auto& cmd = check_size_t<C_CreateGame_DCNTE<TextEncoding::SJIS>>(data);
|
||||
game = create_game_generic(s, c, cmd.name.decode(c->language()), cmd.password.decode(c->language()), Episode::EP1, GameMode::NORMAL, 0, true);
|
||||
|
||||
@@ -5165,7 +5169,7 @@ static void check_unlicensed_command(Version version, uint8_t command) {
|
||||
}
|
||||
break;
|
||||
case Version::DC_NTE:
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
case Version::DC_V2:
|
||||
// newserv doesn't actually know that DC clients are DC until it receives
|
||||
@@ -5235,7 +5239,7 @@ void on_command(
|
||||
void on_command_with_header(shared_ptr<Client> c, const string& data) {
|
||||
switch (c->version()) {
|
||||
case Version::DC_NTE:
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
case Version::DC_V2:
|
||||
case Version::GC_NTE:
|
||||
|
||||
+361
-314
@@ -53,7 +53,8 @@ static void forward_subcommand(
|
||||
uint8_t flag,
|
||||
const void* data,
|
||||
size_t size,
|
||||
uint8_t dc_nte_subcommand = 0x00) {
|
||||
uint8_t dc_nte_subcommand = 0x00,
|
||||
uint8_t dc_11_2000_proto_subcommand = 0x00) {
|
||||
|
||||
// If the command is an Ep3-only command, make sure an Ep3 client sent it
|
||||
bool command_is_ep3 = (command & 0xF0) == 0xC0;
|
||||
@@ -78,6 +79,14 @@ static void forward_subcommand(
|
||||
} else {
|
||||
c->log.warning("Attempted to send unsupported target command to DC NTE client; dropping command");
|
||||
}
|
||||
} else if (target->version() == Version::DC_V1_11_2000_PROTOTYPE) {
|
||||
if (dc_11_2000_proto_subcommand) {
|
||||
string proto_data(reinterpret_cast<const char*>(data), size);
|
||||
proto_data[0] = dc_11_2000_proto_subcommand;
|
||||
send_command(target, command, flag, proto_data);
|
||||
} else {
|
||||
c->log.warning("Attempted to send unsupported target command to DC 11/2000 prototype client; dropping command");
|
||||
}
|
||||
} else {
|
||||
send_command(target, command, flag, data, size);
|
||||
}
|
||||
@@ -93,6 +102,7 @@ static void forward_subcommand(
|
||||
|
||||
} else {
|
||||
string nte_data;
|
||||
string proto_data;
|
||||
for (auto& lc : l->clients) {
|
||||
if (!lc || (lc == c)) {
|
||||
continue;
|
||||
@@ -105,6 +115,14 @@ static void forward_subcommand(
|
||||
}
|
||||
send_command(lc, command, flag, nte_data);
|
||||
}
|
||||
} else if (lc->version() == Version::DC_V1_11_2000_PROTOTYPE) {
|
||||
if (dc_11_2000_proto_subcommand) {
|
||||
if (proto_data.empty()) {
|
||||
proto_data.assign(reinterpret_cast<const char*>(data), size);
|
||||
proto_data[0] = dc_11_2000_proto_subcommand;
|
||||
}
|
||||
send_command(lc, command, flag, proto_data);
|
||||
}
|
||||
} else {
|
||||
send_command(lc, command, flag, data, size);
|
||||
}
|
||||
@@ -522,7 +540,7 @@ static void on_send_guild_card(shared_ptr<Client> c, uint8_t command, uint8_t fl
|
||||
|
||||
switch (c->version()) {
|
||||
case Version::DC_NTE:
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
case Version::DC_V2: {
|
||||
const auto& cmd = check_size_t<G_SendGuildCard_DC_6x06>(data, size);
|
||||
@@ -642,14 +660,14 @@ static void on_set_player_invisible(shared_ptr<Client> c, uint8_t command, uint8
|
||||
if (cmd.header.client_id != c->lobby_client_id) {
|
||||
return;
|
||||
}
|
||||
forward_subcommand(c, command, flag, data, size, 0x1E);
|
||||
forward_subcommand(c, command, flag, data, size, 0x1E, 0x20);
|
||||
}
|
||||
|
||||
static void on_set_player_visible(shared_ptr<Client> c, uint8_t command, uint8_t flag, const void* data, size_t size) {
|
||||
const auto& cmd = check_size_t<G_SetPlayerVisibility_6x22_6x23>(data, size);
|
||||
|
||||
if (cmd.header.client_id == c->lobby_client_id) {
|
||||
forward_subcommand(c, command, flag, data, size, 0x1F);
|
||||
forward_subcommand(c, command, flag, data, size, 0x1F, 0x21);
|
||||
|
||||
auto l = c->require_lobby();
|
||||
if (!l->is_game() && !is_v1(c->version())) {
|
||||
@@ -674,7 +692,7 @@ static void on_change_floor_6x1F(shared_ptr<Client> c, uint8_t command, uint8_t
|
||||
static void on_change_floor_6x21(shared_ptr<Client> c, uint8_t command, uint8_t flag, const void* data, size_t size) {
|
||||
const auto& cmd = check_size_t<G_InterLevelWarp_6x21>(data, size);
|
||||
c->floor = cmd.floor;
|
||||
forward_subcommand(c, command, flag, data, size, 0x1D);
|
||||
forward_subcommand(c, command, flag, data, size, 0x1D, 0x1F);
|
||||
}
|
||||
|
||||
// When a player dies, decrease their mag's synchro
|
||||
@@ -782,7 +800,7 @@ static void on_switch_state_changed(shared_ptr<Client> c, uint8_t command, uint8
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename CmdT, uint8_t DCNTESubcommand>
|
||||
template <typename CmdT, uint8_t DCNTESubcommand, uint8_t DC112000ProtoSubcommand>
|
||||
void on_movement(shared_ptr<Client> c, uint8_t command, uint8_t flag, const void* data, size_t size) {
|
||||
const auto& cmd = check_size_t<CmdT>(data, size);
|
||||
if (cmd.header.client_id != c->lobby_client_id) {
|
||||
@@ -792,10 +810,10 @@ void on_movement(shared_ptr<Client> c, uint8_t command, uint8_t flag, const void
|
||||
c->x = cmd.x;
|
||||
c->z = cmd.z;
|
||||
|
||||
forward_subcommand(c, command, flag, data, size, DCNTESubcommand);
|
||||
forward_subcommand(c, command, flag, data, size, DCNTESubcommand, DC112000ProtoSubcommand);
|
||||
}
|
||||
|
||||
template <typename CmdT, uint8_t DCNTESubcommand>
|
||||
template <typename CmdT, uint8_t DCNTESubcommand, uint8_t DC112000ProtoSubcommand>
|
||||
void on_movement_with_floor(shared_ptr<Client> c, uint8_t command, uint8_t flag, const void* data, size_t size) {
|
||||
const auto& cmd = check_size_t<CmdT>(data, size);
|
||||
if (cmd.header.client_id != c->lobby_client_id) {
|
||||
@@ -806,12 +824,25 @@ void on_movement_with_floor(shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
||||
c->z = cmd.z;
|
||||
c->floor = cmd.floor;
|
||||
|
||||
forward_subcommand(c, command, flag, data, size, DCNTESubcommand);
|
||||
forward_subcommand(c, command, flag, data, size, DCNTESubcommand, DC112000ProtoSubcommand);
|
||||
}
|
||||
|
||||
static void on_toggle_counter_interaction(shared_ptr<Client> c, uint8_t command, uint8_t flag, const void* data, size_t size) {
|
||||
check_size_t<G_ToggleCounterInteraction_6x52>(data, size, 0xFFFF);
|
||||
forward_subcommand(c, command, flag, data, size, 0x46);
|
||||
forward_subcommand(c, command, flag, data, size, 0x46, 0x4C);
|
||||
}
|
||||
|
||||
static void on_set_or_clear_player_flags_multi(shared_ptr<Client> c, uint8_t command, uint8_t flag, const void* data, size_t size) {
|
||||
const auto& cmd = check_size_t<G_ClientIDHeader>(data, size, 0xFFFF);
|
||||
if (cmd.client_id != c->lobby_client_id) {
|
||||
return;
|
||||
}
|
||||
forward_subcommand(c, command, flag, data, size, 0x00, 0x50);
|
||||
}
|
||||
|
||||
static void on_unknown_6x3B(shared_ptr<Client> c, uint8_t command, uint8_t flag, const void* data, size_t size) {
|
||||
check_size_t<G_UnusedHeader>(data, size, 0xFFFF);
|
||||
forward_subcommand(c, command, flag, data, size, 0x00, 0x38);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -2670,7 +2701,273 @@ static void on_write_quest_global_flag_bb(shared_ptr<Client> c, uint8_t, uint8_t
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void handle_subcommand_dc_nte(shared_ptr<Client> c, uint8_t command, uint8_t flag, const void* data, size_t size) {
|
||||
struct SubcommandDefinition {
|
||||
uint8_t nte_subcommand;
|
||||
uint8_t proto_subcommand;
|
||||
uint8_t subcommand;
|
||||
void (*handler)(shared_ptr<Client> c, uint8_t command, uint8_t flag, const void* data, size_t size);
|
||||
};
|
||||
|
||||
SubcommandDefinition subcommand_definitions[0x100] = {
|
||||
/* 6x00 */ {0x00, 0x00, 0x00, on_invalid},
|
||||
/* 6x01 */ {0x00, 0x00, 0x01, nullptr},
|
||||
/* 6x02 */ {0x00, 0x00, 0x02, nullptr},
|
||||
/* 6x03 */ {0x00, 0x00, 0x03, nullptr},
|
||||
/* 6x04 */ {0x00, 0x00, 0x04, nullptr},
|
||||
/* 6x05 */ {0x00, 0x00, 0x05, on_switch_state_changed},
|
||||
/* 6x06 */ {0x00, 0x00, 0x06, on_send_guild_card},
|
||||
/* 6x07 */ {0x00, 0x00, 0x07, on_symbol_chat},
|
||||
/* 6x08 */ {0x00, 0x00, 0x08, nullptr},
|
||||
/* 6x09 */ {0x00, 0x00, 0x09, nullptr},
|
||||
/* 6x0A */ {0x00, 0x00, 0x0A, on_enemy_hit},
|
||||
/* 6x0B */ {0x00, 0x00, 0x0B, on_forward_check_size_game},
|
||||
/* 6x0C */ {0x00, 0x00, 0x0C, on_forward_check_size_game},
|
||||
/* 6x0D */ {0x00, 0x00, 0x0D, on_forward_check_size_game},
|
||||
/* 6x0E */ {0x00, 0x00, 0x0E, nullptr},
|
||||
/* 6x0F */ {0x00, 0x00, 0x0F, nullptr},
|
||||
/* 6x10 */ {0x00, 0x00, 0x10, nullptr},
|
||||
/* 6x11 */ {0x00, 0x00, 0x11, nullptr},
|
||||
/* 6x12 */ {0x00, 0x00, 0x12, on_dragon_actions},
|
||||
/* 6x13 */ {0x00, 0x00, 0x13, on_forward_check_size_game},
|
||||
/* 6x14 */ {0x00, 0x00, 0x14, on_forward_check_size_game},
|
||||
/* 6x15 */ {0x00, 0x00, 0x15, on_forward_check_size_game},
|
||||
/* 6x16 */ {0x00, 0x00, 0x16, on_forward_check_size_game},
|
||||
/* 6x17 */ {0x00, 0x00, 0x17, on_forward_check_size_game},
|
||||
/* 6x18 */ {0x00, 0x00, 0x18, on_forward_check_size_game},
|
||||
/* 6x19 */ {0x00, 0x00, 0x19, on_forward_check_size_game},
|
||||
/* 6x1A */ {0x00, 0x00, 0x1A, nullptr},
|
||||
/* 6x1B */ {0x00, 0x00, 0x1B, on_forward_check_size_game},
|
||||
/* 6x1C */ {0x00, 0x00, 0x1C, on_forward_check_size_game},
|
||||
/* 6x1D */ {0x00, 0x00, 0x1D, nullptr},
|
||||
/* 6x1E */ {0x00, 0x00, 0x1E, nullptr},
|
||||
/* 6x1F */ {0x00, 0x00, 0x1F, on_change_floor_6x1F},
|
||||
/* 6x20 */ {0x00, 0x00, 0x20, on_movement_with_floor<G_SetPosition_6x20, 0x00, 0x00>},
|
||||
/* 6x21 */ {0x1D, 0x1F, 0x21, on_change_floor_6x21},
|
||||
/* 6x22 */ {0x1E, 0x20, 0x22, on_set_player_invisible},
|
||||
/* 6x23 */ {0x1F, 0x21, 0x23, on_set_player_visible},
|
||||
/* 6x24 */ {0x00, 0x00, 0x24, on_forward_check_size_game},
|
||||
/* 6x25 */ {0x00, 0x00, 0x25, on_equip_item},
|
||||
/* 6x26 */ {0x00, 0x00, 0x26, on_unequip_item},
|
||||
/* 6x27 */ {0x00, 0x00, 0x27, on_use_item},
|
||||
/* 6x28 */ {0x00, 0x00, 0x28, on_feed_mag},
|
||||
/* 6x29 */ {0x00, 0x00, 0x29, on_destroy_inventory_item},
|
||||
/* 6x2A */ {0x00, 0x00, 0x2A, on_player_drop_item},
|
||||
/* 6x2B */ {0x00, 0x00, 0x2B, on_create_inventory_item},
|
||||
/* 6x2C */ {0x00, 0x00, 0x2C, on_forward_check_size},
|
||||
/* 6x2D */ {0x00, 0x00, 0x2D, on_forward_check_size},
|
||||
/* 6x2E */ {0x00, 0x00, 0x2E, nullptr}, // TODO: DC112000 uses this as 6x2C; should we support it?
|
||||
/* 6x2F */ {0x00, 0x00, 0x2F, on_hit_by_enemy},
|
||||
/* 6x30 */ {0x00, 0x00, 0x30, on_level_up},
|
||||
/* 6x31 */ {0x00, 0x00, 0x31, on_forward_check_size_game},
|
||||
/* 6x32 */ {0x00, 0x00, 0x32, on_forward_check_size_game},
|
||||
/* 6x33 */ {0x00, 0x00, 0x33, on_forward_check_size_game},
|
||||
/* 6x34 */ {0x00, 0x00, 0x34, nullptr},
|
||||
/* 6x35 */ {0x00, 0x00, 0x35, nullptr},
|
||||
/* 6x36 */ {0x00, 0x00, 0x36, on_forward_check_game},
|
||||
/* 6x37 */ {0x00, 0x00, 0x37, on_forward_check_size_game},
|
||||
/* 6x38 */ {0x00, 0x00, 0x38, nullptr},
|
||||
/* 6x39 */ {0x00, 0x00, 0x39, on_forward_check_size_game},
|
||||
/* 6x3A */ {0x00, 0x00, 0x3A, on_forward_check_size_game},
|
||||
/* 6x3B */ {0x00, 0x38, 0x3B, on_unknown_6x3B},
|
||||
/* 6x3C */ {0x00, 0x00, 0x3C, nullptr},
|
||||
/* 6x3D */ {0x00, 0x00, 0x3D, nullptr},
|
||||
/* 6x3E */ {0x00, 0x00, 0x3E, on_movement_with_floor<G_StopAtPosition_6x3E, 0x00, 0x00>},
|
||||
/* 6x3F */ {0x36, 0x3B, 0x3F, on_movement_with_floor<G_SetPosition_6x3F, 0x36, 0x3B>},
|
||||
/* 6x40 */ {0x37, 0x3C, 0x40, on_movement<G_WalkToPosition_6x40, 0x37, 0x3C>},
|
||||
/* 6x41 */ {0x00, 0x00, 0x41, nullptr},
|
||||
/* 6x42 */ {0x39, 0x3E, 0x42, on_movement<G_RunToPosition_6x42, 0x39, 0x3E>},
|
||||
/* 6x43 */ {0x00, 0x00, 0x43, on_forward_check_size_client},
|
||||
/* 6x44 */ {0x00, 0x00, 0x44, on_forward_check_size_client},
|
||||
/* 6x45 */ {0x00, 0x00, 0x45, on_forward_check_size_client},
|
||||
/* 6x46 */ {0x00, 0x00, 0x46, on_attack_finished},
|
||||
/* 6x47 */ {0x00, 0x00, 0x47, on_cast_technique},
|
||||
/* 6x48 */ {0x00, 0x00, 0x48, on_cast_technique_finished},
|
||||
/* 6x49 */ {0x00, 0x00, 0x49, on_subtract_pb_energy},
|
||||
/* 6x4A */ {0x00, 0x00, 0x4A, on_forward_check_size_client},
|
||||
/* 6x4B */ {0x00, 0x00, 0x4B, on_hit_by_enemy},
|
||||
/* 6x4C */ {0x00, 0x00, 0x4C, on_hit_by_enemy},
|
||||
/* 6x4D */ {0x00, 0x00, 0x4D, on_player_died},
|
||||
/* 6x4E */ {0x00, 0x00, 0x4E, on_forward_check_size_client},
|
||||
/* 6x4F */ {0x00, 0x00, 0x4F, on_forward_check_size_client},
|
||||
/* 6x50 */ {0x00, 0x00, 0x50, on_forward_check_size_client},
|
||||
/* 6x51 */ {0x00, 0x00, 0x51, nullptr},
|
||||
/* 6x52 */ {0x46, 0x4C, 0x52, on_toggle_counter_interaction},
|
||||
/* 6x53 */ {0x00, 0x00, 0x53, on_forward_check_size_game},
|
||||
/* 6x54 */ {0x00, 0x00, 0x54, nullptr},
|
||||
/* 6x55 */ {0x00, 0x00, 0x55, on_forward_check_size_client},
|
||||
/* 6x56 */ {0x00, 0x50, 0x56, on_set_or_clear_player_flags_multi},
|
||||
/* 6x57 */ {0x00, 0x00, 0x57, on_forward_check_size_client},
|
||||
/* 6x58 */ {0x00, 0x00, 0x58, on_forward_check_size_client},
|
||||
/* 6x59 */ {0x00, 0x00, 0x59, on_pick_up_item},
|
||||
/* 6x5A */ {0x00, 0x00, 0x5A, on_pick_up_item_request},
|
||||
/* 6x5B */ {0x00, 0x00, 0x5B, nullptr},
|
||||
/* 6x5C */ {0x00, 0x00, 0x5C, nullptr},
|
||||
/* 6x5D */ {0x00, 0x00, 0x5D, on_drop_partial_stack},
|
||||
/* 6x5E */ {0x00, 0x00, 0x5E, on_buy_shop_item},
|
||||
/* 6x5F */ {0x00, 0x00, 0x5F, on_box_or_enemy_item_drop},
|
||||
/* 6x60 */ {0x00, 0x00, 0x60, on_entity_drop_item_request},
|
||||
/* 6x61 */ {0x00, 0x00, 0x61, on_forward_check_size_game},
|
||||
/* 6x62 */ {0x00, 0x00, 0x62, nullptr},
|
||||
/* 6x63 */ {0x00, 0x00, 0x63, on_destroy_ground_item},
|
||||
/* 6x64 */ {0x00, 0x00, 0x64, nullptr},
|
||||
/* 6x65 */ {0x00, 0x00, 0x65, nullptr},
|
||||
/* 6x66 */ {0x00, 0x00, 0x66, on_forward_check_size_game},
|
||||
/* 6x67 */ {0x00, 0x00, 0x67, on_forward_check_size_game},
|
||||
/* 6x68 */ {0x00, 0x00, 0x68, on_forward_check_size_game},
|
||||
/* 6x69 */ {0x00, 0x00, 0x69, on_forward_check_size_game},
|
||||
/* 6x6A */ {0x00, 0x00, 0x6A, on_forward_check_size_game},
|
||||
/* 6x6B */ {0x00, 0x00, 0x6B, on_forward_sync_joining_player_state},
|
||||
/* 6x6C */ {0x00, 0x00, 0x6C, on_forward_sync_joining_player_state},
|
||||
/* 6x6D */ {0x00, 0x00, 0x6D, on_sync_joining_player_item_state},
|
||||
/* 6x6E */ {0x00, 0x00, 0x6E, on_forward_sync_joining_player_state},
|
||||
/* 6x6F */ {0x00, 0x00, 0x6F, on_forward_check_game_loading},
|
||||
/* 6x70 */ {0x00, 0x00, 0x70, on_sync_joining_player_disp_and_inventory},
|
||||
/* 6x71 */ {0x00, 0x00, 0x71, on_forward_check_game_loading},
|
||||
/* 6x72 */ {0x00, 0x00, 0x72, on_forward_check_game_loading},
|
||||
/* 6x73 */ {0x00, 0x00, 0x73, on_invalid},
|
||||
/* 6x74 */ {0x00, 0x00, 0x74, on_word_select},
|
||||
/* 6x75 */ {0x00, 0x00, 0x75, on_set_quest_flag},
|
||||
/* 6x76 */ {0x00, 0x00, 0x76, on_forward_check_size_game},
|
||||
/* 6x77 */ {0x00, 0x00, 0x77, on_forward_check_size_game},
|
||||
/* 6x78 */ {0x00, 0x00, 0x78, nullptr},
|
||||
/* 6x79 */ {0x00, 0x00, 0x79, on_forward_check_size},
|
||||
/* 6x7A */ {0x00, 0x00, 0x7A, nullptr},
|
||||
/* 6x7B */ {0x00, 0x00, 0x7B, nullptr},
|
||||
/* 6x7C */ {0x00, 0x00, 0x7C, on_forward_check_size_game},
|
||||
/* 6x7D */ {0x00, 0x00, 0x7D, on_forward_check_size_game},
|
||||
/* 6x7E */ {0x00, 0x00, 0x7E, nullptr},
|
||||
/* 6x7F */ {0x00, 0x00, 0x7F, nullptr},
|
||||
/* 6x80 */ {0x00, 0x00, 0x80, on_forward_check_size_game},
|
||||
/* 6x81 */ {0x00, 0x00, 0x81, nullptr},
|
||||
/* 6x82 */ {0x00, 0x00, 0x82, nullptr},
|
||||
/* 6x83 */ {0x00, 0x00, 0x83, on_forward_check_size_game},
|
||||
/* 6x84 */ {0x00, 0x00, 0x84, on_forward_check_size_game},
|
||||
/* 6x85 */ {0x00, 0x00, 0x85, on_forward_check_size_game},
|
||||
/* 6x86 */ {0x00, 0x00, 0x86, on_forward_check_size_game},
|
||||
/* 6x87 */ {0x00, 0x00, 0x87, on_forward_check_size_game},
|
||||
/* 6x88 */ {0x00, 0x00, 0x88, on_forward_check_size_game},
|
||||
/* 6x89 */ {0x00, 0x00, 0x89, on_forward_check_size_game},
|
||||
/* 6x8A */ {0x00, 0x00, 0x8A, on_forward_check_size_game},
|
||||
/* 6x8B */ {0x00, 0x00, 0x8B, nullptr},
|
||||
/* 6x8C */ {0x00, 0x00, 0x8C, nullptr},
|
||||
/* 6x8D */ {0x00, 0x00, 0x8D, on_forward_check_size_client},
|
||||
/* 6x8E */ {0x00, 0x00, 0x8E, nullptr},
|
||||
/* 6x8F */ {0x00, 0x00, 0x8F, nullptr},
|
||||
/* 6x90 */ {0x00, 0x00, 0x90, nullptr},
|
||||
/* 6x91 */ {0x00, 0x00, 0x91, on_forward_check_size_game},
|
||||
/* 6x92 */ {0x00, 0x00, 0x92, nullptr},
|
||||
/* 6x93 */ {0x00, 0x00, 0x93, on_forward_check_size_game},
|
||||
/* 6x94 */ {0x00, 0x00, 0x94, on_forward_check_size_game},
|
||||
/* 6x95 */ {0x00, 0x00, 0x95, nullptr},
|
||||
/* 6x96 */ {0x00, 0x00, 0x96, nullptr},
|
||||
/* 6x97 */ {0x00, 0x00, 0x97, on_forward_check_size_game},
|
||||
/* 6x98 */ {0x00, 0x00, 0x98, nullptr},
|
||||
/* 6x99 */ {0x00, 0x00, 0x99, nullptr},
|
||||
/* 6x9A */ {0x00, 0x00, 0x9A, on_forward_check_size_game},
|
||||
/* 6x9B */ {0x00, 0x00, 0x9B, on_forward_check_size_game},
|
||||
/* 6x9C */ {0x00, 0x00, 0x9C, on_forward_check_size_game},
|
||||
/* 6x9D */ {0x00, 0x00, 0x9D, on_forward_check_size_game},
|
||||
/* 6x9E */ {0x00, 0x00, 0x9E, nullptr},
|
||||
/* 6x9F */ {0x00, 0x00, 0x9F, on_forward_check_size_game},
|
||||
/* 6xA0 */ {0x00, 0x00, 0xA0, on_forward_check_size_game},
|
||||
/* 6xA1 */ {0x00, 0x00, 0xA1, on_forward_check_size_game},
|
||||
/* 6xA2 */ {0x00, 0x00, 0xA2, on_entity_drop_item_request},
|
||||
/* 6xA3 */ {0x00, 0x00, 0xA3, on_forward_check_size_game},
|
||||
/* 6xA4 */ {0x00, 0x00, 0xA4, on_forward_check_size_game},
|
||||
/* 6xA5 */ {0x00, 0x00, 0xA5, on_forward_check_size_game},
|
||||
/* 6xA6 */ {0x00, 0x00, 0xA6, on_forward_check_size},
|
||||
/* 6xA7 */ {0x00, 0x00, 0xA7, nullptr},
|
||||
/* 6xA8 */ {0x00, 0x00, 0xA8, on_gol_dragon_actions},
|
||||
/* 6xA9 */ {0x00, 0x00, 0xA9, on_forward_check_size_game},
|
||||
/* 6xAA */ {0x00, 0x00, 0xAA, on_forward_check_size_game},
|
||||
/* 6xAB */ {0x00, 0x00, 0xAB, on_forward_check_size_client},
|
||||
/* 6xAC */ {0x00, 0x00, 0xAC, nullptr},
|
||||
/* 6xAD */ {0x00, 0x00, 0xAD, on_forward_check_size_game},
|
||||
/* 6xAE */ {0x00, 0x00, 0xAE, on_forward_check_size_client},
|
||||
/* 6xAF */ {0x00, 0x00, 0xAF, on_forward_check_size_client},
|
||||
/* 6xB0 */ {0x00, 0x00, 0xB0, on_forward_check_size_client},
|
||||
/* 6xB1 */ {0x00, 0x00, 0xB1, nullptr},
|
||||
/* 6xB2 */ {0x00, 0x00, 0xB2, nullptr},
|
||||
/* 6xB3 */ {0x00, 0x00, 0xB3, nullptr}, // Should be sent via CA instead
|
||||
/* 6xB4 */ {0x00, 0x00, 0xB4, nullptr}, // Should be sent by the server only
|
||||
/* 6xB5 */ {0x00, 0x00, 0xB5, on_open_shop_bb_or_ep3_battle_subs},
|
||||
/* 6xB6 */ {0x00, 0x00, 0xB6, nullptr},
|
||||
/* 6xB7 */ {0x00, 0x00, 0xB7, on_buy_shop_item_bb},
|
||||
/* 6xB8 */ {0x00, 0x00, 0xB8, on_identify_item_bb},
|
||||
/* 6xB9 */ {0x00, 0x00, 0xB9, nullptr},
|
||||
/* 6xBA */ {0x00, 0x00, 0xBA, on_accept_identify_item_bb},
|
||||
/* 6xBB */ {0x00, 0x00, 0xBB, on_open_bank_bb_or_card_trade_counter_ep3},
|
||||
/* 6xBC */ {0x00, 0x00, 0xBC, on_forward_check_size_ep3_game},
|
||||
/* 6xBD */ {0x00, 0x00, 0xBD, on_ep3_private_word_select_bb_bank_action},
|
||||
/* 6xBE */ {0x00, 0x00, 0xBE, on_ep3_sound_chat},
|
||||
/* 6xBF */ {0x00, 0x00, 0xBF, on_forward_check_size_ep3_lobby},
|
||||
/* 6xC0 */ {0x00, 0x00, 0xC0, on_sell_item_at_shop_bb},
|
||||
/* 6xC1 */ {0x00, 0x00, 0xC1, nullptr},
|
||||
/* 6xC2 */ {0x00, 0x00, 0xC2, nullptr},
|
||||
/* 6xC3 */ {0x00, 0x00, 0xC3, on_drop_partial_stack_bb},
|
||||
/* 6xC4 */ {0x00, 0x00, 0xC4, on_sort_inventory_bb},
|
||||
/* 6xC5 */ {0x00, 0x00, 0xC5, on_medical_center_bb},
|
||||
/* 6xC6 */ {0x00, 0x00, 0xC6, on_steal_exp_bb},
|
||||
/* 6xC7 */ {0x00, 0x00, 0xC7, on_charge_attack_bb},
|
||||
/* 6xC8 */ {0x00, 0x00, 0xC8, on_enemy_exp_request_bb},
|
||||
/* 6xC9 */ {0x00, 0x00, 0xC9, on_meseta_reward_request_bb},
|
||||
/* 6xCA */ {0x00, 0x00, 0xCA, on_item_reward_request_bb},
|
||||
/* 6xCB */ {0x00, 0x00, 0xCB, nullptr},
|
||||
/* 6xCC */ {0x00, 0x00, 0xCC, on_exchange_item_for_team_points_bb},
|
||||
/* 6xCD */ {0x00, 0x00, 0xCD, nullptr},
|
||||
/* 6xCE */ {0x00, 0x00, 0xCE, nullptr},
|
||||
/* 6xCF */ {0x00, 0x00, 0xCF, on_battle_restart_bb},
|
||||
/* 6xD0 */ {0x00, 0x00, 0xD0, on_battle_level_up_bb},
|
||||
/* 6xD1 */ {0x00, 0x00, 0xD1, on_request_challenge_grave_recovery_item_bb},
|
||||
/* 6xD2 */ {0x00, 0x00, 0xD2, on_write_quest_global_flag_bb},
|
||||
/* 6xD3 */ {0x00, 0x00, 0xD3, nullptr},
|
||||
/* 6xD4 */ {0x00, 0x00, 0xD4, nullptr},
|
||||
/* 6xD5 */ {0x00, 0x00, 0xD5, on_quest_exchange_item_bb},
|
||||
/* 6xD6 */ {0x00, 0x00, 0xD6, on_wrap_item_bb},
|
||||
/* 6xD7 */ {0x00, 0x00, 0xD7, on_photon_drop_exchange_bb},
|
||||
/* 6xD8 */ {0x00, 0x00, 0xD8, nullptr},
|
||||
/* 6xD9 */ {0x00, 0x00, 0xD9, on_momoka_item_exchange_bb},
|
||||
/* 6xDA */ {0x00, 0x00, 0xDA, on_upgrade_weapon_attribute_bb},
|
||||
/* 6xDB */ {0x00, 0x00, 0xDB, nullptr},
|
||||
/* 6xDC */ {0x00, 0x00, 0xDC, on_forward_check_size_game},
|
||||
/* 6xDD */ {0x00, 0x00, 0xDD, nullptr},
|
||||
/* 6xDE */ {0x00, 0x00, 0xDE, on_secret_lottery_ticket_exchange_bb},
|
||||
/* 6xDF */ {0x00, 0x00, 0xDF, on_photon_crystal_exchange_bb},
|
||||
/* 6xE0 */ {0x00, 0x00, 0xE0, on_quest_F95E_result_bb},
|
||||
/* 6xE1 */ {0x00, 0x00, 0xE1, on_quest_F95F_result_bb},
|
||||
/* 6xE2 */ {0x00, 0x00, 0xE2, nullptr},
|
||||
/* 6xE3 */ {0x00, 0x00, 0xE3, nullptr},
|
||||
/* 6xE4 */ {0x00, 0x00, 0xE4, nullptr},
|
||||
/* 6xE5 */ {0x00, 0x00, 0xE5, nullptr},
|
||||
/* 6xE6 */ {0x00, 0x00, 0xE6, nullptr},
|
||||
/* 6xE7 */ {0x00, 0x00, 0xE7, nullptr},
|
||||
/* 6xE8 */ {0x00, 0x00, 0xE8, nullptr},
|
||||
/* 6xE9 */ {0x00, 0x00, 0xE9, nullptr},
|
||||
/* 6xEA */ {0x00, 0x00, 0xEA, nullptr},
|
||||
/* 6xEB */ {0x00, 0x00, 0xEB, nullptr},
|
||||
/* 6xEC */ {0x00, 0x00, 0xEC, nullptr},
|
||||
/* 6xED */ {0x00, 0x00, 0xED, nullptr},
|
||||
/* 6xEE */ {0x00, 0x00, 0xEE, nullptr},
|
||||
/* 6xEF */ {0x00, 0x00, 0xEF, nullptr},
|
||||
/* 6xF0 */ {0x00, 0x00, 0xF0, nullptr},
|
||||
/* 6xF1 */ {0x00, 0x00, 0xF1, nullptr},
|
||||
/* 6xF2 */ {0x00, 0x00, 0xF2, nullptr},
|
||||
/* 6xF3 */ {0x00, 0x00, 0xF3, nullptr},
|
||||
/* 6xF4 */ {0x00, 0x00, 0xF4, nullptr},
|
||||
/* 6xF5 */ {0x00, 0x00, 0xF5, nullptr},
|
||||
/* 6xF6 */ {0x00, 0x00, 0xF6, nullptr},
|
||||
/* 6xF7 */ {0x00, 0x00, 0xF7, nullptr},
|
||||
/* 6xF8 */ {0x00, 0x00, 0xF8, nullptr},
|
||||
/* 6xF9 */ {0x00, 0x00, 0xF9, nullptr},
|
||||
/* 6xFA */ {0x00, 0x00, 0xFA, nullptr},
|
||||
/* 6xFB */ {0x00, 0x00, 0xFB, nullptr},
|
||||
/* 6xFC */ {0x00, 0x00, 0xFC, nullptr},
|
||||
/* 6xFD */ {0x00, 0x00, 0xFD, nullptr},
|
||||
/* 6xFE */ {0x00, 0x00, 0xFE, nullptr},
|
||||
/* 6xFF */ {0x00, 0x00, 0xFF, nullptr},
|
||||
};
|
||||
|
||||
static void handle_subcommand_dc_prototypes(shared_ptr<Client> c, uint8_t command, uint8_t flag, const void* data, size_t size) {
|
||||
auto l = c->require_lobby();
|
||||
if (l->is_game()) {
|
||||
// DC NTE doesn't send 6F when it's done loading, so treat this command as
|
||||
@@ -2695,322 +2992,72 @@ static void handle_subcommand_dc_nte(shared_ptr<Client> c, uint8_t command, uint
|
||||
}
|
||||
|
||||
} else {
|
||||
auto& header = check_size_t<G_UnusedHeader>(data, size, 0xFFFF);
|
||||
|
||||
// In a lobby, we have to deal with all other versions of the game having
|
||||
// different subcommand numbers than DC NTE. We'll forward the command
|
||||
// verbatim to other DC NTE clients, but will have to translate it for
|
||||
// non-NTE clients. Some subcommands may not map cleanly; for those, we
|
||||
// don't send anything at all to non-NTE clients.
|
||||
auto& header = check_size_t<G_UnusedHeader>(data, size, 0xFFFF);
|
||||
uint8_t nte_subcommand = header.subcommand;
|
||||
uint8_t non_nte_subcommand = 0x00;
|
||||
switch (nte_subcommand) {
|
||||
case 0x1D:
|
||||
non_nte_subcommand = 0x21;
|
||||
break;
|
||||
case 0x1E:
|
||||
non_nte_subcommand = 0x22;
|
||||
break;
|
||||
case 0x1F:
|
||||
non_nte_subcommand = 0x23;
|
||||
break;
|
||||
case 0x36:
|
||||
non_nte_subcommand = 0x3F;
|
||||
break;
|
||||
case 0x37:
|
||||
non_nte_subcommand = 0x40;
|
||||
break;
|
||||
case 0x39:
|
||||
non_nte_subcommand = 0x42;
|
||||
break;
|
||||
case 0x46:
|
||||
non_nte_subcommand = 0x52;
|
||||
break;
|
||||
default:
|
||||
non_nte_subcommand = 0x00;
|
||||
static vector<uint8_t> nte_to_final_map;
|
||||
static vector<uint8_t> proto_to_final_map;
|
||||
if (nte_to_final_map.empty()) {
|
||||
nte_to_final_map.resize(0x100, 0x00);
|
||||
for (size_t z = 0; z < 0x100; z++) {
|
||||
if (subcommand_definitions[z].nte_subcommand) {
|
||||
nte_to_final_map[subcommand_definitions[z].nte_subcommand] = z;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (proto_to_final_map.empty()) {
|
||||
proto_to_final_map.resize(0x100, 0x00);
|
||||
for (size_t z = 0; z < 0x100; z++) {
|
||||
if (subcommand_definitions[z].proto_subcommand) {
|
||||
proto_to_final_map[subcommand_definitions[z].proto_subcommand] = z;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string non_nte_data;
|
||||
const vector<uint8_t>& client_to_final_map = (c->version() == Version::DC_NTE) ? nte_to_final_map : proto_to_final_map;
|
||||
uint8_t final_subcommand = client_to_final_map[header.subcommand];
|
||||
uint8_t nte_subcommand = subcommand_definitions[final_subcommand].nte_subcommand;
|
||||
uint8_t proto_subcommand = subcommand_definitions[final_subcommand].nte_subcommand;
|
||||
uint8_t other_proto_subcommand = (c->version() == Version::DC_NTE) ? proto_subcommand : nte_subcommand;
|
||||
|
||||
string other_proto_data;
|
||||
string final_data;
|
||||
for (auto lc : l->clients) {
|
||||
if (!lc || (lc == c)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (lc->version() == Version::DC_NTE) {
|
||||
if (lc->version() == c->version()) {
|
||||
send_command(lc, command, flag, data, size);
|
||||
} else if (non_nte_subcommand != 0x00) {
|
||||
if (non_nte_data.empty()) {
|
||||
non_nte_data.assign(reinterpret_cast<const char*>(data), size);
|
||||
non_nte_data[0] = non_nte_subcommand;
|
||||
|
||||
} else if ((lc->version() == Version::DC_NTE) || (lc->version() == Version::DC_V1_11_2000_PROTOTYPE)) {
|
||||
// lc is the other prototype version (e.g. lc is DC_NTE and c is
|
||||
// DC_V1_11_2000_PROTOTYPE, or vice versa)
|
||||
if (other_proto_subcommand) {
|
||||
if (other_proto_data.empty()) {
|
||||
other_proto_data.assign(reinterpret_cast<const char*>(data), size);
|
||||
other_proto_data[0] = other_proto_subcommand;
|
||||
}
|
||||
if (other_proto_data[0]) {
|
||||
send_command(lc, command, flag, other_proto_data);
|
||||
}
|
||||
}
|
||||
send_command(lc, command, flag, non_nte_data);
|
||||
|
||||
} else if (final_subcommand != 0) {
|
||||
if (final_data.empty()) {
|
||||
final_data.assign(reinterpret_cast<const char*>(data), size);
|
||||
final_data[0] = final_subcommand;
|
||||
}
|
||||
send_command(lc, command, flag, final_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef void (*subcommand_handler_t)(shared_ptr<Client> c, uint8_t command, uint8_t flag, const void* data, size_t size);
|
||||
|
||||
subcommand_handler_t subcommand_handlers[0x100] = {
|
||||
/* 6x00 */ on_invalid,
|
||||
/* 6x01 */ nullptr,
|
||||
/* 6x02 */ nullptr,
|
||||
/* 6x03 */ nullptr,
|
||||
/* 6x04 */ nullptr,
|
||||
/* 6x05 */ on_switch_state_changed,
|
||||
/* 6x06 */ on_send_guild_card,
|
||||
/* 6x07 */ on_symbol_chat,
|
||||
/* 6x08 */ nullptr,
|
||||
/* 6x09 */ nullptr,
|
||||
/* 6x0A */ on_enemy_hit,
|
||||
/* 6x0B */ on_forward_check_size_game,
|
||||
/* 6x0C */ on_forward_check_size_game,
|
||||
/* 6x0D */ on_forward_check_size_game,
|
||||
/* 6x0E */ nullptr,
|
||||
/* 6x0F */ nullptr,
|
||||
/* 6x10 */ nullptr,
|
||||
/* 6x11 */ nullptr,
|
||||
/* 6x12 */ on_dragon_actions,
|
||||
/* 6x13 */ on_forward_check_size_game,
|
||||
/* 6x14 */ on_forward_check_size_game,
|
||||
/* 6x15 */ on_forward_check_size_game,
|
||||
/* 6x16 */ on_forward_check_size_game,
|
||||
/* 6x17 */ on_forward_check_size_game,
|
||||
/* 6x18 */ on_forward_check_size_game,
|
||||
/* 6x19 */ on_forward_check_size_game,
|
||||
/* 6x1A */ nullptr,
|
||||
/* 6x1B */ on_forward_check_size_game,
|
||||
/* 6x1C */ on_forward_check_size_game,
|
||||
/* 6x1D */ nullptr,
|
||||
/* 6x1E */ nullptr,
|
||||
/* 6x1F */ on_change_floor_6x1F,
|
||||
/* 6x20 */ on_movement_with_floor<G_SetPosition_6x20, 0x00>,
|
||||
/* 6x21 */ on_change_floor_6x21,
|
||||
/* 6x22 */ on_set_player_invisible,
|
||||
/* 6x23 */ on_set_player_visible,
|
||||
/* 6x24 */ on_forward_check_size_game,
|
||||
/* 6x25 */ on_equip_item,
|
||||
/* 6x26 */ on_unequip_item,
|
||||
/* 6x27 */ on_use_item,
|
||||
/* 6x28 */ on_feed_mag,
|
||||
/* 6x29 */ on_destroy_inventory_item,
|
||||
/* 6x2A */ on_player_drop_item,
|
||||
/* 6x2B */ on_create_inventory_item,
|
||||
/* 6x2C */ on_forward_check_size,
|
||||
/* 6x2D */ on_forward_check_size,
|
||||
/* 6x2E */ nullptr,
|
||||
/* 6x2F */ on_hit_by_enemy,
|
||||
/* 6x30 */ on_level_up,
|
||||
/* 6x31 */ on_forward_check_size_game,
|
||||
/* 6x32 */ on_forward_check_size_game,
|
||||
/* 6x33 */ on_forward_check_size_game,
|
||||
/* 6x34 */ nullptr,
|
||||
/* 6x35 */ nullptr,
|
||||
/* 6x36 */ on_forward_check_game,
|
||||
/* 6x37 */ on_forward_check_size_game,
|
||||
/* 6x38 */ nullptr,
|
||||
/* 6x39 */ on_forward_check_size_game,
|
||||
/* 6x3A */ on_forward_check_size_game,
|
||||
/* 6x3B */ on_forward_check_size,
|
||||
/* 6x3C */ nullptr,
|
||||
/* 6x3D */ nullptr,
|
||||
/* 6x3E */ on_movement_with_floor<G_StopAtPosition_6x3E, 0x00>,
|
||||
/* 6x3F */ on_movement_with_floor<G_SetPosition_6x3F, 0x36>,
|
||||
/* 6x40 */ on_movement<G_WalkToPosition_6x40, 0x37>,
|
||||
/* 6x41 */ nullptr,
|
||||
/* 6x42 */ on_movement<G_RunToPosition_6x42, 0x39>,
|
||||
/* 6x43 */ on_forward_check_size_client,
|
||||
/* 6x44 */ on_forward_check_size_client,
|
||||
/* 6x45 */ on_forward_check_size_client,
|
||||
/* 6x46 */ on_attack_finished,
|
||||
/* 6x47 */ on_cast_technique,
|
||||
/* 6x48 */ on_cast_technique_finished,
|
||||
/* 6x49 */ on_subtract_pb_energy,
|
||||
/* 6x4A */ on_forward_check_size_client,
|
||||
/* 6x4B */ on_hit_by_enemy,
|
||||
/* 6x4C */ on_hit_by_enemy,
|
||||
/* 6x4D */ on_player_died,
|
||||
/* 6x4E */ on_forward_check_size_client,
|
||||
/* 6x4F */ on_forward_check_size_client,
|
||||
/* 6x50 */ on_forward_check_size_client,
|
||||
/* 6x51 */ nullptr,
|
||||
/* 6x52 */ on_toggle_counter_interaction,
|
||||
/* 6x53 */ on_forward_check_size_game,
|
||||
/* 6x54 */ nullptr,
|
||||
/* 6x55 */ on_forward_check_size_client,
|
||||
/* 6x56 */ on_forward_check_size_client,
|
||||
/* 6x57 */ on_forward_check_size_client,
|
||||
/* 6x58 */ on_forward_check_size_client,
|
||||
/* 6x59 */ on_pick_up_item,
|
||||
/* 6x5A */ on_pick_up_item_request,
|
||||
/* 6x5B */ nullptr,
|
||||
/* 6x5C */ nullptr,
|
||||
/* 6x5D */ on_drop_partial_stack,
|
||||
/* 6x5E */ on_buy_shop_item,
|
||||
/* 6x5F */ on_box_or_enemy_item_drop,
|
||||
/* 6x60 */ on_entity_drop_item_request,
|
||||
/* 6x61 */ on_forward_check_size_game,
|
||||
/* 6x62 */ nullptr,
|
||||
/* 6x63 */ on_destroy_ground_item,
|
||||
/* 6x64 */ nullptr,
|
||||
/* 6x65 */ nullptr,
|
||||
/* 6x66 */ on_forward_check_size_game,
|
||||
/* 6x67 */ on_forward_check_size_game,
|
||||
/* 6x68 */ on_forward_check_size_game,
|
||||
/* 6x69 */ on_forward_check_size_game,
|
||||
/* 6x6A */ on_forward_check_size_game,
|
||||
/* 6x6B */ on_forward_sync_joining_player_state,
|
||||
/* 6x6C */ on_forward_sync_joining_player_state,
|
||||
/* 6x6D */ on_sync_joining_player_item_state,
|
||||
/* 6x6E */ on_forward_sync_joining_player_state,
|
||||
/* 6x6F */ on_forward_check_game_loading,
|
||||
/* 6x70 */ on_sync_joining_player_disp_and_inventory,
|
||||
/* 6x71 */ on_forward_check_game_loading,
|
||||
/* 6x72 */ on_forward_check_game_loading,
|
||||
/* 6x73 */ on_invalid,
|
||||
/* 6x74 */ on_word_select,
|
||||
/* 6x75 */ on_set_quest_flag,
|
||||
/* 6x76 */ on_forward_check_size_game,
|
||||
/* 6x77 */ on_forward_check_size_game,
|
||||
/* 6x78 */ nullptr,
|
||||
/* 6x79 */ on_forward_check_size,
|
||||
/* 6x7A */ nullptr,
|
||||
/* 6x7B */ nullptr,
|
||||
/* 6x7C */ on_forward_check_size_game,
|
||||
/* 6x7D */ on_forward_check_size_game,
|
||||
/* 6x7E */ nullptr,
|
||||
/* 6x7F */ nullptr,
|
||||
/* 6x80 */ on_forward_check_size_game,
|
||||
/* 6x81 */ nullptr,
|
||||
/* 6x82 */ nullptr,
|
||||
/* 6x83 */ on_forward_check_size_game,
|
||||
/* 6x84 */ on_forward_check_size_game,
|
||||
/* 6x85 */ on_forward_check_size_game,
|
||||
/* 6x86 */ on_forward_check_size_game,
|
||||
/* 6x87 */ on_forward_check_size_game,
|
||||
/* 6x88 */ on_forward_check_size_game,
|
||||
/* 6x89 */ on_forward_check_size_game,
|
||||
/* 6x8A */ on_forward_check_size_game,
|
||||
/* 6x8B */ nullptr,
|
||||
/* 6x8C */ nullptr,
|
||||
/* 6x8D */ on_forward_check_size_client,
|
||||
/* 6x8E */ nullptr,
|
||||
/* 6x8F */ nullptr,
|
||||
/* 6x90 */ nullptr,
|
||||
/* 6x91 */ on_forward_check_size_game,
|
||||
/* 6x92 */ nullptr,
|
||||
/* 6x93 */ on_forward_check_size_game,
|
||||
/* 6x94 */ on_forward_check_size_game,
|
||||
/* 6x95 */ nullptr,
|
||||
/* 6x96 */ nullptr,
|
||||
/* 6x97 */ on_forward_check_size_game,
|
||||
/* 6x98 */ nullptr,
|
||||
/* 6x99 */ nullptr,
|
||||
/* 6x9A */ on_forward_check_size_game,
|
||||
/* 6x9B */ on_forward_check_size_game,
|
||||
/* 6x9C */ on_forward_check_size_game,
|
||||
/* 6x9D */ on_forward_check_size_game,
|
||||
/* 6x9E */ nullptr,
|
||||
/* 6x9F */ on_forward_check_size_game,
|
||||
/* 6xA0 */ on_forward_check_size_game,
|
||||
/* 6xA1 */ on_forward_check_size_game,
|
||||
/* 6xA2 */ on_entity_drop_item_request,
|
||||
/* 6xA3 */ on_forward_check_size_game,
|
||||
/* 6xA4 */ on_forward_check_size_game,
|
||||
/* 6xA5 */ on_forward_check_size_game,
|
||||
/* 6xA6 */ on_forward_check_size,
|
||||
/* 6xA7 */ nullptr,
|
||||
/* 6xA8 */ on_gol_dragon_actions,
|
||||
/* 6xA9 */ on_forward_check_size_game,
|
||||
/* 6xAA */ on_forward_check_size_game,
|
||||
/* 6xAB */ on_forward_check_size_client,
|
||||
/* 6xAC */ nullptr,
|
||||
/* 6xAD */ on_forward_check_size_game,
|
||||
/* 6xAE */ on_forward_check_size_client,
|
||||
/* 6xAF */ on_forward_check_size_client,
|
||||
/* 6xB0 */ on_forward_check_size_client,
|
||||
/* 6xB1 */ nullptr,
|
||||
/* 6xB2 */ nullptr,
|
||||
/* 6xB3 */ nullptr, // Should be sent via CA instead
|
||||
/* 6xB4 */ nullptr, // Should be sent by the server only
|
||||
/* 6xB5 */ on_open_shop_bb_or_ep3_battle_subs,
|
||||
/* 6xB6 */ nullptr,
|
||||
/* 6xB7 */ on_buy_shop_item_bb,
|
||||
/* 6xB8 */ on_identify_item_bb,
|
||||
/* 6xB9 */ nullptr,
|
||||
/* 6xBA */ on_accept_identify_item_bb,
|
||||
/* 6xBB */ on_open_bank_bb_or_card_trade_counter_ep3,
|
||||
/* 6xBC */ on_forward_check_size_ep3_game,
|
||||
/* 6xBD */ on_ep3_private_word_select_bb_bank_action,
|
||||
/* 6xBE */ on_ep3_sound_chat,
|
||||
/* 6xBF */ on_forward_check_size_ep3_lobby,
|
||||
/* 6xC0 */ on_sell_item_at_shop_bb,
|
||||
/* 6xC1 */ nullptr,
|
||||
/* 6xC2 */ nullptr,
|
||||
/* 6xC3 */ on_drop_partial_stack_bb,
|
||||
/* 6xC4 */ on_sort_inventory_bb,
|
||||
/* 6xC5 */ on_medical_center_bb,
|
||||
/* 6xC6 */ on_steal_exp_bb,
|
||||
/* 6xC7 */ on_charge_attack_bb,
|
||||
/* 6xC8 */ on_enemy_exp_request_bb,
|
||||
/* 6xC9 */ on_meseta_reward_request_bb,
|
||||
/* 6xCA */ on_item_reward_request_bb,
|
||||
/* 6xCB */ nullptr,
|
||||
/* 6xCC */ on_exchange_item_for_team_points_bb,
|
||||
/* 6xCD */ nullptr,
|
||||
/* 6xCE */ nullptr,
|
||||
/* 6xCF */ on_battle_restart_bb,
|
||||
/* 6xD0 */ on_battle_level_up_bb,
|
||||
/* 6xD1 */ on_request_challenge_grave_recovery_item_bb,
|
||||
/* 6xD2 */ on_write_quest_global_flag_bb,
|
||||
/* 6xD3 */ nullptr,
|
||||
/* 6xD4 */ nullptr,
|
||||
/* 6xD5 */ on_quest_exchange_item_bb,
|
||||
/* 6xD6 */ on_wrap_item_bb,
|
||||
/* 6xD7 */ on_photon_drop_exchange_bb,
|
||||
/* 6xD8 */ nullptr,
|
||||
/* 6xD9 */ on_momoka_item_exchange_bb,
|
||||
/* 6xDA */ on_upgrade_weapon_attribute_bb,
|
||||
/* 6xDB */ nullptr,
|
||||
/* 6xDC */ on_forward_check_size_game,
|
||||
/* 6xDD */ nullptr,
|
||||
/* 6xDE */ on_secret_lottery_ticket_exchange_bb,
|
||||
/* 6xDF */ on_photon_crystal_exchange_bb,
|
||||
/* 6xE0 */ on_quest_F95E_result_bb,
|
||||
/* 6xE1 */ on_quest_F95F_result_bb,
|
||||
/* 6xE2 */ nullptr,
|
||||
/* 6xE3 */ nullptr,
|
||||
/* 6xE4 */ nullptr,
|
||||
/* 6xE5 */ nullptr,
|
||||
/* 6xE6 */ nullptr,
|
||||
/* 6xE7 */ nullptr,
|
||||
/* 6xE8 */ nullptr,
|
||||
/* 6xE9 */ nullptr,
|
||||
/* 6xEA */ nullptr,
|
||||
/* 6xEB */ nullptr,
|
||||
/* 6xEC */ nullptr,
|
||||
/* 6xED */ nullptr,
|
||||
/* 6xEE */ nullptr,
|
||||
/* 6xEF */ nullptr,
|
||||
/* 6xF0 */ nullptr,
|
||||
/* 6xF1 */ nullptr,
|
||||
/* 6xF2 */ nullptr,
|
||||
/* 6xF3 */ nullptr,
|
||||
/* 6xF4 */ nullptr,
|
||||
/* 6xF5 */ nullptr,
|
||||
/* 6xF6 */ nullptr,
|
||||
/* 6xF7 */ nullptr,
|
||||
/* 6xF8 */ nullptr,
|
||||
/* 6xF9 */ nullptr,
|
||||
/* 6xFA */ nullptr,
|
||||
/* 6xFB */ nullptr,
|
||||
/* 6xFC */ nullptr,
|
||||
/* 6xFD */ nullptr,
|
||||
/* 6xFE */ nullptr,
|
||||
/* 6xFF */ nullptr,
|
||||
};
|
||||
|
||||
void on_subcommand_multi(shared_ptr<Client> c, uint8_t command, uint8_t flag, const string& data) {
|
||||
if (data.empty()) {
|
||||
throw runtime_error("game command is empty");
|
||||
@@ -3037,12 +3084,12 @@ void on_subcommand_multi(shared_ptr<Client> c, uint8_t command, uint8_t flag, co
|
||||
}
|
||||
const void* data = r.getv(size);
|
||||
|
||||
if (c->version() == Version::DC_NTE) {
|
||||
handle_subcommand_dc_nte(c, command, flag, data, size);
|
||||
if ((c->version() == Version::DC_NTE) || (c->version() == Version::DC_V1_11_2000_PROTOTYPE)) {
|
||||
handle_subcommand_dc_prototypes(c, command, flag, data, size);
|
||||
} else {
|
||||
auto fn = subcommand_handlers[header.subcommand];
|
||||
if (fn) {
|
||||
fn(c, command, flag, data, size);
|
||||
const auto& def = subcommand_definitions[header.subcommand];
|
||||
if (def.handler) {
|
||||
def.handler(c, command, flag, data, size);
|
||||
} else {
|
||||
on_unimplemented(c, command, flag, data, size);
|
||||
}
|
||||
@@ -3051,5 +3098,5 @@ void on_subcommand_multi(shared_ptr<Client> c, uint8_t command, uint8_t flag, co
|
||||
}
|
||||
|
||||
bool subcommand_is_implemented(uint8_t which) {
|
||||
return subcommand_handlers[which] != nullptr;
|
||||
return subcommand_definitions[which].handler != nullptr;
|
||||
}
|
||||
|
||||
@@ -146,7 +146,7 @@ void ReplaySession::check_for_password(shared_ptr<const Event> ev) const {
|
||||
}
|
||||
|
||||
case Version::DC_NTE:
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
case Version::DC_V2:
|
||||
case Version::GC_NTE:
|
||||
@@ -238,7 +238,7 @@ void ReplaySession::apply_default_mask(shared_ptr<Event> ev) {
|
||||
break;
|
||||
}
|
||||
case Version::DC_NTE:
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
case Version::DC_V2:
|
||||
case Version::PC_V2:
|
||||
@@ -292,7 +292,7 @@ void ReplaySession::apply_default_mask(shared_ptr<Event> ev) {
|
||||
auto& mask = check_size_t<S_JoinGame_XB_64>(mask_data, mask_size);
|
||||
mask.variations.clear(0);
|
||||
mask.rare_seed = 0;
|
||||
} else if (version == Version::DC_NTE || version == Version::DC_V1_12_2000_PROTOTYPE) {
|
||||
} else if (version == Version::DC_NTE || version == Version::DC_V1_11_2000_PROTOTYPE) {
|
||||
auto& mask = check_size_t<S_JoinGame_DCNTE_64>(mask_data, mask_size);
|
||||
mask.variations.clear(0);
|
||||
} else {
|
||||
@@ -728,7 +728,7 @@ void ReplaySession::on_command_received(
|
||||
}
|
||||
break;
|
||||
case Version::DC_NTE:
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
case Version::DC_V2:
|
||||
case Version::PC_V2:
|
||||
|
||||
+16
-16
@@ -117,7 +117,7 @@ void send_command_with_header(Channel& ch, const void* data, size_t size) {
|
||||
send_command_with_header_t<PSOCommandHeaderPC>(ch, data, size);
|
||||
break;
|
||||
case Version::DC_NTE:
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
case Version::DC_V2:
|
||||
case Version::GC_NTE:
|
||||
@@ -169,7 +169,7 @@ void send_server_init_dc_pc_v3(shared_ptr<Client> c, uint8_t flags) {
|
||||
c->channel.crypt_out.reset(new PSOV2Encryption(server_key));
|
||||
break;
|
||||
case Version::DC_NTE:
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
case Version::DC_V2:
|
||||
case Version::GC_NTE:
|
||||
@@ -244,7 +244,7 @@ void send_server_init_patch(shared_ptr<Client> c) {
|
||||
void send_server_init(shared_ptr<Client> c, uint8_t flags) {
|
||||
switch (c->version()) {
|
||||
case Version::DC_NTE:
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
case Version::DC_V2:
|
||||
case Version::PC_V2:
|
||||
@@ -270,7 +270,7 @@ void send_server_init(shared_ptr<Client> c, uint8_t flags) {
|
||||
void send_update_client_config(shared_ptr<Client> c) {
|
||||
switch (c->version()) {
|
||||
case Version::DC_NTE:
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
case Version::DC_V2:
|
||||
case Version::PC_V2: {
|
||||
@@ -735,7 +735,7 @@ void send_message_box(shared_ptr<Client> c, const string& text) {
|
||||
command = 0x13;
|
||||
break;
|
||||
case Version::DC_NTE:
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
case Version::DC_V2:
|
||||
case Version::PC_V2:
|
||||
@@ -935,7 +935,7 @@ void send_simple_mail_bb(shared_ptr<Client> c, uint32_t from_guild_card_number,
|
||||
void send_simple_mail(shared_ptr<Client> c, uint32_t from_guild_card_number, const string& from_name, const string& text) {
|
||||
switch (c->version()) {
|
||||
case Version::DC_NTE:
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
case Version::DC_V2:
|
||||
case Version::GC_NTE:
|
||||
@@ -1027,7 +1027,7 @@ void send_card_search_result(
|
||||
shared_ptr<Lobby> result_lobby) {
|
||||
switch (c->version()) {
|
||||
case Version::DC_NTE:
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
case Version::DC_V2:
|
||||
case Version::GC_NTE:
|
||||
@@ -1134,7 +1134,7 @@ void send_guild_card(
|
||||
uint8_t char_class) {
|
||||
switch (ch.version) {
|
||||
case Version::DC_NTE:
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
case Version::DC_V2:
|
||||
// TODO: Is this the right format and subcommand for NTE and the prototype?
|
||||
@@ -1206,9 +1206,9 @@ void send_menu_t(shared_ptr<Client> c, shared_ptr<const Menu> menu, bool is_info
|
||||
bool is_visible = true;
|
||||
switch (c->version()) {
|
||||
case Version::DC_NTE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
is_visible &= !(item.flags & MenuItem::Flag::INVISIBLE_ON_DCNTE);
|
||||
[[fallthrough]];
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
case Version::DC_V2:
|
||||
is_visible &= !(item.flags & MenuItem::Flag::INVISIBLE_ON_DC);
|
||||
@@ -1420,7 +1420,7 @@ void send_quest_menu(shared_ptr<Client> c, uint32_t menu_id,
|
||||
send_quest_menu_t<S_QuestMenuEntry_PC_A2_A4>(c, menu_id, quests, is_download_menu);
|
||||
break;
|
||||
case Version::DC_NTE:
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
case Version::DC_V2:
|
||||
case Version::GC_NTE:
|
||||
@@ -1447,7 +1447,7 @@ void send_quest_categories_menu(shared_ptr<Client> c, uint32_t menu_id,
|
||||
send_quest_categories_menu_t<S_QuestMenuEntry_PC_A2_A4>(c, menu_id, quest_index, menu_type, episode);
|
||||
break;
|
||||
case Version::DC_NTE:
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
case Version::DC_V2:
|
||||
case Version::GC_NTE:
|
||||
@@ -1700,7 +1700,8 @@ void send_join_game(shared_ptr<Client> c, shared_ptr<Lobby> l) {
|
||||
};
|
||||
|
||||
switch (c->version()) {
|
||||
case Version::DC_NTE: {
|
||||
case Version::DC_NTE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE: {
|
||||
S_JoinGame_DCNTE_64 cmd;
|
||||
cmd.client_id = c->lobby_client_id;
|
||||
cmd.leader_id = l->leader_id;
|
||||
@@ -1710,7 +1711,6 @@ void send_join_game(shared_ptr<Client> c, shared_ptr<Lobby> l) {
|
||||
send_command_t(c, 0x64, player_count, cmd);
|
||||
break;
|
||||
}
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
case Version::DC_V2: {
|
||||
S_JoinGame_DC_64 cmd;
|
||||
@@ -2007,7 +2007,7 @@ void send_join_lobby(shared_ptr<Client> c, shared_ptr<Lobby> l) {
|
||||
} else {
|
||||
switch (c->version()) {
|
||||
case Version::DC_NTE:
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
send_join_lobby_dc_nte(c, l);
|
||||
break;
|
||||
case Version::DC_V1:
|
||||
@@ -2046,7 +2046,7 @@ void send_player_join_notification(shared_ptr<Client> c,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> joining_client) {
|
||||
switch (c->version()) {
|
||||
case Version::DC_NTE:
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
send_join_lobby_dc_nte(c, l, joining_client);
|
||||
break;
|
||||
case Version::DC_V1:
|
||||
@@ -3055,7 +3055,7 @@ void send_open_quest_file(
|
||||
shared_ptr<const string> contents) {
|
||||
|
||||
switch (c->version()) {
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
case Version::DC_V2:
|
||||
send_open_quest_file_t<S_OpenFile_DC_44_A6>(c, quest_name, filename, xb_filename, contents->size(), quest_number, type);
|
||||
|
||||
+4
-4
@@ -66,7 +66,7 @@ void ServerState::init() {
|
||||
if (allow_non_ep3) {
|
||||
if (allow_v1) {
|
||||
l->allow_version(Version::DC_NTE);
|
||||
l->allow_version(Version::DC_V1_12_2000_PROTOTYPE);
|
||||
l->allow_version(Version::DC_V1_11_2000_PROTOTYPE);
|
||||
l->allow_version(Version::DC_V1);
|
||||
}
|
||||
l->allow_version(Version::DC_V2);
|
||||
@@ -346,7 +346,7 @@ std::shared_ptr<const Menu> ServerState::information_menu_for_version(Version ve
|
||||
shared_ptr<const Menu> ServerState::proxy_destinations_menu_for_version(Version version) const {
|
||||
switch (version) {
|
||||
case Version::DC_NTE:
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
case Version::DC_V2:
|
||||
return this->proxy_destinations_menu_dc;
|
||||
@@ -367,7 +367,7 @@ shared_ptr<const Menu> ServerState::proxy_destinations_menu_for_version(Version
|
||||
const vector<pair<string, uint16_t>>& ServerState::proxy_destinations_for_version(Version version) const {
|
||||
switch (version) {
|
||||
case Version::DC_NTE:
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
case Version::DC_V2:
|
||||
return this->proxy_destinations_dc;
|
||||
@@ -388,7 +388,7 @@ const vector<pair<string, uint16_t>>& ServerState::proxy_destinations_for_versio
|
||||
std::shared_ptr<const ItemParameterTable> ServerState::item_parameter_table_for_version(Version version) const {
|
||||
switch (version) {
|
||||
case Version::DC_NTE:
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
case Version::DC_V2:
|
||||
case Version::PC_V2:
|
||||
|
||||
+7
-7
@@ -15,7 +15,7 @@ const char* login_port_name_for_version(Version v) {
|
||||
case Version::BB_PATCH:
|
||||
return "bb-patch";
|
||||
case Version::DC_NTE:
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
case Version::DC_V2:
|
||||
case Version::GC_NTE:
|
||||
@@ -41,7 +41,7 @@ const char* lobby_port_name_for_version(Version v) {
|
||||
case Version::BB_PATCH:
|
||||
return "bb-patch";
|
||||
case Version::DC_NTE:
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
case Version::DC_V2:
|
||||
case Version::GC_NTE:
|
||||
@@ -67,7 +67,7 @@ const char* proxy_port_name_for_version(Version v) {
|
||||
case Version::BB_PATCH:
|
||||
return "bb-patch";
|
||||
case Version::DC_NTE:
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
case Version::DC_V2:
|
||||
return "dc-proxy";
|
||||
@@ -96,8 +96,8 @@ const char* name_for_enum<Version>(Version v) {
|
||||
return "BB_PATCH";
|
||||
case Version::DC_NTE:
|
||||
return "DC_NTE";
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
return "DC_V1_12_2000_PROTOTYPE";
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
return "DC_V1_11_2000_PROTOTYPE";
|
||||
case Version::DC_V1:
|
||||
return "DC_V1";
|
||||
case Version::DC_V2:
|
||||
@@ -129,8 +129,8 @@ Version enum_for_name<Version>(const char* name) {
|
||||
return Version::BB_PATCH;
|
||||
} else if (!strcmp(name, "DC_NTE")) {
|
||||
return Version::DC_NTE;
|
||||
} else if (!strcmp(name, "DC_V1_12_2000_PROTOTYPE")) {
|
||||
return Version::DC_V1_12_2000_PROTOTYPE;
|
||||
} else if (!strcmp(name, "DC_V1_11_2000_PROTOTYPE")) {
|
||||
return Version::DC_V1_11_2000_PROTOTYPE;
|
||||
} else if (!strcmp(name, "DC_V1")) {
|
||||
return Version::DC_V1;
|
||||
} else if (!strcmp(name, "DC_V2") || !strcasecmp(name, "dc")) {
|
||||
|
||||
+3
-3
@@ -10,7 +10,7 @@ enum class Version {
|
||||
PC_PATCH = 0,
|
||||
BB_PATCH = 1,
|
||||
DC_NTE = 2,
|
||||
DC_V1_12_2000_PROTOTYPE = 3,
|
||||
DC_V1_11_2000_PROTOTYPE = 3,
|
||||
DC_V1 = 4,
|
||||
DC_V2 = 5,
|
||||
PC_V2 = 6,
|
||||
@@ -32,7 +32,7 @@ inline bool is_patch(Version version) {
|
||||
return (version == Version::PC_PATCH) || (version == Version::BB_PATCH);
|
||||
}
|
||||
inline bool is_v1(Version version) {
|
||||
return (version == Version::DC_NTE) || (version == Version::DC_V1_12_2000_PROTOTYPE) || (version == Version::DC_V1);
|
||||
return (version == Version::DC_NTE) || (version == Version::DC_V1_11_2000_PROTOTYPE) || (version == Version::DC_V1);
|
||||
}
|
||||
inline bool is_v2(Version version) {
|
||||
return (version == Version::DC_V2) || (version == Version::PC_V2) || (version == Version::GC_NTE);
|
||||
@@ -56,7 +56,7 @@ inline bool is_ep3(Version version) {
|
||||
|
||||
inline bool is_dc(Version version) {
|
||||
return (version == Version::DC_NTE) ||
|
||||
(version == Version::DC_V1_12_2000_PROTOTYPE) ||
|
||||
(version == Version::DC_V1_11_2000_PROTOTYPE) ||
|
||||
(version == Version::DC_V1) ||
|
||||
(version == Version::DC_V2);
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ WordSelectTable::WordSelectTable(const JSON& json) {
|
||||
uint16_t WordSelectTable::Token::value_for_version(Version version) const {
|
||||
switch (version) {
|
||||
case Version::DC_NTE:
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
case Version::DC_V2:
|
||||
return this->dc_value;
|
||||
@@ -76,7 +76,7 @@ WordSelectMessage WordSelectTable::translate(
|
||||
const std::vector<size_t>* index;
|
||||
switch (from_version) {
|
||||
case Version::DC_NTE:
|
||||
case Version::DC_V1_12_2000_PROTOTYPE:
|
||||
case Version::DC_V1_11_2000_PROTOTYPE:
|
||||
case Version::DC_V1:
|
||||
case Version::DC_V2:
|
||||
index = &this->dc_index;
|
||||
|
||||
Reference in New Issue
Block a user