Пороги детектора рассинхрона предикта: расхождение считается нарушением,
если |предсказанное − авторитетное| по компоненту player-блока превышает
порог. Раскладка компонентов — игровая, поэтому пороги задаются позиционно
(thresholds[i]), а недостающие берутся из default_threshold.
Движковая половина конфигурации ядра (Wasm Host ABI, PLAN.md §3.4):
общая для любой игры, не знает про модели/оружие/панель. Игровая
половина — G::Config (crate::sim::GameDef::Config), парсится и
живёт в game-crate; корневой JSON, который собирает JS, имеет форму
{engine: {...}, game: {...}} — сборка обоих кусков в один объект
init-конфига делает GameCore::new в game-crate.
Описание одного поля строки блока — порядок в векторе равен порядку
байтов в раскладке (и порядку полей в конкретной Row-структуре
core/src/snapshot.rs — молчаливый контракт, проверяемый тестами).
Класс блока: «горячий» — интерполируется клиентом между кадрами
(танки, динамика карты), «событийный» — одноразовый, кадром как есть
(трассеры/бомбы/взрывы).
Форма блока в бинарном снапшоте (kind из src/config/opcodes.js):
ширина id/count и наличие null-маркера для удалённых строк. Раскладка
ПОЛЕЙ внутри строки — генерик, описывается отдельно схемой fields
(см. BlockSchema) и не зашита в Rust; движок не знает игровых имён
сущностей (танк/снаряд/трассер), только форму их строк.
Длина player-блока предикшена (predicted player state), см.
Tank::prediction_state. Единая константа вместо 4 независимых
литералов 8 (snapshot.rs/unpack.rs/tank.rs/predictor.rs).