Explorar o código

Start refactoring the core to C++ (#7303)

Lemongrass3110 %!s(int64=2) %!d(string=hai) anos
pai
achega
2c4ee64b59

+ 20 - 44
src/char/char.cpp

@@ -37,6 +37,8 @@
 #include "int_storage.hpp"
 #include "packets.hpp"
 
+using namespace rathena::server_character;
+
 //definition of exported var declared in header
 int login_fd=-1; //login file descriptor
 int char_fd=-1; //char file descriptor
@@ -3142,9 +3144,7 @@ void char_do_final_msg(void){
 	_do_final_msg(CHAR_MAX_MSG,msg_table);
 }
 
-
-void do_final(void)
-{
+void CharacterServer::finalize(){
 	ShowStatus("Terminating...\n");
 
 	char_set_all_offline(-1);
@@ -3174,40 +3174,17 @@ void do_final(void)
 	ShowStatus("Finished.\n");
 }
 
-
-void set_server_type(void){
-	SERVER_TYPE = ATHENA_SERVER_CHAR;
-}
-
-//------------------------------
-// Function called when the server
-// has received a crash signal.
-//------------------------------
-void do_abort(void)
-{
-}
-
 /// Called when a terminate signal is received.
-void do_shutdown(void) {
-	if( runflag != CHARSERVER_ST_SHUTDOWN )
-	{
-		int id;
-		runflag = CHARSERVER_ST_SHUTDOWN;
-		ShowStatus("Shutting down...\n");
-		// TODO proper shutdown procedure; wait for acks?, kick all characters, ... [FlavoJS]
-		for( id = 0; id < ARRAYLENGTH(map_server); ++id )
-			chmapif_server_reset(id);
-		chlogif_check_shutdown();
-		flush_fifos();
-		runflag = CORE_ST_STOP;
-	}
+void CharacterServer::handle_shutdown(){
+	ShowStatus("Shutting down...\n");
+	// TODO proper shutdown procedure; wait for acks?, kick all characters, ... [FlavoJS]
+	for( int id = 0; id < ARRAYLENGTH(map_server); ++id )
+		chmapif_server_reset(id);
+	flush_fifos();
 }
 
-
-int do_init(int argc, char **argv)
-{
+bool CharacterServer::initialize( int argc, char *argv[] ){
 	//Read map indexes
-	runflag = CHARSERVER_ST_STARTING;
 	mapindex_init();
 
 	// Init default value
@@ -3227,12 +3204,13 @@ int do_init(int argc, char **argv)
 	char_sql_config_read(SQL_CONF_NAME);
 	msg_config_read(MSG_CONF_NAME_EN);
 
-	// Skip this check if the server is run with run-once flag
-	if (runflag!=CORE_ST_STOP && strcmp(charserv_config.userid, "s1")==0 && strcmp(charserv_config.passwd, "p1")==0) {
+#if !defined(BUILDBOT)
+	if (strcmp(charserv_config.userid, "s1")==0 && strcmp(charserv_config.passwd, "p1")==0) {
 		ShowWarning("Using the default user/password s1/p1 is NOT RECOMMENDED.\n");
 		ShowNotice("Please edit your 'login' table to create a proper inter-server user/password (gender 'S')\n");
 		ShowNotice("And then change the user/password to use in conf/char_athena.conf (or conf/import/char_conf.txt)\n");
 	}
+#endif
 
 	inter_init_sql((argc > 2) ? argv[2] : SQL_CONF_NAME); // inter server configuration
 
@@ -3289,7 +3267,7 @@ int do_init(int argc, char **argv)
 	//check db tables
 	if(charserv_config.char_check_db && char_checkdb() == 0){
 		ShowFatalError("char : A tables is missing in sql-server, please fix it, see (sql-files main.sql for structure) \n");
-		exit(EXIT_FAILURE);
+		return false;
 	}
 	//Cleaning the tables for NULL entrys @ startup [Sirius]
 	//Chardb clean
@@ -3308,13 +3286,7 @@ int do_init(int argc, char **argv)
 
 	if( (char_fd = make_listen_bind(charserv_config.bind_ip,charserv_config.char_port)) == -1 ) {
 		ShowFatalError("Failed to bind to port '" CL_WHITE "%d" CL_RESET "'\n",charserv_config.char_port);
-		exit(EXIT_FAILURE);
-	}
-
-	if( runflag != CORE_ST_STOP )
-	{
-		shutdown_callback = do_shutdown;
-		runflag = CHARSERVER_ST_RUNNING;
+		return false;
 	}
 
 	do_init_chcnslif();
@@ -3323,5 +3295,9 @@ int do_init(int argc, char **argv)
 
 	ShowStatus("The char-server is " CL_GREEN "ready" CL_RESET " (Server is listening on the port %d).\n\n", charserv_config.char_port);
 
-	return 0;
+	return true;
+}
+
+int main( int argc, char *argv[] ){
+	return main_core<CharacterServer>( argc, argv );
 }

+ 19 - 7
src/char/char.hpp

@@ -14,19 +14,31 @@
 
 #include "packets.hpp"
 
+using rathena::server_core::Core;
+using rathena::server_core::e_core_type;
+
+namespace rathena{
+	namespace server_character{
+		class CharacterServer : public Core{
+			protected:
+				bool initialize( int argc, char* argv[] ) override;
+				void finalize() override;
+				void handle_shutdown() override;
+
+			public:
+				CharacterServer() : Core( e_core_type::CHARACTER ){
+
+				}
+		};
+	}
+}
+
 extern int login_fd; //login file descriptor
 extern int char_fd; //char file descriptor
 
 #define MAX_STARTPOINT 5
 #define MAX_STARTITEM 32
 
-enum E_CHARSERVER_ST {
-	CHARSERVER_ST_RUNNING = CORE_ST_LAST,
-	CHARSERVER_ST_STARTING,
-	CHARSERVER_ST_SHUTDOWN,
-	CHARSERVER_ST_LAST
-};
-
 enum e_char_delete {
 	CHAR_DEL_EMAIL = 1,
 	CHAR_DEL_BIRTHDATE

+ 2 - 2
src/char/char_clif.cpp

@@ -674,7 +674,7 @@ int chclif_parse_maplogin(int fd){
 		l_user[23] = '\0';
 		l_pass[23] = '\0';
 		ARR_FIND( 0, ARRAYLENGTH(map_server), i, map_server[i].fd <= 0 );
-		if( runflag != CHARSERVER_ST_RUNNING ||
+		if( !global_core->is_running() ||
 			i == ARRAYLENGTH(map_server) ||
 			strcmp(l_user, charserv_config.userid) != 0 ||
 			strcmp(l_pass, charserv_config.passwd) != 0 )
@@ -735,7 +735,7 @@ int chclif_parse_reqtoconnect(int fd, struct char_session_data* sd,uint32 ipl){
 		WFIFOL(fd,0) = account_id;
 		WFIFOSET(fd,4);
 
-		if( runflag != CHARSERVER_ST_RUNNING ) {
+		if( !global_core->is_running() ){
 			chclif_reject(fd, 0); // rejected from server
 			return 1;
 		}

+ 1 - 1
src/char/char_cnslif.cpp

@@ -74,7 +74,7 @@ int cnslif_parse(const char* buf)
 
 	if( n == 2 && strcmpi("server", type) == 0 ){
 		if( strcmpi("shutdown", command) == 0 || strcmpi("exit", command) == 0 || strcmpi("quit", command) == 0 ){
-			runflag = 0;
+			global_core->signal_shutdown();
 		}
 		else if( strcmpi("alive", command) == 0 || strcmpi("status", command) == 0 )
 			ShowInfo(CL_CYAN "Console: " CL_BOLD "I'm Alive." CL_RESET "\n");

+ 0 - 12
src/char/char_logif.cpp

@@ -813,16 +813,6 @@ void chlogif_reset(void){
 	exit(EXIT_FAILURE);
 }
 
-/// Checks the conditions for the server to stop.
-/// Releases the cookie when all characters are saved.
-/// If all the conditions are met, it stops the core loop.
-void chlogif_check_shutdown(void)
-{
-	if( runflag != CHARSERVER_ST_SHUTDOWN )
-		return;
-	runflag = CORE_ST_STOP;
-}
-
 /// Called when the connection to Login Server is disconnected.
 void chlogif_on_disconnect(void){
 	ShowWarning("Connection to Login Server lost.\n\n");
@@ -833,8 +823,6 @@ void chlogif_on_ready(void)
 {
 	int i;
 
-	chlogif_check_shutdown();
-
 	//Send online accounts to login server.
 	chlogif_send_acc_tologin(INVALID_TIMER, gettick(), 0, 0);
 

+ 4 - 4
src/char/char_mapif.cpp

@@ -458,7 +458,7 @@ int chmapif_parse_authok(int fd){
 		uint32 ip = RFIFOL(fd,14);
 		RFIFOSKIP(fd,18);
 
-		if( runflag != CHARSERVER_ST_RUNNING ){
+		if( !global_core->is_running() ){
 			chmapif_charselres(fd,account_id,0);
 		}else{
 			struct auth_node* node;
@@ -610,7 +610,7 @@ int chmapif_parse_reqchangemapserv(int fd){
 			char_data = (struct mmo_charstatus*)uidb_get(char_db_,RFIFOL(fd,14));
 		}
 
-		if( runflag == CHARSERVER_ST_RUNNING &&
+		if( global_core->is_running() &&
 			session_isActive(map_fd) &&
 			char_data )
 		{	//Send the map server the auth of this player.
@@ -1011,7 +1011,7 @@ int chmapif_parse_reqauth(int fd, int id){
 				char_mmo_char_fromsql(char_id, &char_dat, true);
 				cd = (struct mmo_charstatus*)uidb_get(char_db_,char_id);
 		}
-		if( runflag == CHARSERVER_ST_RUNNING && autotrade && cd ){
+		if( global_core->is_running() && autotrade && cd ){
 			uint16 mmo_charstatus_len = sizeof(struct mmo_charstatus) + 25;
 
 			WFIFOHEAD(fd,mmo_charstatus_len);
@@ -1027,7 +1027,7 @@ int chmapif_parse_reqauth(int fd, int id){
 			WFIFOSET(fd, WFIFOW(fd,2));
 
 			char_set_char_online(id, char_id, account_id);
-		} else if( runflag == CHARSERVER_ST_RUNNING &&
+		} else if( global_core->is_running() &&
 			cd != NULL &&
 			node != NULL &&
 			node->account_id == account_id &&

+ 7 - 9
src/common/cli.cpp

@@ -18,6 +18,8 @@
 #include "showmsg.hpp"
 #include "timer.hpp"
 
+using namespace rathena::server_core;
+
 //map confs
 const char* MAP_CONF_NAME;
 const char* INTER_CONF_NAME;
@@ -110,14 +112,12 @@ int cli_get_options(int argc, char ** argv) {
 					MSG_CONF_NAME_EN = argv[++i];
 			}
 			else if (strcmp(arg, "run-once") == 0) { // close the map-server as soon as its done.. for testing [Celest]
-				runflag = CORE_ST_STOP;
-			}
-			else if (SERVER_TYPE & (ATHENA_SERVER_LOGIN | ATHENA_SERVER_CHAR)) { //login or char
+				global_core->set_run_once( true );
+			}else if( global_core->get_type() == e_core_type::LOGIN || global_core->get_type() == e_core_type::CHARACTER ){
 				if (strcmp(arg, "lan-config") == 0) {
 					if (opt_has_next_value(arg, i, argc))
 						LAN_CONF_NAME = argv[++i];
-				}
-				else if (SERVER_TYPE == ATHENA_SERVER_LOGIN) { //login
+				}else if( global_core->get_type() == e_core_type::LOGIN ){
 					if (strcmp(arg, "login-config") == 0) {
 						if (opt_has_next_value(arg, i, argc))
 							LOGIN_CONF_NAME = argv[++i];
@@ -126,8 +126,7 @@ int cli_get_options(int argc, char ** argv) {
 						ShowError("Unknown option '%s'.\n", argv[i]);
 						exit(EXIT_FAILURE);
 					}
-				}
-				else if (SERVER_TYPE == ATHENA_SERVER_CHAR) { //char
+				}else if( global_core->get_type() == e_core_type::CHARACTER ){
 					if (strcmp(arg, "char-config") == 0) {
 						if (opt_has_next_value(arg, i, argc))
 							CHAR_CONF_NAME = argv[++i];
@@ -141,8 +140,7 @@ int cli_get_options(int argc, char ** argv) {
 						exit(EXIT_FAILURE);
 					}
 				}
-			}
-			else if (SERVER_TYPE == ATHENA_SERVER_MAP) { //map
+			}else if( global_core->get_type() == e_core_type::MAP ){
 				if (strcmp(arg, "map-config") == 0) {
 					if (opt_has_next_value(arg, i, argc))
 						MAP_CONF_NAME = argv[++i];

+ 116 - 37
src/common/core.cpp

@@ -37,19 +37,18 @@
 	#endif
 #endif
 
-/// Called when a terminate signal is received.
-void (*shutdown_callback)(void) = NULL;
+using namespace rathena::server_core;
+
+Core* global_core = nullptr;
 
 #if defined(BUILDBOT)
 	int buildbotflag = 0;
 #endif
 
-int runflag = CORE_ST_RUN;
 char db_path[12] = "db"; /// relative path for db from server
 char conf_path[12] = "conf"; /// relative path for conf from server
 
 char *SERVER_NAME = NULL;
-char SERVER_TYPE = ATHENA_SERVER_NONE;
 
 #ifndef MINICORE	// minimalist Core
 // Added by Gabuzomeu
@@ -91,10 +90,9 @@ static BOOL WINAPI console_handler(DWORD c_event) {
     case CTRL_CLOSE_EVENT:
     case CTRL_LOGOFF_EVENT:
     case CTRL_SHUTDOWN_EVENT:
-		if( shutdown_callback != NULL )
-			shutdown_callback();
-		else
-			runflag = CORE_ST_STOP;// auto-shutdown
+		if( global_core != nullptr ){
+			global_core->signal_shutdown();
+		}
         break;
 	default:
 		return FALSE;
@@ -119,14 +117,15 @@ static void sig_proc(int sn) {
 	case SIGTERM:
 		if (++is_called > 3)
 			exit(EXIT_SUCCESS);
-		if( shutdown_callback != NULL )
-			shutdown_callback();
-		else
-			runflag = CORE_ST_STOP;// auto-shutdown
+		if( global_core != nullptr ){
+			global_core->signal_shutdown();
+		}
 		break;
 	case SIGSEGV:
 	case SIGFPE:
-		do_abort();
+		if( global_core != nullptr ){
+			global_core->signal_crash();
+		}
 		// Pass the signal to the system's default handler
 		compat_signal(sn, SIG_DFL);
 		raise(sn);
@@ -329,11 +328,14 @@ void usercheck(void)
 #endif
 }
 
-/*======================================
- *	CORE : MAINROUTINE
- *--------------------------------------*/
-int main (int argc, char **argv)
-{
+int Core::start( int argc, char **argv ){
+	if( this->get_status() != e_core_status::NOT_STARTED) {
+		ShowFatalError( "Core was already started and cannot be started again!\n" );
+		return EXIT_FAILURE;
+	}
+
+	this->set_status( e_core_status::CORE_INITIALIZING );
+
 	{// initialize program arguments
 		char *p1;
 		if((p1 = strrchr(argv[0], '/')) != NULL ||  (p1 = strrchr(argv[0], '\\')) != NULL ){
@@ -352,17 +354,10 @@ int main (int argc, char **argv)
 	}
 
 	malloc_init();// needed for Show* in display_title() [FlavioJS]
-
-#ifdef MINICORE // minimalist Core
-	display_title();
-	usercheck();
-	do_init(argc,argv);
-	do_final();
-#else// not MINICORE
-	set_server_type();
 	display_title();
 	usercheck();
 
+#ifndef MINICORE
 	Sql_Init();
 	db_init();
 	signals_init();
@@ -370,24 +365,41 @@ int main (int argc, char **argv)
 #ifdef _WIN32
 	cevents_init();
 #endif
-
 	timer_init();
 	socket_init();
+#endif
 
-	do_init(argc,argv);
+	this->set_status( e_core_status::CORE_INITIALIZED );
+
+	this->set_status( e_core_status::SERVER_INITIALIZING );
+	if( !this->initialize( argc, argv ) ){
+		return EXIT_FAILURE;
+	}
 
-	// Main runtime cycle
-	while (runflag != CORE_ST_STOP) { 
-		t_tick next = do_timer(gettick_nocache());
+	// If initialization did not trigger shutdown
+	if( this->status != e_core_status::STOPPING ){
+		this->set_status( e_core_status::SERVER_INITIALIZED );
 
-		if (SERVER_TYPE != ATHENA_SERVER_WEB)
-			do_sockets(next);
-		else
-			do_wait(next);
+		this->set_status( e_core_status::RUNNING );
+#ifndef MINICORE
+		if( !this->run_once ){
+			// Main runtime cycle
+			while( this->get_status() == e_core_status::RUNNING ){
+				t_tick next = do_timer( gettick_nocache() );
+
+				this->handle_main( next );
+			}
+		}
+#endif
+		this->set_status( e_core_status::STOPPING );
 	}
 
-	do_final();
+	this->set_status( e_core_status::SERVER_FINALIZING );
+	this->finalize();
+	this->set_status( e_core_status::SERVER_FINALIZED );
 
+	this->set_status( e_core_status::CORE_FINALIZING );
+#ifndef MINICORE
 	timer_final();
 	socket_final();
 	db_final();
@@ -395,6 +407,7 @@ int main (int argc, char **argv)
 #endif
 
 	malloc_final();
+	this->set_status( e_core_status::CORE_FINALIZED );
 
 #if defined(BUILDBOT)
 	if( buildbotflag ){
@@ -402,5 +415,71 @@ int main (int argc, char **argv)
 	}
 #endif
 
-	return 0;
+	this->set_status( e_core_status::STOPPED );
+
+	return EXIT_SUCCESS;
+}
+
+bool Core::initialize( int argc, char* argv[] ){
+	// Do nothing
+	return true;
+}
+
+void Core::handle_main( t_tick next ){
+#ifndef MINICORE
+	// By default we handle all socket packets
+	do_sockets( next );
+#endif
+}
+
+void Core::handle_crash(){
+	// Do nothing
+}
+
+void Core::handle_shutdown(){
+	// Do nothing
+}
+
+void Core::finalize(){
+	// Do nothing
+}
+
+void Core::set_status( e_core_status status ){
+	this->status = status;
+}
+
+e_core_status Core::get_status(){
+	return this->status;
+}
+
+e_core_type Core::get_type(){
+	return this->type;
+}
+
+bool Core::is_running(){
+	return this->get_status() == e_core_status::RUNNING;
+}
+
+void Core::set_run_once( bool run_once ){
+	this->run_once = run_once;
+}
+
+void Core::signal_crash(){
+	this->set_status( e_core_status::STOPPING );
+
+	if( this->crashed ){
+		ShowFatalError( "Received another crash signal, while trying to handle the last crash!\n" );
+	}else{
+		ShowFatalError( "Received a crash signal, trying to handle it as good as possible!\n" );
+		this->crashed = true;
+		this->handle_crash();
+	}
+
+	// Now stop the process
+	exit( EXIT_FAILURE );
+}
+
+void Core::signal_shutdown(){
+	this->set_status( e_core_status::STOPPING );
+	this->handle_shutdown();
 }

+ 79 - 32
src/common/core.hpp

@@ -4,55 +4,102 @@
 #ifndef CORE_HPP
 #define CORE_HPP
 
+#include <string>
+#include <vector>
+
+#include "timer.hpp"
+
+#ifdef _WIN32
+	#include "winapi.hpp" // Console close event handling
+#endif
+
 /* so that developers with --enable-debug can raise signals from any section of the code they'd like */
 #ifdef DEBUG
 	#include <signal.h>
 #endif
 
-extern int arg_c;
-extern char **arg_v;
-
 #if defined(BUILDBOT)
 	extern int buildbotflag;
 #endif
 
 #define UNKNOWN_VERSION '\x02'
 
-/// @see E_CORE_ST
-extern int runflag;
 extern char *SERVER_NAME;
 extern char db_path[12]; /// relative path for db from servers
 extern char conf_path[12]; /// relative path for conf from servers
 
-enum {
-	ATHENA_SERVER_NONE = 0,	// not defined
-	ATHENA_SERVER_LOGIN	= 1,	// login server
-	ATHENA_SERVER_CHAR = 2,	// char server
-	ATHENA_SERVER_INTER	= 4,	// inter server
-	ATHENA_SERVER_MAP = 8,	// map server
-	ATHENA_SERVER_WEB = 16, // web server
-};
-
-extern char SERVER_TYPE;
-
 extern int parse_console(const char* buf);
 const char *get_svn_revision(void);
 const char *get_git_hash(void);
-extern int do_init(int,char**);
-extern void set_server_type(void);
-extern void do_abort(void);
-extern void do_final(void);
-
-/// The main loop continues until runflag is CORE_ST_STOP
-enum E_CORE_ST
-{
-	CORE_ST_STOP = 0,
-	CORE_ST_RUN,
-	CORE_ST_LAST
-};
-
-/// Called when a terminate signal is received. (Ctrl+C pressed)
-/// If NULL, runflag is set to CORE_ST_STOP instead.
-extern void (*shutdown_callback)(void);
+
+namespace rathena{
+	namespace server_core{
+		enum class e_core_status{
+			NOT_STARTED,
+			CORE_INITIALIZING,
+			CORE_INITIALIZED,
+			SERVER_INITIALIZING,
+			SERVER_INITIALIZED,
+			RUNNING,
+			STOPPING,
+			SERVER_FINALIZING,
+			SERVER_FINALIZED,
+			CORE_FINALIZING,
+			CORE_FINALIZED,
+			STOPPED,
+		};
+
+		enum class e_core_type{
+			LOGIN,
+			CHARACTER,
+			MAP,
+			TOOL,
+			WEB
+		};
+
+		class Core{
+			private:
+				e_core_status status;
+				e_core_type type;
+				bool run_once;
+				bool crashed;
+
+			protected:
+				virtual bool initialize( int argc, char* argv[] );
+				virtual void handle_main( t_tick next );
+				virtual void finalize();
+				virtual void handle_crash();
+				virtual void handle_shutdown();
+				void set_status( e_core_status status );
+
+			public:
+				Core( e_core_type type ){
+					this->status = e_core_status::NOT_STARTED;
+					this->run_once = false;
+					this->crashed = false;
+					this->type = type;
+				}
+
+				e_core_status get_status();
+				e_core_type get_type();
+				bool is_running();
+				// TODO: refactor to protected
+				void set_run_once( bool run_once );
+				void signal_crash();
+				void signal_shutdown();
+				int start( int argc, char* argv[] );
+		};
+	}
+}
+
+extern rathena::server_core::Core* global_core;
+
+template <typename T> int main_core( int argc, char *argv[] ){
+	T server = {};
+
+	global_core = &server;
+
+	return server.start( argc, argv );
+}
 
 #endif /* CORE_HPP */

+ 0 - 11
src/common/socket.cpp

@@ -40,9 +40,6 @@
 	#endif
 #endif
 
-#include <chrono>
-#include <thread>
-
 #include "cbasetypes.hpp"
 #include "malloc.hpp"
 #include "mmo.hpp"
@@ -890,14 +887,6 @@ int WFIFOSET(int fd, size_t len)
 	return 0;
 }
 
-
-// replacement for do_sockets, where it does nothing
-int do_wait(t_tick next)
-{
-	std::this_thread::sleep_for(std::chrono::milliseconds(next));
-	return 0;
-}
-
 int do_sockets(t_tick next)
 {
 #ifndef SOCKET_EPOLL

+ 0 - 1
src/common/socket.hpp

@@ -133,7 +133,6 @@ int WFIFOSET(int fd, size_t len);
 int RFIFOSKIP(int fd, size_t len);
 
 int do_sockets(t_tick next);
-int do_wait(t_tick next);
 void do_close(int fd);
 void socket_init(void);
 void socket_final(void);

+ 16 - 47
src/login/login.cpp

@@ -32,6 +32,7 @@
 #include "loginlog.hpp"
 
 using namespace rathena;
+using namespace rathena::server_login;
 
 #define LOGIN_MAX_MSG 30				/// Max number predefined in msg_conf
 static char* msg_table[LOGIN_MAX_MSG];	/// Login Server messages_conf
@@ -780,7 +781,7 @@ void login_set_defaults() {
  * Login-serv destructor
  *  dealloc..., function called at exit of the login-serv
  */
-void do_final(void) {
+void LoginServer::finalize(){
 	struct client_hash_node *hn = login_config.client_hash_nodes;
 	AccountDB* db = accounts;
 
@@ -822,45 +823,14 @@ void do_final(void) {
 	ShowStatus("Finished.\n");
 }
 
-/**
- * Signal handler
- *  This function attempts to properly close the server when an interrupt signal is received.
- *  current signal catch : SIGTERM, SIGINT
- */
-void do_shutdown(void) {
-	if( runflag != LOGINSERVER_ST_SHUTDOWN ) {
-		runflag = LOGINSERVER_ST_SHUTDOWN;
-		ShowStatus("Shutting down...\n");
-		// TODO proper shutdown procedure; kick all characters, wait for acks, ...  [FlavioJS]
-		do_shutdown_loginchrif();
-		flush_fifos();
-		runflag = CORE_ST_STOP;
-	}
-}
-
-/**
- * Signal handler
- *  Function called when the server has received a crash signal.
- *  current signal catch : SIGSEGV, SIGFPE
- */
-void do_abort(void) {
+void LoginServer::handle_shutdown(){
+	ShowStatus("Shutting down...\n");
+	// TODO proper shutdown procedure; kick all characters, wait for acks, ...  [FlavioJS]
+	do_shutdown_loginchrif();
+	flush_fifos();
 }
 
-// Is this still used ??
-void set_server_type(void) {
-	SERVER_TYPE = ATHENA_SERVER_LOGIN;
-}
-
-/**
- * Login serv constructor
- *  Initialisation, function called at start of the login-serv.
- * @param argc : number of argument from main()
- * @param argv : arguments values from main()
- * @return 0 everything ok else stopping programme execution.
- */
-int do_init(int argc, char** argv) {
-	runflag = LOGINSERVER_ST_STARTING;
-
+bool LoginServer::initialize( int argc, char* argv[] ){
 	// Init default value
 	safestrncpy(console_log_filepath, "./log/login-msg_log.log", sizeof(console_log_filepath));
 
@@ -900,23 +870,18 @@ int do_init(int argc, char** argv) {
 	// Account database init
 	if( accounts == NULL ) {
 		ShowFatalError("do_init: account engine not found.\n");
-		exit(EXIT_FAILURE);
+		return false;
 	} else {
 		if(!accounts->init(accounts)) {
 			ShowFatalError("do_init: Failed to initialize account engine.\n");
-			exit(EXIT_FAILURE);
+			return false;
 		}
 	}
 
 	// server port open & binding
 	if( (login_fd = make_listen_bind(login_config.login_ip,login_config.login_port)) == -1 ) {
 		ShowFatalError("Failed to bind to port '" CL_WHITE "%d" CL_RESET "'\n",login_config.login_port);
-		exit(EXIT_FAILURE);
-	}
-
-	if( runflag != CORE_ST_STOP ) {
-		shutdown_callback = do_shutdown;
-		runflag = LOGINSERVER_ST_RUNNING;
+		return false;
 	}
 
 	do_init_logincnslif();
@@ -924,5 +889,9 @@ int do_init(int argc, char** argv) {
 	ShowStatus("The login-server is " CL_GREEN "ready" CL_RESET " (Server is listening on the port %u).\n\n", login_config.login_port);
 	login_log(0, "login server", 100, "login server started");
 
-	return 0;
+	return true;
+}
+
+int main( int argc, char *argv[] ){
+	return main_core<LoginServer>( argc, argv );
 }

+ 19 - 7
src/login/login.hpp

@@ -7,19 +7,31 @@
 #include <memory>
 
 #include "../common/cbasetypes.hpp"
-#include "../common/core.hpp" // CORE_ST_LAST
+#include "../common/core.hpp"
 #include "../common/mmo.hpp" // NAME_LENGTH,SEX_*
 #include "../common/timer.hpp"
 #include "../config/core.hpp"
 
 #include "account.hpp"
 
-enum E_LOGINSERVER_ST {
-	LOGINSERVER_ST_RUNNING = CORE_ST_LAST,
-	LOGINSERVER_ST_STARTING,
-	LOGINSERVER_ST_SHUTDOWN,
-	LOGINSERVER_ST_LAST
-};
+using rathena::server_core::Core;
+using rathena::server_core::e_core_type;
+
+namespace rathena{
+	namespace server_login{
+		class LoginServer : public Core{
+			protected:
+				bool initialize( int argc, char* argv[] ) override;
+				void finalize() override;
+				void handle_shutdown() override;
+
+			public:
+				LoginServer() : Core( e_core_type::LOGIN ){
+
+				}
+		};
+	}
+}
 
 /// supported encryption types: 1- passwordencrypt, 2- passwordencrypt2, 3- both
 #define PASSWORDENC 3

+ 1 - 1
src/login/loginchrif.cpp

@@ -83,7 +83,7 @@ int logchrif_parse_reqauth(int fd, int id,char* ip){
 
 		struct auth_node* node = login_get_auth_node( account_id );
 
-		if( runflag == LOGINSERVER_ST_RUNNING &&
+		if( global_core->is_running() &&
 			node != nullptr &&
 			node->account_id == account_id &&
 			node->login_id1  == login_id1 &&

+ 2 - 2
src/login/loginclif.cpp

@@ -59,7 +59,7 @@ static void logclif_auth_ok(struct login_session_data* sd) {
 	int size = 160;
 #endif
 
-	if( runflag != LOGINSERVER_ST_RUNNING ){
+	if( !global_core->is_running() ){
 		// players can only login while running
 		logclif_sent_auth_result(fd,1); // server closed
 		return;
@@ -420,7 +420,7 @@ static int logclif_parse_reqcharconnec(int fd, struct login_session_data *sd, ch
 		login_log(session[fd]->client_addr, sd->userid, 100, message);
 
 		result = login_mmo_auth(sd, true);
-		if( runflag == LOGINSERVER_ST_RUNNING &&
+		if( global_core->is_running() &&
 			result == -1 &&
 			sd->sex == 'S' &&
 			sd->account_id < ARRAYLENGTH(ch_server) &&

+ 11 - 13
src/login/logincnslif.cpp

@@ -57,18 +57,16 @@ int logcnslif_get_options(int argc, char ** argv) {
 			} else if (strcmp(arg, "version") == 0) {
 				display_versionscreen(true);
 			} else if (strcmp(arg, "run-once") == 0){ // close the map-server as soon as its done.. for testing [Celest]
-				runflag = CORE_ST_STOP;
-			} else if (SERVER_TYPE & (ATHENA_SERVER_LOGIN)) { //login
-				if (strcmp(arg, "lan-config") == 0) {
-					if (opt_has_next_value(arg, i, argc)) safestrncpy(login_config.lanconf_name, argv[++i], sizeof(login_config.lanconf_name));
-				} else if (strcmp(arg, "login-config") == 0) {
-					if (opt_has_next_value(arg, i, argc)) safestrncpy(login_config.loginconf_name, argv[++i], sizeof(login_config.loginconf_name));
-				} else if (strcmp(arg, "msg-config") == 0) {
-					if (opt_has_next_value(arg, i, argc)) safestrncpy(login_config.msgconf_name, argv[++i], sizeof(login_config.msgconf_name));
-				} else {
-					ShowError("Unknown option '%s'.\n", argv[i]);
-					exit(EXIT_FAILURE);
-				}
+				global_core->set_run_once( true );
+			} else if (strcmp(arg, "lan-config") == 0) {
+				if (opt_has_next_value(arg, i, argc)) safestrncpy(login_config.lanconf_name, argv[++i], sizeof(login_config.lanconf_name));
+			} else if (strcmp(arg, "login-config") == 0) {
+				if (opt_has_next_value(arg, i, argc)) safestrncpy(login_config.loginconf_name, argv[++i], sizeof(login_config.loginconf_name));
+			} else if (strcmp(arg, "msg-config") == 0) {
+				if (opt_has_next_value(arg, i, argc)) safestrncpy(login_config.msgconf_name, argv[++i], sizeof(login_config.msgconf_name));
+			} else {
+				ShowError("Unknown option '%s'.\n", argv[i]);
+				exit(EXIT_FAILURE);
 			}
 		} else switch (arg[0]) {// short option
 			case '?':
@@ -112,7 +110,7 @@ int cnslif_parse(const char* buf){
 	if( n == 2 ){
 		if(strcmpi("server", type) == 0 ){
 			if( strcmpi("shutdown", command) == 0 || strcmpi("exit", command) == 0 || strcmpi("quit", command) == 0 ){
-				runflag = 0;
+				global_core->signal_shutdown();
 			}
 			else if( strcmpi("alive", command) == 0 || strcmpi("status", command) == 0 )
 				ShowInfo(CL_CYAN "Console: " CL_BOLD "I'm Alive." CL_RESET"\n");

+ 2 - 1
src/map/atcommand.cpp

@@ -3972,7 +3972,8 @@ ACMD_FUNC(mapexit)
 {
 	nullpo_retr(-1, sd);
 
-	do_shutdown();
+	global_core->signal_shutdown();
+
 	return 0;
 }
 

+ 5 - 1
src/map/channel.cpp

@@ -143,8 +143,12 @@ struct Channel* channel_create_simple(char *name, char *pass, enum Channel_Type
 int channel_delete(struct Channel *channel, bool force) {
 	if(!channel)
 		return -1;
-	if(!force && channel->type == CHAN_TYPE_PUBLIC && runflag == MAPSERVER_ST_RUNNING) //only delete those serv stop
+
+	// only delete those serv stop
+	if( !force && channel->type == CHAN_TYPE_PUBLIC && global_core->is_running() ){
 		return -2;
+	}
+
 	if( db_size(channel->users)) {
 		map_session_data *sd;
 		DBIterator *iter = db_iterator(channel->users);

+ 4 - 25
src/map/chrif.cpp

@@ -123,25 +123,6 @@ char charserver_name[NAME_LENGTH];
 //This define should spare writing the check in every function. [Skotlex]
 #define chrif_check(a) { if(!chrif_isconnected()) return a; }
 
-
-/// Resets all the data.
-void chrif_reset(void) {
-	// TODO kick everyone out and reset everything [FlavioJS]
-	exit(EXIT_FAILURE);
-}
-
-
-/// Checks the conditions for the server to stop.
-/// Releases the cookie when all characters are saved.
-/// If all the conditions are met, it stops the core loop.
-void chrif_check_shutdown(void) {
-	if( runflag != MAPSERVER_ST_SHUTDOWN )
-		return;
-	if( auth_db->size(auth_db) > 0 )
-		return;
-	runflag = CORE_ST_STOP;
-}
-
 struct auth_node* chrif_search(uint32 account_id) {
 	return (struct auth_node*)idb_get(auth_db, account_id);
 }
@@ -246,12 +227,13 @@ void chrif_setpasswd(char *pwd) {
 
 // security check, prints warning if using default password
 void chrif_checkdefaultlogin(void) {
-	// Skip this check if the server is run with run-once flag
-	if ( runflag != CORE_ST_STOP && strcmp(userid, "s1")==0 && strcmp(passwd, "p1")==0) {
+#if !defined(BUILDBOT)
+	if( strcmp( userid, "s1" ) == 0 && strcmp( passwd, "p1" ) == 0 ){
 		ShowWarning("Using the default user/password s1/p1 is NOT RECOMMENDED.\n");
 		ShowNotice("Please edit your 'login' table to create a proper inter-server user/password (gender 'S')\n");
 		ShowNotice("and then edit your user/password in conf/map_athena.conf (or conf/import/map_conf.txt)\n");
 	}
+#endif
 }
 
 // sets char-server's ip address
@@ -446,7 +428,6 @@ int chrif_removemap(int fd) {
 // received after a character has been "final saved" on the char-server
 static void chrif_save_ack(int fd) {
 	chrif_auth_delete(RFIFOL(fd,2), RFIFOL(fd,6), ST_LOGOUT);
-	chrif_check_shutdown();
 }
 
 // request to move a character between mapservers
@@ -572,8 +553,6 @@ void chrif_on_ready(void) {
 
 	chrif_state = 2;
 
-	chrif_check_shutdown();
-
 	//If there are players online, send them to the char-server. [Skotlex]
 	send_users_tochar();
 
@@ -733,7 +712,7 @@ void chrif_authok(int fd) {
 
 	sd = node->sd;
 
-	if( runflag == MAPSERVER_ST_RUNNING &&
+	if( global_core->is_running() &&
 		node->char_dat == NULL &&
 		node->account_id == account_id &&
 		node->char_id == char_id &&

+ 0 - 1
src/map/chrif.hpp

@@ -43,7 +43,6 @@ int chrif_setip(const char* ip);
 void chrif_setport(uint16 port);
 
 int chrif_isconnected(void);
-void chrif_check_shutdown(void);
 
 extern int chrif_connected;
 extern int other_mapserver_count;

+ 1 - 1
src/map/clif.cpp

@@ -10633,7 +10633,7 @@ void clif_parse_WantToConnection(int fd, map_session_data* sd)
 		return;
 	}
 
-	if( runflag != MAPSERVER_ST_RUNNING ) {// not allowed
+	if( !global_core->is_running() ){ // not allowed
 		clif_authfail_fd(fd,1);// server closed
 		return;
 	}

+ 22 - 44
src/map/map.cpp

@@ -54,6 +54,7 @@
 #include "trade.hpp"
 
 using namespace rathena;
+using namespace rathena::server_map;
 
 std::string default_codepage = "";
 
@@ -3937,7 +3938,7 @@ int parse_console(const char* buf){
 	}
 	else if( n == 2 && strcmpi("server", type) == 0 ){
 		if( strcmpi("shutdown", command) == 0 || strcmpi("exit", command) == 0 || strcmpi("quit", command) == 0 ){
-			runflag = 0;
+			global_core->signal_shutdown();
 		}
 	}
 	else if( strcmpi("ers_report", type) == 0 ){
@@ -4844,7 +4845,7 @@ static int cleanup_db_sub(DBKey key, DBData *data, va_list va)
 /*==========================================
  * map destructor
  *------------------------------------------*/
-void do_final(void){
+void MapServer::finalize(){
 	ShowStatus("Terminating...\n");
 	channel_config.closing = true;
 
@@ -4955,8 +4956,7 @@ static int map_abort_sub(map_session_data* sd, va_list ap)
 // Function called when the server
 // has received a crash signal.
 //------------------------------
-void do_abort(void)
-{
+void MapServer::handle_crash(){
 	static int run = 0;
 	//Save all characters and then flush the inter-connection.
 	if (run) {
@@ -4998,14 +4998,6 @@ void display_helpscreen(bool do_exit)
 		exit(EXIT_SUCCESS);
 }
 
-/*======================================================
- * Map-Server Init and Command-line Arguments [Valaris]
- *------------------------------------------------------*/
-void set_server_type(void)
-{
-	SERVER_TYPE = ATHENA_SERVER_MAP;
-}
-
 /*======================================================
  * Message System
  *------------------------------------------------------*/
@@ -5126,29 +5118,19 @@ int mapgenerator_get_options(int argc, char** argv) {
 	return 1;
 }
 
-
 /// Called when a terminate signal is received.
-void do_shutdown(void)
-{
-	if( runflag != MAPSERVER_ST_SHUTDOWN )
-	{
-		runflag = MAPSERVER_ST_SHUTDOWN;
-		ShowStatus("Shutting down...\n");
-		{
-			map_session_data* sd;
-			struct s_mapiterator* iter = mapit_getallusers();
-			for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) )
-				clif_GM_kick(NULL, sd);
-			mapit_free(iter);
-			flush_fifos();
-		}
-		chrif_check_shutdown();
-	}
+void MapServer::handle_shutdown(){
+	ShowStatus("Shutting down...\n");
+
+	map_session_data* sd;
+	struct s_mapiterator* iter = mapit_getallusers();
+	for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) )
+		clif_GM_kick(NULL, sd);
+	mapit_free(iter);
+	flush_fifos();
 }
 
-int do_init(int argc, char *argv[])
-{
-	runflag = MAPSERVER_ST_STARTING;
+bool MapServer::initialize( int argc, char *argv[] ){
 #ifdef GCOLLECT
 	GC_enable_incremental();
 #endif
@@ -5204,10 +5186,9 @@ int do_init(int argc, char *argv[])
 		char ip_str[16];
 		ip2str(addr_[0], ip_str);
 
-		// Skip this warning if the server is run with run-once flag
-		if( runflag != CORE_ST_STOP ){
-			ShowWarning("Not all IP addresses in map_athena.conf configured, autodetecting...\n");
-		}
+#if !defined(BUILDBOT)
+		ShowWarning( "Not all IP addresses in map_athena.conf configured, autodetecting...\n" );
+#endif
 
 		if (naddr_ == 0)
 			ShowError("Unable to determine your IP address...\n");
@@ -5301,20 +5282,17 @@ int do_init(int argc, char *argv[])
 		itemdb_gen_itemmoveinfo();
 	if (gen_options.reputation)
 		pc_reputation_generate();
-	runflag = CORE_ST_STOP;
+	this->signal_shutdown();
 #endif
 
-	if( runflag != CORE_ST_STOP )
-	{
-		shutdown_callback = do_shutdown;
-		runflag = MAPSERVER_ST_RUNNING;
-	}
-
 	if( console ){ //start listening
 		add_timer_func_list(parse_console_timer, "parse_console_timer");
 		add_timer_interval(gettick()+1000, parse_console_timer, 0, 0, 1000); //start in 1s each 1sec
 	}
 
-	return 0;
+	return true;
 }
 
+int main( int argc, char *argv[] ){
+	return main_core<MapServer>( argc, argv );
+}

+ 20 - 7
src/map/map.hpp

@@ -22,17 +22,30 @@
 #include "navi.hpp"
 #include "script.hpp"
 
+using rathena::server_core::Core;
+using rathena::server_core::e_core_type;
+
+namespace rathena{
+	namespace server_map{
+		class MapServer : public Core{
+			protected:
+				bool initialize( int argc, char* argv[] ) override;
+				void finalize() override;
+				void handle_crash() override;
+				void handle_shutdown() override;
+
+			public:
+				MapServer() : Core( e_core_type::MAP ){
+
+				}
+		};
+	}
+}
+
 struct npc_data;
 struct item_data;
 struct Channel;
 
-enum E_MAPSERVER_ST {
-	MAPSERVER_ST_RUNNING = CORE_ST_LAST,
-	MAPSERVER_ST_STARTING,
-	MAPSERVER_ST_SHUTDOWN,
-	MAPSERVER_ST_LAST
-};
-
 struct map_data *map_getmapdata(int16 m);
 #define msg_config_read(cfgName,isnew) map_msg_config_read(cfgName,isnew)
 #define msg_txt(sd,msg_number) map_msg_txt(sd,msg_number)

+ 53 - 50
src/tool/csv2yaml.cpp

@@ -5,6 +5,8 @@
 
 #include <math.h>
 
+using namespace rathena::tool_csv2yaml;
+
 // Skill database data to memory
 static void skill_txt_data(const std::string& modePath, const std::string& fixedPath) {
 	skill_require.clear();
@@ -202,7 +204,7 @@ bool process( const std::string& type, uint32 version, const std::vector<std::st
 	return true;
 }
 
-int do_init( int argc, char** argv ){
+bool Csv2YamlTool::initialize( int argc, char* argv[] ){
 	const std::string path_db = std::string( db_path );
 	const std::string path_db_mode = path_db + "/" + DBPATH;
 	const std::string path_db_import = path_db + "/" + DBIMPORT + "/";
@@ -241,91 +243,91 @@ int do_init( int argc, char** argv ){
 	if( !process( "GUILD_SKILL_TREE_DB", 1, root_paths, "guild_skill_tree", []( const std::string& path, const std::string& name_ext ) -> bool {
 		return sv_readdb( path.c_str(), name_ext.c_str(), ',', 2 + MAX_GUILD_SKILL_REQUIRE * 2, 2 + MAX_GUILD_SKILL_REQUIRE * 2, -1, &guild_read_guildskill_tree_db, false );
 	} ) ){
-		return 0;
+		return false;
 	}
 
 	if( !process( "PET_DB", 1, root_paths, "pet_db", []( const std::string& path, const std::string& name_ext ) -> bool {
 		return pet_read_db( ( path + name_ext ).c_str() );
 	} ) ){
-		return 0;
+		return false;
 	}
 
 	if (!process("MAGIC_MUSHROOM_DB", 1, root_paths, "magicmushroom_db", [](const std::string &path, const std::string &name_ext) -> bool {
 		return sv_readdb(path.c_str(), name_ext.c_str(), ',', 1, 1, -1, &skill_parse_row_magicmushroomdb, false);
 	})) {
-		return 0;
+		return false;
 	}
 
 	if (!process("ABRA_DB", 1, root_paths, "abra_db", [](const std::string& path, const std::string& name_ext) -> bool {
 		return sv_readdb(path.c_str(), name_ext.c_str(), ',', 3, 3, -1, &skill_parse_row_abradb, false);
 	})) {
-		return 0;
+		return false;
 	}
 
 	if (!process("READING_SPELLBOOK_DB", 1, root_paths, "spellbook_db", [](const std::string& path, const std::string& name_ext) -> bool {
 		return sv_readdb(path.c_str(), name_ext.c_str(), ',', 3, 3, -1, &skill_parse_row_spellbookdb, false);
 	})) {
-		return 0;
+		return false;
 	}
 
 	if (!process("MOB_AVAIL_DB", 1, root_paths, "mob_avail", [](const std::string& path, const std::string& name_ext) -> bool {
 		return sv_readdb(path.c_str(), name_ext.c_str(), ',', 2, 12, -1, &mob_readdb_mobavail, false);
 	})) {
-		return 0;
+		return false;
 	}
 
 	skill_txt_data( path_db_mode, path_db );
 	if (!process("SKILL_DB", 3, { path_db_mode }, "skill_db", [](const std::string& path, const std::string& name_ext) -> bool {
 		return sv_readdb(path.c_str(), name_ext.c_str(), ',', 18, 18, -1, &skill_parse_row_skilldb, false);
 	})){
-		return 0;
+		return false;
 	}
 
 	skill_txt_data( path_db_import, path_db_import );
 	if (!process("SKILL_DB", 3, { path_db_import }, "skill_db", [](const std::string& path, const std::string& name_ext) -> bool {
 		return sv_readdb(path.c_str(), name_ext.c_str(), ',', 18, 18, -1, &skill_parse_row_skilldb, false);
 	})){
-		return 0;
+		return false;
 	}
 
 	if (!process("QUEST_DB", 3, root_paths, "quest_db", [](const std::string &path, const std::string &name_ext) -> bool {
 		return sv_readdb(path.c_str(), name_ext.c_str(), ',', 3 + MAX_QUEST_OBJECTIVES * 2 + MAX_QUEST_DROPS * 3, 100, -1, &quest_read_db, false);
 	})) {
-		return 0;
+		return false;
 	}
 
 	if (!process("INSTANCE_DB", 1, root_paths, "instance_db", [](const std::string& path, const std::string& name_ext) -> bool {
 		return sv_readdb(path.c_str(), name_ext.c_str(), ',', 7, 7 + MAX_MAP_PER_INSTANCE, -1, &instance_readdb_sub, false);
 	})) {
-		return 0;
+		return false;
 	}
 
 	item_txt_data(path_db_mode, path_db);
 	if (!process("ITEM_DB", 3, { path_db_mode }, "item_db", [](const std::string& path, const std::string& name_ext) -> bool {
 		return itemdb_read_db((path + name_ext).c_str());
 	})) {
-		return 0;
+		return false;
 	}
 
 	item_txt_data(path_db_import, path_db_import);
 	if (!process("ITEM_DB", 3, { path_db_import }, "item_db", [](const std::string& path, const std::string& name_ext) -> bool {
 		return itemdb_read_db((path + name_ext).c_str());
 	})) {
-		return 0;
+		return false;
 	}
 
 	rand_opt_db.clear();
 	if (!process("RANDOM_OPTION_DB", 1, root_paths, "item_randomopt_db", [](const std::string& path, const std::string& name_ext) -> bool {
 		return itemdb_read_randomopt((path + name_ext).c_str());
 	})) {
-		return 0;
+		return false;
 	}
 
 	rand_opt_group.clear();
 	if (!process("RANDOM_OPTION_GROUP", 1, root_paths, "item_randomopt_group", [](const std::string& path, const std::string& name_ext) -> bool {
 		return sv_readdb(path.c_str(), name_ext.c_str(), ',', 5, 2 + 5 * MAX_ITEM_RDM_OPT, -1, &itemdb_read_randomopt_group, false) && itemdb_randomopt_group_yaml();
 	})) {
-		return 0;
+		return false;
 	}
 
 #ifdef RENEWAL
@@ -333,14 +335,14 @@ int do_init( int argc, char** argv ){
 	if (!process("PENALTY_DB", 1, { path_db_mode }, "level_penalty", [](const std::string& path, const std::string& name_ext) -> bool {
 		return sv_readdb(path.c_str(), name_ext.c_str(), ',', 4, 4, -1, &pc_readdb_levelpenalty, false) && pc_levelpenalty_yaml();
 	})) {
-		return 0;
+		return false;
 	}
 
 	memset( level_penalty, 0, sizeof( level_penalty ) );
 	if (!process("PENALTY_DB", 1, { path_db_import }, "level_penalty", [](const std::string& path, const std::string& name_ext) -> bool {
 		return sv_readdb(path.c_str(), name_ext.c_str(), ',', 4, 4, -1, &pc_readdb_levelpenalty, false) && pc_levelpenalty_yaml();
 	})) {
-		return 0;
+		return false;
 	}
 #endif
 
@@ -348,132 +350,132 @@ int do_init( int argc, char** argv ){
 	if (!process("MOB_DB", 3, { path_db_mode }, "mob_db", [](const std::string &path, const std::string &name_ext) -> bool {
 		return sv_readdb(path.c_str(), name_ext.c_str(), ',', 31 + 2 * MAX_MVP_DROP + 2 * MAX_MOB_DROP, 31 + 2 * MAX_MVP_DROP + 2 * MAX_MOB_DROP, -1, &mob_readdb_sub, false);
 	})) {
-		return 0;
+		return false;
 	}
 
 	mob_txt_data(path_db_import, path_db_import);
 	if (!process("MOB_DB", 3, { path_db_import }, "mob_db", [](const std::string &path, const std::string &name_ext) -> bool {
 		return sv_readdb(path.c_str(), name_ext.c_str(), ',', 31 + 2 * MAX_MVP_DROP + 2 * MAX_MOB_DROP, 31 + 2 * MAX_MVP_DROP + 2 * MAX_MOB_DROP, -1, &mob_readdb_sub, false);
 	})) {
-		return 0;
+		return false;
 	}
 
 	if (!process("MOB_CHAT_DB", 1, root_paths, "mob_chat_db", [](const std::string& path, const std::string& name_ext) -> bool {
 		return sv_readdb(path.c_str(), name_ext.c_str(), '#', 3, 3, -1, &mob_parse_row_chatdb, false);
 	})) {
-		return 0;
+		return false;
 	}
 
 	if (!process("HOMUN_EXP_DB", 1, { path_db_mode }, "exp_homun", [](const std::string &path, const std::string &name_ext) -> bool {
 		return read_homunculus_expdb((path + name_ext).c_str());
 	})) {
-		return 0;
+		return false;
 	}
 
 	if (!process("HOMUN_EXP_DB", 1, { path_db_import }, "exp_homun", [](const std::string &path, const std::string &name_ext) -> bool {
 		return read_homunculus_expdb((path + name_ext).c_str());
 	})) {
-		return 0;
+		return false;
 	}
 
 	branch_txt_data(path_db_mode, path_db);
 	if (!process("MOB_SUMMONABLE_DB", 1, { path_db_mode }, "mob_branch", [](const std::string &path, const std::string &name_ext) -> bool {
 		return mob_readdb_group_yaml();
 	}, "mob_summon")) {
-		return 0;
+		return false;
 	}
 
 	branch_txt_data(path_db_import, path_db_import);
 	if (!process("MOB_SUMMONABLE_DB", 1, { path_db_import }, "mob_branch", [](const std::string &path, const std::string &name_ext) -> bool {
 		return mob_readdb_group_yaml();
 	}, "mob_summon")) {
-		return 0;
+		return false;
 	}
 
 	if (!process("CREATE_ARROW_DB", 1, root_paths, "create_arrow_db", [](const std::string& path, const std::string& name_ext) -> bool {
 		return sv_readdb(path.c_str(), name_ext.c_str(), ',', 1+2, 1+2*MAX_ARROW_RESULT, MAX_SKILL_ARROW_DB, &skill_parse_row_createarrowdb, false);
 	})) {
-		return 0;
+		return false;
 	}
 
 	if (!process("STATPOINT_DB", 1, { path_db_mode }, "statpoint", [](const std::string &path, const std::string &name_ext) -> bool {
 		return pc_read_statsdb((path + name_ext).c_str());
 	})) {
-		return 0;
+		return false;
 	}
 
 	if (!process("STATPOINT_DB", 1, { path_db_import }, "statpoint", [](const std::string &path, const std::string &name_ext) -> bool {
 		return pc_read_statsdb((path + name_ext).c_str());
 	})) {
-		return 0;
+		return false;
 	}
 
 	if (!process("CASTLE_DB", 1, root_paths, "castle_db", [](const std::string &path, const std::string &name_ext) -> bool {
 		return sv_readdb(path.c_str(), name_ext.c_str(), ',', 4, 4, -1, &guild_read_castledb, false);
 	})) {
-		return 0;
+		return false;
 	}
 
 	if (!process("GUILD_EXP_DB", 1, { path_db_mode }, "exp_guild", [](const std::string &path, const std::string &name_ext) -> bool {
 		return sv_readdb(path.c_str(), name_ext.c_str(), ',', 1, 1, MAX_GUILDLEVEL, &exp_guild_parse_row, false);
 	})) {
-		return 0;
+		return false;
 	}
 
 	if (!process("GUILD_EXP_DB", 1, { path_db_import }, "exp_guild", [](const std::string &path, const std::string &name_ext) -> bool {
 		return sv_readdb(path.c_str(), name_ext.c_str(), ',', 1, 1, MAX_GUILDLEVEL, &exp_guild_parse_row, false);
 	})) {
-		return 0;
+		return false;
 	}
 
 	item_group_txt_data(path_db_mode, path_db);
 	if (!process("ITEM_GROUP_DB", 2, { path_db_mode }, "item_group_db", [](const std::string &path, const std::string &name_ext) -> bool {
 		return itemdb_read_group_yaml();
 	})) {
-		return 0;
+		return false;
 	}
 
 	item_group_txt_data(path_db_import, path_db_import);
 	if (!process("ITEM_GROUP_DB", 2, { path_db_import }, "item_group_db", [](const std::string &path, const std::string &name_ext) -> bool {
 		return itemdb_read_group_yaml();
 	})) {
-		return 0;
+		return false;
 	}
 
 	if (!process("MOB_ITEM_RATIO_DB", 1, root_paths, "mob_item_ratio", [](const std::string& path, const std::string& name_ext) -> bool {
 		return sv_readdb(path.c_str(), name_ext.c_str(), ',', 2, 2+MAX_ITEMRATIO_MOBS, -1, &mob_readdb_itemratio, false);
 	})) {
-		return 0;
+		return false;
 	}
 
 	if (!process("ATTRIBUTE_DB", 1, { path_db_mode }, "attr_fix", [](const std::string &path, const std::string &name_ext) -> bool {
 		return status_readdb_attrfix((path + name_ext).c_str());
 	})) {
-		return 0;
+		return false;
 	}
 
 	if (!process("ATTRIBUTE_DB", 1, { path_db_import }, "attr_fix", [](const std::string &path, const std::string &name_ext) -> bool {
 		return status_readdb_attrfix((path + name_ext).c_str());
 	})) {
-		return 0;
+		return false;
 	}
 
 	if (!process("CONSTANT_DB", 1, root_paths, "const", [](const std::string& path, const std::string& name_ext) -> bool {
 		return sv_readdb(path.c_str(), name_ext.c_str(), ',', 1, 3, -1, &read_constdb, false);
 	})) {
-		return 0;
+		return false;
 	}
 
 	if (!process("JOB_STATS", 2, root_paths, "job_exp", [](const std::string& path, const std::string& name_ext) -> bool {
 		return sv_readdb(path.c_str(), name_ext.c_str(), ',', 4, 1000 + 3, CLASS_COUNT * 2, &pc_readdb_job_exp, false);
 	}, "job_exp")) {
-		return 0;
+		return false;
 	}
 
 	if (!process("JOB_STATS", 2, root_paths, "job_basehpsp_db", [](const std::string& path, const std::string& name_ext) -> bool {
 		return sv_readdb(path.c_str(), name_ext.c_str(), ',', 4, 4 + 500, CLASS_COUNT * 2, &pc_readdb_job_basehpsp, false);
 	}, "job_basepoints")) {
-		return 0;
+		return false;
 	}
 
 	job_txt_data(path_db_mode, path_db);
@@ -484,7 +486,7 @@ int do_init( int argc, char** argv ){
 		return sv_readdb(path.c_str(), name_ext.c_str(), ',', 5 + MAX_WEAPON_TYPE, 5 + MAX_WEAPON_TYPE, CLASS_COUNT, &pc_readdb_job1, false);
 #endif
 	}, "job_stats")) {
-		return 0;
+		return false;
 	}
 
 	job_txt_data(path_db_import, path_db_import);
@@ -495,55 +497,52 @@ int do_init( int argc, char** argv ){
 		return sv_readdb(path.c_str(), name_ext.c_str(), ',', 5 + MAX_WEAPON_TYPE, 5 + MAX_WEAPON_TYPE, CLASS_COUNT, &pc_readdb_job1, false);
 #endif
 	}, "job_stats")) {
-		return 0;
+		return false;
 	}
 
 	elemental_skill_txt_data(path_db_mode, path_db);
 	if (!process("ELEMENTAL_DB", 1, root_paths, "elemental_db", [](const std::string &path, const std::string &name_ext) -> bool {
 		return sv_readdb(path.c_str(), name_ext.c_str(), ',', 26, 26, -1, &read_elementaldb, false);
 	})) {
-		return 0;
+		return false;
 	}
 
 	mercenary_skill_txt_data(path_db_mode, path_db);
 	if (!process("MERCENARY_DB", 1, root_paths, "mercenary_db", [](const std::string &path, const std::string &name_ext) -> bool {
 		return sv_readdb(path.c_str(), name_ext.c_str(), ',', 26, 26, -1, &mercenary_readdb, false);
 	})) {
-		return 0;
+		return false;
 	}
 
 	skilltree_txt_data(path_db_mode, path_db);
 	if (!process("SKILL_TREE_DB", 1, { path_db_mode }, "skill_tree", [](const std::string &path, const std::string &name_ext) -> bool {
 		return pc_readdb_skilltree_yaml();
 	})) {
-		return 0;
+		return false;
 	}
 
 	skilltree_txt_data(path_db_import, path_db_import);
 	if (!process("SKILL_TREE_DB", 1, { path_db_import }, "skill_tree", [](const std::string &path, const std::string &name_ext) -> bool {
 		return pc_readdb_skilltree_yaml();
 	})) {
-		return 0;
+		return false;
 	}
 
 	if (!process("COMBO_DB", 1, { path_db_mode }, "item_combo_db", [](const std::string& path, const std::string& name_ext) -> bool {
 		return itemdb_read_combos((path + name_ext).c_str());
 	}, "item_combos")) {
-		return 0;
+		return false;
 	}
 
 	if (!process("COMBO_DB", 1, { path_db_import }, "item_combo_db", [](const std::string& path, const std::string& name_ext) -> bool {
 		return itemdb_read_combos((path + name_ext).c_str());
 	}, "item_combos")) {
-		return 0;
+		return false;
 	}
 
 	// TODO: add implementations ;-)
 
-	return 0;
-}
-
-void do_final(void){
+	return true;
 }
 
 // Implementation of the conversion functions
@@ -4918,3 +4917,7 @@ static bool itemdb_read_combos(const char* file) {
 
 	return true;
 }
+
+int main( int argc, char *argv[] ){
+	return main_core<Csv2YamlTool>( argc, argv );
+}

+ 19 - 0
src/tool/csv2yaml.hpp

@@ -4,8 +4,27 @@
 #ifndef CSV2YAML_HPP
 #define CSV2YAML_HPP
 
+#include "../common/core.hpp"
+
 #include "yaml.hpp"
 
+using rathena::server_core::Core;
+using rathena::server_core::e_core_type;
+
+namespace rathena{
+	namespace tool_csv2yaml{
+		class Csv2YamlTool : public Core{
+			protected:
+				bool initialize( int argc, char* argv[] ) override;
+
+			public:
+				Csv2YamlTool() : Core( e_core_type::TOOL ){
+
+				}
+		};
+	}
+}
+
 // Required constant and structure definitions
 #define MAX_GUILD_SKILL_REQUIRE 5
 #define MAX_SKILL_ITEM_REQUIRE	10

+ 24 - 7
src/tool/mapcache.cpp

@@ -17,6 +17,24 @@
 #include "../common/showmsg.hpp"
 #include "../common/utils.hpp"
 
+using namespace rathena::server_core;
+
+namespace rathena{
+	namespace tool_mapcache{
+		class MapcacheTool : public Core{
+			protected:
+				bool initialize( int argc, char* argv[] ) override;
+
+			public:
+				MapcacheTool() : Core( e_core_type::TOOL ){
+
+				}
+		};
+	}
+}
+
+using namespace rathena::tool_mapcache;
+
 std::string grf_list_file = "conf/grf-files.txt";
 std::string map_list_file = "map_index.txt";
 std::string map_cache_file;
@@ -185,8 +203,7 @@ void process_args(int argc, char *argv[])
 
 }
 
-int do_init(int argc, char** argv)
-{
+bool MapcacheTool::initialize( int argc, char* argv[] ){
 	/* setup pre-defined, #define-dependant */
 	map_cache_file = std::string(db_path) + "/" + std::string(DBPATH) + "map_cache.dat";
 
@@ -212,7 +229,7 @@ int do_init(int argc, char** argv)
 		map_cache_fp = fopen(map_cache_file.c_str(), "r+b");
 	if(map_cache_fp == NULL) {
 		ShowError("Failure when opening map cache file %s\n", map_cache_file.c_str());
-		exit(EXIT_FAILURE);
+		return false;
 	}
 
 	// Open the map list
@@ -226,7 +243,7 @@ int do_init(int argc, char** argv)
 		list = fopen(filename.c_str(), "r");
 		if (list == NULL) {
 			ShowError("Failure when opening maps list file %s\n", filename.c_str());
-			exit(EXIT_FAILURE);
+			return false;
 		}
 
 		// Initialize the main header
@@ -285,9 +302,9 @@ int do_init(int argc, char** argv)
 
 	ShowInfo("%d maps now in cache\n", header.map_count);
 
-	return 0;
+	return true;
 }
 
-void do_final(void)
-{
+int main( int argc, char *argv[] ){
+	return main_core<MapcacheTool>( argc, argv );
 }

+ 27 - 9
src/tool/yaml2sql.cpp

@@ -53,6 +53,23 @@
 #include "../map/storage.hpp"
 
 using namespace rathena;
+using namespace rathena::server_core;
+
+namespace rathena{
+	namespace tool_yaml2sql{
+		class Yaml2SqlTool : public Core{
+			protected:
+				bool initialize( int argc, char* argv[] ) override;
+
+			public:
+				Yaml2SqlTool() : Core( e_core_type::TOOL ){
+
+				}
+		};
+	}
+}
+
+using namespace rathena::tool_yaml2sql;
 
 #ifndef WIN32
 int getch( void ){
@@ -192,7 +209,7 @@ bool process( const std::string& type, uint32 version, const std::vector<std::st
 	return true;
 }
 
-int do_init( int argc, char** argv ){
+bool Yaml2SqlTool::initialize( int argc, char* argv[] ){
 	const std::string path_db = std::string( db_path );
 	const std::string path_db_mode = path_db + "/" + DBPATH;
 	const std::string path_db_import = path_db + "/" + DBIMPORT + "/";
@@ -220,34 +237,31 @@ int do_init( int argc, char** argv ){
 		if (!process("ITEM_DB", 1, { path_db_mode }, "item_db_" + suffix, item_table_name + "_" + suffix, item_table_name, [](const std::string& path, const std::string& name_ext, const std::string& table) -> bool {
 			return item_db_yaml2sql(path + name_ext, table);
 		})) {
-			return 0;
+			return false;
 		}
 	}
 
 	if (!process("ITEM_DB", 1, { path_db_import }, "item_db", item_import_table_name, item_import_table_name, [](const std::string& path, const std::string& name_ext, const std::string& table) -> bool {
 		return item_db_yaml2sql(path + name_ext, table);
 	})) {
-		return 0;
+		return false;
 	}
 
 	if (!process("MOB_DB", 1, { path_db_mode }, "mob_db", mob_table_name, mob_table_name, [](const std::string &path, const std::string &name_ext, const std::string &table) -> bool {
 		return mob_db_yaml2sql(path + name_ext, table);
 	})) {
-		return 0;
+		return false;
 	}
 
 	if (!process("MOB_DB", 1, { path_db_import }, "mob_db", mob_import_table_name, mob_import_table_name, [](const std::string &path, const std::string &name_ext, const std::string &table) -> bool {
 		return mob_db_yaml2sql(path + name_ext, table);
 	})) {
-		return 0;
+		return false;
 	}
 
 	// TODO: add implementations ;-)
 
-	return 0;
-}
-
-void do_final(void){
+	return true;
 }
 
 bool fileExists( const std::string& path ){
@@ -935,3 +949,7 @@ static bool mob_db_yaml2sql(const std::string &file, const std::string &table) {
 
 	return true;
 }
+
+int main( int argc, char *argv[] ){
+	return main_core<Yaml2SqlTool>( argc, argv );
+}

+ 11 - 8
src/tool/yamlupgrade.cpp

@@ -3,6 +3,8 @@
 
 #include "yamlupgrade.hpp"
 
+using namespace rathena::tool_yamlupgrade;
+
 static bool upgrade_achievement_db(std::string file, const uint32 source_version);
 static bool upgrade_item_db(std::string file, const uint32 source_version);
 static bool upgrade_job_stats(std::string file, const uint32 source_version);
@@ -70,7 +72,7 @@ bool process(const std::string &type, uint32 version, const std::vector<std::str
 	return true;
 }
 
-int do_init(int argc, char** argv) {
+bool YamlUpgradeTool::initialize( int argc, char* argv[] ){
 	const std::string path_db = std::string(db_path);
 	const std::string path_db_mode = path_db + "/" + DBPATH;
 	const std::string path_db_import = path_db + "/" + DBIMPORT;
@@ -108,19 +110,19 @@ int do_init(int argc, char** argv) {
 	if (!process("ACHIEVEMENT_DB", 2, root_paths, "achievement_db", [](const std::string &path, const std::string &name_ext, uint32 source_version) -> bool {
 		return upgrade_achievement_db(path + name_ext, source_version);
 	})) {
-		return 0;
+		return false;
 	}
 
 	if (!process("ITEM_DB", 3, root_paths, "item_db", [](const std::string& path, const std::string& name_ext, uint32 source_version) -> bool {
 		return upgrade_item_db(path + name_ext, source_version);
 		})) {
-		return 0;
+		return false;
 	}
 
 	if (!process("JOB_STATS", 2, root_paths, "job_stats", [](const std::string& path, const std::string& name_ext, uint32 source_version) -> bool {
 		return upgrade_job_stats(path + name_ext, source_version);
 		})) {
-		return 0;
+		return false;
 	}
 	
 	if (!process("STATUS_DB", 3, root_paths, "status", [](const std::string& path, const std::string& name_ext, uint32 source_version) -> bool {
@@ -129,10 +131,7 @@ int do_init(int argc, char** argv) {
 		return 0;
 	}
 
-	return 0;
-}
-
-void do_final(void) {
+	return true;
 }
 
 // Implementation of the upgrade functions
@@ -322,3 +321,7 @@ static bool upgrade_status_db(std::string file, const uint32 source_version) {
 
 	return true;
 }
+
+int main( int argc, char *argv[] ){
+	return main_core<YamlUpgradeTool>( argc, argv );
+}

+ 19 - 0
src/tool/yamlupgrade.hpp

@@ -4,6 +4,25 @@
 #ifndef YAMLUPGRADE_HPP
 #define YAMLUPGRADE_HPP
 
+#include "../common/core.hpp"
+
 #include "yaml.hpp"
 
+using rathena::server_core::Core;
+using rathena::server_core::e_core_type;
+
+namespace rathena{
+	namespace tool_yamlupgrade{
+		class YamlUpgradeTool : public Core{
+			protected:
+				bool initialize( int argc, char* argv[] ) override;
+
+			public:
+				YamlUpgradeTool() : Core( e_core_type::TOOL ){
+
+				}
+		};
+	}
+}
+
 #endif /* YAMLUPGRADE_HPP */

+ 23 - 36
src/web/web.cpp

@@ -33,6 +33,8 @@
 
 
 using namespace rathena;
+using namespace rathena::server_core;
+using namespace rathena::server_web;
 
 #define WEB_MAX_MSG 30				/// Max number predefined in msg_conf
 static char* msg_table[WEB_MAX_MSG];	/// Web Server messages_conf
@@ -318,9 +320,9 @@ int web_sql_close(void)
 
 /**
  * Login-serv destructor
- *  dealloc..., function called at exit of the login-serv
+ *  dealloc..., function called at exit of the web-server
  */
-void do_final(void) {
+void WebServer::finalize(){
 	ShowStatus("Terminating...\n");
 #ifdef WEB_SERVER_ENABLE
 	http_server->stop();
@@ -331,25 +333,12 @@ void do_final(void) {
 	ShowStatus("Finished.\n");
 }
 
-/**
- * Signal handler
- *  This function attempts to properly close the server when an interrupt signal is received.
- *  current signal catch : SIGTERM, SIGINT
- */
-void do_shutdown(void) {
-	if( runflag != WEBSERVER_ST_SHUTDOWN ) {
-		runflag = WEBSERVER_ST_SHUTDOWN;
-		ShowStatus("Shutting down...\n");
-		runflag = CORE_ST_STOP;
-	}
-}
-
 /**
  * Signal handler
  *  Function called when the server has received a crash signal.
  *  current signal catch : SIGSEGV, SIGFPE
  */
-void do_abort(void) {
+void WebServer::handle_crash(){
 #ifdef WEB_SERVER_ENABLE
 	http_server->stop();
 	svr_thr.join();
@@ -366,13 +355,6 @@ void display_helpscreen(bool do_exit)
 		exit(EXIT_SUCCESS);
 }
 
-
-// Is this still used ??
-void set_server_type(void) {
-	SERVER_TYPE = ATHENA_SERVER_WEB;
-}
-
-
 // called just before sending repsonse
 void logger(const Request & req, const Response & res) {
 	// make this a config
@@ -397,11 +379,11 @@ void logger(const Request & req, const Response & res) {
 }
 
 
-int do_init(int argc, char** argv) {
-	runflag = WEBSERVER_ST_STARTING;
+bool WebServer::initialize( int argc, char* argv[] ){
 #ifndef WEB_SERVER_ENABLE
-	ShowStatus("The web-server is " CL_GREEN "idling" CL_RESET " (PACKETVER too old to use).\n\n");
-	return 0;
+	ShowStatus("The web-server is " CL_GREEN "stopping" CL_RESET " (PACKETVER too old to use).\n\n");
+	this->signal_shutdown();
+	return true;
 #else
 	INTER_CONF_NAME="conf/inter_athena.conf";
 
@@ -432,17 +414,16 @@ int do_init(int argc, char** argv) {
 
 	// set up logger
 	http_server->set_logger(logger);
-	shutdown_callback = do_shutdown;
-
-	runflag = WEBSERVER_ST_STARTING;
 
 	svr_thr = std::thread([] {
 		http_server->listen(web_config.web_ip.c_str(), web_config.web_port);
 	});
 
 	for (int i = 0; i < 10; i++) {
-		if (runflag == CORE_ST_STOP)
-			return 0;
+		if( global_core->get_status() == e_core_status::STOPPING ){
+			return true;
+		}
+
 		if (http_server->is_running())
 			break;
 		ShowDebug("Web server not running, sleeping 1 second.\n");
@@ -451,12 +432,18 @@ int do_init(int argc, char** argv) {
 
 	if (!http_server->is_running()) {
 		ShowError("Web server hasn't started, stopping.\n");
-		runflag = CORE_ST_STOP;
-		return 0;
+		return false;
 	}
 
-	runflag = WEBSERVER_ST_RUNNING;
 	ShowStatus("The web-server is " CL_GREEN "ready" CL_RESET " (Server is listening on the port %u).\n\n", web_config.web_port);
-	return 0;
+	return true;
 #endif
 }
+
+void WebServer::handle_main( t_tick next ){
+	std::this_thread::sleep_for( std::chrono::milliseconds( next ) );
+}
+
+int main( int argc, char *argv[] ){
+	return main_core<WebServer>( argc, argv );
+}

+ 19 - 7
src/web/web.hpp

@@ -12,18 +12,30 @@
 #include "../common/timer.hpp"
 #include "../config/core.hpp"
 
+using rathena::server_core::Core;
+using rathena::server_core::e_core_type;
+
+namespace rathena{
+	namespace server_web{
+		class WebServer : public Core{
+			protected:
+				bool initialize( int argc, char* argv[] ) override;
+				void handle_main( t_tick next ) override;
+				void finalize() override;
+				void handle_crash() override;
+
+			public:
+				WebServer() : Core( e_core_type::WEB ){
+
+				}
+		};
+	}
+}
 
 #ifndef SQL_BUFFER_SIZE
 	#define SQL_BUFFER_SIZE 65535
 #endif
 
-enum E_WEBSERVER_ST {
-	WEBSERVER_ST_RUNNING = CORE_ST_LAST,
-	WEBSERVER_ST_STARTING,
-	WEBSERVER_ST_SHUTDOWN,
-	WEBSERVER_ST_LAST
-};
-
 struct Web_Config {
 	std::string web_ip;								// the address to bind to
 	uint16 web_port;								// the port to bind to