Сохранить воспоминания

2026-09-29 - EVE Online Team

Работа по переводу клиента и сервера EVE Online с Python 2 на Python 3 в рамках инициативы «Эволюция EVE» продолжается. Мы делаем это, чтобы у игры был прочный фундамент и чтобы её можно было развивать ещё много лет.

Архивная палата

В этом выпуске «Эволюция EVE» речь пойдёт о памяти NPC-агентов: о том, как она справляется с бюрократией учёта примерно 100 000 заданий, выдаваемых каждый день, и о некоторых интересных сложностях, которые она создаёт и которые в будущем могут коснуться игроков.

Под «агентами» в этой статье понимаются NPC-агенты, населяющие EVE Online: те милые персонажи, которые (порой довольно бесцеремонно) просят вас за вознаграждение перевезти их хлам на другую станцию, устранить очередную пиратскую угрозу или в который раз спасти бедную Девицу.

Начнём с простого

Мы знаем, что вы любите технические подробности, так что скоро углубимся в детали. А для тех, кому нужна только краткая выжимка, вот главное:

  • В рамках модернизации EVE Online и перехода на Python 3 нужно изменить способ хранения данных NPC-агентов. Учёт заданий и других взаимодействий с агентами будет перестроен «за кулисами». Для этого придётся удалить часть старых данных, а остальные преобразовать в более долговечный формат.

    • Этот процесс будет по большей части незаметен. Единственное, что вы можете заметить, — это судьба старого прогресса по заданиям, сохранённого до 29 сентября 2026 года.

  • Ваши отношения с NPC в безопасности, а все агенты, с которыми вы уже общаетесь, останутся доступными, даже если вы не заходите в игру или у вас сейчас нет омега-статуса. Вы не потеряете никакого прогресса.

  • Если начиная с сегодняшнего дня вы запросите у агента новое задание (или выполните/провалите текущее), прогресс по этому заданию будет автоматически перенесён в новую память.

  • Если вы взаимодействовали с агентом ДО сегодняшнего дня и не взаимодействуете с ним ПОСЛЕ, чтобы обновить этот прогресс, то после полного завершения перехода на Python 3 задания от этого агента будут стёрты.

    • Точных сроков этой очистки у нас пока нет — это лишь одна из частей огромного проекта по переходу на Python 3. Речь идёт не о днях, а скорее о месяцах. Когда этот момент приблизится, мы напомним о нём перед тем, как стирать память.

    • Если у вас есть предложенное/принятое задание, полученное ДО сегодняшнего дня, и потом вы не обратитесь к агенту, чтобы его выполнить, то в какой-то момент в будущем прогресс по такому заданию будет удалён.

    • Если ДО сегодняшнего дня вы договорились с агентом-исследователем о получении очков исследований, то потом вам нужно выполнить хотя бы одно задание этого агента, чтобы исследования продолжались. (Это нужно сделать один раз для каждого агента на каждом персонаже.) Со временем мы удалим все старые исследовательские проекты, которых с сегодняшнего дня никто не касался.

Словом, если вы регулярно выполняете задания агентов, продолжайте играть как обычно — для вас ничего не изменится. А если у вас есть любимые агенты (особенно агенты-исследователи), сделайте для них что-нибудь, чтобы они вас не забыли.

Теперь вы знаете основы. Если же вам хочется узнать больше о склонности агентов к накопительству и некоторых тайнах прошлого, читайте дальше…

Столкновение миров

Чтобы понять, что мы подразумеваем под памятью агентов, сначала нужен контекст. Если разложить проект перехода на Python 3 на части, получатся следующие крупные области:

  • Среда выполнения: исполняемые файлы клиента и сервера, благодаря которым игра работает.

  • Данные: информация, которая и делает EVE Online уникальной. Данные можно разделить ещё на несколько категорий:

    • Данные контента: модели, текстуры, тексты, характеристики и всё остальное, что создают наши художники, дизайнеры и сценаристы. Часть этих данных поставляется вам в составе клиента, а часть живёт только на наших серверах.

    • Сетевые данные: пакеты информации, которые идут через интернет между вашим клиентом и нашим сервером, а также между более чем 200 узлами нашего серверного кластера в дата-центре.

  • Сохранённые данные: постоянно растущий «файл сохранения», в котором записаны более 20 лет игровой истории. В первую очередь это огромная база данных SQL, лежащая в самом сердце EVE. Именно здесь хранится память агентов.

  • Экосистема разработчиков: инструменты и процессы, которыми мы, разработчики, пользуемся каждый день, чтобы доставить игру до вас.

Запрос агента

Теперь, когда мы знаем, где живёт память агентов, можно поговорить и о том, что она собой представляет. Каждый раз, когда ваш персонаж взаимодействует с одним из NPC-агентов, мы записываем этот факт в базу данных. Взаимодействием может быть запрос нового задания, выполнение (или провал) ранее предложенного задания, запуск исследовательского проекта или поиска персонажа через агента-локатора, а также направление к одному из особых сюжетных агентов.

Каждый агент помнит, чем закончилось его последнее взаимодействие с каждым персонажем, с которым он когда-либо говорил. Если 20 лет назад вы взяли у агента задание достать партию сомнительных голографических фильмов, этот агент до сих пор вас помнит и всё ещё ждёт, чтобы сообщить, что вы не уложились в разумные сроки!

Агент может хранить о вашем персонаже такие воспоминания:

  • какое задание он вам предложил и в каком оно состоянии (например, уничтожен ли уже целевой NPC);

  • ведёт ли агент исследовательский проект и как он продвигается;

  • поручено ли агенту найти для вас другого персонажа;

  • насколько далеко вы продвинулись по сюжетной цепочке;

  • какие задания эпических цепочек или агентов по профессиональной подготовке вы выполнили.

Обратите внимание: отношения между NPC-персонажами/корпорациями и вашим персонажем НЕ входят в память агентов. Отношения — отдельная механика, и состояние она отслеживает по-своему.

Сбор данных

Наконец, перейдём к тому, как эти данные хранятся и извлекаются, — собственно, ради этого статья и написана.

В самом начале 2000-х, когда велись последние приготовления к запуску EVE Online, мы придумали базу данных памяти агентов. Требовалось хранить сложное состояние, описывающее взаимодействия внутри пары «агент — персонаж». Обычно при проектировании баз данных для таких данных строят очень формальные модели таблиц и связей. Но требования к памяти агентов были запутанными и подвижными: у каждого взаимодействия был свой набор переменных (сравните, например, описание курьерского задания и направления к сюжетному агенту), а вдобавок дизайн быстро менялся вместе с самой игрой.

В то время современное движение NoSQL ещё не зародилось. EVE прочно сидела на слое хранения MSSQL. И один сообразительный программист понял: можно взять Python-объект, в котором хранится память агента, сериализовать его в бинарный блоб и сохранить этот блоб как текстовое поле в таблице базы данных.

Когда в следующий раз взаимодействие с персонажем «будит» агента, происходит обратное: бинарный блоб этого агента извлекается из базы данных и десериализуется обратно в Python-объект, который затем внедряется в работающего агента, восстанавливая его память. (В Python этот процесс также называют pickling и unpickling.)

Это отлично решало насущную проблему, но создало ещё две на будущее:

  • По блобам памяти было трудно искать. Сила базы данных — в поиске: найти все записи, где параметр имеет определённое значение. Но раз каждое воспоминание было упаковано в Python-конверт, эффективно выполнять запросы к его содержимому было невозможно. Чтобы найти, например, все воспоминания, связанные с уже упомянутой Девицей, пришлось бы по очереди загружать каждое изних в Python и проверять. Так себе вариант.

  • Формат данных был привязан к используемой версии Python. По мере развития языка Python

    одни возможности добавлялись, а другие объявлялись устаревшими и в итоге удалялись. А значит, когда-нибудь в будущем эти воспоминания стало бы невозможно прочитать — они были бы утеряны, как слёзы под дождём. С переходом с Python 2 на 3 это будущее уже совсем близко.

Тайник

Чтобы объяснить эту проблему простым языком, представьте, что на время переезда вам нужно сдать вещи на хранение. Один из способов — сложить всё в один огромный опечатанный морской контейнер и отправить его на склад (это «сериализация» ваших данных). К такому формату легко приспособиться (грузовику, который везёт контейнер, всё равно, на каком носителе перевозить вашу музыкальную коллекцию — на виниловых пластинках или компакт-дисках), это быстро, а контейнерные перевозки давно стали стандартизированным процессом.

Потом, когда вы переезжаете в новый дом, вам привозят контейнер, и вы можете распаковать свои сокровища. Но есть и обратная сторона: если на складе понадобится провести проверку безопасности, чтобы убедиться, что там не хранится ничего запрещённого, единственный способ сделать это — вручную вскрыть и обыскать каждый контейнер. Не самый эффективный процесс.

Всё для дела

Несмотря на долгосрочные недостатки такого подхода, он сработал. EVE Online дожила до запуска и пошла дальше. Решение для памяти агентов выжило и, если учесть все обстоятельства, держалось на удивление хорошо. Но ничто не вечно.

Чистка записей

Переход на Python 3 даёт нам прекрасную возможность (мимо которой мы не можем пройти… в самом буквальном смысле) исправить грехи прошлого. Нужно уйти от негибкого и заведомо недолговечного хранения Python-блобов в базе данных SQL. Заодно мы пользуемся случаем, чтобы навести порядок и вычистить массу накопленных данных (таблица памяти агентов — одна из самых больших в нашей БД и одна из очень немногих, которые только растут и никогда не уменьшаются).

Смертельный дуэт

Эта работа уже идёт «за кулисами». Недавно мы изменили способ загрузки и сохранения памяти агентов. Теперь каждое новое воспоминание, которое нужно сохранить, записывается параллельно в двух формах:

  • в старой, непрозрачной форме Python-блоба — ровно так, как мы делали всегда;

  • в новой, прозрачной и долговечной форме, которая не зависит от конкретной версии Python и вдобавок открывает возможности для более удобного поиска и дальнейшего развития.

Пока что все новые и обновлённые воспоминания будут существовать в обеих формах. Если вы сегодня запросите у агента задание, это воспоминание сохранится и там, и там. Это позволяет нам выбирать, какой форме отдавать приоритет при загрузке памяти агента. Заодно снижается риск: прежде чем отключить старый способ, мы можем убедиться, что обе формы рассказывают одну и ту же историю.

Когда память агента нужно загрузить из базы данных, у нас теперь есть несколько вариантов того, какой источник считать приоритетным, и менять их мы будем в три этапа:

  • Этап 1. Сначала мы продолжим загружать данные только из старого хранилища, пока не убедимся, что новая форма работает правильно.

  • Этап 2. Затем мы поменяем приоритет: сначала будем искать воспоминание в новой форме, а если ничего не найдётся — загружать его из старой.

  • Этап 3. В конце концов (когда мы полностью переведём всё остальное на Python 3) мы совсем перестанем читать старую форму. Агентам будут доступны только воспоминания, сохранённые в новой форме. Тогда мы наконец сможем удалить из базы данных старые воспоминания, которые так и не были обновлены, — к радости наших администраторов баз данных.

С сегодняшнего дня любое новое воспоминание отправится вместе с нами в Python 3. Переход будет долгим, так что времени пообщаться с агентами, взять новые задания или закончить текущие у вас будет достаточно. Речь идёт не о днях, а скорее о месяцах. Когда мы подойдём к третьему этапу, то обязательно дадим вам знать.

Материалы для подготовки к войне

Некоторые воспоминания перенести НУЖНО в любом случае, какими бы старыми они ни были, даже если персонаж не заходит в игру и не создаёт новых воспоминаний у каждого агента. Например, некоторые обучающие задания и задания эпических цепочек можно выполнить только один раз, и это нужно отслеживать. В таких немногочисленных случаях мы автоматически перенесём данные в новую форму в фоновом режиме.

Важная часть связи между персонажами и агентами — отношения. Именно над ними вы работаете, продвигаясь от агентов 1-го уровня к агентам 4-го и даже 5-го. Все отношения между персонажами и NPC-агентами, корпорациями и государствами сохранятся, и эти изменения их не затронут. Мы не будем их сбрасывать и не потеряем.

Стройка продолжается

Работа над переходом на Python 3 продолжается. Помимо «простой» части — переписывания кода клиента и сервера — ничуть не меньше (если не больше) работы требует обновление всего, что этот код окружает. Это множество инструментов, которыми наши разработчики пользуются каждый день. Множество стыков, где процесс Python общается по сети с каким-то другим компонентом. Процессы развёртывания, которые позволяют нажать кнопку и выпустить дополнение.

И, как мы увидели здесь, даже данным в базе иногда нужно небольшое обновление.

Безопасных полётов — и до встречи в следующей статье o7