summaryrefslogtreecommitdiff
path: root/src/char/int_storage.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/char/int_storage.c')
-rw-r--r--src/char/int_storage.c501
1 files changed, 137 insertions, 364 deletions
diff --git a/src/char/int_storage.c b/src/char/int_storage.c
index 2a041b286..248a4521f 100644
--- a/src/char/int_storage.c
+++ b/src/char/int_storage.c
@@ -3,414 +3,184 @@
#include "../common/mmo.h"
#include "../common/malloc.h"
-#include "../common/socket.h"
-#include "../common/db.h"
-#include "../common/lock.h"
#include "../common/showmsg.h"
-#include "../common/utils.h"
+#include "../common/socket.h"
+#include "../common/strlib.h" // StringBuf
+#include "../common/sql.h"
#include "char.h"
#include "inter.h"
-#include "int_storage.h"
-#include "int_pet.h"
-#include "int_guild.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
-// ファイル名のデフォルト
-// inter_config_read()で再設定される
-char storage_txt[1024]="save/storage.txt";
-char guild_storage_txt[1024]="save/g_storage.txt";
-static DBMap* storage_db = NULL; // int account_id -> struct storage_data*
-static DBMap* guild_storage_db = NULL; // int guild_id -> struct guild_storage*
+#define STORAGE_MEMINC 16
-// 倉庫データを文字列に変換
-bool storage_tostr(char* str, int account_id, struct storage_data* p)
+/// Save storage data to sql
+int storage_tosql(int account_id, struct storage_data* p)
{
- int i,j;
- char *str_p = str;
- str_p += sprintf(str_p, "%d,%d\t", account_id, p->storage_amount);
-
- for( i = 0; i < MAX_STORAGE; i++ )
- if( p->items[i].nameid > 0 && p->items[i].amount > 0 )
- {
- str_p += sprintf(str_p, "%d,%d,%d,%d,%d,%d,%d",
- p->items[i].id,p->items[i].nameid,p->items[i].amount,p->items[i].equip,
- p->items[i].identify,p->items[i].refine,p->items[i].attribute);
- for(j=0; j<MAX_SLOTS; j++)
- str_p += sprintf(str_p,",%d",p->items[i].card[j]);
- str_p += sprintf(str_p," ");
- }
-
- *(str_p++)='\t';
-
- *str_p='\0';
-
- return true;
-}
-
-// 文字列を倉庫データに変換
-bool storage_fromstr(char* str, int* account_id, struct storage_data* p)
-{
- int tmp_int[256];
- char tmp_str[256];
- int next,len,i,j;
-
- if( sscanf(str, "%d,%d%n", &tmp_int[0], &tmp_int[1], &next) != 2 )
- return false;
-
- *account_id = tmp_int[0];
- p->storage_amount = tmp_int[1]; //FIXME: limit to MAX_STORAGE?
-
- next++;
- for( i = 0; str[next] && str[next]!='\t' && i < MAX_STORAGE; i++ )
- {
- if(sscanf(str + next, "%d,%d,%d,%d,%d,%d,%d%[0-9,-]%n",
- &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3],
- &tmp_int[4], &tmp_int[5], &tmp_int[6], tmp_str, &len) != 8)
- return false;
-
- p->items[i].id = tmp_int[0];
- p->items[i].nameid = tmp_int[1];
- p->items[i].amount = tmp_int[2];
- p->items[i].equip = tmp_int[3];
- p->items[i].identify = tmp_int[4];
- p->items[i].refine = tmp_int[5];
- p->items[i].attribute = tmp_int[6];
-
- for(j = 0; j < MAX_SLOTS && tmp_str[0] && sscanf(tmp_str, ",%d%[0-9,-]",&tmp_int[0], tmp_str) > 0; j++)
- p->items[i].card[j] = tmp_int[0];
-
- next += len;
- if (str[next] == ' ')
- next++;
- }
-
- if( i >= MAX_STORAGE && str[next] && str[next] != '\t' )
- ShowWarning("storage_fromstr: Found a storage line with more items than MAX_STORAGE (%d), remaining items have been discarded!\n", MAX_STORAGE);
-
- return true;
+ memitemdata_to_sql(p->items, MAX_STORAGE, account_id, TABLE_STORAGE);
+ return 0;
}
-int guild_storage_tostr(char *str,struct guild_storage *p)
+/// Load storage data to mem
+int storage_fromsql(int account_id, struct storage_data* p)
{
- int i,j,f=0;
- char *str_p = str;
- str_p+=sprintf(str,"%d,%d\t",p->guild_id,p->storage_amount);
+ StringBuf buf;
+ struct item* item;
+ char* data;
+ int i;
+ int j;
- for(i=0;i<MAX_GUILD_STORAGE;i++)
- if( (p->items[i].nameid) && (p->items[i].amount) ){
- str_p += sprintf(str_p,"%d,%d,%d,%d,%d,%d,%d",
- p->items[i].id,p->items[i].nameid,p->items[i].amount,p->items[i].equip,
- p->items[i].identify,p->items[i].refine,p->items[i].attribute);
- for(j=0; j<MAX_SLOTS; j++)
- str_p += sprintf(str_p,",%d",p->items[i].card[j]);
- str_p += sprintf(str_p," ");
- f++;
- }
-
- *(str_p++)='\t';
+ memset(p, 0, sizeof(struct storage_data)); //clean up memory
+ p->storage_amount = 0;
- *str_p='\0';
- if(!f)
- str[0]=0;
- return 0;
-}
+ // storage {`account_id`/`id`/`nameid`/`amount`/`equip`/`identify`/`refine`/`attribute`/`card0`/`card1`/`card2`/`card3`}
+ StringBuf_Init(&buf);
+ StringBuf_AppendStr(&buf, "SELECT `id`,`nameid`,`amount`,`equip`,`identify`,`refine`,`attribute`,`expire_time`");
+ for( j = 0; j < MAX_SLOTS; ++j )
+ StringBuf_Printf(&buf, ",`card%d`", j);
+ StringBuf_Printf(&buf, " FROM `%s` WHERE `account_id`='%d' ORDER BY `nameid`", storage_db, account_id);
-int guild_storage_fromstr(char *str,struct guild_storage *p)
-{
- int tmp_int[256];
- char tmp_str[256];
- int set,next,len,i,j;
+ if( SQL_ERROR == Sql_Query(sql_handle, StringBuf_Value(&buf)) )
+ Sql_ShowDebug(sql_handle);
- set=sscanf(str,"%d,%d%n",&tmp_int[0],&tmp_int[1],&next);
- p->storage_amount=tmp_int[1];
+ StringBuf_Destroy(&buf);
- if(set!=2)
- return 1;
- if(str[next]=='\n' || str[next]=='\r')
- return 0;
- next++;
- for(i=0;str[next] && str[next]!='\t' && i < MAX_GUILD_STORAGE;i++){
- if(sscanf(str + next, "%d,%d,%d,%d,%d,%d,%d%[0-9,-]%n",
- &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3],
- &tmp_int[4], &tmp_int[5], &tmp_int[6], tmp_str, &len) == 8)
+ for( i = 0; i < MAX_STORAGE && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i )
+ {
+ item = &p->items[i];
+ Sql_GetData(sql_handle, 0, &data, NULL); item->id = atoi(data);
+ Sql_GetData(sql_handle, 1, &data, NULL); item->nameid = atoi(data);
+ Sql_GetData(sql_handle, 2, &data, NULL); item->amount = atoi(data);
+ Sql_GetData(sql_handle, 3, &data, NULL); item->equip = atoi(data);
+ Sql_GetData(sql_handle, 4, &data, NULL); item->identify = atoi(data);
+ Sql_GetData(sql_handle, 5, &data, NULL); item->refine = atoi(data);
+ Sql_GetData(sql_handle, 6, &data, NULL); item->attribute = atoi(data);
+ Sql_GetData(sql_handle, 7, &data, NULL); item->expire_time = (unsigned int)atoi(data);
+ for( j = 0; j < MAX_SLOTS; ++j )
{
- p->items[i].id = tmp_int[0];
- p->items[i].nameid = tmp_int[1];
- p->items[i].amount = tmp_int[2];
- p->items[i].equip = tmp_int[3];
- p->items[i].identify = tmp_int[4];
- p->items[i].refine = tmp_int[5];
- p->items[i].attribute = tmp_int[6];
- for(j = 0; j < MAX_SLOTS && tmp_str[0] && sscanf(tmp_str, ",%d%[0-9,-]",&tmp_int[0], tmp_str) > 0; j++)
- p->items[i].card[j] = tmp_int[0];
- next += len;
- if (str[next] == ' ')
- next++;
+ Sql_GetData(sql_handle, 8+j, &data, NULL); item->card[j] = atoi(data);
}
- else return 1;
}
- if (i >= MAX_GUILD_STORAGE && str[next] && str[next]!='\t')
- ShowWarning("guild_storage_fromstr: Found a storage line with more items than MAX_GUILD_STORAGE (%d), remaining items have been discarded!\n", MAX_GUILD_STORAGE);
- return 0;
-}
-
-#ifndef TXT_SQL_CONVERT
+ p->storage_amount = i;
+ Sql_FreeResult(sql_handle);
-static void* create_storage(DBKey key, va_list args)
-{
- return (struct storage_data *) aCalloc(sizeof(struct storage_data), 1);
+ ShowInfo("storage load complete from DB - id: %d (total: %d)\n", account_id, p->storage_amount);
+ return 1;
}
-static void* create_guildstorage(DBKey key, va_list args)
+/// Save guild_storage data to sql
+int guild_storage_tosql(int guild_id, struct guild_storage* p)
{
- struct guild_storage* gs = NULL;
- gs = (struct guild_storage *) aCalloc(sizeof(struct guild_storage), 1);
- gs->guild_id=key.i;
- return gs;
+ memitemdata_to_sql(p->items, MAX_GUILD_STORAGE, guild_id, TABLE_GUILD_STORAGE);
+ ShowInfo ("guild storage save to DB - guild: %d\n", guild_id);
+ return 0;
}
-/// Loads storage data into the provided data structure.
-/// If data doesn't exist, the destination is zeroed and false is returned.
-bool storage_load(int account_id, struct storage_data* storage)
+/// Load guild_storage data to mem
+int guild_storage_fromsql(int guild_id, struct guild_storage* p)
{
- struct storage_data* s = (struct storage_data*)idb_get(storage_db, account_id);
+ StringBuf buf;
+ struct item* item;
+ char* data;
+ int i;
+ int j;
- if( s != NULL )
- memcpy(storage, s, sizeof(*storage));
- else
- memset(storage, 0x00, sizeof(*storage));
-
- return( s != NULL );
-}
-
-/// Writes provided data into storage cache.
-/// If data contains 0 items, any existing entry in cache is destroyed.
-/// If data contains 1+ items and no cache entry exists, a new one is created.
-bool storage_save(int account_id, struct storage_data* storage)
-{
- if( storage->storage_amount > 0 )
- {
- struct storage_data* s = (struct storage_data*)idb_ensure(storage_db, account_id, create_storage);
- memcpy(s, storage, sizeof(*storage));
- }
- else
- {
- idb_remove(storage_db, account_id);
- }
+ memset(p, 0, sizeof(struct guild_storage)); //clean up memory
+ p->storage_amount = 0;
+ p->guild_id = guild_id;
- return true;
-}
+ // storage {`guild_id`/`id`/`nameid`/`amount`/`equip`/`identify`/`refine`/`attribute`/`card0`/`card1`/`card2`/`card3`}
+ StringBuf_Init(&buf);
+ StringBuf_AppendStr(&buf, "SELECT `id`,`nameid`,`amount`,`equip`,`identify`,`refine`,`attribute`");
+ for( j = 0; j < MAX_SLOTS; ++j )
+ StringBuf_Printf(&buf, ",`card%d`", j);
+ StringBuf_Printf(&buf, " FROM `%s` WHERE `guild_id`='%d' ORDER BY `nameid`", guild_storage_db, guild_id);
-//---------------------------------------------------------
-// 倉庫データを読み込む
-int inter_storage_init()
-{
- char line[65536];
- int c = 0;
- FILE *fp;
+ if( SQL_ERROR == Sql_Query(sql_handle, StringBuf_Value(&buf)) )
+ Sql_ShowDebug(sql_handle);
- storage_db = idb_alloc(DB_OPT_RELEASE_DATA);
+ StringBuf_Destroy(&buf);
- fp=fopen(storage_txt,"r");
- if(fp==NULL){
- ShowError("can't read : %s\n",storage_txt);
- return 1;
- }
- while( fgets(line, sizeof(line), fp) )
+ for( i = 0; i < MAX_GUILD_STORAGE && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i )
{
- int account_id;
- struct storage_data *s;
-
- s = (struct storage_data*)aCalloc(sizeof(struct storage_data), 1);
- if( s == NULL )
- {
- ShowFatalError("int_storage: out of memory!\n");
- exit(EXIT_FAILURE);
- }
-
- if( storage_fromstr(line,&account_id,s) )
+ item = &p->items[i];
+ Sql_GetData(sql_handle, 0, &data, NULL); item->id = atoi(data);
+ Sql_GetData(sql_handle, 1, &data, NULL); item->nameid = atoi(data);
+ Sql_GetData(sql_handle, 2, &data, NULL); item->amount = atoi(data);
+ Sql_GetData(sql_handle, 3, &data, NULL); item->equip = atoi(data);
+ Sql_GetData(sql_handle, 4, &data, NULL); item->identify = atoi(data);
+ Sql_GetData(sql_handle, 5, &data, NULL); item->refine = atoi(data);
+ Sql_GetData(sql_handle, 6, &data, NULL); item->attribute = atoi(data);
+ item->expire_time = 0;
+ for( j = 0; j < MAX_SLOTS; ++j )
{
- idb_put(storage_db,account_id,s);
- }
- else{
- ShowError("int_storage: broken data in [%s] line %d\n",storage_txt,c);
- aFree(s);
+ Sql_GetData(sql_handle, 7+j, &data, NULL); item->card[j] = atoi(data);
}
- c++;
}
- fclose(fp);
-
- c = 0;
- guild_storage_db = idb_alloc(DB_OPT_RELEASE_DATA);
-
- fp=fopen(guild_storage_txt,"r");
- if(fp==NULL){
- ShowError("can't read : %s\n",guild_storage_txt);
- return 1;
- }
- while(fgets(line, sizeof(line), fp))
- {
- int tmp_int;
- struct guild_storage *gs;
-
- sscanf(line,"%d",&tmp_int);
- gs = (struct guild_storage*)aCalloc(sizeof(struct guild_storage), 1);
- if(gs==NULL){
- ShowFatalError("int_storage: out of memory!\n");
- exit(EXIT_FAILURE);
- }
-// memset(gs,0,sizeof(struct guild_storage)); aCalloc...
- gs->guild_id=tmp_int;
- if(gs->guild_id > 0 && guild_storage_fromstr(line,gs) == 0) {
- idb_put(guild_storage_db,gs->guild_id,gs);
- }
- else{
- ShowError("int_storage: broken data [%s] line %d\n",guild_storage_txt,c);
- aFree(gs);
- }
- c++;
- }
- fclose(fp);
+ p->storage_amount = i;
+ Sql_FreeResult(sql_handle);
+ ShowInfo("guild storage load complete from DB - id: %d (total: %d)\n", guild_id, p->storage_amount);
return 0;
}
-void inter_storage_final() {
- if(storage_db)
- {
- storage_db->destroy(storage_db, NULL);
- }
- if(guild_storage_db)
- {
- guild_storage_db->destroy(guild_storage_db, NULL);
- }
- return;
-}
-
//---------------------------------------------------------
-// 倉庫データを書き込む
-int inter_storage_save()
+// storage data initialize
+int inter_storage_sql_init(void)
{
- struct DBIterator* iter;
- DBKey key;
- struct storage_data* data;
- FILE *fp;
- int lock;
- if( (fp=lock_fopen(storage_txt,&lock))==NULL ){
- ShowError("int_storage: can't write [%s] !!! data is lost !!!\n",storage_txt);
- return 1;
- }
-
- iter = storage_db->iterator(storage_db);
- for( data = (struct storage_data*)iter->first(iter,&key); iter->exists(iter); data = (struct storage_data*)iter->next(iter,&key) )
- {
- int account_id = key.i;
- char line[65536];
- storage_tostr(line,account_id,data);
- fprintf(fp,"%s\n",line);
- }
- iter->destroy(iter);
-
- lock_fclose(fp,storage_txt,&lock);
- return 0;
+ return 1;
}
-
-//---------------------------------------------------------
-// 倉庫データを書き込む
-int inter_guild_storage_save()
+// storage data finalize
+void inter_storage_sql_final(void)
{
- struct DBIterator* iter;
- struct guild_storage* data;
- FILE *fp;
- int lock;
- if( (fp=lock_fopen(guild_storage_txt,&lock))==NULL ){
- ShowError("int_storage: can't write [%s] !!! data is lost !!!\n",guild_storage_txt);
- return 1;
- }
-
- iter = guild_storage_db->iterator(guild_storage_db);
- for( data = (struct guild_storage*)iter->first(iter,NULL); iter->exists(iter); data = (struct guild_storage*)iter->next(iter,NULL) )
- {
- char line[65536];
- if(inter_guild_search(data->guild_id) != NULL)
- {
- guild_storage_tostr(line,data);
- if(*line)
- fprintf(fp,"%s\n",line);
- }
- }
- iter->destroy(iter);
-
- lock_fclose(fp,guild_storage_txt,&lock);
- return 0;
+ return;
}
-// 倉庫データ削除
+// q?f[^?
int inter_storage_delete(int account_id)
{
- struct storage_data *s = (struct storage_data*)idb_get(storage_db,account_id);
- if(s) {
- int i;
- for(i=0;i<s->storage_amount;i++){
- if(s->items[i].card[0] == (short)0xff00)
- inter_pet_delete( MakeDWord(s->items[i].card[1],s->items[i].card[2]) );
- }
- idb_remove(storage_db,account_id);
- }
+ if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id`='%d'", storage_db, account_id) )
+ Sql_ShowDebug(sql_handle);
return 0;
}
-
-// ギルド倉庫データ削除
int inter_guild_storage_delete(int guild_id)
{
- struct guild_storage *gs = (struct guild_storage*)idb_get(guild_storage_db,guild_id);
- if(gs) {
- int i;
- for(i=0;i<gs->storage_amount;i++){
- if(gs->items[i].card[0] == (short)0xff00)
- inter_pet_delete( MakeDWord(gs->items[i].card[1],gs->items[i].card[2]) );
- }
- idb_remove(guild_storage_db,guild_id);
- }
+ if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id`='%d'", guild_storage_db, guild_id) )
+ Sql_ShowDebug(sql_handle);
return 0;
}
-struct guild_storage *guild2storage(int guild_id)
-{
- struct guild_storage* gs = NULL;
- if(inter_guild_search(guild_id) != NULL)
- gs = (struct guild_storage*)idb_ensure(guild_storage_db, guild_id, create_guildstorage);
- return gs;
-}
-
//---------------------------------------------------------
-// map serverへの通信
+// packet from map server
int mapif_load_guild_storage(int fd,int account_id,int guild_id)
{
- struct guild_storage *gs=guild2storage(guild_id);
- WFIFOHEAD(fd, sizeof(struct guild_storage)+12);
- WFIFOW(fd,0)=0x3818;
- if(gs) {
- WFIFOW(fd,2)=sizeof(struct guild_storage)+12;
- WFIFOL(fd,4)=account_id;
- WFIFOL(fd,8)=guild_id;
- memcpy(WFIFOP(fd,12),gs,sizeof(struct guild_storage));
- }
- else {
- WFIFOW(fd,2)=12;
- WFIFOL(fd,4)=account_id;
- WFIFOL(fd,8)=0;
+ if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `guild_id` FROM `%s` WHERE `guild_id`='%d'", guild_db, guild_id) )
+ Sql_ShowDebug(sql_handle);
+ else if( Sql_NumRows(sql_handle) > 0 )
+ {// guild exists
+ WFIFOHEAD(fd, sizeof(struct guild_storage)+12);
+ WFIFOW(fd,0) = 0x3818;
+ WFIFOW(fd,2) = sizeof(struct guild_storage)+12;
+ WFIFOL(fd,4) = account_id;
+ WFIFOL(fd,8) = guild_id;
+ guild_storage_fromsql(guild_id, (struct guild_storage*)WFIFOP(fd,12));
+ WFIFOSET(fd, WFIFOW(fd,2));
+ return 0;
}
- WFIFOSET(fd,WFIFOW(fd,2));
-
+ // guild does not exist
+ Sql_FreeResult(sql_handle);
+ WFIFOHEAD(fd, 12);
+ WFIFOW(fd,0) = 0x3818;
+ WFIFOW(fd,2) = 12;
+ WFIFOL(fd,4) = account_id;
+ WFIFOL(fd,8) = 0;
+ WFIFOSET(fd, 12);
return 0;
}
-
int mapif_save_guild_storage_ack(int fd,int account_id,int guild_id,int fail)
{
WFIFOHEAD(fd,11);
@@ -423,7 +193,7 @@ int mapif_save_guild_storage_ack(int fd,int account_id,int guild_id,int fail)
}
//---------------------------------------------------------
-// map serverからの通信
+// packet from map server
int mapif_parse_LoadGuildStorage(int fd)
{
@@ -434,31 +204,35 @@ int mapif_parse_LoadGuildStorage(int fd)
int mapif_parse_SaveGuildStorage(int fd)
{
- struct guild_storage *gs;
- int guild_id, len;
+ int guild_id;
+ int len;
+
RFIFOHEAD(fd);
- guild_id=RFIFOL(fd,8);
- len=RFIFOW(fd,2);
- if(sizeof(struct guild_storage)!=len-12){
- ShowError("inter storage: data size error %d %d\n",sizeof(struct guild_storage),len-12);
+ guild_id = RFIFOL(fd,8);
+ len = RFIFOW(fd,2);
+
+ if( sizeof(struct guild_storage) != len - 12 )
+ {
+ ShowError("inter storage: data size error %d != %d\n", sizeof(struct guild_storage), len - 12);
}
- else {
- gs=guild2storage(guild_id);
- if(gs) {
- memcpy(gs,RFIFOP(fd,12),sizeof(struct guild_storage));
- mapif_save_guild_storage_ack(fd,RFIFOL(fd,4),guild_id,0);
+ else
+ {
+ if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `guild_id` FROM `%s` WHERE `guild_id`='%d'", guild_db, guild_id) )
+ Sql_ShowDebug(sql_handle);
+ else if( Sql_NumRows(sql_handle) > 0 )
+ {// guild exists
+ Sql_FreeResult(sql_handle);
+ guild_storage_tosql(guild_id, (struct guild_storage*)RFIFOP(fd,12));
+ mapif_save_guild_storage_ack(fd, RFIFOL(fd,4), guild_id, 0);
+ return 0;
}
- else
- mapif_save_guild_storage_ack(fd,RFIFOL(fd,4),guild_id,1);
+ Sql_FreeResult(sql_handle);
}
+ mapif_save_guild_storage_ack(fd, RFIFOL(fd,4), guild_id, 1);
return 0;
}
-// map server からの通信
-// ・1パケットのみ解析すること
-// ・パケット長データはinter.cにセットしておくこと
-// ・パケット長チェックや、RFIFOSKIPは呼び出し元で行われるので行ってはならない
-// ・エラーなら0(false)、そうでないなら1(true)をかえさなければならない
+
int inter_storage_parse_frommap(int fd)
{
RFIFOHEAD(fd);
@@ -470,4 +244,3 @@ int inter_storage_parse_frommap(int fd)
}
return 1;
}
-#endif //TXT_SQL_CONVERT