project_cossacks

project_cossacks

Решил сделать улучшенную версию игры Казаки, благо исходники с 2017 года лежат в открытом доступе.

Называться эта версия будет так:

Казаки v1.35 Патч Ренессанс(Возрождение) 2026.1

или

Cossacks v1.35 Renaissance patch 2026.1

Что планируется сделать

Основное:

  • Сохранить совместимость с версией 1_35! Чтобы игроки на оригинальной версии могли играть вместе с игроками на Cossacks 1.35 Renaissance patch.
  • Сделать возможность создавать комнаты на сервере без проброса портов!
  • Сделать улучшения, которые есть в патче Помор и других патчах.
  • Портировать некоторые улучшения из версий 1_42 и 1_52.

Список улучшений:

  • Скроллинг по WASD, а не только клавишами Up-Down-Left-Right.
  • У Швейцарии при выделении всех юнитов первыми должны стоять крестьяне, как и у других стран.

Ссылки

Оригинальные исходники

https://github.com/GSC-fake/Cossacks-back-to-war

Версия 1_42 2017

https://github.com/ereb-thanatos/cossacks-revamp-2017

Версия 1_52 2025

https://github.com/MisterCoderman/cossacks-2025

 

Сервер Аллигатора

http://cossacks-server.net/en.html

Исходники сервера Аллигатора

https://github.com/rloger/SimpleCossacksServer

 

Статьи Ereb'а, который сделал версию 1_42

https://habr.com/ru/articles/277067/

https://habr.com/ru/articles/328212/

 

Интервью Аллигатора

http://www.newlcn.com/blog.php?tid=291

 

Сайты по Казакам

http://www.newlcn.com/

http://rliga.com/

 

 

Полезные патчи:

https://cossacks-war.ru/cossacks/pomor

Сочитание клавиш shift+t  для выделения всех боевых юнитов.
В сетевой игре при нажатии паузы показывается ник нажавшего.
Игра Казаки, в чате возможно отправлять заготовленные сообщений (ctr+буква в режиме чата, всего двадцать шесть заготовок).

https://cossacks-war.ru/cossacks/echoes-of-war

http://evilnoob.at.ua/

 

Дневник разработчика-некроманта

Я совершенно не знаком с технологиями применяемыми в игре, но хочу попробовать поковыряться.

А там используются WinApi, DirectX, DirectDraw, DirectPlay и другие технологии из 2000 года.

Буду разбираться.

251109

1_52

В исходных кодах активно используется WinApi

При запуске, игра попадает в меню.

\src\Main executable\Interface.cpp 488

PeekMessage

TranslateMessage(&msg);

DispatchMessage(&msg);

В меню генертся события, содержащие координаты мышки.

Эти функции описаны здесь

https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-translatemessage

https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-dispatchmessage

Вообще можно найти много инфы на MSDN

https://learn.microsoft.com/en-us/windows/win32/

https://learn.microsoft.com/en-us/windows/win32/api/

https://learn.microsoft.com/en-us/windows/win32/appuistart/designing-a-user-interface

Еще много старых сайтиков с инфой

https://firststeps.ru/mfc/winapi/r.php?52

https://vsokovikov.narod.ru/New_MSDN_API/Message_queue/fn_peekmessage.htm

http://www.directxtutorial.com/Lesson.aspx?lessonid=9-1-4

Там как раз приводится аналогичный пример:

while (true)
{
 while (!::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE)) 
 {
 // функция для работы пока нет сообщений
 }
 if (!::GetMessage(&m_msgCur, NULL, NULL, NULL)) break;
 ::TranslateMessage(&m_msgCur); 
 ::DispatchMessage(&m_msgCur);
}

 

hwnd

Type: HWND

A handle to the window whose window procedure receives the message. This member is NULL when the message is a thread message.

251110 - 251116

Закинул в chatgpt исходники сервера Аллигатора.

Его программа состоит из 3х проектов на perl.

Планирую для прикола переписать его сервер на C++

Закинул в cursor ai исходники сервера Аллигатора и задал переписать их на C++ версию.

Оно даже запускается.

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

ADDON_PROJECT_130/Ddex1.cpp

строка 3156 

word dwVersion=135;

Похоже это то место, где задается версия игры отображаемая в комнате на сервере.

Сделал репозиторий для сравнение кода версий 1_35, 1_42 и 1_52.

Поскольку в версии 1_42 некоторые файлы были переименованы(изменен регистр некоторых букв), то пришлось привести имена файлов в версии 1_35 в соответтветие с версией 1_42. Это нужно для того чтобы git правильно отобразил сделанные изменения.

При нажатии в меню кнопки сетевая игра вызывается функция

\src\Main executable\Interface.cpp:998

processMultiplayer

251117 - 251214

Был занят работой, все хотел вернуться к этому проекту, не заметил как прошел месяц.

251215 - 251221

Заново пересоздал виртуалку с winxp, потому что старая попортилась из-за порчи файловой системы на ssd.

С помощью Cursor и ChatGPT проанализировал и запустил оригинальный сервер локально, сделал версию на cpp, которая хоть как-то принимает подключение от игры.

Пытался понять из игры почему не заходит на оригинальный сервер, который я запускаю локально. Чем он отличается от боевого удаленного?

Язык разметки cml -- cossacks markup language.

251222 - 251228

Оригинальный сервер заработал локально.

Добавлен handshake как на удаленном сервере.

Добавлена заглушка чата.

Cpp сервер проходит процедуру захода на сервер.

Запустил cpp сервер удаленно на VPS.

Выяснил, что на оригинальном удаленном сервере чат работает на ngIRCd.

Установил локально ngIRCd.

251229 - 260104

Почти ничего не делал. Новый год.

260105 - 260111

Оказывается сервер на cpp, который я сделал с помощью ChatGPT уже позволяет создать комнату для двух или трёх игроков (для большего числа не проверял) и успешно запустить игру.

Выясняю как это вообще работает.

Как я понял если к хосту подключается один клиент, то они начинают общаться по UDP между собой.

А если к хосту подключаются два клиента, то хост должен всех подружить. Сообщить клиентам внешние адреса и порты друг друга. Это делает игра в режиме хоста. Поскольку у хоста открыт порт 34000, то к нему могут без проблем подключиться остальные игроки.

При запуске игры клиенты пытаются установить свзязи каждый с каждым. То есть помимо хоста клиент1 пытается наладить прямую свзяь с клиентом2 в обход хоста. И если получилось, то все отлично. Даже если хост выйдет, игра продоолжится.

А если клиенту1 не удалось наладить прямую свзяь с клиентом2 в обход хоста, хосту приходится быть ретранслятором пакетов от клиента1 к клиенту2. При этом задержка увеличивается, игра работает. Но если хост выйдет, то игра завершится, потому что нет прямой связи между клиентами. Это тоже проблема.

Главная проблема в том чтобы сделать так чтобы хосту не надо было открывать порт 34000 и иметь белый IP.

Надо попробовать сделать STUN и TURN хотя бы для хоста.

Или еще проще.

Достаточно сделать сервер ретранслятор для хоста и немного доработать игру-клиент. 

Когда хост игрок создаст комнату, сервер-лобби узнает его внешний ip, пускай он даже не белый.

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

Далее когда подключится клиент1, то сервер-лобби сообщит ему ip и порт 34000 сервера-ретранслятора.

Клиент1 начнёт стучаться к хосту через сервер-ретранслятор.

Сервер-ретранслятор подменит ip и номер порта назначения на хостовые, а ip и номер порта источника заменит на соответствующие серверу-ретранслятору.

Клиент2 также будет стучаться на сервер-ретранслятор, а сервер-ретранслятор подменит ip и номер порта назначения на хостовые, а ip и номер порта источника заменит на соответствующие серверу-ретранслятору.

При этом в обратную сторону, когда хост обращается к клиенту1, сервер-ретранслятор должен подменять ip и номер порта назначения на клиента1, а ip и номер порта источника заменит на соответствующие серверу-ретранслятору. Тоже самое для клиента2.