Архив рубрики: Сервер

Разреженные массивы

В программировании часто встречаются задачи хранения объектов и быстрый поиск их по числовым идентификаторам. Такая задача у нас возникла при работе с трехмерными точками на сервере.

Постановка задачи

Для каждого объекта есть набор точек, каждая точка представляет собой идентификатор (Int) и координаты X, Y, Z. Точек может быть достаточно много — несколько тысяч. Идентификаторы не обязательно последовательные, но последовательность нарушается достаточно редко. С точками определены следующие операции: добавить, удалить и получить все точки для математических операций. Требуется быстрая структура для хранения, создания и редактирования точек. Самый простой способ использовать Map<Int,Vertex>, но потребление памяти и скорость нас не устроила. Сервер должен обрабатывать несколько миллионов точек в секунду и чем больше, тем лучше.
Continue reading Разреженные массивы

Выбор архитектуры сервера

Итак, у нас задача написать сервер для многопользовательской онлайн игры. Вот тут нам повезло, никто не говорил на чем писать и что использовать, был только набор требований и идей. Требования были такие — много людей бегают по миру, общаются, живут. Клиент обязательно на Flash. Вот и всё.

Язык программирования

JAVA — простой и логичный язык, удобная среда разработки, стабильная и достаточно быстрая среда исполнения. К тому же большой набор готовых библиотек. В качестве аналога рассматривали C#. Возможности почти такие же, но менее логичный синтаксис. Только одна среда программирования и одна операционная система. Нет нормальных решений в области серверов приложений, ORM-ов и так далее. Например, попробуйте найти встроенный WEB сервер для приложения на C#. А вот для JAVA существует несколько подобных решений.

База данных

В процессе создания прототипа базы данных было решено использовать базу данных на основе разработок от BerkeleyDB. Получили достаточную скорость работы с данными, но были большие сомнения в масштабируемости и надежности такого решения. В дальнейшем перешли на SQL базу и в качестве объектной прослойки выбрали ORM Hibernate. Скорость работы упала на два порядка, но теперь у нас есть надежда на масштабируемость и надежность, а также появилось право выбора MySQL или Oracle, PostgreSQL или DB2. Первой базой была MySQL, но через месяц работы перешли на PostgreSQL, на том и остались. Вопрос о смене базы данных поднимем после альфа/бета тестирования.

Сервер приложений

Для JAVA есть выбор между JBOSS, Spring и их коммерческими аналогами. Но в итоге мы решили не использовать стандартные подходы, так как для нас они слишком громоздкие и не подходят для нашей идеологии Моделей поведения. Все же игра это не бизнес приложение и подходы здесь совсем другие. С другой стороны программировать сервер как одно большое монолитное приложение не было бы оптимальным решением. Остановились на решении использовать OSGI ядро, тоже самое, что используется в Eclipse. Такой подход позволил нам части игрового сервера оформить в виде отдельных независимых модулей. Плюсы данного подхода — разграничение прав доступа, четкое API для обмена информацией между модулями, возможность менять модули без остановки сервера. К тому же модули можно запускать на нескольких машинах, что даст нам возможность наращивать вычислительную мощность без существенных переделок программного кода.

Выбор среды программирования — Eclipse, так как с OSGI она работает лучше, чем другие IDE.

Данные для создания объектов

Игровой мир построен на объектой модели. Flash-клиент по запросу сервера создаёт игровые объекты. При создании объекта необходимо дать набор необходимых данных. Например, для 3D-тумбочки нужен список точек и граней, её описывающих. При этом механизм передачи данных должен быть быстр, ёмок и удобен для кодеров. Помимо этого должна быть полная синхронизации имён параметров между сервером и клиентом, дабы не вносить путаницу.

Ранее сервером генерировались интерфейсы для обязательного наличия сеттеров и геттеров на каждый параметр, и, соответственно, каждый Flash-класс должен был их реализовывать. Это всё превращалось в километровую портянку set/get. Помимо этого в памяти оседали совершенно уже не нужные данные.

Сегодня реализовали новый подход передачи данных для конструкторов объектов на клиенте.
Сервер генерирует для каждой модели поведения (о моделях расскажем отдельно) не только интерфейс для реализации, но и специальный класс данных, где все свойства указываются публично. Загрузчик объектов наполняет эти классы данными при загрузке и отдает для инициализации объектам.

Continue reading Данные для создания объектов

Обмен данными между сервером и клиентом

Самой первой задачей в далеком 2006 году, когда игра казалась маленьким проектом и работали вечерами после основной работы, возникла первая задача — как же обмениваться данными между сервером и клиентом. Напоминаю, сервер на Java, клиент — на Flash.

Для начала рассмотрим стандартные возможности флеша по передаче данных — XML и AMF. Первый вариант отпадает практически сразу, так как текстовый формат тяжел для парсинга и не оптимальный по размеру.

AMF вроде бы хорош — и размер небольшой, и парсится быстро, но хотелось бы размер поменьше и возможностей побольше, тем более сервер и клиент обмениваются командами, а AMF заточен в основном под передачу объектов. После тщательного анализа было принято решение написать свой протокол, и это было первое изобретение велосипеда. Хотя и довольно удачное изобретение.

Неделя ушла на создание первого прототипа. Сделали поддержку стандартных типов (byte, short, int, long, double), бонусом получили возможность достаточно просто добавлять другие примитивные типы. Далее задумались, как передавать структурные типы (List, Map, Array и String). В итоге пришли к решению передавать размер структуры как byte, short или int — в зависимости от размера. И в заключении ввели рекурсию, то есть можно в List положить Map в Map Array и так далее.

Разработка окончательного варианта на JAVA заняла две недели, включая JUNIT тесты. А далее самое интересное — разработка сетевой библиотеки на Flash.

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

Итог работы — быстрая, асинхронная (и на Java, и на Flash), надежная сетевая библиотека, с широкой поддержкой разных типов данных. Работает быстрее чем AMF и экономнее расходует сетевой трафик.

3D-консоль для игрового мира

Серверные кодеры для отслеживания 3D-мира сделали себе консоль.
У каждой камеры задаются свои параметры (поля внизу или с помощью мыши). Справа дерево объектов мира.

Реализовано на Java с использованием SWT/OpenGL. Консоль может работать автономно или получать данные с игрового сервера посредством RMI.

Просмотр дерева классов Консоль3

Парсер PSD-формата

Photoshop в настоящее время стандарт де-факто для дизайнеров. Но для игры, кроме, собственно, изображения, нужна дополнительная информация. Например, точки привязки, разбивка на спрайты и так далее. Было принято решение, для удобства дизайнеров, задавать дополнительную информацию используя возможности Photoshop-а. То есть точки привязки — в отдельном слое, деление на спрайты — слайсами и так далее. Для обработки сервером этой информации нам потребовался парсер PSD-формата. Стали искать готовые парсеры, нашли, но довольно убогие, например, нет поддержки множественных слоев, слайсов и так далее. Пришлось найти документацию по формату и потратить неделю на написания парсера.

Пример использование парсера:

PSDParser parser = new PSDParser(new FileInputStream("image.psd")); 
PSDLayerAndMask layerAndMask = parser.getLayerAndMask();  
 
List layers = layerAndMask.getLayers(); 
List images = layerAndMask.getImageLayers(); 
int i = 0; 
for (PSDLayerStructure layer : layers) { 
    PSDLayerPixelData pixelData = images.get(i); 
    BufferedImage image = pixelData.getImage(); 
    if (image != null) 
	ImageIO.write(image, "png", new File(layer.getName() + ".png")); 
	    i++; 
}

Исходники проекта

Исходники проекта выложены в свободный доступ, под лицензией APACHE LICENSE.
Возможности — экспорт всех слоев, включая главный. Общая информация о файле, слоях. Полная поддержка слайсов.
Используйте данный код на свой страх и риск, также я буду благодарен, если сообщите об ошибках или способах улучшения кода.

psd_parser.7z

Eclipse — ловим изменения в проекте

Возникла следующая задача: допустим я в Eclipse занимаюсь программированием кода, правлю файлы в различных проектах. Но сервер работает совершенно на другом компьютере. То есть мне надо все свои измененные проекты перенести на сервер, а запоминать какие проекты я изменил, а какие нет не очень удобно. Для решения задачи потратили два часа и написали два плагина, один для серверных программистов, второй для клиентских. Плагины следят за проектами и записывают изменения, первый плагин формирует XML файл с изменениями для ant, второй копирует изменные swf файлы в один каталог, который позже переносится в SVN одной командой.

change_project_flash.7z
change_project.7z

Поиск пересечения луча и сферы

Для теста была написана программа для поиска пересечения луча и сфера, быстродействие получилось — 16 миллионов сфер в секунду на обычном компьютере и 33 на сервере (алгоритм не многопоточный, так что реально цифру умножаем на два), модифицированный (неточный) алгоритм работает в 2-4 раза быстрее. Для алгоритма пересечения с треугольником результаты такие же.
Также обсудили алгоритм хождения, на каждый шаг прийдется пускать два луча, один передвижение — второй гравитация.

Также подумали по графическую карточку — но загрузить туда весь мир не реально, даже если у нас будет 50000 объектов по 500 полигонов, то только на хранение надо будет 2 гига. Но к примеру можно загружать туда густозаселенные области например города, а все остальное считать на JAVA.