[Mini Info] QuestManager Kill ve CancelServerTimers

  • Konuyu açan Konuyu açan nyami
  • Açılış Tarihi Açılış Tarihi
  • Yanıt Yanıt 4
  • Gösterim Gösterim 168

nyami

ZeRo
Premium Üye
Geliştirici
Yardımsever Üye
MT Üye
Mesaj
572
Çözümler
38
Beğeni
894
Puan
929
Ticaret Puanı
0
Kendinizde denemeden uygulamayın.


İlk olarak CancelServerTimers ile ilgili bir core sorunu için küçük bir değişiklik yapalım. Olayın nasıl tetiklendiğini bende çözemedim. Şeytan kulesinde 4. katta town attım ve aşağıdaki gibi core verdi. Bir şekilde timer sıkışması oldu ama ben bulamadım.

1724181197047.webp


game/questmanager.cpp:
Genişlet Daralt Kopyala
//Bul
    void CQuestManager::CancelServerTimers (DWORD arg)
    {
        itertype (m_mapServerTimer) it = m_mapServerTimer.begin();
        for (; it != m_mapServerTimer.end(); ++it)
        {
            if (it->first.second == arg)
            {
                LPEVENT event = it->second;
                event_cancel (&event);
                m_mapServerTimer.erase (it);
            }
        }
    }

//Değiştir
    void CQuestManager::CancelServerTimers(DWORD arg)
    {
        itertype(m_mapServerTimer) it = m_mapServerTimer.begin();
        for (; it != m_mapServerTimer.end();) {
            if (it->first.second == arg) {
                LPEVENT event = it->second;
                event_cancel(&event);
                m_mapServerTimer.erase(it++);
            }
            else {
                ++it;
            }
        }
    }


---------------------------------

Burası Mainline alt yapı kullananlar içindir.

void CQuestManager::Kill(unsigned int pc, unsigned int npc) içerisinde m_mapNPC[npc].OnKill(*pPC); bu kısım için marty nin //@fixme109 unu uyguladıktan sonra en basitinden kulede kestiğiniz bazı moblar bile saymamaya başlıyor. Bunu mümkünse kullanmayın. Bunun yerine aşağıdakini kullanmaya çalışın.

game/questmanager.cpp:
Genişlet Daralt Kopyala
    void CQuestManager::Kill(unsigned int pc, unsigned int npc)
    {
        //m_CurrentNPCRace = npc;
        PC * pPC;

        sys_log(0, "CQuestManager::Kill QUEST_KILL_EVENT (pc=%d, npc=%d)", pc, npc);

        if ((pPC = GetPC(pc)))
        {
            if (!CheckQuestLoaded(pPC))
                return;

            m_mapNPC[npc].OnKill(*pPC);

            LPCHARACTER ch = GetCurrentCharacterPtr();
            LPPARTY pParty = ch->GetParty();
            LPCHARACTER leader = pParty ? pParty->GetLeaderCharacter() : ch;

            if (leader)
            {
                m_pCurrentPartyMember = ch;

                if (m_mapNPC[npc].OnPartyKill(*GetPC(leader->GetPlayerID())))
                    return;

                pPC = GetPC(pc);
            }

                if (npc != QUEST_NO_NPC)
                    m_mapNPC[QUEST_NO_NPC].OnKill(*pPC);
                return;

            if (leader)
            {
                m_pCurrentPartyMember = ch;

                if (m_mapNPC[npc].OnPartyKill(*GetPC(leader->GetPlayerID())))
                    return;

                pPC = GetPC(pc);
            }

            if (m_mapNPC[QUEST_NO_NPC].OnKill(*pPC))
                return;

            if (leader)
            {
                m_pCurrentPartyMember = ch;
                m_mapNPC[QUEST_NO_NPC].OnPartyKill(*GetPC(leader->GetPlayerID()));
            }
        }
        else
            sys_err("QUEST: no such pc id : %d", pc);
    }
---------------------------------

@MT2Dev hocam sizin de bu konular hakkında yorumunuzu merak ediyorum.
 
Selamlar, bu sorun çok yüksek ihtimalle kullandığınız derleyiciyi güncelledikten sonra yaşayabileceğiniz bir problem, yeni sürümlerde bu fonksiyon beklenildiği gibi çalışmaz. GCC13'e ilk geçtiğimde benzer bir sorunla karşılaştım, kullandığım çözüm;

ÖNEMLİ NOT: Bu kodu derleyebilmek için minimum std:c++17 desteği gereklidir.

questmanager.cpp:
Genişlet Daralt Kopyala
    void CQuestManager::CancelServerTimers (DWORD arg)   // DevFix 22
    {
        auto erase_check = [&](auto&& it)
        {
            if (it.first.second == arg)
            {
                auto event = it.second;
                event_cancel (&event);
            }
            return it.first.second == arg;
        };

        std::erase_if (m_mapServerTimer, erase_check);
    }

Ekstra olarak bir düzenleme daha vereyim;

questlua_global.cpp:
Genişlet Daralt Kopyala
// CLEAR_SERVER_TIMER_RENEWAL
    int _clear_server_timer (lua_State* L)   // DevFix 19
    {
        CQuestManager& q = CQuestManager::instance();
        const char* name = lua_tostring (L, 1);
        DWORD arg = (DWORD) lua_tonumber (L, 2);

        if (name && arg)
        {
            q.ClearServerTimer (name, arg);
        }
        else
        {
            sys_err ("QUESTLUA_GLOBAL: Wrong argument on ClearServerTimer!");
        }

        return 0;
    }
// END_OF_CLEAR_SERVER_TIMER_RENEWAL
 
Selamlar, bu sorun çok yüksek ihtimalle kullandığınız derleyiciyi güncelledikten sonra yaşayabileceğiniz bir problem, yeni sürümlerde bu fonksiyon beklenildiği gibi çalışmaz. GCC13'e ilk geçtiğimde benzer bir sorunla karşılaştım, kullandığım çözüm;

ÖNEMLİ NOT: Bu kodu derleyebilmek için minimum std:c++17 desteği gereklidir.

questmanager.cpp:
Genişlet Daralt Kopyala
    void CQuestManager::CancelServerTimers (DWORD arg)   // DevFix 22
    {
        auto erase_check = [&](auto&& it)
        {
            if (it.first.second == arg)
            {
                auto event = it.second;
                event_cancel (&event);
            }
            return it.first.second == arg;
        };

        std::erase_if (m_mapServerTimer, erase_check);
    }

Ekstra olarak bir düzenleme daha vereyim;

questlua_global.cpp:
Genişlet Daralt Kopyala
// CLEAR_SERVER_TIMER_RENEWAL
    int _clear_server_timer (lua_State* L)   // DevFix 19
    {
        CQuestManager& q = CQuestManager::instance();
        const char* name = lua_tostring (L, 1);
        DWORD arg = (DWORD) lua_tonumber (L, 2);

        if (name && arg)
        {
            q.ClearServerTimer (name, arg);
        }
        else
        {
            sys_err ("QUESTLUA_GLOBAL: Wrong argument on ClearServerTimer!");
        }

        return 0;
    }
// END_OF_CLEAR_SERVER_TIMER_RENEWAL
Değerli yorumunuz için teşekkür ederim. Düşük seviyede ki kodlamanın güncel derleyicide patlamasını yaşamışım anlaşılan 😅.
 
backtrace ile daha iyi geri izleme yapabilirsin. Core de sanırım bellekte geçersiz bir adrese erişmekten bahsediyor.
 
backtrace ile daha iyi geri izleme yapabilirsin. Core de sanırım bellekte geçersiz bir adrese erişmekten bahsediyor.
marty nin fixi saymama olayına girince zindan sürekli reset atmaya başladı, town atınca core de geldi arkasından. Yaklaşık 1 saat ince ince takip edince timer da bunu fark ettim, kat sıfırlanma sebebinide marty fix kaynaklandığını buldum.
 
Üst