diff options
Diffstat (limited to 'src/char')
-rw-r--r-- | src/char/char.cpp | 645 | ||||
-rw-r--r-- | src/char/char.hpp | 25 | ||||
-rw-r--r-- | src/char/consts.hpp | 31 | ||||
-rw-r--r-- | src/char/fwd.hpp | 25 | ||||
-rw-r--r-- | src/char/globals.cpp | 68 | ||||
-rw-r--r-- | src/char/globals.hpp | 59 | ||||
-rw-r--r-- | src/char/int_party.cpp | 159 | ||||
-rw-r--r-- | src/char/int_party.hpp | 11 | ||||
-rw-r--r-- | src/char/int_storage.cpp | 55 | ||||
-rw-r--r-- | src/char/int_storage.hpp | 13 | ||||
-rw-r--r-- | src/char/inter.cpp | 80 | ||||
-rw-r--r-- | src/char/inter.hpp | 20 | ||||
-rw-r--r-- | src/char/main.cpp | 2 |
13 files changed, 470 insertions, 723 deletions
diff --git a/src/char/char.cpp b/src/char/char.cpp index d5e887b..ed9e369 100644 --- a/src/char/char.cpp +++ b/src/char/char.cpp @@ -49,13 +49,13 @@ #include "../generic/array.hpp" #include "../io/cxxstdio.hpp" -#include "../io/cxxstdio_enums.hpp" +#include "../io/extract.hpp" #include "../io/lock.hpp" #include "../io/read.hpp" +#include "../io/span.hpp" #include "../io/tty.hpp" #include "../io/write.hpp" -#include "../net/packets.hpp" #include "../net/socket.hpp" #include "../net/timer.hpp" @@ -66,15 +66,23 @@ #include "../proto2/char-user.hpp" #include "../mmo/config_parse.hpp" -#include "../mmo/core.hpp" -#include "../mmo/extract.hpp" +#include "../mmo/cxxstdio_enums.hpp" #include "../mmo/extract_enums.hpp" #include "../mmo/human_time_diff.hpp" -#include "../mmo/mmo.hpp" -#include "../mmo/utils.hpp" #include "../mmo/version.hpp" +#include "../high/core.hpp" +#include "../high/extract_mmo.hpp" +#include "../high/mmo.hpp" +#include "../high/utils.hpp" + +#include "../wire/packets.hpp" + +#include "char_conf.hpp" +#include "char_lan_conf.hpp" +#include "globals.hpp" #include "inter.hpp" +#include "inter_conf.hpp" #include "int_party.hpp" #include "int_storage.hpp" @@ -83,58 +91,8 @@ namespace tmwa { -static -Array<struct mmo_map_server, MAX_MAP_SERVERS> server; -static -Array<Session *, MAX_MAP_SERVERS> server_session; -static -Array<int, MAX_MAP_SERVERS> server_freezeflag; // Map-server anti-freeze system. Counter. 5 ok, 4...0 freezed -static -int anti_freeze_enable = 0; -static -std::chrono::seconds anti_freeze_interval = 6_s; - -constexpr -std::chrono::milliseconds DEFAULT_AUTOSAVE_INTERVAL = - 5_min; - -static -Session *login_session, *char_session; -static -AccountName userid; -static -AccountPass passwd; -static -ServerName server_name; -static -CharName wisp_server_name = stringish<CharName>("Server"_s); -static -IP4Address login_ip; -static -int login_port = 6900; -static -IP4Address char_ip; -static -int char_port = 6121; -static -AString char_txt; -static -CharName unknown_char_name = stringish<CharName>("Unknown"_s); -static -AString char_log_filename = "log/char.log"_s; -//Added for lan support -static -IP4Address lan_map_ip = IP4_LOCALHOST; -static -IP4Mask lan_subnet = IP4Mask(IP4_LOCALHOST, IP4_BROADCAST); -static -int char_name_option = 0; // Option to know which letters/symbols are authorised in the name of a character (0: all, 1: only those in char_name_letters, 2: all EXCEPT those in char_name_letters) by [Yor] -static -std::bitset<256> char_name_letters; // list of letters/symbols authorised (or not) in a character name. by [Yor] -static constexpr -GmLevel default_gm_level = GmLevel::from(0_u32); - - +namespace char_ +{ struct char_session_data : SessionData { AccountId account_id; @@ -142,69 +100,16 @@ struct char_session_data : SessionData SEX sex; unsigned short packet_tmw_version; AccountEmail email; - TimeT connect_until_time; }; +} // namespace char_ void SessionDeleter::operator()(SessionData *sd) { - really_delete1 static_cast<char_session_data *>(sd); + really_delete1 static_cast<char_::char_session_data *>(sd); } -struct AuthFifoEntry +namespace char_ { - AccountId account_id; - CharId char_id; - int login_id1, login_id2; - IP4Address ip; - int delflag; - SEX sex; - unsigned short packet_tmw_version; - TimeT connect_until_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited) -}; -static -std::array<AuthFifoEntry, 256> auth_fifo; -static -auto auth_fifo_iter = auth_fifo.begin(); - -static -int check_ip_flag = 1; // It's to check IP of a player between char-server and other servers (part of anti-hacking system) - -static -CharId char_id_count = wrap<CharId>(150000); -static -std::vector<CharPair> char_keys; -static -int max_connect_user = 0; -static -std::chrono::milliseconds autosave_time = DEFAULT_AUTOSAVE_INTERVAL; - -// Initial position (it's possible to set it in conf file) -static -Point start_point = { {"001-1.gat"_s}, 273, 354 }; - -static -std::vector<GM_Account> gm_accounts; - -// online players by [Yor] -static -AString online_txt_filename = "online.txt"_s; -static -AString online_html_filename = "online.html"_s; -static -int online_sorting_option = 0; // sorting option to display online players in online files -static -int online_refresh_html = 20; // refresh time (in sec) of the html file in the explorer -static -GmLevel online_gm_display_min_level = GmLevel::from(20_u32); // minimum GM level to display 'GM' when we want to display it - -static -std::vector<Session *> online_chars; // same size of char_keys, and id value of current server (or -1) -static -TimeT update_online; // to update online files when we receiving information from a server (not less than 8 seconds) - -static -pid_t pid = 0; // For forked DB writes - auto iter_map_sessions() -> decltype(filter_iterator<Session *>(std::declval<Array<Session *, MAX_MAP_SERVERS> *>())) { @@ -250,7 +155,7 @@ void delete_frommap(Session *sess) //------------------------------ void char_log(XString line) { - io::AppendFile logfp(char_log_filename, true); + io::AppendFile logfp(char_conf.char_log_filename, true); if (!logfp.is_open()) return; log_with_timestamp(logfp, line); @@ -327,7 +232,7 @@ AString mmo_char_tostr(struct CharPair *cp) // on multi-map server, sometimes it's posssible that last_point become void. (reason???) We check that to not lost character at restart. if (!p->last_point.map_) { - p->last_point = start_point; + p->last_point = char_conf.start_point; } MString str_p; @@ -414,12 +319,6 @@ AString mmo_char_tostr(struct CharPair *cp) return AString(str_p); } -static -bool extract(XString str, Point *p) -{ - return extract(str, record<','>(&p->map_, &p->x, &p->y)); -} - struct skill_loader { SkillID id; @@ -428,7 +327,7 @@ struct skill_loader }; static -bool extract(XString str, struct skill_loader *s) +bool impl_extract(XString str, struct skill_loader *s) { uint32_t flags_and_level; if (!extract(str, @@ -438,13 +337,16 @@ bool extract(XString str, struct skill_loader *s) s->flags = SkillFlags(flags_and_level >> 16); return true; } +} // namespace char //------------------------------------------------------------------------- // Function to set the character from the line (at read of characters file) //------------------------------------------------------------------------- static -bool extract(XString str, CharPair *cp) +bool impl_extract(XString str, CharPair *cp) { + using namespace tmwa::char_; + CharKey *k = &cp->key; CharData *p = cp->data.get(); @@ -489,7 +391,7 @@ bool extract(XString str, CharPair *cp) else if (!extract(hair_style, &p->hair)) return false; - if (wisp_server_name == k->name) + if (WISP_SERVER_NAME == k->name) return false; // TODO replace *every* lookup with a map lookup @@ -532,6 +434,8 @@ bool extract(XString str, CharPair *cp) return true; } +namespace char_ +{ //--------------------------------- // Function to read characters file //--------------------------------- @@ -541,11 +445,11 @@ int mmo_char_init(void) char_keys.clear(); online_chars.clear(); - io::ReadFile in(char_txt); + io::ReadFile in(char_conf.char_txt); if (!in.is_open()) { - PRINTF("Characters file not found: %s.\n"_fmt, char_txt); - CHAR_LOG("Characters file not found: %s.\n"_fmt, char_txt); + PRINTF("Characters file not found: %s.\n"_fmt, char_conf.char_txt); + CHAR_LOG("Characters file not found: %s.\n"_fmt, char_conf.char_txt); CHAR_LOG("Id for the next created character: %d.\n"_fmt, char_id_count); return 0; @@ -583,9 +487,9 @@ int mmo_char_init(void) } PRINTF("mmo_char_init: %zu characters read in %s.\n"_fmt, - char_keys.size(), char_txt); + char_keys.size(), char_conf.char_txt); CHAR_LOG("mmo_char_init: %zu characters read in %s.\n"_fmt, - char_keys.size(), char_txt); + char_keys.size(), char_conf.char_txt); CHAR_LOG("Id for the next created character: %d.\n"_fmt, char_id_count); @@ -599,7 +503,7 @@ int mmo_char_init(void) static void mmo_char_sync(void) { - io::WriteLock fp(char_txt); + io::WriteLock fp(char_conf.char_txt); if (!fp.is_open()) { PRINTF("WARNING: Server can't not save characters.\n"_fmt); @@ -687,28 +591,18 @@ CharPair *make_new_char(Session *s, CharName name, const Stats6& stats, uint8_t } // Check Authorised letters/symbols in the name of the character - if (char_name_option == 1) { // only letters/symbols in char_name_letters are authorised for (uint8_t c : name.to__actual()) - if (!char_name_letters[c]) + { + if (!char_conf.char_name_letters[c]) { CHAR_LOG("Make new char error (invalid letter in the name): (connection #%d, account: %d), name: %s, invalid letter: %c.\n"_fmt, s, sd->account_id, name, c); return nullptr; } + } } - else if (char_name_option == 2) - { - // letters/symbols in char_name_letters are forbidden - for (uint8_t c : name.to__actual()) - if (char_name_letters[c]) - { - CHAR_LOG("Make new char error (invalid letter in the name): (connection #%d, account: %d), name: %s, invalid letter: %c.\n"_fmt, - s, sd->account_id, name, c); - return nullptr; - } - } // else, all letters/symbols are authorised (except control char removed before) // TODO this comment is obsolete // this is why it needs to be unsigned @@ -763,10 +657,10 @@ CharPair *make_new_char(Session *s, CharName name, const Stats6& stats, uint8_t } } - if (wisp_server_name == name) + if (WISP_SERVER_NAME == name) { CHAR_LOG("Make new char error (name used is wisp name for server): (connection #%d, account: %d) slot %d, name: %s (actual name whisper server: %s), stats: %d+%d+%d+%d+%d+%d=%d, hair: %d, hair color: %d.\n"_fmt, - s, sd->account_id, slot, name, wisp_server_name, + s, sd->account_id, slot, name, WISP_SERVER_NAME, stats.str, stats.agi, stats.vit, stats.int_, stats.dex, stats.luk, stats.str + stats.agi + stats.vit + stats.int_ + stats.dex + stats.luk, hair_style, hair_color); @@ -807,7 +701,7 @@ CharPair *make_new_char(Session *s, CharName name, const Stats6& stats, uint8_t cd.sp = cd.max_sp; cd.status_point = 0; cd.skill_point = 0; - cd.option = static_cast<Option>(0x0000); // Option is only declared + cd.option = static_cast<Opt0>(0x0000); // Opt0 is only declared cd.karma = 0; cd.manner = 0; cd.party_id = PartyId(); @@ -821,8 +715,8 @@ CharPair *make_new_char(Session *s, CharName name, const Stats6& stats, uint8_t cd.head_top = ItemNameId(); cd.head_mid = ItemNameId(); cd.head_bottom = ItemNameId(); - cd.last_point = start_point; - cd.save_point = start_point; + cd.last_point = char_conf.start_point; + cd.save_point = char_conf.start_point; char_keys.push_back(std::move(cp)); online_chars.push_back(nullptr); @@ -836,10 +730,10 @@ static void create_online_files(void) { // write files - io::WriteFile fp(online_txt_filename); + io::WriteFile fp(char_conf.online_txt_filename); if (fp.is_open()) { - io::WriteFile fp2(online_html_filename); + io::WriteFile fp2(char_conf.online_html_filename); if (fp2.is_open()) { // get time @@ -847,15 +741,15 @@ void create_online_files(void) stamp_time(timetemp); // write heading FPRINTF(fp2, "<HTML>\n"_fmt); - FPRINTF(fp2, " <META http-equiv=\"Refresh\" content=\"%d\">\n"_fmt, online_refresh_html); // update on client explorer every x seconds + FPRINTF(fp2, " <META http-equiv=\"Refresh\" content=\"%d\">\n"_fmt, char_conf.online_refresh_html); // update on client explorer every x seconds FPRINTF(fp2, " <HEAD>\n"_fmt); FPRINTF(fp2, " <TITLE>Online Players on %s</TITLE>\n"_fmt, - server_name); + char_conf.server_name); FPRINTF(fp2, " </HEAD>\n"_fmt); FPRINTF(fp2, " <BODY>\n"_fmt); FPRINTF(fp2, " <H3>Online Players on %s (%s):</H3>\n"_fmt, - server_name, timetemp); - FPRINTF(fp, "Online Players on %s (%s):\n"_fmt, server_name, timetemp); + char_conf.server_name, timetemp); + FPRINTF(fp, "Online Players on %s (%s):\n"_fmt, char_conf.server_name, timetemp); FPRINTF(fp, "\n"_fmt); int players = 0; @@ -891,14 +785,14 @@ void create_online_files(void) // without/with 'GM' display GmLevel gml = isGM(cd.key.account_id); { - if (gml.satisfies(online_gm_display_min_level)) + if (gml.satisfies(char_conf.online_gm_display_min_level)) FPRINTF(fp, "%-24s (GM) "_fmt, cd.key.name); else FPRINTF(fp, "%-24s "_fmt, cd.key.name); } // name of the character in the html (no < >, because that create problem in html code) FPRINTF(fp2, " <td>"_fmt); - if (gml.satisfies(online_gm_display_min_level)) + if (gml.satisfies(char_conf.online_gm_display_min_level)) FPRINTF(fp2, "<b>"_fmt); for (char c : cd.key.name.to__actual()) { @@ -918,7 +812,7 @@ void create_online_files(void) break; }; } - if (gml.satisfies(online_gm_display_min_level)) + if (gml.satisfies(char_conf.online_gm_display_min_level)) FPRINTF(fp2, "</b> (GM)"_fmt); FPRINTF(fp2, "</td>\n"_fmt); } @@ -1278,13 +1172,12 @@ void parse_tologin(Session *ls) fixed_6c.code = 0x42; send_fpacket<0x006c, 3>(s2, fixed_6c); } - else if (max_connect_user == 0 - || count_users() < max_connect_user) + else if (char_conf.max_connect_user == 0 + || count_users() < char_conf.max_connect_user) { sd->email = stringish<AccountEmail>(fixed.email); if (!e_mail_check(sd->email)) sd->email = DEFAULT_EMAIL; - sd->connect_until_time = fixed.connect_until; // send characters to player mmo_char_send006b(s2, sd); } @@ -1323,7 +1216,6 @@ void parse_tologin(Session *ls) sd->email = fixed.email; if (!e_mail_check(sd->email)) sd->email = DEFAULT_EMAIL; - sd->connect_until_time = fixed.connect_until; break; } } @@ -1331,28 +1223,6 @@ void parse_tologin(Session *ls) break; } - case 0x2721: // gm reply - { - Packet_Fixed<0x2721> fixed; - rv = recv_fpacket<0x2721, 10>(ls, fixed); - if (rv != RecvResult::Complete) - break; - - { - AccountId acc = fixed.account_id; - GmLevel gml = fixed.gm_level; - - Packet_Fixed<0x2b0b> fixed_2b; - fixed_2b.account_id = acc; - fixed_2b.gm_level = gml; - for (Session *ss : iter_map_sessions()) - { - send_fpacket<0x2b0b, 10>(ss, fixed_2b); - } - } - break; - } - case 0x2723: // changesex reply (modified by [Yor]) { Packet_Fixed<0x2723> fixed; @@ -1481,65 +1351,6 @@ void parse_tologin(Session *ls) break; } - case 0x7924: - { // [Fate] Itemfrob package: forwarded from login-server - Packet_Fixed<0x7924> fixed; - rv = recv_fpacket<0x7924, 10>(ls, fixed); - if (rv != RecvResult::Complete) - break; - - ItemNameId source_id = fixed.source_item_id; - ItemNameId dest_id = fixed.dest_item_id; - - Packet_Fixed<0x2afa> fixed_fa; - fixed_fa.source_item_id = source_id; - fixed_fa.dest_item_id = dest_id; - - // forward package to map servers - for (Session *ss : iter_map_sessions()) - { - send_fpacket<0x2afa, 10>(ss, fixed_fa); - } - - for (CharPair& cp : char_keys) - { - CharKey *k = &cp.key; - CharData& cd = *cp.data.get(); - CharData *c = &cd; - Storage *s = account2storage(k->account_id); - int changes = 0; -#define FIX(v) if (v == source_id) {v = dest_id; ++changes; } - for (IOff0 j : IOff0::iter()) - { - FIX(c->inventory[j].nameid); - } - // used to FIX cart, but it's no longer supported - // FIX(c->weapon); - FIX(c->shield); - FIX(c->head_top); - FIX(c->head_mid); - FIX(c->head_bottom); - - if (s) - { - for (SOff0 j : SOff0::iter()) - { - FIX(s->storage_[j].nameid); - } - } -#undef FIX - if (changes) - CHAR_LOG("itemfrob(%d -> %d): `%s'(%d, account %d): changed %d times\n"_fmt, - source_id, dest_id, k->name, k->char_id, - k->account_id, changes); - - } - - mmo_char_sync(); - inter_storage_save(); - break; - } - // Account deletion notification (from login-server) case 0x2730: { @@ -1737,22 +1548,6 @@ void parse_frommap(Session *ms) { switch (packet_id) { - // request from map-server to reload GM accounts. Transmission to login-server (by Yor) - case 0x2af7: - { - Packet_Fixed<0x2af7> fixed; - rv = recv_fpacket<0x2af7, 2>(ms, fixed); - if (rv != RecvResult::Complete) - break; - - if (login_session) - { // don't send request if no login-server - Packet_Fixed<0x2709> fixed_09; - send_fpacket<0x2709, 2>(login_session, fixed_09); - } - break; - } - // Receiving map names list from the map-server case 0x2afa: { @@ -1781,7 +1576,6 @@ void parse_frommap(Session *ms) Packet_Fixed<0x2afb> fixed_fb; fixed_fb.unknown = 0; - fixed_fb.whisper_name = wisp_server_name; send_fpacket<0x2afb, 27>(ms, fixed_fb); { @@ -1857,7 +1651,7 @@ void parse_frommap(Session *ms) afi.login_id1 == login_id1 && // here, it's the only area where it's possible that we doesn't know login_id2 (map-server asks just after 0x72 packet, that doesn't given the value) (afi.login_id2 == login_id2 || login_id2 == 0) && // relate to the versions higher than 18 - (!check_ip_flag || afi.ip == ip) + afi.ip == ip && !afi.delflag) { CharPair *cp = nullptr; @@ -1878,7 +1672,6 @@ void parse_frommap(Session *ms) Packet_Payload<0x2afd> payload_fd; // not file descriptor payload_fd.account_id = account_id; payload_fd.login_id2 = afi.login_id2; - payload_fd.connect_until = afi.connect_until_time; cd->sex = afi.sex; payload_fd.packet_tmw_version = afi.packet_tmw_version; FPRINTF(stderr, @@ -1912,7 +1705,7 @@ void parse_frommap(Session *ms) server[id].users = head.users; assert (head.users == repeat.size()); - if (anti_freeze_enable) + if (char_conf.anti_freeze_enable) server_freezeflag[id] = 5; // Map anti-freeze system. Counter. 5 ok, 4...0 freezed // remove all previously online players of the server for (Session *& oci : online_chars) @@ -1984,7 +1777,6 @@ void parse_frommap(Session *ms) auth_fifo_iter->login_id1 = fixed.login_id1; auth_fifo_iter->login_id2 = fixed.login_id2; auth_fifo_iter->delflag = 2; - auth_fifo_iter->connect_until_time = TimeT(); // unlimited/unknown time by default (not display in map-server) auth_fifo_iter->ip = fixed.ip; auth_fifo_iter++; @@ -2023,7 +1815,6 @@ void parse_frommap(Session *ms) auth_fifo_iter->char_id = fixed.char_id; auth_fifo_iter->delflag = 0; auth_fifo_iter->sex = fixed.sex; - auth_fifo_iter->connect_until_time = TimeT(); // unlimited/unknown time by default (not display in map-server) auth_fifo_iter->ip = fixed.client_ip; // default, if not found in the loop @@ -2044,33 +1835,6 @@ void parse_frommap(Session *ms) break; } - // it is a request to become GM - case 0x2b0a: - { - Packet_Head<0x2b0a> head; - AString repeat; - rv = recv_vpacket<0x2b0a, 8, 1>(ms, head, repeat); - if (rv != RecvResult::Complete) - break; - - AccountId account_id = head.account_id; - if (login_session) - { // don't send request if no login-server - Packet_Head<0x2720> head_20; - head_20.account_id = account_id; - AString& repeat_20 = repeat; - send_vpacket<0x2720, 8, 1>(login_session, head_20, repeat_20); - } - else - { - Packet_Fixed<0x2b0b> fixed_0b; - fixed_0b.account_id = account_id; - fixed_0b.gm_level = GmLevel(); - send_fpacket<0x2b0b, 10>(ms, fixed_0b); - } - break; - } - // Map server send information to change an email of an account -> login-server case 0x2b0c: { @@ -2336,7 +2100,7 @@ int search_mapserver(XString map) static int lan_ip_check(IP4Address addr) { - bool lancheck = lan_subnet.covers(addr); + bool lancheck = char_lan_conf.lan_subnet.covers(addr); PRINTF("LAN test (result): %s.\n"_fmt, (lancheck) ? SGR_BOLD SGR_CYAN "LAN source" SGR_RESET ""_s : SGR_BOLD SGR_GREEN "WAN source" SGR_RESET ""_s); @@ -2401,7 +2165,7 @@ void handle_x0066(Session *s, struct char_session_data *sd, uint8_t rfifob_2, IP sd->account_id, ck->char_num, ip); PRINTF("--Send IP of map-server. "_fmt); if (lan_ip_check(ip)) - fixed_71.ip = lan_map_ip; + fixed_71.ip = char_lan_conf.lan_map_ip; else fixed_71.ip = server[i].ip; fixed_71.port = server[i].port; @@ -2415,7 +2179,6 @@ void handle_x0066(Session *s, struct char_session_data *sd, uint8_t rfifob_2, IP auth_fifo_iter->login_id2 = sd->login_id2; auth_fifo_iter->delflag = 0; auth_fifo_iter->sex = sd->sex; - auth_fifo_iter->connect_until_time = sd->connect_until_time; auth_fifo_iter->ip = s->client_ip; auth_fifo_iter->packet_tmw_version = sd->packet_tmw_version; auth_fifo_iter++; @@ -2484,7 +2247,6 @@ void parse_char(Session *s) s->session_data = make_unique<char_session_data, SessionDeleter>(); sd = static_cast<char_session_data *>(s->session_data.get()); sd->email = stringish<AccountEmail>("no mail"_s); // put here a mail without '@' to refuse deletion if we don't receive the e-mail - sd->connect_until_time = TimeT(); // unknow or illimited (not displaying on map-server) } sd->account_id = account_id; sd->login_id1 = fixed.login_id1; @@ -2503,13 +2265,12 @@ void parse_char(Session *s) if (afi.account_id == sd->account_id && afi.login_id1 == sd->login_id1 && afi.login_id2 == sd->login_id2 - && (!check_ip_flag - || afi.ip == s->client_ip) + && afi.ip == s->client_ip && afi.delflag == 2) { afi.delflag = 1; - if (max_connect_user == 0 - || count_users() < max_connect_user) + if (char_conf.max_connect_user == 0 + || count_users() < char_conf.max_connect_user) { { // there is always a login server @@ -2608,7 +2369,7 @@ void parse_char(Session *s) fixed_6d.char_select.gloves = ItemNameId(); fixed_6d.char_select.cape = ItemNameId(); fixed_6d.char_select.misc1 = ItemNameId(); - fixed_6d.char_select.option = Option(); + fixed_6d.char_select.option = Opt0(); fixed_6d.char_select.unused = 0; // this was buggy until the protocol became generated @@ -2663,9 +2424,6 @@ void parse_char(Session *s) s->set_eof(); return; } - AccountEmail email = fixed.email; - if (!e_mail_check(email)) - email = DEFAULT_EMAIL; { { @@ -2723,8 +2481,8 @@ void parse_char(Session *s) } AccountName userid_ = fixed.account_name; AccountPass passwd_ = fixed.account_pass; - if (i == MAX_MAP_SERVERS || userid_ != userid - || passwd_ != passwd) + if (i == MAX_MAP_SERVERS || userid_ != char_conf.userid + || passwd_ != char_conf.passwd) { fixed_f9.code = 3; send_fpacket<0x2af9, 3>(s, fixed_f9); @@ -2734,7 +2492,7 @@ void parse_char(Session *s) fixed_f9.code = 0; s->set_parsers(SessionParsers{.func_parse= parse_frommap, .func_delete= delete_frommap}); server_session[i] = s; - if (anti_freeze_enable) + if (char_conf.anti_freeze_enable) server_freezeflag[i] = 5; // Map anti-freeze system. Counter. 5 ok, 4...0 freezed // ignore fixed.unknown server[i].ip = fixed.ip; @@ -2822,19 +2580,19 @@ void check_connect_login_server(TimerData *, tick_t) if (!login_session) { PRINTF("Attempt to connect to login-server...\n"_fmt); - login_session = make_connection(login_ip, login_port, + login_session = make_connection(char_conf.login_ip, char_conf.login_port, SessionParsers{.func_parse= parse_tologin, .func_delete= delete_tologin}); if (!login_session) return; realloc_fifo(login_session, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK); Packet_Fixed<0x2710> fixed_10; - fixed_10.account_name = userid; - fixed_10.account_pass = passwd; + fixed_10.account_name = char_conf.userid; + fixed_10.account_pass = char_conf.passwd; fixed_10.unknown = 0; - fixed_10.ip = char_ip; - fixed_10.port = char_port; - fixed_10.server_name = server_name; + fixed_10.ip = char_conf.char_ip; + fixed_10.port = char_conf.char_port; + fixed_10.server_name = char_conf.server_name; fixed_10.unknown2 = 0; fixed_10.maintenance = 0; fixed_10.is_new = 0; @@ -2842,61 +2600,13 @@ void check_connect_login_server(TimerData *, tick_t) } } -//------------------------------------------- -// Reading Lan Support configuration by [Yor] -//------------------------------------------- -static -bool char_lan_config(XString w1, ZString w2) -{ - struct hostent *h = nullptr; - - { - if (w1 == "lan_map_ip"_s) - { - // Read map-server Lan IP Address - h = gethostbyname(w2.c_str()); - if (h != nullptr) - { - lan_map_ip = IP4Address({ - static_cast<uint8_t>(h->h_addr[0]), - static_cast<uint8_t>(h->h_addr[1]), - static_cast<uint8_t>(h->h_addr[2]), - static_cast<uint8_t>(h->h_addr[3]), - }); - } - else - { - PRINTF("Bad IP value: %s\n"_fmt, w2); - return false; - } - PRINTF("LAN IP of map-server: %s.\n"_fmt, lan_map_ip); - } - else if (w1 == "subnet"_s /*backward compatibility*/ - || w1 == "lan_subnet"_s) - { - if (!extract(w2, &lan_subnet)) - { - PRINTF("Bad IP mask: %s\n"_fmt, w2); - return false; - } - PRINTF("Sub-network of the map-server: %s.\n"_fmt, - lan_subnet); - } - else - { - return false; - } - } - return true; -} - static bool lan_check() { // sub-network check of the map-server { PRINTF("LAN test of LAN IP of the map-server: "_fmt); - if (!lan_ip_check(lan_map_ip)) + if (!lan_ip_check(char_lan_conf.lan_map_ip)) { PRINTF(SGR_BOLD SGR_RED "***ERROR: LAN IP of the map-server doesn't belong to the specified Sub-network." SGR_RESET "\n"_fmt); return false; @@ -2907,161 +2617,46 @@ bool lan_check() } static -bool char_config(XString w1, ZString w2) +bool char_config(io::Spanned<XString> key, io::Spanned<ZString> value) { - struct hostent *h = nullptr; + return parse_char_conf(char_conf, key, value); +} +static +bool char_lan_config(io::Spanned<XString> key, io::Spanned<ZString> value) +{ + return parse_char_lan_conf(char_lan_conf, key, value); +} + +static +bool inter_config(io::Spanned<XString> key, io::Spanned<ZString> value) +{ + return parse_inter_conf(inter_conf, key, value); +} + +static +bool char_confs(io::Spanned<XString> key, io::Spanned<ZString> value) +{ + if (key.data == "char_conf"_s) { - if (w1 == "userid"_s) - userid = stringish<AccountName>(w2); - else if (w1 == "passwd"_s) - passwd = stringish<AccountPass>(w2); - else if (w1 == "server_name"_s) - { - server_name = stringish<ServerName>(w2); - PRINTF("%s server has been intialized\n"_fmt, w2); - } - else if (w1 == "wisp_server_name"_s) - { - if (w2.size() >= 4) - wisp_server_name = stringish<CharName>(w2); - } - else if (w1 == "login_ip"_s) - { - h = gethostbyname(w2.c_str()); - if (h != nullptr) - { - login_ip = IP4Address({ - static_cast<uint8_t>(h->h_addr[0]), - static_cast<uint8_t>(h->h_addr[1]), - static_cast<uint8_t>(h->h_addr[2]), - static_cast<uint8_t>(h->h_addr[3]), - }); - PRINTF("Login server IP address : %s -> %s\n"_fmt, - w2, login_ip); - } - else - { - PRINTF("Bad IP value: %s\n"_fmt, w2); - return false; - } - } - else if (w1 == "login_port"_s) - { - login_port = atoi(w2.c_str()); - } - else if (w1 == "char_ip"_s) - { - h = gethostbyname(w2.c_str()); - if (h != nullptr) - { - char_ip = IP4Address({ - static_cast<uint8_t>(h->h_addr[0]), - static_cast<uint8_t>(h->h_addr[1]), - static_cast<uint8_t>(h->h_addr[2]), - static_cast<uint8_t>(h->h_addr[3]), - }); - PRINTF("Character server IP address : %s -> %s\n"_fmt, - w2, char_ip); - } - else - { - PRINTF("Bad IP value: %s\n"_fmt, w2); - return false; - } - } - else if (w1 == "char_port"_s) - { - char_port = atoi(w2.c_str()); - } - else if (w1 == "char_txt"_s) - { - char_txt = w2; - } - else if (w1 == "max_connect_user"_s) - { - max_connect_user = atoi(w2.c_str()); - if (max_connect_user < 0) - max_connect_user = 0; // unlimited online players - } - else if (w1 == "check_ip_flag"_s) - { - check_ip_flag = config_switch(w2); - } - else if (w1 == "autosave_time"_s) - { - autosave_time = std::chrono::seconds(atoi(w2.c_str())); - if (autosave_time <= std::chrono::seconds::zero()) - autosave_time = DEFAULT_AUTOSAVE_INTERVAL; - } - else if (w1 == "start_point"_s) - { - extract(w2, &start_point); - } - else if (w1 == "unknown_char_name"_s) - { - unknown_char_name = stringish<CharName>(w2); - } - else if (w1 == "char_log_filename"_s) - { - char_log_filename = w2; - } - else if (w1 == "char_name_option"_s) - { - char_name_option = atoi(w2.c_str()); - } - else if (w1 == "char_name_letters"_s) - { - if (!w2) - char_name_letters.reset(); - else - for (uint8_t c : w2) - char_name_letters[c] = true; - } - else if (w1 == "online_txt_filename"_s) - { - online_txt_filename = w2; - } - else if (w1 == "online_html_filename"_s) - { - online_html_filename = w2; - } - else if (w1 == "online_sorting_option"_s) - { - online_sorting_option = atoi(w2.c_str()); - } - else if (w1 == "online_gm_display_min_level"_s) - { - // minimum GM level to display 'GM' when we want to display it - return extract(w2, &online_gm_display_min_level); - } - else if (w1 == "online_refresh_html"_s) - { - online_refresh_html = atoi(w2.c_str()); - if (online_refresh_html < 1) - online_refresh_html = 1; - } - else if (w1 == "anti_freeze_enable"_s) - { - anti_freeze_enable = config_switch(w2); - } - else if (w1 == "anti_freeze_interval"_s) - { - anti_freeze_interval = std::max( - std::chrono::seconds(atoi(w2.c_str())), - 5_s); - } - else - { - return false; - } + return load_config_file(value.data, char_config); } - - return true; + if (key.data == "char_lan_conf"_s) + { + return load_config_file(value.data, char_lan_config); + } + if (key.data == "inter_conf"_s) + { + return load_config_file(value.data, inter_config); + } + key.span.error("Unknown meta-key for char server"_s); + return false; } +} // namespace char_ void term_func(void) { + using namespace tmwa::char_; // write online players files with no player std::fill(online_chars.begin(), online_chars.end(), nullptr); create_online_files(); @@ -3079,20 +2674,9 @@ void term_func(void) CHAR_LOG("----End of char-server (normal end with closing of all files).\n"_fmt); } -static -bool char_confs(XString key, ZString value) -{ - unsigned sum = 0; - sum += char_config(key, value); - sum += char_lan_config(key, value); - sum += inter_config(key, value); - if (sum >= 2) - abort(); - return sum; -} - int do_init(Slice<ZString> argv) { + using namespace tmwa::char_; ZString argv0 = argv.pop_front(); bool loaded_config_yet = false; @@ -3121,12 +2705,12 @@ int do_init(Slice<ZString> argv) else { loaded_config_yet = true; - runflag &= load_config_file(argvi, char_confs); + runflag &= load_config_file(argvi, char_::char_confs); } } if (!loaded_config_yet) - runflag &= load_config_file("conf/tmwa-char.conf"_s, char_confs); + runflag &= load_config_file("conf/tmwa-char.conf"_s, char_::char_confs); // a newline in the log... CHAR_LOG(""_fmt); @@ -3140,7 +2724,7 @@ int do_init(Slice<ZString> argv) update_online = TimeT::now(); create_online_files(); // update online players files at start of the server - char_session = make_listen_port(char_port, SessionParsers{parse_char, delete_char}); + char_session = make_listen_port(char_conf.char_port, SessionParsers{parse_char, delete_char}); Timer(gettick() + 1_s, check_connect_login_server, @@ -3150,25 +2734,26 @@ int do_init(Slice<ZString> argv) send_users_tologin, 5_s ).detach(); - Timer(gettick() + autosave_time, + Timer(gettick() + char_conf.autosave_time, mmo_char_sync_timer, - autosave_time + char_conf.autosave_time ).detach(); - if (anti_freeze_enable > 0) + if (char_conf.anti_freeze_enable > 0) { Timer(gettick() + 1_s, map_anti_freeze_system, - anti_freeze_interval + char_conf.anti_freeze_interval ).detach(); } CHAR_LOG("The char-server is ready (Server is listening on the port %d).\n"_fmt, - char_port); + char_conf.char_port); PRINTF("The char-server is " SGR_BOLD SGR_GREEN "ready" SGR_RESET " (Server is listening on the port %d).\n\n"_fmt, - char_port); + char_conf.char_port); return 0; } +// namespace char_ ends before term_func and do_init } // namespace tmwa diff --git a/src/char/char.hpp b/src/char/char.hpp index a9c786f..4f55c04 100644 --- a/src/char/char.hpp +++ b/src/char/char.hpp @@ -22,18 +22,36 @@ #include "fwd.hpp" -#include "../strings/fwd.hpp" +#include "../ints/udl.hpp" #include "../generic/array.hpp" #include "../net/ip.hpp" -#include "../mmo/mmo.hpp" +#include "../high/mmo.hpp" + +#include "consts.hpp" namespace tmwa { -constexpr int MAX_MAP_SERVERS = 30; +namespace char_ +{ +constexpr +std::chrono::seconds DEFAULT_AUTOSAVE_INTERVAL = 5_min; +constexpr +GmLevel default_gm_level = GmLevel::from(0_u32); + +struct AuthFifoEntry +{ + AccountId account_id; + CharId char_id; + int login_id1, login_id2; + IP4Address ip; + int delflag; + SEX sex; + unsigned short packet_tmw_version; +}; struct mmo_map_server { @@ -53,4 +71,5 @@ void char_log(XString line); #define CHAR_LOG(fmt, ...) \ char_log(STRPRINTF(fmt, ## __VA_ARGS__)) +} // namespace char_ } // namespace tmwa diff --git a/src/char/consts.hpp b/src/char/consts.hpp new file mode 100644 index 0000000..e3b6c57 --- /dev/null +++ b/src/char/consts.hpp @@ -0,0 +1,31 @@ +#pragma once +// consts.hpp - Constants for tmwa-char. +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "fwd.hpp" + + +namespace tmwa +{ +namespace char_ +{ +constexpr +int MAX_MAP_SERVERS = 30; +} // namespace char_ +} // namespace tmwa diff --git a/src/char/fwd.hpp b/src/char/fwd.hpp index 31cd1ba..8086083 100644 --- a/src/char/fwd.hpp +++ b/src/char/fwd.hpp @@ -20,8 +20,31 @@ #include "../sanity.hpp" +#include "../ints/fwd.hpp" // rank 1 +#include "../strings/fwd.hpp" // rank 1 +#include "../compat/fwd.hpp" // rank 2 +#include "../generic/fwd.hpp" // rank 3 +#include "../io/fwd.hpp" // rank 4 +#include "../net/fwd.hpp" // rank 5 +#include "../mmo/fwd.hpp" // rank 6 +#include "../proto2/fwd.hpp" // rank 8 +#include "../high/fwd.hpp" // rank 9 +#include "../wire/fwd.hpp" // rank 9 +// char/fwd.hpp is rank ∞ because it is an executable + namespace tmwa { -// meh, add more when I feel like it +namespace char_ +{ + struct CharConf; + struct CharLanConf; + struct InterConf; + + struct AuthFifoEntry; + struct mmo_map_server; + + struct accreg; + // meh, add more when I feel like it +} // namespace char_ } // namespace tmwa diff --git a/src/char/globals.cpp b/src/char/globals.cpp new file mode 100644 index 0000000..6733ad5 --- /dev/null +++ b/src/char/globals.cpp @@ -0,0 +1,68 @@ +#include "globals.hpp" +// globals.cpp - Evil global variables for tmwa-char. +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "../compat/time_t.hpp" + +#include "../generic/db.hpp" + +#include "../proto2/net-Storage.hpp" + +#include "char.hpp" +#include "char_conf.hpp" +#include "char_lan_conf.hpp" +#include "inter.hpp" +#include "inter_conf.hpp" + +#include "../poison.hpp" + + +namespace tmwa +{ + namespace char_ + { + CharConf char_conf; + CharLanConf char_lan_conf; + InterConf inter_conf; + Array<mmo_map_server, MAX_MAP_SERVERS> server; + Array<Session *, MAX_MAP_SERVERS> server_session; + // Map-server anti-freeze system. Counter. 5 ok, 4...0 freezed + Array<int, MAX_MAP_SERVERS> server_freezeflag; + Session *login_session, *char_session; + const CharName WISP_SERVER_NAME = stringish<CharName>("Server"_s); + std::array<AuthFifoEntry, 256> auth_fifo; + decltype(auth_fifo)::iterator auth_fifo_iter = auth_fifo.begin(); + CharId char_id_count = wrap<CharId>(150000); + std::vector<CharPair> char_keys; + std::vector<GM_Account> gm_accounts; + // same size of char_keys, and id value of current server (or -1) + std::vector<Session *> online_chars; + // to update online files when we receiving information from a server (not less than 8 seconds) + TimeT update_online; + // For forked DB writes + pid_t pid = 0; + + Map<AccountId, accreg> accreg_db; + + Map<PartyId, PartyMost> party_db; + PartyId party_newid = wrap<PartyId>(100_u32); + + Map<AccountId, Storage> storage_db; + } // namespace char_ +} // namespace tmwa diff --git a/src/char/globals.hpp b/src/char/globals.hpp new file mode 100644 index 0000000..2df3f21 --- /dev/null +++ b/src/char/globals.hpp @@ -0,0 +1,59 @@ +#pragma once +// globals.hpp - Evil global variables for tmwa-char. +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "fwd.hpp" + +#include <sys/types.h> + +#include <array> +#include <vector> + +#include "consts.hpp" + + +namespace tmwa +{ + namespace char_ + { + extern CharConf char_conf; + extern CharLanConf char_lan_conf; + extern InterConf inter_conf; + extern Array<mmo_map_server, MAX_MAP_SERVERS> server; + extern Array<Session *, MAX_MAP_SERVERS> server_session; + extern Array<int, MAX_MAP_SERVERS> server_freezeflag; + extern Session *login_session, *char_session; + extern const CharName WISP_SERVER_NAME; + extern std::array<AuthFifoEntry, 256> auth_fifo; + extern AuthFifoEntry *auth_fifo_iter; + extern CharId char_id_count; + extern std::vector<CharPair> char_keys; + extern std::vector<GM_Account> gm_accounts; + extern std::vector<Session *> online_chars; + extern TimeT update_online; + extern pid_t pid; + + extern Map<AccountId, accreg> accreg_db; + + extern Map<PartyId, PartyMost> party_db; + extern PartyId party_newid; + + extern Map<AccountId, Storage> storage_db; + } // namespace char_ +} // namespace tmwa diff --git a/src/char/int_party.cpp b/src/char/int_party.cpp index c9ab5a4..5ee65ad 100644 --- a/src/char/int_party.cpp +++ b/src/char/int_party.cpp @@ -29,33 +29,32 @@ #include "../generic/db.hpp" #include "../io/cxxstdio.hpp" +#include "../io/extract.hpp" #include "../io/lock.hpp" #include "../io/read.hpp" #include "../io/write.hpp" -#include "../net/packets.hpp" - #include "../proto2/char-map.hpp" -#include "../mmo/extract.hpp" #include "../mmo/ids.hpp" -#include "../mmo/mmo.hpp" + +#include "../high/extract_mmo.hpp" +#include "../high/mmo.hpp" + +#include "../wire/packets.hpp" #include "char.hpp" +#include "globals.hpp" #include "inter.hpp" +#include "inter_conf.hpp" #include "../poison.hpp" namespace tmwa { -AString party_txt = "save/party.txt"_s; - -static -Map<PartyId, PartyMost> party_db; -static -PartyId party_newid = wrap<PartyId>(100_u32); - +namespace char_ +{ static void mapif_party_broken(PartyId party_id, int flag); static @@ -89,9 +88,10 @@ AString inter_party_tostr(PartyPair p) return AString(str); } +} // namespace char_ static -bool extract(XString str, PartyPair *pp) +bool impl_extract(XString str, PartyPair *pp) { PartyPair& p = *pp; @@ -129,6 +129,8 @@ bool extract(XString str, PartyPair *pp) return true; } +namespace char_ +{ static void party_check_deleted_init(PartyPair p) { @@ -153,7 +155,7 @@ void party_check_deleted_init(PartyPair p) // パーティデータのロード void inter_party_init(void) { - io::ReadFile in(party_txt); + io::ReadFile in(inter_conf.party_txt); if (!in.is_open()) return; @@ -171,19 +173,20 @@ void inter_party_init(void) } PartyMost pm; - PartyPair pp; - pp.party_most = ± + PartyPair pp{PartyId(), borrow(pm)}; if (extract(line, &pp) && pp.party_id) { if (party_newid < next(pp.party_id)) party_newid = next(pp.party_id); party_check_deleted_init(pp); party_db.insert(pp.party_id, pm); + // note: this is still referring to the noncanonical copy of + // the PartyMost pointer. This is okay, though. party_check_empty(pp); } else { - PRINTF("int_party: broken data [%s] line %d\n"_fmt, party_txt, + PRINTF("int_party: broken data [%s] line %d\n"_fmt, inter_conf.party_txt, c + 1); } c++; @@ -201,18 +204,16 @@ void inter_party_save_sub(PartyPair data, io::WriteFile& fp) // パーティーデータのセーブ int inter_party_save(void) { - io::WriteLock fp(party_txt); + io::WriteLock fp(inter_conf.party_txt); if (!fp.is_open()) { PRINTF("int_party: cant write [%s] !!! data is lost !!!\n"_fmt, - party_txt); + inter_conf.party_txt); return 1; } for (auto& pair : party_db) { - PartyPair tmp; - tmp.party_id = pair.first; - tmp.party_most = &pair.second; + PartyPair tmp{pair.first, borrow(pair.second)}; inter_party_save_sub(tmp, fp); } @@ -221,23 +222,21 @@ int inter_party_save(void) // パーティ名検索用 static -void search_partyname_sub(PartyPair p, PartyName str, PartyPair *dst) +void search_partyname_sub(PartyPair p, PartyName str, Borrowed<Option<PartyPair>> dst) { if (p->name == str) - *dst = p; + *dst = Some(p); } // パーティ名検索 static -PartyPair search_partyname(PartyName str) +Option<PartyPair> search_partyname(PartyName str) { - PartyPair p; + Option<PartyPair> p = None; for (auto& pair : party_db) { - PartyPair tmp; - tmp.party_id = pair.first; - tmp.party_most = &pair.second; - search_partyname_sub(tmp, str, &p); + PartyPair tmp{pair.first, borrow(pair.second)}; + search_partyname_sub(tmp, str, borrow(p)); } return p; @@ -262,11 +261,11 @@ int party_check_exp_share(PartyPair p) } } - return (maxlv == 0 || maxlv - minlv <= party_share_level); + return (maxlv == 0 || maxlv - minlv <= inter_conf.party_share_level); } // パーティが空かどうかチェック -int party_check_empty(PartyPair p) +int party_check_empty(const PartyPair p) { int i; @@ -313,9 +312,7 @@ void party_check_conflict(PartyId party_id, AccountId account_id, CharName nick) { for (auto& pair : party_db) { - PartyPair tmp; - tmp.party_id = pair.first; - tmp.party_most = &pair.second; + PartyPair tmp{pair.first, borrow(pair.second)}; party_check_conflict_sub(tmp, party_id, account_id, nick); } @@ -326,23 +323,27 @@ void party_check_conflict(PartyId party_id, AccountId account_id, CharName nick) // パーティ作成可否 static -void mapif_party_created(Session *s, AccountId account_id, PartyPair p) +void mapif_party_created(Session *s, AccountId account_id, Option<PartyPair> p_) { Packet_Fixed<0x3820> fixed_20; fixed_20.account_id = account_id; - if (p) - { - fixed_20.error = 0; - fixed_20.party_id = p.party_id; - fixed_20.party_name = p->name; - PRINTF("int_party: created! %d %s\n"_fmt, p.party_id, p->name); - } - else + OMATCH_BEGIN (p_) { - fixed_20.error = 1; - fixed_20.party_id = PartyId(); - fixed_20.party_name = stringish<PartyName>("error"_s); + OMATCH_CASE_SOME (p) + { + fixed_20.error = 0; + fixed_20.party_id = p.party_id; + fixed_20.party_name = p->name; + PRINTF("int_party: created! %d %s\n"_fmt, p.party_id, p->name); + } + OMATCH_CASE_NONE () + { + fixed_20.error = 1; + fixed_20.party_id = PartyId(); + fixed_20.party_name = stringish<PartyName>("error"_s); + } } + OMATCH_END (); send_fpacket<0x3820, 35>(s, fixed_20); } @@ -359,7 +360,7 @@ void mapif_party_noinfo(Session *s, PartyId party_id) // パーティ情報まとめ送り static -void mapif_party_info(Session *s, PartyPair p) +void mapif_party_info(Session *s, const PartyPair p) { Packet_Head<0x3821> head_21; head_21.party_id = p.party_id; @@ -490,22 +491,21 @@ void mapif_parse_CreateParty(Session *s, AccountId account_id, PartyName name, C if (!name.is_print()) { PRINTF("int_party: illegal party name [%s]\n"_fmt, name); - mapif_party_created(s, account_id, PartyPair()); + mapif_party_created(s, account_id, None); return; } } - if (search_partyname(name)) + if (search_partyname(name).is_some()) { PRINTF("int_party: same name party exists [%s]\n"_fmt, name); - mapif_party_created(s, account_id, PartyPair()); + mapif_party_created(s, account_id, None); return; } + PartyMost p {}; - PartyPair pp; - pp.party_most = &p; party_newid = next(party_newid); - pp.party_id = party_newid; + PartyPair pp{party_newid, borrow(p)}; p.name = name; p.exp = 0; p.item = 0; @@ -518,7 +518,8 @@ void mapif_parse_CreateParty(Session *s, AccountId account_id, PartyName name, C party_db.insert(pp.party_id, p); - mapif_party_created(s, account_id, pp); + // pointer to noncanonical version + mapif_party_created(s, account_id, Some(pp)); mapif_party_info(s, pp); } @@ -526,12 +527,19 @@ void mapif_parse_CreateParty(Session *s, AccountId account_id, PartyName name, C static void mapif_parse_PartyInfo(Session *s, PartyId party_id) { - PartyPair p; - p.party_most = party_db.search(party_id); - if (p) - mapif_party_info(s, p); - else - mapif_party_noinfo(s, party_id); + Option<P<PartyMost>> maybe_party_most = party_db.search(party_id); + OMATCH_BEGIN (maybe_party_most) + { + OMATCH_CASE_SOME (party_most) + { + mapif_party_info(s, PartyPair{party_id, party_most}); + } + OMATCH_CASE_NONE () + { + mapif_party_noinfo(s, party_id); + } + } + OMATCH_END (); } // パーティ追加要求 @@ -539,13 +547,13 @@ static void mapif_parse_PartyAddMember(Session *s, PartyId party_id, AccountId account_id, CharName nick, MapName map, int lv) { - PartyPair p; - p.party_most = party_db.search(party_id); - if (!p) - { - mapif_party_memberadded(s, party_id, account_id, 1); - return; - } + Option<P<PartyMost>> maybe_party_most = party_db.search(party_id); + P<PartyMost> party_most = TRY_UNWRAP(maybe_party_most, + { + mapif_party_memberadded(s, party_id, account_id, 1); + return; + }); + PartyPair p{party_id, party_most}; for (int i = 0; i < MAX_PARTY; i++) { @@ -580,10 +588,7 @@ static void mapif_parse_PartyChangeOption(Session *s, PartyId party_id, AccountId account_id, int exp, int item) { - PartyPair p; - p.party_most = party_db.search(party_id); - if (!p) - return; + PartyPair p{party_id, TRY_UNWRAP(party_db.search(party_id), return)}; p->exp = exp; int flag = 0; @@ -601,10 +606,8 @@ void mapif_parse_PartyChangeOption(Session *s, PartyId party_id, AccountId accou // パーティ脱退要求 void mapif_parse_PartyLeave(Session *, PartyId party_id, AccountId account_id) { - PartyPair p; - p.party_most = party_db.search(party_id); - if (!p) - return; + PartyPair p{party_id, TRY_UNWRAP(party_db.search(party_id), return)}; + for (int i = 0; i < MAX_PARTY; i++) { if (p->member[i].account_id != account_id) @@ -623,10 +626,7 @@ static void mapif_parse_PartyChangeMap(Session *s, PartyId party_id, AccountId account_id, MapName map, int online, int lv) { - PartyPair p; - p.party_most = party_db.search(party_id); - if (!p) - return; + PartyPair p{party_id, TRY_UNWRAP(party_db.search(party_id), return)}; for (int i = 0; i < MAX_PARTY; i++) { @@ -822,4 +822,5 @@ void inter_party_leave(PartyId party_id, AccountId account_id) { mapif_parse_PartyLeave(nullptr, party_id, account_id); } +} // namespace char_ } // namespace tmwa diff --git a/src/char/int_party.hpp b/src/char/int_party.hpp index f33fc0d..d66afbf 100644 --- a/src/char/int_party.hpp +++ b/src/char/int_party.hpp @@ -22,21 +22,16 @@ #include "fwd.hpp" -#include "../strings/fwd.hpp" - -#include "../net/fwd.hpp" - -#include "../mmo/fwd.hpp" - namespace tmwa { +namespace char_ +{ void inter_party_init(void); int inter_party_save(void); RecvResult inter_party_parse_frommap(Session *ms, uint16_t); void inter_party_leave(PartyId party_id, AccountId account_id); - -extern AString party_txt; +} // namespace char_ } // namespace tmwa diff --git a/src/char/int_storage.cpp b/src/char/int_storage.cpp index 76eff34..32af231 100644 --- a/src/char/int_storage.cpp +++ b/src/char/int_storage.cpp @@ -28,30 +28,30 @@ #include "../generic/db.hpp" #include "../io/cxxstdio.hpp" -#include "../io/cxxstdio_enums.hpp" +#include "../io/extract.hpp" #include "../io/lock.hpp" #include "../io/read.hpp" #include "../io/write.hpp" -#include "../net/packets.hpp" - #include "../proto2/char-map.hpp" -#include "../mmo/extract.hpp" -#include "../mmo/mmo.hpp" +#include "../mmo/cxxstdio_enums.hpp" + +#include "../high/extract_mmo.hpp" +#include "../high/mmo.hpp" + +#include "../wire/packets.hpp" + +#include "globals.hpp" +#include "inter_conf.hpp" #include "../poison.hpp" namespace tmwa { -// ファイル名のデフォルト -// inter_config_read()で再設定される -AString storage_txt = "save/storage.txt"_s; - -static -Map<AccountId, Storage> storage_db; - +namespace char_ +{ // 倉庫データを文字列に変換 static AString storage_tostr(Storage *p) @@ -90,10 +90,11 @@ AString storage_tostr(Storage *p) return AString(); return AString(str); } +} // namespace char_ // 文字列を倉庫データに変換 static -bool extract(XString str, Storage *p) +bool impl_extract(XString str, Storage *p) { std::vector<Item> storage_items; if (!extract(str, @@ -116,15 +117,13 @@ bool extract(XString str, Storage *p) return true; } +namespace char_ +{ // アカウントから倉庫データインデックスを得る(新規倉庫追加可能) -Storage *account2storage(AccountId account_id) +Borrowed<Storage> account2storage(AccountId account_id) { - Storage *s = storage_db.search(account_id); - if (s == nullptr) - { - s = storage_db.init(account_id); - s->account_id = account_id; - } + P<Storage> s = storage_db.init(account_id); + s->account_id = account_id; return s; } @@ -134,10 +133,10 @@ void inter_storage_init(void) { int c = 0; - io::ReadFile in(storage_txt); + io::ReadFile in(inter_conf.storage_txt); if (!in.is_open()) { - PRINTF("cant't read : %s\n"_fmt, storage_txt); + PRINTF("cant't read : %s\n"_fmt, inter_conf.storage_txt); return; } @@ -152,7 +151,7 @@ void inter_storage_init(void) else { PRINTF("int_storage: broken data [%s] line %d\n"_fmt, - storage_txt, c); + inter_conf.storage_txt, c); } c++; } @@ -170,12 +169,12 @@ void inter_storage_save_sub(Storage *data, io::WriteFile& fp) // 倉庫データを書き込む int inter_storage_save(void) { - io::WriteLock fp(storage_txt); + io::WriteLock fp(inter_conf.storage_txt); if (!fp.is_open()) { PRINTF("int_storage: cant write [%s] !!! data is lost !!!\n"_fmt, - storage_txt); + inter_conf.storage_txt); return 1; } for (auto& pair : storage_db) @@ -196,7 +195,7 @@ void inter_storage_delete(AccountId account_id) static void mapif_load_storage(Session *ss, AccountId account_id) { - Storage *st = account2storage(account_id); + P<Storage> st = account2storage(account_id); Packet_Payload<0x3810> payload_10; payload_10.account_id = account_id; payload_10.storage = *st; @@ -240,11 +239,10 @@ RecvResult mapif_parse_SaveStorage(Session *ss) if (rv != RecvResult::Complete) return rv; - Storage *st; AccountId account_id = payload.account_id; { - st = account2storage(account_id); + P<Storage> st = account2storage(account_id); *st = payload.storage; mapif_save_storage_ack(ss, account_id); } @@ -273,4 +271,5 @@ RecvResult inter_storage_parse_frommap(Session *ms, uint16_t packet_id) } return rv; } +} // namespace char_ } // namespace tmwa diff --git a/src/char/int_storage.hpp b/src/char/int_storage.hpp index b8ec9db..3741061 100644 --- a/src/char/int_storage.hpp +++ b/src/char/int_storage.hpp @@ -22,21 +22,16 @@ #include "fwd.hpp" -#include "../strings/fwd.hpp" - -#include "../net/fwd.hpp" - -#include "../mmo/fwd.hpp" - namespace tmwa { +namespace char_ +{ void inter_storage_init(void); int inter_storage_save(void); void inter_storage_delete(AccountId account_id); -Storage *account2storage(AccountId account_id); +Borrowed<Storage> account2storage(AccountId account_id); RecvResult inter_storage_parse_frommap(Session *ms, uint16_t); - -extern AString storage_txt; +} // namespace char_ } // namespace tmwa diff --git a/src/char/inter.cpp b/src/char/inter.cpp index f757991..3bf3bfc 100644 --- a/src/char/inter.cpp +++ b/src/char/inter.cpp @@ -34,18 +34,24 @@ #include "../generic/db.hpp" #include "../io/cxxstdio.hpp" +#include "../io/extract.hpp" #include "../io/lock.hpp" #include "../io/read.hpp" +#include "../io/span.hpp" #include "../io/write.hpp" -#include "../net/packets.hpp" +#include "../mmo/config_parse.hpp" #include "../proto2/char-map.hpp" -#include "../mmo/extract.hpp" -#include "../mmo/mmo.hpp" +#include "../high/extract_mmo.hpp" +#include "../high/mmo.hpp" + +#include "../wire/packets.hpp" #include "char.hpp" +#include "globals.hpp" +#include "inter_conf.hpp" #include "int_party.hpp" #include "int_storage.hpp" @@ -54,20 +60,8 @@ namespace tmwa { -static -AString accreg_txt = "save/accreg.txt"_s; - -struct accreg +namespace char_ { - AccountId account_id; - int reg_num; - Array<GlobalReg, ACCOUNT_REG_NUM> reg; -}; -static -Map<AccountId, struct accreg> accreg_db; - -int party_share_level = 10; - //-------------------------------------------------------- // アカウント変数を文字列へ変換 @@ -84,7 +78,7 @@ AString inter_accreg_tostr(struct accreg *reg) // アカウント変数を文字列から変換 static -bool extract(XString str, struct accreg *reg) +bool impl_extract(XString str, struct accreg *reg) { std::vector<GlobalReg> vars; if (!extract(str, @@ -108,7 +102,7 @@ void inter_accreg_init(void) { int c = 0; - io::ReadFile in(accreg_txt); + io::ReadFile in(inter_conf.accreg_txt); if (!in.is_open()) return; AString line; @@ -121,7 +115,7 @@ void inter_accreg_init(void) } else { - PRINTF("inter: accreg: broken data [%s] line %d\n"_fmt, accreg_txt, + PRINTF("inter: accreg: broken data [%s] line %d\n"_fmt, inter_conf.accreg_txt, c); } c++; @@ -143,11 +137,11 @@ void inter_accreg_save_sub(struct accreg *reg, io::WriteFile& fp) static int inter_accreg_save(void) { - io::WriteLock fp(accreg_txt); + io::WriteLock fp(inter_conf.accreg_txt); if (!fp.is_open()) { PRINTF("int_accreg: cant write [%s] !!! data is lost !!!\n"_fmt, - accreg_txt); + inter_conf.accreg_txt); return 1; } for (auto& pair : accreg_db) @@ -156,36 +150,6 @@ int inter_accreg_save(void) return 0; } -bool inter_config(XString w1, ZString w2) -{ - { - if (w1 == "storage_txt"_s) - { - storage_txt = w2; - } - else if (w1 == "party_txt"_s) - { - party_txt = w2; - } - else if (w1 == "accreg_txt"_s) - { - accreg_txt = w2; - } - else if (w1 == "party_share_level"_s) - { - party_share_level = atoi(w2.c_str()); - if (party_share_level < 0) - party_share_level = 0; - } - else - { - return false; - } - } - - return true; -} - // セーブ void inter_save(void) { @@ -264,12 +228,12 @@ void mapif_account_reg(Session *s, AccountId account_id, const std::vector<Packe static void mapif_account_reg_reply(Session *s, AccountId account_id) { - struct accreg *reg = accreg_db.search(account_id); + Option<P<struct accreg>> reg_ = accreg_db.search(account_id); Packet_Head<0x3804> head_04; head_04.account_id = account_id; std::vector<Packet_Repeat<0x3804>> repeat_04; - if (reg) + OMATCH_BEGIN_SOME (reg, reg_) { repeat_04.resize(reg->reg_num); assert (reg->reg_num < ACCOUNT_REG_NUM); @@ -279,6 +243,7 @@ void mapif_account_reg_reply(Session *s, AccountId account_id) repeat_04[j].value = reg->reg[j].value; } } + OMATCH_END (); send_vpacket<0x3804, 8, 36>(s, head_04, repeat_04); } @@ -408,13 +373,9 @@ RecvResult mapif_parse_AccReg(Session *s) if (rv != RecvResult::Complete) return rv; - struct accreg *reg = accreg_db.search(head.account_id); - - if (reg == nullptr) + P<struct accreg> reg = accreg_db.init(head.account_id); { - AccountId account_id = head.account_id; - reg = accreg_db.init(account_id); - reg->account_id = account_id; + reg->account_id = head.account_id; } size_t jlim = std::min(repeat.size(), ACCOUNT_REG_NUM); @@ -488,4 +449,5 @@ RecvResult inter_parse_frommap(Session *ms, uint16_t packet_id) return rv; } +} // namespace char_ } // namespace tmwa diff --git a/src/char/inter.hpp b/src/char/inter.hpp index 19900f9..c641254 100644 --- a/src/char/inter.hpp +++ b/src/char/inter.hpp @@ -22,17 +22,27 @@ #include "fwd.hpp" -#include "../strings/fwd.hpp" +#include "../generic/array.hpp" -#include "../net/fwd.hpp" +#include "../mmo/consts.hpp" +#include "../mmo/ids.hpp" + +#include "../proto2/net-GlobalReg.hpp" namespace tmwa { -bool inter_config(XString key, ZString value); +namespace char_ +{ +struct accreg +{ + AccountId account_id; + int reg_num; + Array<GlobalReg, ACCOUNT_REG_NUM> reg; +}; + void inter_init2(); void inter_save(void); RecvResult inter_parse_frommap(Session *ms, uint16_t packet_id); - -extern int party_share_level; +} // namespace char_ } // namespace tmwa diff --git a/src/char/main.cpp b/src/char/main.cpp index 3648a74..7d6fee3 100644 --- a/src/char/main.cpp +++ b/src/char/main.cpp @@ -17,7 +17,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -#include "../mmo/core.hpp" +#include "../high/core.hpp" #include "char.hpp" |