Index: src/common/mmo.h
===================================================================
--- src/common/mmo.h (revision 17373)
+++ src/common/mmo.h (working copy)
@@ -8,52 +8,15 @@
#include "../common/db.h"
#include <time.h>
-// server->client protocol version
-// 0 - pre-?
-// 1 - ? - 0x196
-// 2 - ? - 0x78, 0x79
-// 3 - ? - 0x1c8, 0x1c9, 0x1de
-// 4 - ? - 0x1d7, 0x1d8, 0x1d9, 0x1da
-// 5 - 2003-12-18aSakexe+ - 0x1ee, 0x1ef, 0x1f0, ?0x1c4, 0x1c5?
-// 6 - 2004-03-02aSakexe+ - 0x1f4, 0x1f5
-// 7 - 2005-04-11aSakexe+ - 0x229, 0x22a, 0x22b, 0x22c
-// 20061023 - 2006-10-23aSakexe+ - 0x6b, 0x6d
-// 20070521 - 2007-05-21aSakexe+ - 0x283
-// 20070821 - 2007-08-21aSakexe+ - 0x2c5
-// 20070918 - 2007-09-18aSakexe+ - 0x2d7, 0x2d9, 0x2da
-// 20071106 - 2007-11-06aSakexe+ - 0x78, 0x7c, 0x22c
-// 20080102 - 2008-01-02aSakexe+ - 0x2ec, 0x2ed , 0x2ee
-// 20081126 - 2008-11-26aSakexe+ - 0x1a2
-// 20090408 - 2009-04-08aSakexe+ - 0x44a (dont use as it overlaps with RE client packets)
-// 20080827 - 2008-08-27aRagexeRE+ - First RE Client
-// 20081217 - 2008-12-17aRagexeRE+ - 0x6d (Note: This one still use old Char Info Packet Structure)
-// 20081218 - 2008-12-17bRagexeRE+ - 0x6d (Note: From this one client use new Char Info Packet Structure)
-// 20090603 - 2009-06-03aRagexeRE+ - 0x7d7, 0x7d8, 0x7d9, 0x7da
-// 20090617 - 2009-06-17aRagexeRE+ - 0x7d9
-// 20090922 - 2009-09-22aRagexeRE+ - 0x7e5, 0x7e7, 0x7e8, 0x7e9
-// 20091103 - 2009-11-03aRagexeRE+ - 0x7f7, 0x7f8, 0x7f9
-// 20100105 - 2010-01-05aRagexeRE+ - 0x133, 0x800, 0x801
-// 20100126 - 2010-01-26aRagexeRE+ - 0x80e
-// 20100223 - 2010-02-23aRagexeRE+ - 0x80f
-// 20100413 - 2010-04-13aRagexeRE+ - 0x6b
-// 20100629 - 2010-06-29aRagexeRE+ - 0x2d0, 0xaa, 0x2d1, 0x2d2
-// 20100721 - 2010-07-21aRagexeRE+ - 0x6b, 0x6d
-// 20100727 - 2010-07-27aRagexeRE+ - 0x6b, 0x6d
-// 20100803 - 2010-08-03aRagexeRE+ - 0x6b, 0x6d, 0x827, 0x828, 0x829, 0x82a, 0x82b, 0x82c, 0x842, 0x843
-// 20101124 - 2010-11-24aRagexeRE+ - 0x856, 0x857, 0x858
-// 20110111 - 2011-01-11aRagexeRE+ - 0x6b, 0x6d
-// 20110928 - 2011-09-28aRagexeRE+ - 0x6b, 0x6d
-// 20111025 - 2011-10-25aRagexeRE+ - 0x6b, 0x6d
-// 20120307 - 2012-03-07aRagexeRE+ - 0x970
-
#ifndef PACKETVER
- #define PACKETVER 20120410
- //#define PACKETVER 20130320
+ //#define PACKETVER 20120410
+ #define PACKETVER 20130320
//#define PACKETVER 20111116
#endif
//Remove/Comment this line to disable sc_data saving. [Skotlex]
#define ENABLE_SC_SAVING
+
//Remove/Comment this line to disable server-side hot-key saving support [Skotlex]
//Note that newer clients no longer save hotkeys in the registry!
#define HOTKEY_SAVING
Index: src/common/cli.c
===================================================================
--- src/common/cli.c (revision 17373)
+++ src/common/cli.c (working copy)
@@ -53,12 +53,12 @@
*/
void display_versionscreen(bool do_exit)
{
- ShowInfo(CL_WHITE"rAthena SVN version: %s" CL_RESET"\n", get_svn_revision());
- ShowInfo(CL_GREEN"Website/Forum:"CL_RESET"\thttp://rathena.org/\n");
- ShowInfo(CL_GREEN"IRC Channel:"CL_RESET"\tirc://irc.rizon.net/#rathena\n");
- ShowInfo("Open "CL_WHITE"readme.txt"CL_RESET" for more information.\n");
- if (do_exit)
- exit(EXIT_SUCCESS);
+ ShowInfo(CL_WHITE"rAthena SVN version: %s" CL_RESET"\n", get_svn_revision());
+ ShowInfo(CL_GREEN"Website/Forum:"CL_RESET"\thttp://rathena.org/\n");
+ ShowInfo(CL_GREEN"IRC Channel:"CL_RESET"\tirc://irc.rizon.net/#rathena\n");
+ ShowInfo("Open "CL_WHITE"readme.txt"CL_RESET" for more information.\n");
+ if (do_exit)
+ exit(EXIT_SUCCESS);
}
/*
Index: src/common/cli.h
===================================================================
--- src/common/cli.h (revision 17373)
+++ src/common/cli.h (working copy)
@@ -32,6 +32,8 @@
extern char* MSG_CONF_NAME_EN; //all
extern void display_helpscreen(bool exit);
+void display_versionscreen(bool do_exit);
+bool opt_has_next_value(const char* option, int i, int argc);
int cli_get_options(int argc, char ** argv);
int parse_console_timer(int tid, unsigned int tick, int id, intptr_t data);
extern int parse_console(const char* buf); //particular for each serv
Index: src/common/timer.c
===================================================================
--- src/common/timer.c (revision 17373)
+++ src/common/timer.c (working copy)
@@ -109,28 +109,28 @@
} t;
asm volatile("rdtsc":"=a"(t.dw[0]), "=d"(t.dw[1]) );
-
+
return t.qw;
}
static void rdtsc_calibrate(){
uint64 t1, t2;
int32 i;
-
+
ShowStatus("Calibrating Timer Source, please wait... ");
-
+
RDTSC_CLOCK = 0;
-
+
for(i = 0; i < 5; i++){
t1 = _rdtsc();
usleep(1000000); //1000 MS
t2 = _rdtsc();
- RDTSC_CLOCK += (t2 - t1) / 1000;
+ RDTSC_CLOCK += (t2 - t1) / 1000;
}
RDTSC_CLOCK /= 5;
-
+
RDTSC_BEGINTICK = _rdtsc();
-
+
ShowMessage(" done. (Frequency: %u Mhz)\n", (uint32)(RDTSC_CLOCK/1000) );
}
@@ -243,7 +243,7 @@
int add_timer(unsigned int tick, TimerFunc func, int id, intptr_t data)
{
int tid;
-
+
tid = acquire_timer();
timer_data[tid].tick = tick;
timer_data[tid].func = func;
@@ -267,7 +267,7 @@
ShowError("add_timer_interval: invalid interval (tick=%u %p[%s] id=%d data=%d diff_tick=%d)\n", tick, func, search_timer_func_list(func), id, data, DIFF_TICK(tick, gettick()));
return INVALID_TIMER;
}
-
+
tid = acquire_timer();
timer_data[tid].tick = tick;
timer_data[tid].func = func;
@@ -320,7 +320,7 @@
int settick_timer(int tid, unsigned int tick)
{
size_t i;
-
+
// search timer position
ARR_FIND(0, BHEAP_LENGTH(timer_heap), i, BHEAP_DATA(timer_heap)[i] == tid);
if( i == BHEAP_LENGTH(timer_heap) )
@@ -406,6 +406,16 @@
return (unsigned long)difftime(time(NULL), start_time);
}
+//-----------------------------------------------------
+// custom timestamp formatting (from eApp)
+//-----------------------------------------------------
+const char* timestamp2string(char* str, size_t size, time_t timestamp, const char* format)
+{
+ size_t len = strftime(str, size, format, localtime(×tamp));
+ memset(str + len, '\0', size - len);
+ return str;
+}
+
void timer_init(void)
{
#if defined(ENABLE_RDTSC)
Index: src/common/timer.h
===================================================================
--- src/common/timer.h (revision 17373)
+++ src/common/timer.h (working copy)
@@ -5,6 +5,7 @@
#define _TIMER_H_
#include "../common/cbasetypes.h"
+#include <time.h>
#define DIFF_TICK(a,b) ((int)((a)-(b)))
@@ -51,6 +52,9 @@
unsigned long get_uptime(void);
+//transform a timestamp to string
+const char* timestamp2string(char* str, size_t size, time_t timestamp, const char* format);
+
int do_timer(unsigned int tick);
void timer_init(void);
void timer_final(void);
Index: src/config/const.h
===================================================================
--- src/config/const.h (revision 17373)
+++ src/config/const.h (working copy)
@@ -87,6 +87,9 @@
/* Feb 1st 2012 */
#if PACKETVER >= 20120201
#define NEW_CARTS
+ #ifndef ENABLE_SC_SAVING
+ #warning "Cart won't be able to be saved for relog"
+ #endif
#define MAX_CARTS 9
#else
#define MAX_CARTS 5
Index: src/login/account_sql.c
===================================================================
--- src/login/account_sql.c (revision 17373)
+++ src/login/account_sql.c (working copy)
@@ -1,689 +0,0 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
-
-#include "../common/malloc.h"
-#include "../common/mmo.h"
-#include "../common/showmsg.h"
-#include "../common/sql.h"
-#include "../common/strlib.h"
-#include "../common/timer.h"
-#include "account.h"
-#include <stdlib.h>
-#include <string.h>
-
-/// global defines
-#define ACCOUNT_SQL_DB_VERSION 20110114
-
-/// internal structure
-typedef struct AccountDB_SQL
-{
- AccountDB vtable; // public interface
-
- Sql* accounts; // SQL accounts storage
-
- // global sql settings
- char global_db_hostname[32];
- uint16 global_db_port;
- char global_db_username[32];
- char global_db_password[32];
- char global_db_database[32];
- char global_codepage[32];
- // local sql settings
- char db_hostname[32];
- uint16 db_port;
- char db_username[32];
- char db_password[32];
- char db_database[32];
- char codepage[32];
- // other settings
- bool case_sensitive;
- char account_db[32];
- char accreg_db[32];
-
-} AccountDB_SQL;
-
-/// internal structure
-typedef struct AccountDBIterator_SQL
-{
- AccountDBIterator vtable; // public interface
-
- AccountDB_SQL* db;
- int last_account_id;
-} AccountDBIterator_SQL;
-
-/// internal functions
-static bool account_db_sql_init(AccountDB* self);
-static void account_db_sql_destroy(AccountDB* self);
-static bool account_db_sql_get_property(AccountDB* self, const char* key, char* buf, size_t buflen);
-static bool account_db_sql_set_property(AccountDB* self, const char* option, const char* value);
-static bool account_db_sql_create(AccountDB* self, struct mmo_account* acc);
-static bool account_db_sql_remove(AccountDB* self, const int account_id);
-static bool account_db_sql_save(AccountDB* self, const struct mmo_account* acc);
-static bool account_db_sql_load_num(AccountDB* self, struct mmo_account* acc, const int account_id);
-static bool account_db_sql_load_str(AccountDB* self, struct mmo_account* acc, const char* userid);
-static AccountDBIterator* account_db_sql_iterator(AccountDB* self);
-static void account_db_sql_iter_destroy(AccountDBIterator* self);
-static bool account_db_sql_iter_next(AccountDBIterator* self, struct mmo_account* acc);
-
-static bool mmo_auth_fromsql(AccountDB_SQL* db, struct mmo_account* acc, int account_id);
-static bool mmo_auth_tosql(AccountDB_SQL* db, const struct mmo_account* acc, bool is_new);
-
-/// public constructor
-AccountDB* account_db_sql(void)
-{
- AccountDB_SQL* db = (AccountDB_SQL*)aCalloc(1, sizeof(AccountDB_SQL));
-
- // set up the vtable
- db->vtable.init = &account_db_sql_init;
- db->vtable.destroy = &account_db_sql_destroy;
- db->vtable.get_property = &account_db_sql_get_property;
- db->vtable.set_property = &account_db_sql_set_property;
- db->vtable.save = &account_db_sql_save;
- db->vtable.create = &account_db_sql_create;
- db->vtable.remove = &account_db_sql_remove;
- db->vtable.load_num = &account_db_sql_load_num;
- db->vtable.load_str = &account_db_sql_load_str;
- db->vtable.iterator = &account_db_sql_iterator;
-
- // initialize to default values
- db->accounts = NULL;
- // global sql settings
- safestrncpy(db->global_db_hostname, "127.0.0.1", sizeof(db->global_db_hostname));
- db->global_db_port = 3306;
- safestrncpy(db->global_db_username, "ragnarok", sizeof(db->global_db_username));
- safestrncpy(db->global_db_password, "ragnarok", sizeof(db->global_db_password));
- safestrncpy(db->global_db_database, "ragnarok", sizeof(db->global_db_database));
- safestrncpy(db->global_codepage, "", sizeof(db->global_codepage));
- // local sql settings
- safestrncpy(db->db_hostname, "", sizeof(db->db_hostname));
- db->db_port = 3306;
- safestrncpy(db->db_username, "", sizeof(db->db_username));
- safestrncpy(db->db_password, "", sizeof(db->db_password));
- safestrncpy(db->db_database, "", sizeof(db->db_database));
- safestrncpy(db->codepage, "", sizeof(db->codepage));
- // other settings
- db->case_sensitive = false;
- safestrncpy(db->account_db, "login", sizeof(db->account_db));
- safestrncpy(db->accreg_db, "global_reg_value", sizeof(db->accreg_db));
-
- return &db->vtable;
-}
-
-
-/* ------------------------------------------------------------------------- */
-
-
-/// establishes database connection
-static bool account_db_sql_init(AccountDB* self)
-{
- AccountDB_SQL* db = (AccountDB_SQL*)self;
- Sql* sql_handle;
- const char* username;
- const char* password;
- const char* hostname;
- uint16 port;
- const char* database;
- const char* codepage;
-
- db->accounts = Sql_Malloc();
- sql_handle = db->accounts;
-
- if( db->db_hostname[0] != '\0' )
- {// local settings
- username = db->db_username;
- password = db->db_password;
- hostname = db->db_hostname;
- port = db->db_port;
- database = db->db_database;
- codepage = db->codepage;
- }
- else
- {// global settings
- username = db->global_db_username;
- password = db->global_db_password;
- hostname = db->global_db_hostname;
- port = db->global_db_port;
- database = db->global_db_database;
- codepage = db->global_codepage;
- }
-
- if( SQL_ERROR == Sql_Connect(sql_handle, username, password, hostname, port, database) )
- {
- Sql_ShowDebug(sql_handle);
- Sql_Free(db->accounts);
- db->accounts = NULL;
- return false;
- }
-
- if( codepage[0] != '\0' && SQL_ERROR == Sql_SetEncoding(sql_handle, codepage) )
- Sql_ShowDebug(sql_handle);
-
- return true;
-}
-
-/// disconnects from database
-static void account_db_sql_destroy(AccountDB* self)
-{
- AccountDB_SQL* db = (AccountDB_SQL*)self;
-
- Sql_Free(db->accounts);
- db->accounts = NULL;
- aFree(db);
-}
-
-/// Gets a property from this database.
-static bool account_db_sql_get_property(AccountDB* self, const char* key, char* buf, size_t buflen)
-{
- AccountDB_SQL* db = (AccountDB_SQL*)self;
- const char* signature;
-
- signature = "engine.";
- if( strncmpi(key, signature, strlen(signature)) == 0 )
- {
- key += strlen(signature);
- if( strcmpi(key, "name") == 0 )
- safesnprintf(buf, buflen, "sql");
- else
- if( strcmpi(key, "version") == 0 )
- safesnprintf(buf, buflen, "%d", ACCOUNT_SQL_DB_VERSION);
- else
- if( strcmpi(key, "comment") == 0 )
- safesnprintf(buf, buflen, "SQL Account Database");
- else
- return false;// not found
- return true;
- }
-
- signature = "sql.";
- if( strncmpi(key, signature, strlen(signature)) == 0 )
- {
- key += strlen(signature);
- if( strcmpi(key, "db_hostname") == 0 )
- safesnprintf(buf, buflen, "%s", db->global_db_hostname);
- else
- if( strcmpi(key, "db_port") == 0 )
- safesnprintf(buf, buflen, "%d", db->global_db_port);
- else
- if( strcmpi(key, "db_username") == 0 )
- safesnprintf(buf, buflen, "%s", db->global_db_username);
- else
- if( strcmpi(key, "db_password") == 0 )
- safesnprintf(buf, buflen, "%s", db->global_db_password);
- else
- if( strcmpi(key, "db_database") == 0 )
- safesnprintf(buf, buflen, "%s", db->global_db_database);
- else
- if( strcmpi(key, "codepage") == 0 )
- safesnprintf(buf, buflen, "%s", db->global_codepage);
- else
- return false;// not found
- return true;
- }
-
- signature = "account.sql.";
- if( strncmpi(key, signature, strlen(signature)) == 0 )
- {
- key += strlen(signature);
- if( strcmpi(key, "db_hostname") == 0 )
- safesnprintf(buf, buflen, "%s", db->db_hostname);
- else
- if( strcmpi(key, "db_port") == 0 )
- safesnprintf(buf, buflen, "%d", db->db_port);
- else
- if( strcmpi(key, "db_username") == 0 )
- safesnprintf(buf, buflen, "%s", db->db_username);
- else
- if( strcmpi(key, "db_password") == 0 )
- safesnprintf(buf, buflen, "%s", db->db_password);
- else
- if( strcmpi(key, "db_database") == 0 )
- safesnprintf(buf, buflen, "%s", db->db_database);
- else
- if( strcmpi(key, "codepage") == 0 )
- safesnprintf(buf, buflen, "%s", db->codepage);
- else
- if( strcmpi(key, "case_sensitive") == 0 )
- safesnprintf(buf, buflen, "%d", (db->case_sensitive ? 1 : 0));
- else
- if( strcmpi(key, "account_db") == 0 )
- safesnprintf(buf, buflen, "%s", db->account_db);
- else
- if( strcmpi(key, "accreg_db") == 0 )
- safesnprintf(buf, buflen, "%s", db->accreg_db);
- else
- return false;// not found
- return true;
- }
-
- return false;// not found
-}
-
-/// if the option is supported, adjusts the internal state
-static bool account_db_sql_set_property(AccountDB* self, const char* key, const char* value)
-{
- AccountDB_SQL* db = (AccountDB_SQL*)self;
- const char* signature;
-
-
- signature = "sql.";
- if( strncmp(key, signature, strlen(signature)) == 0 )
- {
- key += strlen(signature);
- if( strcmpi(key, "db_hostname") == 0 )
- safestrncpy(db->global_db_hostname, value, sizeof(db->global_db_hostname));
- else
- if( strcmpi(key, "db_port") == 0 )
- db->global_db_port = (uint16)strtoul(value, NULL, 10);
- else
- if( strcmpi(key, "db_username") == 0 )
- safestrncpy(db->global_db_username, value, sizeof(db->global_db_username));
- else
- if( strcmpi(key, "db_password") == 0 )
- safestrncpy(db->global_db_password, value, sizeof(db->global_db_password));
- else
- if( strcmpi(key, "db_database") == 0 )
- safestrncpy(db->global_db_database, value, sizeof(db->global_db_database));
- else
- if( strcmpi(key, "codepage") == 0 )
- safestrncpy(db->global_codepage, value, sizeof(db->global_codepage));
- else
- return false;// not found
- return true;
- }
-
- signature = "account.sql.";
- if( strncmp(key, signature, strlen(signature)) == 0 )
- {
- key += strlen(signature);
- if( strcmpi(key, "db_hostname") == 0 )
- safestrncpy(db->db_hostname, value, sizeof(db->db_hostname));
- else
- if( strcmpi(key, "db_port") == 0 )
- db->db_port = (uint16)strtoul(value, NULL, 10);
- else
- if( strcmpi(key, "db_username") == 0 )
- safestrncpy(db->db_username, value, sizeof(db->db_username));
- else
- if( strcmpi(key, "db_password") == 0 )
- safestrncpy(db->db_password, value, sizeof(db->db_password));
- else
- if( strcmpi(key, "db_database") == 0 )
- safestrncpy(db->db_database, value, sizeof(db->db_database));
- else
- if( strcmpi(key, "codepage") == 0 )
- safestrncpy(db->codepage, value, sizeof(db->codepage));
- else
- if( strcmpi(key, "case_sensitive") == 0 )
- db->case_sensitive = config_switch(value);
- else
- if( strcmpi(key, "account_db") == 0 )
- safestrncpy(db->account_db, value, sizeof(db->account_db));
- else
- if( strcmpi(key, "accreg_db") == 0 )
- safestrncpy(db->accreg_db, value, sizeof(db->accreg_db));
- else
- return false;// not found
- return true;
- }
-
- return false;// not found
-}
-
-/// create a new account entry
-/// If acc->account_id is -1, the account id will be auto-generated,
-/// and its value will be written to acc->account_id if everything succeeds.
-static bool account_db_sql_create(AccountDB* self, struct mmo_account* acc)
-{
- AccountDB_SQL* db = (AccountDB_SQL*)self;
- Sql* sql_handle = db->accounts;
-
- // decide on the account id to assign
- int account_id;
- if( acc->account_id != -1 )
- {// caller specifies it manually
- account_id = acc->account_id;
- }
- else
- {// ask the database
- char* data;
- size_t len;
-
- if( SQL_SUCCESS != Sql_Query(sql_handle, "SELECT MAX(`account_id`)+1 FROM `%s`", db->account_db) )
- {
- Sql_ShowDebug(sql_handle);
- return false;
- }
- if( SQL_SUCCESS != Sql_NextRow(sql_handle) )
- {
- Sql_ShowDebug(sql_handle);
- Sql_FreeResult(sql_handle);
- return false;
- }
-
- Sql_GetData(sql_handle, 0, &data, &len);
- account_id = ( data != NULL ) ? atoi(data) : 0;
- Sql_FreeResult(sql_handle);
-
- if( account_id < START_ACCOUNT_NUM )
- account_id = START_ACCOUNT_NUM;
-
- }
-
- // zero value is prohibited
- if( account_id == 0 )
- return false;
-
- // absolute maximum
- if( account_id > END_ACCOUNT_NUM )
- return false;
-
- // insert the data into the database
- acc->account_id = account_id;
- return mmo_auth_tosql(db, acc, true);
-}
-
-/// delete an existing account entry + its regs
-static bool account_db_sql_remove(AccountDB* self, const int account_id)
-{
- AccountDB_SQL* db = (AccountDB_SQL*)self;
- Sql* sql_handle = db->accounts;
- bool result = false;
-
- if( SQL_SUCCESS != Sql_QueryStr(sql_handle, "START TRANSACTION")
- || SQL_SUCCESS != Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = %d", db->account_db, account_id)
- || SQL_SUCCESS != Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = %d", db->accreg_db, account_id) )
- Sql_ShowDebug(sql_handle);
- else
- result = true;
-
- result &= ( SQL_SUCCESS == Sql_QueryStr(sql_handle, (result == true) ? "COMMIT" : "ROLLBACK") );
-
- return result;
-}
-
-/// update an existing account with the provided new data (both account and regs)
-static bool account_db_sql_save(AccountDB* self, const struct mmo_account* acc)
-{
- AccountDB_SQL* db = (AccountDB_SQL*)self;
- return mmo_auth_tosql(db, acc, false);
-}
-
-/// retrieve data from db and store it in the provided data structure
-static bool account_db_sql_load_num(AccountDB* self, struct mmo_account* acc, const int account_id)
-{
- AccountDB_SQL* db = (AccountDB_SQL*)self;
- return mmo_auth_fromsql(db, acc, account_id);
-}
-
-/// retrieve data from db and store it in the provided data structure
-static bool account_db_sql_load_str(AccountDB* self, struct mmo_account* acc, const char* userid)
-{
- AccountDB_SQL* db = (AccountDB_SQL*)self;
- Sql* sql_handle = db->accounts;
- char esc_userid[2*NAME_LENGTH+1];
- int account_id;
- char* data;
-
- Sql_EscapeString(sql_handle, esc_userid, userid);
-
- // get the list of account IDs for this user ID
- if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id` FROM `%s` WHERE `userid`= %s '%s'",
- db->account_db, (db->case_sensitive ? "BINARY" : ""), esc_userid) )
- {
- Sql_ShowDebug(sql_handle);
- return false;
- }
-
- if( Sql_NumRows(sql_handle) > 1 )
- {// serious problem - duplicit account
- ShowError("account_db_sql_load_str: multiple accounts found when retrieving data for account '%s'!\n", userid);
- Sql_FreeResult(sql_handle);
- return false;
- }
-
- if( SQL_SUCCESS != Sql_NextRow(sql_handle) )
- {// no such entry
- Sql_FreeResult(sql_handle);
- return false;
- }
-
- Sql_GetData(sql_handle, 0, &data, NULL);
- account_id = atoi(data);
-
- return account_db_sql_load_num(self, acc, account_id);
-}
-
-
-/// Returns a new forward iterator.
-static AccountDBIterator* account_db_sql_iterator(AccountDB* self)
-{
- AccountDB_SQL* db = (AccountDB_SQL*)self;
- AccountDBIterator_SQL* iter = (AccountDBIterator_SQL*)aCalloc(1, sizeof(AccountDBIterator_SQL));
-
- // set up the vtable
- iter->vtable.destroy = &account_db_sql_iter_destroy;
- iter->vtable.next = &account_db_sql_iter_next;
-
- // fill data
- iter->db = db;
- iter->last_account_id = -1;
-
- return &iter->vtable;
-}
-
-
-/// Destroys this iterator, releasing all allocated memory (including itself).
-static void account_db_sql_iter_destroy(AccountDBIterator* self)
-{
- AccountDBIterator_SQL* iter = (AccountDBIterator_SQL*)self;
- aFree(iter);
-}
-
-
-/// Fetches the next account in the database.
-static bool account_db_sql_iter_next(AccountDBIterator* self, struct mmo_account* acc)
-{
- AccountDBIterator_SQL* iter = (AccountDBIterator_SQL*)self;
- AccountDB_SQL* db = (AccountDB_SQL*)iter->db;
- Sql* sql_handle = db->accounts;
- char* data;
-
- // get next account ID
- if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id` FROM `%s` WHERE `account_id` > '%d' ORDER BY `account_id` ASC LIMIT 1",
- db->account_db, iter->last_account_id) )
- {
- Sql_ShowDebug(sql_handle);
- return false;
- }
-
- if( SQL_SUCCESS == Sql_NextRow(sql_handle) &&
- SQL_SUCCESS == Sql_GetData(sql_handle, 0, &data, NULL) &&
- data != NULL )
- {// get account data
- int account_id;
- account_id = atoi(data);
- if( mmo_auth_fromsql(db, acc, account_id) )
- {
- iter->last_account_id = account_id;
- Sql_FreeResult(sql_handle);
- return true;
- }
- }
- Sql_FreeResult(sql_handle);
- return false;
-}
-
-
-static bool mmo_auth_fromsql(AccountDB_SQL* db, struct mmo_account* acc, int account_id)
-{
- Sql* sql_handle = db->accounts;
- char* data;
- int i = 0;
-
- // retrieve login entry for the specified account
- if( SQL_ERROR == Sql_Query(sql_handle,
- "SELECT `account_id`,`userid`,`user_pass`,`sex`,`email`,`group_id`,`state`,`unban_time`,`expiration_time`,`logincount`,`lastlogin`,`last_ip`,`birthdate`,`character_slots`,`pincode`, `pincode_change` FROM `%s` WHERE `account_id` = %d",
- db->account_db, account_id )
- ) {
- Sql_ShowDebug(sql_handle);
- return false;
- }
-
- if( SQL_SUCCESS != Sql_NextRow(sql_handle) )
- {// no such entry
- Sql_FreeResult(sql_handle);
- return false;
- }
-
- Sql_GetData(sql_handle, 0, &data, NULL); acc->account_id = atoi(data);
- Sql_GetData(sql_handle, 1, &data, NULL); safestrncpy(acc->userid, data, sizeof(acc->userid));
- Sql_GetData(sql_handle, 2, &data, NULL); safestrncpy(acc->pass, data, sizeof(acc->pass));
- Sql_GetData(sql_handle, 3, &data, NULL); acc->sex = data[0];
- Sql_GetData(sql_handle, 4, &data, NULL); safestrncpy(acc->email, data, sizeof(acc->email));
- Sql_GetData(sql_handle, 5, &data, NULL); acc->group_id = atoi(data);
- Sql_GetData(sql_handle, 6, &data, NULL); acc->state = strtoul(data, NULL, 10);
- Sql_GetData(sql_handle, 7, &data, NULL); acc->unban_time = atol(data);
- Sql_GetData(sql_handle, 8, &data, NULL); acc->expiration_time = atol(data);
- Sql_GetData(sql_handle, 9, &data, NULL); acc->logincount = strtoul(data, NULL, 10);
- Sql_GetData(sql_handle, 10, &data, NULL); safestrncpy(acc->lastlogin, data, sizeof(acc->lastlogin));
- Sql_GetData(sql_handle, 11, &data, NULL); safestrncpy(acc->last_ip, data, sizeof(acc->last_ip));
- Sql_GetData(sql_handle, 12, &data, NULL); safestrncpy(acc->birthdate, data, sizeof(acc->birthdate));
- Sql_GetData(sql_handle, 13, &data, NULL); acc->char_slots = atoi(data);
- Sql_GetData(sql_handle, 14, &data, NULL); safestrncpy(acc->pincode, data, sizeof(acc->pincode));
- Sql_GetData(sql_handle, 15, &data, NULL); acc->pincode_change = atol(data);
-
- Sql_FreeResult(sql_handle);
-
-
- // retrieve account regs for the specified user
- if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `str`,`value` FROM `%s` WHERE `type`='1' AND `account_id`='%d'", db->accreg_db, acc->account_id) )
- {
- Sql_ShowDebug(sql_handle);
- return false;
- }
-
- acc->account_reg2_num = (int)Sql_NumRows(sql_handle);
-
- while( SQL_SUCCESS == Sql_NextRow(sql_handle) )
- {
- char* data;
- Sql_GetData(sql_handle, 0, &data, NULL); safestrncpy(acc->account_reg2[i].str, data, sizeof(acc->account_reg2[i].str));
- Sql_GetData(sql_handle, 1, &data, NULL); safestrncpy(acc->account_reg2[i].value, data, sizeof(acc->account_reg2[i].value));
- ++i;
- }
- Sql_FreeResult(sql_handle);
-
- if( i != acc->account_reg2_num )
- return false;
-
- return true;
-}
-
-static bool mmo_auth_tosql(AccountDB_SQL* db, const struct mmo_account* acc, bool is_new)
-{
- Sql* sql_handle = db->accounts;
- SqlStmt* stmt = SqlStmt_Malloc(sql_handle);
- bool result = false;
- int i;
-
- // try
- do
- {
-
- if( SQL_SUCCESS != Sql_QueryStr(sql_handle, "START TRANSACTION") )
- {
- Sql_ShowDebug(sql_handle);
- break;
- }
-
- if( is_new )
- {// insert into account table
- if( SQL_SUCCESS != SqlStmt_Prepare(stmt,
- "INSERT INTO `%s` (`account_id`, `userid`, `user_pass`, `sex`, `email`, `group_id`, `state`, `unban_time`, `expiration_time`, `logincount`, `lastlogin`, `last_ip`, `birthdate`, `character_slots`, `pincode`, `pincode_change`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
- db->account_db)
- || SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_INT, (void*)&acc->account_id, sizeof(acc->account_id))
- || SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_STRING, (void*)acc->userid, strlen(acc->userid))
- || SQL_SUCCESS != SqlStmt_BindParam(stmt, 2, SQLDT_STRING, (void*)acc->pass, strlen(acc->pass))
- || SQL_SUCCESS != SqlStmt_BindParam(stmt, 3, SQLDT_ENUM, (void*)&acc->sex, sizeof(acc->sex))
- || SQL_SUCCESS != SqlStmt_BindParam(stmt, 4, SQLDT_STRING, (void*)&acc->email, strlen(acc->email))
- || SQL_SUCCESS != SqlStmt_BindParam(stmt, 5, SQLDT_INT, (void*)&acc->group_id, sizeof(acc->group_id))
- || SQL_SUCCESS != SqlStmt_BindParam(stmt, 6, SQLDT_UINT, (void*)&acc->state, sizeof(acc->state))
- || SQL_SUCCESS != SqlStmt_BindParam(stmt, 7, SQLDT_LONG, (void*)&acc->unban_time, sizeof(acc->unban_time))
- || SQL_SUCCESS != SqlStmt_BindParam(stmt, 8, SQLDT_INT, (void*)&acc->expiration_time, sizeof(acc->expiration_time))
- || SQL_SUCCESS != SqlStmt_BindParam(stmt, 9, SQLDT_UINT, (void*)&acc->logincount, sizeof(acc->logincount))
- || SQL_SUCCESS != SqlStmt_BindParam(stmt, 10, SQLDT_STRING, (void*)&acc->lastlogin, strlen(acc->lastlogin))
- || SQL_SUCCESS != SqlStmt_BindParam(stmt, 11, SQLDT_STRING, (void*)&acc->last_ip, strlen(acc->last_ip))
- || SQL_SUCCESS != SqlStmt_BindParam(stmt, 12, SQLDT_STRING, (void*)&acc->birthdate, strlen(acc->birthdate))
- || SQL_SUCCESS != SqlStmt_BindParam(stmt, 13, SQLDT_UCHAR, (void*)&acc->char_slots, sizeof(acc->char_slots))
- || SQL_SUCCESS != SqlStmt_BindParam(stmt, 14, SQLDT_STRING, (void*)&acc->pincode, strlen(acc->pincode))
- || SQL_SUCCESS != SqlStmt_BindParam(stmt, 15, SQLDT_LONG, (void*)&acc->pincode_change, sizeof(acc->pincode_change))
- || SQL_SUCCESS != SqlStmt_Execute(stmt)
- ) {
- SqlStmt_ShowDebug(stmt);
- break;
- }
- }
- else
- {// update account table
- if( SQL_SUCCESS != SqlStmt_Prepare(stmt, "UPDATE `%s` SET `userid`=?,`user_pass`=?,`sex`=?,`email`=?,`group_id`=?,`state`=?,`unban_time`=?,`expiration_time`=?,`logincount`=?,`lastlogin`=?,`last_ip`=?,`birthdate`=?,`character_slots`=?,`pincode`=?, `pincode_change`=? WHERE `account_id` = '%d'", db->account_db, acc->account_id)
- || SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_STRING, (void*)acc->userid, strlen(acc->userid))
- || SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_STRING, (void*)acc->pass, strlen(acc->pass))
- || SQL_SUCCESS != SqlStmt_BindParam(stmt, 2, SQLDT_ENUM, (void*)&acc->sex, sizeof(acc->sex))
- || SQL_SUCCESS != SqlStmt_BindParam(stmt, 3, SQLDT_STRING, (void*)acc->email, strlen(acc->email))
- || SQL_SUCCESS != SqlStmt_BindParam(stmt, 4, SQLDT_INT, (void*)&acc->group_id, sizeof(acc->group_id))
- || SQL_SUCCESS != SqlStmt_BindParam(stmt, 5, SQLDT_UINT, (void*)&acc->state, sizeof(acc->state))
- || SQL_SUCCESS != SqlStmt_BindParam(stmt, 6, SQLDT_LONG, (void*)&acc->unban_time, sizeof(acc->unban_time))
- || SQL_SUCCESS != SqlStmt_BindParam(stmt, 7, SQLDT_LONG, (void*)&acc->expiration_time, sizeof(acc->expiration_time))
- || SQL_SUCCESS != SqlStmt_BindParam(stmt, 8, SQLDT_UINT, (void*)&acc->logincount, sizeof(acc->logincount))
- || SQL_SUCCESS != SqlStmt_BindParam(stmt, 9, SQLDT_STRING, (void*)&acc->lastlogin, strlen(acc->lastlogin))
- || SQL_SUCCESS != SqlStmt_BindParam(stmt, 10, SQLDT_STRING, (void*)&acc->last_ip, strlen(acc->last_ip))
- || SQL_SUCCESS != SqlStmt_BindParam(stmt, 11, SQLDT_STRING, (void*)&acc->birthdate, strlen(acc->birthdate))
- || SQL_SUCCESS != SqlStmt_BindParam(stmt, 12, SQLDT_UCHAR, (void*)&acc->char_slots, sizeof(acc->char_slots))
- || SQL_SUCCESS != SqlStmt_BindParam(stmt, 13, SQLDT_STRING, (void*)&acc->pincode, strlen(acc->pincode))
- || SQL_SUCCESS != SqlStmt_BindParam(stmt, 14, SQLDT_LONG, (void*)&acc->pincode_change, sizeof(acc->pincode_change))
- || SQL_SUCCESS != SqlStmt_Execute(stmt)
- ) {
- SqlStmt_ShowDebug(stmt);
- break;
- }
- }
-
- // remove old account regs
- if( SQL_SUCCESS != Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `type`='1' AND `account_id`='%d'", db->accreg_db, acc->account_id) )
- {
- Sql_ShowDebug(sql_handle);
- break;
- }
- // insert new account regs
- if( SQL_SUCCESS != SqlStmt_Prepare(stmt, "INSERT INTO `%s` (`type`, `account_id`, `str`, `value`) VALUES ( 1 , '%d' , ? , ? );", db->accreg_db, acc->account_id) )
- {
- SqlStmt_ShowDebug(stmt);
- break;
- }
- for( i = 0; i < acc->account_reg2_num; ++i )
- {
- if( SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_STRING, (void*)acc->account_reg2[i].str, strlen(acc->account_reg2[i].str))
- || SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_STRING, (void*)acc->account_reg2[i].value, strlen(acc->account_reg2[i].value))
- || SQL_SUCCESS != SqlStmt_Execute(stmt)
- ) {
- SqlStmt_ShowDebug(stmt);
- break;
- }
- }
- if( i < acc->account_reg2_num )
- {
- result = false;
- break;
- }
-
- // if we got this far, everything was successful
- result = true;
-
- } while(0);
- // finally
-
- result &= ( SQL_SUCCESS == Sql_QueryStr(sql_handle, (result == true) ? "COMMIT" : "ROLLBACK") );
- SqlStmt_Free(stmt);
-
- return result;
-}
Index: src/login/login.h
===================================================================
--- src/login/login.h (revision 17373)
+++ src/login/login.h (working copy)
@@ -6,6 +6,7 @@
#include "../common/mmo.h" // NAME_LENGTH,SEX_*
#include "../common/core.h" // CORE_ST_LAST
+#include "account.h"
enum E_LOGINSERVER_ST
{
@@ -40,8 +41,8 @@
int fd;
};
+#define MAX_SERVERS 30
struct mmo_char_server {
-
char name[20];
int fd;
uint32 ip;
@@ -49,7 +50,7 @@
uint16 users; // user count on this server
uint16 type; // 0=normal, 1=maintenance, 2=over 18, 3=paying, 4=P2P
uint16 new_; // should display as 'new'?
-};
+} server[MAX_SERVERS]; // char server data
struct client_hash_node {
int group_id;
@@ -83,10 +84,15 @@
char dnsbl_servs[1024]; // comma-separated list of dnsbl servers
char account_engine[256]; // name of the engine to use (defaults to auto, for the first available engine)
+ int allowed_regs; //max number of registration
+ int time_allowed; //registration intervall in seconds
int client_hash_check; // flags for checking client md5
struct client_hash_node *client_hash_nodes; // linked list containg md5 hash for each gm group
-};
+ char *loginconf_name;
+ char *msgconf_name;
+ char *lanconf_name;
+} login_config;
#define sex_num2str(num) ( (num == SEX_FEMALE ) ? 'F' : (num == SEX_MALE ) ? 'M' : 'S' )
#define sex_str2num(str) ( (str == 'F' ) ? SEX_FEMALE : (str == 'M' ) ? SEX_MALE : SEX_SERVER )
@@ -94,15 +100,51 @@
#define msg_config_read(cfgName) login_msg_config_read(cfgName)
#define msg_txt(msg_number) login_msg_txt(msg_number)
#define do_final_msg() login_do_final_msg()
-
int login_msg_config_read(char *cfgName);
const char* login_msg_txt(int msg_number);
void login_do_final_msg(void);
+//-----------------------------------------------------
+// Online User Database [Wizputer]
+//-----------------------------------------------------
+struct online_login_data {
+ int account_id;
+ int waiting_disconnect;
+ int char_server;
+};
+DBMap* online_db; // int account_id -> struct online_login_data*
-#define MAX_SERVERS 30
-extern struct mmo_char_server server[MAX_SERVERS];
-extern struct Login_Config login_config;
+//-----------------------------------------------------
+// Auth database
+//-----------------------------------------------------
+#define AUTH_TIMEOUT 30000
+struct auth_node {
+ int account_id;
+ uint32 login_id1;
+ uint32 login_id2;
+ uint32 ip;
+ char sex;
+ uint32 version;
+ uint8 clienttype;
+};
+DBMap* auth_db; // int account_id -> struct auth_node*
+AccountDB* login_get_accounts_db(void);
+
+
+bool check_encrypted(const char* str1, const char* str2, const char* passwd);
+bool check_password(const char* md5key, int passwdenc, const char* passwd, const char* refpass);
+
+int waiting_disconnect_timer(int tid, unsigned int tick, int id, intptr_t data);
+void remove_online_user(int account_id);
+struct online_login_data* add_online_user(int char_server, int account_id);
+int lan_subnetcheck(uint32 ip);
+
+int online_db_setoffline(DBKey key, DBData *data, va_list ap);
+DBData create_online_user(DBKey key, va_list args);
+
+int mmo_auth_new(const char* userid, const char* pass, const char sex, const char* last_ip);
+int mmo_auth(struct login_session_data* sd, bool isServer);
+
#endif /* _LOGIN_H_ */
Index: src/login/sql/CMakeLists.txt
===================================================================
--- src/login/sql/CMakeLists.txt (revision 17373)
+++ src/login/sql/CMakeLists.txt (working copy)
@@ -8,13 +8,19 @@
"${SQL_LOGIN_SOURCE_DIR}/account.h"
"${SQL_LOGIN_SOURCE_DIR}/ipban.h"
"${SQL_LOGIN_SOURCE_DIR}/login.h"
+ "${SQL_LOGIN_SOURCE_DIR}/loginclif.h"
+ "${SQL_LOGIN_SOURCE_DIR}/loginchrif.h"
+ "${SQL_LOGIN_SOURCE_DIR}/logincnslif.h"
"${SQL_LOGIN_SOURCE_DIR}/loginlog.h"
)
set( SQL_LOGIN_SOURCES
- "${SQL_LOGIN_SOURCE_DIR}/account_sql.c"
- "${SQL_LOGIN_SOURCE_DIR}/ipban_sql.c"
+ "${SQL_LOGIN_SOURCE_DIR}/account.c"
+ "${SQL_LOGIN_SOURCE_DIR}/ipban.c"
"${SQL_LOGIN_SOURCE_DIR}/login.c"
- "${SQL_LOGIN_SOURCE_DIR}/loginlog_sql.c"
+ "${SQL_LOGIN_SOURCE_DIR}/loginclif.c"
+ "${SQL_LOGIN_SOURCE_DIR}/loginchrif.c"
+ "${SQL_LOGIN_SOURCE_DIR}/logincnslif.c"
+ "${SQL_LOGIN_SOURCE_DIR}/loginlog.c"
)
set( DEPENDENCIES common_sql )
set( LIBRARIES ${GLOBAL_LIBRARIES} )
Index: src/login/loginlog_sql.c
===================================================================
--- src/login/loginlog_sql.c (revision 17373)
+++ src/login/loginlog_sql.c (working copy)
@@ -1,184 +0,0 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
-
-#include "../common/cbasetypes.h"
-#include "../common/mmo.h"
-#include "../common/socket.h"
-#include "../common/sql.h"
-#include "../common/strlib.h"
-#include <string.h>
-#include <stdlib.h> // exit
-
-// global sql settings (in ipban_sql.c)
-static char global_db_hostname[32] = "127.0.0.1";
-static uint16 global_db_port = 3306;
-static char global_db_username[32] = "ragnarok";
-static char global_db_password[32] = "ragnarok";
-static char global_db_database[32] = "ragnarok";
-static char global_codepage[32] = "";
-// local sql settings
-static char log_db_hostname[32] = "";
-static uint16 log_db_port = 0;
-static char log_db_username[32] = "";
-static char log_db_password[32] = "";
-static char log_db_database[32] = "";
-static char log_codepage[32] = "";
-static char log_login_db[256] = "loginlog";
-
-static Sql* sql_handle = NULL;
-static bool enabled = false;
-
-
-// Returns the number of failed login attemps by the ip in the last minutes.
-unsigned long loginlog_failedattempts(uint32 ip, unsigned int minutes)
-{
- unsigned long failures = 0;
-
- if( !enabled )
- return 0;
-
- if( SQL_ERROR == Sql_Query(sql_handle, "SELECT count(*) FROM `%s` WHERE `ip` = '%s' AND `rcode` = '1' AND `time` > NOW() - INTERVAL %d MINUTE",
- log_login_db, ip2str(ip,NULL), minutes) )// how many times failed account? in one ip.
- Sql_ShowDebug(sql_handle);
-
- if( SQL_SUCCESS == Sql_NextRow(sql_handle) )
- {
- char* data;
- Sql_GetData(sql_handle, 0, &data, NULL);
- failures = strtoul(data, NULL, 10);
- Sql_FreeResult(sql_handle);
- }
- return failures;
-}
-
-
-/*=============================================
- * Records an event in the login log
- *---------------------------------------------*/
-void login_log(uint32 ip, const char* username, int rcode, const char* message)
-{
- char esc_username[NAME_LENGTH*2+1];
- char esc_message[255*2+1];
- int retcode;
-
- if( !enabled )
- return;
-
- Sql_EscapeStringLen(sql_handle, esc_username, username, strnlen(username, NAME_LENGTH));
- Sql_EscapeStringLen(sql_handle, esc_message, message, strnlen(message, 255));
-
- retcode = Sql_Query(sql_handle,
- "INSERT INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%s', '%s', '%d', '%s')",
- log_login_db, ip2str(ip,NULL), esc_username, rcode, esc_message);
-
- if( retcode != SQL_SUCCESS )
- Sql_ShowDebug(sql_handle);
-}
-
-bool loginlog_init(void)
-{
- const char* username;
- const char* password;
- const char* hostname;
- uint16 port;
- const char* database;
- const char* codepage;
-
- if( log_db_hostname[0] != '\0' )
- {// local settings
- username = log_db_username;
- password = log_db_password;
- hostname = log_db_hostname;
- port = log_db_port;
- database = log_db_database;
- codepage = log_codepage;
- }
- else
- {// global settings
- username = global_db_username;
- password = global_db_password;
- hostname = global_db_hostname;
- port = global_db_port;
- database = global_db_database;
- codepage = global_codepage;
- }
-
- sql_handle = Sql_Malloc();
-
- if( SQL_ERROR == Sql_Connect(sql_handle, username, password, hostname, port, database) )
- {
- Sql_ShowDebug(sql_handle);
- Sql_Free(sql_handle);
- exit(EXIT_FAILURE);
- }
-
- if( codepage[0] != '\0' && SQL_ERROR == Sql_SetEncoding(sql_handle, codepage) )
- Sql_ShowDebug(sql_handle);
-
- enabled = true;
-
- return true;
-}
-
-bool loginlog_final(void)
-{
- Sql_Free(sql_handle);
- sql_handle = NULL;
- return true;
-}
-
-bool loginlog_config_read(const char* key, const char* value)
-{
- const char* signature;
-
- signature = "sql.";
- if( strncmpi(key, signature, strlen(signature)) == 0 )
- {
- key += strlen(signature);
- if( strcmpi(key, "db_hostname") == 0 )
- safestrncpy(global_db_hostname, value, sizeof(global_db_hostname));
- else
- if( strcmpi(key, "db_port") == 0 )
- global_db_port = (uint16)strtoul(value, NULL, 10);
- else
- if( strcmpi(key, "db_username") == 0 )
- safestrncpy(global_db_username, value, sizeof(global_db_username));
- else
- if( strcmpi(key, "db_password") == 0 )
- safestrncpy(global_db_password, value, sizeof(global_db_password));
- else
- if( strcmpi(key, "db_database") == 0 )
- safestrncpy(global_db_database, value, sizeof(global_db_database));
- else
- if( strcmpi(key, "codepage") == 0 )
- safestrncpy(global_codepage, value, sizeof(global_codepage));
- else
- return false;// not found
- return true;
- }
-
- if( strcmpi(key, "log_db_ip") == 0 )
- safestrncpy(log_db_hostname, value, sizeof(log_db_hostname));
- else
- if( strcmpi(key, "log_db_port") == 0 )
- log_db_port = (uint16)strtoul(value, NULL, 10);
- else
- if( strcmpi(key, "log_db_id") == 0 )
- safestrncpy(log_db_username, value, sizeof(log_db_username));
- else
- if( strcmpi(key, "log_db_pw") == 0 )
- safestrncpy(log_db_password, value, sizeof(log_db_password));
- else
- if( strcmpi(key, "log_db_db") == 0 )
- safestrncpy(log_db_database, value, sizeof(log_db_database));
- else
- if( strcmpi(key, "log_codepage") == 0 )
- safestrncpy(log_codepage, value, sizeof(log_codepage));
- else
- if( strcmpi(key, "log_login_db") == 0 )
- safestrncpy(log_login_db, value, sizeof(log_login_db));
- else
- return false;
-
- return true;
-}
Index: src/login/ipban.c
===================================================================
--- src/login/ipban.c (working copy)
+++ src/login/ipban.c (working copy)
@@ -100,7 +100,7 @@
if( login_config.ipban_cleanup_interval > 0 )
// release data
delete_timer(cleanup_timer_id, ipban_cleanup);
-
+
ipban_cleanup(0,0,0,0); // always clean up on login-server stop
// close connections
Index: src/login/Makefile.in
===================================================================
--- src/login/Makefile.in (revision 17373)
+++ src/login/Makefile.in (working copy)
@@ -12,10 +12,9 @@
../../3rdparty/libconfig/strbuf.h ../../3rdparty/libconfig/wincompat.h
LIBCONFIG_INCLUDE = -I../../3rdparty/libconfig
-LOGIN_OBJ = login.o
-LOGIN_SQL_OBJ = $(LOGIN_OBJ:%=obj_sql/%) \
- obj_sql/account_sql.o obj_sql/ipban_sql.o obj_sql/loginlog_sql.o
-LOGIN_H = login.h account.h ipban.h loginlog.h
+LOGIN_OBJ = login.o loginclif.o loginchrif.o logincnslif.o account.o ipban.o loginlog.o
+LOGIN_H = login.h loginclif.h loginchrif.h logincnslif.h account.h ipban.h loginlog.h
+LOGIN_SQL_OBJ = $(LOGIN_OBJ:%=obj_sql/%)
HAVE_MYSQL=@HAVE_MYSQL@
ifeq ($(HAVE_MYSQL),yes)
@@ -62,8 +61,8 @@
login-server_sql: obj_sql $(LOGIN_SQL_OBJ) ../common/obj_sql/common_sql.a ../common/obj_all/common.a $(MT19937AR_OBJ)
@echo " LD $@"
@@CC@ @LDFLAGS@ -o ../../login-server_sql@EXEEXT@ $(LOGIN_SQL_OBJ) ../common/obj_sql/common_sql.a ../common/obj_all/common.a $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) @LIBS@ @MYSQL_LIBS@
-
+
# login object files
obj_sql/%.o: %.c $(LOGIN_H) $(COMMON_H) $(MT19937AR_H) $(LIBCONFIG_H)
Index: src/login/ipban_sql.c
===================================================================
--- src/login/ipban_sql.c (revision 17373)
+++ src/login/ipban_sql.c (working copy)
@@ -1,258 +0,0 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
-
-#include "../common/cbasetypes.h"
-#include "../common/db.h"
-#include "../common/malloc.h"
-#include "../common/sql.h"
-#include "../common/socket.h"
-#include "../common/strlib.h"
-#include "../common/timer.h"
-#include "login.h"
-#include "ipban.h"
-#include "loginlog.h"
-#include <stdlib.h>
-#include <string.h>
-
-// global sql settings
-static char global_db_hostname[32] = "127.0.0.1";
-static uint16 global_db_port = 3306;
-static char global_db_username[32] = "ragnarok";
-static char global_db_password[32] = "ragnarok";
-static char global_db_database[32] = "ragnarok";
-static char global_codepage[32] = "";
-// local sql settings
-static char ipban_db_hostname[32] = "";
-static uint16 ipban_db_port = 0;
-static char ipban_db_username[32] = "";
-static char ipban_db_password[32] = "";
-static char ipban_db_database[32] = "";
-static char ipban_codepage[32] = "";
-static char ipban_table[32] = "ipbanlist";
-
-// globals
-static Sql* sql_handle = NULL;
-static int cleanup_timer_id = INVALID_TIMER;
-static bool ipban_inited = false;
-
-int ipban_cleanup(int tid, unsigned int tick, int id, intptr_t data);
-
-
-// initialize
-void ipban_init(void)
-{
- const char* username;
- const char* password;
- const char* hostname;
- uint16 port;
- const char* database;
- const char* codepage;
-
- ipban_inited = true;
-
- if( !login_config.ipban )
- return;// ipban disabled
-
- if( ipban_db_hostname[0] != '\0' )
- {// local settings
- username = ipban_db_username;
- password = ipban_db_password;
- hostname = ipban_db_hostname;
- port = ipban_db_port;
- database = ipban_db_database;
- codepage = ipban_codepage;
- }
- else
- {// global settings
- username = global_db_username;
- password = global_db_password;
- hostname = global_db_hostname;
- port = global_db_port;
- database = global_db_database;
- codepage = global_codepage;
- }
-
- // establish connections
- sql_handle = Sql_Malloc();
- if( SQL_ERROR == Sql_Connect(sql_handle, username, password, hostname, port, database) )
- {
- Sql_ShowDebug(sql_handle);
- Sql_Free(sql_handle);
- exit(EXIT_FAILURE);
- }
- if( codepage[0] != '\0' && SQL_ERROR == Sql_SetEncoding(sql_handle, codepage) )
- Sql_ShowDebug(sql_handle);
-
- if( login_config.ipban_cleanup_interval > 0 )
- { // set up periodic cleanup of connection history and active bans
- add_timer_func_list(ipban_cleanup, "ipban_cleanup");
- cleanup_timer_id = add_timer_interval(gettick()+10, ipban_cleanup, 0, 0, login_config.ipban_cleanup_interval*1000);
- } else // make sure it gets cleaned up on login-server start regardless of interval-based cleanups
- ipban_cleanup(0,0,0,0);
-}
-
-// finalize
-void ipban_final(void)
-{
- if( !login_config.ipban )
- return;// ipban disabled
-
- if( login_config.ipban_cleanup_interval > 0 )
- // release data
- delete_timer(cleanup_timer_id, ipban_cleanup);
-
- ipban_cleanup(0,0,0,0); // always clean up on login-server stop
-
- // close connections
- Sql_Free(sql_handle);
- sql_handle = NULL;
-}
-
-// load configuration options
-bool ipban_config_read(const char* key, const char* value)
-{
- const char* signature;
-
- if( ipban_inited )
- return false;// settings can only be changed before init
-
- signature = "sql.";
- if( strncmpi(key, signature, strlen(signature)) == 0 )
- {
- key += strlen(signature);
- if( strcmpi(key, "db_hostname") == 0 )
- safestrncpy(global_db_hostname, value, sizeof(global_db_hostname));
- else
- if( strcmpi(key, "db_port") == 0 )
- global_db_port = (uint16)strtoul(value, NULL, 10);
- else
- if( strcmpi(key, "db_username") == 0 )
- safestrncpy(global_db_username, value, sizeof(global_db_username));
- else
- if( strcmpi(key, "db_password") == 0 )
- safestrncpy(global_db_password, value, sizeof(global_db_password));
- else
- if( strcmpi(key, "db_database") == 0 )
- safestrncpy(global_db_database, value, sizeof(global_db_database));
- else
- if( strcmpi(key, "codepage") == 0 )
- safestrncpy(global_codepage, value, sizeof(global_codepage));
- else
- return false;// not found
- return true;
- }
-
- signature = "ipban.sql.";
- if( strncmpi(key, signature, strlen(signature)) == 0 )
- {
- key += strlen(signature);
- if( strcmpi(key, "db_hostname") == 0 )
- safestrncpy(ipban_db_hostname, value, sizeof(ipban_db_hostname));
- else
- if( strcmpi(key, "db_port") == 0 )
- ipban_db_port = (uint16)strtoul(value, NULL, 10);
- else
- if( strcmpi(key, "db_username") == 0 )
- safestrncpy(ipban_db_username, value, sizeof(ipban_db_username));
- else
- if( strcmpi(key, "db_password") == 0 )
- safestrncpy(ipban_db_password, value, sizeof(ipban_db_password));
- else
- if( strcmpi(key, "db_database") == 0 )
- safestrncpy(ipban_db_database, value, sizeof(ipban_db_database));
- else
- if( strcmpi(key, "codepage") == 0 )
- safestrncpy(ipban_codepage, value, sizeof(ipban_codepage));
- else
- if( strcmpi(key, "ipban_table") == 0 )
- safestrncpy(ipban_table, value, sizeof(ipban_table));
- else
- return false;// not found
- return true;
- }
-
- signature = "ipban.";
- if( strncmpi(key, signature, strlen(signature)) == 0 )
- {
- key += strlen(signature);
- if( strcmpi(key, "enable") == 0 )
- login_config.ipban = (bool)config_switch(value);
- else
- if( strcmpi(key, "dynamic_pass_failure_ban") == 0 )
- login_config.dynamic_pass_failure_ban = (bool)config_switch(value);
- else
- if( strcmpi(key, "dynamic_pass_failure_ban_interval") == 0 )
- login_config.dynamic_pass_failure_ban_interval = atoi(value);
- else
- if( strcmpi(key, "dynamic_pass_failure_ban_limit") == 0 )
- login_config.dynamic_pass_failure_ban_limit = atoi(value);
- else
- if( strcmpi(key, "dynamic_pass_failure_ban_duration") == 0 )
- login_config.dynamic_pass_failure_ban_duration = atoi(value);
- else
- return false;// not found
- return true;
- }
-
- return false;// not found
-}
-
-// check ip against active bans list
-bool ipban_check(uint32 ip)
-{
- uint8* p = (uint8*)&ip;
- char* data = NULL;
- int matches;
-
- if( !login_config.ipban )
- return false;// ipban disabled
-
- if( SQL_ERROR == Sql_Query(sql_handle, "SELECT count(*) FROM `%s` WHERE `rtime` > NOW() AND (`list` = '%u.*.*.*' OR `list` = '%u.%u.*.*' OR `list` = '%u.%u.%u.*' OR `list` = '%u.%u.%u.%u')",
- ipban_table, p[3], p[3], p[2], p[3], p[2], p[1], p[3], p[2], p[1], p[0]) )
- {
- Sql_ShowDebug(sql_handle);
- // close connection because we can't verify their connectivity.
- return true;
- }
-
- if( SQL_ERROR == Sql_NextRow(sql_handle) )
- return true;// Shouldn't happen, but just in case...
-
- Sql_GetData(sql_handle, 0, &data, NULL);
- matches = atoi(data);
- Sql_FreeResult(sql_handle);
-
- return( matches > 0 );
-}
-
-// log failed attempt
-void ipban_log(uint32 ip)
-{
- unsigned long failures;
-
- if( !login_config.ipban )
- return;// ipban disabled
-
- failures = loginlog_failedattempts(ip, login_config.dynamic_pass_failure_ban_interval);// how many times failed account? in one ip.
-
- // if over the limit, add a temporary ban entry
- if( failures >= login_config.dynamic_pass_failure_ban_limit )
- {
- uint8* p = (uint8*)&ip;
- if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s`(`list`,`btime`,`rtime`,`reason`) VALUES ('%u.%u.%u.*', NOW() , NOW() + INTERVAL %d MINUTE ,'Password error ban')",
- ipban_table, p[3], p[2], p[1], login_config.dynamic_pass_failure_ban_duration) )
- Sql_ShowDebug(sql_handle);
- }
-}
-
-// remove expired bans
-int ipban_cleanup(int tid, unsigned int tick, int id, intptr_t data)
-{
- if( !login_config.ipban )
- return 0;// ipban disabled
-
- if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `ipbanlist` WHERE `rtime` <= NOW()") )
- Sql_ShowDebug(sql_handle);
-
- return 0;
-}
Index: src/login/login.c
===================================================================
--- src/login/login.c (revision 17373)
+++ src/login/login.c (working copy)
@@ -7,16 +7,18 @@
#include "../common/md5calc.h"
#include "../common/random.h"
#include "../common/showmsg.h"
-#include "../common/socket.h"
+#include "../common/socket.h" //ip2str
#include "../common/strlib.h"
#include "../common/timer.h"
#include "../common/msg_conf.h"
-#include "../common/cli.h"
-#include "../common/ers.h"
+#include "../common/utils.h"
#include "account.h"
#include "ipban.h"
#include "login.h"
#include "loginlog.h"
+#include "loginclif.h"
+#include "loginchrif.h"
+#include "logincnslif.h"
#include <stdio.h>
#include <stdlib.h>
@@ -24,11 +26,6 @@
#define LOGIN_MAX_MSG 30
static char* msg_table[LOGIN_MAX_MSG]; // Login Server messages_conf
-struct Login_Config login_config;
-
-int login_fd; // login server socket
-struct mmo_char_server server[MAX_SERVERS]; // char server data
-
// Account engines available
static struct{
AccountDB* (*constructor)(void);
@@ -53,60 +50,25 @@
// end of structure
{NULL, NULL}
};
-// account database
-AccountDB* accounts = NULL;
-
-//Account registration flood protection [Kevin]
-int allowed_regs = 1;
-int time_allowed = 10; //in seconds
-
+AccountDB* accounts = NULL; // account database«
// Advanced subnet check [LuzZza]
struct s_subnet {
uint32 mask;
uint32 char_ip;
uint32 map_ip;
} subnet[16];
-
int subnet_count = 0;
-int mmo_auth_new(const char* userid, const char* pass, const char sex, const char* last_ip);
+int login_fd; // login server socket
-//-----------------------------------------------------
-// Auth database
-//-----------------------------------------------------
-#define AUTH_TIMEOUT 30000
+AccountDB* login_get_accounts_db(void){
+ return accounts;
+}
-struct auth_node {
-
- int account_id;
- uint32 login_id1;
- uint32 login_id2;
- uint32 ip;
- char sex;
- uint32 version;
- uint8 clienttype;
-};
-
-static DBMap* auth_db; // int account_id -> struct auth_node*
-
-
-//-----------------------------------------------------
-// Online User Database [Wizputer]
-//-----------------------------------------------------
-struct online_login_data {
-
- int account_id;
- int waiting_disconnect;
- int char_server;
-};
-
-static DBMap* online_db; // int account_id -> struct online_login_data*
-static int waiting_disconnect_timer(int tid, unsigned int tick, int id, intptr_t data);
-
/**
* @see DBCreateData
*/
-static DBData create_online_user(DBKey key, va_list args)
+DBData create_online_user(DBKey key, va_list args)
{
struct online_login_data* p;
CREATE(p, struct online_login_data, 1);
@@ -141,7 +103,7 @@
idb_remove(online_db, account_id);
}
-static int waiting_disconnect_timer(int tid, unsigned int tick, int id, intptr_t data)
+int waiting_disconnect_timer(int tid, unsigned int tick, int id, intptr_t data)
{
struct online_login_data* p = (struct online_login_data*)idb_get(online_db, id);
if( p != NULL && p->waiting_disconnect == tid && p->account_id == id )
@@ -154,9 +116,9 @@
}
/**
- * @see DBApply
+ * Mark a char offline
*/
-static int online_db_setoffline(DBKey key, DBData *data, va_list ap)
+int online_db_setoffline(DBKey key, DBData *data, va_list ap)
{
struct online_login_data* p = db_data2ptr(data);
int server = va_arg(ap, int);
@@ -192,766 +154,7 @@
}
-//--------------------------------------------------------------------
-// Packet send to all char-servers, except one (wos: without our self)
-//--------------------------------------------------------------------
-int charif_sendallwos(int sfd, uint8* buf, size_t len)
-{
- int i, c;
- for( i = 0, c = 0; i < ARRAYLENGTH(server); ++i )
- {
- int fd = server[i].fd;
- if( session_isValid(fd) && fd != sfd )
- {
- WFIFOHEAD(fd,len);
- memcpy(WFIFOP(fd,0), buf, len);
- WFIFOSET(fd,len);
- ++c;
- }
- }
-
- return c;
-}
-
-
-/// Initializes a server structure.
-void chrif_server_init(int id)
-{
- memset(&server[id], 0, sizeof(server[id]));
- server[id].fd = -1;
-}
-
-
-/// Destroys a server structure.
-void chrif_server_destroy(int id)
-{
- if( server[id].fd != -1 )
- {
- do_close(server[id].fd);
- server[id].fd = -1;
- }
-}
-
-
-/// Resets all the data related to a server.
-void chrif_server_reset(int id)
-{
- online_db->foreach(online_db, online_db_setoffline, id); //Set all chars from this char server to offline.
- chrif_server_destroy(id);
- chrif_server_init(id);
-}
-
-
-/// Called when the connection to Char Server is disconnected.
-void chrif_on_disconnect(int id)
-{
- ShowStatus("Char-server '%s' has disconnected.\n", server[id].name);
- chrif_server_reset(id);
-}
-
-
-//-----------------------------------------------------
-// periodic ip address synchronization
-//-----------------------------------------------------
-static int sync_ip_addresses(int tid, unsigned int tick, int id, intptr_t data)
-{
- uint8 buf[2];
- ShowInfo("IP Sync in progress...\n");
- WBUFW(buf,0) = 0x2735;
- charif_sendallwos(-1, buf, 2);
- return 0;
-}
-
-
-//-----------------------------------------------------
-// encrypted/unencrypted password check (from eApp)
-//-----------------------------------------------------
-bool check_encrypted(const char* str1, const char* str2, const char* passwd)
-{
- char tmpstr[64+1], md5str[32+1];
-
- safesnprintf(tmpstr, sizeof(tmpstr), "%s%s", str1, str2);
- MD5_String(tmpstr, md5str);
-
- return (0==strcmp(passwd, md5str));
-}
-
-bool check_password(const char* md5key, int passwdenc, const char* passwd, const char* refpass)
-{
- if(passwdenc == 0)
- {
- return (0==strcmp(passwd, refpass));
- }
- else
- {
- // password mode set to 1 -> md5(md5key, refpass) enable with <passwordencrypt></passwordencrypt>
- // password mode set to 2 -> md5(refpass, md5key) enable with <passwordencrypt2></passwordencrypt2>
-
- return ((passwdenc&0x01) && check_encrypted(md5key, refpass, passwd)) ||
- ((passwdenc&0x02) && check_encrypted(refpass, md5key, passwd));
- }
-}
-
-
-//-----------------------------------------------------
-// custom timestamp formatting (from eApp)
-//-----------------------------------------------------
-const char* timestamp2string(char* str, size_t size, time_t timestamp, const char* format)
-{
- size_t len = strftime(str, size, format, localtime(×tamp));
- memset(str + len, '\0', size - len);
- return str;
-}
-
-
-//--------------------------------------------
-// Test to know if an IP come from LAN or WAN.
-//--------------------------------------------
-int lan_subnetcheck(uint32 ip)
-{
- int i;
- ARR_FIND( 0, subnet_count, i, (subnet[i].char_ip & subnet[i].mask) == (ip & subnet[i].mask) );
- return ( i < subnet_count ) ? subnet[i].char_ip : 0;
-}
-
-//----------------------------------
-// Reading Lan Support configuration
-//----------------------------------
-int login_lan_config_read(const char *lancfgName)
-{
- FILE *fp;
- int line_num = 0;
- char line[1024], w1[64], w2[64], w3[64], w4[64];
-
- if((fp = fopen(lancfgName, "r")) == NULL) {
- ShowWarning("LAN Support configuration file is not found: %s\n", lancfgName);
- return 1;
- }
-
- while(fgets(line, sizeof(line), fp))
- {
- line_num++;
- if ((line[0] == '/' && line[1] == '/') || line[0] == '\n' || line[1] == '\n')
- continue;
-
- if(sscanf(line,"%[^:]: %[^:]:%[^:]:%[^\r\n]", w1, w2, w3, w4) != 4)
- {
- ShowWarning("Error syntax of configuration file %s in line %d.\n", lancfgName, line_num);
- continue;
- }
-
- if( strcmpi(w1, "subnet") == 0 )
- {
- subnet[subnet_count].mask = str2ip(w2);
- subnet[subnet_count].char_ip = str2ip(w3);
- subnet[subnet_count].map_ip = str2ip(w4);
-
- if( (subnet[subnet_count].char_ip & subnet[subnet_count].mask) != (subnet[subnet_count].map_ip & subnet[subnet_count].mask) )
- {
- ShowError("%s: Configuration Error: The char server (%s) and map server (%s) belong to different subnetworks!\n", lancfgName, w3, w4);
- continue;
- }
-
- subnet_count++;
- }
- }
-
- if( subnet_count > 1 ) /* only useful if there is more than 1 available */
- ShowStatus("Read information about %d subnetworks.\n", subnet_count);
-
- fclose(fp);
- return 0;
-}
-
-//-----------------------
-// Console Command Parser [Wizputer]
-//-----------------------
-int parse_console(const char* buf){
- char type[64];
- char command[64];
- int n=0;
-
- if( ( n = sscanf(buf, "%127[^:]:%255[^\n\r]", type, command) ) < 2 ){
- if((n = sscanf(buf, "%63[^\n]", type))<1) return -1; //nothing to do no arg
- }
- if( n != 2 ){ //end string
- ShowNotice("Type: '%s'\n",type);
- command[0] = '\0';
- }
- else
- ShowNotice("Type of command: '%s' || Command: '%s'\n",type,command);
-
- if( n == 2 ){
- if(strcmpi("server", type) == 0 ){
- if( strcmpi("shutdown", command) == 0 || strcmpi("exit", command) == 0 || strcmpi("quit", command) == 0 ){
- runflag = 0;
- }
- else if( strcmpi("alive", command) == 0 || strcmpi("status", command) == 0 )
- ShowInfo(CL_CYAN"Console: "CL_BOLD"I'm Alive."CL_RESET"\n");
- }
- if( strcmpi("create",type) == 0 )
- {
- char username[NAME_LENGTH], password[NAME_LENGTH], md5password[32+1], sex; //23+1 plaintext 32+1 md5
- bool md5 = 0;
- if( sscanf(command, "%23s %23s %c", username, password, &sex) < 3 || strnlen(username, sizeof(username)) < 4 || strnlen(password, sizeof(password)) < 1 ){
- ShowWarning("Console: Invalid parameters for '%s'. Usage: %s <username> <password> <sex:F/M>\n", type, type);
- return 0;
- }
- if( login_config.use_md5_passwds ){
- MD5_String(password,md5password);
- md5 = 1;
- }
- if( mmo_auth_new(username,(md5?md5password:password), TOUPPER(sex), "0.0.0.0") != -1 ){
- ShowError("Console: Account creation failed.\n");
- return 0;
- }
- ShowStatus("Console: Account '%s' created successfully.\n", username);
- }
- }
- else if( strcmpi("ers_report", type) == 0 ){
- ers_report();
- }
- else if( strcmpi("help", type) == 0 ){
- ShowInfo("Available commands:\n");
- ShowInfo("\t server:shutdown => Stops the server.\n");
- ShowInfo("\t server:alive => Checks if the server is running.\n");
- ShowInfo("\t ers_report => Displays database usage.\n");
- ShowInfo("\t create:<username> <password> <sex:M|F> => Creates a new account.\n");
- }
- else{ // commands with parameters
-
-
-
- }
-
- return 0;
-}
-
-
-//--------------------------------
-// Packet parsing for char-servers
-//--------------------------------
-int parse_fromchar(int fd){
- int j, id;
- uint32 ipl;
- char ip[16];
-
- ARR_FIND( 0, ARRAYLENGTH(server), id, server[id].fd == fd );
- if( id == ARRAYLENGTH(server) ){// not a char server
- ShowDebug("parse_fromchar: Disconnecting invalid session #%d (is not a char-server)\n", fd);
- set_eof(fd);
- do_close(fd);
- return 0;
- }
-
- if( session[fd]->flag.eof ){
- do_close(fd);
- server[id].fd = -1;
- chrif_on_disconnect(id);
- return 0;
- }
-
- ipl = server[id].ip;
- ip2str(ipl, ip);
-
- while( RFIFOREST(fd) >= 2 ){
- uint16 command = RFIFOW(fd,0);
-
- switch( command ){
-
- case 0x2712: // request from char-server to authenticate an account
- if( RFIFOREST(fd) < 23 )
- return 0;
- else{
- struct auth_node* node;
- int account_id = RFIFOL(fd,2);
- uint32 login_id1 = RFIFOL(fd,6);
- uint32 login_id2 = RFIFOL(fd,10);
- uint8 sex = RFIFOB(fd,14);
- //uint32 ip_ = ntohl(RFIFOL(fd,15));
- int request_id = RFIFOL(fd,19);
- RFIFOSKIP(fd,23);
-
- node = (struct auth_node*)idb_get(auth_db, account_id);
- if( runflag == LOGINSERVER_ST_RUNNING &&
- node != NULL &&
- node->account_id == account_id &&
- node->login_id1 == login_id1 &&
- node->login_id2 == login_id2 &&
- node->sex == sex_num2str(sex) /*&&
- node->ip == ip_*/ ){// found
- //ShowStatus("Char-server '%s': authentication of the account %d accepted (ip: %s).\n", server[id].name, account_id, ip);
-
- // send ack
- WFIFOHEAD(fd,25);
- WFIFOW(fd,0) = 0x2713;
- WFIFOL(fd,2) = account_id;
- WFIFOL(fd,6) = login_id1;
- WFIFOL(fd,10) = login_id2;
- WFIFOB(fd,14) = sex;
- WFIFOB(fd,15) = 0;// ok
- WFIFOL(fd,16) = request_id;
- WFIFOL(fd,20) = node->version;
- WFIFOB(fd,24) = node->clienttype;
- WFIFOSET(fd,25);
-
- // each auth entry can only be used once
- idb_remove(auth_db, account_id);
- }else{// authentication not found
- ShowStatus("Char-server '%s': authentication of the account %d REFUSED (ip: %s).\n", server[id].name, account_id, ip);
- WFIFOHEAD(fd,25);
- WFIFOW(fd,0) = 0x2713;
- WFIFOL(fd,2) = account_id;
- WFIFOL(fd,6) = login_id1;
- WFIFOL(fd,10) = login_id2;
- WFIFOB(fd,14) = sex;
- WFIFOB(fd,15) = 1;// auth failed
- WFIFOL(fd,16) = request_id;
- WFIFOL(fd,20) = 0;
- WFIFOB(fd,24) = 0;
- WFIFOSET(fd,25);
- }
- }
- break;
-
- case 0x2714:
- if( RFIFOREST(fd) < 6 )
- return 0;
- else{
- int users = RFIFOL(fd,2);
- RFIFOSKIP(fd,6);
-
- // how many users on world? (update)
- if( server[id].users != users ){
- ShowStatus("set users %s : %d\n", server[id].name, users);
-
- server[id].users = users;
- }
- }
- break;
-
- case 0x2715: // request from char server to change e-email from default "[email protected]"
- if (RFIFOREST(fd) < 46)
- return 0;
- else{
- struct mmo_account acc;
- char email[40];
-
- int account_id = RFIFOL(fd,2);
- safestrncpy(email, (char*)RFIFOP(fd,6), 40); remove_control_chars(email);
- RFIFOSKIP(fd,46);
-
- if( e_mail_check(email) == 0 )
- ShowNotice("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, account_id, ip);
- else if( !accounts->load_num(accounts, &acc, account_id) || strcmp(acc.email, "[email protected]") == 0 || acc.email[0] == '\0' )
- ShowNotice("Char-server '%s': Attempt to create an e-mail on an account with a default e-mail REFUSED - account doesn't exist or e-mail of account isn't default e-mail (account: %d, ip: %s).\n", server[id].name, account_id, ip);
- else{
- memcpy(acc.email, email, 40);
- ShowNotice("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, account_id, email, ip);
- // Save
- accounts->save(accounts, &acc);
- }
- }
- break;
-
- case 0x2716: // request account data
- if( RFIFOREST(fd) < 6 )
- return 0;
- else{
- struct mmo_account acc;
- time_t expiration_time = 0;
- char email[40] = "";
- uint8 char_slots = 0;
- int group_id = 0;
- char birthdate[10+1] = "";
- char pincode[PINCODE_LENGTH+1];
- int account_id = RFIFOL(fd,2);
-
- memset(pincode,0,PINCODE_LENGTH+1);
-
- RFIFOSKIP(fd,6);
-
- if( !accounts->load_num(accounts, &acc, account_id) )
- ShowNotice("Char-server '%s': account %d NOT found (ip: %s).\n", server[id].name, account_id, ip);
- else{
- safestrncpy(email, acc.email, sizeof(email));
- expiration_time = acc.expiration_time;
- group_id = acc.group_id;
- char_slots = acc.char_slots;
- safestrncpy(birthdate, acc.birthdate, sizeof(birthdate));
- safestrncpy(pincode, acc.pincode, sizeof(pincode));
- }
-
- WFIFOHEAD(fd,72);
- WFIFOW(fd,0) = 0x2717;
- WFIFOL(fd,2) = account_id;
- safestrncpy((char*)WFIFOP(fd,6), email, 40);
- WFIFOL(fd,46) = (uint32)expiration_time;
- WFIFOB(fd,50) = (unsigned char)group_id;
- WFIFOB(fd,51) = char_slots;
- safestrncpy((char*)WFIFOP(fd,52), birthdate, 10+1);
- safestrncpy((char*)WFIFOP(fd,63), pincode, 4+1 );
- WFIFOL(fd,68) = (uint32)acc.pincode_change;
- WFIFOSET(fd,72);
- }
- break;
-
- case 0x2719: // ping request from charserver
- RFIFOSKIP(fd,2);
-
- WFIFOHEAD(fd,2);
- WFIFOW(fd,0) = 0x2718;
- WFIFOSET(fd,2);
- break;
-
- // Map server send information to change an email of an account via char-server
- case 0x2722: // 0x2722 <account_id>.L <actual_e-mail>.40B <new_e-mail>.40B
- if (RFIFOREST(fd) < 86)
- return 0;
- else{
- struct mmo_account acc;
- char actual_email[40];
- char new_email[40];
-
- int account_id = RFIFOL(fd,2);
- safestrncpy(actual_email, (char*)RFIFOP(fd,6), 40);
- safestrncpy(new_email, (char*)RFIFOP(fd,46), 40);
- RFIFOSKIP(fd, 86);
-
- if( e_mail_check(actual_email) == 0 )
- ShowNotice("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, account_id, ip);
- else if( e_mail_check(new_email) == 0 )
- ShowNotice("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, account_id, ip);
- else if( strcmpi(new_email, "[email protected]") == 0 )
- ShowNotice("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, account_id, ip);
- else if( !accounts->load_num(accounts, &acc, account_id) )
- ShowNotice("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but account doesn't exist (account: %d, ip: %s).\n", server[id].name, account_id, ip);
- else if( strcmpi(acc.email, actual_email) != 0 )
- ShowNotice("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but actual e-mail is incorrect (account: %d (%s), actual e-mail: %s, proposed e-mail: %s, ip: %s).\n", server[id].name, account_id, acc.userid, acc.email, actual_email, ip);
- else{
- safestrncpy(acc.email, new_email, 40);
- ShowNotice("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, account_id, acc.userid, new_email, ip);
- // Save
- accounts->save(accounts, &acc);
- }
- }
- break;
-
- case 0x2724: // Receiving an account state update request from a map-server (relayed via char-server)
- if (RFIFOREST(fd) < 10)
- return 0;
- else{
- struct mmo_account acc;
-
- int account_id = RFIFOL(fd,2);
- unsigned int state = RFIFOL(fd,6);
- RFIFOSKIP(fd,10);
-
- if( !accounts->load_num(accounts, &acc, account_id) )
- ShowNotice("Char-server '%s': Error of Status change (account: %d not found, suggested status %d, ip: %s).\n", server[id].name, account_id, state, ip);
- else if( acc.state == state )
- ShowNotice("Char-server '%s': Error of Status change - actual status is already the good status (account: %d, status %d, ip: %s).\n", server[id].name, account_id, state, ip);
- else{
- ShowNotice("Char-server '%s': Status change (account: %d, new status %d, ip: %s).\n", server[id].name, account_id, state, ip);
-
- acc.state = state;
- // Save
- accounts->save(accounts, &acc);
-
- // notify other servers
- if (state != 0){
- uint8 buf[11];
- WBUFW(buf,0) = 0x2731;
- WBUFL(buf,2) = account_id;
- WBUFB(buf,6) = 0; // 0: change of state, 1: ban
- WBUFL(buf,7) = state; // status or final date of a banishment
- charif_sendallwos(-1, buf, 11);
- }
- }
- }
- break;
-
- case 0x2725: // Receiving of map-server via char-server a ban request
- if (RFIFOREST(fd) < 18)
- return 0;
- else{
- struct mmo_account acc;
-
- int account_id = RFIFOL(fd,2);
- int year = (short)RFIFOW(fd,6);
- int month = (short)RFIFOW(fd,8);
- int mday = (short)RFIFOW(fd,10);
- int hour = (short)RFIFOW(fd,12);
- int min = (short)RFIFOW(fd,14);
- int sec = (short)RFIFOW(fd,16);
- RFIFOSKIP(fd,18);
-
- if( !accounts->load_num(accounts, &acc, account_id) )
- ShowNotice("Char-server '%s': Error of ban request (account: %d not found, ip: %s).\n", server[id].name, account_id, ip);
- else{
- time_t timestamp;
- struct tm *tmtime;
- if (acc.unban_time == 0 || acc.unban_time < time(NULL))
- timestamp = time(NULL); // new ban
- else
- timestamp = acc.unban_time; // add to existing ban
- tmtime = localtime(×tamp);
- tmtime->tm_year = tmtime->tm_year + year;
- tmtime->tm_mon = tmtime->tm_mon + month;
- tmtime->tm_mday = tmtime->tm_mday + mday;
- tmtime->tm_hour = tmtime->tm_hour + hour;
- tmtime->tm_min = tmtime->tm_min + min;
- tmtime->tm_sec = tmtime->tm_sec + sec;
- timestamp = mktime(tmtime);
- if (timestamp == -1)
- ShowNotice("Char-server '%s': Error of ban request (account: %d, invalid date, ip: %s).\n", server[id].name, account_id, ip);
- else if( timestamp <= time(NULL) || timestamp == 0 )
- ShowNotice("Char-server '%s': Error of ban request (account: %d, new date unbans the account, ip: %s).\n", server[id].name, account_id, ip);
- else{
- uint8 buf[11];
- char tmpstr[24];
- timestamp2string(tmpstr, sizeof(tmpstr), timestamp, login_config.date_format);
- ShowNotice("Char-server '%s': Ban request (account: %d, new final date of banishment: %d (%s), ip: %s).\n", server[id].name, account_id, timestamp, tmpstr, ip);
-
- acc.unban_time = timestamp;
-
- // Save
- accounts->save(accounts, &acc);
-
- WBUFW(buf,0) = 0x2731;
- WBUFL(buf,2) = account_id;
- WBUFB(buf,6) = 1; // 0: change of status, 1: ban
- WBUFL(buf,7) = (uint32)timestamp; // status or final date of a banishment
- charif_sendallwos(-1, buf, 11);
- }
- }
- }
- break;
-
- case 0x2727: // Change of sex (sex is reversed)
- if( RFIFOREST(fd) < 6 )
- return 0;
- else{
- struct mmo_account acc;
-
- int account_id = RFIFOL(fd,2);
- RFIFOSKIP(fd,6);
-
- if( !accounts->load_num(accounts, &acc, account_id) )
- ShowNotice("Char-server '%s': Error of sex change (account: %d not found, ip: %s).\n", server[id].name, account_id, ip);
- else if( acc.sex == 'S' )
- ShowNotice("Char-server '%s': Error of sex change - account to change is a Server account (account: %d, ip: %s).\n", server[id].name, account_id, ip);
- else{
- unsigned char buf[7];
- char sex = ( acc.sex == 'M' ) ? 'F' : 'M'; //Change gender
-
- ShowNotice("Char-server '%s': Sex change (account: %d, new sex %c, ip: %s).\n", server[id].name, account_id, sex, ip);
-
- acc.sex = sex;
- // Save
- accounts->save(accounts, &acc);
-
- // announce to other servers
- WBUFW(buf,0) = 0x2723;
- WBUFL(buf,2) = account_id;
- WBUFB(buf,6) = sex_str2num(sex);
- charif_sendallwos(-1, buf, 7);
- }
- }
- break;
-
- case 0x2728: // We receive account_reg2 from a char-server, and we send them to other map-servers.
- if( RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2) )
- return 0;
- else{
- struct mmo_account acc;
-
- int account_id = RFIFOL(fd,4);
-
- if( !accounts->load_num(accounts, &acc, account_id) )
- ShowStatus("Char-server '%s': receiving (from the char-server) of account_reg2 (account: %d not found, ip: %s).\n", server[id].name, account_id, ip);
- else{
- int len;
- int p;
- ShowNotice("char-server '%s': receiving (from the char-server) of account_reg2 (account: %d, ip: %s).\n", server[id].name, account_id, ip);
- for( j = 0, p = 13; j < ACCOUNT_REG2_NUM && p < RFIFOW(fd,2); ++j ){
- sscanf((char*)RFIFOP(fd,p), "%31c%n", acc.account_reg2[j].str, &len);
- acc.account_reg2[j].str[len]='\0';
- p +=len+1; //+1 to skip the '\0' between strings.
- sscanf((char*)RFIFOP(fd,p), "%255c%n", acc.account_reg2[j].value, &len);
- acc.account_reg2[j].value[len]='\0';
- p +=len+1;
- remove_control_chars(acc.account_reg2[j].str);
- remove_control_chars(acc.account_reg2[j].value);
- }
- acc.account_reg2_num = j;
-
- // Save
- accounts->save(accounts, &acc);
-
- // Sending information towards the other char-servers.
- RFIFOW(fd,0) = 0x2729;// reusing read buffer
- charif_sendallwos(fd, RFIFOP(fd,0), RFIFOW(fd,2));
- }
- RFIFOSKIP(fd,RFIFOW(fd,2));
- }
- break;
-
- case 0x272a: // Receiving of map-server via char-server an unban request
- if( RFIFOREST(fd) < 6 )
- return 0;
- else{
- struct mmo_account acc;
-
- int account_id = RFIFOL(fd,2);
- RFIFOSKIP(fd,6);
-
- if( !accounts->load_num(accounts, &acc, account_id) )
- ShowNotice("Char-server '%s': Error of UnBan request (account: %d not found, ip: %s).\n", server[id].name, account_id, ip);
- else if( acc.unban_time == 0 )
- ShowNotice("Char-server '%s': Error of UnBan request (account: %d, no change for unban date, ip: %s).\n", server[id].name, account_id, ip);
- else{
- ShowNotice("Char-server '%s': UnBan request (account: %d, ip: %s).\n", server[id].name, account_id, ip);
- acc.unban_time = 0;
- accounts->save(accounts, &acc);
- }
- }
- break;
-
- case 0x272b: // Set account_id to online [Wizputer]
- if( RFIFOREST(fd) < 6 )
- return 0;
- add_online_user(id, RFIFOL(fd,2));
- RFIFOSKIP(fd,6);
- break;
-
- case 0x272c: // Set account_id to offline [Wizputer]
- if( RFIFOREST(fd) < 6 )
- return 0;
- remove_online_user(RFIFOL(fd,2));
- RFIFOSKIP(fd,6);
- break;
-
- case 0x272d: // Receive list of all online accounts. [Skotlex]
- if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
- return 0;
- else{
- struct online_login_data *p;
- int aid;
- uint32 i, users;
- online_db->foreach(online_db, online_db_setoffline, id); //Set all chars from this char-server offline first
- users = RFIFOW(fd,4);
- for (i = 0; i < users; i++) {
- aid = RFIFOL(fd,6+i*4);
- p = idb_ensure(online_db, aid, create_online_user);
- p->char_server = id;
- if (p->waiting_disconnect != INVALID_TIMER){
- delete_timer(p->waiting_disconnect, waiting_disconnect_timer);
- p->waiting_disconnect = INVALID_TIMER;
- }
- }
-
- RFIFOSKIP(fd,RFIFOW(fd,2));
- }
- break;
-
- case 0x272e: //Request account_reg2 for a character.
- if (RFIFOREST(fd) < 10)
- return 0;
- else{
- struct mmo_account acc;
- size_t off;
-
- int account_id = RFIFOL(fd,2);
- int char_id = RFIFOL(fd,6);
- RFIFOSKIP(fd,10);
-
- WFIFOHEAD(fd,ACCOUNT_REG2_NUM*sizeof(struct global_reg));
- WFIFOW(fd,0) = 0x2729;
- WFIFOL(fd,4) = account_id;
- WFIFOL(fd,8) = char_id;
- WFIFOB(fd,12) = 1; //Type 1 for Account2 registry
-
- off = 13;
- if( accounts->load_num(accounts, &acc, account_id) ){
- for( j = 0; j < acc.account_reg2_num; j++ ){
- if( acc.account_reg2[j].str[0] != '\0' ){
- off += sprintf((char*)WFIFOP(fd,off), "%s", acc.account_reg2[j].str)+1; //We add 1 to consider the '\0' in place.
- off += sprintf((char*)WFIFOP(fd,off), "%s", acc.account_reg2[j].value)+1;
- }
- }
- }
-
- WFIFOW(fd,2) = (uint16)off;
- WFIFOSET(fd,WFIFOW(fd,2));
- }
- break;
-
- case 0x2736: // WAN IP update from char-server
- if( RFIFOREST(fd) < 6 )
- return 0;
- server[id].ip = ntohl(RFIFOL(fd,2));
- ShowInfo("Updated IP of Server #%d to %d.%d.%d.%d.\n",id, CONVIP(server[id].ip));
- RFIFOSKIP(fd,6);
- break;
-
- case 0x2737: //Request to set all offline.
- ShowInfo("Setting accounts from char-server %d offline.\n", id);
- online_db->foreach(online_db, online_db_setoffline, id);
- RFIFOSKIP(fd,2);
- break;
-
- case 0x2738: //Change PIN Code for a account
- if( RFIFOREST(fd) < 11 )
- return 0;
- else{
- struct mmo_account acc;
-
- if( accounts->load_num(accounts, &acc, RFIFOL(fd,2) ) ){
- strncpy( acc.pincode, (char*)RFIFOP(fd,6), 5 );
- acc.pincode_change = time( NULL );
- accounts->save(accounts, &acc);
- }
-
- RFIFOSKIP(fd,11);
- }
- break;
-
- case 0x2739: // PIN Code was entered wrong too often
- if( RFIFOREST(fd) < 6 )
- return 0;
- else{
- struct mmo_account acc;
-
- if( accounts->load_num(accounts, &acc, RFIFOL(fd,2) ) ){
- struct online_login_data* ld;
-
- ld = (struct online_login_data*)idb_get(online_db,acc.account_id);
-
- if( ld == NULL )
- return 0;
-
- login_log( host2ip(acc.last_ip), acc.userid, 100, "PIN Code check failed" );
- }
-
- remove_online_user(acc.account_id);
-
- RFIFOSKIP(fd,6);
- }
- break;
-
- default:
- ShowError("parse_fromchar: Unknown packet 0x%x from a char-server! Disconnecting!\n", command);
- set_eof(fd);
- return 0;
- } // switch
- } // while
-
- return 0;
-}
-
-
//-------------------------------------
// Make new account
//-------------------------------------
@@ -964,7 +167,7 @@
//Account Registration Flood Protection by [Kevin]
if( new_reg_tick == 0 )
new_reg_tick = gettick();
- if( DIFF_TICK(tick, new_reg_tick) < 0 && num_regs >= allowed_regs ) {
+ if( DIFF_TICK(tick, new_reg_tick) < 0 && num_regs >= login_config.allowed_regs ) {
ShowNotice("Account registration denied (registration limit exceeded)\n");
return 3;
}
@@ -1004,7 +207,7 @@
if( DIFF_TICK(tick, new_reg_tick) > 0 ) {// Update the registration check.
num_regs = 0;
- new_reg_tick = tick + time_allowed*1000;
+ new_reg_tick = tick + login_config.time_allowed*1000;
}
++num_regs;
@@ -1041,8 +244,11 @@
}
//Client Version check
- if( login_config.check_client_version && sd->version != login_config.client_version_to_connect )
+ if( login_config.check_client_version && sd->version != login_config.client_version_to_connect ){
+ ShowNotice("Invalid version (account: '%s', auth_vers: '%d', received version: '%d', ip: %s)\n",
+ sd->userid, login_config.client_version_to_connect, sd->version, ip);
return 5;
+ }
len = strnlen(sd->userid, NAME_LENGTH);
@@ -1093,15 +299,16 @@
if( login_config.client_hash_check && !isServer ) {
struct client_hash_node *node = login_config.client_hash_nodes;
+ uint8 anyhash[16];
bool match = false;
if( !sd->has_client_hash ) {
ShowNotice("Client doesn't sent client hash (account: %s, pass: %s, ip: %s)\n", sd->userid, sd->passwd, acc.state, ip);
return 5;
}
-
+ memset(anyhash,1,sizeof(anyhash));
while( node ) {
- if( node->group_id <= acc.group_id && memcmp(node->hash, sd->client_hash, 16) == 0 ) {
+ if( node->group_id <= acc.group_id && (memcmp(node->hash,anyhash,16)==0 || memcmp(node->hash, sd->client_hash, 16) == 0 ) ){
match = true;
break;
}
@@ -1145,466 +352,97 @@
return -1; // account OK
}
-void login_auth_ok(struct login_session_data* sd)
+//-----------------------------------------------------
+// encrypted/unencrypted password check (from eApp)
+//-----------------------------------------------------
+bool check_encrypted(const char* str1, const char* str2, const char* passwd)
{
- int fd = sd->fd;
- uint32 ip = session[fd]->client_addr;
+ char tmpstr[64+1], md5str[32+1];
- uint8 server_num, n;
- uint32 subnet_char_ip;
- struct auth_node* node;
- int i;
+ safesnprintf(tmpstr, sizeof(tmpstr), "%s%s", str1, str2);
+ MD5_String(tmpstr, md5str);
- if( runflag != LOGINSERVER_ST_RUNNING )
- {
- // players can only login while running
- WFIFOHEAD(fd,3);
- WFIFOW(fd,0) = 0x81;
- WFIFOB(fd,2) = 1;// server closed
- WFIFOSET(fd,3);
- return;
- }
+ return (0==strcmp(passwd, md5str));
+}
- if( login_config.group_id_to_connect >= 0 && sd->group_id != login_config.group_id_to_connect ) {
- ShowStatus("Connection refused: the required group id for connection is %d (account: %s, group: %d).\n", login_config.group_id_to_connect, sd->userid, sd->group_id);
- WFIFOHEAD(fd,3);
- WFIFOW(fd,0) = 0x81;
- WFIFOB(fd,2) = 1; // 01 = Server closed
- WFIFOSET(fd,3);
- return;
- } else if( login_config.min_group_id_to_connect >= 0 && login_config.group_id_to_connect == -1 && sd->group_id < login_config.min_group_id_to_connect ) {
- ShowStatus("Connection refused: the minium group id required for connection is %d (account: %s, group: %d).\n", login_config.min_group_id_to_connect, sd->userid, sd->group_id);
- WFIFOHEAD(fd,3);
- WFIFOW(fd,0) = 0x81;
- WFIFOB(fd,2) = 1; // 01 = Server closed
- WFIFOSET(fd,3);
- return;
- }
-
- server_num = 0;
- for( i = 0; i < ARRAYLENGTH(server); ++i )
- if( session_isActive(server[i].fd) )
- server_num++;
-
- if( server_num == 0 )
- {// if no char-server, don't send void list of servers, just disconnect the player with proper message
- ShowStatus("Connection refused: there is no char-server online (account: %s).\n", sd->userid);
- WFIFOHEAD(fd,3);
- WFIFOW(fd,0) = 0x81;
- WFIFOB(fd,2) = 1; // 01 = Server closed
- WFIFOSET(fd,3);
- return;
- }
-
+bool check_password(const char* md5key, int passwdenc, const char* passwd, const char* refpass)
+{
+ if(passwdenc == 0)
{
- struct online_login_data* data = (struct online_login_data*)idb_get(online_db, sd->account_id);
- if( data )
- {// account is already marked as online!
- if( data->char_server > -1 )
- {// Request char servers to kick this account out. [Skotlex]
- uint8 buf[6];
- ShowNotice("User '%s' is already online - Rejected.\n", sd->userid);
- WBUFW(buf,0) = 0x2734;
- WBUFL(buf,2) = sd->account_id;
- charif_sendallwos(-1, buf, 6);
- if( data->waiting_disconnect == INVALID_TIMER )
- data->waiting_disconnect = add_timer(gettick()+AUTH_TIMEOUT, waiting_disconnect_timer, sd->account_id, 0);
-
- WFIFOHEAD(fd,3);
- WFIFOW(fd,0) = 0x81;
- WFIFOB(fd,2) = 8; // 08 = Server still recognizes your last login
- WFIFOSET(fd,3);
- return;
- }
- else
- if( data->char_server == -1 )
- {// client has authed but did not access char-server yet
- // wipe previous session
- idb_remove(auth_db, sd->account_id);
- remove_online_user(sd->account_id);
- data = NULL;
- }
- }
+ return (0==strcmp(passwd, refpass));
}
-
- login_log(ip, sd->userid, 100, "login ok");
- ShowStatus("Connection of the account '%s' accepted.\n", sd->userid);
-
- WFIFOHEAD(fd,47+32*server_num);
- WFIFOW(fd,0) = 0x69;
- WFIFOW(fd,2) = 47+32*server_num;
- WFIFOL(fd,4) = sd->login_id1;
- WFIFOL(fd,8) = sd->account_id;
- WFIFOL(fd,12) = sd->login_id2;
- WFIFOL(fd,16) = 0; // in old version, that was for ip (not more used)
- //memcpy(WFIFOP(fd,20), sd->lastlogin, 24); // in old version, that was for name (not more used)
- memset(WFIFOP(fd,20), 0, 24);
- WFIFOW(fd,44) = 0; // unknown
- WFIFOB(fd,46) = sex_str2num(sd->sex);
- for( i = 0, n = 0; i < ARRAYLENGTH(server); ++i )
+ else
{
- if( !session_isValid(server[i].fd) )
- continue;
+ // password mode set to 1 -> md5(md5key, refpass) enable with <passwordencrypt></passwordencrypt>
+ // password mode set to 2 -> md5(refpass, md5key) enable with <passwordencrypt2></passwordencrypt2>
- subnet_char_ip = lan_subnetcheck(ip); // Advanced subnet check [LuzZza]
- WFIFOL(fd,47+n*32) = htonl((subnet_char_ip) ? subnet_char_ip : server[i].ip);
- WFIFOW(fd,47+n*32+4) = ntows(htons(server[i].port)); // [!] LE byte order here [!]
- memcpy(WFIFOP(fd,47+n*32+6), server[i].name, 20);
- WFIFOW(fd,47+n*32+26) = server[i].users;
- WFIFOW(fd,47+n*32+28) = server[i].type;
- WFIFOW(fd,47+n*32+30) = server[i].new_;
- n++;
+ return ((passwdenc&0x01) && check_encrypted(md5key, refpass, passwd)) ||
+ ((passwdenc&0x02) && check_encrypted(refpass, md5key, passwd));
}
- WFIFOSET(fd,47+32*server_num);
-
- // create temporary auth entry
- CREATE(node, struct auth_node, 1);
- node->account_id = sd->account_id;
- node->login_id1 = sd->login_id1;
- node->login_id2 = sd->login_id2;
- node->sex = sd->sex;
- node->ip = ip;
- node->version = sd->version;
- node->clienttype = sd->clienttype;
- idb_put(auth_db, sd->account_id, node);
-
- {
- struct online_login_data* data;
-
- // mark client as 'online'
- data = add_online_user(-1, sd->account_id);
-
- // schedule deletion of this node
- data->waiting_disconnect = add_timer(gettick()+AUTH_TIMEOUT, waiting_disconnect_timer, sd->account_id, 0);
- }
}
-/* Log the result of a failed connection attempt by sd
- * result: nb (msg define in conf)
- 0 = Unregistered ID
- 1 = Incorrect Password
- 2 = This ID is expired
- 3 = Rejected from Server
- 4 = You have been blocked by the GM Team
- 5 = Your Game's EXE file is not the latest version
- 6 = Your are Prohibited to log in until %s
- 7 = Server is jammed due to over populated
- 8 = No more accounts may be connected from this company
- 9 = MSI_REFUSE_BAN_BY_DBA
- 10 = MSI_REFUSE_EMAIL_NOT_CONFIRMED
- 11 = MSI_REFUSE_BAN_BY_GM
- 12 = MSI_REFUSE_TEMP_BAN_FOR_DBWORK
- 13 = MSI_REFUSE_SELF_LOCK
- 14 = MSI_REFUSE_NOT_PERMITTED_GROUP
- 15 = MSI_REFUSE_NOT_PERMITTED_GROUP
- 99 = This ID has been totally erased
- 100 = Login information remains at %s
- 101 = Account has been locked for a hacking investigation. Please contact the GM Team for more information
- 102 = This account has been temporarily prohibited from login due to a bug-related investigation
- 103 = This character is being deleted. Login is temporarily unavailable for the time being
- 104 = This character is being deleted. Login is temporarily unavailable for the time being
- default = Unknown Error.
- */
-void login_auth_failed(struct login_session_data* sd, int result)
+//--------------------------------------------
+// Test to know if an IP come from LAN or WAN.
+//--------------------------------------------
+int lan_subnetcheck(uint32 ip)
{
- int fd = sd->fd;
- uint32 ip = session[fd]->client_addr;
-
- if (login_config.log_login)
- {
- if(result >= 0 && result <= 15)
- login_log(ip, sd->userid, result, msg_txt(result));
- else if(result >= 99 && result <= 104)
- login_log(ip, sd->userid, result, msg_txt(result-83)); //-83 offset
- else
- login_log(ip, sd->userid, result, msg_txt(22)); //unknow error
- }
-
- if( result == 1 && login_config.dynamic_pass_failure_ban )
- ipban_log(ip); // log failed password attempt
-
-#if PACKETVER >= 20120000 /* not sure when this started */
- WFIFOHEAD(fd,26);
- WFIFOW(fd,0) = 0x83e;
- WFIFOL(fd,2) = result;
- if( result != 6 )
- memset(WFIFOP(fd,6), '\0', 20);
- else { // 6 = Your are Prohibited to log in until %s
- struct mmo_account acc;
- time_t unban_time = ( accounts->load_str(accounts, &acc, sd->userid) ) ? acc.unban_time : 0;
- timestamp2string((char*)WFIFOP(fd,6), 20, unban_time, login_config.date_format);
- }
- WFIFOSET(fd,26);
-#else
- WFIFOHEAD(fd,23);
- WFIFOW(fd,0) = 0x6a;
- WFIFOB(fd,2) = (uint8)result;
- if( result != 6 )
- memset(WFIFOP(fd,3), '\0', 20);
- else { // 6 = Your are Prohibited to log in until %s
- struct mmo_account acc;
- time_t unban_time = ( accounts->load_str(accounts, &acc, sd->userid) ) ? acc.unban_time : 0;
- timestamp2string((char*)WFIFOP(fd,3), 20, unban_time, login_config.date_format);
- }
- WFIFOSET(fd,23);
-#endif
+ int i;
+ ARR_FIND( 0, subnet_count, i, (subnet[i].char_ip & subnet[i].mask) == (ip & subnet[i].mask) );
+ return ( i < subnet_count ) ? subnet[i].char_ip : 0;
}
-
-//----------------------------------------------------------------------------------------
-// Default packet parsing (normal players or char-server connection requests)
-//----------------------------------------------------------------------------------------
-int parse_login(int fd)
+//----------------------------------
+// Reading Lan Support configuration
+//----------------------------------
+int login_lan_config_read(const char *lancfgName)
{
- struct login_session_data* sd = (struct login_session_data*)session[fd]->session_data;
- int result;
+ FILE *fp;
+ int line_num = 0;
+ char line[1024], w1[64], w2[64], w3[64], w4[64];
- char ip[16];
- uint32 ipl = session[fd]->client_addr;
- ip2str(ipl, ip);
-
- if( session[fd]->flag.eof )
- {
- ShowInfo("Closed connection from '"CL_WHITE"%s"CL_RESET"'.\n", ip);
- do_close(fd);
- return 0;
+ if((fp = fopen(lancfgName, "r")) == NULL) {
+ ShowWarning("LAN Support configuration file is not found: %s\n", lancfgName);
+ return 1;
}
- if( sd == NULL )
+ while(fgets(line, sizeof(line), fp))
{
- // Perform ip-ban check
- if( login_config.ipban && ipban_check(ipl) )
- {
- ShowStatus("Connection refused: IP isn't authorised (deny/allow, ip: %s).\n", ip);
- login_log(ipl, "unknown", -3, "ip banned");
- WFIFOHEAD(fd,23);
- WFIFOW(fd,0) = 0x6a;
- WFIFOB(fd,2) = 3; // 3 = Rejected from Server
- WFIFOSET(fd,23);
- set_eof(fd);
- return 0;
- }
+ line_num++;
+ if ((line[0] == '/' && line[1] == '/') || line[0] == '\n' || line[1] == '\n')
+ continue;
- // create a session for this new connection
- CREATE(session[fd]->session_data, struct login_session_data, 1);
- sd = (struct login_session_data*)session[fd]->session_data;
- sd->fd = fd;
- }
-
- while( RFIFOREST(fd) >= 2 )
- {
- uint16 command = RFIFOW(fd,0);
-
- switch( command )
+ if(sscanf(line,"%[^:]: %[^:]:%[^:]:%[^\r\n]", w1, w2, w3, w4) != 4)
{
-
- case 0x0200: // New alive packet: structure: 0x200 <account.userid>.24B. used to verify if client is always alive.
- if (RFIFOREST(fd) < 26)
- return 0;
- RFIFOSKIP(fd,26);
- break;
-
- // client md5 hash (binary)
- case 0x0204: // S 0204 <md5 hash>.16B (kRO 2004-05-31aSakexe langtype 0 and 6)
- if (RFIFOREST(fd) < 18)
- return 0;
-
- sd->has_client_hash = 1;
- memcpy(sd->client_hash, RFIFOP(fd, 2), 16);
-
- RFIFOSKIP(fd,18);
- break;
-
- // request client login (raw password)
- case 0x0064: // S 0064 <version>.L <username>.24B <password>.24B <clienttype>.B
- case 0x0277: // S 0277 <version>.L <username>.24B <password>.24B <clienttype>.B <ip address>.16B <adapter address>.13B
- case 0x02b0: // S 02b0 <version>.L <username>.24B <password>.24B <clienttype>.B <ip address>.16B <adapter address>.13B <g_isGravityID>.B
- // request client login (md5-hashed password)
- case 0x01dd: // S 01dd <version>.L <username>.24B <password hash>.16B <clienttype>.B
- case 0x01fa: // S 01fa <version>.L <username>.24B <password hash>.16B <clienttype>.B <?>.B(index of the connection in the clientinfo file (+10 if the command-line contains "pc"))
- case 0x027c: // S 027c <version>.L <username>.24B <password hash>.16B <clienttype>.B <?>.13B(junk)
- case 0x0825: // S 0825 <packetsize>.W <version>.L <clienttype>.B <userid>.24B <password>.27B <mac>.17B <ip>.15B <token>.(packetsize - 0x5C)B
- {
- size_t packet_len = RFIFOREST(fd);
-
- if( (command == 0x0064 && packet_len < 55)
- || (command == 0x0277 && packet_len < 84)
- || (command == 0x02b0 && packet_len < 85)
- || (command == 0x01dd && packet_len < 47)
- || (command == 0x01fa && packet_len < 48)
- || (command == 0x027c && packet_len < 60)
- || (command == 0x0825 && (packet_len < 4 || packet_len < RFIFOW(fd, 2))) )
- return 0;
+ ShowWarning("Error syntax of configuration file %s in line %d.\n", lancfgName, line_num);
+ continue;
}
- {
- uint32 version;
- char username[NAME_LENGTH];
- char password[NAME_LENGTH];
- unsigned char passhash[16];
- uint8 clienttype;
- bool israwpass = (command==0x0064 || command==0x0277 || command==0x02b0 || command == 0x0825);
- // Shinryo: For the time being, just use token as password.
- if(command == 0x0825)
- {
- char *accname = (char *)RFIFOP(fd, 9);
- char *token = (char *)RFIFOP(fd, 0x5C);
- size_t uAccLen = strlen(accname);
- size_t uTokenLen = RFIFOREST(fd) - 0x5C;
-
- version = RFIFOL(fd,4);
-
- if(uAccLen > NAME_LENGTH - 1 || uAccLen <= 0 || uTokenLen > NAME_LENGTH - 1 || uTokenLen <= 0)
- {
- login_auth_failed(sd, 3);
- return 0;
- }
-
- safestrncpy(username, accname, uAccLen + 1);
- safestrncpy(password, token, uTokenLen + 1);
- clienttype = RFIFOB(fd, 8);
- }
- else
- {
- version = RFIFOL(fd,2);
- safestrncpy(username, (const char*)RFIFOP(fd,6), NAME_LENGTH);
- if( israwpass )
- {
- safestrncpy(password, (const char*)RFIFOP(fd,30), NAME_LENGTH);
- clienttype = RFIFOB(fd,54);
- }
- else
- {
- memcpy(passhash, RFIFOP(fd,30), 16);
- clienttype = RFIFOB(fd,46);
- }
- }
- RFIFOSKIP(fd,RFIFOREST(fd)); // assume no other packet was sent
-
- sd->clienttype = clienttype;
- sd->version = version;
- safestrncpy(sd->userid, username, NAME_LENGTH);
- if( israwpass )
- {
- ShowStatus("Request for connection of %s (ip: %s) version=%d\n", sd->userid, ip,sd->version);
- safestrncpy(sd->passwd, password, NAME_LENGTH);
- if( login_config.use_md5_passwds )
- MD5_String(sd->passwd, sd->passwd);
- sd->passwdenc = 0;
- }
- else
- {
- ShowStatus("Request for connection (passwdenc mode) of %s (ip: %s) version=%d\n", sd->userid, ip,sd->version);
- bin2hex(sd->passwd, passhash, 16); // raw binary data here!
- sd->passwdenc = PASSWORDENC;
- }
-
- if( sd->passwdenc != 0 && login_config.use_md5_passwds )
- {
- login_auth_failed(sd, 3); // send "rejected from server"
- return 0;
- }
-
- result = mmo_auth(sd, false);
-
- if( result == -1 )
- login_auth_ok(sd);
- else
- login_auth_failed(sd, result);
- }
- break;
-
- case 0x01db: // Sending request of the coding key
- RFIFOSKIP(fd,2);
+ if( strcmpi(w1, "subnet") == 0 )
{
- memset(sd->md5key, '\0', sizeof(sd->md5key));
- sd->md5keylen = (uint16)(12 + rnd() % 4);
- MD5_Salt(sd->md5keylen, sd->md5key);
+ subnet[subnet_count].mask = str2ip(w2);
+ subnet[subnet_count].char_ip = str2ip(w3);
+ subnet[subnet_count].map_ip = str2ip(w4);
- WFIFOHEAD(fd,4 + sd->md5keylen);
- WFIFOW(fd,0) = 0x01dc;
- WFIFOW(fd,2) = 4 + sd->md5keylen;
- memcpy(WFIFOP(fd,4), sd->md5key, sd->md5keylen);
- WFIFOSET(fd,WFIFOW(fd,2));
- }
- break;
-
- case 0x2710: // Connection request of a char-server
- if (RFIFOREST(fd) < 86)
- return 0;
- {
- char server_name[20];
- char message[256];
- uint32 server_ip;
- uint16 server_port;
- uint16 type;
- uint16 new_;
-
- safestrncpy(sd->userid, (char*)RFIFOP(fd,2), NAME_LENGTH);
- safestrncpy(sd->passwd, (char*)RFIFOP(fd,26), NAME_LENGTH);
- if( login_config.use_md5_passwds )
- MD5_String(sd->passwd, sd->passwd);
- sd->passwdenc = 0;
- sd->version = login_config.client_version_to_connect; // hack to skip version check
- server_ip = ntohl(RFIFOL(fd,54));
- server_port = ntohs(RFIFOW(fd,58));
- safestrncpy(server_name, (char*)RFIFOP(fd,60), 20);
- type = RFIFOW(fd,82);
- new_ = RFIFOW(fd,84);
- RFIFOSKIP(fd,86);
-
- ShowInfo("Connection request of the char-server '%s' @ %u.%u.%u.%u:%u (account: '%s', pass: '%s', ip: '%s')\n", server_name, CONVIP(server_ip), server_port, sd->userid, sd->passwd, ip);
- sprintf(message, "charserver - %s@%u.%u.%u.%u:%u", server_name, CONVIP(server_ip), server_port);
- login_log(session[fd]->client_addr, sd->userid, 100, message);
-
- result = mmo_auth(sd, true);
- if( runflag == LOGINSERVER_ST_RUNNING &&
- result == -1 &&
- sd->sex == 'S' &&
- sd->account_id >= 0 && sd->account_id < ARRAYLENGTH(server) &&
- !session_isValid(server[sd->account_id].fd) )
+ if( (subnet[subnet_count].char_ip & subnet[subnet_count].mask) != (subnet[subnet_count].map_ip & subnet[subnet_count].mask) )
{
- ShowStatus("Connection of the char-server '%s' accepted.\n", server_name);
- safestrncpy(server[sd->account_id].name, server_name, sizeof(server[sd->account_id].name));
- server[sd->account_id].fd = fd;
- server[sd->account_id].ip = server_ip;
- server[sd->account_id].port = server_port;
- server[sd->account_id].users = 0;
- server[sd->account_id].type = type;
- server[sd->account_id].new_ = new_;
-
- session[fd]->func_parse = parse_fromchar;
- session[fd]->flag.server = 1;
- realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
-
- // send connection success
- WFIFOHEAD(fd,3);
- WFIFOW(fd,0) = 0x2711;
- WFIFOB(fd,2) = 0;
- WFIFOSET(fd,3);
+ ShowError("%s: Configuration Error: The char server (%s) and map server (%s) belong to different subnetworks!\n", lancfgName, w3, w4);
+ continue;
}
- else
- {
- ShowNotice("Connection of the char-server '%s' REFUSED.\n", server_name);
- WFIFOHEAD(fd,3);
- WFIFOW(fd,0) = 0x2711;
- WFIFOB(fd,2) = 3;
- WFIFOSET(fd,3);
- }
- }
- return 0; // processing will continue elsewhere
- default:
- ShowNotice("Abnormal end of connection (ip: %s): Unknown packet 0x%x\n", ip, command);
- set_eof(fd);
- return 0;
+ subnet_count++;
}
}
+ if( subnet_count > 1 ) /* only useful if there is more than 1 available */
+ ShowStatus("Read information about %d subnetworks.\n", subnet_count);
+
+ fclose(fp);
return 0;
}
-
+/*
+ * Init default configuration
+ */
void login_set_defaults()
{
login_config.login_ip = INADDR_ANY;
@@ -1620,7 +458,8 @@
login_config.group_id_to_connect = -1;
login_config.min_group_id_to_connect = -1;
login_config.check_client_version = false;
- login_config.client_version_to_connect = 20;
+ login_config.client_version_to_connect = date2version(PACKETVER); //20120410 => 30
+ ShowInfo("loginconfig: client_version_to_connect = %d\n",login_config.client_version_to_connect);
login_config.ipban = true;
login_config.dynamic_pass_failure_ban = true;
@@ -1630,9 +469,16 @@
login_config.use_dnsbl = false;
safestrncpy(login_config.dnsbl_servs, "", sizeof(login_config.dnsbl_servs));
safestrncpy(login_config.account_engine, "auto", sizeof(login_config.account_engine));
+ login_config.allowed_regs = true;
+ login_config.time_allowed = 10; //in second
login_config.client_hash_check = 0;
login_config.client_hash_nodes = NULL;
+
+ //other default conf
+ login_config.loginconf_name = "conf/login_athena.conf";
+ login_config.lanconf_name = "conf/subnet_athena.conf";
+ login_config.msgconf_name = "conf/msg_conf/login_msg.conf";
}
//-----------------------------------
@@ -1696,9 +542,9 @@
else if(!strcmpi(w1, "console"))
login_config.console = (bool)config_switch(w2);
else if(!strcmpi(w1, "allowed_regs")) //account flood protection system
- allowed_regs = atoi(w2);
+ login_config.allowed_regs = atoi(w2);
else if(!strcmpi(w1, "time_allowed"))
- time_allowed = atoi(w2);
+ login_config.time_allowed = atoi(w2);
else if(!strcmpi(w1, "use_dnsbl"))
login_config.use_dnsbl = (bool)config_switch(w2);
else if(!strcmpi(w1, "dnsbl_servers"))
@@ -1718,15 +564,20 @@
int i;
CREATE(nnode, struct client_hash_node, 1);
- for (i = 0; i < 32; i += 2) {
- char buf[3];
- unsigned int byte;
+ if(!strcmpi(md5,"any")){
+ memset(nnode->hash,1,sizeof(nnode->hash));
+ }
+ else {
+ for (i = 0; i < 32; i += 2) {
+ char buf[3];
+ unsigned int byte;
- memcpy(buf, &md5[i], 2);
- buf[2] = 0;
+ memcpy(buf, &md5[i], 2);
+ buf[2] = 0;
- sscanf(buf, "%x", &byte);
- nnode->hash[i / 2] = (uint8)(byte & 0xFF);
+ sscanf(buf, "%x", &byte);
+ nnode->hash[i / 2] = (uint8)(byte & 0xFF);
+ }
}
nnode->group_id = group;
@@ -1818,8 +669,7 @@
online_db->destroy(online_db, NULL);
auth_db->destroy(auth_db, NULL);
- for( i = 0; i < ARRAYLENGTH(server); ++i )
- chrif_server_destroy(i);
+ do_final_loginchrif();
if( login_fd != -1 )
{
@@ -1849,12 +699,10 @@
{
if( runflag != LOGINSERVER_ST_SHUTDOWN )
{
- int id;
runflag = LOGINSERVER_ST_SHUTDOWN;
ShowStatus("Shutting down...\n");
// TODO proper shutdown procedure; kick all characters, wait for acks, ... [FlavioJS]
- for( id = 0; id < ARRAYLENGTH(server); ++id )
- chrif_server_reset(id);
+ do_shutdown_loginchrif();
flush_fifos();
runflag = CORE_ST_STOP;
}
@@ -1874,21 +722,16 @@
// read login-server configuration
login_set_defaults();
+ cnsl_get_options(argc,argv);
- LOGIN_CONF_NAME = "conf/login_athena.conf";
- LAN_CONF_NAME = "conf/subnet_athena.conf";
- MSG_CONF_NAME_EN = "conf/msg_conf/login_msg.conf";
+ login_config_read(login_config.loginconf_name);
+ msg_config_read(login_config.msgconf_name);
+ login_lan_config_read(login_config.lanconf_name);
+ //end config
- cli_get_options(argc,argv);
-
- msg_config_read(MSG_CONF_NAME_EN);
- login_config_read(LOGIN_CONF_NAME);
- login_lan_config_read(LAN_CONF_NAME);
-
rnd_init();
- for( i = 0; i < ARRAYLENGTH(server); ++i )
- chrif_server_init(i);
+ do_init_loginchrif();
// initialize logging
if( login_config.log_login )
@@ -1911,12 +754,6 @@
add_timer_func_list(online_data_cleanup, "online_data_cleanup");
add_timer_interval(gettick() + 600*1000, online_data_cleanup, 0, 0, 600*1000);
- // add timer to detect ip address change and perform update
- if (login_config.ip_sync_interval) {
- add_timer_func_list(sync_ip_addresses, "sync_ip_addresses");
- add_timer_interval(gettick() + login_config.ip_sync_interval, sync_ip_addresses, 0, 0, login_config.ip_sync_interval);
- }
-
// Account database init
accounts = get_account_engine();
if( accounts == NULL ) {
@@ -1941,14 +778,11 @@
runflag = LOGINSERVER_ST_RUNNING;
}
+ do_init_logincnslif();
+
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");
- if( login_config.console ) {
- 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;
}
@@ -1961,21 +795,3 @@
void login_do_final_msg(void){
_do_final_msg(LOGIN_MAX_MSG,msg_table);
}
-
-/*======================================================
- * Login-Server help option info
- *------------------------------------------------------*/
-void display_helpscreen(bool do_exit)
-{
- ShowInfo("Usage: %s [options]\n", SERVER_NAME);
- ShowInfo("\n");
- ShowInfo("Options:\n");
- ShowInfo(" -?, -h [--help]\t\tDisplays this help screen.\n");
- ShowInfo(" -v [--version]\t\tDisplays the server's version.\n");
- ShowInfo(" --run-once\t\t\tCloses server after loading (testing).\n");
- ShowInfo(" --login-config <file>\t\tAlternative login-server configuration.\n");
- ShowInfo(" --lan-config <file>\t\tAlternative lag configuration.\n");
- ShowInfo(" --msg-config <file>\t\tAlternative message configuration.\n");
- if( do_exit )
- exit(EXIT_SUCCESS);
-}
Index: src/map/pc.h
===================================================================
--- src/map/pc.h (revision 17373)
+++ src/map/pc.h (working copy)
@@ -185,6 +185,7 @@
unsigned int bonus_coma : 1;
} special_state;
int login_id1, login_id2;
+ int version;
unsigned short class_; //This is the internal job ID used by the map server to simplify comparisons/queries/etc. [Skotlex]
int group_id, group_pos, group_level;
unsigned int permissions;/* group permissions */
Index: src/map/chrif.c
===================================================================
--- src/map/chrif.c (revision 17373)
+++ src/map/chrif.c (working copy)
@@ -722,13 +722,14 @@
chrif_check(-1);
- WFIFOHEAD(char_fd,18);
+ WFIFOHEAD(char_fd,19);
WFIFOW(char_fd, 0) = 0x2b02;
WFIFOL(char_fd, 2) = sd->bl.id;
WFIFOL(char_fd, 6) = sd->login_id1;
WFIFOL(char_fd,10) = sd->login_id2;
WFIFOL(char_fd,14) = htonl(s_ip);
- WFIFOSET(char_fd,18);
+ WFIFOB(char_fd,18) = sd->version;
+ WFIFOSET(char_fd,19);
return 0;
}
Index: src/char/int_storage.c
===================================================================
--- src/char/int_storage.c (revision 17373)
+++ src/char/int_storage.c (working copy)
@@ -41,7 +41,7 @@
StringBuf_AppendStr(&buf, "SELECT `id`,`nameid`,`amount`,`equip`,`identify`,`refine`,`attribute`,`expire_time`,`bound`,`unique_id`");
for( j = 0; j < MAX_SLOTS; ++j )
StringBuf_Printf(&buf, ",`card%d`", j);
- StringBuf_Printf(&buf, " FROM `%s` WHERE `account_id`='%d' ORDER BY `nameid`", storage_db, account_id);
+ StringBuf_Printf(&buf, " FROM `%s` WHERE `account_id`='%d' ORDER BY `nameid`", schema_config.storage_db, account_id);
if( SQL_ERROR == Sql_Query(sql_handle, StringBuf_Value(&buf)) )
Sql_ShowDebug(sql_handle);
@@ -99,7 +99,7 @@
StringBuf_AppendStr(&buf, "SELECT `id`,`nameid`,`amount`,`equip`,`identify`,`refine`,`attribute`,`bound`,`unique_id`");
for( j = 0; j < MAX_SLOTS; ++j )
StringBuf_Printf(&buf, ",`card%d`", j);
- StringBuf_Printf(&buf, " FROM `%s` WHERE `guild_id`='%d' ORDER BY `nameid`", guild_storage_db, guild_id);
+ StringBuf_Printf(&buf, " FROM `%s` WHERE `guild_id`='%d' ORDER BY `nameid`", schema_config.guild_storage_db, guild_id);
if( SQL_ERROR == Sql_Query(sql_handle, StringBuf_Value(&buf)) )
Sql_ShowDebug(sql_handle);
@@ -146,13 +146,13 @@
// Delete char storage
int inter_storage_delete(int account_id)
{
- if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id`='%d'", storage_db, account_id) )
+ if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id`='%d'", schema_config.storage_db, account_id) )
Sql_ShowDebug(sql_handle);
return 0;
}
int inter_guild_storage_delete(int guild_id)
{
- if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id`='%d'", guild_storage_db, guild_id) )
+ if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id`='%d'", schema_config.guild_storage_db, guild_id) )
Sql_ShowDebug(sql_handle);
return 0;
}
@@ -162,7 +162,7 @@
int mapif_load_guild_storage(int fd,int account_id,int guild_id, char flag)
{
- if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `guild_id` FROM `%s` WHERE `guild_id`='%d'", guild_db, guild_id) )
+ if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `guild_id` FROM `%s` WHERE `guild_id`='%d'", schema_config.guild_db, guild_id) )
Sql_ShowDebug(sql_handle);
else if( Sql_NumRows(sql_handle) > 0 )
{// guild exists
@@ -222,7 +222,7 @@
}
else
{
- if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `guild_id` FROM `%s` WHERE `guild_id`='%d'", guild_db, guild_id) )
+ if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `guild_id` FROM `%s` WHERE `guild_id`='%d'", schema_config.guild_db, guild_id) )
Sql_ShowDebug(sql_handle);
else if( Sql_NumRows(sql_handle) > 0 )
{// guild exists
@@ -266,7 +266,7 @@
StringBuf_AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `bound`");
for( j = 0; j < MAX_SLOTS; ++j )
StringBuf_Printf(&buf, ", `card%d`", j);
- StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`='%d'",inventory_db,char_id);
+ StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`='%d'",schema_config.inventory_db,char_id);
stmt = SqlStmt_Malloc(sql_handle);
if( SQL_ERROR == SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf))
@@ -296,13 +296,13 @@
i++;
}
}
-
+
if(!i) //No items found - No need to continue
return 0;
//First we delete the character's items
StringBuf_Clear(&buf);
- StringBuf_Printf(&buf, "DELETE FROM `%s` WHERE",inventory_db);
+ StringBuf_Printf(&buf, "DELETE FROM `%s` WHERE",schema_config.inventory_db);
for(j=0; j<i; j++) {
if( found )
StringBuf_AppendStr(&buf, " OR");
@@ -324,11 +324,11 @@
//Now let's update the guild storage with those deleted items
found = false;
StringBuf_Clear(&buf);
- StringBuf_Printf(&buf, "INSERT INTO `%s` (`guild_id`, `nameid`, `amount`, `identify`, `refine`, `attribute`, `expire_time`, `bound`", guild_storage_db);
+ StringBuf_Printf(&buf, "INSERT INTO `%s` (`guild_id`, `nameid`, `amount`, `identify`, `refine`, `attribute`, `expire_time`, `bound`", schema_config.guild_storage_db);
for( j = 0; j < MAX_SLOTS; ++j )
StringBuf_Printf(&buf, ", `card%d`", j);
StringBuf_AppendStr(&buf, ") VALUES ");
-
+
for( j = 0; j < i; ++j ) {
if( found )
StringBuf_AppendStr(&buf, ",");
Index: src/char/CMakeLists.txt
===================================================================
--- src/char/CMakeLists.txt (revision 17373)
+++ src/char/CMakeLists.txt (working copy)
@@ -12,6 +12,10 @@
message( STATUS "Creating target char-server_sql" )
set( SQL_CHAR_HEADERS
"${CMAKE_CURRENT_SOURCE_DIR}/char.h"
+ "${CMAKE_CURRENT_SOURCE_DIR}/char_clif.h"
+ "${CMAKE_CURRENT_SOURCE_DIR}/char_cnslif.h"
+ "${CMAKE_CURRENT_SOURCE_DIR}/char_logif.h"
+ "${CMAKE_CURRENT_SOURCE_DIR}/char_mapif.h"
"${CMAKE_CURRENT_SOURCE_DIR}/int_auction.h"
"${CMAKE_CURRENT_SOURCE_DIR}/int_elemental.h"
"${CMAKE_CURRENT_SOURCE_DIR}/int_guild.h"
@@ -26,6 +30,10 @@
)
set( SQL_CHAR_SOURCES
"${CMAKE_CURRENT_SOURCE_DIR}/char.c"
+ "${CMAKE_CURRENT_SOURCE_DIR}/char_clif.c"
+ "${CMAKE_CURRENT_SOURCE_DIR}/char_cnslif.c"
+ "${CMAKE_CURRENT_SOURCE_DIR}/char_logif.c"
+ "${CMAKE_CURRENT_SOURCE_DIR}/char_mapif.c"
"${CMAKE_CURRENT_SOURCE_DIR}/int_auction.c"
"${CMAKE_CURRENT_SOURCE_DIR}/int_elemental.c"
"${CMAKE_CURRENT_SOURCE_DIR}/int_guild.c"
Index: src/char/int_homun.c
===================================================================
--- src/char/int_homun.c (revision 17373)
+++ src/char/int_homun.c (working copy)
@@ -95,7 +95,7 @@
if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` "
"(`char_id`, `class`,`prev_class`,`name`,`level`,`exp`,`intimacy`,`hunger`, `str`, `agi`, `vit`, `int`, `dex`, `luk`, `hp`,`max_hp`,`sp`,`max_sp`,`skill_point`, `rename_flag`, `vaporize`) "
"VALUES ('%d', '%d', '%d', '%s', '%d', '%u', '%u', '%d', '%d', %d, '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')",
- homunculus_db, hd->char_id, hd->class_, hd->prev_class, esc_name, hd->level, hd->exp, hd->intimacy, hd->hunger, hd->str, hd->agi, hd->vit, hd->int_, hd->dex, hd->luk,
+ schema_config.homunculus_db, hd->char_id, hd->class_, hd->prev_class, esc_name, hd->level, hd->exp, hd->intimacy, hd->hunger, hd->str, hd->agi, hd->vit, hd->int_, hd->dex, hd->luk,
hd->hp, hd->max_hp, hd->sp, hd->max_sp, hd->skillpts, hd->rename_flag, hd->vaporize) )
{
Sql_ShowDebug(sql_handle);
@@ -109,7 +109,7 @@
else
{
if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `char_id`='%d', `class`='%d',`prev_class`='%d',`name`='%s',`level`='%d',`exp`='%u',`intimacy`='%u',`hunger`='%d', `str`='%d', `agi`='%d', `vit`='%d', `int`='%d', `dex`='%d', `luk`='%d', `hp`='%d',`max_hp`='%d',`sp`='%d',`max_sp`='%d',`skill_point`='%d', `rename_flag`='%d', `vaporize`='%d' WHERE `homun_id`='%d'",
- homunculus_db, hd->char_id, hd->class_, hd->prev_class, esc_name, hd->level, hd->exp, hd->intimacy, hd->hunger, hd->str, hd->agi, hd->vit, hd->int_, hd->dex, hd->luk,
+ schema_config.homunculus_db, hd->char_id, hd->class_, hd->prev_class, esc_name, hd->level, hd->exp, hd->intimacy, hd->hunger, hd->str, hd->agi, hd->vit, hd->int_, hd->dex, hd->luk,
hd->hp, hd->max_hp, hd->sp, hd->max_sp, hd->skillpts, hd->rename_flag, hd->vaporize, hd->hom_id) )
{
Sql_ShowDebug(sql_handle);
@@ -121,7 +121,7 @@
int i;
stmt = SqlStmt_Malloc(sql_handle);
- if( SQL_ERROR == SqlStmt_Prepare(stmt, "REPLACE INTO `%s` (`homun_id`, `id`, `lv`) VALUES (%d, ?, ?)", skill_homunculus_db, hd->hom_id) )
+ if( SQL_ERROR == SqlStmt_Prepare(stmt, "REPLACE INTO `%s` (`homun_id`, `id`, `lv`) VALUES (%d, ?, ?)", schema_config.skill_homunculus_db, hd->hom_id) )
SqlStmt_ShowDebug(stmt);
for( i = 0; i < MAX_HOMUNSKILL; ++i )
{
@@ -156,7 +156,8 @@
memset(hd, 0, sizeof(*hd));
- if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `homun_id`,`char_id`,`class`,`prev_class`,`name`,`level`,`exp`,`intimacy`,`hunger`, `str`, `agi`, `vit`, `int`, `dex`, `luk`, `hp`,`max_hp`,`sp`,`max_sp`,`skill_point`,`rename_flag`, `vaporize` FROM `%s` WHERE `homun_id`='%u'", homunculus_db, homun_id) )
+ if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `homun_id`,`char_id`,`class`,`prev_class`,`name`,`level`,`exp`,`intimacy`,`hunger`, `str`, `agi`, `vit`, `int`, `dex`, `luk`, `hp`,`max_hp`,`sp`,`max_sp`,`skill_point`,`rename_flag`, `vaporize` FROM `%s` WHERE `homun_id`='%u'",
+ schema_config.homunculus_db, homun_id) )
{
Sql_ShowDebug(sql_handle);
return false;
@@ -202,7 +203,7 @@
hd->hunger = cap_value(hd->hunger, 0, 100);
// Load Homunculus Skill
- if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `id`,`lv` FROM `%s` WHERE `homun_id`=%d", skill_homunculus_db, homun_id) )
+ if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `id`,`lv` FROM `%s` WHERE `homun_id`=%d", schema_config.skill_homunculus_db, homun_id) )
{
Sql_ShowDebug(sql_handle);
return false;
@@ -223,7 +224,7 @@
}
Sql_FreeResult(sql_handle);
- if( save_log )
+ if( charserv_config.save_log )
ShowInfo("Homunculus loaded (%d - %s).\n", hd->hom_id, hd->name);
return true;
@@ -231,8 +232,8 @@
bool mapif_homunculus_delete(int homun_id)
{
- if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `homun_id` = '%u'", homunculus_db, homun_id)
- || SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `homun_id` = '%u'", skill_homunculus_db, homun_id)
+ if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `homun_id` = '%u'", schema_config.homunculus_db, homun_id)
+ || SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `homun_id` = '%u'", schema_config.skill_homunculus_db, homun_id)
) {
Sql_ShowDebug(sql_handle);
return false;
@@ -245,16 +246,16 @@
int i;
// Check Authorised letters/symbols in the name of the homun
- if( char_name_option == 1 )
+ if( charserv_config.char_name_option == 1 )
{// only letters/symbols in char_name_letters are authorised
for( i = 0; i < NAME_LENGTH && name[i]; i++ )
- if( strchr(char_name_letters, name[i]) == NULL )
+ if( strchr(charserv_config.char_name_letters, name[i]) == NULL )
return false;
} else
- if( char_name_option == 2 )
+ if( charserv_config.char_name_option == 2 )
{// letters/symbols in char_name_letters are forbidden
for( i = 0; i < NAME_LENGTH && name[i]; i++ )
- if( strchr(char_name_letters, name[i]) != NULL )
+ if( strchr(charserv_config.char_name_letters, name[i]) != NULL )
return false;
}
Index: src/char/Makefile.in
===================================================================
--- src/char/Makefile.in (revision 17373)
+++ src/char/Makefile.in (working copy)
@@ -15,12 +15,14 @@
COMMON_SQL_OBJ = ../common/obj_sql/sql.o
COMMON_H = ../common/sql.h
-CHAR_OBJ = obj_sql/char.o obj_sql/inter.o obj_sql/int_party.o obj_sql/int_guild.o \
- obj_sql/int_storage.o obj_sql/int_pet.o obj_sql/int_homun.o obj_sql/int_mail.o obj_sql/int_auction.o obj_sql/int_quest.o obj_sql/int_mercenary.o obj_sql/int_elemental.o
-CHAR_H = char.h inter.h int_party.h int_guild.h int_storage.h int_pet.h int_homun.h int_mail.h int_auction.h int_quest.h int_mercenary.h int_elemental.h
+CHAR_OBJ = char.o char_clif.o char_logif.o char_mapif.o char_cnslif.o\
+ inter.o int_party.o int_guild.o int_storage.o int_pet.o int_homun.o int_mail.o int_auction.o int_quest.o int_mercenary.o int_elemental.o
+CHAR_H = char.h \
+ inter.h int_party.h int_guild.h int_storage.h int_pet.h int_homun.h int_mail.h int_auction.h int_quest.h int_mercenary.h int_elemental.h
+CHAR_SQL_OBJ = $(CHAR_OBJ:%=obj_sql/%)
HAVE_MYSQL=@HAVE_MYSQL@
-ifeq ($(HAVE_MYSQL),yes)
+ifeq ($(HAVE_MYSQL),yes)
SQL_DEPENDS=char-server_sql
else
SQL_DEPENDS=needs_mysql
@@ -49,9 +51,9 @@
#####################################################################
-char-server_sql: obj_sql $(CHAR_OBJ) ../common/obj_sql/common_sql.a ../common/obj_all/common.a $(MT19937AR_OBJ)
+char-server_sql: obj_sql $(CHAR_SQL_OBJ) ../common/obj_sql/common_sql.a ../common/obj_all/common.a $(MT19937AR_OBJ)
@echo " LD $@"
- @@CC@ @LDFLAGS@ -o ../../char-server_sql@EXEEXT@ $(CHAR_OBJ) ../common/obj_sql/common_sql.a ../common/obj_all/common.a $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) @LIBS@ @MYSQL_LIBS@
+ @@CC@ @LDFLAGS@ -o ../../char-server_sql@EXEEXT@ $(CHAR_SQL_OBJ) ../common/obj_sql/common_sql.a ../common/obj_all/common.a $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) @LIBS@ @MYSQL_LIBS@
needs_mysql:
@echo "MySQL not found or disabled by the configure script"
Index: src/char/int_pet.c
===================================================================
--- src/char/int_pet.c (revision 17373)
+++ src/char/int_pet.c (working copy)
@@ -32,7 +32,7 @@
if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` "
"(`class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incuvate`) "
"VALUES ('%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')",
- pet_db, p->class_, esc_name, p->account_id, p->char_id, p->level, p->egg_id,
+ schema_config.pet_db, p->class_, esc_name, p->account_id, p->char_id, p->level, p->egg_id,
p->equip, p->intimate, p->hungry, p->rename_flag, p->incuvate) )
{
Sql_ShowDebug(sql_handle);
@@ -43,7 +43,7 @@
else
{// Update pet.
if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `class`='%d',`name`='%s',`account_id`='%d',`char_id`='%d',`level`='%d',`egg_id`='%d',`equip`='%d',`intimate`='%d',`hungry`='%d',`rename_flag`='%d',`incuvate`='%d' WHERE `pet_id`='%d'",
- pet_db, p->class_, esc_name, p->account_id, p->char_id, p->level, p->egg_id,
+ schema_config.pet_db, p->class_, esc_name, p->account_id, p->char_id, p->level, p->egg_id,
p->equip, p->intimate, p->hungry, p->rename_flag, p->incuvate, p->pet_id) )
{
Sql_ShowDebug(sql_handle);
@@ -51,7 +51,7 @@
}
}
- if (save_log)
+ if (charserv_config.save_log)
ShowInfo("Pet saved %d - %s.\n", pet_id, p->name);
return 1;
}
@@ -68,7 +68,7 @@
//`pet` (`pet_id`, `class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incuvate`)
- if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `pet_id`, `class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incuvate` FROM `%s` WHERE `pet_id`='%d'", pet_db, pet_id) )
+ if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `pet_id`, `class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incuvate` FROM `%s` WHERE `pet_id`='%d'", schema_config.pet_db, pet_id) )
{
Sql_ShowDebug(sql_handle);
return 0;
@@ -94,7 +94,7 @@
p->hungry = cap_value(p->hungry, 0, 100);
p->intimate = cap_value(p->intimate, 0, 1000);
- if( save_log )
+ if( charserv_config.save_log )
ShowInfo("Pet loaded (%d - %s).\n", pet_id, p->name);
}
return 0;
@@ -114,7 +114,7 @@
int inter_pet_delete(int pet_id){
ShowInfo("delete pet request: %d...\n",pet_id);
- if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `pet_id`='%d'", pet_db, pet_id) )
+ if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `pet_id`='%d'", schema_config.pet_db, pet_id) )
Sql_ShowDebug(sql_handle);
return 0;
}
Index: src/char/int_quest.c
===================================================================
--- src/char/int_quest.c (revision 17373)
+++ src/char/int_quest.c (working copy)
@@ -34,7 +34,7 @@
memset(&tmp_quest, 0, sizeof(struct quest));
- if( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT `quest_id`, `state`, `time`, `count1`, `count2`, `count3` FROM `%s` WHERE `char_id`=? LIMIT %d", quest_db, MAX_QUEST_DB)
+ if( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT `quest_id`, `state`, `time`, `count1`, `count2`, `count3` FROM `%s` WHERE `char_id`=? LIMIT %d", schema_config.quest_db, MAX_QUEST_DB)
|| SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0)
|| SQL_ERROR == SqlStmt_Execute(stmt)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 0, SQLDT_INT, &tmp_quest.quest_id, 0, NULL, NULL)
@@ -55,7 +55,7 @@
//Delete a quest
bool mapif_quest_delete(int char_id, int quest_id)
{
- if ( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `quest_id` = '%d' AND `char_id` = '%d'", quest_db, quest_id, char_id) )
+ if ( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `quest_id` = '%d' AND `char_id` = '%d'", schema_config.quest_db, quest_id, char_id) )
{
Sql_ShowDebug(sql_handle);
return false;
@@ -67,7 +67,7 @@
//Add a quest to a questlog
bool mapif_quest_add(int char_id, struct quest qd)
{
- if ( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s`(`quest_id`, `char_id`, `state`, `time`, `count1`, `count2`, `count3`) VALUES ('%d', '%d', '%d','%d', '%d', '%d', '%d')", quest_db, qd.quest_id, char_id, qd.state, qd.time, qd.count[0], qd.count[1], qd.count[2]) )
+ if ( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s`(`quest_id`, `char_id`, `state`, `time`, `count1`, `count2`, `count3`) VALUES ('%d', '%d', '%d','%d', '%d', '%d', '%d')", schema_config.quest_db, qd.quest_id, char_id, qd.state, qd.time, qd.count[0], qd.count[1], qd.count[2]) )
{
Sql_ShowDebug(sql_handle);
return false;
@@ -79,7 +79,7 @@
//Update a questlog
bool mapif_quest_update(int char_id, struct quest qd)
{
- if ( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `state`='%d', `count1`='%d', `count2`='%d', `count3`='%d' WHERE `quest_id` = '%d' AND `char_id` = '%d'", quest_db, qd.state, qd.count[0], qd.count[1], qd.count[2], qd.quest_id, char_id) )
+ if ( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `state`='%d', `count1`='%d', `count2`='%d', `count3`='%d' WHERE `quest_id` = '%d' AND `char_id` = '%d'", schema_config.quest_db, qd.state, qd.count[0], qd.count[1], qd.count[2], qd.quest_id, char_id) )
{
Sql_ShowDebug(sql_handle);
return false;
Index: src/char/int_auction.c
===================================================================
--- src/char/int_auction.c (revision 17373)
+++ src/char/int_auction.c (working copy)
@@ -10,6 +10,7 @@
#include "../common/sql.h"
#include "../common/timer.h"
#include "char.h"
+#include "char_mapif.h"
#include "inter.h"
#include "int_mail.h"
#include "int_auction.h"
@@ -50,7 +51,7 @@
StringBuf_Init(&buf);
StringBuf_Printf(&buf, "UPDATE `%s` SET `seller_id` = '%d', `seller_name` = ?, `buyer_id` = '%d', `buyer_name` = ?, `price` = '%d', `buynow` = '%d', `hours` = '%d', `timestamp` = '%lu', `nameid` = '%d', `item_name` = ?, `type` = '%d', `refine` = '%d', `attribute` = '%d'",
- auction_db, auction->seller_id, auction->buyer_id, auction->price, auction->buynow, auction->hours, (unsigned long)auction->timestamp, auction->item.nameid, auction->type, auction->item.refine, auction->item.attribute);
+ schema_config.auction_db, auction->seller_id, auction->buyer_id, auction->price, auction->buynow, auction->hours, (unsigned long)auction->timestamp, auction->item.nameid, auction->type, auction->item.refine, auction->item.attribute);
for( j = 0; j < MAX_SLOTS; j++ )
StringBuf_Printf(&buf, ", `card%d` = '%d'", j, auction->item.card[j]);
StringBuf_Printf(&buf, " WHERE `auction_id` = '%d'", auction->auction_id);
@@ -81,7 +82,7 @@
auction->timestamp = time(NULL) + (auction->hours * 3600);
StringBuf_Init(&buf);
- StringBuf_Printf(&buf, "INSERT INTO `%s` (`seller_id`,`seller_name`,`buyer_id`,`buyer_name`,`price`,`buynow`,`hours`,`timestamp`,`nameid`,`item_name`,`type`,`refine`,`attribute`,`unique_id`", auction_db);
+ StringBuf_Printf(&buf, "INSERT INTO `%s` (`seller_id`,`seller_name`,`buyer_id`,`buyer_name`,`price`,`buynow`,`hours`,`timestamp`,`nameid`,`item_name`,`type`,`refine`,`attribute`,`unique_id`", schema_config.auction_db);
for( j = 0; j < MAX_SLOTS; j++ )
StringBuf_Printf(&buf, ",`card%d`", j);
StringBuf_Printf(&buf, ") VALUES ('%d',?,'%d',?,'%d','%d','%d','%lu','%d',?,'%d','%d','%d','%"PRIu64"'",
@@ -165,7 +166,7 @@
{
unsigned int auction_id = auction->auction_id;
- if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `auction_id` = '%d'", auction_db, auction_id) )
+ if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `auction_id` = '%d'", schema_config.auction_db, auction_id) )
Sql_ShowDebug(sql_handle);
if( auction->auction_end_timer != INVALID_TIMER )
@@ -189,7 +190,7 @@
"`price`,`buynow`,`hours`,`timestamp`,`nameid`,`item_name`,`type`,`refine`,`attribute`,`unique_id`");
for( i = 0; i < MAX_SLOTS; i++ )
StringBuf_Printf(&buf, ",`card%d`", i);
- StringBuf_Printf(&buf, " FROM `%s` ORDER BY `auction_id` DESC", auction_db);
+ StringBuf_Printf(&buf, " FROM `%s` ORDER BY `auction_id` DESC", schema_config.auction_db);
if( SQL_ERROR == Sql_Query(sql_handle, StringBuf_Value(&buf)) )
Sql_ShowDebug(sql_handle);
Index: src/char/char.c
===================================================================
--- src/char/char.c (revision 17373)
+++ src/char/char.c (working copy)
@@ -21,8 +21,12 @@
#include "int_elemental.h"
#include "int_party.h"
#include "int_storage.h"
+#include "inter.h"
+#include "char_logif.h"
+#include "char_mapif.h"
+#include "char_cnslif.h"
+#include "char_clif.h"
#include "char.h"
-#include "inter.h"
#include <sys/types.h>
#include <time.h>
@@ -33,88 +37,22 @@
#include <stdlib.h>
#include <malloc.h>
-#define MAX_STARTITEM 32
+
#define CHAR_MAX_MSG 300
static char* msg_table[CHAR_MAX_MSG]; // Login Server messages_conf
-char char_db[256] = "char";
-char scdata_db[256] = "sc_data";
-char cart_db[256] = "cart_inventory";
-char inventory_db[256] = "inventory";
-char charlog_db[256] = "charlog";
-char storage_db[256] = "storage";
-char interlog_db[256] = "interlog";
-char reg_db[256] = "global_reg_value";
-char skill_db[256] = "skill";
-char memo_db[256] = "memo";
-char guild_db[256] = "guild";
-char guild_alliance_db[256] = "guild_alliance";
-char guild_castle_db[256] = "guild_castle";
-char guild_expulsion_db[256] = "guild_expulsion";
-char guild_member_db[256] = "guild_member";
-char guild_position_db[256] = "guild_position";
-char guild_skill_db[256] = "guild_skill";
-char guild_storage_db[256] = "guild_storage";
-char party_db[256] = "party";
-char pet_db[256] = "pet";
-char mail_db[256] = "mail"; // MAIL SYSTEM
-char auction_db[256] = "auction"; // Auctions System
-char friend_db[256] = "friends";
-char hotkey_db[256] = "hotkey";
-char quest_db[256] = "quest";
-char homunculus_db[256] = "homunculus";
-char skill_homunculus_db[256] = "skill_homunculus";
-char mercenary_db[256] = "mercenary";
-char mercenary_owner_db[256] = "mercenary_owner";
-char ragsrvinfo_db[256] = "ragsrvinfo";
+// check for exit signal
+// 0 is saving complete
+// other is char_id
+unsigned int save_flag = 0;
-// show loading/saving messages
-int save_log = 1;
+#define MAX_STARTITEM 32
+struct startitem {
+ int nameid; //Item ID
+ int amount; //Number of items
+ int pos; //Position (for auto-equip)
+} start_items[MAX_STARTITEM+1];
-static DBMap* char_db_; // int char_id -> struct mmo_charstatus*
-
-char db_path[1024] = "db";
-
-int db_use_sqldbs;
-
-struct mmo_map_server {
- int fd;
- uint32 ip;
- uint16 port;
- int users;
- unsigned short map[MAX_MAP_PER_SERVER];
-} server[MAX_MAP_SERVERS];
-
-int login_fd=-1, char_fd=-1;
-char userid[24];
-char passwd[24];
-char server_name[20];
-char wisp_server_name[NAME_LENGTH] = "Server";
-char login_ip_str[128];
-uint32 login_ip = 0;
-uint16 login_port = 6900;
-char char_ip_str[128];
-uint32 char_ip = 0;
-char bind_ip_str[128];
-uint32 bind_ip = INADDR_ANY;
-uint16 char_port = 6121;
-int char_maintenance = 0;
-bool char_new = true;
-int char_new_display = 0;
-
-bool name_ignoring_case = false; // Allow or not identical name for characters but with a different case by [Yor]
-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]
-char unknown_char_name[NAME_LENGTH] = "Unknown"; // Name to use when the requested name cannot be determined
-#define TRIM_CHARS "\255\xA0\032\t\x0A\x0D " //The following characters are trimmed regardless because they cause confusion and problems on the servers. [Skotlex]
-char char_name_letters[1024] = ""; // list of letters/symbols allowed (or not) in a character name. by [Yor]
-
-int char_per_account = 0; //Maximum chars per account (default unlimited) [Sirius]
-int char_del_level = 0; //From which level u can delete character [Lupus]
-int char_del_delay = 86400;
-
-int log_char = 1; // loggin char or not [devil]
-int log_inter = 1; // loggin inter or not [devil]
-
// Advanced subnet check [LuzZza]
struct s_subnet {
uint32 mask;
@@ -123,130 +61,17 @@
} subnet[16];
int subnet_count = 0;
-struct char_session_data {
- bool auth; // whether the session is authed or not
- int account_id, login_id1, login_id2, sex;
- int found_char[MAX_CHARS]; // ids of chars on this account
- char email[40]; // e-mail (default: [email protected]) by [Yor]
- time_t expiration_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited)
- int group_id; // permission
- uint8 char_slots;
- uint32 version;
- uint8 clienttype;
- char new_name[NAME_LENGTH];
- char birthdate[10+1]; // YYYY-MM-DD
- // Pincode system
- char pincode[PINCODE_LENGTH+1];
- uint32 pincode_seed;
- time_t pincode_change;
- uint16 pincode_try;
- // Addon system
- unsigned int char_moves[MAX_CHARS]; // character moves left
-};
+DBMap* auth_db; // int account_id -> struct auth_node*
+DBMap* online_char_db; // int account_id -> struct online_char_data*
+DBMap* char_db_; // int char_id -> struct mmo_charstatus*
+DBMap* char_get_authdb() { return auth_db; }
+DBMap* char_get_onlinedb() { return online_char_db; }
+DBMap* char_get_chardb() { return char_db_; }
-struct startitem {
- int nameid; //Item ID
- int amount; //Number of items
- int pos; //Position (for auto-equip)
-} start_items[MAX_STARTITEM+1];
-
-int max_connect_user = -1;
-int gm_allow_group = -1;
-int autosave_interval = DEFAULT_AUTOSAVE_INTERVAL;
-int start_zeny = 0;
-int guild_exp_rate = 100;
-
-// Pincode system
-#define PINCODE_OK 0
-#define PINCODE_ASK 1
-#define PINCODE_NOTSET 2
-#define PINCODE_EXPIRED 3
-#define PINCODE_NEW 4
-#define PINCODE_PASSED 7
-#define PINCODE_WRONG 8
-
-bool pincode_enabled = true;
-int pincode_changetime = 0;
-int pincode_maxtry = 3;
-bool pincode_force = true;
-
-void pincode_check( int fd, struct char_session_data* sd );
-void pincode_change( int fd, struct char_session_data* sd );
-void pincode_setnew( int fd, struct char_session_data* sd );
-void pincode_sendstate( int fd, struct char_session_data* sd, uint16 state );
-void pincode_notifyLoginPinUpdate( int account_id, char* pin );
-void pincode_notifyLoginPinError( int account_id );
-void pincode_decrypt( uint32 userSeed, char* pin );
-int pincode_compare( int fd, struct char_session_data* sd, char* pin );
-
-// Addon system
-bool char_move_enabled = true;
-bool char_movetoused = true;
-bool char_moves_unlimited = false;
-
-void moveCharSlot( int fd, struct char_session_data* sd, unsigned short from, unsigned short to );
-void moveCharSlotReply( int fd, struct char_session_data* sd, unsigned short index, short reason );
-
-//Custom limits for the fame lists. [Skotlex]
-int fame_list_size_chemist = MAX_FAME_LIST;
-int fame_list_size_smith = MAX_FAME_LIST;
-int fame_list_size_taekwon = MAX_FAME_LIST;
-
-// Char-server-side stored fame lists [DracoRPG]
-struct fame_list smith_fame_list[MAX_FAME_LIST];
-struct fame_list chemist_fame_list[MAX_FAME_LIST];
-struct fame_list taekwon_fame_list[MAX_FAME_LIST];
-
-// check for exit signal
-// 0 is saving complete
-// other is char_id
-unsigned int save_flag = 0;
-
-// Initial position (it's possible to set it in conf file)
-struct point start_point = { 0, 53, 111 };
-
-int console = 0;
-
-//-----------------------------------------------------
-// Auth database
-//-----------------------------------------------------
-#define AUTH_TIMEOUT 30000
-
-struct auth_node {
- int account_id;
- int char_id;
- uint32 login_id1;
- uint32 login_id2;
- uint32 ip;
- int sex;
- time_t expiration_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited)
- int group_id;
- unsigned changing_mapservers : 1;
-};
-
-static DBMap* auth_db; // int account_id -> struct auth_node*
-
-//-----------------------------------------------------
-// Online User Database
-//-----------------------------------------------------
-
-struct online_char_data {
- int account_id;
- int char_id;
- int fd;
- int waiting_disconnect;
- short server; // -2: unknown server, -1: not connected, 0+: id of server
- bool pincode_success;
-};
-
-static DBMap* online_char_db; // int account_id -> struct online_char_data*
-static int chardb_waiting_disconnect(int tid, unsigned int tick, int id, intptr_t data);
-int delete_char_sql(int char_id);
-
/**
* @see DBCreateData
*/
-static DBData create_online_char_data(DBKey key, va_list args)
+DBData create_online_char_data(DBKey key, va_list args)
{
struct online_char_data* character;
CREATE(character, struct online_char_data, 1);
@@ -276,13 +101,7 @@
character->waiting_disconnect = INVALID_TIMER;
}
- if (login_fd > 0 && !session[login_fd]->flag.eof)
- {
- WFIFOHEAD(login_fd,6);
- WFIFOW(login_fd,0) = 0x272b;
- WFIFOL(login_fd,2) = account_id;
- WFIFOSET(login_fd,6);
- }
+ char_send_setacconline(account_id);
}
@@ -292,7 +111,7 @@
struct mmo_charstatus *cp;
//Update DB
- if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `online`='1' WHERE `char_id`='%d' LIMIT 1", char_db, char_id) )
+ if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `online`='1' WHERE `char_id`='%d' LIMIT 1", schema_config.char_db, char_id) )
Sql_ShowDebug(sql_handle);
//Check to see for online conflicts
@@ -322,13 +141,7 @@
inter_guild_CharOnline(char_id, cp?cp->guild_id:-1);
//Notify login server
- if (login_fd > 0 && !session[login_fd]->flag.eof)
- {
- WFIFOHEAD(login_fd,6);
- WFIFOW(login_fd,0) = 0x272b;
- WFIFOL(login_fd,2) = account_id;
- WFIFOSET(login_fd,6);
- }
+ char_send_setacconline(account_id);
}
void set_char_offline(int char_id, int account_id)
@@ -337,7 +150,7 @@
if ( char_id == -1 )
{
- if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `online`='0' WHERE `account_id`='%d'", char_db, account_id) )
+ if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `online`='0' WHERE `account_id`='%d'", schema_config.char_db, account_id) )
Sql_ShowDebug(sql_handle);
}
else
@@ -347,7 +160,7 @@
if (cp)
idb_remove(char_db_,char_id);
- if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `online`='0' WHERE `char_id`='%d' LIMIT 1", char_db, char_id) )
+ if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `online`='0' WHERE `char_id`='%d' LIMIT 1", schema_config.char_db, char_id) )
Sql_ShowDebug(sql_handle);
}
@@ -374,20 +187,15 @@
}
//Remove char if 1- Set all offline, or 2- character is no longer connected to char-server.
- if (login_fd > 0 && !session[login_fd]->flag.eof && (char_id == -1 || character == NULL || character->fd == -1))
- {
- WFIFOHEAD(login_fd,6);
- WFIFOW(login_fd,0) = 0x272c;
- WFIFOL(login_fd,2) = account_id;
- WFIFOSET(login_fd,6);
+ if (char_id == -1 || character == NULL || character->fd == -1){
+ char_send_setaccoffline(login_fd,account_id);
}
}
/**
* @see DBApply
*/
-static int char_db_setoffline(DBKey key, DBData *data, va_list ap)
-{
+int char_db_setoffline(DBKey key, DBData *data, va_list ap) {
struct online_char_data* character = (struct online_char_data*)db_data2ptr(data);
int server = va_arg(ap, int);
if (server == -1) {
@@ -434,20 +242,17 @@
if (id >= 0 || login_fd <= 0 || session[login_fd]->flag.eof)
return;
- //Tell login-server to also mark all our characters as offline.
- WFIFOHEAD(login_fd,2);
- WFIFOW(login_fd,0) = 0x2737;
- WFIFOSET(login_fd,2);
+ char_send_setallaccoffline(login_fd);
}
void set_all_offline_sql(void)
{
//Set all players to 'OFFLINE'
- if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `online` = '0'", char_db) )
+ if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `online` = '0'", schema_config.char_db) )
Sql_ShowDebug(sql_handle);
- if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `online` = '0'", guild_member_db) )
+ if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `online` = '0'", schema_config.guild_member_db) )
Sql_ShowDebug(sql_handle);
- if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `connect_member` = '0'", guild_db) )
+ if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `connect_member` = '0'", schema_config.guild_db) )
Sql_ShowDebug(sql_handle);
}
@@ -533,7 +338,7 @@
"`last_map`='%s',`last_x`='%d',`last_y`='%d',`save_map`='%s',`save_x`='%d',`save_y`='%d', `rename`='%d',"
"`delete_date`='%lu',`robe`='%d',`moves`='%d'"
" WHERE `account_id`='%d' AND `char_id` = '%d'",
- char_db, p->base_level, p->job_level,
+ schema_config.char_db, p->base_level, p->job_level,
p->base_exp, p->job_exp, p->zeny,
p->max_hp, p->hp, p->max_sp, p->sp, p->status_point, p->skill_point,
p->str, p->agi, p->vit, p->int_, p->dex, p->luk,
@@ -566,7 +371,7 @@
"`partner_id`='%d', `father`='%d', `mother`='%d', `child`='%d',"
"`karma`='%d',`manner`='%d', `fame`='%d'"
" WHERE `account_id`='%d' AND `char_id` = '%d'",
- char_db, p->class_,
+ schema_config.char_db, p->class_,
p->hair, p->hair_color, p->clothes_color,
p->partner_id, p->father, p->mother, p->child,
p->karma, p->manner, p->fame,
@@ -596,7 +401,7 @@
char esc_mapname[NAME_LENGTH*2+1];
//`memo` (`memo_id`,`char_id`,`map`,`x`,`y`)
- if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", memo_db, p->char_id) )
+ if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", schema_config.memo_db, p->char_id) )
{
Sql_ShowDebug(sql_handle);
errors++;
@@ -604,7 +409,7 @@
//insert here.
StringBuf_Clear(&buf);
- StringBuf_Printf(&buf, "INSERT INTO `%s`(`char_id`,`map`,`x`,`y`) VALUES ", memo_db);
+ StringBuf_Printf(&buf, "INSERT INTO `%s`(`char_id`,`map`,`x`,`y`) VALUES ", schema_config.memo_db);
for( i = 0, count = 0; i < MAX_MEMOPOINTS; ++i )
{
if( p->memo_point[i].map )
@@ -637,14 +442,14 @@
if( memcmp(p->skill, cp->skill, sizeof(p->skill)) )
{
//`skill` (`char_id`, `id`, `lv`)
- if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", skill_db, p->char_id) )
+ if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", schema_config.skill_db, p->char_id) )
{
Sql_ShowDebug(sql_handle);
errors++;
}
StringBuf_Clear(&buf);
- StringBuf_Printf(&buf, "INSERT INTO `%s`(`char_id`,`id`,`lv`,`flag`) VALUES ", skill_db);
+ StringBuf_Printf(&buf, "INSERT INTO `%s`(`char_id`,`id`,`lv`,`flag`) VALUES ", schema_config.skill_db);
//insert here.
for( i = 0, count = 0; i < MAX_SKILL; ++i ) {
if( p->skill[i].id != 0 && p->skill[i].flag != SKILL_FLAG_TEMPORARY ) {
@@ -684,14 +489,14 @@
if(diff == 1)
{ //Save friends
- if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", friend_db, char_id) )
+ if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", schema_config.friend_db, char_id) )
{
Sql_ShowDebug(sql_handle);
errors++;
}
StringBuf_Clear(&buf);
- StringBuf_Printf(&buf, "INSERT INTO `%s` (`char_id`, `friend_account`, `friend_id`) VALUES ", friend_db);
+ StringBuf_Printf(&buf, "INSERT INTO `%s` (`char_id`, `friend_account`, `friend_id`) VALUES ", schema_config.friend_db);
for( i = 0, count = 0; i < MAX_FRIENDS; ++i )
{
if( p->friends[i].char_id > 0 )
@@ -716,7 +521,7 @@
#ifdef HOTKEY_SAVING
// hotkeys
StringBuf_Clear(&buf);
- StringBuf_Printf(&buf, "REPLACE INTO `%s` (`char_id`, `hotkey`, `type`, `itemskill_id`, `skill_lvl`) VALUES ", hotkey_db);
+ StringBuf_Printf(&buf, "REPLACE INTO `%s` (`char_id`, `hotkey`, `type`, `itemskill_id`, `skill_lvl`) VALUES ", schema_config.hotkey_db);
diff = 0;
for(i = 0; i < ARRAYLENGTH(p->hotkeys); i++){
if(memcmp(&p->hotkeys[i], &cp->hotkeys[i], sizeof(struct hotkey)))
@@ -737,7 +542,7 @@
}
#endif
StringBuf_Destroy(&buf);
- if (save_status[0]!='\0' && save_log)
+ if (save_status[0]!='\0' && charserv_config.save_log)
ShowInfo("Saved char %d - %s:%s.\n", char_id, p->name, save_status);
if (!errors)
memcpy(cp, p, sizeof(struct mmo_charstatus));
@@ -759,10 +564,10 @@
int errors = 0;
switch (tableswitch) {
- case TABLE_INVENTORY: tablename = inventory_db; selectoption = "char_id"; break;
- case TABLE_CART: tablename = cart_db; selectoption = "char_id"; break;
- case TABLE_STORAGE: tablename = storage_db; selectoption = "account_id"; break;
- case TABLE_GUILD_STORAGE: tablename = guild_storage_db; selectoption = "guild_id"; break;
+ case TABLE_INVENTORY: tablename = schema_config.inventory_db; selectoption = "char_id"; break;
+ case TABLE_CART: tablename = schema_config.cart_db; selectoption = "char_id"; break;
+ case TABLE_STORAGE: tablename = schema_config.storage_db; selectoption = "account_id"; break;
+ case TABLE_GUILD_STORAGE: tablename = schema_config.guild_storage_db; selectoption = "guild_id"; break;
default:
ShowError("Invalid table name!\n");
return 1;
@@ -924,7 +729,7 @@
StringBuf_AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `favorite`, `bound`");
for( j = 0; j < MAX_SLOTS; ++j )
StringBuf_Printf(&buf, ", `card%d`", j);
- StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`='%d'", inventory_db, id);
+ StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`='%d'", schema_config.inventory_db, id);
stmt = SqlStmt_Malloc(sql_handle);
if( SQL_ERROR == SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf))
@@ -980,7 +785,7 @@
// update all fields.
StringBuf_Clear(&buf);
StringBuf_Printf(&buf, "UPDATE `%s` SET `amount`='%d', `equip`='%d', `identify`='%d', `refine`='%d',`attribute`='%d', `expire_time`='%u', `favorite`='%d', `bound`='%d'",
- inventory_db, items[i].amount, items[i].equip, items[i].identify, items[i].refine, items[i].attribute, items[i].expire_time, items[i].favorite, items[i].bound);
+ schema_config.inventory_db, items[i].amount, items[i].equip, items[i].identify, items[i].refine, items[i].attribute, items[i].expire_time, items[i].favorite, items[i].bound);
for( j = 0; j < MAX_SLOTS; ++j )
StringBuf_Printf(&buf, ", `card%d`=%d", j, items[i].card[j]);
StringBuf_Printf(&buf, " WHERE `id`='%d' LIMIT 1", item.id);
@@ -996,7 +801,7 @@
}
}
if( !found ) {// Item not present in inventory, remove it.
- if( SQL_ERROR == Sql_Query(sql_handle, "DELETE from `%s` where `id`='%d' LIMIT 1", inventory_db, item.id) ) {
+ if( SQL_ERROR == Sql_Query(sql_handle, "DELETE from `%s` where `id`='%d' LIMIT 1", schema_config.inventory_db, item.id) ) {
Sql_ShowDebug(sql_handle);
errors++;
}
@@ -1005,7 +810,7 @@
SqlStmt_Free(stmt);
StringBuf_Clear(&buf);
- StringBuf_Printf(&buf, "INSERT INTO `%s` (`char_id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `favorite`, `bound`, `unique_id`", inventory_db);
+ StringBuf_Printf(&buf, "INSERT INTO `%s` (`char_id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `favorite`, `bound`, `unique_id`", schema_config.inventory_db);
for( j = 0; j < MAX_SLOTS; ++j )
StringBuf_Printf(&buf, ", `card%d`", j);
StringBuf_AppendStr(&buf, ") VALUES ");
@@ -1074,7 +879,7 @@
"`status_point`,`skill_point`,`option`,`karma`,`manner`,`hair`,`hair_color`,"
"`clothes_color`,`weapon`,`shield`,`head_top`,`head_mid`,`head_bottom`,`last_map`,`rename`,`delete_date`,"
"`robe`,`moves`"
- " FROM `%s` WHERE `account_id`='%d' AND `char_num` < '%d'", char_db, sd->account_id, MAX_CHARS)
+ " FROM `%s` WHERE `account_id`='%d' AND `char_num` < '%d'", schema_config.char_db, sd->account_id, MAX_CHARS)
|| SQL_ERROR == SqlStmt_Execute(stmt)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 0, SQLDT_INT, &p.char_id, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 1, SQLDT_UCHAR, &p.slot, 0, NULL, NULL)
@@ -1159,7 +964,7 @@
memset(p, 0, sizeof(struct mmo_charstatus));
- if (save_log) ShowInfo("Char load request (%d)\n", char_id);
+ if (charserv_config.save_log) ShowInfo("Char load request (%d)\n", char_id);
stmt = SqlStmt_Malloc(sql_handle);
if( stmt == NULL )
@@ -1175,7 +980,7 @@
"`status_point`,`skill_point`,`option`,`karma`,`manner`,`party_id`,`guild_id`,`pet_id`,`homun_id`,`elemental_id`,`hair`,"
"`hair_color`,`clothes_color`,`weapon`,`shield`,`head_top`,`head_mid`,`head_bottom`,`last_map`,`last_x`,`last_y`,"
"`save_map`,`save_x`,`save_y`,`partner_id`,`father`,`mother`,`child`,`fame`,`rename`,`delete_date`,`robe`, `moves`"
- " FROM `%s` WHERE `char_id`=? LIMIT 1", char_db)
+ " FROM `%s` WHERE `char_id`=? LIMIT 1", schema_config.char_db)
|| SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0)
|| SQL_ERROR == SqlStmt_Execute(stmt)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 0, SQLDT_INT, &p->char_id, 0, NULL, NULL)
@@ -1268,7 +1073,7 @@
//read memo data
//`memo` (`memo_id`,`char_id`,`map`,`x`,`y`)
- if( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT `map`,`x`,`y` FROM `%s` WHERE `char_id`=? ORDER by `memo_id` LIMIT %d", memo_db, MAX_MEMOPOINTS)
+ if( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT `map`,`x`,`y` FROM `%s` WHERE `char_id`=? ORDER by `memo_id` LIMIT %d", schema_config.memo_db, MAX_MEMOPOINTS)
|| SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0)
|| SQL_ERROR == SqlStmt_Execute(stmt)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 0, SQLDT_STRING, &point_map, sizeof(point_map), NULL, NULL)
@@ -1289,7 +1094,7 @@
StringBuf_AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `favorite`, `bound`, `unique_id`");
for( i = 0; i < MAX_SLOTS; ++i )
StringBuf_Printf(&buf, ", `card%d`", i);
- StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`=? LIMIT %d", inventory_db, MAX_INVENTORY);
+ StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`=? LIMIT %d", schema_config.inventory_db, MAX_INVENTORY);
if( SQL_ERROR == SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf))
|| SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0)
@@ -1321,7 +1126,7 @@
StringBuf_AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `bound`, `unique_id`");
for( j = 0; j < MAX_SLOTS; ++j )
StringBuf_Printf(&buf, ", `card%d`", j);
- StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`=? LIMIT %d", cart_db, MAX_CART);
+ StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`=? LIMIT %d", schema_config.cart_db, MAX_CART);
if( SQL_ERROR == SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf))
|| SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0)
@@ -1351,7 +1156,7 @@
//read skill
//`skill` (`char_id`, `id`, `lv`)
- if( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT `id`, `lv`,`flag` FROM `%s` WHERE `char_id`=? LIMIT %d", skill_db, MAX_SKILL)
+ if( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT `id`, `lv`,`flag` FROM `%s` WHERE `char_id`=? LIMIT %d", schema_config.skill_db, MAX_SKILL)
|| SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0)
|| SQL_ERROR == SqlStmt_Execute(stmt)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 0, SQLDT_USHORT, &tmp_skill.id , 0, NULL, NULL)
@@ -1373,7 +1178,7 @@
//read friends
//`friends` (`char_id`, `friend_account`, `friend_id`)
- if( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT c.`account_id`, c.`char_id`, c.`name` FROM `%s` c LEFT JOIN `%s` f ON f.`friend_account` = c.`account_id` AND f.`friend_id` = c.`char_id` WHERE f.`char_id`=? LIMIT %d", char_db, friend_db, MAX_FRIENDS)
+ if( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT c.`account_id`, c.`char_id`, c.`name` FROM `%s` c LEFT JOIN `%s` f ON f.`friend_account` = c.`account_id` AND f.`friend_id` = c.`char_id` WHERE f.`char_id`=? LIMIT %d", schema_config.char_db, schema_config.friend_db, MAX_FRIENDS)
|| SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0)
|| SQL_ERROR == SqlStmt_Execute(stmt)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 0, SQLDT_INT, &tmp_friend.account_id, 0, NULL, NULL)
@@ -1388,7 +1193,7 @@
#ifdef HOTKEY_SAVING
//read hotkeys
//`hotkey` (`char_id`, `hotkey`, `type`, `itemskill_id`, `skill_lvl`
- if( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT `hotkey`, `type`, `itemskill_id`, `skill_lvl` FROM `%s` WHERE `char_id`=?", hotkey_db)
+ if( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT `hotkey`, `type`, `itemskill_id`, `skill_lvl` FROM `%s` WHERE `char_id`=?", schema_config.hotkey_db)
|| SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0)
|| SQL_ERROR == SqlStmt_Execute(stmt)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 0, SQLDT_INT, &hotkey_num, 0, NULL, NULL)
@@ -1412,7 +1217,7 @@
strcat(t_msg, " mercenary");
- if (save_log) ShowInfo("Loaded char (%d - %s): %s\n", char_id, p->name, t_msg); //ok. all data load successfuly!
+ if (charserv_config.save_log) ShowInfo("Loaded char (%d - %s): %s\n", char_id, p->name, t_msg); //ok. all data load successfuly!
SqlStmt_Free(stmt);
StringBuf_Destroy(&buf);
@@ -1426,7 +1231,7 @@
{
char_db_= idb_alloc(DB_OPT_RELEASE_DATA);
- ShowStatus("Characters per Account: '%d'.\n", char_per_account);
+ ShowStatus("Characters per Account: '%d'.\n", char_config.char_per_account);
//the 'set offline' part is now in check_login_conn ...
//if the server connects to loginserver
@@ -1460,13 +1265,13 @@
Sql_EscapeStringLen(sql_handle, esc_name, sd->new_name, strnlen(sd->new_name, NAME_LENGTH));
// check if the char exist
- if( SQL_ERROR == Sql_Query(sql_handle, "SELECT 1 FROM `%s` WHERE `name` LIKE '%s' LIMIT 1", char_db, esc_name) )
+ if( SQL_ERROR == Sql_Query(sql_handle, "SELECT 1 FROM `%s` WHERE `name` LIKE '%s' LIMIT 1", schema_config.char_db, esc_name) )
{
Sql_ShowDebug(sql_handle);
return 4;
}
- if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `name` = '%s', `rename` = '%d' WHERE `char_id` = '%d'", char_db, esc_name, --char_dat.rename, char_id) )
+ if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `name` = '%s', `rename` = '%d' WHERE `char_id` = '%d'", schema_config.char_db, esc_name, --char_dat.rename, char_id) )
{
Sql_ShowDebug(sql_handle);
return 3;
@@ -1480,11 +1285,11 @@
memset(sd->new_name,0,sizeof(sd->new_name));
// log change
- if( log_char )
+ if( charserv_config.log_char )
{
if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` (`time`, `char_msg`,`account_id`,`char_num`,`name`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`hair`,`hair_color`)"
"VALUES (NOW(), '%s', '%d', '%d', '%s', '0', '0', '0', '0', '0', '0', '0', '0')",
- charlog_db, "change char name", sd->account_id, char_dat.slot, esc_name) )
+ schema_config.charlog_db, "change char name", sd->account_id, char_dat.slot, esc_name) )
Sql_ShowDebug(sql_handle);
}
@@ -1509,29 +1314,29 @@
return -2; // control chars in name
// check for reserved names
- if( strcmpi(name, wisp_server_name) == 0 )
+ if( strcmpi(name, charserv_config.wisp_server_name) == 0 )
return -1; // nick reserved for internal server messages
// Check Authorised letters/symbols in the name of the character
- if( char_name_option == 1 )
+ if( charserv_config.char_name_option == 1 )
{ // only letters/symbols in char_name_letters are authorised
for( i = 0; i < NAME_LENGTH && name[i]; i++ )
- if( strchr(char_name_letters, name[i]) == NULL )
+ if( strchr(charserv_config.char_name_letters, name[i]) == NULL )
return -2;
}
- else if( char_name_option == 2 )
+ else if( charserv_config.char_name_option == 2 )
{ // letters/symbols in char_name_letters are forbidden
for( i = 0; i < NAME_LENGTH && name[i]; i++ )
- if( strchr(char_name_letters, name[i]) != NULL )
+ if( strchr(charserv_config.char_name_letters, name[i]) != NULL )
return -2;
}
- if( name_ignoring_case ) {
- if( SQL_ERROR == Sql_Query(sql_handle, "SELECT 1 FROM `%s` WHERE BINARY `name` = '%s' LIMIT 1", char_db, esc_name) ) {
+ if( charserv_config.name_ignoring_case ) {
+ if( SQL_ERROR == Sql_Query(sql_handle, "SELECT 1 FROM `%s` WHERE BINARY `name` = '%s' LIMIT 1", schema_config.char_db, esc_name) ) {
Sql_ShowDebug(sql_handle);
return -2;
}
} else {
- if( SQL_ERROR == Sql_Query(sql_handle, "SELECT 1 FROM `%s` WHERE `name` = '%s' LIMIT 1", char_db, esc_name) ) {
+ if( SQL_ERROR == Sql_Query(sql_handle, "SELECT 1 FROM `%s` WHERE `name` = '%s' LIMIT 1", schema_config.char_db, esc_name) ) {
Sql_ShowDebug(sql_handle);
return -2;
}
@@ -1581,24 +1386,24 @@
// check the number of already existing chars in this account
- if( char_per_account != 0 ) {
- if( SQL_ERROR == Sql_Query(sql_handle, "SELECT 1 FROM `%s` WHERE `account_id` = '%d'", char_db, sd->account_id) )
+ if( char_config.char_per_account != 0 ) {
+ if( SQL_ERROR == Sql_Query(sql_handle, "SELECT 1 FROM `%s` WHERE `account_id` = '%d'", schema_config.char_db, sd->account_id) )
Sql_ShowDebug(sql_handle);
- if( Sql_NumRows(sql_handle) >= char_per_account )
+ if( Sql_NumRows(sql_handle) >= char_config.char_per_account )
return -2; // character account limit exceeded
}
// check char slot
- if( SQL_ERROR == Sql_Query(sql_handle, "SELECT 1 FROM `%s` WHERE `account_id` = '%d' AND `char_num` = '%d' LIMIT 1", char_db, sd->account_id, slot) )
+ if( SQL_ERROR == Sql_Query(sql_handle, "SELECT 1 FROM `%s` WHERE `account_id` = '%d' AND `char_num` = '%d' LIMIT 1", schema_config.char_db, sd->account_id, slot) )
Sql_ShowDebug(sql_handle);
if( Sql_NumRows(sql_handle) > 0 )
return -2; // slot already in use
// validation success, log result
- if (log_char) {
+ if (charserv_config.log_char) {
if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` (`time`, `char_msg`,`account_id`,`char_num`,`name`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`hair`,`hair_color`)"
"VALUES (NOW(), '%s', '%d', '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')",
- charlog_db, "make new char", sd->account_id, slot, esc_name, str, agi, vit, int_, dex, luk, hair_style, hair_color) )
+ schema_config.charlog_db, "make new char", sd->account_id, slot, esc_name, str, agi, vit, int_, dex, luk, hair_style, hair_color) )
Sql_ShowDebug(sql_handle);
}
#if PACKETVER >= 20120307
@@ -1606,9 +1411,9 @@
if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` (`account_id`, `char_num`, `name`, `zeny`, `status_point`,`str`, `agi`, `vit`, `int`, `dex`, `luk`, `max_hp`, `hp`,"
"`max_sp`, `sp`, `hair`, `hair_color`, `last_map`, `last_x`, `last_y`, `save_map`, `save_x`, `save_y`) VALUES ("
"'%d', '%d', '%s', '%d', '%d','%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d','%d', '%d','%d', '%d', '%s', '%d', '%d', '%s', '%d', '%d')",
- char_db, sd->account_id , slot, esc_name, start_zeny, 48, str, agi, vit, int_, dex, luk,
+ schema_config.char_db, sd->account_id , slot, esc_name, charserv_config.start_zeny, 48, str, agi, vit, int_, dex, luk,
(40 * (100 + vit)/100) , (40 * (100 + vit)/100 ), (11 * (100 + int_)/100), (11 * (100 + int_)/100), hair_style, hair_color,
- mapindex_id2name(start_point.map), start_point.x, start_point.y, mapindex_id2name(start_point.map), start_point.x, start_point.y) )
+ mapindex_id2name(charserv_config.start_point.map), charserv_config.start_point.x, charserv_config.start_point.y, mapindex_id2name(charserv_config.start_point.map), charserv_config.start_point.x, charserv_config.start_point.y) )
{
Sql_ShowDebug(sql_handle);
return -2; //No, stop the procedure!
@@ -1616,11 +1421,11 @@
#else
//Insert the new char entry to the database
if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` (`account_id`, `char_num`, `name`, `zeny`, `str`, `agi`, `vit`, `int`, `dex`, `luk`, `max_hp`, `hp`,"
- "`max_sp`, `sp`, `hair`, `hair_color`, `last_map`, `last_x`, `last_y`, `save_map`, `save_x`, `save_y`) VALUES ("
- "'%d', '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d','%d', '%d','%d', '%d', '%s', '%d', '%d', '%s', '%d', '%d')",
- char_db, sd->account_id , slot, esc_name, start_zeny, str, agi, vit, int_, dex, luk,
- (40 * (100 + vit)/100) , (40 * (100 + vit)/100 ), (11 * (100 + int_)/100), (11 * (100 + int_)/100), hair_style, hair_color,
- mapindex_id2name(start_point.map), start_point.x, start_point.y, mapindex_id2name(start_point.map), start_point.x, start_point.y) )
+ "`max_sp`, `sp`, `hair`, `hair_color`, `last_map`, `last_x`, `last_y`, `save_map`, `save_x`, `save_y`) VALUES ("
+ "'%d', '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d','%d', '%d','%d', '%d', '%s', '%d', '%d', '%s', '%d', '%d')",
+ char_db, sd->account_id , slot, esc_name, start_zeny, str, agi, vit, int_, dex, luk,
+ (40 * (100 + vit)/100) , (40 * (100 + vit)/100 ), (11 * (100 + int_)/100), (11 * (100 + int_)/100), hair_style, hair_color,
+ mapindex_id2name(start_point.map), start_point.x, start_point.y, mapindex_id2name(start_point.map), start_point.x, start_point.y) )
{
Sql_ShowDebug(sql_handle);
return -2; //No, stop the procedure!
@@ -1630,7 +1435,7 @@
char_id = (int)Sql_LastInsertId(sql_handle);
//Give the char the default items
for (k = 0; k <= MAX_STARTITEM && start_items[k].nameid != 0; k ++) {
- if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` (`char_id`,`nameid`, `amount`, `equip`, `identify`) VALUES ('%d', '%d', '%d', '%d', '%d')", inventory_db, char_id, start_items[k].nameid, start_items[k].amount, start_items[k].pos, 1) )
+ if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` (`char_id`,`nameid`, `amount`, `equip`, `identify`) VALUES ('%d', '%d', '%d', '%d', '%d')", schema_config.inventory_db, char_id, start_items[k].nameid, start_items[k].amount, start_items[k].pos, 1) )
Sql_ShowDebug(sql_handle);
}
@@ -1641,20 +1446,12 @@
/*----------------------------------------------------------------------------------------------------------*/
/* Divorce Players */
/*----------------------------------------------------------------------------------------------------------*/
-int divorce_char_sql(int partner_id1, int partner_id2)
-{
- unsigned char buf[64];
-
- if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `partner_id`='0' WHERE `char_id`='%d' OR `char_id`='%d' LIMIT 2", char_db, partner_id1, partner_id2) )
+int divorce_char_sql(int partner_id1, int partner_id2){
+ if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `partner_id`='0' WHERE `char_id`='%d' OR `char_id`='%d' LIMIT 2", schema_config.char_db, partner_id1, partner_id2) )
Sql_ShowDebug(sql_handle);
- if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE (`nameid`='%d' OR `nameid`='%d') AND (`char_id`='%d' OR `char_id`='%d') LIMIT 2", inventory_db, WEDDING_RING_M, WEDDING_RING_F, partner_id1, partner_id2) )
+ if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE (`nameid`='%d' OR `nameid`='%d') AND (`char_id`='%d' OR `char_id`='%d') LIMIT 2", schema_config.inventory_db, WEDDING_RING_M, WEDDING_RING_F, partner_id1, partner_id2) )
Sql_ShowDebug(sql_handle);
-
- WBUFW(buf,0) = 0x2b12;
- WBUFL(buf,2) = partner_id1;
- WBUFL(buf,6) = partner_id2;
- mapif_sendall(buf,10);
-
+ char_send_ackdivorce(partner_id1, partner_id2);
return 0;
}
@@ -1672,7 +1469,7 @@
char *data;
size_t len;
- if (SQL_ERROR == Sql_Query(sql_handle, "SELECT `name`,`account_id`,`party_id`,`guild_id`,`base_level`,`homun_id`,`partner_id`,`father`,`mother`,`elemental_id` FROM `%s` WHERE `char_id`='%d'", char_db, char_id))
+ if (SQL_ERROR == Sql_Query(sql_handle, "SELECT `name`,`account_id`,`party_id`,`guild_id`,`base_level`,`homun_id`,`partner_id`,`father`,`mother`,`elemental_id` FROM `%s` WHERE `char_id`='%d'", schema_config.char_db, char_id))
Sql_ShowDebug(sql_handle);
if( SQL_SUCCESS != Sql_NextRow(sql_handle) )
@@ -1698,8 +1495,8 @@
//check for config char del condition [Lupus]
// TODO: Move this out to packet processing (0x68/0x1fb).
- if( ( char_del_level > 0 && base_level >= char_del_level )
- || ( char_del_level < 0 && base_level <= -char_del_level )
+ if( ( char_config.char_del_level > 0 && base_level >= char_config.char_del_level )
+ || ( char_config.char_del_level < 0 && base_level <= -char_config.char_del_level )
) {
ShowInfo("Char deletion aborted: %s, BaseLevel: %i\n", name, base_level);
return -1;
@@ -1714,9 +1511,9 @@
{ // Char is Baby
unsigned char buf[64];
- if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `child`='0' WHERE `char_id`='%d' OR `char_id`='%d'", char_db, father_id, mother_id) )
+ if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `child`='0' WHERE `char_id`='%d' OR `char_id`='%d'", schema_config.char_db, father_id, mother_id) )
Sql_ShowDebug(sql_handle);
- if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `id` = '410'AND (`char_id`='%d' OR `char_id`='%d')", skill_db, father_id, mother_id) )
+ if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `id` = '410'AND (`char_id`='%d' OR `char_id`='%d')", schema_config.skill_db, father_id, mother_id) )
Sql_ShowDebug(sql_handle);
WBUFW(buf,0) = 0x2b25;
@@ -1732,13 +1529,13 @@
/* delete char's pet */
//Delete the hatched pet if you have one...
- if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d' AND `incuvate` = '0'", pet_db, char_id) )
+ if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d' AND `incuvate` = '0'", schema_config.pet_db, char_id) )
Sql_ShowDebug(sql_handle);
//Delete all pets that are stored in eggs (inventory + cart)
- if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` USING `%s` JOIN `%s` ON `pet_id` = `card1`|`card2`<<16 WHERE `%s`.char_id = '%d' AND card0 = -256", pet_db, pet_db, inventory_db, inventory_db, char_id) )
+ if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` USING `%s` JOIN `%s` ON `pet_id` = `card1`|`card2`<<16 WHERE `%s`.char_id = '%d' AND card0 = -256", schema_config.pet_db, schema_config.pet_db, schema_config.inventory_db, schema_config.inventory_db, char_id) )
Sql_ShowDebug(sql_handle);
- if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` USING `%s` JOIN `%s` ON `pet_id` = `card1`|`card2`<<16 WHERE `%s`.char_id = '%d' AND card0 = -256", pet_db, pet_db, cart_db, cart_db, char_id) )
+ if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` USING `%s` JOIN `%s` ON `pet_id` = `card1`|`card2`<<16 WHERE `%s`.char_id = '%d' AND card0 = -256", schema_config.pet_db, schema_config.pet_db, schema_config.cart_db, schema_config.cart_db, char_id) )
Sql_ShowDebug(sql_handle);
/* remove homunculus */
@@ -1753,58 +1550,58 @@
mercenary_owner_delete(char_id);
/* delete char's friends list */
- if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id` = '%d'", friend_db, char_id) )
+ if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id` = '%d'", schema_config.friend_db, char_id) )
Sql_ShowDebug(sql_handle);
/* delete char from other's friend list */
//NOTE: Won't this cause problems for people who are already online? [Skotlex]
- if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `friend_id` = '%d'", friend_db, char_id) )
+ if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `friend_id` = '%d'", schema_config.friend_db, char_id) )
Sql_ShowDebug(sql_handle);
#ifdef HOTKEY_SAVING
/* delete hotkeys */
- if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", hotkey_db, char_id) )
+ if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", schema_config.hotkey_db, char_id) )
Sql_ShowDebug(sql_handle);
#endif
/* delete inventory */
- if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", inventory_db, char_id) )
+ if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", schema_config.inventory_db, char_id) )
Sql_ShowDebug(sql_handle);
/* delete cart inventory */
- if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", cart_db, char_id) )
+ if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", schema_config.cart_db, char_id) )
Sql_ShowDebug(sql_handle);
/* delete memo areas */
- if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", memo_db, char_id) )
+ if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", schema_config.memo_db, char_id) )
Sql_ShowDebug(sql_handle);
/* delete character registry */
- if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `type`=3 AND `char_id`='%d'", reg_db, char_id) )
+ if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `type`=3 AND `char_id`='%d'", schema_config.reg_db, char_id) )
Sql_ShowDebug(sql_handle);
/* delete skills */
- if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", skill_db, char_id) )
+ if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", schema_config.skill_db, char_id) )
Sql_ShowDebug(sql_handle);
/* delete mails (only received) */
- if (SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `dest_id`='%d'", mail_db, char_id))
+ if (SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `dest_id`='%d'", schema_config.mail_db, char_id))
Sql_ShowDebug(sql_handle);
#ifdef ENABLE_SC_SAVING
/* status changes */
- if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = '%d' AND `char_id`='%d'", scdata_db, account_id, char_id) )
+ if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = '%d' AND `char_id`='%d'", schema_config.scdata_db, account_id, char_id) )
Sql_ShowDebug(sql_handle);
#endif
- if (log_char) {
+ if (charserv_config.log_char) {
if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s`(`time`, `account_id`,`char_num`,`char_msg`,`name`) VALUES (NOW(), '%d', '%d', 'Deleted char (CID %d)', '%s')",
- charlog_db, account_id, 0, char_id, esc_name) )
+ schema_config.charlog_db, account_id, 0, char_id, esc_name) )
Sql_ShowDebug(sql_handle);
}
/* delete character */
- if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", char_db, char_id) )
+ if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", schema_config.char_db, char_id) )
Sql_ShowDebug(sql_handle);
/* No need as we used inter_guild_leave [Skotlex]
@@ -1813,7 +1610,7 @@
Sql_ShowDebug(sql_handle);
*/
- if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `guild_id` FROM `%s` WHERE `char_id` = '%d'", guild_db, char_id) )
+ if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `guild_id` FROM `%s` WHERE `char_id` = '%d'", schema_config.guild_db, char_id) )
Sql_ShowDebug(sql_handle);
else if( Sql_NumRows(sql_handle) > 0 )
mapif_parse_BreakGuild(0,guild_id);
@@ -1841,7 +1638,6 @@
// Writes char data to the buffer in the format used by the client.
// Used in packets 0x6b (chars info) and 0x6d (new char info)
// Returns the size
-#define MAX_CHAR_BUF 144 //Max size (for WFIFOHEAD calls)
int mmo_char_tobuf(uint8* buffer, struct mmo_charstatus* p)
{
unsigned short offset = 0;
@@ -1908,9 +1704,9 @@
#if PACKETVER != 20111116 //2011-11-16 wants 136, ask gravity.
#if PACKETVER >= 20110928
// change slot feature (0 = disabled, otherwise enabled)
- if( !char_move_enabled )
+ if( (charmove_config.char_move_enabled)==0 )
WBUFL(buf,132) = 0;
- else if( char_moves_unlimited )
+ else if( charmove_config.char_moves_unlimited )
WBUFL(buf,132) = 1;
else
WBUFL(buf,132) = max( 0, (int)p->character_moves );
@@ -1925,101 +1721,9 @@
return 106+offset;
}
-//----------------------------------------
-// Tell client how many pages, kRO sends 17 (Yommy)
-//----------------------------------------
-void char_charlist_notify( int fd, struct char_session_data* sd ){
- WFIFOHEAD(fd, 6);
- WFIFOW(fd, 0) = 0x9a0;
- // pages to req / send them all in 1 until mmo_chars_fromsql can split them up
- WFIFOL(fd, 2) = (sd->char_slots>3)?sd->char_slots/3:1; //int TotalCnt (nb page to load)
- WFIFOSET(fd,6);
-}
-
-void char_block_character( int fd, struct char_session_data* sd ){
- WFIFOHEAD(fd, 4);
- WFIFOW(fd, 0) = 0x20d;
- WFIFOW(fd, 2) = 4; //packet len
- WFIFOSET(fd,4);
-}
-
-void mmo_char_send099d(int fd, struct char_session_data *sd) {
- WFIFOHEAD(fd,4 + (MAX_CHARS*MAX_CHAR_BUF));
- WFIFOW(fd,0) = 0x99d;
- WFIFOW(fd,2) = mmo_chars_fromsql(sd, WFIFOP(fd,4)) + 4;
- WFIFOSET(fd,WFIFOW(fd,2));
-}
-
-//struct PACKET_CH_CHARLIST_REQ { 0x0 short PacketType}
-void char_parse_req_charlist(int fd, struct char_session_data* sd){
- mmo_char_send099d(fd,sd);
-}
-
-//----------------------------------------
-// Function to send characters to a player
-//----------------------------------------
-int mmo_char_send006b(int fd, struct char_session_data* sd){
- int j, offset = 0;
- //bool newvers = (sd->version >= date2version(20100413) );
-#if PACKETVER >= 20100413
- //if(newvers) //20100413
- offset += 3;
-#endif
- if (save_log)
- ShowInfo("Loading Char Data ("CL_BOLD"%d"CL_RESET")\n",sd->account_id);
-
- j = 24 + offset; // offset
- WFIFOHEAD(fd,j + MAX_CHARS*MAX_CHAR_BUF);
- WFIFOW(fd,0) = 0x6b;
-#if PACKETVER >= 20100413
-// if(newvers){ //20100413
- WFIFOB(fd,4) = MAX_CHARS; // Max slots.
- WFIFOB(fd,5) = sd->char_slots; // Available slots. (PremiumStartSlot)
- WFIFOB(fd,6) = MAX_CHARS; // Premium slots. (Any existent chars past sd->char_slots but within MAX_CHARS will show a 'Premium Service' in red)
-// }
-#endif
- memset(WFIFOP(fd,4 + offset), 0, 20); // unknown bytes
- j+=mmo_chars_fromsql(sd, WFIFOP(fd,j));
- WFIFOW(fd,2) = j; // packet len
- WFIFOSET(fd,j);
-
- return 0;
-}
-
-//----------------------------------------
-// Notify client about charselect window data [Ind]
-//----------------------------------------
-void mmo_char_send082d(int fd, struct char_session_data* sd) {
- if (save_log)
- ShowInfo("Loading Char Data ("CL_BOLD"%d"CL_RESET")\n",sd->account_id);
- WFIFOHEAD(fd,29);
- WFIFOW(fd,0) = 0x82d;
- WFIFOW(fd,2) = 29;
- WFIFOB(fd,4) = sd->char_slots;
- WFIFOB(fd,5) = MAX_CHARS - sd->char_slots;
- WFIFOB(fd,6) = MAX_CHARS - sd->char_slots;
- WFIFOB(fd,7) = sd->char_slots;
- WFIFOB(fd,8) = sd->char_slots;
- memset(WFIFOP(fd,9), 0, 20); // unused bytes
- WFIFOSET(fd,29);
-}
-
-void mmo_char_send(int fd, struct char_session_data* sd){
- //ShowInfo("sd->version = %d\n",sd->version);
-#if PACKETVER >= 20130000
- //if(sd->version > date2version(20130000) ){
- mmo_char_send082d(fd,sd);
- char_charlist_notify(fd,sd);
- char_block_character(fd,sd);
-#endif
- //}
- //@FIXME dump from kro doesn't show 6b transmission
- mmo_char_send006b(fd,sd);
-}
-
int char_married(int pl1, int pl2)
{
- if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `partner_id` FROM `%s` WHERE `char_id` = '%d'", char_db, pl1) )
+ if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `partner_id` FROM `%s` WHERE `char_id` = '%d'", schema_config.char_db, pl1) )
Sql_ShowDebug(sql_handle);
else if( SQL_SUCCESS == Sql_NextRow(sql_handle) )
{
@@ -2038,7 +1742,7 @@
int char_child(int parent_id, int child_id)
{
- if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `child` FROM `%s` WHERE `char_id` = '%d'", char_db, parent_id) )
+ if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `child` FROM `%s` WHERE `char_id` = '%d'", schema_config.char_db, parent_id) )
Sql_ShowDebug(sql_handle);
else if( SQL_SUCCESS == Sql_NextRow(sql_handle) )
{
@@ -2057,7 +1761,7 @@
int char_family(int cid1, int cid2, int cid3)
{
- if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id`,`partner_id`,`child` FROM `%s` WHERE `char_id` IN ('%d','%d','%d')", char_db, cid1, cid2, cid3) )
+ if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id`,`partner_id`,`child` FROM `%s` WHERE `char_id` IN ('%d','%d','%d')", schema_config.char_db, cid1, cid2, cid3) )
Sql_ShowDebug(sql_handle);
else while( SQL_SUCCESS == Sql_NextRow(sql_handle) )
{
@@ -2096,8 +1800,9 @@
set_eof(i);
}
-static void char_auth_ok(int fd, struct char_session_data *sd)
-{
+
+
+void char_auth_ok(int fd, struct char_session_data *sd) {
struct online_char_data* character;
if( (character = (struct online_char_data*)idb_get(online_char_db, sd->account_id)) != NULL )
@@ -2107,30 +1812,18 @@
mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 2);
if (character->waiting_disconnect == INVALID_TIMER)
character->waiting_disconnect = add_timer(gettick()+20000, chardb_waiting_disconnect, character->account_id, 0);
- WFIFOHEAD(fd,3);
- WFIFOW(fd,0) = 0x81;
- WFIFOB(fd,2) = 8;
- WFIFOSET(fd,3);
+ char_send_auth_result(fd,8);
return;
}
if (character->fd >= 0 && character->fd != fd)
{ //There's already a connection from this account that hasn't picked a char yet.
- WFIFOHEAD(fd,3);
- WFIFOW(fd,0) = 0x81;
- WFIFOB(fd,2) = 8;
- WFIFOSET(fd,3);
+ char_send_auth_result(fd,8);
return;
}
character->fd = fd;
}
- if (login_fd > 0) {
- // request account data
- WFIFOHEAD(login_fd,6);
- WFIFOW(login_fd,0) = 0x2716;
- WFIFOL(login_fd,2) = sd->account_id;
- WFIFOSET(login_fd,6);
- }
+ char_send_reqaccdata(login_fd,sd); // request account data
// mark session as 'authed'
sd->auth = true;
@@ -2141,469 +1834,6 @@
// continues when account data is received...
}
-int send_accounts_tologin(int tid, unsigned int tick, int id, intptr_t data);
-void mapif_server_reset(int id);
-
-
-/// Resets all the data.
-void loginif_reset(void)
-{
- int id;
- // TODO kick everyone out and reset everything or wait for connect and try to reaquire locks [FlavioJS]
- for( id = 0; id < ARRAYLENGTH(server); ++id )
- mapif_server_reset(id);
- flush_fifos();
- 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 loginif_check_shutdown(void)
-{
- if( runflag != CHARSERVER_ST_SHUTDOWN )
- return;
- runflag = CORE_ST_STOP;
-}
-
-
-/// Called when the connection to Login Server is disconnected.
-void loginif_on_disconnect(void)
-{
- ShowWarning("Connection to Login Server lost.\n\n");
-}
-
-
-/// Called when all the connection steps are completed.
-void loginif_on_ready(void)
-{
- int i;
-
- loginif_check_shutdown();
-
- //Send online accounts to login server.
- send_accounts_tologin(INVALID_TIMER, gettick(), 0, 0);
-
- // if no map-server already connected, display a message...
- ARR_FIND( 0, ARRAYLENGTH(server), i, server[i].fd > 0 && server[i].map[0] );
- if( i == ARRAYLENGTH(server) )
- ShowStatus("Awaiting maps from map-server.\n");
-}
-
-
-int parse_fromlogin(int fd) {
- struct char_session_data* sd = NULL;
- int i;
-
- // only process data from the login-server
- if( fd != login_fd ) {
- ShowDebug("parse_fromlogin: Disconnecting invalid session #%d (is not the login-server)\n", fd);
- do_close(fd);
- return 0;
- }
-
- if( session[fd]->flag.eof ) {
- do_close(fd);
- login_fd = -1;
- loginif_on_disconnect();
- return 0;
- } else if ( session[fd]->flag.ping ) {/* we've reached stall time */
- if( DIFF_TICK(last_tick, session[fd]->rdata_tick) > (stall_time * 2) ) {/* we can't wait any longer */
- set_eof(fd);
- return 0;
- } else if( session[fd]->flag.ping != 2 ) { /* we haven't sent ping out yet */
- WFIFOHEAD(fd,2);// sends a ping packet to login server (will receive pong 0x2718)
- WFIFOW(fd,0) = 0x2719;
- WFIFOSET(fd,2);
-
- session[fd]->flag.ping = 2;
- }
- }
-
- sd = (struct char_session_data*)session[fd]->session_data;
-
- while(RFIFOREST(fd) >= 2) {
- uint16 command = RFIFOW(fd,0);
-
- switch( command )
- {
-
- // acknowledgement of connect-to-loginserver request
- case 0x2711:
- if (RFIFOREST(fd) < 3)
- return 0;
-
- if (RFIFOB(fd,2)) {
- //printf("connect login server error : %d\n", RFIFOB(fd,2));
- ShowError("Can not connect to login-server.\n");
- ShowError("The server communication passwords (default s1/p1) are probably invalid.\n");
- ShowError("Also, please make sure your login db has the correct communication username/passwords and the gender of the account is S.\n");
- ShowError("The communication passwords are set in map_athena.conf and char_athena.conf\n");
- set_eof(fd);
- return 0;
- } else {
- ShowStatus("Connected to login-server (connection #%d).\n", fd);
- loginif_on_ready();
- }
- RFIFOSKIP(fd,3);
- break;
-
- // acknowledgement of account authentication request
- case 0x2713:
- if (RFIFOREST(fd) < 25)
- return 0;
- {
- int account_id = RFIFOL(fd,2);
- uint32 login_id1 = RFIFOL(fd,6);
- uint32 login_id2 = RFIFOL(fd,10);
- uint8 sex = RFIFOB(fd,14);
- uint8 result = RFIFOB(fd,15);
- int request_id = RFIFOL(fd,16);
- uint32 version = RFIFOL(fd,20);
- uint8 clienttype = RFIFOB(fd,24);
- RFIFOSKIP(fd,25);
-
- if( session_isActive(request_id) && (sd=(struct char_session_data*)session[request_id]->session_data) &&
- !sd->auth && sd->account_id == account_id && sd->login_id1 == login_id1 && sd->login_id2 == login_id2 && sd->sex == sex )
- {
- int client_fd = request_id;
- sd->version = version;
- sd->clienttype = clienttype;
- switch( result )
- {
- case 0:// ok
- char_auth_ok(client_fd, sd);
- break;
- case 1:// auth failed
- WFIFOHEAD(client_fd,3);
- WFIFOW(client_fd,0) = 0x6c;
- WFIFOB(client_fd,2) = 0;// rejected from server
- WFIFOSET(client_fd,3);
- break;
- }
- }
- }
- break;
-
- case 0x2717: // account data
- if (RFIFOREST(fd) < 72)
- return 0;
-
- // find the authenticated session with this account id
- ARR_FIND( 0, fd_max, i, session[i] && (sd = (struct char_session_data*)session[i]->session_data) && sd->auth && sd->account_id == RFIFOL(fd,2) );
- if( i < fd_max )
- {
- int server_id;
- memcpy(sd->email, RFIFOP(fd,6), 40);
- sd->expiration_time = (time_t)RFIFOL(fd,46);
- sd->group_id = RFIFOB(fd,50);
- sd->char_slots = RFIFOB(fd,51);
- if( sd->char_slots > MAX_CHARS ) {
- ShowError("Account '%d' `character_slots` column is higher than supported MAX_CHARS (%d), update MAX_CHARS in mmo.h! capping to MAX_CHARS...\n",sd->account_id,sd->char_slots);
- sd->char_slots = MAX_CHARS;/* cap to maximum */
- } else if ( !sd->char_slots )/* no value aka 0 in sql */
- sd->char_slots = MAX_CHARS;/* cap to maximum */
- safestrncpy(sd->birthdate, (const char*)RFIFOP(fd,52), sizeof(sd->birthdate));
- safestrncpy(sd->pincode, (const char*)RFIFOP(fd,63), sizeof(sd->pincode));
- sd->pincode_change = (time_t)RFIFOL(fd,68);
- ARR_FIND( 0, ARRAYLENGTH(server), server_id, server[server_id].fd > 0 && server[server_id].map[0] );
- // continued from char_auth_ok...
- if( server_id == ARRAYLENGTH(server) || //server not online, bugreport:2359
- (max_connect_user == 0 && sd->group_id != gm_allow_group) ||
- ( max_connect_user > 0 && count_users() >= max_connect_user && sd->group_id != gm_allow_group ) ) {
- // refuse connection (over populated)
- WFIFOHEAD(i,3);
- WFIFOW(i,0) = 0x6c;
- WFIFOW(i,2) = 0;
- WFIFOSET(i,3);
- } else {
- // send characters to player
- mmo_char_send(i, sd);
-#if PACKETVER >= 20110309
- if( pincode_enabled ){
- // PIN code system enabled
- if( strlen( sd->pincode ) <= 0 ){
- // No PIN code has been set yet
- if( pincode_force ){
- pincode_sendstate( i, sd, PINCODE_NEW );
- }else{
- pincode_sendstate( i, sd, PINCODE_PASSED );
- }
- }else{
- if( !pincode_changetime || ( sd->pincode_change + pincode_changetime ) > time(NULL) ){
- struct online_char_data* node = (struct online_char_data*)idb_get( online_char_db, sd->account_id );
-
- if( node != NULL && node->pincode_success ){
- // User has already passed the check
- pincode_sendstate( i, sd, PINCODE_PASSED );
- }else{
- // Ask user for his PIN code
- pincode_sendstate( i, sd, PINCODE_ASK );
- }
- }else{
- // User hasnt changed his PIN code too long
- pincode_sendstate( i, sd, PINCODE_EXPIRED );
- }
- }
- }else{
- // PIN code system disabled
- pincode_sendstate( i, sd, PINCODE_OK );
- }
-#endif
- }
- }
- RFIFOSKIP(fd,72);
- break;
-
- // login-server alive packet
- case 0x2718:
- if (RFIFOREST(fd) < 2)
- return 0;
- RFIFOSKIP(fd,2);
- session[fd]->flag.ping = 0;
- break;
-
- // changesex reply
- case 0x2723:
- if (RFIFOREST(fd) < 7)
- return 0;
- {
- unsigned char buf[7];
-
- int acc = RFIFOL(fd,2);
- int sex = RFIFOB(fd,6);
- RFIFOSKIP(fd,7);
-
- if( acc > 0 )
- {// TODO: Is this even possible?
- int char_id[MAX_CHARS];
- int class_[MAX_CHARS];
- int guild_id[MAX_CHARS];
- int num;
- char* data;
-
- struct auth_node* node = (struct auth_node*)idb_get(auth_db, acc);
- if( node != NULL )
- node->sex = sex;
-
- // get characters
- if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id`,`class`,`guild_id` FROM `%s` WHERE `account_id` = '%d'", char_db, acc) )
- Sql_ShowDebug(sql_handle);
- for( i = 0; i < MAX_CHARS && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i )
- {
- Sql_GetData(sql_handle, 0, &data, NULL); char_id[i] = atoi(data);
- Sql_GetData(sql_handle, 1, &data, NULL); class_[i] = atoi(data);
- Sql_GetData(sql_handle, 2, &data, NULL); guild_id[i] = atoi(data);
- }
- num = i;
- for( i = 0; i < num; ++i )
- {
- if( class_[i] == JOB_BARD || class_[i] == JOB_DANCER ||
- class_[i] == JOB_CLOWN || class_[i] == JOB_GYPSY ||
- class_[i] == JOB_BABY_BARD || class_[i] == JOB_BABY_DANCER ||
- class_[i] == JOB_MINSTREL || class_[i] == JOB_WANDERER ||
- class_[i] == JOB_MINSTREL_T || class_[i] == JOB_WANDERER_T ||
- class_[i] == JOB_BABY_MINSTREL || class_[i] == JOB_BABY_WANDERER ||
- class_[i] == JOB_KAGEROU || class_[i] == JOB_OBORO )
- {
- // job modification
- if( class_[i] == JOB_BARD || class_[i] == JOB_DANCER )
- class_[i] = (sex ? JOB_BARD : JOB_DANCER);
- else if( class_[i] == JOB_CLOWN || class_[i] == JOB_GYPSY )
- class_[i] = (sex ? JOB_CLOWN : JOB_GYPSY);
- else if( class_[i] == JOB_BABY_BARD || class_[i] == JOB_BABY_DANCER )
- class_[i] = (sex ? JOB_BABY_BARD : JOB_BABY_DANCER);
- else if( class_[i] == JOB_MINSTREL || class_[i] == JOB_WANDERER )
- class_[i] = (sex ? JOB_MINSTREL : JOB_WANDERER);
- else if( class_[i] == JOB_MINSTREL_T || class_[i] == JOB_WANDERER_T )
- class_[i] = (sex ? JOB_MINSTREL_T : JOB_WANDERER_T);
- else if( class_[i] == JOB_BABY_MINSTREL || class_[i] == JOB_BABY_WANDERER )
- class_[i] = (sex ? JOB_BABY_MINSTREL : JOB_BABY_WANDERER);
- else if( class_[i] == JOB_KAGEROU || class_[i] == JOB_OBORO )
- class_[i] = (sex ? JOB_KAGEROU : JOB_OBORO);
- }
-
- if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `class`='%d', `weapon`='0', `shield`='0', `head_top`='0', `head_mid`='0', `head_bottom`='0' WHERE `char_id`='%d'", char_db, class_[i], char_id[i]) )
- Sql_ShowDebug(sql_handle);
-
- if( guild_id[i] )// If there is a guild, update the guild_member data [Skotlex]
- inter_guild_sex_changed(guild_id[i], acc, char_id[i], sex);
- }
- Sql_FreeResult(sql_handle);
-
- // disconnect player if online on char-server
- disconnect_player(acc);
- }
-
- // notify all mapservers about this change
- WBUFW(buf,0) = 0x2b0d;
- WBUFL(buf,2) = acc;
- WBUFB(buf,6) = sex;
- mapif_sendall(buf, 7);
- }
- break;
-
- // reply to an account_reg2 registry request
- case 0x2729:
- if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
- return 0;
-
- { //Receive account_reg2 registry, forward to map servers.
- unsigned char buf[13+ACCOUNT_REG2_NUM*sizeof(struct global_reg)];
- memcpy(buf,RFIFOP(fd,0), RFIFOW(fd,2));
- WBUFW(buf,0) = 0x3804; //Map server can now receive all kinds of reg values with the same packet. [Skotlex]
- mapif_sendall(buf, WBUFW(buf,2));
- RFIFOSKIP(fd, RFIFOW(fd,2));
- }
- break;
-
- // State change of account/ban notification (from login-server)
- case 0x2731:
- if (RFIFOREST(fd) < 11)
- return 0;
-
- { // send to all map-servers to disconnect the player
- unsigned char buf[11];
- WBUFW(buf,0) = 0x2b14;
- WBUFL(buf,2) = RFIFOL(fd,2);
- WBUFB(buf,6) = RFIFOB(fd,6); // 0: change of statut, 1: ban
- WBUFL(buf,7) = RFIFOL(fd,7); // status or final date of a banishment
- mapif_sendall(buf, 11);
- }
- // disconnect player if online on char-server
- disconnect_player(RFIFOL(fd,2));
-
- RFIFOSKIP(fd,11);
- break;
-
- // Login server request to kick a character out. [Skotlex]
- case 0x2734:
- if (RFIFOREST(fd) < 6)
- return 0;
- {
- int aid = RFIFOL(fd,2);
- struct online_char_data* character = (struct online_char_data*)idb_get(online_char_db, aid);
- RFIFOSKIP(fd,6);
- if( character != NULL )
- {// account is already marked as online!
- if( character->server > -1 )
- { //Kick it from the map server it is on.
- mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 2);
- if (character->waiting_disconnect == INVALID_TIMER)
- character->waiting_disconnect = add_timer(gettick()+AUTH_TIMEOUT, chardb_waiting_disconnect, character->account_id, 0);
- }
- else
- {// Manual kick from char server.
- struct char_session_data *tsd;
- int i;
- ARR_FIND( 0, fd_max, i, session[i] && (tsd = (struct char_session_data*)session[i]->session_data) && tsd->account_id == aid );
- if( i < fd_max )
- {
- WFIFOHEAD(i,3);
- WFIFOW(i,0) = 0x81;
- WFIFOB(i,2) = 2; // "Someone has already logged in with this id"
- WFIFOSET(i,3);
- set_eof(i);
- }
- else // still moving to the map-server
- set_char_offline(-1, aid);
- }
- }
- idb_remove(auth_db, aid);// reject auth attempts from map-server
- }
- break;
-
- // ip address update signal from login server
- case 0x2735:
- {
- unsigned char buf[2];
- uint32 new_ip = 0;
-
- WBUFW(buf,0) = 0x2b1e;
- mapif_sendall(buf, 2);
-
- new_ip = host2ip(login_ip_str);
- if (new_ip && new_ip != login_ip)
- login_ip = new_ip; //Update login ip, too.
-
- new_ip = host2ip(char_ip_str);
- if (new_ip && new_ip != char_ip)
- { //Update ip.
- char_ip = new_ip;
- ShowInfo("Updating IP for [%s].\n", char_ip_str);
- // notify login server about the change
- WFIFOHEAD(fd,6);
- WFIFOW(fd,0) = 0x2736;
- WFIFOL(fd,2) = htonl(char_ip);
- WFIFOSET(fd,6);
- }
-
- RFIFOSKIP(fd,2);
- }
- break;
-
- default:
- ShowError("Unknown packet 0x%04x received from login-server, disconnecting.\n", command);
- set_eof(fd);
- return 0;
- }
- }
-
- RFIFOFLUSH(fd);
- return 0;
-}
-
-int check_connect_login_server(int tid, unsigned int tick, int id, intptr_t data);
-int send_accounts_tologin(int tid, unsigned int tick, int id, intptr_t data);
-
-void do_init_loginif(void)
-{
- // establish char-login connection if not present
- add_timer_func_list(check_connect_login_server, "check_connect_login_server");
- add_timer_interval(gettick() + 1000, check_connect_login_server, 0, 0, 10 * 1000);
-
- // send a list of all online account IDs to login server
- add_timer_func_list(send_accounts_tologin, "send_accounts_tologin");
- add_timer_interval(gettick() + 1000, send_accounts_tologin, 0, 0, 3600 * 1000); //Sync online accounts every hour
-}
-
-void do_final_loginif(void)
-{
- if( login_fd != -1 )
- {
- do_close(login_fd);
- login_fd = -1;
- }
-}
-
-int request_accreg2(int account_id, int char_id)
-{
- if (login_fd > 0) {
- WFIFOHEAD(login_fd,10);
- WFIFOW(login_fd,0) = 0x272e;
- WFIFOL(login_fd,2) = account_id;
- WFIFOL(login_fd,6) = char_id;
- WFIFOSET(login_fd,10);
- return 1;
- }
- return 0;
-}
-
-//Send packet forward to login-server for account saving
-int save_accreg2(unsigned char* buf, int len)
-{
- if (login_fd > 0) {
- WFIFOHEAD(login_fd,len+4);
- memcpy(WFIFOP(login_fd,4), buf, len);
- WFIFOW(login_fd,0) = 0x2728;
- WFIFOW(login_fd,2) = len+4;
- WFIFOSET(login_fd,len+4);
- return 1;
- }
- return 0;
-}
-
void char_read_fame_list(void)
{
int i;
@@ -2615,7 +1845,7 @@
memset(chemist_fame_list, 0, sizeof(chemist_fame_list));
memset(taekwon_fame_list, 0, sizeof(taekwon_fame_list));
// Build Blacksmith ranking list
- if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id`,`fame`,`name` FROM `%s` WHERE `fame`>0 AND (`class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d') ORDER BY `fame` DESC LIMIT 0,%d", char_db, JOB_BLACKSMITH, JOB_WHITESMITH, JOB_BABY_BLACKSMITH, JOB_MECHANIC, JOB_MECHANIC_T, JOB_BABY_MECHANIC, fame_list_size_smith) )
+ if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id`,`fame`,`name` FROM `%s` WHERE `fame`>0 AND (`class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d') ORDER BY `fame` DESC LIMIT 0,%d", schema_config.char_db, JOB_BLACKSMITH, JOB_WHITESMITH, JOB_BABY_BLACKSMITH, JOB_MECHANIC, JOB_MECHANIC_T, JOB_BABY_MECHANIC, fame_list_size_smith) )
Sql_ShowDebug(sql_handle);
for( i = 0; i < fame_list_size_smith && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i )
{
@@ -2630,7 +1860,7 @@
memcpy(smith_fame_list[i].name, data, min(len, NAME_LENGTH));
}
// Build Alchemist ranking list
- if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id`,`fame`,`name` FROM `%s` WHERE `fame`>0 AND (`class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d') ORDER BY `fame` DESC LIMIT 0,%d", char_db, JOB_ALCHEMIST, JOB_CREATOR, JOB_BABY_ALCHEMIST, JOB_GENETIC, JOB_GENETIC_T, JOB_BABY_GENETIC, fame_list_size_chemist) )
+ if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id`,`fame`,`name` FROM `%s` WHERE `fame`>0 AND (`class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d') ORDER BY `fame` DESC LIMIT 0,%d", schema_config.char_db, JOB_ALCHEMIST, JOB_CREATOR, JOB_BABY_ALCHEMIST, JOB_GENETIC, JOB_GENETIC_T, JOB_BABY_GENETIC, fame_list_size_chemist) )
Sql_ShowDebug(sql_handle);
for( i = 0; i < fame_list_size_chemist && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i )
{
@@ -2645,7 +1875,7 @@
memcpy(chemist_fame_list[i].name, data, min(len, NAME_LENGTH));
}
// Build Taekwon ranking list
- if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id`,`fame`,`name` FROM `%s` WHERE `fame`>0 AND (`class`='%d') ORDER BY `fame` DESC LIMIT 0,%d", char_db, JOB_TAEKWON, fame_list_size_taekwon) )
+ if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id`,`fame`,`name` FROM `%s` WHERE `fame`>0 AND (`class`='%d') ORDER BY `fame` DESC LIMIT 0,%d", schema_config.char_db, JOB_TAEKWON, fame_list_size_taekwon) )
Sql_ShowDebug(sql_handle);
for( i = 0; i < fame_list_size_taekwon && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i )
{
@@ -2662,53 +1892,7 @@
Sql_FreeResult(sql_handle);
}
-// Send map-servers the fame ranking lists
-int char_send_fame_list(int fd)
-{
- int i, len = 8;
- unsigned char buf[32000];
- WBUFW(buf,0) = 0x2b1b;
-
- for(i = 0; i < fame_list_size_smith && smith_fame_list[i].id; i++) {
- memcpy(WBUFP(buf, len), &smith_fame_list[i], sizeof(struct fame_list));
- len += sizeof(struct fame_list);
- }
- // add blacksmith's block length
- WBUFW(buf, 6) = len;
-
- for(i = 0; i < fame_list_size_chemist && chemist_fame_list[i].id; i++) {
- memcpy(WBUFP(buf, len), &chemist_fame_list[i], sizeof(struct fame_list));
- len += sizeof(struct fame_list);
- }
- // add alchemist's block length
- WBUFW(buf, 4) = len;
-
- for(i = 0; i < fame_list_size_taekwon && taekwon_fame_list[i].id; i++) {
- memcpy(WBUFP(buf, len), &taekwon_fame_list[i], sizeof(struct fame_list));
- len += sizeof(struct fame_list);
- }
- // add total packet length
- WBUFW(buf, 2) = len;
-
- if (fd != -1)
- mapif_send(fd, buf, len);
- else
- mapif_sendall(buf, len);
-
- return 0;
-}
-
-void char_update_fame_list(int type, int index, int fame)
-{
- unsigned char buf[8];
- WBUFW(buf,0) = 0x2b22;
- WBUFB(buf,2) = type;
- WBUFB(buf,3) = index;
- WBUFL(buf,4) = fame;
- mapif_sendall(buf, 8);
-}
-
//Loads a character's name and stores it in the buffer given (must be NAME_LENGTH in size)
//Returns 1 on found, 0 on not found (buffer is filled with Unknown char name)
int char_loadName(int char_id, char* name)
@@ -2716,7 +1900,7 @@
char* data;
size_t len;
- if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `name` FROM `%s` WHERE `char_id`='%d'", char_db, char_id) )
+ if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `name` FROM `%s` WHERE `char_id`='%d'", schema_config.char_db, char_id) )
Sql_ShowDebug(sql_handle);
else if( SQL_SUCCESS == Sql_NextRow(sql_handle) )
{
@@ -2726,7 +1910,7 @@
}
else
{
- safestrncpy(name, unknown_char_name, NAME_LENGTH);
+ safestrncpy(name, charserv_config.unknown_char_name, NAME_LENGTH);
}
return 0;
}
@@ -2734,806 +1918,6 @@
int search_mapserver(unsigned short map, uint32 ip, uint16 port);
-/// Initializes a server structure.
-void mapif_server_init(int id)
-{
- memset(&server[id], 0, sizeof(server[id]));
- server[id].fd = -1;
-}
-
-
-/// Destroys a server structure.
-void mapif_server_destroy(int id)
-{
- if( server[id].fd == -1 )
- {
- do_close(server[id].fd);
- server[id].fd = -1;
- }
-}
-
-
-/// Resets all the data related to a server.
-void mapif_server_reset(int id)
-{
- int i,j;
- unsigned char buf[16384];
- int fd = server[id].fd;
- //Notify other map servers that this one is gone. [Skotlex]
- WBUFW(buf,0) = 0x2b20;
- WBUFL(buf,4) = htonl(server[id].ip);
- WBUFW(buf,8) = htons(server[id].port);
- j = 0;
- for(i = 0; i < MAX_MAP_PER_SERVER; i++)
- if (server[id].map[i])
- WBUFW(buf,10+(j++)*4) = server[id].map[i];
- if (j > 0) {
- WBUFW(buf,2) = j * 4 + 10;
- mapif_sendallwos(fd, buf, WBUFW(buf,2));
- }
- if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `index`='%d'", ragsrvinfo_db, server[id].fd) )
- Sql_ShowDebug(sql_handle);
- online_char_db->foreach(online_char_db,char_db_setoffline,id); //Tag relevant chars as 'in disconnected' server.
- mapif_server_destroy(id);
- mapif_server_init(id);
-}
-
-
-/// Called when the connection to a Map Server is disconnected.
-void mapif_on_disconnect(int id)
-{
- ShowStatus("Map-server #%d has disconnected.\n", id);
- mapif_server_reset(id);
-}
-
-
-int parse_frommap(int fd)
-{
- int i, j;
- int id;
-
- ARR_FIND( 0, ARRAYLENGTH(server), id, server[id].fd == fd );
- if( id == ARRAYLENGTH(server) )
- {// not a map server
- ShowDebug("parse_frommap: Disconnecting invalid session #%d (is not a map-server)\n", fd);
- do_close(fd);
- return 0;
- }
- if( session[fd]->flag.eof )
- {
- do_close(fd);
- server[id].fd = -1;
- mapif_on_disconnect(id);
- return 0;
- }
-
- while(RFIFOREST(fd) >= 2){
- switch(RFIFOW(fd,0)){
-
- case 0x2afa: // Receiving map names list from the map-server
- if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
- return 0;
-
- memset(server[id].map, 0, sizeof(server[id].map));
- j = 0;
- for(i = 4; i < RFIFOW(fd,2); i += 4) {
- server[id].map[j] = RFIFOW(fd,i);
- j++;
- }
-
- ShowStatus("Map-Server %d connected: %d maps, from IP %d.%d.%d.%d port %d.\n",
- id, j, CONVIP(server[id].ip), server[id].port);
- ShowStatus("Map-server %d loading complete.\n", id);
-
- // send name for wisp to player
- WFIFOHEAD(fd, 3 + NAME_LENGTH);
- WFIFOW(fd,0) = 0x2afb;
- WFIFOB(fd,2) = 0;
- memcpy(WFIFOP(fd,3), wisp_server_name, NAME_LENGTH);
- WFIFOSET(fd,3+NAME_LENGTH);
-
- char_send_fame_list(fd); //Send fame list.
-
- {
- unsigned char buf[16384];
- int x;
- if (j == 0) {
- ShowWarning("Map-server %d has NO maps.\n", id);
- } else {
- // Transmitting maps information to the other map-servers
- WBUFW(buf,0) = 0x2b04;
- WBUFW(buf,2) = j * 4 + 10;
- WBUFL(buf,4) = htonl(server[id].ip);
- WBUFW(buf,8) = htons(server[id].port);
- memcpy(WBUFP(buf,10), RFIFOP(fd,4), j * 4);
- mapif_sendallwos(fd, buf, WBUFW(buf,2));
- }
- // Transmitting the maps of the other map-servers to the new map-server
- for(x = 0; x < ARRAYLENGTH(server); x++) {
- if (server[x].fd > 0 && x != id) {
- WFIFOHEAD(fd,10 +4*ARRAYLENGTH(server[x].map));
- WFIFOW(fd,0) = 0x2b04;
- WFIFOL(fd,4) = htonl(server[x].ip);
- WFIFOW(fd,8) = htons(server[x].port);
- j = 0;
- for(i = 0; i < ARRAYLENGTH(server[x].map); i++)
- if (server[x].map[i])
- WFIFOW(fd,10+(j++)*4) = server[x].map[i];
- if (j > 0) {
- WFIFOW(fd,2) = j * 4 + 10;
- WFIFOSET(fd,WFIFOW(fd,2));
- }
- }
- }
- }
- RFIFOSKIP(fd,RFIFOW(fd,2));
- break;
-
- case 0x2afc: //Packet command is now used for sc_data request. [Skotlex]
- if (RFIFOREST(fd) < 10)
- return 0;
- {
-#ifdef ENABLE_SC_SAVING
- int aid, cid;
- aid = RFIFOL(fd,2);
- cid = RFIFOL(fd,6);
- if( SQL_ERROR == Sql_Query(sql_handle, "SELECT type, tick, val1, val2, val3, val4 from `%s` WHERE `account_id` = '%d' AND `char_id`='%d'",
- scdata_db, aid, cid) )
- {
- Sql_ShowDebug(sql_handle);
- break;
- }
- if( Sql_NumRows(sql_handle) > 0 )
- {
- struct status_change_data scdata;
- int count;
- char* data;
-
- WFIFOHEAD(fd,14+50*sizeof(struct status_change_data));
- WFIFOW(fd,0) = 0x2b1d;
- WFIFOL(fd,4) = aid;
- WFIFOL(fd,8) = cid;
- for( count = 0; count < 50 && SQL_SUCCESS == Sql_NextRow(sql_handle); ++count )
- {
- Sql_GetData(sql_handle, 0, &data, NULL); scdata.type = atoi(data);
- Sql_GetData(sql_handle, 1, &data, NULL); scdata.tick = atoi(data);
- Sql_GetData(sql_handle, 2, &data, NULL); scdata.val1 = atoi(data);
- Sql_GetData(sql_handle, 3, &data, NULL); scdata.val2 = atoi(data);
- Sql_GetData(sql_handle, 4, &data, NULL); scdata.val3 = atoi(data);
- Sql_GetData(sql_handle, 5, &data, NULL); scdata.val4 = atoi(data);
- memcpy(WFIFOP(fd, 14+count*sizeof(struct status_change_data)), &scdata, sizeof(struct status_change_data));
- }
- if (count >= 50)
- ShowWarning("Too many status changes for %d:%d, some of them were not loaded.\n", aid, cid);
- if (count > 0)
- {
- WFIFOW(fd,2) = 14 + count*sizeof(struct status_change_data);
- WFIFOW(fd,12) = count;
- WFIFOSET(fd,WFIFOW(fd,2));
-
- //Clear the data once loaded.
- if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = '%d' AND `char_id`='%d'", scdata_db, aid, cid) )
- Sql_ShowDebug(sql_handle);
- }
- }
- Sql_FreeResult(sql_handle);
-#endif
- RFIFOSKIP(fd, 10);
- }
- break;
-
- case 0x2afe: //set MAP user count
- if (RFIFOREST(fd) < 4)
- return 0;
- if (RFIFOW(fd,2) != server[id].users) {
- server[id].users = RFIFOW(fd,2);
- ShowInfo("User Count: %d (Server: %d)\n", server[id].users, id);
- }
- RFIFOSKIP(fd, 4);
- break;
-
- case 0x2aff: //set MAP users
- if (RFIFOREST(fd) < 6 || RFIFOREST(fd) < RFIFOW(fd,2))
- return 0;
- {
- //TODO: When data mismatches memory, update guild/party online/offline states.
- int aid, cid;
- struct online_char_data* character;
-
- server[id].users = RFIFOW(fd,4);
- online_char_db->foreach(online_char_db,char_db_setoffline,id); //Set all chars from this server as 'unknown'
- for(i = 0; i < server[id].users; i++) {
- aid = RFIFOL(fd,6+i*8);
- cid = RFIFOL(fd,6+i*8+4);
- character = idb_ensure(online_char_db, aid, create_online_char_data);
- if( character->server > -1 && character->server != id )
- {
- ShowNotice("Set map user: Character (%d:%d) marked on map server %d, but map server %d claims to have (%d:%d) online!\n",
- character->account_id, character->char_id, character->server, id, aid, cid);
- mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 2);
- }
- character->server = id;
- character->char_id = cid;
- }
- //If any chars remain in -2, they will be cleaned in the cleanup timer.
- RFIFOSKIP(fd,RFIFOW(fd,2));
- }
- break;
-
- case 0x2b01: // Receive character data from map-server for saving
- if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
- return 0;
- {
- int aid = RFIFOL(fd,4), cid = RFIFOL(fd,8), size = RFIFOW(fd,2);
- struct online_char_data* character;
-
- if (size - 13 != sizeof(struct mmo_charstatus))
- {
- ShowError("parse_from_map (save-char): Size mismatch! %d != %d\n", size-13, sizeof(struct mmo_charstatus));
- RFIFOSKIP(fd,size);
- break;
- }
- //Check account only if this ain't final save. Final-save goes through because of the char-map reconnect
- if (RFIFOB(fd,12) || RFIFOB(fd,13) || (
- (character = (struct online_char_data*)idb_get(online_char_db, aid)) != NULL &&
- character->char_id == cid))
- {
- struct mmo_charstatus char_dat;
- memcpy(&char_dat, RFIFOP(fd,13), sizeof(struct mmo_charstatus));
- mmo_char_tosql(cid, &char_dat);
- } else { //This may be valid on char-server reconnection, when re-sending characters that already logged off.
- ShowError("parse_from_map (save-char): Received data for non-existant/offline character (%d:%d).\n", aid, cid);
- set_char_online(id, cid, aid);
- }
-
- if (RFIFOB(fd,12))
- { //Flag, set character offline after saving. [Skotlex]
- set_char_offline(cid, aid);
- WFIFOHEAD(fd,10);
- WFIFOW(fd,0) = 0x2b21; //Save ack only needed on final save.
- WFIFOL(fd,2) = aid;
- WFIFOL(fd,6) = cid;
- WFIFOSET(fd,10);
- }
- RFIFOSKIP(fd,size);
- }
- break;
-
- case 0x2b02: // req char selection
- if( RFIFOREST(fd) < 18 )
- return 0;
- else{
- int account_id = RFIFOL(fd,2);
- uint32 login_id1 = RFIFOL(fd,6);
- uint32 login_id2 = RFIFOL(fd,10);
- uint32 ip = RFIFOL(fd,14);
- RFIFOSKIP(fd,18);
-
- if( runflag != CHARSERVER_ST_RUNNING ){
- WFIFOHEAD(fd,7);
- WFIFOW(fd,0) = 0x2b03;
- WFIFOL(fd,2) = account_id;
- WFIFOB(fd,6) = 0;// not ok
- WFIFOSET(fd,7);
- }else{
- struct auth_node* node;
-
- // create temporary auth entry
- CREATE(node, struct auth_node, 1);
- node->account_id = account_id;
- node->char_id = 0;
- node->login_id1 = login_id1;
- node->login_id2 = login_id2;
- //node->sex = 0;
- node->ip = ntohl(ip);
- //node->expiration_time = 0; // unlimited/unknown time by default (not display in map-server)
- //node->gmlevel = 0;
- idb_put(auth_db, account_id, node);
-
- //Set char to "@ char select" in online db [Kevin]
- set_char_charselect(account_id);
-
- {
- struct online_char_data* character = (struct online_char_data*)idb_get(online_char_db, account_id);
-
- if( character != NULL ){
- character->pincode_success = true;
- }
- }
-
- WFIFOHEAD(fd,7);
- WFIFOW(fd,0) = 0x2b03;
- WFIFOL(fd,2) = account_id;
- WFIFOB(fd,6) = 1;// ok
- WFIFOSET(fd,7);
- }
- }
- break;
-
- case 0x2b05: // request "change map server"
- if (RFIFOREST(fd) < 39)
- return 0;
- {
- int map_id, map_fd = -1;
- struct mmo_charstatus* char_data;
- struct mmo_charstatus char_dat;
-
- map_id = search_mapserver(RFIFOW(fd,18), ntohl(RFIFOL(fd,24)), ntohs(RFIFOW(fd,28))); //Locate mapserver by ip and port.
- if (map_id >= 0)
- map_fd = server[map_id].fd;
- //Char should just had been saved before this packet, so this should be safe. [Skotlex]
- char_data = (struct mmo_charstatus*)uidb_get(char_db_,RFIFOL(fd,14));
- if (char_data == NULL) { //Really shouldn't happen.
- mmo_char_fromsql(RFIFOL(fd,14), &char_dat, true);
- char_data = (struct mmo_charstatus*)uidb_get(char_db_,RFIFOL(fd,14));
- }
-
- if( runflag == CHARSERVER_ST_RUNNING &&
- session_isActive(map_fd) &&
- char_data )
- { //Send the map server the auth of this player.
- struct online_char_data* data;
- struct auth_node* node;
-
- //Update the "last map" as this is where the player must be spawned on the new map server.
- char_data->last_point.map = RFIFOW(fd,18);
- char_data->last_point.x = RFIFOW(fd,20);
- char_data->last_point.y = RFIFOW(fd,22);
- char_data->sex = RFIFOB(fd,30);
-
- // create temporary auth entry
- CREATE(node, struct auth_node, 1);
- node->account_id = RFIFOL(fd,2);
- node->char_id = RFIFOL(fd,14);
- node->login_id1 = RFIFOL(fd,6);
- node->login_id2 = RFIFOL(fd,10);
- node->sex = RFIFOB(fd,30);
- node->expiration_time = 0; // FIXME (this thing isn't really supported we could as well purge it instead of fixing)
- node->ip = ntohl(RFIFOL(fd,31));
- node->group_id = RFIFOL(fd,35);
- node->changing_mapservers = 1;
- idb_put(auth_db, RFIFOL(fd,2), node);
-
- data = idb_ensure(online_char_db, RFIFOL(fd,2), create_online_char_data);
- data->char_id = char_data->char_id;
- data->server = map_id; //Update server where char is.
-
- //Reply with an ack.
- WFIFOHEAD(fd,30);
- WFIFOW(fd,0) = 0x2b06;
- memcpy(WFIFOP(fd,2), RFIFOP(fd,2), 28);
- WFIFOSET(fd,30);
- } else { //Reply with nak
- WFIFOHEAD(fd,30);
- WFIFOW(fd,0) = 0x2b06;
- memcpy(WFIFOP(fd,2), RFIFOP(fd,2), 28);
- WFIFOL(fd,6) = 0; //Set login1 to 0.
- WFIFOSET(fd,30);
- }
- RFIFOSKIP(fd,39);
- }
- break;
-
- case 0x2b07: // Remove RFIFOL(fd,6) (friend_id) from RFIFOL(fd,2) (char_id) friend list [Ind]
- if (RFIFOREST(fd) < 10)
- return 0;
- {
- int char_id, friend_id;
- char_id = RFIFOL(fd,2);
- friend_id = RFIFOL(fd,6);
- if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d' AND `friend_id`='%d' LIMIT 1",
- friend_db, char_id, friend_id) ) {
- Sql_ShowDebug(sql_handle);
- break;
- }
- RFIFOSKIP(fd,10);
- }
- break;
-
- case 0x2b08: // char name request
- if (RFIFOREST(fd) < 6)
- return 0;
-
- WFIFOHEAD(fd,30);
- WFIFOW(fd,0) = 0x2b09;
- WFIFOL(fd,2) = RFIFOL(fd,2);
- char_loadName((int)RFIFOL(fd,2), (char*)WFIFOP(fd,6));
- WFIFOSET(fd,30);
-
- RFIFOSKIP(fd,6);
- break;
-
- case 0x2b0c: // Map server send information to change an email of an account -> login-server
- if (RFIFOREST(fd) < 86)
- return 0;
- if (login_fd > 0) { // don't send request if no login-server
- WFIFOHEAD(login_fd,86);
- memcpy(WFIFOP(login_fd,0), RFIFOP(fd,0),86); // 0x2722 <account_id>.L <actual_e-mail>.40B <new_e-mail>.40B
- WFIFOW(login_fd,0) = 0x2722;
- WFIFOSET(login_fd,86);
- }
- RFIFOSKIP(fd, 86);
- break;
-
- case 0x2b0e: // Request from map-server to change an account's status (will just be forwarded to login server)
- if (RFIFOREST(fd) < 44)
- return 0;
- {
- int result = 0; // 0-login-server request done, 1-player not found, 2-gm level too low, 3-login-server offline
- char esc_name[NAME_LENGTH*2+1];
-
- int acc = RFIFOL(fd,2); // account_id of who ask (-1 if server itself made this request)
- const char* name = (char*)RFIFOP(fd,6); // name of the target character
- int type = RFIFOW(fd,30); // type of operation: 1-block, 2-ban, 3-unblock, 4-unban
- short year = RFIFOW(fd,32);
- short month = RFIFOW(fd,34);
- short day = RFIFOW(fd,36);
- short hour = RFIFOW(fd,38);
- short minute = RFIFOW(fd,40);
- short second = RFIFOW(fd,42);
- RFIFOSKIP(fd,44);
-
- Sql_EscapeStringLen(sql_handle, esc_name, name, strnlen(name, NAME_LENGTH));
- if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`name` FROM `%s` WHERE `name` = '%s'", char_db, esc_name) )
- Sql_ShowDebug(sql_handle);
- else
- if( Sql_NumRows(sql_handle) == 0 )
- {
- result = 1; // 1-player not found
- }
- else
- if( SQL_SUCCESS != Sql_NextRow(sql_handle) )
- Sql_ShowDebug(sql_handle);
- //FIXME: set proper result value?
- else
- {
- char name[NAME_LENGTH];
- int account_id;
- char* data;
-
- Sql_GetData(sql_handle, 0, &data, NULL); account_id = atoi(data);
- Sql_GetData(sql_handle, 1, &data, NULL); safestrncpy(name, data, sizeof(name));
-
- if( login_fd <= 0 )
- result = 3; // 3-login-server offline
- //FIXME: need to move this check to login server [ultramage]
-// else
-// if( acc != -1 && isGM(acc) < isGM(account_id) )
-// result = 2; // 2-gm level too low
- else
- switch( type ) {
- case 1: // block
- WFIFOHEAD(login_fd,10);
- WFIFOW(login_fd,0) = 0x2724;
- WFIFOL(login_fd,2) = account_id;
- WFIFOL(login_fd,6) = 5; // new account status
- WFIFOSET(login_fd,10);
- break;
- case 2: // ban
- WFIFOHEAD(login_fd,18);
- WFIFOW(login_fd, 0) = 0x2725;
- WFIFOL(login_fd, 2) = account_id;
- WFIFOW(login_fd, 6) = year;
- WFIFOW(login_fd, 8) = month;
- WFIFOW(login_fd,10) = day;
- WFIFOW(login_fd,12) = hour;
- WFIFOW(login_fd,14) = minute;
- WFIFOW(login_fd,16) = second;
- WFIFOSET(login_fd,18);
- break;
- case 3: // unblock
- WFIFOHEAD(login_fd,10);
- WFIFOW(login_fd,0) = 0x2724;
- WFIFOL(login_fd,2) = account_id;
- WFIFOL(login_fd,6) = 0; // new account status
- WFIFOSET(login_fd,10);
- break;
- case 4: // unban
- WFIFOHEAD(login_fd,6);
- WFIFOW(login_fd,0) = 0x272a;
- WFIFOL(login_fd,2) = account_id;
- WFIFOSET(login_fd,6);
- break;
- case 5: // changesex
- WFIFOHEAD(login_fd,6);
- WFIFOW(login_fd,0) = 0x2727;
- WFIFOL(login_fd,2) = account_id;
- WFIFOSET(login_fd,6);
- break;
- }
- }
-
- Sql_FreeResult(sql_handle);
-
- // send answer if a player ask, not if the server ask
- if( acc != -1 && type != 5) { // Don't send answer for changesex
- WFIFOHEAD(fd,34);
- WFIFOW(fd, 0) = 0x2b0f;
- WFIFOL(fd, 2) = acc;
- safestrncpy((char*)WFIFOP(fd,6), name, NAME_LENGTH);
- WFIFOW(fd,30) = type;
- WFIFOW(fd,32) = result;
- WFIFOSET(fd,34);
- }
- }
- break;
-
- case 0x2b10: // Update and send fame ranking list
- if (RFIFOREST(fd) < 11)
- return 0;
- {
- int cid = RFIFOL(fd, 2);
- int fame = RFIFOL(fd, 6);
- char type = RFIFOB(fd, 10);
- int size;
- struct fame_list* list;
- int player_pos;
- int fame_pos;
-
- switch(type)
- {
- case 1: size = fame_list_size_smith; list = smith_fame_list; break;
- case 2: size = fame_list_size_chemist; list = chemist_fame_list; break;
- case 3: size = fame_list_size_taekwon; list = taekwon_fame_list; break;
- default: size = 0; list = NULL; break;
- }
-
- ARR_FIND(0, size, player_pos, list[player_pos].id == cid);// position of the player
- ARR_FIND(0, size, fame_pos, list[fame_pos].fame <= fame);// where the player should be
-
- if( player_pos == size && fame_pos == size )
- ;// not on list and not enough fame to get on it
- else if( fame_pos == player_pos )
- {// same position
- list[player_pos].fame = fame;
- char_update_fame_list(type, player_pos, fame);
- }
- else
- {// move in the list
- if( player_pos == size )
- {// new ranker - not in the list
- ARR_MOVE(size - 1, fame_pos, list, struct fame_list);
- list[fame_pos].id = cid;
- list[fame_pos].fame = fame;
- char_loadName(cid, list[fame_pos].name);
- }
- else
- {// already in the list
- if( fame_pos == size )
- --fame_pos;// move to the end of the list
- ARR_MOVE(player_pos, fame_pos, list, struct fame_list);
- list[fame_pos].fame = fame;
- }
- char_send_fame_list(-1);
- }
-
- RFIFOSKIP(fd,11);
- }
- break;
-
- // Divorce chars
- case 0x2b11:
- if( RFIFOREST(fd) < 10 )
- return 0;
- divorce_char_sql(RFIFOL(fd,2), RFIFOL(fd,6));
- RFIFOSKIP(fd,10);
- break;
-
- case 0x2b16: // Receive rates [Wizputer]
- if( RFIFOREST(fd) < 14 )
- return 0;
- {
- char esc_server_name[sizeof(server_name)*2+1];
-
- Sql_EscapeString(sql_handle, esc_server_name, server_name);
-
- if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` SET `index`='%d',`name`='%s',`exp`='%d',`jexp`='%d',`drop`='%d'",
- ragsrvinfo_db, fd, esc_server_name, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10)) )
- Sql_ShowDebug(sql_handle);
- RFIFOSKIP(fd,14);
- }
- break;
-
- case 0x2b17: // Character disconnected set online 0 [Wizputer]
- if (RFIFOREST(fd) < 6)
- return 0;
- set_char_offline(RFIFOL(fd,2),RFIFOL(fd,6));
- RFIFOSKIP(fd,10);
- break;
-
- case 0x2b18: // Reset all chars to offline [Wizputer]
- set_all_offline(id);
- RFIFOSKIP(fd,2);
- break;
-
- case 0x2b19: // Character set online [Wizputer]
- if (RFIFOREST(fd) < 10)
- return 0;
- set_char_online(id, RFIFOL(fd,2),RFIFOL(fd,6));
- RFIFOSKIP(fd,10);
- break;
-
- case 0x2b1a: // Build and send fame ranking lists [DracoRPG]
- if (RFIFOREST(fd) < 2)
- return 0;
- char_read_fame_list();
- char_send_fame_list(-1);
- RFIFOSKIP(fd,2);
- break;
-
- case 0x2b1c: //Request to save status change data. [Skotlex]
- if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
- return 0;
- {
-#ifdef ENABLE_SC_SAVING
- int count, aid, cid;
-
- aid = RFIFOL(fd, 4);
- cid = RFIFOL(fd, 8);
- count = RFIFOW(fd, 12);
-
- if( count > 0 )
- {
- struct status_change_data data;
- StringBuf buf;
- int i;
-
- StringBuf_Init(&buf);
- StringBuf_Printf(&buf, "INSERT INTO `%s` (`account_id`, `char_id`, `type`, `tick`, `val1`, `val2`, `val3`, `val4`) VALUES ", scdata_db);
- for( i = 0; i < count; ++i )
- {
- memcpy (&data, RFIFOP(fd, 14+i*sizeof(struct status_change_data)), sizeof(struct status_change_data));
- if( i > 0 )
- StringBuf_AppendStr(&buf, ", ");
- StringBuf_Printf(&buf, "('%d','%d','%hu','%d','%d','%d','%d','%d')", aid, cid,
- data.type, data.tick, data.val1, data.val2, data.val3, data.val4);
- }
- if( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) )
- Sql_ShowDebug(sql_handle);
- StringBuf_Destroy(&buf);
- }
-#endif
- RFIFOSKIP(fd, RFIFOW(fd, 2));
- }
- break;
-
- case 0x2b23: // map-server alive packet
- WFIFOHEAD(fd,2);
- WFIFOW(fd,0) = 0x2b24;
- WFIFOSET(fd,2);
- RFIFOSKIP(fd,2);
- break;
-
- case 0x2b26: // auth request from map-server
- if (RFIFOREST(fd) < 19)
- return 0;
-
- {
- int account_id;
- int char_id;
- int login_id1;
- char sex;
- uint32 ip;
- struct auth_node* node;
- struct mmo_charstatus* cd;
- struct mmo_charstatus char_dat;
-
- account_id = RFIFOL(fd,2);
- char_id = RFIFOL(fd,6);
- login_id1 = RFIFOL(fd,10);
- sex = RFIFOB(fd,14);
- ip = ntohl(RFIFOL(fd,15));
- RFIFOSKIP(fd,19);
-
- node = (struct auth_node*)idb_get(auth_db, account_id);
- cd = (struct mmo_charstatus*)uidb_get(char_db_,char_id);
- if( cd == NULL )
- { //Really shouldn't happen.
- mmo_char_fromsql(char_id, &char_dat, true);
- cd = (struct mmo_charstatus*)uidb_get(char_db_,char_id);
- }
- if( runflag == CHARSERVER_ST_RUNNING &&
- cd != NULL &&
- node != NULL &&
- node->account_id == account_id &&
- node->char_id == char_id &&
- node->login_id1 == login_id1 &&
- node->sex == sex /*&&
- node->ip == ip*/ )
- {// auth ok
- cd->sex = sex;
-
- WFIFOHEAD(fd,25 + sizeof(struct mmo_charstatus));
- WFIFOW(fd,0) = 0x2afd;
- WFIFOW(fd,2) = 25 + sizeof(struct mmo_charstatus);
- WFIFOL(fd,4) = account_id;
- WFIFOL(fd,8) = node->login_id1;
- WFIFOL(fd,12) = node->login_id2;
- WFIFOL(fd,16) = (uint32)node->expiration_time; // FIXME: will wrap to negative after "19-Jan-2038, 03:14:07 AM GMT"
- WFIFOL(fd,20) = node->group_id;
- WFIFOB(fd,24) = node->changing_mapservers;
- memcpy(WFIFOP(fd,25), cd, sizeof(struct mmo_charstatus));
- WFIFOSET(fd, WFIFOW(fd,2));
-
- // only use the auth once and mark user online
- idb_remove(auth_db, account_id);
- set_char_online(id, char_id, account_id);
- }
- else
- {// auth failed
- WFIFOHEAD(fd,19);
- WFIFOW(fd,0) = 0x2b27;
- WFIFOL(fd,2) = account_id;
- WFIFOL(fd,6) = char_id;
- WFIFOL(fd,10) = login_id1;
- WFIFOB(fd,14) = sex;
- WFIFOL(fd,15) = htonl(ip);
- WFIFOSET(fd,19);
- }
- }
- break;
-
- case 0x2736: // ip address update
- if (RFIFOREST(fd) < 6) return 0;
- server[id].ip = ntohl(RFIFOL(fd, 2));
- ShowInfo("Updated IP address of map-server #%d to %d.%d.%d.%d.\n", id, CONVIP(server[id].ip));
- RFIFOSKIP(fd,6);
- break;
-
- case 0x3008:
- if( RFIFOREST(fd) < RFIFOW(fd,4) )
- return 0;/* packet wasn't fully received yet (still fragmented) */
- else {
- int sfd;/* stat server fd */
- RFIFOSKIP(fd, 2);/* we skip first 2 bytes which are the 0x3008, so we end up with a buffer equal to the one we send */
-
- if( (sfd = make_connection(host2ip("stats.rathena.org"),(uint16)25421,true,10) ) == -1 ) {
- RFIFOSKIP(fd, RFIFOW(fd,2) );/* skip this packet */
- break;/* connection not possible, we drop the report */
- }
-
- session[sfd]->flag.server = 1;/* to ensure we won't drop our own packet */
- WFIFOHEAD(sfd, RFIFOW(fd,2) );
- memcpy((char*)WFIFOP(sfd,0), (char*)RFIFOP(fd, 0), RFIFOW(fd,2));
- WFIFOSET(sfd, RFIFOW(fd,2) );
- flush_fifo(sfd);
- do_close(sfd);
- RFIFOSKIP(fd, RFIFOW(fd,2) );/* skip this packet */
- }
- break;
-
- default:
- {
- // inter server - packet
- int r = inter_parse_frommap(fd);
- if (r == 1) break; // processed
- if (r == 2) return 0; // need more packet
-
- // no inter server packet. no char server packet -> disconnect
- ShowError("Unknown packet 0x%04x from map server, disconnecting.\n", RFIFOW(fd,0));
- set_eof(fd);
- return 0;
- }
- } // switch
- } // while
-
- return 0;
-}
-
-void do_init_mapif(void)
-{
- int i;
- for( i = 0; i < ARRAYLENGTH(server); ++i )
- mapif_server_init(i);
-}
-
-void do_final_mapif(void)
-{
- int i;
- for( i = 0; i < ARRAYLENGTH(server); ++i )
- mapif_server_destroy(i);
-}
-
// Searches for the mapserver that has a given map (and optionally ip/port, if not -1).
// If found, returns the server's index in the 'server' array (otherwise returns -1).
int search_mapserver(unsigned short map, uint32 ip, uint16 port)
@@ -3555,17 +1939,10 @@
return -1;
}
-// Initialization process (currently only initialization inter_mapif)
-static int char_mapif_init(int fd)
-{
- return inter_mapif_init(fd);
-}
-
//--------------------------------------------
// Test to know if an IP come from LAN or WAN.
//--------------------------------------------
-int lan_subnetcheck(uint32 ip)
-{
+int lan_subnetcheck(uint32 ip){
int i;
ARR_FIND( 0, subnet_count, i, (subnet[i].char_ip & subnet[i].mask) == (ip & subnet[i].mask) );
if( i < subnet_count ) {
@@ -3578,937 +1955,8 @@
}
-/// @param result
-/// 0 (0x718): An unknown error has occurred.
-/// 1: none/success
-/// 3 (0x719): A database error occurred.
-/// 4 (0x71a): To delete a character you must withdraw from the guild.
-/// 5 (0x71b): To delete a character you must withdraw from the party.
-/// Any (0x718): An unknown error has occurred.
-void char_delete2_ack(int fd, int char_id, uint32 result, time_t delete_date)
-{// HC: <0828>.W <char id>.L <Msg:0-5>.L <deleteDate>.L
- WFIFOHEAD(fd,14);
- WFIFOW(fd,0) = 0x828;
- WFIFOL(fd,2) = char_id;
- WFIFOL(fd,6) = result;
- WFIFOL(fd,10) = TOL(delete_date);
- WFIFOSET(fd,14);
-}
-
-/// @param result
-/// 0 (0x718): An unknown error has occurred.
-/// 1: none/success
-/// 2 (0x71c): Due to system settings can not be deleted.
-/// 3 (0x719): A database error occurred.
-/// 4 (0x71d): Deleting not yet possible time.
-/// 5 (0x71e): Date of birth do not match.
-/// Any (0x718): An unknown error has occurred.
-void char_delete2_accept_ack(int fd, int char_id, uint32 result)
-{// HC: <082a>.W <char id>.L <Msg:0-5>.L
- WFIFOHEAD(fd,10);
- WFIFOW(fd,0) = 0x82a;
- WFIFOL(fd,2) = char_id;
- WFIFOL(fd,6) = result;
- WFIFOSET(fd,10);
-}
-
-
-/// @param result
-/// 1 (0x718): none/success, (if char id not in deletion process): An unknown error has occurred.
-/// 2 (0x719): A database error occurred.
-/// Any (0x718): An unknown error has occurred.
-void char_delete2_cancel_ack(int fd, int char_id, uint32 result)
-{// HC: <082c>.W <char id>.L <Msg:1-2>.L
- WFIFOHEAD(fd,10);
- WFIFOW(fd,0) = 0x82c;
- WFIFOL(fd,2) = char_id;
- WFIFOL(fd,6) = result;
- WFIFOSET(fd,10);
-}
-
-
-static void char_delete2_req(int fd, struct char_session_data* sd)
-{// CH: <0827>.W <char id>.L
- int char_id, i;
- char* data;
- time_t delete_date;
-
- char_id = RFIFOL(fd,2);
-
- ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == char_id );
- if( i == MAX_CHARS )
- {// character not found
- char_delete2_ack(fd, char_id, 3, 0);
- return;
- }
-
- if( SQL_SUCCESS != Sql_Query(sql_handle, "SELECT `delete_date` FROM `%s` WHERE `char_id`='%d'", char_db, char_id) || SQL_SUCCESS != Sql_NextRow(sql_handle) )
- {
- Sql_ShowDebug(sql_handle);
- char_delete2_ack(fd, char_id, 3, 0);
- return;
- }
-
- Sql_GetData(sql_handle, 0, &data, NULL); delete_date = strtoul(data, NULL, 10);
-
- if( delete_date ) {// character already queued for deletion
- char_delete2_ack(fd, char_id, 0, 0);
- return;
- }
-
-/*
- // Aegis imposes these checks probably to avoid dead member
- // entries in guilds/parties, otherwise they are not required.
- // TODO: Figure out how these are enforced during waiting.
- if( guild_id )
- {// character in guild
- char_delete2_ack(fd, char_id, 4, 0);
- return;
- }
-
- if( party_id )
- {// character in party
- char_delete2_ack(fd, char_id, 5, 0);
- return;
- }
-*/
-
- // success
- delete_date = time(NULL)+char_del_delay;
-
- if( SQL_SUCCESS != Sql_Query(sql_handle, "UPDATE `%s` SET `delete_date`='%lu' WHERE `char_id`='%d'", char_db, (unsigned long)delete_date, char_id) )
- {
- Sql_ShowDebug(sql_handle);
- char_delete2_ack(fd, char_id, 3, 0);
- return;
- }
-
- char_delete2_ack(fd, char_id, 1, delete_date);
-}
-
-
-static void char_delete2_accept(int fd, struct char_session_data* sd)
-{// CH: <0829>.W <char id>.L <birth date:YYMMDD>.6B
- char birthdate[8+1];
- int char_id, i, k;
- unsigned int base_level;
- char* data;
- time_t delete_date;
-
- char_id = RFIFOL(fd,2);
-
- ShowInfo(CL_RED"Request Char Deletion: "CL_GREEN"%d (%d)"CL_RESET"\n", sd->account_id, char_id);
-
- // construct "YY-MM-DD"
- birthdate[0] = RFIFOB(fd,6);
- birthdate[1] = RFIFOB(fd,7);
- birthdate[2] = '-';
- birthdate[3] = RFIFOB(fd,8);
- birthdate[4] = RFIFOB(fd,9);
- birthdate[5] = '-';
- birthdate[6] = RFIFOB(fd,10);
- birthdate[7] = RFIFOB(fd,11);
- birthdate[8] = 0;
-
- ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == char_id );
- if( i == MAX_CHARS )
- {// character not found
- char_delete2_accept_ack(fd, char_id, 3);
- return;
- }
-
- if( SQL_SUCCESS != Sql_Query(sql_handle, "SELECT `base_level`,`delete_date` FROM `%s` WHERE `char_id`='%d'", char_db, char_id) || SQL_SUCCESS != Sql_NextRow(sql_handle) )
- {// data error
- Sql_ShowDebug(sql_handle);
- char_delete2_accept_ack(fd, char_id, 3);
- return;
- }
-
- Sql_GetData(sql_handle, 0, &data, NULL); base_level = (unsigned int)strtoul(data, NULL, 10);
- Sql_GetData(sql_handle, 1, &data, NULL); delete_date = strtoul(data, NULL, 10);
-
- if( !delete_date || delete_date>time(NULL) )
- {// not queued or delay not yet passed
- char_delete2_accept_ack(fd, char_id, 4);
- return;
- }
-
- if( strcmp(sd->birthdate+2, birthdate) ) // +2 to cut off the century
- {// birth date is wrong
- char_delete2_accept_ack(fd, char_id, 5);
- return;
- }
-
- if( ( char_del_level > 0 && base_level >= (unsigned int)char_del_level ) || ( char_del_level < 0 && base_level <= (unsigned int)(-char_del_level) ) )
- {// character level config restriction
- char_delete2_accept_ack(fd, char_id, 2);
- return;
- }
-
- // success
- if( delete_char_sql(char_id) < 0 )
- {
- char_delete2_accept_ack(fd, char_id, 3);
- return;
- }
-
- // refresh character list cache
- for(k = i; k < MAX_CHARS-1; k++)
- {
- sd->found_char[k] = sd->found_char[k+1];
- }
- sd->found_char[MAX_CHARS-1] = -1;
-
- char_delete2_accept_ack(fd, char_id, 1);
-}
-
-
-static void char_delete2_cancel(int fd, struct char_session_data* sd)
-{// CH: <082b>.W <char id>.L
- int char_id, i;
-
- char_id = RFIFOL(fd,2);
-
- ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == char_id );
- if( i == MAX_CHARS )
- {// character not found
- char_delete2_cancel_ack(fd, char_id, 2);
- return;
- }
-
- // there is no need to check, whether or not the character was
- // queued for deletion, as the client prints an error message by
- // itself, if it was not the case (@see char_delete2_cancel_ack)
- if( SQL_SUCCESS != Sql_Query(sql_handle, "UPDATE `%s` SET `delete_date`='0' WHERE `char_id`='%d'", char_db, char_id) )
- {
- Sql_ShowDebug(sql_handle);
- char_delete2_cancel_ack(fd, char_id, 2);
- return;
- }
-
- char_delete2_cancel_ack(fd, char_id, 1);
-}
-
-
-int parse_char(int fd)
-{
- int i, ch;
- char email[40];
- unsigned short cmd;
- int map_fd;
- struct char_session_data* sd;
- uint32 ipl = session[fd]->client_addr;
-
- sd = (struct char_session_data*)session[fd]->session_data;
-
- // disconnect any player if no login-server.
- if(login_fd < 0)
- set_eof(fd);
-
- if(session[fd]->flag.eof)
- {
- if( sd != NULL && sd->auth )
- { // already authed client
- struct online_char_data* data = (struct online_char_data*)idb_get(online_char_db, sd->account_id);
- if( data != NULL && data->fd == fd)
- data->fd = -1;
- if( data == NULL || data->server == -1) //If it is not in any server, send it offline. [Skotlex]
- set_char_offline(-1,sd->account_id);
- }
- do_close(fd);
- return 0;
- }
-
- while( RFIFOREST(fd) >= 2 )
- {
- //For use in packets that depend on an sd being present [Skotlex]
- #define FIFOSD_CHECK(rest) { if(RFIFOREST(fd) < rest) return 0; if (sd==NULL || !sd->auth) { RFIFOSKIP(fd,rest); return 0; } }
-
- cmd = RFIFOW(fd,0);
- switch( cmd )
- {
-
- // request to connect
- // 0065 <account id>.L <login id1>.L <login id2>.L <???>.W <sex>.B
- case 0x65:
- if( RFIFOREST(fd) < 17 )
- return 0;
- {
- struct auth_node* node;
-
- int account_id = RFIFOL(fd,2);
- uint32 login_id1 = RFIFOL(fd,6);
- uint32 login_id2 = RFIFOL(fd,10);
- int sex = RFIFOB(fd,16);
- RFIFOSKIP(fd,17);
-
- ShowInfo("request connect - account_id:%d/login_id1:%d/login_id2:%d\n", account_id, login_id1, login_id2);
-
- if (sd) {
- //Received again auth packet for already authentified account?? Discard it.
- //TODO: Perhaps log this as a hack attempt?
- //TODO: and perhaps send back a reply?
- break;
- }
-
- CREATE(session[fd]->session_data, struct char_session_data, 1);
- sd = (struct char_session_data*)session[fd]->session_data;
- sd->account_id = account_id;
- sd->login_id1 = login_id1;
- sd->login_id2 = login_id2;
- sd->sex = sex;
- sd->auth = false; // not authed yet
-
- // send back account_id
- WFIFOHEAD(fd,4);
- WFIFOL(fd,0) = account_id;
- WFIFOSET(fd,4);
-
- if( runflag != CHARSERVER_ST_RUNNING )
- {
- WFIFOHEAD(fd,3);
- WFIFOW(fd,0) = 0x6c;
- WFIFOB(fd,2) = 0;// rejected from server
- WFIFOSET(fd,3);
- break;
- }
-
- // search authentification
- node = (struct auth_node*)idb_get(auth_db, account_id);
- if( node != NULL &&
- node->account_id == account_id &&
- node->login_id1 == login_id1 &&
- node->login_id2 == login_id2 /*&&
- node->ip == ipl*/ )
- {// authentication found (coming from map server)
- idb_remove(auth_db, account_id);
- char_auth_ok(fd, sd);
- }
- else
- {// authentication not found (coming from login server)
- if (login_fd > 0) { // don't send request if no login-server
- WFIFOHEAD(login_fd,23);
- WFIFOW(login_fd,0) = 0x2712; // ask login-server to authentify an account
- WFIFOL(login_fd,2) = sd->account_id;
- WFIFOL(login_fd,6) = sd->login_id1;
- WFIFOL(login_fd,10) = sd->login_id2;
- WFIFOB(login_fd,14) = sd->sex;
- WFIFOL(login_fd,15) = htonl(ipl);
- WFIFOL(login_fd,19) = fd;
- WFIFOSET(login_fd,23);
- } else { // if no login-server, we must refuse connection
- WFIFOHEAD(fd,3);
- WFIFOW(fd,0) = 0x6c;
- WFIFOB(fd,2) = 0;
- WFIFOSET(fd,3);
- }
- }
- }
- break;
-
- // char select
- case 0x66:
- FIFOSD_CHECK(3);
- {
- struct mmo_charstatus char_dat;
- struct mmo_charstatus *cd;
- char* data;
- int char_id;
- uint32 subnet_map_ip;
- struct auth_node* node;
-
- int slot = RFIFOB(fd,2);
- RFIFOSKIP(fd,3);
-
- if ( SQL_SUCCESS != Sql_Query(sql_handle, "SELECT `char_id` FROM `%s` WHERE `account_id`='%d' AND `char_num`='%d'", char_db, sd->account_id, slot)
- || SQL_SUCCESS != Sql_NextRow(sql_handle)
- || SQL_SUCCESS != Sql_GetData(sql_handle, 0, &data, NULL) )
- { //Not found?? May be forged packet.
- Sql_ShowDebug(sql_handle);
- Sql_FreeResult(sql_handle);
- WFIFOHEAD(fd,3);
- WFIFOW(fd,0) = 0x6c;
- WFIFOB(fd,2) = 0; // rejected from server
- WFIFOSET(fd,3);
- break;
- }
-
- char_id = atoi(data);
- Sql_FreeResult(sql_handle);
-
- /* set char as online prior to loading its data so 3rd party applications will realise the sql data is not reliable */
- set_char_online(-2,char_id,sd->account_id);
- if( !mmo_char_fromsql(char_id, &char_dat, true) ) { /* failed? set it back offline */
- set_char_offline(char_id, sd->account_id);
- /* failed to load something. REJECT! */
- WFIFOHEAD(fd,3);
- WFIFOW(fd,0) = 0x6c;
- WFIFOB(fd,2) = 0;
- WFIFOSET(fd,3);
- break;/* jump off this boat */
- }
-
- //Have to switch over to the DB instance otherwise data won't propagate [Kevin]
- cd = (struct mmo_charstatus *)idb_get(char_db_, char_id);
- cd->sex = sd->sex;
-
- if (log_char) {
- char esc_name[NAME_LENGTH*2+1];
-
- Sql_EscapeStringLen(sql_handle, esc_name, char_dat.name, strnlen(char_dat.name, NAME_LENGTH));
- if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s`(`time`, `account_id`,`char_num`,`name`) VALUES (NOW(), '%d', '%d', '%s')",
- charlog_db, sd->account_id, slot, esc_name) )
- Sql_ShowDebug(sql_handle);
- }
- ShowInfo("Selected char: (Account %d: %d - %s)\n", sd->account_id, slot, char_dat.name);
-
- // searching map server
- i = search_mapserver(cd->last_point.map, -1, -1);
-
- // if map is not found, we check major cities
- if (i < 0 || !cd->last_point.map) {
- unsigned short j;
- //First check that there's actually a map server online.
- ARR_FIND( 0, ARRAYLENGTH(server), j, server[j].fd >= 0 && server[j].map[0] );
- if (j == ARRAYLENGTH(server)) {
- ShowInfo("Connection Closed. No map servers available.\n");
- WFIFOHEAD(fd,3);
- WFIFOW(fd,0) = 0x81;
- WFIFOB(fd,2) = 1; // 01 = Server closed
- WFIFOSET(fd,3);
- break;
- }
- if ((i = search_mapserver((j=mapindex_name2id(MAP_PRONTERA)),-1,-1)) >= 0) {
- cd->last_point.x = 273;
- cd->last_point.y = 354;
- } else if ((i = search_mapserver((j=mapindex_name2id(MAP_GEFFEN)),-1,-1)) >= 0) {
- cd->last_point.x = 120;
- cd->last_point.y = 100;
- } else if ((i = search_mapserver((j=mapindex_name2id(MAP_MORROC)),-1,-1)) >= 0) {
- cd->last_point.x = 160;
- cd->last_point.y = 94;
- } else if ((i = search_mapserver((j=mapindex_name2id(MAP_ALBERTA)),-1,-1)) >= 0) {
- cd->last_point.x = 116;
- cd->last_point.y = 57;
- } else if ((i = search_mapserver((j=mapindex_name2id(MAP_PAYON)),-1,-1)) >= 0) {
- cd->last_point.x = 87;
- cd->last_point.y = 117;
- } else if ((i = search_mapserver((j=mapindex_name2id(MAP_IZLUDE)),-1,-1)) >= 0) {
- cd->last_point.x = 94;
- cd->last_point.y = 103;
- } else {
- ShowInfo("Connection Closed. No map server available that has a major city, and unable to find map-server for '%s'.\n", mapindex_id2name(cd->last_point.map));
- WFIFOHEAD(fd,3);
- WFIFOW(fd,0) = 0x81;
- WFIFOB(fd,2) = 1; // 01 = Server closed
- WFIFOSET(fd,3);
- break;
- }
- ShowWarning("Unable to find map-server for '%s', sending to major city '%s'.\n", mapindex_id2name(cd->last_point.map), mapindex_id2name(j));
- cd->last_point.map = j;
- }
-
- //Send NEW auth packet [Kevin]
- //FIXME: is this case even possible? [ultramage]
- if ((map_fd = server[i].fd) < 1 || session[map_fd] == NULL)
- {
- ShowError("parse_char: Attempting to write to invalid session %d! Map Server #%d disconnected.\n", map_fd, i);
- server[i].fd = -1;
- memset(&server[i], 0, sizeof(struct mmo_map_server));
- //Send server closed.
- WFIFOHEAD(fd,3);
- WFIFOW(fd,0) = 0x81;
- WFIFOB(fd,2) = 1; // 01 = Server closed
- WFIFOSET(fd,3);
- break;
- }
-
- //Send player to map
- WFIFOHEAD(fd,28);
- WFIFOW(fd,0) = 0x71;
- WFIFOL(fd,2) = cd->char_id;
- mapindex_getmapname_ext(mapindex_id2name(cd->last_point.map), (char*)WFIFOP(fd,6));
- subnet_map_ip = lan_subnetcheck(ipl); // Advanced subnet check [LuzZza]
- WFIFOL(fd,22) = htonl((subnet_map_ip) ? subnet_map_ip : server[i].ip);
- WFIFOW(fd,26) = ntows(htons(server[i].port)); // [!] LE byte order here [!]
- WFIFOSET(fd,28);
-
- // create temporary auth entry
- CREATE(node, struct auth_node, 1);
- node->account_id = sd->account_id;
- node->char_id = cd->char_id;
- node->login_id1 = sd->login_id1;
- node->login_id2 = sd->login_id2;
- node->sex = sd->sex;
- node->expiration_time = sd->expiration_time;
- node->group_id = sd->group_id;
- node->ip = ipl;
- idb_put(auth_db, sd->account_id, node);
-
- }
- break;
-
- // create new char
-#if PACKETVER >= 20120307
- // S 0970 <name>.24B <slot>.B <hair color>.W <hair style>.W
- case 0x970:
- FIFOSD_CHECK(31);
-#else
- // S 0067 <name>.24B <str>.B <agi>.B <vit>.B <int>.B <dex>.B <luk>.B <slot>.B <hair color>.W <hair style>.W
- case 0x67:
- FIFOSD_CHECK(37);
-#endif
-
- if( !char_new ) //turn character creation on/off [Kevin]
- i = -2;
- else
-#if PACKETVER >= 20120307
- i = make_new_char_sql(sd, (char*)RFIFOP(fd,2),RFIFOB(fd,26),RFIFOW(fd,27),RFIFOW(fd,29));
-#else
- i = make_new_char_sql(sd, (char*)RFIFOP(fd,2),RFIFOB(fd,26),RFIFOB(fd,27),RFIFOB(fd,28),RFIFOB(fd,29),RFIFOB(fd,30),RFIFOB(fd,31),RFIFOB(fd,32),RFIFOW(fd,33),RFIFOW(fd,35));
-#endif
-
- //'Charname already exists' (-1), 'Char creation denied' (-2) and 'You are underaged' (-3)
- if (i < 0) {
- WFIFOHEAD(fd,3);
- WFIFOW(fd,0) = 0x6e;
- /* Others I found [Ind] */
- /* 0x02 = Symbols in Character Names are forbidden */
- /* 0x03 = You are not elegible to open the Character Slot. */
- switch (i) {
- case -1: WFIFOB(fd,2) = 0x00; break;
- case -2: WFIFOB(fd,2) = 0xFF; break;
- case -3: WFIFOB(fd,2) = 0x01; break;
- case -4: WFIFOB(fd,2) = 0x03; break;
- }
- WFIFOSET(fd,3);
- } else {
- int len;
- // retrieve data
- struct mmo_charstatus char_dat;
- mmo_char_fromsql(i, &char_dat, false); //Only the short data is needed.
-
- // send to player
- WFIFOHEAD(fd,2+MAX_CHAR_BUF);
- WFIFOW(fd,0) = 0x6d;
- len = 2 + mmo_char_tobuf(WFIFOP(fd,2), &char_dat);
- WFIFOSET(fd,len);
-
- // add new entry to the chars list
- ARR_FIND( 0, MAX_CHARS, ch, sd->found_char[ch] == -1 );
- if( ch < MAX_CHARS )
- sd->found_char[ch] = i; // the char_id of the new char
- }
-#if PACKETVER >= 20120307
- RFIFOSKIP(fd,31);
-#else
- RFIFOSKIP(fd,37);
-#endif
- break;
-
- // delete char
- case 0x68:
- // 2004-04-19aSakexe+ langtype 12 char deletion packet
- case 0x1fb:
- if (cmd == 0x68) FIFOSD_CHECK(46);
- if (cmd == 0x1fb) FIFOSD_CHECK(56);
- {
- int cid = RFIFOL(fd,2);
-
- ShowInfo(CL_RED"Request Char Deletion: "CL_GREEN"%d (%d)"CL_RESET"\n", sd->account_id, cid);
- memcpy(email, RFIFOP(fd,6), 40);
- RFIFOSKIP(fd,( cmd == 0x68) ? 46 : 56);
-
- // Check if e-mail is correct
- if(strcmpi(email, sd->email) && //email does not matches and
- (
- strcmp("[email protected]", sd->email) || //it is not default email, or
- (strcmp("[email protected]", email) && strcmp("", email)) //email sent does not matches default
- )) { //Fail
- WFIFOHEAD(fd,3);
- WFIFOW(fd,0) = 0x70;
- WFIFOB(fd,2) = 0; // 00 = Incorrect Email address
- WFIFOSET(fd,3);
- break;
- }
-
- // check if this char exists
- ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == cid );
- if( i == MAX_CHARS )
- { // Such a character does not exist in the account
- WFIFOHEAD(fd,3);
- WFIFOW(fd,0) = 0x70;
- WFIFOB(fd,2) = 0;
- WFIFOSET(fd,3);
- break;
- }
-
- // remove char from list and compact it
- for(ch = i; ch < MAX_CHARS-1; ch++)
- sd->found_char[ch] = sd->found_char[ch+1];
- sd->found_char[MAX_CHARS-1] = -1;
-
- /* Delete character */
- if(delete_char_sql(cid)<0){
- //can't delete the char
- //either SQL error or can't delete by some CONFIG conditions
- //del fail
- WFIFOHEAD(fd,3);
- WFIFOW(fd, 0) = 0x70;
- WFIFOB(fd, 2) = 0;
- WFIFOSET(fd, 3);
- break;
- }
- /* Char successfully deleted.*/
- WFIFOHEAD(fd,2);
- WFIFOW(fd,0) = 0x6f;
- WFIFOSET(fd,2);
- }
- break;
-
- // client keep-alive packet (every 12 seconds)
- // R 0187 <account ID>.l
- case 0x187:
- if (RFIFOREST(fd) < 6)
- return 0;
- RFIFOSKIP(fd,6);
- break;
- // char rename request
- // R 08fc <char ID>.l <new name>.24B
- case 0x8fc:
- FIFOSD_CHECK(30);
- {
- int i, cid =RFIFOL(fd,2);
- char name[NAME_LENGTH];
- char esc_name[NAME_LENGTH*2+1];
- safestrncpy(name, (char *)RFIFOP(fd,6), NAME_LENGTH);
- RFIFOSKIP(fd,30);
-
- ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == cid );
- if( i == MAX_CHARS )