From 0bc9b016d6108777108247271bdf7b3a6d59988a Mon Sep 17 00:00:00 2001 From: SylvaniaCore deploy Date: Mon, 31 Aug 2026 10:26:10 +0200 Subject: [PATCH] Commandes : .npc near faisait tomber le serveur MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signale en jeu : « la commande .npc near fait planter le serveur ». L hypothese de l utilisateur etait proche : ce n est pas le rayon en soi, c est l absence de plafond. La requete preparee WORLD_SEL_CREATURE_NEAREST n a AUCUNE limite : SELECT ... FROM creature WHERE map = ? AND (POW(x-?,2)+POW(y-?,2)+POW(z-?,2)) <= ? ORDER BY order_ Elle calcule trois puissances sur les 384 000 lignes de la table, sans index utilisable, puis la boucle d affichage envoie UN message de discussion PAR RESULTAT. Avec un rayon large cela represente des dizaines de milliers de paquets pour une seule commande, ce qui sature la session. La requete etant partagee avec d autres commandes, on pose les garde-fous cote appelant : rayon plafonne a 500, affichage plafonne a 150 lignes. Les omissions sont ANNONCEES et non silencieuses : la commande indique combien de resultats n ont pas ete montres et invite a reduire le rayon. Un plafond muet ferait croire a une recherche complete. Co-Authored-By: Claude Opus 5 --- src/server/scripts/Commands/cs_npc.cpp | 40 ++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp index e8ffe26..809da23 100644 --- a/src/server/scripts/Commands/cs_npc.cpp +++ b/src/server/scripts/Commands/cs_npc.cpp @@ -805,8 +805,37 @@ public: static bool HandleNpcNearCommand(ChatHandler* handler, char const* args) { + // ============================================================= + // SylvaniaCore : .npc near faisait tomber le serveur. + // + // SIGNALE EN JEU : « la commande .npc near fait planter le + // serveur ». La requete preparee WORLD_SEL_CREATURE_NEAREST n'a + // AUCUNE limite : elle calcule trois puissances sur les 384 000 + // lignes de la table creature, sans index utilisable, puis la + // boucle ci-dessous envoie UN message de discussion par resultat. + // Avec un rayon large, cela represente des dizaines de milliers + // de paquets pour une seule commande. + // + // Deux garde-fous, la requete etant partagee avec d'autres + // commandes : + // - le rayon est plafonne ; + // - le nombre de lignes affichees l'est aussi, et l'on ANNONCE + // combien ont ete omises plutot que de tronquer en silence. + // ============================================================= + float const RAYON_MAX = 500.0f; + uint32 const LIGNES_MAX = 150; + float distance = (!*args) ? 10.0f : float((atof(args))); + if (distance > RAYON_MAX) + { + handler->PSendSysMessage("Rayon ramene de %.0f a %.0f : au-dela la recherche parcourt toute la table et sature la session.", distance, RAYON_MAX); + distance = RAYON_MAX; + } + if (distance <= 0.0f) + distance = 10.0f; + uint32 count = 0; + uint32 omises = 0; Player* player = handler->GetSession()->GetPlayer(); @@ -838,14 +867,21 @@ public: if (!creatureTemplate) continue; - handler->PSendSysMessage(LANG_CREATURE_LIST_CHAT, std::to_string(guid).c_str(), entry, std::to_string(guid).c_str(), creatureTemplate->Name.c_str(), x, y, z, o, mapId); - ++count; + if (count > LIGNES_MAX) + { + ++omises; + continue; + } + + handler->PSendSysMessage(LANG_CREATURE_LIST_CHAT, std::to_string(guid).c_str(), entry, std::to_string(guid).c_str(), creatureTemplate->Name.c_str(), x, y, z, o, mapId); } while (result->NextRow()); } handler->PSendSysMessage(LANG_COMMAND_NEAR_NPC_MESSAGE, distance, count); + if (omises) + handler->PSendSysMessage("%u resultats supplementaires non affiches, plafond %u. Reduisez le rayon pour les voir.", omises, LIGNES_MAX); return true; }