Q2PRO-X 1.0 — Архитектурный аудит fairness

Просмотр документа на сайте Q2PRO-X. Оригинальный файл можно скачать из окна сайта.

Q2PRO-X 1.0

Архитектурное ревью по мультиплеерной честности

Русское издание для сайта

Q2PRO-X 1.0 Multiplayer Fairness Audit

Дата: 2026-04-14 Язык: русский Статус: архитектурно-технический аудит по коду

1. Цель проверки

Проверить, предоставляет ли текущий Q2PRO-X в `deathmatch > 0` реальные читерские преимущества по сравнению с допустимым клиентским quality-of-life поведением.

Основной фокус проверки:

  1. Предиктное оружие: может ли клиент реально стрелять быстрее, точнее или раньше, чем это допускает сервер.
  2. Клиентские улучшения движения и сетевого отклика: относятся ли они к читам.
  3. Визуальные системы Q2PRO-X: могут ли они давать gameplay advantage, не нарушая серверную механику напрямую.

2. Итоговый вывод

2.1. Серверно-механических читов по результатам проверки не выявлено

Текущая архитектура Q2PRO-X не содержит подтверждённого пути, при котором клиент мог бы:

  • реально увеличить скорострельность оружия;
  • нанести урон раньше серверного разрешения;
  • повысить реальную точность попадания сверх серверной модели;
  • породить "лишние" projectile/hitscan события вне серверной логики;
  • обойти серверную валидацию времени команд за счёт client prediction.

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

2.2. Клиентские predict/movement-пути не относятся к читам

`cl_fixedmove`, `cl_predict_move_mode`, `cl_movement_feel`, `cl_step_smoothing_mode`, `cl_laghax` и связанные с ними ветки не относятся к читам, поскольку:

  • они не изменяют серверную модель стрельбы и урона;
  • они не создают серверные fire events самостоятельно;
  • они не обходят серверную обработку `usercmd`;
  • они не изменяют серверную физику мира;
  • они являются клиентскими улучшениями локального управления, нормализации ввода, сглаживания и восприятия задержки.

2.3. Остаточный риск относится не к server-authority, а к visibility advantage

При этом в Q2PRO-X остаются клиентские системы, которые не ломают серверную честность, но способны менять визуальную читаемость сцены. Для полу-публичного тестирования 1.0 это следует рассматривать как отдельный policy-risk.

Главный пример: `weapon parts visibility`, позволяющий скрывать часть визуальных эффектов других игроков.

3. Предиктное оружие: техническое обоснование

3.1. Клиентский ghost/predict не управляет реальной стрельбой

В [input.c](O:/Claude2/q2pro/src/client/input.c) атака сначала попадает в обычный `usercmd`, и только после финализации команды вызывается клиентский `Ghost_OnFireCmd`:

  • `BUTTON_ATTACK` выставляется в [input.c](O:/Claude2/q2pro/src/client/input.c:1103)
  • финализированный `usercmd` сохраняется в [input.c](O:/Claude2/q2pro/src/client/input.c:1154)
  • `Ghost_OnFireCmd(...)` вызывается после этого в [input.c](O:/Claude2/q2pro/src/client/input.c:1162)

Следовательно, client ghost layer не является источником серверного fire command; он является реакцией на уже сформированный локальный input path.

3.2. Сервер валидирует клиентское время команд

В [user.c](O:/Claude2/q2pro/src/server/user.c) сервер ведёт учёт `command_msec`:

  • инициализация бюджета времени: [user.c](O:/Claude2/q2pro/src/server/user.c:531)
  • списание `cmd->msec`: [user.c](O:/Claude2/q2pro/src/server/user.c:1123)
  • underflow check через `sv_enforcetime`: [user.c](O:/Claude2/q2pro/src/server/user.c:1127)

`sv_enforcetime` по умолчанию включён:

  • [main.c](O:/Claude2/q2pro/src/server/main.c:2207)

Это означает, что даже при клиентских различиях в cadence/packing сервер сохраняет контроль над допустимым временем исполнения команд.

3.3. Реальное решение о стрельбе принимает серверный `Think_Weapon`

В [p_client.c](O:/Claude2/q2pro/src/game/p_client.c) сервер:

  • принимает `ucmd->buttons` в [p_client.c](O:/Claude2/q2pro/src/game/p_client.c:1637)
  • вычисляет `latched_buttons` в [p_client.c](O:/Claude2/q2pro/src/game/p_client.c:1638)
  • вызывает `Think_Weapon(ent)` при атаке в [p_client.c](O:/Claude2/q2pro/src/game/p_client.c:1656)
  • дополнительно вызывает `Think_Weapon(ent)` в server frame path в [p_client.c](O:/Claude2/q2pro/src/game/p_client.c:1709)

То есть реальная серверная weapon state machine не заменяется клиентским предиктом.

3.4. Скорострельность задаётся серверной weapon state machine

В [p_weapon.c](O:/Claude2/q2pro/src/game/p_weapon.c) `Weapon_Generic(...)` является авторитарным конечным автоматом оружия:

  • вход в `WEAPON_READY`: [p_weapon.c](O:/Claude2/q2pro/src/game/p_weapon.c:413)
  • переход в `WEAPON_FIRING` только при допустимой атаке и наличии ammo: [p_weapon.c](O:/Claude2/q2pro/src/game/p_weapon.c:414)
  • выстрел только на разрешённых `fire_frames[]`: [p_weapon.c](O:/Claude2/q2pro/src/game/p_weapon.c:458)
  • возврат в `WEAPON_READY` по серверной frame logic: [p_weapon.c](O:/Claude2/q2pro/src/game/p_weapon.c:472)

Конкретные fire-frame схемы заданы сервером, например:

  • Rocket Launcher: [p_weapon.c](O:/Claude2/q2pro/src/game/p_weapon.c:720)
  • Blaster: [p_weapon.c](O:/Claude2/q2pro/src/game/p_weapon.c:778)
  • HyperBlaster: [p_weapon.c](O:/Claude2/q2pro/src/game/p_weapon.c:843)
  • Machinegun: [p_weapon.c](O:/Claude2/q2pro/src/game/p_weapon.c:936)
  • Chaingun: [p_weapon.c](O:/Claude2/q2pro/src/game/p_weapon.c:1045)
  • Shotgun: [p_weapon.c](O:/Claude2/q2pro/src/game/p_weapon.c:1105)
  • Super Shotgun: [p_weapon.c](O:/Claude2/q2pro/src/game/p_weapon.c:1162)
  • Railgun: [p_weapon.c](O:/Claude2/q2pro/src/game/p_weapon.c:1222)
  • BFG: [p_weapon.c](O:/Claude2/q2pro/src/game/p_weapon.c:1294)

Из этого следует, что `Super Shotgun` не может реально стрелять быстрее серверно разрешённого цикла только из-за клиентского предикта.

3.5. Реальные projectile, trace и damage создаются на сервере

Настоящая боевая логика находится в [g_weapon.c](O:/Claude2/q2pro/src/game/g_weapon.c):

  • `fire_bullet(...)`: [g_weapon.c](O:/Claude2/q2pro/src/game/g_weapon.c:249)
  • `fire_shotgun(...)`: [g_weapon.c](O:/Claude2/q2pro/src/game/g_weapon.c:261)
  • `fire_blaster(...)`: [g_weapon.c](O:/Claude2/q2pro/src/game/g_weapon.c:312)
  • `fire_rocket(...)`: [g_weapon.c](O:/Claude2/q2pro/src/game/g_weapon.c:575)
  • `T_Damage(...)`: например [g_weapon.c](O:/Claude2/q2pro/src/game/g_weapon.c:202), [g_weapon.c](O:/Claude2/q2pro/src/game/g_weapon.c:550)
  • `T_RadiusDamage(...)`: например [g_weapon.c](O:/Claude2/q2pro/src/game/g_weapon.c:396), [g_weapon.c](O:/Claude2/q2pro/src/game/g_weapon.c:562)

Следовательно:

  • клиент не наносит урон самостоятельно;
  • клиент не создаёт настоящий серверный projectile;
  • клиент не может "ускорить" урон только за счёт ghost-слоя.

3.6. Клиентский ghost-слой прямо описан как visual-only

В [ghost.c](O:/Claude2/q2pro/src/client/ghost.c:1) система прямо описана как `client-side ghost projectile prediction`, немедленно создающая `visual-only ghosts`.

Дополнительно:

  • [weaponfx.c](O:/Claude2/q2pro/src/client/weaponfx.c:6) фиксирует, что weapon FX layer не трогает admission gate и не dispatch-ит sound;
  • [ghost.c](O:/Claude2/q2pro/src/client/ghost.c:2438) фиксирует, что при скрытии predicted visuals bookkeeping handoff/suppress path продолжает работать, а меняется только визуальная часть.

Итог: клиентский predict-слой не является альтернативной системой урона или скорострельности.

4. Movement / Laghax / Fixedmove

Эти механизмы не относятся к читам, поскольку по коду они не создают отдельную серверную физику и не подменяют weapon authority.

Даже если `cl_fixedmove` меняет способ клиентского разбиения команд по времени, сервер всё равно:

  • получает обычные `usercmd`;
  • считает `command_msec`;
  • применяет стандартную game DLL weapon/movement logic.

Следовательно, данные механизмы относятся к категории client experience improvements, а не к server-authority bypass.

5. Визуальные системы: где проходит граница

5.1. Visibility highlights в текущем виде не дают wallhack

Ветка `visibility / highlights` уже содержит multiplayer-safe ограничения:

  • увеличение item/dropped weapon scale выше `1.0` в multiplayer режется в [vis_items.c](O:/Claude2/q2pro/src/client/vis_items.c:537)
  • для увеличенной модели кулинг всё равно считается по исходному размеру через `ent.cull_scale = base` в [entities.c](O:/Claude2/q2pro/src/client/entities.c:945)
  • renderer использует `entcullscale` при sphere cull в [main.c](O:/Claude2/q2pro/src/refresh/main.c:199) и получает его из entity в [main.c](O:/Claude2/q2pro/src/refresh/main.c:309)
  • толщина player shell ограничена малым диапазоном `0.0 .. 0.05` в [vis_items.c](O:/Claude2/q2pro/src/client/vis_items.c:953)

Это означает, что данная система не должна позволять "вытаскивать" pickup или player silhouette из-за геометрии только за счёт увеличения масштаба.

Однако она всё равно повышает визуальную заметность уже видимых целей и объектов. Это не server cheat, но это visual assist.

5.2. Weapon Parts Visibility остаётся policy-risk для competitive multiplayer

Наиболее спорной системой на текущий момент является `weapon parts visibility`.

По коду:

  • система специально позиционируется как `visual-only policy layer` в [weaponfx.c](O:/Claude2/q2pro/src/client/weaponfx.c:1)
  • она не трогает admission gate и не dispatch-ит sound в [weaponfx.c](O:/Claude2/q2pro/src/client/weaponfx.c:6)
  • но она позволяет отключать целые классы FX у источника `WFX_SRC_OTHER` через [weaponfx.c](O:/Claude2/q2pro/src/client/weaponfx.c:38)
  • foreign projectile model скрывается в [entities.c](O:/Claude2/q2pro/src/client/entities.c:716)
  • wall impact path других источников классифицируется в [tent.c](O:/Claude2/q2pro/src/client/tent.c:1602)

Это не меняет урон и не делает стрельбу "сильнее", но может:

  • упростить чтение сцены;
  • уменьшить визуальный шум;
  • скрыть часть информации о стрельбе и projectile path других игроков.

С точки зрения строгой multiplayer fairness это следует считать не серверным читом, а competitive visibility assist.

6. Практическая оценка готовности к 1.0

6.1. Что можно считать безопасным

Для версии 1.0 безопасно утверждать следующее:

  • predicтное оружие не стреляет быстрее серверной нормы;
  • predicтное оружие не наносит урон вне серверной авторизации;
  • fixedmove / laghax / movement feel не относятся к читам;
  • visibility highlights не создают wallhack-пути через geometry protrusion.

6.2. Что требует policy-решения до расширенного тестирования

Перед более широким полу-публичным тестированием рекомендуется отдельно определить multiplayer policy для:

  • `cl_weaponfx_vis_other` и связанных с ним hiding-веток;
  • player/item highlighting в competitive режимах;
  • любых визуальных assist-настроек, очищающих сцену в `deathmatch > 0`.

7. Рекомендация

Для 1.0 рекомендуется разделить вопрос на два класса:

  1. **Server-authority fairness**

Это направление по результатам проверки выглядит корректно и готово.

  1. **Competitive visual policy**

Это направление следует зафиксировать отдельным профилем для `deathmatch > 0`, если цель релиза 1.0 — не только отсутствие механических читов, но и отсутствие спорных визуальных преимуществ.

8. Финальный вывод

По результатам аудита:

  • Q2PRO-X не содержит подтверждённого механизма, позволяющего predicтному оружию реально стрелять быстрее, точнее или сильнее серверной нормы;
  • client predict, fixedmove, movement feel и laghax не относятся к читам, поскольку не обходят серверную игровую механику;
  • основной остаточный риск перед 1.0 относится к visual assist / visibility policy, а не к server-authority exploitation.

Итоговая формулировка:

**Серверно-механических читерских возможностей по проверенному коду не выявлено. Остаточная зона внимания перед 1.0 — клиентские visibility advantages, прежде всего в ветке weapon parts visibility.**