summaryrefslogblamecommitdiff
path: root/src/char/int_storage.c
blob: 744a59f70876b5650166fac13adc6c81d15b49c2 (plain) (tree)
1
2
3
4
5
                                                                    



                   









                             

                                           

                                                    



                                    
                                       
                                                
 






















                                                                              

 
                                       
                                                  
 
































































                                                                                                                                   

 
                                                            
 






















                                                                              

 
                                                              
 
































































                                                                                                                                               

 
                                                                                                
                                                
 














                                                                    

 
                                                  
 



















                                                                                   


                                                           
                                 
                         
 










































































                                                                             

 





                                                      
 






                                                            
 





                                                           

 
                                                              
 






                                                  
 
 
                                                           
                                 
                         
 















                                                                      

 
                                                                    
 











                                                                         
 
 
                                                           
                                 
                               
 















                                                                       

 
                        
                                         
 







                                                                 

 
                                 
                                             
 







                                                                           


                                                           
                         
 
                           
                                               
 






                                                        
 
 
                                    
                                                   
 




                                

 
                                                                   
 

















                                                                    
 


                                                                       
 





                                


                                                           
                            
 
                              
                                    
 

                                            
 
 
                                 
                                    
 














                                                            

 
                                         
 

                                                                  
 

                                         
 



















                                                                           

 




                                                                                                               
                                        
 

















                                              
 
// $Id: int_storage.c,v 1.1.1.1 2004/09/10 17:26:51 MagicalTux Exp $

#include <string.h>
#include <stdlib.h>

#include "../common/mmo.h"
#include "../common/socket.h"
#include "../common/db.h"
#include "../common/lock.h"
#include "../common/malloc.h"
#include "char.h"
#include "inter.h"
#include "int_storage.h"
#include "int_guild.h"

// ファイル名のデフォルト
// inter_config_read()で再設定される
char storage_txt[1024] = "save/storage.txt";
char guild_storage_txt[1024] = "save/g_storage.txt";

static struct dbt *storage_db;
static struct dbt *guild_storage_db;

// 倉庫データを文字列に変換
int storage_tostr (char *str, struct storage *p)
{
    int  i, f = 0;
    char *str_p = str;
    str_p += sprintf (str_p, "%d,%d\t", p->account_id, p->storage_amount);

    for (i = 0; i < MAX_STORAGE; i++)
        if ((p->storage_[i].nameid) && (p->storage_[i].amount))
        {
            str_p += sprintf (str_p, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d ",
                              p->storage_[i].id, p->storage_[i].nameid,
                              p->storage_[i].amount, p->storage_[i].equip,
                              p->storage_[i].identify, p->storage_[i].refine,
                              p->storage_[i].attribute,
                              p->storage_[i].card[0], p->storage_[i].card[1],
                              p->storage_[i].card[2], p->storage_[i].card[3]);
            f++;
        }

    *(str_p++) = '\t';

    *str_p = '\0';
    if (!f)
        str[0] = 0;
    return 0;
}

// 文字列を倉庫データに変換
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 < MAX_STORAGE; 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;
    }
    if (i >= MAX_STORAGE && str[next] && str[next] != '\t')
        printf
            ("storage_fromstr: Found a storage line with more items than MAX_STORAGE (%d), remaining items have been discarded!\n",
             MAX_STORAGE);
    return 0;
}

int guild_storage_tostr (char *str, struct guild_storage *p)
{
    int  i, f = 0;
    char *str_p = str;
    str_p += sprintf (str, "%d,%d\t", p->guild_id, p->storage_amount);

    for (i = 0; i < MAX_GUILD_STORAGE; i++)
        if ((p->storage_[i].nameid) && (p->storage_[i].amount))
        {
            str_p += sprintf (str_p, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d ",
                              p->storage_[i].id, p->storage_[i].nameid,
                              p->storage_[i].amount, p->storage_[i].equip,
                              p->storage_[i].identify, p->storage_[i].refine,
                              p->storage_[i].attribute,
                              p->storage_[i].card[0], p->storage_[i].card[1],
                              p->storage_[i].card[2], p->storage_[i].card[3]);
            f++;
        }

    *(str_p++) = '\t';

    *str_p = '\0';
    if (!f)
        str[0] = 0;
    return 0;
}

int guild_storage_fromstr (char *str, struct guild_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 < MAX_GUILD_STORAGE; 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;
    }
    if (i >= MAX_GUILD_STORAGE && str[next] && str[next] != '\t')
        printf
            ("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;
}

// アカウントから倉庫データインデックスを得る(新規倉庫追加可能)
struct storage *account2storage (int account_id)
{
    struct storage *s;
    s = (struct storage *) numdb_search (storage_db, account_id);
    if (s == NULL)
    {
        s = (struct storage *) aCalloc (sizeof (struct storage), 1);
        if (s == NULL)
        {
            printf ("int_storage: out of memory!\n");
            exit (0);
        }
        memset (s, 0, sizeof (struct storage));
        s->account_id = account_id;
        numdb_insert (storage_db, s->account_id, s);
    }
    return s;
}

struct guild_storage *guild2storage (int guild_id)
{
    struct guild_storage *gs = NULL;
    if (inter_guild_search (guild_id) != NULL)
    {
        gs = (struct guild_storage *) numdb_search (guild_storage_db,
                                                    guild_id);
        if (gs == NULL)
        {
            gs = (struct guild_storage *)
                aCalloc (sizeof (struct guild_storage), 1);
            if (gs == NULL)
            {
                printf ("int_storage: out of memory!\n");
                exit (0);
            }
//          memset(gs,0,sizeof(struct guild_storage)); aCalloc does this! [Skotlex]
            gs->guild_id = guild_id;
            numdb_insert (guild_storage_db, gs->guild_id, gs);
        }
    }
    return gs;
}

//---------------------------------------------------------
// 倉庫データを読み込む
int inter_storage_init ()
{
    char line[65536];
    int  c = 0, tmp_int;
    struct storage *s;
    struct guild_storage *gs;
    FILE *fp;

    storage_db = numdb_init ();

    fp = fopen_ (storage_txt, "r");
    if (fp == NULL)
    {
        printf ("cant't read : %s\n", storage_txt);
        return 1;
    }
    while (fgets (line, 65535, fp))
    {
        sscanf (line, "%d", &tmp_int);
        s = (struct storage *) aCalloc (sizeof (struct storage), 1);
        if (s == NULL)
        {
            printf ("int_storage: out of memory!\n");
            exit (0);
        }
//      memset(s,0,sizeof(struct storage)); aCalloc does this...
        s->account_id = tmp_int;
        if (s->account_id > 0 && storage_fromstr (line, s) == 0)
        {
            numdb_insert (storage_db, s->account_id, s);
        }
        else
        {
            printf ("int_storage: broken data [%s] line %d\n", storage_txt,
                    c);
            free (s);
        }
        c++;
    }
    fclose_ (fp);

    c = 0;
    guild_storage_db = numdb_init ();

    fp = fopen_ (guild_storage_txt, "r");
    if (fp == NULL)
    {
        printf ("cant't read : %s\n", guild_storage_txt);
        return 1;
    }
    while (fgets (line, 65535, fp))
    {
        sscanf (line, "%d", &tmp_int);
        gs = (struct guild_storage *) aCalloc (sizeof (struct guild_storage),
                                               1);
        if (gs == NULL)
        {
            printf ("int_storage: out of memory!\n");
            exit (0);
        }
//      memset(gs,0,sizeof(struct guild_storage)); aCalloc...
        gs->guild_id = tmp_int;
        if (gs->guild_id > 0 && guild_storage_fromstr (line, gs) == 0)
        {
            numdb_insert (guild_storage_db, gs->guild_id, gs);
        }
        else
        {
            printf ("int_storage: broken data [%s] line %d\n",
                    guild_storage_txt, c);
            free (gs);
        }
        c++;
    }
    fclose_ (fp);

    return 0;
}

int storage_db_final (void *k, void *data, va_list ap)
{
    struct storage *p = (struct storage *) data;
    if (p)
        free (p);
    return 0;
}

int guild_storage_db_final (void *k, void *data, va_list ap)
{
    struct guild_storage *p = (struct guild_storage *) data;
    if (p)
        free (p);
    return 0;
}

void inter_storage_final ()
{
    numdb_final (storage_db, storage_db_final);
    numdb_final (guild_storage_db, guild_storage_db_final);
    return;
}

int inter_storage_save_sub (void *key, void *data, va_list ap)
{
    char line[65536];
    FILE *fp;
    storage_tostr (line, (struct storage *) data);
    fp = va_arg (ap, FILE *);
    if (*line)
        fprintf (fp, "%s" RETCODE, line);
    return 0;
}

//---------------------------------------------------------
// 倉庫データを書き込む
int inter_storage_save ()
{
    FILE *fp;
    int  lock;

    if (!storage_db)
        return 1;

    if ((fp = lock_fopen (storage_txt, &lock)) == NULL)
    {
        printf ("int_storage: cant write [%s] !!! data is lost !!!\n",
                storage_txt);
        return 1;
    }
    numdb_foreach (storage_db, inter_storage_save_sub, fp);
    lock_fclose (fp, storage_txt, &lock);
//  printf("int_storage: %s saved.\n",storage_txt);
    return 0;
}

int inter_guild_storage_save_sub (void *key, void *data, va_list ap)
{
    char line[65536];
    FILE *fp;

    if (inter_guild_search (((struct guild_storage *) data)->guild_id) !=
        NULL)
    {
        guild_storage_tostr (line, (struct guild_storage *) data);
        fp = va_arg (ap, FILE *);
        if (*line)
            fprintf (fp, "%s" RETCODE, line);
    }
    return 0;
}

//---------------------------------------------------------
// 倉庫データを書き込む
int inter_guild_storage_save ()
{
    FILE *fp;
    int  lock;

    if (!guild_storage_db)
        return 1;

    if ((fp = lock_fopen (guild_storage_txt, &lock)) == NULL)
    {
        printf ("int_storage: cant write [%s] !!! data is lost !!!\n",
                guild_storage_txt);
        return 1;
    }
    numdb_foreach (guild_storage_db, inter_guild_storage_save_sub, fp);
    lock_fclose (fp, guild_storage_txt, &lock);
//  printf("int_storage: %s saved.\n",guild_storage_txt);
    return 0;
}

// 倉庫データ削除
int inter_storage_delete (int account_id)
{
    struct storage *s =
        (struct storage *) numdb_search (storage_db, account_id);
    if (s)
    {
        numdb_erase (storage_db, account_id);
        free (s);
    }
    return 0;
}

// ギルド倉庫データ削除
int inter_guild_storage_delete (int guild_id)
{
    struct guild_storage *gs =
        (struct guild_storage *) numdb_search (guild_storage_db, guild_id);
    if (gs)
    {
        numdb_erase (guild_storage_db, guild_id);
        free (gs);
    }
    return 0;
}

//---------------------------------------------------------
// map serverへの通信

// 倉庫データの送信
int mapif_load_storage (int fd, int account_id)
{
    struct storage *s = account2storage (account_id);
    WFIFOW (fd, 0) = 0x3810;
    WFIFOW (fd, 2) = sizeof (struct storage) + 8;
    WFIFOL (fd, 4) = account_id;
    memcpy (WFIFOP (fd, 8), s, sizeof (struct storage));
    WFIFOSET (fd, WFIFOW (fd, 2));
    return 0;
}

// 倉庫データ保存完了送信
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)
{
    struct guild_storage *gs = guild2storage (guild_id);
    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;
    }
    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;
}

//---------------------------------------------------------
// map serverからの通信

// 倉庫データ要求受信
int mapif_parse_LoadStorage (int fd)
{
    mapif_load_storage (fd, RFIFOL (fd, 2));
    return 0;
}

// 倉庫データ受信&保存
int mapif_parse_SaveStorage (int fd)
{
    struct storage *s;
    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
    {
        s = account2storage (account_id);
        memcpy (s, RFIFOP (fd, 8), sizeof (struct storage));
        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)
{
    struct guild_storage *gs;
    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
    {
        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
            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)
{
    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;
}