diff --git a/Changelog.txt b/Changelog.txt index eb6bead1f..266fff30b 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -4077,3 +4077,6 @@ When setting a property like MORE to the a spell or skill defname, trying to rea - Changed: Object timers are now saved in worldsave files as TIMERMS, to avoid ambiguity and reliance on git build number to determine if TIMER expressed a number in seconds or milliseconds. - Changed: Added 5 seconds timeout to DNS hostname resolution at startup (avoid getting stuck when connectivity is enabled but not working). - Changed: CANMASK formatted in worldsave files as hexadecimal number, instead of decimal. + +29-11-2025, canerksk +- Added: Added Itemlist.* and Charlist.* function for server. The function is based on the guildstones.* function. It is a function that outputs all items or chars on the server. It can be used with serv.charlist/itemlist.count as serv.charlist/itemlist.0.name/p/uid/. diff --git a/src/game/CServerConfig.cpp b/src/game/CServerConfig.cpp index f62fceb54..9b6069031 100644 --- a/src/game/CServerConfig.cpp +++ b/src/game/CServerConfig.cpp @@ -1926,6 +1926,90 @@ bool CServerConfig::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * return true; } + if (!strnicmp(ptcKey, "CHARLIST.", 9)) + { + lpctstr pszCmd = ptcKey + 9; + CChar *pChar = nullptr; + size_t x = 0; + + if (!strnicmp(pszCmd, "COUNT", 5)) + { + for (size_t i = 0; i < g_World.m_Chars.size(); ++i) + { + pChar = g_World.m_Chars[i].get(); + if (pChar == NULL) + continue; + if (!pChar->IsDeleted()) + ++x; + } + + sVal.FormatSTVal(x); + return true; + } + + size_t iNumber = Exp_GetVal(pszCmd); + SKIP_SEPARATORS(pszCmd); + sVal.SetValFalse(); + + for (size_t i = 0; i < g_World.m_Chars.size(); ++i) + { + pChar = g_World.m_Chars[i].get(); + if (pChar == nullptr) + continue; + if (!pChar->IsDeleted()) + { + if (iNumber == x) + return pChar->r_WriteVal(pszCmd, sVal, pSrc); + ++x; + } + } + + return true; + } + + + if (!strnicmp(ptcKey, "ITEMLIST.", 9)) + { + lpctstr pszCmd = ptcKey + 9; + CItem *pItem = nullptr; + size_t x = 0; + + if (!strnicmp(pszCmd, "COUNT", 5)) + { + for (size_t i = 0; i < g_World.m_Items.size(); ++i) + { + pItem = g_World.m_Items[i].get(); + if (pItem == NULL) + continue; + if (!pItem->IsDeleted()) + ++x; + } + + sVal.FormatSTVal(x); + return true; + } + + size_t iNumber = Exp_GetVal(pszCmd); + SKIP_SEPARATORS(pszCmd); + sVal.SetValFalse(); + + for (size_t i = 0; i < g_World.m_Items.size(); ++i) + { + pItem = g_World.m_Items[i].get(); + if (pItem == nullptr) + continue; + if (!pItem->IsDeleted()) + { + if (iNumber == x) + return pItem->r_WriteVal(pszCmd, sVal, pSrc); + ++x; + } + } + + return true; + } + + if ( !strnicmp( ptcKey, "CLIENT.",7)) { ptcKey += 7; diff --git a/src/game/CWorld.cpp b/src/game/CWorld.cpp index 1b1299cc8..f186631fa 100644 --- a/src/game/CWorld.cpp +++ b/src/game/CWorld.cpp @@ -1402,6 +1402,8 @@ bool CWorld::LoadWorld() // Load world from script CWorldTickingList::ClearTickingLists(); m_Stones.clear(); + m_Items.clear(); + m_Chars.clear(); m_Multis.clear(); m_Parties.clear(); m_GMPages.clear(); @@ -1721,6 +1723,9 @@ void CWorld::Close() m_Stones.clear(); m_Multis.clear(); + m_Chars.clear(); + m_Items.clear(); + { #if MT_ENGINES std::unique_lock lock_su(_Ticker._vObjStatusUpdates.MT_CMUTEX); diff --git a/src/game/CWorld.h b/src/game/CWorld.h index ed8732c6a..02b2b4de6 100644 --- a/src/game/CWorld.h +++ b/src/game/CWorld.h @@ -177,6 +177,10 @@ extern class CWorld : public CScriptObj, public CWorldThread sl::unique_ptr_vector m_GMPages; // Owns current outstanding GM pages. (CGMPage) sl::unique_ptr_vector m_Stones; // Owns guild/town stones. (not saved array) + + sl::raw_ptr_view_vector m_Items; // world dynamic items + sl::raw_ptr_view_vector m_Chars; // world dynamic chars + sl::unique_ptr_vector m_Parties; // Owns all active parties. sl::raw_ptr_view_vector m_Multis; // World multis? sl::smart_ptr_view_vector m_TileTypes; // Links to CItemTypeDef items owned by g_Cfg.m_ResHash diff --git a/src/game/chars/CChar.cpp b/src/game/chars/CChar.cpp index 412f89309..9be70c818 100644 --- a/src/game/chars/CChar.cpp +++ b/src/game/chars/CChar.cpp @@ -266,6 +266,8 @@ CChar::CChar( CREID_TYPE baseID ) : ADDTOCALLSTACK("CChar::CChar"); g_Serv.StatInc( SERV_STAT_CHARS ); // Count created CChars. + g_World.m_Chars.emplace_back(this); + m_pArea = nullptr; m_pParty = nullptr; m_pClient = nullptr; // is the char a logged in player? @@ -368,6 +370,8 @@ CChar::~CChar() g_Serv.StatDec( SERV_STAT_CHARS ); + g_World.m_Chars.erase_element(this); + EXC_CATCH; } diff --git a/src/game/items/CItem.cpp b/src/game/items/CItem.cpp index 5b4e14fef..53704015a 100644 --- a/src/game/items/CItem.cpp +++ b/src/game/items/CItem.cpp @@ -146,6 +146,9 @@ CItem::CItem( ITEMID_TYPE id, CItemBase * pItemDef ) : ASSERT( pItemDef ); g_Serv.StatInc(SERV_STAT_ITEMS); + + g_World.m_Items.emplace_back(this); + m_type = IT_NORMAL; m_Attr = 0; m_CanUse = pItemDef->m_CanUse; @@ -279,6 +282,8 @@ CItem::~CItem() g_Serv.StatDec(SERV_STAT_ITEMS); + g_World.m_Items.erase_element(this); + EXC_CATCH; }