- Mesaj
- 87
- Çözümler
- 3
- Beğeni
- 36
- Puan
- 714
- Ticaret Puanı
- 0
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;
common/service.h
EKLE;
game/src/packet.h
ARAT;
GG paketlerinin en altına ekle. (Numaraya dikkat edin, GG paketlerinin kullanmadığı bir numara olmalıdır.
game/src/packet_info.cpp
ARA;
Fonksiyonun sonuna ekle;
game/src/input_p2p.cpp
ARA;
İçindeki switch (bHeader) bloğunu bulun. Dosyanın başında #include "questmanager.h" olduğundan emin olun.
EKLE;
game/src/cmd_gm.cpp
ARA;
ALTINA EKLE (BREAK satırından hemen önce)
game/src/questmanager.cpp
ARA;
DEĞİŞTİR;
Aynı fonksiyonda ara;
DEĞİŞTİR;
Aynı fonksiyonun sonunda ARA;
Altına ekle (fonksiyonun kapanış } işaretinden önce)
game/src/questmanager.cpp
ARA;
DEĞİŞTİR;
Ö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 EKLE (BREAK 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