Skocz do zawartości
Masz już aplikację Sharegon?

Odkryj wszystkie możliwości. Dowiedz się więcej

Sharegon.pl

Zainstaluj aplikację Sharegon i korzystaj z powiadomień push oraz licznika nowych aktywności bezpośrednio z ekranu głównego.

Aby zainstalować tę aplikację na iOS i iPadOS.
  1. Tap the Share icon in Safari
  2. Przewiń menu i stuknij Dodaj do ekranu początkowego.
  3. Stuknij Dodaj w prawym górnym rogu.
Zainstaluj aplikację Sharegon na Androidzie
  1. Otwórz Sklep Google Play na swoim smarfonie.
  2. Wyszukaj „Sharegon” w pasku wyszukiwania.
  3. Stuknij „Zainstaluj”, aby pobrać aplikację.

Entity Preloading - Extensive version.

Nieaktywny

Featured Replies

Opublikowano

Inaczej mała optymalizacja załadowania map w wersji rozszerzonej, na devie jest tylko podstawowa od amuna

src:
- commonDefines.h 
dodaj: 

#define ENTITY_PRELOADING



char_manager.cpp
poszukaj: 

LPCHARACTER CHARACTER_MANAGER::SpawnMob(DWORD dwVnum, long lMapIndex, long x, long y, long z, bool bSpawnMotion, int iRot, bool bShow)



przed:     

return (ch);



dodaj: 

#ifdef ENTITY_PRELOADING
    //@Amun: or be specific, like if(ch->ispet, mount, whatever)
    if (!ch->IsPC() && !ch->IsGoto() && !ch->IsWarp() && !ch->IsDoor())
        SECTREE_MANAGER::Instance().ExtendPreloadedEntitiesMap(lMapIndex, pkMob->m_table.dwVnum);
#endif



input_login.cpp
poszukaj: 

}

void CInputLogin::Empire(LPDESC d, const char * c_pData)



dodaj nad: 

#ifdef ENTITY_PRELOADING
    SECTREE_MANAGER::Instance().SendPreloadEntitiesPacket(ch);
#endif


packet.h
poszukaj:

HEADER_GC_RESPOND_CHANNELSTATUS            = 210,


dodaj pod:
// jak masz zajęte miejsce 211 to zmień na inne byle żeby pasowało w src i bin.

#ifdef ENTITY_PRELOADING
    HEADER_GC_PRELOAD_ENTITIES                = 211,
#endif


przed:

#pragma pack()
#endif



dodaj:

#ifdef ENTITY_PRELOADING
/*** HEADER_GC_PRELOAD_ENTITIES ***/
typedef struct packet_preload_entities
{
    uint8_t header;
    uint16_t size;
    uint16_t count;
} TPacketGCPreloadEntities;
#endif


sectree_manager.cpp

poszukaj:

pkMapSectree->Build();



dodaj pod:

#ifdef ENTITY_PRELOADING
            GeneratePreloadedEntitiesMap(iIndex, pkMapSectree);
#endif


poszukaj:

size_t SECTREE_MANAGER::GetMonsterCountInMap(long lMapIndex, DWORD dwVnum)
{
    LPSECTREE_MAP sectree = SECTREE_MANAGER::instance().GetMap(lMapIndex);

    if (NULL != sectree)
    {
        struct FCountSpecifiedMonster f(dwVnum);

        sectree->for_each( f );

        return f.cnt;
    }

    return 0;
}



dodaj pod:

#ifdef ENTITY_PRELOADING
void SECTREE_MANAGER::GeneratePreloadedEntitiesMap(int32_t mapIndex, LPSECTREE_MAP lpMapSectree)
{
    if (m_preloadedEntities.find(mapIndex) == m_preloadedEntities.end())
    {
        m_preloadedEntities.insert({ mapIndex, {} });

        auto lmbd = [&mapIndex, this](LPENTITY ent) {
            this->m_preloadedEntities.at(mapIndex).emplace((((LPCHARACTER)ent)->GetRaceNum()));
            };
        lpMapSectree->for_each(lmbd);

        // log unique races
        for (int32_t i : m_preloadedEntities.at(mapIndex))
            sys_log(0, "ENTITY_PRELOADING: [map: %d], [entity race: %d]", mapIndex, i);
    }
}

void SECTREE_MANAGER::ExtendPreloadedEntitiesMap(int32_t mapIndex, uint32_t mob_race)
{
    auto it = m_preloadedEntities.find(mapIndex);
    if (it == m_preloadedEntities.end())// don't create new maps if they're not available from the beginning
        return;

    if ((it->second.emplace(mob_race)).second)
        sys_log(0, "ENTITY_PRELOADING: extended [map: %d], with [entity race: %d]", mapIndex, mob_race);
}

void SECTREE_MANAGER::SendPreloadEntitiesPacket(LPCHARACTER ch)
{
    LPDESC d = ch->GetDesc();
    if (!d)
        return;

    long lMapIndex = ch->GetMapIndex();

    if (m_preloadedEntities.find(lMapIndex) == m_preloadedEntities.end())
        return;

    std::unordered_set<uint32_t>& s = m_preloadedEntities.at(lMapIndex);

    if (s.empty())
        return;

    {
        TEMP_BUFFER buf;
        TPacketGCPreloadEntities pack{};
        pack.header = HEADER_GC_PRELOAD_ENTITIES;
        pack.count = s.size();

        for (const auto& it : s)
            buf.write(&it, sizeof(uint32_t));

        pack.size = sizeof(pack) + buf.size();

        d->BufferedPacket(&pack, sizeof(TPacketGCPreloadEntities));
        d->Packet(buf.read_peek(), buf.size());
    }
}
#endif


sectree_manager.h

w includach daj:
 

#ifdef ENTITY_PRELOADING
#include <unordered_map>
#include <unordered_set>
#endif


poszukaj:

        size_t        GetMonsterCountInMap(long lMpaIndex, DWORD dwVnum);


dodaj pod:
 

#ifdef ENTITY_PRELOADING
        void        GeneratePreloadedEntitiesMap(int32_t mapIndex, LPSECTREE_MAP lpMapSectree);
        void        ExtendPreloadedEntitiesMap(int32_t mapIndex, uint32_t mob_race);
        void        SendPreloadEntitiesPacket(LPCHARACTER ch);
#endif


szukaj:         
 

PrivateIndexMapType next_private_index_map_;


dodaj pod:
 

#ifdef ENTITY_PRELOADING
        std::unordered_map<int32_t, std::unordered_set<uint32_t>> m_preloadedEntities;
#endif


przechodzimy teraz do bin

w locale_inc.h daj:

#define ENTITY_PRELOADING


packet.h

szukaj:

HEADER_GC_RESPOND_CHANNELSTATUS                = 210,


dodaj pod:

#ifdef ENTITY_PRELOADING
    HEADER_GC_PRELOAD_ENTITIES                    = 211,
#endif


przed:

#pragma pack(pop)


dodaj nad:

#ifdef ENTITY_PRELOADING
/*** HEADER_GC_PRELOAD_ENTITIES ***/
typedef struct packet_preload_entities
{
    uint8_t header;
    uint16_t size;
    uint16_t count;
} TPacketGCPreloadEntities;
#endif


PythonNetworkStream.cpp

szukaj:

            Set(HEADER_GC_DRAGON_SOUL_REFINE,        CNetworkPacketHeaderMap::TPacketType(sizeof(TPacketGCDragonSoulRefine), STATIC_SIZE_PACKET));


dodaj pod:

#ifdef ENTITY_PRELOADING
            Set(HEADER_GC_PRELOAD_ENTITIES, CNetworkPacketHeaderMap::TPacketType(sizeof(TPacketGCPreloadEntities), DYNAMIC_SIZE_PACKET));
#endif


PythonNetworkStream.h

szukaj:
 

        bool RecvWarpPacket();


dodaj pod:
 

#ifdef ENTITY_PRELOADING
        bool RecvPreloadEntitiesPacket();
#endif


PythonNetworkStreamPhaseGame.cpp

szukaj:
 

            case HEADER_GC_DRAGON_SOUL_REFINE:
                ret = RecvDragonSoulRefine();
                break;


dodaj pod:
 

#ifdef ENTITY_PRELOADING
            case HEADER_GC_PRELOAD_ENTITIES:
                ret = RecvPreloadEntitiesPacket();
                break;
#endif


dodaj na koncu:

#ifdef ENTITY_PRELOADING
bool CPythonNetworkStream::RecvPreloadEntitiesPacket()
{
    TPacketGCPreloadEntities pack{};
    if (!Recv(sizeof(pack), &pack))
        return false;

    assert(int32_t(pack.size) - sizeof(pack) == pack.count * sizeof(uint32_t) && "HEADER_GC_PRELOAD_ENTITIES");

    uint32_t dwEntityRace = 0;
    CInstanceBase::SCreateData d{};
    CPythonCharacterManager& rkChrMgr = CPythonCharacterManager::Instance();

    for (uint16_t i = 0; i < pack.count; i++)
    {
        if (!Recv(sizeof(uint32_t), &dwEntityRace))
            return false;

#ifdef _DEBUG
        TraceError("Preloading %d", dwEntityRace);
#endif
        d.m_dwRace = dwEntityRace;
        d.m_dwVID = dwEntityRace;

        if (rkChrMgr.CreateInstance(d))//create the entity, force it to load absolutely everything
            rkChrMgr.DeleteInstance(dwEntityRace);// now get rid of it
        else
        {
            //TraceError("Failed to preload race %d", dwEntityRace);
        }
    }

    return true;
}
#endif

 

  • 3 tygodnie później...
Opublikowano
W dniu 12.01.2025 o 16:07, Azurri napisał(a):

Inaczej mała optymalizacja załadowania map w wersji rozszerzonej, na devie jest tylko podstawowa od amuna

Szczerze nie dopatrzyłem się zmian względem wersji Anuma Github 

Trochę edytowałem główną funkcje aby lepiej wpasowywała się w nowe standardy c++ 

  • użyto dynamic_cast, który sprawdza, czy rzutowanie jest możliwe. Jeśli nie, zwraca nullptr, co zapobiega błędom.
  • Lepsza inicjalizacja mapy użyto prostszego zapisu m_preloadedEntities[mapIndex] = std::unordered_set<uint32_t>()
  • Dane były zapisywane bezpośrednio do TEMP_BUFFER, co mogło prowadzić do wielokrotnej alokacji pamięci. W nowej wersji użyto std::vector<uint8_t>, który najpierw zbiera dane, a potem przekazuje je do TEMP_BUFFER (w moim przypadku było 950 rekordów zapisu Entities)
  • Dodano warunek ' if ' 
  • Nowa wersja unika potencjalnych problemów z pamięcią dzięki użyciu std::vector i dynamic_cast, co zmniejsza ryzyko wycieków pamięci i błędów.

Server/game/src/sectree_manager.cpp

#ifdef ENABLE_ENTITY_PRELOADING
void SECTREE_MANAGER::GeneratePreloadedEntitiesMap(int32_t mapIndex, LPSECTREE_MAP lpMapSectree) {
	if (m_preloadedEntities.find(mapIndex) == m_preloadedEntities.end()) {
		m_preloadedEntities[mapIndex] = std::unordered_set<uint32_t>();
		auto lmbd = [&mapIndex, this](LPENTITY ent) {
			if (auto ch = dynamic_cast<LPCHARACTER>(ent)) {
				this->m_preloadedEntities.at(mapIndex).emplace(ch->GetRaceNum());
			}
		};
		lpMapSectree->for_each(lmbd);
		for (const auto& race : m_preloadedEntities.at(mapIndex)) {
			sys_log(0, "ENTITY_PRELOADING: [map: %d], [entity race: %d]", mapIndex, race);
		}
	}
}
void SECTREE_MANAGER::ExtendPreloadedEntitiesMap(int32_t mapIndex, uint32_t mob_race) {
	auto it = m_preloadedEntities.find(mapIndex);
	if (it == m_preloadedEntities.end()) return;
	if (it->second.emplace(mob_race).second) {
		sys_log(0, "ENTITY_PRELOADING: extended [map: %d], with [entity race: %d]", mapIndex, mob_race);
	}
}
void SECTREE_MANAGER::SendPreloadEntitiesPacket(LPCHARACTER ch) {
    if (!ch) return;
    auto d = ch->GetDesc();
    if (!d) return;
    auto lMapIndex = ch->GetMapIndex();
    auto it = m_preloadedEntities.find(lMapIndex);
    if (it == m_preloadedEntities.end() || it->second.empty()) return;
    // rezerwacja pamięci
    std::vector<uint8_t> tempBuffer;
    tempBuffer.reserve(it->second.size() * sizeof(uint32_t));
    // Zapisz dane do bufora
    for (const auto& race : it->second) {
        const uint8_t* raceBytes = reinterpret_cast<const uint8_t*>(&race);
        tempBuffer.insert(tempBuffer.end(), raceBytes, raceBytes + sizeof(uint32_t));
    }

    TEMP_BUFFER buf;
    buf.write(tempBuffer.data(), tempBuffer.size());
    TPacketGCPreloadEntities pack{};
    pack.header = HEADER_GC_PRELOAD_ENTITIES;
    pack.count = static_cast<uint16_t>(it->second.size());
    pack.size = sizeof(pack) + buf.size();

    d->BufferedPacket(&pack, sizeof(pack));
    d->Packet(buf.read_peek(), buf.size());
}
#endif


UserInterface/PythonNetworkStreamPhaseGame.cpp

#ifdef ENABLE_ENTITY_PRELOADING
bool CPythonNetworkStream::RecvPreloadEntitiesPacket() {
    TPacketGCPreloadEntities pack{};
    if (!Recv(sizeof(pack), &pack)) {
		Tracef("Failed to receive preload entities packet header");
        return false;
    }
    if (static_cast<int32_t>(pack.size) - sizeof(pack) != pack.count * sizeof(uint32_t)) {
		Tracef("Invalid preload entities packet size");
        return false;
    }
    uint32_t dwEntityRace = 0;
    CInstanceBase::SCreateData d{};
    auto& rkChrMgr = CPythonCharacterManager::Instance();
    for (uint16_t i = 0; i < pack.count; ++i) {
        if (!Recv(sizeof(uint32_t), &dwEntityRace)) {
			Tracef("Failed to receive entity race data");
            return false;
        }
 #ifdef _DEBUG
        TraceError("Preloading %d", dwEntityRace);
 #endif
        d.m_dwRace = dwEntityRace;
        d.m_dwVID = dwEntityRace;
        if (rkChrMgr.CreateInstance(d)) {
            rkChrMgr.DeleteInstance(dwEntityRace);
        } else {
 #ifdef _DEBUG
            TraceError("Failed to preload race %d", dwEntityRace);
 #endif
        }
    }
    return true;
}
#endif

 

  • 9 miesięcy temu...
  • 1 miesiąc temu...

Jeśli chcesz dodać odpowiedź, zaloguj się lub zarejestruj nowe konto

Konto

Nawigacja

Skonfiguruj powiadomienia push w przeglądarce.

Chrome (Android)
  1. Stuknij ikonę kłódki obok paska adresu.
  2. Wybierz Uprawnienia → Powiadomienia.
  3. Dostosuj swoje preferencje.
Chrome (Desktop)
  1. Kliknij ikonę kłódki na pasku adresu.
  2. Wybierz Ustawienia witryny.
  3. Znajdź Powiadomienia i dostosuj swoje preferencje.