summaryrefslogblamecommitdiff
path: root/src/char/int_storage.cpp
blob: c02f0376b4f7b5645d95d278f6b3d07916c3b7f6 (plain) (tree)
1
                          



















                                                                           
 
                                 
                                 
                                 
                                 
 

                            
                             
                            

                         
                          
 
                                 
 





                                    
 

                        


              

                                           
                                           
 
      
                                   
 
                                       
      
                                 
 

                     
                          
                                              
 
              

                                 
                                                           
         
                             
                                                            
                             


                                          







                                                                 

                
     
 
                
 
           

                         

 
                                       
      
                                     
 
                                    







                                                
                       

                     
                                           
                     
                                                                               
 
                                                  
                                                                      
                

 
                                                                                                
                                                       
 

                                               
             

 
                                                           
                                 
                             
 
              
 
                                 
                      
     
                                                      
               
     
 
                 
                            
     
                     
                              
         
                                               


            
                                                                 
                                    


            

 
      
                                                             
 
                                       
             
                          
 
 
                                                           
                                 
                            
 
                                  
 
                      
     
                                                                         


                             

                                                 
             

 
                        
                                               
 
                                 

 
                                                           
                         
 
                           
      
                                                          
 
                                                



                                         
 
 
                                    
      
                                                              
 



                                          

 
                                                           
                            
 
                              

                                               
 





                                                       
                                       

              
 
 
                                 

                                               
 




                                                      

                                              
     
                                                    
                              
                                               
     

              

 




                                                                                                               
                                                                       
 

                      

                    
                                             

                    
                                             
                  
                
                                     
     
              
 
                   
#include "int_storage.hpp"
//    int_storage.cpp - Internal storage handling.
//
//    Copyright © ????-2004 Athena Dev Teams
//    Copyright © 2004-2011 The Mana World Development Team
//    Copyright © 2011-2014 Ben Longbons <b.r.longbons@gmail.com>
//
//    This file is part of The Mana World (Athena server)
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.

#include "../strings/mstring.hpp"
#include "../strings/astring.hpp"
#include "../strings/xstring.hpp"
#include "../strings/literal.hpp"

#include "../generic/db.hpp"

#include "../io/cxxstdio.hpp"
#include "../io/extract.hpp"
#include "../io/lock.hpp"
#include "../io/read.hpp"
#include "../io/write.hpp"

#include "../proto2/char-map.hpp"

#include "../mmo/cxxstdio_enums.hpp"

#include "../high/extract_mmo.hpp"
#include "../high/mmo.hpp"

#include "../wire/packets.hpp"

#include "../poison.hpp"


namespace tmwa
{
// ファイル名のデフォルト
// inter_config_read()で再設定される
AString storage_txt = "save/storage.txt"_s;

static
Map<AccountId, Storage> storage_db;

// 倉庫データを文字列に変換
static
AString storage_tostr(Storage *p)
{
    MString str;
    str += STRPRINTF(
            "%d,%d\t"_fmt,
            p->account_id, p->storage_amount);

    int f = 0;
    for (SOff0 i : SOff0::iter())
    {
        if (p->storage_[i].nameid && p->storage_[i].amount)
        {
            str += STRPRINTF(
                    "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d "_fmt,
                    0 /*id*/,
                    p->storage_[i].nameid,
                    p->storage_[i].amount,
                    p->storage_[i].equip,
                    0 /*identify*/,
                    0 /*refine*/,
                    0 /*attribute*/,
                    0 /*card[0]*/,
                    0 /*card[1]*/,
                    0 /*card[2]*/,
                    0 /*card[3]*/);
            // shouldn't that include 'broken' also? Oh, well ...
            f++;
        }
    }

    str += '\t';

    if (!f)
        return AString();
    return AString(str);
}

// 文字列を倉庫データに変換
static
bool extract(XString str, Storage *p)
{
    std::vector<Item> storage_items;
    if (!extract(str,
                record<'\t'>(
                    record<','>(
                        &p->account_id,
                        &p->storage_amount),
                    vrec<' '>(&storage_items))))
        return false;

    if (!p->account_id)
        return false;

    if (storage_items.size() > MAX_STORAGE)
        return false;
    std::copy(storage_items.begin(), storage_items.end(), p->storage_.begin());

    if (p->storage_amount != storage_items.size())
        PRINTF("WARNING: storage desync for %d\n"_fmt, p->account_id);
    return true;
}

// アカウントから倉庫データインデックスを得る(新規倉庫追加可能)
Borrowed<Storage> account2storage(AccountId account_id)
{
    P<Storage> s = storage_db.init(account_id);
    s->account_id = account_id;
    return s;
}

//---------------------------------------------------------
// 倉庫データを読み込む
void inter_storage_init(void)
{
    int c = 0;

    io::ReadFile in(storage_txt);
    if (!in.is_open())
    {
        PRINTF("cant't read : %s\n"_fmt, storage_txt);
        return;
    }

    AString line;
    while (in.getline(line))
    {
        Storage s {};
        if (extract(line, &s))
        {
            storage_db.insert(s.account_id, s);
        }
        else
        {
            PRINTF("int_storage: broken data [%s] line %d\n"_fmt,
                    storage_txt, c);
        }
        c++;
    }
}

static
void inter_storage_save_sub(Storage *data, io::WriteFile& fp)
{
    AString line = storage_tostr(data);
    if (line)
        fp.put_line(line);
}

//---------------------------------------------------------
// 倉庫データを書き込む
int inter_storage_save(void)
{
    io::WriteLock fp(storage_txt);

    if (!fp.is_open())
    {
        PRINTF("int_storage: cant write [%s] !!! data is lost !!!\n"_fmt,
                storage_txt);
        return 1;
    }
    for (auto& pair : storage_db)
        inter_storage_save_sub(&pair.second, fp);
    return 0;
}

// 倉庫データ削除
void inter_storage_delete(AccountId account_id)
{
    storage_db.erase(account_id);
}

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

// 倉庫データの送信
static
void mapif_load_storage(Session *ss, AccountId account_id)
{
    P<Storage> st = account2storage(account_id);
    Packet_Payload<0x3810> payload_10;
    payload_10.account_id = account_id;
    payload_10.storage = *st;
    send_ppacket<0x3810>(ss, payload_10);
}

// 倉庫データ保存完了送信
static
void mapif_save_storage_ack(Session *ss, AccountId account_id)
{
    Packet_Fixed<0x3811> fixed_11;
    fixed_11.account_id = account_id;
    fixed_11.unknown = 0;
    send_fpacket<0x3811, 7>(ss, fixed_11);
}

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

// 倉庫データ要求受信
static __attribute__((warn_unused_result))
RecvResult mapif_parse_LoadStorage(Session *ss)
{
    Packet_Fixed<0x3010> fixed;
    RecvResult rv = recv_fpacket<0x3010, 6>(ss, fixed);
    if (rv != RecvResult::Complete)
        return rv;

    AccountId account_id = fixed.account_id;
    mapif_load_storage(ss, account_id);

    return rv;
}

// 倉庫データ受信&保存
static __attribute__((warn_unused_result))
RecvResult mapif_parse_SaveStorage(Session *ss)
{
    Packet_Payload<0x3011> payload;
    RecvResult rv = recv_ppacket<0x3011>(ss, payload);
    if (rv != RecvResult::Complete)
        return rv;

    AccountId account_id = payload.account_id;

    {
        P<Storage> st = account2storage(account_id);
        *st = payload.storage;
        mapif_save_storage_ack(ss, account_id);
    }

    return rv;
}

// map server からの通信
// ・1パケットのみ解析すること
// ・パケット長データはinter.cにセットしておくこと
// ・パケット長チェックや、RFIFOSKIPは呼び出し元で行われるので行ってはならない
// ・エラーなら0(false)、そうでないなら1(true)をかえさなければならない
RecvResult inter_storage_parse_frommap(Session *ms, uint16_t packet_id)
{
    RecvResult rv;
    switch (packet_id)
    {
        case 0x3010:
            rv = mapif_parse_LoadStorage(ms);
            break;
        case 0x3011:
            rv = mapif_parse_SaveStorage(ms);
            break;
        default:
            return RecvResult::Error;
    }
    return rv;
}
} // namespace tmwa