Игровой сервер на node.js, хранить перечни игроков и комнат в object или array?
Допустим, есть некий game.js, содержащий перечень объектов класса player.js , отвечающих за общение с подключёнными сокетами (внутри каждого — сокет и набор служебных методов), а также перечень объектов класса room.js, отвечающих за игровые лобби и сессии. Игрушка — условно-пошаговая с использованием active time battle (ATB) — право хода даётся игроку при заполнении его шкалы хода.
Перечень комнат и подключённых игроков хранить в объекте или в массиве? Вопрос с точки зрения скорости доступа к нужному экземпляру: в object можно обратиться по ключу (уникальный id игрока) напрямую, но перебор в массиве более быстрый. Иногда нужно обратиться к конкретному экземпляру, иногда — к нескольким. Порой может возникнуть ситуация, когда требуется сообщить сигнал всем объектам перечня (отсюда вопрос про array или object), пример — в следующем абзаце.
Второй вопрос вытекает из первого. Требуется реализовать некий game loop для всех игровых "комнат" — заполнять им шкалу ATB. Предполагаю делать перебор всего списка комнат каждые 0.1-0.2 секунды и начислять им этот "шаг". Подключённым к серверу, но не находящимся в данный момент в боевой сессии, нужно каждые 3-5 секунд восстанавливать показатели здоровья. Опять же, напрашивается перебор массива экземпляров player.js с проверкой условия "не находится в игровой сессии".
Корректна ли такая реализация? Число запущенных "комнат" может исчисляться несколькими сотнями при хорошем онлайне, число игроков — тысячами.
В проведённом тесте for in для объекта показал значительно более быстрые результаты, чем перебор массива. Не знаю, насколько универсальны эти результаты. Советуете использовать {}?
Начну со второго вопроса - а Вам не кажется, что нет нужды каждую сотую секунды делать обновления индикатора? Просто можно сделать на сервере, типа, модели комнат, в которой
будет флаг, некий коэффициент, который будет при расчетах браться. А по началу этого события
рассылать на клиенты сообщение, чтобы представления самостоятельно уменьшали тот или иной
индикатор. А если кто-то свое приложение причитерит, то это ему не поможет, так как на сервере
все равно по коэффициенту известно правильное значение.
А по первому тут Вам нужно тестировать, на какие операции больше будет затрат.
А то можно вообще коллекцию на основе массива для итерации сделать + хеш индекса
по ключу.
1) Хорошая идея — полагаю, можно хранить время последнего хода игрока и, зная скорость восстановления его шкалы хода, при запросе от него высчитывать, может ли он ходить или ещё нет. Или в момент завершения его хода сразу высчитывать допустимое время следующего. Спасибо, как-то не додумался до этого. В этом случае основной game loop не нужен в принципе.
Anubis:
1) Вы самое главное не обделяйте представление логикой и тогда не нужно будет все расчеты проводить на сервере.
2) Ну, у Вас же есть коллекция игроков, коллекция комнат?
Если нет, то нужно создать класс с методами insertObject, removeObject и т.д.
И вот в метод insertObject передаетеinsertObject( user, ), а в теле метода добавляете
user в массив, для итерации и в объект для быстрого доступа по ключу.
Но тут, я повторюсь, нужно рассчитывать, что у Вас в конкретном месте более затратно.
А то может вообще нужно, что-то другое делать, вариантов очень много.
При таких объемах - разницы не будет практически. Восстановление ATB можно сделать через события - вы по таймеру генерируете евент - addATBPoints и параметром передаете сколько восстановить, каждый игрок подписывается на это событие - и по его наступлению обрабатывает.