summaryrefslogblamecommitdiff
path: root/src/char/int_storage.cpp
blob: 05553b9cfc4aadc2caa5177cd4824e8d767a1c7c (plain) (tree)
1
2
3
4
5
6
7
8
9
                          
 

                             


                               

                    


                  
 

                                           
                                            
 

                       
 
                                       
      
                                               
 
                 
                      
                                                                         



                                                               
                                                                        





                                                             
                                                       



                                                      








                      

 
                                       
      
                                                 
 

                          
 
                                                                  








                                                                       
                                                                       







                                                                        
                                                     











                                                  
                                                                         







                                                                             
                                                    















                                                           
                                                                                                                                     

                          

 
                                                                                                
                                               
 
                      
                                                                

                  

                                             
                                   
                                                   

             

 
                                                           
                                 
                            
 
                     
                       
                      

             
                              
 
                                  

                   
                                                  

                 
                                  
     

                                     
                                
                                                               
         
                                                       


            
                                                                          
                       
                    


            
                
 
             

 
      
                                                              
 
                     
                                                 
              
                                  
 
 
                                                           
                                 
                            
 
             
             



                    
                                                      
     
                                                                     


                             
                                                                                     
                                        

                                                   

 
                        
                                        
 
                       
                                                                

          

                                            

             

 
                                                           
                         
 
                           
      
                                              
 





                                                     
             
 
 
                                    
      
                                                  
 



                               
             

 
                                                           
                            
 
                              
      
                                   
 
                                          
             
 
 
                                 
      
                                   
 
                      


                                          
     

                                                        


        


                                                         

             

 




                                                                                                               
                                       
 
                          

                    
                                        

                    
                                        
                  



                     
 
#include "int_storage.hpp"

#include "../common/db.hpp"
#include "../common/lock.hpp"
#include "../common/mmo.hpp"
#include "../common/socket.hpp"

#include "char.hpp"
#include "inter.hpp"

#include <cstdlib>
#include <cstring>

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

static
struct dbt *storage_db;

// 倉庫データを文字列に変換
static
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,
                              uint16_t(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;
}

// 文字列を倉庫データに変換
static
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 = EPOS(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 = EPOS(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;
}

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

//---------------------------------------------------------
// 倉庫データを読み込む
int inter_storage_init(void)
{
    char line[65536];
    int c = 0, tmp_int;
    struct storage *s;
    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);
        CREATE(s, struct storage, 1);
        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);

    return 0;
}

static
void inter_storage_save_sub(db_key_t, db_val_t data, FILE *fp)
{
    char line[65536];
    storage_tostr(line, (struct storage *) data);
    if (*line)
        fprintf(fp, "%s\n", line);
}

//---------------------------------------------------------
// 倉庫データを書き込む
int inter_storage_save(void)
{
    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, std::bind(inter_storage_save_sub, ph::_1, ph::_2, fp));
    lock_fclose(fp, storage_txt, &lock);
//  printf("int_storage: %s saved.\n",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;
}

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

// 倉庫データの送信
static
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;
}

// 倉庫データ保存完了送信
static
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;
}

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

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

// 倉庫データ受信&保存
static
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;
}

// 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;
        default:
            return 0;
    }
    return 1;
}