
- Shuffled includes around for files that were leeching off of socket.h - Added code that enforces standard shutdown behavior for sockets git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@9817 54d463be-8e91-2dee-dedb-b68131a5f0ec
741 lines
20 KiB
C
741 lines
20 KiB
C
// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
|
||
// For more information, see LICENCE in the main folder
|
||
|
||
#include <stdio.h>
|
||
#include <string.h>
|
||
#include <stdlib.h>
|
||
|
||
#include "../common/db.h"
|
||
#include "../common/mmo.h"
|
||
#include "../common/socket.h"
|
||
#include "../common/timer.h"
|
||
#include "../common/malloc.h"
|
||
#include "../common/lock.h"
|
||
#include "../common/showmsg.h"
|
||
|
||
#include "char.h"
|
||
#include "inter.h"
|
||
#include "int_party.h"
|
||
#include "int_guild.h"
|
||
#include "int_status.h"
|
||
#include "int_storage.h"
|
||
#include "int_pet.h"
|
||
#include "int_homun.h"
|
||
|
||
#define WISDATA_TTL (60*1000) // Existence time of Wisp/page data (60 seconds)
|
||
// that is the waiting time of answers of all map-servers
|
||
#define WISDELLIST_MAX 256 // Number of elements of Wisp/page data deletion list
|
||
|
||
char accreg_txt[1024] = "save/accreg.txt";
|
||
#ifndef TXT_SQL_CONVERT
|
||
char inter_log_filename[1024] = "log/inter.log";
|
||
char main_chat_nick[16] = "Main";
|
||
|
||
static struct dbt *accreg_db = NULL;
|
||
|
||
unsigned int party_share_level = 10;
|
||
|
||
// sending packet list
|
||
// NOTE: This variable ain't used at all! And it's confusing.. where do I add that the length of packet 0x2b07 is 10? x.x [Skotlex]
|
||
int inter_send_packet_length[]={
|
||
-1,-1,27,-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3000-0x300f
|
||
-1, 7, 0, 0, 0, 0, 0, 0, -1,11, 0, 0, 0, 0, 0, 0,
|
||
35,-1,11,15, 34,29, 7,-1, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
10,-1,15, 0, 79,19, 7,-1, 0,-1,-1,-1, 14,67,186,-1,
|
||
9, 9,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
11,-1, 7, 3, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
};
|
||
// recv. packet list
|
||
int inter_recv_packet_length[]={
|
||
-1,-1, 7,-1, -1,13,36, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3000-0x300f
|
||
6,-1, 0, 0, 0, 0, 0, 0, 10,-1, 0, 0, 0, 0, 0, 0, //0x3010-0x301f
|
||
-1, 6,-1,14, 14,19, 6,-1, 14,14, 0, 0, 0, 0, 0, 0, //0x3020-0x302f
|
||
-1, 6,-1,-1, 55,19, 6,-1, 14,-1,-1,-1, 14,19,186,-1, //0x3030-0x303f
|
||
5, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
48,14,-1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3080-0x308f
|
||
-1,10,-1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x3090 - 0x309f Homunculus packets [albator]
|
||
};
|
||
|
||
struct WisData {
|
||
int id, fd, count, len;
|
||
unsigned long tick;
|
||
unsigned char src[24], dst[24], msg[1024];
|
||
};
|
||
static struct dbt * wis_db = NULL;
|
||
static int wis_dellist[WISDELLIST_MAX], wis_delnum;
|
||
|
||
|
||
//--------------------------------------------------------
|
||
|
||
// <20>A<EFBFBD>J<EFBFBD>E<EFBFBD><45><EFBFBD>g<EFBFBD>ϐ<EFBFBD><CF90><EFBFBD><F095B68E><EFBFBD><EFBFBD>֕ϊ<D695>
|
||
int inter_accreg_tostr(char *str, struct accreg *reg) {
|
||
int j;
|
||
char *p = str;
|
||
|
||
p += sprintf(p, "%d\t", reg->account_id);
|
||
for(j = 0; j < reg->reg_num; j++) {
|
||
p += sprintf(p,"%s,%s ", reg->reg[j].str, reg->reg[j].value);
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
#endif //TXT_SQL_CONVERT
|
||
// <20>A<EFBFBD>J<EFBFBD>E<EFBFBD><45><EFBFBD>g<EFBFBD>ϐ<EFBFBD><CF90><EFBFBD><F095B68E><EFBFBD><F182A982>ϊ<EFBFBD>
|
||
int inter_accreg_fromstr(const char *str, struct accreg *reg) {
|
||
int j, n;
|
||
const char *p = str;
|
||
|
||
if (sscanf(p, "%d\t%n", ®->account_id, &n ) != 1 || reg->account_id <= 0)
|
||
return 1;
|
||
|
||
for(j = 0, p += n; j < ACCOUNT_REG_NUM; j++, p += n) {
|
||
if (sscanf(p, "%[^,],%[^ ] %n", reg->reg[j].str, reg->reg[j].value, &n) != 2)
|
||
break;
|
||
}
|
||
reg->reg_num = j;
|
||
|
||
return 0;
|
||
}
|
||
#ifndef TXT_SQL_CONVERT
|
||
// <20>A<EFBFBD>J<EFBFBD>E<EFBFBD><45><EFBFBD>g<EFBFBD>ϐ<EFBFBD><CF90>̓ǂݍ<C782><DD8D><EFBFBD>
|
||
int inter_accreg_init(void) {
|
||
char line[8192];
|
||
FILE *fp;
|
||
int c = 0;
|
||
struct accreg *reg;
|
||
|
||
accreg_db = db_alloc(__FILE__,__LINE__,DB_INT,DB_OPT_RELEASE_DATA,sizeof(int));
|
||
|
||
if( (fp = fopen(accreg_txt, "r")) == NULL)
|
||
return 1;
|
||
while(fgets(line, sizeof(line)-1, fp)){
|
||
line[sizeof(line)-1] = '\0';
|
||
|
||
reg = (struct accreg*)aCalloc(sizeof(struct accreg), 1);
|
||
if (reg == NULL) {
|
||
ShowFatalError("inter: accreg: out of memory!\n");
|
||
exit(0);
|
||
}
|
||
if (inter_accreg_fromstr(line, reg) == 0 && reg->account_id > 0) {
|
||
idb_put(accreg_db, reg->account_id, reg);
|
||
} else {
|
||
ShowError("inter: accreg: broken data [%s] line %d\n", accreg_txt, c);
|
||
aFree(reg);
|
||
}
|
||
c++;
|
||
}
|
||
fclose(fp);
|
||
// printf("inter: %s read done (%d)\n", accreg_txt, c);
|
||
|
||
return 0;
|
||
}
|
||
|
||
// <20>A<EFBFBD>J<EFBFBD>E<EFBFBD><45><EFBFBD>g<EFBFBD>ϐ<EFBFBD><CF90>̃Z<CC83>[<5B>u<EFBFBD>p
|
||
int inter_accreg_save_sub(DBKey key, void *data, va_list ap) {
|
||
char line[8192];
|
||
FILE *fp;
|
||
struct accreg *reg = (struct accreg *)data;
|
||
|
||
if (reg->reg_num > 0) {
|
||
inter_accreg_tostr(line,reg);
|
||
fp = va_arg(ap, FILE *);
|
||
fprintf(fp, "%s" RETCODE, line);
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
// <20>A<EFBFBD>J<EFBFBD>E<EFBFBD><45><EFBFBD>g<EFBFBD>ϐ<EFBFBD><CF90>̃Z<CC83>[<5B>u
|
||
int inter_accreg_save(void) {
|
||
FILE *fp;
|
||
int lock;
|
||
|
||
if ((fp = lock_fopen(accreg_txt,&lock)) == NULL) {
|
||
ShowError("int_accreg: can't write [%s] !!! data is lost !!!\n", accreg_txt);
|
||
return 1;
|
||
}
|
||
accreg_db->foreach(accreg_db, inter_accreg_save_sub,fp);
|
||
lock_fclose(fp, accreg_txt, &lock);
|
||
// printf("inter: %s saved.\n", accreg_txt);
|
||
|
||
return 0;
|
||
}
|
||
|
||
//--------------------------------------------------------
|
||
#endif //TXT_SQL_CONVERT
|
||
/*==========================================
|
||
* <20>ݒ<EFBFBD><DD92>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD><EFBFBD><EFBFBD>ǂݍ<C782><DD8D><EFBFBD>
|
||
*------------------------------------------
|
||
*/
|
||
static int inter_config_read(const char *cfgName) {
|
||
char line[1024], w1[1024], w2[1024];
|
||
FILE *fp;
|
||
|
||
fp = fopen(cfgName, "r");
|
||
if (fp == NULL) {
|
||
ShowError("file not found: %s\n", cfgName);
|
||
return 1;
|
||
}
|
||
while(fgets(line, sizeof(line) - 1, fp)) {
|
||
if (line[0] == '/' && line[1] == '/')
|
||
continue;
|
||
line[sizeof(line)-1] = '\0';
|
||
|
||
if (sscanf(line,"%[^:]: %[^\r\n]", w1, w2) != 2)
|
||
continue;
|
||
|
||
if (strcmpi(w1, "storage_txt") == 0) {
|
||
strncpy(storage_txt, w2, sizeof(storage_txt));
|
||
} else if (strcmpi(w1, "party_txt") == 0) {
|
||
strncpy(party_txt, w2, sizeof(party_txt));
|
||
} else if (strcmpi(w1, "pet_txt") == 0) {
|
||
strncpy(pet_txt, w2, sizeof(pet_txt));
|
||
} else if (strcmpi(w1, "accreg_txt") == 0) {
|
||
strncpy(accreg_txt, w2, sizeof(accreg_txt));
|
||
} else if (strcmpi(w1, "guild_txt") == 0) {
|
||
strncpy(guild_txt, w2, sizeof(guild_txt));
|
||
} else if (strcmpi(w1, "castle_txt") == 0) {
|
||
strncpy(castle_txt, w2, sizeof(castle_txt));
|
||
} else if (strcmpi(w1, "guild_storage_txt") == 0) {
|
||
strncpy(guild_storage_txt, w2, sizeof(guild_storage_txt));
|
||
#ifndef TXT_SQL_CONVERT
|
||
} else if (strcmpi(w1, "homun_txt") == 0) {
|
||
strncpy(homun_txt, w2, sizeof(homun_txt));
|
||
} else if (strcmpi(w1, "party_share_level") == 0) {
|
||
party_share_level = (unsigned int)atof(w2);
|
||
} else if (strcmpi(w1, "inter_log_filename") == 0) {
|
||
strncpy(inter_log_filename, w2, sizeof(inter_log_filename));
|
||
} else if(strcmpi(w1,"log_inter")==0) {
|
||
log_inter = atoi(w2);
|
||
} else if(strcmpi(w1, "main_chat_nick")==0){ // Main chat nick [LuzZza]
|
||
strcpy(main_chat_nick, w2);
|
||
#endif //TXT_SQL_CONVERT
|
||
} else if (strcmpi(w1, "import") == 0) {
|
||
inter_config_read(w2);
|
||
}
|
||
}
|
||
fclose(fp);
|
||
|
||
return 0;
|
||
}
|
||
#ifndef TXT_SQL_CONVERT
|
||
// <20><><EFBFBD>O<EFBFBD><4F><EFBFBD><EFBFBD><EFBFBD>o<EFBFBD><6F>
|
||
int inter_log(char *fmt,...) {
|
||
FILE *logfp;
|
||
va_list ap;
|
||
|
||
va_start(ap,fmt);
|
||
logfp = fopen(inter_log_filename, "a");
|
||
if (logfp) {
|
||
vfprintf(logfp, fmt, ap);
|
||
fclose(logfp);
|
||
}
|
||
va_end(ap);
|
||
|
||
return 0;
|
||
}
|
||
|
||
// <20>Z<EFBFBD>[<5B>u
|
||
int inter_save(void) {
|
||
#ifdef ENABLE_SC_SAVING
|
||
inter_status_save();
|
||
#endif
|
||
inter_party_save();
|
||
inter_guild_save();
|
||
inter_storage_save();
|
||
inter_guild_storage_save();
|
||
inter_pet_save();
|
||
inter_homun_save();
|
||
inter_accreg_save();
|
||
|
||
return 0;
|
||
}
|
||
#endif //TXT_SQL_CONVERT
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
int inter_init_txt(const char *file) {
|
||
inter_config_read(file);
|
||
|
||
#ifndef TXT_SQL_CONVERT
|
||
wis_db = db_alloc(__FILE__,__LINE__,DB_INT,DB_OPT_RELEASE_DATA,sizeof(int));
|
||
|
||
inter_party_init();
|
||
inter_guild_init();
|
||
inter_storage_init();
|
||
inter_pet_init();
|
||
inter_homun_init();
|
||
inter_accreg_init();
|
||
#endif //TXT_SQL_CONVERT
|
||
return 0;
|
||
}
|
||
#ifndef TXT_SQL_CONVERT
|
||
// finalize
|
||
void inter_final(void) {
|
||
accreg_db->destroy(accreg_db, NULL);
|
||
wis_db->destroy(wis_db, NULL);
|
||
|
||
inter_party_final();
|
||
inter_guild_final();
|
||
inter_storage_final();
|
||
inter_pet_final();
|
||
inter_homun_final();
|
||
|
||
return;
|
||
}
|
||
|
||
// <20>}<7D>b<EFBFBD>v<EFBFBD>T<EFBFBD>[<5B>o<EFBFBD>[<5B>ڑ<EFBFBD>
|
||
int inter_mapif_init(int fd) {
|
||
inter_guild_mapif_init(fd);
|
||
|
||
return 0;
|
||
}
|
||
|
||
//--------------------------------------------------------
|
||
// sended packets to map-server
|
||
|
||
//Sends to map server the current max Account/Char id [Skotlex]
|
||
void mapif_send_maxid(int account_id, int char_id)
|
||
{
|
||
unsigned char buf[12];
|
||
|
||
WBUFW(buf,0) = 0x2b07;
|
||
WBUFL(buf,2) = account_id;
|
||
WBUFL(buf,6) = char_id;
|
||
mapif_sendall(buf, 10);
|
||
}
|
||
|
||
// GM<47><4D><EFBFBD>b<EFBFBD>Z<EFBFBD>[<5B>W<EFBFBD><57><EFBFBD>M
|
||
int mapif_GMmessage(unsigned char *mes, int len, unsigned long color, int sfd) {
|
||
unsigned char buf[2048];
|
||
|
||
if (len > 2048) len = 2047; //Make it fit to avoid crashes. [Skotlex]
|
||
WBUFW(buf,0) = 0x3800;
|
||
WBUFW(buf,2) = len;
|
||
WBUFL(buf,4) = color;
|
||
memcpy(WBUFP(buf,8), mes, len - 8);
|
||
mapif_sendallwos(sfd, buf, len);
|
||
// printf("inter server: GM:%d %s\n", len, mes);
|
||
|
||
return 0;
|
||
}
|
||
|
||
// Wisp/page transmission to one map-server
|
||
int mapif_wis_message2(struct WisData *wd, int fd) {
|
||
WFIFOHEAD(fd, 56+wd->len);
|
||
WFIFOW(fd, 0) = 0x3801;
|
||
WFIFOW(fd, 2) = 56 + wd->len;
|
||
WFIFOL(fd, 4) = wd->id;
|
||
memcpy(WFIFOP(fd, 8), wd->src, NAME_LENGTH);
|
||
memcpy(WFIFOP(fd,32), wd->dst, NAME_LENGTH);
|
||
memcpy(WFIFOP(fd,56), wd->msg, wd->len);
|
||
wd->count = 1;
|
||
WFIFOSET(fd,WFIFOW(fd,2));
|
||
return 1;
|
||
}
|
||
|
||
// Wisp/page transmission to all map-server
|
||
int mapif_wis_message(struct WisData *wd) {
|
||
unsigned char buf[2048];
|
||
if (wd->len > 2047-56) wd->len = 2047-56; //Force it to fit to avoid crashes. [Skotlex]
|
||
|
||
WBUFW(buf, 0) = 0x3801;
|
||
WBUFW(buf, 2) = 56 + wd->len;
|
||
WBUFL(buf, 4) = wd->id;
|
||
memcpy(WBUFP(buf, 8), wd->src, NAME_LENGTH);
|
||
memcpy(WBUFP(buf,32), wd->dst, NAME_LENGTH);
|
||
memcpy(WBUFP(buf,56), wd->msg, wd->len);
|
||
wd->count = mapif_sendall(buf, WBUFW(buf,2));
|
||
|
||
return 0;
|
||
}
|
||
|
||
int mapif_wis_fail(int fd, char *src) {
|
||
unsigned char buf[27];
|
||
WBUFW(buf, 0) = 0x3802;
|
||
memcpy(WBUFP(buf, 2), src, NAME_LENGTH);
|
||
WBUFB(buf,26) = 1; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
|
||
mapif_send(fd, buf, 27);
|
||
return 0;
|
||
|
||
}
|
||
|
||
// Wisp/page transmission result to map-server
|
||
int mapif_wis_end(struct WisData *wd, int flag) {
|
||
unsigned char buf[27];
|
||
|
||
WBUFW(buf, 0) = 0x3802;
|
||
memcpy(WBUFP(buf, 2), wd->src, 24);
|
||
WBUFB(buf,26) = flag; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
|
||
mapif_send(wd->fd, buf, 27);
|
||
// printf("inter server wis_end: flag: %d\n", flag);
|
||
|
||
return 0;
|
||
}
|
||
|
||
// <20>A<EFBFBD>J<EFBFBD>E<EFBFBD><45><EFBFBD>g<EFBFBD>ϐ<EFBFBD><CF90><EFBFBD><EFBFBD>M
|
||
int mapif_account_reg(int fd, unsigned char *src) {
|
||
unsigned char *buf = aCalloc(1,WBUFW(src,2));
|
||
|
||
memcpy(WBUFP(buf,0),src,WBUFW(src,2));
|
||
WBUFW(buf, 0) = 0x3804;
|
||
mapif_sendallwos(fd, buf, WBUFW(buf,2));
|
||
|
||
aFree(buf);
|
||
|
||
return 0;
|
||
}
|
||
|
||
// <20>A<EFBFBD>J<EFBFBD>E<EFBFBD><45><EFBFBD>g<EFBFBD>ϐ<EFBFBD><CF90>v<EFBFBD><76><EFBFBD>ԐM
|
||
int mapif_account_reg_reply(int fd,int account_id, int char_id) {
|
||
struct accreg *reg = idb_get(accreg_db,account_id);
|
||
|
||
WFIFOHEAD(fd, ACCOUNT_REG_NUM * 288+ 13);
|
||
WFIFOW(fd,0) = 0x3804;
|
||
WFIFOL(fd,4) = account_id;
|
||
WFIFOL(fd,8) = char_id;
|
||
WFIFOB(fd,12) = 2; //Acc Reg
|
||
if (reg == NULL) {
|
||
WFIFOW(fd,2) = 13;
|
||
} else {
|
||
int i, p;
|
||
for (p=13,i = 0; i < reg->reg_num; i++) {
|
||
p+= sprintf(WFIFOP(fd,p), "%s", reg->reg[i].str)+1; //We add 1 to consider the '\0' in place.
|
||
p+= sprintf(WFIFOP(fd,p), "%s", reg->reg[i].value)+1;
|
||
}
|
||
WFIFOW(fd,2)=p;
|
||
}
|
||
WFIFOSET(fd,WFIFOW(fd,2));
|
||
return 0;
|
||
}
|
||
|
||
//Request to kick char from a certain map server. [Skotlex]
|
||
int mapif_disconnectplayer(int fd, int account_id, int char_id, int reason)
|
||
{
|
||
if (fd < 0)
|
||
return -1;
|
||
|
||
WFIFOHEAD(fd, 7);
|
||
WFIFOW(fd,0) = 0x2b1f;
|
||
WFIFOL(fd,2) = account_id;
|
||
WFIFOB(fd,6) = reason;
|
||
WFIFOSET(fd,7);
|
||
|
||
return 0;
|
||
}
|
||
|
||
//--------------------------------------------------------
|
||
|
||
// Existence check of WISP data
|
||
int check_ttl_wisdata_sub(DBKey key, void *data, va_list ap) {
|
||
unsigned long tick;
|
||
struct WisData *wd = (struct WisData *)data;
|
||
tick = va_arg(ap, unsigned long);
|
||
|
||
if (DIFF_TICK(tick, wd->tick) > WISDATA_TTL && wis_delnum < WISDELLIST_MAX)
|
||
wis_dellist[wis_delnum++] = wd->id;
|
||
|
||
return 0;
|
||
}
|
||
|
||
int check_ttl_wisdata(void) {
|
||
unsigned long tick = gettick();
|
||
int i;
|
||
|
||
do {
|
||
wis_delnum = 0;
|
||
wis_db->foreach(wis_db, check_ttl_wisdata_sub, tick);
|
||
for(i = 0; i < wis_delnum; i++) {
|
||
struct WisData *wd = idb_get(wis_db, wis_dellist[i]);
|
||
ShowWarning("inter: wis data id=%d time out : from %s to %s\n", wd->id, wd->src, wd->dst);
|
||
// removed. not send information after a timeout. Just no answer for the player
|
||
//mapif_wis_end(wd, 1); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
|
||
idb_remove(wis_db, wd->id);
|
||
}
|
||
} while(wis_delnum >= WISDELLIST_MAX);
|
||
|
||
return 0;
|
||
}
|
||
|
||
//--------------------------------------------------------
|
||
// received packets from map-server
|
||
|
||
// GM<47><4D><EFBFBD>b<EFBFBD>Z<EFBFBD>[<5B>W<EFBFBD><57><EFBFBD>M
|
||
int mapif_parse_GMmessage(int fd) {
|
||
RFIFOHEAD(fd);
|
||
mapif_GMmessage(RFIFOP(fd,8), RFIFOW(fd,2), RFIFOL(fd,4), fd);
|
||
|
||
return 0;
|
||
}
|
||
|
||
static struct WisData* mapif_create_whisper(int fd, char* src, char* dst, char* mes, int meslen)
|
||
{
|
||
static int wisid = 0;
|
||
struct WisData* wd = (struct WisData *)aCalloc(sizeof(struct WisData), 1);
|
||
if (wd == NULL){
|
||
ShowFatalError("inter: WisRequest: out of memory !\n");
|
||
return NULL;
|
||
}
|
||
wd->id = ++wisid;
|
||
wd->fd = fd;
|
||
wd->len= meslen;
|
||
memcpy(wd->src, src, NAME_LENGTH);
|
||
memcpy(wd->dst, dst, NAME_LENGTH);
|
||
memcpy(wd->msg, mes, meslen);
|
||
wd->tick = gettick();
|
||
return wd;
|
||
}
|
||
|
||
// Wisp/page request to send
|
||
int mapif_parse_WisRequest(int fd) {
|
||
struct mmo_charstatus* char_status;
|
||
struct WisData* wd;
|
||
char name[NAME_LENGTH];
|
||
int fd2;
|
||
|
||
RFIFOHEAD(fd);
|
||
|
||
if (RFIFOW(fd,2)-52 >= sizeof(wd->msg)) {
|
||
ShowWarning("inter: Wis message size too long.\n");
|
||
return 0;
|
||
} else if (RFIFOW(fd,2)-52 <= 0) { // normaly, impossible, but who knows...
|
||
ShowError("inter: Wis message doesn't exist.\n");
|
||
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';
|
||
// search if character exists before to ask all map-servers
|
||
char_status = search_character_byname(name);
|
||
if (char_status == NULL)
|
||
return mapif_wis_fail(fd, RFIFOP(fd, 4));
|
||
|
||
// Character exists.
|
||
// to be sure of the correct name, rewrite it
|
||
memset(name, 0, NAME_LENGTH);
|
||
strncpy(name, char_status->name, NAME_LENGTH);
|
||
// if source is destination, don't ask other servers.
|
||
if (strcmp((char*)RFIFOP(fd,4),name) == 0)
|
||
return mapif_wis_fail(fd, RFIFOP(fd, 4));
|
||
|
||
//Look for online character.
|
||
fd2 = search_character_online(char_status->account_id, char_status->char_id);
|
||
if (fd2 >= 0) { //Character online, send whisper.
|
||
wd = mapif_create_whisper(fd, RFIFOP(fd, 4), RFIFOP(fd,28), RFIFOP(fd,52), RFIFOW(fd,2)-52);
|
||
if (!wd) return 1;
|
||
idb_put(wis_db, wd->id, wd);
|
||
mapif_wis_message2(wd, fd2);
|
||
return 0;
|
||
}
|
||
//Not found.
|
||
return mapif_wis_fail(fd, RFIFOP(fd, 4));
|
||
|
||
/* Scrapped since now we know where characters are online in. [Skotlex]
|
||
wd = mapif_create_whisper(fd, RFIFOP(fd, 4), RFIFOP(fd,28), RFIFOP(fd,52), RFIFOW(fd,2)-52);
|
||
if (!wd) return 0;
|
||
idb_put(wis_db, wd->id, wd);
|
||
mapif_wis_message(wd);
|
||
return 0;
|
||
*/
|
||
}
|
||
|
||
// Wisp/page transmission result
|
||
int mapif_parse_WisReply(int fd) {
|
||
int id, flag;
|
||
struct WisData *wd;
|
||
RFIFOHEAD(fd);
|
||
id = RFIFOL(fd,2);
|
||
flag = RFIFOB(fd,6);
|
||
wd = idb_get(wis_db, id);
|
||
|
||
if (wd == NULL)
|
||
return 0; // This wisp was probably suppress before, because it was timeout or because of target was found on another map-server
|
||
|
||
if ((--wd->count) <= 0 || flag != 1) {
|
||
mapif_wis_end(wd, flag); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
|
||
idb_remove(wis_db, id);
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
// Received wisp message from map-server for ALL gm (just copy the message and resends it to ALL map-servers)
|
||
int mapif_parse_WisToGM(int fd) {
|
||
unsigned char buf[2048]; // 0x3003/0x3803 <packet_len>.w <wispname>.24B <min_gm_level>.w <message>.?B
|
||
RFIFOHEAD(fd);
|
||
memcpy(WBUFP(buf,0), RFIFOP(fd,0), RFIFOW(fd,2));
|
||
WBUFW(buf, 0) = 0x3803;
|
||
mapif_sendall(buf, RFIFOW(fd,2));
|
||
|
||
return 0;
|
||
}
|
||
|
||
static void* create_accreg(DBKey key, va_list args) {
|
||
struct accreg *reg;
|
||
reg = (struct accreg*)aCalloc(sizeof(struct accreg), 1);
|
||
reg->account_id = key.i;
|
||
return reg;
|
||
}
|
||
|
||
// <20>A<EFBFBD>J<EFBFBD>E<EFBFBD><45><EFBFBD>g<EFBFBD>ϐ<EFBFBD><CF90>ۑ<EFBFBD><DB91>v<EFBFBD><76>
|
||
int mapif_parse_Registry(int fd) {
|
||
int j, p, len;
|
||
struct accreg *reg;
|
||
RFIFOHEAD(fd);
|
||
|
||
switch (RFIFOB(fd,12)) {
|
||
case 3: //Character registry
|
||
return char_parse_Registry(RFIFOL(fd,4), RFIFOL(fd,8), RFIFOP(fd,13), RFIFOW(fd,2)-13);
|
||
case 2: //Acc Reg
|
||
break;
|
||
case 1: //Acc Reg2, forward to login
|
||
return save_accreg2(RFIFOP(fd,4), RFIFOW(fd,2)-4);
|
||
default: //Error?
|
||
return 1;
|
||
}
|
||
reg = idb_ensure(accreg_db, RFIFOL(fd,4), create_accreg);
|
||
|
||
for(j=0,p=13;j<ACCOUNT_REG_NUM && p<RFIFOW(fd,2);j++){
|
||
sscanf(RFIFOP(fd,p), "%31c%n",reg->reg[j].str,&len);
|
||
reg->reg[j].str[len]='\0';
|
||
p +=len+1; //+1 to skip the '\0' between strings.
|
||
sscanf(RFIFOP(fd,p), "%255c%n",reg->reg[j].value,&len);
|
||
reg->reg[j].value[len]='\0';
|
||
p +=len+1;
|
||
}
|
||
reg->reg_num=j;
|
||
mapif_account_reg(fd, RFIFOP(fd,0)); // <20><><EFBFBD><EFBFBD>MAP<41>T<EFBFBD>[<5B>o<EFBFBD>[<5B>ɑ<EFBFBD><C991>M
|
||
|
||
return 0;
|
||
}
|
||
|
||
// Request the value of all registries.
|
||
int mapif_parse_RegistryRequest(int fd)
|
||
{
|
||
RFIFOHEAD(fd);
|
||
//Load Char Registry
|
||
if (RFIFOB(fd,12))
|
||
char_account_reg_reply(fd,RFIFOL(fd,2),RFIFOL(fd,6));
|
||
//Load Account Registry
|
||
if (RFIFOB(fd,11))
|
||
mapif_account_reg_reply(fd,RFIFOL(fd,2),RFIFOL(fd,6));
|
||
//Ask Login Server for Account2 values.
|
||
if (RFIFOB(fd,10))
|
||
request_accreg2(RFIFOL(fd,2),RFIFOL(fd,6)-2);
|
||
return 1;
|
||
}
|
||
|
||
static void mapif_namechange_ack(int fd, int account_id, int char_id, int type, int flag, char *name){
|
||
WFIFOHEAD(fd, NAME_LENGTH+13);
|
||
WFIFOW(fd, 0) =0x3806;
|
||
WFIFOL(fd, 2) =account_id;
|
||
WFIFOL(fd, 6) =char_id;
|
||
WFIFOB(fd,10) =type;
|
||
WFIFOB(fd,11) =flag;
|
||
memcpy(WFIFOP(fd, 12), name, NAME_LENGTH);
|
||
WFIFOSET(fd, NAME_LENGTH+13);
|
||
}
|
||
|
||
int mapif_parse_NameChangeRequest(int fd)
|
||
{
|
||
int account_id, char_id, type;
|
||
char* name;
|
||
int i;
|
||
|
||
RFIFOHEAD(fd);
|
||
account_id = RFIFOL(fd, 2);
|
||
char_id = RFIFOL(fd, 6);
|
||
type = RFIFOB(fd, 10);
|
||
name = RFIFOP(fd, 11);
|
||
|
||
// Check Authorised letters/symbols in the name
|
||
if (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) {
|
||
mapif_namechange_ack(fd, account_id, char_id, type, 0, name);
|
||
return 0;
|
||
}
|
||
} else if (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) {
|
||
mapif_namechange_ack(fd, account_id, char_id, type, 0, name);
|
||
return 0;
|
||
}
|
||
}
|
||
//TODO: type holds the type of object to rename.
|
||
//If it were a player, it needs to have the guild information and db information
|
||
//updated here, because changing it on the map won't make it be saved [Skotlex]
|
||
|
||
//name allowed.
|
||
mapif_namechange_ack(fd, account_id, char_id, type, 1, name);
|
||
return 0;
|
||
}
|
||
|
||
//--------------------------------------------------------
|
||
|
||
// map server <20><><EFBFBD><EFBFBD><EFBFBD>̒ʐM<CA90>i<EFBFBD>P<EFBFBD>p<EFBFBD>P<EFBFBD>b<EFBFBD>g<EFBFBD>̂݉<CC82><DD89>͂<EFBFBD><CD82>邱<EFBFBD>Ɓj
|
||
// <20>G<EFBFBD><47><EFBFBD>[<5B>Ȃ<EFBFBD>0(false)<29>A<EFBFBD><41><EFBFBD><EFBFBD><EFBFBD>ł<EFBFBD><C582><EFBFBD><EFBFBD>Ȃ<EFBFBD>1<EFBFBD>A
|
||
// <20>p<EFBFBD>P<EFBFBD>b<EFBFBD>g<EFBFBD><67><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȃ<EFBFBD><C882><EFBFBD><EFBFBD><EFBFBD>2<EFBFBD><32><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȃ<EFBFBD><C882><EFBFBD><EFBFBD>Ȃ<CE82><C882>Ȃ<EFBFBD>
|
||
int inter_parse_frommap(int fd) {
|
||
int cmd, len;
|
||
RFIFOHEAD(fd);
|
||
cmd = RFIFOW(fd,0);
|
||
len = 0;
|
||
|
||
// inter<65>I<EFBFBD>NJ<EFBFBD><C78A><EFBFBD><EFBFBD>ׂ<F092B282>
|
||
if (cmd < 0x3000 || cmd >= 0x3000 + (sizeof(inter_recv_packet_length) / sizeof(inter_recv_packet_length[0])))
|
||
return 0;
|
||
|
||
if (inter_recv_packet_length[cmd-0x3000] == 0) //This is necessary, because otherwise we return 2 and the char server will just hang waiting for packets! [Skotlex]
|
||
return 0;
|
||
|
||
// <20>p<EFBFBD>P<EFBFBD>b<EFBFBD>g<EFBFBD><67><EFBFBD>ׂ<F092B282>
|
||
if ((len = inter_check_length(fd, inter_recv_packet_length[cmd - 0x3000])) == 0)
|
||
return 2;
|
||
|
||
switch(cmd) {
|
||
case 0x3000: mapif_parse_GMmessage(fd); break;
|
||
case 0x3001: mapif_parse_WisRequest(fd); break;
|
||
case 0x3002: mapif_parse_WisReply(fd); break;
|
||
case 0x3003: mapif_parse_WisToGM(fd); break;
|
||
case 0x3004: mapif_parse_Registry(fd); break;
|
||
case 0x3005: mapif_parse_RegistryRequest(fd); break;
|
||
case 0x3006: mapif_parse_NameChangeRequest(fd); break;
|
||
default:
|
||
if (inter_party_parse_frommap(fd))
|
||
break;
|
||
if (inter_guild_parse_frommap(fd))
|
||
break;
|
||
if (inter_storage_parse_frommap(fd))
|
||
break;
|
||
if (inter_pet_parse_frommap(fd))
|
||
break;
|
||
if (inter_homun_parse_frommap(fd))
|
||
break;
|
||
return 0;
|
||
}
|
||
RFIFOSKIP(fd, len);
|
||
return 1;
|
||
}
|
||
|
||
// RFIFO<46>̃p<CC83>P<EFBFBD>b<EFBFBD>g<EFBFBD><67><EFBFBD>m<EFBFBD>F
|
||
// <20>K<EFBFBD>v<EFBFBD>p<EFBFBD>P<EFBFBD>b<EFBFBD>g<EFBFBD><67><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>p<CE83>P<EFBFBD>b<EFBFBD>g<EFBFBD><67><EFBFBD>A<EFBFBD>܂<EFBFBD><DC82><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȃ<EFBFBD><C882><EFBFBD><EFBFBD><EFBFBD>0
|
||
int inter_check_length(int fd, int length) {
|
||
if (length == -1) { // <20>σp<CF83>P<EFBFBD>b<EFBFBD>g<EFBFBD><67>
|
||
RFIFOHEAD(fd);
|
||
if (RFIFOREST(fd) < 4) // <20>p<EFBFBD>P<EFBFBD>b<EFBFBD>g<EFBFBD><67><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
return 0;
|
||
length = RFIFOW(fd,2);
|
||
}
|
||
|
||
if ((int)RFIFOREST(fd) < length) // <20>p<EFBFBD>P<EFBFBD>b<EFBFBD>g<EFBFBD><67><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
return 0;
|
||
|
||
return length;
|
||
}
|
||
#endif //TXT_SQL_CONVERT
|