Modified the charservers to use a DBMap instead of a cyclic array for auth data.
Merged the auth fix from r12473 to TXT as well. Removed the no-op from r12547. git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@12551 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
parent
977a966a6c
commit
fd5f918452
600
src/char/char.c
600
src/char/char.c
@ -111,16 +111,6 @@ struct char_session_data {
|
|||||||
time_t expiration_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited)
|
time_t expiration_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited)
|
||||||
};
|
};
|
||||||
|
|
||||||
#define AUTH_FIFO_SIZE 256
|
|
||||||
struct {
|
|
||||||
int account_id, char_id, login_id1, login_id2;
|
|
||||||
uint32 ip;
|
|
||||||
int delflag;
|
|
||||||
int sex;
|
|
||||||
time_t expiration_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited)
|
|
||||||
} auth_fifo[AUTH_FIFO_SIZE];
|
|
||||||
int auth_fifo_pos = 0;
|
|
||||||
|
|
||||||
int char_id_count = START_CHAR_NUM;
|
int char_id_count = START_CHAR_NUM;
|
||||||
struct character_data *char_dat;
|
struct character_data *char_dat;
|
||||||
|
|
||||||
@ -160,7 +150,29 @@ int online_gm_display_min_level = 20; // minimum GM level to display 'GM' when w
|
|||||||
//These are used to aid the map server in identifying valid clients. [Skotlex]
|
//These are used to aid the map server in identifying valid clients. [Skotlex]
|
||||||
static int max_account_id = DEFAULT_MAX_ACCOUNT_ID, max_char_id = DEFAULT_MAX_CHAR_ID;
|
static int max_account_id = DEFAULT_MAX_ACCOUNT_ID, max_char_id = DEFAULT_MAX_CHAR_ID;
|
||||||
|
|
||||||
//Structure for holding in memory which characters are online on the map servers connected.
|
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)
|
||||||
|
};
|
||||||
|
|
||||||
|
static DBMap* auth_db; // int account_id -> struct auth_node*
|
||||||
|
|
||||||
|
//-----------------------------------------------------
|
||||||
|
// Online User Database
|
||||||
|
//-----------------------------------------------------
|
||||||
|
|
||||||
struct online_char_data {
|
struct online_char_data {
|
||||||
int account_id;
|
int account_id;
|
||||||
int char_id;
|
int char_id;
|
||||||
@ -169,135 +181,13 @@ struct online_char_data {
|
|||||||
short server;
|
short server;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Holds all online characters.
|
|
||||||
static DBMap* online_char_db; // int account_id -> struct online_char_data*
|
static DBMap* online_char_db; // int account_id -> struct online_char_data*
|
||||||
|
static int chardb_waiting_disconnect(int tid, unsigned int tick, int id, int data);
|
||||||
|
|
||||||
int console = 0;
|
static void* create_online_char_data(DBKey key, va_list args)
|
||||||
|
|
||||||
//------------------------------
|
|
||||||
// Writing function of logs file
|
|
||||||
//------------------------------
|
|
||||||
int char_log(char *fmt, ...)
|
|
||||||
{
|
|
||||||
if(log_char)
|
|
||||||
{
|
|
||||||
FILE *logfp;
|
|
||||||
va_list ap;
|
|
||||||
time_t raw_time;
|
|
||||||
char tmpstr[2048];
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
|
|
||||||
logfp = fopen(char_log_filename, "a");
|
|
||||||
if (logfp) {
|
|
||||||
if (fmt[0] == '\0') // jump a line if no message
|
|
||||||
fprintf(logfp, "\n");
|
|
||||||
else {
|
|
||||||
time(&raw_time);
|
|
||||||
strftime(tmpstr, 24, "%d-%m-%Y %H:%M:%S", localtime(&raw_time));
|
|
||||||
sprintf(tmpstr + 19, ": %s", fmt);
|
|
||||||
vfprintf(logfp, tmpstr, ap);
|
|
||||||
}
|
|
||||||
fclose(logfp);
|
|
||||||
}
|
|
||||||
va_end(ap);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
|
||||||
// Determine if an account (id) is a GM account
|
|
||||||
// and returns its level (or 0 if it isn't a GM account or if not found)
|
|
||||||
//----------------------------------------------------------------------
|
|
||||||
int isGM(int account_id)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for(i = 0; i < GM_num; i++)
|
|
||||||
if (gm_account[i].account_id == account_id)
|
|
||||||
return gm_account[i].level;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Search character data from the aid/cid givem
|
|
||||||
struct mmo_charstatus* search_character(int aid, int cid)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < char_num; i++) {
|
|
||||||
if (char_dat[i].status.char_id == cid && char_dat[i].status.account_id == aid)
|
|
||||||
return &char_dat[i].status;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mmo_charstatus* search_character_byname(char* character_name)
|
|
||||||
{
|
|
||||||
int i = search_character_index(character_name);
|
|
||||||
if (i == -1) return NULL;
|
|
||||||
return &char_dat[i].status;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------
|
|
||||||
// Search an character id
|
|
||||||
// (return character index or -1 (if not found))
|
|
||||||
// If exact character name is not found,
|
|
||||||
// the function checks without case sensitive
|
|
||||||
// and returns index if only 1 character is found
|
|
||||||
// and similar to the searched name.
|
|
||||||
//----------------------------------------------
|
|
||||||
int search_character_index(char* character_name)
|
|
||||||
{
|
|
||||||
int i, quantity, index;
|
|
||||||
|
|
||||||
quantity = 0;
|
|
||||||
index = -1;
|
|
||||||
for(i = 0; i < char_num; i++) {
|
|
||||||
// Without case sensitive check (increase the number of similar character names found)
|
|
||||||
if (stricmp(char_dat[i].status.name, character_name) == 0) {
|
|
||||||
// Strict comparison (if found, we finish the function immediatly with correct value)
|
|
||||||
if (strcmp(char_dat[i].status.name, character_name) == 0)
|
|
||||||
return i;
|
|
||||||
quantity++;
|
|
||||||
index = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Here, the exact character name is not found
|
|
||||||
// We return the found index of a similar account ONLY if there is 1 similar character
|
|
||||||
if (quantity == 1)
|
|
||||||
return index;
|
|
||||||
|
|
||||||
// Exact character name is not found and 0 or more than 1 similar characters have been found ==> we say not found
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------------------
|
|
||||||
// Return character name with the index
|
|
||||||
//-------------------------------------
|
|
||||||
char * search_character_name(int index)
|
|
||||||
{
|
|
||||||
if (index >= 0 && index < char_num)
|
|
||||||
return char_dat[index].status.name;
|
|
||||||
|
|
||||||
return unknown_char_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Searches if the given character is online, and returns the fd of the
|
|
||||||
// map-server it is connected to.
|
|
||||||
int search_character_online(int aid, int cid)
|
|
||||||
{
|
|
||||||
//Look for online character.
|
|
||||||
struct online_char_data* character;
|
|
||||||
character = (struct online_char_data*)idb_get(online_char_db, aid);
|
|
||||||
if(character &&
|
|
||||||
character->char_id == cid &&
|
|
||||||
character->server > -1)
|
|
||||||
return server[character->server].fd;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
static void * create_online_char_data(DBKey key, va_list args)
|
|
||||||
{
|
{
|
||||||
struct online_char_data* character;
|
struct online_char_data* character;
|
||||||
character = (struct online_char_data*)aCalloc(1, sizeof(struct online_char_data));
|
CREATE(character, struct online_char_data, 1);
|
||||||
character->account_id = key.i;
|
character->account_id = key.i;
|
||||||
character->char_id = -1;
|
character->char_id = -1;
|
||||||
character->server = -1;
|
character->server = -1;
|
||||||
@ -306,12 +196,6 @@ static void * create_online_char_data(DBKey key, va_list args)
|
|||||||
return character;
|
return character;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int chardb_waiting_disconnect(int tid, unsigned int tick, int id, int data);
|
|
||||||
|
|
||||||
//-------------------------------------------------
|
|
||||||
// Set Character online/offline [Wizputer]
|
|
||||||
//-------------------------------------------------
|
|
||||||
|
|
||||||
void set_char_online(int map_id, int char_id, int account_id)
|
void set_char_online(int map_id, int char_id, int account_id)
|
||||||
{
|
{
|
||||||
struct online_char_data* character;
|
struct online_char_data* character;
|
||||||
@ -328,7 +212,7 @@ void set_char_online(int map_id, int char_id, int account_id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
character = (struct online_char_data*)idb_ensure(online_char_db, account_id, create_online_char_data);
|
character = (struct online_char_data*)idb_ensure(online_char_db, account_id, create_online_char_data);
|
||||||
if (online_check && character->char_id != -1 && character->server > -1 && character->server != map_id)
|
if (online_check && character->char_id != -1 && character->server > -1 && character->server != map_id && map_id != -3)
|
||||||
{
|
{
|
||||||
//char == 99 <- Character logging in, so someone has logged in while one
|
//char == 99 <- Character logging in, so someone has logged in while one
|
||||||
//char is still on map-server, so kick him out, but don't print "error"
|
//char is still on map-server, so kick him out, but don't print "error"
|
||||||
@ -339,9 +223,6 @@ void set_char_online(int map_id, int char_id, int account_id)
|
|||||||
mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 2);
|
mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
character->char_id = (char_id==99)?-1:char_id;
|
|
||||||
character->server = (char_id==99)?-1:map_id;
|
|
||||||
|
|
||||||
if( character->server > -1 )
|
if( character->server > -1 )
|
||||||
server[character->server].users++;
|
server[character->server].users++;
|
||||||
|
|
||||||
@ -349,6 +230,13 @@ void set_char_online(int map_id, int char_id, int account_id)
|
|||||||
delete_timer(character->waiting_disconnect, chardb_waiting_disconnect);
|
delete_timer(character->waiting_disconnect, chardb_waiting_disconnect);
|
||||||
character->waiting_disconnect = -1;
|
character->waiting_disconnect = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//If user is NOT at char screen, delete entry [Kevin]
|
||||||
|
if(character->char_id != -1)
|
||||||
|
{
|
||||||
|
idb_remove(online_char_db, account_id);
|
||||||
|
}
|
||||||
|
|
||||||
if (login_fd > 0 && !session[login_fd]->flag.eof)
|
if (login_fd > 0 && !session[login_fd]->flag.eof)
|
||||||
{
|
{
|
||||||
WFIFOHEAD(login_fd,6);
|
WFIFOHEAD(login_fd,6);
|
||||||
@ -435,6 +323,116 @@ void set_all_offline(int id)
|
|||||||
WFIFOSET(login_fd,2);
|
WFIFOSET(login_fd,2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//------------------------------
|
||||||
|
// Writing function of logs file
|
||||||
|
//------------------------------
|
||||||
|
int char_log(char *fmt, ...)
|
||||||
|
{
|
||||||
|
if(log_char)
|
||||||
|
{
|
||||||
|
FILE *logfp;
|
||||||
|
va_list ap;
|
||||||
|
time_t raw_time;
|
||||||
|
char tmpstr[2048];
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
|
||||||
|
logfp = fopen(char_log_filename, "a");
|
||||||
|
if (logfp) {
|
||||||
|
if (fmt[0] == '\0') // jump a line if no message
|
||||||
|
fprintf(logfp, "\n");
|
||||||
|
else {
|
||||||
|
time(&raw_time);
|
||||||
|
strftime(tmpstr, 24, "%d-%m-%Y %H:%M:%S", localtime(&raw_time));
|
||||||
|
sprintf(tmpstr + 19, ": %s", fmt);
|
||||||
|
vfprintf(logfp, tmpstr, ap);
|
||||||
|
}
|
||||||
|
fclose(logfp);
|
||||||
|
}
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// Determine if an account (id) is a GM account
|
||||||
|
// and returns its level (or 0 if it isn't a GM account or if not found)
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
int isGM(int account_id)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for(i = 0; i < GM_num; i++)
|
||||||
|
if (gm_account[i].account_id == account_id)
|
||||||
|
return gm_account[i].level;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Search character data from the aid/cid givem
|
||||||
|
struct mmo_charstatus* search_character(int aid, int cid)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < char_num; i++) {
|
||||||
|
if (char_dat[i].status.char_id == cid && char_dat[i].status.account_id == aid)
|
||||||
|
return &char_dat[i].status;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct mmo_charstatus* search_character_byname(char* character_name)
|
||||||
|
{
|
||||||
|
int i = search_character_index(character_name);
|
||||||
|
if (i == -1) return NULL;
|
||||||
|
return &char_dat[i].status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Searches if the given character is online, and returns the fd of the
|
||||||
|
// map-server it is connected to.
|
||||||
|
int search_character_online(int aid, int cid)
|
||||||
|
{
|
||||||
|
//Look for online character.
|
||||||
|
struct online_char_data* character;
|
||||||
|
character = idb_get(online_char_db, aid);
|
||||||
|
if(character &&
|
||||||
|
character->char_id == cid &&
|
||||||
|
character->server > -1)
|
||||||
|
return server[character->server].fd;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------
|
||||||
|
// Search an character id
|
||||||
|
// (return character index or -1 (if not found))
|
||||||
|
// If exact character name is not found,
|
||||||
|
// the function checks without case sensitive
|
||||||
|
// and returns index if only 1 character is found
|
||||||
|
// and similar to the searched name.
|
||||||
|
//----------------------------------------------
|
||||||
|
int search_character_index(char* character_name)
|
||||||
|
{
|
||||||
|
int i, quantity, index;
|
||||||
|
|
||||||
|
quantity = 0;
|
||||||
|
index = -1;
|
||||||
|
for(i = 0; i < char_num; i++) {
|
||||||
|
// Without case sensitive check (increase the number of similar character names found)
|
||||||
|
if (stricmp(char_dat[i].status.name, character_name) == 0) {
|
||||||
|
// Strict comparison (if found, we finish the function immediatly with correct value)
|
||||||
|
if (strcmp(char_dat[i].status.name, character_name) == 0)
|
||||||
|
return i;
|
||||||
|
quantity++;
|
||||||
|
index = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Here, the exact character name is not found
|
||||||
|
// We return the found index of a similar account ONLY if there is 1 similar character
|
||||||
|
if (quantity == 1)
|
||||||
|
return index;
|
||||||
|
|
||||||
|
// Exact character name is not found and 0 or more than 1 similar characters have been found ==> we say not found
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/*---------------------------------------------------
|
/*---------------------------------------------------
|
||||||
Make a data line for friends list
|
Make a data line for friends list
|
||||||
--------------------------------------------------*/
|
--------------------------------------------------*/
|
||||||
@ -2066,72 +2064,77 @@ int parse_fromlogin(int fd)
|
|||||||
RFIFOSKIP(fd,2);
|
RFIFOSKIP(fd,2);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x2723: // changesex reply (modified by [Yor])
|
// changesex reply
|
||||||
|
case 0x2723:
|
||||||
if (RFIFOREST(fd) < 7)
|
if (RFIFOREST(fd) < 7)
|
||||||
return 0;
|
return 0;
|
||||||
{
|
{
|
||||||
int acc, sex, i, j;
|
int i, j;
|
||||||
unsigned char buf[7];
|
unsigned char buf[7];
|
||||||
acc = RFIFOL(fd,2);
|
|
||||||
sex = RFIFOB(fd,6);
|
|
||||||
if (acc > 0) {
|
|
||||||
for(i = 0; i < AUTH_FIFO_SIZE; i++) {
|
|
||||||
if (auth_fifo[i].account_id == acc)
|
|
||||||
auth_fifo[i].sex = sex;
|
|
||||||
}
|
|
||||||
for (i = 0; i < char_num; i++) {
|
|
||||||
if (char_dat[i].status.account_id == acc) {
|
|
||||||
int jobclass = char_dat[i].status.class_;
|
|
||||||
char_dat[i].status.sex = sex;
|
|
||||||
if (jobclass == JOB_BARD || jobclass == JOB_DANCER ||
|
|
||||||
jobclass == JOB_CLOWN || jobclass == JOB_GYPSY ||
|
|
||||||
jobclass == JOB_BABY_BARD || jobclass == JOB_BABY_DANCER) {
|
|
||||||
// job modification
|
|
||||||
if (jobclass == JOB_BARD || jobclass == JOB_DANCER) {
|
|
||||||
char_dat[i].status.class_ = (sex) ? JOB_BARD : JOB_DANCER;
|
|
||||||
} else if (jobclass == JOB_CLOWN || jobclass == JOB_GYPSY) {
|
|
||||||
char_dat[i].status.class_ = (sex) ? JOB_CLOWN : JOB_GYPSY;
|
|
||||||
} else if (jobclass == JOB_BABY_BARD || jobclass == JOB_BABY_DANCER) {
|
|
||||||
char_dat[i].status.class_ = (sex) ? JOB_BABY_BARD : JOB_BABY_DANCER;
|
|
||||||
}
|
|
||||||
// remove specifical skills of classes 19, 4020 and 4042
|
|
||||||
for(j = 315; j <= 322; j++) {
|
|
||||||
if (char_dat[i].status.skill[j].id > 0 && !char_dat[i].status.skill[j].flag) {
|
|
||||||
if (char_dat[i].status.skill_point > USHRT_MAX - char_dat[i].status.skill[j].lv)
|
|
||||||
char_dat[i].status.skill_point = USHRT_MAX;
|
|
||||||
else
|
|
||||||
char_dat[i].status.skill_point += char_dat[i].status.skill[j].lv;
|
|
||||||
char_dat[i].status.skill[j].id = 0;
|
|
||||||
char_dat[i].status.skill[j].lv = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// remove specifical skills of classes 20, 4021 and 4043
|
|
||||||
for(j = 323; j <= 330; j++) {
|
|
||||||
if (char_dat[i].status.skill[j].id > 0 && !char_dat[i].status.skill[j].flag) {
|
|
||||||
if (char_dat[i].status.skill_point > USHRT_MAX - char_dat[i].status.skill[j].lv)
|
|
||||||
char_dat[i].status.skill_point = USHRT_MAX;
|
|
||||||
else
|
|
||||||
char_dat[i].status.skill_point += char_dat[i].status.skill[j].lv;
|
|
||||||
|
|
||||||
char_dat[i].status.skill[j].id = 0;
|
int acc = RFIFOL(fd,2);
|
||||||
char_dat[i].status.skill[j].lv = 0;
|
int sex = RFIFOB(fd,6);
|
||||||
}
|
RFIFOSKIP(fd,7);
|
||||||
|
|
||||||
|
if( acc > 0 )
|
||||||
|
{
|
||||||
|
struct auth_node* node = (struct auth_node*)idb_get(auth_db, acc);
|
||||||
|
if( node != NULL )
|
||||||
|
node->sex = sex;
|
||||||
|
|
||||||
|
ARR_FIND( 0, char_num, i, char_dat[i].status.account_id == acc );
|
||||||
|
if( i < char_num )
|
||||||
|
{
|
||||||
|
int jobclass = char_dat[i].status.class_;
|
||||||
|
char_dat[i].status.sex = sex;
|
||||||
|
if (jobclass == JOB_BARD || jobclass == JOB_DANCER ||
|
||||||
|
jobclass == JOB_CLOWN || jobclass == JOB_GYPSY ||
|
||||||
|
jobclass == JOB_BABY_BARD || jobclass == JOB_BABY_DANCER) {
|
||||||
|
// job modification
|
||||||
|
if (jobclass == JOB_BARD || jobclass == JOB_DANCER) {
|
||||||
|
char_dat[i].status.class_ = (sex) ? JOB_BARD : JOB_DANCER;
|
||||||
|
} else if (jobclass == JOB_CLOWN || jobclass == JOB_GYPSY) {
|
||||||
|
char_dat[i].status.class_ = (sex) ? JOB_CLOWN : JOB_GYPSY;
|
||||||
|
} else if (jobclass == JOB_BABY_BARD || jobclass == JOB_BABY_DANCER) {
|
||||||
|
char_dat[i].status.class_ = (sex) ? JOB_BABY_BARD : JOB_BABY_DANCER;
|
||||||
|
}
|
||||||
|
// remove specifical skills of classes 19, 4020 and 4042
|
||||||
|
for(j = 315; j <= 322; j++) {
|
||||||
|
if (char_dat[i].status.skill[j].id > 0 && !char_dat[i].status.skill[j].flag) {
|
||||||
|
if (char_dat[i].status.skill_point > USHRT_MAX - char_dat[i].status.skill[j].lv)
|
||||||
|
char_dat[i].status.skill_point = USHRT_MAX;
|
||||||
|
else
|
||||||
|
char_dat[i].status.skill_point += char_dat[i].status.skill[j].lv;
|
||||||
|
char_dat[i].status.skill[j].id = 0;
|
||||||
|
char_dat[i].status.skill[j].lv = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// to avoid any problem with equipment and invalid sex, equipment is unequiped.
|
// remove specifical skills of classes 20, 4021 and 4043
|
||||||
for (j = 0; j < MAX_INVENTORY; j++) {
|
for(j = 323; j <= 330; j++) {
|
||||||
if (char_dat[i].status.inventory[j].nameid && char_dat[i].status.inventory[j].equip)
|
if (char_dat[i].status.skill[j].id > 0 && !char_dat[i].status.skill[j].flag) {
|
||||||
char_dat[i].status.inventory[j].equip = 0;
|
if (char_dat[i].status.skill_point > USHRT_MAX - char_dat[i].status.skill[j].lv)
|
||||||
}
|
char_dat[i].status.skill_point = USHRT_MAX;
|
||||||
char_dat[i].status.weapon = 0;
|
else
|
||||||
char_dat[i].status.shield = 0;
|
char_dat[i].status.skill_point += char_dat[i].status.skill[j].lv;
|
||||||
char_dat[i].status.head_top = 0;
|
|
||||||
char_dat[i].status.head_mid = 0;
|
|
||||||
char_dat[i].status.head_bottom = 0;
|
|
||||||
|
|
||||||
if (char_dat[i].status.guild_id) //If there is a guild, update the guild_member data [Skotlex]
|
char_dat[i].status.skill[j].id = 0;
|
||||||
inter_guild_sex_changed(char_dat[i].status.guild_id, acc, char_dat[i].status.char_id, sex);
|
char_dat[i].status.skill[j].lv = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// to avoid any problem with equipment and invalid sex, equipment is unequiped.
|
||||||
|
for (j = 0; j < MAX_INVENTORY; j++) {
|
||||||
|
if (char_dat[i].status.inventory[j].nameid && char_dat[i].status.inventory[j].equip)
|
||||||
|
char_dat[i].status.inventory[j].equip = 0;
|
||||||
|
}
|
||||||
|
char_dat[i].status.weapon = 0;
|
||||||
|
char_dat[i].status.shield = 0;
|
||||||
|
char_dat[i].status.head_top = 0;
|
||||||
|
char_dat[i].status.head_mid = 0;
|
||||||
|
char_dat[i].status.head_bottom = 0;
|
||||||
|
|
||||||
|
if (char_dat[i].status.guild_id) //If there is a guild, update the guild_member data [Skotlex]
|
||||||
|
inter_guild_sex_changed(char_dat[i].status.guild_id, acc, char_dat[i].status.char_id, sex);
|
||||||
}
|
}
|
||||||
// disconnect player if online on char-server
|
// disconnect player if online on char-server
|
||||||
disconnect_player(acc);
|
disconnect_player(acc);
|
||||||
@ -2140,8 +2143,6 @@ int parse_fromlogin(int fd)
|
|||||||
WBUFL(buf,2) = acc;
|
WBUFL(buf,2) = acc;
|
||||||
WBUFB(buf,6) = sex;
|
WBUFB(buf,6) = sex;
|
||||||
mapif_sendall(buf, 7);
|
mapif_sendall(buf, 7);
|
||||||
|
|
||||||
RFIFOSKIP(fd,7);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -2318,38 +2319,39 @@ int parse_fromlogin(int fd)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
//Login server request to kick a character out. [Skotlex]
|
// Login server request to kick a character out. [Skotlex]
|
||||||
case 0x2734:
|
case 0x2734:
|
||||||
if (RFIFOREST(fd) < 6)
|
if (RFIFOREST(fd) < 6)
|
||||||
return 0;
|
return 0;
|
||||||
{
|
{
|
||||||
struct online_char_data* character;
|
|
||||||
int aid = RFIFOL(fd,2);
|
int aid = RFIFOL(fd,2);
|
||||||
if ((character = (struct online_char_data*)idb_get(online_char_db, aid)) != NULL)
|
struct online_char_data* character = (struct online_char_data*)idb_get(online_char_db, aid);
|
||||||
{ //Kick out this player.
|
RFIFOSKIP(fd,6);
|
||||||
if (character->server > -1)
|
if( character != NULL )
|
||||||
|
{// account is already marked as online!
|
||||||
|
if( character->server > -1 )
|
||||||
{ //Kick it from the map server it is on.
|
{ //Kick it from the map server it is on.
|
||||||
mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 2);
|
mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 2);
|
||||||
if (character->waiting_disconnect == -1)
|
if (character->waiting_disconnect == -1)
|
||||||
character->waiting_disconnect = add_timer(gettick()+15000, chardb_waiting_disconnect, character->account_id, 0);
|
character->waiting_disconnect = add_timer(gettick()+AUTH_TIMEOUT, chardb_waiting_disconnect, character->account_id, 0);
|
||||||
} else { //Manual kick from char server.
|
}
|
||||||
|
else
|
||||||
|
{// Manual kick from char server.
|
||||||
struct char_session_data *tsd;
|
struct char_session_data *tsd;
|
||||||
int i;
|
int i;
|
||||||
for(i = 0; i < fd_max; i++) {
|
ARR_FIND( 0, fd_max, i, session[i] && (tsd = (struct char_session_data*)session[i]->session_data) && tsd->account_id == aid );
|
||||||
if (session[i] && (tsd = (struct char_session_data*)session[i]->session_data) && tsd->account_id == aid)
|
if( i < fd_max )
|
||||||
{
|
{
|
||||||
WFIFOHEAD(i,3);
|
WFIFOHEAD(i,3);
|
||||||
WFIFOW(i,0) = 0x81;
|
WFIFOW(i,0) = 0x81;
|
||||||
WFIFOB(i,2) = 2; // "Someone has already logged in with this id"
|
WFIFOB(i,2) = 2; // "Someone has already logged in with this id"
|
||||||
WFIFOSET(i,3);
|
WFIFOSET(i,3);
|
||||||
break;
|
set_eof(i);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (i == fd_max) //Shouldn't happen, but just in case.
|
else //Shouldn't happen, but just in case.
|
||||||
set_char_offline(99, aid);
|
set_char_offline(99, aid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RFIFOSKIP(fd,6);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -2798,26 +2800,37 @@ int parse_frommap(int fd)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x2b02: // req char selection
|
case 0x2b02: // req char selection
|
||||||
if (RFIFOREST(fd) < 18)
|
if( RFIFOREST(fd) < 18 )
|
||||||
return 0;
|
return 0;
|
||||||
|
{
|
||||||
|
struct auth_node* node;
|
||||||
|
|
||||||
if (auth_fifo_pos >= AUTH_FIFO_SIZE)
|
int account_id = RFIFOL(fd,2);
|
||||||
auth_fifo_pos = 0;
|
uint32 login_id1 = RFIFOL(fd,6);
|
||||||
|
uint32 login_id2 = RFIFOL(fd,10);
|
||||||
|
uint32 ip = RFIFOL(fd,14);
|
||||||
|
RFIFOSKIP(fd,18);
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
idb_put(auth_db, account_id, node);
|
||||||
|
|
||||||
|
//Set char to "@ char select" in online db [Kevin]
|
||||||
|
set_char_online(-3, 99, account_id);
|
||||||
|
|
||||||
auth_fifo[auth_fifo_pos].account_id = RFIFOL(fd,2);
|
|
||||||
auth_fifo[auth_fifo_pos].char_id = 0;
|
|
||||||
auth_fifo[auth_fifo_pos].login_id1 = RFIFOL(fd,6);
|
|
||||||
auth_fifo[auth_fifo_pos].login_id2 = RFIFOL(fd,10);
|
|
||||||
auth_fifo[auth_fifo_pos].delflag = 2;
|
|
||||||
auth_fifo[auth_fifo_pos].expiration_time = 0; // unlimited/unknown time by default (not display in map-server)
|
|
||||||
auth_fifo[auth_fifo_pos].ip = ntohl(RFIFOL(fd,14));
|
|
||||||
auth_fifo_pos++;
|
|
||||||
WFIFOHEAD(fd,7);
|
WFIFOHEAD(fd,7);
|
||||||
WFIFOW(fd,0) = 0x2b03;
|
WFIFOW(fd,0) = 0x2b03;
|
||||||
WFIFOL(fd,2) = RFIFOL(fd,2);
|
WFIFOL(fd,2) = account_id;
|
||||||
WFIFOB(fd,6) = 0;
|
WFIFOB(fd,6) = 0;
|
||||||
WFIFOSET(fd,7);
|
WFIFOSET(fd,7);
|
||||||
RFIFOSKIP(fd,18);
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x2b05: // request "change map server"
|
case 0x2b05: // request "change map server"
|
||||||
@ -3204,7 +3217,7 @@ int parse_char(int fd)
|
|||||||
{
|
{
|
||||||
struct online_char_data* data = (struct online_char_data*)idb_get(online_char_db, sd->account_id);
|
struct online_char_data* data = (struct online_char_data*)idb_get(online_char_db, sd->account_id);
|
||||||
if( data == NULL || data->server == -1) //If it is not in any server, send it offline. [Skotlex]
|
if( data == NULL || data->server == -1) //If it is not in any server, send it offline. [Skotlex]
|
||||||
set_char_offline(99,sd->account_id);
|
set_char_offline(-1,sd->account_id);
|
||||||
if( data != NULL && data->fd == fd)
|
if( data != NULL && data->fd == fd)
|
||||||
data->fd = -1;
|
data->fd = -1;
|
||||||
}
|
}
|
||||||
@ -3224,24 +3237,27 @@ int parse_char(int fd)
|
|||||||
// request to connect
|
// request to connect
|
||||||
// 0065 <account id>.L <login id1>.L <login id2>.L <???>.W <sex>.B
|
// 0065 <account id>.L <login id1>.L <login id2>.L <???>.W <sex>.B
|
||||||
case 0x65:
|
case 0x65:
|
||||||
if (RFIFOREST(fd) < 17)
|
if( RFIFOREST(fd) < 17 )
|
||||||
return 0;
|
return 0;
|
||||||
{
|
{
|
||||||
int account_id = RFIFOL(fd,2);
|
struct auth_node* node;
|
||||||
int login_id1 = RFIFOL(fd,6);
|
|
||||||
int login_id2 = RFIFOL(fd,10);
|
|
||||||
int sex = RFIFOB(fd,16);
|
|
||||||
|
|
||||||
int GM_value;
|
int GM_value;
|
||||||
|
|
||||||
|
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);
|
ShowInfo("request connect - account_id:%d/login_id1:%d/login_id2:%d\n", account_id, login_id1, login_id2);
|
||||||
|
|
||||||
if (sd) {
|
if (sd) {
|
||||||
//Received again auth packet for already authentified account?? Discard it.
|
//Received again auth packet for already authentified account?? Discard it.
|
||||||
//TODO: Perhaps log this as a hack attempt?
|
//TODO: Perhaps log this as a hack attempt?
|
||||||
//TODO: and perhaps send back a reply?
|
//TODO: and perhaps send back a reply?
|
||||||
RFIFOSKIP(fd,17);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( (GM_value = isGM(account_id)) != 0 )
|
if( (GM_value = isGM(account_id)) != 0 )
|
||||||
ShowInfo("Account Logged On; Account ID: %d (GM level %d).\n", account_id, GM_value);
|
ShowInfo("Account Logged On; Account ID: %d (GM level %d).\n", account_id, GM_value);
|
||||||
else
|
else
|
||||||
@ -3263,17 +3279,18 @@ int parse_char(int fd)
|
|||||||
WFIFOSET(fd,4);
|
WFIFOSET(fd,4);
|
||||||
|
|
||||||
// search authentification
|
// search authentification
|
||||||
ARR_FIND( 0, AUTH_FIFO_SIZE, i,
|
node = (struct auth_node*)idb_get(auth_db, account_id);
|
||||||
auth_fifo[i].account_id == sd->account_id &&
|
if( node != NULL &&
|
||||||
auth_fifo[i].login_id1 == sd->login_id1 &&
|
node->account_id == account_id &&
|
||||||
auth_fifo[i].login_id2 == sd->login_id2 &&
|
node->login_id1 == login_id1 &&
|
||||||
auth_fifo[i].ip == session[fd]->client_addr &&
|
node->login_id2 == login_id2 &&
|
||||||
auth_fifo[i].delflag == 2 );
|
node->ip == ipl )
|
||||||
|
{// authentication found (coming from map server)
|
||||||
if( i < AUTH_FIFO_SIZE ) {
|
idb_remove(auth_db, account_id);
|
||||||
auth_fifo[i].delflag = 1;
|
|
||||||
char_auth_ok(fd, sd);
|
char_auth_ok(fd, sd);
|
||||||
} else { // authentication not found
|
}
|
||||||
|
else
|
||||||
|
{// authentication not found (coming from login server)
|
||||||
if (login_fd > 0) { // don't send request if no login-server
|
if (login_fd > 0) { // don't send request if no login-server
|
||||||
WFIFOHEAD(login_fd,19);
|
WFIFOHEAD(login_fd,19);
|
||||||
WFIFOW(login_fd,0) = 0x2712; // ask login-server to authentify an account
|
WFIFOW(login_fd,0) = 0x2712; // ask login-server to authentify an account
|
||||||
@ -3281,7 +3298,7 @@ int parse_char(int fd)
|
|||||||
WFIFOL(login_fd,6) = sd->login_id1;
|
WFIFOL(login_fd,6) = sd->login_id1;
|
||||||
WFIFOL(login_fd,10) = sd->login_id2;
|
WFIFOL(login_fd,10) = sd->login_id2;
|
||||||
WFIFOB(login_fd,14) = sd->sex;
|
WFIFOB(login_fd,14) = sd->sex;
|
||||||
WFIFOL(login_fd,15) = htonl(session[fd]->client_addr);
|
WFIFOL(login_fd,15) = htonl(ipl);
|
||||||
WFIFOSET(login_fd,19);
|
WFIFOSET(login_fd,19);
|
||||||
} else { // if no login-server, we must refuse connection
|
} else { // if no login-server, we must refuse connection
|
||||||
WFIFOHEAD(fd,3);
|
WFIFOHEAD(fd,3);
|
||||||
@ -3291,17 +3308,17 @@ int parse_char(int fd)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RFIFOSKIP(fd,17);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// char select
|
// char select
|
||||||
case 0x66:
|
case 0x66:
|
||||||
FIFOSD_CHECK(3);
|
FIFOSD_CHECK(3);
|
||||||
{
|
{
|
||||||
int slot = RFIFOB(fd,2);
|
|
||||||
struct mmo_charstatus *cd;
|
struct mmo_charstatus *cd;
|
||||||
|
uint32 subnet_map_ip;
|
||||||
|
struct auth_node* node;
|
||||||
|
|
||||||
|
int slot = RFIFOB(fd,2);
|
||||||
RFIFOSKIP(fd,3);
|
RFIFOSKIP(fd,3);
|
||||||
|
|
||||||
// if we activated email creation and email is default email
|
// if we activated email creation and email is default email
|
||||||
@ -3369,33 +3386,8 @@ int parse_char(int fd)
|
|||||||
cd->last_point.map = j;
|
cd->last_point.map = j;
|
||||||
}
|
}
|
||||||
|
|
||||||
//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));
|
|
||||||
{
|
|
||||||
// Advanced subnet check [LuzZza]
|
|
||||||
uint32 subnet_map_ip;
|
|
||||||
subnet_map_ip = lan_subnetcheck(ipl);
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
ShowInfo("Character selection '%s' (account: %d, slot: %d).\n", cd->name, sd->account_id, ch);
|
|
||||||
|
|
||||||
if (auth_fifo_pos >= AUTH_FIFO_SIZE)
|
|
||||||
auth_fifo_pos = 0;
|
|
||||||
auth_fifo[auth_fifo_pos].account_id = sd->account_id;
|
|
||||||
auth_fifo[auth_fifo_pos].char_id = cd->char_id;
|
|
||||||
auth_fifo[auth_fifo_pos].login_id1 = sd->login_id1;
|
|
||||||
auth_fifo[auth_fifo_pos].login_id2 = sd->login_id2;
|
|
||||||
auth_fifo[auth_fifo_pos].delflag = 0;
|
|
||||||
auth_fifo[auth_fifo_pos].sex = sd->sex;
|
|
||||||
auth_fifo[auth_fifo_pos].expiration_time = sd->expiration_time;
|
|
||||||
auth_fifo[auth_fifo_pos].ip = session[fd]->client_addr;
|
|
||||||
|
|
||||||
//Send NEW auth packet [Kevin]
|
//Send NEW auth packet [Kevin]
|
||||||
|
//FIXME: is this case even possible? [ultramage]
|
||||||
if ((map_fd = server[i].fd) < 1 || session[map_fd] == NULL)
|
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);
|
ShowError("parse_char: Attempting to write to invalid session %d! Map Server #%d disconnected.\n", map_fd, i);
|
||||||
@ -3409,19 +3401,43 @@ int parse_char(int fd)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Send auth to server.
|
//Send player to map
|
||||||
WFIFOHEAD(map_fd, 20 + sizeof(struct mmo_charstatus));
|
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));
|
||||||
|
|
||||||
|
// Advanced subnet check [LuzZza]
|
||||||
|
subnet_map_ip = lan_subnetcheck(ipl);
|
||||||
|
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);
|
||||||
|
|
||||||
|
ShowInfo("Character selection '%s' (account: %d, slot: %d).\n", cd->name, sd->account_id, ch);
|
||||||
|
|
||||||
|
//Send auth ok to map server
|
||||||
|
WFIFOHEAD(map_fd,20 + sizeof(struct mmo_charstatus));
|
||||||
WFIFOW(map_fd,0) = 0x2afd;
|
WFIFOW(map_fd,0) = 0x2afd;
|
||||||
WFIFOW(map_fd,2) = 20 + sizeof(struct mmo_charstatus);
|
WFIFOW(map_fd,2) = 20 + sizeof(struct mmo_charstatus);
|
||||||
WFIFOL(map_fd,4) = auth_fifo[auth_fifo_pos].account_id;
|
WFIFOL(map_fd,4) = sd->account_id;
|
||||||
WFIFOL(map_fd,8) = auth_fifo[auth_fifo_pos].login_id1;
|
WFIFOL(map_fd,8) = sd->login_id1;
|
||||||
WFIFOL(map_fd,16) = auth_fifo[auth_fifo_pos].login_id2;
|
WFIFOL(map_fd,16) = sd->login_id2;
|
||||||
WFIFOL(map_fd,12) = (unsigned long)auth_fifo[auth_fifo_pos].expiration_time;
|
WFIFOL(map_fd,12) = (unsigned long)sd->expiration_time;
|
||||||
memcpy(WFIFOP(map_fd,20), cd, sizeof(struct mmo_charstatus));
|
memcpy(WFIFOP(map_fd,20), cd, sizeof(struct mmo_charstatus));
|
||||||
WFIFOSET(map_fd, WFIFOW(map_fd,2));
|
WFIFOSET(map_fd, WFIFOW(map_fd,2));
|
||||||
|
|
||||||
|
// 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->ip = ipl;
|
||||||
|
idb_put(auth_db, sd->account_id, node);
|
||||||
|
|
||||||
set_char_online(i, cd->char_id, cd->account_id);
|
set_char_online(i, cd->char_id, cd->account_id);
|
||||||
auth_fifo_pos++;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -4158,6 +4174,7 @@ void do_final(void)
|
|||||||
online_char_db->clear(online_char_db, NULL); //clean the db...
|
online_char_db->clear(online_char_db, NULL); //clean the db...
|
||||||
create_online_files();
|
create_online_files();
|
||||||
online_char_db->destroy(online_char_db, NULL); //dispose the db...
|
online_char_db->destroy(online_char_db, NULL); //dispose the db...
|
||||||
|
auth_db->destroy(auth_db, NULL);
|
||||||
|
|
||||||
if(gm_account) aFree(gm_account);
|
if(gm_account) aFree(gm_account);
|
||||||
if(char_dat) aFree(char_dat);
|
if(char_dat) aFree(char_dat);
|
||||||
@ -4219,6 +4236,7 @@ int do_init(int argc, char **argv)
|
|||||||
char_log("The char-server starting...\n");
|
char_log("The char-server starting...\n");
|
||||||
|
|
||||||
ShowInfo("Initializing char server.\n");
|
ShowInfo("Initializing char server.\n");
|
||||||
|
auth_db = idb_alloc(DB_OPT_RELEASE_DATA);
|
||||||
online_char_db = idb_alloc(DB_OPT_RELEASE_DATA);
|
online_char_db = idb_alloc(DB_OPT_RELEASE_DATA);
|
||||||
mmo_char_init();
|
mmo_char_init();
|
||||||
char_read_fame_list(); //Read fame lists.
|
char_read_fame_list(); //Read fame lists.
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "../common/malloc.h"
|
#include "../common/malloc.h"
|
||||||
#include "../common/lock.h"
|
#include "../common/lock.h"
|
||||||
#include "../common/showmsg.h"
|
#include "../common/showmsg.h"
|
||||||
|
#include "../common/strlib.h"
|
||||||
#include "char.h"
|
#include "char.h"
|
||||||
#include "inter.h"
|
#include "inter.h"
|
||||||
#include "int_party.h"
|
#include "int_party.h"
|
||||||
@ -480,14 +481,13 @@ static struct WisData* mapif_create_whisper(int fd, char* src, char* dst, char*
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Wisp/page request to send
|
// Wisp/page request to send
|
||||||
int mapif_parse_WisRequest(int fd) {
|
int mapif_parse_WisRequest(int fd)
|
||||||
|
{
|
||||||
struct mmo_charstatus* char_status;
|
struct mmo_charstatus* char_status;
|
||||||
struct WisData* wd;
|
struct WisData* wd;
|
||||||
char name[NAME_LENGTH];
|
char name[NAME_LENGTH];
|
||||||
int fd2;
|
int fd2;
|
||||||
|
|
||||||
RFIFOHEAD(fd);
|
|
||||||
|
|
||||||
if (RFIFOW(fd,2)-52 >= sizeof(wd->msg)) {
|
if (RFIFOW(fd,2)-52 >= sizeof(wd->msg)) {
|
||||||
ShowWarning("inter: Wis message size too long.\n");
|
ShowWarning("inter: Wis message size too long.\n");
|
||||||
return 0;
|
return 0;
|
||||||
@ -496,8 +496,8 @@ int mapif_parse_WisRequest(int fd) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(name, RFIFOP(fd,28), NAME_LENGTH); //Received name may be too large and not contain \0! [Skotlex]
|
safestrncpy(name, (char*)RFIFOP(fd,28), NAME_LENGTH); //Received name may be too large and not contain \0! [Skotlex]
|
||||||
name[NAME_LENGTH-1]= '\0';
|
|
||||||
// search if character exists before to ask all map-servers
|
// search if character exists before to ask all map-servers
|
||||||
char_status = search_character_byname(name);
|
char_status = search_character_byname(name);
|
||||||
if (char_status == NULL)
|
if (char_status == NULL)
|
||||||
|
@ -20,13 +20,6 @@
|
|||||||
#include "char.h"
|
#include "char.h"
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#ifdef WIN32
|
|
||||||
#include <winsock2.h>
|
|
||||||
#else
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#endif
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -143,16 +136,6 @@ struct char_session_data {
|
|||||||
time_t expiration_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited)
|
time_t expiration_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited)
|
||||||
};
|
};
|
||||||
|
|
||||||
#define AUTH_FIFO_SIZE 256
|
|
||||||
struct {
|
|
||||||
int account_id, char_id, login_id1, login_id2;
|
|
||||||
uint32 ip;
|
|
||||||
int delflag;
|
|
||||||
int sex;
|
|
||||||
time_t expiration_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited)
|
|
||||||
} auth_fifo[AUTH_FIFO_SIZE];
|
|
||||||
int auth_fifo_pos = 0;
|
|
||||||
|
|
||||||
int char_num, char_max;
|
int char_num, char_max;
|
||||||
int max_connect_user = 0;
|
int max_connect_user = 0;
|
||||||
int gm_allow_level = 99;
|
int gm_allow_level = 99;
|
||||||
@ -186,7 +169,27 @@ int GM_num = 0;
|
|||||||
|
|
||||||
int console = 0;
|
int console = 0;
|
||||||
|
|
||||||
//Structure for holding in memory which characters are online on the map servers connected.
|
//-----------------------------------------------------
|
||||||
|
// 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)
|
||||||
|
};
|
||||||
|
|
||||||
|
static DBMap* auth_db; // int account_id -> struct auth_node*
|
||||||
|
|
||||||
|
//-----------------------------------------------------
|
||||||
|
// Online User Database
|
||||||
|
//-----------------------------------------------------
|
||||||
|
|
||||||
struct online_char_data {
|
struct online_char_data {
|
||||||
int account_id;
|
int account_id;
|
||||||
int char_id;
|
int char_id;
|
||||||
@ -195,8 +198,8 @@ struct online_char_data {
|
|||||||
short server; // -2: unknown server, -1: not connected, 0+: id of server
|
short server; // -2: unknown server, -1: not connected, 0+: id of server
|
||||||
};
|
};
|
||||||
|
|
||||||
// Holds all online characters.
|
static DBMap* online_char_db; // int account_id -> struct online_char_data*
|
||||||
DBMap* online_char_db; // int account_id -> struct online_char_data*
|
static int chardb_waiting_disconnect(int tid, unsigned int tick, int id, int data);
|
||||||
|
|
||||||
static void* create_online_char_data(DBKey key, va_list args)
|
static void* create_online_char_data(DBKey key, va_list args)
|
||||||
{
|
{
|
||||||
@ -210,12 +213,6 @@ static void* create_online_char_data(DBKey key, va_list args)
|
|||||||
return character;
|
return character;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int chardb_waiting_disconnect(int tid, unsigned int tick, int id, int data);
|
|
||||||
|
|
||||||
//-------------------------------------------------
|
|
||||||
// Set Character online/offline [Wizputer]
|
|
||||||
//-------------------------------------------------
|
|
||||||
|
|
||||||
void set_char_online(int map_id, int char_id, int account_id)
|
void set_char_online(int map_id, int char_id, int account_id)
|
||||||
{
|
{
|
||||||
struct online_char_data* character;
|
struct online_char_data* character;
|
||||||
@ -1876,9 +1873,12 @@ int parse_fromlogin(int fd)
|
|||||||
if (RFIFOREST(fd) < 7)
|
if (RFIFOREST(fd) < 7)
|
||||||
return 0;
|
return 0;
|
||||||
{
|
{
|
||||||
|
unsigned char buf[16];
|
||||||
|
|
||||||
int acc = RFIFOL(fd,2);
|
int acc = RFIFOL(fd,2);
|
||||||
int sex = RFIFOB(fd,6);
|
int sex = RFIFOB(fd,6);
|
||||||
unsigned char buf[16];
|
RFIFOSKIP(fd,7);
|
||||||
|
|
||||||
if( acc > 0 )
|
if( acc > 0 )
|
||||||
{
|
{
|
||||||
int char_id[MAX_CHARS];
|
int char_id[MAX_CHARS];
|
||||||
@ -1888,6 +1888,10 @@ int parse_fromlogin(int fd)
|
|||||||
int i;
|
int i;
|
||||||
char* data;
|
char* data;
|
||||||
|
|
||||||
|
struct auth_node* node = (struct auth_node*)idb_get(auth_db, acc);
|
||||||
|
if( node != NULL )
|
||||||
|
node->sex = sex;
|
||||||
|
|
||||||
// get characters
|
// get characters
|
||||||
if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id`,`class`,`guild_id` FROM `%s` WHERE `account_id` = '%d'", char_db, acc) )
|
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);
|
Sql_ShowDebug(sql_handle);
|
||||||
@ -1943,7 +1947,6 @@ int parse_fromlogin(int fd)
|
|||||||
WBUFB(buf,6) = sex;
|
WBUFB(buf,6) = sex;
|
||||||
mapif_sendall(buf, 7);
|
mapif_sendall(buf, 7);
|
||||||
}
|
}
|
||||||
RFIFOSKIP(fd,7);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// reply to an account_reg2 registry request
|
// reply to an account_reg2 registry request
|
||||||
@ -2013,18 +2016,19 @@ int parse_fromlogin(int fd)
|
|||||||
if (RFIFOREST(fd) < 6)
|
if (RFIFOREST(fd) < 6)
|
||||||
return 0;
|
return 0;
|
||||||
{
|
{
|
||||||
struct online_char_data* character;
|
|
||||||
int aid = RFIFOL(fd,2);
|
int aid = RFIFOL(fd,2);
|
||||||
if ((character = (struct online_char_data*)idb_get(online_char_db, aid)) != NULL)
|
struct online_char_data* character = (struct online_char_data*)idb_get(online_char_db, aid);
|
||||||
{ //Kick out this player.
|
RFIFOSKIP(fd,6);
|
||||||
|
if( character != NULL )
|
||||||
|
{// account is already marked as online!
|
||||||
if( character->server > -1 )
|
if( character->server > -1 )
|
||||||
{ //Kick it from the map server it is on.
|
{ //Kick it from the map server it is on.
|
||||||
mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 2);
|
mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 2);
|
||||||
if (character->waiting_disconnect == -1)
|
if (character->waiting_disconnect == -1)
|
||||||
character->waiting_disconnect = add_timer(gettick()+15000, chardb_waiting_disconnect, character->account_id, 0);
|
character->waiting_disconnect = add_timer(gettick()+AUTH_TIMEOUT, chardb_waiting_disconnect, character->account_id, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ //Manual kick from char server.
|
{// Manual kick from char server.
|
||||||
struct char_session_data *tsd;
|
struct char_session_data *tsd;
|
||||||
int i;
|
int i;
|
||||||
ARR_FIND( 0, fd_max, i, session[i] && (tsd = (struct char_session_data*)session[i]->session_data) && tsd->account_id == aid );
|
ARR_FIND( 0, fd_max, i, session[i] && (tsd = (struct char_session_data*)session[i]->session_data) && tsd->account_id == aid );
|
||||||
@ -2034,14 +2038,13 @@ int parse_fromlogin(int fd)
|
|||||||
WFIFOW(i,0) = 0x81;
|
WFIFOW(i,0) = 0x81;
|
||||||
WFIFOB(i,2) = 2; // "Someone has already logged in with this id"
|
WFIFOB(i,2) = 2; // "Someone has already logged in with this id"
|
||||||
WFIFOSET(i,3);
|
WFIFOSET(i,3);
|
||||||
|
set_eof(i);
|
||||||
}
|
}
|
||||||
else //Shouldn't happen, but just in case.
|
else //Shouldn't happen, but just in case.
|
||||||
set_char_offline(99, aid);
|
set_char_offline(99, aid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RFIFOSKIP(fd,6);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// ip address update signal from login server
|
// ip address update signal from login server
|
||||||
@ -2489,30 +2492,37 @@ int parse_frommap(int fd)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x2b02: // req char selection
|
case 0x2b02: // req char selection
|
||||||
if (RFIFOREST(fd) < 18)
|
if( RFIFOREST(fd) < 18 )
|
||||||
return 0;
|
return 0;
|
||||||
|
{
|
||||||
|
struct auth_node* node;
|
||||||
|
|
||||||
if (auth_fifo_pos >= AUTH_FIFO_SIZE)
|
int account_id = RFIFOL(fd,2);
|
||||||
auth_fifo_pos = 0;
|
uint32 login_id1 = RFIFOL(fd,6);
|
||||||
|
uint32 login_id2 = RFIFOL(fd,10);
|
||||||
|
uint32 ip = RFIFOL(fd,14);
|
||||||
|
RFIFOSKIP(fd,18);
|
||||||
|
|
||||||
auth_fifo[auth_fifo_pos].account_id = RFIFOL(fd,2);
|
// create temporary auth entry
|
||||||
auth_fifo[auth_fifo_pos].char_id = 0;
|
CREATE(node, struct auth_node, 1);
|
||||||
auth_fifo[auth_fifo_pos].login_id1 = RFIFOL(fd,6);
|
node->account_id = account_id;
|
||||||
auth_fifo[auth_fifo_pos].login_id2 = RFIFOL(fd,10);
|
node->char_id = 0;
|
||||||
auth_fifo[auth_fifo_pos].delflag = 2;
|
node->login_id1 = login_id1;
|
||||||
auth_fifo[auth_fifo_pos].expiration_time = 0; // unlimited/unknown time by default (not display in map-server)
|
node->login_id2 = login_id2;
|
||||||
auth_fifo[auth_fifo_pos].ip = ntohl(RFIFOL(fd,14));
|
//node->sex = 0;
|
||||||
auth_fifo_pos++;
|
node->ip = ntohl(ip);
|
||||||
|
node->expiration_time = 0; // unlimited/unknown time by default (not display in map-server)
|
||||||
|
idb_put(auth_db, account_id, node);
|
||||||
|
|
||||||
//Set char to "@ char select" in online db [Kevin]
|
//Set char to "@ char select" in online db [Kevin]
|
||||||
set_char_online(-3, 99, RFIFOL(fd,2));
|
set_char_online(-3, 99, account_id);
|
||||||
|
|
||||||
WFIFOHEAD(fd,7);
|
WFIFOHEAD(fd,7);
|
||||||
WFIFOW(fd,0) = 0x2b03;
|
WFIFOW(fd,0) = 0x2b03;
|
||||||
WFIFOL(fd,2) = RFIFOL(fd,2);
|
WFIFOL(fd,2) = account_id;
|
||||||
WFIFOB(fd,6) = 0;
|
WFIFOB(fd,6) = 0;
|
||||||
WFIFOSET(fd,7);
|
WFIFOSET(fd,7);
|
||||||
RFIFOSKIP(fd,18);
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x2b05: // request "change map server"
|
case 0x2b05: // request "change map server"
|
||||||
@ -2961,20 +2971,23 @@ int parse_char(int fd)
|
|||||||
// request to connect
|
// request to connect
|
||||||
// 0065 <account id>.L <login id1>.L <login id2>.L <???>.W <sex>.B
|
// 0065 <account id>.L <login id1>.L <login id2>.L <???>.W <sex>.B
|
||||||
case 0x65:
|
case 0x65:
|
||||||
if (RFIFOREST(fd) < 17)
|
if( RFIFOREST(fd) < 17 )
|
||||||
return 0;
|
return 0;
|
||||||
{
|
{
|
||||||
|
struct auth_node* node;
|
||||||
|
|
||||||
int account_id = RFIFOL(fd,2);
|
int account_id = RFIFOL(fd,2);
|
||||||
int login_id1 = RFIFOL(fd,6);
|
uint32 login_id1 = RFIFOL(fd,6);
|
||||||
int login_id2 = RFIFOL(fd,10);
|
uint32 login_id2 = RFIFOL(fd,10);
|
||||||
int sex = RFIFOB(fd,16);
|
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);
|
ShowInfo("request connect - account_id:%d/login_id1:%d/login_id2:%d\n", account_id, login_id1, login_id2);
|
||||||
|
|
||||||
if (sd) {
|
if (sd) {
|
||||||
//Received again auth packet for already authentified account?? Discard it.
|
//Received again auth packet for already authentified account?? Discard it.
|
||||||
//TODO: Perhaps log this as a hack attempt?
|
//TODO: Perhaps log this as a hack attempt?
|
||||||
//TODO: and perhaps send back a reply?
|
//TODO: and perhaps send back a reply?
|
||||||
RFIFOSKIP(fd,17);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2993,17 +3006,18 @@ int parse_char(int fd)
|
|||||||
WFIFOSET(fd,4);
|
WFIFOSET(fd,4);
|
||||||
|
|
||||||
// search authentification
|
// search authentification
|
||||||
ARR_FIND( 0, AUTH_FIFO_SIZE, i,
|
node = (struct auth_node*)idb_get(auth_db, account_id);
|
||||||
auth_fifo[i].account_id == sd->account_id &&
|
if( node != NULL &&
|
||||||
auth_fifo[i].login_id1 == sd->login_id1 &&
|
node->account_id == account_id &&
|
||||||
auth_fifo[i].login_id2 == sd->login_id2 &&
|
node->login_id1 == login_id1 &&
|
||||||
auth_fifo[i].ip == session[fd]->client_addr &&
|
node->login_id2 == login_id2 &&
|
||||||
auth_fifo[i].delflag == 2 );
|
node->ip == ipl )
|
||||||
|
{// authentication found (coming from map server)
|
||||||
if( i < AUTH_FIFO_SIZE ) {
|
idb_remove(auth_db, account_id);
|
||||||
auth_fifo[i].delflag = 1;
|
|
||||||
char_auth_ok(fd, sd);
|
char_auth_ok(fd, sd);
|
||||||
} else { // authentication not found
|
}
|
||||||
|
else
|
||||||
|
{// authentication not found (coming from login server)
|
||||||
if (login_fd > 0) { // don't send request if no login-server
|
if (login_fd > 0) { // don't send request if no login-server
|
||||||
WFIFOHEAD(login_fd,19);
|
WFIFOHEAD(login_fd,19);
|
||||||
WFIFOW(login_fd,0) = 0x2712; // ask login-server to authentify an account
|
WFIFOW(login_fd,0) = 0x2712; // ask login-server to authentify an account
|
||||||
@ -3011,7 +3025,7 @@ int parse_char(int fd)
|
|||||||
WFIFOL(login_fd,6) = sd->login_id1;
|
WFIFOL(login_fd,6) = sd->login_id1;
|
||||||
WFIFOL(login_fd,10) = sd->login_id2;
|
WFIFOL(login_fd,10) = sd->login_id2;
|
||||||
WFIFOB(login_fd,14) = sd->sex;
|
WFIFOB(login_fd,14) = sd->sex;
|
||||||
WFIFOL(login_fd,15) = htonl(session[fd]->client_addr);
|
WFIFOL(login_fd,15) = htonl(ipl);
|
||||||
WFIFOSET(login_fd,19);
|
WFIFOSET(login_fd,19);
|
||||||
} else { // if no login-server, we must refuse connection
|
} else { // if no login-server, we must refuse connection
|
||||||
WFIFOHEAD(fd,3);
|
WFIFOHEAD(fd,3);
|
||||||
@ -3021,21 +3035,22 @@ int parse_char(int fd)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RFIFOSKIP(fd,17);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// char select
|
// char select
|
||||||
case 0x66:
|
case 0x66:
|
||||||
FIFOSD_CHECK(3);
|
FIFOSD_CHECK(3);
|
||||||
|
|
||||||
do //FIXME: poor code structure
|
|
||||||
{
|
{
|
||||||
struct mmo_charstatus char_dat;
|
struct mmo_charstatus char_dat;
|
||||||
char* data;
|
char* data;
|
||||||
int char_id;
|
int char_id;
|
||||||
|
uint32 subnet_map_ip;
|
||||||
|
struct auth_node* node;
|
||||||
|
|
||||||
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, RFIFOB(fd,2))
|
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_NextRow(sql_handle)
|
||||||
|| SQL_SUCCESS != Sql_GetData(sql_handle, 0, &data, NULL) )
|
|| SQL_SUCCESS != Sql_GetData(sql_handle, 0, &data, NULL) )
|
||||||
{
|
{
|
||||||
@ -3056,10 +3071,10 @@ int parse_char(int fd)
|
|||||||
|
|
||||||
Sql_EscapeStringLen(sql_handle, esc_name, char_dat.name, strnlen(char_dat.name, NAME_LENGTH));
|
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')",
|
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, RFIFOB(fd, 2), esc_name) )
|
charlog_db, sd->account_id, slot, esc_name) )
|
||||||
Sql_ShowDebug(sql_handle);
|
Sql_ShowDebug(sql_handle);
|
||||||
}
|
}
|
||||||
ShowInfo("Selected char: (Account %d: %d - %s)\n", sd->account_id, RFIFOB(fd, 2), char_dat.name);
|
ShowInfo("Selected char: (Account %d: %d - %s)\n", sd->account_id, slot, char_dat.name);
|
||||||
|
|
||||||
// searching map server
|
// searching map server
|
||||||
i = search_mapserver(char_dat.last_point.map, -1, -1);
|
i = search_mapserver(char_dat.last_point.map, -1, -1);
|
||||||
@ -3107,31 +3122,8 @@ int parse_char(int fd)
|
|||||||
char_dat.last_point.map = j;
|
char_dat.last_point.map = j;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Send player to map
|
|
||||||
WFIFOHEAD(fd,28);
|
|
||||||
WFIFOW(fd,0) = 0x71;
|
|
||||||
WFIFOL(fd,2) = char_dat.char_id;
|
|
||||||
mapindex_getmapname_ext(mapindex_id2name(char_dat.last_point.map), (char*)WFIFOP(fd,6));
|
|
||||||
{
|
|
||||||
// Advanced subnet check [LuzZza]
|
|
||||||
uint32 subnet_map_ip;
|
|
||||||
subnet_map_ip = lan_subnetcheck(ipl);
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
if (auth_fifo_pos >= AUTH_FIFO_SIZE)
|
|
||||||
auth_fifo_pos = 0;
|
|
||||||
auth_fifo[auth_fifo_pos].account_id = sd->account_id;
|
|
||||||
auth_fifo[auth_fifo_pos].char_id = char_dat.char_id;
|
|
||||||
auth_fifo[auth_fifo_pos].login_id1 = sd->login_id1;
|
|
||||||
auth_fifo[auth_fifo_pos].login_id2 = sd->login_id2;
|
|
||||||
auth_fifo[auth_fifo_pos].delflag = 0;
|
|
||||||
auth_fifo[auth_fifo_pos].sex = sd->sex;
|
|
||||||
auth_fifo[auth_fifo_pos].expiration_time = sd->expiration_time;
|
|
||||||
auth_fifo[auth_fifo_pos].ip = session[fd]->client_addr;
|
|
||||||
|
|
||||||
//Send NEW auth packet [Kevin]
|
//Send NEW auth packet [Kevin]
|
||||||
|
//FIXME: is this case even possible? [ultramage]
|
||||||
if ((map_fd = server[i].fd) < 1 || session[map_fd] == NULL)
|
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);
|
ShowError("parse_char: Attempting to write to invalid session %d! Map Server #%d disconnected.\n", map_fd, i);
|
||||||
@ -3145,26 +3137,46 @@ int parse_char(int fd)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Send player to map
|
||||||
|
WFIFOHEAD(fd,28);
|
||||||
|
WFIFOW(fd,0) = 0x71;
|
||||||
|
WFIFOL(fd,2) = char_dat.char_id;
|
||||||
|
mapindex_getmapname_ext(mapindex_id2name(char_dat.last_point.map), (char*)WFIFOP(fd,6));
|
||||||
|
|
||||||
|
// Advanced subnet check [LuzZza]
|
||||||
|
subnet_map_ip = lan_subnetcheck(ipl);
|
||||||
|
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);
|
||||||
|
|
||||||
//Send auth ok to map server
|
//Send auth ok to map server
|
||||||
WFIFOHEAD(map_fd,20 + sizeof(struct mmo_charstatus));
|
WFIFOHEAD(map_fd,20 + sizeof(struct mmo_charstatus));
|
||||||
WFIFOW(map_fd,0) = 0x2afd;
|
WFIFOW(map_fd,0) = 0x2afd;
|
||||||
WFIFOW(map_fd,2) = 20 + sizeof(struct mmo_charstatus);
|
WFIFOW(map_fd,2) = 20 + sizeof(struct mmo_charstatus);
|
||||||
WFIFOL(map_fd,4) = auth_fifo[auth_fifo_pos].account_id;
|
WFIFOL(map_fd,4) = sd->account_id;
|
||||||
WFIFOL(map_fd,8) = auth_fifo[auth_fifo_pos].login_id1;
|
WFIFOL(map_fd,8) = sd->login_id1;
|
||||||
WFIFOL(map_fd,16) = auth_fifo[auth_fifo_pos].login_id2;
|
WFIFOL(map_fd,16) = sd->login_id2;
|
||||||
WFIFOL(map_fd,12) = (unsigned long)auth_fifo[auth_fifo_pos].expiration_time;
|
WFIFOL(map_fd,12) = (unsigned long)sd->expiration_time;
|
||||||
memcpy(WFIFOP(map_fd,20), &char_dat, sizeof(struct mmo_charstatus));
|
memcpy(WFIFOP(map_fd,20), &char_dat, sizeof(struct mmo_charstatus));
|
||||||
WFIFOSET(map_fd, WFIFOW(map_fd,2));
|
WFIFOSET(map_fd, WFIFOW(map_fd,2));
|
||||||
|
|
||||||
set_char_online(i, char_dat.char_id, char_dat.account_id);
|
// create temporary auth entry
|
||||||
auth_fifo_pos++;
|
CREATE(node, struct auth_node, 1);
|
||||||
} while(0);
|
node->account_id = sd->account_id;
|
||||||
|
node->char_id = char_dat.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->ip = ipl;
|
||||||
|
idb_put(auth_db, sd->account_id, node);
|
||||||
|
|
||||||
RFIFOSKIP(fd,3);
|
set_char_online(i, char_dat.char_id, char_dat.account_id);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// create new char
|
// create new char
|
||||||
// S 0067 <name>.24B <str>.B <agi>.B <vit>.B <int>.B <dex>.B <luk>.B <slot.B <hair color>.W <hair style>.W
|
// 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:
|
case 0x67:
|
||||||
FIFOSD_CHECK(37);
|
FIFOSD_CHECK(37);
|
||||||
|
|
||||||
@ -3922,6 +3934,7 @@ void do_final(void)
|
|||||||
do_close(char_fd);
|
do_close(char_fd);
|
||||||
char_db_->destroy(char_db_, NULL);
|
char_db_->destroy(char_db_, NULL);
|
||||||
online_char_db->destroy(online_char_db, NULL);
|
online_char_db->destroy(online_char_db, NULL);
|
||||||
|
auth_db->destroy(auth_db, NULL);
|
||||||
|
|
||||||
Sql_Free(sql_handle);
|
Sql_Free(sql_handle);
|
||||||
if( lsql_handle )
|
if( lsql_handle )
|
||||||
@ -3972,6 +3985,7 @@ int do_init(int argc, char **argv)
|
|||||||
ShowInfo("Finished reading the inter-server configuration.\n");
|
ShowInfo("Finished reading the inter-server configuration.\n");
|
||||||
|
|
||||||
ShowInfo("Initializing char server.\n");
|
ShowInfo("Initializing char server.\n");
|
||||||
|
auth_db = idb_alloc(DB_OPT_RELEASE_DATA);
|
||||||
online_char_db = idb_alloc(DB_OPT_RELEASE_DATA);
|
online_char_db = idb_alloc(DB_OPT_RELEASE_DATA);
|
||||||
mmo_char_sql_init();
|
mmo_char_sql_init();
|
||||||
char_read_fame_list(); //Read fame lists.
|
char_read_fame_list(); //Read fame lists.
|
||||||
|
@ -643,8 +643,8 @@ int mapif_parse_WisRequest(int fd)
|
|||||||
ShowError("inter: Wis message doesn't exist.\n");
|
ShowError("inter: Wis message doesn't exist.\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
memcpy(name, RFIFOP(fd,28), NAME_LENGTH); //Received name may be too large and not contain \0! [Skotlex]
|
|
||||||
name[NAME_LENGTH-1]= '\0';
|
safestrncpy(name, (char*)RFIFOP(fd,28), NAME_LENGTH); //Received name may be too large and not contain \0! [Skotlex]
|
||||||
|
|
||||||
Sql_EscapeStringLen(sql_handle, esc_name, name, strnlen(name, NAME_LENGTH));
|
Sql_EscapeStringLen(sql_handle, esc_name, name, strnlen(name, NAME_LENGTH));
|
||||||
if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `name` FROM `%s` WHERE `name`='%s'", char_db, esc_name) )
|
if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `name` FROM `%s` WHERE `name`='%s'", char_db, esc_name) )
|
||||||
|
@ -1152,15 +1152,6 @@ int parse_fromchar(int fd)
|
|||||||
|
|
||||||
//ShowStatus("Char-server '%s': authentication of the account %d accepted (ip: %s).\n", server[id].name, account_id, ip);
|
//ShowStatus("Char-server '%s': authentication of the account %d accepted (ip: %s).\n", server[id].name, account_id, ip);
|
||||||
|
|
||||||
struct online_login_data* od = (struct online_login_data*)idb_get(online_db, account_id);
|
|
||||||
|
|
||||||
//Leave info in online data DB [Kevin]
|
|
||||||
if(od->waiting_disconnect != -1)
|
|
||||||
{
|
|
||||||
delete_timer(od->waiting_disconnect, waiting_disconnect_timer);
|
|
||||||
od->waiting_disconnect = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// each auth entry can only be used once
|
// each auth entry can only be used once
|
||||||
idb_remove(auth_db, account_id);
|
idb_remove(auth_db, account_id);
|
||||||
|
|
||||||
|
@ -668,8 +668,8 @@ int parse_fromchar(int fd)
|
|||||||
struct auth_node* node;
|
struct auth_node* node;
|
||||||
|
|
||||||
int account_id = RFIFOL(fd,2);
|
int account_id = RFIFOL(fd,2);
|
||||||
int login_id1 = RFIFOL(fd,6);
|
uint32 login_id1 = RFIFOL(fd,6);
|
||||||
int login_id2 = RFIFOL(fd,10);
|
uint32 login_id2 = RFIFOL(fd,10);
|
||||||
char sex = sex_num2str(RFIFOB(fd,14));
|
char sex = sex_num2str(RFIFOB(fd,14));
|
||||||
uint32 ip_ = ntohl(RFIFOL(fd,15));
|
uint32 ip_ = ntohl(RFIFOL(fd,15));
|
||||||
RFIFOSKIP(fd,19);
|
RFIFOSKIP(fd,19);
|
||||||
@ -685,15 +685,6 @@ int parse_fromchar(int fd)
|
|||||||
uint32 expiration_time;
|
uint32 expiration_time;
|
||||||
char email[40];
|
char email[40];
|
||||||
|
|
||||||
struct online_login_data* od = (struct online_login_data*)idb_get(online_db, account_id);
|
|
||||||
|
|
||||||
//Leave info in online data DB [Kevin]
|
|
||||||
if(od->waiting_disconnect != -1)
|
|
||||||
{
|
|
||||||
delete_timer(od->waiting_disconnect, waiting_disconnect_timer);
|
|
||||||
od->waiting_disconnect = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// each auth entry can only be used once
|
// each auth entry can only be used once
|
||||||
idb_remove(auth_db, account_id);
|
idb_remove(auth_db, account_id);
|
||||||
|
|
||||||
|
@ -111,12 +111,14 @@ struct auth_node* chrif_search(int account_id)
|
|||||||
return (struct auth_node*)idb_get(auth_db, account_id);
|
return (struct auth_node*)idb_get(auth_db, account_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct auth_node* chrif_auth_check(int account_id, int char_id, enum sd_state state) {
|
struct auth_node* chrif_auth_check(int account_id, int char_id, enum sd_state state)
|
||||||
|
{
|
||||||
struct auth_node *node = chrif_search(account_id);
|
struct auth_node *node = chrif_search(account_id);
|
||||||
return (node && node->char_id == char_id && node->state == state)?node:NULL;
|
return (node && node->char_id == char_id && node->state == state)?node:NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool chrif_auth_delete(int account_id, int char_id, enum sd_state state) {
|
bool chrif_auth_delete(int account_id, int char_id, enum sd_state state)
|
||||||
|
{
|
||||||
struct auth_node *node;
|
struct auth_node *node;
|
||||||
if ((node=chrif_auth_check(account_id, char_id, state)))
|
if ((node=chrif_auth_check(account_id, char_id, state)))
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user