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
Сайты по Казакам
Полезные патчи:
https://cossacks-war.ru/cossacks/pomor
Сочитание клавиш shift+t для выделения всех боевых юнитов.
В сетевой игре при нажатии паузы показывается ник нажавшего.
Игра Казаки, в чате возможно отправлять заготовленные сообщений (ctr+буква в режиме чата, всего двадцать шесть заготовок).
https://cossacks-war.ru/cossacks/echoes-of-war
Дневник разработчика-некроманта
Я совершенно не знаком с технологиями применяемыми в игре, но хочу попробовать поковыряться.
А там используются 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.