From 620e60eebce2c1f35c5c9a82f6ca365b316587f5 Mon Sep 17 00:00:00 2001 From: Valaris Date: Sun, 29 Jan 2006 16:10:48 +0000 Subject: AS OF SVN REV. 5901, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO INTO TRUNK. IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK. EVERYTHING ELSE GOES INTO TRUNK AND WILL BE MERGED INTO STABLE BY VALARIS AND WIZPUTER. -- VALARIS git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@5094 54d463be-8e91-2dee-dedb-b68131a5f0ec --- src/txt-converter/Makefile | 15 + src/txt-converter/char-converter.c | 1360 +++++++++++++++++++++++++++++++++++ src/txt-converter/login-converter.c | 227 ++++++ 3 files changed, 1602 insertions(+) create mode 100644 src/txt-converter/Makefile create mode 100644 src/txt-converter/char-converter.c create mode 100644 src/txt-converter/login-converter.c (limited to 'src/txt-converter') diff --git a/src/txt-converter/Makefile b/src/txt-converter/Makefile new file mode 100644 index 000000000..7d3203407 --- /dev/null +++ b/src/txt-converter/Makefile @@ -0,0 +1,15 @@ +all sql: char-converter login-converter + +char-converter: char-converter.o ../common/obj/minicore.o ../common/obj/malloc.o ../common/obj/showmsg.o ../common/obj/strlib.o ../common/obj/mapindex.o ../common/obj/ers.o + $(CC) -o ../../tools/$@ $^ $(LIB_S) + +login-converter: login-converter.o ../common/obj/minicore.o ../common/obj/db.o ../common/obj/malloc.o ../common/obj/showmsg.o + $(CC) -o ../../tools/$@ $^ $(LIB_S) + +clean: + rm -f *.o ../../tools/login-converter ../../tools/char-converter + +# DO NOT DELETE + +char-converter.o: char-converter.c +login-converter.o: login-converter.c diff --git a/src/txt-converter/char-converter.c b/src/txt-converter/char-converter.c new file mode 100644 index 000000000..2070b9b9d --- /dev/null +++ b/src/txt-converter/char-converter.c @@ -0,0 +1,1360 @@ +// (c) eAthena Dev Team - Licensed under GNU GPL +// For more information, see LICENCE in the main folder + +#include +#include +#include + +#include "../common/core.h" +#include "../common/strlib.h" +#include "../common/mmo.h" +#include "../common/showmsg.h" +#include "../common/mapindex.h" + +#include + +//Txt Files used. +char char_txt[1024]="save/athena.txt"; +char friends_txt[1024]="save/friends.txt"; // davidsiaw +char pet_txt[256]="save/pet.txt"; +char storage_txt[256]="save/storage.txt"; + +//Databases used. +char char_db[256] = "char"; +char cart_db[256] = "cart_inventory"; +char inventory_db[256] = "inventory"; +char storage_db[256] = "storage"; +char reg_db[256] = "global_reg_value"; +char skill_db[256] = "skill"; +char memo_db[256] = "memo"; +char pet_db[256] = "pet"; +char friend_db[256] = "friends"; +char guild_storage_db[256] = "guild_storage"; + +MYSQL mysql_handle; +MYSQL_RES* sql_res ; +MYSQL_ROW sql_row ; +char tmp_sql[65535]; + +int sql_fields, sql_cnt; + +int db_server_port = 3306; +char db_server_ip[16] = "127.0.0.1"; +char db_server_id[32] = "ragnarok"; +char db_server_pw[32] = "ragnarok"; +char db_server_logindb[32] = "ragnarok"; + +char t_name[256]; + +int char_id_count=100000; + +struct accreg { + int reg_num; + struct global_reg reg[ACCOUNT_REG_NUM]; +}; + +struct character_data { + struct mmo_charstatus status; + struct accreg global; +} *char_dat; +int char_num, char_max; + +//Required for sql saving, taken from src/char_sql/char.h +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, +}; + +#define CHAR_CONF_NAME "conf/char_athena.conf" +#define INTER_CONF_NAME "conf/inter_athena.conf" +//========================================================================================================== +//NOTE: Update this function from the one in src/char/char.c as needed. [Skotlex] +int mmo_char_fromstr(char *str, struct mmo_charstatus *p, struct accreg *reg) { + char tmp_str[3][128]; //To avoid deleting chars with too long names. + int tmp_int[256]; + int set, next, len, i; + + // initilialise character + memset(p, '\0', sizeof(struct mmo_charstatus)); + + // If it's not char structure of version 1488 and after + if ((set = sscanf(str, "%d\t%d,%d\t%127[^\t]\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d\t%d,%d,%d,%d,%d,%d\t%d,%d" + "\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d,%d" + "\t%127[^,],%d,%d\t%127[^,],%d,%d,%d,%d,%d,%d,%d%n", + &tmp_int[0], &tmp_int[1], &tmp_int[2], tmp_str[0], + &tmp_int[3], &tmp_int[4], &tmp_int[5], + &tmp_int[6], &tmp_int[7], &tmp_int[8], + &tmp_int[9], &tmp_int[10], &tmp_int[11], &tmp_int[12], + &tmp_int[13], &tmp_int[14], &tmp_int[15], &tmp_int[16], &tmp_int[17], &tmp_int[18], + &tmp_int[19], &tmp_int[20], + &tmp_int[21], &tmp_int[22], &tmp_int[23], // + &tmp_int[24], &tmp_int[25], &tmp_int[26], + &tmp_int[27], &tmp_int[28], &tmp_int[29], + &tmp_int[30], &tmp_int[31], &tmp_int[32], &tmp_int[33], &tmp_int[34], + tmp_str[1], &tmp_int[35], &tmp_int[36], + tmp_str[2], &tmp_int[37], &tmp_int[38], &tmp_int[39], + &tmp_int[40], &tmp_int[41], &tmp_int[42], &tmp_int[43], &next)) != 47) + { + tmp_int[43] = 0; + // If it's not char structure of version 1363 and after + if ((set = sscanf(str, "%d\t%d,%d\t%127[^\t]\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d\t%d,%d,%d,%d,%d,%d\t%d,%d" + "\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d,%d" + "\t%127[^,],%d,%d\t%127[^,],%d,%d,%d,%d,%d,%d%n", + &tmp_int[0], &tmp_int[1], &tmp_int[2], tmp_str[0], // + &tmp_int[3], &tmp_int[4], &tmp_int[5], + &tmp_int[6], &tmp_int[7], &tmp_int[8], + &tmp_int[9], &tmp_int[10], &tmp_int[11], &tmp_int[12], + &tmp_int[13], &tmp_int[14], &tmp_int[15], &tmp_int[16], &tmp_int[17], &tmp_int[18], + &tmp_int[19], &tmp_int[20], + &tmp_int[21], &tmp_int[22], &tmp_int[23], // + &tmp_int[24], &tmp_int[25], &tmp_int[26], + &tmp_int[27], &tmp_int[28], &tmp_int[29], + &tmp_int[30], &tmp_int[31], &tmp_int[32], &tmp_int[33], &tmp_int[34], + tmp_str[1], &tmp_int[35], &tmp_int[36], // + tmp_str[2], &tmp_int[37], &tmp_int[38], &tmp_int[39], + &tmp_int[40], &tmp_int[41], &tmp_int[42], &next)) != 46) + { + tmp_int[40] = 0; // father + tmp_int[41] = 0; // mother + tmp_int[42] = 0; // child + // If it's not char structure of version 1008 and before 1363 + if ((set = sscanf(str, "%d\t%d,%d\t%127[^\t]\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d\t%d,%d,%d,%d,%d,%d\t%d,%d" + "\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d,%d" + "\t%127[^,],%d,%d\t%127[^,],%d,%d,%d%n", + &tmp_int[0], &tmp_int[1], &tmp_int[2], tmp_str[0], // + &tmp_int[3], &tmp_int[4], &tmp_int[5], + &tmp_int[6], &tmp_int[7], &tmp_int[8], + &tmp_int[9], &tmp_int[10], &tmp_int[11], &tmp_int[12], + &tmp_int[13], &tmp_int[14], &tmp_int[15], &tmp_int[16], &tmp_int[17], &tmp_int[18], + &tmp_int[19], &tmp_int[20], + &tmp_int[21], &tmp_int[22], &tmp_int[23], // + &tmp_int[24], &tmp_int[25], &tmp_int[26], + &tmp_int[27], &tmp_int[28], &tmp_int[29], + &tmp_int[30], &tmp_int[31], &tmp_int[32], &tmp_int[33], &tmp_int[34], + tmp_str[1], &tmp_int[35], &tmp_int[36], // + tmp_str[2], &tmp_int[37], &tmp_int[38], &tmp_int[39], &next)) != 43) + { + tmp_int[39] = 0; // partner id + // If not char structure from version 384 to 1007 + if ((set = sscanf(str, "%d\t%d,%d\t%127[^\t]\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d\t%d,%d,%d,%d,%d,%d\t%d,%d" + "\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d,%d" + "\t%127[^,],%d,%d\t%127[^,],%d,%d%n", + &tmp_int[0], &tmp_int[1], &tmp_int[2], tmp_str[0], // + &tmp_int[3], &tmp_int[4], &tmp_int[5], + &tmp_int[6], &tmp_int[7], &tmp_int[8], + &tmp_int[9], &tmp_int[10], &tmp_int[11], &tmp_int[12], + &tmp_int[13], &tmp_int[14], &tmp_int[15], &tmp_int[16], &tmp_int[17], &tmp_int[18], + &tmp_int[19], &tmp_int[20], + &tmp_int[21], &tmp_int[22], &tmp_int[23], // + &tmp_int[24], &tmp_int[25], &tmp_int[26], + &tmp_int[27], &tmp_int[28], &tmp_int[29], + &tmp_int[30], &tmp_int[31], &tmp_int[32], &tmp_int[33], &tmp_int[34], + tmp_str[1], &tmp_int[35], &tmp_int[36], // + tmp_str[2], &tmp_int[37], &tmp_int[38], &next)) != 42) + { + // It's char structure of a version before 384 + tmp_int[26] = 0; // pet id + set = sscanf(str, "%d\t%d,%d\t%127[^\t]\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d\t%d,%d,%d,%d,%d,%d\t%d,%d" + "\t%d,%d,%d\t%d,%d\t%d,%d,%d\t%d,%d,%d,%d,%d" + "\t%127[^,],%d,%d\t%127[^,],%d,%d%n", + &tmp_int[0], &tmp_int[1], &tmp_int[2], tmp_str[0], // + &tmp_int[3], &tmp_int[4], &tmp_int[5], + &tmp_int[6], &tmp_int[7], &tmp_int[8], + &tmp_int[9], &tmp_int[10], &tmp_int[11], &tmp_int[12], + &tmp_int[13], &tmp_int[14], &tmp_int[15], &tmp_int[16], &tmp_int[17], &tmp_int[18], + &tmp_int[19], &tmp_int[20], + &tmp_int[21], &tmp_int[22], &tmp_int[23], // + &tmp_int[24], &tmp_int[25], // + &tmp_int[27], &tmp_int[28], &tmp_int[29], + &tmp_int[30], &tmp_int[31], &tmp_int[32], &tmp_int[33], &tmp_int[34], + tmp_str[1], &tmp_int[35], &tmp_int[36], // + tmp_str[2], &tmp_int[37], &tmp_int[38], &next); + set += 2; + //printf("char: old char data ver.1\n"); + // Char structure of version 1007 or older + } else { + set++; + //printf("char: old char data ver.2\n"); + } + // Char structure of version 1008+ + } else { + set += 3; + //printf("char: new char data ver.3\n"); + } + // Char structture of version 1363+ + } else { + set++; + //printf("char: new char data ver.4\n"); + } + // Char structure of version 1488+ + } else { + //printf("char: new char data ver.5\n"); + } + if (set != 47) + return 0; + + memcpy(p->name, tmp_str[0], NAME_LENGTH-1); //Overflow protection [Skotlex] + p->char_id = tmp_int[0]; + p->account_id = tmp_int[1]; + p->char_num = tmp_int[2]; + p->class_ = tmp_int[3]; + p->base_level = tmp_int[4]; + p->job_level = tmp_int[5]; + p->base_exp = tmp_int[6]; + p->job_exp = tmp_int[7]; + p->zeny = tmp_int[8]; + p->hp = tmp_int[9]; + p->max_hp = tmp_int[10]; + p->sp = tmp_int[11]; + p->max_sp = tmp_int[12]; + p->str = tmp_int[13]; + p->agi = tmp_int[14]; + p->vit = tmp_int[15]; + p->int_ = tmp_int[16]; + p->dex = tmp_int[17]; + p->luk = tmp_int[18]; + p->status_point = tmp_int[19]; + p->skill_point = tmp_int[20]; + p->option = tmp_int[21]; + p->karma = tmp_int[22]; + p->manner = tmp_int[23]; + p->party_id = tmp_int[24]; + p->guild_id = tmp_int[25]; + p->pet_id = tmp_int[26]; + p->hair = tmp_int[27]; + p->hair_color = tmp_int[28]; + p->clothes_color = tmp_int[29]; + p->weapon = tmp_int[30]; + p->shield = tmp_int[31]; + p->head_top = tmp_int[32]; + p->head_mid = tmp_int[33]; + p->head_bottom = tmp_int[34]; + p->last_point.map = mapindex_name2id(tmp_str[1]); + p->last_point.x = tmp_int[35]; + p->last_point.y = tmp_int[36]; + p->save_point.map = mapindex_name2id(tmp_str[2]); + p->save_point.x = tmp_int[37]; + p->save_point.y = tmp_int[38]; + p->partner_id = tmp_int[39]; + p->father = tmp_int[40]; + p->mother = tmp_int[41]; + p->child = tmp_int[42]; + p->fame = tmp_int[43]; + + // Some checks + for(i = 0; i < char_num; i++) { + if (char_dat[i].status.char_id == p->char_id) { + ShowError("\033[1;31mmmo_auth_init: a character has an identical id to another.\n"); + ShowError(" character id #%d -> new character not readed.\n", p->char_id); + ShowError(" Character saved in log file.\033[0m\n"); + return -1; + } else if (strcmp(char_dat[i].status.name, p->name) == 0) { + ShowError("\033[1;31mmmo_auth_init: a character name already exists.\n"); + ShowError(" character name '%s' -> new character not read.\n", p->name); + ShowError(" Character saved in log file.\033[0m\n"); + return -2; + } + } + + if (str[next] == '\n' || str[next] == '\r') + return 1; // V‹Kƒf[ƒ^ + + next++; + + for(i = 0; str[next] && str[next] != '\t'; i++) { + if (sscanf(str+next, "%[^,],%d,%d%n", tmp_str[0], &tmp_int[0], &tmp_int[1], &len) != 3) + return -3; + p->memo_point[i].map = mapindex_name2id(tmp_str[0]); + p->memo_point[i].x = tmp_int[0]; + p->memo_point[i].y = tmp_int[1]; + next += len; + if (str[next] == ' ') + next++; + } + + next++; + + for(i = 0; str[next] && str[next] != '\t'; i++) { + if (sscanf(str + next, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d%n", + &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3], + &tmp_int[4], &tmp_int[5], &tmp_int[6], + &tmp_int[7], &tmp_int[8], &tmp_int[9], &tmp_int[10], &tmp_int[10], &len) == 12) { + // do nothing, it's ok + } else if (sscanf(str + next, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d%n", + &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3], + &tmp_int[4], &tmp_int[5], &tmp_int[6], + &tmp_int[7], &tmp_int[8], &tmp_int[9], &tmp_int[10], &len) == 11) { + } else // invalid structure + return -4; + p->inventory[i].id = tmp_int[0]; + p->inventory[i].nameid = tmp_int[1]; + p->inventory[i].amount = tmp_int[2]; + p->inventory[i].equip = tmp_int[3]; + p->inventory[i].identify = tmp_int[4]; + p->inventory[i].refine = tmp_int[5]; + p->inventory[i].attribute = tmp_int[6]; + p->inventory[i].card[0] = tmp_int[7]; + p->inventory[i].card[1] = tmp_int[8]; + p->inventory[i].card[2] = tmp_int[9]; + p->inventory[i].card[3] = tmp_int[10]; + next += len; + if (str[next] == ' ') + next++; + } + + next++; + + for(i = 0; str[next] && str[next] != '\t'; i++) { + if (sscanf(str + next, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d%n", + &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3], + &tmp_int[4], &tmp_int[5], &tmp_int[6], + &tmp_int[7], &tmp_int[8], &tmp_int[9], &tmp_int[10], &tmp_int[10], &len) == 12) { + // do nothing, it's ok + } else if (sscanf(str + next, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d%n", + &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3], + &tmp_int[4], &tmp_int[5], &tmp_int[6], + &tmp_int[7], &tmp_int[8], &tmp_int[9], &tmp_int[10], &len) == 11) { + } else // invalid structure + return -5; + p->cart[i].id = tmp_int[0]; + p->cart[i].nameid = tmp_int[1]; + p->cart[i].amount = tmp_int[2]; + p->cart[i].equip = tmp_int[3]; + p->cart[i].identify = tmp_int[4]; + p->cart[i].refine = tmp_int[5]; + p->cart[i].attribute = tmp_int[6]; + p->cart[i].card[0] = tmp_int[7]; + p->cart[i].card[1] = tmp_int[8]; + p->cart[i].card[2] = tmp_int[9]; + p->cart[i].card[3] = tmp_int[10]; + next += len; + if (str[next] == ' ') + next++; + } + + next++; + + for(i = 0; str[next] && str[next] != '\t'; i++) { + if (sscanf(str + next, "%d,%d%n", &tmp_int[0], &tmp_int[1], &len) != 2) + return -6; + p->skill[tmp_int[0]].id = tmp_int[0]; + p->skill[tmp_int[0]].lv = tmp_int[1]; + next += len; + if (str[next] == ' ') + next++; + } + + next++; + + for(i = 0; str[next] && str[next] != '\t' && str[next] != '\n' && str[next] != '\r'; i++) { // global_regŽÀ‘•ˆÈ‘O‚Ìathena.txtŒÝŠ·‚Ì‚½‚߈ꉞ'\n'ƒ`ƒFƒbƒN + if (sscanf(str + next, "%[^,],%s%n", reg->reg[i].str, reg->reg[i].value, &len) != 2) { + // because some scripts are not correct, the str can be "". So, we must check that. + // If it's, we must not refuse the character, but just this REG value. + // Character line will have something like: nov_2nd_cos,9 ,9 nov_1_2_cos_c,1 (here, ,9 is not good) + if (str[next] == ',' && sscanf(str + next, ",%s%n", reg->reg[i].value, &len) == 1) + i--; + else + return -7; + } + next += len; + if (str[next] == ' ') + next++; + } + reg->reg_num = i; + + return 1; +} +/* Because of the friend database update, it is no longer possible to convert friends. +//Note: Keep updated with the same function found in src/char/char.c [Skotlex] +int parse_friend_txt(struct mmo_charstatus *p) +{ + char line[1024]; + int i,cid=0,temp[20]; + FILE *fp; + + // Open the file and look for the ID + fp = fopen(friends_txt, "r"); + + if(fp == NULL) + return 1; + + + while(fgets(line, sizeof(line)-1, fp)) { + + if(line[0] == '/' && line[1] == '/') + continue; + //Character names must not exceed the 23+\0 limit. [Skotlex] + sscanf(line, "%d,%d,%23[^,],%d,%23[^,],%d,%23[^,],%d,%23[^,],%d,%23[^,],%d,%23[^,],%d,%23[^,],%d,%23[^,],%d,%23[^,],%d,%23[^,],%d,%23[^,],%d,%23[^,],%d,%23[^,],%d,%23[^,],%d,%23[^,],%d,%23[^,],%d,%23[^,],%d,%23[^,],%d,%23[^,],%d,%23s",&cid, + &temp[0],p->friends[0].name, + &temp[1],p->friends[1].name, + &temp[2],p->friends[2].name, + &temp[3],p->friends[3].name, + &temp[4],p->friends[4].name, + &temp[5],p->friends[5].name, + &temp[6],p->friends[6].name, + &temp[7],p->friends[7].name, + &temp[8],p->friends[8].name, + &temp[9],p->friends[9].name, + &temp[10],p->friends[10].name, + &temp[11],p->friends[11].name, + &temp[12],p->friends[12].name, + &temp[13],p->friends[13].name, + &temp[14],p->friends[14].name, + &temp[15],p->friends[15].name, + &temp[16],p->friends[16].name, + &temp[17],p->friends[17].name, + &temp[18],p->friends[18].name, + &temp[19],p->friends[19].name); + if (cid == p->char_id) + break; + } + + // No register of friends list + if (cid == 0) { + fclose(fp); + return 0; + } + + // Fill in the list + + for (i=0; i<20; i++) + p->friends[i].char_id = temp[i]; + + fclose(fp); + return 0; +} +*/ + +// Note: Remember to keep this function updated with the one in src/char_sql/char.c [Skotlex] +// Unneded code was left commented for easier merging of changes. +// Function by [Ilpalazzo-sama] + +int memitemdata_to_sql(struct itemtmp mapitem[], int count, int char_id, int tableswitch) +{ + int i; //, flag, id; + char *tablename; + char selectoption[16]; + + switch (tableswitch) { + case TABLE_INVENTORY: + tablename = inventory_db; // no need for sprintf here as *_db are char*. + sprintf(selectoption,"char_id"); + break; + case TABLE_CART: + tablename = cart_db; + sprintf(selectoption,"char_id"); + break; + case TABLE_STORAGE: + tablename = storage_db; + sprintf(selectoption,"account_id"); + break; + case TABLE_GUILD_STORAGE: + tablename = guild_storage_db; + sprintf(selectoption,"guild_id"); + break; + default: + ShowError("Invalid table name!\n"); + return 1; + } + + //=======================================mysql database data > memory=============================================== +/* + sprintf(tmp_sql, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `card0`, `card1`, `card2`, `card3` " + "FROM `%s` WHERE `%s`='%d'", tablename, selectoption, char_id); + + if (mysql_query(&mysql_handle, tmp_sql)) { + ShowSQL("DB server Error (select `%s` to Memory)- %s\n",tablename ,mysql_error(&mysql_handle)); + return 1; + } + sql_res = mysql_store_result(&mysql_handle); + if (sql_res) { + while ((sql_row = mysql_fetch_row(sql_res))) { + flag = 0; + id = atoi(sql_row[0]); + for(i = 0; i < count; i++) { + if(mapitem[i].flag == 1) + continue; + if(mapitem[i].nameid == atoi(sql_row[1])) { // produced items fixup + if((mapitem[i].equip == atoi(sql_row[3])) && + (mapitem[i].identify == atoi(sql_row[4])) && + (mapitem[i].amount == atoi(sql_row[2])) && + (mapitem[i].refine == atoi(sql_row[5])) && + (mapitem[i].attribute == atoi(sql_row[6])) && + (mapitem[i].card[0] == atoi(sql_row[7])) && + (mapitem[i].card[1] == atoi(sql_row[8])) && + (mapitem[i].card[2] == atoi(sql_row[9])) && + (mapitem[i].card[3] == atoi(sql_row[10]))) { + //printf("the same item : %d , equip : %d , i : %d , flag : %d\n", mapitem.equip[i].nameid,mapitem.equip[i].equip , i, mapitem.equip[i].flag); //DEBUG-STRING + } else { +//==============================================Memory data > SQL =============================== + if(itemdb_isequip(mapitem[i].nameid) || (mapitem[i].card[0] == atoi(sql_row[7]))) { + sprintf(tmp_sql,"UPDATE `%s` SET `equip`='%d', `identify`='%d', `refine`='%d'," + "`attribute`='%d', `card0`='%d', `card1`='%d', `card2`='%d', `card3`='%d', `amount`='%d' WHERE `id`='%d' LIMIT 1", + tablename, mapitem[i].equip, mapitem[i].identify, mapitem[i].refine, mapitem[i].attribute, mapitem[i].card[0], + mapitem[i].card[1], mapitem[i].card[2], mapitem[i].card[3], mapitem[i].amount, id); + if(mysql_query(&mysql_handle, tmp_sql)) + ShowSQL("DB server Error (UPdate `equ %s`)- %s\n", tablename, mysql_error(&mysql_handle)); + } + //printf("not the same item : %d ; i : %d ; flag : %d\n", mapitem.equip[i].nameid, i, mapitem.equip[i].flag); + } + flag = mapitem[i].flag = 1; + break; + } + } + if(!flag) { + sprintf(tmp_sql,"DELETE from `%s` where `id`='%d'", tablename, id); + if(mysql_query(&mysql_handle, tmp_sql)) + ShowSQL("DB server Error (DELETE `equ %s`)- %s\n", tablename, mysql_error(&mysql_handle)); + } + } + mysql_free_result(sql_res); + } +*/ + for(i = 0; i < count; i++) { + if(mapitem[i].nameid) { + sprintf(tmp_sql,"INSERT INTO `%s`(`%s`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `card0`, `card1`, `card2`, `card3` )" + " VALUES ( '%d','%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d' )", + tablename, selectoption, char_id, mapitem[i].nameid, mapitem[i].amount, mapitem[i].equip, mapitem[i].identify, mapitem[i].refine, + mapitem[i].attribute, mapitem[i].card[0], mapitem[i].card[1], mapitem[i].card[2], mapitem[i].card[3]); + if(mysql_query(&mysql_handle, tmp_sql)) + ShowSQL("DB server Error (INSERT `equ %s`)- %s\n", tablename, mysql_error(&mysql_handle)); + } + } + return 0; +} + +//Note: Remember to keep this function updated with src/char_sql/char.c [Skotlex] +//Unncessary code is left commented for easy merging. +int mmo_char_tosql(int char_id, struct mmo_charstatus *p){ + int i=0 ,party_exist=0;//,guild_exist; + int count = 0; + int diff = 1; + char *tmp_ptr; //Building a single query should be more efficient than running + //multiple queries for each thing about to be saved, right? [Skotlex] + char save_status[100]; //For displaying save information. [Skotlex] +// struct mmo_charstatus *cp; + struct itemtmp mapitem[MAX_GUILD_STORAGE]; + + if (char_id!=p->char_id) return 0; + +/* + cp = (struct mmo_charstatus*)idb_get(char_db_,char_id); + + if (cp == NULL) { + cp = (struct mmo_charstatus *) aMalloc(sizeof(struct mmo_charstatus)); + memset(cp, 0, sizeof(struct mmo_charstatus)); + idb_put(char_db_, char_id,cp); + } +*/ + ShowInfo("Saving char "CL_WHITE"%d"CL_RESET" (%s)...\n",char_id,p->name); + memset(save_status, 0, sizeof(save_status)); + + count = 0; +// diff = 0; + //map inventory data + for(i=0;iinventory[i], &cp->inventory[i])) +// diff = 1; + if(p->inventory[i].nameid>0){ + mapitem[count].flag=0; + mapitem[count].id = p->inventory[i].id; + mapitem[count].nameid=p->inventory[i].nameid; + mapitem[count].amount = p->inventory[i].amount; + mapitem[count].equip = p->inventory[i].equip; + mapitem[count].identify = p->inventory[i].identify; + mapitem[count].refine = p->inventory[i].refine; + mapitem[count].attribute = p->inventory[i].attribute; + mapitem[count].card[0] = p->inventory[i].card[0]; + mapitem[count].card[1] = p->inventory[i].card[1]; + mapitem[count].card[2] = p->inventory[i].card[2]; + mapitem[count].card[3] = p->inventory[i].card[3]; + count++; + } + } + //printf("- Save item data to MySQL!\n"); + if (diff) + if (!memitemdata_to_sql(mapitem, count, p->char_id,TABLE_INVENTORY)) + strcat(save_status, " inventory"); + + count = 0; + +// diff = 0; + //map cart data + for(i=0;icart[i], &cp->cart[i])) +// diff = 1; + if(p->cart[i].nameid>0){ + mapitem[count].flag=0; + mapitem[count].id = p->cart[i].id; + mapitem[count].nameid=p->cart[i].nameid; + mapitem[count].amount = p->cart[i].amount; + mapitem[count].equip = p->cart[i].equip; + mapitem[count].identify = p->cart[i].identify; + mapitem[count].refine = p->cart[i].refine; + mapitem[count].attribute = p->cart[i].attribute; + mapitem[count].card[0] = p->cart[i].card[0]; + mapitem[count].card[1] = p->cart[i].card[1]; + mapitem[count].card[2] = p->cart[i].card[2]; + mapitem[count].card[3] = p->cart[i].card[3]; + count++; + } + } + + if (diff) + if (!memitemdata_to_sql(mapitem, count, p->char_id,TABLE_CART)) + strcat(save_status, " cart"); +/* + if ((p->base_exp != cp->base_exp) || (p->class_ != cp->class_) || + (p->base_level != cp->base_level) || (p->job_level != cp->job_level) || + (p->job_exp != cp->job_exp) || (p->zeny != cp->zeny) || + (p->last_point.x != cp->last_point.x) || (p->last_point.y != cp->last_point.y) || + (p->max_hp != cp->max_hp) || (p->hp != cp->hp) || + (p->max_sp != cp->max_sp) || (p->sp != cp->sp) || + (p->status_point != cp->status_point) || (p->skill_point != cp->skill_point) || + (p->str != cp->str) || (p->agi != cp->agi) || (p->vit != cp->vit) || + (p->int_ != cp->int_) || (p->dex != cp->dex) || (p->luk != cp->luk) || + (p->option != cp->option) || (p->karma != cp->karma) || (p->manner != cp->manner) || + (p->party_id != cp->party_id) || (p->guild_id != cp->guild_id) || + (p->pet_id != cp->pet_id) || (p->hair != cp->hair) || (p->hair_color != cp->hair_color) || + (p->clothes_color != cp->clothes_color) || (p->weapon != cp->weapon) || + (p->shield != cp->shield) || (p->head_top != cp->head_top) || + (p->head_mid != cp->head_mid) || (p->head_bottom != cp->head_bottom) || + (p->partner_id != cp->partner_id) || (p->father != cp->father) || + (p->mother != cp->mother) || (p->child != cp->child) || (p->fame != cp->fame)) + { //Save status + + //Check for party + party_exist=1; + sprintf(tmp_sql, "SELECT count(*) FROM `%s` WHERE `party_id` = '%d'",party_db, p->party_id); // TBR + if (mysql_query(&mysql_handle, tmp_sql)) { + ShowSQL("DB Error - %s\n", mysql_error(&mysql_handle)); + } else { //In case of failure, don't touch the data. [Skotlex + sql_res = mysql_store_result(&mysql_handle); + sql_row = mysql_fetch_row(sql_res); + if (sql_row) + party_exist = atoi(sql_row[0]); + mysql_free_result(sql_res); + } + + //check guild_exist + guild_exist=1; + sprintf(tmp_sql, "SELECT count(*) FROM `%s` WHERE `guild_id` = '%d'",guild_db, p->guild_id); // TBR + if (mysql_query(&mysql_handle, tmp_sql)) { + ShowSQL("DB Error (select guild): %s\n", mysql_error(&mysql_handle)); + } else { //If we fail to confirm, don't touch the data. + sql_res = mysql_store_result(&mysql_handle); + sql_row = mysql_fetch_row(sql_res); + if (sql_row) + guild_exist = atoi(sql_row[0]); + mysql_free_result(sql_res); + } + if (guild_exist==0) p->guild_id=0; + */ + if (party_exist==0) p->party_id=0; //Parties are not converted. [Skotlex] + + //sql query + //`char`( `char_id`,`account_id`,`char_num`,`name`,`class`,`base_level`,`job_level`,`base_exp`,`job_exp`,`zeny`, //9 + //`str`,`agi`,`vit`,`int`,`dex`,`luk`, //15 + //`max_hp`,`hp`,`max_sp`,`sp`,`status_point`,`skill_point`, //21 + //`option`,`karma`,`manner`,`party_id`,`guild_id`,`pet_id`, //27 + //`hair`,`hair_color`,`clothes_color`,`weapon`,`shield`,`head_top`,`head_mid`,`head_bottom`, //35 + //`last_map`,`last_x`,`last_y`,`save_map`,`save_x`,`save_y`) + + //Rather than converting the update to a insert, let's insert a blank char. [Skotlex] + sprintf(tmp_sql, "INSERT INTO `%s` (`char_id`, `account_id`, `name`, `char_num`) VALUES ('%d','%d','%s', '%d')", char_db, char_id, p->account_id, p->name, p->char_num); + if(mysql_query(&mysql_handle, tmp_sql)) + ShowSQL("DB Error (insert char): %s\n", mysql_error(&mysql_handle)); + //If there is an error, we could assume it already exists, so just update anyway. + + sprintf(tmp_sql ,"UPDATE `%s` SET `class`='%d', `base_level`='%d', `job_level`='%d'," + "`base_exp`='%d', `job_exp`='%d', `zeny`='%d'," + "`max_hp`='%d',`hp`='%d',`max_sp`='%d',`sp`='%d',`status_point`='%d',`skill_point`='%d'," + "`str`='%d',`agi`='%d',`vit`='%d',`int`='%d',`dex`='%d',`luk`='%d'," + "`option`='%d',`karma`='%d',`manner`='%d',`party_id`='%d',`guild_id`='%d',`pet_id`='%d'," + "`hair`='%d',`hair_color`='%d',`clothes_color`='%d',`weapon`='%d',`shield`='%d',`head_top`='%d',`head_mid`='%d',`head_bottom`='%d'," + "`last_map`='%s',`last_x`='%d',`last_y`='%d',`save_map`='%s',`save_x`='%d',`save_y`='%d'," + "`partner_id`='%d', `father`='%d', `mother`='%d', `child`='%d', `fame`='%d'" + "WHERE `account_id`='%d' AND `char_id` = '%d'", + char_db, p->class_, p->base_level, p->job_level, + p->base_exp, p->job_exp, p->zeny, + p->max_hp, p->hp, p->max_sp, p->sp, p->status_point, p->skill_point, + p->str, p->agi, p->vit, p->int_, p->dex, p->luk, + p->option, p->karma, p->manner, p->party_id, p->guild_id, p->pet_id, + p->hair, p->hair_color, p->clothes_color, + p->weapon, p->shield, p->head_top, p->head_mid, p->head_bottom, + mapindex_id2name(p->last_point.map), p->last_point.x, p->last_point.y, + mapindex_id2name(p->save_point.map), p->save_point.x, p->save_point.y, p->partner_id, p->father, p->mother, + p->child, p->fame, p->account_id, p->char_id + ); + + if(mysql_query(&mysql_handle, tmp_sql)) + ShowSQL("DB Error (update char): %s\n", mysql_error(&mysql_handle)); + else + strcat(save_status, " status"); +/* + } + diff = 0; + + for(i=0;imemo_point[i].map,cp->memo_point[i].map) == 0) && (p->memo_point[i].x == cp->memo_point[i].x) && (p->memo_point[i].y == cp->memo_point[i].y)) + continue; + diff = 1; + break; + } +*/ + if (diff) + { //Save memo + //`memo` (`memo_id`,`char_id`,`map`,`x`,`y`) + sprintf(tmp_sql,"DELETE FROM `%s` WHERE `char_id`='%d'",memo_db, p->char_id); + if(mysql_query(&mysql_handle, tmp_sql)) + ShowSQL("DB Error (delete memo): %s\n", mysql_error(&mysql_handle)); + + //insert here. + tmp_ptr = tmp_sql; + tmp_ptr += sprintf(tmp_ptr, "INSERT INTO `%s`(`char_id`,`map`,`x`,`y`) VALUES ", memo_db); + count = 0; + for(i=0;imemo_point[i].map){ + tmp_ptr += sprintf(tmp_ptr,"('%d', '%s', '%d', '%d'),", + char_id, mapindex_id2name(p->memo_point[i].map), p->memo_point[i].x, p->memo_point[i].y); + count++; + } + } + if (count) + { //Dangerous? Only if none of the above sprintf worked. [Skotlex] + tmp_ptr[-1] = '\0'; //Remove the trailing comma. + if(mysql_query(&mysql_handle, tmp_sql)) + ShowSQL("DB Error (insert memo): %s\n", mysql_error(&mysql_handle)); + else + strcat(save_status, " memo"); + } else //Memo Points cleared (how is this possible?). + strcat(save_status, " memo"); + } +/* + diff = 0; + for(i=0;iskill[i].lv != 0) && (p->skill[i].id == 0)) + p->skill[i].id = i; // Fix skill tree + + if((p->skill[i].id != cp->skill[i].id) || (p->skill[i].lv != cp->skill[i].lv) || + (p->skill[i].flag != cp->skill[i].flag)) + { + diff = 1; + break; + } + } +*/ + if (diff) + { //Save skills + + //`skill` (`char_id`, `id`, `lv`) + sprintf(tmp_sql,"DELETE FROM `%s` WHERE `char_id`='%d'",skill_db, p->char_id); + if(mysql_query(&mysql_handle, tmp_sql)) + ShowSQL("DB Error (delete skill): %s\n", mysql_error(&mysql_handle)); + + tmp_ptr = tmp_sql; + tmp_ptr += sprintf(tmp_ptr,"INSERT INTO `%s`(`char_id`,`id`,`lv`) VALUES ", skill_db); + count = 0; + //insert here. + for(i=0;iskill[i].id && p->skill[i].flag!=1) + { + tmp_ptr += sprintf(tmp_ptr,"('%d','%d','%d'),", + char_id, p->skill[i].id, (p->skill[i].flag==0)?p->skill[i].lv:p->skill[i].flag-2); + count++; + } + } + + if (count) + { + tmp_ptr[-1] = '\0'; //Remove trailing comma. + if(mysql_query(&mysql_handle, tmp_sql)) + ShowSQL("DB Error (insert skill): %s\n", mysql_error(&mysql_handle)); + else + strcat(save_status, " skills"); + } else //Skills removed (reset?) + strcat(save_status, " skills"); + } +/* + diff = 0; + for(i=0;iglobal_reg_num;i++) { + if ((p->global_reg[i].str == NULL) && (cp->global_reg[i].str == NULL)) + continue; + if (((p->global_reg[i].str == NULL) != (cp->global_reg[i].str == NULL)) || + (p->global_reg[i].value != cp->global_reg[i].value) || + strcmp(p->global_reg[i].str, cp->global_reg[i].str) != 0 + ) { + diff = 1; + break; + } + } +*/ +/* + if (diff) + { //Save global registry. + //`global_reg_value` (`char_id`, `str`, `value`) + + sprintf(tmp_sql,"DELETE FROM `%s` WHERE `type`=3 AND `char_id`='%d'",reg_db, p->char_id); + if (mysql_query(&mysql_handle, tmp_sql)) + ShowSQL("DB Error (delete global_reg_value): %s\n", mysql_error(&mysql_handle)); + + //insert here. + tmp_ptr = tmp_sql; + tmp_ptr += sprintf(tmp_ptr,"INSERT INTO `%s` (`char_id`, `str`, `value`) VALUES", reg_db); + count = 0; + for(i=0;iglobal_reg_num;i++) + { + if (p->global_reg[i].str && p->global_reg[i].value !=0) + { + tmp_ptr += sprintf(tmp_ptr,"('%d','%s','%s'),", + char_id, jstrescapecpy(temp_str,p->global_reg[i].str), p->global_reg[i].value); + if (++count%100 == 0) + { //Save every X registers to avoid overflowing tmp_sql [Skotlex] + tmp_ptr[-1] = '\0'; + if(mysql_query(&mysql_handle, tmp_sql)) + ShowSQL("DB Error (insert global_reg_value sub): %s\n", mysql_error(&mysql_handle)); + else + strcat(save_status, " global_reg"); + + tmp_ptr = tmp_sql; + tmp_ptr += sprintf(tmp_ptr,"INSERT INTO `%s` (`char_id`, `str`, `value`) VALUES", reg_db); + count = 0; + } + } + } + + if (count) + { + tmp_ptr[-1] = '\0'; + if(mysql_query(&mysql_handle, tmp_sql)) + ShowSQL("DB Error (insert global_reg_value): %s\n", mysql_error(&mysql_handle)); + else + strcat(save_status, " global_reg"); + } else //Values cleared. + strcat(save_status, " global_reg"); + } +*/ +/* + diff = 0; + for(i = 0; i < MAX_FRIENDS; i++){ + if(p->friend_id[i] != cp->friend_id[i]){ + diff = 1; + break; + } + } + if(diff) + { //Save friends + sprintf(tmp_sql, "DELETE FROM `%s` WHERE `char_id`='%d'", friend_db, char_id); + if(mysql_query(&mysql_handle, tmp_sql)){ + ShowSQL("DB Error (delete friend): %s\n", mysql_error(&mysql_handle)); + } + + tmp_ptr = tmp_sql; + tmp_ptr += sprintf(tmp_ptr, "INSERT INTO `%s` (`char_id`, `friend_id`) VALUES ", friend_db); + count = 0; + for(i = 0; i < MAX_FRIENDS; i++){ + if(p->friend_id[i] > 0) + { + tmp_ptr += sprintf(tmp_ptr, "('%d', '%d'),", char_id, p->friend_id[i]); + count++; + } + } + if (count) + { + tmp_ptr[-1] = '\0'; //Remove the last comma. [Skotlex] + if(mysql_query(&mysql_handle, tmp_sql)) + ShowSQL("DB Error (insert friend): %s\n", mysql_error(&mysql_handle)); + else + strcat(save_status, " friends"); + } else //Friend list cleared. + strcat(save_status, " friends"); + + } +*/ + ShowInfo("Saved char %d:%s.\n", char_id, save_status); +// memcpy(cp, p, sizeof(struct mmo_charstatus)); + + return 0; +} + +//-------------------------------------------------------- +// Save registry to sql +int inter_accreg_tosql(int account_id, int char_id, struct accreg *reg, int type){ + + int j; + char temp_str[64]; //Needs be twice the source to ensure it fits [Skotlex] + char temp_str2[512]; + if (account_id<=0) return 0; + + switch (type) { + case 3: //Char Reg + //`global_reg_value` (`type`, `account_id`, `char_id`, `str`, `value`) + sprintf(tmp_sql,"DELETE FROM `%s` WHERE `type`=3 AND `char_id`='%d'",reg_db, char_id); + break; + case 2: //Account Reg + //`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); + break; + case 1: //Account2 Reg + ShowError("inter_accreg_tosql: Char server shouldn't handle type 1 registry values (##). That is the login server's work!\n"); + return 0; + default: + ShowError("inter_accreg_tosql: Invalid type %d\n", type); + return 0; + + } + if(mysql_query(&mysql_handle, tmp_sql) ) { + ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); + ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + } + + if (reg->reg_num<=0) return 0; + + for(j=0;jreg_num;j++){ + if(reg->reg[j].str != NULL){ + sprintf(tmp_sql,"INSERT INTO `%s` (`type`, `account_id`, `char_id`, `str`, `value`) VALUES ('%d','%d','%d','%s','%s')", + reg_db, type, type!=3?account_id:0, type==3?char_id:0, + jstrescapecpy(temp_str,reg->reg[j].str), jstrescapecpy(temp_str2,reg->reg[j].value)); + if(mysql_query(&mysql_handle, tmp_sql) ) { + ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); + ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + } + } + } + return 1; +} +//Note: Keep this function updated with the one in src/char/int_storage.c [Skotlex] +int storage_fromstr(char *str,struct storage *p) +{ + int tmp_int[256]; + int set,next,len,i; + + set=sscanf(str,"%d,%d%n",&tmp_int[0],&tmp_int[1],&next); + p->storage_amount=tmp_int[1]; + + if(set!=2) + return 1; + if(str[next]=='\n' || str[next]=='\r') + return 0; + next++; + for(i=0;str[next] && str[next]!='\t';i++){ + if(sscanf(str + next, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d%n", + &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3], + &tmp_int[4], &tmp_int[5], &tmp_int[6], + &tmp_int[7], &tmp_int[8], &tmp_int[9], &tmp_int[10], &tmp_int[10], &len) == 12) { + p->storage_[i].id = tmp_int[0]; + p->storage_[i].nameid = tmp_int[1]; + p->storage_[i].amount = tmp_int[2]; + p->storage_[i].equip = tmp_int[3]; + p->storage_[i].identify = tmp_int[4]; + p->storage_[i].refine = tmp_int[5]; + p->storage_[i].attribute = tmp_int[6]; + p->storage_[i].card[0] = tmp_int[7]; + p->storage_[i].card[1] = tmp_int[8]; + p->storage_[i].card[2] = tmp_int[9]; + p->storage_[i].card[3] = tmp_int[10]; + next += len; + if (str[next] == ' ') + next++; + } + + else if(sscanf(str + next, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d%n", + &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3], + &tmp_int[4], &tmp_int[5], &tmp_int[6], + &tmp_int[7], &tmp_int[8], &tmp_int[9], &tmp_int[10], &len) == 11) { + p->storage_[i].id = tmp_int[0]; + p->storage_[i].nameid = tmp_int[1]; + p->storage_[i].amount = tmp_int[2]; + p->storage_[i].equip = tmp_int[3]; + p->storage_[i].identify = tmp_int[4]; + p->storage_[i].refine = tmp_int[5]; + p->storage_[i].attribute = tmp_int[6]; + p->storage_[i].card[0] = tmp_int[7]; + p->storage_[i].card[1] = tmp_int[8]; + p->storage_[i].card[2] = tmp_int[9]; + p->storage_[i].card[3] = tmp_int[10]; + next += len; + if (str[next] == ' ') + next++; + } + + else return 1; + } + return 0; +} + +//Note: Keep this function synched with the one in src/char_sql/int_storage.c +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;istorage_[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; +} + +//Note: Keep updated with the function in src/char/int_pet.c [Skotlex] +int inter_pet_fromstr(char *str,struct s_pet *p) +{ + int s; + int tmp_int[16]; + char tmp_str[256]; + + memset(p,0,sizeof(struct s_pet)); + +// printf("sscanf pet main info\n"); + s=sscanf(str,"%d,%d,%[^\t]\t%d,%d,%d,%d,%d,%d,%d,%d,%d",&tmp_int[0],&tmp_int[1],tmp_str,&tmp_int[2], + &tmp_int[3],&tmp_int[4],&tmp_int[5],&tmp_int[6],&tmp_int[7],&tmp_int[8],&tmp_int[9],&tmp_int[10]); + + if(s!=12) + return 1; + + p->pet_id = tmp_int[0]; + p->class_ = tmp_int[1]; + memcpy(p->name,tmp_str,NAME_LENGTH-1); + p->account_id = tmp_int[2]; + p->char_id = tmp_int[3]; + p->level = tmp_int[4]; + p->egg_id = tmp_int[5]; + p->equip = tmp_int[6]; + p->intimate = tmp_int[7]; + p->hungry = tmp_int[8]; + p->rename_flag = tmp_int[9]; + p->incuvate = tmp_int[10]; + + 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; + + return 0; +} + +//Note: Keep updated with the function in src/char_sql/int_pet.c [Skotlex] +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[NAME_LENGTH*2]; + + ShowInfo("Saving 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) ) { + ShowSQL("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) ) { + ShowSQL("DB server Error (inset/update `pet`)- %s\n", mysql_error(&mysql_handle) ); + } + + ShowInfo("Pet saved (%d). \n", pet_id); + return 0; +} + + +int mmo_char_init(void){ + char line[65536]; + struct storage *storage_ = NULL; + struct s_pet *p; + int ret; + int i=0,set,tmp_int[2], c= 0; + char input; + FILE *fp; + + mysql_init(&mysql_handle); + ShowInfo("Connect DB server.... (inter server)\n"); + if(!mysql_real_connect(&mysql_handle, db_server_ip, db_server_id, db_server_pw, + db_server_logindb ,db_server_port, (char *)NULL, 0)) { + //pointer check + ShowFatalError("%s\n",mysql_error(&mysql_handle)); + exit(1); + } + else { + ShowStatus ("connect success! (inter server)\n"); + } + + ShowWarning("Make sure you backup your databases before continuing!\n"); + printf("\n"); + ShowNotice("Do you wish to convert your Character Database to SQL? (y/n) : "); + input=getchar(); + if(input == 'y' || input == 'Y'){ + ShowStatus("Converting Character Database...\n"); + fp=fopen("save/athena.txt","r"); + char_dat = (struct character_data*)malloc(sizeof(struct character_data)*256); + char_max=256; + if(fp==NULL) + return 0; + while(fgets(line, 65535, fp)){ + if(char_num>=char_max){ + char_max+=256; + char_dat = (struct character_data*)realloc(char_dat, sizeof(char_dat[0]) *char_max); + } + memset(&char_dat[char_num], 0, sizeof(char_dat[0])); + ret=mmo_char_fromstr(line, &char_dat[char_num].status, &char_dat[char_num].global); + if(ret){ + mmo_char_tosql(char_dat[char_num].status.char_id , &char_dat[char_num].status); + inter_accreg_tosql(char_dat[char_num].status.account_id, char_dat[char_num].status.char_id, &char_dat[char_num].global, 3); //Type 3: Character regs + if(char_dat[char_num].status.char_id>=char_id_count) + char_id_count=char_dat[char_num].status.char_id+1; + char_num++; + } + } + ShowStatus("char data convert end\n"); + fclose(fp); + } + + while(getchar() != '\n'); + printf("\n"); + ShowNotice("Do you wish to convert your Storage Database to SQL? (y/n) : "); + input=getchar(); + if(input == 'y' || input == 'Y') { + printf("\n"); + ShowStatus("Converting Storage Database...\n"); + fp=fopen(storage_txt,"r"); + if(fp==NULL){ + ShowError("cant't read : %s\n",storage_txt); + return 0; + } + + while(fgets(line,65535,fp)){ + set=sscanf(line,"%d,%d",&tmp_int[0],&tmp_int[1]); + if(set==2) { + if(i==0){ + storage_ = (struct storage*)malloc(sizeof(struct storage)); + }else{ + storage_ = (struct storage*)realloc(storage_,sizeof(struct storage)*(i+1)); + } + memset(&storage_[i],0,sizeof(struct storage)); + storage_[i].account_id=tmp_int[0]; + storage_fromstr(line,&storage_[i]); + storage_tosql(tmp_int[0],&storage_[i]); //to sql. (dump) + i++; + } + } + fclose(fp); + } + + while(getchar() != '\n'); + printf("\n"); + ShowNotice("Do you wish to convert your Pet Database to SQL? (y/n) : "); + input=getchar(); + if(input == 'y' || input == 'Y') { + printf("\n"); + ShowStatus("Converting Pet Database...\n"); + if( (fp=fopen(pet_txt,"r")) ==NULL ) + return 1; + p = (struct s_pet*)malloc(sizeof(struct s_pet)); + while(fgets(line, sizeof(line), fp)){ + if(p==NULL){ + ShowFatalError("int_pet: out of memory!\n"); + exit(0); + } + if(inter_pet_fromstr(line, p)==0 && p->pet_id>0){ + //pet dump + inter_pet_tosql(p->pet_id,p); + }else{ + ShowError("int_pet: broken data [%s] line %d\n", pet_txt, c); + } + c++; + } + fclose(fp); + } + return 0; +} + +int inter_config_read(const char *cfgName) { + int i; + char line[1024], w1[1024], w2[1024]; + FILE *fp; + + ShowStatus("Start reading interserver configuration: %s\n",cfgName); + + fp=fopen(cfgName,"r"); + if(fp==NULL){ + ShowError("File not found: %s\n", cfgName); + return 1; + } + while(fgets(line, 1020, fp)){ + i=sscanf(line,"%[^:]:%s", w1, w2); + if(i!=2) + continue; + if(strcmpi(w1,"storage_txt")==0){ + ShowInfo ("set storage_txt : %s\n",w2); + strncpy(storage_txt, w2, sizeof(storage_txt)); + } else if(strcmpi(w1,"pet_txt")==0){ + ShowInfo ("set pet_txt : %s\n",w2); + strncpy(pet_txt, w2, sizeof(pet_txt)); + } + //add for DB connection + else if(strcmpi(w1,"db_server_ip")==0){ + strcpy(db_server_ip, w2); + ShowInfo ("set db_server_ip : %s\n",w2); + } + else if(strcmpi(w1,"db_server_port")==0){ + db_server_port=atoi(w2); + ShowInfo ("set db_server_port : %s\n",w2); + } + else if(strcmpi(w1,"db_server_id")==0){ + strcpy(db_server_id, w2); + ShowInfo ("set db_server_id : %s\n",w2); + } + else if(strcmpi(w1,"db_server_pw")==0){ + strcpy(db_server_pw, w2); + ShowInfo ("set db_server_pw : %s\n",w2); + } + else if(strcmpi(w1,"db_server_logindb")==0){ + strcpy(db_server_logindb, w2); + ShowInfo ("set db_server_logindb : %s\n",w2); + } + else if(strcmpi(w1,"char_db")==0){ + strcpy(char_db, w2); + ShowInfo ("set char_db : %s\n",w2); + } + else if(strcmpi(w1,"cart_db")==0){ + strcpy(cart_db, w2); + ShowInfo ("set cart_db : %s\n",w2); + } + else if(strcmpi(w1,"inventory_db")==0){ + strcpy(inventory_db, w2); + ShowInfo ("set inventory_db : %s\n",w2); + } + else if(strcmpi(w1,"storage_db")==0){ + strcpy(storage_db, w2); + ShowInfo ("set storage_db : %s\n",w2); + } + else if(strcmpi(w1,"reg_db")==0){ + strcpy(reg_db, w2); + ShowInfo ("set reg_db : %s\n",w2); + } + else if(strcmpi(w1,"skill_db")==0){ + strcpy(skill_db, w2); + ShowInfo ("set skill_db : %s\n",w2); + } + else if(strcmpi(w1,"memo_db")==0){ + strcpy(memo_db, w2); + ShowInfo ("set memo_db : %s\n",w2); + } + else if(strcmpi(w1,"pet_db")==0){ + strcpy(pet_db, w2); + ShowInfo ("set pet_db : %s\n",w2); + } + else if(strcmpi(w1,"friend_db")==0){ + strcpy(friend_db, w2); + ShowInfo ("set friend_db : %s\n",w2); + //support the import command, just like any other config + }else if(strcmpi(w1,"import")==0){ + inter_config_read(w2); + } + } + fclose(fp); + + ShowStatus("Done reading %s.\n", cfgName); + + return 0; +} + +int char_config_read(const char *cfgName) { + int i; + char line[1024], w1[1024], w2[1024]; + FILE *fp; + + ShowStatus ("Start reading char-server configuration: %s\n",cfgName); + + fp=fopen(cfgName,"r"); + if(fp==NULL){ + ShowError("File not found: %s\n", cfgName); + return 1; + } + + while(fgets(line, 1020, fp)){ + if(line[0] == '/' && line[1] == '/') + continue; + + i=sscanf(line,"%[^:]:%s", w1, w2); + if(i!=2) + continue; + if(strcmpi(w1,"char_txt")==0){ + ShowInfo ("set char_txt : %s\n",w2); + strcpy(char_txt, w2); + } else + if(strcmpi(w1,"friends_txt")==0){ + ShowInfo ("set friends_txt : %s\n",w2); + strcpy(friends_txt, w2); + } + } + fclose(fp); + ShowStatus("Done reading %s.\n", cfgName); + + return 0; +} + +int do_init(int argc, char **argv){ + + char_config_read((argc>1)?argv[1]:CHAR_CONF_NAME); + inter_config_read((argc>2)?argv[2]:INTER_CONF_NAME); + mapindex_init(); + + mmo_char_init(); + ShowStatus("Everything's been converted!\n"); + mapindex_final(); + exit (0); +} + +void do_final () {} diff --git a/src/txt-converter/login-converter.c b/src/txt-converter/login-converter.c new file mode 100644 index 000000000..1c8684e95 --- /dev/null +++ b/src/txt-converter/login-converter.c @@ -0,0 +1,227 @@ +// (c) eAthena Dev Team - Licensed under GNU GPL +// For more information, see LICENCE in the main folder + +#include +#include +#include +#include + +#include "../common/core.h" +#include "../common/db.h" +#include "../common/mmo.h" + +struct auth_dat_ { + int account_id, sex; + char userid[24], pass[24], lastlogin[24]; + int logincount; + int state; // packet 0x006a value + 1 (0: compte OK) + char email[40]; // e-mail (by default: a@a.com) + char error_message[20]; // Message of error code #6 = You are Prohibited to log in until %s (packet 0x006a) + time_t ban_until_time; // # of seconds 1/1/1970 (timestamp): ban time limit of the account (0 = no ban) + time_t connect_until_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited) + char last_ip[16]; // save of last IP of connection + char memo[255]; // a memo field + int account_reg2_num; + struct global_reg account_reg2[ACCOUNT_REG2_NUM]; +} *auth_dat; + +char login_account_id[256]="account_id"; +char login_userid[256]="userid"; +char login_user_pass[256]="user_pass"; +char login_db[256]="login"; + +static struct dbt *gm_account_db; + +int db_server_port = 3306; +char db_server_ip[16] = "127.0.0.1"; +char db_server_id[32] = "ragnarok"; +char db_server_pw[32] = "ragnarok"; +char db_server_logindb[32] = "ragnarok"; + +#define INTER_CONF_NAME "conf/inter_athena.conf" + +int isGM(int account_id) +{ + struct gm_account *p; + p = idb_get(gm_account_db,account_id); + if( p == NULL) + return 0; + return p->level; +} + +int read_gm_account() +{ + char line[8192]; + struct gm_account *p; + FILE *fp; + int c=0; + + gm_account_db = db_alloc(__FILE__,__LINE__,DB_INT,DB_OPT_BASE,sizeof(int)); + + printf("Starting reading gm_account\n"); + + if( (fp=fopen("conf/GM_account.txt","r"))==NULL ) + return 1; + while(fgets(line,sizeof(line),fp)){ + if(line[0] == '/' || line[1] == '/' || line[2] == '/') + continue; + + p = (struct gm_account*)malloc(sizeof(struct gm_account)); + if(p==NULL){ + printf("gm_account: out of memory!\n"); + exit(0); + } + + if(sscanf(line,"%d %d",&p->account_id,&p->level) != 2 || p->level <= 0) { + printf("gm_account: broken data [conf/GM_account.txt] line %d\n",c); + continue; + } + else { + if(p->level > 99) + p->level = 99; + idb_put(gm_account_db,p->account_id,p); + c++; + printf("GM ID: %d Level: %d\n",p->account_id,p->level); + } + } + fclose(fp); + printf("%d ID of gm_accounts read.\n",c); + return 0; +} + +int mmo_auth_init(void) +{ + MYSQL mysql_handle; + char tmpsql[1024]; + MYSQL_RES* sql_res ; + MYSQL_ROW sql_row ; + FILE *fp; + int account_id, logincount, user_level, state, n, i; + char line[2048], userid[2048], pass[2048], lastlogin[2048], sex, email[2048], error_message[2048], last_ip[2048], memo[2048]; + time_t ban_until_time; + time_t connect_until_time; + char t_uid[256]; + + mysql_init(&mysql_handle); + if(!mysql_real_connect(&mysql_handle, db_server_ip, db_server_id, db_server_pw, + db_server_logindb ,db_server_port, (char *)NULL, 0)) { + //pointer check + printf("%s\n",mysql_error(&mysql_handle)); + exit(1); + } + else { + printf ("Connect: Success!\n"); + } + printf ("Convert start...\n"); + + + fp=fopen("save/account.txt","r"); + auth_dat = (struct auth_dat_*)malloc(sizeof(auth_dat[0])*256); + if(fp==NULL) + return 0; + while(fgets(line,1023,fp)!=NULL){ + + if(line[0]=='/' && line[1]=='/') + continue; + + i = sscanf(line, "%d\t%[^\t]\t%[^\t]\t%[^\t]\t%c\t%d\t%d\t" + "%[^\t]\t%[^\t]\t%ld\t%[^\t]\t%[^\t]\t%ld%n", + &account_id, userid, pass, lastlogin, &sex, &logincount, &state, + email, error_message, &connect_until_time, last_ip, memo, &ban_until_time, &n); + + sprintf(tmpsql, "SELECT `%s`,`%s`,`%s`,`lastlogin`,`logincount`,`sex`,`connect_until`,`last_ip`,`ban_until`,`state`" + " FROM `%s` WHERE `%s`='%s'", login_account_id, login_userid, login_user_pass, login_db, login_userid, t_uid); + + if(mysql_query(&mysql_handle, tmpsql) ) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle) ); + } + user_level = isGM(account_id); + printf ("userlevel: %s (%d)- %d\n",userid, account_id, user_level); + sql_res = mysql_store_result(&mysql_handle) ; + sql_row = mysql_fetch_row(sql_res); //row fetching + if (!sql_row) //no row -> insert + sprintf(tmpsql, "INSERT INTO `login` (`account_id`, `userid`, `user_pass`, `lastlogin`, `sex`, `logincount`, `email`, `level`) VALUES (%d, '%s', '%s', '%s', '%c', %d, 'user@athena', %d);",account_id , userid, pass,lastlogin,sex,logincount, user_level); + else //row reside -> updating + sprintf(tmpsql, "UPDATE `login` SET `account_id`='%d', `userid`='%s', `user_pass`='%s', `lastlogin`='%s', `sex`='%c', `logincount`='%d', `email`='user@athena', `level`='%d'\nWHERE `account_id`='%d';",account_id , userid, pass,lastlogin,sex,logincount, user_level, account_id); + printf ("Query: %s\n",tmpsql); + mysql_free_result(sql_res) ; //resource free + if(mysql_query(&mysql_handle, tmpsql) ) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle) ); + } + } + fclose(fp); + + printf ("Convert end...\n"); + + return 0; +} + +int login_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)){ + if(line[0] == '/' && line[1] == '/') + continue; + + i=sscanf(line,"%[^:]:%s", w1, w2); + if(i!=2) + continue; + + //add for DB connection + if(strcmpi(w1,"db_server_ip")==0){ + strcpy(db_server_ip, w2); + printf ("set db_server_ip : %s\n",w2); + } + else if(strcmpi(w1,"db_server_port")==0){ + db_server_port=atoi(w2); + printf ("set db_server_port : %s\n",w2); + } + else if(strcmpi(w1,"db_server_id")==0){ + strcpy(db_server_id, w2); + printf ("set db_server_id : %s\n",w2); + } + else if(strcmpi(w1,"db_server_pw")==0){ + strcpy(db_server_pw, w2); + printf ("set db_server_pw : %s\n",w2); + } + else if(strcmpi(w1,"db_server_logindb")==0){ + strcpy(db_server_logindb, w2); + printf ("set db_server_logindb : %s\n",w2); + } + //support the import command, just like any other config + else if(strcmpi(w1,"import")==0){ + login_config_read(w2); + } + } + fclose(fp); + printf ("End reading interserver configuration...\n"); + return 0; +} + +int do_init(int argc,char **argv) +{ + char input; + login_config_read( (argc>1)?argv[1]:INTER_CONF_NAME ); + read_gm_account(); + + printf("\nWarning : Make sure you backup your databases before continuing!\n"); + printf("\nDo you wish to convert your Login Database to SQL? (y/n) : "); + input=getchar(); + if(input == 'y' || input == 'Y') + mmo_auth_init(); + printf ("Everything's been converted!\n"); + exit (0); +} + + +void do_final() {} -- cgit v1.2.3-70-g09d2