summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/common')
-rw-r--r--src/common/CMakeLists.txt4
-rw-r--r--src/common/Makefile.in3
-rw-r--r--src/common/console.c186
-rw-r--r--src/common/console.h48
-rw-r--r--src/common/core.c189
-rw-r--r--src/common/core.h7
6 files changed, 318 insertions, 119 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index e8c6c0a70..508154c00 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -36,6 +36,7 @@ set( COMMON_ALL_HEADERS
set( COMMON_MINI_HEADERS
${COMMON_ALL_HEADERS}
"${COMMON_SOURCE_DIR}/core.h"
+ "${COMMON_SOURCE_DIR}/console.h"
"${COMMON_SOURCE_DIR}/malloc.h"
"${COMMON_SOURCE_DIR}/showmsg.h"
"${COMMON_SOURCE_DIR}/strlib.h"
@@ -43,6 +44,7 @@ set( COMMON_MINI_HEADERS
CACHE INTERNAL "" )
set( COMMON_MINI_SOURCES
"${COMMON_SOURCE_DIR}/core.c"
+ "${COMMON_SOURCE_DIR}/console.c"
"${COMMON_SOURCE_DIR}/malloc.c"
"${COMMON_SOURCE_DIR}/showmsg.c"
"${COMMON_SOURCE_DIR}/strlib.c"
@@ -61,6 +63,7 @@ set( COMMON_BASE_HEADERS
${COMMON_ALL_HEADERS}
"${COMMON_SOURCE_DIR}/conf.h"
"${COMMON_SOURCE_DIR}/core.h"
+ "${COMMON_SOURCE_DIR}/console.h"
"${COMMON_SOURCE_DIR}/db.h"
"${COMMON_SOURCE_DIR}/des.h"
"${COMMON_SOURCE_DIR}/ers.h"
@@ -86,6 +89,7 @@ set( COMMON_BASE_HEADERS
set( COMMON_BASE_SOURCES
"${COMMON_SOURCE_DIR}/conf.c"
"${COMMON_SOURCE_DIR}/core.c"
+ "${COMMON_SOURCE_DIR}/console.c"
"${COMMON_SOURCE_DIR}/db.c"
"${COMMON_SOURCE_DIR}/des.c"
"${COMMON_SOURCE_DIR}/ers.c"
diff --git a/src/common/Makefile.in b/src/common/Makefile.in
index c24499c02..26cae3e51 100644
--- a/src/common/Makefile.in
+++ b/src/common/Makefile.in
@@ -3,7 +3,8 @@ COMMON_OBJ = obj_all/core.o obj_all/socket.o obj_all/timer.o obj_all/db.o \
obj_all/nullpo.o obj_all/malloc.o obj_all/showmsg.o obj_all/strlib.o obj_all/utils.o \
obj_all/grfio.o obj_all/mapindex.o obj_all/ers.o obj_all/md5calc.o \
obj_all/minicore.o obj_all/minisocket.o obj_all/minimalloc.o obj_all/random.o obj_all/des.o \
- obj_all/conf.o obj_all/thread.o obj_all/mutex.o obj_all/raconf.o obj_all/mempool.o
+ obj_all/conf.o obj_all/thread.o obj_all/mutex.o obj_all/raconf.o obj_all/mempool.o obj_all/console.o \
+ obj_all/miniconsole.o
COMMON_H = $(shell ls ../common/*.h)
diff --git a/src/common/console.c b/src/common/console.c
new file mode 100644
index 000000000..ee4570b2a
--- /dev/null
+++ b/src/common/console.c
@@ -0,0 +1,186 @@
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+// Portions Copyright (c) Athena Dev Teams
+
+#include "../common/showmsg.h"
+#include "../common/console.h"
+#include "../config/core.h"
+#include "core.h"
+
+#ifndef MINICORE
+ #include "../common/atomic.h"
+ #include "../common/spinlock.h"
+ #include "../common/thread.h"
+ #include "../common/mutex.h"
+ #include "../common/timer.h"
+ #include "../common/strlib.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifndef _WIN32
+ #include <unistd.h>
+#else
+ #include "../common/winapi.h" // Console close event handling
+#endif
+
+#ifdef CONSOLE_INPUT
+ #ifdef _WIN32
+ #include <conio.h> /* _kbhit() */
+ #endif
+#endif
+
+/*======================================
+ * CORE : Display title
+ *--------------------------------------*/
+void display_title(void) {
+ const char* svn = get_svn_revision();
+ const char* git = get_git_hash();
+
+ ShowMessage("\n");
+ ShowMessage(""CL_BG_RED" "CL_BT_WHITE" "CL_BG_RED""CL_CLL""CL_NORMAL"\n");
+ ShowMessage(""CL_BG_RED" "CL_BT_WHITE" Hercules Development Team presents "CL_BG_RED""CL_CLL""CL_NORMAL"\n");
+ ShowMessage(""CL_BG_RED" "CL_BT_WHITE" _ _ _ "CL_BG_RED""CL_CLL""CL_NORMAL"\n");
+ ShowMessage(""CL_BG_RED" "CL_BT_WHITE" | | | | | | "CL_BG_RED""CL_CLL""CL_NORMAL"\n");
+ ShowMessage(""CL_BG_RED" "CL_BT_WHITE" | |_| | ___ _ __ ___ _ _| | ___ ___ "CL_BG_RED""CL_CLL""CL_NORMAL"\n");
+ ShowMessage(""CL_BG_RED" "CL_BT_WHITE" | _ |/ _ \\ '__/ __| | | | |/ _ \\/ __|"CL_BG_RED""CL_CLL""CL_NORMAL"\n");
+ ShowMessage(""CL_BG_RED" "CL_BT_WHITE" | | | | __/ | | (__| |_| | | __/\\__ \\"CL_BG_RED""CL_CLL""CL_NORMAL"\n");
+ ShowMessage(""CL_BG_RED" "CL_BT_WHITE" \\_| |_/\\___|_| \\___|\\__,_|_|\\___||___/"CL_BG_RED""CL_CLL""CL_NORMAL"\n");
+ ShowMessage(""CL_BG_RED" "CL_BT_WHITE" "CL_BG_RED""CL_CLL""CL_NORMAL"\n");
+ ShowMessage(""CL_BG_RED" "CL_BT_WHITE" http://hercules.ws/board/ "CL_BG_RED""CL_CLL""CL_NORMAL"\n");
+ ShowMessage(""CL_BG_RED" "CL_BT_WHITE" "CL_BG_RED""CL_CLL""CL_NORMAL"\n");
+
+ if( git[0] != HERC_UNKNOWN_VER )
+ ShowInfo("Git Hash: '"CL_WHITE"%s"CL_RESET"'\n", git);
+ else if( svn[0] != HERC_UNKNOWN_VER )
+ ShowInfo("SVN Revision: '"CL_WHITE"%s"CL_RESET"'\n", svn);
+}
+#ifdef CONSOLE_INPUT
+#ifdef _WIN32
+int console_parse_key_pressed(void) {
+ return _kbhit();
+}
+#else /* _WIN32 */
+int console_parse_key_pressed(void) {
+ struct timeval tv;
+ fd_set fds;
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+
+ FD_ZERO(&fds);
+ FD_SET(STDIN_FILENO, &fds);
+
+ select(STDIN_FILENO+1, &fds, NULL, NULL, &tv);
+
+ return FD_ISSET(STDIN_FILENO, &fds);
+}
+#endif /* _WIN32 */
+
+void console_parse(char* line) {
+ int c, i = 0, len = MAX_CONSOLE_INPUT - 1;/* we leave room for the \0 :P */
+
+ while( (c = fgetc(stdin)) != EOF ) {
+ if( --len == 0 )
+ break;
+ if( (line[i++] = c) == '\n') {
+ line[i-1] = '\0';/* clear, we skip the new line */
+ break;/* new line~! we leave it for the next cycle */
+ }
+ }
+
+ line[i++] = '\0';
+}
+void *cThread_main(void *x) {
+
+ while( console->ptstate ) {/* loopx */
+ if( console->key_pressed() ) {
+ char input[MAX_CONSOLE_INPUT];
+
+ console->parse(input);
+ if( input[0] != '\0' ) {/* did we get something? */
+ EnterSpinLock(&console->ptlock);
+
+ if( cinput.count == CONSOLE_PARSE_SIZE ) {
+ LeaveSpinLock(&console->ptlock);
+ continue;/* drop */
+ }
+
+ safestrncpy(cinput.queue[cinput.count++],input,MAX_CONSOLE_INPUT);
+ LeaveSpinLock(&console->ptlock);
+ }
+ }
+ ramutex_lock( console->ptmutex );
+ racond_wait( console->ptcond, console->ptmutex, -1 );
+ ramutex_unlock( console->ptmutex );
+ }
+
+ return NULL;
+}
+int console_parse_timer(int tid, unsigned int tick, int id, intptr_t data) {
+ int i;
+ EnterSpinLock(&console->ptlock);
+ for(i = 0; i < cinput.count; i++) {
+ parse_console(cinput.queue[i]);
+ }
+ cinput.count = 0;
+ LeaveSpinLock(&console->ptlock);
+ racond_signal(console->ptcond);
+ return 0;
+}
+void console_parse_final(void) {
+ InterlockedDecrement(&console->ptstate);
+ racond_signal(console->ptcond);
+
+ /* wait for thread to close */
+ rathread_wait(console->pthread, NULL);
+
+ racond_destroy(console->ptcond);
+ ramutex_destroy(console->ptmutex);
+
+}
+void console_parse_init(void) {
+ cinput.count = 0;
+
+ console->ptstate = 1;
+
+ InitializeSpinLock(&console->ptlock);
+
+ console->ptmutex = ramutex_create();
+ console->ptcond = racond_create();
+
+ if( (console->pthread = rathread_create(console->pthread_main, NULL)) == NULL ){
+ ShowFatalError("console_parse_init: failed to spawn console_parse thread.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ add_timer_func_list(console->parse_timer, "console_parse_timer");
+ add_timer_interval(gettick() + 1000, console->parse_timer, 0, 0, 500);/* start listening in 1s; re-try every 0.5s */
+
+}
+#endif /* CONSOLE_INPUT */
+
+void console_init (void) {
+ console->display_title();
+#ifdef CONSOLE_INPUT
+ console->parse_init();
+#endif
+}
+void console_final(void) {
+#ifdef CONSOLE_INPUT
+ console->parse_final();
+#endif
+}
+void console_defaults(void) {
+ console = &console_s;
+ console->init = console_init;
+ console->final = console_final;
+ console->display_title = display_title;
+#ifdef CONSOLE_INPUT
+ console->parse_init = console_parse_init;
+ console->parse_final = console_parse_final;
+ console->parse_timer = console_parse_timer;
+ console->pthread_main = cThread_main;
+ console->parse = console_parse;
+ console->key_pressed = console_parse_key_pressed;
+#endif
+} \ No newline at end of file
diff --git a/src/common/console.h b/src/common/console.h
new file mode 100644
index 000000000..d0b9e8bb1
--- /dev/null
+++ b/src/common/console.h
@@ -0,0 +1,48 @@
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+
+#ifndef _CONSOLE_H_
+#define _CONSOLE_H_
+
+#include "../common/atomic.h"
+#include "../common/thread.h"
+#include "../common/mutex.h"
+#include "../common/spinlock.h"
+#include "../config/core.h"
+
+/**
+ * Queue Max
+ * why is there a limit, why not make it dynamic? - I'm playing it safe, I'd rather not play with memory management between threads
+ **/
+#define CONSOLE_PARSE_SIZE 10
+struct {
+ char queue[CONSOLE_PARSE_SIZE][MAX_CONSOLE_INPUT];
+ unsigned short count;
+} cinput;
+
+struct console_interface {
+ void (*init) (void);
+ void (*final) (void);
+ void (*display_title) (void);
+#ifdef CONSOLE_INPUT
+ /* vars */
+ SPIN_LOCK ptlock;/* parse thread lock */
+ rAthread pthread;/* parse thread */
+ volatile int32 ptstate;/* parse thread state */
+ ramutex ptmutex;/* parse thread mutex */
+ racond ptcond;/* parse thread cond */
+ /* */
+ void (*parse_init) (void);
+ void (*parse_final) (void);
+ int (*parse_timer) (int tid, unsigned int tick, int id, intptr_t data);
+ void *(*pthread_main) (void *x);
+ void (*parse) (char* line);
+ int (*key_pressed) (void);
+#endif
+} console_s;
+
+struct console_interface *console;
+
+void console_defaults(void);
+
+#endif /* _CONSOLE_H_ */
diff --git a/src/common/core.c b/src/common/core.c
index b004d2b96..da4e4ccf9 100644
--- a/src/common/core.c
+++ b/src/common/core.c
@@ -6,13 +6,17 @@
#include "../common/showmsg.h"
#include "../common/malloc.h"
#include "core.h"
+#include "../common/console.h"
+
#ifndef MINICORE
-#include "../common/db.h"
-#include "../common/socket.h"
-#include "../common/timer.h"
-#include "../common/thread.h"
-#include "../common/mempool.h"
-#include "../common/sql.h"
+ #include "../common/db.h"
+ #include "../common/socket.h"
+ #include "../common/timer.h"
+ #include "../common/thread.h"
+ #include "../common/mempool.h"
+ #include "../common/sql.h"
+ #include "../config/core.h"
+ #include "../common/strlib.h"
#endif
#include <stdio.h>
@@ -25,14 +29,9 @@
#include "../common/winapi.h" // Console close event handling
#endif
-
/// Called when a terminate signal is received.
void (*shutdown_callback)(void) = NULL;
-#if defined(BUILDBOT)
- int buildbotflag = 0;
-#endif
-
int runflag = CORE_ST_RUN;
int arg_c = 0;
char **arg_v = NULL;
@@ -54,8 +53,7 @@ char SERVER_TYPE = ATHENA_SERVER_NONE;
#ifndef POSIX
#define compat_signal(signo, func) signal(signo, func)
#else
-sigfunc *compat_signal(int signo, sigfunc *func)
-{
+sigfunc *compat_signal(int signo, sigfunc *func) {
struct sigaction sact, oact;
sact.sa_handler = func;
@@ -76,26 +74,23 @@ sigfunc *compat_signal(int signo, sigfunc *func)
* CORE : Console events for Windows
*--------------------------------------*/
#ifdef _WIN32
-static BOOL WINAPI console_handler(DWORD c_event)
-{
- switch(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
- break;
- default:
- return FALSE;
+static BOOL WINAPI console_handler(DWORD c_event) {
+ switch(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
+ break;
+ default:
+ return FALSE;
}
return TRUE;
}
-static void cevents_init()
-{
+static void cevents_init() {
if (SetConsoleCtrlHandler(console_handler,TRUE)==FALSE)
ShowWarning ("Unable to install the console handler!\n");
}
@@ -104,42 +99,40 @@ static void cevents_init()
/*======================================
* CORE : Signal Sub Function
*--------------------------------------*/
-static void sig_proc(int sn)
-{
+static void sig_proc(int sn) {
static int is_called = 0;
switch (sn) {
- case SIGINT:
- case SIGTERM:
- if (++is_called > 3)
- exit(EXIT_SUCCESS);
- if( shutdown_callback != NULL )
- shutdown_callback();
- else
- runflag = CORE_ST_STOP;// auto-shutdown
- break;
- case SIGSEGV:
- case SIGFPE:
- do_abort();
- // Pass the signal to the system's default handler
- compat_signal(sn, SIG_DFL);
- raise(sn);
- break;
-#ifndef _WIN32
- case SIGXFSZ:
- // ignore and allow it to set errno to EFBIG
- ShowWarning ("Max file size reached!\n");
- //run_flag = 0; // should we quit?
- break;
- case SIGPIPE:
- //ShowInfo ("Broken pipe found... closing socket\n"); // set to eof in socket.c
- break; // does nothing here
-#endif
+ case SIGINT:
+ case SIGTERM:
+ if (++is_called > 3)
+ exit(EXIT_SUCCESS);
+ if( shutdown_callback != NULL )
+ shutdown_callback();
+ else
+ runflag = CORE_ST_STOP;// auto-shutdown
+ break;
+ case SIGSEGV:
+ case SIGFPE:
+ do_abort();
+ // Pass the signal to the system's default handler
+ compat_signal(sn, SIG_DFL);
+ raise(sn);
+ break;
+ #ifndef _WIN32
+ case SIGXFSZ:
+ // ignore and allow it to set errno to EFBIG
+ ShowWarning ("Max file size reached!\n");
+ //run_flag = 0; // should we quit?
+ break;
+ case SIGPIPE:
+ //ShowInfo ("Broken pipe found... closing socket\n"); // set to eof in socket.c
+ break; // does nothing here
+ #endif
}
}
-void signals_init (void)
-{
+void signals_init (void) {
compat_signal(SIGTERM, sig_proc);
compat_signal(SIGINT, sig_proc);
#ifndef _DEBUG // need unhandled exceptions to debug on Windows
@@ -157,13 +150,11 @@ void signals_init (void)
#endif
#ifdef SVNVERSION
- const char *get_svn_revision(void)
- {
- return EXPAND_AND_QUOTE(SVNVERSION);
- }
+const char *get_svn_revision(void) {
+ return EXPAND_AND_QUOTE(SVNVERSION);
+}
#else// not SVNVERSION
-const char* get_svn_revision(void)
-{
+const char* get_svn_revision(void) {
static char svn_version_buffer[16] = "";
FILE *fp;
@@ -198,12 +189,10 @@ const char* get_svn_revision(void)
fclose(fp);
// parse buffer
- for( i = prefix_len + 1; i + postfix_len <= len; ++i )
- {
+ for( i = prefix_len + 1; i + postfix_len <= len; ++i ) {
if( buffer[i] != postfix[0] || memcmp(buffer + i, postfix, postfix_len) != 0 )
continue; // postfix missmatch
- for( j = i; j > 0; --j )
- {// skip digits
+ for( j = i; j > 0; --j ) {// skip digits
if( !ISDIGIT(buffer[j - 1]) )
break;
}
@@ -220,29 +209,23 @@ const char* get_svn_revision(void)
}
// subversion 1.6 and older?
- if ((fp = fopen(".svn/entries", "r")) != NULL)
- {
+ if ((fp = fopen(".svn/entries", "r")) != NULL) {
char line[1024];
int rev;
// Check the version
- if (fgets(line, sizeof(line), fp))
- {
- if(!ISDIGIT(line[0]))
- {
+ if (fgets(line, sizeof(line), fp)) {
+ if(!ISDIGIT(line[0])) {
// XML File format
while (fgets(line,sizeof(line),fp))
if (strstr(line,"revision=")) break;
if (sscanf(line," %*[^\"]\"%d%*[^\n]", &rev) == 1) {
snprintf(svn_version_buffer, sizeof(svn_version_buffer), "%d", rev);
}
- }
- else
- {
+ } else {
// Bin File format
if ( fgets(line, sizeof(line), fp) == NULL ) { printf("Can't get bin name\n"); } // Get the name
if ( fgets(line, sizeof(line), fp) == NULL ) { printf("Can't get entries kind\n"); } // Get the entries kind
- if(fgets(line, sizeof(line), fp)) // Get the rev numver
- {
+ if(fgets(line, sizeof(line), fp)) { // Get the rev numver
snprintf(svn_version_buffer, sizeof(svn_version_buffer), "%d", atoi(line));
}
}
@@ -287,36 +270,8 @@ const char *get_git_hash (void) {
return HerculesGitHash;
}
-/*======================================
- * CORE : Display title
- * ASCII By CalciumKid 1/12/2011
- *--------------------------------------*/
-static void display_title(void) {
- const char* svn = get_svn_revision();
- const char* git = get_git_hash();
-
- ShowMessage("\n");
- ShowMessage(""CL_BG_RED" "CL_BT_WHITE" "CL_BG_RED""CL_CLL""CL_NORMAL"\n");
- ShowMessage(""CL_BG_RED" "CL_BT_WHITE" Hercules Development Team presents "CL_BG_RED""CL_CLL""CL_NORMAL"\n");
- ShowMessage(""CL_BG_RED" "CL_BT_WHITE" _ _ _ "CL_BG_RED""CL_CLL""CL_NORMAL"\n");
- ShowMessage(""CL_BG_RED" "CL_BT_WHITE" | | | | | | "CL_BG_RED""CL_CLL""CL_NORMAL"\n");
- ShowMessage(""CL_BG_RED" "CL_BT_WHITE" | |_| | ___ _ __ ___ _ _| | ___ ___ "CL_BG_RED""CL_CLL""CL_NORMAL"\n");
- ShowMessage(""CL_BG_RED" "CL_BT_WHITE" | _ |/ _ \\ '__/ __| | | | |/ _ \\/ __|"CL_BG_RED""CL_CLL""CL_NORMAL"\n");
- ShowMessage(""CL_BG_RED" "CL_BT_WHITE" | | | | __/ | | (__| |_| | | __/\\__ \\"CL_BG_RED""CL_CLL""CL_NORMAL"\n");
- ShowMessage(""CL_BG_RED" "CL_BT_WHITE" \\_| |_/\\___|_| \\___|\\__,_|_|\\___||___/"CL_BG_RED""CL_CLL""CL_NORMAL"\n");
- ShowMessage(""CL_BG_RED" "CL_BT_WHITE" "CL_BG_RED""CL_CLL""CL_NORMAL"\n");
- ShowMessage(""CL_BG_RED" "CL_BT_WHITE" http://hercules.ws/board/ "CL_BG_RED""CL_CLL""CL_NORMAL"\n");
- ShowMessage(""CL_BG_RED" "CL_BT_WHITE" "CL_BG_RED""CL_CLL""CL_NORMAL"\n");
-
- if( git[0] != HERC_UNKNOWN_VER )
- ShowInfo("Git Hash: '"CL_WHITE"%s"CL_RESET"'\n", git);
- else if( svn[0] != HERC_UNKNOWN_VER )
- ShowInfo("SVN Revision: '"CL_WHITE"%s"CL_RESET"'\n", svn);
-}
-
// Warning if executed as superuser (root)
-void usercheck(void)
-{
+void usercheck(void) {
#ifndef _WIN32
if (geteuid() == 0) {
ShowWarning ("You are running Hercules with root privileges, it is not necessary.\n");
@@ -340,17 +295,18 @@ int main (int argc, char **argv)
arg_c = argc;
arg_v = argv;
}
-
+ console_defaults();
+
malloc_init();// needed for Show* in display_title() [FlavioJS]
-
+
+ console->display_title();
+
#ifdef MINICORE // minimalist Core
- display_title();
usercheck();
do_init(argc,argv);
do_final();
#else// not MINICORE
set_server_type();
- display_title();
usercheck();
Sql_Init();
@@ -358,12 +314,15 @@ int main (int argc, char **argv)
mempool_init();
db_init();
signals_init();
-
+
#ifdef _WIN32
cevents_init();
#endif
timer_init();
+
+ console->init();
+
socket_init();
do_init(argc,argv);
@@ -376,6 +335,8 @@ int main (int argc, char **argv)
}
}
+ console->final();
+
do_final();
timer_final();
diff --git a/src/common/core.h b/src/common/core.h
index ccdfa6c35..dce8157b1 100644
--- a/src/common/core.h
+++ b/src/common/core.h
@@ -5,6 +5,9 @@
#ifndef _CORE_H_
#define _CORE_H_
+#include "../common/db.h"
+#include "../config/core.h"
+
/* so that developers with --enable-debug can raise signals from any section of the code they'd like */
#ifdef DEBUG
#include <signal.h>
@@ -13,10 +16,6 @@
extern int arg_c;
extern char **arg_v;
-#if defined(BUILDBOT)
- extern int buildbotflag;
-#endif
-
#define HERC_UNKNOWN_VER '\x02'
/// @see E_CORE_ST