11-=test
Призрак «слитых кодов»: почему локализация ломается во всех эмуляторах
«Лирико-инженерная заметка о старой легенде, новых серверах и древнем баге, который путешествует между проектами как чемодан без ручки…»
Есть у админов MMO-серверов особая музыка. Не та, что в рейде под вайпы, а другая — тихий скрип табличек в базе данных, шелест дампов и тяжёлый вздох, когда очередной NPC снова улыбается тебе на английском.
Легенда и реальность
Многие верят, что причина всех бед — в «слитых кодах Blizzard». Но чаще всего за мистикой скрывается обычная ошибка индекса. Одинаковые шаблоны решения кочуют из ядра в ядро, превращаясь в одинаковые шаблоны проблем.
Один маленький индекс, который ломал ruRU
Финальная развязка оказалась классической: неправильный доступ к строке. Код пытался взять данные так, будто локали лежат в массиве строго по порядку. Для английского (0) это работало, но на русской локали (8) система «промахивалась».
if (questGreeting->Greeting.size() > (locale))
strGreeting = questGreeting->Greeting[locale];
else
strGreeting = questGreeting->Greeting[DEFAULT_LOCALE];
Решение: Возвращение к здравому смыслу
Мы заставили сервер использовать стандартный механизм ядра ObjectMgr, который умеет правильно извлекать нужную локаль из контейнера.
strGreeting = questGreeting->Greeting[DEFAULT_LOCALE];
if (locale != LOCALE_enUS)
ObjectMgr::GetLocaleString(questGreeting->Greeting, locale, strGreeting);
Итог
Когда «английские хвосты» снова полезут из всех щелей, не ищите заговор. Ищите источник. Quest Greeting, Gossip или BroadcastText? Как только вы найдете источник, у вас появится власть над сервером.