Выводы исследования: оба лимита структурные
Лимит онлайн-игроков = 255 (жёсткое ограничение разрядности протокола)
| Расположение | Содержание |
|---|---|
src/network/network_type.h:21 | static const uint MAX_CLIENTS = 255; |
src/network/network_type.h:54 | ClientPoolIDTag : PoolIDTraits<uint16_t, MAX_CLIENTS + 1, 0xFFFF> |
src/network/core/network_game_info.cpp | clients_max / companies_max передаются через Send_uint8 / Recv_uint8 в SerializeNetworkGameInfo (строки 251-296) и десериализации (строки 422-432) |
src/table/settings/network_settings.ini:241 | network.max_clients (SLE_UINT8, max = MAX_CLIENTS, по умолч. 25) |
src/network/network_server.cpp:360 | Проверка при подключении _network_clients_connected < MAX_CLIENTS |
Вывод: 255 — это уже предел поля uint8 протокола. Для его превышения необходимо изменить clients_max и связанные поля на uint16 — это изменит протокол client↔server, UDP-широковещательные рассылки и протокол Game Coordinator, что является внешним изменением протокола (в рамках форка оба конца могут играть, но совместимость с публичным списком серверов пострадает).
Лимит количества компаний = 15 (жёсткое ограничение формата хранения владельца тайла)
| Расположение | Содержание |
|---|---|
src/company_type.h:25 | CompanyIDTag : PoolIDTraits<uint8_t, 0xF, 0xFF> → MAX_COMPANIES = CompanyID::End().base() = 15 |
src/tile_map.h:195 | SetTileOwner: SB(_m[tile].m1, 0, 5, owner.base()) — владелец тайла хранится только в 5 битах (младшие 5 бит _m[].m1) |
src/company_type.h:30-33 | OWNER_TOWN{0x0F}, OWNER_NONE{0x10}, OWNER_WATER{0x11}, OWNER_DEITY{0x12}, OWNER_END{0x13} используют то же байтовое пространство, что и ID компаний |
Вывод: Owner и CompanyID — один и тот же тип, поле владельца тайла имеет только 5 бит (значения 0-31), из которых 15-18 заняты специальными владельцами. Таким образом, реальный лимит компаний 15 определяется форматом массива карты — для его увеличения требуется расширить хранение владельца тайла (все 8 бит m1 или изменить структуру _m) и мигрировать константы OWNER_*, что включает полную конвертацию сохранений и рост памяти карты, являясь крупным рефакторингом формата (поэтому OpenTTD upstream не делал этого много лет).
Варианты решений
| Вариант | Изменения | Совместимость | Рекомендация |
|---|---|---|---|
| A. Оставить как есть | Нет | Полная совместимость сохранений/протокола/координатора | ✅ Рекомендуется: 255 клиентов / 15 компаний уже значительно превышает оригинал для многопользовательской игры |
| B. Клиент → протокол uint16 | Сериализация/десериализация network_game_info.cpp изменить на Send_uint16/Recv_uint16; MAX_CLIENTS поднять до 4095; max_clients в network_settings.ini изменить на SLE_UINT16; поле в settings_type.h изменить на uint16; ширина отображения в console_cmds.cpp:1056 | Играбельно в рамках форка; несовместимо с публичным координатором/старыми клиентами | Опционально, если действительно нужно >255 клиентов |
| C. Компании → рефакторинг формата тайлов | Расширение поля владельца тайла + миграция констант OWNER_* + полная конвертация сохранений | Изменение формата сохранений (одноразовая конвертация) | Не рекомендуется для краткосрочной реализации |
Что уже предоставлено
- Данный проектный документ (с точными файлами/строками);
- Опциональный патч
option-clients-uint16.diff(полные изменения для варианта B, не применён, доступен дляgit apply).
Вывод: «Расширение» обоих лимитов по сути является обновлением формата/протокола, а не настройкой; при сохранении совместимости сохранений и публичной сети текущие 255/15 являются пределом. Если допустимы затраты на совместимость, варианты B/C реализуются как описано выше.