summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Longbons <b.r.longbons@gmail.com>2013-06-29 23:23:43 -0700
committerBen Longbons <b.r.longbons@gmail.com>2013-08-01 15:19:45 -0700
commit3b98f3439e33b15bba2036c402f9925340fdb2b9 (patch)
treef6a59330bb747d9cc64f5f83d06e7f76dc01d540
parent8d1480c1be7c9741876d89008277a2b3629a4d01 (diff)
downloadtmwa-3b98f3439e33b15bba2036c402f9925340fdb2b9.tar.gz
tmwa-3b98f3439e33b15bba2036c402f9925340fdb2b9.tar.bz2
tmwa-3b98f3439e33b15bba2036c402f9925340fdb2b9.tar.xz
tmwa-3b98f3439e33b15bba2036c402f9925340fdb2b9.zip
Poison std::string and use the various string classes
-rw-r--r--.gitignore2
-rw-r--r--.travis.yml2
-rw-r--r--Makefile21
-rw-r--r--make.defs10
-rw-r--r--src/char/char.cpp430
-rw-r--r--src/char/char.hpp8
-rw-r--r--src/char/int_party.cpp182
-rw-r--r--src/char/int_party.hpp4
-rw-r--r--src/char/int_storage.cpp26
-rw-r--r--src/char/int_storage.hpp4
-rw-r--r--src/char/inter.cpp99
-rw-r--r--src/char/inter.hpp8
-rw-r--r--src/common/const_array.hpp51
-rw-r--r--src/common/core.cpp6
-rw-r--r--src/common/core.hpp4
-rw-r--r--src/common/cxxstdio.cpp33
-rw-r--r--src/common/cxxstdio.hpp96
-rw-r--r--src/common/cxxstdio_test.cpp3
-rw-r--r--src/common/dumb_ptr.hpp137
-rw-r--r--src/common/extract.cpp30
-rw-r--r--src/common/extract.hpp123
-rw-r--r--src/common/extract_test.cpp319
-rw-r--r--src/common/human_time_diff.hpp85
-rw-r--r--src/common/human_time_diff_test.cpp84
-rw-r--r--src/common/intern-pool.hpp13
-rw-r--r--src/common/intern-pool_test.cpp18
-rw-r--r--src/common/io.hpp26
-rw-r--r--src/common/lock.cpp20
-rw-r--r--src/common/lock.hpp6
-rw-r--r--src/common/md5calc.cpp92
-rw-r--r--src/common/md5calc.hpp37
-rw-r--r--src/common/md5calc_test.cpp27
-rw-r--r--src/common/mmo.hpp121
-rw-r--r--src/common/sanity.hpp23
-rw-r--r--src/common/socket.cpp47
-rw-r--r--src/common/socket.hpp53
-rw-r--r--src/common/strings.hpp695
-rw-r--r--src/common/strings2_test.cpp118
-rw-r--r--src/common/strings_test.cpp162
-rw-r--r--src/common/timer.cpp4
-rw-r--r--src/common/timer.hpp4
-rw-r--r--src/common/utils.cpp131
-rw-r--r--src/common/utils.hpp39
-rw-r--r--src/common/utils2.hpp29
-rw-r--r--src/ladmin/ladmin.cpp1809
-rw-r--r--src/login/login.cpp848
-rw-r--r--src/map/atcommand.cpp1751
-rw-r--r--src/map/atcommand.hpp8
-rw-r--r--src/map/battle.cpp338
-rw-r--r--src/map/battle.hpp2
-rw-r--r--src/map/chrif.cpp95
-rw-r--r--src/map/chrif.hpp20
-rw-r--r--src/map/clif.cpp309
-rw-r--r--src/map/clif.hpp48
-rw-r--r--src/map/grfio.cpp29
-rw-r--r--src/map/grfio.hpp5
-rw-r--r--src/map/intif.cpp76
-rw-r--r--src/map/intif.hpp12
-rw-r--r--src/map/itemdb.cpp121
-rw-r--r--src/map/itemdb.hpp6
-rw-r--r--src/map/magic-expr-eval.hpp4
-rw-r--r--src/map/magic-expr.cpp270
-rw-r--r--src/map/magic-expr.hpp24
-rw-r--r--src/map/magic-interpreter-base.cpp23
-rw-r--r--src/map/magic-interpreter-parser.ypp63
-rw-r--r--src/map/magic-interpreter.hpp30
-rw-r--r--src/map/magic-stmt.cpp124
-rw-r--r--src/map/magic.cpp22
-rw-r--r--src/map/magic.hpp10
-rw-r--r--src/map/map.cpp189
-rw-r--r--src/map/map.hpp100
-rw-r--r--src/map/map.t.hpp5
-rw-r--r--src/map/mob.cpp379
-rw-r--r--src/map/mob.hpp20
-rw-r--r--src/map/npc.cpp571
-rw-r--r--src/map/npc.hpp29
-rw-r--r--src/map/party.cpp40
-rw-r--r--src/map/party.hpp17
-rw-r--r--src/map/pc.cpp231
-rw-r--r--src/map/pc.hpp22
-rw-r--r--src/map/script.cpp532
-rw-r--r--src/map/script.hpp45
-rw-r--r--src/map/skill.cpp142
-rw-r--r--src/map/skill.hpp5
-rw-r--r--src/map/tmw.cpp80
-rw-r--r--src/map/tmw.hpp5
-rw-r--r--src/poison.hpp9
-rw-r--r--src/tool/eathena-monitor.cpp49
-rw-r--r--src/warnings.hpp12
89 files changed, 5860 insertions, 6101 deletions
diff --git a/.gitignore b/.gitignore
index 361fe2d..e27b0e0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,3 +12,5 @@
/src/map/magic-interpreter-lexer.cpp
# generated header dependencies
/deps.make
+# tags file
+/tags
diff --git a/.travis.yml b/.travis.yml
index ead11f8..f45733d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -41,7 +41,7 @@ script:
## Do something after the main test script
after_script:
- - make test
+ - make test TESTER='valgrind --error-exitcode=1 --track-fds=yes'
### The rest of the file creates a build matrix
### containing gcc-4.6 through gcc-4.7 and clang-3.1
diff --git a/Makefile b/Makefile
index 5436881..44b3fc2 100644
--- a/Makefile
+++ b/Makefile
@@ -49,7 +49,7 @@ all: ${PROGS}
most: ${MOSTPROGS}
clean:
rm -rf ${PROGS} ${BUILD_DIR}/
-common: ${BUILD_DIR}/common/core.o ${BUILD_DIR}/common/db.o ${BUILD_DIR}/common/lock.o ${BUILD_DIR}/common/md5calc.o ${BUILD_DIR}/common/random.o ${BUILD_DIR}/common/nullpo.o ${BUILD_DIR}/common/socket.o ${BUILD_DIR}/common/timer.o ${BUILD_DIR}/common/utils.o ${BUILD_DIR}/common/cxxstdio.o ${BUILD_DIR}/common/extract.o
+common: ${BUILD_DIR}/common/core.o ${BUILD_DIR}/common/db.o ${BUILD_DIR}/common/lock.o ${BUILD_DIR}/common/md5calc.o ${BUILD_DIR}/common/random.o ${BUILD_DIR}/common/nullpo.o ${BUILD_DIR}/common/socket.o ${BUILD_DIR}/common/timer.o ${BUILD_DIR}/common/utils.o ${BUILD_DIR}/common/extract.o
magic: ${BUILD_DIR}/map/magic-interpreter-lexer.o ${BUILD_DIR}/map/magic-interpreter-parser.o ${BUILD_DIR}/map/magic-expr.o ${BUILD_DIR}/map/magic-interpreter-base.o ${BUILD_DIR}/map/magic-stmt.o ${BUILD_DIR}/map/magic.o
# Top level programs
@@ -64,15 +64,16 @@ ladmin: ${BUILD_DIR}/ladmin/ladmin
eathena-monitor: ${BUILD_DIR}/tool/eathena-monitor
cp -f $< $@
-${BUILD_DIR}/tests/main: ${BUILD_DIR}/tests/main.o $(patsubst src/%.cpp,obj/%.o,$(wildcard src/*/*_test.cpp)) ${BUILD_DIR}/gtest-all.o
+${BUILD_DIR}/tests/main: ${BUILD_DIR}/tests/main.o $(patsubst src/%.cpp,obj/%.o,$(wildcard src/*/*_test.cpp)) ${BUILD_DIR}/gtest-all.o \
+ ${BUILD_DIR}/common/extract.o ${BUILD_DIR}/common/md5calc.o ${BUILD_DIR}/common/random.o
test: ${BUILD_DIR}/tests/main
- $<
+ ${TESTER} $< ${TEST_ARGS}
# Executable dependencies - generated by hand
-${BUILD_DIR}/char/char: ${BUILD_DIR}/char/char.o ${BUILD_DIR}/char/inter.o ${BUILD_DIR}/char/int_party.o ${BUILD_DIR}/char/int_storage.o ${BUILD_DIR}/common/core.o ${BUILD_DIR}/common/socket.o ${BUILD_DIR}/common/timer.o ${BUILD_DIR}/common/db.o ${BUILD_DIR}/common/lock.o ${BUILD_DIR}/common/random.o ${BUILD_DIR}/common/utils.o ${BUILD_DIR}/common/cxxstdio.o ${BUILD_DIR}/common/extract.o
-${BUILD_DIR}/ladmin/ladmin: ${BUILD_DIR}/ladmin/ladmin.o ${BUILD_DIR}/common/md5calc.o ${BUILD_DIR}/common/core.o ${BUILD_DIR}/common/socket.o ${BUILD_DIR}/common/timer.o ${BUILD_DIR}/common/db.o ${BUILD_DIR}/common/random.o ${BUILD_DIR}/common/utils.o ${BUILD_DIR}/common/cxxstdio.o
-${BUILD_DIR}/login/login: ${BUILD_DIR}/login/login.o ${BUILD_DIR}/common/core.o ${BUILD_DIR}/common/socket.o ${BUILD_DIR}/common/timer.o ${BUILD_DIR}/common/db.o ${BUILD_DIR}/common/lock.o ${BUILD_DIR}/common/random.o ${BUILD_DIR}/common/md5calc.o ${BUILD_DIR}/common/utils.o ${BUILD_DIR}/common/cxxstdio.o ${BUILD_DIR}/common/extract.o
-${BUILD_DIR}/map/map: ${BUILD_DIR}/map/map.o ${BUILD_DIR}/map/tmw.o ${BUILD_DIR}/map/magic-interpreter-lexer.o ${BUILD_DIR}/map/magic-interpreter-parser.o ${BUILD_DIR}/map/magic-interpreter-base.o ${BUILD_DIR}/map/magic-expr.o ${BUILD_DIR}/map/magic-stmt.o ${BUILD_DIR}/map/magic.o ${BUILD_DIR}/map/map.o ${BUILD_DIR}/map/chrif.o ${BUILD_DIR}/map/clif.o ${BUILD_DIR}/map/pc.o ${BUILD_DIR}/map/npc.o ${BUILD_DIR}/map/path.o ${BUILD_DIR}/map/itemdb.o ${BUILD_DIR}/map/mob.o ${BUILD_DIR}/map/script.o ${BUILD_DIR}/map/storage.o ${BUILD_DIR}/map/skill.o ${BUILD_DIR}/map/skill-pools.o ${BUILD_DIR}/map/atcommand.o ${BUILD_DIR}/map/battle.o ${BUILD_DIR}/map/intif.o ${BUILD_DIR}/map/trade.o ${BUILD_DIR}/map/party.o ${BUILD_DIR}/common/core.o ${BUILD_DIR}/common/socket.o ${BUILD_DIR}/common/timer.o ${BUILD_DIR}/map/grfio.o ${BUILD_DIR}/common/db.o ${BUILD_DIR}/common/lock.o ${BUILD_DIR}/common/nullpo.o ${BUILD_DIR}/common/random.o ${BUILD_DIR}/common/md5calc.o ${BUILD_DIR}/common/utils.o ${BUILD_DIR}/common/cxxstdio.o ${BUILD_DIR}/common/extract.o
+${BUILD_DIR}/char/char: ${BUILD_DIR}/char/char.o ${BUILD_DIR}/char/inter.o ${BUILD_DIR}/char/int_party.o ${BUILD_DIR}/char/int_storage.o ${BUILD_DIR}/common/core.o ${BUILD_DIR}/common/socket.o ${BUILD_DIR}/common/timer.o ${BUILD_DIR}/common/db.o ${BUILD_DIR}/common/lock.o ${BUILD_DIR}/common/random.o ${BUILD_DIR}/common/utils.o ${BUILD_DIR}/common/extract.o
+${BUILD_DIR}/ladmin/ladmin: ${BUILD_DIR}/ladmin/ladmin.o ${BUILD_DIR}/common/md5calc.o ${BUILD_DIR}/common/core.o ${BUILD_DIR}/common/socket.o ${BUILD_DIR}/common/timer.o ${BUILD_DIR}/common/db.o ${BUILD_DIR}/common/extract.o ${BUILD_DIR}/common/random.o ${BUILD_DIR}/common/utils.o
+${BUILD_DIR}/login/login: ${BUILD_DIR}/login/login.o ${BUILD_DIR}/common/core.o ${BUILD_DIR}/common/socket.o ${BUILD_DIR}/common/timer.o ${BUILD_DIR}/common/db.o ${BUILD_DIR}/common/lock.o ${BUILD_DIR}/common/random.o ${BUILD_DIR}/common/md5calc.o ${BUILD_DIR}/common/utils.o ${BUILD_DIR}/common/extract.o
+${BUILD_DIR}/map/map: ${BUILD_DIR}/map/map.o ${BUILD_DIR}/map/tmw.o ${BUILD_DIR}/map/magic-interpreter-lexer.o ${BUILD_DIR}/map/magic-interpreter-parser.o ${BUILD_DIR}/map/magic-interpreter-base.o ${BUILD_DIR}/map/magic-expr.o ${BUILD_DIR}/map/magic-stmt.o ${BUILD_DIR}/map/magic.o ${BUILD_DIR}/map/map.o ${BUILD_DIR}/map/chrif.o ${BUILD_DIR}/map/clif.o ${BUILD_DIR}/map/pc.o ${BUILD_DIR}/map/npc.o ${BUILD_DIR}/map/path.o ${BUILD_DIR}/map/itemdb.o ${BUILD_DIR}/map/mob.o ${BUILD_DIR}/map/script.o ${BUILD_DIR}/map/storage.o ${BUILD_DIR}/map/skill.o ${BUILD_DIR}/map/skill-pools.o ${BUILD_DIR}/map/atcommand.o ${BUILD_DIR}/map/battle.o ${BUILD_DIR}/map/intif.o ${BUILD_DIR}/map/trade.o ${BUILD_DIR}/map/party.o ${BUILD_DIR}/common/core.o ${BUILD_DIR}/common/socket.o ${BUILD_DIR}/common/timer.o ${BUILD_DIR}/map/grfio.o ${BUILD_DIR}/common/db.o ${BUILD_DIR}/common/lock.o ${BUILD_DIR}/common/nullpo.o ${BUILD_DIR}/common/random.o ${BUILD_DIR}/common/md5calc.o ${BUILD_DIR}/common/utils.o ${BUILD_DIR}/common/extract.o
${BUILD_DIR}/tool/eathena-monitor: ${BUILD_DIR}/tool/eathena-monitor.o ${BUILD_DIR}/common/utils.o
# silence build warnings for code beyond my control
@@ -93,3 +94,9 @@ BACKUPS=numbered
install:
install -d ${prefix}/bin/
install --backup=${BACKUPS} -t ${prefix}/bin/ $(wildcard ${PROGS})
+
+# might need changes later to handle static declarations (solution:
+# run ctags twice, specifying forward patterns for the declarations
+# and backward patterns for the definition)
+tags: $(shell git ls-files src/)
+ ctags --totals --c-kinds=+px -f $@ $^
diff --git a/make.defs b/make.defs
index b5b47fa..0f35244 100644
--- a/make.defs
+++ b/make.defs
@@ -5,7 +5,10 @@ CXX = g++
LEX = flex
BISON = bison
-CXXFLAGS = -pipe -g -O2 ${WARNINGS}
+CXXFLAGS = ${DEBUG} ${OPT} ${WARNINGS}
+# these being separate use useful for development
+DEBUG = -g
+OPT = -pipe -O2
WARNINGS = -include src/warnings.hpp
# Location of gtest source tree. It must contain the file src/gtest-all.cc
@@ -14,10 +17,11 @@ WARNINGS = -include src/warnings.hpp
# http://code.google.com/p/googletest/wiki/FAQ#Why_is_it_not_recommended_to_install_a_pre-compiled_copy_of_Goog
GTEST_DIR = /usr/src/gtest
-# works on both x86 and x86_64
+# gdb bug 15801
+CXX += -fabi-version=6
override CXX += -std=c++0x
# for linking
override CC = ${CXX}
override CXXFLAGS += -fstack-protector -fno-strict-aliasing
-
+override CXXFLAGS += -fvisibility=hidden
diff --git a/src/char/char.cpp b/src/char/char.cpp
index d7e7a41..6108dca 100644
--- a/src/char/char.cpp
+++ b/src/char/char.cpp
@@ -12,12 +12,15 @@
#include <cstring>
#include <ctime>
+#include <bitset>
#include <fstream>
#include "../common/core.hpp"
#include "../common/cxxstdio.hpp"
#include "../common/db.hpp"
#include "../common/extract.hpp"
+#include "../common/human_time_diff.hpp"
+#include "../common/io.hpp"
#include "../common/lock.hpp"
#include "../common/socket.hpp"
#include "../common/timer.hpp"
@@ -48,21 +51,21 @@ std::chrono::milliseconds DEFAULT_AUTOSAVE_INTERVAL =
static
int login_fd, char_fd;
static
-char userid[24];
+AccountName userid;
static
-char passwd[24];
+AccountPass passwd;
static
-char server_name[20];
+ServerName server_name;
static
-char wisp_server_name[24] = "Server";
+CharName wisp_server_name = stringish<CharName>("Server");
static
-char login_ip_str[16];
+IP_String login_ip_str;
static
int login_ip;
static
int login_port = 6900;
static
-char char_ip_str[16];
+IP_String char_ip_str;
static
int char_ip;
static
@@ -72,31 +75,29 @@ int char_maintenance;
static
int char_new;
static
-char char_txt[1024];
+FString char_txt;
static
-char unknown_char_name[24] = "Unknown";
+CharName unknown_char_name = stringish<CharName>("Unknown");
static
-char char_log_filename[1024] = "log/char.log";
+FString char_log_filename = "log/char.log";
//Added for lan support
static
-char lan_map_ip[128];
+IP_String lan_map_ip;
static
uint8_t subneti[4];
static
uint8_t subnetmaski[4];
static
-int name_ignoring_case = 0; // Allow or not identical name for characters but with a different case by [Yor]
-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
-char char_name_letters[1024] = ""; // list of letters/symbols authorised (or not) in a character name. by [Yor]
+std::bitset<256> char_name_letters; // list of letters/symbols authorised (or not) in a character name. by [Yor]
struct char_session_data : SessionData
{
int account_id, login_id1, login_id2, sex;
unsigned short packet_tmw_version;
- char email[40]; // e-mail (default: a@a.com) by [Yor]
- TimeT connect_until_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited)
+ AccountEmail email;
+ TimeT connect_until_time;
};
void SessionDeleter::operator()(SessionData *sd)
@@ -140,16 +141,16 @@ int start_armor = 1202;
// Initial position (it's possible to set it in conf file)
static
-struct point start_point = { "new_1-1.gat", 53, 111 };
+struct point start_point = { {"001-1.gat"}, 273, 354 };
static
std::vector<GM_Account> gm_accounts;
// online players by [Yor]
static
-char online_txt_filename[1024] = "online.txt";
+FString online_txt_filename = "online.txt";
static
-char online_html_filename[1024] = "online.html";
+FString online_html_filename = "online.html";
static
int online_sorting_option = 0; // sorting option to display online players in online files
static
@@ -168,13 +169,13 @@ pid_t pid = 0; // For forked DB writes
//------------------------------
// Writing function of logs file
//------------------------------
-void char_log(const_string line)
+void char_log(XString line)
{
- FILE *logfp = fopen_(char_log_filename, "a");
+ FILE *logfp = fopen(char_log_filename.c_str(), "a");
if (!logfp)
return;
log_with_timestamp(logfp, line);
- fclose_(logfp);
+ fclose(logfp);
}
//----------------------------------------------------------------------
@@ -198,26 +199,16 @@ int isGM(int account_id)
// and returns index if only 1 character is found
// and similar to the searched name.
//----------------------------------------------
-const mmo_charstatus *search_character(const char *character_name)
+const mmo_charstatus *search_character(CharName character_name)
{
- int quantity = 0;
- const mmo_charstatus *index = nullptr;
for (const mmo_charstatus& cd : char_data)
{
- // Without case sensitive check (increase the number of similar character names found)
- if (strcasecmp(cd.name, character_name) == 0)
{
// Strict comparison (if found, we finish the function immediatly with correct value)
- if (strcmp(cd.name, character_name) == 0)
+ if (cd.name == character_name)
return &cd;
- quantity++;
- index = &cd;
}
}
- // Here, the exact character name is not found
- // We return the found index of a similar account ONLY if there is 1 similar character
- if (quantity == 1)
- return index;
// Exact character name is not found and 0 or more than 1 similar characters have been found ==> we say not found
return nullptr;
@@ -226,18 +217,16 @@ const mmo_charstatus *search_character(const char *character_name)
//-------------------------------------------------
// Function to create the character line (for save)
//-------------------------------------------------
-__inline__ static
-std::string mmo_char_tostr(struct mmo_charstatus *p)
+static
+FString mmo_char_tostr(struct mmo_charstatus *p)
{
// 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_[0] == '\0')
+ if (!p->last_point.map_)
{
- strzcpy(p->last_point.map_, "001-1.gat", 16);
- p->last_point.x = 273;
- p->last_point.y = 354;
+ p->last_point = start_point;
}
- std::string str_p;
+ MString str_p;
str_p += STRPRINTF(
"%d\t"
"%d,%d\t"
@@ -329,11 +318,11 @@ std::string mmo_char_tostr(struct mmo_charstatus *p)
p->global_reg[i].value);
str_p += '\t';
- return str_p;
+ return FString(str_p);
}
static
-bool extract(const_string str, struct point *p)
+bool extract(XString str, struct point *p)
{
return extract(str, record<','>(&p->map_, &p->x, &p->y));
}
@@ -346,7 +335,7 @@ struct skill_loader
};
static
-bool extract(const_string str, struct skill_loader *s)
+bool extract(XString str, struct skill_loader *s)
{
uint32_t flags_and_level;
if (!extract(str,
@@ -361,7 +350,7 @@ bool extract(const_string str, struct skill_loader *s)
// Function to set the character from the line (at read of characters file)
//-------------------------------------------------------------------------
static
-bool extract(const_string str, struct mmo_charstatus *p)
+bool extract(XString str, struct mmo_charstatus *p)
{
// initilialise character
*p = mmo_charstatus{};
@@ -397,14 +386,14 @@ bool extract(const_string str, struct mmo_charstatus *p)
vrec<' '>(&vars))))
return false;
- if (strcmp(wisp_server_name, p->name) == 0)
+ if (wisp_server_name == p->name)
return false;
for (const mmo_charstatus& cd : char_data)
{
if (cd.char_id == p->char_id)
return false;
- if (strcmp(cd.name, p->name) == 0)
+ if (cd.name == p->name)
return false;
}
@@ -448,7 +437,7 @@ int mmo_char_init(void)
char_data.clear();
online_chars.clear();
- std::ifstream in(char_txt);
+ std::ifstream in(char_txt.c_str());
if (!in.is_open())
{
PRINTF("Characters file not found: %s.\n", char_txt);
@@ -459,17 +448,13 @@ int mmo_char_init(void)
}
int line_count = 0;
- std::string line;
- while (std::getline(in, line))
+ FString line;
+ while (io::getline(in, line))
{
line_count++;
- if (line[0] == '/' && line[1] == '/')
+ if (line.startswith("//"))
continue;
- if (line.back() == '\r')
- {
- line.back() = 0;
- }
{
int i, j = 0;
@@ -511,10 +496,7 @@ static
void mmo_char_sync(void)
{
int lock;
- FILE *fp;
-
- // Data save
- fp = lock_fopen(char_txt, &lock);
+ FILE *fp = lock_fopen(char_txt, &lock);
if (fp == NULL)
{
PRINTF("WARNING: Server can't not save characters.\n");
@@ -525,7 +507,7 @@ void mmo_char_sync(void)
// yes, we need a mutable reference to do the saves ...
for (mmo_charstatus& cd : char_data)
{
- std::string line = mmo_char_tostr(&cd);
+ FString line = mmo_char_tostr(&cd);
fwrite(line.data(), 1, line.size(), fp);
fputc('\n', fp);
}
@@ -565,43 +547,17 @@ void mmo_char_sync_timer(TimerData *, tick_t)
_exit(0);
}
-//----------------------------------------------------
-// Remove trailing whitespace from a name
-//----------------------------------------------------
-static
-void remove_trailing_blanks(char *name)
-{
- char *tail = name + strlen(name) - 1;
-
- while (tail > name && *tail == ' ')
- *tail-- = 0;
-}
-
-//----------------------------------------------------
-// Remove prefix whitespace from a name
-//----------------------------------------------------
-static
-void remove_prefix_blanks(char *name)
-{
- char *dst = name;
- char *src = name;
-
- while (*src == ' ') // find first nonblank
- ++src;
- while ((*dst++ = *src++)); // `strmove'
-}
-
//-----------------------------------
// Function to create a new character
//-----------------------------------
static
-mmo_charstatus *make_new_char(int fd, char *name, const uint8_t (&stats)[6], uint8_t slot, uint16_t hair_color, uint16_t hair_style)
+mmo_charstatus *make_new_char(int fd, CharName name, const uint8_t (&stats)[6], uint8_t slot, uint16_t hair_color, uint16_t hair_style)
{
// ugh
char_session_data *sd = static_cast<char_session_data *>(session[fd]->session_data.get());
// remove control characters from the name
- if (remove_control_chars(name))
+ if (!name.to__actual().is_print())
{
CHAR_LOG("Make new char error (control char received in the name): (connection #%d, account: %d).\n",
fd, sd->account_id);
@@ -609,11 +565,15 @@ mmo_charstatus *make_new_char(int fd, char *name, const uint8_t (&stats)[6], uin
}
// Eliminate whitespace
- remove_trailing_blanks(name);
- remove_prefix_blanks(name);
+ if (name.to__actual() != name.to__actual().strip())
+ {
+ CHAR_LOG("Make new char error (leading/trailing whitespace): (connection #%d, account: %d, name: '%s'.\n",
+ fd, sd->account_id, name);
+ return nullptr;
+ }
// check lenght of character name
- if (strlen(name) < 4)
+ if (name.to__actual().size() < 4)
{
CHAR_LOG("Make new char error (character name too small): (connection #%d, account: %d, name: '%s').\n",
fd, sd->account_id, name);
@@ -624,22 +584,22 @@ mmo_charstatus *make_new_char(int fd, char *name, const uint8_t (&stats)[6], uin
if (char_name_option == 1)
{
// only letters/symbols in char_name_letters are authorised
- for (int i = 0; name[i]; i++)
- if (strchr(char_name_letters, name[i]) == NULL)
+ 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",
- fd, sd->account_id, name, name[i]);
+ fd, sd->account_id, name, c);
return nullptr;
}
}
else if (char_name_option == 2)
{
// letters/symbols in char_name_letters are forbidden
- for (int i = 0; name[i]; i++)
- if (strchr(char_name_letters, name[i]) != NULL)
+ 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",
- fd, sd->account_id, name, name[i]);
+ fd, sd->account_id, name, c);
return nullptr;
}
} // else, all letters/symbols are authorised (except control char removed before)
@@ -674,9 +634,7 @@ mmo_charstatus *make_new_char(int fd, char *name, const uint8_t (&stats)[6], uin
for (const mmo_charstatus& cd : char_data)
{
- if ((name_ignoring_case != 0 && strcmp(cd.name, name) == 0)
- || (name_ignoring_case == 0
- && strcasecmp(cd.name, name) == 0))
+ if (cd.name == name)
{
CHAR_LOG("Make new char error (name already exists): (connection #%d, account: %d) slot %d, name: %s (actual name of other char: %s), stats: %d+%d+%d+%d+%d+%d=%d, hair: %d, hair color: %d.\n",
fd, sd->account_id, slot, name, cd.name,
@@ -697,7 +655,7 @@ mmo_charstatus *make_new_char(int fd, char *name, const uint8_t (&stats)[6], uin
}
}
- if (strcmp(wisp_server_name, name) == 0)
+ 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",
fd, sd->account_id, slot, name, wisp_server_name,
@@ -723,7 +681,7 @@ mmo_charstatus *make_new_char(int fd, char *name, const uint8_t (&stats)[6], uin
cd.char_id = char_id_count++;
cd.account_id = sd->account_id;
cd.char_num = slot;
- strcpy(cd.name, name);
+ cd.name = name;
cd.species = 0;
cd.base_level = 1;
cd.job_level = 1;
@@ -771,10 +729,10 @@ static
void create_online_files(void)
{
// write files
- FILE *fp = fopen_(online_txt_filename, "w");
+ FILE *fp = fopen(online_txt_filename.c_str(), "w");
if (fp != NULL)
{
- FILE *fp2 = fopen_(online_html_filename, "w");
+ FILE *fp2 = fopen(online_html_filename.c_str(), "w");
if (fp2 != NULL)
{
// get time
@@ -836,9 +794,9 @@ void create_online_files(void)
FPRINTF(fp2, " <td>");
if (gml >= online_gm_display_min_level)
FPRINTF(fp2, "<b>");
- for (int k = 0; cd.name[k]; k++)
+ for (char c : cd.name.to__actual())
{
- switch (cd.name[k])
+ switch (c)
{
case '&':
FPRINTF(fp2, "&amp;");
@@ -850,7 +808,7 @@ void create_online_files(void)
FPRINTF(fp2, "&gt;");
break;
default:
- FPRINTF(fp2, "%c", cd.name[k]);
+ FPRINTF(fp2, "%c", c);
break;
};
}
@@ -882,9 +840,9 @@ void create_online_files(void)
}
FPRINTF(fp2, " </BODY>\n");
FPRINTF(fp2, "</HTML>\n");
- fclose_(fp2);
+ fclose(fp2);
}
- fclose_(fp);
+ fclose(fp);
}
return;
@@ -983,7 +941,7 @@ int mmo_char_send006b(int fd, struct char_session_data *sd)
WFIFOW(fd, j + 72) = find_equip_view(p, EPOS::MISC2);
// WFIFOW(fd,j+72) = p->clothes_color;
- WFIFO_STRING(fd, j + 74, p->name, 24);
+ WFIFO_STRING(fd, j + 74, p->name.to__actual(), 24);
WFIFOB(fd, j + 98) = min(p->attrs[ATTR::STR], 255);
WFIFOB(fd, j + 99) = min(p->attrs[ATTR::AGI], 255);
@@ -1192,9 +1150,9 @@ void parse_tologin(int fd)
// PRINTF("max_connect_user (unlimited) -> accepted.\n");
// else
// PRINTF("count_users(): %d < max_connect_user (%d) -> accepted.\n", count_users(), max_connect_user);
- RFIFO_STRING(fd, 7, sd->email, 40);
- if (e_mail_check(sd->email) == 0)
- strzcpy(sd->email, "a@a.com", 40); // default e-mail
+ sd->email = stringish<AccountEmail>(RFIFO_STRING<40>(fd, 7));
+ if (!e_mail_check(sd->email))
+ sd->email = DEFAULT_EMAIL;
sd->connect_until_time = static_cast<time_t>(RFIFOL(fd, 47));
// send characters to player
mmo_char_send006b(i, sd);
@@ -1226,9 +1184,9 @@ void parse_tologin(int fd)
{
if (sd->account_id == RFIFOL(fd, 2))
{
- RFIFO_STRING(fd, 6, sd->email, 40);
- if (e_mail_check(sd->email) == 0)
- strzcpy(sd->email, "a@a.com", 40); // default e-mail
+ sd->email = stringish<AccountEmail>(RFIFO_STRING<40>(fd, 6));
+ if (!e_mail_check(sd->email))
+ sd->email = DEFAULT_EMAIL;
sd->connect_until_time = static_cast<time_t>(RFIFOL(fd, 46));
break;
}
@@ -1309,29 +1267,20 @@ void parse_tologin(int fd)
else
{
size_t len = RFIFOL(fd, 4);
- char message[len];
- RFIFO_STRING(fd, 8, message, len);
- remove_control_chars(message);
- // remove all first spaces
- char *p = message;
- while (p[0] == ' ')
- p++;
+ FString message = RFIFO_STRING(fd, 8, len).to_print().lstrip();
// if message is only composed of spaces
- if (p[0] == '\0')
+ if (!message)
CHAR_LOG("Receiving a message for broadcast, but message is only a lot of spaces.\n");
// else send message to all map-servers
else
{
- {
- const char *message_ptr = message;
- CHAR_LOG("'ladmin': Receiving a message for broadcast (message (in yellow): %s)\n",
- message_ptr);
- }
+ CHAR_LOG("'ladmin': Receiving a message for broadcast (message (in yellow): %s)\n",
+ message);
// send broadcast to all map-servers
uint8_t buf[4 + len];
WBUFW(buf, 0) = 0x3800;
- WBUFW(buf, 2) = 4 + sizeof(message);
- WBUF_STRING(buf, 4, message, sizeof(message));
+ WBUFW(buf, 2) = 4 + len;
+ WBUF_STRING(buf, 4, message, len);
mapif_sendall(buf, WBUFW(buf, 2));
}
}
@@ -1351,7 +1300,7 @@ void parse_tologin(int fd)
p < RFIFOW(fd, 2) && j < ACCOUNT_REG2_NUM;
p += 36, j++)
{
- RFIFO_STRING(fd, p, reg[j].str, 32);
+ reg[j].str = stringish<VarName>(RFIFO_STRING<32>(fd, p));
reg[j].value = RFIFOL(fd, p + 32);
}
set_account_reg2(acc, j, reg);
@@ -1594,7 +1543,6 @@ void parse_frommap(int fd)
{ // don't send request if no login-server
WFIFOW(login_fd, 0) = 0x2709;
WFIFOSET(login_fd, 2);
-// PRINTF("char : request from map-server to reload GM accounts -> login-server.\n");
}
RFIFOSKIP(fd, 2);
break;
@@ -1604,13 +1552,12 @@ void parse_frommap(int fd)
if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd, 2))
return;
{
- for (char (&foo)[16] : server[id].maps)
- strzcpy(foo, "", 16);
+ for (MapName &foo : server[id].maps)
+ foo = MapName();
int j = 0;
for (int i = 4; i < RFIFOW(fd, 2); i += 16)
{
- RFIFO_STRING(fd, i, server[id].maps[j], 16);
-// PRINTF("set map %d.%d : %s\n", id, j, server[id].map[j]);
+ server[id].maps[j] = RFIFO_STRING<16>(fd, i);
j++;
}
{
@@ -1624,7 +1571,7 @@ void parse_frommap(int fd)
}
WFIFOW(fd, 0) = 0x2afb;
WFIFOB(fd, 2) = 0;
- WFIFO_STRING(fd, 3, wisp_server_name, 24);
+ WFIFO_STRING(fd, 3, wisp_server_name.to__actual(), 24);
WFIFOSET(fd, 27);
{
unsigned char buf[16384];
@@ -1831,7 +1778,7 @@ void parse_frommap(int fd)
if (RFIFOREST(fd) < 6)
return;
{
- const char *name = unknown_char_name;
+ CharName name = unknown_char_name;
for (const mmo_charstatus& cd : char_data)
{
if (cd.char_id == RFIFOL(fd, 2))
@@ -1842,7 +1789,7 @@ void parse_frommap(int fd)
}
WFIFOW(fd, 0) = 0x2b09;
WFIFOL(fd, 2) = RFIFOL(fd, 2);
- WFIFO_STRING(fd, 6, name, 24);
+ WFIFO_STRING(fd, 6, name.to__actual(), 24);
WFIFOSET(fd, 30);
}
RFIFOSKIP(fd, 6);
@@ -1887,9 +1834,8 @@ void parse_frommap(int fd)
if (RFIFOREST(fd) < 44)
return;
{
- char character_name[24];
int acc = RFIFOL(fd, 2); // account_id of who ask (-1 if nobody)
- RFIFO_STRING(fd, 6, character_name, 24);
+ CharName character_name = stringish<CharName>(RFIFO_STRING<24>(fd, 6));
// prepare answer
WFIFOW(fd, 0) = 0x2b0f; // answer
WFIFOL(fd, 2) = acc; // who want do operation
@@ -1898,7 +1844,7 @@ void parse_frommap(int fd)
const mmo_charstatus *cd = search_character(character_name);
if (cd)
{
- WFIFO_STRING(fd, 6, cd->name, 24); // put correct name if found
+ WFIFO_STRING(fd, 6, cd->name.to__actual(), 24); // put correct name if found
WFIFOW(fd, 32) = 0; // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline
switch (RFIFOW(fd, 30))
{
@@ -1928,12 +1874,9 @@ void parse_frommap(int fd)
{ // don't send request if no login-server
WFIFOW(login_fd, 0) = 0x2725;
WFIFOL(login_fd, 2) = cd->account_id; // account value
- WFIFOW(login_fd, 6) = RFIFOW(fd, 32); // year
- WFIFOW(login_fd, 8) = RFIFOW(fd, 34); // month
- WFIFOW(login_fd, 10) = RFIFOW(fd, 36); // day
- WFIFOW(login_fd, 12) = RFIFOW(fd, 38); // hour
- WFIFOW(login_fd, 14) = RFIFOW(fd, 40); // minute
- WFIFOW(login_fd, 16) = RFIFOW(fd, 42); // second
+ HumanTimeDiff ban_change;
+ RFIFO_STRUCT(fd, 32, ban_change);
+ WFIFO_STRUCT(login_fd, 6, ban_change);
WFIFOSET(login_fd, 18);
// PRINTF("char : status -> login: account %d, ban: %dy %dm %dd %dh %dmn %ds\n",
// char_data[i].account_id, (short)RFIFOW(fd,32), (short)RFIFOW(fd,34), (short)RFIFOW(fd,36), (short)RFIFOW(fd,38), (short)RFIFOW(fd,40), (short)RFIFOW(fd,42));
@@ -2001,7 +1944,7 @@ void parse_frommap(int fd)
else
{
// character name not found
- WFIFO_STRING(fd, 6, character_name, 24);
+ WFIFO_STRING(fd, 6, character_name.to__actual(), 24);
WFIFOW(fd, 32) = 1; // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline
}
// send answer if a player ask, not if the server ask
@@ -2027,7 +1970,7 @@ void parse_frommap(int fd)
p < RFIFOW(fd, 2) && j < ACCOUNT_REG2_NUM;
p += 36, j++)
{
- RFIFO_STRING(fd, p, reg[j].str, 32);
+ reg[j].str = stringish<VarName>(RFIFO_STRING<32>(fd, p));
reg[j].value = RFIFOL(fd, p + 32);
}
set_account_reg2(acc, j, reg);
@@ -2079,29 +2022,14 @@ void parse_frommap(int fd)
}
static
-int search_mapserver(const char *map)
+int search_mapserver(XString map)
{
- int i, j;
- char temp_map[16];
- int temp_map_len;
-
-// PRINTF("Searching the map-server for map '%s'... ", map);
- strzcpy(temp_map, map, sizeof(temp_map));
- if (strchr(temp_map, '.') != NULL)
- temp_map[strchr(temp_map, '.') - temp_map + 1] = '\0'; // suppress the '.gat', but conserve the '.' to be sure of the name of the map
-
- temp_map_len = strlen(temp_map);
- for (i = 0; i < MAX_MAP_SERVERS; i++)
+ for (int i = 0; i < MAX_MAP_SERVERS; i++)
if (server_fd[i] >= 0)
- for (j = 0; server[i].maps[j][0]; j++)
- //PRINTF("%s : %s = %d\n", server[i].map[j], map, strncmp(server[i].map[j], temp_map, temp_map_len));
- if (strncmp(server[i].maps[j], temp_map, temp_map_len) == 0)
- {
-// PRINTF("found -> server #%d.\n", i);
+ for (int j = 0; server[i].maps[j][0]; j++)
+ if (server[i].maps[j] == map)
return i;
- }
-// PRINTF("not found.\n");
return -1;
}
@@ -2134,7 +2062,7 @@ int lan_ip_check(unsigned char *p)
static
void handle_x0066(int fd, struct char_session_data *sd, uint8_t rfifob_2, uint8_t *p)
{
- const char *ip = ip2str(session[fd]->client_addr.sin_addr);
+ IP_String ip = ip2str(session[fd]->client_addr.sin_addr);
{
mmo_charstatus *cd = nullptr;
@@ -2164,7 +2092,7 @@ void handle_x0066(int fd, struct char_session_data *sd, uint8_t rfifob_2, uint8_
&& server[j].maps[0][0])
{ // change save point to one of map found on the server (the first)
i = j;
- strzcpy(cd->last_point.map_, server[j].maps[0], 16);
+ cd->last_point.map_ = server[j].maps[0];
PRINTF("Map-server #%d found with a map: '%s'.\n",
j, server[j].maps[0]);
// coordonates are unknown
@@ -2187,7 +2115,7 @@ void handle_x0066(int fd, struct char_session_data *sd, uint8_t rfifob_2, uint8_
sd->account_id, cd->char_num, ip);
PRINTF("--Send IP of map-server. ");
if (lan_ip_check(p))
- WFIFOL(fd, 22) = inet_addr(lan_map_ip);
+ WFIFOL(fd, 22) = inet_addr(lan_map_ip.c_str());
else
WFIFOL(fd, 22) = server[i].ip;
WFIFOW(fd, 26) = server[i].port;
@@ -2211,7 +2139,6 @@ void handle_x0066(int fd, struct char_session_data *sd, uint8_t rfifob_2, uint8_
static
void parse_char(int fd)
{
- char email[40];
uint8_t *p = reinterpret_cast<uint8_t *>(&session[fd]->client_addr.sin_addr);
if (login_fd < 0 || session[fd]->eof)
@@ -2243,11 +2170,9 @@ void parse_char(int fd)
{
WFIFOW(login_fd, 0) = 0x2740;
WFIFOL(login_fd, 2) = sd->account_id;
- char old_pass[24];
- RFIFO_STRING(fd, 2, old_pass, 24);
+ AccountPass old_pass = stringish<AccountPass>(RFIFO_STRING<24>(fd, 2));
WFIFO_STRING(login_fd, 6, old_pass, 24);
- char new_pass[24];
- RFIFO_STRING(fd, 26, new_pass, 24);
+ AccountPass new_pass = stringish<AccountPass>(RFIFO_STRING<24>(fd, 26));
WFIFO_STRING(login_fd, 30, new_pass, 24);
WFIFOSET(login_fd, 54);
}
@@ -2269,7 +2194,7 @@ void parse_char(int fd)
{
session[fd]->session_data = make_unique<char_session_data, SessionDeleter>();
sd = static_cast<char_session_data *>(session[fd]->session_data.get());
- strzcpy(sd->email, "no mail", 40); // put here a mail without '@' to refuse deletion if we don't receive the e-mail
+ sd->email = stringish<AccountEmail>("no mail"); // 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 = RFIFOL(fd, 2);
@@ -2354,8 +2279,7 @@ void parse_char(int fd)
if (!sd || RFIFOREST(fd) < 37)
return;
{
- char name[24];
- RFIFO_STRING(fd, 2, name, 24);
+ CharName name = stringish<CharName>(RFIFO_STRING<24>(fd, 2));
uint8_t stats[6];
for (int i = 0; i < 6; ++i)
stats[i] = RFIFOB(fd, 26 + i);
@@ -2401,7 +2325,7 @@ void parse_char(int fd)
WFIFOW(fd, 2 + 68) = cd->head_mid;
WFIFOW(fd, 2 + 70) = cd->hair_color;
- WFIFO_STRING(fd, 2 + 74, cd->name, 24);
+ WFIFO_STRING(fd, 2 + 74, cd->name.to__actual(), 24);
WFIFOB(fd, 2 + 98) = min(cd->attrs[ATTR::STR], 255);
WFIFOB(fd, 2 + 99) = min(cd->attrs[ATTR::AGI], 255);
@@ -2419,9 +2343,10 @@ void parse_char(int fd)
case 0x68: // delete char //Yor's Fix
if (!sd || RFIFOREST(fd) < 46)
return;
- RFIFO_STRING(fd, 6, email, 40);
- if (e_mail_check(email) == 0)
- strzcpy(email, "a@a.com", 40); // default e-mail
+ {
+ AccountEmail email = stringish<AccountEmail>(RFIFO_STRING<40>(fd, 6));
+ if (!e_mail_check(email))
+ email = DEFAULT_EMAIL;
{
{
@@ -2457,6 +2382,7 @@ void parse_char(int fd)
WFIFOSET(fd, 3);
}
}
+ }
x68_out:
RFIFOSKIP(fd, 46);
break;
@@ -2472,12 +2398,10 @@ void parse_char(int fd)
if (server_fd[i] < 0)
break;
}
- char userid_[24];
- RFIFO_STRING(fd, 2, userid_, 24);
- char passwd_[24];
- RFIFO_STRING(fd, 26, passwd_, 24);
- if (i == MAX_MAP_SERVERS || strcmp(userid_, userid)
- || strcmp(passwd_, passwd))
+ AccountName userid_ = stringish<AccountName>(RFIFO_STRING<24>(fd, 2));
+ AccountPass passwd_ = stringish<AccountPass>(RFIFO_STRING<24>(fd, 26));
+ if (i == MAX_MAP_SERVERS || userid_ != userid
+ || passwd_ != passwd)
{
WFIFOB(fd, 2) = 3;
WFIFOSET(fd, 3);
@@ -2495,8 +2419,8 @@ void parse_char(int fd)
server[i].ip = RFIFOL(fd, 54);
server[i].port = RFIFOW(fd, 58);
server[i].users = 0;
- for (char (&mapi)[16] : server[i].maps)
- strzcpy(mapi, "", 16);
+ for (MapName& mapi : server[i].maps)
+ mapi = MapName();
WFIFOSET(fd, 3);
RFIFOSKIP(fd, 60);
realloc_fifo(fd, FIFOSIZE_SERVERLINK,
@@ -2653,12 +2577,12 @@ void check_connect_login_server(TimerData *, tick_t)
// Reading Lan Support configuration by [Yor]
//-------------------------------------------
static
-int lan_config_read(const char *lancfgName)
+int lan_config_read(ZString lancfgName)
{
struct hostent *h = NULL;
// set default configuration
- strzcpy(lan_map_ip, "127.0.0.1", sizeof(lan_map_ip));
+ lan_map_ip = stringish<IP_String>("127.0.0.1");
subneti[0] = 127;
subneti[1] = 0;
subneti[2] = 0;
@@ -2666,7 +2590,7 @@ int lan_config_read(const char *lancfgName)
for (int j = 0; j < 4; j++)
subnetmaski[j] = 255;
- std::ifstream in(lancfgName);
+ std::ifstream in(lancfgName.c_str());
if (!in.is_open())
{
@@ -2676,10 +2600,11 @@ int lan_config_read(const char *lancfgName)
PRINTF("---start reading of Lan Support configuration...\n");
- std::string line;
- while (std::getline(in, line))
+ FString line;
+ while (io::getline(in, line))
{
- std::string w1, w2;
+ SString w1;
+ TString w2;
if (!split_key_value(line, &w1, &w2))
continue;
@@ -2689,7 +2614,7 @@ int lan_config_read(const char *lancfgName)
h = gethostbyname(w2.c_str());
if (h != NULL)
{
- sprintf(lan_map_ip, "%d.%d.%d.%d",
+ SNPRINTF(lan_map_ip, 16, "%d.%d.%d.%d",
static_cast<uint8_t>(h->h_addr[0]),
static_cast<uint8_t>(h->h_addr[1]),
static_cast<uint8_t>(h->h_addr[2]),
@@ -2697,7 +2622,7 @@ int lan_config_read(const char *lancfgName)
}
else
{
- strzcpy(lan_map_ip, w2.c_str(), sizeof(lan_map_ip));
+ lan_map_ip = stringish<IP_String>(w2);
}
PRINTF("LAN IP of map-server: %s.\n", lan_map_ip);
}
@@ -2742,14 +2667,15 @@ int lan_config_read(const char *lancfgName)
}
else
{
- PRINTF("WARNING: unknown lan config key: %s\n", w1);
+ FString w1z = w1;
+ PRINTF("WARNING: unknown lan config key: %s\n", w1z);
}
}
// sub-network check of the map-server
{
unsigned char p[4];
- sscanf(lan_map_ip, "%hhu.%hhu.%hhu.%hhu", &p[0], &p[1], &p[2], &p[3]);
+ SSCANF(lan_map_ip, "%hhu.%hhu.%hhu.%hhu", &p[0], &p[1], &p[2], &p[3]);
PRINTF("LAN test of LAN IP of the map-server: ");
if (lan_ip_check(p) == 0)
{
@@ -2763,11 +2689,11 @@ int lan_config_read(const char *lancfgName)
}
static
-int char_config_read(const char *cfgName)
+int char_config_read(ZString cfgName)
{
struct hostent *h = NULL;
- std::ifstream in(cfgName);
+ std::ifstream in(cfgName.c_str());
if (!in.is_open())
{
@@ -2775,45 +2701,43 @@ int char_config_read(const char *cfgName)
exit(1);
}
- std::string line;
- while (std::getline(in, line))
+ FString line;
+ while (io::getline(in, line))
{
- std::string w1, w2;
+ SString w1;
+ TString w2;
if (!split_key_value(line, &w1, &w2))
continue;
if (w1 == "userid")
- strzcpy(userid, w2.c_str(), 24);
+ userid = stringish<AccountName>(w2);
else if (w1 == "passwd")
- strzcpy(passwd, w2.c_str(), 24);
+ passwd = stringish<AccountPass>(w2);
else if (w1 == "server_name")
{
- strzcpy(server_name, w2.c_str(), sizeof(server_name));
+ server_name = stringish<ServerName>(w2);
PRINTF("%s server has been intialized\n", w2);
}
else if (w1 == "wisp_server_name")
{
if (w2.size() >= 4)
- strzcpy(wisp_server_name, w2.c_str(), sizeof(wisp_server_name));
+ wisp_server_name = stringish<CharName>(w2);
}
else if (w1 == "login_ip")
{
h = gethostbyname(w2.c_str());
if (h != NULL)
{
- PRINTF("Login server IP address : %s -> %d.%d.%d.%d\n", w2,
+ SNPRINTF(login_ip_str, 16, "%d.%d.%d.%d",
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]));
- sprintf(login_ip_str, "%d.%d.%d.%d",
- 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",
+ w2, login_ip_str);
}
else
- strzcpy(login_ip_str, w2.c_str(), 16);
+ login_ip_str = stringish<IP_String>(w2);
}
else if (w1 == "login_port")
{
@@ -2824,20 +2748,16 @@ int char_config_read(const char *cfgName)
h = gethostbyname(w2.c_str());
if (h != NULL)
{
- PRINTF("Character server IP address : %s -> %d.%d.%d.%d\n",
- w2,
+ SNPRINTF(char_ip_str, 16, "%d.%d.%d.%d",
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]));
- sprintf(char_ip_str, "%d.%d.%d.%d",
- 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",
+ w2, char_ip_str);
}
else
- strzcpy(char_ip_str, w2.c_str(), 16);
+ char_ip_str = stringish<IP_String>(w2);
}
else if (w1 == "char_port")
{
@@ -2853,7 +2773,7 @@ int char_config_read(const char *cfgName)
}
else if (w1 == "char_txt")
{
- strzcpy(char_txt, w2.c_str(), sizeof(char_txt));
+ char_txt = w2;
}
else if (w1 == "max_connect_user")
{
@@ -2863,7 +2783,7 @@ int char_config_read(const char *cfgName)
}
else if (w1 == "check_ip_flag")
{
- check_ip_flag = config_switch(w2.c_str());
+ check_ip_flag = config_switch(w2);
}
else if (w1 == "autosave_time")
{
@@ -2873,16 +2793,7 @@ int char_config_read(const char *cfgName)
}
else if (w1 == "start_point")
{
- char map[32];
- int x, y;
- if (SSCANF(w2, "%[^,],%d,%d", map, &x, &y) < 3)
- continue;
- if (strstr(map, ".gat") != NULL)
- { // Verify at least if '.gat' is in the map name
- strzcpy(start_point.map_, map, 16);
- start_point.x = x;
- start_point.y = y;
- }
+ extract(w2, &start_point);
}
else if (w1 == "start_zeny")
{
@@ -2904,15 +2815,11 @@ int char_config_read(const char *cfgName)
}
else if (w1 == "unknown_char_name")
{
- strzcpy(unknown_char_name, w2.c_str(), 24);
+ unknown_char_name = stringish<CharName>(w2);
}
else if (w1 == "char_log_filename")
{
- strzcpy(char_log_filename, w2.c_str(), sizeof(char_log_filename));
- }
- else if (w1 == "name_ignoring_case")
- {
- name_ignoring_case = config_switch(w2.c_str());
+ char_log_filename = w2;
}
else if (w1 == "char_name_option")
{
@@ -2920,15 +2827,16 @@ int char_config_read(const char *cfgName)
}
else if (w1 == "char_name_letters")
{
- strzcpy(char_name_letters, w2.c_str(), sizeof(char_name_letters));
+ for (uint8_t c : w2)
+ char_name_letters[c] = true;
}
else if (w1 == "online_txt_filename")
{
- strzcpy(online_txt_filename, w2.c_str(), sizeof(online_txt_filename));
+ online_txt_filename = w2;
}
else if (w1 == "online_html_filename")
{
- strzcpy(online_html_filename, w2.c_str(), sizeof(online_html_filename));
+ online_html_filename = w2;
}
else if (w1 == "online_sorting_option")
{
@@ -2948,7 +2856,7 @@ int char_config_read(const char *cfgName)
}
else if (w1 == "anti_freeze_enable")
{
- anti_freeze_enable = config_switch(w2.c_str());
+ anti_freeze_enable = config_switch(w2);
}
else if (w1 == "anti_freeze_interval")
{
@@ -2958,11 +2866,12 @@ int char_config_read(const char *cfgName)
}
else if (w1 == "import")
{
- char_config_read(w2.c_str());
+ char_config_read(w2);
}
else
{
- PRINTF("WARNING: unknown char config key: %s\n", w1);
+ FString w1z = w1;
+ PRINTF("WARNING: unknown char config key: %s\n", w1z);
}
}
@@ -2988,7 +2897,7 @@ void term_func(void)
CHAR_LOG("----End of char-server (normal end with closing of all files).\n");
}
-int do_init(int argc, char **argv)
+int do_init(int argc, ZString *argv)
{
int i;
@@ -2996,11 +2905,17 @@ int do_init(int argc, char **argv)
CHAR_LOG("");
CHAR_LOG("The char-server starting...\n");
- char_config_read((argc < 2) ? CHAR_CONF_NAME : argv[1]);
- lan_config_read((argc > 1) ? argv[1] : LOGIN_LAN_CONF_NAME);
+ 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);
- login_ip = inet_addr(login_ip_str);
- char_ip = inet_addr(char_ip_str);
+ login_ip = inet_addr(login_ip_str.c_str());
+ char_ip = inet_addr(char_ip_str.c_str());
for (i = 0; i < MAX_MAP_SERVERS; i++)
{
@@ -3013,7 +2928,10 @@ int do_init(int argc, char **argv)
update_online = TimeT::now();
create_online_files(); // update online players files at start of the server
- inter_init((argc > 2) ? argv[2] : inter_cfgName); // inter 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 5e16a6a..8e37c64 100644
--- a/src/char/char.hpp
+++ b/src/char/char.hpp
@@ -15,18 +15,18 @@ struct mmo_map_server
long ip;
short port;
int users;
- char maps[MAX_MAP_PER_SERVER][16];
+ MapName maps[MAX_MAP_PER_SERVER];
};
-const mmo_charstatus *search_character(const char *character_name);
+const mmo_charstatus *search_character(CharName character_name);
int mapif_sendall(const uint8_t *buf, unsigned int len);
int mapif_sendallwos(int fd, const uint8_t *buf, unsigned int len);
int mapif_send(int fd, const uint8_t *buf, unsigned int len);
-void char_log(const_string line);
+void char_log(XString line);
#define CHAR_LOG(fmt, ...) \
- char_log(static_cast<const std::string&>(STRPRINTF(fmt, ## __VA_ARGS__)))
+ char_log(STRPRINTF(fmt, ## __VA_ARGS__))
#endif // CHAR_HPP
diff --git a/src/char/int_party.cpp b/src/char/int_party.cpp
index 38edb9b..d2c64e1 100644
--- a/src/char/int_party.cpp
+++ b/src/char/int_party.cpp
@@ -3,8 +3,12 @@
#include <cstdlib>
#include <cstring>
+#include <fstream>
+
#include "../common/cxxstdio.hpp"
#include "../common/db.hpp"
+#include "../common/extract.hpp"
+#include "../common/io.hpp"
#include "../common/lock.hpp"
#include "../common/mmo.hpp"
#include "../common/socket.hpp"
@@ -14,7 +18,7 @@
#include "../poison.hpp"
-char party_txt[1024] = "save/party.txt";
+FString party_txt = "save/party.txt";
static
Map<int, struct party> party_db;
@@ -30,82 +34,84 @@ void mapif_parse_PartyLeave(int fd, int party_id, int account_id);
// パーティデータの文字列への変換
static
-std::string inter_party_tostr(struct party *p)
+FString inter_party_tostr(struct party *p)
{
- std::string str = STRPRINTF(
- "%d\t"
- "%s\t"
- "%d,%d\t",
- p->party_id,
- p->name,
- p->exp, p->item);
+ MString str;
+ str += STRPRINTF(
+ "%d\t"
+ "%s\t"
+ "%d,%d\t",
+ p->party_id,
+ p->name,
+ p->exp, p->item);
for (int i = 0; i < MAX_PARTY; i++)
{
struct party_member *m = &p->member[i];
+ if (!m->account_id)
+ continue;
str += STRPRINTF(
"%d,%d\t"
"%s\t",
m->account_id, m->leader,
- (m->account_id > 0) ? m->name : "NoMember");
+ m->name);
}
- return str;
+ return FString(str);
}
-// パーティデータの文字列からの変換
static
-int inter_party_fromstr(char *str, struct party *p)
+bool extract(XString str, party *p)
{
*p = party();
- if (sscanf(str,
- "%d\t"
- "%[^\t]\t"
- "%d,%d\t",
- &p->party_id,
- p->name,
- &p->exp, &p->item) != 4)
- return 1;
-
- for (int j = 0; j < 3 && str != NULL; j++)
- str = strchr(str + 1, '\t');
-
- for (int i = 0; i < MAX_PARTY; i++)
+ // not compatible with the normal extract()ors since it has
+ // a variable-size element that uses the same separator
+ std::vector<XString> bits;
+ if (!extract(str, vrec<'\t'>(&bits)))
+ return false;
+ auto begin = bits.begin();
+ auto end = bits.end();
+ if (begin == end || !extract(*begin, &p->party_id))
+ return false;
+ ++begin;
+ if (begin == end || !extract(*begin, &p->name))
+ return false;
+ ++begin;
+ if (begin == end || !extract(*begin, record<','>(&p->exp, &p->item)))
+ return false;
+ ++begin;
+
+ for (int i = 0; begin != end && i < MAX_PARTY; ++i)
{
struct party_member *m = &p->member[i];
- if (str == NULL)
- return 1;
-
- if (sscanf(str + 1,
- "%d,%d\t"
- "%[^\t]\t",
- &m->account_id, &m->leader,
- m->name) != 3)
- return 1;
-
- for (int j = 0; j < 2 && str != NULL; j++)
- str = strchr(str + 1, '\t');
+
+ if (begin == end || !extract(*begin, record<','>(&m->account_id, &m->leader)))
+ return false;
+ ++begin;
+ if (begin == end || !extract(*begin, &m->name))
+ return false;
+ ++begin;
+ if (!m->account_id)
+ --i;
}
- return 0;
+ return true;
}
// パーティデータのロード
int inter_party_init(void)
{
- char line[8192];
- FILE *fp;
- int c = 0;
- int i, j;
-
- if ((fp = fopen_(party_txt, "r")) == NULL)
+ std::ifstream in(party_txt.c_str());
+ if (!in.is_open())
return 1;
// TODO: convert to use char_id, and change to extract()
- while (fgets(line, sizeof(line) - 1, fp))
+ FString line;
+ int c = 0;
+ while (io::getline(in, line))
{
- j = 0;
- if (sscanf(line, "%d\t%%newid%%\n%n", &i, &j) == 1 && j > 0
+ int i, j = 0;
+ if (SSCANF(line, "%d\t%%newid%%\n%n", &i, &j) == 1 && j > 0
&& party_newid <= i)
{
party_newid = i;
@@ -113,7 +119,7 @@ int inter_party_init(void)
}
struct party p {};
- if (inter_party_fromstr(line, &p) == 0 && p.party_id > 0)
+ if (extract(line, &p) && p.party_id > 0)
{
if (p.party_id >= party_newid)
party_newid = p.party_id + 1;
@@ -127,7 +133,6 @@ int inter_party_init(void)
}
c++;
}
- fclose_(fp);
// PRINTF("int_party: %s read done (%d parties)\n", party_txt, c);
return 0;
@@ -137,7 +142,7 @@ int inter_party_init(void)
static
void inter_party_save_sub(struct party *data, FILE *fp)
{
- std::string line = inter_party_tostr(data);
+ FString line = inter_party_tostr(data);
FPRINTF(fp, "%s\n", line);
}
@@ -164,15 +169,15 @@ int inter_party_save(void)
// パーティ名検索用
static
-void search_partyname_sub(struct party *p, const char *str, struct party **dst)
+void search_partyname_sub(struct party *p, PartyName str, struct party **dst)
{
- if (strcasecmp(p->name, str) == 0)
+ if (p->name == str)
*dst = p;
}
// パーティ名検索
static
-struct party *search_partyname(const char *str)
+struct party *search_partyname(PartyName str)
{
struct party *p = NULL;
for (auto& pair : party_db)
@@ -227,7 +232,7 @@ int party_check_empty(struct party *p)
// キャラの競合がないかチェック用
static
void party_check_conflict_sub(struct party *p,
- int party_id, int account_id, const char *nick)
+ int party_id, int account_id, CharName nick)
{
int i;
@@ -237,7 +242,7 @@ void party_check_conflict_sub(struct party *p,
for (i = 0; i < MAX_PARTY; i++)
{
if (p->member[i].account_id == account_id
- && strcmp(p->member[i].name, nick) == 0)
+ && p->member[i].name == nick)
{
// 別のパーティに偽の所属データがあるので脱退
PRINTF("int_party: party conflict! %d %d %d\n", account_id,
@@ -249,7 +254,7 @@ void party_check_conflict_sub(struct party *p,
// キャラの競合がないかチェック
static
-void party_check_conflict(int party_id, int account_id, const char *nick)
+void party_check_conflict(int party_id, int account_id, CharName nick)
{
for (auto& pair : party_db)
party_check_conflict_sub(&pair.second,
@@ -342,14 +347,14 @@ void mapif_party_optionchanged(int fd, struct party *p, int account_id,
// パーティ脱退通知
static
-void mapif_party_leaved(int party_id, int account_id, char *name)
+void mapif_party_leaved(int party_id, int account_id, CharName name)
{
unsigned char buf[34];
WBUFW(buf, 0) = 0x3824;
WBUFL(buf, 2) = party_id;
WBUFL(buf, 6) = account_id;
- WBUF_STRING(buf, 10, name, 24);
+ WBUF_STRING(buf, 10, name.to__actual(), 24);
mapif_sendall(buf, 34);
PRINTF("int_party: party leaved %d %d %s\n", party_id, account_id, name);
}
@@ -382,9 +387,9 @@ void mapif_party_broken(int party_id, int flag)
// パーティ内発言
static
-void mapif_party_message(int party_id, int account_id, const char *mes)
+void mapif_party_message(int party_id, int account_id, XString mes)
{
- size_t len = strlen(mes);
+ size_t len = mes.size() + 1;
unsigned char buf[len + 12];
WBUFW(buf, 0) = 0x3827;
@@ -400,14 +405,11 @@ void mapif_party_message(int party_id, int account_id, const char *mes)
// パーティ
static
-void mapif_parse_CreateParty(int fd, int account_id, const char *name, const char *nick,
- const char *map, int lv)
+void mapif_parse_CreateParty(int fd, int account_id, PartyName name, CharName nick,
+ MapName map, int lv)
{
- int i;
-
- for (i = 0; i < 24 && name[i]; i++)
{
- if (!(name[i] & 0xe0) || name[i] == 0x7f)
+ if (!name.is_print())
{
PRINTF("int_party: illegal party name [%s]\n", name);
mapif_party_created(fd, account_id, NULL);
@@ -423,12 +425,12 @@ void mapif_parse_CreateParty(int fd, int account_id, const char *name, const cha
}
struct party p {};
p.party_id = party_newid++;
- strzcpy(p.name, name, 24);
+ p.name = name;
p.exp = 0;
p.item = 0;
p.member[0].account_id = account_id;
- strzcpy(p.member[0].name, nick, 24);
- strzcpy(p.member[0].map, map, 16);
+ p.member[0].name = nick;
+ p.member[0].map = map;
p.member[0].leader = 1;
p.member[0].online = 1;
p.member[0].lv = lv;
@@ -453,7 +455,7 @@ void mapif_parse_PartyInfo(int fd, int party_id)
// パーティ追加要求
static
void mapif_parse_PartyAddMember(int fd, int party_id, int account_id,
- const char *nick, const char *map, int lv)
+ CharName nick, MapName map, int lv)
{
struct party *p = party_db.search(party_id);
if (p == NULL)
@@ -469,8 +471,8 @@ void mapif_parse_PartyAddMember(int fd, int party_id, int account_id,
int flag = 0;
p->member[i].account_id = account_id;
- strzcpy(p->member[i].name, nick, 24);
- strzcpy(p->member[i].map, map, 16);
+ p->member[i].name = nick;
+ p->member[i].map = map;
p->member[i].leader = 0;
p->member[i].online = 1;
p->member[i].lv = lv;
@@ -493,7 +495,7 @@ void mapif_parse_PartyAddMember(int fd, int party_id, int account_id,
// パーティー設定変更要求
static
void mapif_parse_PartyChangeOption(int fd, int party_id, int account_id,
- int exp, int item)
+ int exp, int item)
{
struct party *p = party_db.search(party_id);
if (p == NULL)
@@ -534,7 +536,7 @@ void mapif_parse_PartyLeave(int, int party_id, int account_id)
// パーティマップ更新要求
static
void mapif_parse_PartyChangeMap(int fd, int party_id, int account_id,
- const char *map, int online, int lv)
+ MapName map, int online, int lv)
{
struct party *p = party_db.search(party_id);
if (p == NULL)
@@ -546,7 +548,7 @@ void mapif_parse_PartyChangeMap(int fd, int party_id, int account_id,
continue;
int flag = 0;
- strzcpy(p->member[i].map, map, 16);
+ p->member[i].map = map;
p->member[i].online = online;
p->member[i].lv = lv;
mapif_party_membermoved(p, i);
@@ -576,14 +578,14 @@ void mapif_parse_BreakParty(int fd, int party_id)
// パーティメッセージ送信
static
-void mapif_parse_PartyMessage(int, int party_id, int account_id, const char *mes)
+void mapif_parse_PartyMessage(int, int party_id, int account_id, XString mes)
{
mapif_party_message(party_id, account_id, mes);
}
// パーティチェック要求
static
-void mapif_parse_PartyCheck(int, int party_id, int account_id, const char *nick)
+void mapif_parse_PartyCheck(int, int party_id, int account_id, CharName nick)
{
party_check_conflict(party_id, account_id, nick);
}
@@ -600,12 +602,9 @@ int inter_party_parse_frommap(int fd)
case 0x3020:
{
int account = RFIFOL(fd, 2);
- char name[24];
- RFIFO_STRING(fd, 6, name, 24);
- char nick[24];
- RFIFO_STRING(fd, 30, nick, 24);
- char map[16];
- RFIFO_STRING(fd, 54, map, 16);
+ PartyName name = stringish<PartyName>(RFIFO_STRING<24>(fd, 6));
+ CharName nick = stringish<CharName>(RFIFO_STRING<24>(fd, 30));
+ MapName map = RFIFO_STRING<16>(fd, 54);
uint16_t lv = RFIFOW(fd, 70);
mapif_parse_CreateParty(fd,
account,
@@ -625,10 +624,8 @@ int inter_party_parse_frommap(int fd)
{
int party_id = RFIFOL(fd, 2);
int account_id = RFIFOL(fd, 6);
- char nick[24];
- RFIFO_STRING(fd, 10, nick, 24);
- char map[16];
- RFIFO_STRING(fd, 34, map, 16);
+ CharName nick = stringish<CharName>(RFIFO_STRING<24>(fd, 10));
+ MapName map = RFIFO_STRING<16>(fd, 34);
uint16_t lv = RFIFOW(fd, 50);
mapif_parse_PartyAddMember(fd,
party_id,
@@ -664,8 +661,7 @@ int inter_party_parse_frommap(int fd)
{
int party_id = RFIFOL(fd, 2);
int account_id = RFIFOL(fd, 6);
- char map[16];
- RFIFO_STRING(fd, 10, map, 16);
+ MapName map = RFIFO_STRING<16>(fd, 10);
uint8_t online = RFIFOB(fd, 26);
uint16_t lv = RFIFOW(fd, 27);
mapif_parse_PartyChangeMap(fd,
@@ -687,8 +683,7 @@ int inter_party_parse_frommap(int fd)
size_t len = RFIFOW(fd, 2) - 12;
int party_id = RFIFOL(fd, 4);
int account_id = RFIFOL(fd, 8);
- char mes[len];
- RFIFO_STRING(fd, 12, mes, len);
+ FString mes = RFIFO_STRING(fd, 12, len);
mapif_parse_PartyMessage(fd,
party_id,
account_id,
@@ -699,8 +694,7 @@ int inter_party_parse_frommap(int fd)
{
int party_id = RFIFOL(fd, 2);
int account_id = RFIFOL(fd, 6);
- char nick[24];
- RFIFO_STRING(fd, 10, nick, 24);
+ CharName nick = stringish<CharName>(RFIFO_STRING<24>(fd, 10));
mapif_parse_PartyCheck(fd,
party_id,
account_id,
diff --git a/src/char/int_party.hpp b/src/char/int_party.hpp
index 8a59b49..d003250 100644
--- a/src/char/int_party.hpp
+++ b/src/char/int_party.hpp
@@ -1,6 +1,8 @@
#ifndef INT_PARTY_HPP
#define INT_PARTY_HPP
+#include "../common/strings.hpp"
+
int inter_party_init(void);
int inter_party_save(void);
@@ -8,6 +10,6 @@ int inter_party_parse_frommap(int fd);
void inter_party_leave(int party_id, int account_id);
-extern char party_txt[1024];
+extern FString party_txt;
#endif // INT_PARTY_HPP
diff --git a/src/char/int_storage.cpp b/src/char/int_storage.cpp
index 09ce9d4..aa605bf 100644
--- a/src/char/int_storage.cpp
+++ b/src/char/int_storage.cpp
@@ -9,6 +9,7 @@
#include "../common/cxxstdio.hpp"
#include "../common/db.hpp"
#include "../common/extract.hpp"
+#include "../common/io.hpp"
#include "../common/lock.hpp"
#include "../common/mmo.hpp"
#include "../common/socket.hpp"
@@ -17,16 +18,17 @@
// ファイル名のデフォルト
// inter_config_read()で再設定される
-char storage_txt[1024] = "save/storage.txt";
+FString storage_txt = "save/storage.txt";
static
Map<int, struct storage> storage_db;
// 倉庫データを文字列に変換
static
-std::string storage_tostr(struct storage *p)
+FString storage_tostr(struct storage *p)
{
- std::string str = STRPRINTF(
+ MString str;
+ str += STRPRINTF(
"%d,%d\t",
p->account_id, p->storage_amount);
@@ -53,13 +55,13 @@ std::string storage_tostr(struct storage *p)
str += '\t';
if (!f)
- str.clear();
- return str;
+ return FString();
+ return FString(str);
}
// 文字列を倉庫データに変換
static
-bool extract(const_string str, struct storage *p)
+bool extract(XString str, struct storage *p)
{
std::vector<struct item> storage_items;
if (!extract(str,
@@ -73,7 +75,7 @@ bool extract(const_string str, struct storage *p)
if (p->account_id <= 0)
return false;
- if (storage_items.size() >= MAX_STORAGE)
+ if (storage_items.size() > MAX_STORAGE)
return false;
std::copy(storage_items.begin(), storage_items.end(), p->storage_);
@@ -98,15 +100,15 @@ int inter_storage_init(void)
{
int c = 0;
- std::ifstream in(storage_txt);
+ std::ifstream in(storage_txt.c_str());
if (!in.is_open())
{
PRINTF("cant't read : %s\n", storage_txt);
return 1;
}
- std::string line;
- while (std::getline(in, line))
+ FString line;
+ while (io::getline(in, line))
{
struct storage s {};
if (extract(line, &s))
@@ -127,8 +129,8 @@ int inter_storage_init(void)
static
void inter_storage_save_sub(struct storage *data, FILE *fp)
{
- std::string line = storage_tostr(data);
- if (!line.empty())
+ FString line = storage_tostr(data);
+ if (line)
FPRINTF(fp, "%s\n", line);
}
diff --git a/src/char/int_storage.hpp b/src/char/int_storage.hpp
index 691f16d..a03d70f 100644
--- a/src/char/int_storage.hpp
+++ b/src/char/int_storage.hpp
@@ -1,6 +1,8 @@
#ifndef INT_STORAGE_HPP
#define INT_STORAGE_HPP
+#include "../common/strings.hpp"
+
int inter_storage_init(void);
int inter_storage_save(void);
void inter_storage_delete(int account_id);
@@ -8,6 +10,6 @@ struct storage *account2storage(int account_id);
int inter_storage_parse_frommap(int fd);
-extern char storage_txt[1024];
+extern FString storage_txt;
#endif // INT_STORAGE_HPP
diff --git a/src/char/inter.cpp b/src/char/inter.cpp
index 68d81e8..3cb51e7 100644
--- a/src/char/inter.cpp
+++ b/src/char/inter.cpp
@@ -10,6 +10,7 @@
#include "../common/cxxstdio.hpp"
#include "../common/db.hpp"
#include "../common/extract.hpp"
+#include "../common/io.hpp"
#include "../common/lock.hpp"
#include "../common/socket.hpp"
#include "../common/timer.hpp"
@@ -25,10 +26,10 @@
// that is the waiting time of answers of all map-servers
constexpr std::chrono::minutes WISDATA_TTL = std::chrono::minutes(1);
-char inter_log_filename[1024] = "log/inter.log";
+FString inter_log_filename = "log/inter.log";
static
-char accreg_txt[1024] = "save/accreg.txt";
+FString accreg_txt = "save/accreg.txt";
struct accreg
{
@@ -59,8 +60,8 @@ struct WisData
{
int id, fd, count;
tick_t tick;
- char src[24], dst[24];
- std::string msg;
+ CharName src, dst;
+ FString msg;
};
static
Map<int, struct WisData> wis_db;
@@ -71,17 +72,18 @@ std::vector<int> wis_dellistv;
// アカウント変数を文字列へ変換
static
-std::string inter_accreg_tostr(struct accreg *reg)
+FString inter_accreg_tostr(struct accreg *reg)
{
- std::string str STRPRINTF("%d\t", reg->account_id);
+ MString str;
+ str += STRPRINTF("%d\t", reg->account_id);
for (int j = 0; j < reg->reg_num; j++)
str += STRPRINTF("%s,%d ", reg->reg[j].str, reg->reg[j].value);
- return str;
+ return FString(str);
}
// アカウント変数を文字列から変換
static
-bool extract(const_string str, struct accreg *reg)
+bool extract(XString str, struct accreg *reg)
{
std::vector<struct global_reg> vars;
if (!extract(str,
@@ -105,11 +107,11 @@ int inter_accreg_init(void)
{
int c = 0;
- std::ifstream in(accreg_txt);
+ std::ifstream in(accreg_txt.c_str());
if (!in.is_open())
return 1;
- std::string line;
- while (std::getline(in, line))
+ FString line;
+ while (io::getline(in, line))
{
struct accreg reg {};
if (extract(line, &reg))
@@ -133,7 +135,7 @@ void inter_accreg_save_sub(struct accreg *reg, FILE *fp)
{
if (reg->reg_num > 0)
{
- std::string line = inter_accreg_tostr(reg);
+ FString line = inter_accreg_tostr(reg);
fwrite(line.data(), 1, line.size(), fp);
fputc('\n', fp);
}
@@ -166,33 +168,34 @@ int inter_accreg_save(void)
*------------------------------------------
*/
static
-int inter_config_read(const char *cfgName)
+int inter_config_read(ZString cfgName)
{
- std::ifstream in(cfgName);
+ std::ifstream in(cfgName.c_str());
if (!in.is_open())
{
PRINTF("file not found: %s\n", cfgName);
return 1;
}
- std::string line;
- while (std::getline(in, line))
+ FString line;
+ while (io::getline(in, line))
{
- std::string w1, w2;
+ SString w1;
+ TString w2;
if (!split_key_value(line, &w1, &w2))
continue;
if (w1 == "storage_txt")
{
- strzcpy(storage_txt, w2.c_str(), sizeof(storage_txt));
+ storage_txt = w2;
}
else if (w1 == "party_txt")
{
- strzcpy(party_txt, w2.c_str(), sizeof(party_txt));
+ party_txt = w2;
}
else if (w1 == "accreg_txt")
{
- strzcpy(accreg_txt, w2.c_str(), sizeof(accreg_txt));
+ accreg_txt = w2;
}
else if (w1 == "party_share_level")
{
@@ -202,15 +205,16 @@ int inter_config_read(const char *cfgName)
}
else if (w1 == "inter_log_filename")
{
- strzcpy(inter_log_filename, w2.c_str(), sizeof(inter_log_filename));
+ inter_log_filename = w2;
}
else if (w1 == "import")
{
- inter_config_read(w2.c_str());
+ inter_config_read(w2);
}
else
{
- PRINTF("WARNING: unknown inter config key: %s\n", w1);
+ FString w1z = w1;
+ PRINTF("WARNING: unknown inter config key: %s\n", w1z);
}
}
@@ -218,25 +222,21 @@ int inter_config_read(const char *cfgName)
}
// セーブ
-int inter_save(void)
+void inter_save(void)
{
inter_party_save();
inter_storage_save();
inter_accreg_save();
-
- return 0;
}
// 初期化
-int inter_init(const char *file)
+void inter_init(ZString file)
{
inter_config_read(file);
inter_party_init();
inter_storage_init();
inter_accreg_init();
-
- return 0;
}
//--------------------------------------------------------
@@ -244,9 +244,9 @@ int inter_init(const char *file)
// GMメッセージ送信
static
-void mapif_GMmessage(const char *mes)
+void mapif_GMmessage(XString mes)
{
- size_t str_len = strlen(mes) + 1;
+ size_t str_len = mes.size() + 1;
size_t msg_len = str_len + 4;
uint8_t buf[msg_len];
@@ -266,9 +266,9 @@ void mapif_wis_message(struct WisData *wd)
WBUFW(buf, 0) = 0x3801;
WBUFW(buf, 2) = 56 + str_size;
WBUFL(buf, 4) = wd->id;
- WBUF_STRING(buf, 8, wd->src, 24);
- WBUF_STRING(buf, 32, wd->dst, 24);
- WBUF_STRING(buf, 56, wd->msg.c_str(), str_size);
+ WBUF_STRING(buf, 8, wd->src.to__actual(), 24);
+ WBUF_STRING(buf, 32, wd->dst.to__actual(), 24);
+ WBUF_STRING(buf, 56, wd->msg, str_size);
wd->count = mapif_sendall(buf, WBUFW(buf, 2));
}
@@ -279,7 +279,7 @@ void mapif_wis_end(struct WisData *wd, int flag)
uint8_t buf[27];
WBUFW(buf, 0) = 0x3802;
- WBUF_STRING(buf, 2, wd->src, 24);
+ WBUF_STRING(buf, 2, wd->src.to__actual(), 24);
WBUFB(buf, 26) = flag; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
mapif_send(wd->fd, buf, 27);
}
@@ -362,8 +362,7 @@ void mapif_parse_GMmessage(int fd)
{
size_t msg_len = RFIFOW(fd, 2);
size_t str_len = msg_len - 4;
- char buf[str_len];
- RFIFO_STRING(fd, 4, buf, str_len);
+ FString buf = RFIFO_STRING(fd, 4, str_len);
mapif_GMmessage(buf);
}
@@ -380,10 +379,8 @@ void mapif_parse_WisRequest(int fd)
return;
}
- char from[24];
- char to[24];
- RFIFO_STRING(fd, 4, from, 24);
- RFIFO_STRING(fd, 28, to, 24);
+ CharName from = stringish<CharName>(RFIFO_STRING<24>(fd, 4));
+ CharName to = stringish<CharName>(RFIFO_STRING<24>(fd, 28));
// search if character exists before to ask all map-servers
const mmo_charstatus *mcs = search_character(to);
@@ -391,7 +388,7 @@ void mapif_parse_WisRequest(int fd)
{
uint8_t buf[27];
WBUFW(buf, 0) = 0x3802;
- WBUF_STRING(buf, 2, from, 24);
+ WBUF_STRING(buf, 2, from.to__actual(), 24);
WBUFB(buf, 26) = 1; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
mapif_send(fd, buf, 27);
// Character exists. So, ask all map-servers
@@ -399,19 +396,19 @@ void mapif_parse_WisRequest(int fd)
else
{
// to be sure of the correct name, rewrite it
- strzcpy(to, mcs->name, 24);
+ to = mcs->name;
// if source is destination, don't ask other servers.
- if (strcmp(from, to) == 0)
+ if (from == to)
{
uint8_t buf[27];
WBUFW(buf, 0) = 0x3802;
- WBUF_STRING(buf, 2, from, 24);
+ WBUF_STRING(buf, 2, from.to__actual(), 24);
WBUFB(buf, 26) = 1; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
mapif_send(fd, buf, 27);
}
else
{
- struct WisData wd;
+ struct WisData wd {};
// Whether the failure of previous wisp/page transmission (timeout)
check_ttl_wisdata();
@@ -419,11 +416,9 @@ void mapif_parse_WisRequest(int fd)
wd.id = ++wisid;
wd.fd = fd;
size_t len = RFIFOW(fd, 2) - 52;
- RFIFO_STRING(fd, 4, wd.src, 24);
- RFIFO_STRING(fd, 28, wd.dst, 24);
- char tmpbuf[len];
- RFIFO_STRING(fd, 52, tmpbuf, len);
- wd.msg = std::string(tmpbuf);
+ wd.src = from;
+ wd.dst = to;
+ wd.msg = RFIFO_STRING(fd, 52, len);
wd.tick = gettick();
wis_db.insert(wd.id, wd);
mapif_wis_message(&wd);
@@ -480,7 +475,7 @@ void mapif_parse_AccReg(int fd)
for (j = 0, p = 8; j < ACCOUNT_REG_NUM && p < RFIFOW(fd, 2);
j++, p += 36)
{
- RFIFO_STRING(fd, p, reg->reg[j].str, 32);
+ reg->reg[j].str = stringish<VarName>(RFIFO_STRING<32>(fd, p));
reg->reg[j].value = RFIFOL(fd, p + 32);
}
reg->reg_num = j;
diff --git a/src/char/inter.hpp b/src/char/inter.hpp
index 0adbf03..ce8447d 100644
--- a/src/char/inter.hpp
+++ b/src/char/inter.hpp
@@ -1,8 +1,10 @@
#ifndef INTER_HPP
#define INTER_HPP
-int inter_init(const char *file);
-int inter_save(void);
+#include "../common/strings.hpp"
+
+void inter_init(ZString file);
+void inter_save(void);
int inter_parse_frommap(int fd);
int inter_check_length(int fd, int length);
@@ -10,6 +12,6 @@ int inter_check_length(int fd, int length);
#define inter_cfgName "conf/inter_athena.conf"
extern int party_share_level;
-extern char inter_log_filename[1024];
+extern FString inter_log_filename;
#endif // INTER_HPP
diff --git a/src/common/const_array.hpp b/src/common/const_array.hpp
index a3a6d58..314eccf 100644
--- a/src/common/const_array.hpp
+++ b/src/common/const_array.hpp
@@ -25,11 +25,11 @@
#include <iterator>
#include <ostream>
-#include <string>
#include <vector>
#ifdef WORKAROUND_GCC46_COMPILER
// constexpr is buggy with templates in this version
+// Is this still needed now that const_string is removed?
# define constexpr /* nothing */
#endif
@@ -125,57 +125,8 @@ public:
}
};
-// subclass just provides a simpler name and some conversions
-// Important note: it must be safe to dereference end, though
-// the value is unspecified.
-class const_string : public const_array<char>
-{
-public:
- // Implicit conversion from C string.
- constexpr
- const_string(const char *z)
- : const_array<char>(z, z ? strlen(z) : 0)
- {}
-
- // Same as parent constructor.
- constexpr
- const_string(const char *s, size_t l)
- : const_array<char>(s, l)
- {}
-
- // Same as parent constructor.
- constexpr
- const_string(const char *b, const char *e)
- : const_array<char>(b, e)
- {}
-
- // Same as parent constructor.
- const_string(const std::vector<char> s)
- : const_array<char>(s)
- {}
-
- // Implicit conversion from C++ string.
- const_string(const std::string& s)
- : const_array<char>(s.data(), s.size())
- {}
-
- // but disallow converion from a temporary.
- const_string(std::string&&) = delete;
-
- // allow being sloppy
- constexpr
- const_string(const_array<char> a)
- : const_array<char>(a)
- {}
-};
#ifdef WORKAROUND_GCC46_COMPILER
# undef constexpr
#endif
-inline
-std::ostream& operator << (std::ostream& o, const_string s)
-{
- return o.write(s.data(), s.size());
-}
-
#endif // CONST_ARRAY_HPP
diff --git a/src/common/core.cpp b/src/common/core.cpp
index 153414d..76aa09c 100644
--- a/src/common/core.cpp
+++ b/src/common/core.cpp
@@ -76,7 +76,11 @@ int main(int argc, char **argv)
{
do_socket();
- do_init(argc, argv);
+ // ZString args[argc]; is (deliberately!) not supported by clang yet
+ ZString *args = static_cast<ZString *>(alloca(argc * sizeof(ZString)));
+ for (int i = 0; i < argc; ++i)
+ args[i] = ZString(ZString::really_construct_from_a_pointer, argv[i], nullptr);
+ do_init(argc, args);
// 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 0c11efb..f1473ed 100644
--- a/src/common/core.hpp
+++ b/src/common/core.hpp
@@ -3,6 +3,8 @@
#include "sanity.hpp"
+#include "strings.hpp"
+
/// core.c contains a server-independent main() function
/// and then runs a do_sendrecv loop
@@ -12,7 +14,7 @@ extern bool runflag;
/// This is an external function defined by each server
/// This function must register stuff for the parse loop
-extern int do_init(int, char **);
+extern int do_init(int, ZString *);
/// Cleanup function called whenever a signal kills us
/// or when if we manage to exit() gracefully.
diff --git a/src/common/cxxstdio.cpp b/src/common/cxxstdio.cpp
deleted file mode 100644
index 8f4001f..0000000
--- a/src/common/cxxstdio.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-#include "cxxstdio.hpp"
-// cxxstdio.cpp - pass C++ types through scanf/printf
-//
-// Copyright © 2013 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 <cstdlib>
-
-namespace cxxstdio
-{
-StringConverter::~StringConverter()
-{
- if (mid)
- {
- out = mid;
- free(mid);
- }
-}
-} // namespace cxxstdio
diff --git a/src/common/cxxstdio.hpp b/src/common/cxxstdio.hpp
index 96c3ca2..89cc5de 100644
--- a/src/common/cxxstdio.hpp
+++ b/src/common/cxxstdio.hpp
@@ -24,37 +24,19 @@
#include <cstdarg>
#include <cstdio>
-#include <string>
-
#include "const_array.hpp"
#include "utils2.hpp"
namespace cxxstdio
{
+ // other implementations of do_vprint or do_vscan are injected by ADL.
inline __attribute__((format(printf, 2, 0)))
int do_vprint(FILE *out, const char *fmt, va_list ap)
{
return vfprintf(out, fmt, ap);
}
- inline __attribute__((format(printf, 2, 0)))
- int do_vprint(std::string& out, const char *fmt, va_list ap)
- {
- int len;
- {
- va_list ap2;
- va_copy(ap2, ap);
- len = vsnprintf(nullptr, 0, fmt, ap2);
- va_end(ap2);
- }
- char buffer[len + 1];
- vsnprintf(buffer, len + 1, fmt, ap);
-
- out = buffer;
- return len;
- }
-
inline __attribute__((format(scanf, 2, 0)))
int do_vscan(FILE *in, const char *fmt, va_list ap)
{
@@ -72,13 +54,6 @@ namespace cxxstdio
int do_vscan(const char *, const char *, va_list) = delete;
#endif
- inline __attribute__((format(scanf, 2, 0)))
- int do_vscan(const std::string& in, const char *fmt, va_list ap)
- {
- return vsscanf(in.c_str(), fmt, ap);
- }
-
-
template<class T>
inline __attribute__((format(printf, 2, 3)))
int do_print(T&& t, const char *fmt, ...) throw()
@@ -104,13 +79,19 @@ namespace cxxstdio
}
- template<class T>
- typename remove_enum<T>::type convert_for_printf(T v)
+ template<class T, typename=typename std::enable_if<!std::is_class<T>::value>::type>
+ typename remove_enum<T>::type decay_for_printf(T v)
{
typedef typename remove_enum<T>::type repr_type;
return repr_type(v);
}
+ template<class T, typename=decltype(decay_for_printf(std::declval<T&&>()))>
+ T&& convert_for_printf(T&& v)
+ {
+ return std::forward<T>(v);
+ }
+
template<class T, typename = typename std::enable_if<!std::is_enum<T>::value>::type>
T& convert_for_scanf(T& v)
{
@@ -152,7 +133,7 @@ namespace cxxstdio
}
template<class E>
constexpr
- E get_max_value(E)
+ E get_enum_max_value(E)
{
return E::max_value;
}
@@ -199,34 +180,6 @@ namespace cxxstdio
return v;
}
-
- inline
- const char *convert_for_printf(const std::string& s)
- {
- return s.c_str();
- }
-
- class StringConverter
- {
- std::string& out;
- char *mid;
- public:
- StringConverter(std::string& s)
- : out(s), mid(nullptr)
- {}
- ~StringConverter();
- char **operator &()
- {
- return &mid;
- }
- };
-
- inline
- StringConverter convert_for_scanf(std::string& s)
- {
- return StringConverter(s);
- }
-
template<class Format>
class PrintFormatter
{
@@ -238,7 +191,7 @@ namespace cxxstdio
constexpr static
const char *print_format = Format::print_format();
return do_print(std::forward<T>(t), print_format,
- convert_for_printf(std::forward<A>(a))...);
+ decay_for_printf(convert_for_printf(std::forward<A>(a)))...);
}
};
@@ -257,7 +210,7 @@ namespace cxxstdio
}
};
-#define FPRINTF(file, fmt, ...) \
+#define XPRINTF(out, fmt, ...) \
([&]() -> int \
{ \
struct format_impl \
@@ -265,10 +218,10 @@ namespace cxxstdio
constexpr static \
const char *print_format() { return fmt; } \
}; \
- return cxxstdio::PrintFormatter<format_impl>::print(file, ## __VA_ARGS__); \
+ return cxxstdio::PrintFormatter<format_impl>::print(out, ## __VA_ARGS__); \
}())
-#define FSCANF(file, fmt, ...) \
+#define XSCANF(out, fmt, ...) \
([&]() -> int \
{ \
struct format_impl \
@@ -276,22 +229,33 @@ namespace cxxstdio
constexpr static \
const char *scan_format() { return fmt; } \
}; \
- return cxxstdio::ScanFormatter<format_impl>::scan(file, ## __VA_ARGS__); \
+ return cxxstdio::ScanFormatter<format_impl>::scan(out, ## __VA_ARGS__); \
}())
+#define FPRINTF(file, fmt, ...) XPRINTF(no_cast<FILE *>(file), fmt, ## __VA_ARGS__)
+#define FSCANF(file, fmt, ...) XSCANF(no_cast<FILE *>(file), fmt, ## __VA_ARGS__)
#define PRINTF(fmt, ...) FPRINTF(stdout, fmt, ## __VA_ARGS__)
-#define SPRINTF(str, fmt, ...) FPRINTF(str, fmt, ## __VA_ARGS__)
+#define SPRINTF(str, fmt, ...) XPRINTF(base_cast<FString&>(str), fmt, ## __VA_ARGS__)
+#define SNPRINTF(str, n, fmt, ...) XPRINTF(base_cast<VString<n-1>&>(str), fmt, ## __VA_ARGS__)
#define SCANF(fmt, ...) FSCANF(stdin, fmt, ## __VA_ARGS__)
-#define SSCANF(str, fmt, ...) FSCANF(str, fmt, ## __VA_ARGS__)
+#define SSCANF(str, fmt, ...) XSCANF(/*ZString or compatible*/str, fmt, ## __VA_ARGS__)
#define STRPRINTF(fmt, ...) \
- ([&]() -> std::string \
+ ([&]() -> FString \
{ \
- std::string _out_impl; \
+ FString _out_impl; \
SPRINTF(_out_impl, fmt, ## __VA_ARGS__);\
return _out_impl; \
}())
+#define STRNPRINTF(n, fmt, ...) \
+ ([&]() -> VString<n - 1> \
+ { \
+ VString<n - 1> _out_impl; \
+ SNPRINTF(_out_impl, n, fmt, ## __VA_ARGS__);\
+ return _out_impl; \
+ }())
+
} // namespace cxxstdio
#endif // CXXSTDIO_HPP
diff --git a/src/common/cxxstdio_test.cpp b/src/common/cxxstdio_test.cpp
new file mode 100644
index 0000000..9b6eeb2
--- /dev/null
+++ b/src/common/cxxstdio_test.cpp
@@ -0,0 +1,3 @@
+#include "cxxstdio.hpp"
+
+#include <gtest/gtest.h>
diff --git a/src/common/dumb_ptr.hpp b/src/common/dumb_ptr.hpp
index 8863ef2..fe5031a 100644
--- a/src/common/dumb_ptr.hpp
+++ b/src/common/dumb_ptr.hpp
@@ -202,25 +202,25 @@ struct dumb_string
{
return dumb_string::copy(sz, sz + strlen(sz));
}
- static dumb_string copys(const std::string& s)
+ static dumb_string copys(XString s)
{
return dumb_string::copy(&*s.begin(), &*s.end());
}
- static dumb_string copyn(const char *sn, size_t n)
+ static
+#ifndef __clang__
+ __attribute__((warning("shouldn't use this - slice instead")))
+#endif
+ dumb_string copyn(const char *sn, size_t n)
{
return dumb_string::copy(sn, sn + strnlen(sn, n));
}
- static dumb_string copyc(const_string s)
- {
- return dumb_string::copy(s.begin(), s.end());
- }
static
- dumb_string fake(const char *p)
+ dumb_string fake(ZString p)
{
dumb_string rv;
- size_t len = p ? strlen(p) : 0;
- rv.impl = dumb_ptr<char[]>(const_cast<char *>(p), len);
+ size_t len = p.size();
+ rv.impl = dumb_ptr<char[]>(const_cast<char *>(p.c_str()), len);
return rv;
}
@@ -235,17 +235,17 @@ struct dumb_string
const char *c_str() const
{
- return impl ? &impl[0] : "";
+ return &impl[0];
}
- std::string str() const
+ operator ZString() const
{
- return c_str();
+ return ZString(ZString::really_construct_from_a_pointer, c_str(), nullptr);
}
- operator const_string() const
+ FString str() const
{
- return const_string(c_str());
+ return ZString(*this);
}
char& operator[](size_t i) const
@@ -262,117 +262,8 @@ struct dumb_string
{
return !impl;
}
-
- operator ZString() { return ZString(ZString::really_construct_from_a_pointer, c_str()); }
-
-#if 0
- friend bool operator == (dumb_string l, dumb_string r)
- {
- return l.impl == r.impl;
- }
- friend bool operator != (dumb_string l, dumb_string r)
- {
- return !(l == r);
- }
-#endif
};
-namespace operators
-{
- inline
- bool operator == (dumb_string l, dumb_string r)
- {
- return strcmp(l.c_str(), r.c_str()) == 0;
- }
- inline
- bool operator != (dumb_string l, dumb_string r)
- {
- return strcmp(l.c_str(), r.c_str()) != 0;
- }
- inline
- bool operator < (dumb_string l, dumb_string r)
- {
- return strcmp(l.c_str(), r.c_str()) < 0;
- }
- inline
- bool operator <= (dumb_string l, dumb_string r)
- {
- return strcmp(l.c_str(), r.c_str()) <= 0;
- }
- inline
- bool operator > (dumb_string l, dumb_string r)
- {
- return strcmp(l.c_str(), r.c_str()) > 0;
- }
- inline
- bool operator >= (dumb_string l, dumb_string r)
- {
- return strcmp(l.c_str(), r.c_str()) >= 0;
- }
-
- inline
- bool operator == (const char *l, dumb_string r)
- {
- return strcmp(l, r.c_str()) == 0;
- }
- inline
- bool operator != (const char *l, dumb_string r)
- {
- return strcmp(l, r.c_str()) != 0;
- }
- inline
- bool operator < (const char *l, dumb_string r)
- {
- return strcmp(l, r.c_str()) < 0;
- }
- inline
- bool operator <= (const char *l, dumb_string r)
- {
- return strcmp(l, r.c_str()) <= 0;
- }
- inline
- bool operator > (const char *l, dumb_string r)
- {
- return strcmp(l, r.c_str()) > 0;
- }
- inline
- bool operator >= (const char *l, dumb_string r)
- {
- return strcmp(l, r.c_str()) >= 0;
- }
-
- inline
- bool operator == (dumb_string l, const char *r)
- {
- return strcmp(l.c_str(), r) == 0;
- }
- inline
- bool operator != (dumb_string l, const char *r)
- {
- return strcmp(l.c_str(), r) != 0;
- }
- inline
- bool operator < (dumb_string l, const char *r)
- {
- return strcmp(l.c_str(), r) < 0;
- }
- inline
- bool operator <= (dumb_string l, const char *r)
- {
- return strcmp(l.c_str(), r) <= 0;
- }
- inline
- bool operator > (dumb_string l, const char *r)
- {
- return strcmp(l.c_str(), r) > 0;
- }
- inline
- bool operator >= (dumb_string l, const char *r)
- {
- return strcmp(l.c_str(), r) >= 0;
- }
-}
-
inline
const char *convert_for_printf(dumb_string ds)
{
diff --git a/src/common/extract.cpp b/src/common/extract.cpp
index 5e89e19..720e6df 100644
--- a/src/common/extract.cpp
+++ b/src/common/extract.cpp
@@ -18,28 +18,31 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
-bool extract(const_string str, const_string *rv)
+#include "../poison.hpp"
+
+bool extract(XString str, XString *rv)
{
*rv = str;
return true;
}
-bool extract(const_string str, std::string *rv)
+bool extract(XString str, FString *rv)
{
- *rv = std::string(str.begin(), str.end());
+ *rv = str;
return true;
}
-bool extract(const_string str, struct global_reg *var)
+bool extract(XString str, struct global_reg *var)
{
return extract(str,
record<','>(&var->str, &var->value));
}
-bool extract(const_string str, struct item *it)
+bool extract(XString str, struct item *it)
{
+ it->broken = 0;
return extract(str,
- record<','>(
+ record<',', 11>(
&it->id,
&it->nameid,
&it->amount,
@@ -51,18 +54,5 @@ bool extract(const_string str, struct item *it)
&it->card[1],
&it->card[2],
&it->card[3],
- &it->broken))
- || extract(str,
- record<','>(
- &it->id,
- &it->nameid,
- &it->amount,
- &it->equip,
- &it->identify,
- &it->refine,
- &it->attribute,
- &it->card[0],
- &it->card[1],
- &it->card[2],
- &it->card[3]));
+ &it->broken));
}
diff --git a/src/common/extract.hpp b/src/common/extract.hpp
index ae1a74b..3c24693 100644
--- a/src/common/extract.hpp
+++ b/src/common/extract.hpp
@@ -27,14 +27,15 @@
#include "mmo.hpp"
#include "utils.hpp"
-template<class T, typename=typename std::enable_if<std::is_integral<T>::value && !std::is_same<T, char>::value>::type>
-bool extract(const_string str, T *iv)
+template<class T, typename=typename std::enable_if<std::is_integral<T>::value && !std::is_same<T, char>::value && !std::is_same<T, bool>::value>::type>
+bool extract(XString str, T *iv)
{
if (!str || str.size() > 20)
return false;
if (!((str.front() == '-' && std::is_signed<T>::value)
|| ('0' <= str.front() && str.front() <= '9')))
return false;
+ // needs a NUL, but can't always be given one. TODO VString?
char buf[20 + 1];
std::copy(str.begin(), str.end(), buf);
buf[str.size()] = '\0';
@@ -60,14 +61,14 @@ bool extract(const_string str, T *iv)
}
inline
-bool extract(const_string str, TimeT *tv)
+bool extract(XString str, TimeT *tv)
{
return extract(str, &tv->value);
}
// extra typename=void to workaround some duplicate overload rule
template<class T, typename=typename std::enable_if<std::is_enum<T>::value>::type, typename=void>
-bool extract(const_string str, T *iv)
+bool extract(XString str, T *iv)
{
typedef typename underlying_type<T>::type U;
U v;
@@ -79,59 +80,90 @@ bool extract(const_string str, T *iv)
return true;
}
-bool extract(const_string str, const_string *rv);
+bool extract(XString str, XString *rv);
-bool extract(const_string str, std::string *rv);
+bool extract(XString str, FString *rv);
-template<size_t N>
-__attribute__((deprecated))
-bool extract(const_string str, char (*out)[N])
+template<uint8_t N>
+bool extract(XString str, VString<N> *out)
{
- if (str.size() >= N)
+ if (str.size() > N)
return false;
- std::copy(str.begin(), str.end(), *out);
- std::fill(*out + str.size() , *out + N, '\0');
+ *out = str;
return true;
}
+template<class T>
+class LStripper
+{
+public:
+ T impl;
+};
+
+template<class T>
+LStripper<T> lstripping(T v)
+{
+ return {v};
+}
+
+template<class T>
+bool extract(XString str, LStripper<T> out)
+{
+ return extract(str.lstrip(), out.impl);
+}
+
// basically just a std::tuple
// but it provides its data members publically
-template<char split, class... T>
+template<char split, int n, class... T>
class Record;
-template<char split>
-class Record<split>
+template<char split, int n>
+class Record<split, n>
{
};
-template<char split, class F, class... R>
-class Record<split, F, R...>
+template<char split, int n, class F, class... R>
+class Record<split, n, F, R...>
{
public:
F frist;
- Record<split, R...> rest;
+ Record<split, n - 1, R...> rest;
public:
Record(F f, R... r)
: frist(f), rest(r...)
{}
};
template<char split, class... T>
-Record<split, T...> record(T... t)
+Record<split, sizeof...(T), T...> record(T... t)
+{
+ return Record<split, sizeof...(T), T...>(t...);
+}
+template<char split, int n, class... T>
+Record<split, n, T...> record(T... t)
{
- return Record<split, T...>(t...);
+ static_assert(0 < n && n < sizeof...(T), "don't be silly");
+ return Record<split, n, T...>(t...);
}
-template<char split>
-bool extract(const_string str, Record<split>)
+template<char split, int n>
+bool extract(XString str, Record<split, n>)
{
return !str;
}
-template<char split, class F, class... R>
-bool extract(const_string str, Record<split, F, R...> rec)
+
+template<char split, int n, class F, class... R>
+bool extract(XString str, Record<split, n, F, R...> rec)
{
- const char *s = std::find(str.begin(), str.end(), split);
+ XString::iterator s = std::find(str.begin(), str.end(), split);
+ XString::iterator s2 = s;
+ if (s2 != str.end())
+ ++s2;
+ XString head = str.xislice_h(s);
+ XString tail = str.xislice_t(s2);
if (s == str.end())
- return sizeof...(R) == 0 && extract(str, rec.frist);
- return extract(const_string(str.begin(), s), rec.frist)
- && extract(const_string(s + 1, str.end()), rec.rest);
+ return (extract(head, rec.frist) && n <= 1)
+ || (!head && n <= 0);
+
+ return (extract(head, rec.frist) || n <= 0)
+ && extract(tail, rec.rest);
}
template<char split, class T>
@@ -147,20 +179,41 @@ VRecord<split, T> vrec(std::vector<T> *arr)
}
template<char split, class T>
-bool extract(const_string str, VRecord<split, T> rec)
+bool extract(XString str, VRecord<split, T> rec)
{
- if (str.empty())
+ if (!str)
return true;
- const char *s = std::find(str.begin(), str.end(), split);
+ XString::iterator s = std::find(str.begin(), str.end(), split);
rec.arr->emplace_back();
if (s == str.end())
return extract(str, &rec.arr->back());
- return extract(const_string(str.begin(), s), &rec.arr->back())
- && extract(const_string(s + 1, str.end()), rec);
+ return extract(str.xislice_h(s), &rec.arr->back())
+ && extract(str.xislice_t(s + 1), rec);
}
-bool extract(const_string str, struct global_reg *var);
+bool extract(XString str, struct global_reg *var);
+
+bool extract(XString str, struct item *it);
+
+inline
+bool extract(XString str, MapName *m)
+{
+ VString<15> tmp;
+ bool rv = extract(str, &tmp);
+ *m = tmp;
+ return rv;
+}
-bool extract(const_string str, struct item *it);
+inline
+bool extract(XString str, CharName *out)
+{
+ VString<23> tmp;
+ if (extract(str, &tmp))
+ {
+ *out = CharName(tmp);
+ return true;
+ }
+ return false;
+}
#endif // EXTRACT_HPP
diff --git a/src/common/extract_test.cpp b/src/common/extract_test.cpp
new file mode 100644
index 0000000..d8e9ebe
--- /dev/null
+++ b/src/common/extract_test.cpp
@@ -0,0 +1,319 @@
+#include "extract.hpp"
+
+#include <gtest/gtest.h>
+
+TEST(extract, record_int)
+{
+ int x, y, z;
+ x = y = z = 0;
+ EXPECT_FALSE(extract("1 2 3 4 ", record<' '>(&x, &y, &z)));
+ EXPECT_EQ(1, x);
+ EXPECT_EQ(2, y);
+ EXPECT_EQ(3, z);
+ x = y = z = 0;
+ EXPECT_FALSE(extract("1 2 3 4", record<' '>(&x, &y, &z)));
+ EXPECT_EQ(1, x);
+ EXPECT_EQ(2, y);
+ EXPECT_EQ(3, z);
+ x = y = z = 0;
+ EXPECT_TRUE(extract("1 2 3 ", record<' '>(&x, &y, &z)));
+ EXPECT_EQ(1, x);
+ EXPECT_EQ(2, y);
+ EXPECT_EQ(3, z);
+ x = y = z = 0;
+ EXPECT_TRUE(extract("1 2 3", record<' '>(&x, &y, &z)));
+ EXPECT_EQ(1, x);
+ EXPECT_EQ(2, y);
+ EXPECT_EQ(3, z);
+ x = y = z = 0;
+ EXPECT_FALSE(extract("1 2 ", record<' '>(&x, &y, &z)));
+ EXPECT_EQ(1, x);
+ EXPECT_EQ(2, y);
+ EXPECT_EQ(0, z);
+ x = y = z = 0;
+ EXPECT_FALSE(extract("1 2", record<' '>(&x, &y, &z)));
+ EXPECT_EQ(1, x);
+ EXPECT_EQ(2, y);
+ EXPECT_EQ(0, z);
+ x = y = z = 0;
+ EXPECT_FALSE(extract("1 ", record<' '>(&x, &y, &z)));
+ EXPECT_EQ(1, x);
+ EXPECT_EQ(0, y);
+ EXPECT_EQ(0, z);
+ x = y = z = 0;
+ EXPECT_FALSE(extract("1", record<' '>(&x, &y, &z)));
+ EXPECT_EQ(1, x);
+ EXPECT_EQ(0, y);
+ EXPECT_EQ(0, z);
+ x = y = z = 0;
+ EXPECT_FALSE(extract(" ", record<' '>(&x, &y, &z)));
+ EXPECT_EQ(0, x);
+ EXPECT_EQ(0, y);
+ EXPECT_EQ(0, z);
+ x = y = z = 0;
+ EXPECT_FALSE(extract("", record<' '>(&x, &y, &z)));
+ EXPECT_EQ(0, x);
+ EXPECT_EQ(0, y);
+ EXPECT_EQ(0, z);
+ x = y = z = 0;
+
+ EXPECT_FALSE(extract("1 2 3 4 ", record<' ', 2>(&x, &y, &z)));
+ EXPECT_EQ(1, x);
+ EXPECT_EQ(2, y);
+ EXPECT_EQ(3, z);
+ x = y = z = 0;
+ EXPECT_FALSE(extract("1 2 3 4", record<' ', 2>(&x, &y, &z)));
+ EXPECT_EQ(1, x);
+ EXPECT_EQ(2, y);
+ EXPECT_EQ(3, z);
+ x = y = z = 0;
+ EXPECT_TRUE(extract("1 2 3 ", record<' ', 2>(&x, &y, &z)));
+ EXPECT_EQ(1, x);
+ EXPECT_EQ(2, y);
+ EXPECT_EQ(3, z);
+ x = y = z = 0;
+ EXPECT_TRUE(extract("1 2 3", record<' ', 2>(&x, &y, &z)));
+ EXPECT_EQ(1, x);
+ EXPECT_EQ(2, y);
+ EXPECT_EQ(3, z);
+ x = y = z = 0;
+ EXPECT_TRUE(extract("1 2 ", record<' ', 2>(&x, &y, &z)));
+ EXPECT_EQ(1, x);
+ EXPECT_EQ(2, y);
+ EXPECT_EQ(0, z);
+ x = y = z = 0;
+ EXPECT_TRUE(extract("1 2", record<' ', 2>(&x, &y, &z)));
+ EXPECT_EQ(1, x);
+ EXPECT_EQ(2, y);
+ EXPECT_EQ(0, z);
+ x = y = z = 0;
+ EXPECT_FALSE(extract("1 ", record<' ', 2>(&x, &y, &z)));
+ EXPECT_EQ(1, x);
+ EXPECT_EQ(0, y);
+ EXPECT_EQ(0, z);
+ x = y = z = 0;
+ EXPECT_FALSE(extract("1", record<' ', 2>(&x, &y, &z)));
+ EXPECT_EQ(1, x);
+ EXPECT_EQ(0, y);
+ EXPECT_EQ(0, z);
+ x = y = z = 0;
+ EXPECT_FALSE(extract(" ", record<' ', 2>(&x, &y, &z)));
+ EXPECT_EQ(0, x);
+ EXPECT_EQ(0, y);
+ EXPECT_EQ(0, z);
+ x = y = z = 0;
+ EXPECT_FALSE(extract("", record<' ', 2>(&x, &y, &z)));
+ EXPECT_EQ(0, x);
+ EXPECT_EQ(0, y);
+ EXPECT_EQ(0, z);
+ x = y = z = 0;
+
+ EXPECT_FALSE(extract("1 2 3 4 ", record<' ', 1>(&x, &y, &z)));
+ EXPECT_EQ(1, x);
+ EXPECT_EQ(2, y);
+ EXPECT_EQ(3, z);
+ x = y = z = 0;
+ EXPECT_FALSE(extract("1 2 3 4", record<' ', 1>(&x, &y, &z)));
+ EXPECT_EQ(1, x);
+ EXPECT_EQ(2, y);
+ EXPECT_EQ(3, z);
+ x = y = z = 0;
+ EXPECT_TRUE(extract("1 2 3 ", record<' ', 1>(&x, &y, &z)));
+ EXPECT_EQ(1, x);
+ EXPECT_EQ(2, y);
+ EXPECT_EQ(3, z);
+ x = y = z = 0;
+ EXPECT_TRUE(extract("1 2 3", record<' ', 1>(&x, &y, &z)));
+ EXPECT_EQ(1, x);
+ EXPECT_EQ(2, y);
+ EXPECT_EQ(3, z);
+ x = y = z = 0;
+ EXPECT_TRUE(extract("1 2 ", record<' ', 1>(&x, &y, &z)));
+ EXPECT_EQ(1, x);
+ EXPECT_EQ(2, y);
+ EXPECT_EQ(0, z);
+ x = y = z = 0;
+ EXPECT_TRUE(extract("1 2", record<' ', 1>(&x, &y, &z)));
+ EXPECT_EQ(1, x);
+ EXPECT_EQ(2, y);
+ EXPECT_EQ(0, z);
+ x = y = z = 0;
+ EXPECT_TRUE(extract("1 ", record<' ', 1>(&x, &y, &z)));
+ EXPECT_EQ(1, x);
+ EXPECT_EQ(0, y);
+ EXPECT_EQ(0, z);
+ x = y = z = 0;
+ EXPECT_TRUE(extract("1", record<' ', 1>(&x, &y, &z)));
+ EXPECT_EQ(1, x);
+ EXPECT_EQ(0, y);
+ EXPECT_EQ(0, z);
+ x = y = z = 0;
+ EXPECT_FALSE(extract(" ", record<' ', 1>(&x, &y, &z)));
+ EXPECT_EQ(0, x);
+ EXPECT_EQ(0, y);
+ EXPECT_EQ(0, z);
+ x = y = z = 0;
+ EXPECT_FALSE(extract("", record<' ', 1>(&x, &y, &z)));
+ EXPECT_EQ(0, x);
+ EXPECT_EQ(0, y);
+ EXPECT_EQ(0, z);
+ x = y = z = 0;
+}
+
+TEST(extract, record_str)
+{
+ XString x, y, z;
+ x = y = z = "";
+ EXPECT_FALSE(extract("1 2 3 4 ", record<' '>(&x, &y, &z)));
+ EXPECT_EQ("1", x);
+ EXPECT_EQ("2", y);
+ EXPECT_EQ("3", z);
+ x = y = z = "";
+ EXPECT_FALSE(extract("1 2 3 4", record<' '>(&x, &y, &z)));
+ EXPECT_EQ("1", x);
+ EXPECT_EQ("2", y);
+ EXPECT_EQ("3", z);
+ x = y = z = "";
+ EXPECT_TRUE(extract("1 2 3 ", record<' '>(&x, &y, &z)));
+ EXPECT_EQ("1", x);
+ EXPECT_EQ("2", y);
+ EXPECT_EQ("3", z);
+ x = y = z = "";
+ EXPECT_TRUE(extract("1 2 3", record<' '>(&x, &y, &z)));
+ EXPECT_EQ("1", x);
+ EXPECT_EQ("2", y);
+ EXPECT_EQ("3", z);
+ x = y = z = "";
+ EXPECT_TRUE(extract("1 2 ", record<' '>(&x, &y, &z)));
+ EXPECT_EQ("1", x);
+ EXPECT_EQ("2", y);
+ EXPECT_EQ("", z);
+ x = y = z = "";
+ EXPECT_FALSE(extract("1 2", record<' '>(&x, &y, &z)));
+ EXPECT_EQ("1", x);
+ EXPECT_EQ("2", y);
+ EXPECT_EQ("", z);
+ x = y = z = "";
+ EXPECT_FALSE(extract("1 ", record<' '>(&x, &y, &z)));
+ EXPECT_EQ("1", x);
+ EXPECT_EQ("", y);
+ EXPECT_EQ("", z);
+ x = y = z = "";
+ EXPECT_FALSE(extract("1", record<' '>(&x, &y, &z)));
+ EXPECT_EQ("1", x);
+ EXPECT_EQ("", y);
+ EXPECT_EQ("", z);
+ x = y = z = "";
+ EXPECT_FALSE(extract(" ", record<' '>(&x, &y, &z)));
+ EXPECT_EQ("", x);
+ EXPECT_EQ("", y);
+ EXPECT_EQ("", z);
+ x = y = z = "";
+ EXPECT_FALSE(extract("", record<' '>(&x, &y, &z)));
+ EXPECT_EQ("", x);
+ EXPECT_EQ("", y);
+ EXPECT_EQ("", z);
+ x = y = z = "";
+
+ EXPECT_FALSE(extract("1 2 3 4 ", record<' ', 2>(&x, &y, &z)));
+ EXPECT_EQ("1", x);
+ EXPECT_EQ("2", y);
+ EXPECT_EQ("3", z);
+ x = y = z = "";
+ EXPECT_FALSE(extract("1 2 3 4", record<' ', 2>(&x, &y, &z)));
+ EXPECT_EQ("1", x);
+ EXPECT_EQ("2", y);
+ EXPECT_EQ("3", z);
+ x = y = z = "";
+ EXPECT_TRUE(extract("1 2 3 ", record<' ', 2>(&x, &y, &z)));
+ EXPECT_EQ("1", x);
+ EXPECT_EQ("2", y);
+ EXPECT_EQ("3", z);
+ x = y = z = "";
+ EXPECT_TRUE(extract("1 2 3", record<' ', 2>(&x, &y, &z)));
+ EXPECT_EQ("1", x);
+ EXPECT_EQ("2", y);
+ EXPECT_EQ("3", z);
+ x = y = z = "";
+ EXPECT_TRUE(extract("1 2 ", record<' ', 2>(&x, &y, &z)));
+ EXPECT_EQ("1", x);
+ EXPECT_EQ("2", y);
+ EXPECT_EQ("", z);
+ x = y = z = "";
+ EXPECT_TRUE(extract("1 2", record<' ', 2>(&x, &y, &z)));
+ EXPECT_EQ("1", x);
+ EXPECT_EQ("2", y);
+ EXPECT_EQ("", z);
+ x = y = z = "";
+ EXPECT_TRUE(extract("1 ", record<' ', 2>(&x, &y, &z)));
+ EXPECT_EQ("1", x);
+ EXPECT_EQ("", y);
+ EXPECT_EQ("", z);
+ x = y = z = "";
+ EXPECT_FALSE(extract("1", record<' ', 2>(&x, &y, &z)));
+ EXPECT_EQ("1", x);
+ EXPECT_EQ("", y);
+ EXPECT_EQ("", z);
+ x = y = z = "";
+ EXPECT_TRUE(extract(" ", record<' ', 2>(&x, &y, &z)));
+ EXPECT_EQ("", x);
+ EXPECT_EQ("", y);
+ EXPECT_EQ("", z);
+ x = y = z = "";
+ EXPECT_FALSE(extract("", record<' ', 2>(&x, &y, &z)));
+ EXPECT_EQ("", x);
+ EXPECT_EQ("", y);
+ EXPECT_EQ("", z);
+ x = y = z = "";
+
+ EXPECT_FALSE(extract("1 2 3 4 ", record<' ', 1>(&x, &y, &z)));
+ EXPECT_EQ("1", x);
+ EXPECT_EQ("2", y);
+ EXPECT_EQ("3", z);
+ x = y = z = "";
+ EXPECT_FALSE(extract("1 2 3 4", record<' ', 1>(&x, &y, &z)));
+ EXPECT_EQ("1", x);
+ EXPECT_EQ("2", y);
+ EXPECT_EQ("3", z);
+ x = y = z = "";
+ EXPECT_TRUE(extract("1 2 3 ", record<' ', 1>(&x, &y, &z)));
+ EXPECT_EQ("1", x);
+ EXPECT_EQ("2", y);
+ EXPECT_EQ("3", z);
+ x = y = z = "";
+ EXPECT_TRUE(extract("1 2 3", record<' ', 1>(&x, &y, &z)));
+ EXPECT_EQ("1", x);
+ EXPECT_EQ("2", y);
+ EXPECT_EQ("3", z);
+ x = y = z = "";
+ EXPECT_TRUE(extract("1 2 ", record<' ', 1>(&x, &y, &z)));
+ EXPECT_EQ("1", x);
+ EXPECT_EQ("2", y);
+ EXPECT_EQ("", z);
+ x = y = z = "";
+ EXPECT_TRUE(extract("1 2", record<' ', 1>(&x, &y, &z)));
+ EXPECT_EQ("1", x);
+ EXPECT_EQ("2", y);
+ EXPECT_EQ("", z);
+ x = y = z = "";
+ EXPECT_TRUE(extract("1 ", record<' ', 1>(&x, &y, &z)));
+ EXPECT_EQ("1", x);
+ EXPECT_EQ("", y);
+ EXPECT_EQ("", z);
+ x = y = z = "";
+ EXPECT_TRUE(extract("1", record<' ', 1>(&x, &y, &z)));
+ EXPECT_EQ("1", x);
+ EXPECT_EQ("", y);
+ EXPECT_EQ("", z);
+ x = y = z = "";
+ EXPECT_TRUE(extract(" ", record<' ', 1>(&x, &y, &z)));
+ EXPECT_EQ("", x);
+ EXPECT_EQ("", y);
+ EXPECT_EQ("", z);
+ x = y = z = "";
+ EXPECT_TRUE(extract("", record<' ', 1>(&x, &y, &z)));
+ EXPECT_EQ("", x);
+ EXPECT_EQ("", y);
+ EXPECT_EQ("", z);
+ x = y = z = "";
+}
diff --git a/src/common/human_time_diff.hpp b/src/common/human_time_diff.hpp
new file mode 100644
index 0000000..3fc0f09
--- /dev/null
+++ b/src/common/human_time_diff.hpp
@@ -0,0 +1,85 @@
+#ifndef TMWA_COMMON_HUMAN_TIME_DIFF_HPP
+#define TMWA_COMMON_HUMAN_TIME_DIFF_HPP
+// human_time_diff.hpp - broken deltas
+//
+// Copyright © 2013 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 "extract.hpp"
+#include "strings.hpp"
+
+struct HumanTimeDiff
+{
+ short year, month, day, hour, minute, second;
+
+ explicit
+ operator bool()
+ {
+ return year || month || day || hour || minute || second;
+ }
+
+ bool operator !()
+ {
+ return !bool(*this);
+ }
+};
+
+inline
+bool extract(XString str, HumanTimeDiff *iv)
+{
+ // str is a sequence of [-+]?[0-9]+([ay]|m|[jd]|h|mn|s)
+ // there are NO spaces here
+ // parse by counting the number starts
+ auto is_num = [](char c)
+ { return c == '-' || c == '+' || ('0' <= c && c <= '9'); };
+ if (!str || !is_num(str.front()))
+ return false;
+ *iv = HumanTimeDiff{};
+ while (str)
+ {
+ auto it = std::find_if_not(str.begin(), str.end(), is_num);
+ auto it2 = std::find_if(it, str.end(), is_num);
+ XString number = str.xislice_h(it);
+ XString suffix = str.xislice(it, it2);
+ str = str.xislice_t(it2);
+
+ short *ptr = nullptr;
+ if (suffix == "y" || suffix == "a")
+ ptr = &iv->year;
+ else if (suffix == "m")
+ ptr = &iv->month;
+ else if (suffix == "j" || suffix == "d")
+ ptr = &iv->day;
+ else if (suffix == "h")
+ ptr = &iv->hour;
+ else if (suffix == "mn")
+ ptr = &iv->minute;
+ else if (suffix == "s")
+ ptr = &iv->second;
+ else
+ return false;
+ if (number.startswith('+') && !number.startswith("+-"))
+ number = number.xslice_t(1);
+ if (*ptr || !extract(number, ptr))
+ return false;
+ }
+ return true;
+}
+
+#endif // TMWA_COMMON_HUMAN_TIME_DIFF_HPP
diff --git a/src/common/human_time_diff_test.cpp b/src/common/human_time_diff_test.cpp
new file mode 100644
index 0000000..d11a116
--- /dev/null
+++ b/src/common/human_time_diff_test.cpp
@@ -0,0 +1,84 @@
+#include "human_time_diff.hpp"
+
+#include <gtest/gtest.h>
+
+// a sequence of [-+]?[0-9]+([ay]|m|[jd]|h|mn|s)
+
+TEST(humantimediff, single)
+{
+ HumanTimeDiff diff;
+
+ EXPECT_TRUE(extract("42y", &diff));
+ EXPECT_EQ(42, diff.year);
+ EXPECT_EQ(0, diff.month);
+ EXPECT_EQ(0, diff.day);
+ EXPECT_EQ(0, diff.hour);
+ EXPECT_EQ(0, diff.minute);
+ EXPECT_EQ(0, diff.second);
+
+ EXPECT_TRUE(extract("42m", &diff));
+ EXPECT_EQ(0, diff.year);
+ EXPECT_EQ(42, diff.month);
+ EXPECT_EQ(0, diff.day);
+ EXPECT_EQ(0, diff.hour);
+ EXPECT_EQ(0, diff.minute);
+ EXPECT_EQ(0, diff.second);
+
+ EXPECT_TRUE(extract("42d", &diff));
+ EXPECT_EQ(0, diff.year);
+ EXPECT_EQ(0, diff.month);
+ EXPECT_EQ(42, diff.day);
+ EXPECT_EQ(0, diff.hour);
+ EXPECT_EQ(0, diff.minute);
+ EXPECT_EQ(0, diff.second);
+
+ EXPECT_TRUE(extract("42h", &diff));
+ EXPECT_EQ(0, diff.year);
+ EXPECT_EQ(0, diff.month);
+ EXPECT_EQ(0, diff.day);
+ EXPECT_EQ(42, diff.hour);
+ EXPECT_EQ(0, diff.minute);
+ EXPECT_EQ(0, diff.second);
+
+ EXPECT_TRUE(extract("42mn", &diff));
+ EXPECT_EQ(0, diff.year);
+ EXPECT_EQ(0, diff.month);
+ EXPECT_EQ(0, diff.day);
+ EXPECT_EQ(0, diff.hour);
+ EXPECT_EQ(42, diff.minute);
+ EXPECT_EQ(0, diff.second);
+
+ EXPECT_TRUE(extract("42s", &diff));
+ EXPECT_EQ(0, diff.year);
+ EXPECT_EQ(0, diff.month);
+ EXPECT_EQ(0, diff.day);
+ EXPECT_EQ(0, diff.hour);
+ EXPECT_EQ(0, diff.minute);
+ EXPECT_EQ(42, diff.second);
+
+ EXPECT_TRUE(extract("+42y", &diff));
+ EXPECT_EQ(42, diff.year);
+ EXPECT_TRUE(extract("-42y", &diff));
+ EXPECT_EQ(-42, diff.year);
+ EXPECT_FALSE(extract("++42y", &diff));
+ EXPECT_FALSE(extract("+-42y", &diff));
+ EXPECT_FALSE(extract("-+42y", &diff));
+ EXPECT_FALSE(extract("--42y", &diff));
+ EXPECT_FALSE(extract("4+2y", &diff));
+ EXPECT_FALSE(extract("42z", &diff));
+}
+
+TEST(humantimediff, multiple)
+{
+ HumanTimeDiff diff;
+
+ EXPECT_TRUE(extract("42y23m-2d", &diff));
+ EXPECT_EQ(42, diff.year);
+ EXPECT_EQ(23, diff.month);
+ EXPECT_EQ(-2, diff.day);
+ EXPECT_EQ(0, diff.hour);
+ EXPECT_EQ(0, diff.minute);
+ EXPECT_EQ(0, diff.second);
+ EXPECT_FALSE(extract("1y2y", &diff));
+}
+
diff --git a/src/common/intern-pool.hpp b/src/common/intern-pool.hpp
index caa54e4..db840a2 100644
--- a/src/common/intern-pool.hpp
+++ b/src/common/intern-pool.hpp
@@ -4,16 +4,19 @@
#include <cassert>
#include <map>
-#include <string>
#include <vector>
+#include "strings.hpp"
+
class InternPool
{
- std::map<std::string, size_t> known;
- std::vector<std::string> names;
+ std::map<FString, size_t> known;
+ std::vector<FString> names;
public:
- size_t intern(const std::string& name)
+ size_t intern(XString name_)
{
+ FString name = name_;
+ // hm, I could change this to do aliases
auto pair = known.insert({name, known.size()});
if (pair.second)
names.push_back(name);
@@ -21,7 +24,7 @@ public:
return pair.first->second;
}
- const std::string& outtern(size_t sz) const
+ ZString outtern(size_t sz) const
{
return names[sz];
}
diff --git a/src/common/intern-pool_test.cpp b/src/common/intern-pool_test.cpp
new file mode 100644
index 0000000..3bbca7b
--- /dev/null
+++ b/src/common/intern-pool_test.cpp
@@ -0,0 +1,18 @@
+#include "intern-pool.hpp"
+
+#include <gtest/gtest.h>
+
+TEST(InternPool, whydoesthisalwaysneedasecondname)
+{
+ InternPool p;
+ EXPECT_EQ(0, p.size());
+ EXPECT_EQ(0, p.intern("hello"));
+ EXPECT_EQ(0, p.intern("hello"));
+ EXPECT_EQ(1, p.size());
+ EXPECT_EQ(1, p.intern("world"));
+ EXPECT_EQ(0, p.intern("hello"));
+ EXPECT_EQ(1, p.intern("world"));
+ EXPECT_EQ(2, p.size());
+ EXPECT_EQ("hello", p.outtern(0));
+ EXPECT_EQ("world", p.outtern(1));
+}
diff --git a/src/common/io.hpp b/src/common/io.hpp
new file mode 100644
index 0000000..1831651
--- /dev/null
+++ b/src/common/io.hpp
@@ -0,0 +1,26 @@
+#ifndef TMWA_COMMON_IO_HPP
+#define TMWA_COMMON_IO_HPP
+
+#include <istream>
+#include <ostream>
+
+#include "strings.hpp"
+
+namespace io
+{
+ inline
+ std::istream& getline(std::istream& in, FString& line)
+ {
+ std::string s;
+ if (std::getline(in, s))
+ {
+ std::string::const_iterator begin = s.cbegin(), end = s.cend();
+ if (begin != end && end[-1] == '\r')
+ --end;
+ line = FString(begin, end);
+ }
+ return in;
+ }
+} // namespace io
+
+#endif //TMWA_COMMON_IO_HPP
diff --git a/src/common/lock.cpp b/src/common/lock.cpp
index 82856e1..f19cd92 100644
--- a/src/common/lock.cpp
+++ b/src/common/lock.cpp
@@ -17,17 +17,17 @@ const int backup_count = 10;
/// (Until the file is closed, it keeps the old file)
// Start writing a tmpfile
-FILE *lock_fopen(const char *filename, int *info)
+FILE *lock_fopen(ZString filename, int *info)
{
FILE *fp;
int no = getpid();
// Get a filename that doesn't already exist
- std::string newfile;
+ FString newfile;
do
{
newfile = STRPRINTF("%s_%d.tmp", filename, no++);
- fp = fopen_(newfile.c_str(), "wx");
+ fp = fopen(newfile.c_str(), "wx");
}
while (!fp);
*info = --no;
@@ -35,22 +35,22 @@ FILE *lock_fopen(const char *filename, int *info)
}
// Delete the old file and rename the new file
-void lock_fclose(FILE *fp, const char *filename, int *info)
+void lock_fclose(FILE *fp, ZString filename, int *info)
{
if (fp)
{
- fclose_(fp);
+ fclose(fp);
int n = backup_count;
- std::string old_filename = STRPRINTF("%s.%d", filename, n);
+ FString old_filename = STRPRINTF("%s.%d", filename, n);
while (--n)
{
- std::string newer_filename = STRPRINTF("%s.%d", filename, n);
+ FString newer_filename = STRPRINTF("%s.%d", filename, n);
rename(newer_filename.c_str(), old_filename.c_str());
old_filename = std::move(newer_filename);
}
- rename(filename, old_filename.c_str());
+ rename(filename.c_str(), old_filename.c_str());
- std::string tmpfile = STRPRINTF("%s_%d.tmp", filename, *info);
- rename(tmpfile.c_str(), filename);
+ FString tmpfile = STRPRINTF("%s_%d.tmp", filename, *info);
+ rename(tmpfile.c_str(), filename.c_str());
}
}
diff --git a/src/common/lock.hpp b/src/common/lock.hpp
index f7ce2d8..df4d1f8 100644
--- a/src/common/lock.hpp
+++ b/src/common/lock.hpp
@@ -5,11 +5,13 @@
#include <cstdio>
+#include "strings.hpp"
+
// TODO replace with a class
/// Locked FILE I/O
// Changes are made in a separate file until lock_fclose
-FILE *lock_fopen(const char *filename, int *info);
-void lock_fclose(FILE * fp, const char *filename, int *info);
+FILE *lock_fopen(ZString filename, int *info);
+void lock_fclose(FILE *fp, ZString filename, int *info);
#endif // LOCK_HPP
diff --git a/src/common/md5calc.cpp b/src/common/md5calc.cpp
index 582c152..ae134b7 100644
--- a/src/common/md5calc.cpp
+++ b/src/common/md5calc.cpp
@@ -2,6 +2,7 @@
#include <cstring>
+#include "cxxstdio.hpp"
#include "random.hpp"
#include "utils.hpp"
@@ -171,7 +172,7 @@ void MD5_do_block(MD5_state* state, MD5_block block)
#undef d
}
-void MD5_to_bin(MD5_state state, uint8_t out[0x10])
+void MD5_to_bin(MD5_state state, md5_binary& out)
{
for (int i = 0; i < 0x10; i++)
out[i] = state.val[i / 4] >> 8 * (i % 4);
@@ -180,47 +181,47 @@ void MD5_to_bin(MD5_state state, uint8_t out[0x10])
static
const char hex[] = "0123456789abcdef";
-void MD5_to_str(MD5_state state, char out[0x21])
+void MD5_to_str(MD5_state state, md5_string& out_)
{
- uint8_t bin[16];
+ md5_binary bin;
MD5_to_bin(state, bin);
+ char out[0x20];
for (int i = 0; i < 0x10; i++)
out[2 * i] = hex[bin[i] >> 4],
out[2 * i + 1] = hex[bin[i] & 0xf];
- out[0x20] = '\0';
+ out_ = stringish<md5_string>(XString(out, out + 0x20, nullptr));
}
-MD5_state MD5_from_string(const char* msg, const size_t msglen)
+MD5_state MD5_from_string(XString msg)
{
MD5_state state;
MD5_init(&state);
MD5_block block;
- size_t rem = msglen;
- while (rem >= 64)
+ const uint64_t msg_full_len = msg.size();
+ while (msg.size() >= 64)
{
for (int i = 0; i < 0x10; i++)
X[i] = msg[4 * i + 0] | msg[4 * i + 1] << 8 | msg[4 * i + 2] << 16 | msg[4 * i + 3] << 24;
MD5_do_block(&state, block);
- msg += 64;
- rem -= 64;
+ msg = msg.xslice_t(64);
}
// now pad 1-512 bits + the 64-bit length - may be two blocks
uint8_t buf[0x40] = {};
- really_memcpy(buf, reinterpret_cast<const uint8_t *>(msg), rem);
- buf[rem] = 0x80; // a single one bit
- if (64 - rem > 8)
+ really_memcpy(buf, reinterpret_cast<const uint8_t *>(msg.data()), msg.size());
+ buf[msg.size()] = 0x80; // a single one bit
+ if (64 - msg.size() > 8)
{
for (int i = 0; i < 8; i++)
- buf[0x38 + i] = (static_cast<uint64_t>(msglen) * 8) >> (i * 8);
+ buf[0x38 + i] = (msg_full_len * 8) >> (i * 8);
}
for (int i = 0; i < 0x10; i++)
X[i] = buf[4 * i + 0] | buf[4 * i + 1] << 8 | buf[4 * i + 2] << 16 | buf[4 * i + 3] << 24;
MD5_do_block(&state, block);
- if (64 - rem <= 8)
+ if (64 - msg.size() <= 8)
{
really_memset0(buf, 0x38);
for (int i = 0; i < 8; i++)
- buf[0x38 + i] = (static_cast<uint64_t>(msglen) * 8) >> (i * 8);
+ buf[0x38 + i] = (msg_full_len * 8) >> (i * 8);
for (int i = 0; i < 0x10; i++)
X[i] = buf[4 * i + 0] | buf[4 * i + 1] << 8 | buf[4 * i + 2] << 16 | buf[4 * i + 3] << 24;
MD5_do_block(&state, block);
@@ -228,12 +229,8 @@ MD5_state MD5_from_string(const char* msg, const size_t msglen)
return state;
}
-// This could be reimplemented without the strlen()
-MD5_state MD5_from_cstring(const char* msg)
-{
- return MD5_from_string(msg, strlen(msg));
-}
-
+// TODO - refactor MD5 into a stream, and merge the implementations
+// I once implemented an ostream that does it ...
MD5_state MD5_from_FILE(FILE* in)
{
uint64_t total_len = 0;
@@ -286,50 +283,53 @@ MD5_state MD5_from_FILE(FILE* in)
// Hash a password with a salt.
// Whoever wrote this FAILS programming
-const char *MD5_saltcrypt(const char *key, const char *salt)
+AccountCrypt MD5_saltcrypt(AccountPass key, SaltString salt)
{
- char buf[65];
+ char cbuf[64] {};
// hash the key then the salt
// buf ends up as a 64-char NUL-terminated string
- MD5_to_str(MD5_from_cstring(key), buf);
- MD5_to_str(MD5_from_cstring(salt), buf + 32);
+ md5_string tbuf, tbuf2;
+ MD5_to_str(MD5_from_string(key), tbuf);
+ MD5_to_str(MD5_from_string(salt), tbuf2);
+ const auto it = std::copy(tbuf.begin(), tbuf.end(), std::begin(cbuf));
+ auto it2 = std::copy(tbuf2.begin(), tbuf2.end(), it);
+ assert(it2 == std::end(cbuf));
+
+ md5_string tbuf3;
+ MD5_to_str(MD5_from_string(XString(std::begin(cbuf), it2, nullptr)), tbuf3);
- // Hash the buffer back into sbuf - this is stupid
- // (luckily, putting the result into itself is safe)
- MD5_to_str(MD5_from_cstring(buf), buf + 32);
+ VString<31> obuf;
- static char obuf[33];
// This truncates the string, but we have to keep it like that for compatibility
- snprintf(obuf, 32, "!%s$%s", salt, buf + 32);
- return obuf;
+ SNPRINTF(obuf, 32, "!%s$%s", salt, tbuf3);
+ return stringish<AccountCrypt>(obuf);
}
-const char *make_salt(void)
+SaltString make_salt(void)
{
- static char salt[6];
+ char salt[5];
for (int i = 0; i < 5; i++)
// 126 would probably actually be okay
salt[i] = random_::in(48, 125);
- return salt;
+ return stringish<SaltString>(XString(salt + 0, salt + 5, nullptr));
}
-bool pass_ok(const char *password, const char *crypted)
+bool pass_ok(AccountPass password, AccountCrypt crypted)
{
- char buf[40];
- strzcpy(buf, crypted, 40);
// crypted is like !salt$hash
- char *salt = buf + 1;
- *strchr(salt, '$') = '\0';
+ auto begin = crypted.begin() + 1;
+ auto end = std::find(begin, crypted.end(), '$');
+ SaltString salt = stringish<SaltString>(crypted.xislice(begin, end));
- return !strcmp(crypted, MD5_saltcrypt(password, salt));
+ return crypted == MD5_saltcrypt(password, salt);
}
// [M|h]ashes up an IP address and a secret key
// to return a hopefully unique masked IP.
-struct in_addr MD5_ip(char *secret, struct in_addr ip)
+struct in_addr MD5_ip(struct in_addr ip)
{
- uint8_t obuf[16];
+ static SaltString secret = make_salt();
union
{
uint8_t bytes[4];
@@ -337,10 +337,10 @@ struct in_addr MD5_ip(char *secret, struct in_addr ip)
} conv;
// MD5sum a secret + the IP address
- char ipbuf[32] {};
- snprintf(ipbuf, sizeof(ipbuf), "%u%s", ip.s_addr, secret);
- /// TODO stop it from being a cstring
- MD5_to_bin(MD5_from_cstring(ipbuf), obuf);
+ VString<31> ipbuf;
+ SNPRINTF(ipbuf, 32, "%u%s", ip.s_addr, secret);
+ md5_binary obuf;
+ MD5_to_bin(MD5_from_string(ipbuf), obuf);
// Fold the md5sum to 32 bits, pack the bytes to an in_addr
conv.bytes[0] = obuf[0] ^ obuf[1] ^ obuf[8] ^ obuf[9];
diff --git a/src/common/md5calc.hpp b/src/common/md5calc.hpp
index de19e0f..98f44d6 100644
--- a/src/common/md5calc.hpp
+++ b/src/common/md5calc.hpp
@@ -9,44 +9,51 @@
#include <cstddef>
#include <cstdio>
+#include <array>
+
+#include "mmo.hpp"
+#include "strings.hpp"
+
/// The digest state - becomes the output
-typedef struct
+struct MD5_state
{
// classically named {A,B,C,D}
// but use an so we can index
uint32_t val[4];
-} MD5_state;
-typedef struct
+};
+struct MD5_block
{
uint32_t data[16];
-} MD5_block;
+};
+
+struct md5_binary : std::array<uint8_t, 0x10> {};
+struct md5_string : VString<0x20> {};
+struct SaltString : VString<5> {};
// Implementation
-void MD5_init(MD5_state* state);
-void MD5_do_block(MD5_state* state, MD5_block block);
+void MD5_init(MD5_state *state);
+void MD5_do_block(MD5_state *state, MD5_block block);
// Output formatting
-void MD5_to_bin(MD5_state state, uint8_t out[0x10]);
-void MD5_to_str(MD5_state state, char out[0x21]);
+void MD5_to_bin(MD5_state state, md5_binary& out);
+void MD5_to_str(MD5_state state, md5_string& out);
// Convenience
-MD5_state MD5_from_string(const char* msg, const size_t msglen);
-MD5_state MD5_from_cstring(const char* msg);
+MD5_state MD5_from_string(XString msg);
MD5_state MD5_from_FILE(FILE* in);
-// statically-allocated output
// whoever wrote this fails basic understanding of
-const char *MD5_saltcrypt(const char *key, const char *salt);
+AccountCrypt MD5_saltcrypt(AccountPass key, SaltString salt);
/// return some random characters (statically allocated)
// Currently, returns a 5-char string
-const char *make_salt(void);
+SaltString make_salt(void);
/// check plaintext password against saved saltcrypt
-bool pass_ok(const char *password, const char *crypted);
+bool pass_ok(AccountPass password, AccountCrypt crypted);
/// This returns an in_addr because it is configurable whether it gets called at all
-struct in_addr MD5_ip(char *secret, struct in_addr ip);
+struct in_addr MD5_ip(struct in_addr ip);
#endif // MD5CALC_HPP
diff --git a/src/common/md5calc_test.cpp b/src/common/md5calc_test.cpp
new file mode 100644
index 0000000..51b0b68
--- /dev/null
+++ b/src/common/md5calc_test.cpp
@@ -0,0 +1,27 @@
+#include "md5calc.hpp"
+
+#include <gtest/gtest.h>
+
+#include "utils.hpp"
+
+// This should be made part of the main API,
+// but is not yet to keep the diff small.
+// Edit: hack to fix the new strict comparison.
+static
+VString<32> MD5(XString in)
+{
+ md5_string out;
+ MD5_to_str(MD5_from_string(in), out);
+ return out;
+}
+
+TEST(md5calc, rfc1321)
+{
+ EXPECT_EQ("d41d8cd98f00b204e9800998ecf8427e", MD5(""));
+ EXPECT_EQ("0cc175b9c0f1b6a831c399e269772661", MD5("a"));
+ EXPECT_EQ("900150983cd24fb0d6963f7d28e17f72", MD5("abc"));
+ EXPECT_EQ("f96b697d7cb7938d525a2f31aaf161d0", MD5("message digest"));
+ EXPECT_EQ("c3fcd3d76192e4007dfb496cca67e13b", MD5("abcdefghijklmnopqrstuvwxyz"));
+ EXPECT_EQ("d174ab98d277d9f5a5611c2c9f419d9f", MD5("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"));
+ EXPECT_EQ("57edf4a22be3c955ac49da2e2107b67a", MD5("12345678901234567890123456789012345678901234567890123456789012345678901234567890"));
+}
diff --git a/src/common/mmo.hpp b/src/common/mmo.hpp
index 450aa61..89ff50a 100644
--- a/src/common/mmo.hpp
+++ b/src/common/mmo.hpp
@@ -4,7 +4,10 @@
# include "sanity.hpp"
# include "timer.t.hpp"
-# include "utils.hpp"
+# include "utils2.hpp"
+
+// affects CharName
+# define NAME_IGNORING_CASE 1
constexpr int FIFOSIZE_SERVERLINK = 256 * 1024;
@@ -37,6 +40,105 @@ constexpr int MAX_PARTY = 12;
# define CHAR_CONF_NAME "conf/char_athena.conf"
+struct AccountName : VString<23> {};
+struct AccountPass : VString<23> {};
+struct AccountCrypt : VString<39> {};
+struct AccountEmail : VString<39> {};
+struct ServerName : VString<19> {};
+struct PartyName : VString<23> {};
+struct VarName : VString<31> {};
+template<class T>
+T stringish(VString<sizeof(T) - 1> iv)
+{
+ T rv;
+ static_cast<VString<sizeof(T) - 1>&>(rv) = iv;
+ return rv;
+}
+#define DEFAULT_EMAIL stringish<AccountEmail>("a@a.com")
+
+// It is decreed: a mapname shall not contain an extension
+class MapName : public strings::_crtp_string<MapName, MapName, ZString, XString>
+{
+ VString<15> _impl;
+public:
+ MapName() = default;
+ MapName(VString<15> v) : _impl(v.oislice_h(std::find(v.begin(), v.end(), '.'))) {}
+
+ iterator begin() const { return &*_impl.begin(); }
+ iterator end() const { return &*_impl.begin(); }
+ const char *c_str() const { return _impl.c_str(); }
+
+ operator FString() const { return _impl; }
+ operator TString() const { return _impl; }
+ operator SString() const { return _impl; }
+ operator ZString() const { return _impl; }
+ operator XString() const { return _impl; }
+};
+template<>
+inline
+MapName stringish<MapName>(VString<15> iv)
+{
+ return iv;
+}
+inline
+const char *decay_for_printf(const MapName& vs) { return vs.c_str(); }
+
+// It is decreed: a charname is sometimes case sensitive
+struct CharName
+{
+private:
+ VString<23> _impl;
+public:
+ CharName() = default;
+ explicit CharName(VString<23> name)
+ : _impl(name)
+ {}
+
+ VString<23> to__actual() const
+ {
+ return _impl;
+ }
+ VString<23> to__lower() const
+ {
+ return _impl.to_lower();
+ }
+ VString<23> to__upper() const
+ {
+ return _impl.to_upper();
+ }
+ VString<23> to__canonical() const
+ {
+#if NAME_IGNORING_CASE == 0
+ return to__actual();
+#endif
+#if NAME_IGNORING_CASE == 1
+ return to__lower();
+#endif
+ }
+
+ friend bool operator == (const CharName& l, const CharName& r)
+ { return l.to__canonical() == r.to__canonical(); }
+ friend bool operator != (const CharName& l, const CharName& r)
+ { return l.to__canonical() != r.to__canonical(); }
+ friend bool operator < (const CharName& l, const CharName& r)
+ { return l.to__canonical() < r.to__canonical(); }
+ friend bool operator <= (const CharName& l, const CharName& r)
+ { return l.to__canonical() <= r.to__canonical(); }
+ friend bool operator > (const CharName& l, const CharName& r)
+ { return l.to__canonical() > r.to__canonical(); }
+ friend bool operator >= (const CharName& l, const CharName& r)
+ { return l.to__canonical() >= r.to__canonical(); }
+
+ friend
+ VString<23> convert_for_printf(const CharName& vs) { return vs.to__actual(); }
+};
+template<>
+inline
+CharName stringish<CharName>(VString<23> iv)
+{
+ return CharName(iv);
+}
+
namespace e
{
enum class EPOS : uint16_t
@@ -78,7 +180,7 @@ struct item
struct point
{
- char map_[16];
+ MapName map_;
short x, y;
};
@@ -105,7 +207,7 @@ struct skill_value
struct global_reg
{
- char str[32];
+ VarName str;
int value;
};
@@ -182,7 +284,7 @@ struct mmo_charstatus
short shield;
short head_top, head_mid, head_bottom;
- char name[24];
+ CharName name;
unsigned char base_level, job_level;
earray<short, ATTR, ATTR::COUNT> attrs;
unsigned char char_num, sex;
@@ -221,7 +323,8 @@ struct GM_Account
struct party_member
{
int account_id;
- char name[24], map[24];
+ CharName name;
+ MapName map;
int leader, online, lv;
struct map_session_data *sd;
};
@@ -229,16 +332,10 @@ struct party_member
struct party
{
int party_id;
- char name[24];
+ PartyName name;
int exp;
int item;
struct party_member member[MAX_PARTY];
};
-struct square
-{
- int val1[5];
- int val2[5];
-};
-
#endif // MMO_HPP
diff --git a/src/common/sanity.hpp b/src/common/sanity.hpp
index 74e24df..3658f9f 100644
--- a/src/common/sanity.hpp
+++ b/src/common/sanity.hpp
@@ -22,29 +22,6 @@
# if __GNUC_MINOR__ < 6 && !defined(__clang__)
# error "Please upgrade to at least GCC 4.6"
# endif // __GNUC_MINOR__ < 6 && !defined(__clang__)
-// temporary workaround for library issues
-// since __GLIBCXX__ is hard to use
-# if __GNUC_MINOR__ == 6
-# define WORKAROUND_GCC46_COMPILER
-# endif // __GNUC_MINOR__ == 6
-# ifdef __GLIBCXX__
-// versions of libstdc++ from gcc
-// 4.6.0, 4.6.1, 4.6.2, 4.6.3, 4.6.4
-# if __GLIBCXX__ == 20110325 \
- || __GLIBCXX__ == 20110627 \
- || __GLIBCXX__ == 20111026 \
- || __GLIBCXX__ == 20120301 \
- || __GLIBCXX__ == 20130412 \
- /* various Debian snapshots */ \
- || __GLIBCXX__ == 20121127 \
- || __GLIBCXX__ == 20130114
-# define WORKAROUND_GCC46_LIBRARY
-# endif // __GLIBCXX__ == ...
-# endif // defined __GLIBCXX__
-# if defined(WORKAROUND_GCC46_COMPILER) \
- && !defined(WORKAROUND_GCC46_LIBRARY)
-# error "Unknown gcc 4.6.x release"
-# endif // compiler and not library
# endif // __GNUC__ == 4
# if not defined(__i386__) and not defined(__x86_64__)
diff --git a/src/common/socket.cpp b/src/common/socket.cpp
index 214fb5a..2d08171 100644
--- a/src/common/socket.cpp
+++ b/src/common/socket.cpp
@@ -21,8 +21,6 @@
static
fd_set readfds;
int fd_max;
-static
-int currentuse;
static
const uint32_t RFIFO_SIZE = 65536;
@@ -128,16 +126,17 @@ void connect_client(int listen_fd)
perror("accept");
return;
}
- if (fd_max <= fd)
- {
- fd_max = fd + 1;
- }
- if (!free_fds())
+ if (fd >= SOFT_LIMIT)
{
FPRINTF(stderr, "softlimit reached, disconnecting : %d\n", fd);
- delete_session(fd);
+ shutdown(fd, SHUT_RDWR);
+ close(fd);
return;
}
+ if (fd_max <= fd)
+ {
+ fd_max = fd + 1;
+ }
const int yes = 1;
/// Allow to bind() again after the server restarts.
@@ -178,8 +177,6 @@ void connect_client(int listen_fd)
session[fd]->client_addr = client_address;
session[fd]->created = TimeT::now();
session[fd]->connected = 0;
-
- currentuse++;
}
int make_listen_port(uint16_t port)
@@ -237,7 +234,6 @@ int make_listen_port(uint16_t port)
session[fd]->created = TimeT::now();
session[fd]->connected = 1;
- currentuse++;
return fd;
}
@@ -295,7 +291,6 @@ int make_connection(uint32_t ip, uint16_t port)
session[fd]->created = TimeT::now();
session[fd]->connected = 1;
- currentuse++;
return fd;
}
@@ -326,13 +321,6 @@ void delete_session(int fd)
// just close() would try to keep sending buffers
shutdown(fd, SHUT_RDWR);
close(fd);
- currentuse--;
- if (currentuse < 0)
- {
- FPRINTF(stderr, "delete_session: current sessions negative!\n");
- currentuse = 0;
- }
- return;
}
void realloc_fifo(int fd, size_t rfifo_size, size_t wfifo_size)
@@ -446,7 +434,6 @@ void do_socket(void)
#pragma GCC diagnostic ignored "-Wold-style-cast"
FD_ZERO(&readfds);
#pragma GCC diagnostic pop
- currentuse = 3;
}
void RFIFOSKIP(int fd, size_t len)
@@ -460,23 +447,3 @@ void RFIFOSKIP(int fd, size_t len)
abort();
}
}
-
-void fclose_(FILE * fp)
-{
- if (fclose(fp))
- perror("fclose"), abort();
- currentuse--;
-}
-
-FILE *fopen_(const char *path, const char *mode)
-{
- FILE *f = fopen(path, mode);
- if (f)
- currentuse++;
- return f;
-}
-
-bool free_fds(void)
-{
- return currentuse < SOFT_LIMIT;
-}
diff --git a/src/common/socket.hpp b/src/common/socket.hpp
index 2366373..dd1c872 100644
--- a/src/common/socket.hpp
+++ b/src/common/socket.hpp
@@ -96,12 +96,6 @@ void do_socket(void);
// themselves as servers
void set_defaultparse(void(*defaultparse)(int));
-/// Wrappers to track number of free FDs
-void fclose_(FILE * fp);
-FILE *fopen_(const char *path, const char *mode);
-
-bool free_fds(void);
-
template<class T>
uint8_t *pod_addressof_m(T& structure)
{
@@ -149,10 +143,22 @@ void RFIFO_STRUCT(int fd, size_t pos, T& structure)
{
really_memcpy(pod_addressof_m(structure), static_cast<const uint8_t *>(RFIFOP(fd, pos)), sizeof(T));
}
+template<uint8_t len>
+inline
+VString<len-1> RFIFO_STRING(int fd, size_t pos)
+{
+ const char *const begin = static_cast<const char *>(RFIFOP(fd, pos));
+ const char *const end = begin + len-1;
+ const char *const mid = std::find(begin, end, '\0');
+ return XString(begin, mid, nullptr);
+}
inline
-void RFIFO_STRING(int fd, size_t pos, char *out, size_t len)
+FString RFIFO_STRING(int fd, size_t pos, size_t len)
{
- strzcpy(out, static_cast<const char *>(RFIFOP(fd, pos)), len);
+ const char *const begin = static_cast<const char *>(RFIFOP(fd, pos));
+ const char *const end = begin + len;
+ const char *const mid = std::find(begin, end, '\0');
+ return XString(begin, mid, nullptr);
}
inline
void RFIFO_BUF_CLONE(int fd, uint8_t *buf, size_t len)
@@ -189,14 +195,27 @@ void RBUF_STRUCT(const uint8_t *p, size_t pos, T& structure)
{
really_memcpy(pod_addressof_m(structure), p + pos, sizeof(T));
}
+template<uint8_t len>
+inline
+VString<len-1> RBUF_STRING(const uint8_t *p, size_t pos)
+{
+ const char *const begin = static_cast<const char *>(RBUFP(p, pos));
+ const char *const end = begin + len-1;
+ const char *const mid = std::find(begin, end, '\0');
+ return XString(begin, mid, nullptr);
+}
inline
-void RBUF_STRING(const uint8_t *p, size_t pos, char *out, size_t len)
+FString RBUF_STRING(const uint8_t *p, size_t pos, size_t len)
{
- strzcpy(out, static_cast<const char *>(RBUFP(p, pos)), len);
+ const char *const begin = static_cast<const char *>(RBUFP(p, pos));
+ const char *const end = begin + len;
+ const char *const mid = std::find(begin, end, '\0');
+ return XString(begin, mid, nullptr);
}
/// Unused - check how much data can be written
+// the existence of this seems scary
inline
size_t WFIFOSPACE(int fd)
{
@@ -229,9 +248,12 @@ void WFIFO_STRUCT(int fd, size_t pos, T& structure)
really_memcpy(static_cast<uint8_t *>(WFIFOP(fd, pos)), pod_addressof_c(structure), sizeof(T));
}
inline
-void WFIFO_STRING(int fd, size_t pos, const char *s, size_t len)
+void WFIFO_STRING(int fd, size_t pos, XString s, size_t len)
{
- strzcpy(static_cast<char *>(WFIFOP(fd, pos)), s, len);
+ char *const begin = static_cast<char *>(WFIFOP(fd, pos));
+ char *const end = begin + len;
+ char *const mid = std::copy(s.begin(), s.end(), begin);
+ std::fill(mid, end, '\0');
}
inline
void WFIFO_ZERO(int fd, size_t pos, size_t len)
@@ -276,9 +298,12 @@ void WBUF_STRUCT(uint8_t *p, size_t pos, T& structure)
really_memcpy(p + pos, pod_addressof_c(structure), sizeof(T));
}
inline
-void WBUF_STRING(uint8_t *p, size_t pos, const char *s, size_t len)
+void WBUF_STRING(uint8_t *p, size_t pos, XString s, size_t len)
{
- strzcpy(static_cast<char *>(WBUFP(p, pos)), s, len);
+ char *const begin = static_cast<char *>(WBUFP(p, pos));
+ char *const end = begin + len;
+ char *const mid = std::copy(s.begin(), s.end(), begin);
+ std::fill(mid, end, '\0');
}
inline
void WBUF_ZERO(uint8_t *p, size_t pos, size_t len)
diff --git a/src/common/strings.hpp b/src/common/strings.hpp
index 8562ec4..ead3f52 100644
--- a/src/common/strings.hpp
+++ b/src/common/strings.hpp
@@ -22,10 +22,17 @@
#include "sanity.hpp"
#include <cassert>
+#include <cstdarg>
#include <cstring>
+#include <algorithm>
+#include <deque>
#include <iterator>
-#include <string>
+#include <memory>
+#include <type_traits>
+#include <vector>
+
+#include "utils2.hpp"
// It is a common mistake to assume that one string class for everything.
// Because C++ and TMWA have a C legacy, there are a few more here
@@ -64,13 +71,13 @@ namespace strings
_iterator(const char *p=nullptr) : _ptr(p) {}
// iterator
- reference operator *() { return *_ptr; }
+ reference operator *() const { return *_ptr; }
X& operator ++() { ++_ptr; return *this; }
// equality comparable
friend bool operator == (X l, X r) { return l._ptr == r._ptr; }
// input iterator
friend bool operator != (X l, X r) { return !(l == r); }
- pointer operator->() { return _ptr; }
+ pointer operator->() const { return _ptr; }
X operator++ (int) { X out = *this; ++*this; return out; }
// forward iterator is mostly semantical, and the ctor is above
// bidirectional iterator
@@ -83,8 +90,8 @@ namespace strings
X& operator -= (difference_type n) { _ptr -= n; return *this; }
friend X operator - (X a, difference_type n) { return a -= n; }
friend difference_type operator - (X b, X a) { return b._ptr - a._ptr; }
- reference operator[](difference_type n) { return _ptr[n]; }
- friend bool operator < (X a, X b) { return a._ptr - b._ptr; }
+ reference operator[](difference_type n) const { return _ptr[n]; }
+ friend bool operator < (X a, X b) { return a._ptr < b._ptr; }
friend bool operator > (X a, X b) { return b < a; }
friend bool operator >= (X a, X b) { return !(a < b); }
friend bool operator <= (X a, X b) { return !(a > b); }
@@ -92,7 +99,7 @@ namespace strings
/// A helper class that implements all the interesting stuff that can
/// be done on any constant string, in terms of .begin() and .end().
- template<class T>
+ template<class T, class O, class Z, class X=XString>
class _crtp_string
{
public:
@@ -108,22 +115,67 @@ namespace strings
size_t size() const { return end() - begin(); }
reverse_iterator rbegin() const { return reverse_iterator(end()); }
reverse_iterator rend() const { return reverse_iterator(begin()); }
- operator bool() { return size(); }
- bool operator !() { return !size(); }
+ explicit
+ operator bool() const { return size(); }
+ bool operator !() const { return !size(); }
char operator[](size_t i) const { return begin()[i]; }
char front() const { return *begin(); }
char back() const { return end()[-1]; }
const char *data() { return &*begin(); }
- XString xslice_t(size_t o) const;
- XString xslice_h(size_t o) const;
- XString xrslice_t(size_t no) const;
- XString xrslice_h(size_t no) const;
- XString xlslice(size_t o, size_t l) const;
- XString xpslice(size_t b, size_t e) const;
+ Z xslice_t(size_t o) const;
+ X xslice_h(size_t o) const;
+ Z xrslice_t(size_t no) const;
+ X xrslice_h(size_t no) const;
+ Z xislice_t(iterator it) const;
+ X xislice_h(iterator it) const;
+ X xlslice(size_t o, size_t l) const;
+ X xpslice(size_t b, size_t e) const;
+ X xislice(iterator b, iterator e) const;
+ Z lstrip() const;
+ X rstrip() const;
+ X strip() const;
+
bool startswith(XString x) const;
bool endswith(XString x) const;
+ bool startswith(char c) const;
+ bool endswith(char c) const;
+
+ bool contains(char c) const;
+ bool contains_seq(XString s) const;
+ bool contains_any(XString s) const;
+
+ bool has_print() const;
+ bool is_print() const;
+ __attribute__((deprecated))
+ O to_print() const;
+
+ bool is_graph() const;
+ bool has_graph() const;
+
+ bool has_lower() const;
+ bool is_lower() const;
+ O to_lower() const;
+
+ bool has_upper() const;
+ bool is_upper() const;
+ O to_upper() const;
+
+ bool has_alpha() const; // equivalent to has_lower || has_upper
+ bool is_alpha() const; // NOT equivalent to is_lower || is_upper
+
+ bool has_digit2() const;
+ bool is_digit2() const;
+ bool has_digit8() const;
+ bool is_digit8() const;
+ bool has_digit10() const;
+ bool is_digit10() const;
+ bool has_digit16() const;
+ bool is_digit16() const;
+
+ bool has_alnum() const; // equivalent to has_alpha || has_digit10
+ bool is_alnum() const; // NOT equivalent to is_alpha || is_digit10
};
@@ -134,53 +186,112 @@ namespace strings
class MString
{
public:
- typedef char *iterator;
- typedef _iterator<MString> const_iterator;
+ typedef std::deque<char>::iterator iterator;
+ typedef std::deque<char>::const_iterator const_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
private:
- std::string _hack;
+ std::deque<char> _hack;
public:
- template<size_t n>
- MString(char (&s)[n]) = delete;
- template<size_t n>
- MString(const char (&s)[n]) : _hack(s) {}
- template<class It>
- MString(It b, It e) : _hack(b, e) {}
-
- iterator begin() { return &*_hack.begin(); }
- iterator end() { return &*_hack.end(); }
- const_iterator begin() const { return &*_hack.begin(); }
- const_iterator end() const { return &*_hack.end(); }
+ iterator begin() { return _hack.begin(); }
+ iterator end() { return _hack.end(); }
+ const_iterator begin() const { return _hack.begin(); }
+ const_iterator end() const { return _hack.end(); }
reverse_iterator rbegin() { return reverse_iterator(end()); }
reverse_iterator rend() { return reverse_iterator(begin()); }
const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
+
+ size_t size() const { return _hack.size(); }
+ explicit
+ operator bool() const { return size(); }
+ bool operator !() const { return !size(); }
+
+ MString& operator += (MString rhs)
+ {
+ _hack.insert(_hack.end(), rhs.begin(), rhs.end());
+ return *this;
+ }
+ MString& operator += (char c)
+ {
+ _hack.push_back(c);
+ return *this;
+ }
+ MString& operator += (XString xs);
+
+ void pop_back(size_t n=1)
+ {
+ while (n--)
+ _hack.pop_back();
+ }
+ char& front()
+ {
+ return _hack.front();
+ }
+ char& back()
+ {
+ return _hack.back();
+ }
};
/// An owning string that has reached its final contents.
/// The storage is NUL-terminated
/// TODO implement a special one, that guarantees refcounting.
- class FString : public _crtp_string<FString>
+ class FString : public _crtp_string<FString, FString, ZString, XString>
{
- /*const*/ std::string _hack;
+ std::shared_ptr<std::vector<char>> _hack2;
+
+ template<class It>
+ void _assign(It b, It e)
+ {
+ if (b == e)
+ {
+ // TODO use a special empty object
+ // return;
+ }
+ if (!std::is_base_of<std::forward_iterator_tag, typename std::iterator_traits<It>::iterator_category>::value)
+ {
+ // can't use std::distance
+ _hack2 = std::make_shared<std::vector<char>>();
+ for (; b != e; ++b)
+ _hack2->push_back(*b);
+ _hack2->push_back('\0');
+ _hack2->shrink_to_fit();
+ }
+ size_t diff = std::distance(b, e);
+ _hack2 = std::make_shared<std::vector<char>>(diff + 1, '\0');
+ std::copy(b, e, _hack2->begin());
+ }
public:
-#ifndef __clang__
- __attribute__((warning("This should be removed in the next diff")))
-#endif
- FString(std::string s) : _hack(std::move(s)) {}
+ FString()
+ {
+ const char *sadness = "";
+ _assign(sadness, sadness);
+ }
+
+ explicit FString(const MString& s)
+ {
+ _assign(s.begin(), s.end());
+ }
- FString() : _hack() {}
- FString(const MString& s) : _hack(s.begin(), s.end()) {}
template<size_t n>
FString(char (&s)[n]) = delete;
+
template<size_t n>
- FString(const char (&s)[n]) : _hack(s) {}
+ FString(const char (&s)[n])
+ {
+ _assign(s, s + strlen(s));
+ }
+
template<class It>
- FString(It b, It e) : _hack(b, e) {}
+ FString(It b, It e)
+ {
+ _assign(b, e);
+ }
+
- iterator begin() const { return &*_hack.begin(); }
- iterator end() const { return &*_hack.end(); }
+ iterator begin() const { return &_hack2->begin()[0]; }
+ iterator end() const { return &_hack2->end()[-1]; }
const FString *base() const { return this; }
const char *c_str() const { return &*begin(); }
@@ -188,13 +299,16 @@ namespace strings
SString oslice_h(size_t o) const;
TString orslice_t(size_t no) const;
SString orslice_h(size_t no) const;
+ TString oislice_t(iterator it) const;
+ SString oislice_h(iterator it) const;
SString olslice(size_t o, size_t l) const;
SString opslice(size_t b, size_t e) const;
+ SString oislice(iterator b, iterator e) const;
};
/// An owning string that represents a tail slice of an FString.
/// Guaranteed to be NUL-terminated.
- class TString : public _crtp_string<TString>
+ class TString : public _crtp_string<TString, TString, ZString, XString>
{
friend class SString;
FString _s;
@@ -206,6 +320,8 @@ namespace strings
TString(char (&s)[n]) = delete;
template<size_t n>
TString(const char (&s)[n]) : _s(s), _o(0) {}
+ //template<class It>
+ //TString(It b, It e) : _s(b, e), _o(0) {}
iterator begin() const { return &_s.begin()[_o]; }
iterator end() const { return &*_s.end(); }
@@ -216,28 +332,32 @@ namespace strings
SString oslice_h(size_t o) const;
TString orslice_t(size_t no) const;
SString orslice_h(size_t no) const;
+ TString oislice_t(iterator it) const;
+ SString oislice_h(iterator it) const;
SString olslice(size_t o, size_t l) const;
SString opslice(size_t b, size_t e) const;
+ SString oislice(iterator b, iterator e) const;
- operator FString()
+ operator FString() const
{ if (_o) return FString(begin(), end()); else return _s; }
};
/// An owning string that represents a arbitrary slice of an FString.
/// Not guaranteed to be NUL-terminated.
- class SString : public _crtp_string<SString>
+ class SString : public _crtp_string<SString, SString, XString, XString>
{
FString _s;
size_t _b, _e;
public:
SString() : _s(), _b(), _e() {}
SString(FString f) : _s(std::move(f)), _b(), _e(_s.size()) {}
- SString(TString t) : _s(t._s), _e(_s.size()) {}
+ SString(TString t) : _s(t._s), _b(0), _e(_s.size()) {}
template<size_t n>
SString(char (&s)[n]) = delete;
template<size_t n>
SString(const char (&s)[n]) : _s(s), _b(0), _e(_s.size()) {}
-
+ //template<class It>
+ //SString(It b, It e) : _s(b, e), _b(0), _e(_s.size()) {}
SString(FString f, size_t b, size_t e) : _s(std::move(f)), _b(b), _e(e) {}
iterator begin() const { return &_s.begin()[_b]; }
@@ -248,34 +368,34 @@ namespace strings
SString oslice_h(size_t o) const;
SString orslice_t(size_t no) const;
SString orslice_h(size_t no) const;
+ SString oislice_t(iterator it) const;
+ SString oislice_h(iterator it) const;
SString olslice(size_t o, size_t l) const;
SString opslice(size_t b, size_t e) const;
+ SString oislice(iterator b, iterator e) const;
- operator FString()
+ operator FString() const
{ if (_b == 0 && _e == _s.size()) return _s; else return FString(begin(), end()); }
- operator TString()
+ operator TString() const
{ if (_e == _s.size()) return TString(_s, _b); else return FString(begin(), end()); }
};
/// A non-owning string that is guaranteed to be NUL-terminated.
/// This should be only used as a parameter.
- class ZString : public _crtp_string<ZString>
+ class ZString : public _crtp_string<ZString, FString, ZString, XString>
{
iterator _b, _e;
// optional
const FString *_base;
public:
-#ifndef __clang__
- __attribute__((warning("This should be removed in the next diff")))
-#endif
- ZString(const std::string& s) : _b(&*s.begin()), _e(&*s.end()), _base(nullptr) {}
-
enum { really_construct_from_a_pointer };
ZString() { *this = ZString(""); }
// no MString
ZString(const FString& s) : _b(&*s.begin()), _e(&*s.end()), _base(s.base()) {}
ZString(const TString& s) : _b(&*s.begin()), _e(&*s.end()), _base(s.base()) {}
ZString(const SString&) = delete;
+ // dangerous
+ ZString(const char *b, const char *e, const FString *base_) : _b(b), _e(e), _base(base_) {}
ZString(decltype(really_construct_from_a_pointer), const char *s, const FString *base_) : _b(s), _e(s + strlen(s)), _base(base_) {}
template<size_t n>
ZString(char (&s)[n]) = delete;
@@ -291,27 +411,30 @@ namespace strings
XString oslice_h(size_t o) const;
ZString orslice_t(size_t no) const;
XString orslice_h(size_t no) const;
+ ZString oislice_t(iterator it) const;
+ XString oislice_h(iterator it) const;
XString olslice(size_t o, size_t l) const;
XString opslice(size_t b, size_t e) const;
+ XString oislice(iterator b, iterator e) const;
- operator FString()
+ operator FString() const
{ if (_base) return SString(*_base, &*_b - &*_base->begin(), &*_e - &*_base->begin()); else return FString(_b, _e); }
- operator TString()
+ operator TString() const
{ if (_base) return SString(*_base, &*_b - &*_base->begin(), &*_e - &*_base->begin()); else return FString(_b, _e); }
- operator SString()
+ operator SString() const
{ if (_base) return SString(*_base, &*_b - &*_base->begin(), &*_e - &*_base->begin()); else return FString(_b, _e); }
};
/// A non-owning string that is not guaranteed to be NUL-terminated.
/// This should be only used as a parameter.
- class XString : public _crtp_string<XString>
+ class XString : public _crtp_string<XString, FString, XString, XString>
{
iterator _b, _e;
// optional
const FString *_base;
public:
// do I really want this?
- XString() : _b(nullptr), _e(nullptr) {}
+ XString() : _b(""), _e(_b), _base() {}
XString(std::nullptr_t) = delete;
// no MString
XString(const FString& s) : _b(&*s.begin()), _e(&*s.end()), _base(s.base()) {}
@@ -331,32 +454,34 @@ namespace strings
iterator begin() const { return _b; }
iterator end() const { return _e; }
- const FString *base() const { return _base; };
+ const FString *base() const { return _base; }
XString oslice_t(size_t o) const { return xslice_t(o); }
XString oslice_h(size_t o) const { return xslice_h(o); }
XString orslice_t(size_t no) const { return xrslice_t(no); }
XString orslice_h(size_t no) const { return xrslice_h(no); }
+ XString oislice_t(iterator it) const { return xislice_t(it); }
+ XString oislice_h(iterator it) const { return xislice_h(it); }
XString olslice(size_t o, size_t l) const { return xlslice(o, l); }
XString opslice(size_t b, size_t e) const { return xpslice(b, e); }
+ XString oislice(iterator b, iterator e) const { return xislice(b, e); }
- operator FString()
+ operator FString() const
{ if (_base) return SString(*_base, &*_b - &*_base->begin(), &*_e - &*_base->begin()); else return FString(_b, _e); }
- operator TString()
+ operator TString() const
{ if (_base) return SString(*_base, &*_b - &*_base->begin(), &*_e - &*_base->begin()); else return FString(_b, _e); }
- operator SString()
+ operator SString() const
{ if (_base) return SString(*_base, &*_b - &*_base->begin(), &*_e - &*_base->begin()); else return FString(_b, _e); }
- operator ZString() = delete;
+ operator ZString() const = delete;
};
template<uint8_t n>
- class VString : public _crtp_string<VString<n>>
+ class VString : public _crtp_string<VString<n>, VString<n>, ZString, XString>
{
char _data[n];
unsigned char _special;
- typedef typename _crtp_string<VString<n>>::iterator iterator;
public:
- static_assert(n & 1, "Size should probably be odd.");
+ typedef typename _crtp_string<VString<n>, VString<n>, ZString, XString>::iterator iterator;
VString(XString x) : _data(), _special()
{
if (x.size() > n)
@@ -397,71 +522,181 @@ namespace strings
{
*this = XString(e, s, nullptr);
}
+ VString(char c)
+ {
+ *this = XString(&c, &c + 1, nullptr);
+ }
VString()
{
*this = XString();
}
+
// hopefully this is obvious
iterator begin() const { return std::begin(_data); }
iterator end() const { return std::end(_data) - _special; }
- const FString *base() const { return nullptr; };
+ const FString *base() const { return nullptr; }
const char *c_str() const { return &*begin(); }
VString oslice_t(size_t o) const { return this->xslice_t(o); }
VString oslice_h(size_t o) const { return this->xslice_h(o); }
VString orslice_t(size_t no) const { return this->xrslice_t(no); }
VString orslice_h(size_t no) const { return this->xrslice_h(no); }
+ VString oislice_t(iterator it) const { return this->xislice_t(it); }
+ VString oislice_h(iterator it) const { return this->xislice_h(it); }
VString olslice(size_t o, size_t l) const { return this->xlslice(o, l); }
VString opslice(size_t b, size_t e) const { return this->xpslice(b, e); }
+ VString oislice(iterator b, iterator e) const { return this->xislice(b, e); }
operator FString() const { return FString(begin(), end()); }
operator TString() const { return FString(begin(), end()); }
operator SString() const { return FString(begin(), end()); }
operator ZString() const { return ZString(_data); }
operator XString() const { return XString(&*begin(), &*end(), nullptr); }
- };
+ template<uint8_t m>
+ operator VString<m>() const
+ {
+ static_assert(m > n, "can only grow");
+ XString x = *this;
+ return VString<m>(XString(x));
+ }
+ };
// not really intended for public use
inline
int xstr_compare(XString l, XString r)
{
- return std::lexicographical_compare(
+ bool less = std::lexicographical_compare(
l.begin(), l.end(),
r.begin(), r.end());
+ bool greater = std::lexicographical_compare(
+ r.begin(), r.end(),
+ l.begin(), l.end());
+ return greater - less;
}
+
template<class L, class R>
- bool operator == (const L& l, const R& r)
+ class string_comparison_allowed
+ {
+ constexpr static bool l_is_vstring_exact = std::is_same<VString<sizeof(L) - 1>, L>::value;
+ constexpr static bool l_is_vstring_approx = std::is_base_of<VString<sizeof(L) - 1>, L>::value;
+ constexpr static bool r_is_vstring_exact = std::is_same<VString<sizeof(R) - 1>, R>::value;
+ constexpr static bool r_is_vstring_approx = std::is_base_of<VString<sizeof(R) - 1>, R>::value;
+
+ constexpr static bool l_is_restricted = l_is_vstring_approx && !l_is_vstring_exact;
+ constexpr static bool r_is_restricted = r_is_vstring_approx && !r_is_vstring_exact;
+ public:
+ constexpr static bool value = std::is_same<L, R>::value || (!l_is_restricted && !r_is_restricted);
+ };
+
+ struct _test : VString<1> {};
+ struct _test2 : VString<1> {};
+
+ static_assert(string_comparison_allowed<_test, _test>::value, "tt");
+ static_assert(string_comparison_allowed<VString<1>, VString<1>>::value, "vv");
+ static_assert(!string_comparison_allowed<_test, XString>::value, "tx");
+ static_assert(!string_comparison_allowed<_test, VString<1>>::value, "tv");
+ static_assert(!string_comparison_allowed<_test, _test2>::value, "t2");
+ static_assert(string_comparison_allowed<VString<1>, XString>::value, "vx");
+ static_assert(string_comparison_allowed<XString, XString>::value, "xx");
+ static_assert(string_comparison_allowed<XString, FString>::value, "xf");
+
+ template<class L, class R, typename=typename std::enable_if<string_comparison_allowed<L, R>::value>::type>
+ auto operator == (const L& l, const R& r) -> decltype((xstr_compare(l, r), true))
{
return xstr_compare(l, r) == 0;
}
- template<class L, class R>
- bool operator != (const L& l, const R& r)
+ template<class L, class R, typename=typename std::enable_if<string_comparison_allowed<L, R>::value>::type>
+ auto operator != (const L& l, const R& r) -> decltype((xstr_compare(l, r), true))
{
return xstr_compare(l, r) != 0;
}
- template<class L, class R>
- bool operator < (const L& l, const R& r)
+ template<class L, class R, typename=typename std::enable_if<string_comparison_allowed<L, R>::value>::type>
+ auto operator < (const L& l, const R& r) -> decltype((xstr_compare(l, r), true))
{
return xstr_compare(l, r) < 0;
}
- template<class L, class R>
- bool operator <= (const L& l, const R& r)
+ template<class L, class R, typename=typename std::enable_if<string_comparison_allowed<L, R>::value>::type>
+ auto operator <= (const L& l, const R& r) -> decltype((xstr_compare(l, r), true))
{
return xstr_compare(l, r) <= 0;
}
- template<class L, class R>
- bool operator > (const L& l, const R& r)
+ template<class L, class R, typename=typename std::enable_if<string_comparison_allowed<L, R>::value>::type>
+ auto operator > (const L& l, const R& r) -> decltype((xstr_compare(l, r), true))
{
return xstr_compare(l, r) > 0;
}
- template<class L, class R>
- bool operator >= (const L& l, const R& r)
+ template<class L, class R, typename=typename std::enable_if<string_comparison_allowed<L, R>::value>::type>
+ auto operator >= (const L& l, const R& r) -> decltype((xstr_compare(l, r), true))
{
return xstr_compare(l, r) >= 0;
}
+ namespace detail
+ {
+ constexpr
+ bool is_print(char c)
+ {
+ return ' ' <= c && c <= '~';
+ }
+ constexpr
+ bool is_graph(char c)
+ {
+ return is_print(c) && c != ' ';
+ }
+ constexpr
+ bool is_lower(char c)
+ {
+ return 'a' <= c && c <= 'z';
+ }
+ constexpr
+ bool is_upper(char c)
+ {
+ return 'A' <= c && c <= 'Z';
+ }
+ constexpr
+ bool is_alpha(char c)
+ {
+ return is_lower(c) || is_upper(c);
+ }
+ constexpr
+ bool is_digit2(char c)
+ {
+ return '0' <= c && c <= '1';
+ }
+ constexpr
+ bool is_digit8(char c)
+ {
+ return '0' <= c && c <= '7';
+ }
+ constexpr
+ bool is_digit10(char c)
+ {
+ return '0' <= c && c <= '9';
+ }
+ constexpr
+ bool is_digit16(char c)
+ {
+ return ('0' <= c && c <= '9') || ('A' <= c && c <= 'F') || ('a' <= c && c <= 'f');
+ }
+ constexpr
+ bool is_alnum(char c)
+ {
+ return is_alpha(c) || is_digit10(c);
+ }
+
+ constexpr
+ char to_lower(char c)
+ {
+ return is_upper(c) ? c | ' ' : c;
+ }
+ constexpr
+ char to_upper(char c)
+ {
+ return is_lower(c) ? c & ~' ' : c;
+ }
+ }
// sadness
typedef MString MS;
@@ -472,30 +707,176 @@ namespace strings
typedef XString XS;
// _crtp_string
- template<class T>
- XS _crtp_string<T>::xslice_t(size_t o) const
- { return XS(&begin()[o], &*end(), base()); }
- template<class T>
- XS _crtp_string<T>::xslice_h(size_t o) const
- { return XS(&*begin(), &begin()[o], base()); }
- template<class T>
- XS _crtp_string<T>::xrslice_t(size_t no) const
- { return XS(&end()[-no], &*end(), base()); }
- template<class T>
- XS _crtp_string<T>::xrslice_h(size_t no) const
- { return XS(&*begin(), &end()[-no], base()); }
- template<class T>
- XS _crtp_string<T>::xlslice(size_t o, size_t l) const
- { return XS(&begin()[o], &begin()[o + l], base()); }
- template<class T>
- XS _crtp_string<T>::xpslice(size_t b, size_t e) const
- { return XS(&begin()[b], &begin()[e], base()); }
- template<class T>
- bool _crtp_string<T>::startswith(XS x) const
- { return size() > x.size() && xslice_h(x.size()) == x; }
- template<class T>
- bool _crtp_string<T>::endswith(XS x) const
+ template<class T, class O, class Z, class X>
+ Z _crtp_string<T, O, Z, X>::xslice_t(size_t o) const
+ { return Z(&begin()[o], &*end(), base()); }
+ template<class T, class O, class Z, class X>
+ X _crtp_string<T, O, Z, X>::xslice_h(size_t o) const
+ { return X(&*begin(), &begin()[o], base()); }
+ template<class T, class O, class Z, class X>
+ Z _crtp_string<T, O, Z, X>::xrslice_t(size_t no) const
+ { return Z(&end()[-no], &*end(), base()); }
+ template<class T, class O, class Z, class X>
+ X _crtp_string<T, O, Z, X>::xrslice_h(size_t no) const
+ { return X(&*begin(), &end()[-no], base()); }
+ template<class T, class O, class Z, class X>
+ Z _crtp_string<T, O, Z, X>::xislice_t(iterator it) const
+ { return Z(&*it, &*end(), base()); }
+ template<class T, class O, class Z, class X>
+ X _crtp_string<T, O, Z, X>::xislice_h(iterator it) const
+ { return X(&*begin(), &*it, base()); }
+ template<class T, class O, class Z, class X>
+ X _crtp_string<T, O, Z, X>::xlslice(size_t o, size_t l) const
+ { return X(&begin()[o], &begin()[o + l], base()); }
+ template<class T, class O, class Z, class X>
+ X _crtp_string<T, O, Z, X>::xpslice(size_t b, size_t e) const
+ { return X(&begin()[b], &begin()[e], base()); }
+ template<class T, class O, class Z, class X>
+ X _crtp_string<T, O, Z, X>::xislice(iterator b, iterator e) const
+ { return X(&*b, &*e, base()); }
+ template<class T, class O, class Z, class X>
+ Z _crtp_string<T, O, Z, X>::lstrip() const
+ {
+ Z z = _ref();
+ while (z.startswith(' '))
+ z = z.xslice_t(1);
+ return z;
+ }
+ template<class T, class O, class Z, class X>
+ X _crtp_string<T, O, Z, X>::rstrip() const
+ {
+ X x = _ref();
+ while (x.endswith(' '))
+ x = x.xrslice_h(1);
+ return x;
+ }
+ template<class T, class O, class Z, class X>
+ X _crtp_string<T, O, Z, X>::strip() const
+ { return lstrip().rstrip(); }
+
+ template<class T, class O, class Z, class X>
+ bool _crtp_string<T, O, Z, X>::startswith(XS x) const
+ { return size() >= x.size() && xslice_h(x.size()) == x; }
+ template<class T, class O, class Z, class X>
+ bool _crtp_string<T, O, Z, X>::endswith(XS x) const
{ return size() > x.size() && xrslice_t(x.size()) == x; }
+ template<class T, class O, class Z, class X>
+ bool _crtp_string<T, O, Z, X>::startswith(char c) const
+ { return size() && front() == c; }
+ template<class T, class O, class Z, class X>
+ bool _crtp_string<T, O, Z, X>::endswith(char c) const
+ { return size() && back() == c; }
+ template<class T, class O, class Z, class X>
+ bool _crtp_string<T, O, Z, X>::contains(char c) const
+ { return std::find(begin(), end(), c) != end(); }
+ template<class T, class O, class Z, class X>
+ bool _crtp_string<T, O, Z, X>::contains_seq(XString s) const
+ { return std::search(begin(), end(), s.begin(), s.end()) != end(); }
+ template<class T, class O, class Z, class X>
+ bool _crtp_string<T, O, Z, X>::contains_any(XString s) const
+ { return std::find_if(begin(), end(), [s](char c) { return s.contains(c); }) != end(); }
+
+ template<class T, class O, class Z, class X>
+ bool _crtp_string<T, O, Z, X>::has_print() const
+ { return std::find_if(begin(), end(), detail::is_print) != end(); }
+ template<class T, class O, class Z, class X>
+ bool _crtp_string<T, O, Z, X>::is_print() const
+ { return std::find_if_not(begin(), end(), detail::is_print) == end(); }
+ template<class T, class O, class Z, class X>
+ O _crtp_string<T, O, Z, X>::to_print() const
+ {
+ if (is_print()) return _ref();
+ char buf[size()];
+ char *const b = buf;
+ char *const e = std::transform(begin(), end(), b, [](char c) { return detail::is_print(c) ? c : '_'; });
+ return XString(b, e, nullptr);
+ }
+
+ template<class T, class O, class Z, class X>
+ bool _crtp_string<T, O, Z, X>::has_graph() const
+ { return std::find_if(begin(), end(), detail::is_graph) != end(); }
+ template<class T, class O, class Z, class X>
+ bool _crtp_string<T, O, Z, X>::is_graph() const
+ { return std::find_if_not(begin(), end(), detail::is_graph) == end(); }
+
+ template<class T, class O, class Z, class X>
+ bool _crtp_string<T, O, Z, X>::has_lower() const
+ { return std::find_if(begin(), end(), detail::is_lower) != end(); }
+ template<class T, class O, class Z, class X>
+ bool _crtp_string<T, O, Z, X>::is_lower() const
+ { return std::find_if_not(begin(), end(), detail::is_lower) == end(); }
+ template<class T, class O, class Z, class X>
+ O _crtp_string<T, O, Z, X>::to_lower() const
+ {
+ if (!has_upper()) return _ref();
+ char buf[size()];
+ char *const b = buf;
+ char *const e = std::transform(begin(), end(), b, detail::to_lower);
+ return XString(b, e, nullptr);
+ }
+
+ template<class T, class O, class Z, class X>
+ bool _crtp_string<T, O, Z, X>::has_upper() const
+ { return std::find_if(begin(), end(), detail::is_upper) != end(); }
+ template<class T, class O, class Z, class X>
+ bool _crtp_string<T, O, Z, X>::is_upper() const
+ { return std::find_if_not(begin(), end(), detail::is_upper) == end(); }
+ template<class T, class O, class Z, class X>
+ O _crtp_string<T, O, Z, X>::to_upper() const
+ {
+ if (!has_lower()) return _ref();
+ char buf[size()];
+ char *const b = buf;
+ char *const e = std::transform(begin(), end(), b, detail::to_upper);
+ return XString(b, e, nullptr);
+ }
+
+ template<class T, class O, class Z, class X>
+ bool _crtp_string<T, O, Z, X>::has_alpha() const
+ { return std::find_if(begin(), end(), detail::is_alpha) != end(); }
+ template<class T, class O, class Z, class X>
+ bool _crtp_string<T, O, Z, X>::is_alpha() const
+ { return std::find_if_not(begin(), end(), detail::is_alpha) == end(); }
+
+ template<class T, class O, class Z, class X>
+ bool _crtp_string<T, O, Z, X>::has_digit2() const
+ { return std::find_if(begin(), end(), detail::is_digit2) != end(); }
+ template<class T, class O, class Z, class X>
+ bool _crtp_string<T, O, Z, X>::is_digit2() const
+ { return std::find_if_not(begin(), end(), detail::is_digit2) == end(); }
+ template<class T, class O, class Z, class X>
+ bool _crtp_string<T, O, Z, X>::has_digit8() const
+ { return std::find_if(begin(), end(), detail::is_digit8) != end(); }
+ template<class T, class O, class Z, class X>
+ bool _crtp_string<T, O, Z, X>::is_digit8() const
+ { return std::find_if_not(begin(), end(), detail::is_digit8) == end(); }
+ template<class T, class O, class Z, class X>
+ bool _crtp_string<T, O, Z, X>::has_digit10() const
+ { return std::find_if(begin(), end(), detail::is_digit10) != end(); }
+ template<class T, class O, class Z, class X>
+ bool _crtp_string<T, O, Z, X>::is_digit10() const
+ { return std::find_if_not(begin(), end(), detail::is_digit10) == end(); }
+ template<class T, class O, class Z, class X>
+ bool _crtp_string<T, O, Z, X>::has_digit16() const
+ { return std::find_if(begin(), end(), detail::is_digit16) != end(); }
+ template<class T, class O, class Z, class X>
+ bool _crtp_string<T, O, Z, X>::is_digit16() const
+ { return std::find_if_not(begin(), end(), detail::is_digit16) == end(); }
+
+ template<class T, class O, class Z, class X>
+ bool _crtp_string<T, O, Z, X>::has_alnum() const
+ { return std::find_if(begin(), end(), detail::is_alnum) != end(); }
+ template<class T, class O, class Z, class X>
+ bool _crtp_string<T, O, Z, X>::is_alnum() const
+ { return std::find_if_not(begin(), end(), detail::is_alnum) == end(); }
+
+ // MString
+ inline
+ MS& MS::operator += (XS x)
+ {
+ _hack.insert(_hack.end(), x.begin(), x.end());
+ return *this;
+ }
// FString
inline
@@ -511,11 +892,20 @@ namespace strings
SS FS::orslice_h(size_t no) const
{ return SS(*this, 0, size() - no); }
inline
+ TS FS::oislice_t(iterator it) const
+ { return TS(*this, it - begin()); }
+ inline
+ SS FS::oislice_h(iterator it) const
+ { return SS(*this, 0, it - begin()); }
+ inline
SS FS::olslice(size_t o, size_t l) const
{ return SS(*this, o, o + l); }
inline
SS FS::opslice(size_t b, size_t e) const
{ return SS(*this, b, e); }
+ inline
+ SS FS::oislice(iterator b, iterator e) const
+ { return SS(*this, b - begin(), e - begin()); }
// TString
inline
@@ -531,11 +921,20 @@ namespace strings
SS TS::orslice_h(size_t no) const
{ return SS(_s, _o, _s.size() - no); }
inline
+ TS TS::oislice_t(iterator it) const
+ { return TS(_s, _o + it - begin()); }
+ inline
+ SS TS::oislice_h(iterator it) const
+ { return SS(_s, _o, _o + it - begin()); }
+ inline
SS TS::olslice(size_t o, size_t l) const
{ return SS(_s, _o + o, _o + o + l); }
inline
SS TS::opslice(size_t b, size_t e) const
{ return SS(_s, _o + b, _o + e); }
+ inline
+ SS TS::oislice(iterator b, iterator e) const
+ { return SS(_s, _o + b - begin(), _o + e - begin()); }
// SString
inline
@@ -551,11 +950,20 @@ namespace strings
SS SS::orslice_h(size_t no) const
{ return SS(_s, _b, _e - no); }
inline
+ SS SS::oislice_t(iterator it) const
+ { return SS(_s, _b + it - begin(), _e); }
+ inline
+ SS SS::oislice_h(iterator it) const
+ { return SS(_s, _b, _b + it - begin()); }
+ inline
SS SS::olslice(size_t o, size_t l) const
{ return SS(_s, _b + o, _b + o + l); }
inline
SS SS::opslice(size_t b, size_t e) const
{ return SS(_s, _b + b, _b + e); }
+ inline
+ SS SS::oislice(iterator b, iterator e) const
+ { return SS(_s, _b + b - begin(), _b + e - begin()); }
// ZString
inline
@@ -571,22 +979,97 @@ namespace strings
XS ZS::orslice_h(size_t no) const
{ return XS(&*begin(), &end()[-no], base()); }
inline
+ ZS ZS::oislice_t(iterator it) const
+ { return ZS(really_construct_from_a_pointer, &*it, base()); }
+ inline
+ XS ZS::oislice_h(iterator it) const
+ { return XS(&*begin(), &*it, base()); }
+ inline
XS ZS::olslice(size_t o, size_t l) const
{ return XS(&begin()[o], &begin()[o + l], base()); }
inline
XS ZS::opslice(size_t b, size_t e) const
{ return XS(&begin()[b], &begin()[e], base()); }
+ inline
+ XS ZS::oislice(iterator b, iterator e) const
+ { return XS(&*b, &*e, base()); }
// cxxstdio helpers
// I think the conversion will happen automatically. TODO test this.
// Nope, it doesn't, since there's a template
+ // Actually, it might now.
+ inline
+ const char *decay_for_printf(const FString& fs) { return fs.c_str(); }
inline
- const char *convert_for_printf(const FString& fs) { return fs.c_str(); }
+ const char *decay_for_printf(const TString& ts) { return ts.c_str(); }
inline
- const char *convert_for_printf(const TString& ts) { return ts.c_str(); }
+ const char *decay_for_printf(const ZString& zs) { return zs.c_str(); }
+ template<uint8_t n>
inline
- const char *convert_for_printf(const ZString& zs) { return zs.c_str(); }
+ const char *decay_for_printf(const VString<n>& vs) { return vs.c_str(); }
+
+ template<uint8_t len>
+ inline __attribute__((format(printf, 2, 0)))
+ int do_vprint(VString<len>& out, const char *fmt, va_list ap)
+ {
+ char buffer[len + 1];
+ vsnprintf(buffer, len + 1, fmt, ap);
+
+ out = const_(buffer);
+ return len;
+ }
+
+ inline __attribute__((format(printf, 2, 0)))
+ int do_vprint(FString& out, const char *fmt, va_list ap)
+ {
+ int len;
+ {
+ va_list ap2;
+ va_copy(ap2, ap);
+ len = vsnprintf(nullptr, 0, fmt, ap2);
+ va_end(ap2);
+ }
+ char buffer[len + 1];
+ vsnprintf(buffer, len + 1, fmt, ap);
+
+ out = FString(buffer, buffer + len);
+ return len;
+ }
+
+ inline __attribute__((format(scanf, 2, 0)))
+ int do_vscan(ZString in, const char *fmt, va_list ap)
+ {
+ return vsscanf(in.c_str(), fmt, ap);
+ }
+
+ class StringConverter
+ {
+ FString& out;
+ char *mid;
+ public:
+ StringConverter(FString& s)
+ : out(s), mid(nullptr)
+ {}
+ ~StringConverter()
+ {
+ if (mid)
+ {
+ out = ZString(ZString::really_construct_from_a_pointer, mid, nullptr);
+ free(mid);
+ }
+ }
+ char **operator &()
+ {
+ return &mid;
+ }
+ };
+
+ inline
+ StringConverter convert_for_scanf(FString& s)
+ {
+ return StringConverter(s);
+ }
} // namespace strings
// owning
diff --git a/src/common/strings2_test.cpp b/src/common/strings2_test.cpp
new file mode 100644
index 0000000..fa4dc6f
--- /dev/null
+++ b/src/common/strings2_test.cpp
@@ -0,0 +1,118 @@
+#include "strings.hpp"
+
+#include <gtest/gtest.h>
+
+TEST(StringTests, traits2)
+{
+ ZString print_non = "\t\e";
+ ZString print_mix = "n\t";
+ FString print_all = "n ";
+ EXPECT_FALSE(print_non.has_print());
+ EXPECT_TRUE(print_mix.has_print());
+ EXPECT_TRUE(print_all.has_print());
+ EXPECT_FALSE(print_non.is_print());
+ EXPECT_FALSE(print_mix.is_print());
+ EXPECT_TRUE(print_all.is_print());
+ EXPECT_EQ("__", print_non.to_print());
+ EXPECT_EQ("n_", print_mix.to_print());
+ EXPECT_EQ("n ", print_all.to_print());
+ EXPECT_EQ(print_all.begin(), print_all.to_print().begin());
+
+ ZString graph_non = " \e";
+ ZString graph_mix = "n ";
+ FString graph_all = "n.";
+ EXPECT_FALSE(graph_non.has_graph());
+ EXPECT_TRUE(graph_mix.has_graph());
+ EXPECT_TRUE(graph_all.has_graph());
+ EXPECT_FALSE(graph_non.is_graph());
+ EXPECT_FALSE(graph_mix.is_graph());
+ EXPECT_TRUE(graph_all.is_graph());
+
+ ZString lower_non = "0A";
+ ZString lower_mix = "Oa";
+ FString lower_all = "oa";
+ EXPECT_FALSE(lower_non.has_lower());
+ EXPECT_TRUE(lower_mix.has_lower());
+ EXPECT_TRUE(lower_all.has_lower());
+ EXPECT_FALSE(lower_non.is_lower());
+ EXPECT_FALSE(lower_mix.is_lower());
+ EXPECT_TRUE(lower_all.is_lower());
+ EXPECT_EQ("0a", lower_non.to_lower());
+ EXPECT_EQ("oa", lower_mix.to_lower());
+ EXPECT_EQ("oa", lower_all.to_lower());
+ EXPECT_EQ(lower_all.begin(), lower_all.to_lower().begin());
+
+ ZString upper_non = "0a";
+ ZString upper_mix = "oA";
+ FString upper_all = "OA";
+ EXPECT_FALSE(upper_non.has_upper());
+ EXPECT_TRUE(upper_mix.has_upper());
+ EXPECT_TRUE(upper_all.has_upper());
+ EXPECT_FALSE(upper_non.is_upper());
+ EXPECT_FALSE(upper_mix.is_upper());
+ EXPECT_TRUE(upper_all.is_upper());
+ EXPECT_EQ("0A", upper_non.to_upper());
+ EXPECT_EQ("OA", upper_mix.to_upper());
+ EXPECT_EQ("OA", upper_all.to_upper());
+ EXPECT_EQ(upper_all.begin(), upper_all.to_upper().begin());
+
+ ZString alpha_non = " 0";
+ ZString alpha_mix = "n ";
+ FString alpha_all = "nA";
+ EXPECT_FALSE(alpha_non.has_alpha());
+ EXPECT_TRUE(alpha_mix.has_alpha());
+ EXPECT_TRUE(alpha_all.has_alpha());
+ EXPECT_FALSE(alpha_non.is_alpha());
+ EXPECT_FALSE(alpha_mix.is_alpha());
+ EXPECT_TRUE(alpha_all.is_alpha());
+
+ ZString digit2_non = "a9";
+ ZString digit2_mix = "20";
+ FString digit2_all = "01";
+ EXPECT_FALSE(digit2_non.has_digit2());
+ EXPECT_TRUE(digit2_mix.has_digit2());
+ EXPECT_TRUE(digit2_all.has_digit2());
+ EXPECT_FALSE(digit2_non.is_digit2());
+ EXPECT_FALSE(digit2_mix.is_digit2());
+ EXPECT_TRUE(digit2_all.is_digit2());
+
+ ZString digit8_non = "a9";
+ ZString digit8_mix = "80";
+ FString digit8_all = "37";
+ EXPECT_FALSE(digit8_non.has_digit8());
+ EXPECT_TRUE(digit8_mix.has_digit8());
+ EXPECT_TRUE(digit8_all.has_digit8());
+ EXPECT_FALSE(digit8_non.is_digit8());
+ EXPECT_FALSE(digit8_mix.is_digit8());
+ EXPECT_TRUE(digit8_all.is_digit8());
+
+ ZString digit10_non = "az";
+ ZString digit10_mix = "a9";
+ FString digit10_all = "42";
+ EXPECT_FALSE(digit10_non.has_digit10());
+ EXPECT_TRUE(digit10_mix.has_digit10());
+ EXPECT_TRUE(digit10_all.has_digit10());
+ EXPECT_FALSE(digit10_non.is_digit10());
+ EXPECT_FALSE(digit10_mix.is_digit10());
+ EXPECT_TRUE(digit10_all.is_digit10());
+
+ ZString digit16_non = "gz";
+ ZString digit16_mix = "ao";
+ FString digit16_all = "be";
+ EXPECT_FALSE(digit16_non.has_digit16());
+ EXPECT_TRUE(digit16_mix.has_digit16());
+ EXPECT_TRUE(digit16_all.has_digit16());
+ EXPECT_FALSE(digit16_non.is_digit16());
+ EXPECT_FALSE(digit16_mix.is_digit16());
+ EXPECT_TRUE(digit16_all.is_digit16());
+
+ ZString alnum_non = " .";
+ ZString alnum_mix = "n ";
+ FString alnum_all = "n0";
+ EXPECT_FALSE(alnum_non.has_alnum());
+ EXPECT_TRUE(alnum_mix.has_alnum());
+ EXPECT_TRUE(alnum_all.has_alnum());
+ EXPECT_FALSE(alnum_non.is_alnum());
+ EXPECT_FALSE(alnum_mix.is_alnum());
+ EXPECT_TRUE(alnum_all.is_alnum());
+}
diff --git a/src/common/strings_test.cpp b/src/common/strings_test.cpp
index b6a6f67..fa04f1c 100644
--- a/src/common/strings_test.cpp
+++ b/src/common/strings_test.cpp
@@ -1,4 +1,6 @@
-#include "../../src/common/strings.hpp"
+#include "strings.hpp"
+
+#include <algorithm>
#include <gtest/gtest.h>
@@ -22,6 +24,118 @@ TYPED_TEST_P(StringTest, basic)
const FString *base = hi.base();
}
+TYPED_TEST_P(StringTest, order)
+{
+ TypeParam a;
+ TypeParam b("Hello");
+ TypeParam c("Hello,");
+ TypeParam d("World!");
+
+ // not using EXPECT_LT, etc. for better visibility
+
+ EXPECT_FALSE(a < a);
+ EXPECT_TRUE(a < b);
+ EXPECT_TRUE(a < c);
+ EXPECT_TRUE(a < d);
+ EXPECT_FALSE(b < a);
+ EXPECT_FALSE(b < b);
+ EXPECT_TRUE(b < c);
+ EXPECT_TRUE(b < d);
+ EXPECT_FALSE(c < a);
+ EXPECT_FALSE(c < b);
+ EXPECT_FALSE(c < c);
+ EXPECT_TRUE(c < d);
+ EXPECT_FALSE(d < a);
+ EXPECT_FALSE(d < b);
+ EXPECT_FALSE(d < c);
+ EXPECT_FALSE(d < d);
+
+ EXPECT_TRUE(a <= a);
+ EXPECT_TRUE(a <= b);
+ EXPECT_TRUE(a <= c);
+ EXPECT_TRUE(a <= d);
+ EXPECT_FALSE(b <= a);
+ EXPECT_TRUE(b <= b);
+ EXPECT_TRUE(b <= c);
+ EXPECT_TRUE(b <= d);
+ EXPECT_FALSE(c <= a);
+ EXPECT_FALSE(c <= b);
+ EXPECT_TRUE(c <= c);
+ EXPECT_TRUE(c <= d);
+ EXPECT_FALSE(d <= a);
+ EXPECT_FALSE(d <= b);
+ EXPECT_FALSE(d <= c);
+ EXPECT_TRUE(d <= d);
+
+ EXPECT_TRUE(a >= a);
+ EXPECT_FALSE(a >= b);
+ EXPECT_FALSE(a >= c);
+ EXPECT_FALSE(a >= d);
+ EXPECT_TRUE(b >= a);
+ EXPECT_TRUE(b >= b);
+ EXPECT_FALSE(b >= c);
+ EXPECT_FALSE(b >= d);
+ EXPECT_TRUE(c >= a);
+ EXPECT_TRUE(c >= b);
+ EXPECT_TRUE(c >= c);
+ EXPECT_FALSE(c >= d);
+ EXPECT_TRUE(d >= a);
+ EXPECT_TRUE(d >= b);
+ EXPECT_TRUE(d >= c);
+ EXPECT_TRUE(d >= d);
+
+ EXPECT_FALSE(a > a);
+ EXPECT_FALSE(a > b);
+ EXPECT_FALSE(a > c);
+ EXPECT_FALSE(a > d);
+ EXPECT_TRUE(b > a);
+ EXPECT_FALSE(b > b);
+ EXPECT_FALSE(b > c);
+ EXPECT_FALSE(b > d);
+ EXPECT_TRUE(c > a);
+ EXPECT_TRUE(c > b);
+ EXPECT_FALSE(c > c);
+ EXPECT_FALSE(c > d);
+ EXPECT_TRUE(d > a);
+ EXPECT_TRUE(d > b);
+ EXPECT_TRUE(d > c);
+ EXPECT_FALSE(d > d);
+
+ EXPECT_TRUE(a == a);
+ EXPECT_FALSE(a == b);
+ EXPECT_FALSE(a == c);
+ EXPECT_FALSE(a == d);
+ EXPECT_FALSE(b == a);
+ EXPECT_TRUE(b == b);
+ EXPECT_FALSE(b == c);
+ EXPECT_FALSE(b == d);
+ EXPECT_FALSE(c == a);
+ EXPECT_FALSE(c == b);
+ EXPECT_TRUE(c == c);
+ EXPECT_FALSE(c == d);
+ EXPECT_FALSE(d == a);
+ EXPECT_FALSE(d == b);
+ EXPECT_FALSE(d == c);
+ EXPECT_TRUE(d == d);
+
+ EXPECT_FALSE(a != a);
+ EXPECT_TRUE(a != b);
+ EXPECT_TRUE(a != c);
+ EXPECT_TRUE(a != d);
+ EXPECT_TRUE(b != a);
+ EXPECT_FALSE(b != b);
+ EXPECT_TRUE(b != c);
+ EXPECT_TRUE(b != d);
+ EXPECT_TRUE(c != a);
+ EXPECT_TRUE(c != b);
+ EXPECT_FALSE(c != c);
+ EXPECT_TRUE(c != d);
+ EXPECT_TRUE(d != a);
+ EXPECT_TRUE(d != b);
+ EXPECT_TRUE(d != c);
+ EXPECT_FALSE(d != d);
+}
+
TYPED_TEST_P(StringTest, iterators)
{
TypeParam hi("Hello");
@@ -39,8 +153,12 @@ TYPED_TEST_P(StringTest, xslice)
EXPECT_EQ("Hello,", hi.xslice_h(6));
EXPECT_EQ("World!", hi.xrslice_t(6));
EXPECT_EQ("Hello, ", hi.xrslice_h(6));
+ typename TypeParam::iterator it = std::find(hi.begin(), hi.end(), ' ');
+ EXPECT_EQ(" World!", hi.xislice_t(it));
+ EXPECT_EQ("Hello,", hi.xislice_h(it));
EXPECT_EQ("World", hi.xlslice(7, 5));
EXPECT_EQ("World", hi.xpslice(7, 12));
+ EXPECT_EQ("World", hi.xislice(hi.begin() + 7, hi.begin() + 12));
EXPECT_TRUE(hi.startswith("Hello"));
EXPECT_TRUE(hi.endswith("World!"));
}
@@ -52,8 +170,12 @@ TYPED_TEST_P(StringTest, oslice)
EXPECT_EQ("Hello,", hi.oslice_h(6));
EXPECT_EQ("World!", hi.orslice_t(6));
EXPECT_EQ("Hello, ", hi.orslice_h(6));
+ typename TypeParam::iterator it = std::find(hi.begin(), hi.end(), ' ');
+ EXPECT_EQ(" World!", hi.oislice_t(it));
+ EXPECT_EQ("Hello,", hi.oislice_h(it));
EXPECT_EQ("World", hi.olslice(7, 5));
EXPECT_EQ("World", hi.opslice(7, 12));
+ EXPECT_EQ("World", hi.oislice(hi.begin() + 7, hi.begin() + 12));
}
TYPED_TEST_P(StringTest, convert)
@@ -67,6 +189,8 @@ TYPED_TEST_P(StringTest, convert)
ZString z = "z";
Xstring x = "x";
VString<255> v = "v";
+ const char l[] = "l";
+ VString<5> hi = "hello";
TypeParam f2 = f;
TypeParam t2 = t;
@@ -74,32 +198,40 @@ TYPED_TEST_P(StringTest, convert)
TypeParam z2 = z;
TypeParam x2 = x;
TypeParam v2 = v;
+ TypeParam l2 = l;
+ TypeParam hi2 = hi;
- EXPECT_EQ(f2, f);
- EXPECT_EQ(t2, t);
- EXPECT_EQ(s2, s);
- EXPECT_EQ(z2, z);
- EXPECT_EQ(x2, x);
- EXPECT_EQ(v2, v);
+ EXPECT_EQ(f, f2);
+ EXPECT_EQ(t, t2);
+ EXPECT_EQ(s, s2);
+ EXPECT_EQ(z, z2);
+ EXPECT_EQ(x, x2);
+ EXPECT_EQ(v, v2);
+ EXPECT_EQ(l, l2);
+ EXPECT_EQ(hi, hi2);
- TypeParam f3, t3, s3, z3, x3, v3;
+ TypeParam f3, t3, s3, z3, x3, v3, l3, hi3;
f3 = f;
t3 = t;
s3 = s;
z3 = z;
x3 = x;
v3 = v;
+ l3 = l;
+ hi3 = hi;
- EXPECT_EQ(f3, f);
- EXPECT_EQ(t3, t);
- EXPECT_EQ(s3, s);
- EXPECT_EQ(z3, z);
- EXPECT_EQ(x3, x);
- EXPECT_EQ(v3, v);
+ EXPECT_EQ(f, f3);
+ EXPECT_EQ(t, t3);
+ EXPECT_EQ(s, s3);
+ EXPECT_EQ(z, z3);
+ EXPECT_EQ(x, x3);
+ EXPECT_EQ(v, v3);
+ EXPECT_EQ(l, l3);
+ EXPECT_EQ(hi, hi3);
}
REGISTER_TYPED_TEST_CASE_P(StringTest,
- basic, iterators, xslice, oslice, convert);
+ basic, order, iterators, xslice, oslice, convert);
typedef ::testing::Types<
FString, TString, SString, ZString, XString, VString<255>
diff --git a/src/common/timer.cpp b/src/common/timer.cpp
index ec1f6b2..c00f06d 100644
--- a/src/common/timer.cpp
+++ b/src/common/timer.cpp
@@ -184,10 +184,10 @@ interval_t do_timer(tick_t tick)
return std::max(nextmin, std::chrono::milliseconds(10));
}
-tick_t file_modified(const char *name)
+tick_t file_modified(ZString name)
{
struct stat buf;
- if (stat(name, &buf))
+ if (stat(name.c_str(), &buf))
return tick_t();
return tick_t(std::chrono::seconds(buf.st_mtime));
}
diff --git a/src/common/timer.hpp b/src/common/timer.hpp
index c581377..b9c9588 100644
--- a/src/common/timer.hpp
+++ b/src/common/timer.hpp
@@ -5,6 +5,8 @@
# include "sanity.hpp"
+# include "strings.hpp"
+
// updated automatically when using milli_clock::now()
// which is done only by core.cpp
extern tick_t gettick_cache;
@@ -20,6 +22,6 @@ tick_t gettick(void)
interval_t do_timer(tick_t tick);
/// Stat a file, and return its modification time, truncated to seconds.
-tick_t file_modified(const char *name);
+tick_t file_modified(ZString name);
#endif // TIMER_HPP
diff --git a/src/common/utils.cpp b/src/common/utils.cpp
index 4e00808..c9c22b9 100644
--- a/src/common/utils.cpp
+++ b/src/common/utils.cpp
@@ -5,120 +5,97 @@
#include <algorithm>
-#include "../poison.hpp"
-
-//-----------------------------------------------------
-// Function to suppress control characters in a string.
-//-----------------------------------------------------
-int remove_control_chars(char *str)
-{
- int i;
- int change = 0;
-
- for (i = 0; str[i]; i++)
- {
- if (0 <= str[i] && str[i] < 32)
- {
- str[i] = '_';
- change = 1;
- }
- }
+#include "cxxstdio.hpp"
+#include "extract.hpp"
- return change;
-}
+#include "../poison.hpp"
//---------------------------------------------------
// E-mail check: return 0 (not correct) or 1 (valid).
//---------------------------------------------------
-int e_mail_check(const char *email)
+bool e_mail_check(XString email)
{
- char ch;
- const char *last_arobas;
-
// athena limits
- if (strlen(email) < 3 || strlen(email) > 39)
+ if (email.size() < 3 || email.size() > 39)
return 0;
// part of RFC limits (official reference of e-mail description)
- if (strchr(email, '@') == NULL || email[strlen(email) - 1] == '@')
+ XString::iterator at = std::find(email.begin(), email.end(), '@');
+ if (at == email.end())
return 0;
-
- if (email[strlen(email) - 1] == '.')
+ XString username = email.xislice_h(at);
+ XString hostname = email.xislice_t(at + 1);
+ if (!username || !hostname)
return 0;
-
- last_arobas = strrchr(email, '@');
-
- if (strstr(last_arobas, "@.") != NULL ||
- strstr(last_arobas, "..") != NULL)
+ if (hostname.contains('@'))
return 0;
-
- for (ch = 1; ch < 32; ch++)
- {
- if (strchr(last_arobas, ch) != NULL)
- {
- return 0;
- }
- }
-
- if (strchr(last_arobas, ' ') != NULL ||
- strchr(last_arobas, ';') != NULL)
+ if (hostname.front() == '.' || hostname.back() == '.')
return 0;
-
- // all correct
- return 1;
+ if (hostname.contains_seq(".."))
+ return 0;
+ if (email.contains_any(" ;"))
+ return 0;
+ return email.is_print();
}
//-------------------------------------------------
// Return numerical value of a switch configuration
// on/off, english, français, deutsch, español
//-------------------------------------------------
-int config_switch (const char *str)
+int config_switch (ZString str)
{
- if (strcasecmp(str, "on") == 0 || strcasecmp(str, "yes") == 0
- || strcasecmp(str, "oui") == 0 || strcasecmp(str, "ja") == 0
- || strcasecmp(str, "si") == 0)
+ if (str == "on" || str == "yes"
+ || str == "oui" || str == "ja"
+ || str == "si")
return 1;
- if (strcasecmp(str, "off") == 0 || strcasecmp(str, "no") == 0
- || strcasecmp(str, "non") == 0 || strcasecmp(str, "nein") == 0)
+ if (str == "off" || str == "no"
+ || str == "non" || str == "nein")
return 0;
- return atoi(str);
+ int rv;
+ if (extract(str, &rv))
+ return rv;
+ FPRINTF(stderr, "Fatal: bad option value %s", str);
+ abort();
}
-const char *ip2str(struct in_addr ip, bool extra_dot)
+IP_String ip2str(struct in_addr ip)
+{
+ const uint8_t *p = reinterpret_cast<const uint8_t *>(&ip);
+
+ IP_String out;
+ SNPRINTF(out, 16, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
+ return out;
+}
+VString<16> ip2str_extradot(struct in_addr ip)
{
const uint8_t *p = reinterpret_cast<const uint8_t *>(&ip);
- static char buf[17];
- if (extra_dot)
- sprintf(buf, "%d.%d.%d.%d.", p[0], p[1], p[2], p[3]);
- else
- sprintf(buf, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
- return buf;
+ VString<16> out;
+ SNPRINTF(out, 17, "%d.%d.%d.%d.", p[0], p[1], p[2], p[3]);
+ return out;
}
-bool split_key_value(const std::string& line, std::string *w1, std::string *w2)
+bool split_key_value(const FString& line, SString *w1, TString *w2)
{
- std::string::const_iterator begin = line.begin(), end = line.end();
+ FString::iterator begin = line.begin(), end = line.end();
- if (line[0] == '/' && line[1] == '/')
+ if (line.startswith("//"))
return false;
- if (line.back() == '\r')
- --end;
- if (line.empty())
+ if (begin == end)
return false;
if (std::find_if(begin, end,
[](unsigned char c) { return c < ' '; }
) != line.end())
return false;
- std::string::const_iterator colon = std::find(begin, end, ':');
+ FString::iterator colon = std::find(begin, end, ':');
if (colon == end)
return false;
- w1->assign(begin, colon);
+ *w1 = line.oislice(begin, colon);
++colon;
while (std::isspace(*colon))
++colon;
- w2->assign(colon, end);
+ *w2 = line.oislice(colon, end);
return true;
}
@@ -128,18 +105,22 @@ static_assert(sizeof(timestamp_milliseconds_buffer) == 24, "millis buffer");
void stamp_time(timestamp_seconds_buffer& out, const TimeT *t)
{
struct tm when = t ? *t : TimeT::now();
- strftime(out, 20, "%Y-%m-%d %H:%M:%S", &when);
+ char buf[20];
+ strftime(buf, 20, "%Y-%m-%d %H:%M:%S", &when);
+ out = stringish<timestamp_seconds_buffer>(const_(buf));
}
void stamp_time(timestamp_milliseconds_buffer& out)
{
struct timeval tv;
gettimeofday(&tv, NULL);
struct tm when = TimeT(tv.tv_sec);
- strftime(out, 20, "%Y-%m-%d %H:%M:%S", &when);
- sprintf(out + 19, ".%03d", int(tv.tv_usec / 1000));
+ char buf[24];
+ strftime(buf, 20, "%Y-%m-%d %H:%M:%S", &when);
+ sprintf(buf + 19, ".%03d", static_cast<int>(tv.tv_usec / 1000));
+ out = stringish<timestamp_milliseconds_buffer>(const_(buf));
}
-void log_with_timestamp(FILE *out, const_string line)
+void log_with_timestamp(FILE *out, XString line)
{
if (!line)
{
@@ -148,7 +129,7 @@ void log_with_timestamp(FILE *out, const_string line)
}
timestamp_milliseconds_buffer tmpstr;
stamp_time(tmpstr);
- fwrite(tmpstr, 1, sizeof(tmpstr), out);
+ fputs(tmpstr.c_str(), out);
fputs(": ", out);
fwrite(line.data(), 1, line.size(), out);
if (line.back() != '\n')
diff --git a/src/common/utils.hpp b/src/common/utils.hpp
index ab32948..196bb3e 100644
--- a/src/common/utils.hpp
+++ b/src/common/utils.hpp
@@ -6,13 +6,15 @@
#include <cstdio>
#include <cstring>
-#include <string>
#include <type_traits>
#include "const_array.hpp"
#include "operators.hpp"
+#include "strings.hpp"
#include "utils2.hpp"
+struct IP_String : VString<15> {};
+
template<class T>
struct is_trivially_copyable
: std::integral_constant<bool,
@@ -22,23 +24,12 @@ struct is_trivially_copyable
&& __has_trivial_destructor(T)>
{};
-int remove_control_chars(char *str);
-int e_mail_check(const char *email);
-int config_switch (const char *str);
-const char *ip2str(struct in_addr ip, bool extra_dot = false);
+bool e_mail_check(XString email);
+int config_switch (ZString str);
+IP_String ip2str(struct in_addr ip);
+VString<15 + 1> ip2str_extradot(struct in_addr ip);
-bool split_key_value(const std::string& line, std::string *w1, std::string *w2);
-
-inline
-void strzcpy(char *dest, const char *src, size_t n)
-{
- if (n)
- {
- // hmph
- strncpy(dest, src, n - 1);
- dest[n - 1] = '\0';
- }
-}
+bool split_key_value(const FString& line, SString *w1, TString *w2);
inline
void really_memcpy(uint8_t *dest, const uint8_t *src, size_t n)
@@ -123,13 +114,14 @@ long long& convert_for_scanf(TimeT& t)
return t.value;
}
-typedef char timestamp_seconds_buffer[20];
-typedef char timestamp_milliseconds_buffer[24];
+struct timestamp_seconds_buffer : VString<19> {};
+struct timestamp_milliseconds_buffer : VString<23> {};
void stamp_time(timestamp_seconds_buffer&, const TimeT *t=nullptr);
void stamp_time(timestamp_milliseconds_buffer&);
-void log_with_timestamp(FILE *out, const_string line);
+void log_with_timestamp(FILE *out, XString line);
+// TODO VString?
#define TIMESTAMP_DUMMY "YYYY-MM-DD HH:MM:SS"
static_assert(sizeof(TIMESTAMP_DUMMY) == sizeof(timestamp_seconds_buffer),
"timestamp size");
@@ -138,6 +130,7 @@ static_assert(sizeof(TIMESTAMP_DUMMY) == sizeof(timestamp_seconds_buffer),
// sizeof: 01234567890123456789012345678
// str + sizeof: ^
// -1: ^
+// there's probably a better way to do this now
#define REPLACE_TIMESTAMP(str, t) \
stamp_time( \
reinterpret_cast<timestamp_seconds_buffer *>( \
@@ -146,10 +139,4 @@ static_assert(sizeof(TIMESTAMP_DUMMY) == sizeof(timestamp_seconds_buffer),
&t \
)
-template<class T>
-const T& const_(T& t)
-{
- return t;
-}
-
#endif //UTILS_HPP
diff --git a/src/common/utils2.hpp b/src/common/utils2.hpp
index d7d6f8a..119cc13 100644
--- a/src/common/utils2.hpp
+++ b/src/common/utils2.hpp
@@ -248,4 +248,33 @@ typename std::enable_if<is_array_of_unknown_bound<T>::value, std::unique_ptr<T,
return std::unique_ptr<E[], D>(new E[sz]());
}
+template<class T>
+const T& const_(T& t)
+{
+ return t;
+}
+
+template<class T, class U>
+T no_cast(U&& u)
+{
+ typedef typename std::remove_reference<T>::type Ti;
+ typedef typename std::remove_reference<U>::type Ui;
+ typedef typename std::remove_cv<Ti>::type Tb;
+ typedef typename std::remove_cv<Ui>::type Ub;
+ static_assert(std::is_same<Tb, Ub>::value, "not no cast");
+ return std::forward<U>(u);
+}
+
+template<class T, class U>
+T base_cast(U&& u)
+{
+ static_assert(std::is_reference<T>::value, "must base cast with references");
+ typedef typename std::remove_reference<T>::type Ti;
+ typedef typename std::remove_reference<U>::type Ui;
+ typedef typename std::remove_cv<Ti>::type Tb;
+ typedef typename std::remove_cv<Ui>::type Ub;
+ static_assert(std::is_base_of<Tb, Ub>::value, "not base cast");
+ return std::forward<U>(u);
+}
+
#endif // UTILS2_HPP
diff --git a/src/ladmin/ladmin.cpp b/src/ladmin/ladmin.cpp
index 5f3ef7b..2581456 100644
--- a/src/ladmin/ladmin.cpp
+++ b/src/ladmin/ladmin.cpp
@@ -6,13 +6,17 @@
#include <cassert>
#include <fstream>
+#include <iostream>
-#include "../common/cxxstdio.hpp"
#include "../common/core.hpp"
+#include "../common/cxxstdio.hpp"
+#include "../common/human_time_diff.hpp"
+#include "../common/io.hpp"
#include "../common/md5calc.hpp"
+#include "../common/mmo.hpp"
#include "../common/socket.hpp"
-#include "../common/version.hpp"
#include "../common/utils.hpp"
+#include "../common/version.hpp"
#include "../poison.hpp"
@@ -32,15 +36,13 @@ int eathena_interactive_session;
// (see login_athena.conf, 'admin_state' parameter)
//-------------------------------------------------------------------------
static
-char loginserverip[16] = "127.0.0.1"; // IP of login-server
+IP_String loginserverip = stringish<IP_String>("127.0.0.1"); // IP of login-server
static
int loginserverport = 6900; // Port of login-server
static
-char loginserveradminpassword[24] = "admin"; // Administration password
+AccountPass loginserveradminpassword = stringish<AccountPass>("admin"); // Administration password
static
-int passenc = 2; // Encoding type of the password
-static
-char ladmin_log_filename[1024] = "log/ladmin.log";
+FString ladmin_log_filename = "log/ladmin.log";
//-------------------------------------------------------------------------
// LIST of COMMANDs that you can type at the prompt:
// To use these commands you can only type only the first letters.
@@ -228,7 +230,7 @@ int login_ip;
static
int bytes_to_read = 0; // flag to know if we waiting bytes from login-server
static
-char parameters[1024]; // needs to be global since it's passed to the parse function
+TString parameters; // needs to be global since it's passed to the parse function
// really should be added to session data
static
int list_first, list_last, list_type, list_count; // parameter to display a list of accounts
@@ -247,311 +249,84 @@ void SessionDeleter::operator()(SessionData *)
// Writing function of logs file
//------------------------------
#define LADMIN_LOG(fmt, ...) \
- ladmin_log(static_cast<const std::string&>(STRPRINTF(fmt, ## __VA_ARGS__)))
+ ladmin_log(STRPRINTF(fmt, ## __VA_ARGS__))
static
-void ladmin_log(const_string line)
+void ladmin_log(XString line)
{
- FILE *logfp = fopen_(ladmin_log_filename, "a");
+ FILE *logfp = fopen(ladmin_log_filename.c_str(), "a");
if (!logfp)
return;
log_with_timestamp(logfp, line);
- fclose_(logfp);
-}
-
-//---------------------------------------------
-// Function to return ordonal text of a number.
-//---------------------------------------------
-static
-const char *makeordinal(int number)
-{
- if ((number % 10) < 4 && (number % 10) != 0
- && (number < 10 || number > 20))
- {
- if ((number % 10) == 1)
- return "st";
- else if ((number % 10) == 2)
- return "nd";
- else
- return "rd";
- }
- else
- {
- return "th";
- }
-}
-
-//-----------------------------------------------------------------------------------------
-// Function to test of the validity of an account name (return 0 if incorrect, and 1 if ok)
-//-----------------------------------------------------------------------------------------
-static
-int verify_accountname(const char *account_name)
-{
- int i;
-
- for (i = 0; account_name[i]; i++)
- {
- if (account_name[i] < 32)
- {
- PRINTF("Illegal character found in the account name (%d%s character).\n",
- i + 1, makeordinal(i + 1));
- LADMIN_LOG("Illegal character found in the account name (%d%s character).\n",
- i + 1, makeordinal(i + 1));
- return 0;
- }
- }
-
- if (strlen(account_name) < 4)
- {
- PRINTF("Account name is too short. Please input an account name of 4-23 bytes.\n");
- LADMIN_LOG("Account name is too short. Please input an account name of 4-23 bytes.\n");
- return 0;
- }
-
- if (strlen(account_name) > 23)
- {
- PRINTF("Account name is too long. Please input an account name of 4-23 bytes.\n");
- LADMIN_LOG("Account name is too long. Please input an account name of 4-23 bytes.\n");
- return 0;
- }
-
- return 1;
+ fclose(logfp);
}
-//----------------------------------
-// Sub-function: Input of a password
-//----------------------------------
static
-int typepasswd(char *password)
+bool qsplit(ZString src)
{
- char password1[1023] {};
- char password2[1023] {};
- int letter;
- int i;
-
- LADMIN_LOG("No password was given. Request to obtain a password.\n");
-
- PRINTF("\033[1;36m Type the password > \033[0;32;42m");
- i = 0;
- while ((letter = getchar()) != '\n')
- password1[i++] = letter;
- PRINTF("\033[0m\033[1;36m Verify the password > \033[0;32;42m");
- i = 0;
- while ((letter = getchar()) != '\n')
- password2[i++] = letter;
-
- PRINTF("\033[0m");
- fflush(stdout);
- fflush(stdin);
-
- if (strcmp(password1, password2) != 0)
- {
- PRINTF("Password verification failed. Please input same password.\n");
- LADMIN_LOG("Password verification failed. Please input same password.\n");
- LADMIN_LOG(" First password: %s, second password: %s.\n",
- password1, password2);
- return 0;
- }
- LADMIN_LOG("Typed password: %s.\n", password1);
- strcpy(password, password1);
- return 1;
+ return !src;
}
-//------------------------------------------------------------------------------------
-// Sub-function: Test of the validity of password (return 0 if incorrect, and 1 if ok)
-//------------------------------------------------------------------------------------
+template<class F, class... R>
static
-int verify_password(const char *password)
+bool qsplit(ZString src, F first, R... rest)
{
- int i;
-
- for (i = 0; password[i]; i++)
- {
- if (password[i] < 32)
- {
- PRINTF("Illegal character found in the password (%d%s character).\n",
- i + 1, makeordinal(i + 1));
- LADMIN_LOG("Illegal character found in the password (%d%s character).\n",
- i + 1, makeordinal(i + 1));
- return 0;
- }
+ if (!src)
+ return false;
+ XString one;
+ if (src.startswith('\''))
+ {
+ src = src.xslice_t(1);
+ auto it = std::find(src.begin(), src.end(), '\'');
+ if (it == src.end())
+ return false;
+ one = src.xislice_h(it);
+ src = src.xislice_t(it + 1);
+ while (src.startswith(' '))
+ src = src.xslice_t(1);
+ }
+ else if (src.startswith('"'))
+ {
+ src = src.xslice_t(1);
+ auto it = std::find(src.begin(), src.end(), '"');
+ if (it == src.end())
+ return false;
+ one = src.xislice_h(it);
+ src = src.xislice_t(it + 1);
+ while (src.startswith(' '))
+ src = src.xslice_t(1);
}
-
- if (strlen(password) < 4)
- {
- PRINTF("Account name is too short. Please input an account name of 4-23 bytes.\n");
- LADMIN_LOG("Account name is too short. Please input an account name of 4-23 bytes.\n");
- return 0;
- }
-
- if (strlen(password) > 23)
+ else
{
- PRINTF("Password is too long. Please input a password of 4-23 bytes.\n");
- LADMIN_LOG("Password is too long. Please input a password of 4-23 bytes.\n");
- return 0;
+ auto it = std::find(src.begin(), src.end(), ' ');
+ one = src.xislice_h(it);
+ src = src.xislice_t(it);
+ while (src.startswith(' '))
+ src = src.xslice_t(1);
}
-
- return 1;
-}
-
-//------------------------------------------------------------------
-// Sub-function: Check the name of a command (return complete name)
-//-----------------------------------------------------------------
-static
-int check_command(char *command)
-{
-// help
- if (strncmp(command, "help", 1) == 0
- && strncmp(command, "help", strlen(command)) == 0)
- strcpy(command, "help");
-// general commands
- else if (strncmp(command, "add", 2) == 0 && strncmp(command, "add", strlen(command)) == 0)
- strcpy(command, "add");
- else if ((strncmp(command, "ban", 3) == 0
- && strncmp(command, "ban", strlen(command)) == 0)
- ||(strncmp(command, "banish", 4) == 0
- && strncmp(command, "banish", strlen(command)) == 0))
- strcpy(command, "ban");
- else if ((strncmp(command, "banadd", 4) == 0 && strncmp(command, "banadd", strlen(command)) == 0) || // not 1 letter command: 'ba' or 'bs'? 'banadd' or 'banset' ?
- strcmp(command, "ba") == 0)
- strcpy(command, "banadd");
- else if ((strncmp(command, "banset", 4) == 0 && strncmp(command, "banset", strlen(command)) == 0) || // not 1 letter command: 'ba' or 'bs'? 'banadd' or 'banset' ?
- strcmp(command, "bs") == 0)
- strcpy(command, "banset");
- else if (strncmp(command, "block", 2) == 0
- && strncmp(command, "block", strlen(command)) == 0)
- strcpy(command, "block");
- else if (strncmp(command, "check", 2) == 0 && strncmp(command, "check", strlen(command)) == 0) // not 1 letter command: 'check' or 'create'?
- strcpy(command, "check");
- else if (strncmp(command, "create", 2) == 0 && strncmp(command, "create", strlen(command)) == 0) // not 1 letter command: 'check' or 'create'?
- strcpy(command, "create");
- else if (strncmp(command, "delete", 1) == 0
- && strncmp(command, "delete", strlen(command)) == 0)
- strcpy(command, "delete");
- else if ((strncmp(command, "email", 2) == 0 && strncmp(command, "email", strlen(command)) == 0) || // not 1 letter command: 'email', 'end' or 'exit'?
- (strncmp(command, "e-mail", 2) == 0
- && strncmp(command, "e-mail", strlen(command)) == 0))
- strcpy(command, "email");
- else if (strncmp(command, "getcount", 2) == 0 && strncmp(command, "getcount", strlen(command)) == 0) // not 1 letter command: 'getcount' or 'gm'?
- strcpy(command, "getcount");
-// else if (strncmp(command, "gm", 2) == 0 && strncmp(command, "gm", strlen(command)) == 0) // not 1 letter command: 'getcount' or 'gm'?
-// strcpy(command, "gm");
-// else if (strncmp(command, "id", 2) == 0 && strncmp(command, "id", strlen(command)) == 0) // not 1 letter command: 'id' or 'info'?
-// strcpy(command, "id");
- else if (strncmp(command, "info", 2) == 0 && strncmp(command, "info", strlen(command)) == 0) // not 1 letter command: 'id' or 'info'?
- strcpy(command, "info");
-// else if (strncmp(command, "kami", 4) == 0 && strncmp(command, "kami", strlen(command)) == 0) // only all letters command: 'kami' or 'kamib'?
-// strcpy(command, "kami");
-// else if (strncmp(command, "kamib", 5) == 0 && strncmp(command, "kamib", strlen(command)) == 0) // only all letters command: 'kami' or 'kamib'?
-// strcpy(command, "kamib");
- else if ((strncmp(command, "list", 2) == 0 && strncmp(command, "list", strlen(command)) == 0) || // 'list' is default list command
- strcmp(command, "ls") == 0)
- strcpy(command, "list");
- else if (strncmp(command, "itemfrob", 6) == 0)
- strcpy(command, "itemfrob");
- else if ((strncmp(command, "listban", 5) == 0
- && strncmp(command, "listban", strlen(command)) == 0)
- ||(strncmp(command, "lsban", 3) == 0
- && strncmp(command, "lsban", strlen(command)) == 0)
- || strcmp(command, "lb") == 0)
- strcpy(command, "listban");
- else if ((strncmp(command, "listgm", 5) == 0
- && strncmp(command, "listgm", strlen(command)) == 0)
- ||(strncmp(command, "lsgm", 3) == 0
- && strncmp(command, "lsgm", strlen(command)) == 0)
- || strcmp(command, "lg") == 0)
- strcpy(command, "listgm");
- else if ((strncmp(command, "listok", 5) == 0
- && strncmp(command, "listok", strlen(command)) == 0)
- ||(strncmp(command, "lsok", 3) == 0
- && strncmp(command, "lsok", strlen(command)) == 0)
- || strcmp(command, "lo") == 0)
- strcpy(command, "listok");
- else if (strncmp(command, "memo", 1) == 0
- && strncmp(command, "memo", strlen(command)) == 0)
- strcpy(command, "memo");
- else if (strncmp(command, "name", 1) == 0
- && strncmp(command, "name", strlen(command)) == 0)
- strcpy(command, "name");
- else if ((strncmp(command, "password", 1) == 0
- && strncmp(command, "password", strlen(command)) == 0)
- || strcmp(command, "passwd") == 0)
- strcpy(command, "password");
- else if (strncmp(command, "reloadgm", 1) == 0
- && strncmp(command, "reloadgm", strlen(command)) == 0)
- strcpy(command, "reloadgm");
- else if (strncmp(command, "search", 3) == 0 && strncmp(command, "search", strlen(command)) == 0) // not 1 letter command: 'search', 'state' or 'sex'?
- strcpy(command, "search"); // not 2 letters command: 'search' or 'sex'?
-// else if (strncmp(command, "sex", 3) == 0 && strncmp(command, "sex", strlen(command)) == 0) // not 1 letter command: 'search', 'state' or 'sex'?
-// strcpy(command, "sex"); // not 2 letters command: 'search' or 'sex'?
- else if (strncmp(command, "state", 2) == 0 && strncmp(command, "state", strlen(command)) == 0) // not 1 letter command: 'search', 'state' or 'sex'?
- strcpy(command, "state");
- else if ((strncmp(command, "timeadd", 5) == 0 && strncmp(command, "timeadd", strlen(command)) == 0) || // not 1 letter command: 'ta' or 'ts'? 'timeadd' or 'timeset'?
- strcmp(command, "ta") == 0)
- strcpy(command, "timeadd");
- else if ((strncmp(command, "timeset", 5) == 0 && strncmp(command, "timeset", strlen(command)) == 0) || // not 1 letter command: 'ta' or 'ts'? 'timeadd' or 'timeset'?
- strcmp(command, "ts") == 0)
- strcpy(command, "timeset");
- else if ((strncmp(command, "unban", 5) == 0
- && strncmp(command, "unban", strlen(command)) == 0)
- ||(strncmp(command, "unbanish", 4) == 0
- && strncmp(command, "unbanish", strlen(command)) == 0))
- strcpy(command, "unban");
- else if (strncmp(command, "unblock", 4) == 0
- && strncmp(command, "unblock", strlen(command)) == 0)
- strcpy(command, "unblock");
- else if (strncmp(command, "version", 1) == 0
- && strncmp(command, "version", strlen(command)) == 0)
- strcpy(command, "version");
- else if (strncmp(command, "who", 1) == 0
- && strncmp(command, "who", strlen(command)) == 0)
- strcpy(command, "who");
-// quit
- else if (strncmp(command, "quit", 1) == 0
- && strncmp(command, "quit", strlen(command)) == 0)
- strcpy(command, "quit");
- else if (strncmp(command, "exit", 2) == 0 && strncmp(command, "exit", strlen(command)) == 0) // not 1 letter command: 'email', 'end' or 'exit'?
- strcpy(command, "exit");
- else if (strncmp(command, "end", 2) == 0 && strncmp(command, "end", strlen(command)) == 0) // not 1 letter command: 'email', 'end' or 'exit'?
- strcpy(command, "end");
-
- return 0;
+ return extract(one, first) && qsplit(src, rest...);
}
//-----------------------------------------
// Sub-function: Display commands of ladmin
//-----------------------------------------
static
-void display_help(const char *param)
+void display_help(ZString param)
{
- char command[1023] {};
- int i;
-
- if (sscanf(param, "%s ", command) < 1 || strlen(command) == 0)
- strcpy(command, ""); // any value that is not a command
-
- if (command[0] == '?')
- {
- strcpy(command, "help");
- }
+ XString command = param.xislice_h(std::find(param.begin(), param.end(), ' '));
- // lowercase for command
- for (i = 0; command[i]; i++)
- command[i] = tolower(command[i]);
-
- // Analyse of the command
- check_command(command); // give complete name to the command
+ if (command.startswith('?'))
+ command = "help";
LADMIN_LOG("Displaying of the commands or a command.\n");
- if (strcmp(command, "help") == 0)
+ if (command == "help")
{
PRINTF("help/?\n");
PRINTF(" Display the description of the commands\n");
PRINTF("help/? [command]\n");
PRINTF(" Display the description of the specified command\n");
-// general commands
}
- else if (strcmp(command, "add") == 0)
+ else if (command == "add")
{
PRINTF("add <account_name> <sex> <password>\n");
PRINTF(" Create an account with the default email (a@a.com).\n");
@@ -561,13 +336,13 @@ void display_help(const char *param)
PRINTF(" the input is done without displaying of the pressed keys.\n");
PRINTF(" <example> add testname Male testpass\n");
}
- else if (strcmp(command, "ban") == 0)
+ else if (command == "ban")
{
PRINTF("ban/banish yyyy/mm/dd hh:mm:ss <account name>\n");
PRINTF(" Changes the final date of a banishment of an account.\n");
PRINTF(" Like banset, but <account name> is at end.\n");
}
- else if (strcmp(command, "banadd") == 0)
+ else if (command == "banadd")
{
PRINTF("banadd <account_name> <modifier>\n");
PRINTF(" Adds or substracts time from the final date of a banishment of an account.\n");
@@ -586,7 +361,7 @@ void display_help(const char *param)
PRINTF("NOTE: If you modify the final date of a non-banished account,\n");
PRINTF(" you fix the final date to (actual time +- adjustments)\n");
}
- else if (strcmp(command, "banset") == 0)
+ else if (command == "banset")
{
PRINTF("banset <account_name> yyyy/mm/dd [hh:mm:ss]\n");
PRINTF(" Changes the final date of a banishment of an account.\n");
@@ -594,13 +369,13 @@ void display_help(const char *param)
PRINTF("banset <account_name> 0\n");
PRINTF(" Set a non-banished account (0 = unbanished).\n");
}
- else if (strcmp(command, "block") == 0)
+ else if (command == "block")
{
PRINTF("block <account name>\n");
PRINTF(" Set state 5 (You have been blocked by the GM Team) to an account.\n");
PRINTF(" This command works like state <account_name> 5.\n");
}
- else if (strcmp(command, "check") == 0)
+ else if (command == "check")
{
PRINTF("check <account_name> <password>\n");
PRINTF(" Check the validity of a password for an account.\n");
@@ -608,56 +383,56 @@ void display_help(const char *param)
PRINTF(" It's the only method you have to know if a password is correct.\n");
PRINTF(" The other method is to have a ('physical') access to the accounts file.\n");
}
- else if (strcmp(command, "create") == 0)
+ else if (command == "create")
{
PRINTF("create <account_name> <sex> <email> <password>\n");
PRINTF(" Like the 'add' command, but with e-mail moreover.\n");
PRINTF(" <example> create testname Male my@mail.com testpass\n");
}
- else if (strcmp(command, "delete") == 0)
+ else if (command == "delete")
{
PRINTF("del <account name>\n");
PRINTF(" Remove an account.\n");
PRINTF(" This order requires confirmation. After confirmation, the account is deleted.\n");
}
- else if (strcmp(command, "email") == 0)
+ else if (command == "email")
{
PRINTF("email <account_name> <email>\n");
PRINTF(" Modify the e-mail of an account.\n");
}
- else if (strcmp(command, "getcount") == 0)
+ else if (command == "getcount")
{
PRINTF("getcount\n");
PRINTF(" Give the number of players online on all char-servers.\n");
}
- else if (strcmp(command, "gm") == 0)
+ else if (command == "gm")
{
PRINTF("gm <account_name> [GM_level]\n");
PRINTF(" Modify the GM level of an account.\n");
PRINTF(" Default value remove GM level (GM level = 0).\n");
PRINTF(" <example> gm testname 80\n");
}
- else if (strcmp(command, "id") == 0)
+ else if (command == "id")
{
PRINTF("id <account name>\n");
PRINTF(" Give the id of an account.\n");
}
- else if (strcmp(command, "info") == 0)
+ else if (command == "info")
{
PRINTF("info <account_id>\n");
PRINTF(" Display complete information of an account.\n");
}
- else if (strcmp(command, "kami") == 0)
+ else if (command == "kami")
{
PRINTF("kami <message>\n");
PRINTF(" Sends a broadcast message on all map-server (in yellow).\n");
}
- else if (strcmp(command, "kamib") == 0)
+ else if (command == "kamib")
{
PRINTF("kamib <message>\n");
PRINTF(" Sends a broadcast message on all map-server (in blue).\n");
}
- else if (strcmp(command, "list") == 0)
+ else if (command == "list")
{
PRINTF("list/ls [start_id [end_id]]\n");
PRINTF(" Display a list of accounts.\n");
@@ -665,67 +440,64 @@ void display_help(const char *param)
PRINTF(" Research by name is not possible with this command.\n");
PRINTF(" <example> list 10 9999999\n");
}
- else if (strcmp(command, "itemfrob") == 0)
+ else if (command == "itemfrob")
{
PRINTF("itemfrob <source-id> <dest-id>\n");
PRINTF(" Translates item IDs for all accounts.\n");
PRINTF(" Any items matching the source item ID will be mapped to the dest-id.\n");
PRINTF(" <example> itemfrob 500 700\n");
}
- else if (strcmp(command, "listban") == 0)
+ else if (command == "listban")
{
PRINTF("listBan/lsBan [start_id [end_id]]\n");
PRINTF(" Like list/ls, but only for accounts with state or banished.\n");
}
- else if (strcmp(command, "listgm") == 0)
+ else if (command == "listgm")
{
PRINTF("listGM/lsGM [start_id [end_id]]\n");
PRINTF(" Like list/ls, but only for GM accounts.\n");
}
- else if (strcmp(command, "listok") == 0)
+ else if (command == "listok")
{
PRINTF("listOK/lsOK [start_id [end_id]]\n");
PRINTF(" Like list/ls, but only for accounts without state and not banished.\n");
}
- else if (strcmp(command, "memo") == 0)
+ else if (command == "memo")
{
PRINTF("memo <account_name> <memo>\n");
PRINTF(" Modify the memo of an account.\n");
PRINTF(" 'memo': it can have until 253 characters (with spaces or not).\n");
}
- else if (strcmp(command, "name") == 0)
+ else if (command == "name")
{
PRINTF("name <account_id>\n");
PRINTF(" Give the name of an account.\n");
}
- else if (strcmp(command, "password") == 0)
+ else if (command == "password")
{
PRINTF("passwd <account_name> <new_password>\n");
PRINTF(" Change the password of an account.\n");
PRINTF(" When new password is omitted,\n");
PRINTF(" the input is done without displaying of the pressed keys.\n");
}
- else if (strcmp(command, "reloadgm") == 0)
+ else if (command == "reloadgm")
{
PRINTF("reloadGM\n");
PRINTF(" Reload GM configuration file\n");
}
- else if (strcmp(command, "search") == 0)
+ else if (command == "search")
{
PRINTF("search <expression>\n");
PRINTF(" Seek accounts.\n");
PRINTF(" Displays the accounts whose names correspond.\n");
-// PRINTF("search -r/-e/--expr/--regex <expression>\n");
-// PRINTF(" Seek accounts by regular expression.\n");
-// PRINTF(" Displays the accounts whose names correspond.\n");
}
- else if (strcmp(command, "sex") == 0)
+ else if (command == "sex")
{
PRINTF("sex <account_name> <sex>\n");
PRINTF(" Modify the sex of an account.\n");
PRINTF(" <example> sex testname Male\n");
}
- else if (strcmp(command, "state") == 0)
+ else if (command == "state")
{
PRINTF("state <account_name> <new_state> <error_message_#7>\n");
PRINTF(" Change the state of an account.\n");
@@ -746,7 +518,7 @@ void display_help(const char *param)
PRINTF(" 'error_message_#7': message of the code error 6\n");
PRINTF(" = Your are Prohibited to log in until... (packet 0x006a)\n");
}
- else if (strcmp(command, "timeadd") == 0)
+ else if (command == "timeadd")
{
PRINTF("timeadd <account_name> <modifier>\n");
PRINTF(" Adds or substracts time from the validity limit of an account.\n");
@@ -766,7 +538,7 @@ void display_help(const char *param)
PRINTF(" If you want modify it, you want probably create a limited validity limit.\n");
PRINTF(" So, at first, you must set the validity limit to a date/time.\n");
}
- else if (strcmp(command, "timeadd") == 0)
+ else if (command == "timeadd")
{
PRINTF("timeset <account_name> yyyy/mm/dd [hh:mm:ss]\n");
PRINTF(" Changes the validity limit of an account.\n");
@@ -774,42 +546,40 @@ void display_help(const char *param)
PRINTF("timeset <account_name> 0\n");
PRINTF(" Gives an unlimited validity limit (0 = unlimited).\n");
}
- else if (strcmp(command, "unban") == 0)
+ else if (command == "unban")
{
PRINTF("unban/unbanish <account name>\n");
PRINTF(" Remove the banishment of an account.\n");
PRINTF(" This command works like banset <account_name> 0.\n");
}
- else if (strcmp(command, "unblock") == 0)
+ else if (command == "unblock")
{
PRINTF("unblock <account name>\n");
PRINTF(" Set state 0 (Account ok) to an account.\n");
PRINTF(" This command works like state <account_name> 0.\n");
}
- else if (strcmp(command, "version") == 0)
+ else if (command == "version")
{
PRINTF("version\n");
PRINTF(" Display the version of the login-server.\n");
}
- else if (strcmp(command, "who") == 0)
+ else if (command == "who")
{
PRINTF("who <account name>\n");
PRINTF(" Displays complete information of an account.\n");
-// quit
}
- else if (strcmp(command, "quit") == 0 ||
- strcmp(command, "exit") == 0 ||
- strcmp(command, "end") == 0)
+ else if (command == "quit"
+ || command == "exit"
+ || command == "end")
{
PRINTF("quit/end/exit\n");
PRINTF(" End of the program of administration.\n");
-// unknown command
}
else
{
- if (strlen(command) > 0)
+ if (command)
PRINTF("Unknown command [%s] for help. Displaying of all commands.\n",
- command);
+ FString(command));
PRINTF(" help/? -- Display this help\n");
PRINTF(" help/? [command] -- Display the help of the command\n");
PRINTF(" add <account_name> <sex> <password> -- Create an account with default email\n");
@@ -842,7 +612,6 @@ void display_help(const char *param)
PRINTF(" quit/end/exit -- End of the program of administation\n");
PRINTF(" reloadGM -- Reload GM configuration file\n");
PRINTF(" search <expression> -- Seek accounts\n");
-// PRINTF(" search -e/-r/--expr/--regex <expressn> -- Seek accounts by regular-expression\n");
PRINTF(" sex <nomcompte> <sexe> -- Modify the sex of an account\n");
PRINTF(" state <account_name> <new_state> <error_message_#7> -- Change the state\n");
PRINTF(" timeadd/ta <account_name> <modifier> -- Add or substract time from the\n");
@@ -862,195 +631,93 @@ void display_help(const char *param)
// Sub-function: add an account
//-----------------------------
static
-int addaccount(const char *param, int emailflag)
+void addaccount(ZString param, int emailflag)
{
- char name[1023] {};
- char sex[1023] {};
- char email[1023] {};
- char password[1023] {};
+ AccountName name;
+ VString<1> sex_;
+ XString email_;
+ AccountPass password;
if (emailflag == 0)
- { // add command
- if (sscanf(param, "\"%[^\"]\" %s %[^\r\n]", name, sex, password) < 2 && // password can be void
- sscanf(param, "'%[^']' %s %[^\r\n]", name, sex, password) < 2 && // password can be void
- sscanf(param, "%s %s %[^\r\n]", name, sex, password) < 2)
- { // password can be void
+ {
+ // add command
+ if (!qsplit(param, &name, &sex_, &password))
+ {
PRINTF("Please input an account name, a sex and a password.\n");
PRINTF("<example> add testname Male testpass\n");
LADMIN_LOG("Incomplete parameters to create an account ('add' command).\n");
- return 136;
+ return;
}
- strcpy(email, "a@a.com"); // default email
+ email_ = DEFAULT_EMAIL;
}
else
- { // 1: create command
- if (sscanf(param, "\"%[^\"]\" %s %s %[^\r\n]", name, sex, email, password) < 3 && // password can be void
- sscanf(param, "'%[^']' %s %s %[^\r\n]", name, sex, email, password) < 3 && // password can be void
- sscanf(param, "%s %s %s %[^\r\n]", name, sex, email,
- password) < 3)
- { // password can be void
+ {
+ // 1: create command
+ if (!qsplit(param, &name, &sex_, &email_, &password))
+ {
PRINTF("Please input an account name, a sex and a password.\n");
PRINTF("<example> create testname Male my@mail.com testpass\n");
LADMIN_LOG("Incomplete parameters to create an account ('create' command).\n");
- return 136;
+ return;
}
}
- if (verify_accountname(name) == 0)
- {
- return 102;
- }
+ char sex = sex_.front();
+ if (!name.is_print())
+ return;
- sex[0] = toupper(sex[0]);
- if (strchr("MF", sex[0]) == NULL)
+ if (XString("MF").contains(sex))
{
- PRINTF("Illegal gender [%s]. Please input M or F.\n", sex);
- LADMIN_LOG("Illegal gender [%s]. Please input M or F.\n",
- sex);
- return 103;
+ PRINTF("Illegal gender [%c]. Please input M or F.\n", sex);
+ LADMIN_LOG("Illegal gender [%c]. Please input M or F.\n", sex);
+ return;
}
- if (strlen(email) < 3)
- {
- PRINTF("Email is too short [%s]. Please input a valid e-mail.\n",
- email);
- LADMIN_LOG("Email is too short [%s]. Please input a valid e-mail.\n",
- email);
- return 109;
- }
- if (strlen(email) > 39)
- {
- PRINTF("Email is too long [%s]. Please input an e-mail with 39 bytes at the most.\n",
- email);
- LADMIN_LOG("Email is too long [%s]. Please input an e-mail with 39 bytes at the most.\n",
- email);
- return 109;
- }
- if (e_mail_check(email) == 0)
+ if (!e_mail_check(email_))
{
PRINTF("Invalid email [%s]. Please input a valid e-mail.\n",
- email);
+ FString(email_));
LADMIN_LOG("Invalid email [%s]. Please input a valid e-mail.\n",
- email);
- return 109;
+ FString(email_));
+ return;
}
+ AccountEmail email = stringish<AccountEmail>(email_);
- if (strlen(password) == 0)
- {
- if (typepasswd(password) == 0)
- return 108;
- }
- if (verify_password(password) == 0)
- return 104;
+ if (!password.is_print())
+ return;
LADMIN_LOG("Request to login-server to create an account.\n");
WFIFOW(login_fd, 0) = 0x7930;
WFIFO_STRING(login_fd, 2, name, 24);
WFIFO_STRING(login_fd, 26, password, 24);
- WFIFOB(login_fd, 50) = sex[0];
+ WFIFOB(login_fd, 50) = sex;
WFIFO_STRING(login_fd, 51, email, 40);
WFIFOSET(login_fd, 91);
bytes_to_read = 1;
-
- return 0;
}
//---------------------------------------------------------------------------------
// Sub-function: Add/substract time to the final date of a banishment of an account
//---------------------------------------------------------------------------------
static
-int banaddaccount(const char *param)
+void banaddaccount(ZString param)
{
- char name[1023] {};
- char modif[1023] {};
- int year, month, day, hour, minute, second;
- const char *p_modif;
- int value, i;
-
- year = month = day = hour = minute = second = 0;
+ AccountName name;
+ HumanTimeDiff modif {};
- if (sscanf(param, "\"%[^\"]\" %[^\r\n]", name, modif) < 2 &&
- sscanf(param, "'%[^']' %[^\r\n]", name, modif) < 2 &&
- sscanf(param, "%s %[^\r\n]", name, modif) < 2)
+ if (!qsplit(param, &name, &modif))
{
PRINTF("Please input an account name and a modifier.\n");
PRINTF(" <example>: banadd testname +1m-2mn1s-6y\n");
PRINTF(" this example adds 1 month and 1 second, and substracts 2 minutes\n");
PRINTF(" and 6 years at the same time.\n");
LADMIN_LOG("Incomplete parameters to modify the ban date/time of an account ('banadd' command).\n");
- return 136;
- }
- if (verify_accountname(name) == 0)
- {
- return 102;
- }
-
- // lowercase for modif
- for (i = 0; modif[i]; i++)
- modif[i] = tolower(modif[i]);
- p_modif = modif;
- while (strlen(p_modif) > 0)
- {
- value = atoi(p_modif);
- if (value == 0)
- {
- p_modif++;
- }
- else
- {
- if (p_modif[0] == '-' || p_modif[0] == '+')
- p_modif++;
- while (strlen(p_modif) > 0 && p_modif[0] >= '0'
- && p_modif[0] <= '9')
- {
- p_modif++;
- }
- if (p_modif[0] == 's')
- {
- second = value;
- p_modif++;
- }
- else if (p_modif[0] == 'm' && p_modif[1] == 'n')
- {
- minute = value;
- p_modif += 2;
- }
- else if (p_modif[0] == 'h')
- {
- hour = value;
- p_modif++;
- }
- else if (p_modif[0] == 'd' || p_modif[0] == 'j')
- {
- day = value;
- p_modif += 2;
- }
- else if (p_modif[0] == 'm')
- {
- month = value;
- p_modif++;
- }
- else if (p_modif[0] == 'y' || p_modif[0] == 'a')
- {
- year = value;
- p_modif++;
- }
- else
- {
- p_modif++;
- }
- }
+ return;
}
+ if (!name.is_print())
+ return;
- PRINTF(" year: %d\n", year);
- PRINTF(" month: %d\n", month);
- PRINTF(" day: %d\n", day);
- PRINTF(" hour: %d\n", hour);
- PRINTF(" minute: %d\n", minute);
- PRINTF(" second: %d\n", second);
-
- if (year == 0 && month == 0 && day == 0 && hour == 0 && minute == 0
- && second == 0)
+ if (!modif)
{
PRINTF("Please give an adjustment with this command:\n");
PRINTF(" Adjustment value (-1, 1, +1, etc...)\n");
@@ -1065,59 +732,16 @@ int banaddaccount(const char *param)
PRINTF(" this example adds 1 month and 1 second, and substracts 2 minutes\n");
PRINTF(" and 6 years at the same time.\n");
LADMIN_LOG("No adjustment isn't an adjustment ('banadd' command).\n");
- return 137;
- }
- if (year > 127 || year < -127)
- {
- PRINTF("Please give a correct adjustment for the years (from -127 to 127).\n");
- LADMIN_LOG("Abnormal adjustement for the year ('banadd' command).\n");
- return 137;
- }
- if (month > 255 || month < -255)
- {
- PRINTF("Please give a correct adjustment for the months (from -255 to 255).\n");
- LADMIN_LOG("Abnormal adjustement for the month ('banadd' command).\n");
- return 137;
- }
- if (day > 32767 || day < -32767)
- {
- PRINTF("Please give a correct adjustment for the days (from -32767 to 32767).\n");
- LADMIN_LOG("Abnormal adjustement for the days ('banadd' command).\n");
- return 137;
- }
- if (hour > 32767 || hour < -32767)
- {
- PRINTF("Please give a correct adjustment for the hours (from -32767 to 32767).\n");
- LADMIN_LOG("Abnormal adjustement for the hours ('banadd' command).\n");
- return 137;
- }
- if (minute > 32767 || minute < -32767)
- {
- PRINTF("Please give a correct adjustment for the minutes (from -32767 to 32767).\n");
- LADMIN_LOG("Abnormal adjustement for the minutes ('banadd' command).\n");
- return 137;
- }
- if (second > 32767 || second < -32767)
- {
- PRINTF("Please give a correct adjustment for the seconds (from -32767 to 32767).\n");
- LADMIN_LOG("Abnormal adjustement for the seconds ('banadd' command).\n");
- return 137;
+ return;
}
LADMIN_LOG("Request to login-server to modify a ban date/time.\n");
WFIFOW(login_fd, 0) = 0x794c;
WFIFO_STRING(login_fd, 2, name, 24);
- WFIFOW(login_fd, 26) = year;
- WFIFOW(login_fd, 28) = month;
- WFIFOW(login_fd, 30) = day;
- WFIFOW(login_fd, 32) = hour;
- WFIFOW(login_fd, 34) = minute;
- WFIFOW(login_fd, 36) = second;
+ WFIFO_STRUCT(login_fd, 24, modif);
WFIFOSET(login_fd, 38);
bytes_to_read = 1;
-
- return 0;
}
//-----------------------------------------------------------------------
@@ -1125,7 +749,7 @@ int banaddaccount(const char *param)
// Set the final date of a banishment of an account
//-----------------------------------------------------------------------
static
-int bansetaccountsub(const char *name, const char *date, const char *time_)
+void bansetaccountsub(AccountName name, XString date, XString time_)
{
int year, month, day, hour, minute, second;
year = month = day = hour = minute = second = 0;
@@ -1134,24 +758,22 @@ int bansetaccountsub(const char *name, const char *date, const char *time_)
TimeT ban_until_time = TimeT();
struct tm tmtime = ban_until_time; // initialize
- if (verify_accountname(name) == 0)
- {
- return 102;
- }
+ if (!name.is_print())
+ return;
- if (atoi(date) != 0 &&
- ((sscanf(date, "%d/%d/%d", &year, &month, &day) < 3 &&
- sscanf(date, "%d-%d-%d", &year, &month, &day) < 3 &&
- sscanf(date, "%d.%d.%d", &year, &month, &day) < 3) ||
- sscanf(time_, "%d:%d:%d", &hour, &minute, &second) < 3))
+ if (date != "0"
+ && ((!extract(date, record<'/'>(&year, &month, &day))
+ && !extract(date, record<'-'>(&year, &month, &day))
+ && !extract(date, record<'.'>(&year, &month, &day)))
+ || !extract(time_, record<':'>(&hour, &minute, &second))))
{
PRINTF("Please input a date and a time (format: yyyy/mm/dd hh:mm:ss).\n");
PRINTF("You can imput 0 instead of if you use 'banset' command.\n");
LADMIN_LOG("Invalid format for the date/time ('banset' or 'ban' command).\n");
- return 102;
+ return;
}
- if (atoi(date) == 0)
+ if (date == "0")
{
ban_until_time = TimeT();
}
@@ -1169,40 +791,40 @@ int bansetaccountsub(const char *name, const char *date, const char *time_)
{
PRINTF("Please give a correct value for the month (from 1 to 12).\n");
LADMIN_LOG("Invalid month for the date ('banset' or 'ban' command).\n");
- return 102;
+ return;
}
month = month - 1;
if (day < 1 || day > 31)
{
PRINTF("Please give a correct value for the day (from 1 to 31).\n");
LADMIN_LOG("Invalid day for the date ('banset' or 'ban' command).\n");
- return 102;
+ return;
}
if (((month == 3 || month == 5 || month == 8 || month == 10)
- && day > 30) ||(month == 1 && day > 29))
+ && day > 30) || (month == 1 && day > 29))
{
PRINTF("Please give a correct value for a day of this month (%d).\n",
month);
LADMIN_LOG("Invalid day for this month ('banset' or 'ban' command).\n");
- return 102;
+ return;
}
if (hour < 0 || hour > 23)
{
PRINTF("Please give a correct value for the hour (from 0 to 23).\n");
LADMIN_LOG("Invalid hour for the time ('banset' or 'ban' command).\n");
- return 102;
+ return;
}
if (minute < 0 || minute > 59)
{
PRINTF("Please give a correct value for the minutes (from 0 to 59).\n");
LADMIN_LOG("Invalid minute for the time ('banset' or 'ban' command).\n");
- return 102;
+ return;
}
if (second < 0 || second > 59)
{
PRINTF("Please give a correct value for the seconds (from 0 to 59).\n");
LADMIN_LOG("Invalid second for the time ('banset' or 'ban' command).\n");
- return 102;
+ return;
}
tmtime.tm_year = year;
tmtime.tm_mon = month;
@@ -1218,7 +840,7 @@ int bansetaccountsub(const char *name, const char *date, const char *time_)
PRINTF("Please input a date and a time (format: yyyy/mm/dd hh:mm:ss).\n");
PRINTF("You can imput 0 instead of if you use 'banset' command.\n");
LADMIN_LOG("Invalid date. ('banset' or 'ban' command).\n");
- return 102;
+ return;
}
}
@@ -1229,23 +851,19 @@ int bansetaccountsub(const char *name, const char *date, const char *time_)
WFIFOL(login_fd, 26) = static_cast<time_t>(ban_until_time);
WFIFOSET(login_fd, 30);
bytes_to_read = 1;
-
- return 0;
}
//---------------------------------------------------------------------
// Sub-function: Set the final date of a banishment of an account (ban)
//---------------------------------------------------------------------
static
-int banaccount(const char *param)
+void banaccount(ZString param)
{
- char name[1023] {};
- char date[1023] {};
- char time_[1023] {};
+ AccountName name;
+ XString date;
+ XString time_;
- if (sscanf(param, "%s %s \"%[^\"]\"", date, time_, name) < 3 &&
- sscanf(param, "%s %s '%[^']'", date, time_, name) < 3 &&
- sscanf(param, "%s %s %[^\r\n]", date, time_, name) < 3)
+ if (!qsplit(param, &date, &time_, &name))
{
PRINTF("Please input an account name, a date and a hour.\n");
PRINTF("<example>: banset <account_name> yyyy/mm/dd [hh:mm:ss]\n");
@@ -1254,26 +872,27 @@ int banaccount(const char *param)
PRINTF(" unban/unbanish <account name>\n");
PRINTF(" Default time [hh:mm:ss]: 23:59:59.\n");
LADMIN_LOG("Incomplete parameters to set a ban ('banset' or 'ban' command).\n");
- return 136;
+ return;
}
- return bansetaccountsub(name, date, time_);
+ if (!time_)
+ time_ = "23:59:59";
+
+ bansetaccountsub(name, date, time_);
}
//------------------------------------------------------------------------
// Sub-function: Set the final date of a banishment of an account (banset)
//------------------------------------------------------------------------
static
-int bansetaccount(const char *param)
+void bansetaccount(ZString param)
{
- char name[1023] {};
- char date[1023] {};
- char time_[1023] {};
-
- if (sscanf(param, "\"%[^\"]\" %s %[^\r\n]", name, date, time_) < 2 && // if date = 0, time_ can be void
- sscanf(param, "'%[^']' %s %[^\r\n]", name, date, time_) < 2 && // if date = 0, time_ can be void
- sscanf(param, "%s %s %[^\r\n]", name, date, time_) < 2)
- { // if date = 0, time_ can be void
+ AccountName name;
+ XString date;
+ XString time_;
+
+ if (!qsplit(param, &name, &date, &time_))
+ {
PRINTF("Please input an account name, a date and a hour.\n");
PRINTF("<example>: banset <account_name> yyyy/mm/dd [hh:mm:ss]\n");
PRINTF(" banset <account_name> 0 (0 = un-banished)\n");
@@ -1281,27 +900,24 @@ int bansetaccount(const char *param)
PRINTF(" unban/unbanish <account name>\n");
PRINTF(" Default time [hh:mm:ss]: 23:59:59.\n");
LADMIN_LOG("Incomplete parameters to set a ban ('banset' or 'ban' command).\n");
- return 136;
+ return;
}
- if (time_[0] == '\0')
- strcpy(time_, "23:59:59");
+ if (!time_)
+ time_ = "23:59:59";
- return bansetaccountsub(name, date, time_);
+ bansetaccountsub(name, date, time_);
}
//-------------------------------------------------
// Sub-function: unbanishment of an account (unban)
//-------------------------------------------------
static
-int unbanaccount(const char *param)
+void unbanaccount(ZString param)
{
- char name[1023] {};
+ AccountName name;
- if (strlen(param) == 0 ||
- (sscanf(param, "\"%[^\"]\"", name) < 1 &&
- sscanf(param, "'%[^']'", name) < 1 &&
- sscanf(param, "%[^\r\n]", name) < 1) || strlen(name) == 0)
+ if (!qsplit(param, &name))
{
PRINTF("Please input an account name.\n");
PRINTF("<example>: banset <account_name> yyyy/mm/dd [hh:mm:ss]\n");
@@ -1310,10 +926,10 @@ int unbanaccount(const char *param)
PRINTF(" unban/unbanish <account name>\n");
PRINTF(" Default time [hh:mm:ss]: 23:59:59.\n");
LADMIN_LOG("Incomplete parameters to set a ban ('unban' command).\n");
- return 136;
+ return;
}
- return bansetaccountsub(name, "0", "");
+ bansetaccountsub(name, "0", "");
}
//---------------------------------------------------------
@@ -1321,33 +937,24 @@ int unbanaccount(const char *param)
// (Note: never send back a password with login-server!! security of passwords)
//---------------------------------------------------------
static
-int checkaccount(const char *param)
+void checkaccount(ZString param)
{
- char name[1023] {};
- char password[1023] {};
+ AccountName name;
+ AccountPass password;
- if (sscanf(param, "\"%[^\"]\" %[^\r\n]", name, password) < 1 && // password can be void
- sscanf(param, "'%[^']' %[^\r\n]", name, password) < 1 && // password can be void
- sscanf(param, "%s %[^\r\n]", name, password) < 1)
- { // password can be void
+ if (!qsplit(param, &name, &password))
+ {
PRINTF("Please input an account name.\n");
PRINTF("<example> check testname password\n");
LADMIN_LOG("Incomplete parameters to check the password of an account ('check' command).\n");
- return 136;
+ return;
}
- if (verify_accountname(name) == 0)
- {
- return 102;
- }
+ if (!name.is_print())
+ return;
- if (strlen(password) == 0)
- {
- if (typepasswd(password) == 0)
- return 134;
- }
- if (verify_password(password) == 0)
- return 131;
+ if (!password.is_print())
+ return;
LADMIN_LOG("Request to login-server to check a password.\n");
@@ -1356,53 +963,47 @@ int checkaccount(const char *param)
WFIFO_STRING(login_fd, 26, password, 24);
WFIFOSET(login_fd, 50);
bytes_to_read = 1;
-
- return 0;
}
//------------------------------------------------
// Sub-function: Asking for deletion of an account
//------------------------------------------------
static
-int delaccount(const char *param)
+void delaccount(ZString param)
{
- char name[1023] {};
- char letter;
- int i;
+ AccountName name;
- if (strlen(param) == 0 ||
- (sscanf(param, "\"%[^\"]\"", name) < 1 &&
- sscanf(param, "'%[^']'", name) < 1 &&
- sscanf(param, "%[^\r\n]", name) < 1) || strlen(name) == 0)
+ if (!qsplit(param, &name))
{
PRINTF("Please input an account name.\n");
PRINTF("<example> del testnametodelete\n");
LADMIN_LOG("No name given to delete an account ('delete' command).\n");
- return 136;
+ return;
}
- if (verify_accountname(name) == 0)
- {
- return 102;
- }
+ if (!name.is_print())
+ return;
- char confirm[1023] {};
- while (confirm[0] != 'n'
- && confirm[0] != 'y')
+ char confirm;
+ do
{
PRINTF("\033[1;36m ** Are you really sure to DELETE account [%s]? (y/n) > \033[0m", name);
fflush(stdout);
- strzcpy(confirm, "", sizeof(confirm));
- i = 0;
- while ((letter = getchar()) != '\n')
- confirm[i++] = letter;
+ int seek = getchar();
+ confirm = seek;
+ if (seek == EOF)
+ confirm = 'n';
+ else
+ while (seek != '\n' && seek != EOF)
+ seek = getchar();
}
+ while (!XString("yn").contains(confirm));
- if (confirm[0] == 'n')
+ if (confirm == 'n')
{
PRINTF("Deletion canceled.\n");
LADMIN_LOG("Deletion canceled by user ('delete' command).\n");
- return 121;
+ return;
}
LADMIN_LOG("Request to login-server to delete an acount.\n");
@@ -1411,58 +1012,36 @@ int delaccount(const char *param)
WFIFO_STRING(login_fd, 2, name, 24);
WFIFOSET(login_fd, 26);
bytes_to_read = 1;
-
- return 0;
}
//----------------------------------------------------------
// Sub-function: Asking to modification of an account e-mail
//----------------------------------------------------------
static
-int changeemail(const char *param)
+void changeemail(ZString param)
{
- char name[1023] {};
- char email[1023] {};
-
- if (sscanf(param, "\"%[^\"]\" %[^\r\n]", name, email) < 2 &&
- sscanf(param, "'%[^']' %[^\r\n]", name, email) < 2 &&
- sscanf(param, "%s %[^\r\n]", name, email) < 2)
+ AccountName name;
+ XString email_;
+ if (!qsplit(param, &name, &email_))
{
PRINTF("Please input an account name and an email.\n");
PRINTF("<example> email testname newemail\n");
LADMIN_LOG("Incomplete parameters to change the email of an account ('email' command).\n");
- return 136;
+ return;
}
- if (verify_accountname(name) == 0)
- {
- return 102;
- }
+ if (!name.is_print())
+ return;
- if (strlen(email) < 3)
- {
- PRINTF("Email is too short [%s]. Please input a valid e-mail.\n",
- email);
- LADMIN_LOG("Email is too short [%s]. Please input a valid e-mail.\n",
- email);
- return 109;
- }
- if (strlen(email) > 39)
- {
- PRINTF("Email is too long [%s]. Please input an e-mail with 39 bytes at the most.\n",
- email);
- LADMIN_LOG("Email is too long [%s]. Please input an e-mail with 39 bytes at the most.\n",
- email);
- return 109;
- }
- if (e_mail_check(email) == 0)
+ if (!e_mail_check(email_))
{
PRINTF("Invalid email [%s]. Please input a valid e-mail.\n",
- email);
+ FString(email_));
LADMIN_LOG("Invalid email [%s]. Please input a valid e-mail.\n",
- email);
- return 109;
+ FString(email_));
+ return;
}
+ AccountEmail email = stringish<AccountEmail>(email_);
LADMIN_LOG("Request to login-server to change an email.\n");
@@ -1471,48 +1050,40 @@ int changeemail(const char *param)
WFIFO_STRING(login_fd, 26, email, 40);
WFIFOSET(login_fd, 66);
bytes_to_read = 1;
-
- return 0;
}
//-----------------------------------------------------
// Sub-function: Asking of the number of online players
//-----------------------------------------------------
static
-int getlogincount(void)
+void getlogincount(void)
{
LADMIN_LOG("Request to login-server to obtain the # of online players.\n");
WFIFOW(login_fd, 0) = 0x7938;
WFIFOSET(login_fd, 2);
bytes_to_read = 1;
-
- return 0;
}
//----------------------------------------------------------
// Sub-function: Asking to modify the GM level of an account
//----------------------------------------------------------
static
-int changegmlevel(const char *param)
+void changegmlevel(ZString param)
{
- char name[1023] {};
+ AccountName name;
int GM_level = 0;
- if (sscanf(param, "\"%[^\"]\" %d", name, &GM_level) < 1 &&
- sscanf(param, "'%[^']' %d", name, &GM_level) < 1 &&
- sscanf(param, "%s %d", name, &GM_level) < 1)
+ if (!qsplit(param, &name, &GM_level))
{
PRINTF("Please input an account name and a GM level.\n");
PRINTF("<example> gm testname 80\n");
LADMIN_LOG("Incomplete parameters to change the GM level of an account ('gm' command).\n");
- return 136;
+ return;
}
- if (verify_accountname(name) == 0)
- {
- return 102;
- }
+ if (!name.is_print())
+ return;
if (GM_level < 0 || GM_level > 99)
{
@@ -1520,7 +1091,7 @@ int changegmlevel(const char *param)
GM_level);
LADMIN_LOG("Illegal GM level [%d]. The value can be from 0 to 99.\n",
GM_level);
- return 103;
+ return;
}
LADMIN_LOG("Request to login-server to change a GM level.\n");
@@ -1530,32 +1101,27 @@ int changegmlevel(const char *param)
WFIFOB(login_fd, 26) = GM_level;
WFIFOSET(login_fd, 27);
bytes_to_read = 1;
-
- return 0;
}
//---------------------------------------------
// Sub-function: Asking to obtain an account id
//---------------------------------------------
static
-int idaccount(const char *param)
+void idaccount(ZString param)
{
- char name[1023] {};
+ AccountName name;
- if (strlen(param) == 0 ||
- (sscanf(param, "\"%[^\"]\"", name) < 1 &&
- sscanf(param, "'%[^']'", name) < 1 &&
- sscanf(param, "%[^\r\n]", name) < 1) || strlen(name) == 0)
+ if (!qsplit(param, &name))
{
PRINTF("Please input an account name.\n");
PRINTF("<example> id testname\n");
LADMIN_LOG("No name given to search an account id ('id' command).\n");
- return 136;
+ return;
}
- if (verify_accountname(name) == 0)
+ if (!name.is_print())
{
- return 102;
+ return;
}
LADMIN_LOG("Request to login-server to know an account id.\n");
@@ -1564,21 +1130,19 @@ int idaccount(const char *param)
WFIFO_STRING(login_fd, 2, name, 24);
WFIFOSET(login_fd, 26);
bytes_to_read = 1;
-
- return 0;
}
//----------------------------------------------------------------------------
// Sub-function: Asking to displaying information about an account (by its id)
//----------------------------------------------------------------------------
static
-int infoaccount(int account_id)
+void infoaccount(int account_id)
{
if (account_id < 0)
{
PRINTF("Please input a positive value for the id.\n");
LADMIN_LOG("Negative value was given to found the account.\n");
- return 136;
+ return;
}
LADMIN_LOG("Request to login-server to obtain information about an account (by its id).\n");
@@ -1587,40 +1151,31 @@ int infoaccount(int account_id)
WFIFOL(login_fd, 2) = account_id;
WFIFOSET(login_fd, 6);
bytes_to_read = 1;
-
- return 0;
}
//---------------------------------------
// Sub-function: Send a broadcast message
//---------------------------------------
static
-int sendbroadcast(short type, const char *message)
+void sendbroadcast(ZString message)
{
- if (strlen(message) == 0)
+ if (!message)
{
PRINTF("Please input a message.\n");
- if (type == 0)
{
PRINTF("<example> kami a message\n");
}
- else
- {
- PRINTF("<example> kamib a message\n");
- }
- LADMIN_LOG("The message is void ('kami(b)' command).\n");
- return 136;
+ LADMIN_LOG("The message is void ('kami' command).\n");
+ return;
}
WFIFOW(login_fd, 0) = 0x794e;
- WFIFOW(login_fd, 2) = type;
- size_t len = strlen(message) + 1;
+ WFIFOW(login_fd, 2) = 0;
+ size_t len = message.size() + 1;
WFIFOL(login_fd, 4) = len;
WFIFO_STRING(login_fd, 8, message, len);
WFIFOSET(login_fd, 8 + len);
bytes_to_read = 1;
-
- return 0;
}
@@ -1628,11 +1183,9 @@ int sendbroadcast(short type, const char *message)
// Sub-function: Asking to Displaying of the accounts list
//--------------------------------------------------------
static
-int listaccount(char *param, int type)
+void listaccount(ZString param, int type)
{
//int list_first, list_last, list_type; // parameter to display a list of accounts
- int i;
-
list_type = type;
// set default values
@@ -1645,8 +1198,6 @@ int listaccount(char *param, int type)
}
else if (list_type == 2)
{ // if search
- for (i = 0; param[i]; i++)
- param[i] = tolower(param[i]);
// get all accounts = use default
}
else if (list_type == 3)
@@ -1658,23 +1209,13 @@ int listaccount(char *param, int type)
// get all accounts = use default
}
else
- { // if list (list_type == 0)
- switch (sscanf(param, "%d %d", &list_first, &list_last))
- {
- case 0:
- // get all accounts = use default
- break;
- case 1:
- list_last = 0;
- // use tests of the following value
- FALLTHROUGH;
- default:
- if (list_first < 0)
- list_first = 0;
- if (list_last < list_first || list_last < 0)
- list_last = 0;
- break;
- }
+ {
+ // if list (list_type == 0)
+ extract(param, record<' '>(&list_first, &list_last));
+ if (list_first < 0)
+ list_first = 0;
+ if (list_last < list_first || list_last < 0)
+ list_last = 0;
}
LADMIN_LOG("Request to login-server to obtain the list of accounts from %d to %d.\n",
@@ -1690,19 +1231,17 @@ int listaccount(char *param, int type)
Iprintf("account_id GM user_name sex count state\n");
Iprintf("-------------------------------------------------------------------------------\n");
list_count = 0;
-
- return 0;
}
//--------------------------------------------------------
// Sub-function: Frobnicate items
//--------------------------------------------------------
static
-int itemfrob(const char *param)
+int itemfrob(ZString param)
{
int source_id, dest_id;
- if (sscanf(param, "%d %d", &source_id, &dest_id) < 2)
+ if (!extract(param, record<' '>(&source_id, &dest_id)))
{
PRINTF("You must provide the source and destination item IDs.\n");
return 1;
@@ -1721,27 +1260,23 @@ int itemfrob(const char *param)
// Sub-function: Asking to modify a memo field
//--------------------------------------------
static
-int changememo(const char *param)
+void changememo(ZString param)
{
- char name[1023] {};
- char memo[1023] {};
+ AccountName name;
+ XString memo;
- if (sscanf(param, "\"%[^\"]\" %[^\r\n]", name, memo) < 1 && // memo can be void
- sscanf(param, "'%[^']' %[^\r\n]", name, memo) < 1 && // memo can be void
- sscanf(param, "%s %[^\r\n]", name, memo) < 1)
- { // memo can be void
+ if (!qsplit(param, &name, &memo) && !qsplit(param, &name))
+ {
PRINTF("Please input an account name and a memo.\n");
PRINTF("<example> memo testname new memo\n");
LADMIN_LOG("Incomplete parameters to change the memo of an account ('email' command).\n");
- return 136;
+ return;
}
- if (verify_accountname(name) == 0)
- {
- return 102;
- }
+ if (!name.is_print())
+ return;
- size_t len = strlen(memo);
+ size_t len = memo.size();
size_t len1 = len + 1;
if (len > 254)
{
@@ -1749,7 +1284,7 @@ int changememo(const char *param)
PRINTF("Please input a memo of 254 bytes at the maximum.\n");
LADMIN_LOG("Email is too long (%zu characters). Please input a memo of 254 bytes at the maximum.\n",
len);
- return 102;
+ return;
}
LADMIN_LOG("Request to login-server to change a memo.\n");
@@ -1760,21 +1295,19 @@ int changememo(const char *param)
WFIFO_STRING(login_fd, 28, memo, len);
WFIFOSET(login_fd, 28 + len1);
bytes_to_read = 1;
-
- return 0;
}
//-----------------------------------------------
// Sub-function: Asking to obtain an account name
//-----------------------------------------------
static
-int nameaccount(int id)
+void nameaccount(int id)
{
if (id < 0)
{
PRINTF("Please input a positive value for the id.\n");
LADMIN_LOG("Negativ id given to search an account name ('name' command).\n");
- return 136;
+ return;
}
LADMIN_LOG("Request to login-server to know an account name.\n");
@@ -1783,8 +1316,6 @@ int nameaccount(int id)
WFIFOL(login_fd, 2) = id;
WFIFOSET(login_fd, 6);
bytes_to_read = 1;
-
- return 0;
}
//------------------------------------------
@@ -1792,33 +1323,26 @@ int nameaccount(int id)
// (Note: never send back a password with login-server!! security of passwords)
//------------------------------------------
static
-int changepasswd(const char *param)
+void changepasswd(ZString param)
{
- char name[1023] {};
- char password[1023] {};
+ AccountName name;
+ AccountPass password;
- if (sscanf(param, "\"%[^\"]\" %[^\r\n]", name, password) < 1 &&
- sscanf(param, "'%[^']' %[^\r\n]", name, password) < 1 &&
- sscanf(param, "%s %[^\r\n]", name, password) < 1)
+ if (!qsplit(param, &name, &password))
{
PRINTF("Please input an account name.\n");
PRINTF("<example> passwd testname newpassword\n");
LADMIN_LOG("Incomplete parameters to change the password of an account ('password' command).\n");
- return 136;
+ return;
}
- if (verify_accountname(name) == 0)
+ if (!name.is_print())
{
- return 102;
+ return;
}
- if (strlen(password) == 0)
- {
- if (typepasswd(password) == 0)
- return 134;
- }
- if (verify_password(password) == 0)
- return 131;
+ if (!password.is_print())
+ return;
LADMIN_LOG("Request to login-server to change a password.\n");
@@ -1827,8 +1351,6 @@ int changepasswd(const char *param)
WFIFO_STRING(login_fd, 26, password, 24);
WFIFOSET(login_fd, 50);
bytes_to_read = 1;
-
- return 0;
}
//----------------------------------------------------------------------
@@ -1836,7 +1358,7 @@ int changepasswd(const char *param)
// this function have no answer
//----------------------------------------------------------------------
static
-int reloadGM(char *params)
+void reloadGM(ZString params)
{
WFIFOW(login_fd, 0) = 0x7955;
WFIFOSET(login_fd, 2);
@@ -1846,52 +1368,45 @@ int reloadGM(char *params)
PRINTF("Request to reload the GM configuration file sended.\n");
PRINTF("Check the actual GM accounts (after reloading):\n");
listaccount(params, 1); // 1: to list only GM
-
- return 180;
}
//-----------------------------------------------------
// Sub-function: Asking to modify the sex of an account
//-----------------------------------------------------
static
-int changesex(const char *param)
+void changesex(ZString param)
{
- char name[1023] {};
- char sex[1023] {};
+ AccountName name;
+ VString<1> sex_;
- if (sscanf(param, "\"%[^\"]\" %[^\r\n]", name, sex) < 2 &&
- sscanf(param, "'%[^']' %[^\r\n]", name, sex) < 2 &&
- sscanf(param, "%s %[^\r\n]", name, sex) < 2)
+ if (!qsplit(param, &name, &sex_))
{
PRINTF("Please input an account name and a sex.\n");
PRINTF("<example> sex testname Male\n");
LADMIN_LOG("Incomplete parameters to change the sex of an account ('sex' command).\n");
- return 136;
+ return;
}
+ char sex = sex_.front();
- if (verify_accountname(name) == 0)
+ if (name.is_print())
{
- return 102;
+ return;
}
- sex[0] = toupper(sex[0]);
- if (strchr("MF", sex[0]) == NULL)
+ if (!XString("MF").contains(sex))
{
- PRINTF("Illegal gender [%s]. Please input M or F.\n", sex);
- LADMIN_LOG("Illegal gender [%s]. Please input M or F.\n",
- sex);
- return 103;
+ PRINTF("Illegal gender [%c]. Please input M or F.\n", sex);
+ LADMIN_LOG("Illegal gender [%c]. Please input M or F.\n", sex);
+ return;
}
LADMIN_LOG("Request to login-server to change a sex.\n");
WFIFOW(login_fd, 0) = 0x793c;
WFIFO_STRING(login_fd, 2, name, 24);
- WFIFOB(login_fd, 26) = sex[0];
+ WFIFOB(login_fd, 26) = sex;
WFIFOSET(login_fd, 27);
bytes_to_read = 1;
-
- return 0;
}
//-------------------------------------------------------------------------
@@ -1899,10 +1414,8 @@ int changesex(const char *param)
// Asking to modify the state of an account
//-------------------------------------------------------------------------
static
-int changestatesub(const char *name, int state, const char *error_message7)
+void changestatesub(AccountName name, int state, XString error_message)
{
- const char *error_message = error_message7;
-
if ((state < 0 || state > 9) && state != 100)
{ // Valid values: 0: ok, or value of the 0x006a packet + 1
PRINTF("Please input one of these states:\n");
@@ -1917,13 +1430,11 @@ int changestatesub(const char *name, int state, const char *error_message7)
PRINTF(" block <account name>\n");
PRINTF(" unblock <account name>\n");
LADMIN_LOG("Invalid value for the state of an account ('state', 'block' or 'unblock' command).\n");
- return 151;
+ return;
}
- if (verify_accountname(name) == 0)
- {
- return 102;
- }
+ if (!name.is_print())
+ return;
if (state != 7)
{
@@ -1931,17 +1442,17 @@ int changestatesub(const char *name, int state, const char *error_message7)
}
else
{
- if (strlen(error_message) < 1)
+ if (error_message.size() < 1)
{
PRINTF("Error message is too short. Please input a message of 1-19 bytes.\n");
LADMIN_LOG("Error message is too short. Please input a message of 1-19 bytes.\n");
- return 102;
+ return;
}
- if (strlen(error_message) > 19)
+ if (error_message.size() > 19)
{
PRINTF("Error message is too long. Please input a message of 1-19 bytes.\n");
LADMIN_LOG("Error message is too long. Please input a message of 1-19 bytes.\n");
- return 102;
+ return;
}
}
@@ -1953,23 +1464,19 @@ int changestatesub(const char *name, int state, const char *error_message7)
WFIFO_STRING(login_fd, 30, error_message, 20);
WFIFOSET(login_fd, 50);
bytes_to_read = 1;
-
- return 0;
}
//-------------------------------------------------------
// Sub-function: Asking to modify the state of an account
//-------------------------------------------------------
static
-int changestate(const char *param)
+void changestate(ZString param)
{
- char name[1023] {};
- char error_message[1023] {};
+ AccountName name;
int state;
+ XString error_message;
- if (sscanf(param, "\"%[^\"]\" %d %[^\r\n]", name, &state, error_message) < 2
- && sscanf(param, "'%[^']' %d %[^\r\n]", name, &state, error_message) < 2
- && sscanf(param, "%s %d %[^\r\n]", name, &state, error_message) < 2)
+ if (!qsplit(param, &name, &state, &error_message) && !qsplit(param, &name, &state))
{
PRINTF("Please input an account name and a state.\n");
PRINTF("<examples> state testname 5\n");
@@ -1977,24 +1484,21 @@ int changestate(const char *param)
PRINTF(" block <account name>\n");
PRINTF(" unblock <account name>\n");
LADMIN_LOG("Incomplete parameters to change the state of an account ('state' command).\n");
- return 136;
+ return;
}
- return changestatesub(name, state, error_message);
+ changestatesub(name, state, error_message);
}
//-------------------------------------------
// Sub-function: Asking to unblock an account
//-------------------------------------------
static
-int unblockaccount(const char *param)
+void unblockaccount(ZString param)
{
- char name[1023] {};
+ AccountName name;
- if (strlen(param) == 0 ||
- (sscanf(param, "\"%[^\"]\"", name) < 1 &&
- sscanf(param, "'%[^']'", name) < 1 &&
- sscanf(param, "%[^\r\n]", name) < 1) || strlen(name) == 0)
+ if (!qsplit(param, &name))
{
PRINTF("Please input an account name.\n");
PRINTF("<examples> state testname 5\n");
@@ -2002,24 +1506,21 @@ int unblockaccount(const char *param)
PRINTF(" block <account name>\n");
PRINTF(" unblock <account name>\n");
LADMIN_LOG("Incomplete parameters to change the state of an account ('unblock' command).\n");
- return 136;
+ return;
}
- return changestatesub(name, 0, "-"); // state 0, no error message
+ changestatesub(name, 0, "-"); // state 0, no error message
}
//-------------------------------------------
// Sub-function: Asking to unblock an account
//-------------------------------------------
static
-int blockaccount(const char *param)
+void blockaccount(ZString param)
{
- char name[1023] {};
+ AccountName name;
- if (strlen(param) == 0 ||
- (sscanf(param, "\"%[^\"]\"", name) < 1 &&
- sscanf(param, "'%[^']'", name) < 1 &&
- sscanf(param, "%[^\r\n]", name) < 1) || strlen(name) == 0)
+ if (!qsplit(param, &name))
{
PRINTF("Please input an account name.\n");
PRINTF("<examples> state testname 5\n");
@@ -2027,108 +1528,36 @@ int blockaccount(const char *param)
PRINTF(" block <account name>\n");
PRINTF(" unblock <account name>\n");
LADMIN_LOG("Incomplete parameters to change the state of an account ('block' command).\n");
- return 136;
+ return;
}
- return changestatesub(name, 5, "-"); // state 5, no error message
+ changestatesub(name, 5, "-"); // state 5, no error message
}
//---------------------------------------------------------------------
// Sub-function: Add/substract time to the validity limit of an account
//---------------------------------------------------------------------
static
-int timeaddaccount(const char *param)
+void timeaddaccount(ZString param)
{
- char name[1023] {};
- char modif[1023] {};
- int year, month, day, hour, minute, second;
- const char *p_modif;
- int value, i;
+ AccountName name;
+ HumanTimeDiff modif {};
- year = month = day = hour = minute = second = 0;
-
- if (sscanf(param, "\"%[^\"]\" %[^\r\n]", name, modif) < 2 &&
- sscanf(param, "'%[^']' %[^\r\n]", name, modif) < 2 &&
- sscanf(param, "%s %[^\r\n]", name, modif) < 2)
+ if (!qsplit(param, &name, &modif))
{
PRINTF("Please input an account name and a modifier.\n");
PRINTF(" <example>: timeadd testname +1m-2mn1s-6y\n");
PRINTF(" this example adds 1 month and 1 second, and substracts 2 minutes\n");
PRINTF(" and 6 years at the same time.\n");
LADMIN_LOG("Incomplete parameters to modify a limit time ('timeadd' command).\n");
- return 136;
- }
- if (verify_accountname(name) == 0)
- {
- return 102;
+ return;
}
-
- // lowercase for modif
- for (i = 0; modif[i]; i++)
- modif[i] = tolower(modif[i]);
- p_modif = modif;
- while (strlen(p_modif) > 0)
+ if (name.is_print())
{
- value = atoi(p_modif);
- if (value == 0)
- {
- p_modif++;
- }
- else
- {
- if (p_modif[0] == '-' || p_modif[0] == '+')
- p_modif++;
- while (strlen(p_modif) > 0 && p_modif[0] >= '0'
- && p_modif[0] <= '9')
- {
- p_modif++;
- }
- if (p_modif[0] == 's')
- {
- second = value;
- p_modif++;
- }
- else if (p_modif[0] == 'm' && p_modif[1] == 'n')
- {
- minute = value;
- p_modif += 2;
- }
- else if (p_modif[0] == 'h')
- {
- hour = value;
- p_modif++;
- }
- else if (p_modif[0] == 'd' || p_modif[0] == 'j')
- {
- day = value;
- p_modif += 2;
- }
- else if (p_modif[0] == 'm')
- {
- month = value;
- p_modif++;
- }
- else if (p_modif[0] == 'y' || p_modif[0] == 'a')
- {
- year = value;
- p_modif++;
- }
- else
- {
- p_modif++;
- }
- }
+ return;
}
- PRINTF(" year: %d\n", year);
- PRINTF(" month: %d\n", month);
- PRINTF(" day: %d\n", day);
- PRINTF(" hour: %d\n", hour);
- PRINTF(" minute: %d\n", minute);
- PRINTF(" second: %d\n", second);
-
- if (year == 0 && month == 0 && day == 0 && hour == 0 && minute == 0
- && second == 0)
+ if (!modif)
{
PRINTF("Please give an adjustment with this command:\n");
PRINTF(" Adjustment value (-1, 1, +1, etc...)\n");
@@ -2143,70 +1572,27 @@ int timeaddaccount(const char *param)
PRINTF(" this example adds 1 month and 1 second, and substracts 2 minutes\n");
PRINTF(" and 6 years at the same time.\n");
LADMIN_LOG("No adjustment isn't an adjustment ('timeadd' command).\n");
- return 137;
- }
- if (year > 127 || year < -127)
- {
- PRINTF("Please give a correct adjustment for the years (from -127 to 127).\n");
- LADMIN_LOG("Abnormal adjustement for the year ('timeadd' command).\n");
- return 137;
- }
- if (month > 255 || month < -255)
- {
- PRINTF("Please give a correct adjustment for the months (from -255 to 255).\n");
- LADMIN_LOG("Abnormal adjustement for the month ('timeadd' command).\n");
- return 137;
- }
- if (day > 32767 || day < -32767)
- {
- PRINTF("Please give a correct adjustment for the days (from -32767 to 32767).\n");
- LADMIN_LOG("Abnormal adjustement for the days ('timeadd' command).\n");
- return 137;
- }
- if (hour > 32767 || hour < -32767)
- {
- PRINTF("Please give a correct adjustment for the hours (from -32767 to 32767).\n");
- LADMIN_LOG("Abnormal adjustement for the hours ('timeadd' command).\n");
- return 137;
- }
- if (minute > 32767 || minute < -32767)
- {
- PRINTF("Please give a correct adjustment for the minutes (from -32767 to 32767).\n");
- LADMIN_LOG("Abnormal adjustement for the minutes ('timeadd' command).\n");
- return 137;
- }
- if (second > 32767 || second < -32767)
- {
- PRINTF("Please give a correct adjustment for the seconds (from -32767 to 32767).\n");
- LADMIN_LOG("Abnormal adjustement for the seconds ('timeadd' command).\n");
- return 137;
+ return;
}
LADMIN_LOG("Request to login-server to modify a time limit.\n");
WFIFOW(login_fd, 0) = 0x7950;
WFIFO_STRING(login_fd, 2, name, 24);
- WFIFOW(login_fd, 26) = year;
- WFIFOW(login_fd, 28) = month;
- WFIFOW(login_fd, 30) = day;
- WFIFOW(login_fd, 32) = hour;
- WFIFOW(login_fd, 34) = minute;
- WFIFOW(login_fd, 36) = second;
+ WFIFO_STRUCT(login_fd, 26, modif);
WFIFOSET(login_fd, 38);
bytes_to_read = 1;
-
- return 0;
}
//-------------------------------------------------
// Sub-function: Set a validity limit of an account
//-------------------------------------------------
static
-int timesetaccount(const char *param)
+void timesetaccount(ZString param)
{
- char name[1023] {};
- char date[1023] {};
- char time_[1023] {};
+ AccountName name;
+ XString date;
+ XString time_;
int year, month, day, hour, minute, second;
year = month = day = hour = minute = second = 0;
@@ -2215,38 +1601,33 @@ int timesetaccount(const char *param)
TimeT connect_until_time = TimeT();
struct tm tmtime = connect_until_time; // initialize
- if (sscanf(param, "\"%[^\"]\" %s %[^\r\n]", name, date, time_) < 2 && // if date = 0, time_ can be void
- sscanf(param, "'%[^']' %s %[^\r\n]", name, date, time_) < 2 && // if date = 0, time_ can be void
- sscanf(param, "%s %s %[^\r\n]", name, date, time_) < 2)
- { // if date = 0, time_ can be void
+ if (!qsplit(param, &name, &date, &time_))
+ {
PRINTF("Please input an account name, a date and a hour.\n");
PRINTF("<example>: timeset <account_name> yyyy/mm/dd [hh:mm:ss]\n");
PRINTF(" timeset <account_name> 0 (0 = unlimited)\n");
PRINTF(" Default time [hh:mm:ss]: 23:59:59.\n");
LADMIN_LOG("Incomplete parameters to set a limit time ('timeset' command).\n");
- return 136;
- }
- if (verify_accountname(name) == 0)
- {
- return 102;
+ return;
}
+ if (!name.is_print())
+ return;
- if (time_[0] == '\0')
- strcpy(time_, "23:59:59");
+ if (!time_)
+ time_ = "23:59:59";
- if (atoi(date) != 0 &&
- ((sscanf(date, "%d/%d/%d", &year, &month, &day) < 3 &&
- sscanf(date, "%d-%d-%d", &year, &month, &day) < 3 &&
- sscanf(date, "%d.%d.%d", &year, &month, &day) < 3 &&
- sscanf(date, "%d'%d'%d", &year, &month, &day) < 3) ||
- sscanf(time_, "%d:%d:%d", &hour, &minute, &second) < 3))
+ if (date != "0"
+ && ((!extract(date, record<'/'>(&year, &month, &day))
+ && !extract(date, record<'-'>(&year, &month, &day))
+ && !extract(date, record<'.'>(&year, &month, &day)))
+ || !extract(time_, record<':'>(&hour, &minute, &second))))
{
PRINTF("Please input 0 or a date and a time (format: 0 or yyyy/mm/dd hh:mm:ss).\n");
LADMIN_LOG("Invalid format for the date/time ('timeset' command).\n");
- return 102;
+ return;
}
- if (atoi(date) == 0)
+ if (date == "0")
{
connect_until_time = TimeT();
}
@@ -2264,14 +1645,14 @@ int timesetaccount(const char *param)
{
PRINTF("Please give a correct value for the month (from 1 to 12).\n");
LADMIN_LOG("Invalid month for the date ('timeset' command).\n");
- return 102;
+ return;
}
month = month - 1;
if (day < 1 || day > 31)
{
PRINTF("Please give a correct value for the day (from 1 to 31).\n");
LADMIN_LOG("Invalid day for the date ('timeset' command).\n");
- return 102;
+ return;
}
if (((month == 3 || month == 5 || month == 8 || month == 10)
&& day > 30) ||(month == 1 && day > 29))
@@ -2279,25 +1660,25 @@ int timesetaccount(const char *param)
PRINTF("Please give a correct value for a day of this month (%d).\n",
month);
LADMIN_LOG("Invalid day for this month ('timeset' command).\n");
- return 102;
+ return;
}
if (hour < 0 || hour > 23)
{
PRINTF("Please give a correct value for the hour (from 0 to 23).\n");
LADMIN_LOG("Invalid hour for the time ('timeset' command).\n");
- return 102;
+ return;
}
if (minute < 0 || minute > 59)
{
PRINTF("Please give a correct value for the minutes (from 0 to 59).\n");
LADMIN_LOG("Invalid minute for the time ('timeset' command).\n");
- return 102;
+ return;
}
if (second < 0 || second > 59)
{
PRINTF("Please give a correct value for the seconds (from 0 to 59).\n");
LADMIN_LOG("Invalid second for the time ('timeset' command).\n");
- return 102;
+ return;
}
tmtime.tm_year = year;
tmtime.tm_mon = month;
@@ -2312,7 +1693,7 @@ int timesetaccount(const char *param)
PRINTF("Invalid date.\n");
PRINTF("Please add 0 or a date and a time (format: 0 or yyyy/mm/dd hh:mm:ss).\n");
LADMIN_LOG("Invalid date. ('timeset' command).\n");
- return 102;
+ return;
}
}
@@ -2323,31 +1704,26 @@ int timesetaccount(const char *param)
WFIFOL(login_fd, 26) = static_cast<time_t>(connect_until_time);
WFIFOSET(login_fd, 30);
bytes_to_read = 1;
-
- return 0;
}
//------------------------------------------------------------------------------
// Sub-function: Asking to displaying information about an account (by its name)
//------------------------------------------------------------------------------
static
-int whoaccount(const char *param)
+void whoaccount(ZString param)
{
- char name[1023] {};
+ AccountName name;
- if (strlen(param) == 0 ||
- (sscanf(param, "\"%[^\"]\"", name) < 1 &&
- sscanf(param, "'%[^']'", name) < 1 &&
- sscanf(param, "%[^\r\n]", name) < 1) || strlen(name) == 0)
+ if (!qsplit(param, &name))
{
PRINTF("Please input an account name.\n");
PRINTF("<example> who testname\n");
LADMIN_LOG("No name was given to found the account.\n");
- return 136;
+ return;
}
- if (verify_accountname(name) == 0)
+ if (!name.is_print())
{
- return 102;
+ return;
}
LADMIN_LOG("Request to login-server to obtain information about an account (by its name).\n");
@@ -2356,23 +1732,19 @@ int whoaccount(const char *param)
WFIFO_STRING(login_fd, 2, name, 24);
WFIFOSET(login_fd, 26);
bytes_to_read = 1;
-
- return 0;
}
//--------------------------------------------------------
// Sub-function: Asking of the version of the login-server
//--------------------------------------------------------
static
-int checkloginversion(void)
+void checkloginversion(void)
{
LADMIN_LOG("Request to login-server to obtain its version.\n");
WFIFOW(login_fd, 0) = 0x7530;
WFIFOSET(login_fd, 2);
bytes_to_read = 1;
-
- return 0;
}
//---------------------------------------------
@@ -2381,12 +1753,8 @@ int checkloginversion(void)
// and analyse the command.
//---------------------------------------------
static
-int prompt(void)
+void prompt(void)
{
- int i, j;
- char buf[1024];
- char *p;
-
// while we don't wait new packets
while (bytes_to_read == 0)
{
@@ -2404,246 +1772,117 @@ int prompt(void)
fflush(stdout);
// get command and parameter
- strzcpy(buf, "", sizeof(buf));
- fflush(stdin);
- if (!fgets(buf, 1023, stdin))
- exit(0);
- buf[1023] = '\0';
+ FString buf;
+ io::getline(std::cin, buf);
Iprintf("\033[0m");
fflush(stdout);
- if (!eathena_interactive_session && !strlen(buf))
+ if (!eathena_interactive_session && !buf)
exit(0);
- // remove final \n
- if ((p = strrchr(buf, '\n')) != NULL)
- p[0] = '\0';
- // remove all control char
- for (i = 0; buf[i]; i++)
- if (buf[i] < 32)
- {
- // remove cursor control.
- if (buf[i] == 27
- && buf[i + 1] == '['
- && (buf[i + 2] == 'H' // home position (cursor)
- || buf[i + 2] == 'J' // clear screen
- || buf[i + 2] == 'A' // up 1 line
- || buf[i + 2] == 'B' // down 1 line
- || buf[i + 2] == 'C' // right 1 position
- || buf[i + 2] == 'D' // left 1 position
- || buf[i + 2] == 'G')) // center cursor (windows)
- {
- for (j = i; buf[j]; j++)
- buf[j] = buf[j + 3];
- }
- else if (buf[i] == 27 && buf[i + 1] == '['
- && buf[i + 2] == '2' && buf[i + 3] == 'J')
- {
- // clear screen
- for (j = i; buf[j]; j++)
- buf[j] = buf[j + 4];
- }
- else if (buf[i] == 27
- && buf[i + 1] == '['
- && buf[i + 3] == '~'
- && (buf[i + 2] == '1' // home (windows)
- || buf[i + 2] == '2' // insert (windows)
- || buf[i + 2] == '3' // del (windows)
- || buf[i + 2] == '4' // end (windows)
- || buf[i + 2] == '5' // pgup (windows)
- || buf[i + 2] == '6')) // pgdown (windows)
- {
- for (j = i; buf[j]; j++)
- buf[j] = buf[j + 4];
- }
- else
- {
- // remove other control char.
- for (j = i; buf[j]; j++)
- buf[j] = buf[j + 1];
- }
- i--;
- }
+ if (!buf.is_print())
+ {
+ printf("Cowardly refusing to execute a command that includes control or non-ascii characters\n");
+ LADMIN_LOG("Cowardly refusing to execute a command that includes control or non-ascii characters\n");
+ continue;
+ }
- char command[1024] {};
// extract command name and parameters
- strzcpy(parameters, "", sizeof(parameters));
- sscanf(buf, "%1023s %[^\n]", command, parameters);
- command[1023] = '\0';
- parameters[1023] = '\0';
+ auto space = std::find(buf.begin(), buf.end(), ' ');
+ FString command = buf.xislice_h(space);
+ while (*space == ' ')
+ ++space;
- // lowercase for command line
- for (i = 0; command[i]; i++)
- command[i] = tolower(command[i]);
+ parameters = buf.xislice_t(space);
- if (command[0] == '?' || strlen(command) == 0)
- {
- strcpy(buf, "help");
- strcpy(command, "help");
- }
+ if (!command || command.startswith('?'))
+ command = "help";
- // Analyse of the command
- check_command(command); // give complete name to the command
-
- if (strlen(parameters) == 0)
+ if (!parameters)
{
LADMIN_LOG("Command: '%s' (without parameters)\n",
- command);
+ command);
}
else
{
LADMIN_LOG("Command: '%s', parameters: '%s'\n",
- command, parameters);
+ command, parameters);
}
// Analyse of the command
-// help
- if (strcmp(command, "help") == 0)
- {
+ if (command == "help")
display_help(parameters);
-// general commands
- }
- else if (strcmp(command, "add") == 0)
- {
+ else if (command == "add")
addaccount(parameters, 0); // 0: no email
- }
- else if (strcmp(command, "ban") == 0)
- {
+ else if (command == "ban")
banaccount(parameters);
- }
- else if (strcmp(command, "banadd") == 0)
- {
+ else if (command == "banadd")
banaddaccount(parameters);
- }
- else if (strcmp(command, "banset") == 0)
- {
+ else if (command == "banset")
bansetaccount(parameters);
- }
- else if (strcmp(command, "block") == 0)
- {
+ else if (command == "block")
blockaccount(parameters);
- }
- else if (strcmp(command, "check") == 0)
- {
+ else if (command == "check")
checkaccount(parameters);
- }
- else if (strcmp(command, "create") == 0)
- {
+ else if (command == "create")
addaccount(parameters, 1); // 1: with email
- }
- else if (strcmp(command, "delete") == 0)
- {
+ else if (command == "delete")
delaccount(parameters);
- }
- else if (strcmp(command, "email") == 0)
- {
+ else if (command == "email")
changeemail(parameters);
- }
- else if (strcmp(command, "getcount") == 0)
- {
+ else if (command == "getcount")
getlogincount();
- }
- else if (strcmp(command, "gm") == 0)
- {
+ else if (command == "gm")
changegmlevel(parameters);
- }
- else if (strcmp(command, "id") == 0)
- {
+ else if (command == "id")
idaccount(parameters);
- }
- else if (strcmp(command, "info") == 0)
- {
- infoaccount(atoi(parameters));
- }
- else if (strcmp(command, "kami") == 0)
- {
- sendbroadcast(0, parameters); // flag for normal
- }
- else if (strcmp(command, "kamib") == 0)
- {
- sendbroadcast(0x10, parameters); // flag for blue
- }
- else if (strcmp(command, "itemfrob") == 0)
- {
+ else if (command == "info")
+ infoaccount(atoi(parameters.c_str()));
+ else if (command == "kami")
+ sendbroadcast(parameters); // flag for normal
+ else if (command == "itemfrob")
itemfrob(parameters); // 0: to list all
- }
- else if (strcmp(command, "list") == 0)
- {
+ else if (command == "list")
listaccount(parameters, 0); // 0: to list all
- }
- else if (strcmp(command, "listban") == 0)
- {
+ else if (command == "listban")
listaccount(parameters, 3); // 3: to list only accounts with state or bannished
- }
- else if (strcmp(command, "listgm") == 0)
- {
+ else if (command == "listgm")
listaccount(parameters, 1); // 1: to list only GM
- }
- else if (strcmp(command, "listok") == 0)
- {
+ else if (command == "listok")
listaccount(parameters, 4); // 4: to list only accounts without state and not bannished
- }
- else if (strcmp(command, "memo") == 0)
- {
+ else if (command == "memo")
changememo(parameters);
- }
- else if (strcmp(command, "name") == 0)
- {
- nameaccount(atoi(parameters));
- }
- else if (strcmp(command, "password") == 0)
- {
+ else if (command == "name")
+ nameaccount(atoi(parameters.c_str()));
+ else if (command == "password")
changepasswd(parameters);
- }
- else if (strcmp(command, "reloadgm") == 0)
- {
+ else if (command == "reloadgm")
reloadGM(parameters);
- }
- else if (strcmp(command, "search") == 0)
- { // no regex in C version
+ else if (command == "search")
listaccount(parameters, 2); // 2: to list with pattern
- }
- else if (strcmp(command, "sex") == 0)
- {
+ else if (command == "sex")
changesex(parameters);
- }
- else if (strcmp(command, "state") == 0)
- {
+ else if (command == "state")
changestate(parameters);
- }
- else if (strcmp(command, "timeadd") == 0)
- {
+ else if (command == "timeadd")
timeaddaccount(parameters);
- }
- else if (strcmp(command, "timeset") == 0)
- {
+ else if (command == "timeset")
timesetaccount(parameters);
- }
- else if (strcmp(command, "unban") == 0)
- {
+ else if (command == "unban")
unbanaccount(parameters);
- }
- else if (strcmp(command, "unblock") == 0)
- {
+ else if (command == "unblock")
unblockaccount(parameters);
- }
- else if (strcmp(command, "version") == 0)
- {
+ else if (command == "version")
checkloginversion();
- }
- else if (strcmp(command, "who") == 0)
- {
+ else if (command == "who")
whoaccount(parameters);
-// quit
- }
- else if (strcmp(command, "quit") == 0 ||
- strcmp(command, "exit") == 0 ||
- strcmp(command, "end") == 0)
+ else if (command == "quit"
+ || command == "exit"
+ || command == "end")
{
PRINTF("Bye.\n");
exit(0);
-// unknown command
}
else
{
@@ -2651,8 +1890,6 @@ int prompt(void)
LADMIN_LOG("Unknown command [%s].\n", buf);
}
}
-
- return 0;
}
//-------------------------------------------------------------
@@ -2702,39 +1939,6 @@ void parse_fromlogin(int fd)
RFIFOSKIP(fd, 3);
break;
- case 0x01dc: // answer of a coding key request
- if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd, 2))
- return;
- {
- char md5str[64] = "";
- size_t key_len = RFIFOW(fd, 2) - 4;
- uint8_t md5bin[32];
- char md5key[key_len];
- RFIFO_STRING(fd, 4, md5key, key_len);
- if (passenc == 1)
- {
- strcpy(md5str, md5key);
- strcat(md5str, loginserveradminpassword);
- }
- else if (passenc == 2)
- {
- strcpy(md5str, loginserveradminpassword);
- strcat(md5str, md5key);
- }
- MD5_to_bin(MD5_from_cstring(md5str), md5bin);
- WFIFOW(login_fd, 0) = 0x7918; // Request for administation login (encrypted password)
- WFIFOW(login_fd, 2) = passenc; // Encrypted type
- really_memcpy(static_cast<uint8_t *>(WFIFOP(login_fd, 4)), md5bin, 16);
- WFIFOSET(login_fd, 20);
- Iprintf("Receiving of the MD5 key.\n");
- LADMIN_LOG("Receiving of the MD5 key.\n");
- Iprintf("Sending of the encrypted password...\n");
- LADMIN_LOG("Sending of the encrypted password...\n");
- }
- bytes_to_read = 1;
- RFIFOSKIP(fd, RFIFOW(fd, 2));
- break;
-
case 0x7531: // Displaying of the version of the login-server
if (RFIFOREST(fd) < 10)
return;
@@ -2793,20 +1997,15 @@ void parse_fromlogin(int fd)
LADMIN_LOG(" Receiving of a accounts list.\n");
for (i = 4; i < RFIFOW(fd, 2); i += 38)
{
- int j;
- char userid[24];
- char lower_userid[24] {};
- RFIFO_STRING(fd, i + 5, userid, 24);
- for (j = 0; userid[j]; j++)
- lower_userid[j] = tolower(userid[j]);
+ AccountName userid = stringish<AccountName>(RFIFO_STRING<24>(fd, i + 5));
+ VString<23> lower_userid = userid.to_lower();
list_first = RFIFOL(fd, i) + 1;
// here are checks...
- if (list_type == 0 ||
- (list_type == 1 && RFIFOB(fd, i + 4) > 0) ||
- (list_type == 2
- && strstr(lower_userid, parameters) != NULL)
- ||(list_type == 3 && RFIFOL(fd, i + 34) != 0)
- ||(list_type == 4 && RFIFOL(fd, i + 34) == 0))
+ if (list_type == 0
+ || (list_type == 1 && RFIFOB(fd, i + 4) > 0)
+ || (list_type == 2 && lower_userid.contains_seq(parameters))
+ || (list_type == 3 && RFIFOL(fd, i + 34) != 0)
+ || (list_type == 4 && RFIFOL(fd, i + 34) == 0))
{
PRINTF("%10d ", RFIFOL(fd, i));
if (RFIFOB(fd, i + 4) == 0)
@@ -2880,8 +2079,7 @@ void parse_fromlogin(int fd)
return;
{
int accid = RFIFOL(fd, 2);
- char name[24];
- RFIFO_STRING(fd, 6, name, 24);
+ AccountName name = stringish<AccountName>(RFIFO_STRING<24>(fd, 6));
if (accid == -1)
{
PRINTF("Account [%s] creation failed. Same account already exists.\n",
@@ -2906,8 +2104,7 @@ void parse_fromlogin(int fd)
return;
{
int accid = RFIFOL(fd, 2);
- char name[24];
- RFIFO_STRING(fd, 6, name, 24);
+ AccountName name = stringish<AccountName>(RFIFO_STRING<24>(fd, 6));
if (accid == -1)
{
PRINTF("Account [%s] deletion failed. Account doesn't exist.\n",
@@ -2932,8 +2129,7 @@ void parse_fromlogin(int fd)
return;
{
int accid = RFIFOL(fd, 2);
- char name[24];
- RFIFO_STRING(fd, 6, name, 24);
+ AccountName name = stringish<AccountName>(RFIFO_STRING<24>(fd, 6));
if (accid == -1)
{
PRINTF("Account [%s] password changing failed.\n",
@@ -2960,8 +2156,7 @@ void parse_fromlogin(int fd)
return;
{
int accid = RFIFOL(fd, 2);
- char name[24];
- RFIFO_STRING(fd, 6, name, 24);
+ AccountName name = stringish<AccountName>(RFIFO_STRING<24>(fd, 6));
int state = RFIFOL(fd, 30);
if (accid == -1)
{
@@ -2972,7 +2167,8 @@ void parse_fromlogin(int fd)
}
else
{
- std::string tmpstr = STRPRINTF(
+ MString tmpstr;
+ tmpstr += STRPRINTF(
"Account [%s] state successfully changed in [",
name);
switch (state)
@@ -3012,8 +2208,9 @@ void parse_fromlogin(int fd)
break;
}
tmpstr += ']';
- PRINTF("%s\n", tmpstr);
- LADMIN_LOG("%s\n", tmpstr);
+ FString tmpstr_ = FString(tmpstr);
+ PRINTF("%s\n", tmpstr_);
+ LADMIN_LOG("%s\n", tmpstr_);
}
bytes_to_read = 0;
}
@@ -3037,8 +2234,7 @@ void parse_fromlogin(int fd)
// Displaying of result
for (int i = 4; i < RFIFOW(fd, 2); i += 32)
{
- char name[20];
- RFIFO_STRING(fd, i + 6, name, 20);
+ ServerName name = stringish<ServerName>(RFIFO_STRING<20>(fd, i + 6));
PRINTF(" %-20s : %5d\n", name,
RFIFOW(fd, i + 26));
}
@@ -3053,8 +2249,7 @@ void parse_fromlogin(int fd)
return;
{
int account_id = RFIFOL(fd, 2);
- char name[24];
- RFIFO_STRING(fd, 6, name, 24);
+ AccountName name = stringish<AccountName>(RFIFO_STRING<24>(fd, 6));
if (account_id == -1)
{
PRINTF("The account [%s] doesn't exist or the password is incorrect.\n",
@@ -3079,8 +2274,7 @@ void parse_fromlogin(int fd)
return;
{
int account_id = RFIFOL(fd, 2);
- char name[24];
- RFIFO_STRING(fd, 6, name, 24);
+ AccountName name = stringish<AccountName>(RFIFO_STRING<24>(fd, 6));
if (account_id == -1)
{
PRINTF("Account [%s] sex changing failed.\n",
@@ -3107,8 +2301,7 @@ void parse_fromlogin(int fd)
return;
{
int account_id = RFIFOL(fd, 2);
- char name[24];
- RFIFO_STRING(fd, 6, name, 24);
+ AccountName name = stringish<AccountName>(RFIFO_STRING<24>(fd, 6));
if (account_id == -1)
{
PRINTF("Account [%s] GM level changing failed.\n",
@@ -3136,8 +2329,7 @@ void parse_fromlogin(int fd)
return;
{
int account_id = RFIFOL(fd, 2);
- char name[24];
- RFIFO_STRING(fd, 6, name, 24);
+ AccountName name = stringish<AccountName>(RFIFO_STRING<24>(fd, 6));
if (account_id == -1)
{
PRINTF("Account [%s] e-mail changing failed.\n",
@@ -3164,8 +2356,7 @@ void parse_fromlogin(int fd)
return;
{
int account_id = RFIFOL(fd, 2);
- char name[24];
- RFIFO_STRING(fd, 6, name, 24);
+ AccountName name = stringish<AccountName>(RFIFO_STRING<24>(fd, 6));
if (account_id == -1)
{
PRINTF("Account [%s] memo changing failed. Account doesn't exist.\n",
@@ -3190,8 +2381,7 @@ void parse_fromlogin(int fd)
return;
{
int account_id = RFIFOL(fd, 2);
- char name[24];
- RFIFO_STRING(fd, 6, name, 24);
+ AccountName name = stringish<AccountName>(RFIFO_STRING<24>(fd, 6));
if (account_id == -1)
{
PRINTF("Unable to find the account [%s] id. Account doesn't exist.\n",
@@ -3216,9 +2406,8 @@ void parse_fromlogin(int fd)
return;
{
int account_id = RFIFOL(fd, 2);
- char name[24];
- RFIFO_STRING(fd, 6, name, 24);
- if (strcmp(name, "") == 0)
+ AccountName name = stringish<AccountName>(RFIFO_STRING<24>(fd, 6));
+ if (!name)
{
PRINTF("Unable to find the account [%d] name. Account doesn't exist.\n",
account_id);
@@ -3242,8 +2431,7 @@ void parse_fromlogin(int fd)
return;
{
int account_id = RFIFOL(fd, 2);
- char name[24];
- RFIFO_STRING(fd, 6, name, 24);
+ AccountName name = stringish<AccountName>(RFIFO_STRING<24>(fd, 6));
if (RFIFOL(fd, 2) == -1)
{
PRINTF("Account [%s] validity limit changing failed. Account doesn't exist.\n",
@@ -3282,8 +2470,7 @@ void parse_fromlogin(int fd)
return;
{
int account_id = RFIFOL(fd, 2);
- char name[24];
- RFIFO_STRING(fd, 6, name, 24);
+ AccountName name = stringish<AccountName>(RFIFO_STRING<24>(fd, 6));
if (account_id == -1)
{
PRINTF("Account [%s] final date of banishment changing failed. Account doesn't exist.\n",
@@ -3322,8 +2509,7 @@ void parse_fromlogin(int fd)
return;
{
int account_id = RFIFOL(fd, 2);
- char name[24];
- RFIFO_STRING(fd, 6, name, 24);
+ AccountName name = stringish<AccountName>(RFIFO_STRING<24>(fd, 6));
if (account_id == -1)
{
PRINTF("Account [%s] final date of banishment changing failed. Account doesn't exist.\n",
@@ -3378,12 +2564,15 @@ void parse_fromlogin(int fd)
case 0x7951: // answer of an account validity limit changing
if (RFIFOREST(fd) < 34)
return;
- if (RFIFOL(fd, 2) == -1)
+ {
+ int account_id = RFIFOL(fd, 2);
+ AccountName name = stringish<AccountName>(RFIFO_STRING<24>(fd, 6));
+ if (account_id == -1)
{
PRINTF("Account [%s] validity limit changing failed. Account doesn't exist.\n",
- static_cast<const char *>(RFIFOP(fd, 6)));
+ name);
LADMIN_LOG("Account [%s] validity limit changing failed. Account doesn't exist.\n",
- static_cast<const char *>(RFIFOP(fd, 6)));
+ name);
}
else
{
@@ -3391,25 +2580,26 @@ void parse_fromlogin(int fd)
if (!timestamp)
{
PRINTF("Validity limit of the account [%s][id: %d] unchanged.\n",
- static_cast<const char *>(RFIFOP(fd, 6)), RFIFOL(fd, 2));
+ name, account_id);
PRINTF("The account have an unlimited validity limit or\n");
PRINTF("the changing is impossible with the proposed adjustments.\n");
LADMIN_LOG("Validity limit of the account [%s][id: %d] unchanged. The account have an unlimited validity limit or the changing is impossible with the proposed adjustments.\n",
- static_cast<const char *>(RFIFOP(fd, 6)), RFIFOL(fd, 2));
+ name, account_id);
}
else
{
timestamp_seconds_buffer tmpstr;
stamp_time(tmpstr, &timestamp);
PRINTF("Validity limit of the account [%s][id: %d] successfully changed to be until %s.\n",
- static_cast<const char *>(RFIFOP(fd, 6)), RFIFOL(fd, 2),
+ name, account_id,
tmpstr);
LADMIN_LOG("Validity limit of the account [%s][id: %d] successfully changed to be until %s.\n",
- static_cast<const char *>( RFIFOP(fd, 6)), RFIFOL(fd, 2),
+ name, account_id,
tmpstr);
}
}
bytes_to_read = 0;
+ }
RFIFOSKIP(fd, 34);
break;
@@ -3418,54 +2608,55 @@ void parse_fromlogin(int fd)
|| RFIFOREST(fd) < (150 + RFIFOW(fd, 148)))
return;
{
- char userid[24], error_message[20], lastlogin[24],
- last_ip[16], email[40], memo[255];
- TimeT ban_until_time; // # of seconds 1/1/1970 (timestamp): ban time limit of the account (0 = no ban)
- TimeT connect_until_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited)
- RFIFO_STRING(fd, 7, userid, 24);
- RFIFO_STRING(fd, 40, error_message, 20);
- RFIFO_STRING(fd, 60, lastlogin, 24);
- RFIFO_STRING(fd, 84, last_ip, 16);
- RFIFO_STRING(fd, 100, email, 40);
- connect_until_time = static_cast<time_t>(RFIFOL(fd, 140));
- ban_until_time = static_cast<time_t>(RFIFOL(fd, 144));
- RFIFO_STRING(fd, 150, memo, RFIFOW(fd, 148));
- if (RFIFOL(fd, 2) == -1)
+ int account_id = RFIFOL(fd, 2);
+ uint8_t gm = RFIFOB(fd, 6);
+ AccountName userid = stringish<AccountName>(RFIFO_STRING<24>(fd, 7));
+ uint8_t sex = RFIFOB(fd, 31);
+ int connections = RFIFOL(fd, 32);
+ int state = RFIFOL(fd, 36);
+ timestamp_seconds_buffer error_message = stringish<timestamp_seconds_buffer>(RFIFO_STRING<20>(fd, 40));
+ timestamp_milliseconds_buffer lastlogin = stringish<timestamp_milliseconds_buffer>(RFIFO_STRING<24>(fd, 60));
+ IP_String last_ip = stringish<IP_String>(RFIFO_STRING<16>(fd, 84));
+ AccountEmail email = stringish<AccountEmail>(RFIFO_STRING<40>(fd, 100));
+ TimeT connect_until_time = static_cast<time_t>(RFIFOL(fd, 140));
+ TimeT ban_until_time = static_cast<time_t>(RFIFOL(fd, 144));
+ FString memo = RFIFO_STRING(fd, 150, RFIFOW(fd, 148));
+ if (account_id == -1)
{
PRINTF("Unabled to find the account [%s]. Account doesn't exist.\n",
- parameters);
+ userid);
LADMIN_LOG("Unabled to find the account [%s]. Account doesn't exist.\n",
- parameters);
+ userid);
}
- else if (strlen(userid) == 0)
+ else if (!userid)
{
- PRINTF("Unabled to find the account [id: %s]. Account doesn't exist.\n",
- parameters);
- LADMIN_LOG("Unabled to find the account [id: %s]. Account doesn't exist.\n",
- parameters);
+ PRINTF("Unabled to find the account [id: %d]. Account doesn't exist.\n",
+ account_id);
+ LADMIN_LOG("Unabled to find the account [id: %d]. Account doesn't exist.\n",
+ account_id);
}
else
{
LADMIN_LOG("Receiving information about an account.\n");
PRINTF("The account is set with:\n");
- if (RFIFOB(fd, 6) == 0)
+ if (!gm)
{
- PRINTF(" Id: %d (non-GM)\n", RFIFOL(fd, 2));
+ PRINTF(" Id: %d (non-GM)\n", account_id);
}
else
{
PRINTF(" Id: %d (GM level %d)\n",
- RFIFOL(fd, 2), RFIFOB(fd, 6));
+ account_id, gm);
}
PRINTF(" Name: '%s'\n", userid);
- if (RFIFOB(fd, 31) == 0)
+ if (sex == 0)
PRINTF(" Sex: Female\n");
- else if (RFIFOB(fd, 31) == 1)
+ else if (sex == 1)
PRINTF(" Sex: Male\n");
else
PRINTF(" Sex: Server\n");
PRINTF(" E-mail: %s\n", email);
- switch (RFIFOL(fd, 36))
+ switch (state)
{
case 0:
PRINTF(" Statut: 0 [Account OK]\n");
@@ -3500,7 +2691,7 @@ void parse_fromlogin(int fd)
break;
default: // 100
PRINTF(" Statut: %d [This ID is totally erased]\n",
- RFIFOL(fd, 36));
+ state);
break;
}
if (!ban_until_time)
@@ -3513,12 +2704,12 @@ void parse_fromlogin(int fd)
stamp_time(tmpstr, &ban_until_time);
PRINTF(" Banishment: until %s.\n", tmpstr);
}
- if (RFIFOL(fd, 32) > 1)
+ if (connections > 1)
PRINTF(" Count: %d connections.\n",
- RFIFOL(fd, 32));
+ connections);
else
PRINTF(" Count: %d connection.\n",
- RFIFOL(fd, 32));
+ connections);
PRINTF(" Last connection at: %s (ip: %s)\n",
lastlogin, last_ip);
if (!connect_until_time)
@@ -3563,7 +2754,6 @@ int Connect_login_server(void)
if ((login_fd = make_connection(login_ip, loginserverport)) < 0)
return 0;
- if (passenc == 0)
{
WFIFOW(login_fd, 0) = 0x7918; // Request for administation login
WFIFOW(login_fd, 2) = 0; // no encrypted
@@ -3574,14 +2764,6 @@ int Connect_login_server(void)
Iprintf("Sending of the password...\n");
LADMIN_LOG("Sending of the password...\n");
}
- else
- {
- WFIFOW(login_fd, 0) = 0x791a; // Sending request about the coding key
- WFIFOSET(login_fd, 2);
- bytes_to_read = 1;
- Iprintf("Request about the MD5 key...\n");
- LADMIN_LOG("Request about the MD5 key...\n");
- }
return 0;
}
@@ -3590,9 +2772,9 @@ int Connect_login_server(void)
// Reading general configuration file
//-----------------------------------
static
-int ladmin_config_read(const char *cfgName)
+int ladmin_config_read(ZString cfgName)
{
- std::ifstream in(cfgName);
+ std::ifstream in(cfgName.c_str());
if (!in.is_open())
{
PRINTF("\033[0mConfiguration file (%s) not found.\n", cfgName);
@@ -3601,10 +2783,11 @@ int ladmin_config_read(const char *cfgName)
Iprintf("\033[0m---Start reading of Ladmin configuration file (%s)\n",
cfgName);
- std::string line;
- while (std::getline(in, line))
+ FString line;
+ while (io::getline(in, line))
{
- std::string w1, w2;
+ SString w1;
+ TString w2;
if (!split_key_value(line, &w1, &w2))
continue;
@@ -3619,14 +2802,14 @@ int ladmin_config_read(const char *cfgName)
static_cast<uint8_t>(h->h_addr[1]),
static_cast<uint8_t>(h->h_addr[2]),
static_cast<uint8_t>(h->h_addr[3]));
- sprintf(loginserverip, "%d.%d.%d.%d",
+ SNPRINTF(loginserverip, 16, "%d.%d.%d.%d",
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
- strzcpy(loginserverip, w2.c_str(), 16);
+ loginserverip = stringish<IP_String>(w2);
}
else if (w1 == "login_port")
{
@@ -3634,29 +2817,23 @@ int ladmin_config_read(const char *cfgName)
}
else if (w1 == "admin_pass")
{
- strzcpy(loginserveradminpassword, w2.c_str(), sizeof(loginserveradminpassword));
- }
- else if (w1 == "passenc")
- {
- passenc = atoi(w2.c_str());
- if (passenc < 0 || passenc > 2)
- passenc = 0;
+ loginserveradminpassword = stringish<AccountPass>(w2);
}
else if (w1 == "ladmin_log_filename")
{
- strzcpy(ladmin_log_filename, w2.c_str(), sizeof(ladmin_log_filename));
+ ladmin_log_filename = w2;
}
else if (w1 == "import")
{
- ladmin_config_read(w2.c_str());
+ ladmin_config_read(w2);
}
else
{
- PRINTF("WARNING: unknown ladmin config key: %s\n", w1);
+ PRINTF("WARNING: unknown ladmin config key: %s\n", FString(w1));
}
}
- login_ip = inet_addr(loginserverip);
+ login_ip = inet_addr(loginserverip.c_str());
Iprintf("---End reading of Ladmin configuration file.\n");
@@ -3683,7 +2860,7 @@ void term_func(void)
//------------------------
// Main function of ladmin
//------------------------
-int do_init(int argc, char **argv)
+int do_init(int argc, ZString *argv)
{
eathena_interactive_session = isatty(0);
// read ladmin configuration
diff --git a/src/login/login.cpp b/src/login/login.cpp
index b3c7790..852cd3d 100644
--- a/src/login/login.cpp
+++ b/src/login/login.cpp
@@ -18,6 +18,8 @@
#include "../common/cxxstdio.hpp"
#include "../common/db.hpp"
#include "../common/extract.hpp"
+#include "../common/human_time_diff.hpp"
+#include "../common/io.hpp"
#include "../common/lock.hpp"
#include "../common/md5calc.hpp"
#include "../common/mmo.hpp"
@@ -39,21 +41,21 @@ constexpr int END_ACCOUNT_NUM = 100000000;
struct mmo_account
{
- char userid[24];
- char passwd[24];
+ AccountName userid;
+ AccountPass passwd;
int passwdenc;
long account_id;
long login_id1;
long login_id2;
long char_id;
- char lastlogin[24];
+ timestamp_milliseconds_buffer lastlogin;
int sex;
};
struct mmo_char_server
{
- char name[20];
+ ServerName name;
long ip;
short port;
int users;
@@ -70,24 +72,24 @@ int new_account_flag = 0;
static
int login_port = 6900;
static
-char lan_char_ip[16];
+IP_String lan_char_ip;
static
uint8_t subneti[4];
static
uint8_t subnetmaski[4];
static
-char update_host[128] = "";
+FString update_host;
static
-char main_server[20] = "";
+ServerName main_server;
static
-char account_filename[1024] = "save/account.txt";
+FString account_filename = "save/account.txt";
static
-char GM_account_filename[1024] = "conf/GM_account.txt";
+FString GM_account_filename = "conf/GM_account.txt";
static
-char login_log_filename[1024] = "log/login.log";
+FString login_log_filename = "log/login.log";
static
-char login_log_unknown_packets_filename[1024] = "log/login_unknown_packets.log";
+FString login_log_unknown_packets_filename = "log/login_unknown_packets.log";
static
int save_unknown_packets = 0;
static
@@ -124,7 +126,7 @@ enum class ACO
};
// TODO: port the new code for this
-typedef std::array<char, 128> AccessEntry;
+struct AccessEntry : VString<127> {};
static
ACO access_order = ACO::DENY_ALLOW;
@@ -141,17 +143,13 @@ int start_limited_time = -1; // Starting additional sec from now for the limit
static
int check_ip_flag = 1; // It's to check IP of a player between login-server and char-server (part of anti-hacking system)
-
-struct login_session_data : SessionData
-{
- int md5keylen;
- char md5key[20];
-};
-
-void SessionDeleter::operator()(SessionData *sd)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wmissing-noreturn"
+void SessionDeleter::operator()(SessionData *)
{
- really_delete1 static_cast<login_session_data *>(sd);
+ assert(false && "login server does not have sessions anymore");
}
+#pragma GCC diagnostic pop
constexpr int AUTH_FIFO_SIZE = 256;
struct
@@ -165,15 +163,17 @@ int auth_fifo_pos = 0;
struct AuthData
{
int account_id, sex;
- char userid[24], pass[40], lastlogin[24];
+ AccountName userid;
+ AccountCrypt pass;
+ timestamp_milliseconds_buffer lastlogin;
int logincount;
int state; // packet 0x006a value + 1 (0: compte OK)
- char email[40]; // e-mail (by default: a@a.com)
- char error_message[20]; // Message of error code #6 = Your are Prohibited to log in until %s (packet 0x006a)
+ AccountEmail email; // e-mail (by default: a@a.com)
+ timestamp_seconds_buffer error_message; // Message of error code #6 = Your are Prohibited to log in until %s (packet 0x006a)
TimeT ban_until_time; // # of seconds 1/1/1970 (timestamp): ban time limit of the account (0 = no ban)
TimeT connect_until_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited)
- char last_ip[16]; // save of last IP of connection
- char memo[255]; // a memo field
+ IP_String last_ip; // save of last IP of connection
+ VString<254> memo; // a memo field
int account_reg2_num;
struct global_reg account_reg2[ACCOUNT_REG2_NUM];
};
@@ -183,9 +183,9 @@ std::vector<AuthData> auth_data;
static
int admin_state = 0;
static
-char admin_pass[24] = "";
+AccountPass admin_pass;
static
-char gm_pass[64] = "";
+FString gm_pass;
static
int level_new_gm = 60;
@@ -213,15 +213,15 @@ using e::VERSION_2;
// Writing function of logs file
//------------------------------
#define LOGIN_LOG(fmt, ...) \
- login_log(static_cast<const std::string&>(STRPRINTF(fmt, ## __VA_ARGS__)))
+ login_log(STRPRINTF(fmt, ## __VA_ARGS__))
static
-void login_log(const_string line)
+void login_log(XString line)
{
- FILE *logfp = fopen_(login_log_filename, "a");
+ FILE *logfp = fopen(login_log_filename.c_str(), "a");
if (!logfp)
return;
log_with_timestamp(logfp, line);
- fclose_(logfp);
+ fclose(logfp);
}
//----------------------------------------------------------------------
@@ -252,7 +252,7 @@ int read_gm_account(void)
creation_time_GM_account_file = file_modified(GM_account_filename);
- if ((fp = fopen_(GM_account_filename, "r")) == NULL)
+ if ((fp = fopen(GM_account_filename.c_str(), "r")) == NULL)
{
PRINTF("read_gm_account: GM accounts file [%s] not found.\n",
GM_account_filename);
@@ -266,8 +266,7 @@ int read_gm_account(void)
// int (id) + int (level) = 8 bytes * 4000 = 32k (limit of packets in windows)
while (fgets(line, sizeof(line) - 1, fp) && c < 4000)
{
- if ((line[0] == '/' && line[1] == '/') || line[0] == '\0'
- || line[0] == '\n' || line[0] == '\r')
+ if ((line[0] == '/' && line[1] == '/') || line[0] == '\0' || line[0] == '\n')
continue;
GM_Account p {};
if (sscanf(line, "%d %hhu", &p.account_id, &p.level) != 2
@@ -310,7 +309,7 @@ int read_gm_account(void)
}
}
}
- fclose_(fp);
+ fclose(fp);
PRINTF("read_gm_account: file '%s' readed (%d GM accounts found).\n",
GM_account_filename, c);
@@ -325,7 +324,7 @@ int read_gm_account(void)
// (ip: IP to be tested, str: mask x.x.x.x/# or x.x.x.x/y.y.y.y)
//--------------------------------------------------------------
static
-int check_ipmask(struct in_addr ip, const char *str)
+int check_ipmask(struct in_addr ip, ZString str)
{
unsigned int mask = 0, ip2;
uint8_t *p = reinterpret_cast<uint8_t *>(&ip2),
@@ -333,17 +332,17 @@ int check_ipmask(struct in_addr ip, const char *str)
int i = 0;
unsigned int m;
- if (sscanf(str, "%hhu.%hhu.%hhu.%hhu/%n",
+ if (SSCANF(str, "%hhu.%hhu.%hhu.%hhu/%n",
&p[0], &p[1], &p[2], &p[3], &i) != 4
|| i == 0)
return 0;
- if (sscanf(str + i, "%hhu.%hhu.%hhu.%hhu",
+ if (SSCANF(str.oslice_t(i), "%hhu.%hhu.%hhu.%hhu",
&p2[0], &p2[1], &p2[2], &p2[3]) == 4)
{
mask = ntohl(mask);
}
- else if (sscanf(str + i, "%u", &m) == 1 && m <= 32)
+ else if (SSCANF(str.oslice_t(i), "%u", &m) == 1 && m <= 32)
{
for (i = 0; i < m && i < 32; i++)
mask = (mask >> 1) | 0x80000000;
@@ -386,13 +385,12 @@ bool check_ip(struct in_addr ip)
// If we have an answer, there is no guarantee to have a 100% correct value.
// And, the waiting time (to check) can be long (over 1 minute to a timeout). That can block the software.
// So, DNS notation isn't authorised for ip checking.
- const char *buf = ip2str(ip, true);
+ VString<16> buf = ip2str_extradot(ip);
for (const AccessEntry& ae : access_allow)
{
- const char *p = ae.data();
-#warning "TODO remove the strncmp part and use an IPAddress4 class"
- if (strncmp(p, buf, strlen(p)) == 0 || check_ipmask(ip, p))
+#warning "TODO use an IPAddress4 and IPMask4 class"
+ if (buf.startswith(ae) || check_ipmask(ip, ae))
{
flag = ACF::ALLOW;
if (access_order == ACO::ALLOW_DENY)
@@ -404,8 +402,7 @@ bool check_ip(struct in_addr ip)
for (const AccessEntry& ae : access_deny)
{
- const char *p = ae.data();
- if (strncmp(p, buf, strlen(p)) == 0 || check_ipmask(ip, p))
+ if (buf.startswith(ae) || check_ipmask(ip, ae))
{
flag = ACF::DENY;
return 0;
@@ -439,12 +436,11 @@ bool check_ladminip(struct in_addr ip)
// If we have an answer, there is no guarantee to have a 100% correct value.
// And, the waiting time (to check) can be long (over 1 minute to a timeout). That can block the software.
// So, DNS notation isn't authorised for ip checking.
- const char *buf = ip2str(ip, true);
+ VString<16> buf = ip2str_extradot(ip);
for (const AccessEntry& ae : access_ladmin)
{
- const char *p = ae.data();
- if (strncmp(p, buf, strlen(p)) == 0 || check_ipmask(ip, p))
+ if (buf.startswith(ae) || check_ipmask(ip, ae))
return true;
}
@@ -454,34 +450,18 @@ bool check_ladminip(struct in_addr ip)
//-----------------------------------------------
// Search an account id
// (return account pointer or nullptr (if not found))
-// If exact account name is not found,
-// the function checks without case sensitive
-// and returns index if only 1 account is found
-// and similar to the searched name.
//-----------------------------------------------
static
-AuthData *search_account(const char *account_name)
+AuthData *search_account(AccountName account_name)
{
- int quantity = 0;
- AuthData *index = nullptr;
for (AuthData& ad : auth_data)
{
- // Without case sensitive check (increase the number of similar account names found)
- if (strcasecmp(ad.userid, account_name) == 0)
{
- // Strict comparison (if found, we finish the function immediatly with correct value)
- if (strcmp(ad.userid, account_name) == 0)
+ if (ad.userid == account_name)
return &ad;
- quantity++;
- index = &ad;
}
}
- // Here, the exact account name is not found
- // We return the found index of a similar account ONLY if there is 1 similar account
- if (quantity == 1)
- return index;
- // Exact account name is not found and 0 or more than 1 similar accounts have been found ==> we say not found
return nullptr;
}
@@ -489,9 +469,10 @@ AuthData *search_account(const char *account_name)
// Create a string to save the account in the account file
//--------------------------------------------------------
static
-std::string mmo_auth_tostr(const AuthData *p)
+FString mmo_auth_tostr(const AuthData *p)
{
- std::string str = STRPRINTF(
+ MString str;
+ str += STRPRINTF(
"%d\t"
"%s\t"
"%s\t"
@@ -524,14 +505,14 @@ std::string mmo_auth_tostr(const AuthData *p)
str += STRPRINTF("%s,%d ",
p->account_reg2[i].str, p->account_reg2[i].value);
- return str;
+ return FString(str);
}
static
-bool extract(const_string line, AuthData *ad)
+bool extract(XString line, AuthData *ad)
{
std::vector<struct global_reg> vars;
- const_string sex = nullptr; // really only 1 char
+ VString<1> sex;
if (!extract(line,
record<'\t'>(
&ad->account_id,
@@ -555,19 +536,22 @@ bool extract(const_string line, AuthData *ad)
{
if (adi.account_id == ad->account_id)
return false;
- if (strcmp(adi.userid, ad->userid) == 0)
+ if (adi.userid == ad->userid)
return false;
}
// If a password is not encrypted, we encrypt it now.
// A password beginning with ! and - in the memo field is our magic
- if (ad->pass[0] != '!' && ad->memo[0] == '-') {
- strcpy(ad->pass, MD5_saltcrypt(ad->pass, make_salt()));
- ad->memo[0] = '!';
+ if (ad->pass[0] != '!' && ad->memo[0] == '-')
+ {
+ XString pass = ad->pass;
+ AccountPass plain = stringish<AccountPass>(pass);
+ ad->pass = MD5_saltcrypt(plain, make_salt());
+ ad->memo = '!';
}
if (sex.size() != 1)
return false;
- switch(sex.front())
+ switch (sex.front())
{
case 'S': case 's': ad->sex = 2; break;
case 'M': case 'm': ad->sex = 1; break;
@@ -575,12 +559,12 @@ bool extract(const_string line, AuthData *ad)
default: return false;
}
- if (e_mail_check(ad->email) == 0)
- strzcpy(ad->email, "a@a.com", 40);
+ if (!e_mail_check(ad->email))
+ ad->email = DEFAULT_EMAIL;
- if (ad->error_message[0] == '\0' || ad->state != 7)
+ if (!ad->error_message || ad->state != 7)
// 7, because state is packet 0x006a value + 1
- strzcpy(ad->error_message, "-", 20);
+ ad->error_message = stringish<timestamp_seconds_buffer>("-");
if (vars.size() > ACCOUNT_REG2_NUM)
return false;
@@ -599,7 +583,7 @@ int mmo_auth_init(void)
int GM_count = 0;
int server_count = 0;
- std::ifstream in(account_filename);
+ std::ifstream in(account_filename.c_str());
if (!in.is_open())
{
// no account file -> no account -> no login, including char-server (ERROR)
@@ -608,19 +592,11 @@ int mmo_auth_init(void)
return 0;
}
- std::string line;
- while (std::getline(in, line))
+ FString line;
+ while (io::getline(in, line))
{
- if (line[0] == '/' && line[1] == '/')
+ if (line.startswith("//"))
continue;
- if (line.back() == '\r')
- {
-#ifdef WORKAROUND_GCC46_LIBRARY
- line.resize(line.size() - 1);
-#else
- line.pop_back();
-#endif
- }
if (std::find_if(line.begin(), line.end(),
[](unsigned char c) { return c < ' ' && c != '\t'; }
) != line.end())
@@ -649,7 +625,7 @@ int mmo_auth_init(void)
account_id_count = ad.account_id + 1;
}
- std::string str = STRPRINTF("%s has %zu accounts (%d GMs, %d servers)\n",
+ FString str = STRPRINTF("%s has %zu accounts (%d GMs, %d servers)\n",
account_filename, auth_data.size(), GM_count, server_count);
PRINTF("%s: %s\n", __PRETTY_FUNCTION__, str);
LOGIN_LOG("%s\n", line);
@@ -696,7 +672,7 @@ void mmo_auth_sync(void)
if (ad.account_id < 0)
continue;
- std::string line = mmo_auth_tostr(&ad);
+ FString line = mmo_auth_tostr(&ad);
FPRINTF(fp, "%s\n", line);
}
FPRINTF(fp, "%d\t%%newid%%\n", account_id_count);
@@ -804,7 +780,7 @@ void check_GM_file(TimerData *, tick_t)
// Account creation (with e-mail check)
//-------------------------------------
static
-int mmo_auth_new(struct mmo_account *account, char sex, const char *email)
+int mmo_auth_new(struct mmo_account *account, char sex, AccountEmail email)
{
while (isGM(account_id_count) > 0)
account_id_count++;
@@ -812,19 +788,19 @@ int mmo_auth_new(struct mmo_account *account, char sex, const char *email)
struct AuthData ad {};
ad.account_id = account_id_count++;
- strzcpy(ad.userid, account->userid, 24);
- strzcpy(ad.pass, MD5_saltcrypt(account->passwd, make_salt()), 40);
- strcpy(ad.lastlogin, "-");
+ ad.userid = account->userid;
+ ad.pass = MD5_saltcrypt(account->passwd, make_salt());
+ ad.lastlogin = stringish<timestamp_milliseconds_buffer>("-");
ad.sex = (sex == 'M');
ad.logincount = 0;
ad.state = 0;
- if (e_mail_check(email) == 0)
- strzcpy(ad.email, "a@a.com", 40);
+ if (!e_mail_check(email))
+ ad.email = DEFAULT_EMAIL;
else
- strzcpy(ad.email, email, 40);
+ ad.email = email;
- strcpy(ad.error_message, "-");
+ ad.error_message = stringish<timestamp_seconds_buffer>("-");
ad.ban_until_time = TimeT();
if (start_limited_time < 0)
@@ -838,8 +814,8 @@ int mmo_auth_new(struct mmo_account *account, char sex, const char *email)
ad.connect_until_time = timestamp;
}
- strcpy(ad.last_ip, "-");
- strcpy(ad.memo, "!");
+ ad.last_ip = stringish<IP_String>("-");
+ ad.memo = "!";
ad.account_reg2_num = 0;
auth_data.push_back(ad);
@@ -852,51 +828,30 @@ int mmo_auth_new(struct mmo_account *account, char sex, const char *email)
static
int mmo_auth(struct mmo_account *account, int fd)
{
- int len, newaccount = 0;
-#ifdef PASSWDENC
- char md5str[64], md5bin[32];
-#endif
+ char new_account_sex = '\0';
- const char *ip = ip2str(session[fd]->client_addr.sin_addr);
+ IP_String ip = ip2str(session[fd]->client_addr.sin_addr);
- len = strlen(account->userid) - 2;
// Account creation with _M/_F
- if (account->passwdenc == 0 && account->userid[len] == '_' &&
- (account->userid[len + 1] == 'F' || account->userid[len + 1] == 'M')
+ if (account->passwdenc == 0
+ && (account->userid.endswith("_F") || account->userid.endswith("_M"))
&& new_account_flag == 1 && account_id_count <= END_ACCOUNT_NUM
- && len >= 4 && strlen(account->passwd) >= 4)
+ && (account->userid.size() - 2) >= 4 && account->passwd.size() >= 4)
{
- if (new_account_flag == 1)
- newaccount = 1;
- account->userid[len] = '\0';
+ new_account_sex = account->userid.back();
+ account->userid = stringish<AccountName>(account->userid.orslice_h(2));
}
// Strict account search
- AuthData *ad = nullptr;
- for (AuthData& adi : auth_data)
- {
- if (strcmp(account->userid, adi.userid) == 0)
- {
- ad = &adi;
- break;
- }
- }
- // if there is no creation request and strict account search fails, we do a no sensitive case research for index
- if (newaccount == 0 && !ad)
- {
- ad = search_account(account->userid);
- if (ad)
- strzcpy(account->userid, ad->userid, 24);
- // for the possible tests/checks afterwards (copy correcte sensitive case).
- }
+ AuthData *ad = search_account(account->userid);
if (ad)
{
int encpasswdok = 0;
- if (newaccount)
+ if (new_account_sex)
{
LOGIN_LOG("Attempt of creation of an already existant account (account: %s_%c, ip: %s)\n",
- account->userid, account->userid[len + 1], ip);
+ account->userid, new_account_sex, ip);
return 9; // 9 = Account already exists
}
if ((!pass_ok(account->passwd, ad->pass)) && !encpasswdok)
@@ -965,7 +920,7 @@ int mmo_auth(struct mmo_account *account, int fd)
}
else
{
- if (newaccount == 0)
+ if (new_account_sex == '\0')
{
LOGIN_LOG("Unknown account (account: %s, ip: %s)\n",
account->userid, ip);
@@ -973,11 +928,10 @@ int mmo_auth(struct mmo_account *account, int fd)
}
else
{
- int new_id =
- mmo_auth_new(account, account->userid[len + 1], "a@a.com");
+ int new_id = mmo_auth_new(account, new_account_sex, DEFAULT_EMAIL);
LOGIN_LOG("Account creation and authentification accepted (account %s (id: %d), sex: %c, connection with _F/_M, ip: %s)\n",
account->userid, new_id,
- account->userid[len + 1], ip);
+ new_account_sex, ip);
ad = &auth_data.back();
}
}
@@ -988,10 +942,10 @@ int mmo_auth(struct mmo_account *account, int fd)
account->account_id = ad->account_id;
account->login_id1 = random_::generate();
account->login_id2 = random_::generate();
- strzcpy(account->lastlogin, ad->lastlogin, 24);
- strzcpy(ad->lastlogin, tmpstr, 24);
+ account->lastlogin = ad->lastlogin;
+ ad->lastlogin = tmpstr;
account->sex = ad->sex;
- strzcpy(ad->last_ip, ip, 16);
+ ad->last_ip = ip;
ad->logincount++;
return -1; // account OK
@@ -1029,7 +983,7 @@ void char_anti_freeze_system(TimerData *, tick_t)
static
void parse_fromchar(int fd)
{
- const char *ip = ip2str(session[fd]->client_addr.sin_addr);
+ IP_String ip = ip2str(session[fd]->client_addr.sin_addr);
int id;
for (id = 0; id < MAX_SERVERS; id++)
@@ -1144,15 +1098,12 @@ void parse_fromchar(int fd)
// we receive a e-mail creation of an account with a default e-mail (no answer)
case 0x2715:
- {
- int acc;
- char email[40];
if (RFIFOREST(fd) < 46)
return;
- acc = RFIFOL(fd, 2); // speed up
- RFIFO_STRING(fd, 6, email, 40);
- remove_control_chars(email);
- if (e_mail_check(email) == 0)
+ {
+ int acc = RFIFOL(fd, 2);
+ AccountEmail email = stringish<AccountEmail>(RFIFO_STRING<40>(fd, 6));
+ if (!e_mail_check(email))
LOGIN_LOG("Char-server '%s': Attempt to create an e-mail on an account with a default e-mail REFUSED - e-mail is invalid (account: %d, ip: %s)\n",
server[id].name, acc, ip);
else
@@ -1160,10 +1111,9 @@ void parse_fromchar(int fd)
for (AuthData& ad : auth_data)
{
if (ad.account_id == acc
- && (strcmp(ad.email, "a@a.com") == 0
- || ad.email[0] == '\0'))
+ && (ad.email == DEFAULT_EMAIL || !ad.email))
{
- strzcpy(ad.email, email, 40);
+ ad.email = email;
LOGIN_LOG("Char-server '%s': Create an e-mail on an account with a default e-mail (account: %d, new e-mail: %s, ip: %s).\n",
server[id].name, acc, email, ip);
goto x2715_out;
@@ -1181,15 +1131,17 @@ void parse_fromchar(int fd)
case 0x2716:
if (RFIFOREST(fd) < 6)
return;
+ {
+ int account_id = RFIFOL(fd, 2);
//PRINTF("parse_fromchar: E-mail/limited time request from '%s' server (concerned account: %d)\n", server[id].name, RFIFOL(fd,2));
for (const AuthData& ad : auth_data)
{
- if (ad.account_id == RFIFOL(fd, 2))
+ if (ad.account_id == account_id)
{
LOGIN_LOG("Char-server '%s': e-mail of the account %d found (ip: %s).\n",
- server[id].name, RFIFOL(fd, 2), ip);
+ server[id].name, account_id, ip);
WFIFOW(fd, 0) = 0x2717;
- WFIFOL(fd, 2) = RFIFOL(fd, 2);
+ WFIFOL(fd, 2) = account_id;
WFIFO_STRING(fd, 6, ad.email, 40);
WFIFOL(fd, 46) = static_cast<time_t>(ad.connect_until_time);
WFIFOSET(fd, 50);
@@ -1197,7 +1149,8 @@ void parse_fromchar(int fd)
}
}
LOGIN_LOG("Char-server '%s': e-mail of the account %d NOT found (ip: %s).\n",
- server[id].name, RFIFOL(fd, 2), ip);
+ server[id].name, account_id, ip);
+ }
x2716_end:
RFIFOSKIP(fd, 6);
break;
@@ -1215,10 +1168,9 @@ void parse_fromchar(int fd)
WBUFL(buf, 2) = acc;
WBUFL(buf, 6) = 0;
size_t len = RFIFOW(fd, 2) - 8;
- char pass[len];
- RFIFO_STRING(fd, 8, pass, len);
+ FString pass = RFIFO_STRING(fd, 8, len);
- if (strcmp(pass, gm_pass) == 0)
+ if (pass == gm_pass)
{
// only non-GM can become GM
if (isGM(acc) == 0)
@@ -1227,9 +1179,7 @@ void parse_fromchar(int fd)
if (level_new_gm > 0)
{
// if we can open the file to add the new GM
- if ((fp =
- fopen_(GM_account_filename,
- "a")) != NULL)
+ if ((fp = fopen(GM_account_filename.c_str(), "a")) != NULL)
{
timestamp_seconds_buffer tmpstr;
stamp_time(tmpstr);
@@ -1237,7 +1187,7 @@ void parse_fromchar(int fd)
"\n// %s: @GM command on account %d\n%d %d\n",
tmpstr,
acc, acc, level_new_gm);
- fclose_(fp);
+ fclose(fp);
WBUFL(buf, 6) = level_new_gm;
read_gm_account();
send_GM_accounts();
@@ -1288,20 +1238,16 @@ void parse_fromchar(int fd)
if (RFIFOREST(fd) < 86)
return;
{
- int acc;
- char actual_email[40], new_email[40];
- acc = RFIFOL(fd, 2);
- RFIFO_STRING(fd, 6, actual_email, 40);
- remove_control_chars(actual_email);
- RFIFO_STRING(fd, 46, new_email, 40);
- remove_control_chars(new_email);
- if (e_mail_check(actual_email) == 0)
+ int acc = RFIFOL(fd, 2);
+ AccountEmail actual_email = stringish<AccountEmail>(RFIFO_STRING<40>(fd, 6).to_print());
+ AccountEmail new_email = stringish<AccountEmail>(RFIFO_STRING<40>(fd, 46));
+ if (!e_mail_check(actual_email))
LOGIN_LOG("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but actual email is invalid (account: %d, ip: %s)\n",
server[id].name, acc, ip);
- else if (e_mail_check(new_email) == 0)
+ else if (!e_mail_check(new_email))
LOGIN_LOG("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command) with a invalid new e-mail (account: %d, ip: %s)\n",
server[id].name, acc, ip);
- else if (strcasecmp(new_email, "a@a.com") == 0)
+ else if (new_email == DEFAULT_EMAIL)
LOGIN_LOG("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command) with a default e-mail (account: %d, ip: %s)\n",
server[id].name, acc, ip);
else
@@ -1310,9 +1256,9 @@ void parse_fromchar(int fd)
{
if (ad.account_id == acc)
{
- if (strcasecmp(ad.email, actual_email) == 0)
+ if (ad.email == actual_email)
{
- strzcpy(ad.email, new_email, 40);
+ ad.email = new_email;
LOGIN_LOG("Char-server '%s': Modify an e-mail on an account (@email GM command) (account: %d (%s), new e-mail: %s, ip: %s).\n",
server[id].name, acc,
ad.userid, new_email, ip);
@@ -1396,12 +1342,14 @@ void parse_fromchar(int fd)
else
timestamp = ad.ban_until_time;
struct tm tmtime = timestamp;
- tmtime.tm_year += static_cast<short>(RFIFOW(fd, 6));
- tmtime.tm_mon += static_cast<short>(RFIFOW(fd, 8));
- tmtime.tm_mday += static_cast<short>(RFIFOW(fd, 10));
- tmtime.tm_hour += static_cast<short>(RFIFOW(fd, 12));
- tmtime.tm_min += static_cast<short>(RFIFOW(fd, 14));
- tmtime.tm_sec += static_cast<short>(RFIFOW(fd, 16));
+ HumanTimeDiff ban_diff;
+ RFIFO_STRUCT(fd, 6, ban_diff);
+ tmtime.tm_year += ban_diff.year;
+ tmtime.tm_mon += ban_diff.month;
+ tmtime.tm_mday += ban_diff.day;
+ tmtime.tm_hour += ban_diff.hour;
+ tmtime.tm_min += ban_diff.minute;
+ tmtime.tm_sec += ban_diff.second;
timestamp = tmtime;
if (timestamp.okay())
{
@@ -1521,8 +1469,7 @@ void parse_fromchar(int fd)
p < len && j < ACCOUNT_REG2_NUM;
p += 36, j++)
{
- RFIFO_STRING(fd, p, ad.account_reg2[j].str, 32);
- remove_control_chars(ad.account_reg2[j].str);
+ ad.account_reg2[j].str = stringish<VarName>(RFIFO_STRING<32>(fd, p).to_print());
ad.account_reg2[j].value = RFIFOL(fd, p + 32);
}
ad.account_reg2_num = j;
@@ -1577,13 +1524,9 @@ void parse_fromchar(int fd)
if (RFIFOREST(fd) < 54)
return;
{
- int acc;
- char actual_pass[24], new_pass[24];
- acc = RFIFOL(fd, 2);
- RFIFO_STRING(fd, 6, actual_pass, 24);
- remove_control_chars(actual_pass);
- RFIFO_STRING(fd, 30, new_pass, 24);
- remove_control_chars(new_pass);
+ int acc = RFIFOL(fd, 2);
+ AccountPass actual_pass = stringish<AccountPass>(RFIFO_STRING<24>(fd, 6).to_print());
+ AccountPass new_pass = stringish<AccountPass>(RFIFO_STRING<24>(fd, 30).to_print());
int status = 0;
@@ -1593,12 +1536,12 @@ void parse_fromchar(int fd)
{
if (pass_ok(actual_pass, ad.pass))
{
- if (strlen(new_pass) < 4)
+ if (new_pass.size() < 4)
status = 3;
else
{
status = 1;
- strcpy(ad.pass, MD5_saltcrypt(new_pass, make_salt()));
+ ad.pass = MD5_saltcrypt(new_pass, make_salt());
LOGIN_LOG("Char-server '%s': Change pass success (account: %d (%s), ip: %s.\n",
server[id].name, acc,
ad.userid, ip);
@@ -1626,8 +1569,7 @@ void parse_fromchar(int fd)
default:
{
- FILE *logfp;
- logfp = fopen_(login_log_unknown_packets_filename, "a");
+ FILE *logfp = fopen(login_log_unknown_packets_filename.c_str(), "a");
if (logfp)
{
timestamp_milliseconds_buffer timestr;
@@ -1657,7 +1599,7 @@ void parse_fromchar(int fd)
else if ((i + 1) % 16 == 0)
{
FPRINTF(logfp, " %s\n", tmpstr);
- strzcpy(tmpstr, "", 16 + 1);
+ std::fill(tmpstr + 0, tmpstr + 17, '\0');
}
}
if (i % 16 != 0)
@@ -1671,7 +1613,7 @@ void parse_fromchar(int fd)
FPRINTF(logfp, " %s\n", tmpstr);
}
FPRINTF(logfp, "\n");
- fclose_(logfp);
+ fclose(logfp);
}
}
PRINTF("parse_fromchar: Unknown packet 0x%x (from a char-server)! -> disconnection.\n",
@@ -1690,9 +1632,7 @@ void parse_fromchar(int fd)
static
void parse_admin(int fd)
{
- char account_name[24];
-
- const char *ip = ip2str(session[fd]->client_addr.sin_addr);
+ IP_String ip = ip2str(session[fd]->client_addr.sin_addr);
if (session[fd]->eof)
{
@@ -1792,14 +1732,14 @@ void parse_admin(int fd)
return;
{
struct mmo_account ma;
- RFIFO_STRING(fd, 2, ma.userid, 24);
- RFIFO_STRING(fd, 26, ma.passwd, 24);
- strzcpy(ma.lastlogin, "-", 24);
+ ma.userid = stringish<AccountName>(RFIFO_STRING<24>(fd, 2).to_print());
+ ma.passwd = stringish<AccountPass>(RFIFO_STRING<24>(fd, 26).to_print());
+ ma.lastlogin = stringish<timestamp_milliseconds_buffer>("-");
ma.sex = RFIFOB(fd, 50);
WFIFOW(fd, 0) = 0x7931;
WFIFOL(fd, 2) = -1;
WFIFO_STRING(fd, 6, ma.userid, 24);
- if (strlen(ma.userid) < 4 || strlen(ma.passwd) < 4)
+ if (ma.userid.size() < 4 || ma.passwd.size() < 4)
{
LOGIN_LOG("'ladmin': Attempt to create an invalid account (account or pass is too short, ip: %s)\n",
ip);
@@ -1816,11 +1756,9 @@ void parse_admin(int fd)
}
else
{
- remove_control_chars(ma.userid);
- remove_control_chars(ma.passwd);
for (const AuthData& ad : auth_data)
{
- if (strncmp(ad.userid, ma.userid, 24) == 0)
+ if (ad.userid == ma.userid)
{
LOGIN_LOG("'ladmin': Attempt to create an already existing account (account: %s ip: %s)\n",
ad.userid, ip);
@@ -1828,11 +1766,8 @@ void parse_admin(int fd)
}
}
{
- int new_id;
- char email[40];
- RFIFO_STRING(fd, 51, email, 40);
- remove_control_chars(email);
- new_id = mmo_auth_new(&ma, ma.sex, email);
+ AccountEmail email = stringish<AccountEmail>(RFIFO_STRING<40>(fd, 51));
+ int new_id = mmo_auth_new(&ma, ma.sex, email);
LOGIN_LOG("'ladmin': Account creation (account: %s (id: %d), sex: %c, email: %s, ip: %s)\n",
ma.userid, new_id,
ma.sex, auth_data.back().email, ip);
@@ -1851,12 +1786,10 @@ void parse_admin(int fd)
{
WFIFOW(fd, 0) = 0x7933;
WFIFOL(fd, 2) = -1;
- RFIFO_STRING(fd, 2, account_name, 24);
- remove_control_chars(account_name);
+ AccountName account_name = stringish<AccountName>(RFIFO_STRING<24>(fd, 2).to_print());
AuthData *ad = search_account(account_name);
if (ad)
{
- // TODO rename so I don't need anti-shadow braces
// Char-server is notified of deletion (for characters deletion).
uint8_t buf[6];
WBUFW(buf, 0) = 0x2730;
@@ -1870,11 +1803,11 @@ void parse_admin(int fd)
ad->userid, ad->account_id,
ip);
{
- std::string buf2 = mmo_auth_tostr(ad);
+ FString buf2 = mmo_auth_tostr(ad);
LOGIN_LOG("%s\n", buf2);
}
// delete account
- strzcpy(ad->userid, "", 24);
+ ad->userid = AccountName();
ad->account_id = -1;
}
else
@@ -1894,15 +1827,13 @@ void parse_admin(int fd)
{
WFIFOW(fd, 0) = 0x7935;
WFIFOL(fd, 2) = -1;
- RFIFO_STRING(fd, 2, account_name, 24);
- remove_control_chars(account_name);
+ AccountName account_name = stringish<AccountName>(RFIFO_STRING<24>(fd, 2).to_print());
AuthData *ad = search_account(account_name);
if (ad)
{
WFIFO_STRING(fd, 6, ad->userid, 24);
- char plain[24];
- RFIFO_STRING(fd, 26, plain, 24);
- strzcpy(ad->pass, MD5_saltcrypt(plain, make_salt()), 40);
+ AccountPass plain = stringish<AccountPass>(RFIFO_STRING<24>(fd, 26));
+ ad->pass = MD5_saltcrypt(plain, make_salt());
WFIFOL(fd, 2) = ad->account_id;
LOGIN_LOG("'ladmin': Modification of a password (account: %s, new password: %s, ip: %s)\n",
ad->userid, ad->pass, ip);
@@ -1922,18 +1853,15 @@ void parse_admin(int fd)
if (RFIFOREST(fd) < 50)
return;
{
- char error_message[20];
- int statut;
WFIFOW(fd, 0) = 0x7937;
WFIFOL(fd, 2) = -1;
- RFIFO_STRING(fd, 2, account_name, 24);
- remove_control_chars(account_name);
- statut = RFIFOL(fd, 26);
- RFIFO_STRING(fd, 30, error_message, 20);
- remove_control_chars(error_message);
- if (statut != 7 || error_message[0] == '\0')
- { // 7: // 6 = Your are Prohibited to log in until %s
- strcpy(error_message, "-");
+ AccountName account_name = stringish<AccountName>(RFIFO_STRING<24>(fd, 2).to_print());
+ int statut = RFIFOL(fd, 26);
+ timestamp_seconds_buffer error_message = stringish<timestamp_seconds_buffer>(RFIFO_STRING<20>(fd, 30).to_print());
+ if (statut != 7 || !error_message)
+ {
+ // 7: // 6 = Your are Prohibited to log in until %s
+ error_message = stringish<timestamp_seconds_buffer>("-");
}
AuthData *ad = search_account(account_name);
if (ad)
@@ -1941,7 +1869,7 @@ void parse_admin(int fd)
WFIFO_STRING(fd, 6, ad->userid, 24);
WFIFOL(fd, 2) = ad->account_id;
if (ad->state == statut
- && strcmp(ad->error_message, error_message) == 0)
+ && ad->error_message == error_message)
LOGIN_LOG("'ladmin': Modification of a state, but the state of the account is already the good state (account: %s, received state: %d, ip: %s)\n",
account_name, statut, ip);
else
@@ -1967,7 +1895,7 @@ void parse_admin(int fd)
auth_fifo[j].login_id1++; // to avoid reconnection error when come back from map-server (char-server will ask again the authentification)
}
ad->state = statut;
- strzcpy(ad->error_message, error_message, 20);
+ ad->error_message = error_message;
}
}
else
@@ -2010,14 +1938,12 @@ void parse_admin(int fd)
{
WFIFOW(fd, 0) = 0x793b;
WFIFOL(fd, 2) = -1;
- RFIFO_STRING(fd, 2, account_name, 24);
- remove_control_chars(account_name);
+ AccountName account_name = stringish<AccountName>(RFIFO_STRING<24>(fd, 2).to_print());
const AuthData *ad = search_account(account_name);
if (ad)
{
WFIFO_STRING(fd, 6, ad->userid, 24);
- char pass[24];
- RFIFO_STRING(fd, 26, pass, 24);
+ AccountPass pass = stringish<AccountPass>(RFIFO_STRING<24>(fd, 26));
if (pass_ok(pass, ad->pass))
{
WFIFOL(fd, 2) = ad->account_id;
@@ -2027,9 +1953,8 @@ void parse_admin(int fd)
}
else
{
- remove_control_chars(pass);
LOGIN_LOG("'ladmin': Failure of password check (account: %s, proposed pass: %s, ip: %s)\n",
- ad->userid, pass, ip);
+ ad->userid, pass.to_print(), ip);
}
}
else
@@ -2046,10 +1971,10 @@ void parse_admin(int fd)
case 0x793c: // Request to modify sex
if (RFIFOREST(fd) < 27)
return;
+ {
WFIFOW(fd, 0) = 0x793d;
WFIFOL(fd, 2) = -1;
- RFIFO_STRING(fd, 2, account_name, 24);
- remove_control_chars(account_name);
+ AccountName account_name = stringish<AccountName>(RFIFO_STRING<24>(fd, 2).to_print());
WFIFO_STRING(fd, 6, account_name, 24);
{
char sex;
@@ -2103,16 +2028,17 @@ void parse_admin(int fd)
}
}
WFIFOSET(fd, 30);
+ }
RFIFOSKIP(fd, 27);
break;
case 0x793e: // Request to modify GM level
if (RFIFOREST(fd) < 27)
return;
+ {
WFIFOW(fd, 0) = 0x793f;
WFIFOL(fd, 2) = -1;
- RFIFO_STRING(fd, 2, account_name, 24);
- remove_control_chars(account_name);
+ AccountName account_name = stringish<AccountName>(RFIFO_STRING<24>(fd, 2).to_print());
WFIFO_STRING(fd, 6, account_name, 24);
{
char new_gm_level;
@@ -2137,13 +2063,9 @@ void parse_admin(int fd)
char line[512];
int GM_account, GM_level;
int modify_flag;
- if ((fp2 =
- lock_fopen(GM_account_filename,
- &lock)) != NULL)
+ if ((fp2 = lock_fopen(GM_account_filename, &lock)) != NULL)
{
- if ((fp =
- fopen_(GM_account_filename,
- "r")) != NULL)
+ if ((fp = fopen(GM_account_filename.c_str(), "r")) != NULL)
{
timestamp_seconds_buffer tmpstr;
stamp_time(tmpstr);
@@ -2152,12 +2074,8 @@ void parse_admin(int fd)
while (fgets(line, sizeof(line) - 1, fp))
{
while (line[0] != '\0'
- && (line[strlen(line) - 1]
- == '\n'
- || line[strlen(line) -
- 1] == '\r'))
- line[strlen(line) - 1] =
- '\0';
+ && line[strlen(line) - 1] == '\n')
+ line[strlen(line) - 1] = '\0';
if ((line[0] == '/'
&& line[1] == '/')
|| line[0] == '\0')
@@ -2209,7 +2127,7 @@ void parse_admin(int fd)
tmpstr, acc,
ad->userid, acc,
new_gm_level);
- fclose_(fp);
+ fclose(fp);
}
else
{
@@ -2249,33 +2167,32 @@ void parse_admin(int fd)
}
}
WFIFOSET(fd, 30);
+ }
RFIFOSKIP(fd, 27);
break;
case 0x7940: // Request to modify e-mail
if (RFIFOREST(fd) < 66)
return;
+ {
WFIFOW(fd, 0) = 0x7941;
WFIFOL(fd, 2) = -1;
- RFIFO_STRING(fd, 2, account_name, 24);
- remove_control_chars(account_name);
+ AccountName account_name = stringish<AccountName>(RFIFO_STRING<24>(fd, 2).to_print());
WFIFO_STRING(fd, 6, account_name, 24);
{
- char email[40];
- RFIFO_STRING(fd, 26, email, 40);
- if (e_mail_check(email) == 0)
+ AccountEmail email = stringish<AccountEmail>(RFIFO_STRING<40>(fd, 26));
+ if (!e_mail_check(email))
{
LOGIN_LOG("'ladmin': Attempt to give an invalid e-mail (account: %s, ip: %s)\n",
account_name, ip);
}
else
{
- remove_control_chars(email);
AuthData *ad = search_account(account_name);
if (ad)
{
WFIFO_STRING(fd, 6, ad->userid, 24);
- strzcpy(ad->email, email, 40);
+ ad->email = email;
WFIFOL(fd, 2) = ad->account_id;
LOGIN_LOG("'ladmin': Modification of an email (account: %s, new e-mail: %s, ip: %s)\n",
ad->userid, email, ip);
@@ -2288,6 +2205,7 @@ void parse_admin(int fd)
}
}
WFIFOSET(fd, 30);
+ }
RFIFOSKIP(fd, 66);
break;
@@ -2298,27 +2216,23 @@ void parse_admin(int fd)
{
WFIFOW(fd, 0) = 0x7943;
WFIFOL(fd, 2) = -1;
- RFIFO_STRING(fd, 2, account_name, 24);
- remove_control_chars(account_name);
+ AccountName account_name = stringish<AccountName>(RFIFO_STRING<24>(fd, 2).to_print());
AuthData *ad = search_account(account_name);
if (ad)
{
- size_t size_of_memo = sizeof(ad->memo);
WFIFO_STRING(fd, 6, ad->userid, 24);
- strzcpy(ad->memo, "", size_of_memo);
+ ad->memo = "";
if (RFIFOW(fd, 26) == 0)
{
- strzcpy(ad->memo, "!", size_of_memo);
+ ad->memo = "!";
}
else
{
size_t len = RFIFOW(fd, 26);
- if (len > size_of_memo)
- len = size_of_memo;
- RFIFO_STRING(fd, 28, ad->memo, len);
+ // may truncate
+ ad->memo = RFIFO_STRING(fd, 28, len);
}
- ad->memo[size_of_memo - 1] = '\0';
- remove_control_chars(ad->memo);
+ ad->memo = ad->memo.to_print();
WFIFOL(fd, 2) = ad->account_id;
LOGIN_LOG("'ladmin': Modification of a memo field (account: %s, new memo: %s, ip: %s)\n",
ad->userid, ad->memo, ip);
@@ -2340,8 +2254,7 @@ void parse_admin(int fd)
{
WFIFOW(fd, 0) = 0x7945;
WFIFOL(fd, 2) = -1;
- RFIFO_STRING(fd, 2, account_name, 24);
- remove_control_chars(account_name);
+ AccountName account_name = stringish<AccountName>(RFIFO_STRING<24>(fd, 2).to_print());
const AuthData *ad = search_account(account_name);
if (ad)
{
@@ -2365,24 +2278,27 @@ void parse_admin(int fd)
case 0x7946: // Request to found an account name
if (RFIFOREST(fd) < 6)
return;
+ {
+ int account_id = RFIFOL(fd, 2);
WFIFOW(fd, 0) = 0x7947;
- WFIFOL(fd, 2) = RFIFOL(fd, 2);
+ WFIFOL(fd, 2) = account_id;
WFIFO_ZERO(fd, 6, 24);
for (const AuthData& ad : auth_data)
{
- if (ad.account_id == RFIFOL(fd, 2))
+ if (ad.account_id == account_id)
{
WFIFO_STRING(fd, 6, ad.userid, 24);
LOGIN_LOG("'ladmin': Request (by id) of an account name (account: %s, id: %d, ip: %s)\n",
- ad.userid, RFIFOL(fd, 2), ip);
+ ad.userid, account_id, ip);
goto x7946_out;
}
}
LOGIN_LOG("'ladmin': Name request (by id) of an unknown account (id: %d, ip: %s)\n",
- RFIFOL(fd, 2), ip);
+ account_id, ip);
WFIFO_STRING(fd, 6, "", 24);
x7946_out:
WFIFOSET(fd, 30);
+ }
RFIFOSKIP(fd, 6);
break;
@@ -2392,10 +2308,9 @@ void parse_admin(int fd)
{
WFIFOW(fd, 0) = 0x7949;
WFIFOL(fd, 2) = -1;
- RFIFO_STRING(fd, 2, account_name, 24);
- remove_control_chars(account_name);
+ AccountName account_name = stringish<AccountName>(RFIFO_STRING<24>(fd, 2).to_print());
TimeT timestamp = static_cast<time_t>(RFIFOL(fd, 26));
- timestamp_seconds_buffer tmpstr = "unlimited";
+ timestamp_seconds_buffer tmpstr = stringish<timestamp_seconds_buffer>("unlimited");
if (timestamp)
stamp_time(tmpstr, &timestamp);
AuthData *ad = search_account(account_name);
@@ -2431,12 +2346,11 @@ void parse_admin(int fd)
{
WFIFOW(fd, 0) = 0x794b;
WFIFOL(fd, 2) = -1;
- RFIFO_STRING(fd, 2, account_name, 24);
- remove_control_chars(account_name);
+ AccountName account_name = stringish<AccountName>(RFIFO_STRING<24>(fd, 2).to_print());
TimeT timestamp = static_cast<time_t>(RFIFOL(fd, 26));
if (timestamp <= TimeT::now())
timestamp = TimeT();
- timestamp_seconds_buffer tmpstr = "no banishment";
+ timestamp_seconds_buffer tmpstr = stringish<timestamp_seconds_buffer>("no banishment");
if (timestamp)
stamp_time(tmpstr, &timestamp);
AuthData *ad = search_account(account_name);
@@ -2486,8 +2400,7 @@ void parse_admin(int fd)
{
WFIFOW(fd, 0) = 0x794d;
WFIFOL(fd, 2) = -1;
- RFIFO_STRING(fd, 2, account_name, 24);
- remove_control_chars(account_name);
+ AccountName account_name = stringish<AccountName>(RFIFO_STRING<24>(fd, 2).to_print());
AuthData *ad = search_account(account_name);
if (ad)
{
@@ -2501,25 +2414,27 @@ void parse_admin(int fd)
else
timestamp = ad->ban_until_time;
struct tm tmtime = timestamp;
- tmtime.tm_year += static_cast<short>(RFIFOW(fd, 26));
- tmtime.tm_mon += static_cast<short>(RFIFOW(fd, 28));
- tmtime.tm_mday += static_cast<short>(RFIFOW(fd, 30));
- tmtime.tm_hour += static_cast<short>(RFIFOW(fd, 32));
- tmtime.tm_min += static_cast<short>(RFIFOW(fd, 34));
- tmtime.tm_sec += static_cast<short>(RFIFOW(fd, 36));
+ HumanTimeDiff ban_diff;
+ RFIFO_STRUCT(fd, 26, ban_diff);
+ tmtime.tm_year += ban_diff.year;
+ tmtime.tm_mon += ban_diff.month;
+ tmtime.tm_mday += ban_diff.day;
+ tmtime.tm_hour += ban_diff.hour;
+ tmtime.tm_min += ban_diff.minute;
+ tmtime.tm_sec += ban_diff.second;
timestamp = tmtime;
if (timestamp.okay())
{
if (timestamp <= now)
timestamp = TimeT();
- timestamp_seconds_buffer tmpstr = "no banishment";
+ timestamp_seconds_buffer tmpstr = stringish<timestamp_seconds_buffer>("no banishment");
if (timestamp)
stamp_time(tmpstr, &timestamp);
LOGIN_LOG("'ladmin': Adjustment of a final date of a banishment (account: %s, (%+d y %+d m %+d d %+d h %+d mn %+d s) -> new validity: %lld (%s), ip: %s)\n",
ad->userid,
- static_cast<short>(RFIFOW(fd, 26)), static_cast<short>(RFIFOW(fd, 28)),
- static_cast<short>(RFIFOW(fd, 30)), static_cast<short>(RFIFOW(fd, 32)),
- static_cast<short>(RFIFOW(fd, 34)), static_cast<short>(RFIFOW(fd, 36)),
+ ban_diff.year, ban_diff.month,
+ ban_diff.day, ban_diff.hour,
+ ban_diff.minute, ban_diff.second,
timestamp,
tmpstr,
ip);
@@ -2543,16 +2458,16 @@ void parse_admin(int fd)
}
else
{
- timestamp_seconds_buffer tmpstr = "no banishment";
+ timestamp_seconds_buffer tmpstr = stringish<timestamp_seconds_buffer>("no banishment");
if (ad->ban_until_time)
stamp_time(tmpstr, &ad->ban_until_time);
LOGIN_LOG("'ladmin': Impossible to adjust the final date of a banishment (account: %s, %lld (%s) + (%+d y %+d m %+d d %+d h %+d mn %+d s) -> ???, ip: %s)\n",
ad->userid,
ad->ban_until_time,
tmpstr,
- static_cast<short>(RFIFOW(fd, 26)), static_cast<short>(RFIFOW(fd, 28)),
- static_cast<short>(RFIFOW(fd, 30)), static_cast<short>(RFIFOW(fd, 32)),
- static_cast<short>(RFIFOW(fd, 34)), static_cast<short>(RFIFOW(fd, 36)),
+ ban_diff.year, ban_diff.month,
+ ban_diff.day, ban_diff.hour,
+ ban_diff.minute, ban_diff.second,
ip);
}
WFIFOL(fd, 30) = static_cast<time_t>(ad->ban_until_time);
@@ -2595,24 +2510,15 @@ void parse_admin(int fd)
WFIFOW(fd, 2) = 0;
size_t len = RFIFOL(fd, 4);
- char message[len];
- RFIFO_STRING(fd, 8, message, len);
- remove_control_chars(message);
- const char *message_ptr = message;
+ FString message = RFIFO_STRING(fd, 8, len).to_print();
LOGIN_LOG("'ladmin': Receiving a message for broadcast (message: %s, ip: %s)\n",
- message_ptr, ip);
+ message, ip);
// send same message to all char-servers (no answer)
uint8_t buf[len + 8];
RFIFO_BUF_CLONE(fd, buf, 8 + len);
WBUFW(buf, 0) = 0x2726;
charif_sendallwos(-1, buf, 8 + len);
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wuninitialized" // work around a gcc bug
-#pragma GCC diagnostic ignored "-Wunknown-pragmas"
-#pragma GCC diagnostic ignored "-Wpragmas"
-#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
}
-#pragma GCC diagnostic pop
}
x794e_have_no_server:
WFIFOSET(fd, 4);
@@ -2625,8 +2531,7 @@ void parse_admin(int fd)
{
WFIFOW(fd, 0) = 0x7951;
WFIFOL(fd, 2) = -1;
- RFIFO_STRING(fd, 2, account_name, 24);
- remove_control_chars(account_name);
+ AccountName account_name = stringish<AccountName>(RFIFO_STRING<24>(fd, 2).to_print());
AuthData *ad = search_account(account_name);
if (ad)
{
@@ -2645,17 +2550,19 @@ void parse_admin(int fd)
if (!timestamp || timestamp < now)
timestamp = now;
struct tm tmtime = timestamp;
- tmtime.tm_year += static_cast<short>(RFIFOW(fd, 26));
- tmtime.tm_mon += static_cast<short>(RFIFOW(fd, 28));
- tmtime.tm_mday += static_cast<short>(RFIFOW(fd, 30));
- tmtime.tm_hour += static_cast<short>(RFIFOW(fd, 32));
- tmtime.tm_min += static_cast<short>(RFIFOW(fd, 34));
- tmtime.tm_sec += static_cast<short>(RFIFOW(fd, 36));
+ HumanTimeDiff v_diff;
+ RFIFO_STRUCT(fd, 26, v_diff);
+ tmtime.tm_year += v_diff.year;
+ tmtime.tm_mon += v_diff.month;
+ tmtime.tm_mday += v_diff.day;
+ tmtime.tm_hour += v_diff.hour;
+ tmtime.tm_min += v_diff.minute;
+ tmtime.tm_sec += v_diff.second;
timestamp = tmtime;
if (timestamp.okay())
{
- timestamp_seconds_buffer tmpstr = "unlimited";
- timestamp_seconds_buffer tmpstr2 = "unlimited";
+ timestamp_seconds_buffer tmpstr = stringish<timestamp_seconds_buffer>("unlimited");
+ timestamp_seconds_buffer tmpstr2 = stringish<timestamp_seconds_buffer>("unlimited");
if (ad->connect_until_time)
stamp_time(tmpstr, &ad->connect_until_time);
if (timestamp)
@@ -2664,12 +2571,12 @@ void parse_admin(int fd)
ad->userid,
ad->connect_until_time,
tmpstr,
- static_cast<short>(RFIFOW(fd, 26)),
- static_cast<short>(RFIFOW(fd, 28)),
- static_cast<short>(RFIFOW(fd, 30)),
- static_cast<short>(RFIFOW(fd, 32)),
- static_cast<short>(RFIFOW(fd, 34)),
- static_cast<short>(RFIFOW(fd, 36)),
+ v_diff.year,
+ v_diff.month,
+ v_diff.day,
+ v_diff.hour,
+ v_diff.minute,
+ v_diff.second,
timestamp,
tmpstr2,
ip);
@@ -2678,19 +2585,19 @@ void parse_admin(int fd)
}
else
{
- timestamp_seconds_buffer tmpstr = "unlimited";
+ timestamp_seconds_buffer tmpstr = stringish<timestamp_seconds_buffer>("unlimited");
if (ad->connect_until_time)
stamp_time(tmpstr, &ad->connect_until_time);
LOGIN_LOG("'ladmin': Impossible to adjust a validity limit (account: %s, %lld (%s) + (%+d y %+d m %+d d %+d h %+d mn %+d s) -> ???, ip: %s)\n",
ad->userid,
ad->connect_until_time,
tmpstr,
- static_cast<short>(RFIFOW(fd, 26)),
- static_cast<short>(RFIFOW(fd, 28)),
- static_cast<short>(RFIFOW(fd, 30)),
- static_cast<short>(RFIFOW(fd, 32)),
- static_cast<short>(RFIFOW(fd, 34)),
- static_cast<short>(RFIFOW(fd, 36)),
+ v_diff.year,
+ v_diff.month,
+ v_diff.day,
+ v_diff.hour,
+ v_diff.minute,
+ v_diff.second,
ip);
WFIFOL(fd, 30) = 0;
}
@@ -2714,8 +2621,7 @@ void parse_admin(int fd)
{
WFIFOW(fd, 0) = 0x7953;
WFIFOL(fd, 2) = -1;
- RFIFO_STRING(fd, 2, account_name, 24);
- remove_control_chars(account_name);
+ AccountName account_name = stringish<AccountName>(RFIFO_STRING<24>(fd, 2).to_print());
const AuthData *ad = search_account(account_name);
if (ad)
{
@@ -2731,7 +2637,7 @@ void parse_admin(int fd)
WFIFO_STRING(fd, 100, ad->email, 40);
WFIFOL(fd, 140) = static_cast<time_t>(ad->connect_until_time);
WFIFOL(fd, 144) = static_cast<time_t>(ad->ban_until_time);
- size_t len = strlen(ad->memo) + 1;
+ size_t len = ad->memo.size() + 1;
WFIFOW(fd, 148) = len;
WFIFO_STRING(fd, 150, ad->memo, len);
LOGIN_LOG("'ladmin': Sending information of an account (request by the name; account: %s, id: %d, ip: %s)\n",
@@ -2774,7 +2680,7 @@ void parse_admin(int fd)
WFIFO_STRING(fd, 100, ad.email, 40);
WFIFOL(fd, 140) = static_cast<time_t>(ad.connect_until_time);
WFIFOL(fd, 144) = static_cast<time_t>(ad.ban_until_time);
- size_t len = strlen(ad.memo) + 1;
+ size_t len = ad.memo.size() + 1;
WFIFOW(fd, 148) = len;
WFIFO_STRING(fd, 150, ad.memo, len);
WFIFOSET(fd, 150 + len);
@@ -2803,8 +2709,7 @@ void parse_admin(int fd)
default:
{
- FILE *logfp;
- logfp = fopen_(login_log_unknown_packets_filename, "a");
+ FILE *logfp = fopen(login_log_unknown_packets_filename.c_str(), "a");
if (logfp)
{
timestamp_milliseconds_buffer timestr;
@@ -2834,7 +2739,7 @@ void parse_admin(int fd)
else if ((i + 1) % 16 == 0)
{
FPRINTF(logfp, " %s\n", tmpstr);
- strzcpy(tmpstr, "", 16 + 1);
+ std::fill(tmpstr + 0, tmpstr + 17, '\0');
}
}
if (i % 16 != 0)
@@ -2848,7 +2753,7 @@ void parse_admin(int fd)
FPRINTF(logfp, " %s\n", tmpstr);
}
FPRINTF(logfp, "\n");
- fclose_(logfp);
+ fclose(logfp);
}
}
LOGIN_LOG("'ladmin': End of connection, unknown packet (ip: %s)\n",
@@ -2900,7 +2805,7 @@ void parse_login(int fd)
int result, j;
uint8_t *p = reinterpret_cast<uint8_t *>(&session[fd]->client_addr.sin_addr);
- const char *ip = ip2str(session[fd]->client_addr.sin_addr);
+ IP_String ip = ip2str(session[fd]->client_addr.sin_addr);
if (session[fd]->eof)
{
@@ -2916,8 +2821,7 @@ void parse_login(int fd)
{
if (RFIFOREST(fd) >= ((RFIFOW(fd, 0) == 0x64) ? 55 : 47))
{
- char account_name[24];
- RFIFO_STRING(fd, 6, account_name, 24);
+ AccountName account_name = stringish<AccountName>(RFIFO_STRING<24>(fd, 6));
PRINTF("parse_login: connection #%d, packet: 0x%x (with being read: %zu), account: %s.\n",
fd, RFIFOW(fd, 0), RFIFOREST(fd),
account_name);
@@ -2927,8 +2831,7 @@ void parse_login(int fd)
{
if (RFIFOREST(fd) >= 86)
{
- char server_name[16];
- RFIFO_STRING(fd, 60, server_name, 16);
+ ServerName server_name = stringish<ServerName>(RFIFO_STRING<20>(fd, 60));
PRINTF("parse_login: connection #%d, packet: 0x%x (with being read: %zu), server: %s.\n",
fd, RFIFOW(fd, 0), RFIFOREST(fd),
server_name);
@@ -2957,10 +2860,8 @@ void parse_login(int fd)
if (RFIFOREST(fd) < 55)
return;
- RFIFO_STRING(fd, 6, account.userid, 24);
- remove_control_chars(account.userid);
- RFIFO_STRING(fd, 30, account.passwd, 24);
- remove_control_chars(account.passwd);
+ account.userid = stringish<AccountName>(RFIFO_STRING<24>(fd, 6).to_print());
+ account.passwd = stringish<AccountPass>(RFIFO_STRING<24>(fd, 30).to_print());
account.passwdenc = 0;
LOGIN_LOG("Request for connection (non encryption mode) of %s (ip: %s).\n",
@@ -3022,10 +2923,9 @@ void parse_login(int fd)
*/
// if (version_2 & VERSION_2_UPDATEHOST)
{
- size_t host_len = strlen(update_host);
- if (host_len > 0)
+ if (update_host)
{
- host_len++;
+ size_t host_len = update_host.size() + 1;
WFIFOW(fd, 0) = 0x63;
WFIFOW(fd, 2) = 4 + host_len;
WFIFO_STRING(fd, 4, update_host, host_len);
@@ -3041,7 +2941,7 @@ void parse_login(int fd)
if (server_fd[i] >= 0)
{
if (lan_ip_check(p))
- WFIFOL(fd, 47 + server_num * 32) = inet_addr(lan_char_ip);
+ WFIFOL(fd, 47 + server_num * 32) = inet_addr(lan_char_ip.c_str());
else
WFIFOL(fd, 47 + server_num * 32) = server[i].ip;
WFIFOW(fd, 47 + server_num * 32 + 4) = server[i].port;
@@ -3118,56 +3018,15 @@ void parse_login(int fd)
RFIFOSKIP(fd, (RFIFOW(fd, 0) == 0x64) ? 55 : 47);
break;
- case 0x01db: // Sending request of the coding key
- case 0x791a: // Sending request of the coding key (administration packet)
- {
- if (session[fd]->session_data)
- {
- PRINTF("login: abnormal request of MD5 key (already opened session).\n");
- session[fd]->eof = 1;
- return;
- }
- std::unique_ptr<login_session_data, SessionDeleter> ld;
- ld = make_unique<login_session_data, SessionDeleter>();
- if (RFIFOW(fd, 0) == 0x01db)
- {
- LOGIN_LOG("Sending request of the coding key (ip: %s)\n",
- ip);
- }
- else
- {
- LOGIN_LOG("'ladmin': Sending request of the coding key (ip: %s)\n",
- ip);
- }
- // TODO fix or get rid of this
- // Creation of the coding key
- strzcpy(ld->md5key, "", sizeof(ld->md5key));
- ld->md5keylen = random_::in(12, 15);
- for (int i = 0; i < ld->md5keylen; i++)
- ld->md5key[i] = random_::in(1, 255);
-
- RFIFOSKIP(fd, 2);
- WFIFOW(fd, 0) = 0x01dc;
- WFIFOW(fd, 2) = 4 + ld->md5keylen + 1;
- WFIFO_STRING(fd, 4, ld->md5key, ld->md5keylen + 1);
- WFIFOSET(fd, WFIFOW(fd, 2));
- session[fd]->session_data = std::move(ld);
- }
- break;
-
case 0x2710: // Connection request of a char-server
if (RFIFOREST(fd) < 86)
return;
{
int len;
- char server_name[20];
- RFIFO_STRING(fd, 2, account.userid, 24);
- remove_control_chars(account.userid);
- RFIFO_STRING(fd, 26, account.passwd, 24);
- remove_control_chars(account.passwd);
+ account.userid = stringish<AccountName>(RFIFO_STRING<24>(fd, 2).to_print());
+ account.passwd = stringish<AccountPass>(RFIFO_STRING<24>(fd, 26).to_print());
account.passwdenc = 0;
- RFIFO_STRING(fd, 60, server_name, 20);
- remove_control_chars(server_name);
+ ServerName server_name = stringish<ServerName>(RFIFO_STRING<20>(fd, 60).to_print());
LOGIN_LOG("Connection request of the char-server '%s' @ %d.%d.%d.%d:%d (ip: %s)\n",
server_name, RFIFOB(fd, 54), RFIFOB(fd, 55),
RFIFOB(fd, 56), RFIFOB(fd, 57), RFIFOW(fd, 58),
@@ -3178,7 +3037,7 @@ void parse_login(int fd)
{
// If this is the main server, and we don't already have a main server
if (server_fd[0] <= 0
- && strcasecmp(server_name, main_server) == 0)
+ && server_name == main_server)
{
account.account_id = 0;
}
@@ -3208,7 +3067,7 @@ void parse_login(int fd)
server[account.account_id] = mmo_char_server{};
server[account.account_id].ip = RFIFOL(fd, 54);
server[account.account_id].port = RFIFOW(fd, 58);
- strzcpy(server[account.account_id].name, server_name, 20);
+ server[account.account_id].name = server_name;
server[account.account_id].users = 0;
server[account.account_id].maintenance = RFIFOW(fd, 82);
server[account.account_id].is_new = RFIFOW(fd, 84);
@@ -3278,16 +3137,13 @@ void parse_login(int fd)
}
else
{
- struct login_session_data *ld = static_cast<login_session_data *>(session[fd]->session_data.get());
if (RFIFOW(fd, 2) == 0)
{
// non encrypted password
- char password[24];
- RFIFO_STRING(fd, 4, password, 24);
- remove_control_chars(password);
+ AccountPass password = stringish<AccountPass>(RFIFO_STRING<24>(fd, 4).to_print());
// If remote administration is enabled and password sent by client matches password read from login server configuration file
if ((admin_state == 1)
- && (strcmp(password, admin_pass) == 0))
+ && (password == admin_pass))
{
LOGIN_LOG("'ladmin'-login: Connection in administration mode accepted (non encrypted password: %s, ip: %s)\n",
password, ip);
@@ -3303,39 +3159,10 @@ void parse_login(int fd)
password, ip);
}
else
- { // encrypted password
- if (!ld)
- PRINTF("'ladmin'-login: error! MD5 key not created/requested for an administration login.\n");
- else
+ {
+ // encrypted password
{
- char md5str[64] = "";
- uint8_t md5bin[32];
- if (RFIFOW(fd, 2) == 1)
- {
- strcpy(md5str, ld->md5key); // 20
- strcat(md5str, admin_pass); // 24
- }
- else if (RFIFOW(fd, 2) == 2)
- {
- strcpy(md5str, admin_pass); // 24
- strcat(md5str, ld->md5key); // 20
- }
- MD5_to_bin(MD5_from_cstring(md5str), md5bin);
- // If remote administration is enabled and password hash sent by client matches hash of password read from login server configuration file
- if ((admin_state == 1)
- && really_memequal(md5bin, static_cast<const uint8_t *>(RFIFOP(fd, 4)), 16))
- {
- LOGIN_LOG("'ladmin'-login: Connection in administration mode accepted (encrypted password, ip: %s)\n",
- ip);
- PRINTF("Connection of a remote administration accepted (encrypted password).\n");
- WFIFOB(fd, 2) = 0;
- session[fd]->func_parse = parse_admin;
- }
- else if (admin_state != 1)
- LOGIN_LOG("'ladmin'-login: Connection in administration mode REFUSED - remote administration is disabled (encrypted password, ip: %s)\n",
- ip);
- else
- LOGIN_LOG("'ladmin'-login: Connection in administration mode REFUSED - invalid password (encrypted password, ip: %s)\n",
+ LOGIN_LOG("'ladmin'-login: Connection in administration mode REFUSED - encrypted login is disabled (ip: %s)\n",
ip);
}
}
@@ -3347,8 +3174,7 @@ void parse_login(int fd)
default:
if (save_unknown_packets)
{
- FILE *logfp;
- logfp = fopen_(login_log_unknown_packets_filename, "a");
+ FILE *logfp = fopen(login_log_unknown_packets_filename.c_str(), "a");
if (logfp)
{
timestamp_milliseconds_buffer timestr;
@@ -3381,7 +3207,7 @@ void parse_login(int fd)
else if ((i + 1) % 16 == 0)
{
FPRINTF(logfp, " %s\n", tmpstr);
- strzcpy(tmpstr, "", 16 + 1);
+ std::fill(tmpstr + 0, tmpstr + 17, '\0');
}
}
if (i % 16 != 0)
@@ -3395,7 +3221,7 @@ void parse_login(int fd)
FPRINTF(logfp, " %s\n", tmpstr);
}
FPRINTF(logfp, "\n");
- fclose_(logfp);
+ fclose(logfp);
}
}
LOGIN_LOG("End of connection, unknown packet (ip: %s)\n", ip);
@@ -3410,12 +3236,12 @@ void parse_login(int fd)
// Reading Lan Support configuration
//----------------------------------
static
-int login_lan_config_read(const char *lancfgName)
+int login_lan_config_read(ZString lancfgName)
{
struct hostent *h = NULL;
// set default configuration
- strcpy(lan_char_ip, "127.0.0.1");
+ lan_char_ip = stringish<IP_String>("127.0.0.1");
subneti[0] = 127;
subneti[1] = 0;
subneti[2] = 0;
@@ -3423,7 +3249,7 @@ int login_lan_config_read(const char *lancfgName)
for (int j = 0; j < 4; j++)
subnetmaski[j] = 255;
- std::ifstream in(lancfgName);
+ std::ifstream in(lancfgName.c_str());
if (!in.is_open())
{
@@ -3434,10 +3260,11 @@ int login_lan_config_read(const char *lancfgName)
PRINTF("---Start reading Lan Support configuration file\n");
- std::string line;
- while (std::getline(in, line))
+ FString line;
+ while (io::getline(in, line))
{
- std::string w1, w2;
+ SString w1;
+ TString w2;
if (!split_key_value(line, &w1, &w2))
continue;
@@ -3447,7 +3274,7 @@ int login_lan_config_read(const char *lancfgName)
h = gethostbyname(w2.c_str());
if (h != NULL)
{
- sprintf(lan_char_ip, "%d.%d.%d.%d",
+ SNPRINTF(lan_char_ip, 16, "%d.%d.%d.%d",
static_cast<uint8_t>(h->h_addr[0]),
static_cast<uint8_t>(h->h_addr[1]),
static_cast<uint8_t>(h->h_addr[2]),
@@ -3455,7 +3282,7 @@ int login_lan_config_read(const char *lancfgName)
}
else
{
- strzcpy(lan_char_ip, w2.c_str(), sizeof(lan_char_ip));
+ lan_char_ip = stringish<IP_String>(w2);
}
PRINTF("LAN IP of char-server: %s.\n", lan_char_ip);
}
@@ -3499,7 +3326,8 @@ int login_lan_config_read(const char *lancfgName)
}
else
{
- PRINTF("WARNING: unknown lan-config key: %s\n", w1);
+ FString w1z = w1;
+ PRINTF("WARNING: unknown lan-config key: %s\n", w1z);
}
}
@@ -3513,7 +3341,7 @@ int login_lan_config_read(const char *lancfgName)
// sub-network check of the char-server
{
unsigned char p[4];
- sscanf(lan_char_ip, "%hhu.%hhu.%hhu.%hhu",
+ SSCANF(lan_char_ip, "%hhu.%hhu.%hhu.%hhu",
&p[0], &p[1], &p[2], &p[3]);
PRINTF("LAN test of LAN IP of the char-server: ");
if (lan_ip_check(p) == 0)
@@ -3532,9 +3360,9 @@ int login_lan_config_read(const char *lancfgName)
// Reading general configuration file
//-----------------------------------
static
-int login_config_read(const char *cfgName)
+int login_config_read(ZString cfgName)
{
- std::ifstream in(cfgName);
+ std::ifstream in(cfgName.c_str());
if (!in.is_open())
{
PRINTF("Configuration file (%s) not found.\n", cfgName);
@@ -3543,20 +3371,21 @@ int login_config_read(const char *cfgName)
PRINTF("---Start reading of Login Server configuration file (%s)\n",
cfgName);
- std::string line;
- while (std::getline(in, line))
+ FString line;
+ while (io::getline(in, line))
{
- std::string w1, w2;
+ SString w1;
+ TString w2;
if (!split_key_value(line, &w1, &w2))
continue;
if (w1 == "admin_state")
{
- admin_state = config_switch(w2.c_str());
+ admin_state = config_switch(w2);
}
else if (w1 == "admin_pass")
{
- strzcpy(admin_pass, w2.c_str(), sizeof(admin_pass));
+ admin_pass = stringish<AccountPass>(w2);
}
else if (w1 == "ladminallowip")
{
@@ -3573,20 +3402,19 @@ int login_config_read(const char *cfgName)
// set to all
access_ladmin.push_back(AccessEntry());
}
- else if (!w2.empty()
+ else if (w2
&& !(access_ladmin.size() == 1
&& access_ladmin.front() == AccessEntry()))
{
// don't add IP if already 'all'
- AccessEntry n;
- strzcpy(n.data(), w2.c_str(), sizeof(n));
+ AccessEntry n = stringish<AccessEntry>(w2);
access_ladmin.push_back(n);
}
}
}
else if (w1 == "gm_pass")
{
- strzcpy(gm_pass, w2.c_str(), sizeof(gm_pass));
+ gm_pass = w2;
}
else if (w1 == "level_new_gm")
{
@@ -3594,7 +3422,7 @@ int login_config_read(const char *cfgName)
}
else if (w1 == "new_account")
{
- new_account_flag = config_switch(w2.c_str());
+ new_account_flag = config_switch(w2);
}
else if (w1 == "login_port")
{
@@ -3602,11 +3430,11 @@ int login_config_read(const char *cfgName)
}
else if (w1 == "account_filename")
{
- strzcpy(account_filename, w2.c_str(), sizeof(account_filename));
+ account_filename = w2;
}
else if (w1 == "gm_account_filename")
{
- strzcpy(GM_account_filename, w2.c_str(), sizeof(GM_account_filename));
+ GM_account_filename = w2;
}
else if (w1 == "gm_account_filename_check_timer")
{
@@ -3614,28 +3442,27 @@ int login_config_read(const char *cfgName)
}
else if (w1 == "login_log_filename")
{
- strzcpy(login_log_filename, w2.c_str(), sizeof(login_log_filename));
+ login_log_filename = w2;
}
else if (w1 == "login_log_unknown_packets_filename")
{
- strzcpy(login_log_unknown_packets_filename, w2.c_str(),
- sizeof(login_log_unknown_packets_filename));
+ login_log_unknown_packets_filename = w2;
}
else if (w1 == "save_unknown_packets")
{
- save_unknown_packets = config_switch(w2.c_str());
+ save_unknown_packets = config_switch(w2);
}
else if (w1 == "display_parse_login")
{
- display_parse_login = config_switch(w2.c_str()); // 0: no, 1: yes
+ display_parse_login = config_switch(w2); // 0: no, 1: yes
}
else if (w1 == "display_parse_admin")
{
- display_parse_admin = config_switch(w2.c_str()); // 0: no, 1: yes
+ display_parse_admin = config_switch(w2); // 0: no, 1: yes
}
else if (w1 == "display_parse_fromchar")
{
- display_parse_fromchar = config_switch(w2.c_str()); // 0: no, 1: yes (without packet 0x2714), 2: all packets
+ display_parse_fromchar = config_switch(w2); // 0: no, 1: yes (without packet 0x2714), 2: all packets
}
else if (w1 == "min_level_to_connect")
{
@@ -3643,7 +3470,7 @@ int login_config_read(const char *cfgName)
}
else if (w1 == "add_to_unlimited_account")
{
- add_to_unlimited_account = config_switch(w2.c_str());
+ add_to_unlimited_account = config_switch(w2);
}
else if (w1 == "start_limited_time")
{
@@ -3651,7 +3478,7 @@ int login_config_read(const char *cfgName)
}
else if (w1 == "check_ip_flag")
{
- check_ip_flag = config_switch(w2.c_str());
+ check_ip_flag = config_switch(w2);
}
else if (w1 == "order")
{
@@ -3679,13 +3506,12 @@ int login_config_read(const char *cfgName)
// set to all
access_allow.push_back(AccessEntry());
}
- else if (!w2.empty()
+ else if (w2
&& !(access_allow.size() == 1
&& access_allow.front() == AccessEntry()))
{
// don't add IP if already 'all'
- AccessEntry n;
- strzcpy(n.data(), w2.c_str(), sizeof(n));
+ AccessEntry n = stringish<AccessEntry>(w2);
access_allow.push_back(n);
}
}
@@ -3705,20 +3531,19 @@ int login_config_read(const char *cfgName)
// set to all
access_deny.push_back(AccessEntry());
}
- else if (!w2.empty()
+ else if (w2
&& !(access_deny.size() == 1
&& access_deny.front() == AccessEntry()))
{
// don't add IP if already 'all'
- AccessEntry n;
- strzcpy(n.data(), w2.c_str(), sizeof(n));
+ AccessEntry n = stringish<AccessEntry>(w2);
access_deny.push_back(n);
}
}
}
else if (w1 == "anti_freeze_enable")
{
- anti_freeze_enable = config_switch(w2.c_str());
+ anti_freeze_enable = config_switch(w2);
}
else if (w1 == "anti_freeze_interval")
{
@@ -3728,19 +3553,20 @@ int login_config_read(const char *cfgName)
}
else if (w1 == "import")
{
- login_config_read(w2.c_str());
+ login_config_read(w2);
}
else if (w1 == "update_host")
{
- strzcpy(update_host, w2.c_str(), sizeof(update_host));
+ update_host = w2;
}
else if (w1 == "main_server")
{
- strzcpy(main_server, w2.c_str(), sizeof(main_server));
+ main_server = stringish<ServerName>(w2);
}
else
{
- PRINTF("WARNING: unknown login config key: %s\n", w1);
+ FString w1z = w1;
+ PRINTF("WARNING: unknown login config key: %s\n", w1z);
}
}
@@ -3763,23 +3589,23 @@ void display_conf_warnings(void)
if (admin_state == 1)
{
- if (admin_pass[0] == '\0')
+ if (!admin_pass)
{
PRINTF("***WARNING: Administrator password is void (admin_pass).\n");
}
- else if (strcmp(admin_pass, "admin") == 0)
+ else if (admin_pass == stringish<AccountPass>("admin"))
{
PRINTF("***WARNING: You are using the default administrator password (admin_pass).\n");
PRINTF(" We highly recommend that you change it.\n");
}
}
- if (gm_pass[0] == '\0')
+ if (!gm_pass)
{
PRINTF("***WARNING: 'To GM become' password is void (gm_pass).\n");
PRINTF(" We highly recommend that you set one password.\n");
}
- else if (strcmp(gm_pass, "gm") == 0)
+ else if (gm_pass == "gm")
{
PRINTF("***WARNING: You are using the default GM password (gm_pass).\n");
PRINTF(" We highly recommend that you change it.\n");
@@ -3910,8 +3736,6 @@ void display_conf_warnings(void)
PRINTF(" But, you refuse ALL IP!\n");
}
}
-
- return;
}
//-------------------------------
@@ -3929,13 +3753,13 @@ void save_config_in_log(void)
if (admin_state != 1)
LOGIN_LOG("- with no remote administration.\n");
- else if (admin_pass[0] == '\0')
+ else if (!admin_pass)
LOGIN_LOG("- with a remote administration with a VOID password.\n");
- else if (strcmp(admin_pass, "admin") == 0)
+ else if (admin_pass == stringish<AccountPass>("admin"))
LOGIN_LOG("- with a remote administration with the DEFAULT password.\n");
else
LOGIN_LOG("- with a remote administration with the password of %zu character(s).\n",
- strlen(admin_pass));
+ admin_pass.size());
if (access_ladmin.empty()
|| (access_ladmin.size() == 1 && access_ladmin.front() == AccessEntry()))
{
@@ -3945,16 +3769,16 @@ void save_config_in_log(void)
{
LOGIN_LOG("- to accept following IP for remote administration:\n");
for (const AccessEntry& ae : access_ladmin)
- LOGIN_LOG(" %s\n", ae.data());
+ LOGIN_LOG(" %s\n", ae);
}
- if (gm_pass[0] == '\0')
+ if (!gm_pass)
LOGIN_LOG("- with a VOID 'To GM become' password (gm_pass).\n");
- else if (strcmp(gm_pass, "gm") == 0)
+ else if (gm_pass == "gm")
LOGIN_LOG("- with the DEFAULT 'To GM become' password (gm_pass).\n");
else
LOGIN_LOG("- with a 'To GM become' password (gm_pass) of %zu character(s).\n",
- strlen(gm_pass));
+ gm_pass.size());
if (level_new_gm == 0)
LOGIN_LOG("- to refuse any creation of GM with @gm.\n");
else
@@ -4037,7 +3861,7 @@ void save_config_in_log(void)
{
LOGIN_LOG("- with the IP security order: 'deny,allow' (allow if not deny). Refused IP are:\n");
for (const AccessEntry& ae : access_deny)
- LOGIN_LOG(" %s\n", ae.data());
+ LOGIN_LOG(" %s\n", ae);
}
}
else if (access_order == ACO::ALLOW_DENY)
@@ -4054,7 +3878,7 @@ void save_config_in_log(void)
{
LOGIN_LOG("- with the IP security order: 'allow,deny' (deny if not allow). Authorised IP are:\n");
for (const AccessEntry& ae : access_allow)
- LOGIN_LOG(" %s\n", ae.data());
+ LOGIN_LOG(" %s\n", ae);
}
}
else
@@ -4078,11 +3902,11 @@ void save_config_in_log(void)
{
LOGIN_LOG(" Authorised IP are:\n");
for (const AccessEntry& ae : access_allow)
- LOGIN_LOG(" %s\n", ae.data());
+ LOGIN_LOG(" %s\n", ae);
}
LOGIN_LOG(" Refused IP are:\n");
for (const AccessEntry& ae : access_deny)
- LOGIN_LOG(" %s\n", ae.data());
+ LOGIN_LOG(" %s\n", ae);
}
}
}
@@ -4111,13 +3935,19 @@ void term_func(void)
//------------------------------
// Main function of login-server
//------------------------------
-int do_init(int argc, char **argv)
+int do_init(int argc, ZString *argv)
{
// read login-server configuration
- login_config_read((argc > 1) ? argv[1] : LOGIN_CONF_NAME);
+ 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
- login_lan_config_read((argc > 1) ? argv[1] : LAN_CONF_NAME);
+ if (argc > 2)
+ login_lan_config_read(argv[2]);
+ else
+ login_lan_config_read(LAN_CONF_NAME);
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 1926f83..18ea0e0 100644
--- a/src/map/atcommand.cpp
+++ b/src/map/atcommand.cpp
@@ -8,9 +8,12 @@
#include "../common/core.hpp"
#include "../common/cxxstdio.hpp"
+#include "../common/extract.hpp"
+#include "../common/human_time_diff.hpp"
+#include "../common/io.hpp"
#include "../common/mmo.hpp"
-#include "../common/random.hpp"
#include "../common/nullpo.hpp"
+#include "../common/random.hpp"
#include "../common/socket.hpp"
#include "../common/timer.hpp"
#include "../common/utils2.hpp"
@@ -34,7 +37,7 @@
#include "../poison.hpp"
#define ATCOMMAND_FUNC(x) static \
-int atcommand_##x(const int fd, dumb_ptr<map_session_data> sd, const char *, const char *message)
+int atcommand_##x(const int fd, dumb_ptr<map_session_data> sd, ZString message)
ATCOMMAND_FUNC(setup);
ATCOMMAND_FUNC(broadcast);
ATCOMMAND_FUNC(localbroadcast);
@@ -175,13 +178,16 @@ ATCOMMAND_FUNC(doomspot);
*AtCommandInfo atcommand_info[]構造体の定義
*------------------------------------------
*/
-
struct AtCommandInfo
{
- const char *command;
+ ZString command;
int level;
- int(*proc)(const int, dumb_ptr<map_session_data>,
- const char *command, const char *message);
+ int (*proc)(const int fd, dumb_ptr<map_session_data> sd, ZString message);
+
+
+ AtCommandInfo(ZString c, int l, int (*p)(const int, dumb_ptr<map_session_data>, ZString))
+ : command(c), level(l), proc(p)
+ {}
};
// First char of commands is configured in atcommand_athena.conf. Leave @ in this list for default value.
@@ -335,9 +341,50 @@ AtCommandInfo atcommand_info[] =
{"@doomspot", 60, atcommand_doomspot},
// add new commands before this line
- {NULL, 1, NULL}
+ {ZString(), 1, nullptr}
};
+// If your last arg is not a ZString, you probably wanted extract()
+// but not always ...
+static
+bool asplit(ZString raw, ZString *last)
+{
+ *last = raw;
+ return true;
+}
+
+// but this case is just so common and useful. In fact, is the previous ever used otherwise?
+static
+bool asplit(ZString raw, CharName *last)
+{
+ if (raw.size() < 4 || raw.size() > 23)
+ return false;
+ *last = stringish<CharName>(raw);
+ return true;
+}
+
+// huh.
+static
+bool asplit(ZString raw, NpcName *last)
+{
+ if (!raw || raw.size() > 23)
+ return false;
+ *last = stringish<NpcName>(raw);
+ return true;
+}
+
+// This differs from extract() in that it does not consume extra spaces.
+template<class F, class... R, typename=typename std::enable_if<sizeof...(R) != 0>::type>
+bool asplit(ZString raw, F *first_arg, R *... rest_args)
+{
+ ZString::iterator it = std::find(raw.begin(), raw.end(), ' ');
+ XString frist = raw.xislice_h(it);
+ while (*it == ' ')
+ ++it;
+ ZString rest = raw.xislice_t(it);
+ return extract(frist, first_arg) && asplit(rest, rest_args...);
+}
+
/*==========================================
* get_atcommand_level @コマンドの必要レベルを取得
*------------------------------------------
@@ -357,28 +404,28 @@ FILE *get_gm_log();
/*========================================
* At-command logging
*/
-void log_atcommand(dumb_ptr<map_session_data> sd, const_string cmd)
+void log_atcommand(dumb_ptr<map_session_data> sd, XString cmd)
{
FILE *fp = get_gm_log();
if (!fp)
return;
timestamp_seconds_buffer tmpstr;
stamp_time(tmpstr);
- fprintf(fp, "[%s] %s(%d,%d) %s(%d) : ",
+ FPRINTF(fp, "[%s] %s(%d,%d) %s(%d) : ",
tmpstr,
sd->bl_m->name_, sd->bl_x, sd->bl_y,
sd->status.name, sd->status.account_id);
fwrite(cmd.data(), 1, cmd.size(), fp);
}
-std::string gm_logfile_name;
+FString gm_logfile_name;
/*==========================================
* Log a timestamped line to GM log file
*------------------------------------------
*/
FILE *get_gm_log()
{
- if (gm_logfile_name.empty())
+ if (!gm_logfile_name)
return NULL;
struct tm ctime = TimeT::now();
@@ -393,65 +440,56 @@ FILE *get_gm_log()
return gm_logfile;
last_logfile_nr = logfile_nr;
- std::string fullname = STRPRINTF("%s.%04d-%02d",
+ FString fullname = STRPRINTF("%s.%04d-%02d",
gm_logfile_name, year, month);
if (gm_logfile)
- fclose_(gm_logfile);
+ fclose(gm_logfile);
- gm_logfile = fopen_(fullname.c_str(), "a");
+ gm_logfile = fopen(fullname.c_str(), "a");
if (!gm_logfile)
{
perror("GM log file");
- gm_logfile_name.clear();
+ gm_logfile_name = FString();
}
return gm_logfile;
}
static
-AtCommandInfo *atcommand(const int level, const char *message);
+AtCommandInfo *atcommand(const int level, ZString message);
/*==========================================
*is_atcommand @コマンドに存在するかどうか確認する
*------------------------------------------
*/
bool is_atcommand(const int fd, dumb_ptr<map_session_data> sd,
- const char *message, int gmlvl)
+ ZString message, int gmlvl)
{
nullpo_retr(false, sd);
- if (!message || message[0] != '@')
+ if (!message.startswith('@'))
return false;
AtCommandInfo *info = atcommand(gmlvl > 0 ? gmlvl : pc_isGM(sd), message);
if (!info)
{
- std::string output = STRPRINTF("GM command not found: %s",
+ FString output = STRPRINTF("GM command not found: %s",
message);
clif_displaymessage(fd, output);
return true; // don't show in chat
}
{
- const char *str = message;
- const char *p = message;
- // split the first word
- while (*p && !isspace(*p))
- p++;
- size_t len = p - str;
- char command[len + 1];
- strzcpy(command, str, len + 1);
- // skip the spaces; pass as argv
- while (isspace(*p))
- p++;
+ XString command;
+ ZString arg;
+ asplit(message, &command, &arg);
{
- if (info->proc(fd, sd, command, p) != 0)
+ if (info->proc(fd, sd, arg) != 0)
{
// Command can not be executed
- const char *command_ = command;
- std::string output = STRPRINTF("%s failed.", command_);
+ FString output = STRPRINTF("%s failed.", FString(command));
clif_displaymessage(fd, output);
}
else
@@ -469,28 +507,27 @@ bool is_atcommand(const int fd, dumb_ptr<map_session_data> sd,
*
*------------------------------------------
*/
-AtCommandInfo *atcommand(const int level, const char *message)
+AtCommandInfo *atcommand(const int level, ZString message)
{
- const char *p = message;
+ ZString p = message;
if (battle_config.atc_gmonly != 0 && !level) // level = pc_isGM(sd)
return nullptr;
- if (!p || !*p)
+ if (!p)
{
FPRINTF(stderr, "at command message is empty\n");
return nullptr;
}
- if (*p == '@')
- { // check first char.
- char command[101];
+ if (p.startswith('@'))
+ {
+ ZString::iterator space = std::find(p.begin(), p.end(), ' ');
+ XString command = p.xislice_h(space);
int i = 0;
- sscanf(p, "%100s", command);
- command[sizeof(command) - 1] = '\0';
while (atcommand_info[i].command)
{
- if (strcasecmp(command, atcommand_info[i].command) == 0
+ if (command == atcommand_info[i].command
&& level >= atcommand_info[i].level)
{
return &atcommand_info[i];
@@ -522,12 +559,10 @@ void atkillmonster_sub(dumb_ptr<block_list> bl, int flag)
*------------------------------------------
*/
static
-AtCommandInfo *get_atcommandinfo_byname(const char *name)
+AtCommandInfo *get_atcommandinfo_byname(XString name)
{
- int i;
-
- for (i = 0; atcommand_info[i].command; i++)
- if (strcasecmp(atcommand_info[i].command + 1, name) == 0)
+ for (int i = 0; atcommand_info[i].command; i++)
+ if (atcommand_info[i].command.xslice_t(1) == name)
return &atcommand_info[i];
return NULL;
@@ -537,39 +572,36 @@ AtCommandInfo *get_atcommandinfo_byname(const char *name)
*
*------------------------------------------
*/
-int atcommand_config_read(const char *cfgName)
+int atcommand_config_read(ZString cfgName)
{
- char line[1024], w1[1024], w2[1024];
- AtCommandInfo *p;
- FILE *fp;
-
- if ((fp = fopen_(cfgName, "r")) == NULL)
+ std::ifstream in(cfgName.c_str());
+ if (!in.is_open())
{
PRINTF("At commands configuration file not found: %s\n", cfgName);
return 1;
}
- while (fgets(line, sizeof(line) - 1, fp))
+ FString line;
+ while (io::getline(in, line))
{
- if (line[0] == '/' && line[1] == '/')
- continue;
-
- if (sscanf(line, "%1023[^:]:%1023s", w1, w2) != 2)
+ SString w1;
+ TString w2;
+ if (!split_key_value(line, &w1, &w2))
continue;
- p = get_atcommandinfo_byname(w1);
+ AtCommandInfo *p = get_atcommandinfo_byname(w1);
if (p != NULL)
{
- p->level = atoi(w2);
+ p->level = atoi(w2.c_str());
if (p->level > 100)
p->level = 100;
else if (p->level < 0)
p->level = 0;
}
-
- if (strcasecmp(w1, "import") == 0)
+ else if (w1 == "import")
atcommand_config_read(w2);
+ else
+ PRINTF("%s: bad line: %s\n", cfgName, line);
}
- fclose_(fp);
return 0;
}
@@ -585,42 +617,41 @@ int atcommand_config_read(const char *cfgName)
*------------------------------------------
*/
int atcommand_setup(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
- char character[100] {};
int level = 1;
+ CharName character;
- if (!message || !*message
- || sscanf(message, "%d %99[^\n]", &level, character) < 2)
+ if (!asplit(message, &level, &character))
{
clif_displaymessage(fd, "Usage: @setup <level> <char name>");
return -1;
}
level--;
- std::string buf;
+ FString buf;
buf = STRPRINTF("-255 %s", character);
- atcommand_character_baselevel(fd, sd, "@charbaselvl", buf.c_str());
+ atcommand_character_baselevel(fd, sd, buf);
buf = STRPRINTF("%d %s", level, character);
- atcommand_character_baselevel(fd, sd, "@charbaselvl", buf.c_str());
+ atcommand_character_baselevel(fd, sd, buf);
// Emote skill
buf = STRPRINTF("1 1 %s", character);
- atcommand_skill_learn(fd, sd, "@skill-learn", buf.c_str());
+ atcommand_skill_learn(fd, sd, buf);
// Trade skill
buf = STRPRINTF("2 1 %s", character);
- atcommand_skill_learn(fd, sd, "@skill-learn", buf.c_str());
+ atcommand_skill_learn(fd, sd, buf);
// Party skill
STRPRINTF("2 2 %s", character);
- atcommand_skill_learn(fd, sd, "@skill-learn", buf.c_str());
+ atcommand_skill_learn(fd, sd, buf);
STRPRINTF("018-1.gat 24 98 %s", character);
- atcommand_charwarp(fd, sd, "@charwarp", buf.c_str());
+ atcommand_charwarp(fd, sd, buf);
- return (0);
+ return 0;
}
@@ -629,19 +660,16 @@ int atcommand_setup(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_charwarp(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
- char map_name[100] {};
- char character[100] {};
+ MapName map_name;
+ CharName character;
int x = 0, y = 0;
- dumb_ptr<map_session_data> pl_sd;
- if (!message || !*message
- || sscanf(message, "%99s %d %d %99[^\n]", map_name, &x, &y,
- character) < 4)
+ if (!asplit(message, &map_name, &x, &y, &character))
{
clif_displaymessage(fd,
- "Usage: @charwarp/@rura+ <mapname> <x> <y> <char name>");
+ "Usage: @charwarp/@rura+ <mapname> <x> <y> <char name>");
return -1;
}
@@ -649,13 +677,13 @@ int atcommand_charwarp(const int fd, dumb_ptr<map_session_data> sd,
x = random_::in(1, 399);
if (y <= 0)
y = random_::in(1, 399);
- if (strstr(map_name, ".gat") == NULL && strstr(map_name, ".afm") == NULL && strlen(map_name) < 13) // 16 - 4 (.gat)
- strcat(map_name, ".gat");
- if ((pl_sd = map_nick2sd(character)) != NULL)
+ dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
+ if (pl_sd)
{
if (pc_isGM(sd) >= pc_isGM(pl_sd))
- { // you can rura+ only lower or same GM level
+ {
+ // you can rura+ only lower or same GM level
if (x > 0 && x < 800 && y > 0 && y < 800)
{
map_local *m = map_mapname2mapid(map_name);
@@ -663,14 +691,14 @@ int atcommand_charwarp(const int fd, dumb_ptr<map_session_data> sd,
&& battle_config.any_warp_GM_min_level > pc_isGM(sd))
{
clif_displaymessage(fd,
- "You are not authorised to warp someone to this map.");
+ "You are not authorised to warp someone to this map.");
return -1;
}
if (pl_sd->bl_m && pl_sd->bl_m->flag.nowarp
&& battle_config.any_warp_GM_min_level > pc_isGM(sd))
{
clif_displaymessage(fd,
- "You are not authorised to warp this player from its actual map.");
+ "You are not authorised to warp this player from its actual map.");
return -1;
}
if (pc_setpos(pl_sd, map_name, x, y, BeingRemoveWhy::WARPED) == 0)
@@ -710,16 +738,16 @@ int atcommand_charwarp(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_warp(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
- char map_name[100] {};
+ MapName map_name;
int x = 0, y = 0;
- if (!message || !*message
- || sscanf(message, "%99s %d %d", map_name, &x, &y) < 1)
+ if (!message
+ || !extract(message, record<' ', 1>(&map_name, &x, &y)))
{
clif_displaymessage(fd,
- "Please, enter a map (usage: @warp <mapname> <x> <y>).");
+ "Please, enter a map (usage: @warp <mapname> <x> <y>).");
return -1;
}
@@ -728,9 +756,6 @@ int atcommand_warp(const int fd, dumb_ptr<map_session_data> sd,
if (y <= 0)
y = random_::in(1, 399);
- if (strstr(map_name, ".gat") == NULL && strstr(map_name, ".afm") == NULL && strlen(map_name) < 13) // 16 - 4 (.gat)
- strcat(map_name, ".gat");
-
if (x > 0 && x < 800 && y > 0 && y < 800)
{
map_local *m = map_mapname2mapid(map_name);
@@ -738,14 +763,14 @@ int atcommand_warp(const int fd, dumb_ptr<map_session_data> sd,
&& battle_config.any_warp_GM_min_level > pc_isGM(sd))
{
clif_displaymessage(fd,
- "You are not authorised to warp you to this map.");
+ "You are not authorised to warp you to this map.");
return -1;
}
if (sd->bl_m && sd->bl_m->flag.nowarp
&& battle_config.any_warp_GM_min_level > pc_isGM(sd))
{
clif_displaymessage(fd,
- "You are not authorised to warp you from your actual map.");
+ "You are not authorised to warp you from your actual map.");
return -1;
}
if (pc_setpos(sd, map_name, x, y, BeingRemoveWhy::WARPED) == 0)
@@ -770,20 +795,18 @@ int atcommand_warp(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_where(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
- char character[100] {};
- dumb_ptr<map_session_data> pl_sd;
+ CharName character;
+ extract(message, &character);
- if (sscanf(message, "%99[^\n]", character) < 1)
- strcpy(character, sd->status.name);
-
- if ((pl_sd = map_nick2sd(character)) != NULL &&
+ dumb_ptr<map_session_data> pl_sd = character.to__actual() ? map_nick2sd(character) : sd;
+ if (pl_sd != NULL &&
!((battle_config.hide_GM_session
|| bool(pl_sd->status.option & Option::HIDE))
&& (pc_isGM(pl_sd) > pc_isGM(sd))))
{ // you can look only lower or same level
- std::string output = STRPRINTF("%s: %s (%d,%d)",
+ FString output = STRPRINTF("%s: %s (%d,%d)",
pl_sd->status.name,
pl_sd->mapname_, pl_sd->bl_x, pl_sd->bl_y);
clif_displaymessage(fd, output);
@@ -802,36 +825,36 @@ int atcommand_where(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_goto(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
- char character[100] {};
- dumb_ptr<map_session_data> pl_sd;
+ CharName character;
- if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1)
+ if (!asplit(message, &character))
{
clif_displaymessage(fd,
- "Please, enter a player name (usage: @jumpto/@warpto/@goto <char name>).");
+ "Please, enter a player name (usage: @jumpto/@warpto/@goto <char name>).");
return -1;
}
- if ((pl_sd = map_nick2sd(character)) != NULL)
+ dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
+ if (pl_sd != NULL)
{
if (pl_sd->bl_m && pl_sd->bl_m->flag.nowarpto
&& battle_config.any_warp_GM_min_level > pc_isGM(sd))
{
clif_displaymessage(fd,
- "You are not authorised to warp you to the map of this player.");
+ "You are not authorised to warp you to the map of this player.");
return -1;
}
if (sd->bl_m && sd->bl_m->flag.nowarp
&& battle_config.any_warp_GM_min_level > pc_isGM(sd))
{
clif_displaymessage(fd,
- "You are not authorised to warp you from your actual map.");
+ "You are not authorised to warp you from your actual map.");
return -1;
}
pc_setpos(sd, pl_sd->mapname_, pl_sd->bl_x, pl_sd->bl_y, BeingRemoveWhy::WARPED);
- std::string output = STRPRINTF("Jump to %s", character);
+ FString output = STRPRINTF("Jump to %s", character);
clif_displaymessage(fd, output);
}
else
@@ -848,10 +871,11 @@ int atcommand_goto(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_jump(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
int x = 0, y = 0;
- sscanf(message, "%d %d", &x, &y);
+ // may fail
+ extract(message, record<' '>(&x, &y));
if (x <= 0)
x = random_::in(1, 399);
@@ -863,18 +887,18 @@ int atcommand_jump(const int fd, dumb_ptr<map_session_data> sd,
&& battle_config.any_warp_GM_min_level > pc_isGM(sd))
{
clif_displaymessage(fd,
- "You are not authorised to warp you to your actual map.");
+ "You are not authorised to warp you to your actual map.");
return -1;
}
if (sd->bl_m && sd->bl_m->flag.nowarp
&& battle_config.any_warp_GM_min_level > pc_isGM(sd))
{
clif_displaymessage(fd,
- "You are not authorised to warp you from your actual map.");
+ "You are not authorised to warp you from your actual map.");
return -1;
}
pc_setpos(sd, sd->mapname_, x, y, BeingRemoveWhy::WARPED);
- std::string output = STRPRINTF("Jump to %d %d", x, y);
+ FString output = STRPRINTF("Jump to %d %d", x, y);
clif_displaymessage(fd, output);
}
else
@@ -891,17 +915,12 @@ int atcommand_jump(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_who(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
int count;
int pl_GM_level, GM_level;
- char match_text[100] {};
- char player_name[24] {};
-
- if (sscanf(message, "%99[^\n]", match_text) < 1)
- strcpy(match_text, "");
- for (int j = 0; match_text[j]; j++)
- match_text[j] = tolower(match_text[j]);
+ VString<23> match_text = message;
+ match_text = match_text.to_lower();
count = 0;
GM_level = pc_isGM(sd);
@@ -919,13 +938,11 @@ int atcommand_who(const int fd, dumb_ptr<map_session_data> sd,
&& (pl_GM_level > GM_level)))
{
// you can look only lower or same level
- strzcpy(player_name, pl_sd->status.name, 24);
- for (int j = 0; player_name[j]; j++)
- player_name[j] = tolower(player_name[j]);
- if (strstr(player_name, match_text) != NULL)
+ VString<23> player_name = pl_sd->status.name.to__lower();
+ if (player_name.contains_seq(match_text))
{
// search with no case sensitive
- std::string output;
+ FString output;
if (pl_GM_level > 0)
output = STRPRINTF(
"Name: %s (GM:%d) | Location: %s %d %d",
@@ -949,7 +966,7 @@ int atcommand_who(const int fd, dumb_ptr<map_session_data> sd,
clif_displaymessage(fd, "1 player found.");
else
{
- std::string output = STRPRINTF("%d players found.", count);
+ FString output = STRPRINTF("%d players found.", count);
clif_displaymessage(fd, output);
}
@@ -961,18 +978,14 @@ int atcommand_who(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_whogroup(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
int count;
int pl_GM_level, GM_level;
- char match_text[100] {};
- char player_name[24] {};
struct party *p;
- if (sscanf(message, "%99[^\n]", match_text) < 1)
- strcpy(match_text, "");
- for (int j = 0; match_text[j]; j++)
- match_text[j] = tolower(match_text[j]);
+ VString<23> match_text = message;
+ match_text = match_text.to_lower();
count = 0;
GM_level = pc_isGM(sd);
@@ -990,15 +1003,13 @@ int atcommand_whogroup(const int fd, dumb_ptr<map_session_data> sd,
&& (pl_GM_level > GM_level)))
{
// you can look only lower or same level
- strzcpy(player_name, pl_sd->status.name, 24);
- for (int j = 0; player_name[j]; j++)
- player_name[j] = tolower(player_name[j]);
- if (strstr(player_name, match_text) != NULL)
+ VString<23> player_name = pl_sd->status.name.to__lower();
+ if (player_name.contains_seq(match_text))
{
// search with no case sensitive
p = party_search(pl_sd->status.party_id);
- const char *temp0 = p ? p->name : "None";
- std::string output;
+ PartyName temp0 = p ? p->name : stringish<PartyName>("None");
+ FString output;
if (pl_GM_level > 0)
output = STRPRINTF(
"Name: %s (GM:%d) | Party: '%s'",
@@ -1016,7 +1027,7 @@ int atcommand_whogroup(const int fd, dumb_ptr<map_session_data> sd,
clif_displaymessage(fd, "1 player found.");
else
{
- std::string output = STRPRINTF("%d players found.", count);
+ FString output = STRPRINTF("%d players found.", count);
clif_displaymessage(fd, output);
}
@@ -1028,20 +1039,15 @@ int atcommand_whogroup(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_whomap(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
int count;
int pl_GM_level, GM_level;
map_local *map_id;
- char map_name[100] {};
- if (!message || !*message)
- map_id = sd->bl_m;
- else
{
- sscanf(message, "%99s", map_name);
- if (strstr(map_name, ".gat") == NULL && strstr(map_name, ".afm") == NULL && strlen(map_name) < 13) // 16 - 4 (.gat)
- strcat(map_name, ".gat");
+ MapName map_name;
+ extract(message, &map_name);
map_id = map_mapname2mapid(map_name);
if (map_id == nullptr)
map_id = sd->bl_m;
@@ -1064,7 +1070,7 @@ int atcommand_whomap(const int fd, dumb_ptr<map_session_data> sd,
{ // you can look only lower or same level
if (pl_sd->bl_m == map_id)
{
- std::string output;
+ FString output;
if (pl_GM_level > 0)
output = STRPRINTF(
"Name: %s (GM:%d) | Location: %s %d %d",
@@ -1082,7 +1088,7 @@ int atcommand_whomap(const int fd, dumb_ptr<map_session_data> sd,
}
}
- std::string output = STRPRINTF("%d players found in map '%s'.",
+ FString output = STRPRINTF("%d players found in map '%s'.",
count, map_id->name_);
clif_displaymessage(fd, output);
@@ -1094,21 +1100,16 @@ int atcommand_whomap(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_whomapgroup(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
int count;
int pl_GM_level, GM_level;
- char map_name[100] {};
struct party *p;
map_local *map_id;
- if (!message || !*message)
- map_id = sd->bl_m;
- else
{
- sscanf(message, "%99s", map_name);
- if (strstr(map_name, ".gat") == NULL && strstr(map_name, ".afm") == NULL && strlen(map_name) < 13) // 16 - 4 (.gat)
- strcat(map_name, ".gat");
+ MapName map_name;
+ extract(message, &map_name);
map_id = map_mapname2mapid(map_name);
if (map_id == nullptr)
map_id = sd->bl_m;
@@ -1133,8 +1134,8 @@ int atcommand_whomapgroup(const int fd, dumb_ptr<map_session_data> sd,
if (pl_sd->bl_m == map_id)
{
p = party_search(pl_sd->status.party_id);
- const char *temp0 = p ? p->name : "None";
- std::string output;
+ PartyName temp0 = p ? p->name : stringish<PartyName>("None");
+ FString output;
if (pl_GM_level > 0)
output = STRPRINTF("Name: %s (GM:%d) | Party: '%s'",
pl_sd->status.name, pl_GM_level, temp0);
@@ -1148,7 +1149,7 @@ int atcommand_whomapgroup(const int fd, dumb_ptr<map_session_data> sd,
}
}
- std::string output;
+ FString output;
if (count == 0)
output = STRPRINTF("No player found in map '%s'.", map_id->name_);
else if (count == 1)
@@ -1167,18 +1168,14 @@ int atcommand_whomapgroup(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_whogm(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
int count;
int pl_GM_level, GM_level;
- char match_text[100] {};
- char player_name[24] {};
struct party *p;
- if (sscanf(message, "%99[^\n]", match_text) < 1)
- strcpy(match_text, "");
- for (int j = 0; match_text[j]; j++)
- match_text[j] = tolower(match_text[j]);
+ VString<23> match_text = message;
+ match_text = match_text.to_lower();
count = 0;
GM_level = pc_isGM(sd);
@@ -1198,13 +1195,11 @@ int atcommand_whogm(const int fd, dumb_ptr<map_session_data> sd,
&& (pl_GM_level > GM_level)))
{
// you can look only lower or same level
- strzcpy(player_name, pl_sd->status.name, 24);
- for (int j = 0; player_name[j]; j++)
- player_name[j] = tolower(player_name[j]);
- if (strstr(player_name, match_text) != NULL)
+ VString<23> player_name = pl_sd->status.name.to__lower();
+ if (player_name.contains_seq(match_text))
{
// search with no case sensitive
- std::string output;
+ FString output;
output = STRPRINTF(
"Name: %s (GM:%d) | Location: %s %d %d",
pl_sd->status.name, pl_GM_level,
@@ -1217,7 +1212,7 @@ int atcommand_whogm(const int fd, dumb_ptr<map_session_data> sd,
pl_sd->status.job_level);
clif_displaymessage(fd, output);
p = party_search(pl_sd->status.party_id);
- const char *temp0 = p ? p->name : "None";
+ PartyName temp0 = p ? p->name : stringish<PartyName>("None");
output = STRPRINTF(
" Party: '%s'",
temp0);
@@ -1235,7 +1230,7 @@ int atcommand_whogm(const int fd, dumb_ptr<map_session_data> sd,
clif_displaymessage(fd, "1 GM found.");
else
{
- std::string output = STRPRINTF("%d GMs found.", count);
+ FString output = STRPRINTF("%d GMs found.", count);
clif_displaymessage(fd, output);
}
@@ -1247,7 +1242,7 @@ int atcommand_whogm(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_save(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *)
+ ZString)
{
nullpo_retr(-1, sd);
@@ -1264,7 +1259,7 @@ int atcommand_save(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_load(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *)
+ ZString)
{
map_local *m = map_mapname2mapid(sd->status.save_point.map_);
if (m != nullptr && m->flag.nowarpto
@@ -1294,11 +1289,11 @@ int atcommand_load(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_speed(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
- if (!message || !*message)
+ if (!message)
{
- std::string output = STRPRINTF(
+ FString output = STRPRINTF(
"Please, enter a speed value (usage: @speed <%d-%d>).",
static_cast<uint32_t>(MIN_WALK_SPEED.count()),
static_cast<uint32_t>(MAX_WALK_SPEED.count()));
@@ -1306,7 +1301,7 @@ int atcommand_speed(const int fd, dumb_ptr<map_session_data> sd,
return -1;
}
- interval_t speed = static_cast<interval_t>(atoi(message));
+ interval_t speed = static_cast<interval_t>(atoi(message.c_str()));
if (speed >= MIN_WALK_SPEED && speed <= MAX_WALK_SPEED)
{
sd->speed = speed;
@@ -1317,7 +1312,7 @@ int atcommand_speed(const int fd, dumb_ptr<map_session_data> sd,
}
else
{
- std::string output = STRPRINTF(
+ FString output = STRPRINTF(
"Please, enter a valid speed value (usage: @speed <%d-%d>).",
static_cast<uint32_t>(MIN_WALK_SPEED.count()),
static_cast<uint32_t>(MAX_WALK_SPEED.count()));
@@ -1333,7 +1328,7 @@ int atcommand_speed(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_storage(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *)
+ ZString)
{
struct storage *stor; //changes from Freya/Yor
nullpo_retr(-1, sd);
@@ -1361,24 +1356,21 @@ int atcommand_storage(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_option(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
- int param1_ = 0, param2_ = 0, param3_ = 0;
nullpo_retr(-1, sd);
- if (!message || !*message
- || sscanf(message, "%d %d %d", &param1_, &param2_, &param3_) < 1
- || param1_ < 0 || param2_ < 0 || param3_ < 0)
+ Opt1 param1 = Opt1::ZERO;
+ Opt2 param2 = Opt2::ZERO;
+ Option param3 = Option::ZERO;
+
+ if (!extract(message, record<',', 1>(&param1, &param2, &param3)))
{
clif_displaymessage(fd,
- "Please, enter at least a option (usage: @option <param1:0+> <param2:0+> <param3:0+>).");
+ "Please, enter at least a option (usage: @option <param1:0+> <param2:0+> <param3:0+>).");
return -1;
}
- Opt1 param1 = Opt1(param1_);
- Opt2 param2 = Opt2(param2_);
- Option param3 = Option(param3_);
-
sd->opt1 = param1;
sd->opt2 = param2;
sd->status.option = param3;
@@ -1395,7 +1387,7 @@ int atcommand_option(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_hide(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *)
+ ZString)
{
if (bool(sd->status.option & Option::HIDE))
{
@@ -1417,7 +1409,7 @@ int atcommand_hide(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_die(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *)
+ ZString)
{
pc_damage(NULL, sd, sd->status.hp + 1);
clif_displaymessage(fd, "A pity! You've died.");
@@ -1430,19 +1422,19 @@ int atcommand_die(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_kill(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
- char character[100] {};
- dumb_ptr<map_session_data> pl_sd;
+ CharName character;
- if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1)
+ if (!asplit(message, &character))
{
clif_displaymessage(fd,
- "Please, enter a player name (usage: @kill <char name>).");
+ "Please, enter a player name (usage: @kill <char name>).");
return -1;
}
- if ((pl_sd = map_nick2sd(character)) != NULL)
+ dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
+ if (pl_sd != NULL)
{
if (pc_isGM(sd) >= pc_isGM(pl_sd))
{ // you can kill only lower or same level
@@ -1469,7 +1461,7 @@ int atcommand_kill(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_alive(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *)
+ ZString)
{
sd->status.hp = sd->status.max_hp;
sd->status.sp = sd->status.max_sp;
@@ -1489,12 +1481,12 @@ int atcommand_alive(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_kami(const int fd, dumb_ptr<map_session_data>,
- const char *, const char *message)
+ ZString message)
{
- if (!message || !*message)
+ if (!message)
{
clif_displaymessage(fd,
- "Please, enter a message (usage: @kami <message>).");
+ "Please, enter a message (usage: @kami <message>).");
return -1;
}
@@ -1508,11 +1500,11 @@ int atcommand_kami(const int fd, dumb_ptr<map_session_data>,
*------------------------------------------
*/
int atcommand_heal(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
int hp = 0, sp = 0; // [Valaris] thanks to fov
- sscanf(message, "%d %d", &hp, &sp);
+ extract(message, record<' '>(&hp, &sp));
if (hp == 0 && sp == 0)
{
@@ -1556,18 +1548,17 @@ int atcommand_heal(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_item(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
- char item_name[100] {};
+ ItemName item_name;
int number = 0, item_id;
struct item_data *item_data;
int get_count, i;
- if (!message || !*message
- || sscanf(message, "%99s %d", item_name, &number) < 1)
+ if (!extract(message, record<' ', 1>(&item_name, &number)))
{
clif_displaymessage(fd,
- "Please, enter an item name/id (usage: @item <item name or ID> [quantity]).");
+ "Please, enter an item name/id (usage: @item <item name or ID> [quantity]).");
return -1;
}
@@ -1576,7 +1567,7 @@ int atcommand_item(const int fd, dumb_ptr<map_session_data> sd,
item_id = 0;
if ((item_data = itemdb_searchname(item_name)) != NULL ||
- (item_data = itemdb_exists(atoi(item_name))) != NULL)
+ (item_data = itemdb_exists(atoi(item_name.c_str()))) != NULL)
item_id = item_data->nameid;
if (item_id >= 500)
@@ -1615,7 +1606,7 @@ int atcommand_item(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_itemreset(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *)
+ ZString)
{
int i;
@@ -1635,7 +1626,7 @@ int atcommand_itemreset(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_itemcheck(const int, dumb_ptr<map_session_data> sd,
- const char *, const char *)
+ ZString)
{
pc_checkitem(sd);
@@ -1647,14 +1638,14 @@ int atcommand_itemcheck(const int, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_baselevelup(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
int level, i;
- if (!message || !*message || (level = atoi(message)) == 0)
+ if (!extract(message, &level) || !level)
{
clif_displaymessage(fd,
- "Please, enter a level adjustement (usage: @blvl <number of levels>).");
+ "Please, enter a level adjustement (usage: @blvl <number of levels>).");
return -1;
}
@@ -1713,14 +1704,14 @@ int atcommand_baselevelup(const int fd, dumb_ptr<map_session_data> sd,
// TODO: merge this with pc_setparam(SP::JOBLEVEL)
// then fix the funny 50 and/or 10 limitation.
int atcommand_joblevelup(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
int up_level = 50, level;
- if (!message || !*message || (level = atoi(message)) == 0)
+ if (!extract(message, &level) || !level)
{
clif_displaymessage(fd,
- "Please, enter a level adjustement (usage: @jlvl <number of levels>).");
+ "Please, enter a level adjustement (usage: @jlvl <number of levels>).");
return -1;
}
@@ -1775,20 +1766,23 @@ int atcommand_joblevelup(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_help(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *)
+ ZString)
{
- std::ifstream in(help_txt);
+ std::ifstream in(help_txt.c_str());
if (in.is_open())
{
clif_displaymessage(fd, "Help commands:");
int gm_level = pc_isGM(sd);
- std::string line;
- while (std::getline(in, line))
+ FString line;
+ while (io::getline(in, line))
{
- std::string w1, w2;
+ SString w1;
+ TString w2;
if (!split_key_value(line, &w1, &w2))
continue;
- if (gm_level >= atoi(w1.c_str()))
+ int level;
+ extract(w1, &level);
+ if (gm_level >= level)
clif_displaymessage(fd, w2);
}
}
@@ -1806,14 +1800,12 @@ int atcommand_help(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_gm(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
- char password[100] {};
-
- if (!message || !*message || sscanf(message, "%99[^\n]", password) < 1)
+ if (!message)
{
clif_displaymessage(fd,
- "Please, enter a password (usage: @gm <password>).");
+ "Please, enter a password (usage: @gm <password>).");
return -1;
}
@@ -1823,8 +1815,7 @@ int atcommand_gm(const int fd, dumb_ptr<map_session_data> sd,
return -1;
}
else
- chrif_changegm(sd->status.account_id, password,
- strlen(password) + 1);
+ chrif_changegm(sd->status.account_id, message);
return 0;
}
@@ -1834,7 +1825,7 @@ int atcommand_gm(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_pvpoff(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *)
+ ZString)
{
if (battle_config.pk_mode)
{ //disable command if server is in PK mode [Valaris]
@@ -1874,7 +1865,7 @@ int atcommand_pvpoff(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_pvpon(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *)
+ ZString)
{
if (battle_config.pk_mode)
{ //disable command if server is in PK mode [Valaris]
@@ -1918,15 +1909,13 @@ int atcommand_pvpon(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_model(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
int hair_style = 0, hair_color = 0, cloth_color = 0;
- if (!message || !*message
- || sscanf(message, "%d %d %d", &hair_style, &hair_color,
- &cloth_color) < 1)
+ if (!extract(message, record<' ', 1>(&hair_style, &hair_color, &cloth_color)))
{
- std::string output = STRPRINTF(
+ FString output = STRPRINTF(
"Please, enter at least a value (usage: @model <hair ID: %d-%d> <hair color: %d-%d> <clothes color: %d-%d>).",
MIN_HAIR_STYLE, MAX_HAIR_STYLE,
MIN_HAIR_COLOR, MAX_HAIR_COLOR,
@@ -1960,13 +1949,13 @@ int atcommand_model(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_dye(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
int cloth_color = 0;
- if (!message || !*message || sscanf(message, "%d", &cloth_color) < 1)
+ if (!extract(message, &cloth_color))
{
- std::string output = STRPRINTF(
+ FString output = STRPRINTF(
"Please, enter a clothes color (usage: @dye/@ccolor <clothes color: %d-%d>).",
MIN_CLOTH_COLOR, MAX_CLOTH_COLOR);
clif_displaymessage(fd, output);
@@ -1994,13 +1983,13 @@ int atcommand_dye(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_hair_style(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
int hair_style = 0;
- if (!message || !*message || sscanf(message, "%d", &hair_style) < 1)
+ if (!extract(message, &hair_style))
{
- std::string output = STRPRINTF(
+ FString output = STRPRINTF(
"Please, enter a hair style (usage: @hairstyle/@hstyle <hair ID: %d-%d>).",
MIN_HAIR_STYLE, MAX_HAIR_STYLE);
clif_displaymessage(fd, output);
@@ -2028,13 +2017,13 @@ int atcommand_hair_style(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_hair_color(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
int hair_color = 0;
- if (!message || !*message || sscanf(message, "%d", &hair_color) < 1)
+ if (!extract(message, &hair_color))
{
- std::string output = STRPRINTF(
+ FString output = STRPRINTF(
"Please, enter a hair color (usage: @haircolor/@hcolor <hair color: %d-%d>).",
MIN_HAIR_COLOR, MAX_HAIR_COLOR);
clif_displaymessage(fd, output);
@@ -2062,9 +2051,9 @@ int atcommand_hair_color(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_spawn(const int fd, dumb_ptr<map_session_data> sd,
- const char *command, const char *message)
+ ZString message)
{
- char monster[100] {};
+ MobName monster;
int mob_id;
int number = 0;
int x = 0, y = 0;
@@ -2072,8 +2061,7 @@ int atcommand_spawn(const int fd, dumb_ptr<map_session_data> sd,
int i, j, k;
int mx, my, range;
- if (!message || !*message
- || sscanf(message, "%99s %d %d %d", monster, &number, &x, &y) < 1)
+ if (!extract(message, record<' ', 1>(&monster, &number, &x, &y)))
{
clif_displaymessage(fd, "Give a monster name/id please.");
return -1;
@@ -2081,7 +2069,7 @@ int atcommand_spawn(const int fd, dumb_ptr<map_session_data> sd,
// If monster identifier/name argument is a name
if ((mob_id = mobdb_searchname(monster)) == 0) // check name first (to avoid possible name begining by a number)
- mob_id = mobdb_checkid(atoi(monster));
+ mob_id = mobdb_checkid(atoi(monster.c_str()));
if (mob_id == 0)
{
@@ -2089,12 +2077,6 @@ int atcommand_spawn(const int fd, dumb_ptr<map_session_data> sd,
return -1;
}
- if (mob_id == 1288)
- {
- clif_displaymessage(fd, "Cannot spawn emperium.");
- return -1;
- }
-
if (number <= 0)
number = 1;
@@ -2104,8 +2086,8 @@ int atcommand_spawn(const int fd, dumb_ptr<map_session_data> sd,
number = battle_config.atc_spawn_quantity_limit;
if (battle_config.etc_log)
- PRINTF("%s monster='%s' id=%d count=%d (%d,%d)\n", command, monster,
- mob_id, number, x, y);
+ PRINTF("@spawn monster='%s' id=%d count=%d (%d,%d)\n",
+ monster, mob_id, number, x, y);
count = 0;
range = sqrt(number) / 2;
@@ -2125,7 +2107,7 @@ int atcommand_spawn(const int fd, dumb_ptr<map_session_data> sd,
my = sd->bl_y + random_::in(-range / 2, range / 2);
else
my = y;
- k = mob_once_spawn(sd, "this", mx, my, "", mob_id, 1, "");
+ k = mob_once_spawn(sd, MOB_THIS_MAP, mx, my, MobName(), mob_id, 1, NpcEvent());
}
count += (k != 0) ? 1 : 0;
}
@@ -2135,7 +2117,7 @@ int atcommand_spawn(const int fd, dumb_ptr<map_session_data> sd,
clif_displaymessage(fd, "All monster summoned!");
else
{
- std::string output = STRPRINTF("%d monster(s) summoned!",
+ FString output = STRPRINTF("%d monster(s) summoned!",
count);
clif_displaymessage(fd, output);
}
@@ -2154,17 +2136,12 @@ int atcommand_spawn(const int fd, dumb_ptr<map_session_data> sd,
*/
static
void atcommand_killmonster_sub(const int fd, dumb_ptr<map_session_data> sd,
- const char *message, const int drop)
+ ZString message, const int drop)
{
- char map_name[100] {};
-
map_local *map_id;
- if (!message || !*message || sscanf(message, "%99s", map_name) < 1)
- map_id = sd->bl_m;
- else
{
- if (strstr(map_name, ".gat") == NULL && strstr(map_name, ".afm") == NULL && strlen(map_name) < 13) // 16 - 4 (.gat)
- strcat(map_name, ".gat");
+ MapName map_name;
+ extract(message, &map_name);
map_id = map_mapname2mapid(map_name);
if (map_id == nullptr)
map_id = sd->bl_m;
@@ -2177,8 +2154,6 @@ void atcommand_killmonster_sub(const int fd, dumb_ptr<map_session_data> sd,
BL::MOB);
clif_displaymessage(fd, "All monsters killed!");
-
- return;
}
/*==========================================
@@ -2186,7 +2161,7 @@ void atcommand_killmonster_sub(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_killmonster(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
atcommand_killmonster_sub(fd, sd, message, 1);
@@ -2202,7 +2177,7 @@ void atlist_nearby_sub(dumb_ptr<block_list> bl, int fd)
{
nullpo_retv(bl);
- std::string buf = STRPRINTF(" - \"%s\"",
+ FString buf = STRPRINTF(" - \"%s\"",
bl->as_player()->status.name);
clif_displaymessage(fd, buf);
}
@@ -2212,7 +2187,7 @@ void atlist_nearby_sub(dumb_ptr<block_list> bl, int fd)
*------------------------------------------
*/
int atcommand_list_nearby(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *)
+ ZString)
{
clif_displaymessage(fd, "Nearby players:");
map_foreachinarea(std::bind(atlist_nearby_sub, ph::_1, fd),
@@ -2229,7 +2204,7 @@ int atcommand_list_nearby(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_killmonster2(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
atcommand_killmonster_sub(fd, sd, message, 0);
@@ -2241,13 +2216,13 @@ int atcommand_killmonster2(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_gat(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *)
+ ZString)
{
int y;
for (y = 2; y >= -2; y--)
{
- std::string output = STRPRINTF(
+ FString output = STRPRINTF(
"%s (x= %d, y= %d) %02X %02X %02X %02X %02X",
sd->bl_m->name_, sd->bl_x - 2, sd->bl_y + y,
map_getcell(sd->bl_m, sd->bl_x - 2, sd->bl_y + y),
@@ -2266,18 +2241,19 @@ int atcommand_gat(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_packet(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
- int type = 0, flag = 0;
+ StatusChange type {};
+ int flag = 0;
- if (!message || !*message || sscanf(message, "%d %d", &type, &flag) < 2)
+ if (!extract(message, record<' '>(&type, &flag)))
{
clif_displaymessage(fd,
- "Please, enter a status type/flag (usage: @packet <status type> <flag>).");
+ "Please, enter a status type/flag (usage: @packet <status type> <flag>).");
return -1;
}
- clif_status_change(sd, StatusChange(type), flag);
+ clif_status_change(sd, type, flag);
return 0;
}
@@ -2287,14 +2263,14 @@ int atcommand_packet(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_statuspoint(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
int point, new_status_point;
- if (!message || !*message || (point = atoi(message)) == 0)
+ if (!extract(message, &point) || point == 0)
{
clif_displaymessage(fd,
- "Please, enter a number (usage: @stpoint <number of points>).");
+ "Please, enter a number (usage: @stpoint <number of points>).");
return -1;
}
@@ -2327,14 +2303,14 @@ int atcommand_statuspoint(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_skillpoint(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
int point, new_skill_point;
- if (!message || !*message || (point = atoi(message)) == 0)
+ if (!extract(message, &point) || point == 0)
{
clif_displaymessage(fd,
- "Please, enter a number (usage: @skpoint <number of points>).");
+ "Please, enter a number (usage: @skpoint <number of points>).");
return -1;
}
@@ -2367,14 +2343,14 @@ int atcommand_skillpoint(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_zeny(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
int zeny, new_zeny;
- if (!message || !*message || (zeny = atoi(message)) == 0)
+ if (!extract(message, &zeny) || zeny == 0)
{
clif_displaymessage(fd,
- "Please, enter an amount (usage: @zeny <amount>).");
+ "Please, enter an amount (usage: @zeny <amount>).");
return -1;
}
@@ -2408,14 +2384,13 @@ int atcommand_zeny(const int fd, dumb_ptr<map_session_data> sd,
*/
template<ATTR attr>
int atcommand_param(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
int value = 0, new_value;
- if (!message || !*message || sscanf(message, "%d", &value) < 1
+ if (!extract(message, &value)
|| value == 0)
{
-
// there was a clang bug here
// fortunately, STRPRINTF was not actually needed
clif_displaymessage(fd,
@@ -2455,11 +2430,11 @@ int atcommand_param(const int fd, dumb_ptr<map_session_data> sd,
*/
//** Stat all by fritz (rewritten by [Yor])
int atcommand_all_stats(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
int count, value = 0, new_value;
- if (!message || !*message || sscanf(message, "%d", &value) < 1
+ if (!extract(message, &value)
|| value == 0)
value = battle_config.max_parameter;
@@ -2501,19 +2476,19 @@ int atcommand_all_stats(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_recall(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
- char character[100] {};
- dumb_ptr<map_session_data> pl_sd;
+ CharName character;
- if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1)
+ if (!asplit(message, &character))
{
clif_displaymessage(fd,
- "Please, enter a player name (usage: @recall <char name>).");
+ "Please, enter a player name (usage: @recall <char name>).");
return -1;
}
- if ((pl_sd = map_nick2sd(character)) != NULL)
+ dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
+ if (pl_sd != NULL)
{
if (pc_isGM(sd) >= pc_isGM(pl_sd))
{ // you can recall only lower or same level
@@ -2521,18 +2496,18 @@ int atcommand_recall(const int fd, dumb_ptr<map_session_data> sd,
&& battle_config.any_warp_GM_min_level > pc_isGM(sd))
{
clif_displaymessage(fd,
- "You are not authorised to warp somenone to your actual map.");
+ "You are not authorised to warp somenone to your actual map.");
return -1;
}
if (pl_sd->bl_m && pl_sd->bl_m->flag.nowarp
&& battle_config.any_warp_GM_min_level > pc_isGM(sd))
{
clif_displaymessage(fd,
- "You are not authorised to warp this player from its actual map.");
+ "You are not authorised to warp this player from its actual map.");
return -1;
}
pc_setpos(pl_sd, sd->mapname_, sd->bl_x, sd->bl_y, BeingRemoveWhy::QUIT);
- std::string output = STRPRINTF("%s recalled!", character);
+ FString output = STRPRINTF("%s recalled!", character);
clif_displaymessage(fd, output);
}
else
@@ -2555,19 +2530,19 @@ int atcommand_recall(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_revive(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
- char character[100] {};
- dumb_ptr<map_session_data> pl_sd;
+ CharName character;
- if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1)
+ if (!asplit(message, &character))
{
clif_displaymessage(fd,
- "Please, enter a player name (usage: @revive <char name>).");
+ "Please, enter a player name (usage: @revive <char name>).");
return -1;
}
- if ((pl_sd = map_nick2sd(character)) != NULL)
+ dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
+ if (pl_sd != NULL)
{
pl_sd->status.hp = pl_sd->status.max_hp;
pc_setstand(pl_sd);
@@ -2592,21 +2567,21 @@ int atcommand_revive(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_character_stats(const int fd, dumb_ptr<map_session_data>,
- const char *, const char *message)
+ ZString message)
{
- char character[100] {};
- dumb_ptr<map_session_data> pl_sd;
+ CharName character;
- if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1)
+ if (!asplit(message, &character))
{
clif_displaymessage(fd,
- "Please, enter a player name (usage: @charstats <char name>).");
+ "Please, enter a player name (usage: @charstats <char name>).");
return -1;
}
- if ((pl_sd = map_nick2sd(character)) != NULL)
+ dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
+ if (pl_sd != NULL)
{
- std::string output;
+ FString output;
output = STRPRINTF("'%s' stats:", pl_sd->status.name);
clif_displaymessage(fd, output);
output = STRPRINTF("Base Level - %d", pl_sd->status.base_level),
@@ -2651,7 +2626,7 @@ int atcommand_character_stats(const int fd, dumb_ptr<map_session_data>,
*/
//** Character Stats All by fritz
int atcommand_character_stats_all(const int fd, dumb_ptr<map_session_data>,
- const char *, const char *)
+ ZString)
{
int count;
@@ -2663,13 +2638,13 @@ int atcommand_character_stats_all(const int fd, dumb_ptr<map_session_data>,
dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(session[i]->session_data.get()));
if (pl_sd && pl_sd->state.auth)
{
- std::string gmlevel;
+ FString gmlevel;
if (pc_isGM(pl_sd) > 0)
gmlevel = STRPRINTF("| GM Lvl: %d", pc_isGM(pl_sd));
else
gmlevel = " ";
- std::string output;
+ FString output;
output = STRPRINTF(
"Name: %s | BLvl: %d | Job: Novice/Human (Lvl: %d) | HP: %d/%d | SP: %d/%d",
pl_sd->status.name, pl_sd->status.base_level,
@@ -2698,7 +2673,7 @@ int atcommand_character_stats_all(const int fd, dumb_ptr<map_session_data>,
clif_displaymessage(fd, "1 player found.");
else
{
- std::string output = STRPRINTF("%d players found.", count);
+ FString output = STRPRINTF("%d players found.", count);
clif_displaymessage(fd, output);
}
@@ -2710,26 +2685,21 @@ int atcommand_character_stats_all(const int fd, dumb_ptr<map_session_data>,
*------------------------------------------
*/
int atcommand_character_option(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
- char character[100] {};
- int opt1_ = 0, opt2_ = 0, opt3_ = 0;
- dumb_ptr<map_session_data> pl_sd;
-
- if (!message || !*message
- || sscanf(message, "%d %d %d %99[^\n]", &opt1_, &opt2_, &opt3_,
- character) < 4 || opt1_ < 0 || opt2_ < 0 || opt3_ < 0)
+ Opt1 opt1;
+ Opt2 opt2;
+ Option opt3;
+ CharName character;
+ if (!asplit(message, &opt1, &opt2, &opt3, &character))
{
clif_displaymessage(fd,
- "Please, enter valid options and a player name (usage: @charoption <param1> <param2> <param3> <charname>).");
+ "Please, enter valid options and a player name (usage: @charoption <param1> <param2> <param3> <charname>).");
return -1;
}
- Opt1 opt1 = Opt1(opt1_);
- Opt2 opt2 = Opt2(opt2_);
- Option opt3 = Option(opt3_);
-
- if ((pl_sd = map_nick2sd(character)) != NULL)
+ dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
+ if (pl_sd != NULL)
{
if (pc_isGM(sd) >= pc_isGM(pl_sd))
{
@@ -2762,31 +2732,19 @@ int atcommand_character_option(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_char_change_sex(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
- char character[100] {};
+ CharName character;
- if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1)
+ if (!asplit(message, &character))
{
clif_displaymessage(fd,
- "Please, enter a player name (usage: @charchangesex <name>).");
+ "Please, enter a player name (usage: @charchangesex <name>).");
return -1;
}
- // check player name
- if (strlen(character) < 4)
{
- clif_displaymessage(fd, "Sorry, but a player name have at least 4 characters.");
- return -1;
- }
- else if (strlen(character) > 23)
- {
- clif_displaymessage(fd, "Sorry, but a player name have 23 characters maximum.");
- return -1;
- }
- else
- {
- chrif_char_ask_name(sd->status.account_id, character, 5, 0, 0, 0, 0, 0, 0); // type: 5 - changesex
+ chrif_char_ask_name(sd->status.account_id, character, 5, HumanTimeDiff()); // type: 5 - changesex
clif_displaymessage(fd, "Character name sends to char-server to ask it.");
}
@@ -2799,31 +2757,19 @@ int atcommand_char_change_sex(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_char_block(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
- char character[100] {};
+ CharName character;
- if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1)
+ if (!asplit(message, &character))
{
clif_displaymessage(fd,
- "Please, enter a player name (usage: @block <name>).");
+ "Please, enter a player name (usage: @block <name>).");
return -1;
}
- // check player name
- if (strlen(character) < 4)
{
- clif_displaymessage(fd, "Sorry, but a player name have at least 4 characters.");
- return -1;
- }
- else if (strlen(character) > 23)
- {
- clif_displaymessage(fd, "Sorry, but a player name have 23 characters maximum.");
- return -1;
- }
- else
- {
- chrif_char_ask_name(sd->status.account_id, character, 1, 0, 0, 0, 0, 0, 0); // type: 1 - block
+ chrif_char_ask_name(sd->status.account_id, character, 1, HumanTimeDiff()); // type: 1 - block
clif_displaymessage(fd, "Character name sends to char-server to ask it.");
}
@@ -2847,94 +2793,21 @@ int atcommand_char_block(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_char_ban(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
- char modif[100] {};
- char character[100] {};
- char *modif_p;
- int year, month, day, hour, minute, second, value;
+ HumanTimeDiff modif;
+ CharName character;
- if (!message || !*message
- || sscanf(message, "%s %99[^\n]", modif, character) < 2)
+ if (!asplit(message, &modif, &character)
+ || !modif)
{
clif_displaymessage(fd,
- "Please, enter ban time and a player name (usage: @charban/@ban/@banish/@charbanish <time> <name>).");
- return -1;
- }
-
- modif[sizeof(modif) - 1] = '\0';
- character[sizeof(character) - 1] = '\0';
-
- modif_p = modif;
- year = month = day = hour = minute = second = 0;
- while (modif_p[0] != '\0')
- {
- value = atoi(modif_p);
- if (value == 0)
- modif_p++;
- else
- {
- if (modif_p[0] == '-' || modif_p[0] == '+')
- modif_p++;
- while (modif_p[0] >= '0' && modif_p[0] <= '9')
- modif_p++;
- if (modif_p[0] == 's')
- {
- second = value;
- modif_p++;
- }
- else if (modif_p[0] == 'm' && modif_p[1] == 'n')
- {
- minute = value;
- modif_p = modif_p + 2;
- }
- else if (modif_p[0] == 'h')
- {
- hour = value;
- modif_p++;
- }
- else if (modif_p[0] == 'd' || modif_p[0] == 'j')
- {
- day = value;
- modif_p++;
- }
- else if (modif_p[0] == 'm')
- {
- month = value;
- modif_p++;
- }
- else if (modif_p[0] == 'y' || modif_p[0] == 'a')
- {
- year = value;
- modif_p++;
- }
- else if (modif_p[0] != '\0')
- {
- modif_p++;
- }
- }
- }
- if (year == 0 && month == 0 && day == 0 && hour == 0 && minute == 0
- && second == 0)
- {
- clif_displaymessage(fd, "Invalid time for ban command.");
+ "Please, enter ban time and a player name (usage: @charban/@ban/@banish/@charbanish <time> <name>).");
return -1;
}
- // check player name
- if (strlen(character) < 4)
- {
- clif_displaymessage(fd, "Sorry, but a player name have at least 4 characters.");
- return -1;
- }
- else if (strlen(character) > 23)
{
- clif_displaymessage(fd, "Sorry, but a player name have 23 characters maximum.");
- return -1;
- }
- else
- {
- chrif_char_ask_name(sd->status.account_id, character, 2, year, month, day, hour, minute, second); // type: 2 - ban
+ chrif_char_ask_name(sd->status.account_id, character, 2, modif); // type: 2 - ban
clif_displaymessage(fd, "Character name sends to char-server to ask it.");
}
@@ -2946,32 +2819,20 @@ int atcommand_char_ban(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_char_unblock(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
- char character[100] {};
+ CharName character;
- if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1)
+ if (!asplit(message, &character))
{
clif_displaymessage(fd,
- "Please, enter a player name (usage: @charunblock <player_name>).");
+ "Please, enter a player name (usage: @charunblock <player_name>).");
return -1;
}
- // check player name
- if (strlen(character) < 4)
- {
- clif_displaymessage(fd, "Sorry, but a player name have at least 4 characters.");
- return -1;
- }
- else if (strlen(character) > 23)
- {
- clif_displaymessage(fd, "Sorry, but a player name have 23 characters maximum.");
- return -1;
- }
- else
{
// send answer to login server via char-server
- chrif_char_ask_name(sd->status.account_id, character, 3, 0, 0, 0, 0, 0, 0); // type: 3 - unblock
+ chrif_char_ask_name(sd->status.account_id, character, 3, HumanTimeDiff()); // type: 3 - unblock
clif_displaymessage(fd, "Character name sends to char-server to ask it.");
}
@@ -2983,32 +2844,20 @@ int atcommand_char_unblock(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_char_unban(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
- char character[100] {};
+ CharName character;
- if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1)
+ if (!asplit(message, &character))
{
clif_displaymessage(fd,
- "Please, enter a player name (usage: @charunban <player_name>).");
+ "Please, enter a player name (usage: @charunban <player_name>).");
return -1;
}
- // check player name
- if (strlen(character) < 4)
- {
- clif_displaymessage(fd, "Sorry, but a player name have at least 4 characters.");
- return -1;
- }
- else if (strlen(character) > 23)
- {
- clif_displaymessage(fd, "Sorry, but a player name have 23 characters maximum.");
- return -1;
- }
- else
{
// send answer to login server via char-server
- chrif_char_ask_name(sd->status.account_id, character, 4, 0, 0, 0, 0, 0, 0); // type: 4 - unban
+ chrif_char_ask_name(sd->status.account_id, character, 4, HumanTimeDiff()); // type: 4 - unban
clif_displaymessage(fd, "Character name sends to char-server to ask it.");
}
@@ -3020,26 +2869,22 @@ int atcommand_char_unban(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_character_save(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
- char map_name[100] {};
- char character[100] {};
- dumb_ptr<map_session_data> pl_sd;
+ MapName map_name;
+ CharName character;
int x = 0, y = 0;
- if (!message || !*message
- || sscanf(message, "%99s %d %d %99[^\n]", map_name, &x, &y,
- character) < 4 || x < 0 || y < 0)
+ if (!asplit(message, &map_name, &x, &y, &character)
+ || x < 0 || y < 0)
{
clif_displaymessage(fd,
- "Please, enter a valid save point and a player name (usage: @charsave <map> <x> <y> <charname>).");
+ "Please, enter a valid save point and a player name (usage: @charsave <map> <x> <y> <charname>).");
return -1;
}
- if (strstr(map_name, ".gat") == NULL && strstr(map_name, ".afm") == NULL && strlen(map_name) < 13) // 16 - 4 (.gat)
- strcat(map_name, ".gat");
-
- if ((pl_sd = map_nick2sd(character)) != NULL)
+ dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
+ if (pl_sd != NULL)
{
if (pc_isGM(sd) >= pc_isGM(pl_sd))
{
@@ -3056,7 +2901,7 @@ int atcommand_character_save(const int fd, dumb_ptr<map_session_data> sd,
&& battle_config.any_warp_GM_min_level > pc_isGM(sd))
{
clif_displaymessage(fd,
- "You are not authorised to set this map as a save map.");
+ "You are not authorised to set this map as a save map.");
return -1;
}
pc_setsavepoint(pl_sd, map_name, x, y);
@@ -3083,7 +2928,7 @@ int atcommand_character_save(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_doom(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *)
+ ZString)
{
for (int i = 0; i < fd_max; i++)
{
@@ -3108,7 +2953,7 @@ int atcommand_doom(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_doommap(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *)
+ ZString)
{
for (int i = 0; i < fd_max; i++)
{
@@ -3152,7 +2997,7 @@ void atcommand_raise_sub(dumb_ptr<map_session_data> sd)
*------------------------------------------
*/
int atcommand_raise(const int fd, dumb_ptr<map_session_data>,
- const char *, const char *)
+ ZString)
{
for (int i = 0; i < fd_max; i++)
{
@@ -3171,7 +3016,7 @@ int atcommand_raise(const int fd, dumb_ptr<map_session_data>,
*------------------------------------------
*/
int atcommand_raisemap(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *)
+ ZString)
{
for (int i = 0; i < fd_max; i++)
{
@@ -3192,26 +3037,24 @@ int atcommand_raisemap(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_character_baselevel(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
- dumb_ptr<map_session_data> pl_sd;
- char character[100] {};
+ CharName character;
int level = 0, i;
- if (!message || !*message
- || sscanf(message, "%d %99[^\n]", &level, character) < 2
+ if (!asplit(message, &level, &character)
|| level == 0)
{
clif_displaymessage(fd,
- "Please, enter a level adjustement and a player name (usage: @charblvl <#> <nickname>).");
+ "Please, enter a level adjustement and a player name (usage: @charblvl <#> <nickname>).");
return -1;
}
- if ((pl_sd = map_nick2sd(character)) != NULL)
+ dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
+ if (pl_sd != NULL)
{
if (pc_isGM(sd) >= pc_isGM(pl_sd))
{ // you can change base level only lower or same gm level
-
if (level > 0)
{
if (pl_sd->status.base_level == battle_config.maximum_level)
@@ -3262,7 +3105,7 @@ int atcommand_character_baselevel(const int fd, dumb_ptr<map_session_data> sd,
clif_displaymessage(fd, "Character's base level lowered.");
}
// Reset their stat points to prevent extra points from stacking
- atcommand_charstreset(fd, sd,"@charstreset", character);
+ atcommand_charstreset(fd, sd, character.to__actual());
}
else
{
@@ -3284,22 +3127,21 @@ int atcommand_character_baselevel(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_character_joblevel(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
- dumb_ptr<map_session_data> pl_sd;
- char character[100] {};
+ CharName character;
int max_level = 50, level = 0;
- if (!message || !*message
- || sscanf(message, "%d %99[^\n]", &level, character) < 2
+ if (!asplit(message, &level, &character)
|| level == 0)
{
clif_displaymessage(fd,
- "Please, enter a level adjustement and a player name (usage: @charjlvl <#> <nickname>).");
+ "Please, enter a level adjustement and a player name (usage: @charjlvl <#> <nickname>).");
return -1;
}
- if ((pl_sd = map_nick2sd(character)) != NULL)
+ dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
+ if (pl_sd != NULL)
{
if (pc_isGM(sd) >= pc_isGM(pl_sd))
{
@@ -3367,19 +3209,19 @@ int atcommand_character_joblevel(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_kick(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
- dumb_ptr<map_session_data> pl_sd;
- char character[100] {};
+ CharName character;
- if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1)
+ if (!asplit(message, &character))
{
clif_displaymessage(fd,
- "Please, enter a player name (usage: @kick <charname>).");
+ "Please, enter a player name (usage: @kick <charname>).");
return -1;
}
- if ((pl_sd = map_nick2sd(character)) != NULL)
+ dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
+ if (pl_sd != NULL)
{
if (pc_isGM(sd) >= pc_isGM(pl_sd)) // you can kick only lower or same gm level
clif_GM_kick(sd, pl_sd, 1);
@@ -3403,7 +3245,7 @@ int atcommand_kick(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_kickall(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *)
+ ZString)
{
for (int i = 0; i < fd_max; i++)
{
@@ -3429,19 +3271,17 @@ int atcommand_kickall(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_questskill(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
- int skill_id_;
+ SkillID skill_id;
- if (!message || !*message || (skill_id_ = atoi(message)) < 0)
+ if (!extract(message, &skill_id))
{
clif_displaymessage(fd,
- "Please, enter a quest skill number (usage: @questskill <#:0+>).");
+ "Please, enter a quest skill number (usage: @questskill <#:0+>).");
return -1;
}
- SkillID skill_id = SkillID(skill_id_);
-
if (/*skill_id >= SkillID() &&*/ skill_id < SkillID::MAX_SKILL_DB)
{
if (skill_get_inf2(skill_id) & 0x01)
@@ -3477,28 +3317,24 @@ int atcommand_questskill(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_charquestskill(const int fd, dumb_ptr<map_session_data>,
- const char *, const char *message)
+ ZString message)
{
- char character[100] {};
- dumb_ptr<map_session_data> pl_sd;
- int skill_id_ = 0;
+ CharName character;
+ SkillID skill_id;
- if (!message || !*message
- || sscanf(message, "%d %99[^\n]", &skill_id_, character) < 2
- || skill_id_ < 0)
+ if (!asplit(message, &skill_id, &character))
{
clif_displaymessage(fd,
- "Please, enter a quest skill number and a player name (usage: @charquestskill <#:0+> <char_name>).");
+ "Please, enter a quest skill number and a player name (usage: @charquestskill <#:0+> <char_name>).");
return -1;
}
- SkillID skill_id = SkillID(skill_id_);
-
if (/*skill_id >= SkillID() &&*/ skill_id < SkillID::MAX_SKILL_DB)
{
if (skill_get_inf2(skill_id) & 0x01)
{
- if ((pl_sd = map_nick2sd(character)) != NULL)
+ dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
+ if (pl_sd != NULL)
{
if (pc_checkskill(pl_sd, skill_id) == 0)
{
@@ -3537,19 +3373,17 @@ int atcommand_charquestskill(const int fd, dumb_ptr<map_session_data>,
*------------------------------------------
*/
int atcommand_lostskill(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
- int skill_id_;
+ SkillID skill_id;
- if (!message || !*message || (skill_id_ = atoi(message)) < 0)
+ if (!extract(message, &skill_id))
{
clif_displaymessage(fd,
- "Please, enter a quest skill number (usage: @lostskill <#:0+>).");
+ "Please, enter a quest skill number (usage: @lostskill <#:0+>).");
return -1;
}
- SkillID skill_id = SkillID(skill_id_);
-
if (/*skill_id >= SkillID() &&*/ skill_id < MAX_SKILL)
{
if (skill_get_inf2(skill_id) & 0x01)
@@ -3587,28 +3421,24 @@ int atcommand_lostskill(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_charlostskill(const int fd, dumb_ptr<map_session_data>,
- const char *, const char *message)
+ ZString message)
{
- char character[100] {};
- dumb_ptr<map_session_data> pl_sd;
- int skill_id_ = 0;
+ CharName character;
+ SkillID skill_id;
- if (!message || !*message
- || sscanf(message, "%d %99[^\n]", &skill_id_, character) < 2
- || skill_id_ < 0)
+ if (!asplit(message, &skill_id, &character))
{
clif_displaymessage(fd,
- "Please, enter a quest skill number and a player name (usage: @charlostskill <#:0+> <char_name>).");
+ "Please, enter a quest skill number and a player name (usage: @charlostskill <#:0+> <char_name>).");
return -1;
}
- SkillID skill_id = SkillID(skill_id_);
-
if (/*skill_id >= SkillID() &&*/ skill_id < MAX_SKILL)
{
if (skill_get_inf2(skill_id) & 0x01)
{
- if ((pl_sd = map_nick2sd(character)) != NULL)
+ dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
+ if (pl_sd != NULL)
{
if (pc_checkskill(pl_sd, skill_id) > 0)
{
@@ -3649,14 +3479,14 @@ int atcommand_charlostskill(const int fd, dumb_ptr<map_session_data>,
*------------------------------------------
*/
int atcommand_party(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
- char party[100] {};
+ PartyName party;
- if (!message || !*message || sscanf(message, "%99[^\n]", party) < 1)
+ if (!extract(message, &party) || !party)
{
clif_displaymessage(fd,
- "Please, enter a party name (usage: @party <party_name>).");
+ "Please, enter a party name (usage: @party <party_name>).");
return -1;
}
@@ -3670,7 +3500,7 @@ int atcommand_party(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_mapexit(const int, dumb_ptr<map_session_data> sd,
- const char *, const char *)
+ ZString)
{
for (int i = 0; i < fd_max; i++)
{
@@ -3695,26 +3525,26 @@ int atcommand_mapexit(const int, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_idsearch(const int fd, dumb_ptr<map_session_data>,
- const char *, const char *message)
+ ZString message)
{
- char item_name[100] {};
+ ItemName item_name;
int i, match;
struct item_data *item;
- if (!message || !*message || sscanf(message, "%99s", item_name) < 0)
+ if (!extract(message, &item_name) || !item_name)
{
clif_displaymessage(fd,
- "Please, enter a part of item name (usage: @idsearch <part_of_item_name>).");
+ "Please, enter a part of item name (usage: @idsearch <part_of_item_name>).");
return -1;
}
- std::string output = STRPRINTF("The reference result of '%s' (name: id):", item_name);
+ FString output = STRPRINTF("The reference result of '%s' (name: id):", item_name);
clif_displaymessage(fd, output);
match = 0;
for (i = 0; i < 20000; i++)
{
if ((item = itemdb_exists(i)) != NULL
- && strstr(item->jname, item_name) != NULL)
+ && item->jname.contains_seq(item_name))
{
match++;
output = STRPRINTF("%s: %d", item->jname, item->nameid);
@@ -3732,24 +3562,24 @@ int atcommand_idsearch(const int fd, dumb_ptr<map_session_data>,
*------------------------------------------
*/
int atcommand_charskreset(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
- char character[100] {};
- dumb_ptr<map_session_data> pl_sd;
+ CharName character;
- if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1)
+ if (!asplit(message, &character))
{
clif_displaymessage(fd,
- "Please, enter a player name (usage: @charskreset <charname>).");
+ "Please, enter a player name (usage: @charskreset <charname>).");
return -1;
}
- if ((pl_sd = map_nick2sd(character)) != NULL)
+ dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
+ if (pl_sd != NULL)
{
if (pc_isGM(sd) >= pc_isGM(pl_sd))
{ // you can reset skill points only lower or same gm level
pc_resetskill(pl_sd);
- std::string output = STRPRINTF(
+ FString output = STRPRINTF(
"'%s' skill points reseted!", character);
clif_displaymessage(fd, output);
}
@@ -3773,24 +3603,24 @@ int atcommand_charskreset(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_charstreset(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
- char character[100] {};
- dumb_ptr<map_session_data> pl_sd;
+ CharName character;
- if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1)
+ if (!asplit(message, &character))
{
clif_displaymessage(fd,
- "Please, enter a player name (usage: @charstreset <charname>).");
+ "Please, enter a player name (usage: @charstreset <charname>).");
return -1;
}
- if ((pl_sd = map_nick2sd(character)) != NULL)
+ dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
+ if (pl_sd != NULL)
{
if (pc_isGM(sd) >= pc_isGM(pl_sd))
{ // you can reset stats points only lower or same gm level
pc_resetstate(pl_sd);
- std::string output = STRPRINTF(
+ FString output = STRPRINTF(
"'%s' stats points reseted!",
character);
clif_displaymessage(fd, output);
@@ -3815,27 +3645,27 @@ int atcommand_charstreset(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_charreset(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
- char character[100] {};
- dumb_ptr<map_session_data> pl_sd;
+ CharName character;
- if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1)
+ if (!asplit(message, &character))
{
clif_displaymessage(fd,
- "Please, enter a player name (usage: @charreset <charname>).");
+ "Please, enter a player name (usage: @charreset <charname>).");
return -1;
}
- if ((pl_sd = map_nick2sd(character)) != NULL)
+ dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
+ if (pl_sd != NULL)
{
if (pc_isGM(sd) >= pc_isGM(pl_sd))
{ // you can reset a character only for lower or same GM level
pc_resetstate(pl_sd);
pc_resetskill(pl_sd);
- pc_setglobalreg(pl_sd, "MAGIC_FLAGS", 0); // [Fate] Reset magic quest variables
- pc_setglobalreg(pl_sd, "MAGIC_EXP", 0); // [Fate] Reset magic experience
- std::string output = STRPRINTF(
+ pc_setglobalreg(pl_sd, stringish<VarName>("MAGIC_FLAGS"), 0); // [Fate] Reset magic quest variables
+ pc_setglobalreg(pl_sd, stringish<VarName>("MAGIC_EXP"), 0); // [Fate] Reset magic experience
+ FString output = STRPRINTF(
"'%s' skill and stats points reseted!", character);
clif_displaymessage(fd, output);
}
@@ -3859,19 +3689,19 @@ int atcommand_charreset(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_char_wipe(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
- char character[100] {};
- dumb_ptr<map_session_data> pl_sd;
+ CharName character;
- if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1)
+ if (!asplit(message, &character))
{
clif_displaymessage(fd,
- "Please, enter a player name (usage: @charwipe <charname>).");
+ "Please, enter a player name (usage: @charwipe <charname>).");
return -1;
}
- if ((pl_sd = map_nick2sd(character)) != NULL)
+ dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
+ if (pl_sd != NULL)
{
if (pc_isGM(sd) >= pc_isGM(pl_sd))
{ // you can reset a character only for lower or same GM level
@@ -3919,10 +3749,10 @@ int atcommand_char_wipe(const int fd, dumb_ptr<map_session_data> sd,
pc_calcstatus(pl_sd, 0);
pc_resetstate(pl_sd);
pc_resetskill(pl_sd);
- pc_setglobalreg(pl_sd, "MAGIC_FLAGS", 0); // [Fate] Reset magic quest variables
- pc_setglobalreg(pl_sd, "MAGIC_EXP", 0); // [Fate] Reset magic experience
+ pc_setglobalreg(pl_sd, stringish<VarName>("MAGIC_FLAGS"), 0); // [Fate] Reset magic quest variables
+ pc_setglobalreg(pl_sd, stringish<VarName>("MAGIC_EXP"), 0); // [Fate] Reset magic experience
- std::string output = STRPRINTF("%s: wiped.", character);
+ FString output = STRPRINTF("%s: wiped.", character);
clif_displaymessage(fd, output);
}
else
@@ -3945,18 +3775,14 @@ int atcommand_char_wipe(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_charmodel(const int fd, dumb_ptr<map_session_data>,
- const char *, const char *message)
+ ZString message)
{
- int hair_style = 0, hair_color = 0, cloth_color = 0;
- dumb_ptr<map_session_data> pl_sd;
- char character[100] {};
+ unsigned hair_style = 0, hair_color = 0, cloth_color = 0;
+ CharName character;
- if (!message || !*message
- || sscanf(message, "%d %d %d %99[^\n]", &hair_style, &hair_color,
- &cloth_color, character) < 4 || hair_style < 0
- || hair_color < 0 || cloth_color < 0)
+ if (!asplit(message, &hair_style, &hair_color, &cloth_color, &character))
{
- std::string output = STRPRINTF(
+ FString output = STRPRINTF(
"Please, enter a valid model and a player name (usage: @charmodel <hair ID: %d-%d> <hair color: %d-%d> <clothes color: %d-%d> <name>).",
MIN_HAIR_STYLE, MAX_HAIR_STYLE,
MIN_HAIR_COLOR, MAX_HAIR_COLOR,
@@ -3965,7 +3791,8 @@ int atcommand_charmodel(const int fd, dumb_ptr<map_session_data>,
return -1;
}
- if ((pl_sd = map_nick2sd(character)) != NULL)
+ dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
+ if (pl_sd != NULL)
{
if (hair_style >= MIN_HAIR_STYLE && hair_style <= MAX_HAIR_STYLE &&
hair_color >= MIN_HAIR_COLOR && hair_color <= MAX_HAIR_COLOR &&
@@ -3998,23 +3825,22 @@ int atcommand_charmodel(const int fd, dumb_ptr<map_session_data>,
*------------------------------------------
*/
int atcommand_charskpoint(const int fd, dumb_ptr<map_session_data>,
- const char *, const char *message)
+ ZString message)
{
- dumb_ptr<map_session_data> pl_sd;
- char character[100] {};
+ CharName character;
int new_skill_point;
int point = 0;
- if (!message || !*message
- || sscanf(message, "%d %99[^\n]", &point, character) < 2
+ if (!asplit(message, &point, &character)
|| point == 0)
{
clif_displaymessage(fd,
- "Please, enter a number and a player name (usage: @charskpoint <amount> <name>).");
+ "Please, enter a number and a player name (usage: @charskpoint <amount> <name>).");
return -1;
}
- if ((pl_sd = map_nick2sd(character)) != NULL)
+ dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
+ if (pl_sd != NULL)
{
new_skill_point = pl_sd->status.skill_point + point;
if (point > 0 && (point > 0x7FFF || new_skill_point > 0x7FFF)) // fix positiv overflow
@@ -4050,23 +3876,22 @@ int atcommand_charskpoint(const int fd, dumb_ptr<map_session_data>,
*------------------------------------------
*/
int atcommand_charstpoint(const int fd, dumb_ptr<map_session_data>,
- const char *, const char *message)
+ ZString message)
{
- dumb_ptr<map_session_data> pl_sd;
- char character[100] {};
+ CharName character;
int new_status_point;
int point = 0;
- if (!message || !*message
- || sscanf(message, "%d %99[^\n]", &point, character) < 2
+ if (!asplit(message, &point, &character)
|| point == 0)
{
clif_displaymessage(fd,
- "Please, enter a number and a player name (usage: @charstpoint <amount> <name>).");
+ "Please, enter a number and a player name (usage: @charstpoint <amount> <name>).");
return -1;
}
- if ((pl_sd = map_nick2sd(character)) != NULL)
+ dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
+ if (pl_sd != NULL)
{
new_status_point = pl_sd->status.status_point + point;
if (point > 0 && (point > 0x7FFF || new_status_point > 0x7FFF)) // fix positiv overflow
@@ -4102,21 +3927,20 @@ int atcommand_charstpoint(const int fd, dumb_ptr<map_session_data>,
*------------------------------------------
*/
int atcommand_charzeny(const int fd, dumb_ptr<map_session_data>,
- const char *, const char *message)
+ ZString message)
{
- dumb_ptr<map_session_data> pl_sd;
- char character[100] {};
+ CharName character;
int zeny = 0, new_zeny;
- if (!message || !*message
- || sscanf(message, "%d %99[^\n]", &zeny, character) < 2 || zeny == 0)
+ if (!asplit(message, &zeny, &character) || zeny == 0)
{
clif_displaymessage(fd,
- "Please, enter a number and a player name (usage: @charzeny <zeny> <name>).");
+ "Please, enter a number and a player name (usage: @charzeny <zeny> <name>).");
return -1;
}
- if ((pl_sd = map_nick2sd(character)) != NULL)
+ dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
+ if (pl_sd != NULL)
{
new_zeny = pl_sd->status.zeny + zeny;
if (zeny > 0 && (zeny > MAX_ZENY || new_zeny > MAX_ZENY)) // fix positiv overflow
@@ -4152,7 +3976,7 @@ int atcommand_charzeny(const int fd, dumb_ptr<map_session_data>,
*------------------------------------------
*/
int atcommand_recallall(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *)
+ ZString)
{
int count;
@@ -4160,7 +3984,7 @@ int atcommand_recallall(const int fd, dumb_ptr<map_session_data> sd,
&& battle_config.any_warp_GM_min_level > pc_isGM(sd))
{
clif_displaymessage(fd,
- "You are not authorised to warp somenone to your actual map.");
+ "You are not authorised to warp somenone to your actual map.");
return -1;
}
@@ -4187,7 +4011,7 @@ int atcommand_recallall(const int fd, dumb_ptr<map_session_data> sd,
clif_displaymessage(fd, "All characters recalled!");
if (count)
{
- std::string output = STRPRINTF(
+ FString output = STRPRINTF(
"Because you are not authorised to warp from some maps, %d player(s) have not been recalled.",
count);
clif_displaymessage(fd, output);
@@ -4201,16 +4025,16 @@ int atcommand_recallall(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_partyrecall(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
- char party_name[100] {};
+ PartyName party_name;
struct party *p;
int count;
- if (!message || !*message || sscanf(message, "%99[^\n]", party_name) < 1)
+ if (!extract(message, &party_name) || !party_name)
{
clif_displaymessage(fd,
- "Please, enter a party name/id (usage: @partyrecall <party_name/id>).");
+ "Please, enter a party name/id (usage: @partyrecall <party_name/id>).");
return -1;
}
@@ -4218,12 +4042,12 @@ int atcommand_partyrecall(const int fd, dumb_ptr<map_session_data> sd,
&& battle_config.any_warp_GM_min_level > pc_isGM(sd))
{
clif_displaymessage(fd,
- "You are not authorised to warp somenone to your actual map.");
+ "You are not authorised to warp somenone to your actual map.");
return -1;
}
if ((p = party_searchname(party_name)) != NULL || // name first to avoid error when name begin with a number
- (p = party_search(atoi(message))) != NULL)
+ (p = party_search(atoi(message.c_str()))) != NULL)
{
count = 0;
for (int i = 0; i < fd_max; i++)
@@ -4242,7 +4066,7 @@ int atcommand_partyrecall(const int fd, dumb_ptr<map_session_data> sd,
pc_setpos(pl_sd, sd->mapname_, sd->bl_x, sd->bl_y, BeingRemoveWhy::QUIT);
}
}
- std::string output = STRPRINTF("All online characters of the %s party are near you.", p->name);
+ FString output = STRPRINTF("All online characters of the %s party are near you.", p->name);
clif_displaymessage(fd, output);
if (count)
{
@@ -4266,7 +4090,7 @@ int atcommand_partyrecall(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_reloaditemdb(const int fd, dumb_ptr<map_session_data>,
- const char *, const char *)
+ ZString)
{
itemdb_reload();
clif_displaymessage(fd, "Item database reloaded.");
@@ -4279,7 +4103,7 @@ int atcommand_reloaditemdb(const int fd, dumb_ptr<map_session_data>,
*------------------------------------------
*/
int atcommand_reloadmobdb(const int fd, dumb_ptr<map_session_data>,
- const char *, const char *)
+ ZString)
{
mob_reload();
clif_displaymessage(fd, "Monster database reloaded.");
@@ -4292,7 +4116,7 @@ int atcommand_reloadmobdb(const int fd, dumb_ptr<map_session_data>,
*------------------------------------------
*/
int atcommand_reloadskilldb(const int fd, dumb_ptr<map_session_data>,
- const char *, const char *)
+ ZString)
{
skill_reload();
clif_displaymessage(fd, "Skill database reloaded.");
@@ -4305,7 +4129,7 @@ int atcommand_reloadskilldb(const int fd, dumb_ptr<map_session_data>,
*------------------------------------------
*/
int atcommand_reloadscript(const int fd, dumb_ptr<map_session_data>,
- const char *, const char *)
+ ZString)
{
do_init_npc();
do_init_script();
@@ -4322,7 +4146,7 @@ int atcommand_reloadscript(const int fd, dumb_ptr<map_session_data>,
*------------------------------------------
*/
int atcommand_reloadgmdb(const int fd, dumb_ptr<map_session_data>,
- const char *, const char *)
+ ZString)
{
chrif_reloadGMdb();
@@ -4340,26 +4164,24 @@ int atcommand_reloadgmdb(const int fd, dumb_ptr<map_session_data>,
*------------------------------------------
*/
int atcommand_mapinfo(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
dumb_ptr<npc_data> nd = NULL;
- char map_name[100] {};
+ MapName map_name;
const char *direction = NULL;
int list = 0;
- sscanf(message, "%d %99[^\n]", &list, map_name);
+ extract(message, record<' '>(&list, &map_name));
if (list < 0 || list > 3)
{
clif_displaymessage(fd,
- "Please, enter at least a valid list number (usage: @mapinfo <0-3> [map]).");
+ "Please, enter at least a valid list number (usage: @mapinfo <0-3> [map]).");
return -1;
}
- if (map_name[0] == '\0')
- strcpy(map_name, sd->mapname_);
- if (strstr(map_name, ".gat") == NULL && strstr(map_name, ".afm") == NULL && strlen(map_name) < 13) // 16 - 4 (.gat)
- strcat(map_name, ".gat");
+ if (!map_name)
+ map_name = sd->mapname_;
map_local *m_id = map_mapname2mapid(map_name);
if (m_id != nullptr)
@@ -4369,7 +4191,7 @@ int atcommand_mapinfo(const int fd, dumb_ptr<map_session_data> sd,
}
clif_displaymessage(fd, "------ Map Info ------");
- std::string output = STRPRINTF("Map Name: %s", map_name);
+ FString output = STRPRINTF("Map Name: %s", map_name);
clif_displaymessage(fd, output);
output = STRPRINTF("Players In Map: %d", m_id->users);
clif_displaymessage(fd, output);
@@ -4418,11 +4240,11 @@ int atcommand_mapinfo(const int fd, dumb_ptr<map_session_data> sd,
continue;
dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(session[i]->session_data.get()));
if (pl_sd && pl_sd->state.auth
- && strcmp(pl_sd->mapname_, map_name) == 0)
+ && pl_sd->mapname_ == map_name)
{
output = STRPRINTF(
- "Player '%s' (session #%d) | Location: %d,%d",
- pl_sd->status.name, i, pl_sd->bl_x, pl_sd->bl_y);
+ "Player '%s' (session #%d) | Location: %d,%d",
+ pl_sd->status.name, i, pl_sd->bl_x, pl_sd->bl_y);
clif_displaymessage(fd, output);
}
}
@@ -4476,7 +4298,7 @@ int atcommand_mapinfo(const int fd, dumb_ptr<map_session_data> sd,
break;
default: // normally impossible to arrive here
clif_displaymessage(fd,
- "Please, enter at least a valid list number (usage: @mapinfo <0-2> [map]).");
+ "Please, enter at least a valid list number (usage: @mapinfo <0-2> [map]).");
return -1;
}
@@ -4488,31 +4310,31 @@ int atcommand_mapinfo(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_partyspy(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
- char party_name[100] {};
- struct party *p;
+ PartyName party_name;
- if (!message || !*message || sscanf(message, "%99[^\n]", party_name) < 1)
+ if (!extract(message, &party_name))
{
clif_displaymessage(fd,
- "Please, enter a party name/id (usage: @partyspy <party_name/id>).");
+ "Please, enter a party name/id (usage: @partyspy <party_name/id>).");
return -1;
}
+ struct party *p;
if ((p = party_searchname(party_name)) != NULL || // name first to avoid error when name begin with a number
- (p = party_search(atoi(message))) != NULL)
+ (p = party_search(atoi(message.c_str()))) != NULL)
{
if (sd->partyspy == p->party_id)
{
sd->partyspy = 0;
- std::string output = STRPRINTF("No longer spying on the %s party.", p->name);
+ FString output = STRPRINTF("No longer spying on the %s party.", p->name);
clif_displaymessage(fd, output);
}
else
{
sd->partyspy = p->party_id;
- std::string output = STRPRINTF("Spying on the %s party.", p->name);
+ FString output = STRPRINTF("Spying on the %s party.", p->name);
clif_displaymessage(fd, output);
}
}
@@ -4530,14 +4352,14 @@ int atcommand_partyspy(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_enablenpc(const int fd, dumb_ptr<map_session_data>,
- const char *, const char *message)
+ ZString message)
{
- char NPCname[100] {};
+ NpcName NPCname;
- if (!message || !*message || sscanf(message, "%99[^\n]", NPCname) < 1)
+ if (!extract(message, &NPCname) || !NPCname)
{
clif_displaymessage(fd,
- "Please, enter a NPC name (usage: @npcon <NPC_name>).");
+ "Please, enter a NPC name (usage: @npcon <NPC_name>).");
return -1;
}
@@ -4560,14 +4382,14 @@ int atcommand_enablenpc(const int fd, dumb_ptr<map_session_data>,
*------------------------------------------
*/
int atcommand_disablenpc(const int fd, dumb_ptr<map_session_data>,
- const char *, const char *message)
+ ZString message)
{
- char NPCname[100] {};
+ NpcName NPCname;
- if (!message || !*message || sscanf(message, "%99[^\n]", NPCname) < 1)
+ if (!extract(message, &NPCname) || !NPCname)
{
clif_displaymessage(fd,
- "Please, enter a NPC name (usage: @npcoff <NPC_name>).");
+ "Please, enter a NPC name (usage: @npcoff <NPC_name>).");
return -1;
}
@@ -4591,11 +4413,11 @@ int atcommand_disablenpc(const int fd, dumb_ptr<map_session_data>,
*------------------------------------------
*/
int atcommand_servertime(const int fd, dumb_ptr<map_session_data>,
- const char *, const char *)
+ ZString)
{
timestamp_seconds_buffer tsbuf;
stamp_time(tsbuf);
- std::string temp = STRPRINTF("Server time: %s", tsbuf);
+ FString temp = STRPRINTF("Server time: %s", tsbuf);
clif_displaymessage(fd, temp);
{
@@ -4614,31 +4436,29 @@ int atcommand_servertime(const int fd, dumb_ptr<map_session_data>,
*------------------------------------------
*/
int atcommand_chardelitem(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
- dumb_ptr<map_session_data> pl_sd;
- char character[100] {};
- char item_name[100] {};
+ CharName character;
+ ItemName item_name;
int i, number = 0, item_id, item_position, count;
struct item_data *item_data;
- if (!message || !*message
- || sscanf(message, "%s %d %99[^\n]", item_name, &number,
- character) < 3 || number < 1)
+ if (!asplit(message, &item_name, &number, &character) || number < 1)
{
clif_displaymessage(fd,
- "Please, enter an item name/id, a quantity and a player name (usage: @chardelitem <item_name_or_ID> <quantity> <player>).");
+ "Please, enter an item name/id, a quantity and a player name (usage: @chardelitem <item_name_or_ID> <quantity> <player>).");
return -1;
}
item_id = 0;
if ((item_data = itemdb_searchname(item_name)) != NULL ||
- (item_data = itemdb_exists(atoi(item_name))) != NULL)
+ (item_data = itemdb_exists(atoi(item_name.c_str()))) != NULL)
item_id = item_data->nameid;
if (item_id > 500)
{
- if ((pl_sd = map_nick2sd(character)) != NULL)
+ dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
+ if (pl_sd != NULL)
{
if (pc_isGM(sd) >= pc_isGM(pl_sd))
{ // you can kill only lower or same level
@@ -4652,7 +4472,7 @@ int atcommand_chardelitem(const int fd, dumb_ptr<map_session_data> sd,
count++;
item_position = pc_search_inventory(pl_sd, item_id); // for next loop
}
- std::string output = STRPRINTF(
+ FString output = STRPRINTF(
"%d item(s) removed by a GM.",
count);
clif_displaymessage(pl_sd->fd, output);
@@ -4695,16 +4515,16 @@ int atcommand_chardelitem(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_broadcast(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
- if (!message || !*message)
+ if (!message)
{
clif_displaymessage(fd,
- "Please, enter a message (usage: @broadcast <message>).");
+ "Please, enter a message (usage: @broadcast <message>).");
return -1;
}
- std::string output = STRPRINTF("%s : %s", sd->status.name, message);
+ FString output = STRPRINTF("%s : %s", sd->status.name, message);
intif_GMmessage(output);
return 0;
@@ -4715,16 +4535,16 @@ int atcommand_broadcast(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_localbroadcast(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
- if (!message || !*message)
+ if (!message)
{
clif_displaymessage(fd,
- "Please, enter a message (usage: @localbroadcast <message>).");
+ "Please, enter a message (usage: @localbroadcast <message>).");
return -1;
}
- std::string output = STRPRINTF("%s : %s", sd->status.name, message);
+ FString output = STRPRINTF("%s : %s", sd->status.name, message);
clif_GMmessage(sd, output, 1); // 1: ALL_SAMEMAP
@@ -4736,35 +4556,34 @@ int atcommand_localbroadcast(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_email(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
- char actual_email[100] {};
- char new_email[100] {};
+ AccountEmail actual_email;
+ AccountEmail new_email;
- if (!message || !*message
- || sscanf(message, "%99s %99s", actual_email, new_email) < 2)
+ if (!extract(message, record<' '>(&actual_email, &new_email)))
{
clif_displaymessage(fd,
- "Please enter 2 emails (usage: @email <actual@email> <new@email>).");
+ "Please enter 2 emails (usage: @email <actual@email> <new@email>).");
return -1;
}
- if (e_mail_check(actual_email) == 0)
+ if (!e_mail_check(actual_email))
{
clif_displaymessage(fd, "Invalid actual email. If you have default e-mail, type a@a.com."); // Invalid actual email. If you have default e-mail, give a@a.com.
return -1;
}
- else if (e_mail_check(new_email) == 0)
+ else if (!e_mail_check(new_email))
{
clif_displaymessage(fd, "Invalid new email. Please enter a real e-mail.");
return -1;
}
- else if (strcasecmp(new_email, "a@a.com") == 0)
+ else if (new_email == DEFAULT_EMAIL)
{
clif_displaymessage(fd, "New email must be a real e-mail.");
return -1;
}
- else if (strcasecmp(actual_email, new_email) == 0)
+ else if (actual_email == new_email)
{
clif_displaymessage(fd, "New email must be different of the actual e-mail.");
return -1;
@@ -4783,14 +4602,14 @@ int atcommand_email(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_effect(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
int type = 0, flag = 0;
- if (!message || !*message || sscanf(message, "%d %d", &type, &flag) < 2)
+ if (!extract(message, record<' '>(&type, &flag)))
{
clif_displaymessage(fd,
- "Please, enter at least a option (usage: @effect <type+>).");
+ "Please, enter at least a option (usage: @effect <type+>).");
return -1;
}
if (flag <= 0)
@@ -4821,22 +4640,21 @@ int atcommand_effect(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_character_item_list(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
- dumb_ptr<map_session_data> pl_sd;
struct item_data *item_data, *item_temp;
int i, j, count, counter, counter2;
- char character[100] {};
- char equipstr[100];
+ CharName character;
- if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1)
+ if (!asplit(message, &character))
{
clif_displaymessage(fd,
- "Please, enter a player name (usage: @charitemlist <char name>).");
+ "Please, enter a player name (usage: @charitemlist <char name>).");
return -1;
}
- if ((pl_sd = map_nick2sd(character)) != NULL)
+ dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
+ if (pl_sd != NULL)
{
if (pc_isGM(sd) >= pc_isGM(pl_sd))
{ // you can look items only lower or same level
@@ -4853,50 +4671,51 @@ int atcommand_character_item_list(const int fd, dumb_ptr<map_session_data> sd,
count++;
if (count == 1)
{
- std::string output = STRPRINTF(
+ FString output = STRPRINTF(
"------ Items list of '%s' ------",
pl_sd->status.name);
clif_displaymessage(fd, output);
}
- EPOS equip;
- if (bool(equip = pl_sd->status.inventory[i].equip))
+ EPOS equip = pl_sd->status.inventory[i].equip;
+ MString equipstr;
+ if (bool(equip))
{
- strcpy(equipstr, "| equiped: ");
+ equipstr += "| equiped: ";
if (bool(equip & EPOS::GLOVES))
- strcat(equipstr, "robe/gargment, ");
+ equipstr += "robe/gargment, ";
if (bool(equip & EPOS::CAPE))
- strcat(equipstr, "left accessory, ");
+ equipstr += "left accessory, ";
if (bool(equip & EPOS::MISC1))
- strcat(equipstr, "body/armor, ");
+ equipstr += "body/armor, ";
if ((equip & (EPOS::WEAPON | EPOS::SHIELD)) == EPOS::WEAPON)
- strcat(equipstr, "right hand, ");
+ equipstr += "right hand, ";
if ((equip & (EPOS::WEAPON | EPOS::SHIELD)) == EPOS::SHIELD)
- strcat(equipstr, "left hand, ");
+ equipstr += "left hand, ";
if ((equip & (EPOS::WEAPON | EPOS::SHIELD)) == (EPOS::WEAPON | EPOS::SHIELD))
- strcat(equipstr, "both hands, ");
+ equipstr += "both hands, ";
if (bool(equip & EPOS::SHOES))
- strcat(equipstr, "feet, ");
+ equipstr += "feet, ";
if (bool(equip & EPOS::MISC2))
- strcat(equipstr, "right accessory, ");
+ equipstr += "right accessory, ";
if ((equip & (EPOS::TORSO | EPOS::HAT | EPOS::LEGS)) == EPOS::LEGS)
- strcat(equipstr, "lower head, ");
+ equipstr += "lower head, ";
if ((equip & (EPOS::TORSO | EPOS::HAT | EPOS::LEGS)) == EPOS::HAT)
- strcat(equipstr, "top head, ");
+ equipstr += "top head, ";
if ((equip & (EPOS::TORSO | EPOS::HAT | EPOS::LEGS)) == (EPOS::HAT | EPOS::LEGS))
- strcat(equipstr, "lower/top head, ");
+ equipstr += "lower/top head, ";
if ((equip & (EPOS::TORSO | EPOS::HAT | EPOS::LEGS)) == EPOS::TORSO)
- strcat(equipstr, "mid head, ");
+ equipstr += "mid head, ";
if ((equip & (EPOS::TORSO | EPOS::HAT | EPOS::LEGS)) == (EPOS::TORSO | EPOS::LEGS))
- strcat(equipstr, "lower/mid head, ");
+ equipstr += "lower/mid head, ";
if ((equip & (EPOS::TORSO | EPOS::HAT | EPOS::LEGS)) == (EPOS::TORSO | EPOS::HAT | EPOS::LEGS))
- strcat(equipstr, "lower/mid/top head, ");
+ equipstr += "lower/mid/top head, ";
// remove final ', '
- equipstr[strlen(equipstr) - 2] = '\0';
+ equipstr.pop_back(2);
}
else
- strzcpy(equipstr, "", sizeof(equipstr));
+ equipstr = MString();
- std::string output;
+ FString output;
if (sd->status.inventory[i].refine)
output = STRPRINTF("%d %s %+d (%s %+d, id: %d) %s",
pl_sd->status.inventory[i].amount,
@@ -4904,15 +4723,17 @@ int atcommand_character_item_list(const int fd, dumb_ptr<map_session_data> sd,
pl_sd->status.inventory[i].refine,
item_data->jname,
pl_sd->status.inventory[i].refine,
- pl_sd->status.inventory[i].nameid, equipstr);
+ pl_sd->status.inventory[i].nameid,
+ FString(equipstr));
else
output = STRPRINTF("%d %s (%s, id: %d) %s",
pl_sd->status.inventory[i].amount,
item_data->name, item_data->jname,
- pl_sd->status.inventory[i].nameid, equipstr);
+ pl_sd->status.inventory[i].nameid,
+ FString(equipstr));
clif_displaymessage(fd, output);
- output.clear();
+ MString voutput;
counter2 = 0;
for (j = 0; j < item_data->slot; j++)
{
@@ -4923,14 +4744,15 @@ int atcommand_character_item_list(const int fd, dumb_ptr<map_session_data> sd,
inventory[i].card[j])) !=
NULL)
{
- if (output.empty())
- output = STRPRINTF(
- " -> (card(s): #%d %s (%s), ",
+ if (!voutput)
+ voutput += STRPRINTF(
+ " -> (card(s): "
+ "#%d %s (%s), ",
++counter2,
item_temp->name,
item_temp->jname);
else
- output += STRPRINTF(
+ voutput += STRPRINTF(
"#%d %s (%s), ",
++counter2,
item_temp->name,
@@ -4938,16 +4760,12 @@ int atcommand_character_item_list(const int fd, dumb_ptr<map_session_data> sd,
}
}
}
- if (!output.empty())
+ if (voutput)
{
// replace trailing ", "
-#ifdef WORKAROUND_GCC46_LIBRARY
- output.resize(output.size() - 1);
-#else
- output.pop_back();
-#endif
- output.back() = ')';
- clif_displaymessage(fd, output);
+ voutput.pop_back();
+ voutput.back() = ')';
+ clif_displaymessage(fd, FString(voutput));
}
}
}
@@ -4955,7 +4773,7 @@ int atcommand_character_item_list(const int fd, dumb_ptr<map_session_data> sd,
clif_displaymessage(fd, "No item found on this player.");
else
{
- std::string output = STRPRINTF(
+ FString output = STRPRINTF(
"%d item(s) found in %d kind(s) of items.",
counter, count);
clif_displaymessage(fd, output);
@@ -4981,22 +4799,22 @@ int atcommand_character_item_list(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_character_storage_list(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
struct storage *stor;
- dumb_ptr<map_session_data> pl_sd;
struct item_data *item_data, *item_temp;
int i, j, count, counter, counter2;
- char character[100] {};
+ CharName character;
- if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1)
+ if (!asplit(message, &character))
{
clif_displaymessage(fd,
- "Please, enter a player name (usage: @charitemlist <char name>).");
+ "Please, enter a player name (usage: @charitemlist <char name>).");
return -1;
}
- if ((pl_sd = map_nick2sd(character)) != NULL)
+ dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
+ if (pl_sd != NULL)
{
if (pc_isGM(sd) >= pc_isGM(pl_sd))
{ // you can look items only lower or same level
@@ -5014,12 +4832,12 @@ int atcommand_character_storage_list(const int fd, dumb_ptr<map_session_data> sd
count++;
if (count == 1)
{
- std::string output = STRPRINTF(
- "------ Storage items list of '%s' ------",
- pl_sd->status.name);
+ FString output = STRPRINTF(
+ "------ Storage items list of '%s' ------",
+ pl_sd->status.name);
clif_displaymessage(fd, output);
}
- std::string output;
+ FString output;
if (stor->storage_[i].refine)
output = STRPRINTF("%d %s %+d (%s %+d, id: %d)",
stor->storage_[i].amount,
@@ -5035,7 +4853,7 @@ int atcommand_character_storage_list(const int fd, dumb_ptr<map_session_data> sd
stor->storage_[i].nameid);
clif_displaymessage(fd, output);
- output.clear();
+ MString voutput;
counter2 = 0;
for (j = 0; j < item_data->slot; j++)
{
@@ -5046,14 +4864,15 @@ int atcommand_character_storage_list(const int fd, dumb_ptr<map_session_data> sd
storage_[i].card[j])) !=
NULL)
{
- if (output.empty())
- output = STRPRINTF(
- " -> (card(s): #%d %s (%s), ",
+ if (!voutput)
+ voutput += STRPRINTF(
+ " -> (card(s): "
+ "#%d %s (%s), ",
++counter2,
item_temp->name,
item_temp->jname);
else
- output += STRPRINTF(
+ voutput += STRPRINTF(
"#%d %s (%s), ",
++counter2,
item_temp->name,
@@ -5061,27 +4880,23 @@ int atcommand_character_storage_list(const int fd, dumb_ptr<map_session_data> sd
}
}
}
- if (!output.empty())
+ if (voutput)
{
// replace last ", "
-#ifdef WORKAROUND_GCC46_LIBRARY
- output.resize(output.size() - 1);
-#else
- output.pop_back();
-#endif
- output.back() = ')';
- clif_displaymessage(fd, output);
+ voutput.pop_back();
+ voutput.back() = ')';
+ clif_displaymessage(fd, FString(voutput));
}
}
}
if (count == 0)
clif_displaymessage(fd,
- "No item found in the storage of this player.");
+ "No item found in the storage of this player.");
else
{
- std::string output = STRPRINTF(
- "%d item(s) found in %d kind(s) of items.",
- counter, count);
+ FString output = STRPRINTF(
+ "%d item(s) found in %d kind(s) of items.",
+ counter, count);
clif_displaymessage(fd, output);
}
}
@@ -5111,21 +4926,21 @@ int atcommand_character_storage_list(const int fd, dumb_ptr<map_session_data> sd
*------------------------------------------
*/
int atcommand_character_cart_list(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
- dumb_ptr<map_session_data> pl_sd;
struct item_data *item_data, *item_temp;
int i, j, count, counter, counter2;
- char character[100] {};
+ CharName character;
- if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1)
+ if (!asplit(message, &character))
{
clif_displaymessage(fd,
- "Please, enter a player name (usage: @charitemlist <char name>).");
+ "Please, enter a player name (usage: @charitemlist <char name>).");
return -1;
}
- if ((pl_sd = map_nick2sd(character)) != NULL)
+ dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
+ if (pl_sd != NULL)
{
if (pc_isGM(sd) >= pc_isGM(pl_sd))
{ // you can look items only lower or same level
@@ -5141,13 +4956,13 @@ int atcommand_character_cart_list(const int fd, dumb_ptr<map_session_data> sd,
count++;
if (count == 1)
{
- std::string output = STRPRINTF(
+ FString output = STRPRINTF(
"------ Cart items list of '%s' ------",
pl_sd->status.name);
clif_displaymessage(fd, output);
}
- std::string output;
+ FString output;
if (pl_sd->status.cart[i].refine)
output = STRPRINTF("%d %s %+d (%s %+d, id: %d)",
pl_sd->status.cart[i].amount,
@@ -5164,7 +4979,7 @@ int atcommand_character_cart_list(const int fd, dumb_ptr<map_session_data> sd,
pl_sd->status.cart[i].nameid);
clif_displaymessage(fd, output);
- output.clear();
+ MString voutput;
counter2 = 0;
for (j = 0; j < item_data->slot; j++)
{
@@ -5174,14 +4989,15 @@ int atcommand_character_cart_list(const int fd, dumb_ptr<map_session_data> sd,
itemdb_search(pl_sd->status.
cart[i].card[j])) != NULL)
{
- if (output.empty())
- output = STRPRINTF(
- " -> (card(s): #%d %s (%s), ",
+ if (!voutput)
+ voutput += STRPRINTF(
+ " -> (card(s): "
+ "#%d %s (%s), ",
++counter2,
item_temp->name,
item_temp->jname);
else
- output += STRPRINTF(
+ voutput += STRPRINTF(
"#%d %s (%s), ",
++counter2,
item_temp->name,
@@ -5189,24 +5005,20 @@ int atcommand_character_cart_list(const int fd, dumb_ptr<map_session_data> sd,
}
}
}
- if (!output.empty())
+ if (voutput)
{
-#ifdef WORKAROUND_GCC46_LIBRARY
- output.resize(output.size() - 1);
-#else
- output.pop_back();
-#endif
- output.back() = '0';
- clif_displaymessage(fd, output);
+ voutput.pop_back();
+ voutput.back() = '0';
+ clif_displaymessage(fd, FString(voutput));
}
}
}
if (count == 0)
clif_displaymessage(fd,
- "No item found in the cart of this player.");
+ "No item found in the cart of this player.");
else
{
- std::string output = STRPRINTF("%d item(s) found in %d kind(s) of items.",
+ FString output = STRPRINTF("%d item(s) found in %d kind(s) of items.",
counter, count);
clif_displaymessage(fd, output);
}
@@ -5232,7 +5044,7 @@ int atcommand_character_cart_list(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_killer(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *)
+ ZString)
{
sd->special_state.killer = !sd->special_state.killer;
@@ -5250,7 +5062,7 @@ int atcommand_killer(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_killable(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *)
+ ZString)
{
sd->special_state.killable = !sd->special_state.killable;
@@ -5268,14 +5080,15 @@ int atcommand_killable(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_charkillable(const int fd, dumb_ptr<map_session_data>,
- const char *, const char *message)
+ ZString message)
{
- dumb_ptr<map_session_data> pl_sd = NULL;
+ CharName character;
- if (!message || !*message)
+ if (!asplit(message, &character))
return -1;
- if ((pl_sd = map_nick2sd(message)) == NULL)
+ dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
+ if (pl_sd == NULL)
return -1;
pl_sd->special_state.killable = !pl_sd->special_state.killable;
@@ -5295,19 +5108,16 @@ int atcommand_charkillable(const int fd, dumb_ptr<map_session_data>,
*------------------------------------------
*/
int atcommand_npcmove(const int, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
- char character[100] {};
+ NpcName character;
int x = 0, y = 0;
dumb_ptr<npc_data> nd = 0;
if (sd == NULL)
return -1;
- if (!message || !*message)
- return -1;
-
- if (sscanf(message, "%d %d %99[^\n]", &x, &y, character) < 3)
+ if (!asplit(message, &x, &y, &character))
return -1;
nd = npc_name2id(character);
@@ -5329,24 +5139,22 @@ int atcommand_npcmove(const int, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_addwarp(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
- char mapname[30];
- int x, y, ret;
+ MapName mapname;
+ int x, y;
- if (!message || !*message)
+ if (!extract(message, record<' '>(&mapname, &x, &y)))
return -1;
- if (sscanf(message, "%29s %d %d[^\n]", mapname, &x, &y) < 3)
- return -1;
-
- std::string w1 = STRPRINTF("%s,%d,%d", sd->mapname_, sd->bl_x, sd->bl_y);
- std::string w3 = STRPRINTF("%s%d%d%d%d", mapname, sd->bl_x, sd->bl_y, x, y);
- std::string w4 = STRPRINTF("1,1,%s.gat,%d,%d", mapname, x, y);
+ FString w1 = STRPRINTF("%s,%d,%d", sd->mapname_, sd->bl_x, sd->bl_y);
+ FString w3 = STRPRINTF("%s%d%d%d%d", mapname, sd->bl_x, sd->bl_y, x, y);
+ FString w4 = STRPRINTF("1,1,%s.gat,%d,%d", mapname, x, y);
- ret = npc_parse_warp(w1.c_str(), "warp", w3.c_str(), w4.c_str());
+ NpcName w3name = stringish<NpcName>(w3);
+ int ret = npc_parse_warp(w1, ZString("warp"), w3name, w4);
- std::string output = STRPRINTF("New warp NPC => %s", w3);
+ FString output = STRPRINTF("New warp NPC => %s", w3);
clif_displaymessage(fd, output);
return ret;
@@ -5359,20 +5167,19 @@ int atcommand_addwarp(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_chareffect(const int fd, dumb_ptr<map_session_data>,
- const char *, const char *message)
+ ZString message)
{
- dumb_ptr<map_session_data> pl_sd = NULL;
- char target[255];
+ CharName target;
int type = 0;
- if (!message || !*message
- || sscanf(message, "%d %s", &type, target) != 2)
+ if (!asplit(message, &type, &target))
{
clif_displaymessage(fd, "usage: @chareffect <type+> <target>.");
return -1;
}
- if ((pl_sd = map_nick2sd(target)) == NULL)
+ dumb_ptr<map_session_data> pl_sd = map_nick2sd(target);
+ if (pl_sd == NULL)
return -1;
clif_specialeffect(pl_sd, type, 0);
@@ -5388,7 +5195,7 @@ int atcommand_chareffect(const int fd, dumb_ptr<map_session_data>,
*------------------------------------------
*/
int atcommand_dropall(const int, dumb_ptr<map_session_data> sd,
- const char *, const char *)
+ ZString)
{
int i;
for (i = 0; i < MAX_INVENTORY; i++)
@@ -5411,16 +5218,16 @@ int atcommand_dropall(const int, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_chardropall(const int fd, dumb_ptr<map_session_data>,
- const char *, const char *message)
+ ZString message)
{
- int i;
- dumb_ptr<map_session_data> pl_sd = NULL;
+ CharName character;
- if (!message || !*message)
+ if (!asplit(message, &character))
return -1;
- if ((pl_sd = map_nick2sd(message)) == NULL)
+ dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
+ if (pl_sd == NULL)
return -1;
- for (i = 0; i < MAX_INVENTORY; i++)
+ for (int i = 0; i < MAX_INVENTORY; i++)
{
if (pl_sd->status.inventory[i].amount)
{
@@ -5445,7 +5252,7 @@ int atcommand_chardropall(const int fd, dumb_ptr<map_session_data>,
*------------------------------------------
*/
int atcommand_storeall(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *)
+ ZString)
{
int i;
nullpo_retr(-1, sd);
@@ -5459,7 +5266,7 @@ int atcommand_storeall(const int fd, dumb_ptr<map_session_data> sd,
return 0;
case 1: //Failure
clif_displaymessage(fd,
- "You can't open the storage currently.");
+ "You can't open the storage currently.");
return 1;
}
}
@@ -5485,24 +5292,24 @@ int atcommand_storeall(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_charstoreall(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
- int i;
- dumb_ptr<map_session_data> pl_sd = NULL;
+ CharName character;
- if (!message || !*message)
+ if (!asplit(message, &character))
return -1;
- if ((pl_sd = map_nick2sd(message)) == NULL)
+ dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
+ if (pl_sd == NULL)
return -1;
if (storage_storageopen(pl_sd) == 1)
{
clif_displaymessage(fd,
- "Had to open the characters storage window...");
+ "Had to open the characters storage window...");
clif_displaymessage(fd, "run this command again..");
return 0;
}
- for (i = 0; i < MAX_INVENTORY; i++)
+ for (int i = 0; i < MAX_INVENTORY; i++)
{
if (pl_sd->status.inventory[i].amount)
{
@@ -5514,9 +5321,9 @@ int atcommand_charstoreall(const int fd, dumb_ptr<map_session_data> sd,
storage_storageclose(pl_sd);
clif_displaymessage(pl_sd->fd,
- "Everything you own has been put away for safe keeping.");
+ "Everything you own has been put away for safe keeping.");
clif_displaymessage(pl_sd->fd,
- "go to the nearest kafka to retrieve it..");
+ "go to the nearest kafka to retrieve it..");
clif_displaymessage(pl_sd->fd, " -- the management");
clif_displaymessage(fd, "It is done");
@@ -5529,7 +5336,7 @@ int atcommand_charstoreall(const int fd, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_rain(const int, dumb_ptr<map_session_data> sd,
- const char *, const char *)
+ ZString)
{
int effno = 0;
effno = 161;
@@ -5547,7 +5354,7 @@ int atcommand_rain(const int, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_snow(const int, dumb_ptr<map_session_data> sd,
- const char *, const char *)
+ ZString)
{
int effno = 0;
effno = 162;
@@ -5565,7 +5372,7 @@ int atcommand_snow(const int, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_sakura(const int, dumb_ptr<map_session_data> sd,
- const char *, const char *)
+ ZString)
{
int effno = 0;
effno = 163;
@@ -5583,7 +5390,7 @@ int atcommand_sakura(const int, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_fog(const int, dumb_ptr<map_session_data> sd,
- const char *, const char *)
+ ZString)
{
int effno = 0;
effno = 233;
@@ -5602,7 +5409,7 @@ int atcommand_fog(const int, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_leaves(const int, dumb_ptr<map_session_data> sd,
- const char *, const char *)
+ ZString)
{
int effno = 0;
effno = 333;
@@ -5620,24 +5427,21 @@ int atcommand_leaves(const int, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_summon(const int, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
- char name[100];
+ MobName name;
int mob_id = 0;
int x = 0;
int y = 0;
int id = 0;
- dumb_ptr<mob_data> md;
tick_t tick = gettick();
nullpo_retr(-1, sd);
- if (!message || !*message)
- return -1;
- if (sscanf(message, "%99[^\n]", name) < 1)
+ if (!extract(message, &name) || !name)
return -1;
- if ((mob_id = atoi(name)) == 0)
+ if ((mob_id = atoi(name.c_str())) == 0)
mob_id = mobdb_searchname(name);
if (mob_id == 0)
return -1;
@@ -5645,8 +5449,9 @@ int atcommand_summon(const int, dumb_ptr<map_session_data> sd,
x = sd->bl_x + random_::in(-5, 4);
y = sd->bl_y + random_::in(-5, 4);
- id = mob_once_spawn(sd, "this", x, y, "--ja--", mob_id, 1, "");
- if ((md = map_id_as_mob(id)))
+ id = mob_once_spawn(sd, MOB_THIS_MAP, x, y, JAPANESE_NAME, mob_id, 1, NpcEvent());
+ dumb_ptr<mob_data> md = map_id_as_mob(id);
+ if (md)
{
md->master_id = sd->bl_id;
md->state.special_mob_ai = 1;
@@ -5670,19 +5475,19 @@ int atcommand_summon(const int, dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
int atcommand_adjcmdlvl(const int fd, dumb_ptr<map_session_data>,
- const char *, const char *message)
+ ZString message)
{
- int i, newlev;
- char cmd[100];
+ int newlev;
+ XString cmd;
- if (!message || !*message || sscanf(message, "%d %s", &newlev, cmd) != 2)
+ if (!extract(message, record<' '>(&newlev, &cmd)))
{
clif_displaymessage(fd, "usage: @adjcmdlvl <lvl> <command>.");
return -1;
}
- for (i = 0; atcommand_info[i].command; i++)
- if (strcasecmp(cmd, atcommand_info[i].command + 1) == 0)
+ for (int i = 0; atcommand_info[i].command; i++)
+ if (cmd == atcommand_info[i].command.xslice_t(1))
{
atcommand_info[i].level = newlev;
clif_displaymessage(fd, "@command level changed.");
@@ -5703,21 +5508,20 @@ int atcommand_adjcmdlvl(const int fd, dumb_ptr<map_session_data>,
*------------------------------------------
*/
int atcommand_adjgmlvl(const int fd, dumb_ptr<map_session_data>,
- const char *, const char *message)
+ ZString message)
{
int newlev;
- char user[100];
- dumb_ptr<map_session_data> pl_sd;
+ CharName user;
- if (!message || !*message
- || sscanf(message, "%d %s", &newlev, user) != 2
+ if (!asplit(message, &newlev, &user)
|| newlev < 0 || newlev > 99)
{
clif_displaymessage(fd, "usage: @adjgmlvl <lvl> <user>.");
return -1;
}
- if ((pl_sd = map_nick2sd(user)) == NULL)
+ dumb_ptr<map_session_data> pl_sd = map_nick2sd(user);
+ if (pl_sd == NULL)
return -1;
pc_set_gm_level(pl_sd->status.account_id, newlev);
@@ -5735,13 +5539,15 @@ int atcommand_adjgmlvl(const int fd, dumb_ptr<map_session_data>,
*------------------------------------------
*/
int atcommand_trade(const int, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
- dumb_ptr<map_session_data> pl_sd = NULL;
+ CharName character;
- if (!message || !*message)
+ if (!asplit(message, &character))
return -1;
- if ((pl_sd = map_nick2sd(message)) != NULL)
+
+ dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
+ if (pl_sd)
{
trade_traderequest(sd, pl_sd->bl_id);
return 0;
@@ -5766,7 +5572,7 @@ constexpr
size_t magic_skills_nr = sizeof(magic_skills) / sizeof(magic_skills[0]);
static
-const char *magic_skill_names[magic_skills_nr] =
+ZString magic_skill_names[magic_skills_nr] =
{
"magic",
"life",
@@ -5777,20 +5583,20 @@ const char *magic_skill_names[magic_skills_nr] =
};
int atcommand_magic_info(const int fd, dumb_ptr<map_session_data>,
- const char *, const char *message)
+ ZString message)
{
- char character[100] {};
- dumb_ptr<map_session_data> pl_sd;
+ CharName character;
- if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1)
+ if (!asplit(message, &character))
{
clif_displaymessage(fd, "Usage: @magicinfo <char_name>");
return -1;
}
- if ((pl_sd = map_nick2sd(character)) != NULL)
+ dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
+ if (pl_sd)
{
- std::string buf = STRPRINTF(
+ FString buf = STRPRINTF(
"`%s' has the following magic skills:",
character);
clif_displaymessage(fd, buf);
@@ -5821,30 +5627,27 @@ void set_skill(dumb_ptr<map_session_data> sd, SkillID i, int level)
}
int atcommand_set_magic(const int fd, dumb_ptr<map_session_data>,
- const char *, const char *message)
+ ZString message)
{
- char character[100] {};
- char magic_type[20];
+ CharName character;
+ XString magic_type;
int value;
- dumb_ptr<map_session_data> pl_sd;
- if (!message || !*message
- || sscanf(message, "%19s %i %99[^\n]", magic_type, &value,
- character) < 1)
+ if (!asplit(message, &magic_type, &value, &character))
{
clif_displaymessage(fd,
- "Usage: @setmagic <school> <value> <char-name>, where <school> is either `magic', one of the school names, or `all'.");
+ "Usage: @setmagic <school> <value> <char-name>, where <school> is either `magic', one of the school names, or `all'.");
return -1;
}
SkillID skill_index = SkillID::NEGATIVE;
- if (!strcasecmp("all", magic_type))
+ if ("all" == magic_type)
skill_index = SkillID::ZERO;
else
{
for (size_t i = 0; i < magic_skills_nr; i++)
{
- if (!strcasecmp(magic_skill_names[i], magic_type))
+ if (magic_skill_names[i] == magic_type)
{
skill_index = magic_skills[i];
break;
@@ -5855,11 +5658,12 @@ int atcommand_set_magic(const int fd, dumb_ptr<map_session_data>,
if (skill_index == SkillID::NEGATIVE)
{
clif_displaymessage(fd,
- "Incorrect school of magic. Use `magic', `nature', `life', `war', `transmute', `ether', or `all'.");
+ "Incorrect school of magic. Use `magic', `nature', `life', `war', `transmute', `ether', or `all'.");
return -1;
}
- if ((pl_sd = map_nick2sd(character)) != NULL)
+ dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
+ if (pl_sd != NULL)
{
if (skill_index == SkillID::ZERO)
for (SkillID sk : magic_skills)
@@ -5877,32 +5681,32 @@ int atcommand_set_magic(const int fd, dumb_ptr<map_session_data>,
}
int atcommand_log(const int, dumb_ptr<map_session_data>,
- const char *, const char *)
+ ZString)
{
return 0;
// only used for (implicit) logging
}
int atcommand_tee(const int, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
- char data[strlen(message) + 28];
- strcpy(data, sd->status.name);
- strcat(data, " : ");
- strcat(data, message);
- clif_message(sd, data);
+ MString data;
+ data += sd->status.name.to__actual();
+ data += " : ";
+ data += message;
+ clif_message(sd, FString(data));
return 0;
}
int atcommand_invisible(const int, dumb_ptr<map_session_data> sd,
- const char *, const char *)
+ ZString)
{
pc_invisibility(sd, 1);
return 0;
}
int atcommand_visible(const int, dumb_ptr<map_session_data> sd,
- const char *, const char *)
+ ZString)
{
pc_invisibility(sd, 0);
return 0;
@@ -5910,7 +5714,6 @@ int atcommand_visible(const int, dumb_ptr<map_session_data> sd,
static
int atcommand_jump_iterate(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *,
dumb_ptr<map_session_data> (*get_start)(void),
dumb_ptr<map_session_data> (*get_next)(dumb_ptr<map_session_data>))
{
@@ -5935,18 +5738,18 @@ int atcommand_jump_iterate(const int fd, dumb_ptr<map_session_data> sd,
&& battle_config.any_warp_GM_min_level > pc_isGM(sd))
{
clif_displaymessage(fd,
- "You are not authorised to warp you to the map of this player.");
+ "You are not authorised to warp you to the map of this player.");
return -1;
}
if (sd->bl_m && sd->bl_m->flag.nowarp
&& battle_config.any_warp_GM_min_level > pc_isGM(sd))
{
clif_displaymessage(fd,
- "You are not authorised to warp you from your actual map.");
+ "You are not authorised to warp you from your actual map.");
return -1;
}
pc_setpos(sd, pl_sd->bl_m->name_, pl_sd->bl_x, pl_sd->bl_y, BeingRemoveWhy::WARPED);
- std::string output = STRPRINTF("Jump to %s", pl_sd->status.name);
+ FString output = STRPRINTF("Jump to %s", pl_sd->status.name);
clif_displaymessage(fd, output);
sd->followtarget = pl_sd->bl_id;
@@ -5954,33 +5757,23 @@ int atcommand_jump_iterate(const int fd, dumb_ptr<map_session_data> sd,
return 0;
}
-int atcommand_iterate_forward_over_players(const int fd,
- dumb_ptr<map_session_data> sd,
- const char *command,
- const char *message)
+int atcommand_iterate_forward_over_players(const int fd, dumb_ptr<map_session_data> sd, ZString)
{
- return atcommand_jump_iterate(fd, sd, command, message,
- map_get_first_session,
- map_get_next_session);
+ return atcommand_jump_iterate(fd, sd, map_get_first_session, map_get_next_session);
}
-int atcommand_iterate_backwards_over_players(const int fd,
- dumb_ptr<map_session_data> sd,
- const char *command,
- const char *message)
+int atcommand_iterate_backwards_over_players(const int fd, dumb_ptr<map_session_data> sd, ZString)
{
- return atcommand_jump_iterate(fd, sd, command, message,
- map_get_last_session,
- map_get_prev_session);
+ return atcommand_jump_iterate(fd, sd, map_get_last_session, map_get_prev_session);
}
int atcommand_wgm(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *message)
+ ZString message)
{
if (tmw_CheckChatSpam(sd, message))
return 0;
- tmw_GmHackMsg(STRPRINTF("[GM] %s: %s", sd->status.name, message).c_str());
+ tmw_GmHackMsg(STRPRINTF("[GM] %s: %s", sd->status.name, message));
if (!pc_isGM(sd))
clif_displaymessage(fd, "Message sent.");
@@ -5989,24 +5782,24 @@ int atcommand_wgm(const int fd, dumb_ptr<map_session_data> sd,
int atcommand_skillpool_info(const int fd, dumb_ptr<map_session_data>,
- const char *, const char *message)
+ ZString message)
{
- char character[100];
- dumb_ptr<map_session_data> pl_sd;
+ CharName character;
- if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1)
+ if (!asplit(message, &character))
{
clif_displaymessage(fd, "Usage: @sp-info <char_name>");
return -1;
}
- if ((pl_sd = map_nick2sd(character)) != NULL)
+ dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
+ if (pl_sd != NULL)
{
SkillID pool_skills[MAX_SKILL_POOL];
int pool_skills_nr = skill_pool(pl_sd, pool_skills);
int i;
- std::string buf = STRPRINTF(
+ FString buf = STRPRINTF(
"Active skills %d out of %d for %s:",
pool_skills_nr, skill_pool_max(pl_sd), character);
clif_displaymessage(fd, buf);
@@ -6044,22 +5837,19 @@ int atcommand_skillpool_info(const int fd, dumb_ptr<map_session_data>,
}
int atcommand_skillpool_focus(const int fd, dumb_ptr<map_session_data>,
- const char *, const char *message)
+ ZString message)
{
- char character[100];
- int skill_;
- dumb_ptr<map_session_data> pl_sd;
+ CharName character;
+ SkillID skill;
- if (!message || !*message
- || sscanf(message, "%d %99[^\n]", &skill_, character) < 1)
+ if (!asplit(message, &skill, &character))
{
clif_displaymessage(fd, "Usage: @sp-focus <skill-nr> <char_name>");
return -1;
}
- SkillID skill = SkillID(skill_);
-
- if ((pl_sd = map_nick2sd(character)) != NULL)
+ dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
+ if (pl_sd != NULL)
{
if (skill_pool_activate(pl_sd, skill))
clif_displaymessage(fd, "Activation failed.");
@@ -6073,22 +5863,19 @@ int atcommand_skillpool_focus(const int fd, dumb_ptr<map_session_data>,
}
int atcommand_skillpool_unfocus(const int fd, dumb_ptr<map_session_data>,
- const char *, const char *message)
+ ZString message)
{
- char character[100];
- int skill_;
- dumb_ptr<map_session_data> pl_sd;
+ CharName character;
+ SkillID skill;
- if (!message || !*message
- || sscanf(message, "%d %99[^\n]", &skill_, character) < 1)
+ if (!asplit(message, &skill, &character))
{
clif_displaymessage(fd, "Usage: @sp-unfocus <skill-nr> <char_name>");
return -1;
}
- SkillID skill = SkillID(skill_);
-
- if ((pl_sd = map_nick2sd(character)) != NULL)
+ dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
+ if (pl_sd != NULL)
{
if (skill_pool_deactivate(pl_sd, skill))
clif_displaymessage(fd, "Deactivation failed.");
@@ -6102,23 +5889,21 @@ int atcommand_skillpool_unfocus(const int fd, dumb_ptr<map_session_data>,
}
int atcommand_skill_learn(const int fd, dumb_ptr<map_session_data>,
- const char *, const char *message)
+ ZString message)
{
- char character[100];
- int skill_, level;
- dumb_ptr<map_session_data> pl_sd;
+ CharName character;
+ SkillID skill;
+ int level;
- if (!message || !*message
- || sscanf(message, "%d %d %99[^\n]", &skill_, &level, character) < 1)
+ if (!asplit(message, &skill, &level, &character))
{
clif_displaymessage(fd,
- "Usage: @skill-learn <skill-nr> <level> <char_name>");
+ "Usage: @skill-learn <skill-nr> <level> <char_name>");
return -1;
}
- SkillID skill = SkillID(skill_);
-
- if ((pl_sd = map_nick2sd(character)) != NULL)
+ dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
+ if (pl_sd != NULL)
{
set_skill(pl_sd, skill, level);
clif_skillinfoblock(pl_sd);
@@ -6130,14 +5915,14 @@ int atcommand_skill_learn(const int fd, dumb_ptr<map_session_data>,
}
int atcommand_ipcheck(const int fd, dumb_ptr<map_session_data>,
- const char *, const char *message)
+ ZString message)
{
struct sockaddr_in sai;
- char character[25] {};
+ CharName character;
socklen_t sa_len = sizeof(struct sockaddr);
unsigned long ip;
- if (sscanf(message, "%24[^\n]", character) < 1)
+ if (!asplit(message, &character))
{
clif_displaymessage(fd, "Usage: @ipcheck <char name>");
return -1;
@@ -6153,7 +5938,7 @@ int atcommand_ipcheck(const int fd, dumb_ptr<map_session_data>,
if (getpeername(pl_sd->fd, reinterpret_cast<struct sockaddr *>(&sai), &sa_len))
{
clif_displaymessage(fd,
- "Guru Meditation Error: getpeername() failed");
+ "Guru Meditation Error: getpeername() failed");
return -1;
}
@@ -6175,7 +5960,7 @@ int atcommand_ipcheck(const int fd, dumb_ptr<map_session_data>,
// Is checking GM levels really needed here?
if (ip == sai.sin_addr.s_addr)
{
- std::string output = STRPRINTF(
+ FString output = STRPRINTF(
"Name: %s | Location: %s %d %d",
pl_sd->status.name, pl_sd->mapname_,
pl_sd->bl_x, pl_sd->bl_y);
@@ -6189,7 +5974,7 @@ int atcommand_ipcheck(const int fd, dumb_ptr<map_session_data>,
}
int atcommand_doomspot(const int fd, dumb_ptr<map_session_data> sd,
- const char *, const char *)
+ ZString)
{
for (int i = 0; i < fd_max; i++)
{
diff --git a/src/map/atcommand.hpp b/src/map/atcommand.hpp
index d81f04d..7f31491 100644
--- a/src/map/atcommand.hpp
+++ b/src/map/atcommand.hpp
@@ -6,13 +6,13 @@
#include "map.hpp"
bool is_atcommand(const int fd, dumb_ptr<map_session_data> sd,
- const char *message, int gmlvl);
+ ZString message, int gmlvl);
-int atcommand_config_read(const char *cfgName);
+int atcommand_config_read(ZString cfgName);
-void log_atcommand(dumb_ptr<map_session_data> sd, const_string cmd);
+void log_atcommand(dumb_ptr<map_session_data> sd, XString cmd);
// only used by map.cpp
-extern std::string gm_logfile_name;
+extern FString gm_logfile_name;
#endif // ATCOMMAND_HPP
diff --git a/src/map/battle.cpp b/src/map/battle.cpp
index abef80b..4045348 100644
--- a/src/map/battle.cpp
+++ b/src/map/battle.cpp
@@ -5,8 +5,9 @@
#include <fstream>
#include "../common/cxxstdio.hpp"
-#include "../common/random.hpp"
+#include "../common/io.hpp"
#include "../common/nullpo.hpp"
+#include "../common/random.hpp"
#include "clif.hpp"
#include "itemdb.hpp"
@@ -2290,7 +2291,7 @@ int battle_check_range(dumb_ptr<block_list> src, dumb_ptr<block_list> bl,
* 設定ファイルを読み込む
*------------------------------------------
*/
-int battle_config_read(const char *cfgName)
+int battle_config_read(ZString cfgName)
{
static int count = 0;
@@ -2458,200 +2459,203 @@ int battle_config_read(const char *cfgName)
battle_config.mob_splash_radius = -1;
}
- std::ifstream in(cfgName);
+ std::ifstream in(cfgName.c_str());
if (!in.is_open())
{
PRINTF("file not found: %s\n", cfgName);
return 1;
}
- std::string line;
- while (std::getline(in, line))
+ FString line;
+ while (io::getline(in, line))
{
+#define BATTLE_CONFIG_VAR2(name, varname) {{name}, &battle_config.varname}
+#define BATTLE_CONFIG_VAR(name) BATTLE_CONFIG_VAR2(#name, name)
// s/{"\([a-zA-Z_0-9]*\)", &battle_config.\1}/BATTLE_CONFIG_VAR(\1)/
const struct
{
- const char *str;
+ ZString str;
int *val;
} data[] =
{
- {"warp_point_debug", &battle_config.warp_point_debug},
- {"enemy_critical", &battle_config.enemy_critical},
- {"enemy_critical_rate", &battle_config.enemy_critical_rate},
- {"enemy_str", &battle_config.enemy_str},
- {"enemy_perfect_flee", &battle_config.enemy_perfect_flee},
- {"casting_rate", &battle_config.cast_rate},
- {"delay_rate", &battle_config.delay_rate},
- {"delay_dependon_dex", &battle_config.delay_dependon_dex},
- {"skill_delay_attack_enable", &battle_config.sdelay_attack_enable},
- {"left_cardfix_to_right", &battle_config.left_cardfix_to_right},
- {"player_skill_add_range", &battle_config.pc_skill_add_range},
- {"skill_out_range_consume", &battle_config.skill_out_range_consume},
- {"monster_skill_add_range", &battle_config.mob_skill_add_range},
- {"player_damage_delay", &battle_config.pc_damage_delay},
- {"defunit_not_enemy", &battle_config.defnotenemy},
- {"random_monster_checklv", &battle_config.random_monster_checklv},
- {"attribute_recover", &battle_config.attr_recover},
- {"flooritem_lifetime", &battle_config.flooritem_lifetime},
- {"item_auto_get", &battle_config.item_auto_get},
- {"drop_pickup_safety_zone", &battle_config.drop_pickup_safety_zone},
- {"item_first_get_time", &battle_config.item_first_get_time},
- {"item_second_get_time", &battle_config.item_second_get_time},
- {"item_third_get_time", &battle_config.item_third_get_time},
- {"base_exp_rate", &battle_config.base_exp_rate},
- {"job_exp_rate", &battle_config.job_exp_rate},
- {"gtb_pvp_only", &battle_config.gtb_pvp_only},
- {"death_penalty_type", &battle_config.death_penalty_type},
- {"death_penalty_base", &battle_config.death_penalty_base},
- {"death_penalty_job", &battle_config.death_penalty_job},
- {"zeny_penalty", &battle_config.zeny_penalty},
- {"restart_hp_rate", &battle_config.restart_hp_rate},
- {"restart_sp_rate", &battle_config.restart_sp_rate},
- {"monster_hp_rate", &battle_config.monster_hp_rate},
- {"monster_max_aspd", &battle_config.monster_max_aspd},
- {"atcommand_gm_only", &battle_config.atc_gmonly},
- {"atcommand_spawn_quantity_limit", &battle_config.atc_spawn_quantity_limit},
- {"gm_all_skill", &battle_config.gm_allskill},
- {"gm_all_skill_add_abra", &battle_config.gm_allskill_addabra},
- {"gm_all_equipment", &battle_config.gm_allequip},
- {"gm_skill_unconditional", &battle_config.gm_skilluncond},
- {"player_skillfree", &battle_config.skillfree},
- {"player_skillup_limit", &battle_config.skillup_limit},
- {"weapon_produce_rate", &battle_config.wp_rate},
- {"potion_produce_rate", &battle_config.pp_rate},
- {"monster_active_enable", &battle_config.monster_active_enable},
- {"mob_skill_use", &battle_config.mob_skill_use},
- {"mob_count_rate", &battle_config.mob_count_rate},
- {"quest_skill_learn", &battle_config.quest_skill_learn},
- {"quest_skill_reset", &battle_config.quest_skill_reset},
- {"basic_skill_check", &battle_config.basic_skill_check},
- {"player_invincible_time", &battle_config.pc_invincible_time},
- {"skill_min_damage", &battle_config.skill_min_damage},
- {"finger_offensive_type", &battle_config.finger_offensive_type},
- {"heal_exp", &battle_config.heal_exp},
- {"resurrection_exp", &battle_config.resurrection_exp},
- {"shop_exp", &battle_config.shop_exp},
- {"combo_delay_rate", &battle_config.combo_delay_rate},
- {"wedding_modifydisplay", &battle_config.wedding_modifydisplay},
- {"natural_healhp_interval", &battle_config.natural_healhp_interval},
- {"natural_healsp_interval", &battle_config.natural_healsp_interval},
- {"natural_heal_skill_interval", &battle_config.natural_heal_skill_interval},
- {"natural_heal_weight_rate", &battle_config.natural_heal_weight_rate},
- {"itemheal_regeneration_factor", &battle_config.itemheal_regeneration_factor},
- {"item_name_override_grffile", &battle_config.item_name_override_grffile},
- {"arrow_decrement", &battle_config.arrow_decrement},
- {"max_aspd", &battle_config.max_aspd},
- {"max_hp", &battle_config.max_hp},
- {"max_sp", &battle_config.max_sp},
- {"max_lv", &battle_config.max_lv},
- {"max_parameter", &battle_config.max_parameter},
- {"max_cart_weight", &battle_config.max_cart_weight},
- {"player_skill_log", &battle_config.pc_skill_log},
- {"monster_skill_log", &battle_config.mob_skill_log},
- {"battle_log", &battle_config.battle_log},
- {"save_log", &battle_config.save_log},
- {"error_log", &battle_config.error_log},
- {"etc_log", &battle_config.etc_log},
- {"save_clothcolor", &battle_config.save_clothcolor},
- {"undead_detect_type", &battle_config.undead_detect_type},
- {"player_auto_counter_type", &battle_config.pc_auto_counter_type},
- {"monster_auto_counter_type", &battle_config.monster_auto_counter_type},
- {"agi_penaly_type", &battle_config.agi_penaly_type},
- {"agi_penaly_count", &battle_config.agi_penaly_count},
- {"agi_penaly_num", &battle_config.agi_penaly_num},
- {"agi_penaly_count_lv", &battle_config.agi_penaly_count_lv},
- {"vit_penaly_type", &battle_config.vit_penaly_type},
- {"vit_penaly_count", &battle_config.vit_penaly_count},
- {"vit_penaly_num", &battle_config.vit_penaly_num},
- {"vit_penaly_count_lv", &battle_config.vit_penaly_count_lv},
- {"player_skill_reiteration", &battle_config.pc_skill_reiteration},
- {"monster_skill_reiteration", &battle_config.monster_skill_reiteration},
- {"player_skill_nofootset", &battle_config.pc_skill_nofootset},
- {"monster_skill_nofootset", &battle_config.monster_skill_nofootset},
- {"player_cloak_check_type", &battle_config.pc_cloak_check_type},
- {"monster_cloak_check_type", &battle_config.monster_cloak_check_type},
- {"mob_changetarget_byskill", &battle_config.mob_changetarget_byskill},
- {"player_attack_direction_change", &battle_config.pc_attack_direction_change},
- {"monster_attack_direction_change", &battle_config.monster_attack_direction_change},
- {"player_land_skill_limit", &battle_config.pc_land_skill_limit},
- {"monster_land_skill_limit", &battle_config.monster_land_skill_limit},
- {"party_skill_penaly", &battle_config.party_skill_penaly},
- {"monster_class_change_full_recover", &battle_config.monster_class_change_full_recover},
- {"produce_item_name_input", &battle_config.produce_item_name_input},
- {"produce_potion_name_input", &battle_config.produce_potion_name_input},
- {"making_arrow_name_input", &battle_config.making_arrow_name_input},
- {"holywater_name_input", &battle_config.holywater_name_input},
- {"display_delay_skill_fail", &battle_config.display_delay_skill_fail},
- {"chat_warpportal", &battle_config.chat_warpportal},
- {"mob_warpportal", &battle_config.mob_warpportal},
- {"dead_branch_active", &battle_config.dead_branch_active},
- {"show_steal_in_same_party", &battle_config.show_steal_in_same_party},
- {"enable_upper_class", &battle_config.enable_upper_class},
- {"mob_attack_attr_none", &battle_config.mob_attack_attr_none},
- {"mob_ghostring_fix", &battle_config.mob_ghostring_fix},
- {"pc_attack_attr_none", &battle_config.pc_attack_attr_none},
- {"gx_allhit", &battle_config.gx_allhit},
- {"gx_cardfix", &battle_config.gx_cardfix},
- {"gx_dupele", &battle_config.gx_dupele},
- {"gx_disptype", &battle_config.gx_disptype},
- {"player_skill_partner_check", &battle_config.player_skill_partner_check},
- {"hide_GM_session", &battle_config.hide_GM_session},
- {"unit_movement_type", &battle_config.unit_movement_type},
- {"invite_request_check", &battle_config.invite_request_check},
- {"skill_removetrap_type", &battle_config.skill_removetrap_type},
- {"disp_experience", &battle_config.disp_experience},
- {"riding_weight", &battle_config.riding_weight},
- {"prevent_logout", &battle_config.prevent_logout}, // Added by RoVeRT
- {"alchemist_summon_reward", &battle_config.alchemist_summon_reward}, // [Valaris]
- {"maximum_level", &battle_config.maximum_level}, // [Valaris]
- {"drops_by_luk", &battle_config.drops_by_luk}, // [Valaris]
- {"monsters_ignore_gm", &battle_config.monsters_ignore_gm}, // [Valaris]
- {"pk_mode", &battle_config.pk_mode}, // [Valaris]
- {"multi_level_up", &battle_config.multi_level_up}, // [Valaris]
- {"backstab_bow_penalty", &battle_config.backstab_bow_penalty},
- {"show_mob_hp", &battle_config.show_mob_hp}, // [Valaris]
- {"hack_info_GM_level", &battle_config.hack_info_GM_level}, // added by [Yor]
- {"any_warp_GM_min_level", &battle_config.any_warp_GM_min_level}, // added by [Yor]
- {"packet_ver_flag", &battle_config.packet_ver_flag}, // added by [Yor]
- {"min_hair_style", &battle_config.min_hair_style}, // added by [MouseJstr]
- {"max_hair_style", &battle_config.max_hair_style}, // added by [MouseJstr]
- {"min_hair_color", &battle_config.min_hair_color}, // added by [MouseJstr]
- {"max_hair_color", &battle_config.max_hair_color}, // added by [MouseJstr]
- {"min_cloth_color", &battle_config.min_cloth_color}, // added by [MouseJstr]
- {"max_cloth_color", &battle_config.max_cloth_color}, // added by [MouseJstr]
- {"castrate_dex_scale", &battle_config.castrate_dex_scale}, // added by [MouseJstr]
- {"area_size", &battle_config.area_size}, // added by [MouseJstr]
- {"chat_lame_penalty", &battle_config.chat_lame_penalty},
- {"chat_spam_threshold", &battle_config.chat_spam_threshold},
- {"chat_spam_flood", &battle_config.chat_spam_flood},
- {"chat_spam_ban", &battle_config.chat_spam_ban},
- {"chat_spam_warn", &battle_config.chat_spam_warn},
- {"chat_maxline", &battle_config.chat_maxline},
- {"packet_spam_threshold", &battle_config.packet_spam_threshold},
- {"packet_spam_flood", &battle_config.packet_spam_flood},
- {"packet_spam_kick", &battle_config.packet_spam_kick},
- {"mask_ip_gms", &battle_config.mask_ip_gms},
- {"mob_splash_radius", &battle_config.mob_splash_radius},
+ BATTLE_CONFIG_VAR(warp_point_debug),
+ BATTLE_CONFIG_VAR(enemy_critical),
+ BATTLE_CONFIG_VAR(enemy_critical_rate),
+ BATTLE_CONFIG_VAR(enemy_str),
+ BATTLE_CONFIG_VAR(enemy_perfect_flee),
+ BATTLE_CONFIG_VAR2("casting_rate", cast_rate),
+ BATTLE_CONFIG_VAR(delay_rate),
+ BATTLE_CONFIG_VAR(delay_dependon_dex),
+ BATTLE_CONFIG_VAR2("skill_delay_attack_enable", sdelay_attack_enable),
+ BATTLE_CONFIG_VAR(left_cardfix_to_right),
+ BATTLE_CONFIG_VAR2("player_skill_add_range", pc_skill_add_range),
+ BATTLE_CONFIG_VAR(skill_out_range_consume),
+ BATTLE_CONFIG_VAR2("monster_skill_add_range", mob_skill_add_range),
+ BATTLE_CONFIG_VAR2("player_damage_delay", pc_damage_delay),
+ BATTLE_CONFIG_VAR2("defunit_not_enemy", defnotenemy),
+ BATTLE_CONFIG_VAR(random_monster_checklv),
+ BATTLE_CONFIG_VAR2("attribute_recover", attr_recover),
+ BATTLE_CONFIG_VAR(flooritem_lifetime),
+ BATTLE_CONFIG_VAR(item_auto_get),
+ BATTLE_CONFIG_VAR(drop_pickup_safety_zone),
+ BATTLE_CONFIG_VAR(item_first_get_time),
+ BATTLE_CONFIG_VAR(item_second_get_time),
+ BATTLE_CONFIG_VAR(item_third_get_time),
+ BATTLE_CONFIG_VAR(base_exp_rate),
+ BATTLE_CONFIG_VAR(job_exp_rate),
+ BATTLE_CONFIG_VAR(gtb_pvp_only),
+ BATTLE_CONFIG_VAR(death_penalty_type),
+ BATTLE_CONFIG_VAR(death_penalty_base),
+ BATTLE_CONFIG_VAR(death_penalty_job),
+ BATTLE_CONFIG_VAR(zeny_penalty),
+ BATTLE_CONFIG_VAR(restart_hp_rate),
+ BATTLE_CONFIG_VAR(restart_sp_rate),
+ BATTLE_CONFIG_VAR(monster_hp_rate),
+ BATTLE_CONFIG_VAR(monster_max_aspd),
+ BATTLE_CONFIG_VAR2("atcommand_gm_only", atc_gmonly),
+ BATTLE_CONFIG_VAR2("atcommand_spawn_quantity_limit", atc_spawn_quantity_limit),
+ BATTLE_CONFIG_VAR2("gm_all_skill", gm_allskill),
+ BATTLE_CONFIG_VAR2("gm_all_skill_add_abra", gm_allskill_addabra),
+ BATTLE_CONFIG_VAR2("gm_all_equipment", gm_allequip),
+ BATTLE_CONFIG_VAR2("gm_skill_unconditional", gm_skilluncond),
+ BATTLE_CONFIG_VAR2("player_skillfree", skillfree),
+ BATTLE_CONFIG_VAR2("player_skillup_limit", skillup_limit),
+ BATTLE_CONFIG_VAR2("weapon_produce_rate", wp_rate),
+ BATTLE_CONFIG_VAR2("potion_produce_rate", pp_rate),
+ BATTLE_CONFIG_VAR(monster_active_enable),
+ BATTLE_CONFIG_VAR(mob_skill_use),
+ BATTLE_CONFIG_VAR(mob_count_rate),
+ BATTLE_CONFIG_VAR(quest_skill_learn),
+ BATTLE_CONFIG_VAR(quest_skill_reset),
+ BATTLE_CONFIG_VAR(basic_skill_check),
+ BATTLE_CONFIG_VAR2("player_invincible_time", pc_invincible_time),
+ BATTLE_CONFIG_VAR(skill_min_damage),
+ BATTLE_CONFIG_VAR(finger_offensive_type),
+ BATTLE_CONFIG_VAR(heal_exp),
+ BATTLE_CONFIG_VAR(resurrection_exp),
+ BATTLE_CONFIG_VAR(shop_exp),
+ BATTLE_CONFIG_VAR(combo_delay_rate),
+ BATTLE_CONFIG_VAR(wedding_modifydisplay),
+ BATTLE_CONFIG_VAR(natural_healhp_interval),
+ BATTLE_CONFIG_VAR(natural_healsp_interval),
+ BATTLE_CONFIG_VAR(natural_heal_skill_interval),
+ BATTLE_CONFIG_VAR(natural_heal_weight_rate),
+ BATTLE_CONFIG_VAR(itemheal_regeneration_factor),
+ BATTLE_CONFIG_VAR(item_name_override_grffile),
+ BATTLE_CONFIG_VAR(arrow_decrement),
+ BATTLE_CONFIG_VAR(max_aspd),
+ BATTLE_CONFIG_VAR(max_hp),
+ BATTLE_CONFIG_VAR(max_sp),
+ BATTLE_CONFIG_VAR(max_lv),
+ BATTLE_CONFIG_VAR(max_parameter),
+ BATTLE_CONFIG_VAR(max_cart_weight),
+ BATTLE_CONFIG_VAR2("player_skill_log", pc_skill_log),
+ BATTLE_CONFIG_VAR2("monster_skill_log", mob_skill_log),
+ BATTLE_CONFIG_VAR(battle_log),
+ BATTLE_CONFIG_VAR(save_log),
+ BATTLE_CONFIG_VAR(error_log),
+ BATTLE_CONFIG_VAR(etc_log),
+ BATTLE_CONFIG_VAR(save_clothcolor),
+ BATTLE_CONFIG_VAR(undead_detect_type),
+ BATTLE_CONFIG_VAR2("player_auto_counter_type", pc_auto_counter_type),
+ BATTLE_CONFIG_VAR(monster_auto_counter_type),
+ BATTLE_CONFIG_VAR(agi_penaly_type),
+ BATTLE_CONFIG_VAR(agi_penaly_count),
+ BATTLE_CONFIG_VAR(agi_penaly_num),
+ BATTLE_CONFIG_VAR(agi_penaly_count_lv),
+ BATTLE_CONFIG_VAR(vit_penaly_type),
+ BATTLE_CONFIG_VAR(vit_penaly_count),
+ BATTLE_CONFIG_VAR(vit_penaly_num),
+ BATTLE_CONFIG_VAR(vit_penaly_count_lv),
+ BATTLE_CONFIG_VAR2("player_skill_reiteration", pc_skill_reiteration),
+ BATTLE_CONFIG_VAR(monster_skill_reiteration),
+ BATTLE_CONFIG_VAR2("player_skill_nofootset", pc_skill_nofootset),
+ BATTLE_CONFIG_VAR(monster_skill_nofootset),
+ BATTLE_CONFIG_VAR2("player_cloak_check_type", pc_cloak_check_type),
+ BATTLE_CONFIG_VAR(monster_cloak_check_type),
+ BATTLE_CONFIG_VAR(mob_changetarget_byskill),
+ BATTLE_CONFIG_VAR2("player_attack_direction_change", pc_attack_direction_change),
+ BATTLE_CONFIG_VAR(monster_attack_direction_change),
+ BATTLE_CONFIG_VAR2("player_land_skill_limit", pc_land_skill_limit),
+ BATTLE_CONFIG_VAR(monster_land_skill_limit),
+ BATTLE_CONFIG_VAR(party_skill_penaly),
+ BATTLE_CONFIG_VAR(monster_class_change_full_recover),
+ BATTLE_CONFIG_VAR(produce_item_name_input),
+ BATTLE_CONFIG_VAR(produce_potion_name_input),
+ BATTLE_CONFIG_VAR(making_arrow_name_input),
+ BATTLE_CONFIG_VAR(holywater_name_input),
+ BATTLE_CONFIG_VAR(display_delay_skill_fail),
+ BATTLE_CONFIG_VAR(chat_warpportal),
+ BATTLE_CONFIG_VAR(mob_warpportal),
+ BATTLE_CONFIG_VAR(dead_branch_active),
+ BATTLE_CONFIG_VAR(show_steal_in_same_party),
+ BATTLE_CONFIG_VAR(enable_upper_class),
+ BATTLE_CONFIG_VAR(mob_attack_attr_none),
+ BATTLE_CONFIG_VAR(mob_ghostring_fix),
+ BATTLE_CONFIG_VAR(pc_attack_attr_none),
+ BATTLE_CONFIG_VAR(gx_allhit),
+ BATTLE_CONFIG_VAR(gx_cardfix),
+ BATTLE_CONFIG_VAR(gx_dupele),
+ BATTLE_CONFIG_VAR(gx_disptype),
+ BATTLE_CONFIG_VAR(player_skill_partner_check),
+ BATTLE_CONFIG_VAR(hide_GM_session),
+ BATTLE_CONFIG_VAR(unit_movement_type),
+ BATTLE_CONFIG_VAR(invite_request_check),
+ BATTLE_CONFIG_VAR(skill_removetrap_type),
+ BATTLE_CONFIG_VAR(disp_experience),
+ BATTLE_CONFIG_VAR(riding_weight),
+ BATTLE_CONFIG_VAR(prevent_logout), // Added by RoVeRT
+ BATTLE_CONFIG_VAR(alchemist_summon_reward), // [Valaris]
+ BATTLE_CONFIG_VAR(maximum_level), // [Valaris]
+ BATTLE_CONFIG_VAR(drops_by_luk), // [Valaris]
+ BATTLE_CONFIG_VAR(monsters_ignore_gm), // [Valaris]
+ BATTLE_CONFIG_VAR(pk_mode), // [Valaris]
+ BATTLE_CONFIG_VAR(multi_level_up), // [Valaris]
+ BATTLE_CONFIG_VAR(backstab_bow_penalty),
+ BATTLE_CONFIG_VAR(show_mob_hp), // [Valaris]
+ BATTLE_CONFIG_VAR(hack_info_GM_level), // added by [Yor]
+ BATTLE_CONFIG_VAR(any_warp_GM_min_level), // added by [Yor]
+ BATTLE_CONFIG_VAR(packet_ver_flag), // added by [Yor]
+ BATTLE_CONFIG_VAR(min_hair_style), // added by [MouseJstr]
+ BATTLE_CONFIG_VAR(max_hair_style), // added by [MouseJstr]
+ BATTLE_CONFIG_VAR(min_hair_color), // added by [MouseJstr]
+ BATTLE_CONFIG_VAR(max_hair_color), // added by [MouseJstr]
+ BATTLE_CONFIG_VAR(min_cloth_color), // added by [MouseJstr]
+ BATTLE_CONFIG_VAR(max_cloth_color), // added by [MouseJstr]
+ BATTLE_CONFIG_VAR(castrate_dex_scale), // added by [MouseJstr]
+ BATTLE_CONFIG_VAR(area_size), // added by [MouseJstr]
+ BATTLE_CONFIG_VAR(chat_lame_penalty),
+ BATTLE_CONFIG_VAR(chat_spam_threshold),
+ BATTLE_CONFIG_VAR(chat_spam_flood),
+ BATTLE_CONFIG_VAR(chat_spam_ban),
+ BATTLE_CONFIG_VAR(chat_spam_warn),
+ BATTLE_CONFIG_VAR(chat_maxline),
+ BATTLE_CONFIG_VAR(packet_spam_threshold),
+ BATTLE_CONFIG_VAR(packet_spam_flood),
+ BATTLE_CONFIG_VAR(packet_spam_kick),
+ BATTLE_CONFIG_VAR(mask_ip_gms),
+ BATTLE_CONFIG_VAR(mob_splash_radius),
};
- std::string w1, w2;
+ SString w1;
+ TString w2;
if (!split_key_value(line, &w1, &w2))
continue;
if (w1 == "import")
{
- battle_config_read(w2.c_str());
+ battle_config_read(w2);
continue;
}
for (auto datum : data)
if (w1 == datum.str)
{
- *datum.val = config_switch(w2.c_str());
+ *datum.val = config_switch(w2);
goto continue_outer;
}
- PRINTF("WARNING: unknown battle conf key: %s\n", w1);
+ PRINTF("WARNING: unknown battle conf key: %s\n", FString(w1));
continue_outer:
;
diff --git a/src/map/battle.hpp b/src/map/battle.hpp
index 0f9b2d1..6ed32fd 100644
--- a/src/map/battle.hpp
+++ b/src/map/battle.hpp
@@ -259,6 +259,6 @@ extern struct Battle_Config
int mob_splash_radius;
} battle_config;
-int battle_config_read(const char *cfgName);
+int battle_config_read(ZString cfgName);
#endif // BATTLE_HPP
diff --git a/src/map/chrif.cpp b/src/map/chrif.cpp
index a1e0f55..126235c 100644
--- a/src/map/chrif.cpp
+++ b/src/map/chrif.cpp
@@ -32,13 +32,15 @@ const int packet_len_table[0x20] =
int char_fd;
static
-char char_ip_str[16];
+IP_String char_ip_str;
static
int char_ip;
static
int char_port = 6121;
static
-char userid[24], passwd[24];
+AccountName userid;
+static
+AccountPass passwd;
static
int chrif_state;
@@ -47,21 +49,21 @@ int chrif_state;
*
*------------------------------------------
*/
-void chrif_setuserid(const char *id)
+void chrif_setuserid(AccountName id)
{
- strzcpy(userid, id, sizeof(userid));
+ userid = id;
}
/*==========================================
*
*------------------------------------------
*/
-void chrif_setpasswd(const char *pwd)
+void chrif_setpasswd(AccountPass pwd)
{
- strzcpy(passwd, pwd, sizeof(passwd));
+ passwd = pwd;
}
-char *chrif_getpasswd(void)
+AccountPass chrif_getpasswd(void)
{
return passwd;
}
@@ -70,10 +72,10 @@ char *chrif_getpasswd(void)
*
*------------------------------------------
*/
-void chrif_setip(const char *ip)
+void chrif_setip(IP_String ip)
{
- strzcpy(char_ip_str, ip, sizeof(char_ip_str));
- char_ip = inet_addr(char_ip_str);
+ char_ip_str = ip;
+ char_ip = inet_addr(char_ip_str.c_str());
}
/*==========================================
@@ -180,8 +182,7 @@ int chrif_recvmap(int fd)
port = RFIFOW(fd, 8);
for (i = 10, j = 0; i < RFIFOW(fd, 2); i += 16, j++)
{
- char map[16];
- RFIFO_STRING(fd, i, map, 16);
+ MapName map = RFIFO_STRING<16>(fd, i);
map_setipport(map, ip, port);
}
if (battle_config.etc_log)
@@ -194,8 +195,8 @@ int chrif_recvmap(int fd)
* マップ鯖間移動のためのデータ準備要求
*------------------------------------------
*/
-int chrif_changemapserver(dumb_ptr<map_session_data> sd, char *name, int x,
- int y, struct in_addr ip, short port)
+int chrif_changemapserver(dumb_ptr<map_session_data> sd,
+ MapName name, int x, int y, struct in_addr ip, short port)
{
int i, s_ip;
@@ -245,8 +246,7 @@ int chrif_changemapserverack(int fd)
pc_authfail(sd->fd);
return 0;
}
- char mapname[16];
- RFIFO_STRING(fd, 18, mapname, 16);
+ MapName mapname = RFIFO_STRING<16>(fd, 18);
uint16_t x = RFIFOW(fd, 34);
uint16_t y = RFIFOW(fd, 36);
auto ip = in_addr{RFIFOL(fd, 38)};
@@ -274,9 +274,9 @@ int chrif_connectack(int fd)
chrif_sendmap(fd);
PRINTF("chrif: OnCharIfInit event done. (%d events)\n",
- npc_event_doall("OnCharIfInit"));
+ npc_event_doall(stringish<ScriptLabel>("OnCharIfInit")));
PRINTF("chrif: OnInterIfInit event done. (%d events)\n",
- npc_event_doall("OnInterIfInit"));
+ npc_event_doall(stringish<ScriptLabel>("OnInterIfInit")));
// <Agit> Run Event [AgitInit]
// PRINTF("NPC_Event:[OnAgitInit] do (%d) events (Agit Initialize).\n", npc_event_doall("OnAgitInit"));
@@ -298,7 +298,7 @@ int chrif_sendmapack(int fd)
exit(1);
}
- RFIFO_STRING(fd, 3, wisp_server_name, 24);
+ wisp_server_name = stringish<CharName>(RFIFO_STRING<24>(fd, 3));
chrif_state = 2;
@@ -385,26 +385,25 @@ int chrif_searchcharid(int char_id)
* GMに変化要求
*------------------------------------------
*/
-int chrif_changegm(int id, const char *pass, int len)
+void chrif_changegm(int id, ZString pass)
{
if (battle_config.etc_log)
PRINTF("chrif_changegm: account: %d, password: '%s'.\n", id, pass);
+ size_t len = pass.size() + 1;
WFIFOW(char_fd, 0) = 0x2b0a;
WFIFOW(char_fd, 2) = len + 8;
WFIFOL(char_fd, 4) = id;
WFIFO_STRING(char_fd, 8, pass, len);
WFIFOSET(char_fd, len + 8);
-
- return 0;
}
/*==========================================
* Change Email
*------------------------------------------
*/
-int chrif_changeemail(int id, const char *actual_email,
- const char *new_email)
+void chrif_changeemail(int id, AccountEmail actual_email,
+ AccountEmail new_email)
{
if (battle_config.etc_log)
PRINTF("chrif_changeemail: account: %d, actual_email: '%s', new_email: '%s'.\n",
@@ -415,8 +414,6 @@ int chrif_changeemail(int id, const char *actual_email,
WFIFO_STRING(char_fd, 6, actual_email, 40);
WFIFO_STRING(char_fd, 46, new_email, 40);
WFIFOSET(char_fd, 86);
-
- return 0;
}
/*==========================================
@@ -430,27 +427,17 @@ int chrif_changeemail(int id, const char *actual_email,
* 5: changesex
*------------------------------------------
*/
-int chrif_char_ask_name(int id, char *character_name, short operation_type,
- int year, int month, int day, int hour, int minute,
- int second)
+void chrif_char_ask_name(int id, CharName character_name, short operation_type,
+ HumanTimeDiff modif)
{
WFIFOW(char_fd, 0) = 0x2b0e;
WFIFOL(char_fd, 2) = id; // account_id of who ask (for answer) -1 if nobody
- WFIFO_STRING(char_fd, 6, character_name, 24);
+ WFIFO_STRING(char_fd, 6, character_name.to__actual(), 24);
WFIFOW(char_fd, 30) = operation_type; // type of operation
if (operation_type == 2)
- {
- WFIFOW(char_fd, 32) = year;
- WFIFOW(char_fd, 34) = month;
- WFIFOW(char_fd, 36) = day;
- WFIFOW(char_fd, 38) = hour;
- WFIFOW(char_fd, 40) = minute;
- WFIFOW(char_fd, 42) = second;
- }
+ WFIFO_STRUCT(char_fd, 32, modif);
PRINTF("chrif : sended 0x2b0e\n");
WFIFOSET(char_fd, 44);
-
- return 0;
}
/*==========================================
@@ -472,17 +459,13 @@ int chrif_char_ask_name(int id, char *character_name, short operation_type,
static
int chrif_char_ask_name_answer(int fd)
{
- int acc;
- dumb_ptr<map_session_data> sd;
- char player_name[24];
+ int acc = RFIFOL(fd, 2); // account_id of who has asked (-1 if nobody)
+ CharName player_name = stringish<CharName>(RFIFO_STRING<24>(fd, 6));
- acc = RFIFOL(fd, 2); // account_id of who has asked (-1 if nobody)
- RFIFO_STRING(fd, 6, player_name, 24);
-
- sd = map_id2sd(acc);
+ dumb_ptr<map_session_data> sd = map_id2sd(acc);
if (acc >= 0 && sd != NULL)
{
- std::string output;
+ FString output;
if (RFIFOW(fd, 32) == 1) // player not found
output = STRPRINTF("The player '%s' doesn't exist.",
player_name);
@@ -597,7 +580,7 @@ int chrif_char_ask_name_answer(int fd)
break;
}
}
- if (!output.empty())
+ if (output)
clif_displaymessage(sd->fd, output);
}
else
@@ -611,7 +594,7 @@ int chrif_char_ask_name_answer(int fd)
*------------------------------------------
*/
static
-int chrif_changedgm(int fd)
+void chrif_changedgm(int fd)
{
int acc, level;
dumb_ptr<map_session_data> sd = NULL;
@@ -631,8 +614,6 @@ int chrif_changedgm(int fd)
else
clif_displaymessage(sd->fd, "Failure of GM modification.");
}
-
- return 0;
}
/*==========================================
@@ -640,7 +621,7 @@ int chrif_changedgm(int fd)
*------------------------------------------
*/
static
-int chrif_changedsex(int fd)
+void chrif_changedsex(int fd)
{
int acc, sex, i;
dumb_ptr<map_session_data> sd;
@@ -678,8 +659,6 @@ int chrif_changedsex(int fd)
PRINTF("chrif_changedsex failed.\n");
}
}
-
- return 0;
}
/*==========================================
@@ -726,11 +705,10 @@ int chrif_accountreg2(int fd)
for (p = 8, j = 0; p < RFIFOW(fd, 2) && j < ACCOUNT_REG2_NUM;
p += 36, j++)
{
- RFIFO_STRING(fd, p, sd->status.account_reg2[j].str, 32);
+ sd->status.account_reg2[j].str = stringish<VarName>(RFIFO_STRING<32>(fd, p));
sd->status.account_reg2[j].value = RFIFOL(fd, p + 32);
}
sd->status.account_reg2_num = j;
-// PRINTF("chrif: accountreg2\n");
return 0;
}
@@ -1133,8 +1111,7 @@ void chrif_parse(int fd)
case 0x2b09:
{
int charid = RFIFOL(fd, 2);
- char name[24];
- RFIFO_STRING(fd, 6, name, 24);
+ CharName name = stringish<CharName>(RFIFO_STRING<24>(fd, 6));
map_addchariddb(charid, name);
}
break;
diff --git a/src/map/chrif.hpp b/src/map/chrif.hpp
index 6dca70c..97760c3 100644
--- a/src/map/chrif.hpp
+++ b/src/map/chrif.hpp
@@ -2,14 +2,15 @@
#define CHRIF_HPP
#include "../common/dumb_ptr.hpp"
+#include "../common/human_time_diff.hpp"
#include "map.hpp"
-void chrif_setuserid(const char *);
-void chrif_setpasswd(const char *);
-char *chrif_getpasswd(void);
+void chrif_setuserid(AccountName);
+void chrif_setpasswd(AccountPass);
+AccountPass chrif_getpasswd(void);
-void chrif_setip(const char *);
+void chrif_setip(IP_String);
void chrif_setport(int);
int chrif_isconnect(void);
@@ -19,15 +20,14 @@ int chrif_save(dumb_ptr<map_session_data>);
int chrif_charselectreq(dumb_ptr<map_session_data>);
int chrif_changemapserver(dumb_ptr<map_session_data> sd,
- char *name, int x, int y,
+ MapName name, int x, int y,
struct in_addr ip, short port);
int chrif_searchcharid(int char_id);
-int chrif_changegm(int id, const char *pass, int len);
-int chrif_changeemail(int id, const char *actual_email,
- const char *new_email);
-int chrif_char_ask_name(int id, char *character_name, short operation_type,
- int year, int month, int day, int hour, int minute, int second);
+void chrif_changegm(int id, ZString pass);
+void chrif_changeemail(int id, AccountEmail actual_email, AccountEmail new_email);
+void chrif_char_ask_name(int id, CharName character_name, short operation_type,
+ HumanTimeDiff modif);
int chrif_saveaccountreg2(dumb_ptr<map_session_data> sd);
int chrif_reloadGMdb(void);
int chrif_send_divorce(int char_id);
diff --git a/src/map/clif.cpp b/src/map/clif.cpp
index 9f06bfc..494e09f 100644
--- a/src/map/clif.cpp
+++ b/src/map/clif.cpp
@@ -107,7 +107,7 @@ void WFIFOPOS2(int fd, size_t pos, uint16_t x0, uint16_t y0, uint16_t x1, uint16
}
static
-char map_ip_str[16];
+IP_String map_ip_str;
static
struct in_addr map_ip;
static
@@ -121,10 +121,10 @@ int clif_changelook_towards(dumb_ptr<block_list> bl, LOOK type, int val,
* map鯖のip設定
*------------------------------------------
*/
-void clif_setip(const char *ip)
+void clif_setip(IP_String ip)
{
- strzcpy(map_ip_str, ip, 16);
- map_ip.s_addr = inet_addr(map_ip_str);
+ map_ip_str = ip;
+ map_ip.s_addr = inet_addr(map_ip_str.c_str());
}
/*==========================================
@@ -212,7 +212,7 @@ enum class ChatType
};
static
-std::string clif_validate_chat(dumb_ptr<map_session_data> sd, ChatType type);
+FString clif_validate_chat(dumb_ptr<map_session_data> sd, ChatType type);
/*==========================================
* clif_sendでSendWho::AREA*指定時用
@@ -1096,7 +1096,7 @@ void clif_setwaitclose(int fd)
*
*------------------------------------------
*/
-void clif_changemap(dumb_ptr<map_session_data> sd, const char *mapname, int x, int y)
+void clif_changemap(dumb_ptr<map_session_data> sd, MapName mapname, int x, int y)
{
nullpo_retv(sd);
@@ -1113,8 +1113,8 @@ void clif_changemap(dumb_ptr<map_session_data> sd, const char *mapname, int x, i
*
*------------------------------------------
*/
-void clif_changemapserver(dumb_ptr<map_session_data> sd, const char *mapname, int x,
- int y, struct in_addr ip, int port)
+void clif_changemapserver(dumb_ptr<map_session_data> sd,
+ MapName mapname, int x, int y, struct in_addr ip, int port)
{
nullpo_retv(sd);
@@ -1228,125 +1228,103 @@ int clif_selllist(dumb_ptr<map_session_data> sd)
*
*------------------------------------------
*/
-int clif_scriptmes(dumb_ptr<map_session_data> sd, int npcid, const char *mes)
+void clif_scriptmes(dumb_ptr<map_session_data> sd, int npcid, XString mes)
{
- nullpo_ret(sd);
+ nullpo_retv(sd);
int fd = sd->fd;
- size_t len = strlen(mes) + 1;
+ size_t len = mes.size() + 1;
WFIFOW(fd, 0) = 0xb4;
WFIFOW(fd, 2) = len + 8;
WFIFOL(fd, 4) = npcid;
WFIFO_STRING(fd, 8, mes, len);
WFIFOSET(fd, WFIFOW(fd, 2));
-
- return 0;
}
/*==========================================
*
*------------------------------------------
*/
-int clif_scriptnext(dumb_ptr<map_session_data> sd, int npcid)
+void clif_scriptnext(dumb_ptr<map_session_data> sd, int npcid)
{
- int fd;
-
- nullpo_ret(sd);
+ nullpo_retv(sd);
- fd = sd->fd;
+ int fd = sd->fd;
WFIFOW(fd, 0) = 0xb5;
WFIFOL(fd, 2) = npcid;
WFIFOSET(fd, clif_parse_func_table[0xb5].len);
-
- return 0;
}
/*==========================================
*
*------------------------------------------
*/
-int clif_scriptclose(dumb_ptr<map_session_data> sd, int npcid)
+void clif_scriptclose(dumb_ptr<map_session_data> sd, int npcid)
{
- int fd;
-
- nullpo_ret(sd);
+ nullpo_retv(sd);
- fd = sd->fd;
+ int fd = sd->fd;
WFIFOW(fd, 0) = 0xb6;
WFIFOL(fd, 2) = npcid;
WFIFOSET(fd, clif_parse_func_table[0xb6].len);
-
- return 0;
}
/*==========================================
*
*------------------------------------------
*/
-int clif_scriptmenu(dumb_ptr<map_session_data> sd, int npcid, const char *mes)
+void clif_scriptmenu(dumb_ptr<map_session_data> sd, int npcid, XString mes)
{
- nullpo_ret(sd);
+ nullpo_retv(sd);
int fd = sd->fd;
- size_t len = strlen(mes) + 1;
+ size_t len = mes.size() + 1;
WFIFOW(fd, 0) = 0xb7;
WFIFOW(fd, 2) = len + 8;
WFIFOL(fd, 4) = npcid;
WFIFO_STRING(fd, 8, mes, len);
WFIFOSET(fd, WFIFOW(fd, 2));
-
- return 0;
}
/*==========================================
*
*------------------------------------------
*/
-int clif_scriptinput(dumb_ptr<map_session_data> sd, int npcid)
+void clif_scriptinput(dumb_ptr<map_session_data> sd, int npcid)
{
- int fd;
-
- nullpo_ret(sd);
+ nullpo_retv(sd);
- fd = sd->fd;
+ int fd = sd->fd;
WFIFOW(fd, 0) = 0x142;
WFIFOL(fd, 2) = npcid;
WFIFOSET(fd, clif_parse_func_table[0x142].len);
-
- return 0;
}
/*==========================================
*
*------------------------------------------
*/
-int clif_scriptinputstr(dumb_ptr<map_session_data> sd, int npcid)
+void clif_scriptinputstr(dumb_ptr<map_session_data> sd, int npcid)
{
- int fd;
-
- nullpo_ret(sd);
+ nullpo_retv(sd);
- fd = sd->fd;
+ int fd = sd->fd;
WFIFOW(fd, 0) = 0x1d4;
WFIFOL(fd, 2) = npcid;
WFIFOSET(fd, clif_parse_func_table[0x1d4].len);
-
- return 0;
}
/*==========================================
*
*------------------------------------------
*/
-int clif_viewpoint(dumb_ptr<map_session_data> sd, int npc_id, int type, int x,
- int y, int id, int color)
+void clif_viewpoint(dumb_ptr<map_session_data> sd, int npc_id, int type,
+ int x, int y, int id, int color)
{
- int fd;
-
- nullpo_ret(sd);
+ nullpo_retv(sd);
- fd = sd->fd;
+ int fd = sd->fd;
WFIFOW(fd, 0) = 0x144;
WFIFOL(fd, 2) = npc_id;
WFIFOL(fd, 6) = type;
@@ -1355,8 +1333,6 @@ int clif_viewpoint(dumb_ptr<map_session_data> sd, int npc_id, int type, int x,
WFIFOB(fd, 18) = id;
WFIFOL(fd, 19) = color;
WFIFOSET(fd, clif_parse_func_table[0x144].len);
-
- return 0;
}
/*==========================================
@@ -1432,29 +1408,25 @@ int clif_additem(dumb_ptr<map_session_data> sd, int n, int amount, PickupFail fa
*
*------------------------------------------
*/
-int clif_delitem(dumb_ptr<map_session_data> sd, int n, int amount)
+void clif_delitem(dumb_ptr<map_session_data> sd, int n, int amount)
{
- int fd;
-
- nullpo_ret(sd);
+ nullpo_retv(sd);
- fd = sd->fd;
+ int fd = sd->fd;
WFIFOW(fd, 0) = 0xaf;
WFIFOW(fd, 2) = n + 2;
WFIFOW(fd, 4) = amount;
WFIFOSET(fd, clif_parse_func_table[0xaf].len);
-
- return 0;
}
/*==========================================
*
*------------------------------------------
*/
-int clif_itemlist(dumb_ptr<map_session_data> sd)
+void clif_itemlist(dumb_ptr<map_session_data> sd)
{
- nullpo_ret(sd);
+ nullpo_retv(sd);
int n = 0;
int arrow = -1;
@@ -1492,16 +1464,15 @@ int clif_itemlist(dumb_ptr<map_session_data> sd)
}
if (arrow >= 0)
clif_arrowequip(sd, arrow);
- return 0;
}
/*==========================================
*
*------------------------------------------
*/
-int clif_equiplist(dumb_ptr<map_session_data> sd)
+void clif_equiplist(dumb_ptr<map_session_data> sd)
{
- nullpo_ret(sd);
+ nullpo_retv(sd);
int fd = sd->fd;
WFIFOW(fd, 0) = 0xa4;
@@ -1549,7 +1520,6 @@ int clif_equiplist(dumb_ptr<map_session_data> sd)
WFIFOW(fd, 2) = 4 + n * 20;
WFIFOSET(fd, WFIFOW(fd, 2));
}
- return 0;
}
/*==========================================
@@ -2153,45 +2123,39 @@ int clif_useitemack(dumb_ptr<map_session_data> sd, int index, int amount,
* 取り引き要請受け
*------------------------------------------
*/
-int clif_traderequest(dumb_ptr<map_session_data> sd, const char *name)
+void clif_traderequest(dumb_ptr<map_session_data> sd, CharName name)
{
- nullpo_ret(sd);
+ nullpo_retv(sd);
int fd = sd->fd;
WFIFOW(fd, 0) = 0xe5;
- WFIFO_STRING(fd, 2, name, 24);
+ WFIFO_STRING(fd, 2, name.to__actual(), 24);
WFIFOSET(fd, clif_parse_func_table[0xe5].len);
-
- return 0;
}
/*==========================================
* 取り引き要求応答
*------------------------------------------
*/
-int clif_tradestart(dumb_ptr<map_session_data> sd, int type)
+void clif_tradestart(dumb_ptr<map_session_data> sd, int type)
{
- int fd;
-
- nullpo_ret(sd);
+ nullpo_retv(sd);
- fd = sd->fd;
+ int fd = sd->fd;
WFIFOW(fd, 0) = 0xe7;
WFIFOB(fd, 2) = type;
WFIFOSET(fd, clif_parse_func_table[0xe7].len);
-
- return 0;
}
/*==========================================
* 相手方からのアイテム追加
*------------------------------------------
*/
-int clif_tradeadditem(dumb_ptr<map_session_data> sd,
- dumb_ptr<map_session_data> tsd, int index, int amount)
+void clif_tradeadditem(dumb_ptr<map_session_data> sd,
+ dumb_ptr<map_session_data> tsd, int index, int amount)
{
- nullpo_ret(sd);
- nullpo_ret(tsd);
+ nullpo_retv(sd);
+ nullpo_retv(tsd);
int fd = tsd->fd;
WFIFOW(fd, 0) = 0xe9;
@@ -2235,8 +2199,6 @@ int clif_tradeadditem(dumb_ptr<map_session_data> sd,
}
}
WFIFOSET(fd, clif_parse_func_table[0xe9].len);
-
- return 0;
}
/*==========================================
@@ -2967,7 +2929,7 @@ int clif_status_change(dumb_ptr<block_list> bl, StatusChange type, int flag)
* Send message (modified by [Yor])
*------------------------------------------
*/
-void clif_displaymessage(int fd, ZString mes)
+void clif_displaymessage(int fd, XString mes)
{
if (mes)
{
@@ -2975,7 +2937,7 @@ void clif_displaymessage(int fd, ZString mes)
WFIFOW(fd, 0) = 0x8e;
size_t str_len = mes.size() + 1; // NUL (might not be NUL yet)
WFIFOW(fd, 2) = 4 + str_len;
- WFIFO_STRING(fd, 4, mes.c_str(), str_len);
+ WFIFO_STRING(fd, 4, mes, str_len);
WFIFOSET(fd, 4 + str_len);
}
}
@@ -2984,14 +2946,14 @@ void clif_displaymessage(int fd, ZString mes)
* 天の声を送信する
*------------------------------------------
*/
-void clif_GMmessage(dumb_ptr<block_list> bl, ZString mes, int flag)
+void clif_GMmessage(dumb_ptr<block_list> bl, XString mes, int flag)
{
size_t str_len = mes.size() + 1;
unsigned char buf[str_len + 4];
WBUFW(buf, 0) = 0x9a;
WBUFW(buf, 2) = str_len + 4;
- WBUF_STRING(buf, 4, mes.c_str(), str_len);
+ WBUF_STRING(buf, 4, mes, str_len);
flag &= 0x07;
clif_send(buf, WBUFW(buf, 2), bl,
(flag == 1) ? SendWho::ALL_SAMEMAP :
@@ -3022,12 +2984,12 @@ void clif_resurrection(dumb_ptr<block_list> bl, int type)
* Wisp/page is transmitted to the destination player
*------------------------------------------
*/
-void clif_wis_message(int fd, const char *nick, const char *mes) // R 0097 <len>.w <nick>.24B <message>.?B
+void clif_wis_message(int fd, CharName nick, XString mes) // R 0097 <len>.w <nick>.24B <message>.?B
{
- size_t mes_len = strlen(mes) + 1;
+ size_t mes_len = mes.size() + 1;
WFIFOW(fd, 0) = 0x97;
WFIFOW(fd, 2) = mes_len + 24 + 4;
- WFIFO_STRING(fd, 4, nick, 24);
+ WFIFO_STRING(fd, 4, nick.to__actual(), 24);
WFIFO_STRING(fd, 28, mes, mes_len);
WFIFOSET(fd, WFIFOW(fd, 2));
}
@@ -3090,7 +3052,7 @@ int clif_party_info(struct party *p, int fd)
if (sd == NULL)
sd = dumb_ptr<map_session_data>(m->sd);
WBUFL(buf, 28 + c * 46) = m->account_id;
- WBUF_STRING(buf, 28 + c * 46 + 4, m->name, 24);
+ WBUF_STRING(buf, 28 + c * 46 + 4, m->name.to__actual(), 24);
WBUF_STRING(buf, 28 + c * 46 + 28, m->map, 16);
WBUFB(buf, 28 + c * 46 + 44) = (m->leader) ? 0 : 1;
WBUFB(buf, 28 + c * 46 + 45) = (m->online) ? 0 : 1;
@@ -3153,18 +3115,15 @@ void clif_party_invite(dumb_ptr<map_session_data> sd,
* 4 The character is in the same party.
*------------------------------------------
*/
-int clif_party_inviteack(dumb_ptr<map_session_data> sd, const char *nick, int flag)
+void clif_party_inviteack(dumb_ptr<map_session_data> sd, CharName nick, int flag)
{
- int fd;
-
- nullpo_ret(sd);
+ nullpo_retv(sd);
- fd = sd->fd;
+ int fd = sd->fd;
WFIFOW(fd, 0) = 0xfd;
- WFIFO_STRING(fd, 2, nick, 24);
+ WFIFO_STRING(fd, 2, nick.to__actual(), 24);
WFIFOB(fd, 26) = flag;
WFIFOSET(fd, clif_parse_func_table[0xfd].len);
- return 0;
}
/*==========================================
@@ -3207,17 +3166,17 @@ void clif_party_option(struct party *p, dumb_ptr<map_session_data> sd, int flag)
* パーティ脱退(脱退前に呼ぶこと)
*------------------------------------------
*/
-int clif_party_leaved(struct party *p, dumb_ptr<map_session_data> sd,
- int account_id, const char *name, int flag)
+void clif_party_leaved(struct party *p, dumb_ptr<map_session_data> sd,
+ int account_id, CharName name, int flag)
{
unsigned char buf[64];
int i;
- nullpo_ret(p);
+ nullpo_retv(p);
WBUFW(buf, 0) = 0x105;
WBUFL(buf, 2) = account_id;
- WBUF_STRING(buf, 6, name, 24);
+ WBUF_STRING(buf, 6, name.to__actual(), 24);
WBUFB(buf, 30) = flag & 0x0f;
if ((flag & 0xf0) == 0)
@@ -3237,14 +3196,13 @@ int clif_party_leaved(struct party *p, dumb_ptr<map_session_data> sd,
WFIFO_BUF_CLONE(sd->fd, buf, clif_parse_func_table[0x105].len);
WFIFOSET(sd->fd, clif_parse_func_table[0x105].len);
}
- return 0;
}
/*==========================================
* パーティメッセージ送信
*------------------------------------------
*/
-void clif_party_message(struct party *p, int account_id, const char *mes)
+void clif_party_message(struct party *p, int account_id, XString mes)
{
// always set, but clang is not smart enough
dumb_ptr<map_session_data> sd = nullptr;
@@ -3260,7 +3218,7 @@ void clif_party_message(struct party *p, int account_id, const char *mes)
}
if (sd != NULL)
{
- size_t len = strlen(mes) + 1;
+ size_t len = mes.size() + 1;
unsigned char buf[len + 8];
WBUFW(buf, 0) = 0x109;
WBUFW(buf, 2) = len + 8;
@@ -3748,12 +3706,12 @@ void clif_parse_GetCharNameRequest(int fd, dumb_ptr<map_session_data> sd)
if (ssd->state.shroud_active)
WFIFO_STRING(fd, 6, "", 24);
else
- WFIFO_STRING(fd, 6, ssd->status.name, 24);
+ WFIFO_STRING(fd, 6, ssd->status.name.to__actual(), 24);
WFIFOSET(fd, clif_parse_func_table[0x95].len);
struct party *p = NULL;
- const char *party_name = "";
+ PartyName party_name;
int send = 0;
@@ -3782,7 +3740,7 @@ void clif_parse_GetCharNameRequest(int fd, dumb_ptr<map_session_data> sd)
// Mask the IP using the char-server password
if (battle_config.mask_ip_gms)
- ip = MD5_ip(chrif_getpasswd(), ssd->ip);
+ ip = MD5_ip(ssd->ip);
WFIFOL(fd, 2) = account_id;
WFIFOL(fd, 6) = ip.s_addr;
@@ -3793,18 +3751,10 @@ void clif_parse_GetCharNameRequest(int fd, dumb_ptr<map_session_data> sd)
break;
case BL::NPC:
{
- char name[24];
- strzcpy(name, bl->as_npc()->name, 24);
+ NpcName name = bl->as_npc()->name;
// [fate] elim hashed out/invisible names for the client
- *strchrnul(name, '#') = '\0';
- for (char& c : name)
- {
- // [fate] Elim preceding underscores for (hackish) name position fine-tuning
- if (c != '_')
- break;
- c = ' ';
- }
- WFIFO_STRING(fd, 6, name, 24);
+ auto it = std::find(name.begin(), name.end(), '#');
+ WFIFO_STRING(fd, 6, name.oislice_h(it), 24);
WFIFOSET(fd, clif_parse_func_table[0x95].len);
}
break;
@@ -3838,20 +3788,20 @@ void clif_parse_GlobalMessage(int fd, dumb_ptr<map_session_data> sd)
{
nullpo_retv(sd);
- std::string mbuf = clif_validate_chat(sd, ChatType::Global);
- if (mbuf.empty())
+ FString mbuf = clif_validate_chat(sd, ChatType::Global);
+ if (!mbuf)
{
clif_displaymessage(fd, "Your message could not be sent.");
return;
}
- if (is_atcommand(fd, sd, mbuf.c_str(), 0))
+ if (is_atcommand(fd, sd, mbuf, 0))
return;
if (!magic_message(sd, mbuf))
{
/* Don't send chat that results in an automatic ban. */
- if (tmw_CheckChatSpam(sd, mbuf.c_str()))
+ if (tmw_CheckChatSpam(sd, mbuf))
{
clif_displaymessage(fd, "Your message could not be sent.");
return;
@@ -3863,7 +3813,7 @@ void clif_parse_GlobalMessage(int fd, dumb_ptr<map_session_data> sd)
WBUFW(sendbuf, 0) = 0x8d;
WBUFW(sendbuf, 2) = mbuf_size + 8; /* Header(2) + length(2) + ID(4). */
WBUFL(sendbuf, 4) = sd->bl_id;
- WBUF_STRING(sendbuf, 8, mbuf.c_str(), mbuf_size);
+ WBUF_STRING(sendbuf, 8, mbuf, mbuf_size);
clif_send(sendbuf, mbuf_size + 8, sd, SendWho::AREA_CHAT_WOC);
}
@@ -3875,9 +3825,9 @@ void clif_parse_GlobalMessage(int fd, dumb_ptr<map_session_data> sd)
WFIFOSET(fd, len);
}
-void clif_message(dumb_ptr<block_list> bl, const char *msg)
+void clif_message(dumb_ptr<block_list> bl, XString msg)
{
- size_t msg_len = strlen(msg) + 1;
+ size_t msg_len = msg.size() + 1;
uint8_t buf[512];
if (msg_len + 16 > 512)
@@ -4079,20 +4029,20 @@ void clif_parse_Wis(int fd, dumb_ptr<map_session_data> sd)
nullpo_retv(sd);
- std::string mbuf = clif_validate_chat(sd, ChatType::Whisper);
- if (mbuf.empty())
+ FString mbuf = clif_validate_chat(sd, ChatType::Whisper);
+ if (!mbuf)
{
clif_displaymessage(fd, "Your message could not be sent.");
return;
}
- if (is_atcommand(fd, sd, mbuf.c_str(), 0))
+ if (is_atcommand(fd, sd, mbuf, 0))
{
return;
}
/* Don't send chat that results in an automatic ban. */
- if (tmw_CheckChatSpam(sd, mbuf.c_str()))
+ if (tmw_CheckChatSpam(sd, mbuf))
{
clif_displaymessage(fd, "Your message could not be sent.");
return;
@@ -4104,17 +4054,16 @@ void clif_parse_Wis(int fd, dumb_ptr<map_session_data> sd)
* conflict (for instance, "Test" versus "test"), the char-server must
* settle the discrepancy.
*/
- char tname[24];
- RFIFO_STRING(fd, 4, tname, 24);
+ CharName tname = stringish<CharName>(RFIFO_STRING<24>(fd, 4));
if (!(dstsd = map_nick2sd(tname))
- || strcmp(dstsd->status.name, tname) != 0)
- intif_wis_message(sd, tname, mbuf.c_str());
+ || dstsd->status.name != tname)
+ intif_wis_message(sd, tname, mbuf);
else
{
/* Refuse messages addressed to self. */
if (dstsd->fd == fd)
{
- const char *mes = "You cannot page yourself.";
+ ZString mes = "You cannot page yourself.";
clif_wis_message(fd, wisp_server_name, mes);
}
else
@@ -4122,7 +4071,7 @@ void clif_parse_Wis(int fd, dumb_ptr<map_session_data> sd)
{
/* The player is not being ignored. */
{
- clif_wis_message(dstsd->fd, sd->status.name, mbuf.c_str());
+ clif_wis_message(dstsd->fd, sd->status.name, mbuf);
/* The whisper was sent successfully. */
clif_wis_end(fd, 0);
}
@@ -4519,9 +4468,7 @@ void clif_parse_NpcStringInput(int fd, dumb_ptr<map_session_data> sd)
*/
if (len < 0)
return;
- char buf[len];
- RFIFO_STRING(fd, 8, buf, len);
- sd->npc_str = buf;
+ sd->npc_str = RFIFO_STRING(fd, 8, len);
map_scriptcont(sd, RFIFOL(fd, 4));
}
@@ -4606,8 +4553,7 @@ void clif_parse_CreateParty(int fd, dumb_ptr<map_session_data> sd)
if (battle_config.basic_skill_check == 0
|| pc_checkskill(sd, SkillID::NV_PARTY) >= 2)
{
- char name[24];
- RFIFO_STRING(fd, 2, name, 24);
+ PartyName name = stringish<PartyName>(RFIFO_STRING<24>(fd, 2));
party_create(sd, name);
}
else
@@ -4667,9 +4613,8 @@ static
void clif_parse_RemovePartyMember(int fd, dumb_ptr<map_session_data> sd)
{
int account_id = RFIFOL(fd, 2);
- char name[24];
- RFIFO_STRING(fd, 6, name, 24);
- party_removemember(sd, account_id, name);
+ // unused RFIFO_STRING<24>(fd, 6);
+ party_removemember(sd, account_id);
}
/*==========================================
@@ -4695,24 +4640,24 @@ void clif_parse_PartyMessage(int fd, dumb_ptr<map_session_data> sd)
{
nullpo_retv(sd);
- std::string mbuf = clif_validate_chat(sd, ChatType::Party);
- if (mbuf.empty())
+ FString mbuf = clif_validate_chat(sd, ChatType::Party);
+ if (!mbuf)
{
clif_displaymessage(fd, "Your message could not be sent.");
return;
}
- if (is_atcommand(fd, sd, mbuf.c_str(), 0))
+ if (is_atcommand(fd, sd, mbuf, 0))
return;
/* Don't send chat that results in an automatic ban. */
- if (tmw_CheckChatSpam(sd, mbuf.c_str()))
+ if (tmw_CheckChatSpam(sd, mbuf))
{
clif_displaymessage(fd, "Your message could not be sent.");
return;
}
- party_send_message(sd, mbuf.c_str());
+ party_send_message(sd, mbuf);
}
func_table clif_parse_func_table[0x0220] =
@@ -5361,19 +5306,19 @@ void WARN_MALFORMED_MSG(dumb_ptr<map_session_data> sd, const char *msg)
* @return a dynamically allocated copy of the message, or empty string upon failure
*/
static
-std::string clif_validate_chat(dumb_ptr<map_session_data> sd, ChatType type)
+FString clif_validate_chat(dumb_ptr<map_session_data> sd, ChatType type)
{
- nullpo_retr(std::string(), sd);
+ nullpo_retr(FString(), sd);
/*
* Don't send chat in the period between the ban and the connection's
* closure.
*/
if (sd->auto_ban_info.in_progress)
- return std::string();
+ return FString();
int fd = sd->fd;
size_t msg_len = RFIFOW(fd, 2) - 4;
- size_t name_len = strlen(sd->status.name);
+ size_t name_len = sd->status.name.to__actual().size();
/*
* At least one character is required in all instances.
* Notes for length checks:
@@ -5393,14 +5338,14 @@ std::string clif_validate_chat(dumb_ptr<map_session_data> sd, ChatType type)
if (!msg_len)
{
WARN_MALFORMED_MSG(sd, "no message sent");
- return std::string();
+ return FString();
}
/* The client sent (or claims to have sent) an empty message. */
if (msg_len == min_len)
{
WARN_MALFORMED_MSG(sd, "empty message");
- return std::string();
+ return FString();
}
/* The protocol specifies that the target must be 24 bytes long. */
@@ -5409,7 +5354,7 @@ std::string clif_validate_chat(dumb_ptr<map_session_data> sd, ChatType type)
/* Disallow malformed messages. */
clif_setwaitclose(fd);
WARN_MALFORMED_MSG(sd, "illegal target name");
- return std::string();
+ return FString();
}
size_t pstart = 4;
@@ -5419,9 +5364,7 @@ std::string clif_validate_chat(dumb_ptr<map_session_data> sd, ChatType type)
pstart += 24;
buf_len -= 24;
}
- char pbuf[buf_len + 1];
- // I had to change strzcpy for this :(
- RFIFO_STRING(fd, pstart, pbuf, buf_len + 1);
+ FString pbuf = RFIFO_STRING(fd, pstart, buf_len);
/*
* The client attempted to exceed the maximum message length.
@@ -5433,22 +5376,22 @@ std::string clif_validate_chat(dumb_ptr<map_session_data> sd, ChatType type)
if (buf_len >= battle_config.chat_maxline)
{
WARN_MALFORMED_MSG(sd, "exceeded maximum message length");
- return std::string();
+ return FString();
}
if (type == ChatType::Global)
{
- XString p = ZString(ZString::really_construct_from_a_pointer, pbuf);
- if (!(p.startswith(const_(sd->status.name)) && p.xslice_t(name_len).startswith(" : ")))
+ XString p = pbuf;
+ if (!(p.startswith(sd->status.name.to__actual()) && p.xslice_t(name_len).startswith(" : ")))
{
/* Disallow malformed/spoofed messages. */
clif_setwaitclose(fd);
WARN_MALFORMED_MSG(sd, "spoofed name/invalid format");
- return std::string();
+ return FString();
}
/* Step beyond the separator. */
XString xs = p.xslice_t(name_len + 3);
- return std::string(xs.begin(), xs.end());
+ return xs;
}
return pbuf;
}
@@ -5483,10 +5426,8 @@ void clif_parse(int fd)
{
pc_logout(sd);
clif_quitsave(fd, sd);
- if (sd->status.name != NULL)
- PRINTF("Player [%s] has logged off your server.\n", sd->status.name); // Player logout display [Valaris]
- else
- PRINTF("Player with account [%d] has logged off your server.\n", sd->bl_id); // Player logout display [Yor]
+
+ PRINTF("Player [%s] has logged off your server.\n", sd->status.name); // Player logout display [Valaris]
}
else if (sd)
{ // not authentified! (refused by char-server or disconnect before to be authentified)
@@ -5587,17 +5528,14 @@ void clif_parse(int fd)
}
if (sd && sd->state.auth)
{
- if (sd->status.name != NULL)
- PRINTF("\nAccount ID %d, character ID %d, player name %s.\n",
- sd->status.account_id, sd->status.char_id,
- sd->status.name);
- else
- PRINTF("\nAccount ID %d.\n", sd->bl_id);
+ PRINTF("\nAccount ID %d, character ID %d, player name %s.\n",
+ sd->status.account_id, sd->status.char_id,
+ sd->status.name);
}
else if (sd) // not authentified! (refused by char-server or disconnect before to be authentified)
PRINTF("\nAccount ID %d.\n", sd->bl_id);
- if ((fp = fopen_(packet_txt, "a")) == NULL)
+ if ((fp = fopen(packet_txt, "a")) == NULL)
{
PRINTF("clif.c: cant write [%s] !!! data is lost !!!\n",
packet_txt);
@@ -5609,16 +5547,11 @@ void clif_parse(int fd)
stamp_time(now);
if (sd && sd->state.auth)
{
- if (sd->status.name != NULL)
- FPRINTF(fp,
- "%s\nPlayer with account ID %d (character ID %d, player name %s) sent wrong packet:\n",
- now,
- sd->status.account_id,
- sd->status.char_id, sd->status.name);
- else
- FPRINTF(fp,
- "%s\nPlayer with account ID %d sent wrong packet:\n",
- now, sd->bl_id);
+ FPRINTF(fp,
+ "%s\nPlayer with account ID %d (character ID %d, player name %s) sent wrong packet:\n",
+ now,
+ sd->status.account_id,
+ sd->status.char_id, sd->status.name);
}
else if (sd) // not authentified! (refused by char-server or disconnect before to be authentified)
FPRINTF(fp,
@@ -5634,7 +5567,7 @@ void clif_parse(int fd)
FPRINTF(fp, "%02X ", RFIFOB(fd, i));
}
FPRINTF(fp, "\n\n");
- fclose_(fp);
+ fclose(fp);
}
}
#endif
diff --git a/src/map/clif.hpp b/src/map/clif.hpp
index b9e2233..20f9912 100644
--- a/src/map/clif.hpp
+++ b/src/map/clif.hpp
@@ -14,7 +14,7 @@
#include "pc.t.hpp"
#include "skill.t.hpp"
-void clif_setip(const char *);
+void clif_setip(IP_String);
void clif_setport(int);
struct in_addr clif_getip(void);
@@ -38,23 +38,23 @@ int clif_spawnmob(dumb_ptr<mob_data>); // area
int clif_walkok(dumb_ptr<map_session_data>); // self
int clif_movechar(dumb_ptr<map_session_data>); // area
int clif_movemob(dumb_ptr<mob_data>); //area
-void clif_changemap(dumb_ptr<map_session_data>, const char *, int, int); //self
-void clif_changemapserver(dumb_ptr<map_session_data>, const char *, int, int, struct in_addr, int); //self
+void clif_changemap(dumb_ptr<map_session_data>, MapName, int, int); //self
+void clif_changemapserver(dumb_ptr<map_session_data>, MapName, int, int, struct in_addr, int); //self
void clif_fixpos(dumb_ptr<block_list>); // area
int clif_fixmobpos(dumb_ptr<mob_data> md);
int clif_fixpcpos(dumb_ptr<map_session_data> sd);
int clif_npcbuysell(dumb_ptr<map_session_data>, int); //self
int clif_buylist(dumb_ptr<map_session_data>, dumb_ptr<npc_data_shop>); //self
int clif_selllist(dumb_ptr<map_session_data>); //self
-int clif_scriptmes(dumb_ptr<map_session_data>, int, const char *); //self
-int clif_scriptnext(dumb_ptr<map_session_data>, int); //self
-int clif_scriptclose(dumb_ptr<map_session_data>, int); //self
-int clif_scriptmenu(dumb_ptr<map_session_data>, int, const char *); //self
-int clif_scriptinput(dumb_ptr<map_session_data>, int); //self
-int clif_scriptinputstr(dumb_ptr<map_session_data> sd, int npcid); // self
-int clif_viewpoint(dumb_ptr<map_session_data>, int, int, int, int, int, int); //self
+void clif_scriptmes(dumb_ptr<map_session_data>, int, XString); //self
+void clif_scriptnext(dumb_ptr<map_session_data>, int); //self
+void clif_scriptclose(dumb_ptr<map_session_data>, int); //self
+void clif_scriptmenu(dumb_ptr<map_session_data>, int, XString); //self
+void clif_scriptinput(dumb_ptr<map_session_data>, int); //self
+void clif_scriptinputstr(dumb_ptr<map_session_data> sd, int npcid); // self
+void clif_viewpoint(dumb_ptr<map_session_data>, int, int, int, int, int, int); //self
int clif_additem(dumb_ptr<map_session_data>, int, int, PickupFail); //self
-int clif_delitem(dumb_ptr<map_session_data>, int, int); //self
+void clif_delitem(dumb_ptr<map_session_data>, int, int); //self
int clif_updatestatus(dumb_ptr<map_session_data>, SP); //self
int clif_damage(dumb_ptr<block_list>, dumb_ptr<block_list>,
tick_t, interval_t, interval_t,
@@ -79,9 +79,9 @@ void clif_emotion(dumb_ptr<block_list> bl, int type);
void clif_sitting(int fd, dumb_ptr<map_session_data> sd);
// trade
-int clif_traderequest(dumb_ptr<map_session_data> sd, const char *name);
-int clif_tradestart(dumb_ptr<map_session_data> sd, int type);
-int clif_tradeadditem(dumb_ptr<map_session_data> sd,
+void clif_traderequest(dumb_ptr<map_session_data> sd, CharName name);
+void clif_tradestart(dumb_ptr<map_session_data> sd, int type);
+void clif_tradeadditem(dumb_ptr<map_session_data> sd,
dumb_ptr<map_session_data> tsd, int index, int amount);
int clif_tradeitemok(dumb_ptr<map_session_data> sd, int index, int amount,
int fail);
@@ -122,11 +122,11 @@ int clif_skill_damage(dumb_ptr<block_list> src, dumb_ptr<block_list> dst,
int clif_status_change(dumb_ptr<block_list> bl,
StatusChange type, int flag);
-void clif_wis_message(int fd, const char *nick, const char *mes);
+void clif_wis_message(int fd, CharName nick, XString mes);
void clif_wis_end(int fd, int flag);
-int clif_itemlist(dumb_ptr<map_session_data> sd);
-int clif_equiplist(dumb_ptr<map_session_data> sd);
+void clif_itemlist(dumb_ptr<map_session_data> sd);
+void clif_equiplist(dumb_ptr<map_session_data> sd);
int clif_mvp_effect(dumb_ptr<map_session_data> sd);
@@ -137,22 +137,22 @@ int clif_party_created(dumb_ptr<map_session_data> sd, int flag);
int clif_party_info(struct party *p, int fd);
void clif_party_invite(dumb_ptr<map_session_data> sd,
dumb_ptr<map_session_data> tsd);
-int clif_party_inviteack(dumb_ptr<map_session_data> sd, const char *nick, int flag);
+void clif_party_inviteack(dumb_ptr<map_session_data> sd, CharName nick, int flag);
void clif_party_option(struct party *p, dumb_ptr<map_session_data> sd,
int flag);
-int clif_party_leaved(struct party *p, dumb_ptr<map_session_data> sd,
- int account_id, const char *name, int flag);
-void clif_party_message(struct party *p, int account_id, const char *mes);
+void clif_party_leaved(struct party *p, dumb_ptr<map_session_data> sd,
+ int account_id, CharName name, int flag);
+void clif_party_message(struct party *p, int account_id, XString mes);
int clif_party_xy(struct party *p, dumb_ptr<map_session_data> sd);
int clif_party_hp(struct party *p, dumb_ptr<map_session_data> sd);
// atcommand
-void clif_displaymessage(int fd, ZString mes);
-void clif_GMmessage(dumb_ptr<block_list> bl, ZString mes, int flag);
+void clif_displaymessage(int fd, XString mes);
+void clif_GMmessage(dumb_ptr<block_list> bl, XString mes, int flag);
void clif_resurrection(dumb_ptr<block_list> bl, int type);
int clif_specialeffect(dumb_ptr<block_list> bl, int type, int flag); // special effects [Valaris]
-void clif_message(dumb_ptr<block_list> bl, const char *msg); // messages (from mobs/npcs) [Valaris]
+void clif_message(dumb_ptr<block_list> bl, XString msg); // messages (from mobs/npcs) [Valaris]
int clif_GM_kick(dumb_ptr<map_session_data> sd, dumb_ptr<map_session_data> tsd,
int type);
diff --git a/src/map/grfio.cpp b/src/map/grfio.cpp
index a190d1b..cbb5a86 100644
--- a/src/map/grfio.cpp
+++ b/src/map/grfio.cpp
@@ -15,11 +15,12 @@
#include "../common/cxxstdio.hpp"
#include "../common/extract.hpp"
+#include "../common/io.hpp"
#include "../poison.hpp"
static
-std::map<std::string, std::string> load_resnametable()
+std::map<MapName, FString> load_resnametable()
{
std::ifstream in("data/resnametable.txt");
if (!in.is_open())
@@ -27,12 +28,13 @@ std::map<std::string, std::string> load_resnametable()
fprintf(stderr, "Missing data/resnametable.txt");
abort();
}
- std::map<std::string, std::string> out;
+ std::map<MapName, FString> out;
- std::string line;
- while (std::getline(in, line))
+ FString line;
+ while (io::getline(in, line))
{
- std::string key, value;
+ MapName key;
+ FString value;
if (!extract(line,
record<'#'>(&key, &value)))
continue;
@@ -43,29 +45,32 @@ std::map<std::string, std::string> load_resnametable()
/// Change *.gat to *.wlk
static
-std::string grfio_resnametable(const_string rname)
+FString grfio_resnametable(MapName rname)
{
static
- std::map<std::string, std::string> resnametable = load_resnametable();
+ std::map<MapName, FString> resnametable = load_resnametable();
- return resnametable.at(std::string(rname.begin(), rname.end()));
+ return resnametable.at(rname);
}
-std::vector<uint8_t> grfio_reads(const_string rname)
+std::vector<uint8_t> grfio_reads(MapName rname)
{
- std::string lfname = "data/" + grfio_resnametable(rname);
+ MString lfname_;
+ lfname_ += "data/";
+ lfname_ += grfio_resnametable(rname);
+ FString lfname = FString(lfname_);
int fd = open(lfname.c_str(), O_RDONLY);
if (fd == -1)
{
FPRINTF(stderr, "Resource %s (file %s) not found\n",
- std::string(rname.begin(), rname.end()), lfname);
+ rname, lfname);
return {};
}
off_t len = lseek(fd, 0, SEEK_END);
assert (len != -1);
std::vector<uint8_t> buffer(len);
- int err = pread(fd, buffer.data(), len, 0);
+ ssize_t err = pread(fd, buffer.data(), len, 0);
assert (err == len);
close(fd);
return buffer;
diff --git a/src/map/grfio.hpp b/src/map/grfio.hpp
index fd7b871..aa222c6 100644
--- a/src/map/grfio.hpp
+++ b/src/map/grfio.hpp
@@ -5,11 +5,12 @@
#include <vector>
-#include "../common/const_array.hpp"
+#include "../common/mmo.hpp"
+#include "../common/strings.hpp"
/// Load a resource into memory, subject to data/resnametable.txt.
/// Normally, resourcename is xxx-y.gat and the file is xxx-y.wlk.
/// Currently there is exactly one .wlk per .gat, but multiples are fine.
-std::vector<uint8_t> grfio_reads(const_string resourcename);
+std::vector<uint8_t> grfio_reads(MapName resourcename);
#endif // GRFIO_HPP
diff --git a/src/map/intif.cpp b/src/map/intif.cpp
index 311c661..d22519b 100644
--- a/src/map/intif.cpp
+++ b/src/map/intif.cpp
@@ -36,25 +36,25 @@ const int packet_len_table[] =
// inter serverへの送信
// Message for all GMs on all map servers
-void intif_GMmessage(const_string mes)
+void intif_GMmessage(XString mes)
{
WFIFOW(char_fd, 0) = 0x3000;
size_t len = mes.size() + 1;
WFIFOW(char_fd, 2) = 4 + len;
- WFIFO_STRING(char_fd, 4, mes.data(), len);
+ WFIFO_STRING(char_fd, 4, mes, len);
WFIFOSET(char_fd, WFIFOW(char_fd, 2));
}
// The transmission of Wisp/Page to inter-server (player not found on this server)
-void intif_wis_message(dumb_ptr<map_session_data> sd, const char *nick, const char *mes)
+void intif_wis_message(dumb_ptr<map_session_data> sd, CharName nick, ZString mes)
{
nullpo_retv(sd);
- size_t mes_len = strlen(mes) + 1;
+ size_t mes_len = mes.size() + 1;
WFIFOW(char_fd, 0) = 0x3001;
WFIFOW(char_fd, 2) = mes_len + 52;
- WFIFO_STRING(char_fd, 4, sd->status.name, 24);
- WFIFO_STRING(char_fd, 28, nick, 24);
+ WFIFO_STRING(char_fd, 4, sd->status.name.to__actual(), 24);
+ WFIFO_STRING(char_fd, 28, nick.to__actual(), 24);
WFIFO_STRING(char_fd, 52, mes, mes_len);
WFIFOSET(char_fd, WFIFOW(char_fd, 2));
@@ -77,19 +77,19 @@ void intif_wis_replay(int id, int flag)
}
// The transmission of GM only Wisp/Page from server to inter-server
-void intif_wis_message_to_gm(const char *Wisp_name, int min_gm_level, const char *mes)
+void intif_wis_message_to_gm(CharName Wisp_name, int min_gm_level, ZString mes)
{
- size_t mes_len = strlen(mes) + 1;
+ size_t mes_len = mes.size() + 1;
WFIFOW(char_fd, 0) = 0x3003;
WFIFOW(char_fd, 2) = mes_len + 30;
- WFIFO_STRING(char_fd, 4, Wisp_name, 24);
+ WFIFO_STRING(char_fd, 4, Wisp_name.to__actual(), 24);
WFIFOW(char_fd, 28) = min_gm_level;
WFIFO_STRING(char_fd, 30, mes, mes_len);
WFIFOSET(char_fd, WFIFOW(char_fd, 2));
if (battle_config.etc_log)
PRINTF("intif_wis_message_to_gm: from: '%s', min level: %d, message: '%s'.\n",
- Wisp_name, min_gm_level, mes);
+ Wisp_name, min_gm_level, mes);
}
// アカウント変数送信
@@ -140,14 +140,14 @@ void intif_send_storage(struct storage *stor)
}
// パーティ作成要求
-void intif_create_party(dumb_ptr<map_session_data> sd, const char *name)
+void intif_create_party(dumb_ptr<map_session_data> sd, PartyName name)
{
nullpo_retv(sd);
WFIFOW(char_fd, 0) = 0x3020;
WFIFOL(char_fd, 2) = sd->status.account_id;
WFIFO_STRING(char_fd, 6, name, 24);
- WFIFO_STRING(char_fd, 30, sd->status.name, 24);
+ WFIFO_STRING(char_fd, 30, sd->status.name.to__actual(), 24);
WFIFO_STRING(char_fd, 54, sd->bl_m->name_, 16);
WFIFOW(char_fd, 70) = sd->status.base_level;
WFIFOSET(char_fd, 72);
@@ -171,7 +171,7 @@ void intif_party_addmember(int party_id, int account_id)
WFIFOW(char_fd, 0) = 0x3022;
WFIFOL(char_fd, 2) = party_id;
WFIFOL(char_fd, 6) = account_id;
- WFIFO_STRING(char_fd, 10, sd->status.name, 24);
+ WFIFO_STRING(char_fd, 10, sd->status.name.to__actual(), 24);
WFIFO_STRING(char_fd, 34, sd->bl_m->name_, 16);
WFIFOW(char_fd, 50) = sd->status.base_level;
WFIFOSET(char_fd, 52);
@@ -214,9 +214,9 @@ void intif_party_changemap(dumb_ptr<map_session_data> sd, int online)
}
// パーティ会話送信
-void intif_party_message(int party_id, int account_id, const char *mes)
+void intif_party_message(int party_id, int account_id, XString mes)
{
- size_t len = strlen(mes) + 1;
+ size_t len = mes.size() + 1;
WFIFOW(char_fd, 0) = 0x3027;
WFIFOW(char_fd, 2) = len + 12;
WFIFOL(char_fd, 4) = party_id;
@@ -226,12 +226,12 @@ void intif_party_message(int party_id, int account_id, const char *mes)
}
// パーティ競合チェック要求
-void intif_party_checkconflict(int party_id, int account_id, const char *nick)
+void intif_party_checkconflict(int party_id, int account_id, CharName nick)
{
WFIFOW(char_fd, 0) = 0x3028;
WFIFOL(char_fd, 2) = party_id;
WFIFOL(char_fd, 6) = account_id;
- WFIFO_STRING(char_fd, 10, nick, 24);
+ WFIFO_STRING(char_fd, 10, nick.to__actual(), 24);
WFIFOSET(char_fd, 34);
}
@@ -245,26 +245,22 @@ int intif_parse_WisMessage(int fd)
// rewritten by [Yor]
dumb_ptr<map_session_data> sd;
- char from[24];
- RFIFO_STRING(fd, 8, from, 24);
- char to[24];
- RFIFO_STRING(fd, 32, to, 24);
+ CharName from = stringish<CharName>(RFIFO_STRING<24>(fd, 8));
+ CharName to = stringish<CharName>(RFIFO_STRING<24>(fd, 32));
size_t len = RFIFOW(fd, 2) - 56;
- char buf[len];
- RFIFO_STRING(fd, 56, buf, len);
+ FString buf = RFIFO_STRING(fd, 56, len);
if (battle_config.etc_log)
{
- const char *mes = buf;
PRINTF("intif_parse_wismessage: id: %d, from: %s, to: %s, message: '%s'\n",
RFIFOL(fd, 4),
from,
to,
- mes);
+ buf);
}
sd = map_nick2sd(to); // Searching destination player
- if (sd != NULL && strcmp(sd->status.name, to) == 0)
+ if (sd != NULL && sd->status.name == to)
{
// exactly same name (inter-server have checked the name before)
{
@@ -286,8 +282,7 @@ int intif_parse_WisEnd(int fd)
{
dumb_ptr<map_session_data> sd;
- char name[24];
- RFIFO_STRING(fd, 2, name, 24);
+ CharName name = stringish<CharName>(RFIFO_STRING<24>(fd, 2));
uint8_t flag = RFIFOB(fd, 26);
if (battle_config.etc_log)
// flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
@@ -306,17 +301,15 @@ void mapif_parse_WisToGM(int fd)
{
// 0x3003/0x3803 <packet_len>.w <wispname>.24B <min_gm_level>.w <message>.?B
int min_gm_level, len;
- char Wisp_name[24];
if (RFIFOW(fd, 2) - 30 <= 0)
return;
len = RFIFOW(fd, 2) - 30;
- char message[len];
min_gm_level = RFIFOW(fd, 28);
- RFIFO_STRING(fd, 4, Wisp_name, 24);
- RFIFO_STRING(fd, 30, message, len);
+ CharName Wisp_name = stringish<CharName>(RFIFO_STRING<24>(fd, 4));
+ FString message = RFIFO_STRING(fd, 30, len);
// information is sended to all online GM
for (int i = 0; i < fd_max; i++)
{
@@ -341,7 +334,7 @@ int intif_parse_AccountReg(int fd)
for (p = 8, j = 0; p < RFIFOW(fd, 2) && j < ACCOUNT_REG_NUM;
p += 36, j++)
{
- RFIFO_STRING(fd, p, sd->status.account_reg[j].str, 32);
+ sd->status.account_reg[j].str = stringish<VarName>(RFIFO_STRING<32>(fd, p));
sd->status.account_reg[j].value = RFIFOL(fd, p + 32);
}
sd->status.account_reg_num = j;
@@ -420,8 +413,7 @@ void intif_parse_PartyCreated(int fd)
int account_id = RFIFOL(fd, 2);
int fail = RFIFOB(fd, 6);
int party_id = RFIFOL(fd, 7);
- char name[24];
- RFIFO_STRING(fd, 11, name, 24);
+ PartyName name = stringish<PartyName>(RFIFO_STRING<24>(fd, 11));
party_created(account_id, fail, party_id, name);
}
@@ -474,8 +466,7 @@ void intif_parse_PartyMemberLeaved(int fd)
{
int party_id = RFIFOL(fd, 2);
int account_id = RFIFOL(fd, 6);
- char name[24];
- RFIFO_STRING(fd, 10, name, 24);
+ CharName name = stringish<CharName>(RFIFO_STRING<24>(fd, 10));
if (battle_config.etc_log)
PRINTF("intif: party member leaved %d %d %s\n",
party_id, account_id, name);
@@ -495,8 +486,7 @@ void intif_parse_PartyMove(int fd)
{
int party_id = RFIFOL(fd, 2);
int account_id = RFIFOL(fd, 6);
- char map[16];
- RFIFO_STRING(fd, 10, map, 16);
+ MapName map = stringish<MapName>(RFIFO_STRING<16>(fd, 10));
uint8_t online = RFIFOB(fd, 26);
uint16_t lv = RFIFOW(fd, 27);
party_recv_movemap(party_id, account_id, map, online, lv);
@@ -507,8 +497,7 @@ static
void intif_parse_PartyMessage(int fd)
{
size_t len = RFIFOW(fd, 2) - 12;
- char buf[len];
- RFIFO_STRING(fd, 12, buf, len);
+ FString buf = RFIFO_STRING(fd, 12, len);
party_recv_message(RFIFOL(fd, 4), RFIFOL(fd, 8), buf);
}
@@ -547,9 +536,8 @@ int intif_parse(int fd)
{
case 0x3800:
{
- char mes[packet_len - 4];
- RFIFO_STRING(fd, 4, mes, packet_len - 4);
- clif_GMmessage(NULL, ZString(ZString::really_construct_from_a_pointer, mes), 0);
+ FString mes = RFIFO_STRING(fd, 4, packet_len - 4);
+ clif_GMmessage(NULL, mes, 0);
}
break;
case 0x3801:
diff --git a/src/map/intif.hpp b/src/map/intif.hpp
index 73a06e5..08added 100644
--- a/src/map/intif.hpp
+++ b/src/map/intif.hpp
@@ -7,10 +7,10 @@
int intif_parse(int fd);
-void intif_GMmessage(const_string mes);
+void intif_GMmessage(XString mes);
-void intif_wis_message(dumb_ptr<map_session_data> sd, const char *nick, const char *mes);
-void intif_wis_message_to_gm(const char *Wisp_name, int min_gm_level, const char *mes);
+void intif_wis_message(dumb_ptr<map_session_data> sd, CharName nick, ZString mes);
+void intif_wis_message_to_gm(CharName Wisp_name, int min_gm_level, ZString mes);
void intif_saveaccountreg(dumb_ptr<map_session_data> sd);
void intif_request_accountreg(dumb_ptr<map_session_data> sd);
@@ -18,14 +18,14 @@ void intif_request_accountreg(dumb_ptr<map_session_data> sd);
void intif_request_storage(int account_id);
void intif_send_storage(struct storage *stor);
-void intif_create_party(dumb_ptr<map_session_data> sd, const char *name);
+void intif_create_party(dumb_ptr<map_session_data> sd, PartyName name);
void intif_request_partyinfo(int party_id);
void intif_party_addmember(int party_id, int account_id);
void intif_party_changeoption(int party_id, int account_id, int exp,
int item);
void intif_party_leave(int party_id, int accound_id);
void intif_party_changemap(dumb_ptr<map_session_data> sd, int online);
-void intif_party_message(int party_id, int account_id, const char *mes);
-void intif_party_checkconflict(int party_id, int account_id, const char *nick);
+void intif_party_message(int party_id, int account_id, XString mes);
+void intif_party_checkconflict(int party_id, int account_id, CharName nick);
#endif // INTIF_HPP
diff --git a/src/map/itemdb.cpp b/src/map/itemdb.cpp
index 570b517..cb47b21 100644
--- a/src/map/itemdb.cpp
+++ b/src/map/itemdb.cpp
@@ -3,10 +3,14 @@
#include <cstdlib>
#include <cstring>
+#include <fstream>
+
#include "../common/cxxstdio.hpp"
#include "../common/db.hpp"
-#include "../common/random.hpp"
+#include "../common/extract.hpp"
+#include "../common/io.hpp"
#include "../common/nullpo.hpp"
+#include "../common/random.hpp"
#include "../common/socket.hpp"
#include "../poison.hpp"
@@ -33,9 +37,9 @@ int itemdb_readdb(void);
*/
// name = item alias, so we should find items aliases first. if not found then look for "jname" (full name)
static
-void itemdb_searchname_sub(struct item_data *item, const char *str, struct item_data **dst)
+void itemdb_searchname_sub(struct item_data *item, ItemName str, struct item_data **dst)
{
- if (strcasecmp(item->name, str) == 0) //by lupus
+ if (item->name == str)
*dst = item;
}
@@ -43,7 +47,7 @@ void itemdb_searchname_sub(struct item_data *item, const char *str, struct item_
* 名前で検索
*------------------------------------------
*/
-struct item_data *itemdb_searchname(const char *str)
+struct item_data *itemdb_searchname(ItemName str)
{
struct item_data *item = NULL;
for (auto& pair : item_db)
@@ -148,62 +152,70 @@ int itemdb_isequip3(int nameid)
static
int itemdb_readdb(void)
{
- FILE *fp;
- char line[1024];
int ln = 0, lines = 0;
- int nameid, j;
- struct item_data *id;
- int i = 0;
- const char *filename[] = { "db/item_db.txt", "db/item_db2.txt" };
+ const char *filename = "db/item_db.txt";
- for (i = 0; i < 2; i++)
{
+ std::ifstream in(filename);
- fp = fopen_(filename[i], "r");
- if (fp == NULL)
+ if (!in.is_open())
{
- if (i > 0)
- continue;
- PRINTF("can't read %s\n", filename[i]);
+ PRINTF("can't read %s\n", filename);
exit(1);
}
lines = 0;
- while (fgets(line, 1020, fp))
+
+ FString line;
+ while (io::getline(in, line))
{
lines++;
- if (line[0] == '/' && line[1] == '/')
+ if (!line)
continue;
- char *str[32] {};
- char *p;
- char *np;
- for (j = 0, np = p = line; j < 17 && p; j++)
+ if (line.startswith("//"))
+ continue;
+ // a line is 17 normal fields followed by 2 {} fields
+ // the fields are separated by ", *", but there may be ,
+ // in the {}.
+
+ auto it = std::find(line.begin(), line.end(), '{');
+ XString main_part = line.xislice_h(it).rstrip();
+ // According to the code, tail_part may be empty. See later.
+ ZString tail_part = line.xislice_t(it);
+
+ item_data idv {};
+ if (!extract(
+ main_part, record<','>(
+ &idv.nameid,
+ lstripping(&idv.name),
+ lstripping(&idv.jname),
+ lstripping(&idv.type),
+ lstripping(&idv.value_buy),
+ lstripping(&idv.value_sell),
+ lstripping(&idv.weight),
+ lstripping(&idv.atk),
+ lstripping(&idv.def),
+ lstripping(&idv.range),
+ lstripping(&idv.magic_bonus),
+ lstripping(&idv.slot),
+ lstripping(&idv.sex),
+ lstripping(&idv.equip),
+ lstripping(&idv.wlv),
+ lstripping(&idv.elv),
+ lstripping(&idv.look)
+ )
+ )
+ )
{
- while (*p == '\t' || *p == ' ')
- p++;
- str[j] = p;
- p = strchr(p, ',');
- if (p)
- {
- *p++ = 0;
- np = p;
- }
- }
- if (str[0] == NULL)
+ PRINTF("%s:%d: error: bad item line: %s\n",
+ filename, lines, line);
continue;
+ }
- nameid = atoi(str[0]);
- if (nameid <= 0 || nameid >= 20000)
- continue;
ln++;
- //ID,Name,Jname,Type,Price,Sell,Weight,ATK,DEF,Range,Slot,Job,Gender,Loc,wLV,eLV,View
- id = itemdb_search(nameid);
- strzcpy(id->name, str[1], 24);
- strzcpy(id->jname, str[2], 24);
- id->type = ItemType(atoi(str[3]));
- id->value_buy = atoi(str[4]);
- id->value_sell = atoi(str[5]);
+ struct item_data *id = itemdb_search(idv.nameid);
+ *id = std::move(idv);
if (id->value_buy == 0 && id->value_sell == 0)
{
}
@@ -215,31 +227,20 @@ int itemdb_readdb(void)
{
id->value_sell = id->value_buy / 2;
}
- id->weight = atoi(str[6]);
- id->atk = atoi(str[7]);
- id->def = atoi(str[8]);
- id->range = atoi(str[9]);
- id->magic_bonus = atoi(str[10]);
- id->slot = atoi(str[11]);
- id->sex = atoi(str[12]);
- id->equip = EPOS(atoi(str[13]));
- id->wlv = atoi(str[14]);
- id->elv = atoi(str[15]);
- id->look = static_cast<ItemLook>(atoi(str[16]));
id->use_script = NULL;
id->equip_script = NULL;
- if ((p = strchr(np, '{')) == NULL)
+ if (!tail_part)
continue;
- id->use_script = parse_script(p, lines);
+ id->use_script = parse_script(tail_part, lines);
- if ((p = strchr(p + 1, '{')) == NULL)
+ tail_part = tail_part.xislice_t(std::find(tail_part.begin() + 1, tail_part.end(), '{'));
+ if (!tail_part)
continue;
- id->equip_script = parse_script(p, lines);
+ id->equip_script = parse_script(tail_part, lines);
}
- fclose_(fp);
- PRINTF("read %s done (count=%d)\n", filename[i], ln);
+ PRINTF("read %s done (count=%d)\n", filename, ln);
}
return 0;
}
diff --git a/src/map/itemdb.hpp b/src/map/itemdb.hpp
index 17b2057..7e5aa34 100644
--- a/src/map/itemdb.hpp
+++ b/src/map/itemdb.hpp
@@ -9,9 +9,7 @@
struct item_data
{
int nameid;
- char name[24], jname[24];
- char prefix[24], suffix[24];
- char cardillustname[64];
+ ItemName name, jname;
int value_buy;
int value_sell;
ItemType type;
@@ -37,7 +35,7 @@ struct random_item_data
int per;
};
-struct item_data *itemdb_searchname(const char *name);
+struct item_data *itemdb_searchname(ItemName name);
struct item_data *itemdb_search(int nameid);
struct item_data *itemdb_exists(int nameid);
diff --git a/src/map/magic-expr-eval.hpp b/src/map/magic-expr-eval.hpp
index 9c9591b..76b86f8 100644
--- a/src/map/magic-expr-eval.hpp
+++ b/src/map/magic-expr-eval.hpp
@@ -7,7 +7,7 @@
/* Helper definitions for dealing with functions and operations */
-int magic_signature_check(const char *opname, const char *funname, const char *signature,
+int magic_signature_check(ZString opname, ZString funname, ZString signature,
int args_nr, val_t *args, int line, int column);
void magic_area_rect(map_local **m, int *x, int *y, int *width, int *height,
@@ -15,7 +15,7 @@ void magic_area_rect(map_local **m, int *x, int *y, int *width, int *height,
#define ARGINT(x) args[x].v.v_int
#define ARGDIR(x) args[x].v.v_dir
-#define ARGSTR(x) args[x].v.v_string
+#define ARGSTR(x) ZString(args[x].v.v_string)
#define ARGENTITY(x) args[x].v.v_entity
#define ARGLOCATION(x) args[x].v.v_location
#define ARGAREA(x) args[x].v.v_area
diff --git a/src/map/magic-expr.cpp b/src/map/magic-expr.cpp
index 5aad257..872ba6f 100644
--- a/src/map/magic-expr.cpp
+++ b/src/map/magic-expr.cpp
@@ -87,12 +87,12 @@ void magic_clear_var(val_t *v)
}
static
-const char *show_entity(dumb_ptr<block_list> entity)
+FString show_entity(dumb_ptr<block_list> entity)
{
switch (entity->bl_type)
{
case BL::PC:
- return entity->as_player()->status.name;
+ return entity->as_player()->status.name.to__actual();
case BL::NPC:
return entity->as_npc()->name;
case BL::MOB:
@@ -104,23 +104,23 @@ const char *show_entity(dumb_ptr<block_list> entity)
// return ((struct item_data *) (&entity->as_item()->item_data))->name;
abort();
case BL::SPELL:
- return "%invocation(ERROR:this-should-not-be-an-entity)";
+ return {"%invocation(ERROR:this-should-not-be-an-entity)"};
default:
- return "%unknown-entity";
+ return {"%unknown-entity"};
}
}
static
void stringify(val_t *v, int within_op)
{
- static const char *dirs[8] =
- {
- "south", "south-west",
- "west", "north-west",
- "north", "north-east",
- "east", "south-east"
- };
- std::string buf;
+ static earray<ZString, DIR, DIR::COUNT> dirs //=
+ {{
+ {"south"}, {"south-west"},
+ {"west"}, {"north-west"},
+ {"north"}, {"north-east"},
+ {"east"}, {"south-east"},
+ }};
+ FString buf;
switch (v->ty)
{
@@ -136,7 +136,7 @@ void stringify(val_t *v, int within_op)
return;
case TYPE::DIR:
- buf = dirs[v->v.v_int];
+ buf = dirs[v->v.v_dir];
break;
case TYPE::ENTITY:
@@ -278,7 +278,10 @@ int fun_add(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
stringify(&args[1], 1);
/* Yes, we could speed this up. */
// ugh
- RESULTSTR = dumb_string::copys(ARGSTR(0).str() + ARGSTR(1).str());
+ MString m;
+ m += ARGSTR(0);
+ m += ARGSTR(1);
+ RESULTSTR = dumb_string::copys(FString(m));
result->ty = TYPE::STRING;
}
return 0;
@@ -351,7 +354,6 @@ int fun_gte(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
{
stringify(&args[0], 1);
stringify(&args[1], 1);
- using namespace operators;
RESULTINT = ARGSTR(0) >= ARGSTR(1);
}
else
@@ -370,7 +372,6 @@ int fun_gt(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
{
stringify(&args[0], 1);
stringify(&args[1], 1);
- using namespace operators;
RESULTINT = ARGSTR(0) > ARGSTR(1);
}
else
@@ -389,7 +390,6 @@ int fun_eq(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
{
stringify(&args[0], 1);
stringify(&args[1], 1);
- using namespace operators;
RESULTINT = ARGSTR(0) == ARGSTR(1);
}
else if (ARG_TYPE(0) == TYPE::DIR && ARG_TYPE(1) == TYPE::DIR)
@@ -652,7 +652,7 @@ int fun_name_of(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
{
if (ARG_TYPE(0) == TYPE::ENTITY)
{
- RESULTSTR = dumb_string::copy(show_entity(ARGENTITY(0)));
+ RESULTSTR = dumb_string::copys(show_entity(ARGENTITY(0)));
return 0;
}
else if (ARG_TYPE(0) == TYPE::SPELL)
@@ -745,7 +745,7 @@ magic_find_item(const_array<val_t> args, int index, struct item *item_, int *sta
if (ARG_TYPE(index) == TYPE::INT)
item_data = itemdb_exists(ARGINT(index));
else if (ARG_TYPE(index) == TYPE::STRING)
- item_data = itemdb_searchname(ARGSTR(index).c_str());
+ item_data = itemdb_searchname(stringish<ItemName>(ARGSTR(index)));
else
return -1;
@@ -874,14 +874,16 @@ int fun_failed(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
static
int fun_npc(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
{
- RESULTENTITY = npc_name2id(ARGSTR(0).c_str());
+ NpcName name = stringish<NpcName>(ARGSTR(0));
+ RESULTENTITY = npc_name2id(name);
return RESULTENTITY == NULL;
}
static
int fun_pc(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
{
- RESULTENTITY = map_nick2sd(ARGSTR(0).c_str());
+ CharName name = stringish<CharName>(ARGSTR(0));
+ RESULTENTITY = map_nick2sd(name);
return RESULTENTITY == NULL;
}
@@ -913,7 +915,7 @@ int fun_rdistance(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
static
int fun_anchor(dumb_ptr<env_t> env, val_t *result, const_array<val_t> args)
{
- dumb_ptr<teleport_anchor_t> anchor = magic_find_anchor(ARGSTR(0).str());
+ dumb_ptr<teleport_anchor_t> anchor = magic_find_anchor(ARGSTR(0));
if (!anchor)
return 1;
@@ -997,12 +999,12 @@ static
int fun_read_script_int(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
{
dumb_ptr<block_list> subject_p = ARGENTITY(0);
- dumb_string var_name = ARGSTR(1);
+ VarName var_name = stringish<VarName>(ARGSTR(1));
if (subject_p->bl_type != BL::PC)
return 1;
- RESULTINT = pc_readglobalreg(subject_p->as_player(), var_name.c_str());
+ RESULTINT = pc_readglobalreg(subject_p->as_player(), var_name);
return 0;
}
@@ -1055,13 +1057,6 @@ int fun_element_level(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
}
static
-int fun_index(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
-{
- RESULTINT = ARGSPELL(0)->index_;
- return 0;
-}
-
-static
int fun_is_exterior(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
{
#warning "Evil assumptions!"
@@ -1136,7 +1131,7 @@ static
int fun_map_nr(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
{
#warning "Evil assumptions!"
- const char *mapname = ARGLOCATION(0).m->name_;
+ MapName mapname = ARGLOCATION(0).m->name_;
RESULTINT = ((mapname[0] - '0') * 100)
+ ((mapname[1] - '0') * 10) + ((mapname[2] - '0'));
@@ -1221,123 +1216,93 @@ int fun_extract_healer_xp(dumb_ptr<env_t>, val_t *result, const_array<val_t> arg
return 0;
}
-static
-fun_t functions[] =
-{
- {"+", "..", '.', fun_add},
- {"-", "ii", 'i', fun_sub},
- {"*", "ii", 'i', fun_mul},
- {"/", "ii", 'i', fun_div},
- {"%", "ii", 'i', fun_mod},
- {"||", "ii", 'i', fun_or},
- {"&&", "ii", 'i', fun_and},
- {">", "..", 'i', fun_gt},
- {">=", "..", 'i', fun_gte},
- {"=", "..", 'i', fun_eq},
- {"|", "..", 'i', fun_bitor},
- {"&", "ii", 'i', fun_bitand},
- {"^", "ii", 'i', fun_bitxor},
- {"<<", "ii", 'i', fun_bitshl},
- {">>", "ii", 'i', fun_bitshr},
- {"not", "i", 'i', fun_not},
- {"neg", "i", 'i', fun_neg},
- {"max", "ii", 'i', fun_max},
- {"min", "ii", 'i', fun_min},
- {"is_in", "la", 'i', fun_is_in},
- {"if_then_else", "i__", '_', fun_if_then_else},
- {"skill", "ei", 'i', fun_skill},
- {"str", "e", 'i', fun_get_str},
- {"agi", "e", 'i', fun_get_agi},
- {"vit", "e", 'i', fun_get_vit},
- {"dex", "e", 'i', fun_get_dex},
- {"luk", "e", 'i', fun_get_luk},
- {"int", "e", 'i', fun_get_int},
- {"level", "e", 'i', fun_get_lv},
- {"mdef", "e", 'i', fun_get_mdef},
- {"def", "e", 'i', fun_get_def},
- {"hp", "e", 'i', fun_get_hp},
- {"max_hp", "e", 'i', fun_get_max_hp},
- {"sp", "e", 'i', fun_get_sp},
- {"max_sp", "e", 'i', fun_get_max_sp},
- {"dir", "e", 'd', fun_get_dir},
- {"name_of", ".", 's', fun_name_of},
- {"mob_id", "e", 'i', fun_mob_id},
- {"location", "e", 'l', fun_location},
- {"random", "i", 'i', fun_random},
- {"random_dir", "i", 'd', fun_random_dir},
- {"hash_entity", "e", 'i', fun_hash_entity},
- {"is_married", "e", 'i', fun_is_married},
- {"partner", "e", 'e', fun_partner},
- {"awayfrom", "ldi", 'l', fun_awayfrom},
- {"failed", "_", 'i', fun_failed},
- {"pc", "s", 'e', fun_pc},
- {"npc", "s", 'e', fun_npc},
- {"distance", "ll", 'i', fun_distance},
- {"rdistance", "ll", 'i', fun_rdistance},
- {"anchor", "s", 'a', fun_anchor},
- {"random_location", "a", 'l', fun_pick_location},
- {"script_int", "es", 'i', fun_read_script_int},
- {"rbox", "li", 'a', fun_rbox},
- {"count_item", "e.", 'i', fun_count_item},
- {"line_of_sight", "ll", 'i', fun_line_of_sight},
- {"running_status_update", "ei", 'i', fun_running_status_update},
- {"status_option", "ei", 'i', fun_status_option},
- {"element", "e", 'i', fun_element},
- {"element_level", "e", 'i', fun_element_level},
- {"has_shroud", "e", 'i', fun_has_shroud},
- {"is_equipped", "e.", 'i', fun_is_equipped},
- {"spell_index", "S", 'i', fun_index},
- {"is_exterior", "l", 'i', fun_is_exterior},
- {"contains_string", "ss", 'i', fun_contains_string},
- {"strstr", "ss", 'i', fun_strstr},
- {"strlen", "s", 'i', fun_strlen},
- {"substr", "sii", 's', fun_substr},
- {"sqrt", "i", 'i', fun_sqrt},
- {"map_level", "l", 'i', fun_map_level},
- {"map_nr", "l", 'i', fun_map_nr},
- {"dir_towards", "lli", 'd', fun_dir_towards},
- {"is_dead", "e", 'i', fun_is_dead},
- {"is_pc", "e", 'i', fun_is_pc},
- {"extract_healer_experience", "ei", 'i', fun_extract_healer_xp},
- {NULL, NULL, '.', NULL}
+#define MAGIC_FUNCTION(name, args, ret, impl) {{name}, {{name}, {args}, ret, impl}}
+#define MAGIC_FUNCTION1(name, args, ret) MAGIC_FUNCTION(#name, args, ret, fun_##name)
+static
+std::map<ZString, fun_t> functions =
+{
+ MAGIC_FUNCTION("+", "..", '.', fun_add),
+ MAGIC_FUNCTION("-", "ii", 'i', fun_sub),
+ MAGIC_FUNCTION("*", "ii", 'i', fun_mul),
+ MAGIC_FUNCTION("/", "ii", 'i', fun_div),
+ MAGIC_FUNCTION("%", "ii", 'i', fun_mod),
+ MAGIC_FUNCTION("||", "ii", 'i', fun_or),
+ MAGIC_FUNCTION("&&", "ii", 'i', fun_and),
+ MAGIC_FUNCTION(">", "..", 'i', fun_gt),
+ MAGIC_FUNCTION(">=", "..", 'i', fun_gte),
+ MAGIC_FUNCTION("=", "..", 'i', fun_eq),
+ MAGIC_FUNCTION("|", "..", 'i', fun_bitor),
+ MAGIC_FUNCTION("&", "ii", 'i', fun_bitand),
+ MAGIC_FUNCTION("^", "ii", 'i', fun_bitxor),
+ MAGIC_FUNCTION("<<", "ii", 'i', fun_bitshl),
+ MAGIC_FUNCTION(">>", "ii", 'i', fun_bitshr),
+ MAGIC_FUNCTION1(not, "i", 'i'),
+ MAGIC_FUNCTION1(neg, "i", 'i'),
+ MAGIC_FUNCTION1(max, "ii", 'i'),
+ MAGIC_FUNCTION1(min, "ii", 'i'),
+ MAGIC_FUNCTION1(is_in, "la", 'i'),
+ MAGIC_FUNCTION1(if_then_else, "i__", '_'),
+ MAGIC_FUNCTION1(skill, "ei", 'i'),
+ MAGIC_FUNCTION("str", "e", 'i', fun_get_str),
+ MAGIC_FUNCTION("agi", "e", 'i', fun_get_agi),
+ MAGIC_FUNCTION("vit", "e", 'i', fun_get_vit),
+ MAGIC_FUNCTION("dex", "e", 'i', fun_get_dex),
+ MAGIC_FUNCTION("luk", "e", 'i', fun_get_luk),
+ MAGIC_FUNCTION("int", "e", 'i', fun_get_int),
+ MAGIC_FUNCTION("level", "e", 'i', fun_get_lv),
+ MAGIC_FUNCTION("mdef", "e", 'i', fun_get_mdef),
+ MAGIC_FUNCTION("def", "e", 'i', fun_get_def),
+ MAGIC_FUNCTION("hp", "e", 'i', fun_get_hp),
+ MAGIC_FUNCTION("max_hp", "e", 'i', fun_get_max_hp),
+ MAGIC_FUNCTION("sp", "e", 'i', fun_get_sp),
+ MAGIC_FUNCTION("max_sp", "e", 'i', fun_get_max_sp),
+ MAGIC_FUNCTION("dir", "e", 'd', fun_get_dir),
+ MAGIC_FUNCTION1(name_of, ".", 's'),
+ MAGIC_FUNCTION1(mob_id, "e", 'i'),
+ MAGIC_FUNCTION1(location, "e", 'l'),
+ MAGIC_FUNCTION1(random, "i", 'i'),
+ MAGIC_FUNCTION1(random_dir, "i", 'd'),
+ MAGIC_FUNCTION1(hash_entity, "e", 'i'),
+ MAGIC_FUNCTION1(is_married, "e", 'i'),
+ MAGIC_FUNCTION1(partner, "e", 'e'),
+ MAGIC_FUNCTION1(awayfrom, "ldi", 'l'),
+ MAGIC_FUNCTION1(failed, "_", 'i'),
+ MAGIC_FUNCTION1(pc, "s", 'e'),
+ MAGIC_FUNCTION1(npc, "s", 'e'),
+ MAGIC_FUNCTION1(distance, "ll", 'i'),
+ MAGIC_FUNCTION1(rdistance, "ll", 'i'),
+ MAGIC_FUNCTION1(anchor, "s", 'a'),
+ MAGIC_FUNCTION("random_location", "a", 'l', fun_pick_location),
+ MAGIC_FUNCTION("script_int", "es", 'i', fun_read_script_int),
+ MAGIC_FUNCTION1(rbox, "li", 'a'),
+ MAGIC_FUNCTION1(count_item, "e.", 'i'),
+ MAGIC_FUNCTION1(line_of_sight, "ll", 'i'),
+ MAGIC_FUNCTION1(running_status_update, "ei", 'i'),
+ MAGIC_FUNCTION1(status_option, "ei", 'i'),
+ MAGIC_FUNCTION1(element, "e", 'i'),
+ MAGIC_FUNCTION1(element_level, "e", 'i'),
+ MAGIC_FUNCTION1(has_shroud, "e", 'i'),
+ MAGIC_FUNCTION1(is_equipped, "e.", 'i'),
+ MAGIC_FUNCTION1(is_exterior, "l", 'i'),
+ MAGIC_FUNCTION1(contains_string, "ss", 'i'),
+ MAGIC_FUNCTION1(strstr, "ss", 'i'),
+ MAGIC_FUNCTION1(strlen, "s", 'i'),
+ MAGIC_FUNCTION1(substr, "sii", 's'),
+ MAGIC_FUNCTION1(sqrt, "i", 'i'),
+ MAGIC_FUNCTION1(map_level, "l", 'i'),
+ MAGIC_FUNCTION1(map_nr, "l", 'i'),
+ MAGIC_FUNCTION1(dir_towards, "lli", 'd'),
+ MAGIC_FUNCTION1(is_dead, "e", 'i'),
+ MAGIC_FUNCTION1(is_pc, "e", 'i'),
+ MAGIC_FUNCTION("extract_healer_experience", "ei", 'i', fun_extract_healer_xp),
};
-static
-int functions_are_sorted = 0;
-
-static __attribute__((deprecated))
-int compare_fun(const void *lhs, const void *rhs)
-{
- return strcmp(static_cast<const fun_t *>(lhs)->name, static_cast<const fun_t *>(rhs)->name);
-}
-
-fun_t *magic_get_fun(const std::string& name, int *index)
+fun_t *magic_get_fun(ZString name)
{
- static
- int functions_nr;
- fun_t *result;
- fun_t key;
-
- if (!functions_are_sorted)
- {
- fun_t *it = functions;
-
- while (it->name)
- ++it;
- functions_nr = it - functions;
-
- qsort(functions, functions_nr, sizeof(fun_t), compare_fun);
- functions_are_sorted = 1;
- }
-
- key.name = name.c_str();
- result = static_cast<fun_t *>(bsearch(&key, functions, functions_nr, sizeof(fun_t),
- compare_fun));
-
- if (result && index)
- *index = result - functions;
-
- return result;
+ auto it = functions.find(name);
+ if (it == functions.end())
+ return nullptr;
+ return &it->second;
}
// 1 on failure
@@ -1352,7 +1317,8 @@ int eval_location(dumb_ptr<env_t> env, location_t *dest, e_location_t *expr)
if (CHECK_TYPE(&m, TYPE::STRING)
&& CHECK_TYPE(&x, TYPE::INT) && CHECK_TYPE(&y, TYPE::INT))
{
- map_local *map_id = map_mapname2mapid(m.v.v_string.c_str());
+ MapName name = VString<15>(ZString(m.v.v_string));
+ map_local *map_id = map_mapname2mapid(name);
magic_clear_var(&m);
if (!map_id)
return 1;
@@ -1509,8 +1475,8 @@ TYPE type_key(char ty_key)
}
}
-int magic_signature_check(const char *opname, const char *funname, const char *signature,
- int args_nr, val_t *args, int line, int column)
+int magic_signature_check(ZString opname, ZString funname, ZString signature,
+ int args_nr, val_t *args, int line, int column)
{
int i;
for (i = 0; i < args_nr; i++)
@@ -1620,7 +1586,7 @@ void magic_eval(dumb_ptr<env_t> env, val_t *dest, dumb_ptr<expr_t> expr)
val_t arguments[MAX_ARGS];
int args_nr = expr->e.e_funapp.args_nr;
int i;
- fun_t *f = functions + expr->e.e_funapp.id;
+ fun_t *f = expr->e.e_funapp.funp;
for (i = 0; i < args_nr; ++i)
magic_eval(env, &arguments[i], expr->e.e_funapp.args[i]);
@@ -1705,13 +1671,13 @@ int magic_eval_int(dumb_ptr<env_t> env, dumb_ptr<expr_t> expr)
return result.v.v_int;
}
-std::string magic_eval_str(dumb_ptr<env_t> env, dumb_ptr<expr_t> expr)
+FString magic_eval_str(dumb_ptr<env_t> env, dumb_ptr<expr_t> expr)
{
val_t result;
magic_eval(env, &result, expr);
if (result.ty == TYPE::FAIL || result.ty == TYPE::UNDEF)
- return "?";
+ return {"?"};
stringify(&result, 0);
diff --git a/src/map/magic-expr.hpp b/src/map/magic-expr.hpp
index 7f3e1e1..2bffcbc 100644
--- a/src/map/magic-expr.hpp
+++ b/src/map/magic-expr.hpp
@@ -16,34 +16,34 @@
* . : any, except for fail/undef
* _ : any, including fail, but not undef
*/
-typedef struct fun
+struct fun_t
{
- const char *name;
- const char *signature;
+ ZString name;
+ ZString signature;
char ret_ty;
int (*fun)(dumb_ptr<env_t> env, val_t *result, const_array<val_t> arga);
-} fun_t;
+};
-typedef struct op
+struct op_t
{
- const char *name;
- const char *signature;
+ ZString name;
+ ZString signature;
int (*op)(dumb_ptr<env_t> env, const_array<val_t> arga);
-} op_t;
+};
/**
* Retrieves a function by name
* @param name The name to look up
- * @return A function of that name, or NULL, and a function index
+ * @return A function of that name, or NULL.
*/
-fun_t *magic_get_fun(const std::string& name, int *index);
+fun_t *magic_get_fun(ZString name);
/**
* Retrieves an operation by name
* @param name The name to look up
* @return An operation of that name, or NULL, and a function index
*/
-op_t *magic_get_op(const std::string& name, int *index);
+op_t *magic_get_op(ZString name);
/**
* Evaluates an expression and stores the result in `dest'
@@ -58,7 +58,7 @@ int magic_eval_int(dumb_ptr<env_t> env, dumb_ptr<expr_t> expr);
/**
* Evaluates an expression and coerces the result into a string
*/
-std::string magic_eval_str(dumb_ptr<env_t> env, dumb_ptr<expr_t> expr);
+FString magic_eval_str(dumb_ptr<env_t> env, dumb_ptr<expr_t> expr);
dumb_ptr<expr_t> magic_new_expr(EXPR ty);
diff --git a/src/map/magic-interpreter-base.cpp b/src/map/magic-interpreter-base.cpp
index 3d0c853..1a80617 100644
--- a/src/map/magic-interpreter-base.cpp
+++ b/src/map/magic-interpreter-base.cpp
@@ -62,16 +62,16 @@ void set_spell SETTER(dumb_ptr<spell_t>, TYPE::SPELL, v_spell)
magic_conf_t magic_conf; /* Global magic conf */
env_t magic_default_env = { &magic_conf, NULL };
-const char *magic_find_invocation(const std::string& spellname)
+FString magic_find_invocation(XString spellname)
{
auto it = magic_conf.spells_by_name.find(spellname);
if (it != magic_conf.spells_by_name.end())
- return it->second->invocation.c_str();
+ return it->second->invocation;
- return NULL;
+ return FString();
}
-dumb_ptr<spell_t> magic_find_spell(const std::string& invocation)
+dumb_ptr<spell_t> magic_find_spell(XString invocation)
{
auto it = magic_conf.spells_by_invocation.find(invocation);
if (it != magic_conf.spells_by_invocation.end())
@@ -84,17 +84,17 @@ dumb_ptr<spell_t> magic_find_spell(const std::string& invocation)
/* Spell anchors */
/* -------------------------------------------------------------------------------- */
-const char *magic_find_anchor_invocation(const std::string& anchor_name)
+FString magic_find_anchor_invocation(XString anchor_name)
{
auto it = magic_conf.anchors_by_name.find(anchor_name);
if (it != magic_conf.anchors_by_name.end())
- return it->second->invocation.c_str();
+ return it->second->invocation;
- return NULL;
+ return FString();
}
-dumb_ptr<teleport_anchor_t> magic_find_anchor(const std::string& name)
+dumb_ptr<teleport_anchor_t> magic_find_anchor(XString name)
{
auto it = magic_conf.anchors_by_invocation.find(name);
if (it != magic_conf.anchors_by_invocation.end())
@@ -137,7 +137,7 @@ void magic_free_env(dumb_ptr<env_t> env)
}
dumb_ptr<env_t> spell_create_env(magic_conf_t *conf, dumb_ptr<spell_t> spell,
- dumb_ptr<map_session_data> caster, int spellpower, const_string param)
+ dumb_ptr<map_session_data> caster, int spellpower, XString param)
{
dumb_ptr<env_t> env = alloc_env(conf);
@@ -145,12 +145,13 @@ dumb_ptr<env_t> spell_create_env(magic_conf_t *conf, dumb_ptr<spell_t> spell,
{
case SPELLARG::STRING:
- set_env_string(spell->arg, dumb_string::copyc(param));
+ set_env_string(spell->arg, dumb_string::copys(param));
break;
case SPELLARG::PC:
{
- dumb_ptr<map_session_data> subject = map_nick2sd(std::string(param.begin(), param.end()).c_str());
+ CharName name = stringish<CharName>(param);
+ dumb_ptr<map_session_data> subject = map_nick2sd(name);
if (!subject)
subject = caster;
set_env_entity(spell->arg, subject);
diff --git a/src/map/magic-interpreter-parser.ypp b/src/map/magic-interpreter-parser.ypp
index a392bc7..e6d69b4 100644
--- a/src/map/magic-interpreter-parser.ypp
+++ b/src/map/magic-interpreter-parser.ypp
@@ -19,21 +19,25 @@
// I still don't get why this is necessary.
#define YYLEX_PARAM 0, 0
+// can't use src/warnings.hpp in generated code
#pragma GCC diagnostic warning "-Wall"
#pragma GCC diagnostic warning "-Wextra"
#pragma GCC diagnostic warning "-Wformat"
+#ifndef __clang__
+#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
+#endif
static
-size_t intern_id(const_string id_name);
+size_t intern_id(ZString id_name);
static
-dumb_ptr<expr_t> fun_expr(const std::string& name, const_array<dumb_ptr<expr_t>> argv, int line, int column);
+dumb_ptr<expr_t> fun_expr(FString name, const_array<dumb_ptr<expr_t>> argv, int line, int column);
static
dumb_ptr<expr_t> dot_expr(dumb_ptr<expr_t> lhs, int id);
static
-void BIN_EXPR(dumb_ptr<expr_t> & x, const std::string& name, dumb_ptr<expr_t> arg1, dumb_ptr<expr_t> arg2, int line, int column)
+void BIN_EXPR(dumb_ptr<expr_t>& x, FString name, dumb_ptr<expr_t> arg1, dumb_ptr<expr_t> arg2, int line, int column)
{
dumb_ptr<expr_t> e[2];
e[0] = arg1;
@@ -72,7 +76,7 @@ static
void add_teleport_anchor(dumb_ptr<teleport_anchor_t> anchor, int line_nr);
static
-dumb_ptr<effect_t> op_effect(const std::string& name, const_array<dumb_ptr<expr_t>> argv, int line, int column);
+dumb_ptr<effect_t> op_effect(FString name, const_array<dumb_ptr<expr_t>> argv, int line, int column);
// in magic-interpreter-lexer.cpp
int magic_frontend_lex(YYSTYPE *, YYLTYPE *);
@@ -81,13 +85,13 @@ static
void install_proc(dumb_ptr<proc_t> proc);
static
-dumb_ptr<effect_t> call_proc(const_string name, dumb_ptr<std::vector<dumb_ptr<expr_t>>> argvp, int line_nr, int column);
+dumb_ptr<effect_t> call_proc(ZString name, dumb_ptr<std::vector<dumb_ptr<expr_t>>> argvp, int line_nr, int column);
static
-void bind_constant(const std::string& name, val_t *val, int line_nr);
+void bind_constant(FString name, val_t *val, int line_nr);
static
-val_t *find_constant(const std::string& name);
+val_t *find_constant(FString name);
} // %code
@@ -919,7 +923,7 @@ item_name
: STRING
{
- struct item_data *item = itemdb_searchname($1.c_str());
+ struct item_data *item = itemdb_searchname(stringish<ItemName>(ZString($1)));
if (!item)
{
fail(@1.first_line, @1.first_column, "Unknown item `%s'\n", $1.c_str());
@@ -1066,7 +1070,7 @@ effect
| SCRIPT_DATA
{
$$ = new_effect(EFFECT::SCRIPT);
- $$->e.e_script = dumb_ptr<const ScriptBuffer>(parse_script($1.c_str(), @1.first_line).release());
+ $$->e.e_script = dumb_ptr<const ScriptBuffer>(parse_script(ZString($1), @1.first_line).release());
$1.delete_();
if ($$->e.e_script == NULL)
fail(@1.first_line, @1.first_column, "Failed to compile script\n");
@@ -1098,9 +1102,8 @@ effect_list
%%
-size_t intern_id(const_string id_name_)
+size_t intern_id(ZString id_name)
{
- std::string id_name(id_name_.begin(), id_name_.end());
size_t i;
for (i = 0; i < magic_conf.varv.size(); i++)
if (id_name == magic_conf.varv[i].name)
@@ -1173,18 +1176,17 @@ dumb_ptr<expr_t> dot_expr(dumb_ptr<expr_t> expr, int id)
return retval;
}
-dumb_ptr<expr_t> fun_expr(const std::string& name, const_array<dumb_ptr<expr_t>> argv, int line, int column)
+dumb_ptr<expr_t> fun_expr(FString name, const_array<dumb_ptr<expr_t>> argv, int line, int column)
{
- int id;
dumb_ptr<expr_t> expr;
- fun_t *fun = magic_get_fun(name, &id);
+ fun_t *fun = magic_get_fun(name);
if (!fun)
fail(line, column, "Unknown function `%s'\n", name.c_str());
- else if (strlen(fun->signature) != argv.size())
+ else if (fun->signature.size() != argv.size())
{
fail(line, column, "Incorrect number of arguments to function `%s': Expected %zu, found %zu\n",
- name.c_str(), strlen(fun->signature), argv.size());
+ name.c_str(), fun->signature.size(), argv.size());
fun = NULL;
}
@@ -1193,7 +1195,7 @@ dumb_ptr<expr_t> fun_expr(const std::string& name, const_array<dumb_ptr<expr_t>>
expr = magic_new_expr(EXPR::FUNAPP);
expr->e.e_funapp.line_nr = line;
expr->e.e_funapp.column = column;
- expr->e.e_funapp.id = id;
+ expr->e.e_funapp.funp = fun;
assert (argv.size() <= MAX_ARGS);
expr->e.e_funapp.args_nr = argv.size();
@@ -1212,10 +1214,7 @@ dumb_ptr<expr_t> fun_expr(const std::string& name, const_array<dumb_ptr<expr_t>>
dumb_ptr<spell_t> new_spell(dumb_ptr<spellguard_t> guard)
{
- static int spell_counter = 0;
-
auto retval = dumb_ptr<spell_t>::make();
- retval->index_ = ++spell_counter;
retval->spellguard = guard;
return retval;
}
@@ -1288,18 +1287,17 @@ dumb_ptr<effect_t> set_effect_continuation(dumb_ptr<effect_t> src, dumb_ptr<effe
return retval;
}
-dumb_ptr<effect_t> op_effect(const std::string& name, const_array<dumb_ptr<expr_t>> argv, int line, int column)
+dumb_ptr<effect_t> op_effect(FString name, const_array<dumb_ptr<expr_t>> argv, int line, int column)
{
- int id;
dumb_ptr<effect_t> effect;
- op_t *op = magic_get_op(name, &id);
+ op_t *op = magic_get_op(name);
if (!op)
fail(line, column, "Unknown operation `%s'\n", name.c_str());
- else if (strlen(op->signature) != argv.size())
+ else if (op->signature.size() != argv.size())
{
fail(line, column, "Incorrect number of arguments to operation `%s': Expected %zu, found %zu\n",
- name.c_str(), strlen(op->signature), argv.size());
+ name.c_str(), op->signature.size(), argv.size());
op = NULL;
}
@@ -1308,7 +1306,7 @@ dumb_ptr<effect_t> op_effect(const std::string& name, const_array<dumb_ptr<expr_
effect = new_effect(EFFECT::OP);
effect->e.e_op.line_nr = line;
effect->e.e_op.column = column;
- effect->e.e_op.id = id;
+ effect->e.e_op.opp = op;
assert (argv.size() <= MAX_ARGS);
effect->e.e_op.args_nr = argv.size();
@@ -1321,7 +1319,7 @@ dumb_ptr<effect_t> op_effect(const std::string& name, const_array<dumb_ptr<expr_
}
-std::map<std::string, proc_t> procs;
+std::map<FString, proc_t> procs;
// I think this was a memory leak (or undefined behavior)
void install_proc(dumb_ptr<proc_t> proc)
@@ -1329,9 +1327,8 @@ void install_proc(dumb_ptr<proc_t> proc)
procs.insert({proc->name, std::move(*proc)});
}
-dumb_ptr<effect_t> call_proc(const_string name_, dumb_ptr<std::vector<dumb_ptr<expr_t>>> argvp, int line_nr, int column)
+dumb_ptr<effect_t> call_proc(ZString name, dumb_ptr<std::vector<dumb_ptr<expr_t>>> argvp, int line_nr, int column)
{
- std::string name(name_.begin(), name_.end());
auto pi = procs.find(name);
if (pi == procs.end())
{
@@ -1355,9 +1352,9 @@ dumb_ptr<effect_t> call_proc(const_string name_, dumb_ptr<std::vector<dumb_ptr<e
return retval;
}
-std::map<std::string, val_t> const_defm;
+std::map<FString, val_t> const_defm;
-void bind_constant(const std::string& name, val_t *val, int line_nr)
+void bind_constant(FString name, val_t *val, int line_nr)
{
if (!const_defm.insert({name, *val}).second)
{
@@ -1365,7 +1362,7 @@ void bind_constant(const std::string& name, val_t *val, int line_nr)
}
}
-val_t *find_constant(const std::string& name)
+val_t *find_constant(FString name)
{
auto it = const_defm.find(name);
if (it != const_defm.end())
@@ -1379,7 +1376,7 @@ static
int error_flag;
inline
-void INTERN_ASSERT(const char *name, int id)
+void INTERN_ASSERT(ZString name, int id)
{
int zid = intern_id(name);
if (zid != id)
diff --git a/src/map/magic-interpreter.hpp b/src/map/magic-interpreter.hpp
index 9b60d998..13c91e9 100644
--- a/src/map/magic-interpreter.hpp
+++ b/src/map/magic-interpreter.hpp
@@ -10,6 +10,8 @@
#include "script.hpp"
#include "skill.t.hpp"
+struct fun_t;
+struct op_t;
struct expr_t;
struct val_t;
struct location_t;
@@ -118,7 +120,8 @@ struct expr_t
e_area_t e_area;
struct
{
- int id, line_nr, column;
+ fun_t *funp;
+ int line_nr, column;
int args_nr;
dumb_ptr<expr_t> args[MAX_ARGS];
} e_funapp;
@@ -169,7 +172,7 @@ struct effect_t
dumb_ptr<const ScriptBuffer> e_script;
struct
{
- int id;
+ op_t *opp;
int args_nr;
int line_nr, column;
dumb_ptr<expr_t> args[MAX_ARGS];
@@ -238,9 +241,8 @@ struct letdef_t
struct spell_t
{
- std::string name;
- std::string invocation;
- int index_; // Relative location in the definitions file
+ FString name;
+ FString invocation;
SPELL_FLAG flags;
int arg;
SPELLARG spellarg_ty;
@@ -256,8 +258,8 @@ struct spell_t
struct teleport_anchor_t
{
- std::string name;
- std::string invocation;
+ FString name;
+ FString invocation;
dumb_ptr<expr_t> location;
};
@@ -269,15 +271,15 @@ struct magic_conf_t
{
struct mcvar
{
- std::string name;
+ FString name;
val_t val;
};
// This should probably be done by a dedicated "intern pool" class
std::vector<mcvar> varv;
- std::map<std::string, dumb_ptr<spell_t>> spells_by_name, spells_by_invocation;
+ std::map<FString, dumb_ptr<spell_t>> spells_by_name, spells_by_invocation;
- std::map<std::string, dumb_ptr<teleport_anchor_t>> anchors_by_name, anchors_by_invocation;
+ std::map<FString, dumb_ptr<teleport_anchor_t>> anchors_by_name, anchors_by_invocation;
};
/* Execution environment */
@@ -390,10 +392,10 @@ extern env_t magic_default_env; /* Fake default environment */
*/
void magic_add_component(dumb_ptr<component_t> *component_holder, int id, int count);
-dumb_ptr<teleport_anchor_t> magic_find_anchor(const std::string& name);
+dumb_ptr<teleport_anchor_t> magic_find_anchor(XString name);
dumb_ptr<env_t> spell_create_env(magic_conf_t *conf, dumb_ptr<spell_t> spell,
- dumb_ptr<map_session_data> caster, int spellpower, const_string param);
+ dumb_ptr<map_session_data> caster, int spellpower, XString param);
void magic_free_env(dumb_ptr<env_t> env);
@@ -419,7 +421,7 @@ int spell_unbind(dumb_ptr<map_session_data> subject, dumb_ptr<invocation> invoca
*/
dumb_ptr<invocation> spell_clone_effect(dumb_ptr<invocation> source);
-dumb_ptr<spell_t> magic_find_spell(const std::string& invocation);
+dumb_ptr<spell_t> magic_find_spell(XString invocation);
/* The following is used only by the parser: */
struct args_rec_t
@@ -429,7 +431,7 @@ struct args_rec_t
struct proc_t
{
- std::string name;
+ FString name;
std::vector<int> argv;
dumb_ptr<effect_t> body;
diff --git a/src/map/magic-stmt.cpp b/src/map/magic-stmt.cpp
index 5d732c8..6b013ab 100644
--- a/src/map/magic-stmt.cpp
+++ b/src/map/magic-stmt.cpp
@@ -276,7 +276,7 @@ dumb_ptr<npc_data> local_spell_effect(map_local *m, int x, int y, int effect,
/* 1 minute should be enough for all interesting spell effects, I hope */
std::chrono::seconds delay = std::chrono::seconds(30);
dumb_ptr<npc_data> effect_npc = npc_spawn_text(m, x, y,
- INVISIBLE_NPC, "", "?");
+ INVISIBLE_NPC, NpcName(), "?");
int effect_npc_id = effect_npc->bl_id;
entity_effect(effect_npc, effect, tdelay);
@@ -415,8 +415,9 @@ int op_messenger_npc(dumb_ptr<env_t>, const_array<val_t> args)
dumb_ptr<npc_data> npc;
location_t *loc = &ARGLOCATION(0);
+ NpcName npcname = stringish<NpcName>(ARGSTR(2));
npc = npc_spawn_text(loc->m, loc->x, loc->y,
- ARGINT(1), ARGSTR(2).c_str(), ARGSTR(3).c_str());
+ ARGINT(1), npcname, ARGSTR(3));
Timer(gettick() + static_cast<interval_t>(ARGINT(4)),
std::bind(timer_callback_kill_npc, ph::_1, ph::_2,
@@ -446,13 +447,13 @@ void entity_warp(dumb_ptr<block_list> target, map_local *destm, int destx, int d
pc_touch_all_relevant_npcs(character);
// Note that touching NPCs may have triggered warping and thereby updated x and y:
- const char *map_name = character->bl_m->name_;
+ MapName map_name = character->bl_m->name_;
// Warp part #1: update relevant data, interrupt trading etc.:
pc_setpos(character, map_name, character->bl_x, character->bl_y, BeingRemoveWhy::GONE);
// Warp part #2: now notify the client
clif_changemap(character, map_name,
- character->bl_x, character->bl_y);
+ character->bl_x, character->bl_y);
break;
}
case BL::MOB:
@@ -688,8 +689,8 @@ int op_spawn(dumb_ptr<env_t>, const_array<val_t> args)
int mob_id;
dumb_ptr<mob_data> mob;
- mob_id = mob_once_spawn(owner, loc.m->name_, loc.x, loc.y, "--ja--", // Is that needed?
- monster_id, 1, "");
+ mob_id = mob_once_spawn(owner, loc.m->name_, loc.x, loc.y, JAPANESE_NAME, // Is that needed?
+ monster_id, 1, NpcEvent());
mob = map_id_as_mob(mob_id);
@@ -823,7 +824,8 @@ int op_set_script_variable(dumb_ptr<env_t>, const_array<val_t> args)
if (!c)
return 1;
- pc_setglobalreg(c, ARGSTR(1).c_str(), ARGINT(2));
+ VarName varname = stringish<VarName>(ARGSTR(1));
+ pc_setglobalreg(c, varname, ARGINT(2));
return 0;
}
@@ -893,73 +895,43 @@ int op_gain_exp(dumb_ptr<env_t>, const_array<val_t> args)
return 0;
}
+#define MAGIC_OPERATION(name, args, impl) {{name}, {{name}, {args}, impl}}
+#define MAGIC_OPERATION1(name, args) MAGIC_OPERATION(#name, args, op_##name)
static
-op_t operations[] =
-{
- {"sfx", ".ii", op_sfx},
- {"instaheal", "eii", op_instaheal},
- {"itemheal", "eii", op_itemheal},
- {"shroud", "ei", op_shroud},
- {"unshroud", "e", op_reveal},
- {"message", "es", op_message},
- {"messenger_npc", "lissi", op_messenger_npc},
- {"move", "ed", op_move},
- {"warp", "el", op_warp},
- {"banish", "e", op_banish},
- {"status_change", "eiiiiii", op_status_change},
- {"stop_status_change", "ei", op_stop_status_change},
- {"override_attack", "eiiiiii", op_override_attack},
- {"create_item", "e.i", op_create_item},
- {"aggravate", "eie", op_aggravate},
- {"spawn", "aeiiii", op_spawn},
- {"injure", "eeii", op_injure},
- {"emote", "ei", op_emote},
- {"set_script_variable", "esi", op_set_script_variable},
- {"set_hair_colour", "ei", op_set_hair_colour},
- {"set_hair_style", "ei", op_set_hair_style},
- {"drop_item", "l.ii", op_drop_item_for},
- {"drop_item_for", "l.iiei", op_drop_item_for},
- {"gain_experience", "eiii", op_gain_exp},
- {NULL, NULL, NULL}
+std::map<ZString, op_t> operations =
+{
+ MAGIC_OPERATION1(sfx, ".ii"),
+ MAGIC_OPERATION1(instaheal, "eii"),
+ MAGIC_OPERATION1(itemheal, "eii"),
+ MAGIC_OPERATION1(shroud, "ei"),
+ MAGIC_OPERATION("unshroud", "e", op_reveal),
+ MAGIC_OPERATION1(message, "es"),
+ MAGIC_OPERATION1(messenger_npc, "lissi"),
+ MAGIC_OPERATION1(move, "ed"),
+ MAGIC_OPERATION1(warp, "el"),
+ MAGIC_OPERATION1(banish, "e"),
+ MAGIC_OPERATION1(status_change, "eiiiiii"),
+ MAGIC_OPERATION1(stop_status_change, "ei"),
+ MAGIC_OPERATION1(override_attack, "eiiiiii"),
+ MAGIC_OPERATION1(create_item, "e.i"),
+ MAGIC_OPERATION1(aggravate, "eie"),
+ MAGIC_OPERATION1(spawn, "aeiiii"),
+ MAGIC_OPERATION1(injure, "eeii"),
+ MAGIC_OPERATION1(emote, "ei"),
+ MAGIC_OPERATION1(set_script_variable, "esi"),
+ MAGIC_OPERATION1(set_hair_colour, "ei"),
+ MAGIC_OPERATION1(set_hair_style, "ei"),
+ MAGIC_OPERATION("drop_item", "l.ii", op_drop_item_for),
+ MAGIC_OPERATION1(drop_item_for, "l.iiei"),
+ MAGIC_OPERATION("gain_experience", "eiii", op_gain_exp),
};
-static
-int operations_sorted = 0;
-static
-int operation_count;
-
-static __attribute__((deprecated))
-int compare_operations(const void *lhs, const void *rhs)
-{
- return strcmp(static_cast<const op_t *>(lhs)->name, static_cast<const op_t *>(rhs)->name);
-}
-
-op_t *magic_get_op(const std::string& name, int *index)
+op_t *magic_get_op(ZString name)
{
- op_t key;
-
- if (!operations_sorted)
- {
- op_t *opc = operations;
-
- while (opc->name)
- ++opc;
-
- operation_count = opc - operations;
-
- qsort(operations, operation_count, sizeof(op_t),
- compare_operations);
- operations_sorted = 1;
- }
-
- key.name = name.c_str();
- op_t *op = static_cast<op_t *>(bsearch(&key, operations, operation_count, sizeof(op_t),
- compare_operations));
-
- if (op && index)
- *index = op - operations;
-
- return op;
+ auto it = operations.find(name);
+ if (it == operations.end())
+ return nullptr;
+ return &it->second;
}
void spell_effect_report_termination(int invocation_id, int bl_id,
@@ -1443,11 +1415,12 @@ interval_t spell_run(dumb_ptr<invocation> invocation_, int allow_delete)
if (caster)
{
dumb_ptr<env_t> env = invocation_->env;
- argrec_t arg[] =
+ ZString caster_name = (caster ? caster->status.name : CharName()).to__actual();
+ argrec_t arg[3] =
{
{"@target", env->VAR(VAR_TARGET).ty == TYPE::ENTITY ? 0 : env->VAR(VAR_TARGET).v.v_int},
{"@caster", invocation_->caster},
- {"@caster_name$", caster ? caster->status.name : ""},
+ {"@caster_name$", caster_name},
};
int message_recipient =
env->VAR(VAR_SCRIPTTARGET).ty ==
@@ -1461,14 +1434,13 @@ interval_t spell_run(dumb_ptr<invocation> invocation_, int allow_delete)
if (!invocation_->script_pos) // first time running this script?
clif_spawn_fake_npc_for_player(recipient,
- invocation_->bl_id);
+ invocation_->bl_id);
// We have to do this or otherwise the client won't think that it's
// dealing with an NPC
int newpos = run_script_l(
ScriptPointer(&*e->e.e_script, invocation_->script_pos),
- message_recipient,
- invocation_->bl_id,
+ message_recipient, invocation_->bl_id,
3, arg);
/* Returns the new script position, or -1 once the script is finished */
if (newpos != -1)
@@ -1492,7 +1464,7 @@ interval_t spell_run(dumb_ptr<invocation> invocation_, int allow_delete)
case EFFECT::OP:
{
- op_t *op = &operations[e->e.e_op.id];
+ op_t *op = e->e.e_op.opp;
val_t args[MAX_ARGS];
for (i = 0; i < e->e.e_op.args_nr; i++)
diff --git a/src/map/magic.cpp b/src/map/magic.cpp
index e225830..9c07dd1 100644
--- a/src/map/magic.cpp
+++ b/src/map/magic.cpp
@@ -12,31 +12,29 @@
/// Return a pair of strings, {spellname, parameter}
/// Parameter may be empty.
static
-std::pair<std::string, std::string> magic_tokenise(std::string src)
+std::pair<XString, XString> magic_tokenise(XString src)
{
- std::string retval = std::move(src);
- const std::string::iterator rvb = retval.begin(), rve = retval.end();
- std::string::iterator seeker = std::find(rvb, rve, ' ');
+ auto seeker = std::find(src.begin(), src.end(), ' ');
- if (seeker == retval.end())
+ if (seeker == src.end())
{
- return {retval, std::string()};
+ return {src, XString()};
}
else
{
- std::string rv1(rvb, seeker);
+ XString rv1 = src.xislice_h(seeker);
++seeker;
- while (seeker != rve && *seeker == ' ')
+ while (seeker != src.end() && *seeker == ' ')
++seeker;
// Note: this very well could be empty
- std::string rv2(seeker, rve);
+ XString rv2 = src.xislice_t(seeker);
return {rv1, rv2};
}
}
-int magic_message(dumb_ptr<map_session_data> caster, const std::string& source_invocation)
+int magic_message(dumb_ptr<map_session_data> caster, XString source_invocation)
{
if (pc_isdead(caster))
return 0;
@@ -52,8 +50,8 @@ int magic_message(dumb_ptr<map_session_data> caster, const std::string& source_i
magic_unshroud(caster);
auto pair = magic_tokenise(source_invocation);
- std::string spell_invocation = std::move(pair.first);
- std::string parameter = std::move(pair.second);
+ XString spell_invocation = pair.first;
+ XString parameter = pair.second;
dumb_ptr<spell_t> spell = magic_find_spell(spell_invocation);
diff --git a/src/map/magic.hpp b/src/map/magic.hpp
index cec5bf4..5b10367 100644
--- a/src/map/magic.hpp
+++ b/src/map/magic.hpp
@@ -21,7 +21,7 @@ struct invocation; /* Spell invocation */
* \return 1 or -1 if the input message was magic and was handled by this function, 0 otherwise. -1 is returned when the
* message should not be repeated.
*/
-int magic_message(dumb_ptr<map_session_data> caster, const std::string& source_invocation);
+int magic_message(dumb_ptr<map_session_data> caster, XString source_invocation);
/**
* Removes the shroud from a character
@@ -49,16 +49,16 @@ void do_init_magic(void);
/**
* Identifies the invocation used to trigger a spell
*
- * Returns NULL if not found
+ * Returns empty string if not found
*/
-const char *magic_find_invocation(const std::string& spellame);
+FString magic_find_invocation(XString spellname);
/**
* Identifies the invocation used to denote a teleport location
*
- * Returns NULL if not found
+ * Returns empty string if not found
*/
-const char *magic_find_anchor_invocation(const std::string& teleport_location);
+FString magic_find_anchor_invocation(XString teleport_location);
/**
* Execute a spell invocation and sets up timers to finish
diff --git a/src/map/map.cpp b/src/map/map.cpp
index fdae071..f2eefe5 100644
--- a/src/map/map.cpp
+++ b/src/map/map.cpp
@@ -15,6 +15,8 @@
#include "../common/core.hpp"
#include "../common/cxxstdio.hpp"
#include "../common/db.hpp"
+#include "../common/extract.hpp"
+#include "../common/io.hpp"
#include "../common/random2.hpp"
#include "../common/nullpo.hpp"
#include "../common/socket.hpp"
@@ -41,14 +43,14 @@
DMap<int, dumb_ptr<block_list>> id_db;
-UPMap<std::string, map_abstract> maps_db;
+UPMap<MapName, map_abstract> maps_db;
static
-DMap<std::string, dumb_ptr<map_session_data>> nick_db;
+DMap<CharName, dumb_ptr<map_session_data>> nick_db;
struct charid2nick
{
- char nick[24];
+ CharName nick;
int req_id;
};
@@ -65,19 +67,25 @@ int first_free_object_id = 0, last_object_id = 0;
interval_t autosave_interval = DEFAULT_AUTOSAVE_INTERVAL;
int save_settings = 0xFFFF;
-char motd_txt[256] = "conf/motd.txt";
-char help_txt[256] = "conf/help.txt";
+FString motd_txt = "conf/motd.txt";
+FString help_txt = "conf/help.txt";
-char wisp_server_name[24] = "Server"; // can be modified in char-server configuration file
+CharName wisp_server_name = stringish<CharName>("Server"); // can be modified in char-server configuration file
static
-void map_delmap(const std::string& mapname);
+void map_delmap(MapName mapname);
void SessionDeleter::operator()(SessionData *sd)
{
really_delete1 static_cast<map_session_data *>(sd);
}
+bool extract(XString str, NpcEvent *ev)
+{
+ XString mid;
+ return extract(str, record<':'>(&ev->npc, &mid, &ev->label)) && !mid;
+}
+
/*==========================================
* 全map鯖総計での接続数設定
* (char鯖から送られてくる)
@@ -740,13 +748,13 @@ int map_addflooritem(struct item *item_data, int amount,
* charid_dbへ追加(返信待ちがあれば返信)
*------------------------------------------
*/
-void map_addchariddb(int charid, const char *name)
+void map_addchariddb(int charid, CharName name)
{
struct charid2nick *p = charid_db.search(charid);
if (p == NULL)
p = charid_db.init(charid);
- strzcpy(p->nick, name, 24);
+ p->nick = name;
p->req_id = 0;
}
@@ -876,14 +884,14 @@ dumb_ptr<map_session_data> map_id2sd(int id)
* char_id番号の名前を探す
*------------------------------------------
*/
-char *map_charid2nick(int id)
+CharName map_charid2nick(int id)
{
struct charid2nick *p = charid_db.search(id);
if (p == NULL)
- return NULL;
+ return CharName();
if (p->req_id != 0)
- return NULL;
+ return CharName();
return p->nick;
}
@@ -958,40 +966,21 @@ dumb_ptr<map_session_data> map_get_prev_session(dumb_ptr<map_session_data> d)
* return map_session_data pointer or NULL
*------------------------------------------
*/
-dumb_ptr<map_session_data> map_nick2sd(const char *nick)
+dumb_ptr<map_session_data> map_nick2sd(CharName nick)
{
- int i, quantity = 0, nicklen;
- dumb_ptr<map_session_data> sd = NULL;
-
- if (nick == NULL)
- return NULL;
-
- nicklen = strlen(nick);
-
- for (i = 0; i < fd_max; i++)
+ for (int i = 0; i < fd_max; i++)
{
if (!session[i])
continue;
map_session_data *pl_sd = static_cast<map_session_data *>(session[i]->session_data.get());
if (pl_sd && pl_sd->state.auth)
{
- // Without case sensitive check (increase the number of similar character names found)
- if (strncasecmp(pl_sd->status.name, nick, nicklen) == 0)
{
- // Strict comparison (if found, we finish the function immediatly with correct value)
- if (strcmp(pl_sd->status.name, nick) == 0)
+ if (pl_sd->status.name == nick)
return dumb_ptr<map_session_data>(pl_sd);
- quantity++;
- sd = dumb_ptr<map_session_data>(pl_sd);
}
}
}
- // Here, the exact character name is not found
- // We return the found index of a similar account ONLY if there is 1 similar character
- if (quantity == 1)
- return sd;
-
- // Exact character name is not found and 0 or more than 1 similar characters have been found ==> we say not found
return NULL;
}
@@ -1077,7 +1066,7 @@ void map_removenpc(void)
* map名からmap番号へ変換
*------------------------------------------
*/
-map_local *map_mapname2mapid(const char *name)
+map_local *map_mapname2mapid(MapName name)
{
map_abstract *md = maps_db.get(name);
if (md == NULL || md->gat == NULL)
@@ -1089,7 +1078,7 @@ map_local *map_mapname2mapid(const char *name)
* 他鯖map名からip,port変換
*------------------------------------------
*/
-int map_mapname2ipport(const char *name, struct in_addr *ip, int *port)
+int map_mapname2ipport(MapName name, struct in_addr *ip, int *port)
{
map_abstract *md = maps_db.get(name);
if (md == NULL || md->gat)
@@ -1198,14 +1187,14 @@ void map_setcell(map_local *m, int x, int y, MapCell t)
* 他鯖管理のマップをdbに追加
*------------------------------------------
*/
-int map_setipport(const char *name, struct in_addr ip, int port)
+int map_setipport(MapName name, struct in_addr ip, int port)
{
map_abstract *md = maps_db.get(name);
if (md == NULL)
{
// not exist -> add new data
auto mdos = make_unique<map_remote>();
- strzcpy(mdos->name_, name, 16);
+ mdos->name_ = name;
mdos->gat = NULL;
mdos->ip = ip;
mdos->port = port;
@@ -1239,7 +1228,7 @@ int map_setipport(const char *name, struct in_addr ip, int port)
*------------------------------------------
*/
static
-bool map_readmap(map_local *m, size_t num, const std::string& fn)
+bool map_readmap(map_local *m, size_t num, MapName fn)
{
// read & convert fn
std::vector<uint8_t> gat_v = grfio_reads(fn);
@@ -1251,7 +1240,7 @@ bool map_readmap(map_local *m, size_t num, const std::string& fn)
int ys = m->ys = gat_v[2] | gat_v[3] << 8;
PRINTF("\rLoading Maps [%zu/%zu]: %-30s (%i, %i)",
num, maps_db.size(),
- std::string(fn.begin(), fn.end()), xs, ys);
+ fn, xs, ys);
fflush(stdout);
assert (s == xs * ys);
@@ -1284,7 +1273,6 @@ int map_readallmap(void)
for (auto& mit : maps_db)
{
- assert (strstr(mit.second->name_, ".gat") != NULL);
{
{
map_local *ml = static_cast<map_local *>(mit.second.get());
@@ -1316,7 +1304,7 @@ int map_readallmap(void)
*------------------------------------------
*/
static
-void map_addmap(const std::string& mapname)
+void map_addmap(MapName mapname)
{
if (mapname == "clear")
{
@@ -1325,9 +1313,10 @@ void map_addmap(const std::string& mapname)
}
auto newmap = make_unique<map_local>();
- strzcpy(newmap->name_, mapname.c_str(), 16);
- // novice challenge: figure out why this is necessary, and why it works
- const char *name = newmap->name_;
+ newmap->name_ = mapname;
+ // novice challenge: figure out why this is necessary,
+ // and why the previous version worked
+ MapName name = newmap->name_;
maps_db.put(name, std::move(newmap));
}
@@ -1335,7 +1324,7 @@ void map_addmap(const std::string& mapname)
* 読み込むmapを削除する
*------------------------------------------
*/
-void map_delmap(const std::string& mapname)
+void map_delmap(MapName mapname)
{
if (mapname == "all")
{
@@ -1351,7 +1340,7 @@ constexpr int LOGFILE_SECONDS_PER_CHUNK_SHIFT = 10;
static
FILE *map_logfile = NULL;
static
-std::string map_logfile_name;
+FString map_logfile_name;
static
long map_logfile_index;
@@ -1360,7 +1349,7 @@ void map_close_logfile(void)
{
if (map_logfile)
{
- std::string filename = STRPRINTF("%s.%ld", map_logfile_name, map_logfile_index);
+ FString filename = STRPRINTF("%s.%ld", map_logfile_name, map_logfile_index);
const char *args[] =
{
"gzip",
@@ -1386,7 +1375,7 @@ void map_start_logfile(long index)
{
map_logfile_index = index;
- std::string filename_buf = STRPRINTF(
+ FString filename_buf = STRPRINTF(
"%s.%ld",
map_logfile_name,
map_logfile_index);
@@ -1396,7 +1385,7 @@ void map_start_logfile(long index)
}
static
-void map_set_logfile(std::string filename)
+void map_set_logfile(FString filename)
{
struct timeval tv;
@@ -1408,7 +1397,7 @@ void map_set_logfile(std::string filename)
MAP_LOG("log-start v5");
}
-void map_log(const_string line)
+void map_log(XString line)
{
if (!map_logfile)
return;
@@ -1430,49 +1419,51 @@ void map_log(const_string line)
*------------------------------------------
*/
static
-int map_config_read(const char *cfgName)
+int map_config_read(ZString cfgName)
{
struct hostent *h = NULL;
- std::ifstream in(cfgName);
+ std::ifstream in(cfgName.c_str());
if (!in.is_open())
{
PRINTF("Map configuration file not found at: %s\n", cfgName);
exit(1);
}
- std::string line;
- while (std::getline(in, line))
+ FString line;
+ while (io::getline(in, line))
{
- std::string w1, w2;
+ SString w1;
+ TString w2;
if (!split_key_value(line, &w1, &w2))
continue;
if (w1 == "userid")
{
- chrif_setuserid(w2.c_str());
+ AccountName name = stringish<AccountName>(w2);
+ chrif_setuserid(name);
}
else if (w1 == "passwd")
{
- chrif_setpasswd(w2.c_str());
+ AccountPass pass = stringish<AccountPass>(w2);
+ chrif_setpasswd(pass);
}
else if (w1 == "char_ip")
{
h = gethostbyname(w2.c_str());
+ IP_String w2ip;
if (h != NULL)
{
- PRINTF("Character server IP address : %s -> %d.%d.%d.%d\n",
- w2,
- 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]));
- SPRINTF(w2, "%d.%d.%d.%d",
- 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]));
+ SNPRINTF(w2ip, 16, "%d.%d.%d.%d",
+ 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",
+ w2, w2ip);
}
- chrif_setip(w2.c_str());
+ else
+ w2ip = stringish<IP_String>(w2);
+ chrif_setip(w2ip);
}
else if (w1 == "char_port")
{
@@ -1481,20 +1472,20 @@ int map_config_read(const char *cfgName)
else if (w1 == "map_ip")
{
h = gethostbyname(w2.c_str());
+ IP_String w2ip;
if (h != NULL)
{
- PRINTF("Map server IP address : %s -> %d.%d.%d.%d\n", w2,
- 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]));
- SPRINTF(w2, "%d.%d.%d.%d",
+ SNPRINTF(w2ip, 16, "%d.%d.%d.%d",
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("Map server IP address : %s -> %s\n",
+ w2, w2ip);
}
- clif_setip(w2.c_str());
+ else
+ w2ip = stringish<IP_String>(w2);
+ clif_setip(w2ip);
}
else if (w1 == "map_port")
{
@@ -1502,19 +1493,21 @@ int map_config_read(const char *cfgName)
}
else if (w1 == "map")
{
- map_addmap(w2.c_str());
+ MapName name = VString<15>(w2);
+ map_addmap(name);
}
else if (w1 == "delmap")
{
- map_delmap(w2.c_str());
+ MapName name = VString<15>(w2);
+ map_delmap(name);
}
else if (w1 == "npc")
{
- npc_addsrcfile(w2.c_str());
+ npc_addsrcfile(w2);
}
else if (w1 == "delnpc")
{
- npc_delsrcfile(w2.c_str());
+ npc_delsrcfile(w2);
}
else if (w1 == "autosave_time")
{
@@ -1524,15 +1517,15 @@ int map_config_read(const char *cfgName)
}
else if (w1 == "motd_txt")
{
- strzcpy(motd_txt, w2.c_str(), sizeof(motd_txt));
+ motd_txt = w2;
}
else if (w1 == "help_txt")
{
- strzcpy(help_txt, w2.c_str(), sizeof(help_txt));
+ help_txt = w2;
}
else if (w1 == "mapreg_txt")
{
- strzcpy(mapreg_txt, w2.c_str(), sizeof(mapreg_txt));
+ mapreg_txt = w2;
}
else if (w1 == "gm_log")
{
@@ -1540,11 +1533,11 @@ int map_config_read(const char *cfgName)
}
else if (w1 == "log_file")
{
- map_set_logfile(w2.c_str());
+ map_set_logfile(w2);
}
else if (w1 == "import")
{
- map_config_read(w2.c_str());
+ map_config_read(w2);
}
}
@@ -1632,26 +1625,26 @@ int compare_item(struct item *a, struct item *b)
* Map-Server Init and Command-line Arguments [Valaris]
*------------------------------------------------------
*/
-int do_init(int argc, char *argv[])
+int do_init(int argc, ZString *argv)
{
int i;
- const char *MAP_CONF_NAME = "conf/map_athena.conf";
- const char *BATTLE_CONF_FILENAME = "conf/battle_athena.conf";
- const char *ATCOMMAND_CONF_FILENAME = "conf/atcommand_athena.conf";
+ ZString MAP_CONF_NAME = "conf/map_athena.conf";
+ ZString BATTLE_CONF_FILENAME = "conf/battle_athena.conf";
+ ZString ATCOMMAND_CONF_FILENAME = "conf/atcommand_athena.conf";
for (i = 1; i < argc; i++)
{
- if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "--h") == 0
- || strcmp(argv[i], "--?") == 0 || strcmp(argv[i], "/?") == 0)
+ if (argv[i] == "--help" || argv[i] == "-h"
+ || argv[i] == "-?" || argv[i] == "/?")
map_helpscreen();
- else if (strcmp(argv[i], "--map_config") == 0)
- MAP_CONF_NAME = argv[i + 1];
- else if (strcmp(argv[i], "--battle_config") == 0)
- BATTLE_CONF_FILENAME = argv[i + 1];
- else if (strcmp(argv[i], "--atcommand_config") == 0)
- ATCOMMAND_CONF_FILENAME = argv[i + 1];
+ 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];
}
map_config_read(MAP_CONF_NAME);
diff --git a/src/map/map.hpp b/src/map/map.hpp
index f0d0310..87bf1f9 100644
--- a/src/map/map.hpp
+++ b/src/map/map.hpp
@@ -8,9 +8,11 @@
#include <functional>
#include <list>
+#include "../common/cxxstdio.hpp"
#include "../common/db.hpp"
#include "../common/matrix.hpp"
#include "../common/socket.hpp"
+#include "../common/strings.hpp"
#include "../common/timer.t.hpp"
#include "battle.t.hpp"
@@ -33,6 +35,38 @@ constexpr int MAX_DROP_PER_MAP = 48;
constexpr interval_t DEFAULT_AUTOSAVE_INTERVAL = std::chrono::minutes(1);
+// formerly VString<49>, as name::label
+struct NpcEvent
+{
+ NpcName npc;
+ ScriptLabel label;
+
+ explicit operator bool()
+ {
+ return npc || label;
+ }
+ bool operator !()
+ {
+ return !bool(*this);
+ }
+
+ friend bool operator == (const NpcEvent& l, const NpcEvent& r)
+ {
+ return l.npc == r.npc && l.label == r.label;
+ }
+
+ friend bool operator < (const NpcEvent& l, const NpcEvent& r)
+ {
+ return l.npc < r.npc || (l.npc == r.npc && l.label < r.label);
+ }
+
+ friend VString<49> convert_for_printf(NpcEvent ev)
+ {
+ return STRNPRINTF(50, "%s::%s", ev.npc, ev.label);
+ }
+};
+bool extract(XString str, NpcEvent *ev);
+
struct map_session_data;
struct npc_data;
struct mob_data;
@@ -71,16 +105,6 @@ struct walkpath_data
unsigned char path_len, path_pos, path_half;
DIR path[MAX_WALKPATH];
};
-struct script_reg
-{
- int index;
- int data;
-};
-struct script_regstr
-{
- int index;
- char data[256];
-};
struct status_change
{
Timer timer;
@@ -92,7 +116,6 @@ struct invocation;
struct npc_data;
struct item_data;
-struct square;
struct quick_regeneration
{ // [Fate]
@@ -141,7 +164,7 @@ struct map_session_data : block_list, SessionData
earray<short, EQUIP, EQUIP::COUNT> equip_index;
int weight, max_weight;
int cart_weight, cart_max_weight, cart_num, cart_max_num;
- char mapname_[16];
+ MapName mapname_;
int fd, new_fd;
short to_x, to_y;
interval_t speed;
@@ -161,7 +184,7 @@ struct map_session_data : block_list, SessionData
// but one should probably be replaced with a ScriptPointer ???
const ScriptBuffer *npc_script, *npc_scriptroot;
std::vector<struct script_data> npc_stackbuf;
- std::string npc_str;
+ FString npc_str;
struct
{
unsigned storage:1;
@@ -236,7 +259,7 @@ struct map_session_data : block_list, SessionData
DMap<SIR, int> regm;
// can't be DMap because we want predictable .c_str()s
// This could change once FString ensures CoW.
- Map<SIR, std::string> regstrm;
+ Map<SIR, FString> regstrm;
earray<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data;
short sc_count;
@@ -252,15 +275,13 @@ struct map_session_data : block_list, SessionData
int partyspy; // [Syrus22]
- char message[80];
-
int catch_target_class;
int pvp_point, pvp_rank;
Timer pvp_timer;
int pvp_lastusers;
- std::list<std::string> eventqueuel;
+ std::list<NpcEvent> eventqueuel;
Timer eventtimer[MAX_EVENTTIMER];
struct
@@ -272,7 +293,7 @@ struct map_session_data : block_list, SessionData
TimeT chat_repeat_reset_due;
int chat_lines_in;
int chat_total_repeats;
- char chat_lastmsg[513];
+ FString chat_lastmsg;
tick_t flood_rates[0x220];
TimeT packet_flood_reset_due;
@@ -288,7 +309,7 @@ struct npc_timerevent_list
};
struct npc_label_list
{
- char name[24];
+ ScriptLabel name;
int pos;
};
struct npc_item_list
@@ -307,15 +328,14 @@ struct npc_data : block_list
short npc_class;
DIR dir;
interval_t speed;
- char name[24];
- char exname[24];
+ NpcName name;
Opt1 opt1;
Opt2 opt2;
Opt3 opt3;
Option option;
short flag;
- std::list<std::string> eventqueuel;
+ std::list<FString> eventqueuel;
Timer eventtimer[MAX_EVENTTIMER];
short arenaflag;
@@ -370,14 +390,14 @@ public:
{
short xs, ys;
short x, y;
- char name[16];
+ MapName name;
} warp;
};
class npc_data_message : public npc_data
{
public:
- std::string message;
+ FString message;
};
constexpr int MOB_XP_BONUS_BASE = 1024;
@@ -395,7 +415,7 @@ struct mob_data : block_list
short x0, y0, xs, ys;
interval_t delay1, delay2;
} spawn;
- char name[24];
+ MobName name;
struct
{
MS state;
@@ -448,7 +468,7 @@ struct mob_data : block_list
LevelElement def_ele;
int master_id, master_dist;
int exclusion_src, exclusion_party;
- char npc_event[50];
+ NpcEvent npc_event;
// [Fate] mob-specific stats
earray<unsigned short, mob_stat, mob_stat::LAST> stats;
short size;
@@ -461,14 +481,14 @@ struct BlockLists
struct map_abstract
{
- char name_[16];
+ MapName name_;
// gat is NULL for map_remote and non-NULL or map_local
std::unique_ptr<MapCell[]> gat;
virtual ~map_abstract() {}
};
extern
-UPMap<std::string, map_abstract> maps_db;
+UPMap<MapName, map_abstract> maps_db;
struct map_local : map_abstract
{
@@ -537,10 +557,10 @@ struct flooritem_data : block_list
extern interval_t autosave_interval;
extern int save_settings;
-extern char motd_txt[];
-extern char help_txt[];
+extern FString motd_txt;
+extern FString help_txt;
-extern char wisp_server_name[];
+extern CharName wisp_server_name;
// 鯖全体情報
void map_setusers(int);
@@ -587,13 +607,13 @@ void map_quit(dumb_ptr<map_session_data>);
// npc
int map_addnpc(map_local *, dumb_ptr<npc_data>);
-void map_log(const_string line);
+void map_log(XString line);
#define MAP_LOG(format, ...) \
- map_log(static_cast<const std::string&>(STRPRINTF(format, ## __VA_ARGS__)))
+ map_log(STRPRINTF(format, ## __VA_ARGS__))
#define MAP_LOG_PC(sd, fmt, ...) \
MAP_LOG("PC%d %s:%d,%d " fmt, \
- sd->status.char_id, (sd->bl_m ? sd->bl_m->name_ : "undefined.gat"), sd->bl_x, sd->bl_y, ## __VA_ARGS__)
+ sd->status.char_id, (sd->bl_m ? sd->bl_m->name_ : stringish<MapName>("undefined.gat")), sd->bl_x, sd->bl_y, ## __VA_ARGS__)
// 床アイテム関連
void map_clearflooritem_timer(TimerData *, tick_t, int);
@@ -614,8 +634,8 @@ int map_addflooritem(struct item *, int,
// キャラid=>キャラ名 変換関連
extern
DMap<int, dumb_ptr<block_list>> id_db;
-void map_addchariddb(int charid, const char *name);
-char *map_charid2nick(int);
+void map_addchariddb(int charid, CharName name);
+CharName map_charid2nick(int);
dumb_ptr<map_session_data> map_id2sd(int);
dumb_ptr<block_list> map_id2bl(int);
@@ -683,14 +703,14 @@ dumb_ptr<invocation> map_id_is_spell(int id)
}
-map_local *map_mapname2mapid(const char *);
-int map_mapname2ipport(const char *, struct in_addr *, int *);
-int map_setipport(const char *name, struct in_addr ip, int port);
+map_local *map_mapname2mapid(MapName);
+int map_mapname2ipport(MapName, struct in_addr *, int *);
+int map_setipport(MapName name, struct in_addr ip, int port);
void map_addiddb(dumb_ptr<block_list>);
void map_deliddb(dumb_ptr<block_list> bl);
void map_addnickdb(dumb_ptr<map_session_data>);
int map_scriptcont(dumb_ptr<map_session_data> sd, int id); /* Continues a script either on a spell or on an NPC */
-dumb_ptr<map_session_data> map_nick2sd(const char *);
+dumb_ptr<map_session_data> map_nick2sd(CharName);
int compare_item(struct item *a, struct item *b);
dumb_ptr<map_session_data> map_get_first_session(void);
diff --git a/src/map/map.t.hpp b/src/map/map.t.hpp
index d7b86ec..19f80c3 100644
--- a/src/map/map.t.hpp
+++ b/src/map/map.t.hpp
@@ -555,4 +555,9 @@ ENUM_BITWISE_OPERATORS(MapCell)
}
using e::MapCell;
+struct MobName : VString<23> {};
+struct NpcName : VString<23> {};
+struct ScriptLabel : VString<23> {};
+struct ItemName : VString<23> {};
+
#endif // MAP_T_HPP
diff --git a/src/map/mob.cpp b/src/map/mob.cpp
index 345f5a6..a2122d6 100644
--- a/src/map/mob.cpp
+++ b/src/map/mob.cpp
@@ -7,10 +7,13 @@
#include <cstring>
#include <algorithm>
+#include <fstream>
#include "../common/cxxstdio.hpp"
-#include "../common/random.hpp"
+#include "../common/extract.hpp"
+#include "../common/io.hpp"
#include "../common/nullpo.hpp"
+#include "../common/random.hpp"
#include "../common/socket.hpp"
#include "../common/timer.hpp"
@@ -53,14 +56,13 @@ int mobskill_use_id(dumb_ptr<mob_data> md, dumb_ptr<block_list> target,
* Mob is searched with a name.
*------------------------------------------
*/
-int mobdb_searchname(const char *str)
+int mobdb_searchname(MobName str)
{
int i;
for (i = 0; i < sizeof(mob_db) / sizeof(mob_db[0]); i++)
{
- if (strcasecmp(mob_db[i].name, str) == 0
- || strcmp(mob_db[i].jname, str) == 0)
+ if (mob_db[i].name == str || mob_db[i].jname == str)
return i;
}
@@ -88,16 +90,16 @@ void mob_init(dumb_ptr<mob_data> md);
*------------------------------------------
*/
static
-void mob_spawn_dataset(dumb_ptr<mob_data> md, const char *mobname, int mob_class)
+void mob_spawn_dataset(dumb_ptr<mob_data> md, MobName mobname, int mob_class)
{
nullpo_retv(md);
- if (strcmp(mobname, "--en--") == 0)
- strzcpy(md->name, mob_db[mob_class].name, 24);
- else if (strcmp(mobname, "--ja--") == 0)
- strzcpy(md->name, mob_db[mob_class].jname, 24);
+ if (mobname == ENGLISH_NAME)
+ md->name = mob_db[mob_class].name;
+ else if (mobname == JAPANESE_NAME)
+ md->name = mob_db[mob_class].jname;
else
- strzcpy(md->name, mobname, 24);
+ md->name = mobname;
md->bl_prev = NULL;
md->bl_next = NULL;
@@ -362,15 +364,16 @@ void mob_init(dumb_ptr<mob_data> md)
* The MOB appearance for one time (for scripts)
*------------------------------------------
*/
-int mob_once_spawn(dumb_ptr<map_session_data> sd, const char *mapname,
- int x, int y, const char *mobname, int mob_class, int amount,
- const char *event)
+int mob_once_spawn(dumb_ptr<map_session_data> sd,
+ MapName mapname, int x, int y,
+ MobName mobname, int mob_class, int amount,
+ NpcEvent event)
{
dumb_ptr<mob_data> md = NULL;
map_local *m;
int count, r = mob_class;
- if (sd && strcmp(mapname, "this") == 0)
+ if (sd && mapname == MOB_THIS_MAP)
m = sd->bl_m;
else
m = map_mapname2mapid(mapname);
@@ -410,7 +413,7 @@ int mob_once_spawn(dumb_ptr<map_session_data> sd, const char *mapname,
md->spawn.delay1 = static_cast<interval_t>(-1); // Only once is a flag.
md->spawn.delay2 = static_cast<interval_t>(-1); // Only once is a flag.
- strzcpy(md->npc_event, event, 50);
+ md->npc_event = event;
md->bl_type = BL::MOB;
map_addiddb(md);
@@ -423,15 +426,15 @@ int mob_once_spawn(dumb_ptr<map_session_data> sd, const char *mapname,
* The MOB appearance for one time (& area specification for scripts)
*------------------------------------------
*/
-int mob_once_spawn_area(dumb_ptr<map_session_data> sd, const char *mapname,
- int x0, int y0, int x1, int y1,
- const char *mobname, int mob_class, int amount,
- const char *event)
+int mob_once_spawn_area(dumb_ptr<map_session_data> sd,
+ MapName mapname, int x0, int y0, int x1, int y1,
+ MobName mobname, int mob_class, int amount,
+ NpcEvent event)
{
int x, y, i, max, lx = -1, ly = -1, id = 0;
map_local *m;
- if (strcmp(mapname, "this") == 0)
+ if (mapname == MOB_THIS_MAP)
m = sd->bl_m;
else
m = map_mapname2mapid(mapname);
@@ -2624,7 +2627,7 @@ int mob_damage(dumb_ptr<block_list> src, dumb_ptr<mob_data> md, int damage,
} // [MouseJstr]
// SCRIPT実行
- if (md->npc_event[0])
+ if (md->npc_event)
{
if (sd == NULL)
{
@@ -2877,7 +2880,7 @@ int mob_summonslave(dumb_ptr<mob_data> md2, int *value, int amount, int flag)
y = by;
}
- mob_spawn_dataset(md, "--ja--", mob_class);
+ mob_spawn_dataset(md, JAPANESE_NAME, mob_class);
md->bl_prev = NULL;
md->bl_next = NULL;
md->bl_m = m;
@@ -2893,7 +2896,7 @@ int mob_summonslave(dumb_ptr<mob_data> md2, int *value, int amount, int flag)
md->spawn.delay1 = static_cast<interval_t>(-1); // 一度のみフラグ
md->spawn.delay2 = static_cast<interval_t>(-1); // 一度のみフラグ
- strzcpy(md->npc_event, "", 50);
+ md->npc_event = NpcEvent();
md->bl_type = BL::MOB;
map_addiddb(md);
mob_spawn(md->bl_id);
@@ -3341,8 +3344,8 @@ int mob_makedummymobdb(int mob_class)
{
int i;
- sprintf(mob_db[mob_class].name, "mob%d", mob_class);
- sprintf(mob_db[mob_class].jname, "mob%d", mob_class);
+ SNPRINTF(mob_db[mob_class].name, 24, "mob%d", mob_class);
+ SNPRINTF(mob_db[mob_class].jname, 24, "mob%d", mob_class);
mob_db[mob_class].lv = 1;
mob_db[mob_class].max_hp = 1000;
mob_db[mob_class].max_sp = 1;
@@ -3377,6 +3380,18 @@ int mob_makedummymobdb(int mob_class)
return 0;
}
+static
+bool extract(XString str, LevelElement *le)
+{
+ int tmp;
+ if (extract(str, &tmp))
+ {
+ le->unpack(tmp);
+ return true;
+ }
+ return false;
+}
+
/*==========================================
* db/mob_db.txt reading
*------------------------------------------
@@ -3384,57 +3399,95 @@ int mob_makedummymobdb(int mob_class)
static
int mob_readdb(void)
{
- FILE *fp;
- char line[1024];
- const char *filename[] = { "db/mob_db.txt", "db/mob_db2.txt" };
+ const char *filename = "db/mob_db.txt";
for (mob_db_& e : mob_db)
e = mob_db_{};
- for (int j = 0; j < 2; j++)
{
-
- fp = fopen_(filename[j], "r");
- if (fp == NULL)
+ std::ifstream in(filename);
+ if (!in.is_open())
{
- if (j > 0)
- continue;
return -1;
}
- while (fgets(line, 1020, fp))
+ FString line;
+ while (io::getline(in, line))
{
int mob_class;
- char *str[57], *p, *np;
- if (line[0] == '/' && line[1] == '/')
+ if (line.startswith("//"))
continue;
+ struct mob_db_ mdbv {};
+
+ XString ignore;
+
+ extract(line, record<','>(
+ &mob_class,
+ lstripping(&mdbv.name),
+ lstripping(&mdbv.jname),
+ lstripping(&mdbv.lv),
+ lstripping(&mdbv.max_hp),
+ lstripping(&mdbv.max_sp),
+ lstripping(&mdbv.base_exp),
+ lstripping(&mdbv.job_exp),
+ lstripping(&mdbv.range),
+ lstripping(&mdbv.atk1),
+ lstripping(&mdbv.atk2),
+ lstripping(&mdbv.def),
+ lstripping(&mdbv.mdef),
+ lstripping(&mdbv.attrs[ATTR::STR]),
+ lstripping(&mdbv.attrs[ATTR::AGI]),
+ lstripping(&mdbv.attrs[ATTR::VIT]),
+ lstripping(&mdbv.attrs[ATTR::INT]),
+ lstripping(&mdbv.attrs[ATTR::DEX]),
+ lstripping(&mdbv.attrs[ATTR::LUK]),
+ lstripping(&mdbv.range2),
+ lstripping(&mdbv.range3),
+ lstripping(&mdbv.size),
+ lstripping(&mdbv.race),
+ lstripping(&mdbv.element),
+ lstripping(&mdbv.mode),
+ lstripping(&mdbv.speed),
+ lstripping(&mdbv.adelay),
+ lstripping(&mdbv.amotion),
+ lstripping(&mdbv.dmotion),
+ lstripping(&mdbv.dropitem[0].nameid),
+ lstripping(&mdbv.dropitem[0].p.num),
+ lstripping(&mdbv.dropitem[1].nameid),
+ lstripping(&mdbv.dropitem[1].p.num),
+ lstripping(&mdbv.dropitem[2].nameid),
+ lstripping(&mdbv.dropitem[2].p.num),
+ lstripping(&mdbv.dropitem[3].nameid),
+ lstripping(&mdbv.dropitem[3].p.num),
+ lstripping(&mdbv.dropitem[4].nameid),
+ lstripping(&mdbv.dropitem[4].p.num),
+ lstripping(&mdbv.dropitem[5].nameid),
+ lstripping(&mdbv.dropitem[5].p.num),
+ lstripping(&mdbv.dropitem[6].nameid),
+ lstripping(&mdbv.dropitem[6].p.num),
+ lstripping(&mdbv.dropitem[7].nameid),
+ lstripping(&mdbv.dropitem[7].p.num),
+ &ignore,
+ &ignore,
+ &ignore,
+ &ignore,
+ &ignore,
+ &ignore,
+ &ignore,
+ &ignore,
+ &ignore,
+ &ignore,
+ lstripping(&mdbv.mutations_nr),
+ lstripping(&mdbv.mutation_power)
+ )
+ );
- p = line;
- for (int i = 0; i < 57; i++)
- {
- while (*p == '\t' || *p == ' ')
- p++;
- if ((np = strchr(p, ',')) != NULL)
- {
- str[i] = p;
- *np = 0;
- p = np + 1;
- }
- else
- str[i] = p;
- }
-
- mob_class = atoi(str[0]);
if (mob_class <= 1000 || mob_class > 2000)
continue;
- strzcpy(mob_db[mob_class].name, str[1], 24);
- strzcpy(mob_db[mob_class].jname, str[2], 24);
- mob_db[mob_class].lv = atoi(str[3]);
- mob_db[mob_class].max_hp = atoi(str[4]);
- mob_db[mob_class].max_sp = atoi(str[5]);
+ // TODO move this lower
+ mob_db[mob_class] = std::move(mdbv);
- mob_db[mob_class].base_exp = atoi(str[6]);
if (mob_db[mob_class].base_exp < 0)
mob_db[mob_class].base_exp = 0;
else if (mob_db[mob_class].base_exp > 0
@@ -3444,9 +3497,8 @@ int mob_readdb(void)
battle_config.base_exp_rate / 100 < 0))
mob_db[mob_class].base_exp = 1000000000;
else
- mob_db[mob_class].base_exp *= battle_config.base_exp_rate / 100;
+ mob_db[mob_class].base_exp = mob_db[mob_class].base_exp * battle_config.base_exp_rate / 100;
- mob_db[mob_class].job_exp = atoi(str[7]);
if (mob_db[mob_class].job_exp < 0)
mob_db[mob_class].job_exp = 0;
else if (mob_db[mob_class].job_exp > 0
@@ -3456,40 +3508,16 @@ int mob_readdb(void)
battle_config.job_exp_rate / 100 < 0))
mob_db[mob_class].job_exp = 1000000000;
else
- mob_db[mob_class].job_exp *= battle_config.job_exp_rate / 100;
-
- mob_db[mob_class].range = atoi(str[8]);
- mob_db[mob_class].atk1 = atoi(str[9]);
- mob_db[mob_class].atk2 = atoi(str[10]);
- mob_db[mob_class].def = atoi(str[11]);
- mob_db[mob_class].mdef = atoi(str[12]);
- mob_db[mob_class].attrs[ATTR::STR] = atoi(str[13]);
- mob_db[mob_class].attrs[ATTR::AGI] = atoi(str[14]);
- mob_db[mob_class].attrs[ATTR::VIT] = atoi(str[15]);
- mob_db[mob_class].attrs[ATTR::INT] = atoi(str[16]);
- mob_db[mob_class].attrs[ATTR::DEX] = atoi(str[17]);
- mob_db[mob_class].attrs[ATTR::LUK] = atoi(str[18]);
- mob_db[mob_class].range2 = atoi(str[19]);
- mob_db[mob_class].range3 = atoi(str[20]);
- mob_db[mob_class].size = atoi(str[21]); // always 1
- mob_db[mob_class].race = static_cast<Race>(atoi(str[22]));
- mob_db[mob_class].element = LevelElement::unpack(atoi(str[23]));
- mob_db[mob_class].mode = static_cast<MobMode>(atoi(str[24]));
- mob_db[mob_class].speed = atoi(str[25]);
- mob_db[mob_class].adelay = atoi(str[26]);
- mob_db[mob_class].amotion = atoi(str[27]);
- mob_db[mob_class].dmotion = atoi(str[28]);
+ mob_db[mob_class].job_exp = mob_db[mob_class].job_exp * battle_config.job_exp_rate / 100;
for (int i = 0; i < 8; i++)
{
- mob_db[mob_class].dropitem[i].nameid = atoi(str[29 + i * 2]);
- int rate = atoi(str[30 + i * 2]);
+ int rate = mob_db[mob_class].dropitem[i].p.num;
if (rate < 1) rate = 1;
if (rate > 10000) rate = 10000;
mob_db[mob_class].dropitem[i].p.num = rate;
}
- mob_db[mob_class].mutations_nr = atoi(str[55]);
- mob_db[mob_class].mutation_power = atoi(str[56]);
+
mob_db[mob_class].skills.clear();
@@ -3506,22 +3534,14 @@ int mob_readdb(void)
if (mob_db[mob_class].base_exp == 0)
mob_db[mob_class].base_exp = mob_gen_exp(&mob_db[mob_class]);
}
- fclose_(fp);
- PRINTF("read %s done\n", filename[j]);
+ PRINTF("read %s done\n", filename);
}
return 0;
}
-/*==========================================
- * db/mob_skill_db.txt reading
- *------------------------------------------
- */
-static
-int mob_readskilldb(void)
+template<>
+bool extract<MobSkillCondition, void, void>(XString str, MobSkillCondition *msc)
{
- FILE *fp;
- char line[1024];
-
const struct
{
char str[32];
@@ -3534,6 +3554,18 @@ int mob_readskilldb(void)
{"slavelt", MobSkillCondition::MSC_SLAVELT},
{"slavele", MobSkillCondition::MSC_SLAVELE},
};
+ for (auto& pair : cond1)
+ if (str == pair.str)
+ {
+ *msc = pair.id;
+ return true;
+ }
+ return false;
+}
+
+template<>
+bool extract<MobSkillState, void, void>(XString str, MobSkillState *mss)
+{
const struct
{
char str[32];
@@ -3545,6 +3577,18 @@ int mob_readskilldb(void)
{"walk", MobSkillState::MSS_WALK},
{"attack", MobSkillState::MSS_ATTACK},
};
+ for (auto& pair : state)
+ if (str == pair.str)
+ {
+ *mss = pair.id;
+ return true;
+ }
+ return false;
+}
+
+template<>
+bool extract<MobSkillTarget, void, void>(XString str, MobSkillTarget *mst)
+{
const struct
{
char str[32];
@@ -3554,90 +3598,93 @@ int mob_readskilldb(void)
{"target", MobSkillTarget::MST_TARGET},
{"self", MobSkillTarget::MST_SELF},
};
+ for (auto& pair : target)
+ if (str == pair.str)
+ {
+ *mst = pair.id;
+ return true;
+ }
+ return false;
+}
- int x;
- const char *filename[] = { "db/mob_skill_db.txt", "db/mob_skill_db2.txt" };
+/*==========================================
+ * db/mob_skill_db.txt reading
+ *------------------------------------------
+ */
+static
+int mob_readskilldb(void)
+{
+ const char *filename = "db/mob_skill_db.txt";
- for (x = 0; x < 2; x++)
{
-
- fp = fopen_(filename[x], "r");
- if (fp == NULL)
+ std::ifstream in(filename);
+ if (!in.is_open())
{
- if (x == 0)
- PRINTF("can't read %s\n", filename[x]);
- continue;
+ PRINTF("can't read %s\n", filename);
+ return 0;
}
- while (fgets(line, 1020, fp))
+ FString line;
+ while (io::getline(in, line))
{
int mob_id;
- int j = 0;
-
- if (line[0] == '/' && line[1] == '/')
- continue;
- char *sp[20] {};
- char *p;
- int i;
- for (i = 0, p = line; i < 18 && p; i++)
- {
- sp[i] = p;
- p = strchr(p, ',');
- if (p != NULL)
- *p++ = 0;
- }
- if ((mob_id = atoi(sp[0])) <= 0)
+ if (line.startswith("//"))
continue;
- if (strcmp(sp[1], "clear") == 0)
+ XString blah;
+ if (extract(line, record<','>(&mob_id, &blah)) && mob_id > 0 && blah == "clear")
{
mob_db[mob_id].skills.clear();
continue;
}
- mob_db[mob_id].skills.push_back(mob_skill{});
- struct mob_skill *ms = &mob_db[mob_id].skills.back();
-
- ms->state = static_cast<MobSkillState>(atoi(sp[2]));
- for (j = 0; j < sizeof(state) / sizeof(state[0]); j++)
- {
- if (strcmp(sp[2], state[j].str) == 0)
- ms->state = state[j].id;
- }
- ms->skill_id = SkillID(atoi(sp[3]));
- ms->skill_lv = atoi(sp[4]);
-
- ms->permillage = atoi(sp[5]);
- ms->casttime = static_cast<interval_t>(atoi(sp[6]));
- ms->delay = static_cast<interval_t>(atoi(sp[7]));
- ms->cancel = atoi(sp[8]);
- if (strcmp(sp[8], "yes") == 0)
- ms->cancel = 1;
- ms->target = static_cast<MobSkillTarget>(atoi(sp[9]));
- for (j = 0; j < sizeof(target) / sizeof(target[0]); j++)
- {
- if (strcmp(sp[9], target[j].str) == 0)
- ms->target = target[j].id;
- }
- ms->cond1 = MobSkillCondition::ANY;
- for (j = 0; j < sizeof(cond1) / sizeof(cond1[0]); j++)
- {
- if (strcmp(sp[10], cond1[j].str) == 0)
- ms->cond1 = cond1[j].id;
- }
- ms->cond2i = atoi(sp[11]);
- ms->val[0] = atoi(sp[12]);
- ms->val[1] = atoi(sp[13]);
- ms->val[2] = atoi(sp[14]);
- ms->val[3] = atoi(sp[15]);
- ms->val[4] = atoi(sp[16]);
- if (sp[17] != NULL && strlen(sp[17]) > 2)
- ms->emotion = atoi(sp[17]);
+ struct mob_skill msv {};
+ msv.emotion = -1;
+ int casttime, delay;
+ XString cancellable;
+
+ if (!extract(
+ line,
+ record<',', 17>(
+ &mob_id,
+ &blah,
+ &msv.state,
+ &msv.skill_id,
+ &msv.skill_lv,
+ &msv.permillage,
+ &casttime,
+ &delay,
+ &cancellable,
+ &msv.target,
+ &msv.cond1,
+ &msv.cond2i,
+ &msv.val[0],
+ &msv.val[1],
+ &msv.val[2],
+ &msv.val[3],
+ &msv.val[4],
+
+ &msv.emotion
+ )
+ )
+ )
+ continue;
+ if (cancellable == "yes")
+ msv.cancel = true;
+ else if (cancellable == "no")
+ msv.cancel = false;
else
- ms->emotion = -1;
+ continue;
+
+ msv.casttime = std::chrono::milliseconds(casttime);
+ msv.delay = std::chrono::milliseconds(delay);
+
+ if (mob_id <= 0)
+ continue;
+
+ mob_db[mob_id].skills.push_back(std::move(msv));
}
- fclose_(fp);
- PRINTF("read %s done\n", filename[x]);
+ PRINTF("read %s done\n", filename);
}
return 0;
}
diff --git a/src/map/mob.hpp b/src/map/mob.hpp
index 66dbc53..bf53798 100644
--- a/src/map/mob.hpp
+++ b/src/map/mob.hpp
@@ -11,6 +11,10 @@
#include "map.hpp"
#include "skill.t.hpp"
+#define ENGLISH_NAME stringish<MobName>("--en--")
+#define JAPANESE_NAME stringish<MobName>("--ja--")
+#define MOB_THIS_MAP stringish<MapName>("this")
+
struct mob_skill
{
MobSkillState state;
@@ -18,7 +22,7 @@ struct mob_skill
short skill_lv;
short permillage;
interval_t casttime, delay;
- short cancel;
+ bool cancel;
MobSkillCondition cond1;
int cond2i;
MobSkillTarget target;
@@ -28,7 +32,7 @@ struct mob_skill
struct mob_db_
{
- char name[24], jname[24];
+ MobName name, jname;
int lv;
int max_hp, max_sp;
int base_exp, job_exp;
@@ -55,14 +59,16 @@ struct mob_db_
};
extern struct mob_db_ mob_db[];
-int mobdb_searchname(const char *str);
+int mobdb_searchname(MobName str);
int mobdb_checkid(const int id);
int mob_once_spawn(dumb_ptr<map_session_data> sd,
- const char *mapname, int x, int y,
- const char *mobname, int class_, int amount, const char *event);
+ MapName mapname, int x, int y,
+ MobName mobname, int class_, int amount,
+ NpcEvent event);
int mob_once_spawn_area(dumb_ptr<map_session_data> sd,
- const char *mapname, int x0, int y0, int x1, int y1,
- const char *mobname, int class_, int amount, const char *event);
+ MapName mapname, int x0, int y0, int x1, int y1,
+ MobName mobname, int class_, int amount,
+ NpcEvent event);
int mob_target(dumb_ptr<mob_data> md, dumb_ptr<block_list> bl, int dist);
int mob_stop_walking(dumb_ptr<mob_data> md, int type);
diff --git a/src/map/npc.cpp b/src/map/npc.cpp
index 68b5ad7..41f0966 100644
--- a/src/map/npc.cpp
+++ b/src/map/npc.cpp
@@ -9,6 +9,7 @@
#include "../common/cxxstdio.hpp"
#include "../common/db.hpp"
+#include "../common/extract.hpp"
#include "../common/nullpo.hpp"
#include "../common/socket.hpp"
#include "../common/timer.hpp"
@@ -25,7 +26,7 @@
#include "../poison.hpp"
static
-std::list<std::string> npc_srcs;
+std::list<FString> npc_srcs;
static
int npc_id = START_NPC_NUM;
@@ -43,9 +44,9 @@ struct event_data
int pos;
};
static
-Map<std::string, struct event_data> ev_db;
+Map<NpcEvent, struct event_data> ev_db;
static
-DMap<std::string, dumb_ptr<npc_data>> npcname_db;
+DMap<NpcName, dumb_ptr<npc_data>> npcname_db;
// used for clock-based event triggers
// only tm_min, tm_hour, and tm_mday are used
@@ -62,7 +63,6 @@ static
void npc_enable_sub(dumb_ptr<block_list> bl, dumb_ptr<npc_data> nd)
{
dumb_ptr<map_session_data> sd;
- char aname[50] {};
nullpo_retv(bl);
@@ -74,16 +74,17 @@ void npc_enable_sub(dumb_ptr<block_list> bl, dumb_ptr<npc_data> nd)
if (nd->flag & 1)
return;
- strzcpy(aname, nd->name, sizeof(nd->name));
+ NpcEvent aname;
+ aname.npc = nd->name;
+ aname.label = stringish<ScriptLabel>("OnTouch");
if (sd->areanpc_id == nd->bl_id)
return;
sd->areanpc_id = nd->bl_id;
- strcat(aname, "::OnTouch");
npc_event(sd, aname, 0);
}
}
-int npc_enable(const char *name, bool flag)
+int npc_enable(NpcName name, bool flag)
{
dumb_ptr<npc_data> nd = npcname_db.get(name);
if (nd == NULL)
@@ -121,7 +122,7 @@ int npc_enable(const char *name, bool flag)
* NPCを名前で探す
*------------------------------------------
*/
-dumb_ptr<npc_data> npc_name2id(const char *name)
+dumb_ptr<npc_data> npc_name2id(NpcName name)
{
return npcname_db.get(name);
}
@@ -138,7 +139,7 @@ int npc_event_dequeue(dumb_ptr<map_session_data> sd)
if (!sd->eventqueuel.empty())
{
- if (!pc_addeventtimer(sd, std::chrono::milliseconds(100), sd->eventqueuel.front().c_str()))
+ if (!pc_addeventtimer(sd, std::chrono::milliseconds(100), sd->eventqueuel.front()))
{
PRINTF("npc_event_dequeue(): Event timer is full.\n");
return 0;
@@ -163,7 +164,7 @@ int npc_delete(dumb_ptr<npc_data> nd)
return 0;
}
-int npc_timer_event(const char *eventname) // Added by RoVeRT
+void npc_timer_event(NpcEvent eventname)
{
struct event_data *ev = ev_db.search(eventname);
dumb_ptr<npc_data_script> nd;
@@ -171,13 +172,12 @@ int npc_timer_event(const char *eventname) // Added by RoVeRT
if ((ev == NULL || (nd = ev->nd) == NULL))
{
- PRINTF("npc_event: event not found [%s]\n", eventname);
- return 0;
+ PRINTF("npc_event: event not found [%s]\n",
+ eventname);
+ return;
}
run_script(ScriptPointer(nd->scr.script.get(), ev->pos), nd->bl_id, nd->bl_id);
-
- return 0;
}
/*==========================================
@@ -185,55 +185,51 @@ int npc_timer_event(const char *eventname) // Added by RoVeRT
*------------------------------------------
*/
static
-void npc_event_doall_sub(const std::string& key, struct event_data *ev,
- int *c, const char *name, int rid, int argc, argrec_t *argv)
+void npc_event_doall_sub(NpcEvent key, struct event_data *ev,
+ int *c, ScriptLabel name, int rid, int argc, argrec_t *argv)
{
- const char *p = key.c_str();
+ ScriptLabel p = key.label;
nullpo_retv(ev);
- if ((p = strchr(p, ':')) && p && strcasecmp(name, p) == 0)
+ if (name == p)
{
- run_script_l(ScriptPointer(ev->nd->scr.script.get(), ev->pos), rid, ev->nd->bl_id, argc,
- argv);
+ run_script_l(ScriptPointer(ev->nd->scr.script.get(), ev->pos), rid, ev->nd->bl_id,
+ argc, argv);
(*c)++;
}
}
-int npc_event_doall_l(const char *name, int rid, int argc, argrec_t *args)
+int npc_event_doall_l(ScriptLabel name, int rid, int argc, argrec_t *args)
{
int c = 0;
- char buf[64] = "::";
- strzcpy(buf + 2, name, 62);
for (auto& pair : ev_db)
- npc_event_doall_sub(pair.first, &pair.second, &c, buf, rid, argc, args);
+ npc_event_doall_sub(pair.first, &pair.second, &c, name, rid, argc, args);
return c;
}
static
-void npc_event_do_sub(const std::string& key, struct event_data *ev,
- int *c, const char *name, int rid, int argc, argrec_t *argv)
+void npc_event_do_sub(NpcEvent key, struct event_data *ev,
+ int *c, NpcEvent name, int rid, int argc, argrec_t *argv)
{
- const char *p = key.c_str();
-
nullpo_retv(ev);
- if (p && strcasecmp(name, p) == 0)
+ if (name == key)
{
- run_script_l(ScriptPointer(ev->nd->scr.script.get(), ev->pos), rid, ev->nd->bl_id, argc,
- argv);
+ run_script_l(ScriptPointer(ev->nd->scr.script.get(), ev->pos), rid, ev->nd->bl_id,
+ argc, argv);
(*c)++;
}
}
-int npc_event_do_l(const char *name, int rid, int argc, argrec_t *args)
+int npc_event_do_l(NpcEvent name, int rid, int argc, argrec_t *args)
{
int c = 0;
- if (*name == ':' && name[1] == ':')
+ if (!name.npc)
{
- return npc_event_doall_l(name + 2, rid, argc, args);
+ return npc_event_doall_l(name.label, rid, argc, args);
}
for (auto& pair : ev_db)
@@ -250,25 +246,23 @@ void npc_event_do_clock(TimerData *, tick_t)
{
struct tm t = TimeT::now();
+ ScriptLabel buf;
if (t.tm_min != ev_tm_b.tm_min)
{
- std::string buf;
- buf = STRPRINTF("OnMinute%02d", t.tm_min);
- npc_event_doall(buf.c_str());
- buf = STRPRINTF("OnClock%02d%02d", t.tm_hour, t.tm_min);
- npc_event_doall(buf.c_str());
+ SNPRINTF(buf, 24, "OnMinute%02d", t.tm_min);
+ npc_event_doall(buf);
+ SNPRINTF(buf, 24, "OnClock%02d%02d", t.tm_hour, t.tm_min);
+ npc_event_doall(buf);
}
if (t.tm_hour != ev_tm_b.tm_hour)
{
- std::string buf;
- buf = STRPRINTF("OnHour%02d", t.tm_hour);
- npc_event_doall(buf.c_str());
+ SNPRINTF(buf, 24, "OnHour%02d", t.tm_hour);
+ npc_event_doall(buf);
}
if (t.tm_mday != ev_tm_b.tm_mday)
{
- std::string buf;
- buf = STRPRINTF("OnDay%02d%02d", t.tm_mon + 1, t.tm_mday);
- npc_event_doall(buf.c_str());
+ SNPRINTF(buf, 24, "OnDay%02d%02d", t.tm_mon + 1, t.tm_mday);
+ npc_event_doall(buf);
}
ev_tm_b = t;
}
@@ -279,7 +273,7 @@ void npc_event_do_clock(TimerData *, tick_t)
*/
int npc_event_do_oninit(void)
{
- int c = npc_event_doall("OnInit");
+ int c = npc_event_doall(stringish<ScriptLabel>("OnInit"));
PRINTF("npc: OnInit Event done. (%d npc)\n", c);
Timer(gettick() + std::chrono::milliseconds(100),
@@ -414,41 +408,34 @@ void npc_settimerevent_tick(dumb_ptr<npc_data_script> nd, interval_t newtimer)
* イベント型のNPC処理
*------------------------------------------
*/
-int npc_event(dumb_ptr<map_session_data> sd, const char *eventname,
- int mob_kill)
+int npc_event(dumb_ptr<map_session_data> sd, NpcEvent eventname,
+ int mob_kill)
{
struct event_data *ev = ev_db.search(eventname);
dumb_ptr<npc_data_script> nd;
int xs, ys;
- char mobevent[100];
if (sd == NULL)
{
PRINTF("npc_event nullpo?\n");
}
- if (ev == NULL && eventname
- && strcmp(((eventname) + strlen(eventname) - 9), "::OnTouch") == 0)
+ if (ev == NULL && eventname.label == stringish<ScriptLabel>("OnTouch"))
return 1;
if (ev == NULL || (nd = ev->nd) == NULL)
{
- if (mob_kill && (ev == NULL || (nd = ev->nd) == NULL))
+ if (mob_kill)
{
- strcpy(mobevent, eventname);
- strcat(mobevent, "::OnMyMobDead");
- ev = ev_db.search(mobevent);
- if (ev == NULL || (nd = ev->nd) == NULL)
{
- if (strncasecmp(eventname, "GM_MONSTER", 10) != 0)
- PRINTF("npc_event: event not found [%s]\n", mobevent);
return 0;
}
}
else
{
if (battle_config.error_log)
- PRINTF("npc_event: event not found [%s]\n", eventname);
+ PRINTF("npc_event: event not found [%s]\n",
+ eventname);
return 0;
}
}
@@ -485,22 +472,19 @@ int npc_event(dumb_ptr<map_session_data> sd, const char *eventname,
}
static
-void npc_command_sub(const std::string& key, struct event_data *ev, const char *npcname, const char *command)
+void npc_command_sub(NpcEvent key, struct event_data *ev, NpcName npcname, XString command)
{
- const char *p = key.c_str();
- char temp[100];
-
- if (strcmp(ev->nd->name, npcname) == 0 && (p = strchr(p, ':')) && p
- && strncasecmp("::OnCommand", p, 10) == 0)
+ if (ev->nd->name == npcname
+ && key.label.startswith("OnCommand"))
{
- sscanf(&p[11], "%s", temp);
+ XString temp = key.label.xslice_t(9);
- if (strcmp(command, temp) == 0)
+ if (command == temp)
run_script(ScriptPointer(ev->nd->scr.script.get(), ev->pos), 0, ev->nd->bl_id);
}
}
-int npc_command(dumb_ptr<map_session_data>, const char *npcname, const char *command)
+int npc_command(dumb_ptr<map_session_data>, NpcName npcname, XString command)
{
for (auto& pair : ev_db)
npc_command_sub(pair.first, &pair.second, npcname, command);
@@ -575,14 +559,14 @@ int npc_touch_areanpc(dumb_ptr<map_session_data> sd, map_local *m, int x, int y)
break;
case NpcSubtype::SCRIPT:
{
- char aname[50] {};
- strzcpy(aname, m->npc[i]->name, 24);
+ NpcEvent aname;
+ aname.npc = m->npc[i]->name;
+ aname.label = stringish<ScriptLabel>("OnTouch");
if (sd->areanpc_id == m->npc[i]->bl_id)
return 1;
sd->areanpc_id = m->npc[i]->bl_id;
- strcat(aname, "::OnTouch");
if (npc_event(sd, aname, 0) > 0)
npc_click(sd, m->npc[i]->bl_id);
break;
@@ -658,9 +642,9 @@ int npc_click(dumb_ptr<map_session_data> sd, int id)
sd->npc_pos = run_script(ScriptPointer(nd->as_script()->scr.script.get(), 0), sd->bl_id, id);
break;
case NpcSubtype::MESSAGE:
- if (!nd->as_message()->message.empty())
+ if (nd->as_message()->message)
{
- clif_scriptmes(sd, id, nd->as_message()->message.c_str());
+ clif_scriptmes(sd, id, nd->as_message()->message);
clif_scriptclose(sd, id);
}
break;
@@ -893,9 +877,9 @@ void npc_clearsrcfile(void)
* 読み込むnpcファイルの追加
*------------------------------------------
*/
-void npc_addsrcfile(const char *name)
+void npc_addsrcfile(FString name)
{
- if (strcasecmp(name, "clear") == 0)
+ if (name == "clear")
{
npc_clearsrcfile();
return;
@@ -908,9 +892,9 @@ void npc_addsrcfile(const char *name)
* 読み込むnpcファイルの削除
*------------------------------------------
*/
-void npc_delsrcfile(const char *name)
+void npc_delsrcfile(FString name)
{
- if (strcasecmp(name, "all") == 0)
+ if (name == "all")
{
npc_clearsrcfile();
return;
@@ -930,17 +914,15 @@ void npc_delsrcfile(const char *name)
* warp行解析
*------------------------------------------
*/
-int npc_parse_warp(const char *w1, const char *, const char *w3, const char *w4)
+int npc_parse_warp(XString w1, XString, NpcName w3, XString w4)
{
int x, y, xs, ys, to_x, to_y;
int i, j;
- char mapname[24], to_mapname[24];
+ MapName mapname, to_mapname;
dumb_ptr<npc_data_warp> nd;
- // 引数の個数チェック
- if (sscanf(w1, "%[^,],%d,%d", mapname, &x, &y) != 3 ||
- sscanf(w4, "%d,%d,%[^,],%d,%d", &xs, &ys, to_mapname, &to_x,
- &to_y) != 5)
+ if (!extract(w1, record<','>(&mapname, &x, &y)) ||
+ !extract(w4, record<','>(&xs, &ys, &to_mapname, &to_x, &to_y)))
{
PRINTF("bad warp line : %s\n", w3);
return 1;
@@ -958,8 +940,7 @@ int npc_parse_warp(const char *w1, const char *, const char *w3, const char *w4)
nd->bl_y = y;
nd->dir = DIR::S;
nd->flag = 0;
- strzcpy(nd->name, w3, 24);
- strzcpy(nd->exname, w3, 24);
+ nd->name = w3;
if (!battle_config.warp_point_debug)
nd->npc_class = WARP_CLASS;
@@ -970,7 +951,7 @@ int npc_parse_warp(const char *w1, const char *, const char *w3, const char *w4)
nd->opt1 = Opt1::ZERO;
nd->opt2 = Opt2::ZERO;
nd->opt3 = Opt3::ZERO;
- strzcpy(nd->warp.name, to_mapname, 16);
+ nd->warp.name = to_mapname;
xs += 2;
ys += 2;
nd->warp.x = to_x;
@@ -1004,24 +985,51 @@ int npc_parse_warp(const char *w1, const char *, const char *w3, const char *w4)
return 0;
}
+static
+bool extract(XString xs, npc_item_list *itv)
+{
+ XString name_or_id;
+ if (!extract(xs, record<':'>(&name_or_id, &itv->value)))
+ return false;
+ struct item_data *id = nullptr;
+ if (extract(name_or_id, &itv->nameid) && itv->nameid > 0)
+ goto return_true;
+
+ id = itemdb_searchname(stringish<ItemName>(name_or_id.rstrip()));
+ if (id == NULL)
+ return false;
+ itv->nameid = id->nameid;
+ goto return_true;
+
+return_true:
+ if (itv->value < 0)
+ {
+ if (id == NULL)
+ id = itemdb_search(itv->nameid);
+ itv->value = id->value_buy * abs(itv->value);
+ }
+ return true;
+}
+
/*==========================================
* shop行解析
*------------------------------------------
*/
static
-int npc_parse_shop(char *w1, char *, char *w3, char *w4)
+int npc_parse_shop(XString w1, XString, NpcName w3, ZString w4a)
{
- char *p;
int x, y;
DIR dir;
- char mapname[24];
+ MapName mapname;
dumb_ptr<npc_data_shop> nd;
+ ZString::iterator w4comma;
+ int npc_class;
- // 引数の個数チェック
- int dir_; // TODO use SSCANF or extract
- if (sscanf(w1, "%[^,],%d,%d,%d", mapname, &x, &y, &dir_) != 4
+ int dir_; // TODO use enum directly in extract
+ if (!extract(w1, record<','>(&mapname, &x, &y, &dir_))
|| dir_ < 0 || dir_ >= 8
- || strchr(w4, ',') == NULL)
+ || (w4comma = std::find(w4a.begin(), w4a.end(), ',')) == w4a.end()
+ || !extract(w4a.xislice_h(w4comma), &npc_class))
{
PRINTF("bad shop line : %s\n", w3);
return 1;
@@ -1030,44 +1038,15 @@ int npc_parse_shop(char *w1, char *, char *w3, char *w4)
map_local *m = map_mapname2mapid(mapname);
nd.new_();
- p = strchr(w4, ',');
+ ZString w4b = w4a.xislice_t(w4comma + 1);
- while (p)
+ if (!extract(w4b, vrec<','>(&nd->shop_items)))
{
- int nameid, value;
- char name[24];
- struct item_data *id = NULL;
- p++;
- if (sscanf(p, "%d:%d", &nameid, &value) == 2)
- {
- }
- else if (sscanf(p, "%s :%d", name, &value) == 2)
- {
- id = itemdb_searchname(name);
- if (id == NULL)
- nameid = -1;
- else
- nameid = id->nameid;
- }
- else
- break;
-
- if (nameid > 0)
- {
- npc_item_list sh_it;
- sh_it.nameid = nameid;
- if (value < 0)
- {
- if (id == NULL)
- id = itemdb_search(nameid);
- value = id->value_buy * abs(value);
-
- }
- sh_it.value = value;
- nd->shop_items.push_back(sh_it);
- }
- p = strchr(p, ',');
+ PRINTF("bad shop items : %s\n", w3);
+ PRINTF(" somewhere --> %s\n", w4b);
+ nd->shop_items.clear();
}
+
if (nd->shop_items.empty())
{
nd.delete_();
@@ -1081,15 +1060,14 @@ int npc_parse_shop(char *w1, char *, char *w3, char *w4)
nd->bl_id = npc_get_new_npc_id();
nd->dir = dir;
nd->flag = 0;
- strzcpy(nd->name, w3, 24);
- nd->npc_class = atoi(w4);
+ nd->name = w3;
+ nd->npc_class = npc_class;
nd->speed = std::chrono::milliseconds(200);
nd->option = Option::ZERO;
nd->opt1 = Opt1::ZERO;
nd->opt2 = Opt2::ZERO;
nd->opt3 = Opt3::ZERO;
- //PRINTF("shop npc %s %d read done\n",mapname,nd->bl_id);
npc_shop++;
nd->bl_type = BL::NPC;
nd->npc_subtype = NpcSubtype::SHOP;
@@ -1106,12 +1084,12 @@ int npc_parse_shop(char *w1, char *, char *w3, char *w4)
*------------------------------------------
*/
static
-void npc_convertlabel_db(const std::string& lname, int pos, dumb_ptr<npc_data_script> nd)
+void npc_convertlabel_db(ScriptLabel lname, int pos, dumb_ptr<npc_data_script> nd)
{
nullpo_retv(nd);
struct npc_label_list eln {};
- strzcpy(eln.name, lname.c_str(), sizeof(eln.name));
+ eln.name = lname;
eln.pos = pos;
nd->scr.label_listv.push_back(std::move(eln));
}
@@ -1121,20 +1099,19 @@ void npc_convertlabel_db(const std::string& lname, int pos, dumb_ptr<npc_data_sc
*------------------------------------------
*/
static
-int npc_parse_script(char *w1, char *w2, char *w3, char *w4,
- const char *first_line, FILE * fp, int *lines)
+int npc_parse_script(XString w1, XString w2, NpcName w3, ZString w4,
+ XString first_line, FILE *fp, int *lines)
{
int x, y;
DIR dir = DIR::S;
map_local *m;
int xs = 0, ys = 0, npc_class = 0; // [Valaris] thanks to fov
- char mapname[24];
+ MapName mapname;
std::unique_ptr<const ScriptBuffer> script = NULL;
dumb_ptr<npc_data_script> nd;
int evflag = 0;
- char *p;
- if (strcmp(w1, "-") == 0)
+ if (w1 == "-")
{
x = 0;
y = 0;
@@ -1142,11 +1119,10 @@ int npc_parse_script(char *w1, char *w2, char *w3, char *w4,
}
else
{
- // 引数の個数チェック
- int dir_; // TODO use SSCANF or extract
- if (sscanf(w1, "%[^,],%d,%d,%d", mapname, &x, &y, &dir_) != 4
+ int dir_; // TODO use enum directly in extract
+ if (!extract(w1, record<','>(&mapname, &x, &y, &dir_))
|| dir_ < 0 || dir_ >= 8
- || (strcmp(w2, "script") == 0 && strchr(w4, ',') == NULL))
+ || (w2 == "script" && !w4.contains(',')))
{
PRINTF("bad script line : %s\n", w3);
return 1;
@@ -1155,29 +1131,33 @@ int npc_parse_script(char *w1, char *w2, char *w3, char *w4,
m = map_mapname2mapid(mapname);
}
- if (strcmp(w2, "script") == 0)
+ if (w2 == "script")
{
// may be empty
- std::string srcbuf = strchrnul(first_line, '{');
+ MString srcbuf;
+ srcbuf += first_line.xislice_t(std::find(first_line.begin(), first_line.end(), '{'));
// Note: it was a bug that this was missing. I think.
int startline = *lines;
- while (1)
+ // while (!srcbuf.rstrip().endswith('}'))
+ while (true)
{
- size_t i = srcbuf.find_last_not_of(" \t\n\r\f\v");
- if (i != std::string::npos && srcbuf[i] == '}')
+ auto it = std::find_if_not(srcbuf.rbegin(), srcbuf.rend(), [](char c){ return c == ' ' || c == '\n'; });
+ if (it != srcbuf.rend() && *it == '}')
break;
- char line[1024];
- if (!fgets(line, 1020, fp))
+
+ char line_[1024];
+ if (!fgets(line_, 1020, fp))
// eof
break;
(*lines)++;
if (feof(fp))
break;
- if (srcbuf.empty())
+ ZString line(ZString::really_construct_from_a_pointer, line_, nullptr);
+ if (!srcbuf)
{
// may be a no-op
- srcbuf = strchrnul(line, '{');
+ srcbuf += line.xislice_t(std::find(line.begin(), line.end(), '{'));
// safe to execute more than once
// But will usually only happen once
startline = *lines;
@@ -1185,7 +1165,7 @@ int npc_parse_script(char *w1, char *w2, char *w3, char *w4,
else
srcbuf += line;
}
- script = parse_script(srcbuf.c_str(), startline);
+ script = parse_script(FString(srcbuf), startline);
if (script == NULL)
// script parse error?
return 1;
@@ -1200,13 +1180,9 @@ int npc_parse_script(char *w1, char *w2, char *w3, char *w4,
if (m == nullptr)
{
- // スクリプトコピー用のダミーNPC
}
- else if (sscanf(w4, "%d,%d,%d", &npc_class, &xs, &ys) == 3)
+ else if (extract(w4, record<','>(&npc_class, &xs, &ys)))
{
- // 接触型NPC
- int i, j;
-
if (xs >= 0)
xs = xs * 2 + 1;
if (ys >= 0)
@@ -1215,9 +1191,9 @@ int npc_parse_script(char *w1, char *w2, char *w3, char *w4,
if (npc_class >= 0)
{
- for (i = 0; i < ys; i++)
+ for (int i = 0; i < ys; i++)
{
- for (j = 0; j < xs; j++)
+ for (int j = 0; j < xs; j++)
{
int x_lo = x - xs / 2;
int y_lo = y - ys / 2;
@@ -1235,32 +1211,24 @@ int npc_parse_script(char *w1, char *w2, char *w3, char *w4,
nd->scr.ys = ys;
}
else
- { // クリック型NPC
- npc_class = atoi(w4);
+ {
+ npc_class = atoi(w4.c_str());
nd->scr.xs = 0;
nd->scr.ys = 0;
}
if (npc_class < 0 && m != nullptr)
- { // イベント型NPC
+ {
evflag = 1;
}
- while ((p = strchr(w3, ':')))
- {
- if (p[1] == ':')
- break;
- }
- if (p)
+ if (w3.contains(':'))
{
- *p = 0;
- strzcpy(nd->name, w3, 24);
- strzcpy(nd->exname, p + 2, 24);
+ assert(false && "feature removed");
+ abort();
}
- else
{
- strzcpy(nd->name, w3, 24);
- strzcpy(nd->exname, w3, 24);
+ nd->name = w3;
}
nd->bl_prev = nd->bl_next = NULL;
@@ -1288,37 +1256,36 @@ int npc_parse_script(char *w1, char *w2, char *w3, char *w4,
map_addblock(nd);
if (evflag)
- { // イベント型
+ {
struct event_data ev {};
ev.nd = nd;
ev.pos = 0;
- ev_db.insert(nd->exname, ev);
+ NpcEvent npcev;
+ npcev.npc = nd->name;
+ npcev.label = ScriptLabel();
+ ev_db.insert(npcev, ev);
}
else
clif_spawnnpc(nd);
}
- npcname_db.put(nd->exname, nd);
+ npcname_db.put(nd->name, nd);
for (auto& pair : scriptlabel_db)
npc_convertlabel_db(pair.first, pair.second, nd);
for (npc_label_list& el : nd->scr.label_listv)
{
- char *lname = el.name;
+ ScriptLabel lname = el.name;
int pos = el.pos;
- if ((lname[0] == 'O' || lname[0] == 'o')
- && (lname[1] == 'N' || lname[1] == 'n'))
+ if (lname.startswith("On"))
{
- if (strlen(lname) > 24)
- {
- PRINTF("npc_parse_script: label name error !\n");
- exit(1);
- }
struct event_data ev {};
ev.nd = nd;
ev.pos = pos;
- std::string buf = STRPRINTF("%s::%s", nd->exname, lname);
+ NpcEvent buf;
+ buf.npc = nd->name;
+ buf.label = lname;
ev_db.insert(buf, ev);
}
}
@@ -1327,10 +1294,10 @@ int npc_parse_script(char *w1, char *w2, char *w3, char *w4,
// ラベルデータからタイマーイベント取り込み
for (npc_label_list& el : nd->scr.label_listv)
{
- int t_ = 0, n = 0;
- char *lname = el.name;
+ int t_ = 0;
+ ScriptLabel lname = el.name;
int pos = el.pos;
- if (sscanf(lname, "OnTimer%d%n", &t_, &n) == 1 && lname[n] == '\0')
+ if (lname.startswith("OnTimer") && extract(lname.xslice_t(7), &t_))
{
interval_t t = static_cast<interval_t>(t_);
@@ -1360,40 +1327,41 @@ int npc_parse_script(char *w1, char *w2, char *w3, char *w4,
*------------------------------------------
*/
static
-int npc_parse_function(char *, char *, char *w3, char *,
- char *first_line, FILE * fp, int *lines)
+int npc_parse_function(XString, XString, XString w3, ZString,
+ XString first_line, FILE *fp, int *lines)
{
- std::string srcbuf = strchrnul(first_line, '{');
+ MString srcbuf;
+ srcbuf += first_line.xislice_t(std::find(first_line.begin(), first_line.end(), '{'));
int startline = *lines;
- while (1)
+ while (true)
{
- size_t i = srcbuf.find_last_not_of(" \t\n\r\f\v");
- if (i != std::string::npos && srcbuf[i] == '}')
+ auto it = std::find_if_not(srcbuf.rbegin(), srcbuf.rend(), [](char c){ return c == ' ' || c == '\n'; });
+ if (it != srcbuf.rend() && *it == '}')
break;
- char line[1024];
- if (!fgets(line, 1020, fp))
+ char line_[1024];
+ if (!fgets(line_, 1020, fp))
break;
(*lines)++;
if (feof(fp))
break;
- if (srcbuf.empty())
+ ZString line(ZString::really_construct_from_a_pointer, line_, nullptr);
+ if (!srcbuf)
{
- srcbuf = strchrnul(line, '{');
+ srcbuf += line.xislice_t(std::find(line.begin(), line.end(), '{'));
startline = *lines;
}
else
srcbuf += line;
}
- std::unique_ptr<const ScriptBuffer> script = parse_script(srcbuf.c_str(), startline);
+ std::unique_ptr<const ScriptBuffer> script = parse_script(FString(srcbuf), startline);
if (script == NULL)
{
// script parse error?
return 1;
}
- std::string p = w3;
- userfunc_db.put(p, std::move(script));
+ userfunc_db.put(w3, std::move(script));
return 0;
}
@@ -1403,20 +1371,18 @@ int npc_parse_function(char *, char *, char *w3, char *,
*------------------------------------------
*/
static
-int npc_parse_mob(const char *w1, const char *, const char *w3, const char *w4)
+int npc_parse_mob(XString w1, XString, MobName w3, ZString w4)
{
int x, y, xs, ys, mob_class, num;
int i;
- char mapname[24];
- char eventname[24] = "";
+ MapName mapname;
+ NpcEvent eventname;
dumb_ptr<mob_data> md;
xs = ys = 0;
int delay1_ = 0, delay2_ = 0;
- // 引数の個数チェック
- if (sscanf(w1, "%[^,],%d,%d,%d,%d", mapname, &x, &y, &xs, &ys) < 3 ||
- sscanf(w4, "%d,%d,%d,%d,%s", &mob_class, &num, &delay1_, &delay2_,
- eventname) < 2)
+ if (!extract(w1, record<',', 3>(&mapname, &x, &y, &xs, &ys)) ||
+ !extract(w4, record<',', 2>(&mob_class, &num, &delay1_, &delay2_, &eventname)))
{
PRINTF("bad monster line : %s\n", w3);
return 1;
@@ -1441,12 +1407,12 @@ int npc_parse_mob(const char *w1, const char *, const char *w3, const char *w4)
md->bl_m = m;
md->bl_x = x;
md->bl_y = y;
- if (strcmp(w3, "--en--") == 0)
- strzcpy(md->name, mob_db[mob_class].name, 24);
- else if (strcmp(w3, "--ja--") == 0)
- strzcpy(md->name, mob_db[mob_class].jname, 24);
+ if (w3 == ENGLISH_NAME)
+ md->name = mob_db[mob_class].name;
+ else if (w3 == JAPANESE_NAME)
+ md->name = mob_db[mob_class].jname;
else
- strzcpy(md->name, w3, 24);
+ md->name = w3;
md->n = i;
md->mob_class = mob_class;
@@ -1466,10 +1432,7 @@ int npc_parse_mob(const char *w1, const char *, const char *w3, const char *w4)
md->lootitemv.clear();
- if (strlen(eventname) >= 4)
- strzcpy(md->npc_event, eventname, 24);
- else
- strzcpy(md->npc_event, "", 24);
+ md->npc_event = eventname;
md->bl_type = BL::MOB;
map_addiddb(md);
@@ -1487,123 +1450,121 @@ int npc_parse_mob(const char *w1, const char *, const char *w3, const char *w4)
*------------------------------------------
*/
static
-int npc_parse_mapflag(char *w1, char *, char *w3, char *w4)
+int npc_parse_mapflag(XString w1, XString, XString w3, ZString w4)
{
- char mapname[24], savemap[16];
+ MapName mapname, savemap;
int savex, savey;
- // 引数の個数チェック
-// if ( sscanf(w1,"%[^,],%d,%d,%d",mapname,&x,&y,&dir) != 4 )
- if (sscanf(w1, "%[^,]", mapname) != 1)
+ mapname = stringish<MapName>(w1);
+ if (!mapname)
return 1;
map_local *m = map_mapname2mapid(mapname);
if (m == nullptr)
return 1;
-//マップフラグ
- if (strcasecmp(w3, "nosave") == 0)
+ if (w3 == "nosave")
{
- if (strcmp(w4, "SavePoint") == 0)
+ if (w4 == "SavePoint")
{
- strzcpy(m->save.map_, "SavePoint", 16);
+ m->save.map_ = stringish<MapName>("SavePoint");
m->save.x = -1;
m->save.y = -1;
}
- else if (sscanf(w4, "%[^,],%d,%d", savemap, &savex, &savey) == 3)
+ else if (extract(w4, record<','>(&savemap, &savex, &savey)))
{
- strzcpy(m->save.map_, savemap, 16);
+ m->save.map_ = savemap;
m->save.x = savex;
m->save.y = savey;
}
m->flag.nosave = 1;
}
- else if (strcasecmp(w3, "nomemo") == 0)
+ else if (w3 == "nomemo")
{
m->flag.nomemo = 1;
}
- else if (strcasecmp(w3, "noteleport") == 0)
+ else if (w3 == "noteleport")
{
m->flag.noteleport = 1;
}
- else if (strcasecmp(w3, "nowarp") == 0)
+ else if (w3 == "nowarp")
{
m->flag.nowarp = 1;
}
- else if (strcasecmp(w3, "nowarpto") == 0)
+ else if (w3 == "nowarpto")
{
m->flag.nowarpto = 1;
}
- else if (strcasecmp(w3, "noreturn") == 0)
+ else if (w3 == "noreturn")
{
m->flag.noreturn = 1;
}
- else if (strcasecmp(w3, "monster_noteleport") == 0)
+ else if (w3 == "monster_noteleport")
{
m->flag.monster_noteleport = 1;
}
- else if (strcasecmp(w3, "nobranch") == 0)
+ else if (w3 == "nobranch")
{
m->flag.nobranch = 1;
}
- else if (strcasecmp(w3, "nopenalty") == 0)
+ else if (w3 == "nopenalty")
{
m->flag.nopenalty = 1;
}
- else if (strcasecmp(w3, "pvp") == 0)
+ else if (w3 == "pvp")
{
m->flag.pvp = 1;
}
- else if (strcasecmp(w3, "pvp_noparty") == 0)
+ else if (w3 == "pvp_noparty")
{
m->flag.pvp_noparty = 1;
}
- else if (strcasecmp(w3, "pvp_nocalcrank") == 0)
+ else if (w3 == "pvp_nocalcrank")
{
m->flag.pvp_nocalcrank = 1;
}
- else if (strcasecmp(w3, "nozenypenalty") == 0)
+ else if (w3 == "nozenypenalty")
{
m->flag.nozenypenalty = 1;
}
- else if (strcasecmp(w3, "notrade") == 0)
+ else if (w3 == "notrade")
{
m->flag.notrade = 1;
}
- else if (battle_config.pk_mode && strcasecmp(w3, "nopvp") == 0)
+ else if (battle_config.pk_mode && w3 == "nopvp")
{ // nopvp for pk mode [Valaris]
m->flag.nopvp = 1;
m->flag.pvp = 0;
}
- else if (strcasecmp(w3, "noicewall") == 0)
+ else if (w3 == "noicewall")
{ // noicewall [Valaris]
m->flag.noicewall = 1;
}
- else if (strcasecmp(w3, "snow") == 0)
+ else if (w3 == "snow")
{ // snow [Valaris]
m->flag.snow = 1;
}
- else if (strcasecmp(w3, "fog") == 0)
+ else if (w3 == "fog")
{ // fog [Valaris]
m->flag.fog = 1;
}
- else if (strcasecmp(w3, "sakura") == 0)
+ else if (w3 == "sakura")
{ // sakura [Valaris]
m->flag.sakura = 1;
}
- else if (strcasecmp(w3, "leaves") == 0)
+ else if (w3 == "leaves")
{ // leaves [Valaris]
m->flag.leaves = 1;
}
- else if (strcasecmp(w3, "rain") == 0)
+ else if (w3 == "rain")
{ // rain [Valaris]
m->flag.rain = 1;
}
- else if (strcasecmp(w3, "no_player_drops") == 0)
+ else if (w3 == "no_player_drops")
{ // no player drops [Jaxad0127]
m->flag.no_player_drops = 1;
}
- else if (strcasecmp(w3, "town") == 0)
+ else if (w3 == "town")
{ // town/safe zone [remoitnane]
m->flag.town = 1;
}
@@ -1612,7 +1573,7 @@ int npc_parse_mapflag(char *w1, char *, char *w3, char *w4)
}
dumb_ptr<npc_data> npc_spawn_text(map_local *m, int x, int y,
- int npc_class, const char *name, const char *message)
+ int npc_class, NpcName name, FString message)
{
dumb_ptr<npc_data_message> retval;
retval.new_();
@@ -1623,8 +1584,7 @@ dumb_ptr<npc_data> npc_spawn_text(map_local *m, int x, int y,
retval->bl_type = BL::NPC;
retval->npc_subtype = NpcSubtype::MESSAGE;
- strzcpy(retval->name, name, 24);
- strzcpy(retval->exname, name, 24);
+ retval->name = name;
if (message)
retval->message = message;
@@ -1656,7 +1616,7 @@ void npc_free_internal(dumb_ptr<npc_data> nd_)
else if (nd_->npc_subtype == NpcSubtype::MESSAGE)
{
dumb_ptr<npc_data_message> nd = nd_->as_message();
- nd->message.clear();
+ nd->message = FString();
}
nd_.delete_();
}
@@ -1699,100 +1659,91 @@ int do_init_npc(void)
for (; !npc_srcs.empty(); npc_srcs.pop_front())
{
- std::string& nsl = npc_srcs.front();
- FILE *fp = fopen_(nsl.c_str(), "r");
+ FString nsl = npc_srcs.front();
+ FILE *fp = fopen(nsl.c_str(), "r");
if (fp == NULL)
{
PRINTF("file not found : %s\n", nsl);
exit(1);
}
int lines = 0;
- char line[1024];
- while (fgets(line, 1020, fp))
+ char line_[1024];
+ while (fgets(line_, 1020, fp))
{
- char w1[1024], w2[1024], w3[1024], w4[1024], mapname[1024];
- int i, j, w4pos, count;
+ // because it's still fgets
+ line_[strlen(line_) - 1] = '\0';
+ ZString zline(ZString::really_construct_from_a_pointer, line_, nullptr);
+ XString w1, w2, w3, w4x;
+ ZString w4z;
lines++;
- if (line[0] == '/' && line[1] == '/')
+ if (!zline)
+ continue;
+ if (zline.startswith("//"))
continue;
- // 不要なスペースやタブの連続は詰める
- for (i = j = 0; line[i]; i++)
+
+ if (!extract(zline, record<'|', 3>(&w1, &w2, &w3, &w4x)) || !w1 || !w2 || !w3)
{
- if (line[i] == ' ')
- {
- if (!
- ((line[i + 1]
- && (isspace(line[i + 1]) || line[i + 1] == ','))
- || (j && line[j - 1] == ',')))
- line[j++] = ' ';
- }
- else if (line[i] == '\t' || line[i] == '|')
- {
- if (!(j && (line[j - 1] == '\t' || line[j - 1] == '|')))
- line[j++] = '\t';
- }
- else
- line[j++] = line[i];
+ FPRINTF(stderr, "%s:%d: Broken script line: %s\n", nsl, lines, zline);
+ continue;
}
- // 最初はタブ区切りでチェックしてみて、ダメならスペース区切りで確認
- if ((count =
- sscanf(line, "%[^\t]\t%[^\t]\t%[^\t\r\n]\t%n%[^\t\r\n]", w1,
- w2, w3, &w4pos, w4)) < 3
- && (count =
- sscanf(line, "%s%s%s%n%s", w1, w2, w3, &w4pos, w4)) < 3)
+ if (&*w4x.end() == &*zline.end())
{
- continue;
+ w4z = zline.xrslice_t(w4x.size());
}
- // マップの存在確認
- if (strcmp(w1, "-") != 0 && strcasecmp(w1, "function") != 0)
+ assert(bool(w4x) == bool(w4z));
+
+ if (w1 != "-" && w1 != "function")
{
- sscanf(w1, "%[^,]", mapname);
+ auto comma = std::find(w1.begin(), w1.end(), ',');
+ MapName mapname = stringish<MapName>(w1.xislice_h(comma));
map_local *m = map_mapname2mapid(mapname);
- if (strlen(mapname) > 16 || m == nullptr)
+ if (m == nullptr)
{
// "mapname" is not assigned to this server
+ FPRINTF(stderr, "%s:%d: Map not found: %s\n", nsl, lines, mapname);
continue;
}
}
- if (strcasecmp(w2, "warp") == 0 && count > 3)
+ if (w2 == "warp")
{
- npc_parse_warp(w1, w2, w3, w4);
+ NpcName npcname = stringish<NpcName>(w3);
+ npc_parse_warp(w1, w2, npcname, w4z);
}
- else if (strcasecmp(w2, "shop") == 0 && count > 3)
+ else if (w2 == "shop")
{
- npc_parse_shop(w1, w2, w3, w4);
+ NpcName npcname = stringish<NpcName>(w3);
+ npc_parse_shop(w1, w2, npcname, w4z);
}
- else if (strcasecmp(w2, "script") == 0 && count > 3)
+ else if (w2 == "script")
{
- if (strcasecmp(w1, "function") == 0)
+ if (w1 == "function")
{
- npc_parse_function(w1, w2, w3, w4, line + w4pos, fp,
- &lines);
+ npc_parse_function(w1, w2, w3, w4z,
+ w4x, fp, &lines);
}
else
{
- npc_parse_script(w1, w2, w3, w4, line + w4pos, fp,
- &lines);
+ NpcName npcname = stringish<NpcName>(w3);
+ npc_parse_script(w1, w2, npcname, w4z,
+ w4x, fp, &lines);
}
}
- else if ((i =
- 0, sscanf(w2, "duplicate%n", &i), (i > 0
- && w2[i] == '('))
- && count > 3)
+ else if (w2 == "monster")
{
- npc_parse_script(w1, w2, w3, w4, line + w4pos, fp, &lines);
+ MobName mobname = stringish<MobName>(w3);
+ npc_parse_mob(w1, w2, mobname, w4z);
}
- else if (strcasecmp(w2, "monster") == 0 && count > 3)
+ else if (w2 == "mapflag")
{
- npc_parse_mob(w1, w2, w3, w4);
+ npc_parse_mapflag(w1, w2, w3, w4z);
}
- else if (strcasecmp(w2, "mapflag") == 0 && count >= 3)
+ else
{
- npc_parse_mapflag(w1, w2, w3, w4);
+ PRINTF("odd script line: %s\n", zline);
}
}
- fclose_(fp);
+ fclose(fp);
PRINTF("\rLoading NPCs [%d]: %-54s", npc_id - START_NPC_NUM,
nsl);
fflush(stdout);
diff --git a/src/map/npc.hpp b/src/map/npc.hpp
index 539152f..36f4e4d 100644
--- a/src/map/npc.hpp
+++ b/src/map/npc.hpp
@@ -15,19 +15,19 @@ constexpr int WARP_DEBUG_CLASS = 722;
constexpr int INVISIBLE_CLASS = 32767;
int npc_event_dequeue(dumb_ptr<map_session_data> sd);
-int npc_event(dumb_ptr<map_session_data> sd, const char *npcname, int);
-int npc_timer_event(const char *eventname); // Added by RoVeRT
-int npc_command(dumb_ptr<map_session_data> sd, const char *npcname, const char *command);
+int npc_event(dumb_ptr<map_session_data> sd, NpcEvent npcname, int);
+void npc_timer_event(NpcEvent eventname); // Added by RoVeRT
+int npc_command(dumb_ptr<map_session_data> sd, NpcName npcname, XString command);
int npc_touch_areanpc(dumb_ptr<map_session_data>, map_local *, int, int);
int npc_click(dumb_ptr<map_session_data>, int);
int npc_scriptcont(dumb_ptr<map_session_data>, int);
int npc_buysellsel(dumb_ptr<map_session_data>, int, int);
int npc_buylist(dumb_ptr<map_session_data>, int, const uint16_t *);
int npc_selllist(dumb_ptr<map_session_data>, int, const uint16_t *);
-int npc_parse_warp(const char *w1, const char *w2, const char *w3, const char *w4);
+int npc_parse_warp(XString w1, XString, NpcName w3, XString w4);
-int npc_enable(const char *name, bool flag);
-dumb_ptr<npc_data> npc_name2id(const char *name);
+int npc_enable(NpcName name, bool flag);
+dumb_ptr<npc_data> npc_name2id(NpcName name);
int npc_get_new_npc_id(void);
@@ -37,30 +37,27 @@ int npc_get_new_npc_id(void);
* \param message The message to speak. If message is NULL, the NPC will not do anything at all.
*/
dumb_ptr<npc_data> npc_spawn_text(map_local *m, int x, int y,
- int class_, const char *name, const char *message); // message is strdup'd within
+ int class_, NpcName name, FString message);
/**
* Uninstalls and frees an NPC
*/
void npc_free(dumb_ptr<npc_data> npc);
-void npc_addsrcfile(const char *);
-void npc_delsrcfile(const char *);
+void npc_addsrcfile(FString);
+void npc_delsrcfile(FString);
int do_init_npc(void);
int npc_event_do_oninit(void);
-struct argrec;
-int npc_event_doall_l(const char *name, int rid,
- int argc, struct argrec *argv);
-int npc_event_do_l(const char *name, int rid,
- int argc, struct argrec *argv);
+int npc_event_doall_l(ScriptLabel name, int rid, int argc, struct argrec_t *argv);
+int npc_event_do_l(NpcEvent name, int rid, int argc, struct argrec_t *argv);
inline
-int npc_event_doall(const char *name)
+int npc_event_doall(ScriptLabel name)
{
return npc_event_doall_l(name, 0, 0, NULL);
}
inline
-int npc_event_do(const char *name)
+int npc_event_do(NpcEvent name)
{
return npc_event_do_l(name, 0, 0, NULL);
}
diff --git a/src/map/party.cpp b/src/map/party.cpp
index 62493c8..c6b0bcc 100644
--- a/src/map/party.cpp
+++ b/src/map/party.cpp
@@ -44,14 +44,14 @@ struct party *party_search(int party_id)
}
static
-void party_searchname_sub(struct party *p, const char *str, struct party **dst)
+void party_searchname_sub(struct party *p, PartyName str, struct party **dst)
{
- if (strcasecmp(p->name, str) == 0)
+ if (p->name == str)
*dst = p;
}
// パーティ名検索
-struct party *party_searchname(const char *str)
+struct party *party_searchname(PartyName str)
{
struct party *p = NULL;
for (auto& pair : party_db)
@@ -60,21 +60,19 @@ struct party *party_searchname(const char *str)
}
/* Process a party creation request. */
-int party_create(dumb_ptr<map_session_data> sd, const char *name)
+int party_create(dumb_ptr<map_session_data> sd, PartyName name)
{
- char pname[24];
nullpo_ret(sd);
- strzcpy(pname, name, 24);
- tmw_TrimStr(pname);
+ name = stringish<PartyName>(name.strip());
/* The party name is empty/invalid. */
- if (!*pname)
+ if (!name)
clif_party_created(sd, 1);
/* Make sure the character isn't already in a party. */
if (sd->status.party_id == 0)
- intif_create_party(sd, pname);
+ intif_create_party(sd, name);
else
clif_party_created(sd, 2);
@@ -82,7 +80,7 @@ int party_create(dumb_ptr<map_session_data> sd, const char *name)
}
/* Relay the result of a party creation request. */
-void party_created(int account_id, int fail, int party_id, const char *name)
+void party_created(int account_id, int fail, int party_id, PartyName name)
{
dumb_ptr<map_session_data> sd;
sd = map_id2sd(account_id);
@@ -103,7 +101,7 @@ void party_created(int account_id, int fail, int party_id, const char *name)
p = party_db.init(party_id);
p->party_id = party_id;
- strzcpy(p->name, name, 24);
+ p->name = name;
/* The party was created successfully. */
clif_party_created(sd, 0);
@@ -139,7 +137,7 @@ int party_check_member(struct party *p)
{ // パーティにデータがあるか確認
if (p->member[j].account_id == sd->status.account_id)
{
- if (strcmp(p->member[j].name, sd->status.name) == 0)
+ if (p->member[j].name == sd->status.name)
f = 0; // データがある
else
{
@@ -369,7 +367,7 @@ int party_member_added(int party_id, int account_id, int flag)
}
// パーティ除名要求
-int party_removemember(dumb_ptr<map_session_data> sd, int account_id, const char *)
+int party_removemember(dumb_ptr<map_session_data> sd, int account_id)
{
struct party *p;
int i;
@@ -420,7 +418,7 @@ int party_leave(dumb_ptr<map_session_data> sd)
}
// パーティメンバが脱退した
-int party_member_leaved(int party_id, int account_id, const char *name)
+int party_member_leaved(int party_id, int account_id, CharName name)
{
dumb_ptr<map_session_data> sd = map_id2sd(account_id);
struct party *p = party_search(party_id);
@@ -499,8 +497,8 @@ int party_optionchanged(int party_id, int account_id, int exp, int item,
}
// パーティメンバの移動通知
-void party_recv_movemap(int party_id, int account_id, const char *mapname, int online,
- int lv)
+void party_recv_movemap(int party_id, int account_id, MapName mapname,
+ int online, int lv)
{
struct party *p;
int i;
@@ -516,7 +514,7 @@ void party_recv_movemap(int party_id, int account_id, const char *mapname, int o
}
if (m->account_id == account_id)
{
- strzcpy(m->map, mapname, 16);
+ m->map = mapname;
m->online = online;
m->lv = lv;
break;
@@ -597,7 +595,7 @@ int party_send_logout(dumb_ptr<map_session_data> sd)
}
// パーティメッセージ送信
-void party_send_message(dumb_ptr<map_session_data> sd, const char *mes)
+void party_send_message(dumb_ptr<map_session_data> sd, XString mes)
{
if (sd->status.party_id == 0)
return;
@@ -605,7 +603,7 @@ void party_send_message(dumb_ptr<map_session_data> sd, const char *mes)
}
// パーティメッセージ受信
-void party_recv_message(int party_id, int account_id, const char *mes)
+void party_recv_message(int party_id, int account_id, XString mes)
{
struct party *p;
if ((p = party_search(party_id)) == NULL)
@@ -618,8 +616,8 @@ void party_check_conflict(dumb_ptr<map_session_data> sd)
{
nullpo_retv(sd);
- intif_party_checkconflict(sd->status.party_id, sd->status.account_id,
- sd->status.name);
+ intif_party_checkconflict(sd->status.party_id,
+ sd->status.account_id, sd->status.name);
}
// 位置やHP通知用
diff --git a/src/map/party.hpp b/src/map/party.hpp
index c27cc08..80679ad 100644
--- a/src/map/party.hpp
+++ b/src/map/party.hpp
@@ -11,22 +11,21 @@ struct block_list;
void do_init_party(void);
struct party *party_search(int party_id);
-struct party *party_searchname(const char *str);
+struct party *party_searchname(PartyName str);
-int party_create(dumb_ptr<map_session_data> sd, const char *name);
-void party_created(int account_id, int fail, int party_id, const char *name);
+int party_create(dumb_ptr<map_session_data> sd, PartyName name);
+void party_created(int account_id, int fail, int party_id, PartyName name);
void party_request_info(int party_id);
int party_invite(dumb_ptr<map_session_data> sd, int account_id);
int party_member_added(int party_id, int account_id, int flag);
int party_leave(dumb_ptr<map_session_data> sd);
-int party_removemember(dumb_ptr<map_session_data> sd, int account_id,
- const char *name);
-int party_member_leaved(int party_id, int account_id, const char *name);
+int party_removemember(dumb_ptr<map_session_data> sd, int account_id);
+int party_member_leaved(int party_id, int account_id, CharName name);
int party_reply_invite(dumb_ptr<map_session_data> sd, int account_id,
int flag);
int party_recv_noinfo(int party_id);
int party_recv_info(const struct party *sp);
-void party_recv_movemap(int party_id, int account_id, const char *map,
+void party_recv_movemap(int party_id, int account_id, MapName map,
int online, int lv);
int party_broken(int party_id);
int party_optionchanged(int party_id, int account_id, int exp, int item,
@@ -36,8 +35,8 @@ int party_changeoption(dumb_ptr<map_session_data> sd, int exp, int item);
int party_send_movemap(dumb_ptr<map_session_data> sd);
int party_send_logout(dumb_ptr<map_session_data> sd);
-void party_send_message(dumb_ptr<map_session_data> sd, const char *mes);
-void party_recv_message(int party_id, int account_id, const char *mes);
+void party_send_message(dumb_ptr<map_session_data> sd, XString mes);
+void party_recv_message(int party_id, int account_id, XString mes);
void party_send_xy_clear(struct party *p);
void party_send_hp_check(dumb_ptr<block_list> bl, int party_id, int *flag);
diff --git a/src/map/pc.cpp b/src/map/pc.cpp
index 08f873a..8cc74b8 100644
--- a/src/map/pc.cpp
+++ b/src/map/pc.cpp
@@ -7,8 +7,9 @@
#include <fstream>
#include "../common/cxxstdio.hpp"
-#include "../common/random.hpp"
+#include "../common/io.hpp"
#include "../common/nullpo.hpp"
+#include "../common/random.hpp"
#include "../common/socket.hpp"
#include "../common/timer.hpp"
@@ -56,7 +57,7 @@ constexpr int MAGIC_SKILL_THRESHOLD = 200;
MAP_LOG_PC(sd, "XP %d %d JOB %d %d %d ZENY %d + %d " suffix, \
sd->status.base_level, sd->status.base_exp, \
sd->status.job_level, sd->status.job_exp, sd->status.skill_point, \
- sd->status.zeny, pc_readaccountreg(sd, "BankAccount"))
+ sd->status.zeny, pc_readaccountreg(sd, stringish<VarName>("BankAccount")))
#define MAP_LOG_MAGIC(sd, suffix) \
MAP_LOG_PC(sd, "MAGIC %d %d %d %d %d %d EXP %d %d " suffix, \
@@ -66,8 +67,8 @@ constexpr int MAGIC_SKILL_THRESHOLD = 200;
sd->status.skill[SkillID::TMW_MAGIC_TRANSMUTE].lv, \
sd->status.skill[SkillID::TMW_MAGIC_NATURE].lv, \
sd->status.skill[SkillID::TMW_MAGIC_ETHER].lv, \
- pc_readglobalreg(sd, "MAGIC_EXPERIENCE") & 0xffff, \
- (pc_readglobalreg(sd, "MAGIC_EXPERIENCE") >> 24) & 0xff)
+ pc_readglobalreg(sd, stringish<VarName>("MAGIC_EXPERIENCE")) & 0xffff, \
+ (pc_readglobalreg(sd, stringish<VarName>("MAGIC_EXPERIENCE")) >> 24) & 0xff)
static //const
int max_weight_base_0 = 20000;
@@ -412,7 +413,7 @@ void pc_makesavestatus(dumb_ptr<map_session_data> sd)
}
else
{
- strzcpy(sd->status.last_point.map_, sd->mapname_, 16);
+ sd->status.last_point.map_ = sd->mapname_;
sd->status.last_point.x = sd->bl_x;
sd->status.last_point.y = sd->bl_y;
}
@@ -421,7 +422,7 @@ void pc_makesavestatus(dumb_ptr<map_session_data> sd)
if (sd->bl_m->flag.nosave)
{
map_local *m = sd->bl_m;
- if (strcmp(m->save.map_, "SavePoint") == 0)
+ if (m->save.map_ == "SavePoint")
sd->status.last_point = sd->status.save_point;
else
sd->status.last_point = m->save;
@@ -712,11 +713,11 @@ int pc_authok(int id, int login_id2, TimeT connect_until_time,
clif_authok(sd);
map_addnickdb(sd);
- if (map_charid2nick(sd->status.char_id) == NULL)
+ if (!map_charid2nick(sd->status.char_id).to__actual())
map_addchariddb(sd->status.char_id, sd->status.name);
//スパノビ用死にカウンターのスクリプト変数からの読み出しとsdへのセット
- sd->die_counter = pc_readglobalreg(sd, "PC_DIE_COUNTER");
+ sd->die_counter = pc_readglobalreg(sd, stringish<VarName>("PC_DIE_COUNTER"));
// ステータス初期計算など
pc_calcstatus(sd, 1);
@@ -732,12 +733,13 @@ int pc_authok(int id, int login_id2, TimeT connect_until_time,
sd->status.name, sd->status.account_id);
// TODO fix this to cache and use inotify
+ // this is far from the only such thing, but most of the others are logs
{
- std::ifstream in(motd_txt);
+ std::ifstream in(motd_txt.c_str());
if (in.is_open())
{
- std::string buf;
- while (std::getline(in, buf))
+ FString buf;
+ while (io::getline(in, buf))
{
clif_displaymessage(sd->fd, buf);
}
@@ -750,7 +752,7 @@ int pc_authok(int id, int login_id2, TimeT connect_until_time,
sd->chat_reset_due = TimeT();
sd->chat_lines_in = sd->chat_total_repeats = 0;
sd->chat_repeat_reset_due = TimeT();
- sd->chat_lastmsg[0] = '\0';
+ sd->chat_lastmsg = FString();
for (tick_t& t : sd->flood_rates)
t = tick_t();
@@ -768,7 +770,7 @@ int pc_authok(int id, int login_id2, TimeT connect_until_time,
char tmpstr[] = WITH_TIMESTAMP("Your account time limit is: ");
REPLACE_TIMESTAMP(tmpstr, connect_until_time);
- clif_wis_message(sd->fd, wisp_server_name, tmpstr);
+ clif_wis_message(sd->fd, wisp_server_name, const_(tmpstr));
}
pc_calcstatus(sd, 1);
@@ -1024,16 +1026,16 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first)
int c = sd->status.inventory[index].card[j];
if (c > 0)
{
- argrec_t arg[2];
- arg[0].name = "@slotId";
- arg[0].v.i = int(i);
- arg[1].name = "@itemId";
- arg[1].v.i = sd->inventory_data[index]->nameid;
+ argrec_t arg[2] =
+ {
+ {"@slotId", static_cast<int>(i)},
+ {"@itemId", sd->inventory_data[index]->nameid},
+ };
if (i == EQUIP::SHIELD
&& sd->status.inventory[index].equip == EPOS::SHIELD)
sd->state.lr_flag = 1;
- run_script_l(ScriptPointer(itemdb_equipscript(c), 0), sd->bl_id,
- 0, 2, arg);
+ run_script_l(ScriptPointer(itemdb_equipscript(c), 0), sd->bl_id, 0,
+ 2, arg);
sd->state.lr_flag = 0;
}
}
@@ -1050,13 +1052,13 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first)
{ // カード
int c = sd->status.inventory[index].card[j];
if (c > 0) {
- argrec_t arg[2];
- arg[0].name = "@slotId";
- arg[0].v.i = int(i);
- arg[1].name = "@itemId";
- arg[1].v.i = sd->inventory_data[index]->nameid;
- run_script_l(ScriptPointer(itemdb_equipscript(c), 0), sd->bl_id,
- 0, 2, arg);
+ argrec_t arg[2] =
+ {
+ {"@slotId", static_cast<int>(i)},
+ {"@itemId", sd->inventory_data[index]->nameid}
+ };
+ run_script_l(ScriptPointer(itemdb_equipscript(c), 0), sd->bl_id, 0,
+ 2, arg);
}
}
}
@@ -1113,23 +1115,25 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first)
sd->attackrange_ += sd->inventory_data[index]->range;
sd->state.lr_flag = 1;
{
- argrec_t arg[2];
- arg[0].name = "@slotId";
- arg[0].v.i = int(i);
- arg[1].name = "@itemId";
- arg[1].v.i = sd->inventory_data[index]->nameid;
+ argrec_t arg[2] =
+ {
+ {"@slotId", static_cast<int>(i)},
+ {"@itemId", sd->inventory_data[index]->nameid},
+ };
run_script_l(ScriptPointer(sd->inventory_data[index]->equip_script.get(), 0),
- sd->bl_id, 0, 2, arg);
+ sd->bl_id, 0,
+ 2, arg);
}
sd->state.lr_flag = 0;
}
else
- { //二刀流武器以外
- argrec_t arg[2];
- arg[0].name = "@slotId";
- arg[0].v.i = int(i);
- arg[1].name = "@itemId";
- arg[1].v.i = sd->inventory_data[index]->nameid;
+ {
+ //二刀流武器以外
+ argrec_t arg[2] =
+ {
+ {"@slotId", static_cast<int>(i)},
+ {"@itemId", sd->inventory_data[index]->nameid},
+ };
sd->watk += sd->inventory_data[index]->atk;
sd->watk2 += (r = sd->status.inventory[index].refine) * // 精錬攻撃力
0;
@@ -1142,21 +1146,23 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first)
}
sd->attackrange += sd->inventory_data[index]->range;
run_script_l(ScriptPointer(sd->inventory_data[index]->equip_script.get(), 0),
- sd->bl_id, 0, 2, arg);
+ sd->bl_id, 0,
+ 2, arg);
}
}
else if (sd->inventory_data[index]->type == ItemType::ARMOR)
{
- argrec_t arg[2];
- arg[0].name = "@slotId";
- arg[0].v.i = int(i);
- arg[1].name = "@itemId";
- arg[1].v.i = sd->inventory_data[index]->nameid;
+ argrec_t arg[2] =
+ {
+ {"@slotId", static_cast<int>(i)},
+ {"@itemId", sd->inventory_data[index]->nameid},
+ };
sd->watk += sd->inventory_data[index]->atk;
refinedef +=
sd->status.inventory[index].refine * 0;
run_script_l(ScriptPointer(sd->inventory_data[index]->equip_script.get(), 0),
- sd->bl_id, 0, 2, arg);
+ sd->bl_id, 0,
+ 2, arg);
}
}
}
@@ -1174,14 +1180,15 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first)
index = sd->equip_index[EQUIP::ARROW];
if (sd->inventory_data[index])
{ //まだ属性が入っていない
- argrec_t arg[2];
- arg[0].name = "@slotId";
- arg[0].v.i = int(EQUIP::ARROW);
- arg[1].name = "@itemId";
- arg[1].v.i = sd->inventory_data[index]->nameid;
+ argrec_t arg[2] =
+ {
+ {"@slotId", static_cast<int>(EQUIP::ARROW)},
+ {"@itemId", sd->inventory_data[index]->nameid},
+ };
sd->state.lr_flag = 2;
- run_script_l(ScriptPointer(sd->inventory_data[index]->equip_script.get(), 0), sd->bl_id,
- 0, 2, arg);
+ run_script_l(ScriptPointer(sd->inventory_data[index]->equip_script.get(), 0),
+ sd->bl_id, 0,
+ 2, arg);
sd->state.lr_flag = 0;
sd->arrow_atk += sd->inventory_data[index]->atk;
}
@@ -1888,7 +1895,6 @@ int pc_payzeny(dumb_ptr<map_session_data> sd, int zeny)
{
nullpo_ret(sd);
-#warning "Why is this a double?"
double z = sd->status.zeny;
if (sd->status.zeny < zeny || z - zeny > MAX_ZENY)
return 1;
@@ -2270,10 +2276,10 @@ int pc_useitem(dumb_ptr<map_session_data> sd, int n)
* PCの位置設定
*------------------------------------------
*/
-int pc_setpos(dumb_ptr<map_session_data> sd, const char *mapname_org, int x, int y,
- BeingRemoveWhy clrtype)
+int pc_setpos(dumb_ptr<map_session_data> sd,
+ MapName mapname_org, int x, int y, BeingRemoveWhy clrtype)
{
- char mapname_[16];
+ MapName mapname_;
nullpo_ret(sd);
@@ -2294,16 +2300,12 @@ int pc_setpos(dumb_ptr<map_session_data> sd, const char *mapname_org, int x, int
// pc_setstand (sd); // [fate] Nothing wrong with warping while sitting
}
- strzcpy(mapname_, mapname_org, 16);
- if (strstr(mapname_, ".gat") == NULL && strlen(mapname_) < 16 - 4)
- {
- strcat(mapname_, ".gat");
- }
+ mapname_ = mapname_org;
map_local *m = map_mapname2mapid(mapname_);
if (!m)
{
- if (sd->mapname_[0])
+ if (sd->mapname_)
{
struct in_addr ip;
int port;
@@ -2312,7 +2314,7 @@ int pc_setpos(dumb_ptr<map_session_data> sd, const char *mapname_org, int x, int
skill_stop_dancing(sd, 1);
clif_clearchar(sd, clrtype);
map_delblock(sd);
- strzcpy(sd->mapname_, mapname_, 16);
+ sd->mapname_ = mapname_;
sd->bl_x = x;
sd->bl_y = y;
sd->state.waitingdisconnect = 1;
@@ -2359,7 +2361,7 @@ int pc_setpos(dumb_ptr<map_session_data> sd, const char *mapname_org, int x, int
clif_changemap(sd, m->name_, x, y); // [MouseJstr]
}
- strzcpy(sd->mapname_, mapname_, 16);
+ sd->mapname_ = mapname_;
sd->bl_m = m;
sd->to_x = x;
sd->to_y = y;
@@ -3080,7 +3082,7 @@ int pc_gainexp_reason(dumb_ptr<map_session_data> sd, int base_exp, int job_exp,
if (battle_config.disp_experience)
{
- std::string output = STRPRINTF(
+ FString output = STRPRINTF(
"Experienced Gained Base:%d Job:%d",
base_exp, job_exp);
clif_displaymessage(sd->fd, output);
@@ -3476,7 +3478,7 @@ int pc_damage(dumb_ptr<block_list> src, dumb_ptr<map_session_data> sd,
pc_stop_walking(sd, 0);
skill_castcancel(sd, 0); // 詠唱の中止
clif_clearchar(sd, BeingRemoveWhy::DEAD);
- pc_setglobalreg(sd, "PC_DIE_COUNTER", ++sd->die_counter); //死にカウンター書き込み
+ pc_setglobalreg(sd, stringish<VarName>("PC_DIE_COUNTER"), ++sd->die_counter); //死にカウンター書き込み
skill_status_change_clear(sd, 0); // ステータス異常を解除する
clif_updatestatus(sd, SP::HP);
pc_calcstatus(sd, 0);
@@ -3566,17 +3568,16 @@ int pc_damage(dumb_ptr<block_list> src, dumb_ptr<map_session_data> sd,
if (src && src->bl_type == BL::PC)
{
// [Fate] PK death, trigger scripts
- argrec_t arg[3];
- arg[0].name = "@killerrid";
- arg[0].v.i = src->bl_id;
- arg[1].name = "@victimrid";
- arg[1].v.i = sd->bl_id;
- arg[2].name = "@victimlvl";
- arg[2].v.i = sd->status.base_level;
- npc_event_doall_l("OnPCKilledEvent", sd->bl_id, 3, arg);
- npc_event_doall_l("OnPCKillEvent", src->bl_id, 3, arg);
- }
- npc_event_doall_l("OnPCDieEvent", sd->bl_id, 0, NULL);
+ argrec_t arg[3] =
+ {
+ {"@killerrid", src->bl_id},
+ {"@victimrid", sd->bl_id},
+ {"@victimlvl", sd->status.base_level},
+ };
+ npc_event_doall_l(stringish<ScriptLabel>("OnPCKilledEvent"), sd->bl_id, 3, arg);
+ npc_event_doall_l(stringish<ScriptLabel>("OnPCKillEvent"), src->bl_id, 3, arg);
+ }
+ npc_event_doall_l(stringish<ScriptLabel>("OnPCDieEvent"), sd->bl_id, 0, NULL);
return 0;
}
@@ -4101,26 +4102,26 @@ void pc_setreg(dumb_ptr<map_session_data> sd, SIR reg, int val)
* script用文字列変数の値を読む
*------------------------------------------
*/
-const char *pc_readregstr(dumb_ptr<map_session_data> sd, SIR reg)
+ZString pc_readregstr(dumb_ptr<map_session_data> sd, SIR reg)
{
- nullpo_ret(sd);
+ nullpo_retr(ZString(), sd);
- std::string *s = sd->regstrm.search(reg);
+ FString *s = sd->regstrm.search(reg);
if (s)
- return s->c_str();
+ return *s;
- return NULL;
+ return ZString();
}
/*==========================================
* script用文字列変数の値を設定
*------------------------------------------
*/
-void pc_setregstr(dumb_ptr<map_session_data> sd, SIR reg, const char *str)
+void pc_setregstr(dumb_ptr<map_session_data> sd, SIR reg, FString str)
{
nullpo_retv(sd);
- if (!*str)
+ if (!str)
{
sd->regstrm.erase(reg);
return;
@@ -4133,7 +4134,7 @@ void pc_setregstr(dumb_ptr<map_session_data> sd, SIR reg, const char *str)
* script用グローバル変数の値を読む
*------------------------------------------
*/
-int pc_readglobalreg(dumb_ptr<map_session_data> sd, const char *reg)
+int pc_readglobalreg(dumb_ptr<map_session_data> sd, VarName reg)
{
int i;
@@ -4141,7 +4142,7 @@ int pc_readglobalreg(dumb_ptr<map_session_data> sd, const char *reg)
for (i = 0; i < sd->status.global_reg_num; i++)
{
- if (strcmp(sd->status.global_reg[i].str, reg) == 0)
+ if (sd->status.global_reg[i].str == reg)
return sd->status.global_reg[i].value;
}
@@ -4152,14 +4153,14 @@ int pc_readglobalreg(dumb_ptr<map_session_data> sd, const char *reg)
* script用グローバル変数の値を設定
*------------------------------------------
*/
-int pc_setglobalreg(dumb_ptr<map_session_data> sd, const char *reg, int val)
+int pc_setglobalreg(dumb_ptr<map_session_data> sd, VarName reg, int val)
{
int i;
nullpo_ret(sd);
//PC_DIE_COUNTERがスクリプトなどで変更された時の処理
- if (strcmp(reg, "PC_DIE_COUNTER") == 0 && sd->die_counter != val)
+ if (reg == stringish<VarName>("PC_DIE_COUNTER") && sd->die_counter != val)
{
sd->die_counter = val;
pc_calcstatus(sd, 0);
@@ -4168,7 +4169,7 @@ int pc_setglobalreg(dumb_ptr<map_session_data> sd, const char *reg, int val)
{
for (i = 0; i < sd->status.global_reg_num; i++)
{
- if (strcmp(sd->status.global_reg[i].str, reg) == 0)
+ if (sd->status.global_reg[i].str == reg)
{
sd->status.global_reg[i] =
sd->status.global_reg[sd->status.global_reg_num - 1];
@@ -4180,7 +4181,7 @@ int pc_setglobalreg(dumb_ptr<map_session_data> sd, const char *reg, int val)
}
for (i = 0; i < sd->status.global_reg_num; i++)
{
- if (strcmp(sd->status.global_reg[i].str, reg) == 0)
+ if (sd->status.global_reg[i].str == reg)
{
sd->status.global_reg[i].value = val;
return 0;
@@ -4188,7 +4189,7 @@ int pc_setglobalreg(dumb_ptr<map_session_data> sd, const char *reg, int val)
}
if (sd->status.global_reg_num < GLOBAL_REG_NUM)
{
- strcpy(sd->status.global_reg[i].str, reg);
+ sd->status.global_reg[i].str = reg;
sd->status.global_reg[i].value = val;
sd->status.global_reg_num++;
return 0;
@@ -4204,7 +4205,7 @@ int pc_setglobalreg(dumb_ptr<map_session_data> sd, const char *reg, int val)
* script用アカウント変数の値を読む
*------------------------------------------
*/
-int pc_readaccountreg(dumb_ptr<map_session_data> sd, const char *reg)
+int pc_readaccountreg(dumb_ptr<map_session_data> sd, VarName reg)
{
int i;
@@ -4212,7 +4213,7 @@ int pc_readaccountreg(dumb_ptr<map_session_data> sd, const char *reg)
for (i = 0; i < sd->status.account_reg_num; i++)
{
- if (strcmp(sd->status.account_reg[i].str, reg) == 0)
+ if (sd->status.account_reg[i].str == reg)
return sd->status.account_reg[i].value;
}
@@ -4223,7 +4224,7 @@ int pc_readaccountreg(dumb_ptr<map_session_data> sd, const char *reg)
* script用アカウント変数の値を設定
*------------------------------------------
*/
-int pc_setaccountreg(dumb_ptr<map_session_data> sd, const char *reg, int val)
+int pc_setaccountreg(dumb_ptr<map_session_data> sd, VarName reg, int val)
{
int i;
@@ -4233,7 +4234,7 @@ int pc_setaccountreg(dumb_ptr<map_session_data> sd, const char *reg, int val)
{
for (i = 0; i < sd->status.account_reg_num; i++)
{
- if (strcmp(sd->status.account_reg[i].str, reg) == 0)
+ if (sd->status.account_reg[i].str == reg)
{
sd->status.account_reg[i] =
sd->status.account_reg[sd->status.account_reg_num - 1];
@@ -4246,7 +4247,7 @@ int pc_setaccountreg(dumb_ptr<map_session_data> sd, const char *reg, int val)
}
for (i = 0; i < sd->status.account_reg_num; i++)
{
- if (strcmp(sd->status.account_reg[i].str, reg) == 0)
+ if (sd->status.account_reg[i].str == reg)
{
sd->status.account_reg[i].value = val;
intif_saveaccountreg(sd);
@@ -4255,7 +4256,7 @@ int pc_setaccountreg(dumb_ptr<map_session_data> sd, const char *reg, int val)
}
if (sd->status.account_reg_num < ACCOUNT_REG_NUM)
{
- strcpy(sd->status.account_reg[i].str, reg);
+ sd->status.account_reg[i].str == reg;
sd->status.account_reg[i].value = val;
sd->status.account_reg_num++;
intif_saveaccountreg(sd);
@@ -4272,7 +4273,7 @@ int pc_setaccountreg(dumb_ptr<map_session_data> sd, const char *reg, int val)
* script用アカウント変数2の値を読む
*------------------------------------------
*/
-int pc_readaccountreg2(dumb_ptr<map_session_data> sd, const char *reg)
+int pc_readaccountreg2(dumb_ptr<map_session_data> sd, VarName reg)
{
int i;
@@ -4280,7 +4281,7 @@ int pc_readaccountreg2(dumb_ptr<map_session_data> sd, const char *reg)
for (i = 0; i < sd->status.account_reg2_num; i++)
{
- if (strcmp(sd->status.account_reg2[i].str, reg) == 0)
+ if (sd->status.account_reg2[i].str == reg)
return sd->status.account_reg2[i].value;
}
@@ -4291,7 +4292,7 @@ int pc_readaccountreg2(dumb_ptr<map_session_data> sd, const char *reg)
* script用アカウント変数2の値を設定
*------------------------------------------
*/
-int pc_setaccountreg2(dumb_ptr<map_session_data> sd, const char *reg, int val)
+int pc_setaccountreg2(dumb_ptr<map_session_data> sd, VarName reg, int val)
{
int i;
@@ -4301,7 +4302,7 @@ int pc_setaccountreg2(dumb_ptr<map_session_data> sd, const char *reg, int val)
{
for (i = 0; i < sd->status.account_reg2_num; i++)
{
- if (strcmp(sd->status.account_reg2[i].str, reg) == 0)
+ if (sd->status.account_reg2[i].str == reg)
{
sd->status.account_reg2[i] =
sd->status.account_reg2[sd->status.account_reg2_num - 1];
@@ -4314,7 +4315,7 @@ int pc_setaccountreg2(dumb_ptr<map_session_data> sd, const char *reg, int val)
}
for (i = 0; i < sd->status.account_reg2_num; i++)
{
- if (strcmp(sd->status.account_reg2[i].str, reg) == 0)
+ if (sd->status.account_reg2[i].str == reg)
{
sd->status.account_reg2[i].value = val;
chrif_saveaccountreg2(sd);
@@ -4323,7 +4324,7 @@ int pc_setaccountreg2(dumb_ptr<map_session_data> sd, const char *reg, int val)
}
if (sd->status.account_reg2_num < ACCOUNT_REG2_NUM)
{
- strcpy(sd->status.account_reg2[i].str, reg);
+ sd->status.account_reg2[i].str = reg;
sd->status.account_reg2[i].value = val;
sd->status.account_reg2_num++;
chrif_saveaccountreg2(sd);
@@ -4341,21 +4342,19 @@ int pc_setaccountreg2(dumb_ptr<map_session_data> sd, const char *reg, int val)
*------------------------------------------
*/
static
-void pc_eventtimer(TimerData *, tick_t, int id, dumb_string data)
+void pc_eventtimer(TimerData *, tick_t, int id, NpcEvent data)
{
dumb_ptr<map_session_data> sd = map_id2sd(id);
assert (sd != NULL);
- npc_event(sd, data.c_str(), 0);
-
- data.delete_();
+ npc_event(sd, data, 0);
}
/*==========================================
* イベントタイマー追加
*------------------------------------------
*/
-int pc_addeventtimer(dumb_ptr<map_session_data> sd, interval_t tick, const char *name)
+int pc_addeventtimer(dumb_ptr<map_session_data> sd, interval_t tick, NpcEvent name)
{
int i;
@@ -4367,10 +4366,9 @@ int pc_addeventtimer(dumb_ptr<map_session_data> sd, interval_t tick, const char
if (i < MAX_EVENTTIMER)
{
- dumb_string evname = dumb_string::copyn(name, 24);
sd->eventtimer[i] = Timer(gettick() + tick,
std::bind(pc_eventtimer, ph::_1, ph::_2,
- sd->bl_id, evname));
+ sd->bl_id, name));
return 1;
}
@@ -4869,13 +4867,12 @@ int pc_divorce(dumb_ptr<map_session_data> sd)
dumb_ptr<map_session_data> pc_get_partner(dumb_ptr<map_session_data> sd)
{
dumb_ptr<map_session_data> p_sd = NULL;
- char *nick;
if (sd == NULL || !pc_ismarried(sd))
return NULL;
- nick = map_charid2nick(sd->status.partner_id);
+ CharName nick = map_charid2nick(sd->status.partner_id);
- if (nick == NULL)
+ if (!nick.to__actual())
return NULL;
if ((p_sd = map_nick2sd(nick)) == NULL)
@@ -5167,11 +5164,11 @@ void pc_natural_heal(TimerData *, tick_t tick)
* セーブポイントの保存
*------------------------------------------
*/
-void pc_setsavepoint(dumb_ptr<map_session_data> sd, const char *mapname, int x, int y)
+void pc_setsavepoint(dumb_ptr<map_session_data> sd, MapName mapname, int x, int y)
{
nullpo_retv(sd);
- strzcpy(sd->status.save_point.map_, mapname, 16);
+ sd->status.save_point.map_ = mapname;
sd->status.save_point.x = x;
sd->status.save_point.y = y;
}
@@ -5316,7 +5313,7 @@ int pc_logout(dumb_ptr<map_session_data> sd) // [fate] Player logs out
}
else
#endif
- pc_setglobalreg(sd, "MAGIC_CAST_TICK", 0);
+ pc_setglobalreg(sd, stringish<VarName>("MAGIC_CAST_TICK"), 0);
MAP_LOG_STATS(sd, "LOGOUT");
return 0;
diff --git a/src/map/pc.hpp b/src/map/pc.hpp
index 4ebfa1b..4796011 100644
--- a/src/map/pc.hpp
+++ b/src/map/pc.hpp
@@ -62,8 +62,8 @@ int pc_checkequip(dumb_ptr<map_session_data> sd, EPOS pos);
int pc_walktoxy(dumb_ptr<map_session_data>, int, int);
int pc_stop_walking(dumb_ptr<map_session_data>, int);
int pc_movepos(dumb_ptr<map_session_data>, int, int);
-int pc_setpos(dumb_ptr<map_session_data>, const char *, int, int, BeingRemoveWhy);
-void pc_setsavepoint(dumb_ptr<map_session_data>, const char *, int, int);
+int pc_setpos(dumb_ptr<map_session_data>, MapName, int, int, BeingRemoveWhy);
+void pc_setsavepoint(dumb_ptr<map_session_data>, MapName, int, int);
int pc_randomwarp(dumb_ptr<map_session_data> sd, BeingRemoveWhy type);
ADDITEM pc_checkadditem(dumb_ptr<map_session_data>, int, int);
@@ -120,17 +120,17 @@ int pc_readparam(dumb_ptr<map_session_data>, SP);
int pc_setparam(dumb_ptr<map_session_data>, SP, int);
int pc_readreg(dumb_ptr<map_session_data>, SIR);
void pc_setreg(dumb_ptr<map_session_data>, SIR, int);
-const char *pc_readregstr(dumb_ptr<map_session_data> sd, SIR reg);
-void pc_setregstr(dumb_ptr<map_session_data> sd, SIR reg, const char *str);
-int pc_readglobalreg(dumb_ptr<map_session_data>, const char *);
-int pc_setglobalreg(dumb_ptr<map_session_data>, const char *, int);
-int pc_readaccountreg(dumb_ptr<map_session_data>, const char *);
-int pc_setaccountreg(dumb_ptr<map_session_data>, const char *, int);
-int pc_readaccountreg2(dumb_ptr<map_session_data>, const char *);
-int pc_setaccountreg2(dumb_ptr<map_session_data>, const char *, int);
+ZString pc_readregstr(dumb_ptr<map_session_data> sd, SIR reg);
+void pc_setregstr(dumb_ptr<map_session_data> sd, SIR reg, FString str);
+int pc_readglobalreg(dumb_ptr<map_session_data>, VarName );
+int pc_setglobalreg(dumb_ptr<map_session_data>, VarName , int);
+int pc_readaccountreg(dumb_ptr<map_session_data>, VarName );
+int pc_setaccountreg(dumb_ptr<map_session_data>, VarName , int);
+int pc_readaccountreg2(dumb_ptr<map_session_data>, VarName );
+int pc_setaccountreg2(dumb_ptr<map_session_data>, VarName , int);
int pc_addeventtimer(dumb_ptr<map_session_data> sd, interval_t tick,
- const char *name);
+ NpcEvent name);
int pc_cleareventtimer(dumb_ptr<map_session_data> sd);
int pc_calc_pvprank(dumb_ptr<map_session_data> sd);
diff --git a/src/map/script.cpp b/src/map/script.cpp
index 854a42f..e82c843 100644
--- a/src/map/script.cpp
+++ b/src/map/script.cpp
@@ -13,6 +13,7 @@
#include "../common/db.hpp"
#include "../common/extract.hpp"
#include "../common/intern-pool.hpp"
+#include "../common/io.hpp"
#include "../common/lock.hpp"
#include "../common/random.hpp"
#include "../common/socket.hpp"
@@ -42,27 +43,27 @@ constexpr bool DEBUG_RUN = false;
struct str_data_t
{
ByteCode type;
- std::string strs;
+ FString strs;
int backpatch;
int label_;
int val;
};
static
-Map<std::string, str_data_t> str_datam;
+Map<FString, str_data_t> str_datam;
static
str_data_t LABEL_NEXTLINE_;
static
DMap<SIR, int> mapreg_db;
static
-Map<SIR, std::string> mapregstr_db;
+Map<SIR, FString> mapregstr_db;
static
int mapreg_dirty = -1;
-char mapreg_txt[256] = "save/mapreg.txt";
+FString mapreg_txt = "save/mapreg.txt";
constexpr std::chrono::milliseconds MAPREG_AUTOSAVE_INTERVAL = std::chrono::seconds(10);
-Map<std::string, int> scriptlabel_db;
-UPMap<std::string, const ScriptBuffer> userfunc_db;
+Map<ScriptLabel, int> scriptlabel_db;
+UPMap<FString, const ScriptBuffer> userfunc_db;
static
const char *pos[11] =
@@ -101,13 +102,13 @@ void run_func(ScriptState *st);
static
void mapreg_setreg(SIR num, int val);
static
-void mapreg_setregstr(SIR num, const char *str);
+void mapreg_setregstr(SIR num, XString str);
struct BuiltinFunction
{
void (*func)(ScriptState *);
- const char *name;
- const char *arg;
+ ZString name;
+ ZString arg;
};
// defined later
extern BuiltinFunction builtin_functions[];
@@ -132,29 +133,21 @@ enum class ByteCode : uint8_t
};
static
-str_data_t *search_strp(const std::string& p)
+str_data_t *search_strp(XString p)
{
return str_datam.search(p);
}
static
-str_data_t *add_strp(const std::string& p)
+str_data_t *add_strp(XString p)
{
- // TODO remove lowcase
- std::string lowcase = p;
- for (char& c : lowcase)
- c = tolower(c);
-
- if (str_data_t *rv = search_strp(lowcase))
- return rv;
-
- // ?
if (str_data_t *rv = search_strp(p))
return rv;
- str_data_t *datum = str_datam.init(p);
+ FString p2 = p;
+ str_data_t *datum = str_datam.init(p2);
datum->type = ByteCode::NOP;
- datum->strs = p;
+ datum->strs = p2;
datum->backpatch = -1;
datum->label_ = -1;
return datum;
@@ -266,7 +259,7 @@ void ScriptBuffer::set_label(str_data_t *ld, int pos_)
*------------------------------------------
*/
static
-const char *skip_space(const char *p)
+ZString::iterator skip_space(ZString::iterator p)
{
while (1)
{
@@ -296,7 +289,7 @@ const char *skip_space(const char *p)
*------------------------------------------
*/
static
-const char *skip_word(const char *p)
+ZString::iterator skip_word(ZString::iterator p)
{
// prefix
if (*p == '$')
@@ -320,8 +313,10 @@ const char *skip_word(const char *p)
return p;
}
+// TODO: replace this whole mess with some sort of input stream that works
+// a line at a time.
static
-const char *startptr;
+ZString startptr;
static
int startline;
@@ -331,30 +326,23 @@ int script_errors = 0;
*------------------------------------------
*/
static
-void disp_error_message(const char *mes, const char *pos_)
+void disp_error_message(ZString mes, ZString::iterator pos_)
{
script_errors++;
+ assert (startptr.begin() <= pos_ && pos_ <= startptr.end());
+
int line;
- const char *p;
+ ZString::iterator p;
- for (line = startline, p = startptr; p && *p; line++)
+ for (line = startline, p = startptr.begin(); p != startptr.end(); line++)
{
- const char *linestart = p;
- char *lineend = const_cast<char *>(strchr(p, '\n'));
- // always initialized, but clang is not smart enough
- char c = '\0';
- if (lineend)
- {
- c = *lineend;
- *lineend = 0;
- }
- if (lineend == NULL || pos_ < lineend)
+ ZString::iterator linestart = p;
+ ZString::iterator lineend = std::find(p, startptr.end(), '\n');
+ if (pos_ < lineend)
{
PRINTF("\n%s\nline %d : ", mes, line);
- for (int i = 0;
- (linestart[i] != '\r') && (linestart[i] != '\n')
- && linestart[i]; i++)
+ for (int i = 0; linestart + i != lineend; i++)
{
if (linestart + i != pos_)
PRINTF("%c", linestart[i]);
@@ -362,11 +350,8 @@ void disp_error_message(const char *mes, const char *pos_)
PRINTF("\'%c\'", linestart[i]);
}
PRINTF("\a\n");
- if (lineend)
- *lineend = c;
return;
}
- *lineend = c;
p = lineend + 1;
}
}
@@ -375,9 +360,8 @@ void disp_error_message(const char *mes, const char *pos_)
* 項の解析
*------------------------------------------
*/
-const char *ScriptBuffer::parse_simpleexpr(const char *p)
+ZString::iterator ScriptBuffer::parse_simpleexpr(ZString::iterator p)
{
- int i;
p = skip_space(p);
if (*p == ';' || *p == ',')
@@ -399,9 +383,9 @@ const char *ScriptBuffer::parse_simpleexpr(const char *p)
else if (isdigit(*p) || ((*p == '-' || *p == '+') && isdigit(p[1])))
{
char *np;
- i = strtoul(p, &np, 0);
+ int i = strtoul(&*p, &np, 0);
add_scripti(i);
- p = np;
+ p += np - &*p;
}
else if (*p == '"')
{
@@ -409,7 +393,7 @@ const char *ScriptBuffer::parse_simpleexpr(const char *p)
p++;
while (*p && *p != '"')
{
- if (p[-1] <= 0x7e && *p == '\\')
+ if (*p == '\\')
p++;
else if (*p == '\n')
{
@@ -429,13 +413,13 @@ const char *ScriptBuffer::parse_simpleexpr(const char *p)
else
{
// label , register , function etc
- const char *p2 = skip_word(p);
+ ZString::iterator p2 = skip_word(p);
if (p2 == p)
{
disp_error_message("unexpected character", p);
exit(1);
}
- std::string word(p, p2);
+ XString word(&*p, &*p2, nullptr);
if (parse_cmd_if && (word == "callsub" || word == "callfunc"))
{
disp_error_message("callsub/callfunc not allowed in an if statement", p);
@@ -476,7 +460,7 @@ const char *ScriptBuffer::parse_simpleexpr(const char *p)
* 式の解析
*------------------------------------------
*/
-const char *ScriptBuffer::parse_subexpr(const char *p, int limit)
+ZString::iterator ScriptBuffer::parse_subexpr(ZString::iterator p, int limit)
{
ByteCode op;
int opl, len;
@@ -485,7 +469,7 @@ const char *ScriptBuffer::parse_subexpr(const char *p, int limit)
if (*p == '-')
{
- const char *tmpp = skip_space(p + 1);
+ ZString::iterator tmpp = skip_space(p + 1);
if (*tmpp == ';' || *tmpp == ',')
{
add_scriptl(&LABEL_NEXTLINE_);
@@ -493,7 +477,7 @@ const char *ScriptBuffer::parse_subexpr(const char *p, int limit)
return p;
}
}
- const char *tmpp = p;
+ ZString::iterator tmpp = p;
if ((op = ByteCode::NEG, *p == '-') || (op = ByteCode::LNOT, *p == '!')
|| (op = ByteCode::NOT, *p == '~'))
{
@@ -528,7 +512,7 @@ const char *ScriptBuffer::parse_subexpr(const char *p, int limit)
{
int i = 0;
str_data_t *funcp = parse_cmdp;
- const char *plist[128];
+ ZString::iterator plist[128];
if (funcp->type != ByteCode::FUNC_)
{
@@ -563,7 +547,7 @@ const char *ScriptBuffer::parse_subexpr(const char *p, int limit)
if (funcp->type == ByteCode::FUNC_
&& script_config.warn_func_mismatch_paramnum)
{
- const char *arg = builtin_functions[funcp->val].arg;
+ ZString arg = builtin_functions[funcp->val].arg;
int j = 0;
for (j = 0; arg[j]; j++)
if (arg[j] == '*')
@@ -571,7 +555,7 @@ const char *ScriptBuffer::parse_subexpr(const char *p, int limit)
if ((arg[j] == 0 && i != j) || (arg[j] == '*' && i < j))
{
disp_error_message("illegal number of parameters",
- plist[(i < j) ? i : j]);
+ plist[std::min(i, j)]);
}
}
}
@@ -589,7 +573,7 @@ const char *ScriptBuffer::parse_subexpr(const char *p, int limit)
* 式の評価
*------------------------------------------
*/
-const char *ScriptBuffer::parse_expr(const char *p)
+ZString::iterator ScriptBuffer::parse_expr(ZString::iterator p)
{
switch (*p)
{
@@ -610,10 +594,10 @@ const char *ScriptBuffer::parse_expr(const char *p)
* 行の解析
*------------------------------------------
*/
-const char *ScriptBuffer::parse_line(const char *p)
+ZString::iterator ScriptBuffer::parse_line(ZString::iterator p)
{
int i = 0;
- const char *plist[128];
+ ZString::iterator plist[128];
p = skip_space(p);
if (*p == ';')
@@ -622,7 +606,7 @@ const char *ScriptBuffer::parse_line(const char *p)
parse_cmd_if = 0; // warn_cmd_no_commaのために必要
// 最初は関数名
- const char *p2 = p;
+ ZString::iterator p2 = p;
p = parse_simpleexpr(p);
p = skip_space(p);
@@ -634,7 +618,7 @@ const char *ScriptBuffer::parse_line(const char *p)
}
add_scriptc(ByteCode::ARG);
- while (p && *p && *p != ';' && i < 128)
+ while (*p && *p != ';' && i < 128)
{
plist[i] = p;
@@ -652,7 +636,7 @@ const char *ScriptBuffer::parse_line(const char *p)
i++;
}
plist[i] = p;
- if (!p || *(p++) != ';')
+ if (*(p++) != ';')
{
disp_error_message("need ';'", p);
exit(1);
@@ -662,7 +646,7 @@ const char *ScriptBuffer::parse_line(const char *p)
if (cmd->type == ByteCode::FUNC_
&& script_config.warn_cmd_mismatch_paramnum)
{
- const char *arg = builtin_functions[cmd->val].arg;
+ ZString arg = builtin_functions[cmd->val].arg;
int j = 0;
for (j = 0; arg[j]; j++)
if (arg[j] == '*')
@@ -670,7 +654,7 @@ const char *ScriptBuffer::parse_line(const char *p)
if ((arg[j] == 0 && i != j) || (arg[j] == '*' && i < j))
{
disp_error_message("illegal number of parameters",
- plist[(i < j) ? i : j]);
+ plist[std::min(i, j)]);
}
}
@@ -706,26 +690,24 @@ void read_constdb(void)
return;
}
- std::string line;
- while (std::getline(in, line))
+ FString line;
+ while (io::getline(in, line))
{
- if (line[0] == '/' && line[1] == '/')
+ if (line.startswith("//"))
continue;
- std::string name;
+ FString name;
int val;
int type = 0; // if not provided
if (SSCANF(line, "%m[A-Za-z0-9_] %i %i", &name, &val, &type) < 2)
continue;
- for (char& c : name)
- c = tolower(c);
str_data_t *n = add_strp(name);
n->type = type ? ByteCode::PARAM_ : ByteCode::INT;
n->val = val;
}
}
-std::unique_ptr<const ScriptBuffer> parse_script(const char *src, int line)
+std::unique_ptr<const ScriptBuffer> parse_script(ZString src, int line)
{
auto script_buf = make_unique<ScriptBuffer>();
script_buf->parse_script(src, line);
@@ -736,9 +718,8 @@ std::unique_ptr<const ScriptBuffer> parse_script(const char *src, int line)
* スクリプトの解析
*------------------------------------------
*/
-void ScriptBuffer::parse_script(const char *src, int line)
+void ScriptBuffer::parse_script(ZString src, int line)
{
- const char *p;
static int first = 1;
if (first)
@@ -768,21 +749,20 @@ void ScriptBuffer::parse_script(const char *src, int line)
startptr = src;
startline = line;
- p = src;
+ ZString::iterator p = src.begin();
p = skip_space(p);
if (*p != '{')
{
disp_error_message("not found '{'", p);
abort();
}
- for (p++; p && *p && *p != '}';)
+ for (p++; *p && *p != '}';)
{
p = skip_space(p);
- // labelだけ特殊処理
if (*skip_space(skip_word(p)) == ':')
{
- const char *tmpp = skip_word(p);
- std::string str(p, tmpp);
+ ZString::iterator tmpp = skip_word(p);
+ XString str(&*p, &*tmpp, nullptr);
str_data_t *ld = add_strp(str);
bool e1 = ld->type != ByteCode::NOP;
bool e2 = ld->type == ByteCode::POS;
@@ -794,7 +774,7 @@ void ScriptBuffer::parse_script(const char *src, int line)
exit(1);
}
set_label(ld, script_buf.size());
- scriptlabel_db.insert(str, script_buf.size());
+ scriptlabel_db.insert(stringish<ScriptLabel>(str), script_buf.size());
p = tmpp + 1;
continue;
}
@@ -894,7 +874,8 @@ void get_val(ScriptState *st, struct script_data *data)
}
else if (data->type == ByteCode::VARIABLE)
{
- const std::string& name = variable_names.outtern(data->u.reg.base());
+ ZString name_ = variable_names.outtern(data->u.reg.base());
+ VarName name = stringish<VarName>(name_);
char prefix = name.front();
char postfix = name.back();
@@ -913,8 +894,8 @@ void get_val(ScriptState *st, struct script_data *data)
}
else if (prefix == '$')
{
- std::string *s = mapregstr_db.search(data->u.reg);
- data->u.str = s ? dumb_string::fake(s->c_str()) : dumb_string();
+ FString *s = mapregstr_db.search(data->u.reg);
+ data->u.str = s ? dumb_string::fake(*s) : dumb_string();
}
else
{
@@ -941,18 +922,18 @@ void get_val(ScriptState *st, struct script_data *data)
if (name[1] == '#')
{
if (sd)
- data->u.numi = pc_readaccountreg2(sd, name.c_str());
+ data->u.numi = pc_readaccountreg2(sd, name);
}
else
{
if (sd)
- data->u.numi = pc_readaccountreg(sd, name.c_str());
+ data->u.numi = pc_readaccountreg(sd, name);
}
}
else
{
if (sd)
- data->u.numi = pc_readglobalreg(sd, name.c_str());
+ data->u.numi = pc_readglobalreg(sd, name);
}
}
}
@@ -988,7 +969,8 @@ void set_reg(dumb_ptr<map_session_data> sd, ByteCode type, SIR reg, struct scrip
}
assert (type == ByteCode::VARIABLE);
- const std::string& name = variable_names.outtern(reg.base());
+ ZString name_ = variable_names.outtern(reg.base());
+ VarName name = stringish<VarName>(name_);
char prefix = name.front();
char postfix = name.back();
@@ -997,11 +979,11 @@ void set_reg(dumb_ptr<map_session_data> sd, ByteCode type, SIR reg, struct scrip
dumb_string str = vd.u.str;
if (prefix == '@' || prefix == 'l')
{
- pc_setregstr(sd, reg, str.c_str());
+ pc_setregstr(sd, reg, str.str());
}
else if (prefix == '$')
{
- mapreg_setregstr(reg, str.c_str());
+ mapreg_setregstr(reg, str.str());
}
else
{
@@ -1023,13 +1005,13 @@ void set_reg(dumb_ptr<map_session_data> sd, ByteCode type, SIR reg, struct scrip
else if (prefix == '#')
{
if (name[1] == '#')
- pc_setaccountreg2(sd, name.c_str(), val);
+ pc_setaccountreg2(sd, name, val);
else
- pc_setaccountreg(sd, name.c_str(), val);
+ pc_setaccountreg(sd, name, val);
}
else
{
- pc_setglobalreg(sd, name.c_str(), val);
+ pc_setglobalreg(sd, name, val);
}
}
}
@@ -1063,7 +1045,7 @@ dumb_string conv_str(ScriptState *st, struct script_data *data)
assert (data->type != ByteCode::RETINFO);
if (data->type == ByteCode::INT)
{
- std::string buf = STRPRINTF("%d", data->u.numi);
+ FString buf = STRPRINTF("%d", data->u.numi);
data->type = ByteCode::STR;
data->u.str = dumb_string::copys(buf);
}
@@ -1193,7 +1175,7 @@ static
void builtin_mes(ScriptState *st)
{
dumb_string mes = conv_str(st, &AARGO2(2));
- clif_scriptmes(script_rid2sd(st), st->oid, mes.c_str());
+ clif_scriptmes(script_rid2sd(st), st->oid, ZString(mes));
}
/*==========================================
@@ -1334,17 +1316,17 @@ void builtin_menu(ScriptState *st)
st->state = ScriptEndState::RERUNLINE;
sd->state.menu_or_input = 1;
- std::string buf;
+ MString buf;
for (int i = st->start + 2; i < st->end; i += 2)
{
dumb_string choice_str = conv_str(st, &AARGO2(i - st->start));
if (!choice_str[0])
break;
- buf += choice_str.c_str();
+ buf += ZString(choice_str);
buf += ':';
}
- clif_scriptmenu(script_rid2sd(st), st->oid, buf.c_str());
+ clif_scriptmenu(script_rid2sd(st), st->oid, FString(buf));
}
else
{
@@ -1427,14 +1409,13 @@ void builtin_isat(ScriptState *st)
int x, y;
dumb_ptr<map_session_data> sd = script_rid2sd(st);
- dumb_string str = conv_str(st, &AARGO2(2));
+ MapName str = stringish<MapName>(ZString(conv_str(st, &AARGO2(2))));
x = conv_num(st, &AARGO2(3));
y = conv_num(st, &AARGO2(4));
if (!sd)
return;
- using namespace operators;
push_int(st->stack, ByteCode::INT,
(x == sd->bl_x) && (y == sd->bl_y)
&& (str == sd->bl_m->name_));
@@ -1450,10 +1431,9 @@ void builtin_warp(ScriptState *st)
int x, y;
dumb_ptr<map_session_data> sd = script_rid2sd(st);
- dumb_string str = conv_str(st, &AARGO2(2));
+ MapName str = stringish<MapName>(ZString(conv_str(st, &AARGO2(2))));
x = conv_num(st, &AARGO2(3));
y = conv_num(st, &AARGO2(4));
- using namespace operators;
if (str == "Random")
pc_randomwarp(sd, BeingRemoveWhy::WARPED);
else if (str == "SavePoint")
@@ -1461,19 +1441,19 @@ void builtin_warp(ScriptState *st)
if (sd->bl_m->flag.noreturn) // 蝶禁止
return;
- pc_setpos(sd, sd->status.save_point.map_,
- sd->status.save_point.x, sd->status.save_point.y, BeingRemoveWhy::WARPED);
+ pc_setpos(sd, sd->status.save_point.map_, sd->status.save_point.x, sd->status.save_point.y,
+ BeingRemoveWhy::WARPED);
}
else if (str == "Save")
{
if (sd->bl_m->flag.noreturn) // 蝶禁止
return;
- pc_setpos(sd, sd->status.save_point.map_,
- sd->status.save_point.x, sd->status.save_point.y, BeingRemoveWhy::WARPED);
+ pc_setpos(sd, sd->status.save_point.map_, sd->status.save_point.x, sd->status.save_point.y,
+ BeingRemoveWhy::WARPED);
}
else
- pc_setpos(sd, str.c_str(), x, y, BeingRemoveWhy::GONE);
+ pc_setpos(sd, str, x, y, BeingRemoveWhy::GONE);
}
/*==========================================
@@ -1481,14 +1461,13 @@ void builtin_warp(ScriptState *st)
*------------------------------------------
*/
static
-void builtin_areawarp_sub(dumb_ptr<block_list> bl, dumb_string mapname, int x, int y)
+void builtin_areawarp_sub(dumb_ptr<block_list> bl, MapName mapname, int x, int y)
{
dumb_ptr<map_session_data> sd = bl->as_player();
- using namespace operators;
if (mapname == "Random")
pc_randomwarp(sd, BeingRemoveWhy::WARPED);
else
- pc_setpos(sd, mapname.c_str(), x, y, BeingRemoveWhy::GONE);
+ pc_setpos(sd, mapname, x, y, BeingRemoveWhy::GONE);
}
static
@@ -1497,16 +1476,16 @@ void builtin_areawarp(ScriptState *st)
int x, y;
int x0, y0, x1, y1;
- dumb_string mapname = conv_str(st, &AARGO2(2));
+ MapName mapname = stringish<MapName>(ZString(conv_str(st, &AARGO2(2))));
x0 = conv_num(st, &AARGO2(3));
y0 = conv_num(st, &AARGO2(4));
x1 = conv_num(st, &AARGO2(5));
y1 = conv_num(st, &AARGO2(6));
- dumb_string str = conv_str(st, &AARGO2(7));
+ MapName str = stringish<MapName>(ZString(conv_str(st, &AARGO2(7))));
x = conv_num(st, &AARGO2(8));
y = conv_num(st, &AARGO2(9));
- map_local *m = map_mapname2mapid(mapname.c_str());
+ map_local *m = map_mapname2mapid(mapname);
if (m == nullptr)
return;
@@ -1572,7 +1551,7 @@ void builtin_input(ScriptState *st)
assert (type == ByteCode::VARIABLE);
SIR reg = scrd.u.reg;
- const std::string& name = variable_names.outtern(reg.base());
+ ZString name = variable_names.outtern(reg.base());
// char prefix = name.front();
char postfix = name.back();
@@ -1583,7 +1562,7 @@ void builtin_input(ScriptState *st)
sd->state.menu_or_input = 0;
if (postfix == '$')
{
- set_reg(sd, type, reg, dumb_string::fake(sd->npc_str.c_str()));
+ set_reg(sd, type, reg, dumb_string::fake(sd->npc_str));
}
else
{
@@ -1653,7 +1632,7 @@ void builtin_set(ScriptState *st)
set_reg(sd, ByteCode::PARAM_, reg, val);
return;
}
- const std::string& name = variable_names.outtern(reg.base());
+ ZString name = variable_names.outtern(reg.base());
char prefix = name.front();
char postfix = name.back();
@@ -1687,7 +1666,7 @@ void builtin_setarray(ScriptState *st)
dumb_ptr<map_session_data> sd = NULL;
assert (AARGO2(2).type == ByteCode::VARIABLE);
SIR reg = AARGO2(2).u.reg;
- const std::string& name = variable_names.outtern(reg.base());
+ ZString name = variable_names.outtern(reg.base());
char prefix = name.front();
char postfix = name.back();
@@ -1718,7 +1697,7 @@ void builtin_cleararray(ScriptState *st)
dumb_ptr<map_session_data> sd = NULL;
assert (AARGO2(2).type == ByteCode::VARIABLE);
SIR reg = AARGO2(2).u.reg;
- const std::string& name = variable_names.outtern(reg.base());
+ ZString name = variable_names.outtern(reg.base());
char prefix = name.front();
char postfix = name.back();
int sz = conv_num(st, &AARGO2(4));
@@ -1764,7 +1743,7 @@ void builtin_getarraysize(ScriptState *st)
{
assert (AARGO2(2).type == ByteCode::VARIABLE);
SIR reg = AARGO2(2).u.reg;
- const std::string& name = variable_names.outtern(reg.base());
+ ZString name = variable_names.outtern(reg.base());
char prefix = name.front();
char postfix = name.back();
@@ -1838,8 +1817,8 @@ void builtin_countitem(ScriptState *st)
get_val(st, data);
if (data->type == ByteCode::STR || data->type == ByteCode::CONSTSTR)
{
- dumb_string name = conv_str(st, data);
- struct item_data *item_data = itemdb_searchname(name.c_str());
+ ItemName name = stringish<ItemName>(ZString(conv_str(st, data)));
+ struct item_data *item_data = itemdb_searchname(name);
if (item_data != NULL)
nameid = item_data->nameid;
}
@@ -1878,8 +1857,8 @@ void builtin_checkweight(ScriptState *st)
get_val(st, data);
if (data->type == ByteCode::STR || data->type == ByteCode::CONSTSTR)
{
- dumb_string name = conv_str(st, data);
- struct item_data *item_data = itemdb_searchname(name.c_str());
+ ItemName name = stringish<ItemName>(ZString(conv_str(st, data)));
+ struct item_data *item_data = itemdb_searchname(name);
if (item_data)
nameid = item_data->nameid;
}
@@ -1922,8 +1901,8 @@ void builtin_getitem(ScriptState *st)
get_val(st, data);
if (data->type == ByteCode::STR || data->type == ByteCode::CONSTSTR)
{
- dumb_string name = conv_str(st, data);
- struct item_data *item_data = itemdb_searchname(name.c_str());
+ ItemName name = stringish<ItemName>(ZString(conv_str(st, data)));
+ struct item_data *item_data = itemdb_searchname(name);
nameid = 727; //Default to iten
if (item_data != NULL)
nameid = item_data->nameid;
@@ -1976,8 +1955,8 @@ void builtin_makeitem(ScriptState *st)
get_val(st, data);
if (data->type == ByteCode::STR || data->type == ByteCode::CONSTSTR)
{
- dumb_string name = conv_str(st, data);
- struct item_data *item_data = itemdb_searchname(name.c_str());
+ ItemName name = stringish<ItemName>(ZString(conv_str(st, data)));
+ struct item_data *item_data = itemdb_searchname(name);
nameid = 512; //Apple Item ID
if (item_data)
nameid = item_data->nameid;
@@ -1986,16 +1965,15 @@ void builtin_makeitem(ScriptState *st)
nameid = conv_num(st, data);
amount = conv_num(st, &AARGO2(3));
- dumb_string mapname = conv_str(st, &AARGO2(4));
+ MapName mapname = stringish<MapName>(ZString(conv_str(st, &AARGO2(4))));
x = conv_num(st, &AARGO2(5));
y = conv_num(st, &AARGO2(6));
map_local *m;
- using namespace operators;
- if (sd && mapname == "this")
+ if (sd && mapname == MOB_THIS_MAP)
m = sd->bl_m;
else
- m = map_mapname2mapid(mapname.c_str());
+ m = map_mapname2mapid(mapname);
if (nameid > 0)
{
@@ -2028,8 +2006,8 @@ void builtin_delitem(ScriptState *st)
get_val(st, data);
if (data->type == ByteCode::STR || data->type == ByteCode::CONSTSTR)
{
- dumb_string name = conv_str(st, data);
- struct item_data *item_data = itemdb_searchname(name.c_str());
+ ItemName name = stringish<ItemName>(ZString(conv_str(st, data)));
+ struct item_data *item_data = itemdb_searchname(name);
//nameid=512;
if (item_data)
nameid = item_data->nameid;
@@ -2087,7 +2065,7 @@ void builtin_readparam(ScriptState *st)
SP type = SP(conv_num(st, &AARGO2(2)));
if (HARGO2(3))
- sd = map_nick2sd(conv_str(st, &AARGO2(3)).c_str());
+ sd = map_nick2sd(stringish<CharName>(ZString(conv_str(st, &AARGO2(3)))));
else
sd = script_rid2sd(st);
@@ -2113,7 +2091,7 @@ void builtin_getcharid(ScriptState *st)
num = conv_num(st, &AARGO2(2));
if (HARGO2(3))
- sd = map_nick2sd(conv_str(st, &AARGO2(3)).c_str());
+ sd = map_nick2sd(stringish<CharName>(ZString(conv_str(st, &AARGO2(3)))));
else
sd = script_rid2sd(st);
if (sd == NULL)
@@ -2141,7 +2119,7 @@ dumb_string builtin_getpartyname_sub(int party_id)
struct party *p = party_search(party_id);
if (p)
- return dumb_string::copy(p->name);
+ return dumb_string::copys(p->name);
return dumb_string();
}
@@ -2160,7 +2138,7 @@ void builtin_strcharinfo(ScriptState *st)
num = conv_num(st, &AARGO2(2));
if (num == 0)
{
- dumb_string buf = dumb_string::copy(sd->status.name);
+ dumb_string buf = dumb_string::copys(sd->status.name.to__actual());
push_str(st->stack, ByteCode::STR, buf);
}
if (num == 1)
@@ -2240,7 +2218,7 @@ void builtin_getequipname(ScriptState *st)
dumb_ptr<map_session_data> sd;
struct item_data *item;
- std::string buf;
+ FString buf;
sd = script_rid2sd(st);
num = conv_num(st, &AARGO2(2));
@@ -2418,10 +2396,10 @@ void builtin_savepoint(ScriptState *st)
{
int x, y;
- dumb_string str = conv_str(st, &AARGO2(2));
+ MapName str = stringish<MapName>(ZString(conv_str(st, &AARGO2(2))));
x = conv_num(st, &AARGO2(3));
y = conv_num(st, &AARGO2(4));
- pc_setsavepoint(script_rid2sd(st), str.c_str(), x, y);
+ pc_setsavepoint(script_rid2sd(st), str, x, y);
}
/*==========================================
@@ -2551,19 +2529,19 @@ static
void builtin_monster(ScriptState *st)
{
int mob_class, amount, x, y;
- const char *event = "";
+ NpcEvent event;
- dumb_string mapname = conv_str(st, &AARGO2(2));
+ MapName mapname = stringish<MapName>(ZString(conv_str(st, &AARGO2(2))));
x = conv_num(st, &AARGO2(3));
y = conv_num(st, &AARGO2(4));
- dumb_string str = conv_str(st, &AARGO2(5));
+ MobName str = stringish<MobName>(ZString(conv_str(st, &AARGO2(5))));
mob_class = conv_num(st, &AARGO2(6));
amount = conv_num(st, &AARGO2(7));
if (HARGO2(8))
- event = conv_str(st, &AARGO2(8)).c_str();
+ extract(ZString(conv_str(st, &AARGO2(8))), &event);
- mob_once_spawn(map_id2sd(st->rid), mapname.c_str(), x, y, str.c_str(), mob_class, amount,
- event);
+ mob_once_spawn(map_id2sd(st->rid), mapname, x, y, str, mob_class, amount,
+ event);
}
/*==========================================
@@ -2574,21 +2552,21 @@ static
void builtin_areamonster(ScriptState *st)
{
int mob_class, amount, x0, y0, x1, y1;
- const char *event = "";
+ NpcEvent event;
- dumb_string mapname = conv_str(st, &AARGO2(2));
+ MapName mapname = stringish<MapName>(ZString(conv_str(st, &AARGO2(2))));
x0 = conv_num(st, &AARGO2(3));
y0 = conv_num(st, &AARGO2(4));
x1 = conv_num(st, &AARGO2(5));
y1 = conv_num(st, &AARGO2(6));
- dumb_string str = conv_str(st, &AARGO2(7));
+ MobName str = stringish<MobName>(ZString(conv_str(st, &AARGO2(7))));
mob_class = conv_num(st, &AARGO2(8));
amount = conv_num(st, &AARGO2(9));
if (HARGO2(10))
- event = conv_str(st, &AARGO2(10)).c_str();
+ extract(ZString(conv_str(st, &AARGO2(10))), &event);
- mob_once_spawn_area(map_id2sd(st->rid), mapname.c_str(), x0, y0, x1, y1, str.c_str(), mob_class,
- amount, event);
+ mob_once_spawn_area(map_id2sd(st->rid), mapname, x0, y0, x1, y1, str, mob_class,
+ amount, event);
}
/*==========================================
@@ -2596,17 +2574,16 @@ void builtin_areamonster(ScriptState *st)
*------------------------------------------
*/
static
-void builtin_killmonster_sub(dumb_ptr<block_list> bl, dumb_string event, int allflag)
+void builtin_killmonster_sub(dumb_ptr<block_list> bl, NpcEvent event)
{
dumb_ptr<mob_data> md = bl->as_mob();
- if (!allflag)
+ if (event)
{
- using namespace operators;
if (event == md->npc_event)
mob_delete(md);
return;
}
- else if (allflag)
+ else if (!event)
{
if (md->spawn.delay1 == static_cast<interval_t>(-1)
&& md->spawn.delay2 == static_cast<interval_t>(-1))
@@ -2618,17 +2595,16 @@ void builtin_killmonster_sub(dumb_ptr<block_list> bl, dumb_string event, int all
static
void builtin_killmonster(ScriptState *st)
{
- int allflag = 0;
- dumb_string mapname = conv_str(st, &AARGO2(2));
- dumb_string event = conv_str(st, &AARGO2(3));
- using namespace operators;
- if (event == "All")
- allflag = 1;
+ MapName mapname = stringish<MapName>(ZString(conv_str(st, &AARGO2(2))));
+ ZString event_ = ZString(conv_str(st, &AARGO2(3)));
+ NpcEvent event;
+ if (event_ != "All")
+ extract(event_, &event);
- map_local *m = map_mapname2mapid(mapname.c_str());
+ map_local *m = map_mapname2mapid(mapname);
if (m == nullptr)
return;
- map_foreachinarea(std::bind(builtin_killmonster_sub, ph::_1, event, allflag),
+ map_foreachinarea(std::bind(builtin_killmonster_sub, ph::_1, event),
m,
0, 0,
m->xs, m->ys,
@@ -2644,9 +2620,9 @@ void builtin_killmonsterall_sub(dumb_ptr<block_list> bl)
static
void builtin_killmonsterall(ScriptState *st)
{
- dumb_string mapname = conv_str(st, &AARGO2(2));
+ MapName mapname = stringish<MapName>(ZString(conv_str(st, &AARGO2(2))));
- map_local *m = map_mapname2mapid(mapname.c_str());
+ map_local *m = map_mapname2mapid(mapname);
if (m == nullptr)
return;
map_foreachinarea(builtin_killmonsterall_sub,
@@ -2663,8 +2639,10 @@ void builtin_killmonsterall(ScriptState *st)
static
void builtin_donpcevent(ScriptState *st)
{
- dumb_string event = conv_str(st, &AARGO2(2));
- npc_event_do(event.c_str());
+ ZString event_ = ZString(conv_str(st, &AARGO2(2)));
+ NpcEvent event;
+ extract(event_, &event);
+ npc_event_do(event);
}
/*==========================================
@@ -2675,8 +2653,10 @@ static
void builtin_addtimer(ScriptState *st)
{
interval_t tick = static_cast<interval_t>(conv_num(st, &AARGO2(2)));
- dumb_string event = conv_str(st, &AARGO2(3));
- pc_addeventtimer(script_rid2sd(st), tick, event.c_str());
+ ZString event_ = ZString(conv_str(st, &AARGO2(3)));
+ NpcEvent event;
+ extract(event_, &event);
+ pc_addeventtimer(script_rid2sd(st), tick, event);
}
/*==========================================
@@ -2688,7 +2668,7 @@ void builtin_initnpctimer(ScriptState *st)
{
dumb_ptr<npc_data> nd_;
if (HARGO2(2))
- nd_ = npc_name2id(conv_str(st, &AARGO2(2)).c_str());
+ nd_ = npc_name2id(stringish<NpcName>(ZString(conv_str(st, &AARGO2(2)))));
else
nd_ = map_id_as_npc(st->oid);
assert (nd_ && nd_->npc_subtype == NpcSubtype::SCRIPT);
@@ -2707,7 +2687,7 @@ void builtin_startnpctimer(ScriptState *st)
{
dumb_ptr<npc_data> nd_;
if (HARGO2(2))
- nd_ = npc_name2id(conv_str(st, &AARGO2(2)).c_str());
+ nd_ = npc_name2id(stringish<NpcName>(ZString(conv_str(st, &AARGO2(2)))));
else
nd_ = map_id_as_npc(st->oid);
assert (nd_ && nd_->npc_subtype == NpcSubtype::SCRIPT);
@@ -2725,7 +2705,7 @@ void builtin_stopnpctimer(ScriptState *st)
{
dumb_ptr<npc_data> nd_;
if (HARGO2(2))
- nd_ = npc_name2id(conv_str(st, &AARGO2(2)).c_str());
+ nd_ = npc_name2id(stringish<NpcName>(ZString(conv_str(st, &AARGO2(2)))));
else
nd_ = map_id_as_npc(st->oid);
assert (nd_ && nd_->npc_subtype == NpcSubtype::SCRIPT);
@@ -2745,7 +2725,7 @@ void builtin_getnpctimer(ScriptState *st)
int type = conv_num(st, &AARGO2(2));
int val = 0;
if (HARGO2(3))
- nd_ = npc_name2id(conv_str(st, &AARGO2(3)).c_str());
+ nd_ = npc_name2id(stringish<NpcName>(ZString(conv_str(st, &AARGO2(3)))));
else
nd_ = map_id_as_npc(st->oid);
assert (nd_ && nd_->npc_subtype == NpcSubtype::SCRIPT);
@@ -2776,7 +2756,7 @@ void builtin_setnpctimer(ScriptState *st)
dumb_ptr<npc_data> nd_;
interval_t tick = static_cast<interval_t>(conv_num(st, &AARGO2(2)));
if (HARGO2(3))
- nd_ = npc_name2id(conv_str(st, &AARGO2(3)).c_str());
+ nd_ = npc_name2id(stringish<NpcName>(ZString(conv_str(st, &AARGO2(3)))));
else
nd_ = map_id_as_npc(st->oid);
assert (nd_ && nd_->npc_subtype == NpcSubtype::SCRIPT);
@@ -2793,7 +2773,7 @@ static
void builtin_announce(ScriptState *st)
{
int flag;
- dumb_string str = conv_str(st, &AARGO2(2));
+ ZString str = ZString(conv_str(st, &AARGO2(2)));
flag = conv_num(st, &AARGO2(3));
if (flag & 0x0f)
@@ -2814,7 +2794,7 @@ void builtin_announce(ScriptState *st)
*------------------------------------------
*/
static
-void builtin_mapannounce_sub(dumb_ptr<block_list> bl, dumb_string str, int flag)
+void builtin_mapannounce_sub(dumb_ptr<block_list> bl, XString str, int flag)
{
clif_GMmessage(bl, str, flag | 3);
}
@@ -2824,11 +2804,11 @@ void builtin_mapannounce(ScriptState *st)
{
int flag;
- dumb_string mapname = conv_str(st, &AARGO2(2));
- dumb_string str = conv_str(st, &AARGO2(3));
+ MapName mapname = stringish<MapName>(ZString(conv_str(st, &AARGO2(2))));
+ ZString str = ZString(conv_str(st, &AARGO2(3)));
flag = conv_num(st, &AARGO2(4));
- map_local *m = map_mapname2mapid(mapname.c_str());
+ map_local *m = map_mapname2mapid(mapname);
if (m == nullptr)
return;
map_foreachinarea(std::bind(builtin_mapannounce_sub, ph::_1, str, flag & 0x10),
@@ -2867,8 +2847,8 @@ void builtin_getusers(ScriptState *st)
static
void builtin_getmapusers(ScriptState *st)
{
- dumb_string str = conv_str(st, &AARGO2(2));
- map_local *m = map_mapname2mapid(str.c_str());
+ MapName str = stringish<MapName>(ZString(conv_str(st, &AARGO2(2))));
+ map_local *m = map_mapname2mapid(str);
if (m == nullptr)
{
push_int(st->stack, ByteCode::INT, -1);
@@ -2898,7 +2878,7 @@ static
void builtin_getareausers(ScriptState *st)
{
int x0, y0, x1, y1, users = 0;
- dumb_string str = conv_str(st, &AARGO2(2));
+ MapName str = stringish<MapName>(ZString(conv_str(st, &AARGO2(2))));
x0 = conv_num(st, &AARGO2(3));
y0 = conv_num(st, &AARGO2(4));
x1 = conv_num(st, &AARGO2(5));
@@ -2909,7 +2889,7 @@ void builtin_getareausers(ScriptState *st)
{
living = conv_num(st, &AARGO2(7));
}
- map_local *m = map_mapname2mapid(str.c_str());
+ map_local *m = map_mapname2mapid(str);
if (m == nullptr)
{
push_int(st->stack, ByteCode::INT, -1);
@@ -2956,7 +2936,7 @@ void builtin_getareadropitem(ScriptState *st)
int x0, y0, x1, y1, item, amount = 0, delitems = 0;
struct script_data *data;
- dumb_string str = conv_str(st, &AARGO2(2));
+ MapName str = stringish<MapName>(ZString(conv_str(st, &AARGO2(2))));
x0 = conv_num(st, &AARGO2(3));
y0 = conv_num(st, &AARGO2(4));
x1 = conv_num(st, &AARGO2(5));
@@ -2966,8 +2946,8 @@ void builtin_getareadropitem(ScriptState *st)
get_val(st, data);
if (data->type == ByteCode::STR || data->type == ByteCode::CONSTSTR)
{
- dumb_string name = conv_str(st, data);
- struct item_data *item_data = itemdb_searchname(name.c_str());
+ ItemName name = stringish<ItemName>(ZString(conv_str(st, data)));
+ struct item_data *item_data = itemdb_searchname(name);
item = 512;
if (item_data)
item = item_data->nameid;
@@ -2978,7 +2958,7 @@ void builtin_getareadropitem(ScriptState *st)
if (HARGO2(8))
delitems = conv_num(st, &AARGO2(8));
- map_local *m = map_mapname2mapid(str.c_str());
+ map_local *m = map_mapname2mapid(str);
if (m == nullptr)
{
push_int(st->stack, ByteCode::INT, -1);
@@ -3007,8 +2987,8 @@ void builtin_getareadropitem(ScriptState *st)
static
void builtin_enablenpc(ScriptState *st)
{
- dumb_string str = conv_str(st, &AARGO2(2));
- npc_enable(str.c_str(), 1);
+ NpcName str = stringish<NpcName>(ZString(conv_str(st, &AARGO2(2))));
+ npc_enable(str, 1);
}
/*==========================================
@@ -3018,8 +2998,8 @@ void builtin_enablenpc(ScriptState *st)
static
void builtin_disablenpc(ScriptState *st)
{
- dumb_string str = conv_str(st, &AARGO2(2));
- npc_enable(str.c_str(), 0);
+ NpcName str = stringish<NpcName>(ZString(conv_str(st, &AARGO2(2))));
+ npc_enable(str, 0);
}
/*==========================================
@@ -3118,7 +3098,7 @@ void builtin_changesex(ScriptState *st)
sd->status.sex = 0;
sd->sex = 0;
}
- chrif_char_ask_name(-1, sd->status.name, 5, 0, 0, 0, 0, 0, 0); // type: 5 - changesex
+ chrif_char_ask_name(-1, sd->status.name, 5, HumanTimeDiff()); // type: 5 - changesex
chrif_save(sd);
}
@@ -3187,9 +3167,9 @@ enum
static
void builtin_setmapflag(ScriptState *st)
{
- dumb_string str = conv_str(st, &AARGO2(2));
+ MapName str = stringish<MapName>(ZString(conv_str(st, &AARGO2(2))));
int i = conv_num(st, &AARGO2(3));
- map_local *m = map_mapname2mapid(str.c_str());
+ map_local *m = map_mapname2mapid(str);
if (m != nullptr)
{
switch (i)
@@ -3247,9 +3227,9 @@ void builtin_setmapflag(ScriptState *st)
static
void builtin_removemapflag(ScriptState *st)
{
- dumb_string str = conv_str(st, &AARGO2(2));
+ MapName str = stringish<MapName>(ZString(conv_str(st, &AARGO2(2))));
int i = conv_num(st, &AARGO2(3));
- map_local *m = map_mapname2mapid(str.c_str());
+ map_local *m = map_mapname2mapid(str);
if (m != nullptr)
{
switch (i)
@@ -3308,9 +3288,9 @@ void builtin_getmapflag(ScriptState *st)
{
int r = -1;
- dumb_string str = conv_str(st, &AARGO2(2));
+ MapName str = stringish<MapName>(ZString(conv_str(st, &AARGO2(2))));
int i = conv_num(st, &AARGO2(3));
- map_local *m = map_mapname2mapid(str.c_str());
+ map_local *m = map_mapname2mapid(str);
if (m != nullptr)
{
switch (i)
@@ -3369,8 +3349,8 @@ void builtin_getmapflag(ScriptState *st)
static
void builtin_pvpon(ScriptState *st)
{
- dumb_string str = conv_str(st, &AARGO2(2));
- map_local *m = map_mapname2mapid(str.c_str());
+ MapName str = stringish<MapName>(ZString(conv_str(st, &AARGO2(2))));
+ map_local *m = map_mapname2mapid(str);
if (m != nullptr && !m->flag.pvp && !m->flag.nopvp)
{
m->flag.pvp = 1;
@@ -3403,8 +3383,8 @@ void builtin_pvpon(ScriptState *st)
static
void builtin_pvpoff(ScriptState *st)
{
- dumb_string str = conv_str(st, &AARGO2(2));
- map_local *m = map_mapname2mapid(str.c_str());
+ MapName str = stringish<MapName>(ZString(conv_str(st, &AARGO2(2))));
+ map_local *m = map_mapname2mapid(str);
if (m != nullptr && m->flag.pvp && m->flag.nopvp)
{
m->flag.pvp = 0;
@@ -3450,13 +3430,13 @@ void builtin_mapwarp(ScriptState *st) // Added by RoVeRT
int x, y;
int x0, y0, x1, y1;
- dumb_string mapname = conv_str(st, &AARGO2(2));
+ MapName mapname = stringish<MapName>(ZString(conv_str(st, &AARGO2(2))));
x0 = 0;
y0 = 0;
- map_local *m = map_mapname2mapid(mapname.c_str());
+ map_local *m = map_mapname2mapid(mapname);
x1 = m->xs;
y1 = m->ys;
- dumb_string str = conv_str(st, &AARGO2(3));
+ MapName str = stringish<MapName>(ZString(conv_str(st, &AARGO2(3))));
x = conv_num(st, &AARGO2(4));
y = conv_num(st, &AARGO2(5));
@@ -3473,16 +3453,15 @@ void builtin_mapwarp(ScriptState *st) // Added by RoVeRT
static
void builtin_cmdothernpc(ScriptState *st) // Added by RoVeRT
{
- dumb_string npc = conv_str(st, &AARGO2(2));
- dumb_string command = conv_str(st, &AARGO2(3));
+ NpcName npc = stringish<NpcName>(ZString(conv_str(st, &AARGO2(2))));
+ ZString command = ZString(conv_str(st, &AARGO2(3)));
- npc_command(map_id2sd(st->rid), npc.c_str(), command.c_str());
+ npc_command(map_id2sd(st->rid), npc, command);
}
static
-void builtin_mobcount_sub(dumb_ptr<block_list> bl, dumb_string event, int *c)
+void builtin_mobcount_sub(dumb_ptr<block_list> bl, NpcEvent event, int *c)
{
- using namespace operators;
if (event == bl->as_mob()->npc_event)
(*c)++;
}
@@ -3491,10 +3470,12 @@ static
void builtin_mobcount(ScriptState *st) // Added by RoVeRT
{
int c = 0;
- dumb_string mapname = conv_str(st, &AARGO2(2));
- dumb_string event = conv_str(st, &AARGO2(3));
+ MapName mapname = stringish<MapName>(ZString(conv_str(st, &AARGO2(2))));
+ ZString event_ = ZString(conv_str(st, &AARGO2(3)));
+ NpcEvent event;
+ extract(event_, &event);
- map_local *m = map_mapname2mapid(mapname.c_str());
+ map_local *m = map_mapname2mapid(mapname);
if (m == nullptr)
{
push_int(st->stack, ByteCode::INT, -1);
@@ -3513,9 +3494,9 @@ void builtin_mobcount(ScriptState *st) // Added by RoVeRT
static
void builtin_marriage(ScriptState *st)
{
- dumb_string partner = conv_str(st, &AARGO2(2));
+ CharName partner = stringish<CharName>(ZString(conv_str(st, &AARGO2(2))));
dumb_ptr<map_session_data> sd = script_rid2sd(st);
- dumb_ptr<map_session_data> p_sd = map_nick2sd(partner.c_str());
+ dumb_ptr<map_session_data> p_sd = map_nick2sd(partner);
if (sd == NULL || p_sd == NULL || pc_marriage(sd, p_sd) < 0)
{
@@ -3557,8 +3538,8 @@ void builtin_getitemname(ScriptState *st)
get_val(st, data);
if (data->type == ByteCode::STR || data->type == ByteCode::CONSTSTR)
{
- dumb_string name = conv_str(st, data);
- i_data = itemdb_searchname(name.c_str());
+ ItemName name = stringish<ItemName>(ZString(conv_str(st, data)));
+ i_data = itemdb_searchname(name);
}
else
{
@@ -3568,9 +3549,9 @@ void builtin_getitemname(ScriptState *st)
dumb_string item_name;
if (i_data)
- item_name = dumb_string::copy(i_data->jname);
+ item_name = dumb_string::copys(i_data->jname);
else
- item_name = dumb_string::copy("Unknown Item");
+ item_name = dumb_string::copys("Unknown Item");
push_str(st->stack, ByteCode::STR, item_name);
}
@@ -3580,11 +3561,11 @@ void builtin_getspellinvocation(ScriptState *st)
{
dumb_string name = conv_str(st, &AARGO2(2));
- const char *invocation = magic_find_invocation(name.str());
+ FString invocation = magic_find_invocation(name.str());
if (!invocation)
invocation = "...";
- push_str(st->stack, ByteCode::STR, dumb_string::copy(invocation));
+ push_str(st->stack, ByteCode::STR, dumb_string::copys(invocation));
}
static
@@ -3661,7 +3642,7 @@ void builtin_getactivatedpoolskilllist(ScriptState *st)
pc_setreg(sd, SIR::from(variable_names.intern("@skilllist_flag"), count),
static_cast<uint16_t>(sd->status.skill[skill_id].flags));
pc_setregstr(sd, SIR::from(variable_names.intern("@skilllist_name$"), count),
- skill_name(skill_id).c_str());
+ skill_name(skill_id));
++count;
}
}
@@ -3692,7 +3673,7 @@ void builtin_getunactivatedpoolskilllist(ScriptState *st)
pc_setreg(sd, SIR::from(variable_names.intern("@skilllist_flag"), count),
static_cast<uint16_t>(sd->status.skill[skill_id].flags));
pc_setregstr(sd, SIR::from(variable_names.intern("@skilllist_name$"), count),
- skill_name(skill_id).c_str());
+ skill_name(skill_id));
++count;
}
}
@@ -3737,7 +3718,7 @@ void builtin_misceffect(ScriptState *st)
{
int type;
int id = 0;
- dumb_string name;
+ CharName name;
dumb_ptr<block_list> bl = NULL;
type = conv_num(st, &AARGO2(2));
@@ -3749,14 +3730,14 @@ void builtin_misceffect(ScriptState *st)
get_val(st, sdata);
if (sdata->type == ByteCode::STR || sdata->type == ByteCode::CONSTSTR)
- name = conv_str(st, sdata);
+ name = stringish<CharName>(ZString(conv_str(st, sdata)));
else
id = conv_num(st, sdata);
}
- if (name)
+ if (name.to__actual())
{
- dumb_ptr<map_session_data> sd = map_nick2sd(name.c_str());
+ dumb_ptr<map_session_data> sd = map_nick2sd(name);
if (sd)
bl = sd;
}
@@ -3867,7 +3848,7 @@ void builtin_gmcommand(ScriptState *st)
sd = script_rid2sd(st);
dumb_string cmd = conv_str(st, &AARGO2(2));
- is_atcommand(sd->fd, sd, cmd.c_str(), 99);
+ is_atcommand(sd->fd, sd, cmd, 99);
}
@@ -3884,8 +3865,8 @@ void builtin_npcwarp(ScriptState *st)
x = conv_num(st, &AARGO2(2));
y = conv_num(st, &AARGO2(3));
- dumb_string npc = conv_str(st, &AARGO2(4));
- nd = npc_name2id(npc.c_str());
+ NpcName npc = stringish<NpcName>(ZString(conv_str(st, &AARGO2(4))));
+ nd = npc_name2id(npc);
if (!nd)
return;
@@ -3898,12 +3879,12 @@ void builtin_npcwarp(ScriptState *st)
|| y < 0 || y > m->ys - 1)
return;
- npc_enable(npc.c_str(), 0);
+ npc_enable(npc, 0);
map_delblock(nd); /* [Freeyorp] */
nd->bl_x = x;
nd->bl_y = y;
map_addblock(nd);
- npc_enable(npc.c_str(), 1);
+ npc_enable(npc, 1);
}
@@ -3915,10 +3896,10 @@ void builtin_npcwarp(ScriptState *st)
static
void builtin_message(ScriptState *st)
{
- dumb_string player = conv_str(st, &AARGO2(2));
- dumb_string msg = conv_str(st, &AARGO2(3));
+ CharName player = stringish<CharName>(ZString(conv_str(st, &AARGO2(2))));
+ ZString msg = ZString(conv_str(st, &AARGO2(3)));
- dumb_ptr<map_session_data> pl_sd = map_nick2sd(player.c_str());
+ dumb_ptr<map_session_data> pl_sd = map_nick2sd(player);
if (pl_sd == NULL)
return;
clif_displaymessage(pl_sd->fd, msg);
@@ -3939,8 +3920,11 @@ void builtin_npctalk(ScriptState *st)
if (nd)
{
- std::string message = std::string(nd->name) + " : " + str.c_str();
- clif_message(nd, message.c_str());
+ MString message;
+ message += nd->name;
+ message += " : ";
+ message += ZString(str);
+ clif_message(nd, FString(message));
}
}
@@ -4008,7 +3992,7 @@ void builtin_getsavepoint(ScriptState *st)
{
case 0:
{
- dumb_string mapname = dumb_string::copy(sd->status.save_point.map_);
+ dumb_string mapname = dumb_string::copys(sd->status.save_point.map_);
push_str(st->stack, ByteCode::STR, mapname);
}
break;
@@ -4026,9 +4010,9 @@ void builtin_getsavepoint(ScriptState *st)
*------------------------------------------
*/
static
-void builtin_areatimer_sub(dumb_ptr<block_list> bl, interval_t tick, dumb_string event)
+void builtin_areatimer_sub(dumb_ptr<block_list> bl, interval_t tick, NpcEvent event)
{
- pc_addeventtimer(bl->as_player(), tick, event.c_str());
+ pc_addeventtimer(bl->as_player(), tick, event);
}
static
@@ -4036,15 +4020,17 @@ void builtin_areatimer(ScriptState *st)
{
int x0, y0, x1, y1;
- dumb_string mapname = conv_str(st, &AARGO2(2));
+ MapName mapname = stringish<MapName>(ZString(conv_str(st, &AARGO2(2))));
x0 = conv_num(st, &AARGO2(3));
y0 = conv_num(st, &AARGO2(4));
x1 = conv_num(st, &AARGO2(5));
y1 = conv_num(st, &AARGO2(6));
interval_t tick = static_cast<interval_t>(conv_num(st, &AARGO2(7)));
- dumb_string event = conv_str(st, &AARGO2(8));
+ ZString event_ = ZString(conv_str(st, &AARGO2(8)));
+ NpcEvent event;
+ extract(event_, &event);
- map_local *m = map_mapname2mapid(mapname.c_str());
+ map_local *m = map_mapname2mapid(mapname);
if (m == nullptr)
return;
@@ -4065,7 +4051,7 @@ void builtin_isin(ScriptState *st)
int x1, y1, x2, y2;
dumb_ptr<map_session_data> sd = script_rid2sd(st);
- dumb_string str = conv_str(st, &AARGO2(2));
+ MapName str = stringish<MapName>(ZString(conv_str(st, &AARGO2(2))));
x1 = conv_num(st, &AARGO2(3));
y1 = conv_num(st, &AARGO2(4));
x2 = conv_num(st, &AARGO2(5));
@@ -4074,7 +4060,6 @@ void builtin_isin(ScriptState *st)
if (!sd)
return;
- using namespace operators;
push_int(st->stack, ByteCode::INT,
(sd->bl_x >= x1 && sd->bl_x <= x2)
&& (sd->bl_y >= y1 && sd->bl_y <= y2)
@@ -4091,7 +4076,7 @@ void builtin_shop(ScriptState *st)
if (!sd)
return;
- nd = npc_name2id(conv_str(st, &AARGO2(2)).c_str());
+ nd = npc_name2id(stringish<NpcName>(ZString(conv_str(st, &AARGO2(2)))));
if (!nd)
return;
@@ -4118,18 +4103,18 @@ void builtin_isdead(ScriptState *st)
static
void builtin_fakenpcname(ScriptState *st)
{
- dumb_string name = conv_str(st, &AARGO2(2));
- dumb_string newname = conv_str(st, &AARGO2(3));
+ NpcName name = stringish<NpcName>(ZString(conv_str(st, &AARGO2(2))));
+ NpcName newname = stringish<NpcName>(ZString(conv_str(st, &AARGO2(3))));
int newsprite = conv_num(st, &AARGO2(4));
- dumb_ptr<npc_data> nd = npc_name2id(name.c_str());
+ dumb_ptr<npc_data> nd = npc_name2id(name);
if (!nd)
return;
- strzcpy(nd->name, newname.c_str(), sizeof(nd->name));
+ nd->name = newname;
nd->npc_class = newsprite;
// Refresh this npc
- npc_enable(name.c_str(), 0);
- npc_enable(name.c_str(), 1);
+ npc_enable(name, 0);
+ npc_enable(name, 1);
}
@@ -4254,13 +4239,15 @@ void op_add(ScriptState *st)
{
dumb_string sb = conv_str(st, &back);
dumb_string sb1 = conv_str(st, &back1);
- std::string buf = sb1.str() + sb.str();
+ MString buf;
+ buf += ZString(sb1);
+ buf += ZString(sb);
if (back1.type == ByteCode::STR)
back1.u.str.delete_();
if (back.type == ByteCode::STR)
back.u.str.delete_();
back1.type = ByteCode::STR;
- back1.u.str = dumb_string::copys(buf);
+ back1.u.str = dumb_string::copys(FString(buf));
}
}
@@ -4269,11 +4256,12 @@ void op_add(ScriptState *st)
*------------------------------------------
*/
static
-void op_2str(ScriptState *st, ByteCode op, dumb_string s1, dumb_string s2)
+void op_2str(ScriptState *st, ByteCode op, dumb_string s1_, dumb_string s2_)
{
+ ZString s1 = ZString(s1_);
+ ZString s2 = ZString(s2_);
int a = 0;
- using namespace operators;
switch (op)
{
case ByteCode::EQ:
@@ -4697,7 +4685,7 @@ int run_script(ScriptPointer sp, int rid, int oid)
}
int run_script_l(ScriptPointer sp, int rid, int oid,
- int args_nr, argrec_t *args)
+ int args_nr, argrec_t *args)
{
struct script_stack stack;
ScriptState st;
@@ -4719,7 +4707,7 @@ int run_script_l(ScriptPointer sp, int rid, int oid,
st.oid = oid;
for (i = 0; i < args_nr; i++)
{
- if (args[i].name[strlen(args[i].name) - 1] == '$')
+ if (args[i].name.back() == '$')
pc_setregstr(sd, SIR::from(variable_names.intern(args[i].name)), args[i].v.s);
else
pc_setreg(sd, SIR::from(variable_names.intern(args[i].name)), args[i].v.i);
@@ -4745,9 +4733,9 @@ void mapreg_setreg(SIR reg, int val)
* 文字列型マップ変数の変更
*------------------------------------------
*/
-void mapreg_setregstr(SIR reg, const char *str)
+void mapreg_setregstr(SIR reg, XString str)
{
- if (!str || !*str)
+ if (!str)
mapregstr_db.erase(reg);
else
mapregstr_db.insert(reg, str);
@@ -4762,15 +4750,15 @@ void mapreg_setregstr(SIR reg, const char *str)
static
void script_load_mapreg(void)
{
- std::ifstream in(mapreg_txt);
+ std::ifstream in(mapreg_txt.c_str());
if (!in.is_open())
return;
- std::string line;
- while (std::getline(in, line))
+ FString line;
+ while (io::getline(in, line))
{
- std::string buf1, buf2;
+ XString buf1, buf2;
int index = 0;
if (extract(line,
record<'\t'>(
@@ -4798,7 +4786,7 @@ void script_load_mapreg(void)
else
{
borken:
- PRINTF("%s: %s broken data !\n", mapreg_txt, buf1);
+ PRINTF("%s: %s broken data !\n", mapreg_txt, FString(buf1));
continue;
}
}
@@ -4813,7 +4801,7 @@ static
void script_save_mapreg_intsub(SIR key, int data, FILE *fp)
{
int num = key.base(), i = key.index();
- const std::string& name = variable_names.outtern(num);
+ ZString name = variable_names.outtern(num);
if (name[1] != '@')
{
if (i == 0)
@@ -4824,10 +4812,10 @@ void script_save_mapreg_intsub(SIR key, int data, FILE *fp)
}
static
-void script_save_mapreg_strsub(SIR key, const std::string& data, FILE *fp)
+void script_save_mapreg_strsub(SIR key, ZString data, FILE *fp)
{
int num = key.base(), i = key.index();
- const std::string& name = variable_names.outtern(num);
+ ZString name = variable_names.outtern(num);
if (name[1] != '@')
{
if (i == 0)
@@ -4876,12 +4864,8 @@ void do_final_script(void)
script_save_mapreg();
mapreg_db.clear();
- for (auto& pair : mapregstr_db)
- pair.second.clear();
mapregstr_db.clear();
scriptlabel_db.clear();
- for (auto& pair : userfunc_db)
- pair.second.reset();
userfunc_db.clear();
str_datam.clear();
@@ -4902,7 +4886,7 @@ void do_init_script(void)
}
#define BUILTIN(func, args) \
-{builtin_##func, #func, args}
+{builtin_##func, {#func}, {args}}
BuiltinFunction builtin_functions[] =
{
@@ -5022,5 +5006,5 @@ BuiltinFunction builtin_functions[] =
BUILTIN(getx, ""),
BUILTIN(gety, ""),
BUILTIN(getmap, ""),
- {NULL, NULL, NULL},
+ {nullptr, ZString(), ZString()},
};
diff --git a/src/map/script.hpp b/src/map/script.hpp
index 66939aa..4e8f9ac 100644
--- a/src/map/script.hpp
+++ b/src/map/script.hpp
@@ -4,11 +4,11 @@
#include <cstdint>
#include <cstring> // for inlined get_str - TODO remove
-#include <string>
#include <vector>
#include "../common/db.hpp"
#include "../common/dumb_ptr.hpp"
+#include "../common/utils.hpp"
#include "map.t.hpp"
@@ -25,17 +25,17 @@ public:
void add_scripti(uint32_t a);
void add_scriptl(str_data_t *a);
void set_label(str_data_t *ld, int pos_);
- const char *parse_simpleexpr(const char *p);
- const char *parse_subexpr(const char *p, int limit);
- const char *parse_expr(const char *p);
- const char *parse_line(const char *p);
- void parse_script(const char *src, int line);
+ ZString::iterator parse_simpleexpr(ZString::iterator p);
+ ZString::iterator parse_subexpr(ZString::iterator p, int limit);
+ ZString::iterator parse_expr(ZString::iterator p);
+ ZString::iterator parse_line(ZString::iterator p);
+ void parse_script(ZString src, int line);
// consumption methods used only by script.cpp
ByteCode operator[](size_t i) const { return script_buf[i]; }
- const char *get_str(size_t i) const
+ ZString get_str(size_t i) const
{
- return reinterpret_cast<const char *>(&script_buf[i]);
+ return ZString(ZString::really_construct_from_a_pointer, reinterpret_cast<const char *>(&script_buf[i]), nullptr);
}
// method used elsewhere
@@ -58,10 +58,10 @@ struct ScriptPointer
ByteCode peek() const { return (*code)[pos]; }
ByteCode pop() { return (*code)[pos++]; }
- const char *pops()
+ ZString pops()
{
- const char *rv = code->get_str(pos);
- pos += strlen(rv);
+ ZString rv = code->get_str(pos);
+ pos += rv.size();
++pos;
return rv;
}
@@ -129,33 +129,36 @@ public:
int defsp, new_defsp;
};
-std::unique_ptr<const ScriptBuffer> parse_script(const char *, int);
-typedef struct argrec
+std::unique_ptr<const ScriptBuffer> parse_script(ZString, int);
+struct argrec_t
{
- const char *name;
+ ZString name;
union _aru
{
int i;
- const char *s;
+ ZString s;
- _aru() = default;
_aru(int n) : i(n) {}
- _aru(const char *z) : s(z) {}
+ _aru(ZString z) : s(z) {}
} v;
-} argrec_t;
+
+ argrec_t(ZString n, int i) : name(n), v(i) {}
+ argrec_t(ZString n, ZString z) : name(n), v(z) {}
+};
int run_script_l(ScriptPointer, int, int, int, argrec_t *args);
int run_script(ScriptPointer, int, int);
+struct ScriptLabel;
extern
-Map<std::string, int> scriptlabel_db;
+Map<ScriptLabel, int> scriptlabel_db;
extern
-UPMap<std::string, const ScriptBuffer> userfunc_db;
+UPMap<FString, const ScriptBuffer> userfunc_db;
void script_config_read();
void do_init_script(void);
void do_final_script(void);
-extern char mapreg_txt[256];
+extern FString mapreg_txt;
extern int script_errors;
diff --git a/src/map/skill.cpp b/src/map/skill.cpp
index c4b1dc8..7489731 100644
--- a/src/map/skill.cpp
+++ b/src/map/skill.cpp
@@ -5,9 +5,13 @@
#include <cstring>
#include <ctime>
+#include <fstream>
+
#include "../common/cxxstdio.hpp"
-#include "../common/random.hpp"
+#include "../common/extract.hpp"
+#include "../common/io.hpp"
#include "../common/nullpo.hpp"
+#include "../common/random.hpp"
#include "../common/socket.hpp"
#include "../common/timer.hpp"
@@ -1144,24 +1148,24 @@ void skill_unit_timer_sub_ondelete(dumb_ptr<block_list> bl,
*/
static
-SP scan_stat(char *statname)
+SP scan_stat(XString statname)
{
- if (!strcasecmp(statname, "str"))
+ if (statname == "str")
return SP::STR;
- if (!strcasecmp(statname, "dex"))
+ if (statname == "dex")
return SP::DEX;
- if (!strcasecmp(statname, "agi"))
+ if (statname == "agi")
return SP::AGI;
- if (!strcasecmp(statname, "vit"))
+ if (statname == "vit")
return SP::VIT;
- if (!strcasecmp(statname, "int"))
+ if (statname == "int")
return SP::INT;
- if (!strcasecmp(statname, "luk"))
+ if (statname == "luk")
return SP::LUK;
- if (!strcasecmp(statname, "none"))
+ if (statname == "none")
return SP::ZERO;
- FPRINTF(stderr, "Unknown stat `%s'\n", statname);
+ FPRINTF(stderr, "Unknown stat `%s'\n", FString(statname));
return SP::ZERO;
}
@@ -1174,93 +1178,89 @@ SP scan_stat(char *statname)
static
int skill_readdb(void)
{
- int j;
- FILE *fp;
- char line[1024], *p;
-
/* The main skill database */
for (skill_db_& skdb : skill_db)
skdb = skill_db_{};
- fp = fopen_("db/skill_db.txt", "r");
- if (fp == NULL)
+ std::ifstream in("db/skill_db.txt");
+ if (!in)
{
PRINTF("can't read db/skill_db.txt\n");
return 1;
}
- while (fgets(line, 1020, fp))
+
+ FString line_;
+ while (io::getline(in, line_))
{
- char *split[50];
- if (line[0] == '/' && line[1] == '/')
+ XString comment = "//";
+ XString line = line_.xislice_h(std::search(line_.begin(), line_.end(), comment.begin(), comment.end())).rstrip();
+ if (!line)
continue;
- for (j = 0, p = line; j < 18 && p; j++)
- {
- while (*p == '\t' || *p == ' ')
- p++;
- split[j] = p;
- p = strchr(p, ',');
- if (p)
- *p++ = 0;
- }
- if (split[17] == NULL || j < 18)
- {
- FPRINTF(stderr, "Incomplete skill db data online (%d entries)\n",
- j);
- continue;
- }
- SkillID i = SkillID(atoi(split[0]));
+ struct skill_db_ skdb {};
+
+ SkillID i;
+ XString castcancel, ignore, flags, stat, desc;
+ if (!extract(line,
+ record<','>(
+ &i,
+ lstripping(&skdb.range_k),
+ lstripping(&skdb.hit),
+ lstripping(&skdb.inf),
+ lstripping(&skdb.pl),
+ lstripping(&skdb.nk),
+ lstripping(&skdb.max_raise),
+ lstripping(&skdb.max),
+ lstripping(&skdb.num_k),
+ lstripping(&castcancel),
+ lstripping(&skdb.cast_def_rate),
+ lstripping(&skdb.inf2),
+ lstripping(&skdb.maxcount),
+ lstripping(&ignore), // weapon/magic/misc/none
+ lstripping(&ignore), // blow count
+ lstripping(&flags),
+ lstripping(&stat),
+ lstripping(&desc)
+ )
+ )
+ )
+ continue;
if (/*i < SkillID() ||*/ i > SkillID::MAX_SKILL_DB)
continue;
- char *split2_0;
- split2_0 = split[1];
- skill_db[i].range_k = atoi(split2_0);
- skill_db[i].hit = atoi(split[2]);
- skill_db[i].inf = atoi(split[3]);
- skill_db[i].pl = atoi(split[4]);
- skill_db[i].nk = atoi(split[5]);
- skill_db[i].max_raise = atoi(split[6]);
- skill_db[i].max = atoi(split[7]);
-
- split2_0 = split[8];
- skill_db[i].num_k = atoi(split2_0);
-
- if (strcasecmp(split[9], "yes") == 0)
- skill_db[i].castcancel = 1;
+ if (castcancel == "yes")
+ skdb.castcancel = true;
+ else if (castcancel == "no")
+ skdb.castcancel = false;
else
- skill_db[i].castcancel = 0;
- skill_db[i].cast_def_rate = atoi(split[10]);
- skill_db[i].inf2 = atoi(split[11]);
- skill_db[i].maxcount = atoi(split[12]);
- // split[13] was one of: BF::WEAPON, BF::MAGIC, BF::MISC, BF::ZERO
- // split[14] was colon-separated blow counts.
-
- if (!strcasecmp(split[15], "passive"))
+ continue;
+
+ if (flags == "passive")
{
skill_pool_register(i);
- skill_db[i].poolflags = SkillFlags::POOL_FLAG;
+ skdb.poolflags = SkillFlags::POOL_FLAG;
}
- else if (!strcasecmp(split[15], "active"))
+ else if (flags == "active")
{
skill_pool_register(i);
- skill_db[i].poolflags = SkillFlags::POOL_FLAG | SkillFlags::POOL_ACTIVE;
+ skdb.poolflags = SkillFlags::POOL_FLAG | SkillFlags::POOL_ACTIVE;
}
+ else if (flags == "no")
+ skdb.poolflags = SkillFlags::ZERO;
else
- skill_db[i].poolflags = SkillFlags::ZERO;
+ continue;
- skill_db[i].stat = scan_stat(split[16]);
+ skdb.stat = scan_stat(stat);
- std::string tmp = split[17];
- size_t space = tmp.find_first_of(" \t\n");
- if (space != std::string::npos)
- tmp.resize(space);
+ MString tmp;
+ tmp += desc;
for (char& c : tmp)
if (c == '_')
c = ' ';
- skill_lookup_by_id(i).desc = std::move(tmp);
+
+ skill_db[i] = skdb;
+ skill_lookup_by_id(i).desc = FString(tmp);
}
- fclose_(fp);
PRINTF("read db/skill_db.txt done\n");
return 0;
@@ -1299,10 +1299,10 @@ skill_name_db& skill_lookup_by_id(SkillID id)
return skill_names[num_names - 1];
}
-skill_name_db& skill_lookup_by_name(const char *name)
+skill_name_db& skill_lookup_by_name(XString name)
{
for (skill_name_db& ner : skill_names)
- if (!strcasecmp(name, ner.name.c_str()) || !strcasecmp(name, ner.desc.c_str()))
+ if (name == ner.name || name == ner.desc)
return ner;
return skill_names[num_names - 1];
}
diff --git a/src/map/skill.hpp b/src/map/skill.hpp
index c5a2f03..bcd0261 100644
--- a/src/map/skill.hpp
+++ b/src/map/skill.hpp
@@ -21,7 +21,8 @@ struct skill_db_
int num_k;
int cast[MAX_SKILL_LEVEL], delay[MAX_SKILL_LEVEL];
int upkeep_time[MAX_SKILL_LEVEL], upkeep_time2[MAX_SKILL_LEVEL];
- int castcancel, cast_def_rate;
+ bool castcancel;
+ int cast_def_rate;
int inf2, maxcount;
int hp[MAX_SKILL_LEVEL], sp[MAX_SKILL_LEVEL], mhp[MAX_SKILL_LEVEL],
hp_rate[MAX_SKILL_LEVEL], sp_rate[MAX_SKILL_LEVEL],
@@ -49,7 +50,7 @@ struct skill_name_db
extern struct skill_name_db skill_names[];
skill_name_db& skill_lookup_by_id(SkillID id);
-skill_name_db& skill_lookup_by_name(const char *name);
+skill_name_db& skill_lookup_by_name(XString name);
struct block_list;
struct map_session_data;
diff --git a/src/map/tmw.cpp b/src/map/tmw.cpp
index 7afe3ca..ed00110 100644
--- a/src/map/tmw.cpp
+++ b/src/map/tmw.cpp
@@ -17,14 +17,12 @@
#include "../poison.hpp"
static
-void tmw_AutoBan(dumb_ptr<map_session_data> sd, const char *reason, int length);
+void tmw_AutoBan(dumb_ptr<map_session_data> sd, ZString reason, int length);
static
-int tmw_CheckChatLameness(dumb_ptr<map_session_data> sd, const char *message);
-static
-int tmw_ShorterStrlen(const char *s1, const char *s2);
+bool tmw_CheckChatLameness(dumb_ptr<map_session_data> sd, XString message);
-int tmw_CheckChatSpam(dumb_ptr<map_session_data> sd, const char *message)
+int tmw_CheckChatSpam(dumb_ptr<map_session_data> sd, XString message)
{
nullpo_retr(1, sd);
TimeT now = TimeT::now();
@@ -48,8 +46,7 @@ int tmw_CheckChatSpam(dumb_ptr<map_session_data> sd, const char *message)
sd->chat_lines_in++;
// Penalty for repeats.
- if (strncmp(sd->chat_lastmsg, message,
- tmw_ShorterStrlen(sd->chat_lastmsg, message)) == 0)
+ if (sd->chat_lastmsg.startswith(message) || message.startswith(sd->chat_lastmsg))
{
sd->chat_lines_in += battle_config.chat_lame_penalty;
sd->chat_total_repeats++;
@@ -63,7 +60,7 @@ int tmw_CheckChatSpam(dumb_ptr<map_session_data> sd, const char *message)
if (tmw_CheckChatLameness(sd, message))
sd->chat_lines_in += battle_config.chat_lame_penalty;
- strzcpy(sd->chat_lastmsg, message, battle_config.chat_maxline);
+ sd->chat_lastmsg = message;
if (sd->chat_lines_in >= battle_config.chat_spam_flood
|| sd->chat_total_repeats >= battle_config.chat_spam_flood)
@@ -86,73 +83,58 @@ int tmw_CheckChatSpam(dumb_ptr<map_session_data> sd, const char *message)
return 0;
}
-void tmw_AutoBan(dumb_ptr<map_session_data> sd, const char *reason, int length)
+void tmw_AutoBan(dumb_ptr<map_session_data> sd, ZString reason, int length)
{
if (length == 0 || sd->auto_ban_info.in_progress)
return;
sd->auto_ban_info.in_progress = 1;
- std::string hack_msg = STRPRINTF("[GM] %s has been autobanned for %s spam",
+ FString hack_msg = STRPRINTF("[GM] %s has been autobanned for %s spam",
sd->status.name,
reason);
- tmw_GmHackMsg(hack_msg.c_str());
+ tmw_GmHackMsg(hack_msg);
- std::string fake_command = STRPRINTF("@autoban %s %dh (%s spam)",
+ FString fake_command = STRPRINTF("@autoban %s %dh (%s spam)",
sd->status.name, length, reason);
log_atcommand(sd, fake_command);
- std::string anotherbuf = STRPRINTF("You have been banned for %s spamming. Please do not spam.",
+ FString anotherbuf = STRPRINTF("You have been banned for %s spamming. Please do not spam.",
reason);
clif_displaymessage(sd->fd, anotherbuf);
/* type: 2 - ban(year, month, day, hour, minute, second) */
- chrif_char_ask_name(-1, sd->status.name, 2, 0, 0, 0, length, 0, 0);
+ HumanTimeDiff ban_len {};
+ ban_len.hour = length;
+ chrif_char_ask_name(-1, sd->status.name, 2, ban_len);
clif_setwaitclose(sd->fd);
}
-// Compares the length of two strings and returns that of the shorter
-int tmw_ShorterStrlen(const char *s1, const char *s2)
-{
- int s1_len = strlen(s1);
- int s2_len = strlen(s2);
- return (s2_len >= s1_len ? s1_len : s2_len);
-}
-
// Returns true if more than 50% of input message is caps or punctuation
-int tmw_CheckChatLameness(dumb_ptr<map_session_data>, const char *message)
+bool tmw_CheckChatLameness(dumb_ptr<map_session_data>, XString message)
{
- int count, lame;
-
- for (count = lame = 0; *message; message++, count++)
- if (isupper(*message) || ispunct(*message))
- lame++;
+ int lame = 0;
- if (count > 7 && lame > count / 2)
- return (1);
+ for (char c : message)
+ {
+ if (c <= ' ')
+ continue;
+ if (c > '~')
+ continue;
+ if ('0' <= c && c <= '9')
+ continue;
+ if ('a' <= c && c <= 'z')
+ continue;
+ lame++;
+ }
- return (0);
+ return message.size() > 7 && lame > message.size() / 2;
}
// Sends a whisper to all GMs
-void tmw_GmHackMsg(const char *line)
+void tmw_GmHackMsg(ZString line)
{
intif_wis_message_to_gm(wisp_server_name,
- battle_config.hack_info_GM_level,
- line);
-}
-
-/* Remove leading and trailing spaces from a string, modifying in place. */
-void tmw_TrimStr(char *const ob)
-{
- char *const oe = ob + strlen(ob);
- char *nb = ob;
- while (*nb && isspace(*nb))
- nb++;
- char *ne = oe;
- while (ne != nb && isspace(ne[-1]))
- ne--;
- // not like memcpy - allowed to overlap one way
- char *zb = std::copy(nb, ne, ob);
- std::fill(zb, oe, '\0');
+ battle_config.hack_info_GM_level,
+ line);
}
diff --git a/src/map/tmw.hpp b/src/map/tmw.hpp
index 5551504..5f1d215 100644
--- a/src/map/tmw.hpp
+++ b/src/map/tmw.hpp
@@ -6,8 +6,7 @@
#include "map.hpp"
-int tmw_CheckChatSpam(dumb_ptr<map_session_data> sd, const char *message);
-void tmw_GmHackMsg(const char *line);
-void tmw_TrimStr(char *str);
+int tmw_CheckChatSpam(dumb_ptr<map_session_data> sd, XString message);
+void tmw_GmHackMsg(ZString line);
#endif // TMW_HPP
diff --git a/src/poison.hpp b/src/poison.hpp
index 0a7cc57..e7cc4cc 100644
--- a/src/poison.hpp
+++ b/src/poison.hpp
@@ -6,6 +6,8 @@
// double (use a fixed class)
#pragma GCC poison float
+#pragma GCC poison dynamic_cast
+
// Local time is forbidden.
#pragma GCC poison timelocal // timegm
#pragma GCC poison mktime // timegm
@@ -76,3 +78,10 @@
#pragma GCC poison memset
#pragma GCC poison memcmp
#pragma GCC poison strncpy // in favor of strzcpy
+
+#pragma GCC poison string // in favor of FString, MString, etc.
+#pragma GCC poison strcasecmp
+#pragma GCC poison toupper
+#pragma GCC poison tolower
+#pragma GCC poison isupper
+#pragma GCC poison islower
diff --git a/src/tool/eathena-monitor.cpp b/src/tool/eathena-monitor.cpp
index 2196c7c..f6e8271 100644
--- a/src/tool/eathena-monitor.cpp
+++ b/src/tool/eathena-monitor.cpp
@@ -17,6 +17,7 @@
#include <fstream>
#include "../common/cxxstdio.hpp"
+#include "../common/io.hpp"
#include "../common/utils.hpp"
#include "../poison.hpp"
@@ -29,30 +30,30 @@
// initialiized to $HOME/tmwserver
static
-std::string workdir;
+FString workdir;
//the rest are relative to workdir
static
-std::string login_server = LOGIN_SERVER;
+FString login_server = LOGIN_SERVER;
static
-std::string map_server = MAP_SERVER;
+FString map_server = MAP_SERVER;
static
-std::string char_server = CHAR_SERVER;
+FString char_server = CHAR_SERVER;
static
pid_t pid_login, pid_map, pid_char;
static
-std::string make_path(const std::string& base, const std::string& path)
+FString make_path(XString base, XString path)
{
- std::string out(base.size() + 1 + path.size(), '\0');
- std::string::iterator it = std::copy(base.begin(), base.end(), out.begin());
- *it++ = '/';
- std::copy(path.begin(), path.end(), it);
- return out;
+ MString m;
+ m += base;
+ m += '/';
+ m += path;
+ return FString(m);
}
static
-void parse_option(const std::string& name, const std::string& value)
+void parse_option(XString name, ZString value)
{
if (name == "login_server")
login_server = value;
@@ -63,23 +64,28 @@ void parse_option(const std::string& name, const std::string& value)
else if (name == "workdir")
workdir = value;
else
- FPRINTF(stderr, "WARNING: ingnoring invalid option '%s' : '%s'\n", name, value);
+ {
+ FString name_ = name;
+ FPRINTF(stderr, "WARNING: ingnoring invalid option '%s' : '%s'\n",
+ name_, value);
+ }
}
static
-void read_config(const std::string& filename)
+void read_config(ZString filename)
{
- std::ifstream in(filename);
+ std::ifstream in(filename.c_str());
if (!in.is_open())
{
FPRINTF(stderr, "Monitor config file not found: %s\n", filename);
exit(1);
}
- std::string line;
- while (std::getline(in, line))
+ FString line;
+ while (io::getline(in, line))
{
- std::string name, value;
+ SString name;
+ TString value;
if (!split_key_value(line, &name, &value))
continue;
@@ -88,7 +94,8 @@ void read_config(const std::string& filename)
}
static
-pid_t start_process(const std::string& exec) {
+pid_t start_process(ZString exec)
+{
const char *args[2] = {exec.c_str(), NULL};
pid_t pid = fork();
if (pid == -1)
@@ -135,11 +142,11 @@ int main(int argc, char *argv[])
signal(SIGQUIT, stop_process);
signal(SIGABRT, stop_process);
- workdir = make_path(getenv("HOME"), "tmwserver");
+ workdir = make_path(ZString(ZString::really_construct_from_a_pointer, getenv("HOME"), nullptr), "tmwserver");
- std::string config = CONFIG;
+ ZString config = CONFIG;
if (argc > 1)
- config = argv[1];
+ config = ZString(ZString::really_construct_from_a_pointer, argv[1], nullptr);
read_config(config);
if (chdir(workdir.c_str()) < 0)
diff --git a/src/warnings.hpp b/src/warnings.hpp
index 9ce78ee..9f184a5 100644
--- a/src/warnings.hpp
+++ b/src/warnings.hpp
@@ -167,7 +167,8 @@
/// Warn about things that will change when compiling
/// with an ABI-compliant compiler
-I(-Wabi)
+// see note about -fabi-version=6 in the makefile
+E(-Wabi)
/// Warn if a subobject has an abi_tag attribute that
/// the complete object type does not have
@@ -191,9 +192,10 @@ E(-Wbuiltin-macro-redefined)
/// Warn about C++ constructs whose meaning differs
/// between ISO C++ 1998 and ISO C++ 2011
-// This has gone funky lately. It probably doesn't do anything anyway.
+// This has gone funky lately. It probably doesn't do anything useful anyway.
//E(-Wc++0x-compat)
//W(-Wc++11-compat)
+I(-Wc++0x-compat)
/// Warn about pointer casts which increase alignment
X(-Wcast-align)
@@ -298,7 +300,7 @@ E(-Wfloat-equal)
// see below
EG(-Wformat)
// but gcc 4.8 warns on %ms, since we enabled -Wpedantic.
-WG48(-Wformat)
+//WG48(-Wformat)
/// Warn about format strings that contain NUL bytes
EG(-Wformat-contains-nul)
@@ -474,7 +476,9 @@ E(-Wparentheses)
/// Issue warnings needed for strict compliance to
/// the standard
-EG48(-Wpedantic)
+//EG48(-Wpedantic)
+// lots of minor extensions are used
+IG48(-Wpedantic)
// a bit too noisy
XC(-Wpedantic)