боты русифицированы

This commit is contained in:
2026-07-30 19:06:57 +04:00
parent 6f075133f7
commit 85adbe19da
26 changed files with 11211 additions and 28 deletions
@@ -17,6 +17,7 @@
#include "QuestDef.h"
#include "ScriptMgr.h"
#include "SharedDefines.h"
#include "WorldSession.h"
#include <cstdlib>
#include <string>
@@ -31,6 +32,8 @@ namespace MoonWell::PlayerGuide
return;
if (!player || !player->GetSession() || player->IsBeingTeleported())
return;
if (player->GetSession()->IsBot())
return;
Payload p = sPlayerGuideMgr->BuildFor(player);
std::string json = sPlayerGuideMgr->SerializeJson(p);
@@ -25,6 +25,29 @@ namespace MoonWell::PlayerGuide
// The mgr clamps its configured chunk size into a safe range.
constexpr std::size_t HARD_LIMIT = 250;
std::size_t Utf8ChunkSize(std::string_view body, std::size_t offset,
std::size_t budget)
{
std::size_t take = std::min(budget, body.size() - offset);
if (offset + take == body.size())
return take;
// A chunk must not end between a UTF-8 leading byte and one of
// its continuation bytes. Chat packet validation rejects such
// an individually invalid string before the addon can reassemble
// the complete JSON payload.
while (take > 0 &&
(static_cast<unsigned char>(body[offset + take]) & 0xC0) == 0x80)
{
--take;
}
// The configured budget is clamped to at least 64 bytes, so a
// valid UTF-8 code point always fits. Keep a defensive fallback
// for malformed input to guarantee forward progress.
return take > 0 ? take : std::min(budget, body.size() - offset);
}
void SendOneChunk(Player* player, std::string_view command,
uint32 seq, uint32 total, std::string_view body)
{
@@ -71,16 +94,20 @@ namespace MoonWell::PlayerGuide
return;
}
// Multi-chunk: split blindly by byte budget. JSON tolerates
// concatenation on the client.
uint32 total = static_cast<uint32>(
(body.size() + budget - 1) / budget);
uint32 seq = 1;
for (std::size_t off = 0; off < body.size(); off += budget, ++seq)
// Calculate UTF-8-safe slices first because backing up from a
// continuation byte can increase the number of chunks.
std::vector<std::string_view> chunks;
for (std::size_t off = 0; off < body.size();)
{
std::size_t take = std::min(budget, body.size() - off);
SendOneChunk(player, command, seq, total,
std::string_view(body.data() + off, take));
std::size_t take = Utf8ChunkSize(body, off, budget);
chunks.emplace_back(body.data() + off, take);
off += take;
}
uint32 total = static_cast<uint32>(chunks.size());
for (uint32 i = 0; i < total; ++i)
{
SendOneChunk(player, command, i + 1, total, chunks[i]);
}
}