боты русифицированы
This commit is contained in:
@@ -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]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user