1. Друзья, в это тяжёлое и непонятное для всех нас время мы просим вас воздержаться от любых упоминаний политики на форуме, - этим ситуации не поможешь, а только возникнут ненужные ссоры и обиды. Это касается также шуток и юмора на тему конфликта. Пусть войны будут только виртуальными, а политики решают разногласия дипломатическим путём. С уважением, администрация Old-Games.RU.

    Скрыть объявление
  2. Если Вы видите это сообщение, значит, вы ещё не зарегистрировались на нашем форуме.

    Зарегистрируйтесь, если вы хотите принять участие в обсуждениях. Перед регистрацией примите к сведению:
    1. Не регистрируйтесь с никами типа asdfdadhgd, 354621 и тому подобными, не несущими смысловой нагрузки (ник должен быть читаемым!): такие пользователи будут сразу заблокированы!
    2. Не регистрируйте больше одной учётной записи. Если у вас возникли проблемы при регистрации, то вы можете воспользоваться формой обратной связи внизу страницы.
    3. Регистрируйтесь с реально существующими E-mail адресами, иначе вы не сможете завершить регистрацию.
    4. Обязательно ознакомьтесь с правилами поведения на нашем форуме, чтобы избежать дальнейших конфликтов и непонимания.
    С уважением, администрация форума Old-Games.RU
    Скрыть объявление

[Ковыряние] Warcraft Orc and Humans. Шепчет! Шепчет! -2

Автор: Zelya · 15 май 2019 · ·
  1. Обещанный длиннопост.



    Начну, пожалуй, с конца. С того, что больше всего попило кровушки.

    Небольшой ликбез для тех, кто даже не знал, что в Варкрафте или Досбоксе есть сеть (можно пропустить):
    Warcraft имеет поддержку сетевого IPX протокола. Нет, он не совместим с TCP/IP. Протокол уже много лет не поддерживается, и я даже не знаю, существует ли его реализация для Винды позже ХР. В ДосБоксе пошли навстречу всем страждущим и "запилили" эмуляцию. Приблизительно так: игра передает подготовленный IPX пакет "драйверу", его ловит ДосБокс, "обворачивает" в UDP и предает по TCP/IP другому Досбоксу, который его "разворачивает", вытягивает IPX пакет и подкладывает, как бы из "драйвера" запущенной игре. Но никто не запрещает другой программе слушать тот же UDP, ловить те же UDP пакеты и извлекать из них IPX данные. И наоборот, отправлять по UDP Досбоксу свои данные. Чем я, собственно, и занимаюсь.


    Большинство современных разработчиков представляют упрощенную картину сетевого приложения приблизительно вот так:
    [​IMG]

    Да и я, хоть и имел некоторый опыт гонять данные через сокеты, будучи нубом в этой сфере, думал так же. При этом, прочитав однажды где-то в журнале "Мурзилка", что IPX пакеты очень похожи на UDP пакеты, я сразу же представил схему портирования сетевого кода как-то так (оранжевая область - то, что надо переписать)
    [​IMG]

    Но обычно мы забываем о тех мелких удобствах, которые несет нам прогресс. Реальная картина сетевого софта выглядит как-то так:
    [​IMG]

    И вроде бы ничего страшного для современного программиста нет. Но в моем случае все немного печальнее:

    [​IMG]

    Причем, я не уверен, использовали ли Blizzard сторонние либы или писали все сами. Я склоняюсь все же ко второму варианту, так как в суровые 90-е разработчиков под ДОС сетевыми либами не очень-то и баловали. Да и стиль кода очень похож. В любом случае, в виде ассемблера, для меня это все стало общей кодовой кашей. И если игровая логика мне была уже более-менее понятна, то чем ближе к низкоуровневому коду сети, тем становилось грустнее.

    [​IMG]

    Кроме того, многие части этого кода обслуживали нюансы работы IPX драйвера, о которых я не подозревал: IPX мне знаком на уровне самых примитивных основ, а в TCP/IP всю эту муть скрывают от нас любезные разработчики либ. Как оказалось, сам драйвер умеет не так уж много, но зато его нужно очень деликатно умасливать, чтобы получить ожидаемые данные. Так что старая схема по портирования пошла в корзину, а под новую схему были два варианта.

    Вариант первый, "как есть":
    [​IMG]
    Т.е. я ручками переписываю всю логику по обслуживанию драйвера и нюансов работы IPX сети.

    Вариант второй:
    [​IMG]
    Всем мил и прост второй вариант. За одним теоретичесвим исключением. Начиная разбирать этот кусок игры, я понятия не имел (да и сейчас не имею) какие опции/эвенты сетевого кода важны для игровой логики. Может, игра совершенно игнорирует всю эту составляющую, просто передавая туда пакеты данных. А может, она следит за каждым чихом сети, чтобы подстроить latency, повторить запрос и т.д. И если я выберу второй вариант, у меня появится, хоть и не большой, но очень критический риск: на позних этапах доработки сетевой игры я не смогу синхрониховать WinWar с оригиналом. Будут какие-то критически малые различия в таймингах, и я не смогу заставить стандартные dotNET сокеты реагировать правильно. У меня просто не будет контроля над внутренней кухней отправки/получения данных. И хоть, опять же, вероятность такого события невелика, я в таком случае просто заброшу разработку.

    Ну, соответсвенно, я выбрал первый вариант. Если честно, то работу с таймингами я до сих пор не довел до ума, просто расставив "на глазок" sleep-ы, чтобы оно хоть как-то работало, ибо слишком быстрая или слишком медленная передача данных разваливает синхронизацию оригинала. И все же, я более-менее спокоен, так как я контролирую бОльшую часть сетевого кода, а все "провтыки" основаны нежеланием моей ленивой жопы читать огромные талмуды по нюансам работы IPX протокола.



    Теперь вернемся к игровому уровню. Тут, хоть все и попроще, но тоже напрягает. Формат игровых команд высчитывается на "раз-два". Вот, допустим, жмакнули мы на Таун Холл, сформировалась команда, типа:

    Команда="выбьрать" Объект="42"

    Что с ней делать дальше? В одиночной игре - взять и сразу обработать. А в сетевой? Передать в сетевой код для отправки? Нее.. Сначала мы пложоим ее в очередь на отправку. Задержка-то в сетевой игре существует, и по одному пакету гонять - несерьезно (с пингом, скажем в 100мс, получится не больше 10 АПМ для игры).

    ОК, собрали мы очередь команд, подошло время отправки. Что мы делаем дальше, пихаем команды в сеть? Ну что вы! Мы пихаем их в пакет (мое временное название s_PacketData3), который кроме очень полезных, но теоретически необязательных флагов, имеет Id синхронизации. Чтобы игра с той стороны понимала, на какой мы стадии, и не случилась ли рассинхра.


    [​IMG]

    Хорошо. Использовали мы твой, прости господи, s_PacketData3. Можно отправлять? Увы, мы должны запихать его в пакет. Да-да, пакет s_PacketData3 в пакет s_PacketDataExt. Он имеет еще CRC и позволяет проверить, не поломался ли наш пакет при передаче через сеть. Сейчас-то сети хорошие, Ютубчик редко глючит, а раньше и не угадаешь, что придет на тот конец провода. CRC не то, что гарантирует целостность данных, но довольно часто помогает отбросить поломанные пакеты.

    [​IMG]

    Все, спаковали мы s_PacketDataExt, можем отправлять? Нет. Угадаете, что мы будем делать с пакетом? Да! Запихивать в другой пакет! Называется он у меня банальнее: WarcraftPacket. Что он имеет? Не поверите, тоже Id. Что за хрень? Зачем нам еще одно Id, мы уже имеем его в, прости господи, s_PacketData3! Это Id, совсем не то Id. В s_PacketData3 Id служит для того, чтобы игра понимала, какой набор команд должна обработать сейчас, а Id из WarcraftPacket имеет уровень ниже. Дело в том, что броадкаст в IPX тех времен, это такая себе дыра в которую все кричат, а ты что-то записываешь. Причем кричат частно кричат невпопад. Но даже если б кричали строго по-порядку, то и тогда ты не всегда успевал бы все записывать. Для таких целей Варкрафт слушает IPX "дыру" в 9 ух. Соовтетсвенно, что на выходе получается каша-малаша. И чтобы хоть как-то навести порядок, мы делаем дополнительную Id. Теперь, на уровне WarcraftPacket мы все упорядочним для передаче игре, и тогда, уже недочет по s_PacketData3 Id, будет означать именно потерю пакета, а не неправильный порядок. Стало быть надо подождать или сообщит о рассинхре.

    [​IMG]

    Вот, теперь мы почти готовы к отправке, осталось только WarcraftPacket положить в IPX пакет, а его в UDP пакет и дело сделано!


    Про установление игровой сессии и поддержке ее синхронизации - как-нибудь позже.
    fR0z3nS0u1, Dimouse, 6y3eJIok и 3 другим нравится это.

Комментарии

  1. fR0z3nS0u1
    Прости, я не смог с фразы "..."обворачивает" в UDP и предает по TCP другому Досбоксу... "
    Это как? Всё-таки как TCP или UDP пакет передаётся?

    IPX, кстати, не совместим не с TCP, а с TCP/IP, а именно с его IP частью (протоколы одного уровня). При необходимости можно написать реализацию TCP протокола через IPX, по идее, но это ж такой монстр корявый будет...

    А вообще, написано просто, но интересно. Как человек, немного понимающий в сетях, но не разрабатывавший под уровни ниже application, прочитал легко и непринуждённо.
  2. ВелоВояджер
    Почти ничего не понял (слабо разбираюсь), но прочитать было интересно, потому что больше года назад я переводил руководство к этому Варкрафту, и в нём довольно много рассказано о том, как соединяться через сеть. Правда, перевёл я из этого не всё - Troubleshooting оставил на потом, да так и не перевёл.
    Кстати, некоторое время назад в местном "Бюро переводов" мы обсуждали тоже "неэмулируемую" вещь: у игры Veil of Darkness (выпущена она была примерно в то же время, что и Варкрафт) есть возможность прямо во время игры распечатывать диалоги персонажей и даже внутриигровые карты. В процессе тестирования перевода возник вопрос: а как проверить, работает ли эта функция в переведённой игре, не используя для проверки настоящий ДОС? Ответа тогда не нашли. Обычный Досбокс не позволяет распечатывать что-либо на принтере. Так что нужно было бы либо искать специальный Досбоксовский драйвер для принтера (если такой существует), либо отказаться от проверки. Что в итоге и сделали, поскольку "распечатывать" можно и в файлы на компьютере - игра это позволяет.
  3. Zelya
    @fR0z3nS0u1,
    Сорри, так бывает, в голове "упростил", и в тексте забыл исправить. Кругом, где TCP - читайте TCP/IP. ДосБокс только UDP использует.

    Сейчас поправлю текст. (Done)
      fR0z3nS0u1 нравится это.
  4. Bato-San
    Сетевой код писался в близзард Джесси (LAN) и Морхемом (модем).
Чтобы оставить комментарий просто зарегистрируйтесь и станьте участником!
  1. На этом сайте используются файлы cookie, чтобы персонализировать содержимое, хранить Ваши предпочтения и держать Вас авторизованным в системе, если Вы зарегистрировались.
    Продолжая пользоваться данным сайтом, Вы соглашаетесь на использование нами Ваших файлов cookie.
    Скрыть объявление