diff --git a/src/ReceiveCommands.cc b/src/ReceiveCommands.cc index d164c997..99e8990b 100644 --- a/src/ReceiveCommands.cc +++ b/src/ReceiveCommands.cc @@ -2860,7 +2860,14 @@ static void on_06(shared_ptr c, uint16_t, uint32_t, string& data) { } if (l->battle_record && l->battle_record->battle_in_progress()) { - auto prepared_message = prepare_chat_data(c->version(), c->language(), p->disp.name.decode(c->language()), text, private_flags); + auto prepared_message = prepare_chat_data( + c->version(), + c->flags & Client::Flag::IS_DC_TRIAL_EDITION, + c->language(), + c->lobby_client_id, + p->disp.name.decode(c->language()), + text, + private_flags); l->battle_record->add_chat_message(c->license->serial_number, std::move(prepared_message)); } } diff --git a/src/SendCommands.cc b/src/SendCommands.cc index 0e8f6d7a..fb4ef6b0 100644 --- a/src/SendCommands.cc +++ b/src/SendCommands.cc @@ -679,10 +679,32 @@ void send_patch_file(shared_ptr c, shared_ptr f) { //////////////////////////////////////////////////////////////////////////////// // message functions -void send_text(Channel& ch, StringWriter& w, uint16_t command, const string& text, bool should_add_color) { +enum class ColorMode { + NONE, + ADD, + STRIP, +}; + +static void send_text( + Channel& ch, + StringWriter& w, + uint16_t command, + const string& text, + ColorMode color_mode) { bool is_w = (ch.version == GameVersion::PC || ch.version == GameVersion::BB || ch.version == GameVersion::PATCH); - w.write(tt_encode_marked_optional(should_add_color ? add_color(text) : text, ch.language, is_w)); + switch (color_mode) { + case ColorMode::NONE: + w.write(tt_encode_marked_optional(text, ch.language, is_w)); + break; + case ColorMode::ADD: + w.write(tt_encode_marked_optional(add_color(text), ch.language, is_w)); + break; + case ColorMode::STRIP: + w.write(tt_encode_marked_optional(strip_color(text), ch.language, is_w)); + break; + } + if (is_w) { w.put_u16(0); } else { @@ -695,15 +717,15 @@ void send_text(Channel& ch, StringWriter& w, uint16_t command, const string& tex ch.send(command, 0x00, w.str()); } -void send_text(Channel& ch, uint16_t command, const string& text, bool should_add_color) { +static void send_text(Channel& ch, uint16_t command, const string& text, ColorMode color_mode) { StringWriter w; - send_text(ch, w, command, text, should_add_color); + send_text(ch, w, command, text, color_mode); } -void send_header_text(Channel& ch, uint16_t command, uint32_t guild_card_number, const string& text, bool should_add_color) { +static void send_header_text(Channel& ch, uint16_t command, uint32_t guild_card_number, const string& text, ColorMode color_mode) { StringWriter w; w.put(SC_TextHeader_01_06_11_B0_EE({0, guild_card_number})); - send_text(ch, w, command, text, should_add_color); + send_text(ch, w, command, text, color_mode); } void send_message_box(shared_ptr c, const string& text) { @@ -724,7 +746,7 @@ void send_message_box(shared_ptr c, const string& text) { default: throw logic_error("invalid game version"); } - send_text(c->channel, command, text, true); + send_text(c->channel, command, text, (c->flags & Client::Flag::IS_DC_TRIAL_EDITION) ? ColorMode::STRIP : ColorMode::ADD); } void send_ep3_timed_message_box(Channel& ch, uint32_t frames, const string& message) { @@ -740,31 +762,35 @@ void send_ep3_timed_message_box(Channel& ch, uint32_t frames, const string& mess } void send_lobby_name(shared_ptr c, const string& text) { - send_text(c->channel, 0x8A, text, false); + send_text(c->channel, 0x8A, text, ColorMode::NONE); } void send_quest_info(shared_ptr c, const string& text, bool is_download_quest) { - send_text(c->channel, is_download_quest ? 0xA5 : 0xA3, text, true); + send_text( + c->channel, is_download_quest ? 0xA5 : 0xA3, text, + (c->flags & Client::Flag::IS_DC_TRIAL_EDITION) ? ColorMode::STRIP : ColorMode::ADD); } void send_lobby_message_box(shared_ptr c, const string& text) { - send_header_text(c->channel, 0x01, 0, text, true); + send_header_text(c->channel, 0x01, 0, text, (c->flags & Client::Flag::IS_DC_TRIAL_EDITION) ? ColorMode::STRIP : ColorMode::ADD); } void send_ship_info(shared_ptr c, const string& text) { - send_header_text(c->channel, 0x11, 0, text, true); + send_header_text(c->channel, 0x11, 0, text, (c->flags & Client::Flag::IS_DC_TRIAL_EDITION) ? ColorMode::STRIP : ColorMode::ADD); } void send_ship_info(Channel& ch, const string& text) { - send_header_text(ch, 0x11, 0, text, true); + send_header_text(ch, 0x11, 0, text, ColorMode::ADD); } void send_text_message(Channel& ch, const string& text) { - send_header_text(ch, 0xB0, 0, text, true); + send_header_text(ch, 0xB0, 0, text, ColorMode::ADD); } void send_text_message(shared_ptr c, const string& text) { - send_header_text(c->channel, 0xB0, 0, text, true); + if (!(c->flags & Client::Flag::IS_DC_TRIAL_EDITION)) { + send_header_text(c->channel, 0xB0, 0, text, ColorMode::ADD); + } } void send_text_message(shared_ptr l, const string& text) { @@ -797,26 +823,37 @@ __attribute__((format(printf, 2, 3))) void send_ep3_text_message_printf(shared_p } } -string prepare_chat_data(GameVersion version, uint8_t language, const string& from_name, const string& text, char private_flags) { +string prepare_chat_data( + GameVersion version, + bool is_nte, + uint8_t language, + uint8_t from_client_id, + const string& from_name, + const string& text, + char private_flags) { string data; - if ((version == GameVersion::BB) || (version == GameVersion::PC)) { - if (version == GameVersion::BB) { - data.append("\tJ"); - } - data.append(from_name); + + if (version == GameVersion::BB) { + data.append("\tJ"); + } + data.append(from_name); + if (is_nte) { + data.append(string_printf(">%X", from_client_id)); + } else { data.append(1, '\t'); - if (private_flags) { - data.append(1, static_cast(private_flags)); - } + } + if (private_flags) { + data.append(1, static_cast(private_flags)); + } + + if ((version == GameVersion::BB) || (version == GameVersion::PC)) { data.append(language ? "\tE" : "\tJ"); data.append(text); return tt_utf8_to_utf16(data); + } else if (is_nte) { + data.append(tt_utf8_to_sjis(text)); + return data; } else { - data.append(from_name); - data.append(1, '\t'); - if (private_flags) { - data.append(1, static_cast(private_flags)); - } data.append(tt_encode_marked(text, language, false)); return data; } @@ -830,9 +867,9 @@ void send_chat_message_from_client(Channel& ch, const string& text, char private string effective_text; effective_text.push_back(private_flags); effective_text += text; - send_header_text(ch, 0x06, 0, effective_text, false); + send_header_text(ch, 0x06, 0, effective_text, ColorMode::NONE); } else { - send_header_text(ch, 0x06, 0, text, false); + send_header_text(ch, 0x06, 0, text, ColorMode::NONE); } } @@ -859,7 +896,15 @@ void send_prepared_chat_message(shared_ptr l, uint32_t from_guild_card_nu } void send_chat_message(shared_ptr c, uint32_t from_guild_card_number, const string& from_name, const string& text, char private_flags) { - send_prepared_chat_message(c, from_guild_card_number, prepare_chat_data(c->version(), c->language(), from_name, text, private_flags)); + string prepared_data = prepare_chat_data( + c->version(), + c->flags & Client::Flag::IS_DC_TRIAL_EDITION, + c->language(), + c->lobby_client_id, + from_name, + text, + private_flags); + send_prepared_chat_message(c, from_guild_card_number, prepared_data); } template diff --git a/src/SendCommands.hh b/src/SendCommands.hh index 733abae0..1e24cbf0 100644 --- a/src/SendCommands.hh +++ b/src/SendCommands.hh @@ -189,7 +189,9 @@ void send_text_message(std::shared_ptr s, const std::string& text); std::string prepare_chat_data( GameVersion version, + bool is_nte, uint8_t language, + uint8_t from_client_id, const std::string& from_name, const std::string& text, char private_flags); diff --git a/src/Text.cc b/src/Text.cc index a66aa210..ba315f2b 100644 --- a/src/Text.cc +++ b/src/Text.cc @@ -132,7 +132,7 @@ TextTranscoder tt_utf8_to_utf16("UTF-16LE", "UTF-8"); TextTranscoder tt_ascii_to_utf8("UTF-8", "ASCII"); TextTranscoder tt_utf8_to_ascii("ASCII", "UTF-8"); -std::string tt_encode_marked_optional(const std::string& utf8, uint8_t default_language, bool is_utf16) { +string tt_encode_marked_optional(const string& utf8, uint8_t default_language, bool is_utf16) { if (is_utf16) { return tt_utf8_to_utf16(utf8); } else { @@ -152,7 +152,7 @@ std::string tt_encode_marked_optional(const std::string& utf8, uint8_t default_l } } -std::string tt_encode_marked(const std::string& utf8, uint8_t default_language, bool is_utf16) { +string tt_encode_marked(const string& utf8, uint8_t default_language, bool is_utf16) { if (is_utf16) { return tt_utf8_to_utf16((default_language ? "\tE" : "\tJ") + utf8); } else { @@ -172,7 +172,7 @@ std::string tt_encode_marked(const std::string& utf8, uint8_t default_language, } } -std::string tt_decode_marked(const std::string& data, uint8_t default_language, bool is_utf16) { +string tt_decode_marked(const string& data, uint8_t default_language, bool is_utf16) { if (is_utf16) { string ret = tt_utf16_to_utf8(data); if (ret.size() >= 2 && ret[0] == '\t' && (ret[1] == 'E' || ret[1] == 'J')) { @@ -286,8 +286,21 @@ void add_color(StringWriter& w, const char* src, size_t max_input_chars) { w.put(0); } -std::string add_color(const std::string& s) { +string add_color(const string& s) { StringWriter w; add_color(w, s.data(), s.size()); return std::move(w.str()); } + +string strip_color(const string& s) { + string ret; + for (size_t r = 0; r < s.size(); r++) { + if ((s[r] == '$' || s[r] == '\t') && + (s[r + 1] == 'C') && (((s[r + 2] >= '0') && (s[r + 2] <= '9')) || (s[r + 2] == 'G') || (s[r + 2] == 'a'))) { + r += 2; + } else { + ret.push_back(s[r]); + } + } + return ret; +} diff --git a/src/Text.hh b/src/Text.hh index 017ee16e..86b46c25 100644 --- a/src/Text.hh +++ b/src/Text.hh @@ -521,3 +521,5 @@ std::string add_color(const std::string& s); size_t add_color_inplace(char* a, size_t max_chars); void add_color_inplace(std::string& s); + +std::string strip_color(const std::string& s);