В течение долгих лет промышленники были вынуждены вручную просматривать море чертежей, чтобы найти среди копий бесценные оригиналы.
Эта история о том, как мы исправили это.
Перво-наперво: Почему они с самого начала не выглядели по-разному?
Проблема была в том, что идентификаторы (ID) в нашей инвентарной системе были одинаковыми; чертежи, которые делали Огров («Ogres») или Тораксы («Thoraxes») имели одинаковый идентификатор, вне зависимости от того, что это, BPO или BPC. Конечно, наши таблицы содержали поле тип, но эти атрибуты не хранились в тех же таблицах. Такие атрибуты хранились в специальных таблицах, например в Науке и Производстве (Science and Industry — S&I;) подсистемной таблице в случае с чертежами.
Когда вы запрашиваете список предметов в определенной локации из инвентарной системы, всё что вы получите — это только «общие атрибуты», атрибуты предметов без дополнительной специфичной информации. Таким образом, BPO и BPC имеют одинаковые базовые атрибуты, в частности для получения параметра «тип» клиенту пришлось бы сделать еще один запрос к серверу (к S&I;подсистеме) чтобы выяснить, где оригиналы, а где копии. Так же обстояли дела при нажатии на «показать информацию».
Мы не хотели, чтобы вы так жестоко обращались с нашим маленьким милым сервером, когда открывали бы ангар полный чертежей и копий. Это просто ужасное решение, особенно учитывая то, что в большинстве случаев дополнительная информация не требуется. Мы так же не хотели создавать условно-объединенные таблицы каждый раз для отображения содержимого ваших ангаров. Это называется SQL-терроризм!
Так как же так замечательно получилось, что появилась возможность различать BPO и BPC без дополнительной нагрузки на сервер БД?
Первый шаг мы сделали еще в прошлом году с выпуском Tyrannis 1.2, подробности можно узнать в дев блоге «64 бита должно хватить всем!». Хотя те изменения были направлены на перевод инвентарной системы на 64 бита, далее мы сделали больше. Мы внесли изменения в таблицу предметов, изменили битность колонки typeID (идентификатор типа) и некоторых других, объединили пару столбцов и подчистили устаревшие колонки. Последнее — очень важно! Ранее мы имели 'singleton' битовую колонку (bit-column — тип данных в SQL Server, прим. пер.), которая показывала, что данный предмет не является частью стека и что его идентификатор может быть использован в качестве внешнего ключа в других таблицах. Мы так же использовали неотрицательную колонку 'quantity', которая обозначает, сколько предметов хранится в стеке. Возможно, некоторые из вас заметили, что это взаимоисключающие действия. Синглтоны (одиночка — паттерн проектирования, прим. пер.) должны иметь размер стека равный 1, и что-либо с quantity > 1 не может быть синглтоном (quantity = 1 так же не подразумевает синглтон).
Объединение цельночисленной колонки 'quantity' с новой семантикой, которая предполагает отрицательные значение 'quantity' для обозначения синглтона, позволило сохранить размер и пропускную способность БД. В общем мы просто массово обновили таблицу инвентаря, изменив все 'singleton == 1' предметы на 'quantity = -1'.
Следующий шаг был сделан в Incursion 1.3, подробности которого вы можете прочитать тут. Это стало продолжение предыдущего этапа, но тут мы доработали некоторые особенности, сделали несколько улучшений по защите от эксплойтов и заново ввели поле 'singleton' в структуру БД, но на этот раз как виртуальную колонку. Виртуальная колонка выглядит как обычная для программистов, на самом деле в ней хранится не значение, а функция, значение которой определяется по другим признакам (в данном случае quantity).
Объединив эти два изменения, мы получили 30-битный простор отрицательных значений quantity для кодировки специфической информации синглтонов и унифицированные методы обращения к ним. Используя эти факты, мы изменили способ создания синглтонов чертежей, установив 'quantity' для оригиналов в -1, а для копий в -2.
Итак, теперь клиент может определить тип чертежа, проверив виртуальную колонку синглтона и получив значение 1 или 2 (мы всегда возвращаем только положительные значения при проверке синглтона) выбрать нужную иконку, и все это происходит без дополнительных обращений к серверу и нагрузки БД.
Ловко, правда?
Теперь у нас предметы сортируются бекэндом и имеется причудливый флаг BPC синглтона, все готово, верно?
Не совсем. Это работает отлично в вашем ангаре или в грузовом отсеке корабли, т.к. туда направляются флаги различий, но что теперь делать с местами, где нет предмета как такового, например с магазином LP? Там у нас нет реального предмета и нет соответствующей записи о предлагаемом вам чертеже в дополнительных таблицах. В данном случае нам, несомненно, помогло то, что в магазине LP есть только копии, а релевантные метаданные, такие как количество запусков и качество копии, можно получить при отображении полной информации (show info) о несуществующем предмете, так же как и для обычного предмета.
И что я получил в итоге?
Так как теперь мы имеем один тип с двумя очень разными формами, с отдельными иконками и множеством связанных метаданных, мы добавили множество специальных функций только для одного этого класса типов. Почти в каждом месте, где это используется, мы расширили функцию отображения информации, а не просто изменили иконки. Сейчас, видя различные иконки для копий, вы ожидаете получить соответствующую информацию, при клике на show info. Ранее вы не имели возможности получить эту информацию таким образом. Special-case (паттерн особый случай, прим. пер.) код запускается клиентом, и поэтому является дружественным для сервера и БД, что очень важно при разработке масштабных MMO с единым миром.
Окончательный результат был достигнут в Incursion 1.5.
Это большой объем работы, в который было вовлечено множество людей в нескольких командах на протяжении 3х отдельных обновлений, зато теперь вы можете визуально отличить BPO от BPC.
И теперь вы знаете как!
Перевод © Chegevarich, правки © .up
Обсуждение на форуме EVE-RU.