Skip to content

Текущее состояние (выводы исследования) ​

ПунктТекущее состояние
Сервер контента (протокол метаданных)src/network/core/config.cpp NetworkContentServerConnectionString(): переменная окружения OTTD_CONTENT_SERVER_CS, по умолчанию content.openttd.org (TCP порт 3978)
Зеркала загрузкиNetworkContentMirrorUriString(): переменная окружения OTTD_CONTENT_MIRROR_URI, по умолчанию https://binaries.openttd.org/bananas
Способ загрузкиnetwork_content.cpp DownloadSelectedContentHTTP(): один POST-запрос со всеми ID контента → зеркало возвращает список заголовков файлов (id,type,filesize,url на строку) → последовательная загрузка каждого файла (каждый через отдельное GET-соединение) → AfterDownload() gunzip + tar распаковка
Модель потоковHTTP-слой (WinHttp) работает в фоновом потоке, но загрузка файлов последовательная; нет списка зеркал, нет внутриигровых настроек, нет параллельности

Реализация данной функции ​

1. Новые настройки (network_settings.ini + settings_type.h) ​

  • network.content_server (SLE_STR, по умолчанию пусто = официальный сервер)
  • network.content_mirrors (SLE_STR, несколько URI зеркал через запятую, по умолчанию пусто = официальное зеркало)

Приоритет: переменная окружения > настройки игры > официальные значения по умолчанию.

2. Разбор конфигурации (src/network/core/config.cpp/h) ​

  • NetworkContentServerConnectionString() читает настройки;
  • Новый NetworkContentMirrorUris() разбирает список через запятую (удаление пробелов, пропуск пустых, запасной официальный источник);
  • NetworkContentMirrorUriString() изменён для возврата первого элемента списка.

3. Параллельная загрузка (src/network/network_content.h/.cpp) ​

  • Новый ContentFileDownload (один файл для загрузки: id/type/filesize/url/filename);
  • Новый ContentDownloadSession : HTTPCallback (независимый статус загрузки каждого файла и колбэк; IsCancelled взаимодействует с handler);
  • DownloadSelectedContentHTTP(): POST к mirrors[mirror_index] → ParseResponseHeaders() однократный разбор всех заголовков файлов → StartDownloadSessions() запускает до 4 параллельных сессий (CONTENT_DOWNLOAD_PARALLEL), каждая завершённая сессия автоматически берёт следующий файл для загрузки;
  • Цепочка повторов при сбое: сбой сессии/сбой запроса к зеркалу → повторный запрос к следующему зеркалу → все зеркала не удались → откат к старому протоколу TCP (DownloadSelectedContentFallback);
  • Корректное завершение: при сбое/отмене устанавливается download_cancelled, ожидание завершения всех текущих сессий (OnAllSessionsDone) перед повторной попыткой или откатом, чтобы избежать зависших колбэков;
  • ResetMirrorIndex(): новая загрузка начинается с первого зеркала (вызывается при запуске из GUI).

Затронутые файлы ​

  • src/table/settings/network_settings.ini (добавлено 2 настройки)
  • src/settings_type.h (NetworkSettings добавлено 2 поля)
  • src/network/core/config.cpp / config.h (разбор списка зеркал)
  • src/network/network_content.h / .cpp (параллельные сессии)
  • src/network/network_content_gui.cpp (сброс индекса зеркала перед загрузкой)

Ключевые моменты проверки ​

  1. После заполнения network.content_mirrors несколькими URI (через запятую) загрузка контента должна работать и загружать несколько файлов параллельно (наблюдать прогресс загрузки / несколько одновременных соединений);
  2. При отсутствии сети/ошибочном зеркале должен автоматически пробоваться следующее зеркало, затем откат к старому протоколу;
  3. При отмене загрузки не должно оставаться незавершённых .tar.gz файлов;
  4. Требуется проверка на реальном железе (в репозитории нет среды сборки, код не компилировался).

Известные ограничения ​

  • Степень параллельности жёстко задана как 4 (CONTENT_DOWNLOAD_PARALLEL), в будущем может быть сделана настраиваемой;
  • Протокол зеркал зависит от формата официального bananas API (POST со списком ID возвращает список заголовков файлов).