kaptanmikro1 1
kaptanmikro1
Bvural41 1
Bvural41
mavzermete 1
mavzermete
noisiv 1
noisiv
Manwe Work 1
Manwe Work
Reklam vermek için turkmmo@gmail.com

Güvenli Quest Reload

  • Konuyu başlatan Konuyu başlatan Darqhues
  • Başlangıç tarihi Başlangıç tarihi
  • Cevaplar Cevaplar 6
  • Görüntüleme Görüntüleme 270
Merhaba, özellikle kalabalık sunucularında reload q çekilmez. Kanal çökmelerine sebep olur, eşya kaybına sebep olur, zindanların patlamasına sebep olur. Yazdığım bu sistem bu sorunların hiçbir şekilde yaşanmamasını sağlayan bir sistemdir. Reload Q komutu p2p komutu değildir. Ancak bu sistemle artık p2p komutudur. Yani tek core üzerinde yazmanız diğer corelerde de etki edecektir. Rahatlıkla kullanabilirsiniz. 1500 online ile denenmiştir. Ücretsiz paylaşıyorum.


Önce neden çöktüğüne bakalım;

  • Açık quest penceresi: Reload() içindeki lua_close(L) bütün Lua ortamını kapatıyor. NPC menüsü, select, input ya da wait adımında bekleyen oyuncu cevap verince sunucu kapatılmış ortama yazıyor (CQuestManager::Select → lua_pushnumber çökmesi).
  • Zindan zamanlayıcıları: m_mapTimerID.clear() zamanlayıcı numaralarını sıfırlıyor. Çalışan zamanlayıcılar eski numarayla kalıyor; yenilemeden sonra yanlış scripte gidip Lua hatası veriyor.
  • Oyuncusuz script: server_timer hata verince SendScript boş karakterin GetDesc()'ini çağırıyor (CEntity::GetDesc (this=0x0) çökmesi).
  • Tek kanal: /reload q sadece komutun yazıldığı core'u yeniliyordu.




common/service.h

EKLE;

Kod:
#define TETRA_SAFE_QUEST_RELOAD

game/src/packet.h

ARAT;

Kod:
HEADER_GG_LOGIN = 1

GG paketlerinin en altına ekle. (Numaraya dikkat edin, GG paketlerinin kullanmadığı bir numara olmalıdır.

Kod:
#ifdef TETRA_SAFE_QUEST_RELOAD
    HEADER_GG_RELOAD_QUEST                = 40,
#endif

game/src/packet_info.cpp

ARA;

Kod:
CPacketInfoGG::CPacketInfoGG()
{

Fonksiyonun sonuna ekle;

Kod:
#ifdef TETRA_SAFE_QUEST_RELOAD
    Set (HEADER_GG_RELOAD_QUEST,    sizeof (BYTE),    "ReloadQuest",    false);
#endif

game/src/input_p2p.cpp

ARA;

Kod:
int CInputP2P::Analyze (LPDESC d, BYTE bHeader, const char* c_pData)

İçindeki switch (bHeader) bloğunu bulun. Dosyanın başında #include "questmanager.h" olduğundan emin olun.

EKLE;

Kod:
#ifdef TETRA_SAFE_QUEST_RELOAD
        case HEADER_GG_RELOAD_QUEST:
            sys_log (0, "QUEST_RELOAD: diger core'dan istek geldi");
            quest::CQuestManager::instance().Reload();
            break;
#endif

game/src/cmd_gm.cpp

ARA;

Kod:
            case 'q':
                ch->ChatPacket (CHAT_TYPE_INFO, "Reloading quest.");
                quest::CQuestManager::instance().Reload();

ALTINA#includeREAK satırından hemen önce)

Kod:
#ifdef TETRA_SAFE_QUEST_RELOAD
                {
                    BYTE bHeader = HEADER_GG_RELOAD_QUEST;
                    P2P_MANAGER::instance().Send (&bHeader, sizeof (BYTE));
                    ch->ChatPacket (CHAT_TYPE_INFO, "Quest reloaded across all channels.");
                }
#endif


game/src/questmanager.cpp

ARA;

Kod:
    void CQuestManager::Reload()
    {
        lua_close (L);

DEĞİŞTİR;

Kod:
    void CQuestManager::Reload()
    {
#ifdef TETRA_SAFE_QUEST_RELOAD
        int iClosedQuest = 0;
        for (PCMap::iterator itPC = m_mapPC.begin(); itPC != m_mapPC.end(); ++itPC)
        {
            PC& rkPC = itPC->second;
            if (!rkPC.IsRunning())
                continue;

            QuestState* pkState = rkPC.GetRunningQuestState();
            if (pkState)
                CloseState (*pkState);   
            rkPC.CancelRunning();
            ++iClosedQuest;

            LPCHARACTER ch = CHARACTER_MANAGER::instance().FindByPID (itPC->first);
            if (!ch)
                continue;

            LPCHARACTER npc = ch->GetQuestNPC();
            if (npc && !npc->IsPC() && npc->GetQuestNPCID() == ch->GetPlayerID())
                npc->SetQuestNPCID (0);
            ch->SetQuestNPCID (0);

            if (ch->GetDesc())
            {
                const char* c_szDone = "[DONE]";
                struct ::packet_script ps;
                ps.header = HEADER_GC_SCRIPT;
                ps.skin = QUEST_SKIN_NOWINDOW;
                ps.src_size = strlen (c_szDone);
                ps.size = ps.src_size + sizeof (struct ::packet_script);

                TEMP_BUFFER buf;
                buf.write (&ps, sizeof (struct ::packet_script));
                buf.write (c_szDone, ps.src_size);
                ch->GetDesc()->Packet (buf.read_peek(), buf.size());
            }
        }
        sys_log (0, "QUEST_RELOAD: %d acik quest kapatildi", iClosedQuest);
#endif
        lua_close (L);

Aynı fonksiyonda ara;

Kod:
    m_mapTimerID.clear();

DEĞİŞTİR;

Kod:
#ifndef TETRA_SAFE_QUEST_RELOAD
        m_mapTimerID.clear();
#endif

Aynı fonksiyonun sonunda ARA;

Kod:
            m_mapNPC[dwVnum].Set (dwVnum, buf);
        }

Altına ekle (fonksiyonun kapanış } işaretinden önce)

Kod:
#ifdef TETRA_SAFE_QUEST_RELOAD
        for (map<string, unsigned int>::iterator itTimer = m_mapTimerID.begin(); itTimer != m_mapTimerID.end(); ++itTimer)
            m_mapNPC[itTimer->second].Set (itTimer->second, itTimer->first);
#endif


game/src/questmanager.cpp

ARA;

Kod:
GetCurrentCharacterPtr()->GetDesc()->Packet (buf.read_peek(), buf.size());

DEĞİŞTİR;

Kod:
#ifdef TETRA_SAFE_QUEST_RELOAD
        LPCHARACTER pkScriptChr = GetCurrentCharacterPtr();
        if (!pkScriptChr || !pkScriptChr->GetDesc())
        {
            ClearScript();
            return;
        }
        pkScriptChr->GetDesc()->Packet (buf.read_peek(), buf.size());
#else
        GetCurrentCharacterPtr()->GetDesc()->Packet (buf.read_peek(), buf.size());
#endif
 

Şu an konuyu görüntüleyenler (Toplam : 1, Üye: 0, Misafir: 1)

Geri
Üst