Рубрика "Весёлое багло в мультике и не только"

Это одна из маленьких историй о трех маленьких, но храбрых и независимых разработчиках в жестоком мире гейм дева! Приключения Сира Т, Сира R и Сира I с их славной игрой "First Feudal" начинается здесь и сейчас!

Рубрика "Весёлое багло в мультике и не только" Игры, Gamedev, Gamemaker Studio 2, Инди, Indiedev, Длиннопост

Сегодня окунемся в мир багла! Но не абы какого, а весёлого, непредсказуемого, но в меру адекватного! Поехали!

Идея завести мультиплеер в игру теплилась в душе очень долгое время. Но не решались, т.к. это был, очевидно, очень серьезный объем работ, связанный с перепиливанием архитектуры, залазанием в новую сферу без опыта и т.п.

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

В этом же посте хотел рассказать про особый баг, который был и нелеп, и прост, и весел, и раздражающь. Воспроизводился он как в мультике, так и в соло игре. Здесь стоит оговориться, что мы выбрали клиент-серверную архитектуру, что по факту означало реализацию сетевого коннекта в обоих режимах. Т.е. даже в одиночной игре запускается 2 приложения: клиент и сервер. Простейший и чуть ли не единственный способ общаться двум аппам в Windows без лишнего геммороя и кучи сложных багов - соединить их по сети: один создал сокет, второй создал сокет, соединились и болтают по стандартному tcp. Выбирать именно такие архитектурные решения сподвигали определенные обстоятельства и попутные фичи типа стабильного fps на клиенте или необходимости соблюдения последовательности пакетов.

В итоге мы имели обыное tcp соединение, на базовом network функционале GameMaker. Естесн была написана библа, чтобы упростить обращение с базовым нетворкингом, но внутри это были именно  network_send_packet, network_create_server и т.п.

Когда это дело улетело на прод периодически стали прилетать баги с текстом, который можно было расшифровать как "Какого-то фига прилетел кривой пакет, я упаль". Более того, это багло воспроизводилось редко и локально на компахи Сиров, однако делало это очень нестабильно. Иногда 5 раз подряд, а потом само проходило.

Сир I был осведомлен, что tcp лишь гарантирует, что если что-то пойдет не так - он об этом оповестит, но пересылать сам не будет, поэтому были прикручены несколько механизмов повторной посылки пакетов и разруливания ситуации кривых пакетов. Но и они не спасали. Опрос 3-их знакомых сетевиков ни к чему конкретному не привел, хотя совет поставить WireShark и посмотреть, что там в потоке прилетел именно от них. Впрочем логи не помогли ни сетевикам, ни тем более Сирам, с виду все ровно, однако сие черные строчки не давали покоя Сиру I:

Рубрика "Весёлое багло в мультике и не только" Игры, Gamedev, Gamemaker Studio 2, Инди, Indiedev, Длиннопост

Дальше было 100500 расспросов и гуглений в слепую на тему "что за Window Full" и "что на заполненность этого Window влияет"?

Оказалось, что в tcp есть понятие входящего окна, условно это кеш определенного размера "сколько сообщений по tcp готова принимать винда, пока не начнет их отвергать". Стандартно это дело выставлено в 64Кб. И если окно переполняется, тоооо - дальше все зависит от локальных настроек, которые выставляются при помощи:

`netsh interface tcp set global rss=enabled`

`netsh interface tcp set global autotuninglevel=normal`

Если autotuninglevel - выставлен, то в ситуации переполнения окна - он сам расширится (станет 128Кб, 256Кб и т.д.), а если нет, то следующие пакеты будут отвергаться (на клиент прилетит -1, при попытке вызова network_send_packet). Однако все это не объясняет почему прилетают кривые пакеты. Это же tcp, что отослал, то и прилетело, а если не прилетело, то и кривиться нечему. И все было бы так, если бы не GameMaker. Во всяком случае Сир I в итоге обвинил его во всех tcp грехах, и само собой, что такую шляпу не могли обнаружить сетевики.

Прикол тут в том, что поведение GameMaker в ситуации, когда autotuninglevel отключен - абсолютно неочевидно. Он дублирует пакет, который пришел последним, а после этого получает все оставшиеся в tcp окне пакеты (которые набились) разом, слепленные в один. Само собой клиент не ожидает такого поведения и падает. Точнее не ожидал. Эту особенность, про получение дубликата пакета и взяли за индикатор влетания в эту ситуацию. Теперь, когда такое происходит, мы выполняем полную синхронизацию соедининия, по факту, разрывая его и создавая вновь.

После чего порешали главную причину переполнения окна. Проще всего его переполнить послав ооочень большой пакет, именно такой мы шлем, когда впервые создаем/загружаем игру. Поэтому на архитектурном уровне сети дополнительно пришлось реализовать разбивание и собирание больших пакетов на подпакеты (привет tcp), чтобы винда успевала обработать пакеты без переполнения гораздо реже. Дополнительно в настройки вынесли размер подпакета, на случай если найдется пользователь с базовым размером окна меньше 64к. Т.е. по факту реализовывали часть tcp под tcp.

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

P.S.

Опция rss (как понял Сир I) отвечает за многопоточную обработку пакетов tcp, что увеличивает скорость его работы. Его отключение увеличивает шанс переполнения окна.

Всем добра, господа и дамы. Пойду допиливать новое событие в следующий патч!)

Лига Разработчиков Видеоигр

6.8K постов22.2K подписчиков

Добавить пост

Правила сообщества

ОБЩИЕ ПРАВИЛА:

- Уважайте чужой труд и используйте конструктивную критику

- Не занимайтесь саморекламой, пишите качественные и интересные посты

- Никакой политики


СТОИТ ПУБЛИКОВАТЬ:

- Посты о Вашей игре с историей её разработки и описанием полученного опыта

- Обучающие материалы, туториалы

- Интервью с опытными разработчиками

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

НЕ СТОИТ ПУБЛИКОВАТЬ:

- Посты, содержащие только вопрос или просьбу помочь
- Посты, содержащие только идею игры

- Посты, единственная цель которых - набор команды для разработки игры

- Посты, не относящиеся к тематике сообщества

Подобные посты по решению администрации могут быть перемещены из сообщества в общую ленту.

ЗАПРЕЩЕНО:

- Публиковать бессодержательные посты с рекламой Вашего проекта (см. следующий пункт), а также все прочие посты, содержащие рекламу/рекламные интеграции

- Выдавать чужой труд за свой

Подобные посты будут перемещены из сообщества в общую ленту, а их авторы по решению администрации могут быть внесены в игнор-лист сообщества.


О РАЗМЕЩЕНИИ ССЫЛОК:

Ссылка на сторонний ресурс, связанный с игрой, допускается только при следующих условиях:

- Пост должен быть содержательным и интересным для пользователей, нести пользу для сообщества

- Ссылка должна размещаться непосредственно в начале или конце поста и только один раз

- Cсылка размещается в формате: "Страница игры в Steam: URL"