Clearing trunk.

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@5091 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
Valaris
2006-01-29 16:00:45 +00:00
parent e43133494b
commit fd99753f8e
793 changed files with 0 additions and 302210 deletions

View File

@@ -1,20 +0,0 @@
all: char-server_sql
sql: char-server_sql
COMMON_OBJ = ../common/obj/core.o ../common/obj/socket.o ../common/obj/timer.o ../common/obj/db.o ../common/obj/malloc.o ../common/obj/showmsg.o ../common/obj/utils.o ../common/obj/strlib.o
COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/db.h ../common/malloc.h ../common/showmsg.h ../common/utils.h ../common/strlib.h
char-server_sql: char.o inter.o int_party.o int_guild.o int_storage.o int_pet.o itemdb.o $(COMMON_OBJ)
$(CC) -o ../../$@ $^ $(LIB_S)
char.o: char.c char.h ../common/strlib.h itemdb.h ../common/showmsg.h
inter.o: inter.c inter.h int_party.h int_guild.h int_storage.h int_pet.h ../common/mmo.h char.h ../common/socket.h ../common/showmsg.h
int_party.o: int_party.c int_party.h inter.h ../common/mmo.h char.h ../common/socket.h ../common/timer.h ../common/db.h ../common/showmsg.h
int_guild.o: int_guild.c int_guild.h inter.h ../common/mmo.h char.h ../common/socket.h ../common/db.h ../common/showmsg.h
int_storage.o: int_storage.c int_storage.h char.h itemdb.h ../common/showmsg.h
int_pet.o: int_pet.c int_pet.h inter.h char.h ../common/mmo.h ../common/socket.h ../common/db.h ../common/showmsg.h
itemdb.o: itemdb.c itemdb.h ../common/db.h ../common/mmo.h ../common/showmsg.h
$(COMMON_OBJ): $(COMMON_H)
clean:
rm -f *.o ../../char-server_sql

File diff suppressed because it is too large Load Diff

View File

@@ -1,90 +0,0 @@
#include "../common/core.h"
#include "../common/socket.h"
#include "../common/timer.h"
#include "../common/mmo.h"
#include "../common/version.h"
#include "../common/db.h"
#ifndef _CHAR_H_
#define _CHAR_H_
#define MAX_MAP_SERVERS 30
#define LAN_CONF_NAME "conf/lan_support.conf"
#define DEFAULT_AUTOSAVE_INTERVAL 300*1000
struct mmo_map_server{
long ip;
short port;
int users;
char map[MAX_MAP_PER_SERVER][16];
};
struct itemtmp {
int flag;//checked = 1 else 0
int id;
short nameid;
short amount;
unsigned short equip;
char identify;
char refine;
char attribute;
short card[4];
};
enum {
TABLE_INVENTORY,
TABLE_CART,
TABLE_STORAGE,
TABLE_GUILD_STORAGE,
};
struct itemtemp{
struct itemtmp equip[MAX_GUILD_STORAGE],notequip[MAX_GUILD_STORAGE];
};
int memitemdata_to_sql(struct itemtmp mapitem[], int count, int char_id,int tableswitch);
int mapif_sendall(unsigned char *buf,unsigned int len);
int mapif_sendallwos(int fd,unsigned char *buf,unsigned int len);
int mapif_send(int fd,unsigned char *buf,unsigned int len);
int char_nick2id (char *name);
int char_married(int pl1,int pl2);
int char_child(int parent_id, int child_id);
extern int autosave_interval;
extern char db_path[];
extern char char_db[256];
extern char cart_db[256];
extern char inventory_db[256];
extern char charlog_db[256];
extern char storage_db[256];
extern char interlog_db[256];
extern char reg_db[256];
extern char skill_db[256];
extern char memo_db[256];
extern char guild_db[256];
extern char guild_alliance_db[256];
extern char guild_castle_db[256];
extern char guild_expulsion_db[256];
extern char guild_member_db[256];
extern char guild_position_db[256];
extern char guild_skill_db[256];
extern char guild_storage_db[256];
extern char party_db[256];
extern char pet_db[256];
extern int db_use_sqldbs; // added for sql item_db read for char server [Valaris]
extern char login_db_level[32];
extern char login_db_account_id[32];
extern int lowest_gm_level;
extern int GM_num;
extern struct gm_account *gm_account;
extern int debug_mysql_query(char *file, int line, void *mysql, const char *q);
#endif
#include "inter.h"
#include "int_pet.h"
#include "int_guild.h"
#include "int_party.h"
#include "int_storage.h"

File diff suppressed because it is too large Load Diff

View File

@@ -1,11 +0,0 @@
#ifndef _INT_GUILD_H_
#define _INT_GUILD_H_
int inter_guild_parse_frommap(int fd);
int inter_guild_sql_init();
void inter_guild_sql_final();
int inter_guild_mapif_init(int fd);
int inter_guild_leave(int guild_id,int account_id,int char_id);
#endif

View File

@@ -1,777 +0,0 @@
//
// original code from athena
// SQL conversion by hack
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "char.h"
#include "../common/strlib.h"
#include "socket.h"
static struct party *party_pt;
static int party_newid=100;
int mapif_party_broken(int party_id,int flag);
int party_check_empty(struct party *p);
int mapif_parse_PartyLeave(int fd,int party_id,int account_id);
#define mysql_query(_x, _y) debug_mysql_query(__FILE__, __LINE__, _x, _y)
// Save party to mysql
int inter_party_tosql(int party_id,struct party *p)
{
// 'party' ('party_id','name','exp','item','leader')
char t_name[100];
char t_member[24];
int party_member = 0, party_online_member = 0;
int party_exist = 0;
int leader_id = 0;
int i = 0;
printf("(\033[1;64m%d\033[0m) Request save party - ",party_id);
jstrescapecpy(t_name, p->name);
if (p==NULL || party_id==0 || p->party_id ==0 || party_id!=p->party_id) {
printf("- Party pointer or party_id error \n");
return 0;
}
// Check if party exists
sprintf(tmp_sql,"SELECT count(*) FROM `%s` WHERE `party_id`='%d'",party_db, party_id); // TBR
if(mysql_query(&mysql_handle, tmp_sql) ) {
printf("DB server Error - %s\n", mysql_error(&mysql_handle) );
return 0;
}
sql_res = mysql_store_result(&mysql_handle) ;
if (sql_res!=NULL && mysql_num_rows(sql_res)>0) {
sql_row = mysql_fetch_row(sql_res);
party_exist = atoi (sql_row[0]);
//printf("- Check if party %d exists : %s\n",party_id,party_exist==0?"No":"Yes");
}
mysql_free_result(sql_res) ; //resource free
if (party_exist >0){
// Check members in party
sprintf(tmp_sql,"SELECT count(*) FROM `%s` WHERE `party_id`='%d'",char_db, party_id); // TBR
if(mysql_query(&mysql_handle, tmp_sql) ) {
printf("DB server Error - %s\n", mysql_error(&mysql_handle) );
return 0;
}
sql_res = mysql_store_result(&mysql_handle) ;
if (sql_res!=NULL && mysql_num_rows(sql_res)>0) {
sql_row = mysql_fetch_row(sql_res);
party_member = atoi (sql_row[0]);
// printf("- Check members in party %d : %d \n",party_id,party_member);
}
mysql_free_result(sql_res) ; //resource free
party_online_member = 0;
i=0;
while (i<MAX_PARTY){
if (p->member[i].account_id>0) party_online_member++;
i++;
}
//if (party_online_member==0) printf("- No member online \n"); else printf("- Some member %d online \n", party_online_member);
if (party_member <= 0 && party_online_member == 0) {
// Delete the party, if has no member.
sprintf(tmp_sql,"DELETE FROM `%s` WHERE `party_id`='%d'",party_db, party_id);
if(mysql_query(&mysql_handle, tmp_sql) ) {
printf("DB server Error - %s\n", mysql_error(&mysql_handle) );
}
// printf("No member in party %d, break it \n",party_id);
memset(p, 0, sizeof(struct party));
return 0;
} else {
// Update party information, if exists
int i=0;
for (i=0;i<MAX_PARTY;i++){
if (p->member[i].account_id>0){
sprintf(tmp_sql,"UPDATE `%s` SET `party_id`='%d' WHERE `account_id`='%d' AND `name`='%s'",
char_db, party_id, p->member[i].account_id,jstrescapecpy(t_member,p->member[i].name));
//printf("%s",tmp_sql);
if(mysql_query(&mysql_handle, tmp_sql) ) {
printf("DB server Error (update `char`)- %s\n", mysql_error(&mysql_handle) );
}
}
}
sprintf(tmp_sql,"UPDATE `%s` SET `name`='%s', `exp`='%d', `item`='%d', `leader_id`=`leader_id` WHERE `party_id`='%d'",
party_db, t_name,p->exp,p->item,party_id);
if(mysql_query(&mysql_handle, tmp_sql) ) {
printf("DB server Error (inset/update `party`)- %s\n", mysql_error(&mysql_handle) );
}
// printf("- Update party %d information \n",party_id);
}
} else {
// Add new party, if not exist
int i = 0;
while (i<MAX_PARTY&&((p->member[i].account_id>0&&p->member[i].leader==0)||(p->member[i].account_id<0))) i++;
if (i<MAX_PARTY) leader_id = p->member[i].account_id;
sprintf(tmp_sql,"INSERT INTO `%s` (`party_id`, `name`, `exp`, `item`, `leader_id`) VALUES ('%d', '%s', '%d', '%d', '%d')",
party_db, party_id, t_name, p->exp, p->item,leader_id);
if(mysql_query(&mysql_handle, tmp_sql) ) {
printf("DB server Error (inset/update `party`)- %s\n", mysql_error(&mysql_handle) );
return 0;
}
sprintf(tmp_sql,"UPDATE `%s` SET `party_id`='%d' WHERE `account_id`='%d' AND `name`='%s'",
char_db, party_id,leader_id, jstrescapecpy(t_member,p->member[i].name));
if(mysql_query(&mysql_handle, tmp_sql) ) {
printf("DB server Error (inset/update `party`)- %s\n", mysql_error(&mysql_handle) );
}
//printf("- Insert new party %d \n",party_id);
}
printf("Party save success\n");
return 0;
}
// Read party from mysql
int inter_party_fromsql(int party_id,struct party *p)
{
int leader_id=0;
printf("(\033[1;64m%d\033[0m) Request load party - ",party_id);
memset(p, 0, sizeof(struct party));
sprintf(tmp_sql,"SELECT `party_id`, `name`,`exp`,`item`, `leader_id` FROM `%s` WHERE `party_id`='%d'",party_db, party_id); // TBR
if(mysql_query(&mysql_handle, tmp_sql) ) {
printf("DB server Error (select `party`)- %s\n", mysql_error(&mysql_handle) );
return 0;
}
sql_res = mysql_store_result(&mysql_handle) ;
if (sql_res!=NULL && mysql_num_rows(sql_res)>0) {
sql_row = mysql_fetch_row(sql_res);
// printf("- Read party %d from MySQL\n",party_id);
p->party_id = party_id;
strcpy(p->name, sql_row[1]);
p->exp = atoi(sql_row[2]);
p->item = atoi(sql_row[3]);
leader_id = atoi(sql_row[4]);
} else {
mysql_free_result(sql_res);
// printf("- Cannot find party %d \n",party_id);
return 0;
}
mysql_free_result(sql_res);
// Load members
sprintf(tmp_sql,"SELECT `account_id`, `name`,`base_level`,`last_map`,`online` FROM `%s` WHERE `party_id`='%d'",char_db, party_id); // TBR
if(mysql_query(&mysql_handle, tmp_sql) ) {
printf("DB server Error (select `party`)- %s\n", mysql_error(&mysql_handle) );
return 0;
}
sql_res = mysql_store_result(&mysql_handle) ;
if (sql_res!=NULL && mysql_num_rows(sql_res)>0) {
int i;
for(i=0;(sql_row = mysql_fetch_row(sql_res));i++){
struct party_member *m = &p->member[i];
m->account_id = atoi(sql_row[0]);
if (m->account_id == leader_id) m->leader = 1; else m->leader = 0;
strncpy(m->name,sql_row[1],sizeof(m->name));
m->lv = atoi(sql_row[2]);
strncpy(m->map,sql_row[3],sizeof(m->map));
m->online = atoi(sql_row[4]);
}
// printf("- %d members found in party %d \n",i,party_id);
}
mysql_free_result(sql_res);
printf("Party load success\n");
return 0;
}
int inter_party_sql_init(){
int i;
//memory alloc
printf("interserver party memory initialize.... (%d byte)\n",sizeof(struct party));
party_pt = (struct party*)aCalloc(sizeof(struct party), 1);
sprintf (tmp_sql , "SELECT count(*) FROM `%s`",party_db);
if(mysql_query(&mysql_handle, tmp_sql) ) {
printf("DB server Error - %s\n", mysql_error(&mysql_handle) );
}
sql_res = mysql_store_result(&mysql_handle) ;
sql_row = mysql_fetch_row(sql_res);
printf("total party data -> '%s'.......\n",sql_row[0]);
i = atoi (sql_row[0]);
mysql_free_result(sql_res);
if (i > 0) {
//set party_newid
sprintf (tmp_sql , "SELECT max(`party_id`) FROM `%s`", party_db);
if(mysql_query(&mysql_handle, tmp_sql) ) {
printf("DB server Error - %s\n", mysql_error(&mysql_handle) );
}
sql_res = mysql_store_result(&mysql_handle) ;
sql_row = mysql_fetch_row(sql_res);
party_newid = atoi (sql_row[0])+1;
mysql_free_result(sql_res);
}
printf("set party_newid: %d.......\n",party_newid);
return 0;
}
void inter_party_sql_final(){
if (party_pt) aFree(party_pt);
return;
}
// Search for the party according to its name
struct party* search_partyname(char *str)
{
struct party *p=NULL;
int leader_id = 0;
char t_name[24];
sprintf(tmp_sql,"SELECT `party_id`, `name`,`exp`,`item`,`leader_id` FROM `%s` WHERE `name`='%s'",party_db, jstrescapecpy(t_name,str));
if(mysql_query(&mysql_handle, tmp_sql) ) {
printf("DB server Error (select `party`)- %s\n", mysql_error(&mysql_handle) );
}
sql_res = mysql_store_result(&mysql_handle) ;
if (sql_res==NULL || mysql_num_rows(sql_res)<=0) { mysql_free_result(sql_res); return p; }
sql_row = mysql_fetch_row(sql_res);
p = party_pt;
p->party_id = atoi(sql_row[0]);
strcpy(p->name, sql_row[1]);
p->exp = atoi(sql_row[2]);
p->item = atoi(sql_row[3]);
leader_id = atoi(sql_row[4]);
mysql_free_result(sql_res);
// Load members
sprintf(tmp_sql,"SELECT `account_id`, `name`,`base_level`,`last_map`,`online` FROM `%s` WHERE `party_id`='%d'",char_db, p->party_id);
if(mysql_query(&mysql_handle, tmp_sql) ) {
printf("DB server Error (select `party`)- %s\n", mysql_error(&mysql_handle) );
return 0;
}
sql_res = mysql_store_result(&mysql_handle) ;
if (sql_res!=NULL && mysql_num_rows(sql_res)>0) {
int i;
for(i=0;(sql_row = mysql_fetch_row(sql_res));i++){
struct party_member *m = &p->member[i];
m->account_id = atoi(sql_row[0]);
if (m->account_id == leader_id) m->leader = 1; else m->leader = 0;
strncpy(m->name,sql_row[1],sizeof(m->name));
m->lv = atoi(sql_row[2]);
strncpy(m->map,sql_row[3],sizeof(m->map));
m->online = atoi(sql_row[4]);
}
printf("- %d members found in party %d \n",i,p->party_id);
}
mysql_free_result(sql_res);
return p;
}
// EXP公平分配できるかチェック
int party_check_exp_share(struct party *p)
{
int i, dudes=0;
int pl1=0,pl2=0,pl3=0;
int maxlv=0,minlv=0x7fffffff;
for(i=0;i<MAX_PARTY;i++){
int lv=p->member[i].lv;
if (!lv) continue;
if( p->member[i].online ){
if( lv < minlv ) minlv=lv;
if( maxlv < lv ) maxlv=lv;
if( lv >= 70 ) dudes+=1000;
dudes++;
}
}
if((dudes/1000 >= 2) && (dudes%1000 == 3) && (!strcmp(p->member[0].map,p->member[1].map)) && (!strcmp(p->member[1].map,p->member[2].map))) {
pl1=char_nick2id(p->member[0].name);
pl2=char_nick2id(p->member[1].name);
pl3=char_nick2id(p->member[2].name);
printf("PARTY: group of 3 Id1 %d lv %d name %s Id2 %d lv %d name %s Id3 %d lv %d name %s\n",pl1,p->member[0].lv,p->member[0].name,pl2,p->member[1].lv,p->member[1].name,pl3,p->member[2].lv,p->member[2].name);
if (char_married(pl1,pl2) && char_child(pl1,pl3))
return 1;
if (char_married(pl1,pl3) && char_child(pl1,pl2))
return 1;
if (char_married(pl2,pl3) && char_child(pl2,pl1))
return 1;
}
return (maxlv==0 || maxlv-minlv<=party_share_level);
}
// Is there any member in the party?
int party_check_empty(struct party *p)
{
int i;
if (p==NULL||p->party_id==0) return 1;
// printf("party check empty %08X\n",(int)p);
for(i=0;i<MAX_PARTY;i++){
// printf("%d acc=%d\n",i,p->member[i].account_id);
if(p->member[i].account_id>0){
return 0;
}
}
// If there is no member, then break the party
mapif_party_broken(p->party_id,0);
inter_party_tosql(p->party_id,p);
return 1;
}
// Check if a member is in two party, not necessary :)
int party_check_conflict(int party_id,int account_id,char *nick)
{
return 0;
}
//-------------------------------------------------------------------
// map serverへの通信
// パーティ作成可否
int mapif_party_created(int fd,int account_id,struct party *p)
{
WFIFOW(fd,0)=0x3820;
WFIFOL(fd,2)=account_id;
if(p!=NULL){
WFIFOB(fd,6)=0;
WFIFOL(fd,7)=p->party_id;
memcpy(WFIFOP(fd,11),p->name,24);
printf("int_party: created! %d %s\n",p->party_id,p->name);
}else{
WFIFOB(fd,6)=1;
WFIFOL(fd,7)=0;
memcpy(WFIFOP(fd,11),"error",24);
}
WFIFOSET(fd,35);
return 0;
}
// パーティ情報見つからず
int mapif_party_noinfo(int fd,int party_id)
{
WFIFOW(fd,0)=0x3821;
WFIFOW(fd,2)=8;
WFIFOL(fd,4)=party_id;
WFIFOSET(fd,8);
printf("int_party: info not found %d\n",party_id);
return 0;
}
// パーティ情報まとめ送り
int mapif_party_info(int fd,struct party *p)
{
unsigned char buf[1024];
WBUFW(buf,0)=0x3821;
memcpy(buf+4,p,sizeof(struct party));
WBUFW(buf,2)=4+sizeof(struct party);
if(fd<0)
mapif_sendall(buf,WBUFW(buf,2));
else
mapif_send(fd,buf,WBUFW(buf,2));
// printf("int_party: info %d %s\n",p->party_id,p->name);
return 0;
}
// パーティメンバ追加可否
int mapif_party_memberadded(int fd,int party_id,int account_id,int flag)
{
WFIFOW(fd,0)=0x3822;
WFIFOL(fd,2)=party_id;
WFIFOL(fd,6)=account_id;
WFIFOB(fd,10)=flag;
WFIFOSET(fd,11);
return 0;
}
// パーティ設定変更通知
int mapif_party_optionchanged(int fd,struct party *p,int account_id,int flag)
{
unsigned char buf[16];
WBUFW(buf,0)=0x3823;
WBUFL(buf,2)=p->party_id;
WBUFL(buf,6)=account_id;
WBUFW(buf,10)=p->exp;
WBUFW(buf,12)=p->item;
WBUFB(buf,14)=flag;
if(flag==0)
mapif_sendall(buf,15);
else
mapif_send(fd,buf,15);
//printf("int_party: option changed %d %d %d %d %d\n",p->party_id,account_id,p->exp,p->item,flag);
return 0;
}
// パーティ脱退通知
int mapif_party_leaved(int party_id,int account_id,char *name)
{
unsigned char buf[64];
WBUFW(buf,0)=0x3824;
WBUFL(buf,2)=party_id;
WBUFL(buf,6)=account_id;
memcpy(WBUFP(buf,10),name,24);
mapif_sendall(buf,34);
//printf("int_party: party leaved %d %d %s\n",party_id,account_id,name);
return 0;
}
// パーティマップ更新通知
int mapif_party_membermoved(struct party *p,int idx)
{
unsigned char buf[32];
WBUFW(buf,0)=0x3825;
WBUFL(buf,2)=p->party_id;
WBUFL(buf,6)=p->member[idx].account_id;
memcpy(WBUFP(buf,10),p->member[idx].map,16);
WBUFB(buf,26)=p->member[idx].online;
WBUFW(buf,27)=p->member[idx].lv;
mapif_sendall(buf,29);
return 0;
}
// パーティ解散通知
int mapif_party_broken(int party_id,int flag)
{
unsigned char buf[16];
WBUFW(buf,0)=0x3826;
WBUFL(buf,2)=party_id;
WBUFB(buf,6)=flag;
mapif_sendall(buf,7);
//printf("int_party: broken %d\n",party_id);
return 0;
}
// パーティ内発言
int mapif_party_message(int party_id,int account_id,char *mes,int len, int sfd)
{
unsigned char buf[512];
WBUFW(buf,0)=0x3827;
WBUFW(buf,2)=len+12;
WBUFL(buf,4)=party_id;
WBUFL(buf,8)=account_id;
memcpy(WBUFP(buf,12),mes,len);
mapif_sendallwos(sfd, buf,len+12);
return 0;
}
//-------------------------------------------------------------------
// map serverからの通信
// Create Party
int mapif_parse_CreateParty(int fd,int account_id,char *name,char *nick,char *map,int lv, int item, int item2)
{
struct party *p;
if( (p=search_partyname(name))!=NULL){
// printf("int_party: same name party exists [%s]\n",name);
mapif_party_created(fd,account_id,NULL);
return 0;
}
p=party_pt;
if(p==NULL){
printf("int_party: out of memory !\n");
mapif_party_created(fd,account_id,NULL);
return 0;
}
memset(p,0,sizeof(struct party));
p->party_id=party_newid++;
memcpy(p->name,name,24);
p->exp=0;
p->item=item;
//<item1>アイテム?集方法。0で個人別、1でパ?ティ公有
//<item2>アイテム分配方法。0で個人別、1でパ?ティに均等分配
//difference between "collection" and "distribution" is...? ^^;
p->itemc = 0;
p->member[0].account_id=account_id;
memcpy(p->member[0].name,nick,24);
memcpy(p->member[0].map,map,16);
p->member[0].leader=1;
p->member[0].online=1;
p->member[0].lv=lv;
inter_party_tosql(p->party_id,p);
mapif_party_created(fd,account_id,p);
mapif_party_info(fd,p);
return 0;
}
// パーティ情報要求
int mapif_parse_PartyInfo(int fd,int party_id)
{
struct party *p = party_pt;
if(p==NULL){
printf("int_party: out of memory !\n");
return 0;
}
inter_party_fromsql(party_id, p);
if(p->party_id >= 0)
mapif_party_info(fd,p);
else
mapif_party_noinfo(fd,party_id);
return 0;
}
// パーティ追加要求
int mapif_parse_PartyAddMember(int fd,int party_id,int account_id,char *nick,char *map,int lv)
{
struct party *p;
int i;
p = party_pt;
if(p==NULL){
printf("int_party: out of memory !\n");
return 0;
}
inter_party_fromsql(party_id, p);
if(p->party_id <= 0){
mapif_party_memberadded(fd,party_id,account_id,1);
return 0;
}
for(i=0;i<MAX_PARTY;i++){
if(p->member[i].account_id==0){
int flag=0;
p->member[i].account_id=account_id;
memcpy(p->member[i].name,nick,24);
memcpy(p->member[i].map,map,16);
p->member[i].leader=0;
p->member[i].online=1;
p->member[i].lv=lv;
mapif_party_memberadded(fd,party_id,account_id,0);
mapif_party_info(-1,p);
if( p->exp>0 && !party_check_exp_share(p) ){
p->exp=0;
flag=0x01;
}
if(flag)
mapif_party_optionchanged(fd,p,0,0);
inter_party_tosql(party_id, p);
return 0;
}
}
mapif_party_memberadded(fd,party_id,account_id,1);
//inter_party_tosql(party_id, p);
return 0;
}
// パーティー設定変更要求
int mapif_parse_PartyChangeOption(int fd,int party_id,int account_id,int exp,int item)
{
struct party *p;
int flag=0;
p = party_pt;
if(p==NULL){
printf("int_party: out of memory !\n");
return 0;
}
inter_party_fromsql(party_id, p);
if(p->party_id <= 0){
return 0;
}
p->exp=exp;
if( exp>0 && !party_check_exp_share(p) ){
flag|=0x01;
p->exp=0;
}
p->item=item;
mapif_party_optionchanged(fd,p,account_id,flag);
inter_party_tosql(party_id, p);
return 0;
}
// パーティ脱退要求
int mapif_parse_PartyLeave(int fd,int party_id,int account_id)
{
char t_member[24];
struct party *p = party_pt;
if(p==NULL){
printf("int_party: out of memory !\n");
return 0;
}
inter_party_fromsql(party_id, p);
if(p->party_id >= 0){
int i,j;
for(i=0;i<MAX_PARTY;i++){
if(p->member[i].account_id==account_id){
//printf("p->member[i].account_id = %d , account_id = %d \n",p->member[i].account_id,account_id);
mapif_party_leaved(party_id,account_id,p->member[i].name);
// Update char information, does the name need encoding?
sprintf(tmp_sql,"UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d' AND `name`='%s'",
char_db, party_id, jstrescapecpy(t_member,p->member[i].name));
if(mysql_query(&mysql_handle, tmp_sql) ) {
printf("DB server Error (update `char`)- %s\n", mysql_error(&mysql_handle) );
}
// printf("Delete member %s from MySQL \n", p->member[i].name);
if (p->member[i].leader==1){
for(j=0;j<MAX_PARTY;j++)
{
//printf("j = %d , p->member[j].account_id = %d , p->member[j].account_id = %d \n",j,p->member[j].account_id,p->member[j].account_id);
if(p->member[j].account_id>0&&j!=i){
mapif_party_leaved(party_id,p->member[j].account_id,p->member[j].name);
// Update char information, does the name need encoding?
sprintf(tmp_sql,"UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d' AND `name`='%s'",
char_db, party_id, jstrescapecpy(t_member,p->member[i].name));
if(mysql_query(&mysql_handle, tmp_sql) ) {
printf("DB server Error (update `char`)- %s\n", mysql_error(&mysql_handle) );
}
// printf("Delete member %s from MySQL \n", p->member[j].name);
}
}
// Delete the party, if has no member.
sprintf(tmp_sql,"DELETE FROM `%s` WHERE `party_id`='%d'",party_db, party_id);
if(mysql_query(&mysql_handle, tmp_sql) ) {
printf("DB server Error - %s\n", mysql_error(&mysql_handle) );
}
// printf("Leader breaks party %d \n",party_id);
memset(p, 0, sizeof(struct party));
}else memset(&p->member[i],0,sizeof(struct party_member));
break;
}
}
if( party_check_empty(p)==0 )
mapif_party_info(-1,p);// まだ人がいるのでデータ送信
/*
else
inter_party_tosql(party_id,p); // Break the party if no member
*/
}else{
sprintf(tmp_sql,"UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d' AND `account_id`='%d' AND `online`='1'",
char_db, party_id, account_id);
if(mysql_query(&mysql_handle, tmp_sql) ) {
printf("DB server Error (update `char`)- %s\n", mysql_error(&mysql_handle) );
}
}
return 0;
}
// When member goes to other map
int mapif_parse_PartyChangeMap(int fd,int party_id,int account_id,char *map,int online,int lv)
{
struct party *p;
int i;
p = party_pt;
if(p==NULL){
printf("int_party: out of memory !\n");
return 0;
}
inter_party_fromsql(party_id, p);
if(p->party_id <= 0){
return 0;
}
for(i=0;i<MAX_PARTY;i++){
if(p->member[i].account_id==account_id){
int flag=0;
memcpy(p->member[i].map,map,16);
p->member[i].online=online;
p->member[i].lv=lv;
mapif_party_membermoved(p,i);
if( p->exp>0 && !party_check_exp_share(p) ){
p->exp=0;
flag=1;
}
if(flag)
mapif_party_optionchanged(fd,p,0,0);
break;
}
}
inter_party_tosql(party_id, p);
return 0;
}
// パーティ解散要求
int mapif_parse_BreakParty(int fd,int party_id)
{
struct party *p;
p = party_pt;
if(p==NULL){
printf("int_party: out of memory !\n");
return 0;
}
inter_party_fromsql(party_id, p);
if(p->party_id <= 0){
return 0;
}
inter_party_tosql(party_id,p);
mapif_party_broken(fd,party_id);
return 0;
}
// パーティメッセージ送信
int mapif_parse_PartyMessage(int fd,int party_id,int account_id,char *mes,int len)
{
return mapif_party_message(party_id,account_id,mes,len, fd);
}
// パーティチェック要求
int mapif_parse_PartyCheck(int fd,int party_id,int account_id,char *nick)
{
return party_check_conflict(party_id,account_id,nick);
}
// map server からの通信
// ・1パケットのみ解析すること
// ・パケット長データはinter.cにセットしておくこと
// ・パケット長チェックや、RFIFOSKIPは呼び出し元で行われるので行ってはならない
// ・エラーなら0(false)、そうでないなら1(true)をかえさなければならない
int inter_party_parse_frommap(int fd)
{
switch(RFIFOW(fd,0)){
case 0x3020: mapif_parse_CreateParty(fd,RFIFOL(fd,2),(char*)RFIFOP(fd,6),(char*)RFIFOP(fd,30),(char*)RFIFOP(fd,54),RFIFOW(fd,70), RFIFOB(fd,72), RFIFOB(fd,73)); break;
case 0x3021: mapif_parse_PartyInfo(fd,RFIFOL(fd,2)); break;
case 0x3022: mapif_parse_PartyAddMember(fd,RFIFOL(fd,2),RFIFOL(fd,6),(char*)RFIFOP(fd,10),(char*)RFIFOP(fd,34),RFIFOW(fd,50)); break;
case 0x3023: mapif_parse_PartyChangeOption(fd,RFIFOL(fd,2),RFIFOL(fd,6),RFIFOW(fd,10),RFIFOW(fd,12)); break;
case 0x3024: mapif_parse_PartyLeave(fd,RFIFOL(fd,2),RFIFOL(fd,6)); break;
case 0x3025: mapif_parse_PartyChangeMap(fd,RFIFOL(fd,2),RFIFOL(fd,6),(char*)RFIFOP(fd,10),RFIFOB(fd,26),RFIFOW(fd,27)); break;
case 0x3026: mapif_parse_BreakParty(fd,RFIFOL(fd,2)); break;
case 0x3027: mapif_parse_PartyMessage(fd,RFIFOL(fd,4),RFIFOL(fd,8),(char*)RFIFOP(fd,12),RFIFOW(fd,2)-12); break;
case 0x3028: mapif_parse_PartyCheck(fd,RFIFOL(fd,2),RFIFOL(fd,6),(char*)RFIFOP(fd,10)); break;
default:
return 0;
}
return 1;
}
// サーバーから脱退要求(キャラ削除用)
int inter_party_leave(int party_id,int account_id)
{
return mapif_parse_PartyLeave(-1,party_id,account_id);
}

View File

@@ -1,9 +0,0 @@
#ifndef _INT_PARTY_H_
#define _INT_PARTY_H_
int inter_party_parse_frommap(int fd);
int inter_party_sql_init();
void inter_party_sql_final();
int inter_party_leave(int party_id,int account_id);
#endif

View File

@@ -1,329 +0,0 @@
//
// original code from athena
// SQL conversion by Jioh L. Jung
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "char.h"
#include "../common/strlib.h"
struct s_pet *pet_pt;
static int pet_newid = 100;
#define mysql_query(_x, _y) debug_mysql_query(__FILE__, __LINE__, _x, _y)
//---------------------------------------------------------
int inter_pet_tosql(int pet_id, struct s_pet *p) {
//`pet` (`pet_id`, `class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incuvate`)
char t_name[100];
printf("request save pet: %d.......\n",pet_id);
jstrescapecpy(t_name, p->name);
if(p->hungry < 0)
p->hungry = 0;
else if(p->hungry > 100)
p->hungry = 100;
if(p->intimate < 0)
p->intimate = 0;
else if(p->intimate > 1000)
p->intimate = 1000;
sprintf(tmp_sql,"SELECT * FROM `%s` WHERE `pet_id`='%d'",pet_db, pet_id);
if(mysql_query(&mysql_handle, tmp_sql) ) {
printf("DB server Error - %s\n", mysql_error(&mysql_handle) );
}
sql_res = mysql_store_result(&mysql_handle) ;
if (sql_res!=NULL && mysql_num_rows(sql_res)>0)
//row reside -> updating
sprintf(tmp_sql, "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_, t_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);
else //no row -> insert
sprintf(tmp_sql,"INSERT INTO `%s` (`pet_id`, `class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incuvate`) VALUES ('%d', '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')",
pet_db, pet_id, p->class_, t_name, p->account_id, p->char_id, p->level, p->egg_id,
p->equip, p->intimate, p->hungry, p->rename_flag, p->incuvate);
mysql_free_result(sql_res) ; //resource free
if(mysql_query(&mysql_handle, tmp_sql) ) {
printf("DB server Error (inset/update `pet`)- %s\n", mysql_error(&mysql_handle) );
}
printf("pet save success.......\n");
return 0;
}
int inter_pet_fromsql(int pet_id, struct s_pet *p){
printf("request load pet: %d.......\n",pet_id);
memset(p, 0, sizeof(struct s_pet));
//`pet` (`pet_id`, `class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incuvate`)
sprintf(tmp_sql,"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(mysql_query(&mysql_handle, tmp_sql) ) {
printf("DB server Error (select `pet`)- %s\n", mysql_error(&mysql_handle) );
return 0;
}
sql_res = mysql_store_result(&mysql_handle) ;
if (sql_res!=NULL && mysql_num_rows(sql_res)>0) {
sql_row = mysql_fetch_row(sql_res);
p->pet_id = pet_id;
p->class_ = atoi(sql_row[1]);
memcpy(p->name, sql_row[2],24);
p->account_id = atoi(sql_row[3]);
p->char_id = atoi(sql_row[4]);
p->level = atoi(sql_row[5]);
p->egg_id = atoi(sql_row[6]);
p->equip = atoi(sql_row[7]);
p->intimate = atoi(sql_row[8]);
p->hungry = atoi(sql_row[9]);
p->rename_flag = atoi(sql_row[10]);
p->incuvate = atoi(sql_row[11]);
}
if(p->hungry < 0)
p->hungry = 0;
else if(p->hungry > 100)
p->hungry = 100;
if(p->intimate < 0)
p->intimate = 0;
else if(p->intimate > 1000)
p->intimate = 1000;
mysql_free_result(sql_res);
printf("pet load success.......\n");
return 0;
}
//----------------------------------------------
int inter_pet_sql_init(){
int i;
//memory alloc
printf("interserver pet memory initialize.... (%d byte)\n",sizeof(struct s_pet));
pet_pt = (struct s_pet*)aCalloc(sizeof(struct s_pet), 1);
sprintf (tmp_sql , "SELECT count(*) FROM `%s`", pet_db);
if(mysql_query(&mysql_handle, tmp_sql) ) {
printf("DB server Error - %s\n", mysql_error(&mysql_handle) );
exit(0);
}
sql_res = mysql_store_result(&mysql_handle) ;
sql_row = mysql_fetch_row(sql_res);
printf("total pet data -> '%s'.......\n",sql_row[0]);
i = atoi (sql_row[0]);
mysql_free_result(sql_res);
if (i > 0) {
//set pet_newid
sprintf (tmp_sql , "SELECT max(`pet_id`) FROM `%s`",pet_db );
if(mysql_query(&mysql_handle, tmp_sql) ) {
printf("DB server Error - %s\n", mysql_error(&mysql_handle) );
}
sql_res = mysql_store_result(&mysql_handle) ;
sql_row = mysql_fetch_row(sql_res);
pet_newid = atoi (sql_row[0])+1; //should SET MAX existing PET ID + 1 [Lupus]
mysql_free_result(sql_res);
}
printf("set pet_newid: %d.......\n",pet_newid);
return 0;
}
void inter_pet_sql_final(){
if (pet_pt) aFree(pet_pt);
return;
}
//----------------------------------
int inter_pet_delete(int pet_id){
printf("request delete pet: %d.......\n",pet_id);
sprintf(tmp_sql,"DELETE FROM `%s` WHERE `pet_id`='%d'",pet_db, pet_id);
if(mysql_query(&mysql_handle, tmp_sql) ) {
printf("DB server Error - %s\n", mysql_error(&mysql_handle) );
}
return 0;
}
//------------------------------------------------------
int mapif_pet_created(int fd, int account_id, struct s_pet *p)
{
WFIFOW(fd, 0) =0x3880;
WFIFOL(fd, 2) =account_id;
if(p!=NULL){
WFIFOB(fd, 6)=0;
WFIFOL(fd, 7) =p->pet_id;
printf("int_pet: created! %d %s\n", p->pet_id, p->name);
}else{
WFIFOB(fd, 6)=1;
WFIFOL(fd, 7)=0;
}
WFIFOSET(fd, 11);
return 0;
}
int mapif_pet_info(int fd, int account_id, struct s_pet *p){
WFIFOW(fd, 0) =0x3881;
WFIFOW(fd, 2) =sizeof(struct s_pet) + 9;
WFIFOL(fd, 4) =account_id;
WFIFOB(fd, 8)=0;
memcpy(WFIFOP(fd, 9), p, sizeof(struct s_pet));
WFIFOSET(fd, WFIFOW(fd, 2));
return 0;
}
int mapif_pet_noinfo(int fd, int account_id){
WFIFOW(fd, 0) =0x3881;
WFIFOW(fd, 2) =sizeof(struct s_pet) + 9;
WFIFOL(fd, 4) =account_id;
WFIFOB(fd, 8)=1;
memset(WFIFOP(fd, 9), 0, sizeof(struct s_pet));
WFIFOSET(fd, WFIFOW(fd, 2));
return 0;
}
int mapif_save_pet_ack(int fd, int account_id, int flag){
WFIFOW(fd, 0) =0x3882;
WFIFOL(fd, 2) =account_id;
WFIFOB(fd, 6) =flag;
WFIFOSET(fd, 7);
return 0;
}
int mapif_delete_pet_ack(int fd, int flag){
WFIFOW(fd, 0) =0x3883;
WFIFOB(fd, 2) =flag;
WFIFOSET(fd, 3);
return 0;
}
int mapif_create_pet(int fd, int account_id, int char_id, short pet_class, short pet_lv, short pet_egg_id,
short pet_equip, short intimate, short hungry, char rename_flag, char incuvate, char *pet_name){
memset(pet_pt, 0, sizeof(struct s_pet));
pet_pt->pet_id = pet_newid++;
memcpy(pet_pt->name, pet_name, 24);
if(incuvate == 1)
pet_pt->account_id = pet_pt->char_id = 0;
else {
pet_pt->account_id = account_id;
pet_pt->char_id = char_id;
}
pet_pt->class_ = pet_class;
pet_pt->level = pet_lv;
pet_pt->egg_id = pet_egg_id;
pet_pt->equip = pet_equip;
pet_pt->intimate = intimate;
pet_pt->hungry = hungry;
pet_pt->rename_flag = rename_flag;
pet_pt->incuvate = incuvate;
if(pet_pt->hungry < 0)
pet_pt->hungry = 0;
else if(pet_pt->hungry > 100)
pet_pt->hungry = 100;
if(pet_pt->intimate < 0)
pet_pt->intimate = 0;
else if(pet_pt->intimate > 1000)
pet_pt->intimate = 1000;
inter_pet_tosql(pet_pt->pet_id,pet_pt);
mapif_pet_created(fd, account_id, pet_pt);
return 0;
}
int mapif_load_pet(int fd, int account_id, int char_id, int pet_id){
memset(pet_pt, 0, sizeof(struct s_pet));
inter_pet_fromsql(pet_id, pet_pt);
if(pet_pt!=NULL) {
if(pet_pt->incuvate == 1) {
pet_pt->account_id = pet_pt->char_id = 0;
mapif_pet_info(fd, account_id, pet_pt);
}
else if(account_id == pet_pt->account_id && char_id == pet_pt->char_id)
mapif_pet_info(fd, account_id, pet_pt);
else
mapif_pet_noinfo(fd, account_id);
}
else
mapif_pet_noinfo(fd, account_id);
return 0;
}
int mapif_save_pet(int fd, int account_id, struct s_pet *data) {
//here process pet save request.
int len=RFIFOW(fd, 2);
if(sizeof(struct s_pet)!=len-8) {
printf("inter pet: data size error %d %d\n", sizeof(struct s_pet), len-8);
}
else{
if(data->hungry < 0)
data->hungry = 0;
else if(data->hungry > 100)
data->hungry = 100;
if(data->intimate < 0)
data->intimate = 0;
else if(data->intimate > 1000)
data->intimate = 1000;
inter_pet_tosql(data->pet_id,data);
mapif_save_pet_ack(fd, account_id, 0);
}
return 0;
}
int mapif_delete_pet(int fd, int pet_id){
mapif_delete_pet_ack(fd, inter_pet_delete(pet_id));
return 0;
}
int mapif_parse_CreatePet(int fd){
mapif_create_pet(fd, RFIFOL(fd, 2), RFIFOL(fd, 6), RFIFOW(fd, 10), RFIFOW(fd, 12), RFIFOW(fd, 14), RFIFOW(fd, 16), RFIFOL(fd, 18),
RFIFOL(fd, 20), RFIFOB(fd, 22), RFIFOB(fd, 23), (char*)RFIFOP(fd, 24));
return 0;
}
int mapif_parse_LoadPet(int fd){
mapif_load_pet(fd, RFIFOL(fd, 2), RFIFOL(fd, 6), RFIFOL(fd, 10));
return 0;
}
int mapif_parse_SavePet(int fd){
mapif_save_pet(fd, RFIFOL(fd, 4), (struct s_pet *) RFIFOP(fd, 8));
return 0;
}
int mapif_parse_DeletePet(int fd){
mapif_delete_pet(fd, RFIFOL(fd, 2));
return 0;
}
int inter_pet_parse_frommap(int fd){
switch(RFIFOW(fd, 0)){
case 0x3080: mapif_parse_CreatePet(fd); break;
case 0x3081: mapif_parse_LoadPet(fd); break;
case 0x3082: mapif_parse_SavePet(fd); break;
case 0x3083: mapif_parse_DeletePet(fd); break;
default:
return 0;
}
return 1;
}

View File

@@ -1,13 +0,0 @@
#ifndef _INT_PET_H_
#define _INT_PET_H_
int inter_pet_init();
void inter_pet_sql_final();
int inter_pet_save();
int inter_pet_delete(int pet_id);
int inter_pet_parse_frommap(int fd);
int inter_pet_sql_init();
//extern char pet_txt[256];
#endif

View File

@@ -1,339 +0,0 @@
//
// original code from athena
// SQL conversion by Jioh L. Jung
//
#include <string.h>
#include <stdlib.h>
#include "char.h"
#include "itemdb.h"
#define STORAGE_MEMINC 16
// reset by inter_config_read()
struct storage *storage_pt=NULL;
struct guild_storage *guild_storage_pt=NULL;
#define mysql_query(_x, _y) debug_mysql_query(__FILE__, __LINE__, _x, _y)
// storage data -> DB conversion
int storage_tosql(int account_id,struct storage *p){
int i;
// int eqcount=1;
// int noteqcount=1;
int count=0;
struct itemtmp mapitem[MAX_GUILD_STORAGE];
for(i=0;i<MAX_STORAGE;i++){
if(p->storage_[i].nameid>0){
mapitem[count].flag=0;
mapitem[count].id = p->storage_[i].id;
mapitem[count].nameid=p->storage_[i].nameid;
mapitem[count].amount = p->storage_[i].amount;
mapitem[count].equip = p->storage_[i].equip;
mapitem[count].identify = p->storage_[i].identify;
mapitem[count].refine = p->storage_[i].refine;
mapitem[count].attribute = p->storage_[i].attribute;
mapitem[count].card[0] = p->storage_[i].card[0];
mapitem[count].card[1] = p->storage_[i].card[1];
mapitem[count].card[2] = p->storage_[i].card[2];
mapitem[count].card[3] = p->storage_[i].card[3];
count++;
}
}
memitemdata_to_sql(mapitem, count, account_id,TABLE_STORAGE);
//printf ("storage dump to DB - id: %d (total: %d)\n", account_id, j);
return 0;
}
// DB -> storage data conversion
int storage_fromsql(int account_id, struct storage *p){
int i=0;
memset(p,0,sizeof(struct storage)); //clean up memory
p->storage_amount = 0;
p->account_id = account_id;
// storage {`account_id`/`id`/`nameid`/`amount`/`equip`/`identify`/`refine`/`attribute`/`card0`/`card1`/`card2`/`card3`}
sprintf(tmp_sql,"SELECT `id`,`nameid`,`amount`,`equip`,`identify`,`refine`,`attribute`,`card0`,`card1`,`card2`,`card3` FROM `%s` WHERE `account_id`='%d'",storage_db, account_id);
if(mysql_query(&mysql_handle, tmp_sql) ) {
printf("DB server Error - %s\n", mysql_error(&mysql_handle) );
}
sql_res = mysql_store_result(&mysql_handle) ;
if (sql_res) {
while((sql_row = mysql_fetch_row(sql_res))) { //start to fetch
p->storage_[i].id= atoi(sql_row[0]);
p->storage_[i].nameid= atoi(sql_row[1]);
p->storage_[i].amount= atoi(sql_row[2]);
p->storage_[i].equip= atoi(sql_row[3]);
p->storage_[i].identify= atoi(sql_row[4]);
p->storage_[i].refine= atoi(sql_row[5]);
p->storage_[i].attribute= atoi(sql_row[6]);
p->storage_[i].card[0]= atoi(sql_row[7]);
p->storage_[i].card[1]= atoi(sql_row[8]);
p->storage_[i].card[2]= atoi(sql_row[9]);
p->storage_[i].card[3]= atoi(sql_row[10]);
p->storage_amount = ++i;
}
mysql_free_result(sql_res);
}
printf ("storage load complete from DB - id: %d (total: %d)\n", account_id, p->storage_amount);
return 1;
}
// Save guild_storage data to sql
int guild_storage_tosql(int guild_id, struct guild_storage *p){
int i;
// int eqcount=1;
// int noteqcount=1;
int count=0;
struct itemtmp mapitem[MAX_GUILD_STORAGE];
for(i=0;i<MAX_GUILD_STORAGE;i++){
if(p->storage_[i].nameid>0){
mapitem[count].flag=0;
mapitem[count].id = p->storage_[i].id;
mapitem[count].nameid=p->storage_[i].nameid;
mapitem[count].amount = p->storage_[i].amount;
mapitem[count].equip = p->storage_[i].equip;
mapitem[count].identify = p->storage_[i].identify;
mapitem[count].refine = p->storage_[i].refine;
mapitem[count].attribute = p->storage_[i].attribute;
mapitem[count].card[0] = p->storage_[i].card[0];
mapitem[count].card[1] = p->storage_[i].card[1];
mapitem[count].card[2] = p->storage_[i].card[2];
mapitem[count].card[3] = p->storage_[i].card[3];
count++;
}
}
memitemdata_to_sql(mapitem, count, guild_id,TABLE_GUILD_STORAGE);
printf ("guild storage save to DB - id: %d (total: %d)\n", guild_id,i);
return 0;
}
// Load guild_storage data to mem
int guild_storage_fromsql(int guild_id, struct guild_storage *p){
int i=0;
struct guild_storage *gs=guild_storage_pt;
p=gs;
memset(p,0,sizeof(struct guild_storage)); //clean up memory
p->storage_amount = 0;
p->guild_id = guild_id;
// storage {`guild_id`/`id`/`nameid`/`amount`/`equip`/`identify`/`refine`/`attribute`/`card0`/`card1`/`card2`/`card3`}
sprintf(tmp_sql,"SELECT `id`,`nameid`,`amount`,`equip`,`identify`,`refine`,`attribute`,`card0`,`card1`,`card2`,`card3` FROM `%s` WHERE `guild_id`='%d'",guild_storage_db, guild_id);
if(mysql_query(&mysql_handle, tmp_sql) ) {
printf("DB server Error - %s\n", mysql_error(&mysql_handle) );
}
sql_res = mysql_store_result(&mysql_handle) ;
if (sql_res) {
while((sql_row = mysql_fetch_row(sql_res))) { //start to fetch
p->storage_[i].id= atoi(sql_row[0]);
p->storage_[i].nameid= atoi(sql_row[1]);
p->storage_[i].amount= atoi(sql_row[2]);
p->storage_[i].equip= atoi(sql_row[3]);
p->storage_[i].identify= atoi(sql_row[4]);
p->storage_[i].refine= atoi(sql_row[5]);
p->storage_[i].attribute= atoi(sql_row[6]);
p->storage_[i].card[0]= atoi(sql_row[7]);
p->storage_[i].card[1]= atoi(sql_row[8]);
p->storage_[i].card[2]= atoi(sql_row[9]);
p->storage_[i].card[3]= atoi(sql_row[10]);
p->storage_amount = ++i;
if (i >= MAX_GUILD_STORAGE)
break;
}
mysql_free_result(sql_res);
}
printf ("guild storage load complete from DB - id: %d (total: %d)\n", guild_id, p->storage_amount);
return 0;
}
//---------------------------------------------------------
// storage data initialize
int inter_storage_sql_init(){
//memory alloc
printf("interserver storage memory initialize....(%d byte)\n",sizeof(struct storage));
storage_pt = (struct storage*)aCalloc(sizeof(struct storage), 1);
guild_storage_pt = (struct guild_storage*)aCalloc(sizeof(struct guild_storage), 1);
memset(storage_pt,0,sizeof(struct storage));
memset(guild_storage_pt,0,sizeof(struct guild_storage));
return 1;
}
// storage data finalize
void inter_storage_sql_final()
{
if (storage_pt) aFree(storage_pt);
if (guild_storage_pt) aFree(guild_storage_pt);
return;
}
// q?f[^?
int inter_storage_delete(int account_id)
{
sprintf(tmp_sql, "DELETE FROM `%s` WHERE `account_id`='%d'",storage_db, account_id);
if(mysql_query(&mysql_handle, tmp_sql) ) {
printf("DB server Error (delete `storage`)- %s\n", mysql_error(&mysql_handle) );
}
return 0;
}
int inter_guild_storage_delete(int guild_id)
{
sprintf(tmp_sql, "DELETE FROM `%s` WHERE `guild_id`='%d'",guild_storage_db, guild_id);
if(mysql_query(&mysql_handle, tmp_sql) ) {
printf("DB server Error (delete `guild_storage`)- %s\n", mysql_error(&mysql_handle) );
}
return 0;
}
//---------------------------------------------------------
// packet from map server
// recive packet about storage data
int mapif_load_storage(int fd,int account_id){
//load from DB
storage_fromsql(account_id, storage_pt);
WFIFOW(fd,0)=0x3810;
WFIFOW(fd,2)=sizeof(struct storage)+8;
WFIFOL(fd,4)=account_id;
memcpy(WFIFOP(fd,8),storage_pt,sizeof(struct storage));
WFIFOSET(fd,WFIFOW(fd,2));
return 0;
}
// send ack to map server which is "storage data save ok."
int mapif_save_storage_ack(int fd,int account_id){
WFIFOW(fd,0)=0x3811;
WFIFOL(fd,2)=account_id;
WFIFOB(fd,6)=0;
WFIFOSET(fd,7);
return 0;
}
int mapif_load_guild_storage(int fd,int account_id,int guild_id)
{
int guild_exist=0;
WFIFOW(fd,0)=0x3818;
// Check if guild exists, I may write a function for this later, coz I use it several times.
//printf("- Check if guild %d exists\n",g->guild_id);
sprintf(tmp_sql, "SELECT count(*) FROM `%s` WHERE `guild_id`='%d'",guild_db, guild_id);
if(mysql_query(&mysql_handle, tmp_sql) ) {
printf("DB server Error (delete `guild`)- %s\n", mysql_error(&mysql_handle) );
}
sql_res = mysql_store_result(&mysql_handle) ;
if (sql_res!=NULL && mysql_num_rows(sql_res)>0) {
sql_row = mysql_fetch_row(sql_res);
guild_exist = atoi (sql_row[0]);
//printf("- Check if guild %d exists : %s\n",g->guild_id,((guild_exist==0)?"No":"Yes"));
}
mysql_free_result(sql_res) ; //resource free
if(guild_exist==1) {
guild_storage_fromsql(guild_id,guild_storage_pt);
WFIFOW(fd,2)=sizeof(struct guild_storage)+12;
WFIFOL(fd,4)=account_id;
WFIFOL(fd,8)=guild_id;
memcpy(WFIFOP(fd,12),guild_storage_pt,sizeof(struct guild_storage));
}
else {
WFIFOW(fd,2)=12;
WFIFOL(fd,4)=account_id;
WFIFOL(fd,8)=0;
}
WFIFOSET(fd,WFIFOW(fd,2));
return 0;
}
int mapif_save_guild_storage_ack(int fd,int account_id,int guild_id,int fail)
{
WFIFOW(fd,0)=0x3819;
WFIFOL(fd,2)=account_id;
WFIFOL(fd,6)=guild_id;
WFIFOB(fd,10)=fail;
WFIFOSET(fd,11);
return 0;
}
//---------------------------------------------------------
// packet from map server
// recive request about storage data
int mapif_parse_LoadStorage(int fd){
mapif_load_storage(fd,RFIFOL(fd,2));
return 0;
}
// storage data recive and save
int mapif_parse_SaveStorage(int fd){
int account_id=RFIFOL(fd,4);
int len=RFIFOW(fd,2);
if(sizeof(struct storage)!=len-8){
printf("inter storage: data size error %d %d\n",sizeof(struct storage),len-8);
}else{
memcpy(&storage_pt[0],RFIFOP(fd,8),sizeof(struct storage));
storage_tosql(account_id, storage_pt);
mapif_save_storage_ack(fd,account_id);
}
return 0;
}
int mapif_parse_LoadGuildStorage(int fd)
{
mapif_load_guild_storage(fd,RFIFOL(fd,2),RFIFOL(fd,6));
return 0;
}
int mapif_parse_SaveGuildStorage(int fd)
{
int guild_exist=0;
int guild_id=RFIFOL(fd,8);
int len=RFIFOW(fd,2);
if(sizeof(struct guild_storage)!=len-12){
printf("inter storage: data size error %d %d\n",sizeof(struct guild_storage),len-12);
}
else {
// Check if guild exists, I may write a function for this later, coz I use it several times.
//printf("- Check if guild %d exists\n",g->guild_id);
sprintf(tmp_sql, "SELECT count(*) FROM `%s` WHERE `guild_id`='%d'",guild_db, guild_id);
if(mysql_query(&mysql_handle, tmp_sql) ) {
printf("DB server Error (delete `guild`)- %s\n", mysql_error(&mysql_handle) );
}
sql_res = mysql_store_result(&mysql_handle) ;
if (sql_res!=NULL && mysql_num_rows(sql_res)>0) {
sql_row = mysql_fetch_row(sql_res);
guild_exist = atoi (sql_row[0]);
//printf("- Check if guild %d exists : %s\n",g->guild_id,((guild_exist==0)?"No":"Yes"));
}
mysql_free_result(sql_res) ; //resource free
if(guild_exist==1) {
memcpy(guild_storage_pt,RFIFOP(fd,12),sizeof(struct guild_storage));
guild_storage_tosql(guild_id,guild_storage_pt);
mapif_save_guild_storage_ack(fd,RFIFOL(fd,4),guild_id,0);
}
else
mapif_save_guild_storage_ack(fd,RFIFOL(fd,4),guild_id,1);
}
return 0;
}
int inter_storage_parse_frommap(int fd){
switch(RFIFOW(fd,0)){
case 0x3010: mapif_parse_LoadStorage(fd); break;
case 0x3011: mapif_parse_SaveStorage(fd); break;
case 0x3018: mapif_parse_LoadGuildStorage(fd); break;
case 0x3019: mapif_parse_SaveGuildStorage(fd); break;
default:
return 0;
}
return 1;
}

View File

@@ -1,14 +0,0 @@
#ifndef _INT_STORAGE_H_
#define _INT_STORAGE_H_
int inter_storage_sql_init();
void inter_storage_sql_final();
int inter_storage_delete(int account_id);
int inter_guild_storage_delete(int guild_id);
int inter_storage_parse_frommap(int fd);
//extern char storage_txt[256];
#endif

View File

@@ -1,625 +0,0 @@
//
// original code from athena
// SQL conversion by Jioh L. Jung
//
#include <string.h>
#include <stdlib.h>
#include "char.h"
#include "../common/strlib.h"
#include "inter.h"
#include "int_party.h"
#include "int_guild.h"
#include "int_storage.h"
#include "int_pet.h"
#include "lock.h"
#define WISDATA_TTL (60*1000) // Wisデータの生存時間(60秒)
#define WISDELLIST_MAX 256 // Wisデータ削除リストの要素数
struct accreg {
int account_id,reg_num;
struct global_reg reg[ACCOUNT_REG_NUM];
};
static struct accreg *accreg_pt;
int party_share_level = 10;
MYSQL mysql_handle;
MYSQL_RES* sql_res ;
MYSQL_ROW sql_row ;
int sql_fields, sql_cnt;
char tmp_sql[65535];
MYSQL lmysql_handle;
char tmp_lsql[65535];
MYSQL_RES* lsql_res ;
MYSQL_ROW lsql_row ;
int char_server_port = 3306;
char char_server_ip[32] = "127.0.0.1";
char char_server_id[32] = "ragnarok";
char char_server_pw[32] = "ragnarok";
char char_server_db[32] = "ragnarok";
int login_server_port = 3306;
char login_server_ip[32] = "127.0.0.1";
char login_server_id[32] = "ragnarok";
char login_server_pw[32] = "ragnarok";
char login_server_db[32] = "ragnarok";
// sending packet list
int inter_send_packet_length[]={
-1,-1,27, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
// recv. packet list
int inter_recv_packet_length[]={
-1,-1, 7, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6,-1, 0, 0, 0, 0, 0, 0, 10,-1, 0, 0, 0, 0, 0, 0,
74, 6,52,14, 10,29, 6,-1, 34, 0, 0, 0, 0, 0, 0, 0,
-1, 6,-1, 0, 55,19, 6,-1, 14,-1,-1,-1, 14,19,186,-1,
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,
};
struct WisData {
int id,fd,count,len;
unsigned long tick;
unsigned char src[24],dst[24],msg[512];
};
static struct dbt * wis_db = NULL;
static int wis_dellist[WISDELLIST_MAX], wis_delnum;
//--------------------------------------------------------
// Save account_reg to sql (type=2)
int inter_accreg_tosql(int account_id,struct accreg *reg){
int j;
char temp_str[32];
if (account_id<=0) return 0;
reg->account_id=account_id;
//`global_reg_value` (`type`, `account_id`, `char_id`, `str`, `value`)
sprintf(tmp_sql,"DELETE FROM `%s` WHERE `type`=2 AND `account_id`='%d'",reg_db, account_id);
if(mysql_query(&mysql_handle, tmp_sql) ) {
printf("DB server Error (delete `global_reg_value`)- %s\n", mysql_error(&mysql_handle) );
}
if (reg->reg_num<=0) return 0;
for(j=0;j<reg->reg_num;j++){
if(reg->reg[j].str != NULL){
sprintf(tmp_sql,"INSERT INTO `%s` (`type`, `account_id`, `str`, `value`) VALUES (2,'%d', '%s','%d')",
reg_db, reg->account_id, jstrescapecpy(temp_str,reg->reg[j].str), reg->reg[j].value);
if(mysql_query(&mysql_handle, tmp_sql) ) {
printf("DB server Error (insert `global_reg_value`)- %s\n", mysql_error(&mysql_handle) );
}
}
}
return 0;
}
// Load account_reg from sql (type=2)
int inter_accreg_fromsql(int account_id,struct accreg *reg)
{
int j=0;
if (reg==NULL) return 0;
memset(reg, 0, sizeof(struct accreg));
reg->account_id=account_id;
//`global_reg_value` (`type`, `account_id`, `char_id`, `str`, `value`)
sprintf (tmp_sql, "SELECT `str`, `value` FROM `%s` WHERE `type`=2 AND `account_id`='%d'",reg_db, reg->account_id);
if(mysql_query(&mysql_handle, tmp_sql) ) {
printf("DB server Error (select `global_reg_value`)- %s\n", mysql_error(&mysql_handle) );
}
sql_res = mysql_store_result(&mysql_handle);
if (sql_res) {
for(j=0;(sql_row = mysql_fetch_row(sql_res));j++){
memcpy(reg->reg[j].str, sql_row[0],32);
reg->reg[j].value = atoi(sql_row[1]);
}
mysql_free_result(sql_res);
}
reg->reg_num=j;
return 0;
}
// Initialize
int inter_accreg_sql_init()
{
CREATE(accreg_pt, struct accreg, 1);
return 0;
}
/*==========================================
* read config file
*------------------------------------------
*/
int inter_config_read(const char *cfgName) {
int i;
char line[1024], w1[1024], w2[1024];
FILE *fp;
printf ("start reading interserver configuration: %s\n",cfgName);
fp=fopen(cfgName,"r");
if(fp==NULL){
printf("file not found: %s\n", cfgName);
return 1;
}
while(fgets(line, 1020, fp)){
i=sscanf(line,"%[^:]: %[^\r\n]",w1,w2);
if(i!=2)
continue;
if(strcmpi(w1,"char_server_ip")==0){
strcpy(char_server_ip, w2);
printf ("set char_server_ip : %s\n",w2);
}
else if(strcmpi(w1,"char_server_port")==0){
char_server_port=atoi(w2);
printf ("set char_server_port : %s\n",w2);
}
else if(strcmpi(w1,"char_server_id")==0){
strcpy(char_server_id, w2);
printf ("set char_server_id : %s\n",w2);
}
else if(strcmpi(w1,"char_server_pw")==0){
strcpy(char_server_pw, w2);
printf ("set char_server_pw : %s\n",w2);
}
else if(strcmpi(w1,"char_server_db")==0){
strcpy(char_server_db, w2);
printf ("set char_server_db : %s\n",w2);
}
//Logins information to be read from the inter_athena.conf
//for character deletion (checks email in the loginDB)
else if(strcmpi(w1,"login_server_ip")==0){
strcpy(login_server_ip, w2);
printf ("set login_server_ip : %s\n",w2);
}
else if(strcmpi(w1,"login_server_port")==0){
login_server_port=atoi(w2);
printf ("set login_server_port : %s\n",w2);
}
else if(strcmpi(w1,"login_server_id")==0){
strcpy(login_server_id, w2);
printf ("set login_server_id : %s\n",w2);
}
else if(strcmpi(w1,"login_server_pw")==0){
strcpy(login_server_pw, w2);
printf ("set login_server_pw : %s\n",w2);
}
else if(strcmpi(w1,"login_server_db")==0){
strcpy(login_server_db, w2);
printf ("set login_server_db : %s\n",w2);
}
else if(strcmpi(w1,"party_share_level")==0){
party_share_level=atoi(w2);
if(party_share_level < 0) party_share_level = 0;
}else if(strcmpi(w1,"import")==0){
inter_config_read(w2);
}
else if(strcmpi(w1,"log_inter")==0){
log_inter = atoi(w2);
}
else if(strcmpi(w1,"login_server_db")==0){
strcpy(login_server_db, w2);
printf ("set login_server_db : %s\n",w2);
}
}
fclose(fp);
printf ("success reading interserver configuration\n");
return 0;
}
// Save interlog into sql
int inter_log(char *fmt,...)
{
char str[255];
char temp_str[255];
va_list ap;
va_start(ap,fmt);
vsprintf(str,fmt,ap);
sprintf(tmp_sql,"INSERT INTO `%s` (`time`, `log`) VALUES (NOW(), '%s')",interlog_db, jstrescapecpy(temp_str,str));
if(mysql_query(&mysql_handle, tmp_sql) ) {
printf("DB server Error (insert `interlog`)- %s\n", mysql_error(&mysql_handle) );
}
va_end(ap);
return 0;
}
// initialize
int inter_init(const char *file)
{
//int i;
printf ("interserver initialize...\n");
inter_config_read(file);
//DB connection initialized
mysql_init(&mysql_handle);
printf("Connect Character DB server.... (Character Server)\n");
if(!mysql_real_connect(&mysql_handle, char_server_ip, char_server_id, char_server_pw,
char_server_db ,char_server_port, (char *)NULL, 0)) {
//pointer check
printf("%s\n",mysql_error(&mysql_handle));
exit(1);
}
else {
printf ("Connect Success! (Character Server)\n");
}
mysql_init(&lmysql_handle);
printf("Connect Character DB server.... (login server)\n");
if(!mysql_real_connect(&lmysql_handle, login_server_ip, login_server_id, login_server_pw,
login_server_db ,login_server_port, (char *)NULL, 0)) {
//pointer check
printf("%s\n",mysql_error(&lmysql_handle));
exit(1);
}else {
printf ("Connect Success! (Login Server)");
}
wis_db = numdb_init();
inter_guild_sql_init();
inter_storage_sql_init();
inter_party_sql_init();
inter_pet_sql_init();
inter_accreg_sql_init();
atexit(inter_final);
//printf ("interserver timer initializing : %d sec...\n",autosave_interval);
//i=add_timer_interval(gettick()+autosave_interval,inter_save_timer,0,0,autosave_interval);
return 0;
}
// finalize
int wis_db_final (void *k, void *data, va_list ap) {
struct WisData *p = (struct WisData *) data;
if (p) aFree(p);
return 0;
}
void inter_final() {
numdb_final(wis_db, wis_db_final);
inter_guild_sql_final();
inter_storage_sql_final();
inter_party_sql_final();
inter_pet_sql_final();
if (accreg_pt) aFree(accreg_pt);
return;
}
int inter_mapif_init(int fd) {
inter_guild_mapif_init(fd);
return 0;
}
//--------------------------------------------------------
// GM message sending
int mapif_GMmessage(unsigned char *mes, int len, int sfd) {
unsigned char buf[len];
WBUFW(buf, 0) = 0x3800;
WBUFW(buf, 2) = len;
memcpy(WBUFP(buf, 4), mes, len-4);
mapif_sendallwos(sfd, buf, len);
printf("\033[1;34m inter server: GM[len:%d] - '%s' \033[0m\n", len, mes);
return 0;
}
// Wis sending
int mapif_wis_message(struct WisData *wd) {
unsigned char buf[56 + wd->len];
WBUFW(buf, 0) = 0x3801;
WBUFW(buf, 2) = 56 +wd->len;
WBUFL(buf, 4) = wd->id;
memcpy(WBUFP(buf, 8), wd->src, 24);
memcpy(WBUFP(buf,32), wd->dst, 24);
memcpy(WBUFP(buf,56), wd->msg, wd->len);
wd->count = mapif_sendall(buf,WBUFW(buf,2));
return 0;
}
// Wis sending result
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;
mapif_send(wd->fd,buf,27);
// printf("inter server wis_end %d\n",flag);
return 0;
}
int mapif_account_reg(int fd,unsigned char *src)
{
unsigned char buf[WBUFW(src,2)];
memcpy(WBUFP(buf,0),src,WBUFW(src,2));
WBUFW(buf, 0)=0x3804;
mapif_sendallwos(fd,buf,WBUFW(buf,2));
return 0;
}
// Send the requested account_reg
int mapif_account_reg_reply(int fd,int account_id)
{
struct accreg *reg=accreg_pt;
inter_accreg_fromsql(account_id,reg);
WFIFOW(fd,0)=0x3804;
WFIFOL(fd,4)=account_id;
if(reg->reg_num==0){
WFIFOW(fd,2)=8;
}else{
int j,p;
for(j=0,p=8;j<reg->reg_num;j++,p+=36){
memcpy(WFIFOP(fd,p),reg->reg[j].str,32);
WFIFOL(fd,p+32)=reg->reg[j].value;
}
WFIFOW(fd,2)=p;
}
WFIFOSET(fd,WFIFOW(fd,2));
return 0;
}
int mapif_send_gmaccounts()
{
int i, len = 4;
unsigned char buf[32000];
// forward the gm accounts to the map server
len = 4;
WBUFW(buf,0) = 0x2b15;
for(i = 0; i < GM_num; i++) {
WBUFL(buf, len) = gm_account[i].account_id;
WBUFB(buf, len+4) = (unsigned char)gm_account[i].level;
len += 5;
}
WBUFW(buf, 2) = len;
mapif_sendall(buf, len);
return 0;
}
//--------------------------------------------------------
// Existence check of WISP data
int check_ttl_wisdata_sub(void *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() {
unsigned long tick = gettick();
int i;
do {
wis_delnum = 0;
numdb_foreach(wis_db, check_ttl_wisdata_sub, tick);
for(i = 0; i < wis_delnum; i++) {
struct WisData *wd = (struct WisData*)numdb_search(wis_db, wis_dellist[i]);
printf("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
numdb_erase(wis_db, wd->id);
aFree(wd);
}
} while(wis_delnum >= WISDELLIST_MAX);
return 0;
}
//--------------------------------------------------------
// GM message sending
int mapif_parse_GMmessage(int fd)
{
mapif_GMmessage(RFIFOP(fd, 4), RFIFOW(fd, 2), fd);
return 0;
}
// Wisp/page request to send
int mapif_parse_WisRequest(int fd) {
struct WisData* wd;
static int wisid = 0;
char t_name[32];
if (RFIFOW(fd,2)-52 >= sizeof(wd->msg)) {
printf("inter: Wis message size too long.\n");
return 0;
} else if (RFIFOW(fd,2)-52 <= 0) { // normaly, impossible, but who knows...
printf("inter: Wis message doesn't exist.\n");
return 0;
}
sprintf (tmp_sql, "SELECT `name` FROM `%s` WHERE `name`='%s'",
char_db, jstrescapecpy(t_name, (char *)RFIFOP(fd,28)));
if(mysql_query(&mysql_handle, tmp_sql) ) {
printf("DB server Error - %s\n", mysql_error(&mysql_handle) );
}
sql_res = mysql_store_result(&mysql_handle);
// search if character exists before to ask all map-servers
if (!(sql_row = mysql_fetch_row(sql_res))) {
unsigned char buf[27];
WBUFW(buf, 0) = 0x3802;
memcpy(WBUFP(buf, 2), RFIFOP(fd, 4), 24);
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);
// Character exists. So, ask all map-servers
} else {
// to be sure of the correct name, rewrite it
memset(RFIFOP(fd,28), 0, 24);
strncpy((char*)RFIFOP(fd,28), sql_row[0], 24);
// if source is destination, don't ask other servers.
if (strcmp((char*)RFIFOP(fd,4),(char*)RFIFOP(fd,28)) == 0) {
unsigned char buf[27];
WBUFW(buf, 0) = 0x3802;
memcpy(WBUFP(buf, 2), RFIFOP(fd, 4), 24);
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);
} else {
CREATE(wd, struct WisData, 1);
// Whether the failure of previous wisp/page transmission (timeout)
check_ttl_wisdata();
wd->id = ++wisid;
wd->fd = fd;
wd->len= RFIFOW(fd,2)-52;
memcpy(wd->src, RFIFOP(fd, 4), 24);
memcpy(wd->dst, RFIFOP(fd,28), 24);
memcpy(wd->msg, RFIFOP(fd,52), wd->len);
wd->tick = gettick();
numdb_insert(wis_db, wd->id, wd);
mapif_wis_message(wd);
}
}
//Freeing ... O.o
if(sql_res){
mysql_free_result(sql_res);
}
return 0;
}
// Wisp/page transmission result
int mapif_parse_WisReply(int fd) {
int id = RFIFOL(fd,2), flag = RFIFOB(fd,6);
struct WisData *wd = (struct WisData*)numdb_search(wis_db, id);
if (wd == NULL)
return 0; // This wisp was probably suppress before, because it was timeout of 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
numdb_erase(wis_db, id);
aFree(wd);
}
return 0;
}
// Save account_reg into sql (type=2)
int mapif_parse_AccReg(int fd)
{
int j,p;
struct accreg *reg=accreg_pt;
int account_id = RFIFOL(fd,4);
memset(accreg_pt,0,sizeof(struct accreg));
for(j=0,p=8;j<ACCOUNT_REG_NUM && p<RFIFOW(fd,2);j++,p+=36){
memcpy(reg->reg[j].str,RFIFOP(fd,p),32);
reg->reg[j].value=RFIFOL(fd,p+32);
}
reg->reg_num=j;
inter_accreg_tosql(account_id,reg);
mapif_account_reg(fd,RFIFOP(fd,0)); // Send confirm message to map
return 0;
}
// Request the value of account_reg
int mapif_parse_AccRegRequest(int fd)
{
// printf("mapif: accreg request\n");
return mapif_account_reg_reply(fd,RFIFOL(fd,2));
}
//--------------------------------------------------------
int inter_parse_frommap(int fd)
{
int cmd=RFIFOW(fd,0);
int len=0;
// inter鯖管轄かを調べる
if(cmd<0x3000 || cmd>=0x3000+( sizeof(inter_recv_packet_length)/
sizeof(inter_recv_packet_length[0]) ) )
return 0;
// パケット長を調べる
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 0x3004: mapif_parse_AccReg(fd); break;
case 0x3005: mapif_parse_AccRegRequest(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;
return 0;
}
RFIFOSKIP(fd, len );
return 1;
}
// RFIFO check
int inter_check_length(int fd, int length)
{
if(length==-1){ // v-len packet
if(RFIFOREST(fd)<4) // packet not yet
return 0;
length = RFIFOW(fd, 2);
}
if(RFIFOREST(fd)<length) // packet not yet
return 0;
return length;
}

View File

@@ -1,47 +0,0 @@
#ifndef _INTER_H_
#define _INTER_H_
int inter_init(const char *file);
void inter_final();
int inter_parse_frommap(int fd);
int inter_mapif_init(int fd);
int mapif_send_gmaccounts();
int inter_check_length(int fd,int length);
int inter_log(char *fmt,...);
#define inter_cfgName "conf/inter_athena.conf"
extern int party_share_level;
extern char inter_log_filename[1024];
//add include for DBMS(mysql)
#include <mysql.h>
extern MYSQL mysql_handle;
extern char tmp_sql[65535];
extern MYSQL_RES* sql_res ;
extern MYSQL_ROW sql_row ;
extern int sql_cnt;
extern MYSQL lmysql_handle;
extern char tmp_lsql[65535];
extern MYSQL_RES* lsql_res ;
extern MYSQL_ROW lsql_row ;
extern int char_server_port;
extern char char_server_ip[32];
extern char char_server_id[32];
extern char char_server_pw[32];
extern char char_server_db[32];
extern int login_db_server_port;
extern char login_db_server_ip[32];
extern char login_db_server_id[32];
extern char login_db_server_pw[32];
extern char login_db_server_db[32];
extern int log_inter;
#endif

View File

@@ -1,247 +0,0 @@
// $Id: itemdb.c,v 1.1.1.1 2004/09/10 17:44:48 MagicalTux Exp $
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "itemdb.h"
#include "db.h"
#include "inter.h"
#include "char.h"
#include "utils.h"
#ifdef MEMWATCH
#include "memwatch.h"
#endif
#define MAX_RANDITEM 2000
// ** ITEMDB_OVERRIDE_NAME_VERBOSE **
// 定義すると、itemdb.txtとgrfで名前が異なる場合、表示します.
//#define ITEMDB_OVERRIDE_NAME_VERBOSE 1
char item_db_db[256]="item_db"; // added to specify item_db sql table [Valaris]
static struct dbt* item_db;
/*==========================================
* DBの検索
*------------------------------------------
*/
struct item_data* itemdb_search(int nameid)
{
struct item_data *id;
id = (struct item_data*)numdb_search(item_db,nameid);
if(id) return id;
CREATE(id, struct item_data, 1);
numdb_insert(item_db,nameid,id);
if(nameid>500 && nameid<600)
id->type=0; //heal item
else if(nameid>600 && nameid<700)
id->type=2; //use item
else if((nameid>700 && nameid<1100) ||
(nameid>7000 && nameid<8000))
id->type=3; //correction
else if(nameid>=1750 && nameid<1771)
id->type=10; //arrow
else if(nameid>1100 && nameid<2000)
id->type=4; //weapon
else if((nameid>2100 && nameid<3000) ||
(nameid>5000 && nameid<6000))
id->type=5; //armor
else if(nameid>4000 && nameid<5000)
id->type=6; //card
else if(nameid>9000 && nameid<10000)
id->type=7; //egg
else if(nameid>10000)
id->type=8; //petequip
return id;
}
/*==========================================
*
*------------------------------------------
*/
int itemdb_isequip(int nameid)
{
int type=itemdb_type(nameid);
if(type==0 || type==2 || type==3 || type==6 || type==10)
return 0;
return 1;
}
/*==========================================
*
*------------------------------------------
*/
int itemdb_isequip2(struct item_data *data)
{
if(data) {
int type=data->type;
if(type==0 || type==2 || type==3 || type==6 || type==10)
return 0;
else
return 1;
}
return 0;
}
/*==========================================
* アイテムデータベースの読み込み
*------------------------------------------
*/
static int itemdb_readdb(void)
{
FILE *fp;
char line[1024];
int ln=0;
int nameid,j;
char *str[32],*p,*np;
struct item_data *id;
fp=fopen("db/item_db.txt","r");
if(fp==NULL){
printf("can't read db/item_db.txt\n");
exit(1);
}
while(fgets(line,1020,fp)){
if(line[0]=='/' && line[1]=='/')
continue;
memset(str,0,sizeof(str));
for(j=0,np=p=line;j<17 && p;j++){
str[j]=p;
p=strchr(p,',');
if(p){ *p++=0; np=p; }
}
if(str[0]==NULL)
continue;
nameid=atoi(str[0]);
if(nameid<=0 || nameid>=20000)
continue;
ln++;
//ID,Name,Jname,Type,Price,Sell,Weight,ATK,DEF,Range,Slot,Job,Gender,Loc,wLV,eLV,View
id=itemdb_search(nameid);
memcpy(id->name,str[1],24);
memcpy(id->jname,str[2],24);
id->type=atoi(str[3]);
}
fclose(fp);
printf("read db/item_db.txt done (count=%d)\n",ln);
return 0;
}
static int itemdb_read_sqldb(void) // sql item_db read, shortened version of map-server item_db read [Valaris]
{
unsigned int nameid; // Type should be "unsigned short int", but currently isn't for compatibility with numdb_insert()
struct item_data *id;
// ----------
// Output query to retrieve all rows from the item database table
sprintf(tmp_sql, "SELECT * FROM `%s`", item_db_db);
// Execute the query; if the query execution fails, output an error
if (mysql_query(&mysql_handle, tmp_sql)) {
printf("Database server error (executing query for %s): %s\n", item_db_db, mysql_error(&mysql_handle));
}
// Store the query result
sql_res = mysql_store_result(&mysql_handle);
// If the storage of the query result succeeded
if (sql_res) {
// Parse each row in the query result into sql_row
while ((sql_row = mysql_fetch_row(sql_res))) {
nameid = atoi(sql_row[0]);
// If the identifier is not within the valid range, process the next row
if (nameid == 0 || nameid >= 20000) { // Should ">= 20000" be "> 20000"?
continue;
}
// ----------
// Insert a new row into the item database
/*
id = aCalloc(sizeof(struct item_data), 1);
if (id == NULL) {
printf("out of memory : itemdb_read_sqldb\n");
exit(1);
}
memset(id, 0, sizeof(struct item_data));
numdb_insert(item_db, nameid, id);
// ----------
*/
id=itemdb_search(nameid);
memcpy(id->name, sql_row[1], 24);
memcpy(id->jname, sql_row[2], 24);
id->type = atoi(sql_row[3]);
}
// If the retrieval failed, output an error
if (mysql_errno(&mysql_handle)) {
printf("Database server error (retrieving rows from %s): %s\n", item_db_db, mysql_error(&mysql_handle));
}
printf("read %s done (count = %lu)\n", item_db_db, (unsigned long) mysql_num_rows(sql_res));
// Free the query result
mysql_free_result(sql_res);
} else {
printf("MySQL error (storing query result for %s): %s\n", item_db_db, mysql_error(&mysql_handle));
}
return 0;
}
static int itemdb_final(void *key,void *data,va_list ap)
{
struct item_data *id;
id = (struct item_data*)data;
if(id->use_script)
aFree(id->use_script);
if(id->equip_script)
aFree(id->equip_script);
aFree(id);
return 0;
}
/*==========================================
*
*------------------------------------------
*/
void do_final_itemdb(void)
{
if(item_db){
numdb_final(item_db,itemdb_final);
item_db=NULL;
}
}
int do_init_itemdb(void)
{
item_db = numdb_init();
if (db_use_sqldbs) // it db_use_sqldbs in inter config are yes, will read from item_db for char server display [Valaris]
itemdb_read_sqldb();
else
itemdb_readdb();
return 0;
}

View File

@@ -1,34 +0,0 @@
#ifndef _ITEMDB_H_
#define _ITEMDB_H_
struct item_data {
int nameid;
char name[24],jname[24];
int value_buy,value_sell,value_notdc,value_notoc;
int type;
int class_;
int sex;
int equip;
int weight;
int atk;
int def;
int range;
int slot;
int look;
int elv;
int wlv;
char *use_script; // 回復とかも全部この中でやろうかなと
char *equip_script; // 攻撃,防御の属性設定もこの中で可能かな?
char available;
};
struct item_data* itemdb_search(int nameid);
#define itemdb_type(n) itemdb_search(n)->type
int itemdb_isequip(int);
int itemdb_isequip2(struct item_data *);
void do_final_itemdb(void);
int do_init_itemdb(void);
#endif

View File

@@ -1,10 +0,0 @@
#!/bin/sh
rsqlt=`rm -rf *.o`
gcc -c char.c -I/usr/local/include/mysql/
gcc -c int_guild.c -I/usr/local/include/mysql/
gcc -c int_party.c -I/usr/local/include/mysql/
gcc -c int_pet.c -I/usr/local/include/mysql/
gcc -c int_storage.c -I/usr/local/include/mysql/
gcc -c inter.c -I/usr/local/include/mysql/
gcc -c itemdb.c -I../common/
gcc -o ../char-server inter.o char.o int_pet.o int_storage.o int_guild.o int_party.o ../common/strlib.o itemdb.o ../common/core.o ../common/socket.o ../common/timer.o ../common/db.o -L/usr/local/lib/mysql -lmysqlclient -lz

View File

@@ -1,250 +0,0 @@
//Encoded with UTF-8 (UNICODE)
//---------------------------------------------
// V.018 - Aarlex
1. ADD Makefile & GNUmakefile
2. fix guild_leave.
3. fix char select windows HP & SP value error.
// V.017 - Aarlex
1. fix guild member view job update.(For mod-0728)
inter.c
int_guild.c
// V.016 - by Aarlex
1. Add e-mail check when you Delete char data.
2. modify storage save func like 014.
2. remove Lan_support func.
// v.014 - by Aarlex
I rewrite save function.
besause myfriend find that Mysql will use more than 40% CPU.
And log file is too big (4 days 22G ..= =+)
(maybe he sets autosave_time less then 1 min.)
but. i still rewrite save func.
char server will delete all of user item(inventory & Cart) data then insert them again before.
so i use two struct to save item data from map & database.
then compare two struct to get different .
AND add some debug message.but message maybe too much XD.
1. ADDED itemdb.c itemdb.h
2. modify mmo_char_tosql().
3. ADDED memitemdata_to_sql().
4. ADDED some debug message in memitemdata_to_sql().
5. modify make.sh
// v.013 - by Aarlex
1. some SQL sentance fix in old version Mysql .
2. in_guild.c mapif_guild_leaved()
unsigned char buf[64] -> unsigned char buf[128]
3. in_pet.c inter_pet_tosql()
if (sql_res) - > if (mysql_num_rows(sql_res)!=0)
4. in_char.c mmo_char_send006b()
WFIFOW(fd, offset+(i*106)+42) = char_dat[0].hp -> WFIFOW(fd,offset+(i*106)+42) = (char_dat[j].hp > 0x7fff)? 0x7fff:char_dat[j].hp;
WFIFOW(fd, offset+(i*106)+44) = char_dat[0].max_hp -> WFIFOW(fd,offset+(i*106)+44) = (char_dat[j].max_hp > 0x7fff)? 0x7fff:char_dat[j].max_hp;
WFIFOW(fd, offset+(i*106)+46) = char_dat[0].sp -> WFIFOW(fd,offset+(i*106)+46) = (char_dat[j].sp > 0x7fff)? 0x7fff:char_dat[j].sp
WFIFOW(fd, offset+(i*106)+48) = char_dat[0].max_sp -> WFIFOW(fd,offset+(i*106)+48) = (char_dat[j].max_sp > 0x7fff)? 0x7fff:char_dat[j].max_sp;
in_char.c parse_char()
WFIFOW(fd, offset+(i*106)+42) = char_dat[0].hp -> WFIFOW(fd,offset+(i*106)+42) = (char_dat[j].hp > 0x7fff)? 0x7fff:char_dat[j].hp;
WFIFOW(fd, offset+(i*106)+44) = char_dat[0].max_hp -> WFIFOW(fd,offset+(i*106)+44) = (char_dat[j].max_hp > 0x7fff)? 0x7fff:char_dat[j].max_hp;
WFIFOW(fd, offset+(i*106)+46) = char_dat[0].sp -> WFIFOW(fd,offset+(i*106)+46) = (char_dat[j].sp > 0x7fff)? 0x7fff:char_dat[j].sp
WFIFOW(fd, offset+(i*106)+48) = char_dat[0].max_sp -> WFIFOW(fd,offset+(i*106)+48) = (char_dat[j].max_sp > 0x7fff)? 0x7fff:char_dat[j].max_sp;
// v.012 - by Jazz
1. 0627 official versionに合わせて修正しました.
2. no more binary files are supplied.
//---------------------------------------------
// v.011 - by Mark
1. Fixed a couple bugs which would cause segfaults under linux :)
//---------------------------------------------
// v.010 - by Jazz
1. added some debug info - for reporting.
//---------------------------------------------
// v.009 - by Jazz
1. code added for debug.
2. some SQL sentance fix.
//---------------------------------------------
// v.009 - by Jazz
1. fix crash bug. - pet db.
//---------------------------------------------
// v.008 - by Jazz
1. DB table fix. - char.fix-from.007.to.008.sql
既存の table 構造には矢が装着解除される場合があります.
item.equipは 'unsigned short' 形式です.
このために SQL tableを修正しなければなりません.
修正コードは char.fix-from.007.to.008.sql です.
MySQLで一度行ってくれれば適用されます. 既存のデータは安全です.
//---------------------------------------------
// v.007 - by Jazz
1. domain 解釈に対する問題を修正しました.
//---------------------------------------------
// v.006 - by Jazz
1. crash bug fix. - when your pet DB is empty
//---------------------------------------------
// v.005 - by Jazz
1. 0590 official versionに合わせて修正しました.
//---------------------------------------------
// v.004 - by Jazz
1. 0586 official versionに合わせて修正しました.
//---------------------------------------------
// v.003 - by Jazz
1. officialの guild.c と party.c ファイルでまた再修正しました.
//---------------------------------------------
// v.002 - by Jazz
1. aphostropy 問題を解決しました. これは保安と連関がある問題です.
2. SQLの構造を修正しました.
//---------------------------------------------
// v.001 - by Jazz
1. 一番目安定 versionです. alpha versionに問題点を多数修正しました.
//------------------------------------------------------------------------
//For JAPANESE USER
Athena Char-Server for MySQL. 005
一応 guildと partyはよく呼び出しされる部分なので既存の athena char-serverが使っている file 基盤の構造を持って行きます.
これは, 一度にメモリーで皆読んで, もう一度に皆 fileで使う方が部下が少なくかかると思います.
そして char データに比べて, lostになっても問題がもっと少ないと判断してそうしました.
MySQLバージョンの compileは MySQL Clients Libraryが必要です. windows(cygwin) バージョンにコンパイルされた binaryを添付しました.
設置:
まだ text->DBの converterはまともに支援しないです. 内部的にちょっとバグが発見されてバグを修正中です.
できるだけ早く uploadをします.
1. char.sqlを MySQLに dumpします.
2. inter_athena.confに次を追加します. そして自分の DBサーバーの情報に合わせてくれます.
ここで windows(cygwin)の場合には localhostを使ってはいけないです. ipで書いてくれなければなりません.
localhostで使う場合 UNIX domain socketが作動するから連結が不可能になります.
//3306 is default
db_server_port: 3306
//DB ip
db_server_ip: 127.0.0.1
//DB id
db_server_id: ragnarok
//DB pass
db_server_pw: ragnarok
//DB name
db_server_logindb: ragnarok
3. MySQL バージョンは 2個の MySQL connect sessionを持ちます.
一つはキャラクターデータを読んで書くのに使われて, 二番目は inter serverのために連結します.
開発とテスト環境は P4 2.4a/1024MB/WinXP pro(MediaCenter Edition 2K4 KR)/Cygwin GCC です.
本人が韓国人だから韓国語開発者の連絡も歓迎します.
韓国語と日本語の上手な方は連絡をください. 日本語の使用に難しさを感じています.
現在 DarkWeissが login serverに MySQLを支援し始めました.
しかし athenaのそれは DarkWeiss よりもっとよく作動すると思います.
contact : jazz@creper.com
//------------------------------------------------------------------------
//For KOREAN USER
Athena Char-Server for MySQL. 005
일단 guild와 party는 자주 호출되는 부분이라서 기존의 athena char-server가 사용하고 있는 file 기반의 구조를 가지고 갑니다.
이 것은, 한번에 메모리로 모두 읽고, 다시 한번에 모두 file로 쓰는 쪽이 부하가 적게 걸린다고 생각합니다.
그리고 char 데이터에 비해, lost가 되더라도 문제가 더 적다고 판단해서 그렇게 하였습니다.
MySQL버전의 compile은 MySQL Clients Library가 필요합니다. windows(cygwin) 버전으로 컴파일된 binary를 첨부하였습니다.
설치:
아직 text->DB의 converter는 제대로 지원하지 않습니다. 내부적으로 약간 버그가 발견되어 버그를 수정중입니다.
되도록 빨리 upload를 하겠습니다.
1. char.sql을 MySQL에 dump합니다.
2. inter_athena.conf에 다음을 추가 합니다. 그리고 자신의 DB서버의 정보에 맞추어 줍니다.
여기에서 windows(cygwin)의 경우에는 localhost를 쓰면 안됩니다. ip로 적어주어야 합니다.
localhost로 사용하는 경우 UNIX domain socket이 작동 하기 때문에 연결이 불가능해 집니다.
//3306 is default
db_server_port: 3306
//DB ip
db_server_ip: 127.0.0.1
//DB id
db_server_id: ragnarok
//DB pass
db_server_pw: ragnarok
//DB name
db_server_logindb: ragnarok
3. MySQL 버전은 2개의 MySQL connect session을 가집니다.
하나는 캐릭터 데이터를 읽고 쓰는데 사용되며, 두번째는 inter server를 위해서 연결합니다.
개발과 테스트 환경은 P4 2.4a/1024MB/WinXP pro(MediaCenter Edition 2K4 KR)/Cygwin GCC 입니다.
본인이 한국인이기 때문에 한국어 개발자의 연락도 환영합니다.
한국어와 일본어가 능숙한 분은 연락을 주세요. 일본어의 사용에 어려움을 느끼고 있습니다.
현재 DarkWeiss가 login server에 MySQL을 지원하기 시작했습니다.
하지만 athena의 그것은 DarkWeiss 보다 더 잘 작동한다고 생각합니다.
contact : jazz@creper.com
//------------------------------------------------------------------------
//For ENGLISH USER
Athena Char-Server for MySQL. alpha 005
= hehe. My English is poor. and I have no time to write. :)
anyway this version use guild and party data on text file base system.
It accesses many times, so memory dumping is useful for less cpu consume.
MySQL version need MySQL Clients Library to compile. This include Win32-binary compiled by cygwin-gcc.
Install:
not yet text->DB converter. I found some bug on it, so It's under debug progress.
1. dump char.sql to MySQL.
2. add below on inter_athena.conf. and set your own information.
do not use 'localhost' as domain on cygwin. you must set as ip.
if you use localhost on cygwin, cygwin tries to connect MySQL as UNIX domain socket.
but, MySQL does not support UNIX domain socket on windows.
//3306 is default
db_server_port: 3306
//DB ip
db_server_ip: 127.0.0.1
//DB id
db_server_id: ragnarok
//DB pass
db_server_pw: ragnarok
//DB name
db_server_logindb: ragnarok
3. MySQL version has 2 MySQL connect session.
one is for char-server and the other one is for inter-server.
developement enviroment)
P4 2.4a/1024MB/WinXP pro(MediaCenter Edition 2K4 KR)/Cygwin GCC
I'm korean, so contect if U're Korean developer.
Please contact me, If U can use Korean & Japanese well.
DarkWeiss starts to support MySQL version of login server, but Athena's one works better, I thnik.
contact : jazz@creper.com