diff options
Diffstat (limited to 'src/char/char.cpp')
-rw-r--r-- | src/char/char.cpp | 645 |
1 files changed, 115 insertions, 530 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 |