summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Longbons <b.r.longbons@gmail.com>2014-01-25 09:43:09 -0800
committerBen Longbons <b.r.longbons@gmail.com>2014-01-25 10:14:44 -0800
commit34f0540da418b01dd4d49f6ecf72569d3cfecfdf (patch)
treebf7c4623b0d794e4db8c72b0906bb40807d62ba8
parent9a4c3a44476f3306a8deed8a836e8fbc25ceb55f (diff)
downloadtmwa-34f0540da418b01dd4d49f6ecf72569d3cfecfdf.tar.gz
tmwa-34f0540da418b01dd4d49f6ecf72569d3cfecfdf.tar.bz2
tmwa-34f0540da418b01dd4d49f6ecf72569d3cfecfdf.tar.xz
tmwa-34f0540da418b01dd4d49f6ecf72569d3cfecfdf.zip
Implement unified config parsing (mostly)
-rw-r--r--src/admin/ladmin.cpp67
-rw-r--r--src/char/char.cpp156
-rw-r--r--src/char/char.hpp4
-rw-r--r--src/char/int_party.cpp7
-rw-r--r--src/char/int_party.hpp2
-rw-r--r--src/char/int_storage.cpp6
-rw-r--r--src/char/int_storage.hpp2
-rw-r--r--src/char/inter.cpp43
-rw-r--r--src/char/inter.hpp5
-rw-r--r--src/common/config_parse.cpp154
-rw-r--r--src/common/config_parse.hpp36
-rw-r--r--src/common/core.cpp18
-rw-r--r--src/common/core.hpp5
-rw-r--r--src/common/utils.cpp22
-rw-r--r--src/common/utils.hpp2
-rw-r--r--src/common/version.cpp18
-rw-r--r--src/common/version.hpp35
-rw-r--r--src/login/login.cpp192
-rw-r--r--src/map/atcommand.cpp91
-rw-r--r--src/map/atcommand.hpp2
-rw-r--r--src/map/battle.cpp46
-rw-r--r--src/map/battle.hpp3
-rw-r--r--src/map/chrif.cpp4
-rw-r--r--src/map/chrif.hpp2
-rw-r--r--src/map/clif.cpp8
-rw-r--r--src/map/clif.hpp2
-rw-r--r--src/map/itemdb.cpp74
-rw-r--r--src/map/itemdb.hpp2
-rw-r--r--src/map/magic-interpreter-parser.ypp19
-rw-r--r--src/map/magic-interpreter.hpp3
-rw-r--r--src/map/magic.cpp5
-rw-r--r--src/map/magic.hpp5
-rw-r--r--src/map/map.cpp148
-rw-r--r--src/map/map.hpp1
-rw-r--r--src/map/mob.cpp69
-rw-r--r--src/map/mob.hpp5
-rw-r--r--src/map/npc.cpp19
-rw-r--r--src/map/npc.hpp2
-rw-r--r--src/map/pc.cpp8
-rw-r--r--src/map/pc.hpp2
-rw-r--r--src/map/script.cpp32
-rw-r--r--src/map/script.hpp1
-rw-r--r--src/map/skill.cpp61
-rw-r--r--src/map/skill.hpp2
-rw-r--r--src/map/storage.cpp4
-rw-r--r--src/map/storage.hpp1
-rw-r--r--src/monitor/main.cpp24
-rw-r--r--src/strings/fstring.tcc1
48 files changed, 759 insertions, 661 deletions
diff --git a/src/admin/ladmin.cpp b/src/admin/ladmin.cpp
index 93002c6..ff83530 100644
--- a/src/admin/ladmin.cpp
+++ b/src/admin/ladmin.cpp
@@ -15,6 +15,7 @@
#include "../io/read.hpp"
#include "../io/write.hpp"
+#include "../common/config_parse.hpp"
#include "../common/core.hpp"
#include "../common/human_time_diff.hpp"
#include "../common/md5calc.hpp"
@@ -25,7 +26,6 @@
#include "../poison.hpp"
-#define LADMIN_CONF_NAME "conf/ladmin_athena.conf"
static
int eathena_interactive_session;
@@ -2784,29 +2784,10 @@ int Connect_login_server(void)
return 0;
}
-//-----------------------------------
-// Reading general configuration file
-//-----------------------------------
static
-int ladmin_config_read(ZString cfgName)
+bool admin_confs(XString w1, ZString w2)
{
- io::ReadFile in(cfgName);
- if (!in.is_open())
{
- PRINTF("\033[0mConfiguration file (%s) not found.\n", cfgName);
- return 1;
- }
-
- Iprintf("\033[0m---Start reading of Ladmin configuration file (%s)\n",
- cfgName);
- FString line;
- while (in.getline(line))
- {
- XString w1;
- ZString w2;
- if (!split_key_value(line, &w1, &w2))
- continue;
-
if (w1 == "login_ip")
{
struct hostent *h = gethostbyname(w2.c_str());
@@ -2834,19 +2815,13 @@ int ladmin_config_read(ZString cfgName)
{
ladmin_log_filename = w2;
}
- else if (w1 == "import")
- {
- ladmin_config_read(w2);
- }
else
{
PRINTF("WARNING: unknown ladmin config key: %s\n", FString(w1));
+ return false;
}
}
-
- Iprintf("---End reading of Ladmin configuration file.\n");
-
- return 0;
+ return true;
}
//--------------------------------------
@@ -2871,9 +2846,39 @@ void term_func(void)
//------------------------
int do_init(int argc, ZString *argv)
{
+ bool loaded_config_yet = false;
+ for (int i = 1; i < argc; ++i)
+ {
+ if (argv[i].startswith('-'))
+ {
+ if (argv[i] == "--help")
+ {
+ PRINTF("Usage: %s [--help] [--version] [files...]\n",
+ argv[0]);
+ exit(0);
+ }
+ else if (argv[i] == "--version")
+ {
+ PRINTF("%s\n", CURRENT_VERSION_STRING);
+ exit(0);
+ }
+ else
+ {
+ FPRINTF(stderr, "Unknown argument: %s\n", argv[i]);
+ runflag = false;
+ }
+ }
+ else
+ {
+ loaded_config_yet = true;
+ runflag &= load_config_file(argv[i], admin_confs);
+ }
+ }
+
+ if (!loaded_config_yet)
+ runflag &= load_config_file("conf/tmwa-admin.conf", admin_confs);
+
eathena_interactive_session = isatty(0);
- // read ladmin configuration
- ladmin_config_read((argc > 1) ? argv[1] : LADMIN_CONF_NAME);
LADMIN_LOG("");
LADMIN_LOG("Configuration file readed.\n");
diff --git a/src/char/char.cpp b/src/char/char.cpp
index 5c5179d..cb159c3 100644
--- a/src/char/char.cpp
+++ b/src/char/char.cpp
@@ -24,6 +24,7 @@
#include "../io/lock.hpp"
#include "../io/read.hpp"
+#include "../common/config_parse.hpp"
#include "../common/core.hpp"
#include "../common/db.hpp"
#include "../common/extract.hpp"
@@ -80,9 +81,9 @@ static
FString char_log_filename = "log/char.log";
//Added for lan support
static
-IP4Address lan_map_ip;
+IP4Address lan_map_ip = IP4_LOCALHOST;
static
-IP4Mask lan_subnet;
+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
@@ -451,7 +452,7 @@ int mmo_char_init(void)
{
line_count++;
- if (line.startswith("//"))
+ if (is_comment(line))
continue;
{
@@ -2536,32 +2537,11 @@ void check_connect_login_server(TimerData *, tick_t)
// Reading Lan Support configuration by [Yor]
//-------------------------------------------
static
-int lan_config_read(ZString lancfgName)
+bool char_lan_config(XString w1, ZString w2)
{
struct hostent *h = NULL;
- // set default configuration
- lan_map_ip = IP4_LOCALHOST;
- lan_subnet = IP4Mask(IP4_LOCALHOST, IP4_BROADCAST);
-
- io::ReadFile in(lancfgName);
-
- if (!in.is_open())
- {
- PRINTF("LAN support configuration file not found: %s\n", lancfgName);
- return 1;
- }
-
- PRINTF("---start reading of Lan Support configuration...\n");
-
- FString line;
- while (in.getline(line))
{
- XString w1;
- ZString w2;
- if (!split_key_value(line, &w1, &w2))
- continue;
-
if (w1 == "lan_map_ip")
{
// Read map-server Lan IP Address
@@ -2577,8 +2557,8 @@ int lan_config_read(ZString lancfgName)
}
else
{
- PRINTF("Bad IP value: %s\n", line);
- abort();
+ PRINTF("Bad IP value: %s\n", w2);
+ return false;
}
PRINTF("LAN IP of map-server: %s.\n", lan_map_ip);
}
@@ -2587,54 +2567,42 @@ int lan_config_read(ZString lancfgName)
{
if (!extract(w2, &lan_subnet))
{
- PRINTF("Bad IP mask: %s\n", line);
- abort();
+ PRINTF("Bad IP mask: %s\n", w2);
+ return false;
}
PRINTF("Sub-network of the map-server: %s.\n",
lan_subnet);
}
else
{
- FString w1z = w1;
- PRINTF("WARNING: unknown lan config key: %s\n", w1z);
+ 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: ");
if (!lan_ip_check(lan_map_ip))
{
PRINTF("\033[1;31m***ERROR: LAN IP of the map-server doesn't belong to the specified Sub-network.\033[0m\n");
+ return false;
}
}
- PRINTF("---End reading of Lan Support configuration...\n");
-
- return 0;
+ return true;
}
static
-int char_config_read(ZString cfgName)
+bool char_config(XString w1, ZString w2)
{
struct hostent *h = NULL;
- io::ReadFile in(cfgName);
-
- if (!in.is_open())
{
- PRINTF("Configuration file not found: %s.\n", cfgName);
- exit(1);
- }
-
- FString line;
- while (in.getline(line))
- {
- XString w1;
- ZString w2;
- if (!split_key_value(line, &w1, &w2))
- continue;
-
if (w1 == "userid")
userid = stringish<AccountName>(w2);
else if (w1 == "passwd")
@@ -2665,8 +2633,8 @@ int char_config_read(ZString cfgName)
}
else
{
- PRINTF("Bad IP value: %s\n", line);
- abort();
+ PRINTF("Bad IP value: %s\n", w2);
+ return false;
}
}
else if (w1 == "login_port")
@@ -2689,8 +2657,8 @@ int char_config_read(ZString cfgName)
}
else
{
- PRINTF("Bad IP value: %s\n", line);
- abort();
+ PRINTF("Bad IP value: %s\n", w2);
+ return false;
}
}
else if (w1 == "char_port")
@@ -2775,18 +2743,13 @@ int char_config_read(ZString cfgName)
std::chrono::seconds(atoi(w2.c_str())),
std::chrono::seconds(5));
}
- else if (w1 == "import")
- {
- char_config_read(w2);
- }
else
{
- FString w1z = w1;
- PRINTF("WARNING: unknown char config key: %s\n", w1z);
+ return false;
}
}
- return 0;
+ return true;
}
void term_func(void)
@@ -2808,39 +2771,70 @@ void term_func(void)
CHAR_LOG("----End of char-server (normal end with closing of all files).\n");
}
+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(int argc, ZString *argv)
{
- int i;
+ for (int i = 0; i < MAX_MAP_SERVERS; i++)
+ {
+ server[i] = mmo_map_server{};
+ server_fd[i] = -1;
+ }
+
+ bool loaded_config_yet = false;
+ for (int i = 1; i < argc; ++i)
+ {
+ if (argv[i].startswith('-'))
+ {
+ if (argv[i] == "--help")
+ {
+ PRINTF("Usage: %s [--help] [--version] [files...]\n",
+ argv[0]);
+ exit(0);
+ }
+ else if (argv[i] == "--version")
+ {
+ PRINTF("%s\n", CURRENT_VERSION_STRING);
+ exit(0);
+ }
+ else
+ {
+ FPRINTF(stderr, "Unknown argument: %s\n", argv[i]);
+ runflag = false;
+ }
+ }
+ else
+ {
+ loaded_config_yet = true;
+ runflag &= load_config_file(argv[i], char_confs);
+ }
+ }
+
+ if (!loaded_config_yet)
+ runflag &= load_config_file("conf/tmwa-char.conf", char_confs);
// a newline in the log...
CHAR_LOG("");
CHAR_LOG("The char-server starting...\n");
- if (argc > 1)
- char_config_read(argv[1]);
- else
- char_config_read(CHAR_CONF_NAME);
- if (argc > 1)
- lan_config_read(argv[2]);
- else
- lan_config_read(LOGIN_LAN_CONF_NAME);
-
- for (i = 0; i < MAX_MAP_SERVERS; i++)
- {
- server[i] = mmo_map_server{};
- server_fd[i] = -1;
- }
+ runflag &= lan_check();
+ inter_init2();
mmo_char_init();
update_online = TimeT::now();
create_online_files(); // update online players files at start of the server
- if (argc > 3)
- inter_init(argv[3]);
- else
- inter_init(inter_cfgName);
-
// set_termfunc (do_final);
set_defaultparse(parse_char);
diff --git a/src/char/char.hpp b/src/char/char.hpp
index f24acbc..27bdd36 100644
--- a/src/char/char.hpp
+++ b/src/char/char.hpp
@@ -9,10 +9,6 @@
constexpr int MAX_MAP_SERVERS = 30;
-# define CHAR_CONF_NAME "conf/char_athena.conf"
-
-# define LOGIN_LAN_CONF_NAME "conf/lan_support.conf"
-
struct mmo_map_server
{
IP4Address ip;
diff --git a/src/char/int_party.cpp b/src/char/int_party.cpp
index 2972689..1fc0c05 100644
--- a/src/char/int_party.cpp
+++ b/src/char/int_party.cpp
@@ -102,11 +102,11 @@ bool extract(XString str, party *p)
}
// パーティデータのロード
-int inter_party_init(void)
+void inter_party_init(void)
{
io::ReadFile in(party_txt);
if (!in.is_open())
- return 1;
+ return;
// TODO: convert to use char_id, and change to extract()
FString line;
@@ -136,9 +136,6 @@ int inter_party_init(void)
}
c++;
}
-// PRINTF("int_party: %s read done (%d parties)\n", party_txt, c);
-
- return 0;
}
// パーティーデータのセーブ用
diff --git a/src/char/int_party.hpp b/src/char/int_party.hpp
index e5a3ab9..4e5547c 100644
--- a/src/char/int_party.hpp
+++ b/src/char/int_party.hpp
@@ -3,7 +3,7 @@
# include "../strings/fwd.hpp"
-int inter_party_init(void);
+void inter_party_init(void);
int inter_party_save(void);
int inter_party_parse_frommap(int fd);
diff --git a/src/char/int_storage.cpp b/src/char/int_storage.cpp
index 4e52215..323a451 100644
--- a/src/char/int_storage.cpp
+++ b/src/char/int_storage.cpp
@@ -100,7 +100,7 @@ struct storage *account2storage(int account_id)
//---------------------------------------------------------
// 倉庫データを読み込む
-int inter_storage_init(void)
+void inter_storage_init(void)
{
int c = 0;
@@ -108,7 +108,7 @@ int inter_storage_init(void)
if (!in.is_open())
{
PRINTF("cant't read : %s\n", storage_txt);
- return 1;
+ return;
}
FString line;
@@ -126,8 +126,6 @@ int inter_storage_init(void)
}
c++;
}
-
- return 0;
}
static
diff --git a/src/char/int_storage.hpp b/src/char/int_storage.hpp
index 6c13923..23d7441 100644
--- a/src/char/int_storage.hpp
+++ b/src/char/int_storage.hpp
@@ -3,7 +3,7 @@
# include "../strings/fwd.hpp"
-int inter_storage_init(void);
+void inter_storage_init(void);
int inter_storage_save(void);
void inter_storage_delete(int account_id);
struct storage *account2storage(int account_id);
diff --git a/src/char/inter.cpp b/src/char/inter.cpp
index 38e6194..a0569a7 100644
--- a/src/char/inter.cpp
+++ b/src/char/inter.cpp
@@ -15,6 +15,7 @@
#include "../io/lock.hpp"
#include "../io/read.hpp"
+#include "../common/config_parse.hpp"
#include "../common/db.hpp"
#include "../common/extract.hpp"
#include "../common/socket.hpp"
@@ -106,13 +107,13 @@ bool extract(XString str, struct accreg *reg)
// アカウント変数の読み込み
static
-int inter_accreg_init(void)
+void inter_accreg_init(void)
{
int c = 0;
io::ReadFile in(accreg_txt);
if (!in.is_open())
- return 1;
+ return;
FString line;
while (in.getline(line))
{
@@ -128,8 +129,6 @@ int inter_accreg_init(void)
}
c++;
}
-
- return 0;
}
// アカウント変数のセーブ用
@@ -160,30 +159,9 @@ int inter_accreg_save(void)
return 0;
}
-//--------------------------------------------------------
-
-/*==========================================
- * 設定ファイルを読み込む
- *------------------------------------------
- */
-static
-int inter_config_read(ZString cfgName)
+bool inter_config(XString w1, ZString w2)
{
- io::ReadFile in(cfgName);
- if (!in.is_open())
- {
- PRINTF("file not found: %s\n", cfgName);
- return 1;
- }
-
- FString line;
- while (in.getline(line))
{
- XString w1;
- ZString w2;
- if (!split_key_value(line, &w1, &w2))
- continue;
-
if (w1 == "storage_txt")
{
storage_txt = w2;
@@ -202,18 +180,13 @@ int inter_config_read(ZString cfgName)
if (party_share_level < 0)
party_share_level = 0;
}
- else if (w1 == "import")
- {
- inter_config_read(w2);
- }
else
{
- FString w1z = w1;
- PRINTF("WARNING: unknown inter config key: %s\n", w1z);
+ return false;
}
}
- return 0;
+ return true;
}
// セーブ
@@ -225,10 +198,8 @@ void inter_save(void)
}
// 初期化
-void inter_init(ZString file)
+void inter_init2()
{
- inter_config_read(file);
-
inter_party_init();
inter_storage_init();
inter_accreg_init();
diff --git a/src/char/inter.hpp b/src/char/inter.hpp
index ece340a..ae508f6 100644
--- a/src/char/inter.hpp
+++ b/src/char/inter.hpp
@@ -3,14 +3,13 @@
# include "../strings/fwd.hpp"
-void inter_init(ZString file);
+bool inter_config(XString key, ZString value);
+void inter_init2();
void inter_save(void);
int inter_parse_frommap(int fd);
int inter_check_length(int fd, int length);
-# define inter_cfgName "conf/inter_athena.conf"
-
extern int party_share_level;
#endif // INTER_HPP
diff --git a/src/common/config_parse.cpp b/src/common/config_parse.cpp
new file mode 100644
index 0000000..d677d8e
--- /dev/null
+++ b/src/common/config_parse.cpp
@@ -0,0 +1,154 @@
+#include "config_parse.hpp"
+// config_parse.hpp - Framework for per-server config parsers.
+//
+// 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 "../strings/xstring.hpp"
+#include "../strings/zstring.hpp"
+
+#include "../io/cxxstdio.hpp"
+#include "../io/line.hpp"
+
+#include "version.hpp"
+
+#include "../poison.hpp"
+
+bool is_comment(XString line)
+{
+ return not line or line.startswith("//");
+}
+
+template<class ZS>
+inline
+bool config_split_impl(ZS line, XString *key, ZS *value)
+{
+ // unconditionally fail if line contains control characters
+ if (std::find_if(line.begin(), line.end(),
+ [](unsigned char c) { return c < ' '; }
+ ) != line.end())
+ return false;
+ // try to find a colon, fail if not found
+ typename ZS::iterator colon = std::find(line.begin(), line.end(), ':');
+ if (colon == line.end())
+ return false;
+
+ *key = line.xislice_h(colon).strip();
+ // move past the colon and any spaces
+ ++colon;
+ *value = line.xislice_t(colon).lstrip();
+ return true;
+}
+
+// eventually this should go away
+bool config_split(ZString line, XString *key, ZString *value)
+{
+ return config_split_impl(line, key, value);
+}
+// and use this instead
+bool config_split(XString line, XString *key, XString *value)
+{
+ return config_split_impl(line, key, value);
+}
+
+/// Master config parser. This handles 'import' and 'version-ge' etc.
+/// Then it defers to the inferior parser for a line it does not understand.
+bool load_config_file(ZString filename, ConfigItemParser slave)
+{
+ io::LineReader in(filename);
+ if (!in.is_open())
+ {
+ PRINTF("Unable to open file: %s\n", filename);
+ return false;
+ }
+ io::Line line;
+ bool rv = true;
+ while (in.read_line(line))
+ {
+ if (is_comment(line.text))
+ continue;
+ XString key;
+ ZString value;
+ if (!config_split(line.text, &key, &value))
+ {
+ line.error("Bad config line");
+ rv = false;
+ continue;
+ }
+ if (key == "import")
+ {
+ rv &= load_config_file(value, slave);
+ continue;
+ }
+ else if (key == "version-lt")
+ {
+ Version vers;
+ if (!extract(value, &vers))
+ {
+ rv = false;
+ continue;
+ }
+ if (CURRENT_VERSION < vers)
+ continue;
+ break;
+ }
+ else if (key == "version-le")
+ {
+ Version vers;
+ if (!extract(value, &vers))
+ {
+ rv = false;
+ continue;
+ }
+ if (CURRENT_VERSION <= vers)
+ continue;
+ break;
+ }
+ else if (key == "version-gt")
+ {
+ Version vers;
+ if (!extract(value, &vers))
+ {
+ rv = false;
+ continue;
+ }
+ if (CURRENT_VERSION > vers)
+ continue;
+ break;
+ }
+ else if (key == "version-ge")
+ {
+ Version vers;
+ if (!extract(value, &vers))
+ {
+ rv = false;
+ continue;
+ }
+ if (CURRENT_VERSION >= vers)
+ continue;
+ break;
+ }
+ else if (!slave(key, value))
+ {
+ line.error("Bad config key or value");
+ rv = false;
+ continue;
+ }
+ // nothing to see here, move along
+ }
+ return rv;
+}
diff --git a/src/common/config_parse.hpp b/src/common/config_parse.hpp
new file mode 100644
index 0000000..6a55174
--- /dev/null
+++ b/src/common/config_parse.hpp
@@ -0,0 +1,36 @@
+#ifndef TMWA_COMMON_CONFIG_PARSE_HPP
+#define TMWA_COMMON_CONFIG_PARSE_HPP
+// config_parse.hpp - Framework for per-server config parsers.
+//
+// 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 "../sanity.hpp"
+
+# include "../strings/fwd.hpp"
+
+typedef bool (*ConfigItemParser)(XString key, ZString value);
+
+bool is_comment(XString line);
+bool config_split(ZString line, XString *key, ZString *value);
+bool config_split(XString line, XString *key, XString *value);
+
+/// Master config parser. This handles 'import' and 'version-ge' etc.
+/// Then it defers to the inferior parser for a line it does not understand.
+bool load_config_file(ZString filename, ConfigItemParser slave);
+
+#endif // TMWA_COMMON_CONFIG_PARSE_HPP
diff --git a/src/common/core.cpp b/src/common/core.cpp
index 727babd..fe2f660 100644
--- a/src/common/core.cpp
+++ b/src/common/core.cpp
@@ -10,6 +10,8 @@
#include "../strings/zstring.hpp"
+#include "../io/cxxstdio.hpp"
+
#include "random.hpp"
#include "socket.hpp"
#include "timer.hpp"
@@ -46,12 +48,15 @@ sigfunc compat_signal(int signo, sigfunc func)
return oact.sa_handler;
}
+volatile
+bool runflag = true;
+
static
void chld_proc(int)
{
wait(NULL);
}
-static __attribute__((noreturn))
+static
void sig_proc(int)
{
for (int i = 1; i < 31; ++i)
@@ -59,12 +64,9 @@ void sig_proc(int)
#pragma GCC diagnostic ignored "-Wold-style-cast"
compat_signal(i, SIG_IGN);
#pragma GCC diagnostic pop
- term_func();
- _exit(0);
+ runflag = false;
}
-bool runflag = true;
-
/*
Note about fatal signals:
@@ -83,6 +85,12 @@ int main(int argc, char **argv)
for (int i = 0; i < argc; ++i)
args[i] = ZString(strings::really_construct_from_a_pointer, argv[i], nullptr);
do_init(argc, args);
+
+ if (!runflag)
+ {
+ PRINTF("Fatal error during startup; exiting\n");
+ return 1;
+ }
// set up exit handlers *after* the initialization has happened.
// This is because term_func is likely to depend on successful init.
diff --git a/src/common/core.hpp b/src/common/core.hpp
index f93f5a1..8141e9c 100644
--- a/src/common/core.hpp
+++ b/src/common/core.hpp
@@ -8,9 +8,8 @@
/// core.c contains a server-independent main() function
/// and then runs a do_sendrecv loop
-/// When this is cleared, the server exits gracefully
-/// only used by map server's GM command: @mapexit
-extern bool runflag;
+/// When this is cleared, the server exits gracefully.
+extern volatile bool runflag;
/// This is an external function defined by each server
/// This function must register stuff for the parse loop
diff --git a/src/common/utils.cpp b/src/common/utils.cpp
index 7f9a7ee..3a26e6d 100644
--- a/src/common/utils.cpp
+++ b/src/common/utils.cpp
@@ -65,28 +65,6 @@ int config_switch(ZString str)
abort();
}
-bool split_key_value(ZString line, XString *w1, ZString *w2)
-{
- if (line.startswith("//"))
- return false;
- if (!line)
- return false;
-
- if (std::find_if(line.begin(), line.end(),
- [](unsigned char c) { return c < ' '; }
- ) != line.end())
- return false;
- ZString::iterator colon = std::find(line.begin(), line.end(), ':');
- if (colon == line.end())
- return false;
- *w1 = line.xislice_h(colon);
- ++colon;
- while (std::isspace(*colon))
- ++colon;
- *w2 = line.xislice_t(colon);
- return true;
-}
-
static_assert(sizeof(timestamp_seconds_buffer) == 20, "seconds buffer");
static_assert(sizeof(timestamp_milliseconds_buffer) == 24, "millis buffer");
diff --git a/src/common/utils.hpp b/src/common/utils.hpp
index f975e34..161cbd4 100644
--- a/src/common/utils.hpp
+++ b/src/common/utils.hpp
@@ -29,8 +29,6 @@ struct is_trivially_copyable
bool e_mail_check(XString email);
int config_switch (ZString str);
-bool split_key_value(ZString line, XString *w1, ZString *w2);
-
inline
void really_memcpy(uint8_t *dest, const uint8_t *src, size_t n)
{
diff --git a/src/common/version.cpp b/src/common/version.cpp
index 1ee4071..811ffdf 100644
--- a/src/common/version.cpp
+++ b/src/common/version.cpp
@@ -2,6 +2,18 @@
#include "../conf/version.hpp"
+#include "../strings/xstring.hpp"
+
+#include "extract.hpp"
+
+Version CURRENT_VERSION =
+{
+ VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH,
+ VERSION_DEVEL,
+
+ 0, 0,
+ VENDOR_VERSION,
+};
Version CURRENT_LOGIN_SERVER_VERSION =
{
VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH,
@@ -33,3 +45,9 @@ Version CURRENT_MAP_SERVER_VERSION =
const char CURRENT_VERSION_STRING[] = "TMWA "
S(VERSION_MAJOR) "." S(VERSION_MINOR) "." S(VERSION_PATCH)
" dev" S(VERSION_DEVEL) " (" VENDOR " " S(VENDOR_VERSION) ")";
+
+bool extract(XString str, Version *vers)
+{
+ *vers = {};
+ return extract(str, record<'.'>(&vers->major, &vers->minor, &vers->patch));
+}
diff --git a/src/common/version.hpp b/src/common/version.hpp
index 677806b..a2c4e05 100644
--- a/src/common/version.hpp
+++ b/src/common/version.hpp
@@ -3,6 +3,8 @@
# include <cstdint>
+# include "../strings/fwd.hpp"
+
// TODO make these bitwise enums
# define TMWA_FLAG_REGISTRATION 0x01
@@ -25,10 +27,43 @@ struct Version
};
static_assert(sizeof(Version) == 8, "this is sent over the network, can't change");
+extern Version CURRENT_VERSION;
+
extern Version CURRENT_LOGIN_SERVER_VERSION;
extern Version CURRENT_CHAR_SERVER_VERSION;
extern Version CURRENT_MAP_SERVER_VERSION;
extern const char CURRENT_VERSION_STRING[];
+bool extract(XString str, Version *vers);
+
+constexpr
+bool operator < (Version l, Version r)
+{
+ return (l.major < r.major
+ || (l.major == r.major
+ && (l.minor < r.minor
+ || (l.minor == r.minor
+ && (l.patch < r.patch
+ || (l.patch == r.patch
+ && (l.devel < r.devel
+ || (l.devel == r.devel
+ && l.vend < r.vend))))))));
+}
+constexpr
+bool operator > (Version l, Version r)
+{
+ return r < l;
+}
+constexpr
+bool operator <= (Version l, Version r)
+{
+ return !(r < l);
+}
+constexpr
+bool operator >= (Version l, Version r)
+{
+ return !(l < r);
+}
+
#endif // TMWA_COMMON_VERSION_HPP
diff --git a/src/login/login.cpp b/src/login/login.cpp
index 6ba09d2..ea2d19c 100644
--- a/src/login/login.cpp
+++ b/src/login/login.cpp
@@ -24,6 +24,7 @@
#include "../io/lock.hpp"
#include "../io/read.hpp"
+#include "../common/config_parse.hpp"
#include "../common/core.hpp"
#include "../common/db.hpp"
#include "../common/extract.hpp"
@@ -40,9 +41,6 @@
constexpr int MAX_SERVERS = 30;
-#define LOGIN_CONF_NAME "conf/login_athena.conf"
-#define LAN_CONF_NAME "conf/lan_support.conf"
-
constexpr int START_ACCOUNT_NUM = 2000000;
constexpr int END_ACCOUNT_NUM = 100000000;
@@ -77,9 +75,9 @@ int new_account = 0;
static
int login_port = 6900;
static
-IP4Address lan_char_ip;
+IP4Address lan_char_ip = IP4_LOCALHOST;
static
-IP4Mask lan_subnet;
+IP4Mask lan_subnet = IP4Mask(IP4_LOCALHOST, IP4_BROADCAST);
static
FString update_host;
static
@@ -272,9 +270,7 @@ int read_gm_account(void)
FString line;
while (fp.getline(line) && c < 4000)
{
- if (!line)
- continue;
- if (line.startswith("//"))
+ if (is_comment(line))
continue;
GM_Account p {};
if (!extract(line, record<' '>(&p.account_id, &p.level)))
@@ -540,6 +536,7 @@ int mmo_auth_init(void)
if (!in.is_open())
{
// no account file -> no account -> no login, including char-server (ERROR)
+ // not anymore! :-)
PRINTF("\033[1;31mmmo_auth_init: Accounts file [%s] not found.\033[0m\n",
account_filename);
return 0;
@@ -548,7 +545,7 @@ int mmo_auth_init(void)
FString line;
while (in.getline(line))
{
- if (line.startswith("//"))
+ if (is_comment(line))
continue;
if (std::find_if(line.begin(), line.end(),
[](unsigned char c) { return c < ' ' && c != '\t'; }
@@ -2005,7 +2002,7 @@ void parse_admin(int fd)
FString line;
while (fp.getline(line))
{
- if (!line || line.startswith("//"))
+ if (is_comment(line))
fp2.put_line(line);
else
{
@@ -3138,33 +3135,11 @@ void parse_login(int fd)
// Reading Lan Support configuration
//----------------------------------
static
-int login_lan_config_read(ZString lancfgName)
+bool login_lan_config(XString w1, ZString w2)
{
struct hostent *h = NULL;
- // set default configuration
- lan_char_ip = IP4_LOCALHOST;
- lan_subnet = IP4Mask(IP4_LOCALHOST, IP4_BROADCAST);
-
- io::ReadFile in(lancfgName);
-
- if (!in.is_open())
{
- PRINTF("***WARNING: LAN Support configuration file is not found: %s\n",
- lancfgName);
- return 1;
- }
-
- PRINTF("---Start reading Lan Support configuration file\n");
-
- FString line;
- while (in.getline(line))
- {
- XString w1;
- ZString w2;
- if (!split_key_value(line, &w1, &w2))
- continue;
-
if (w1 == "lan_char_ip")
{
// Read Char-Server Lan IP Address
@@ -3180,8 +3155,8 @@ int login_lan_config_read(ZString lancfgName)
}
else
{
- PRINTF("Bad IP value: %s\n", line);
- abort();
+ PRINTF("Bad IP value: %s\n", w2);
+ return false;
}
PRINTF("LAN IP of char-server: %s.\n", lan_char_ip);
}
@@ -3190,19 +3165,23 @@ int login_lan_config_read(ZString lancfgName)
{
if (!extract(w2, &lan_subnet))
{
- PRINTF("Bad IP mask: %s\n", line);
- abort();
+ PRINTF("Bad IP mask: %s\n", w2);
+ return false;
}
PRINTF("Sub-network of the char-server: %s.\n",
lan_subnet);
}
else
{
- FString w1z = w1;
- PRINTF("WARNING: unknown lan-config key: %s\n", w1z);
+ return false;
}
}
+ return true;
+}
+static
+bool lan_check()
+{
// log the LAN configuration
LOGIN_LOG("The LAN configuration of the server is set:\n");
LOGIN_LOG("- with LAN IP of char-server: %s.\n", lan_char_ip);
@@ -3216,37 +3195,20 @@ int login_lan_config_read(ZString lancfgName)
{
PRINTF("\033[1;31m***ERROR: LAN IP of the char-server doesn't belong to the specified Sub-network\033[0m\n");
LOGIN_LOG("***ERROR: LAN IP of the char-server doesn't belong to the specified Sub-network.\n");
+ return false;
}
}
- PRINTF("---End reading of Lan Support configuration file\n");
-
- return 0;
+ return true;
}
//-----------------------------------
// Reading general configuration file
//-----------------------------------
static
-int login_config_read(ZString cfgName)
+bool login_config(XString w1, ZString w2)
{
- io::ReadFile in(cfgName);
- if (!in.is_open())
{
- PRINTF("Configuration file (%s) not found.\n", cfgName);
- return 1;
- }
-
- PRINTF("---Start reading of Login Server configuration file (%s)\n",
- cfgName);
- FString line;
- while (in.getline(line))
- {
- XString w1;
- ZString w2;
- if (!split_key_value(line, &w1, &w2))
- continue;
-
if (w1 == "admin_state")
{
admin_state = config_switch(w2);
@@ -3279,8 +3241,8 @@ int login_config_read(ZString cfgName)
IP4Mask n;
if (!extract(w2, &n))
{
- PRINTF("Bad IP mask: %s\n", line);
- abort();
+ PRINTF("Bad IP mask: %s\n", w2);
+ return false;
}
access_ladmin.push_back(n);
}
@@ -3363,7 +3325,10 @@ int login_config_read(ZString cfgName)
else if (w2 == "mutual-failture" || w2 == "mutual-failure")
access_order = ACO::MUTUAL_FAILURE;
else
+ {
PRINTF("Bad order: %s\n", w2);
+ return false;
+ }
}
else if (w1 == "allow")
{
@@ -3388,8 +3353,8 @@ int login_config_read(ZString cfgName)
IP4Mask n;
if (!extract(w2, &n))
{
- PRINTF("Bad IP mask: %s\n", line);
- abort();
+ PRINTF("Bad IP mask: %s\n", w2);
+ return false;
}
access_allow.push_back(n);
}
@@ -3418,8 +3383,8 @@ int login_config_read(ZString cfgName)
IP4Mask n;
if (!extract(w2, &n))
{
- PRINTF("Bad IP mask: %s\n", line);
- abort();
+ PRINTF("Bad IP mask: %s\n", w2);
+ return false;
}
access_deny.push_back(n);
}
@@ -3435,10 +3400,6 @@ int login_config_read(ZString cfgName)
std::chrono::seconds(atoi(w2.c_str())),
std::chrono::seconds(5));
}
- else if (w1 == "import")
- {
- login_config_read(w2);
- }
else if (w1 == "update_host")
{
update_host = w2;
@@ -3457,26 +3418,25 @@ int login_config_read(ZString cfgName)
}
else
{
- FString w1z = w1;
- PRINTF("WARNING: unknown login config key: %s\n", w1z);
+ return false;
}
}
- PRINTF("---End reading of Login Server configuration file.\n");
-
- return 0;
+ return true;
}
//-------------------------------------
// Displaying of configuration warnings
//-------------------------------------
static
-void display_conf_warnings(void)
+bool display_conf_warnings(void)
{
+ bool rv = true;
if (admin_state != 0 && admin_state != 1)
{
PRINTF("***WARNING: Invalid value for admin_state parameter -> set to 0 (no remote admin).\n");
admin_state = 0;
+ rv = false;
}
if (admin_state == 1)
@@ -3484,6 +3444,7 @@ void display_conf_warnings(void)
if (!admin_pass)
{
PRINTF("***WARNING: Administrator password is void (admin_pass).\n");
+ rv = false;
}
else if (admin_pass == stringish<AccountPass>("admin"))
{
@@ -3496,6 +3457,7 @@ void display_conf_warnings(void)
{
PRINTF("***WARNING: 'To GM become' password is void (gm_pass).\n");
PRINTF(" We highly recommend that you set one password.\n");
+ rv = false;
}
else if (gm_pass == "gm")
{
@@ -3507,18 +3469,21 @@ void display_conf_warnings(void)
{
PRINTF("***WARNING: Invalid value for level_new_gm parameter -> set to 60 (default).\n");
level_new_gm = 60;
+ rv = false;
}
if (new_account != 0 && new_account != 1)
{
PRINTF("***WARNING: Invalid value for new_account parameter -> set to 0 (no new account).\n");
new_account = 0;
+ rv = false;
}
if (login_port < 1024 || login_port > 65535)
{
PRINTF("***WARNING: Invalid value for login_port parameter -> set to 6900 (default).\n");
login_port = 6900;
+ rv = false;
}
if (gm_account_filename_check_timer.count() < 0)
@@ -3526,18 +3491,21 @@ void display_conf_warnings(void)
PRINTF("***WARNING: Invalid value for gm_account_filename_check_timer parameter.\n");
PRINTF(" -> set to 15 sec (default).\n");
gm_account_filename_check_timer = std::chrono::seconds(15);
+ rv = false;
}
else if (gm_account_filename_check_timer == std::chrono::seconds(1))
{
PRINTF("***WARNING: Invalid value for gm_account_filename_check_timer parameter.\n");
PRINTF(" -> set to 2 sec (minimum value).\n");
gm_account_filename_check_timer = std::chrono::seconds(2);
+ rv = false;
}
if (save_unknown_packets != 0 && save_unknown_packets != 1)
{
PRINTF("WARNING: Invalid value for save_unknown_packets parameter -> set to 0-no save.\n");
save_unknown_packets = 0;
+ rv = false;
}
if (display_parse_login != 0 && display_parse_login != 1)
@@ -3545,6 +3513,7 @@ void display_conf_warnings(void)
PRINTF("***WARNING: Invalid value for display_parse_login parameter\n");
PRINTF(" -> set to 0 (no display).\n");
display_parse_login = 0;
+ rv = false;
}
if (display_parse_admin != 0 && display_parse_admin != 1)
@@ -3552,6 +3521,7 @@ void display_conf_warnings(void)
PRINTF("***WARNING: Invalid value for display_parse_admin parameter\n");
PRINTF(" -> set to 0 (no display).\n");
display_parse_admin = 0;
+ rv = false;
}
if (display_parse_fromchar < 0 || display_parse_fromchar > 2)
@@ -3559,6 +3529,7 @@ void display_conf_warnings(void)
PRINTF("***WARNING: Invalid value for display_parse_fromchar parameter\n");
PRINTF(" -> set to 0 (no display).\n");
display_parse_fromchar = 0;
+ rv = false;
}
if (min_level_to_connect < 0)
@@ -3567,6 +3538,7 @@ void display_conf_warnings(void)
min_level_to_connect);
PRINTF(" -> set to 0 (any player).\n");
min_level_to_connect = 0;
+ rv = false;
}
else if (min_level_to_connect > 99)
{ // 0: all players, 1-99 at least gm level x
@@ -3574,6 +3546,7 @@ void display_conf_warnings(void)
min_level_to_connect);
PRINTF(" -> set to 99 (only GM level 99).\n");
min_level_to_connect = 99;
+ rv = false;
}
if (add_to_unlimited_account != 0 && add_to_unlimited_account != 1)
@@ -3581,6 +3554,7 @@ void display_conf_warnings(void)
PRINTF("***WARNING: Invalid value for add_to_unlimited_account parameter\n");
PRINTF(" -> set to 0 (impossible to add a time to an unlimited account).\n");
add_to_unlimited_account = 0;
+ rv = false;
}
if (start_limited_time < -1)
@@ -3588,6 +3562,7 @@ void display_conf_warnings(void)
PRINTF("***WARNING: Invalid value for start_limited_time parameter\n");
PRINTF(" -> set to -1 (new accounts are created with unlimited time).\n");
start_limited_time = -1;
+ rv = false;
}
if (check_ip_flag != 0 && check_ip_flag != 1)
@@ -3595,6 +3570,7 @@ void display_conf_warnings(void)
PRINTF("***WARNING: Invalid value for check_ip_flag parameter\n");
PRINTF(" -> set to 1 (check players ip between login-server & char-server).\n");
check_ip_flag = 1;
+ rv = false;
}
if (access_order == ACO::DENY_ALLOW)
@@ -3603,6 +3579,7 @@ void display_conf_warnings(void)
{
PRINTF("***WARNING: The IP security order is 'deny,allow' (allow if not deny).\n");
PRINTF(" And you refuse ALL IP.\n");
+ rv = false;
}
}
else if (access_order == ACO::ALLOW_DENY)
@@ -3611,6 +3588,7 @@ void display_conf_warnings(void)
{
PRINTF("***WARNING: The IP security order is 'allow,deny' (deny if not allow).\n");
PRINTF(" But, NO IP IS AUTHORISED!\n");
+ rv = false;
}
}
else
@@ -3621,14 +3599,17 @@ void display_conf_warnings(void)
PRINTF("***WARNING: The IP security order is 'mutual-failture'\n");
PRINTF(" (allow if in the allow list and not in the deny list).\n");
PRINTF(" But, NO IP IS AUTHORISED!\n");
+ rv = false;
}
else if (access_deny.size() == 1 && access_deny.front().mask() == IP4Address())
{
PRINTF("***WARNING: The IP security order is mutual-failture\n");
PRINTF(" (allow if in the allow list and not in the deny list).\n");
PRINTF(" But, you refuse ALL IP!\n");
+ rv = false;
}
}
+ return rv;
}
//-------------------------------
@@ -3825,22 +3806,61 @@ void term_func(void)
LOGIN_LOG("----End of login-server (normal end with closing of all files).\n");
}
+static
+bool login_confs(XString key, ZString value)
+{
+ unsigned sum = 0;
+ sum += login_config(key, value);
+ sum += login_lan_config(key, value);
+ if (sum >= 2)
+ abort();
+ return sum;
+}
+
//------------------------------
// Main function of login-server
//------------------------------
int do_init(int argc, ZString *argv)
{
- // read login-server configuration
- if (argc > 1)
- login_config_read(argv[1]);
- else
- login_config_read(LOGIN_CONF_NAME);
- display_conf_warnings(); // not in login_config_read, because we can use 'import' option, and display same message twice or more
- save_config_in_log(); // not before, because log file name can be changed
- if (argc > 2)
- login_lan_config_read(argv[2]);
- else
- login_lan_config_read(LAN_CONF_NAME);
+ bool loaded_config_yet = false;
+ for (int i = 1; i < argc; ++i)
+ {
+ if (argv[i].startswith('-'))
+ {
+ if (argv[i] == "--help")
+ {
+ PRINTF("Usage: %s [--help] [--version] [files...]\n",
+ argv[0]);
+ exit(0);
+ }
+ else if (argv[i] == "--version")
+ {
+ PRINTF("%s\n", CURRENT_VERSION_STRING);
+ exit(0);
+ }
+ else
+ {
+ FPRINTF(stderr, "Unknown argument: %s\n", argv[i]);
+ runflag = false;
+ }
+ }
+ else
+ {
+ loaded_config_yet = true;
+ runflag &= load_config_file(argv[i], login_confs);
+ }
+ }
+
+ if (!loaded_config_yet)
+ runflag &= load_config_file("conf/tmwa-login.conf", login_confs);
+
+ // not in login_config_read, because we can use 'import' option, and display same message twice or more
+ // (why is that bad?)
+ runflag &= display_conf_warnings();
+ // not before, because log file name can be changed
+ // (that doesn't stop the char-server though)
+ save_config_in_log();
+ runflag &= lan_check();
for (int i = 0; i < AUTH_FIFO_SIZE; i++)
auth_fifo[i].delflag = 1;
diff --git a/src/map/atcommand.cpp b/src/map/atcommand.cpp
index 5256121..9687968 100644
--- a/src/map/atcommand.cpp
+++ b/src/map/atcommand.cpp
@@ -14,6 +14,7 @@
#include "../io/read.hpp"
#include "../io/write.hpp"
+#include "../common/config_parse.hpp"
#include "../common/core.hpp"
#include "../common/extract.hpp"
#include "../common/human_time_diff.hpp"
@@ -317,22 +318,29 @@ AtCommandInfo *get_atcommandinfo_byname(XString name)
return atcommand_info.search(name);
}
-int atcommand_config_read(ZString cfgName)
+bool atcommand_config_read(ZString cfgName)
{
io::ReadFile in(cfgName);
if (!in.is_open())
{
PRINTF("At commands configuration file not found: %s\n", cfgName);
- return 1;
+ return false;
}
+ bool rv = true;
FString line;
while (in.getline(line))
{
+ if (is_comment(line))
+ continue;
XString w1;
ZString w2;
- if (!split_key_value(line, &w1, &w2))
+ if (!config_split(line, &w1, &w2))
+ {
+ PRINTF("Bad config line: %s\n", line);
+ rv = false;
continue;
+ }
AtCommandInfo *p = get_atcommandinfo_byname(w1);
if (p != NULL)
{
@@ -343,12 +351,15 @@ int atcommand_config_read(ZString cfgName)
p->level = 0;
}
else if (w1 == "import")
- atcommand_config_read(w2);
+ rv &= atcommand_config_read(w2);
else
+ {
PRINTF("%s: bad line: %s\n", cfgName, line);
+ rv = false;
+ }
}
- return 0;
+ return rv;
}
/// @ command processing functions
@@ -3384,61 +3395,6 @@ ATCE atcommand_partyrecall(const int fd, dumb_ptr<map_session_data> sd,
}
static
-ATCE atcommand_reloaditemdb(const int fd, dumb_ptr<map_session_data>,
- ZString)
-{
- itemdb_reload();
- clif_displaymessage(fd, "Item database reloaded.");
-
- return ATCE::OKAY;
-}
-
-static
-ATCE atcommand_reloadmobdb(const int fd, dumb_ptr<map_session_data>,
- ZString)
-{
- mob_reload();
- clif_displaymessage(fd, "Monster database reloaded.");
-
- return ATCE::OKAY;
-}
-
-static
-ATCE atcommand_reloadskilldb(const int fd, dumb_ptr<map_session_data>,
- ZString)
-{
- skill_reload();
- clif_displaymessage(fd, "Skill database reloaded.");
-
- return ATCE::OKAY;
-}
-
-static
-ATCE atcommand_reloadscript(const int fd, dumb_ptr<map_session_data>,
- ZString)
-{
- do_init_npc();
- do_init_script();
-
- npc_event_do_oninit();
-
- clif_displaymessage(fd, "Scripts reloaded.");
-
- return ATCE::OKAY;
-}
-
-static
-ATCE atcommand_reloadgmdb(const int fd, dumb_ptr<map_session_data>,
- ZString)
-{
- chrif_reloadGMdb();
-
- clif_displaymessage(fd, "Login-server asked to reload GM accounts and their level.");
-
- return ATCE::OKAY;
-}
-
-static
ATCE atcommand_mapinfo(const int fd, dumb_ptr<map_session_data> sd,
ZString message)
{
@@ -5331,21 +5287,6 @@ Map<XString, AtCommandInfo> atcommand_info =
{"charstreset", {"<charname>",
60, atcommand_charstreset,
"Reset a player's stat points"}},
- {"reloaditemdb", {"",
- 99, atcommand_reloaditemdb,
- "Allegedly to reload the item database"}},
- {"reloadmobdb", {"",
- 99, atcommand_reloadmobdb,
- "Allegedly to reload the mob database"}},
- {"reloadskilldb", {"",
- 99, atcommand_reloadskilldb,
- "Allegedly to reload the skill database"}},
- {"reloadscript", {"",
- 99, atcommand_reloadscript,
- "Allegedly to reload the script database"}},
- {"reloadgmdb", {"",
- 99, atcommand_reloadgmdb,
- "Unnecessarily reload the GM database"}},
{"charreset", {"<charname>",
60, atcommand_charreset,
"Reset a player's skills, stats, and magic"}},
diff --git a/src/map/atcommand.hpp b/src/map/atcommand.hpp
index 31f1432..b494a25 100644
--- a/src/map/atcommand.hpp
+++ b/src/map/atcommand.hpp
@@ -10,7 +10,7 @@
bool is_atcommand(const int fd, dumb_ptr<map_session_data> sd,
ZString message, int gmlvl);
-int atcommand_config_read(ZString cfgName);
+bool atcommand_config_read(ZString cfgName);
void log_atcommand(dumb_ptr<map_session_data> sd, ZString cmd);
diff --git a/src/map/battle.cpp b/src/map/battle.cpp
index 05bacd4..35cef79 100644
--- a/src/map/battle.cpp
+++ b/src/map/battle.cpp
@@ -8,6 +8,7 @@
#include "../io/cxxstdio.hpp"
#include "../io/read.hpp"
+#include "../common/config_parse.hpp"
#include "../common/nullpo.hpp"
#include "../common/random.hpp"
@@ -21,7 +22,13 @@
#include "../poison.hpp"
-struct Battle_Config battle_config;
+
+static Battle_Config init_battle_config();
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wshadow"
+struct Battle_Config battle_config = init_battle_config();
+#pragma GCC diagnostic pop
/*==========================================
* 自分をロックしている対象の数を返す(汎用)
@@ -2289,15 +2296,12 @@ int battle_check_range(dumb_ptr<block_list> src, dumb_ptr<block_list> bl,
bl->bl_x - dx, bl->bl_y - dy, 0x10001) != -1) ? 1 : 0;
}
-/*==========================================
- * 設定ファイルを読み込む
- *------------------------------------------
- */
-int battle_config_read(ZString cfgName)
+Battle_Config init_battle_config()
{
- static int count = 0;
-
- if ((count++) == 0)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wshadow"
+ Battle_Config battle_config;
+#pragma GCC diagnostic pop
{
battle_config.warp_point_debug = 0;
battle_config.enemy_critical = 0;
@@ -2403,12 +2407,17 @@ int battle_config_read(ZString cfgName)
battle_config.mob_splash_radius = -1;
}
+ return battle_config;
+}
+bool battle_config_read(ZString cfgName)
+{
+ bool rv = true;
io::ReadFile in(cfgName);
if (!in.is_open())
{
PRINTF("file not found: %s\n", cfgName);
- return 1;
+ return false;
}
FString line;
@@ -2522,10 +2531,16 @@ int battle_config_read(ZString cfgName)
BATTLE_CONFIG_VAR(mob_splash_radius),
};
+ if (is_comment(line))
+ continue;
XString w1;
ZString w2;
- if (!split_key_value(line, &w1, &w2))
+ if (!config_split(line, &w1, &w2))
+ {
+ PRINTF("Bad config line: %s\n", line);
+ rv = false;
continue;
+ }
if (w1 == "import")
{
@@ -2541,12 +2556,17 @@ int battle_config_read(ZString cfgName)
}
PRINTF("WARNING: unknown battle conf key: %s\n", FString(w1));
+ rv = false;
continue_outer:
;
}
- if (--count == 0)
+ return rv;
+}
+
+void battle_config_check()
+{
{
if (static_cast<interval_t>(battle_config.flooritem_lifetime) < std::chrono::seconds(1))
battle_config.flooritem_lifetime = std::chrono::duration_cast<std::chrono::milliseconds>(LIFETIME_FLOORITEM).count();
@@ -2657,6 +2677,4 @@ int battle_config_read(ZString cfgName)
else if (battle_config.mask_ip_gms > 1)
battle_config.mask_ip_gms = 1;
}
-
- return 0;
}
diff --git a/src/map/battle.hpp b/src/map/battle.hpp
index 02a32ad..32c479e 100644
--- a/src/map/battle.hpp
+++ b/src/map/battle.hpp
@@ -202,6 +202,7 @@ extern struct Battle_Config
int mob_splash_radius;
} battle_config;
-int battle_config_read(ZString cfgName);
+bool battle_config_read(ZString cfgName);
+void battle_config_check();
#endif // BATTLE_HPP
diff --git a/src/map/chrif.cpp b/src/map/chrif.cpp
index 4afccb7..5b9f96f 100644
--- a/src/map/chrif.cpp
+++ b/src/map/chrif.cpp
@@ -1187,7 +1187,7 @@ void check_connect_char_server(TimerData *, tick_t)
*
*------------------------------------------
*/
-int do_init_chrif (void)
+void do_init_chrif(void)
{
Timer(gettick() + std::chrono::seconds(1),
check_connect_char_server,
@@ -1197,6 +1197,4 @@ int do_init_chrif (void)
send_users_tochar,
std::chrono::seconds(5)
).detach();
-
- return 0;
}
diff --git a/src/map/chrif.hpp b/src/map/chrif.hpp
index 51c6d20..dfa2d35 100644
--- a/src/map/chrif.hpp
+++ b/src/map/chrif.hpp
@@ -34,7 +34,7 @@ int chrif_saveaccountreg2(dumb_ptr<map_session_data> sd);
int chrif_reloadGMdb(void);
int chrif_send_divorce(int char_id);
-int do_init_chrif (void);
+void do_init_chrif(void);
// only used by intif.cpp
extern int char_fd;
diff --git a/src/map/clif.cpp b/src/map/clif.cpp
index 5b7c21d..b4ac24a 100644
--- a/src/map/clif.cpp
+++ b/src/map/clif.cpp
@@ -5597,14 +5597,8 @@ void clif_parse(int fd)
RFIFOSKIP(fd, packet_len);
}
-/*==========================================
- *
- *------------------------------------------
- */
-int do_init_clif (void)
+void do_init_clif(void)
{
set_defaultparse(clif_parse);
make_listen_port(map_port);
-
- return 0;
}
diff --git a/src/map/clif.hpp b/src/map/clif.hpp
index bf7393c..ad51fc8 100644
--- a/src/map/clif.hpp
+++ b/src/map/clif.hpp
@@ -161,6 +161,6 @@ int clif_GM_kick(dumb_ptr<map_session_data> sd, dumb_ptr<map_session_data> tsd,
int clif_foreachclient(std::function<void(dumb_ptr<map_session_data>)>);
-int do_init_clif (void);
+void do_init_clif(void);
#endif // CLIF_HPP
diff --git a/src/map/itemdb.cpp b/src/map/itemdb.cpp
index 313ff23..bcef583 100644
--- a/src/map/itemdb.cpp
+++ b/src/map/itemdb.cpp
@@ -10,6 +10,7 @@
#include "../io/cxxstdio.hpp"
#include "../io/read.hpp"
+#include "../common/config_parse.hpp"
#include "../common/db.hpp"
#include "../common/extract.hpp"
#include "../common/nullpo.hpp"
@@ -29,11 +30,6 @@ Map<int, struct item_data> item_db;
// Function declarations
-static
-void itemdb_read(void);
-static
-int itemdb_readdb(void);
-
/*==========================================
* 名前で検索用
*------------------------------------------
@@ -148,15 +144,11 @@ int itemdb_isequip3(int nameid)
|| type == ItemType::_8);
}
-/*==========================================
- * アイテムデータベースの読み込み
- *------------------------------------------
- */
-static
-int itemdb_readdb(void)
+bool itemdb_readdb(ZString filename)
{
+ bool rv = true;
+
int ln = 0, lines = 0;
- ZString filename = "db/item_db.txt";
{
io::ReadFile in(filename);
@@ -164,7 +156,7 @@ int itemdb_readdb(void)
if (!in.is_open())
{
PRINTF("can't read %s\n", filename);
- exit(1);
+ return false;
}
lines = 0;
@@ -173,9 +165,7 @@ int itemdb_readdb(void)
while (in.getline(line))
{
lines++;
- if (!line)
- continue;
- if (line.startswith("//"))
+ if (is_comment(line))
continue;
// a line is 17 normal fields followed by 2 {} fields
// the fields are separated by ", *", but there may be ,
@@ -212,6 +202,7 @@ int itemdb_readdb(void)
{
PRINTF("%s:%d: error: bad item line: %s\n",
filename, lines, line);
+ rv = false;
continue;
}
@@ -245,7 +236,8 @@ int itemdb_readdb(void)
}
PRINTF("read %s done (count=%d)\n", filename, ln);
}
- return 0;
+
+ return rv;
}
/*==========================================
@@ -259,18 +251,6 @@ void itemdb_final(struct item_data *id)
id->equip_script.reset();
}
-void itemdb_reload(void)
-{
- /*
- *
- * <empty item databases>
- * itemdb_read();
- *
- */
-
- do_init_itemdb();
-}
-
/*==========================================
*
*------------------------------------------
@@ -281,39 +261,3 @@ void do_final_itemdb(void)
itemdb_final(&pair.second);
item_db.clear();
}
-
-/*
-static
-FILE *dfp;
-static
-int itemdebug(void *key,void *data,_va_list ap){
-// struct item_data *id=(struct item_data *)data;
- FPRINTF(dfp,"%6d", (int)key);
- return 0;
-}
-void itemdebugtxt()
-{
- dfp=fopen_("itemdebug.txt","wt");
- numdb_foreach(item_db,itemdebug);
- fclose_(dfp);
-}
-*/
-
-/*====================================
- * Removed item_value_db, don't re-add
- *------------------------------------
- */
-static
-void itemdb_read(void)
-{
- itemdb_readdb();
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-void do_init_itemdb(void)
-{
- itemdb_read();
-}
diff --git a/src/map/itemdb.hpp b/src/map/itemdb.hpp
index e41be41..2ec8f1c 100644
--- a/src/map/itemdb.hpp
+++ b/src/map/itemdb.hpp
@@ -77,6 +77,6 @@ int itemdb_isequip3(int);
void itemdb_reload(void);
void do_final_itemdb(void);
-void do_init_itemdb(void);
+bool itemdb_readdb(ZString filename);
#endif // ITEMDB_HPP
diff --git a/src/map/magic-interpreter-parser.ypp b/src/map/magic-interpreter-parser.ypp
index d59519a..0e03afb 100644
--- a/src/map/magic-interpreter-parser.ypp
+++ b/src/map/magic-interpreter-parser.ypp
@@ -1381,16 +1381,17 @@ void INTERN_ASSERT(ZString name, int id)
{
int zid = intern_id(name);
if (zid != id)
+ {
FPRINTF(stderr,
"[magic-conf] INTERNAL ERROR: Builtin special var %s interned to %d, not %d as it should be!\n",
name, zid, id);
- error_flag = 1;
+ error_flag = 1;
+ }
}
extern FILE *magic_frontend_in;
-// must be called after itemdb initialisation
-int magic_init(const char *conffile)
+bool magic_init0()
{
error_flag = 0;
@@ -1404,18 +1405,24 @@ int magic_init(const char *conffile)
INTERN_ASSERT("script_target", VAR_SCRIPTTARGET);
INTERN_ASSERT("location", VAR_LOCATION);
- magic_frontend_in = fopen(conffile, "r");
+ return !error_flag;
+}
+
+// must be called after itemdb initialisation
+bool magic_init1(ZString conffile)
+{
+ magic_frontend_in = fopen(conffile.c_str(), "r");
if (!magic_frontend_in)
{
FPRINTF(stderr, "[magic-conf] Magic configuration file `%s' not found -> no magic.\n", conffile);
- return 0;
+ return false;
}
magic_frontend_parse();
PRINTF("[magic-conf] Magic initialised. %zu spells, %zu teleport anchors.\n",
magic_conf.spells_by_name.size(), magic_conf.anchors_by_name.size());
- return error_flag;
+ return !error_flag;
}
extern int magic_frontend_lineno;
diff --git a/src/map/magic-interpreter.hpp b/src/map/magic-interpreter.hpp
index 8afb8af..19f8574 100644
--- a/src/map/magic-interpreter.hpp
+++ b/src/map/magic-interpreter.hpp
@@ -445,8 +445,9 @@ struct proc_t
{}
};
+bool magic_init0();
// must be called after itemdb initialisation
-int magic_init(const char *);
+bool magic_init1(ZString filename);
void spell_update_location(dumb_ptr<invocation> invocation);
#endif // MAGIC_INTERPRETER_HPP
diff --git a/src/map/magic.cpp b/src/map/magic.cpp
index fd848f5..2e521b2 100644
--- a/src/map/magic.cpp
+++ b/src/map/magic.cpp
@@ -104,8 +104,3 @@ int magic_message(dumb_ptr<map_session_data> caster, XString source_invocation)
return 0; /* Not a spell */
}
-
-void do_init_magic(void)
-{
- magic_init(MAGIC_CONFIG_FILE);
-}
diff --git a/src/map/magic.hpp b/src/map/magic.hpp
index 79e2a84..30c6e62 100644
--- a/src/map/magic.hpp
+++ b/src/map/magic.hpp
@@ -44,11 +44,6 @@ void spell_effect_report_termination(int invocation, int bl_id,
StatusChange sc_id, int supplanted);
/**
- * Initialise all spells, read config data
- */
-void do_init_magic(void);
-
-/**
* Identifies the invocation used to trigger a spell
*
* Returns empty string if not found
diff --git a/src/map/map.cpp b/src/map/map.cpp
index 32df1fd..e141ae1 100644
--- a/src/map/map.cpp
+++ b/src/map/map.cpp
@@ -19,6 +19,7 @@
#include "../io/write.hpp"
#include "../io/read.hpp"
+#include "../common/config_parse.hpp"
#include "../common/core.hpp"
#include "../common/db.hpp"
#include "../common/extract.hpp"
@@ -26,6 +27,7 @@
#include "../common/nullpo.hpp"
#include "../common/socket.hpp"
#include "../common/timer.hpp"
+#include "../common/version.hpp"
#include "atcommand.hpp"
#include "battle.hpp"
@@ -73,7 +75,6 @@ interval_t autosave_time = DEFAULT_AUTOSAVE_INTERVAL;
int save_settings = 0xFFFF;
FString motd_txt = "conf/motd.txt";
-FString help_txt = "conf/help.txt";
CharName wisp_server_name = stringish<CharName>("Server"); // can be modified in char-server configuration file
@@ -1271,8 +1272,10 @@ bool map_readmap(map_local *m, size_t num, MapName fn)
*------------------------------------------
*/
static
-int map_readallmap(void)
+bool map_readallmap(void)
{
+ // I am increasingly of the opinion that this needs to be moved earlier.
+
int maps_removed = 0;
int num = 0;
@@ -1299,9 +1302,10 @@ int map_readallmap(void)
{
PRINTF("Cowardly refusing to keep going after removing %d maps.\n",
maps_removed);
- exit(1);
+ return false;
}
- return 0;
+
+ return true;
}
/*==========================================
@@ -1427,7 +1431,7 @@ void map_log(XString line)
*------------------------------------------
*/
static
-int map_config_read(ZString cfgName)
+bool map_config_read(ZString cfgName)
{
struct hostent *h = NULL;
@@ -1435,16 +1439,23 @@ int map_config_read(ZString cfgName)
if (!in.is_open())
{
PRINTF("Map configuration file not found at: %s\n", cfgName);
- exit(1);
+ return false;
}
+ bool rv = true;
FString line;
while (in.getline(line))
{
+ if (is_comment(line))
+ continue;
XString w1;
ZString w2;
- if (!split_key_value(line, &w1, &w2))
+ if (!config_split(line, &w1, &w2))
+ {
+ PRINTF("Bad config line: %s\n", line);
+ rv = false;
continue;
+ }
if (w1 == "userid")
{
AccountName name = stringish<AccountName>(w2);
@@ -1473,7 +1484,7 @@ int map_config_read(ZString cfgName)
else
{
PRINTF("Bad IP value: %s\n", line);
- abort();
+ return false;
}
chrif_setip(w2ip);
}
@@ -1499,7 +1510,7 @@ int map_config_read(ZString cfgName)
else
{
PRINTF("Bad IP value: %s\n", line);
- abort();
+ return false;
}
clif_setip(w2ip);
}
@@ -1535,10 +1546,6 @@ int map_config_read(ZString cfgName)
{
motd_txt = w2;
}
- else if (w1 == "help_txt")
- {
- help_txt = w2;
- }
else if (w1 == "mapreg_txt")
{
mapreg_txt = w2;
@@ -1553,11 +1560,11 @@ int map_config_read(ZString cfgName)
}
else if (w1 == "import")
{
- map_config_read(w2);
+ rv &= map_config_read(w2);
}
}
- return 0;
+ return rv;
}
static
@@ -1618,14 +1625,6 @@ void term_func(void)
map_close_logfile();
}
-/// --help was passed
-// FIXME this should produce output
-static __attribute__((noreturn))
-void map_helpscreen(void)
-{
- exit(1);
-}
-
int compare_item(struct item *a, struct item *b)
{
return ((a->nameid == b->nameid) &&
@@ -1637,56 +1636,93 @@ int compare_item(struct item *a, struct item *b)
(a->card[2] == b->card[2]) && (a->card[3] == b->card[3]));
}
+static
+bool map_confs(XString key, ZString value)
+{
+ if (key == "map_conf")
+ return map_config_read(value);
+ if (key == "battle_conf")
+ return battle_config_read(value);
+ if (key == "atcommand_conf")
+ return atcommand_config_read(value);
+
+ if (key == "item_db")
+ return itemdb_readdb(value);
+ if (key == "mob_db")
+ return mob_readdb(value);
+ if (key == "mob_skill_db")
+ return mob_readskilldb(value);
+ if (key == "skill_db")
+ return skill_readdb(value);
+ if (key == "magic_conf")
+ return magic_init1(value);
+ PRINTF("unknown map conf key: %s\n", FString(key));
+ return false;
+}
+
/*======================================================
* Map-Server Init and Command-line Arguments [Valaris]
*------------------------------------------------------
*/
int do_init(int argc, ZString *argv)
{
- int i;
-
- ZString MAP_CONF_NAME = "conf/map_athena.conf";
- ZString BATTLE_CONF_FILENAME = "conf/battle_athena.conf";
- ZString ATCOMMAND_CONF_FILENAME = "conf/atcommand_athena.conf";
+ runflag &= magic_init0();
- for (i = 1; i < argc; i++)
+ bool loaded_config_yet = false;
+ for (int i = 1; i < argc; ++i)
{
-
- if (argv[i] == "--help" || argv[i] == "-h"
- || argv[i] == "-?" || argv[i] == "/?")
- map_helpscreen();
- else if (argv[i] == "--map_config")
- MAP_CONF_NAME = argv[++i];
- else if (argv[i] == "--battle_config")
- BATTLE_CONF_FILENAME = argv[++i];
- else if (argv[i] == "--atcommand_config")
- ATCOMMAND_CONF_FILENAME = argv[++i];
- else if (argv[i] == "--write-atcommand-config")
+ if (argv[i].startswith('-'))
+ {
+ if (argv[i] == "--help")
+ {
+ PRINTF("Usage: %s [--help] [--version] [--write_atcommand_config outfile] [files...]\n",
+ argv[0]);
+ exit(0);
+ }
+ else if (argv[i] == "--version")
+ {
+ PRINTF("%s\n", CURRENT_VERSION_STRING);
+ exit(0);
+ }
+ else if (argv[i] == "--write-atcommand-config")
+ {
+ ++i;
+ if (i == argc)
+ {
+ PRINTF("Missing argument\n");
+ exit(1);
+ }
+ ZString filename = argv[i];
+ atcommand_config_write(filename);
+ exit(0);
+ }
+ else
+ {
+ FPRINTF(stderr, "Unknown argument: %s\n", argv[i]);
+ runflag = false;
+ }
+ }
+ else
{
- ZString filename = argv[++i];
- atcommand_config_write(filename);
- exit(0);
+ loaded_config_yet = true;
+ runflag &= load_config_file(argv[i], map_confs);
}
}
- map_config_read(MAP_CONF_NAME);
- battle_config_read(BATTLE_CONF_FILENAME);
- atcommand_config_read(ATCOMMAND_CONF_FILENAME);
- script_config_read();
+ if (!loaded_config_yet)
+ runflag &= load_config_file("conf/tmwa-map.conf", map_confs);
- map_readallmap();
+ battle_config_check();
+ runflag &= map_readallmap();
- do_init_chrif ();
- do_init_clif ();
- do_init_itemdb();
- do_init_mob(); // npcの初期化時内でmob_spawnして、mob_dbを参照するのでinit_npcより先
+ do_init_chrif();
+ do_init_clif();
+ do_init_mob2();
do_init_script();
- do_init_npc();
+
+ runflag &= do_init_npc();
do_init_pc();
do_init_party();
- do_init_storage();
- do_init_skill();
- do_init_magic();
npc_event_do_oninit(); // npcのOnInitイベント実行
diff --git a/src/map/map.hpp b/src/map/map.hpp
index 882fde6..0038e67 100644
--- a/src/map/map.hpp
+++ b/src/map/map.hpp
@@ -575,7 +575,6 @@ extern interval_t autosave_time;
extern int save_settings;
extern FString motd_txt;
-extern FString help_txt;
extern CharName wisp_server_name;
diff --git a/src/map/mob.cpp b/src/map/mob.cpp
index 960c58e..d68c580 100644
--- a/src/map/mob.cpp
+++ b/src/map/mob.cpp
@@ -14,6 +14,7 @@
#include "../io/cxxstdio.hpp"
#include "../io/read.hpp"
+#include "../common/config_parse.hpp"
#include "../common/extract.hpp"
#include "../common/nullpo.hpp"
#include "../common/random.hpp"
@@ -3408,31 +3409,24 @@ bool extract(XString str, LevelElement *le)
return false;
}
-/*==========================================
- * db/mob_db.txt reading
- *------------------------------------------
- */
-static
-int mob_readdb(void)
+bool mob_readdb(ZString filename)
{
- ZString filename = "db/mob_db.txt";
-
- for (mob_db_& e : mob_db)
- e = mob_db_{};
-
+ bool rv = true;
{
io::ReadFile in(filename);
if (!in.is_open())
{
- return -1;
+ PRINTF("Unable to read mob db: %s\n", filename);
+ return false;
}
FString line;
while (in.getline(line))
{
int mob_class;
- if (!line || line.startswith("//"))
+ if (is_comment(line))
continue;
+
struct mob_db_ mdbv {};
XString ignore;
@@ -3501,6 +3495,7 @@ int mob_readdb(void)
if (!okay || mob_class <= 1000 || mob_class > 2000)
{
PRINTF("bad mob line: %s\n", line);
+ rv = false;
continue;
}
@@ -3554,7 +3549,7 @@ int mob_readdb(void)
}
PRINTF("read %s done\n", filename);
}
- return 0;
+ return rv;
}
template<>
@@ -3625,28 +3620,22 @@ bool extract<MobSkillTarget, void, void>(XString str, MobSkillTarget *mst)
return false;
}
-/*==========================================
- * db/mob_skill_db.txt reading
- *------------------------------------------
- */
-static
-int mob_readskilldb(void)
+bool mob_readskilldb(ZString filename)
{
- ZString filename = "db/mob_skill_db.txt";
-
+ bool rv = true;
{
io::ReadFile in(filename);
if (!in.is_open())
{
PRINTF("can't read %s\n", filename);
- return 0;
+ return false;
}
FString line;
while (in.getline(line))
{
int mob_id;
- if (line.startswith("//"))
+ if (is_comment(line))
continue;
XString blah;
@@ -3692,43 +3681,29 @@ int mob_readskilldb(void)
else if (cancellable == "no")
msv.cancel = false;
else
+ {
+ rv = false;
continue;
+ }
msv.casttime = std::chrono::milliseconds(casttime);
msv.delay = std::chrono::milliseconds(delay);
if (mob_id <= 0)
+ {
+ rv = false;
continue;
+ }
mob_db[mob_id].skills.push_back(std::move(msv));
}
PRINTF("read %s done\n", filename);
}
- return 0;
+ return rv;
}
-void mob_reload(void)
+void do_init_mob2(void)
{
- /*
- *
- * <empty monster database>
- * mob_read();
- *
- */
-
- do_init_mob();
-}
-
-/*==========================================
- * Circumference initialization of mob
- *------------------------------------------
- */
-int do_init_mob(void)
-{
- mob_readdb();
-
- mob_readskilldb();
-
Timer(gettick() + MIN_MOBTHINKTIME,
mob_ai_hard,
MIN_MOBTHINKTIME
@@ -3737,6 +3712,4 @@ int do_init_mob(void)
mob_ai_lazy,
MIN_MOBTHINKTIME * 10
).detach();
-
- return 0;
}
diff --git a/src/map/mob.hpp b/src/map/mob.hpp
index b0445de..bc8350a 100644
--- a/src/map/mob.hpp
+++ b/src/map/mob.hpp
@@ -84,7 +84,10 @@ short mob_get_head_mid(int);
short mob_get_head_buttom(int);
short mob_get_clothes_color(int); //player mob dye [Valaris]
int mob_get_equip(int); // mob equip [Valaris]
-int do_init_mob(void);
+
+bool mob_readdb(ZString filename);
+bool mob_readskilldb(ZString filename);
+void do_init_mob2(void);
int mob_delete(dumb_ptr<mob_data> md);
int mob_catch_delete(dumb_ptr<mob_data> md, BeingRemoveWhy type);
diff --git a/src/map/npc.cpp b/src/map/npc.cpp
index f5a1f21..4a116b2 100644
--- a/src/map/npc.cpp
+++ b/src/map/npc.cpp
@@ -15,6 +15,7 @@
#include "../io/cxxstdio.hpp"
#include "../io/read.hpp"
+#include "../common/config_parse.hpp"
#include "../common/db.hpp"
#include "../common/extract.hpp"
#include "../common/nullpo.hpp"
@@ -1711,8 +1712,9 @@ void npc_free(dumb_ptr<npc_data> nd)
* npc初期化
*------------------------------------------
*/
-int do_init_npc(void)
+bool do_init_npc(void)
{
+ bool rv = true;
// other fields unused
ev_tm_b.tm_min = -1;
ev_tm_b.tm_hour = -1;
@@ -1725,7 +1727,8 @@ int do_init_npc(void)
if (!fp.is_open())
{
PRINTF("file not found : %s\n", nsl);
- exit(1);
+ rv = false;
+ continue;
}
PRINTF("\rLoading NPCs [%d]: %-54s", npc_id - START_NPC_NUM,
nsl);
@@ -1737,14 +1740,13 @@ int do_init_npc(void)
ZString w4z;
lines++;
- if (!zline)
- continue;
- if (zline.startswith("//"))
+ if (is_comment(zline))
continue;
if (!extract(zline, record<'|', 3>(&w1, &w2, &w3, &w4x)) || !w1 || !w2 || !w3)
{
FPRINTF(stderr, "%s:%d: Broken script line: %s\n", nsl, lines, zline);
+ rv = false;
continue;
}
if (&*w4x.end() == &*zline.end())
@@ -1762,6 +1764,7 @@ int do_init_npc(void)
{
// "mapname" is not assigned to this server
FPRINTF(stderr, "%s:%d: Map not found: %s\n", nsl, lines, mapname);
+ rv = false;
continue;
}
}
@@ -1801,6 +1804,7 @@ int do_init_npc(void)
else
{
PRINTF("odd script line: %s\n", zline);
+ script_errors++;
}
}
fflush(stdout);
@@ -1811,8 +1815,7 @@ int do_init_npc(void)
if (script_errors)
{
PRINTF("Cowardly refusing to continue after %d errors\n", script_errors);
- abort();
+ rv = false;
}
-
- return 0;
+ return rv;
}
diff --git a/src/map/npc.hpp b/src/map/npc.hpp
index 0bc00ed..17eea04 100644
--- a/src/map/npc.hpp
+++ b/src/map/npc.hpp
@@ -48,7 +48,7 @@ void npc_free(dumb_ptr<npc_data> npc);
void npc_addsrcfile(FString);
void npc_delsrcfile(FString);
-int do_init_npc(void);
+bool do_init_npc(void);
int npc_event_do_oninit(void);
int npc_event_doall_l(ScriptLabel name, int rid, int argc, struct argrec_t *argv);
diff --git a/src/map/pc.cpp b/src/map/pc.cpp
index 4cfa107..73639dd 100644
--- a/src/map/pc.cpp
+++ b/src/map/pc.cpp
@@ -5269,11 +5269,7 @@ void pc_calc_sigma(void)
}
}
-/*==========================================
- * pc関 係初期化
- *------------------------------------------
- */
-int do_init_pc(void)
+void do_init_pc(void)
{
pc_calc_sigma();
natural_heal_prev_tick = gettick() + NATURAL_HEAL_INTERVAL;
@@ -5284,8 +5280,6 @@ int do_init_pc(void)
Timer(gettick() + autosave_time,
pc_autosave
).detach();
-
- return 0;
}
void pc_cleanup(dumb_ptr<map_session_data> sd)
diff --git a/src/map/pc.hpp b/src/map/pc.hpp
index 40d0e76..54394a2 100644
--- a/src/map/pc.hpp
+++ b/src/map/pc.hpp
@@ -153,6 +153,6 @@ int pc_logout(dumb_ptr<map_session_data> sd); // [fate] Player logs out
void pc_show_motd(dumb_ptr<map_session_data> sd);
-int do_init_pc(void);
+void do_init_pc(void);
#endif // PC_HPP
diff --git a/src/map/script.cpp b/src/map/script.cpp
index e947208..51f228f 100644
--- a/src/map/script.cpp
+++ b/src/map/script.cpp
@@ -16,6 +16,7 @@
#include "../io/lock.hpp"
#include "../io/read.hpp"
+#include "../common/config_parse.hpp"
#include "../common/core.hpp"
#include "../common/db.hpp"
#include "../common/extract.hpp"
@@ -89,13 +90,20 @@ const char *pos_str[11] =
static
struct Script_Config
{
- int warn_func_no_comma;
- int warn_cmd_no_comma;
- int warn_func_mismatch_paramnum;
- int warn_cmd_mismatch_paramnum;
- int check_cmdcount;
- int check_gotocount;
+ static const
+ int warn_func_no_comma = 1;
+ static const
+ int warn_cmd_no_comma = 1;
+ static const
+ int warn_func_mismatch_paramnum = 1;
+ static const
+ int warn_cmd_mismatch_paramnum = 1;
+ static const
+ int check_cmdcount = 8192;
+ static const
+ int check_gotocount = 512;
} script_config;
+
static
int parse_cmd_if = 0;
static
@@ -698,7 +706,7 @@ void read_constdb(void)
FString line;
while (in.getline(line))
{
- if (line.startswith("//"))
+ if (is_comment(line))
continue;
FString name;
@@ -5001,16 +5009,6 @@ void script_autosave_mapreg(TimerData *, tick_t)
script_save_mapreg();
}
-void script_config_read()
-{
- script_config.warn_func_no_comma = 1;
- script_config.warn_cmd_no_comma = 1;
- script_config.warn_func_mismatch_paramnum = 1;
- script_config.warn_cmd_mismatch_paramnum = 1;
- script_config.check_cmdcount = 8192;
- script_config.check_gotocount = 512;
-}
-
void do_final_script(void)
{
if (mapreg_dirty >= 0)
diff --git a/src/map/script.hpp b/src/map/script.hpp
index da1d3ce..a05ecf6 100644
--- a/src/map/script.hpp
+++ b/src/map/script.hpp
@@ -159,7 +159,6 @@ Map<ScriptLabel, int> scriptlabel_db;
extern
UPMap<FString, const ScriptBuffer> userfunc_db;
-void script_config_read();
void do_init_script(void);
void do_final_script(void);
diff --git a/src/map/skill.cpp b/src/map/skill.cpp
index 5c8ba09..2253d9d 100644
--- a/src/map/skill.cpp
+++ b/src/map/skill.cpp
@@ -1173,29 +1173,21 @@ SP scan_stat(XString statname)
return SP::ZERO;
}
-/*==========================================
- * スキル関係ファイル読み込み
- * skill_db.txt スキルデータ
- * skill_cast_db.txt スキルの詠唱時間とディレイデータ
- *------------------------------------------
- */
-static
-int skill_readdb(void)
+bool skill_readdb(ZString filename)
{
- /* The main skill database */
- for (skill_db_& skdb : skill_db)
- skdb = skill_db_{};
-
- io::ReadFile in("db/skill_db.txt");
+ io::ReadFile in(filename);
if (!in.is_open())
{
- PRINTF("can't read db/skill_db.txt\n");
- return 1;
+ PRINTF("can't read %s\n", filename);
+ return false;
}
+ bool rv = true;
FString line_;
while (in.getline(line_))
{
+ // is_comment only works for whole-line comments
+ // that could change once the Z dependency is dropped ...
XString comment = "//";
XString line = line_.xislice_h(std::search(line_.begin(), line_.end(), comment.begin(), comment.end())).rstrip();
if (!line)
@@ -1228,16 +1220,25 @@ int skill_readdb(void)
)
)
)
+ {
+ rv = false;
continue;
+ }
if (/*i < SkillID() ||*/ i > SkillID::MAX_SKILL_DB)
+ {
+ rv = false;
continue;
+ }
if (castcancel == "yes")
skdb.castcancel = true;
else if (castcancel == "no")
skdb.castcancel = false;
else
+ {
+ rv = false;
continue;
+ }
if (flags == "passive")
{
@@ -1252,7 +1253,10 @@ int skill_readdb(void)
else if (flags == "no")
skdb.poolflags = SkillFlags::ZERO;
else
+ {
+ rv = false;
continue;
+ }
skdb.stat = scan_stat(stat);
@@ -1265,32 +1269,9 @@ int skill_readdb(void)
skill_db[i] = skdb;
skill_lookup_by_id(i).desc = FString(tmp);
}
- PRINTF("read db/skill_db.txt done\n");
-
- return 0;
-}
-
-void skill_reload(void)
-{
- /*
- *
- * <empty skill database>
- * <?>
- *
- */
-
- do_init_skill();
-}
+ PRINTF("read %s done\n", filename);
-/*==========================================
- * スキル関係初期化処理
- *------------------------------------------
- */
-int do_init_skill(void)
-{
- skill_readdb();
-
- return 0;
+ return rv;
}
constexpr size_t num_names = sizeof(skill_names) / sizeof(skill_names[0]);
diff --git a/src/map/skill.hpp b/src/map/skill.hpp
index 14ff1b5..5f29443 100644
--- a/src/map/skill.hpp
+++ b/src/map/skill.hpp
@@ -57,7 +57,7 @@ skill_name_db& skill_lookup_by_name(XString name);
struct block_list;
struct map_session_data;
-int do_init_skill(void);
+bool skill_readdb(ZString filename);
// スキルデータベースへのアクセサ
int skill_get_hit(SkillID id);
diff --git a/src/map/storage.cpp b/src/map/storage.cpp
index 54bc792..d6832c8 100644
--- a/src/map/storage.cpp
+++ b/src/map/storage.cpp
@@ -21,10 +21,6 @@
static
Map<int, struct storage> storage_db;
-void do_init_storage(void)
-{
-}
-
void do_final_storage(void)
{
storage_db.clear();
diff --git a/src/map/storage.hpp b/src/map/storage.hpp
index f923ebe..76be7d6 100644
--- a/src/map/storage.hpp
+++ b/src/map/storage.hpp
@@ -10,7 +10,6 @@ int storage_storageopen(dumb_ptr<map_session_data> sd);
int storage_storageadd(dumb_ptr<map_session_data> sd, int index, int amount);
int storage_storageget(dumb_ptr<map_session_data> sd, int index, int amount);
int storage_storageclose(dumb_ptr<map_session_data> sd);
-void do_init_storage(void);
void do_final_storage(void);
struct storage *account2storage(int account_id);
struct storage *account2storage2(int account_id);
diff --git a/src/monitor/main.cpp b/src/monitor/main.cpp
index 934e24f..1bc9880 100644
--- a/src/monitor/main.cpp
+++ b/src/monitor/main.cpp
@@ -22,6 +22,7 @@
#include "../io/cxxstdio.hpp"
#include "../io/read.hpp"
+#include "../common/config_parse.hpp"
#include "../common/utils.hpp"
#include "../poison.hpp"
@@ -57,7 +58,7 @@ FString make_path(XString base, XString path)
}
static
-void parse_option(XString name, ZString value)
+bool parse_option(XString name, ZString value)
{
if (name == "login_server")
login_server = value;
@@ -72,12 +73,15 @@ void parse_option(XString name, ZString value)
FString name_ = name;
FPRINTF(stderr, "WARNING: ingnoring invalid option '%s' : '%s'\n",
name_, value);
+ return false;
}
+ return true;
}
static
-void read_config(ZString filename)
+bool read_config(ZString filename)
{
+ bool rv = true;
io::ReadFile in(filename);
if (!in.is_open())
{
@@ -88,13 +92,25 @@ void read_config(ZString filename)
FString line;
while (in.getline(line))
{
+ if (is_comment(line))
+ continue;
XString name;
ZString value;
- if (!split_key_value(line, &name, &value))
+ if (!config_split(line, &name, &value))
+ {
+ PRINTF("Bad line: %s\n", line);
+ rv = false;
continue;
+ }
- parse_option(name, value);
+ if (!parse_option(name, value))
+ {
+ PRINTF("Bad key/value: %s\n", line);
+ rv = false;
+ continue;
+ }
}
+ return rv;
}
static
diff --git a/src/strings/fstring.tcc b/src/strings/fstring.tcc
index 9c5f37b..8072fb0 100644
--- a/src/strings/fstring.tcc
+++ b/src/strings/fstring.tcc
@@ -24,6 +24,7 @@ namespace strings
template<class It>
void FString::_assign(It b, It e)
{
+ owned = nullptr;
if (b == e)
{
*this = FString();