Фаза тиков: скрытая задержка Майнкрафта, которой нет в табе

При одинаковом пинге 2 один игрок видит соперника с опозданием 44 мс, а другой — 6 мс. Разницу даёт фаза тиков — сдвиг между тиками сервера и вашего клиента. В табе её не видно, но именно она решает размены, КБ и тот самый «рич 3,2».

Ниже — разбор и документация: как устроена фаза, почему она плывёт, как её выравнивает мод Tick Sync, сколько это даёт на самом деле и что вышло, когда мы проверили всё на себе.

Коротко

Два игрока, один пинг

Возьмём двух игроков с одинаковым пингом 2, одинаковыми клиентами и реакцией. Они бегут друг на друга — и один попадает первым в четырёх разменах из пяти. Это не читы и не «у него руки лучше».

Пинг 2 у обоих, а игрок Б бьёт первым в 4 разменах из 5.

В Майнкрафте есть задержка, которую пинг в табе не показывает вообще. Она случайная, у каждого своя и доходит до 50 мс — даже когда пинг 2. Например, при одинаковых 2 мс в табе реальная задержка у меня без мода может быть 44 мс, а у PynPun с модом — 6 мс.

В табе у обоих 2 мс, на деле 44 и 6 мс (пример). В таб попадает только дорога пакета.

Один PvP-клиент прямо обещает в рекламе «минус 25 мс к любому серверу». Правда ли это — проверим. По пунктам:

  1. Откуда берётся задержка, которой нет в табе.
  2. Почему именно она решает размены в PvP, КБ и откуда ощущение «рича 3,2».
  3. Почему в моменте игра идёт идеально, а потом на спад.
  4. Как мод убирает эту задержку и сколько он даёт на самом деле.
  5. Что вышло, когда мы проверили всё это на себе.

Тики: как Майнкрафт считает мир

Майнкрафт считает мир не непрерывно, а шагами — тиками. Их 20 в секунду, значит один тик длится 50 мс. Между тиками мир стоит, а в тик игра двигает игроков и мобов и считает удары.

Мир двигается шагами по 50 мс, а сервер и клиент — два метронома на одной скорости.

Важная деталь: тикает и сервер, и ваш клиент — каждый по своим часам. Сервер начал считать тики, когда запустился, а клиент — когда вы запустили игру. Темп одинаковый, 20 в секунду, но щелчки не совпадают — как у двух метрономов, которые включили в разные моменты.

Источник: Minecraft Wiki — Tick, 20 игровых тиков в секунду.

Фаза на пальцах: курьер и почтовый ящик

Представьте курьера, который кладёт газету в ящик строго каждые 50 минут: в 12:00, 12:50, 13:40. Вы тоже проверяете ящик раз в 50 минут, но по своему расписанию.

Если вы заглядываете в 12:45, 13:35 и 14:25, газета каждый раз лежит 45 минут, и вы всегда читаете старые новости. Если в 12:05, 12:55 и 13:45 — она лежит всего 5 минут. Курьер одинаково быстрый, вы проверяете одинаково часто: разница только в сдвиге вашего расписания относительно курьера. Этот сдвиг и есть фаза.

Газета лежит 45 или 5 минут; сдвиг расписания — это фаза. Вторая половина ролика переводит аналогию на Minecraft.

В Майнкрафте курьер — это сервер: в такт своим тикам он рассылает, где стоят игроки. Дорога — это пинг. Проверка ящика — ваш клиентский тик: только в него игра применяет пришедшие данные — двигает соперника, его хитбокс и вас самих, включая ваш КБ.

То же пишет автор мода Tick Sync: клиент ждёт конца текущего тика, прежде чем применить пришедший пакет. В его примере пакет пришёл на 2-й миллисекунде тика и ждёт 48.

Пинг 2 — не задержка 2

Пинг — это путь туда и обратно, поэтому при пинге 2 пакет от сервера летит к каждому игроку 1 мс. Сервер отправляет данные в 0, 50 и 100 мс, и к обоим они приходят в 1, 51 и 101 мс.

У игрока А тики идут в 44, 94 и 144 мс. Пакет пришёл в 1, а ближайший тик только в 44: данные лежат 43 мс, и так каждый раз. У игрока Б тики в 6, 56 и 106 мс: пакет пришёл в 1, тик в 6 — данные лежат 5 мс.

Пакет летит 1 мс и ждёт тика: у А — 43 мс, у Б — 5 мс.

В табе у обоих 2. Но А видит соперника с опозданием 1 + 43 = 44 мс, а Б — 1 + 5 = 6 мс. Разница 38 мс, и пинг её не показывает: при пинге 2 почти вся задержка — это ожидание тика.

Дорога плюс ожидание: 44 мс против 6 мс при одинаковом пинге.

Игрок Б — в удачной фазе. В комьюнити это состояние иногда называют «Потоком». Числа 44 и 6 — пример: у каждого игрока своя фаза, а арифметику можно проверить в симуляции из материалов к статье.

Что фаза меняет в бою

Удачная фаза работает как пинг на десятки миллисекунд ниже. В PvP это заметно в трёх местах: размен, КБ и «рич».

Размен

Игрок с удачной фазой раньше видит соперника в зоне удара, раньше кликает — и его удар первым долетает до сервера. Грубо говоря, в размене решает сумма: пинг плюс ожидание своего тика. У игрока А это 2 + 43 = 45, у игрока Б — 2 + 5 = 7.

Пинг + ожидание: 4 из 5 разменов при одинаковом пинге и 7 из 10 у игрока с пингом 20.

В нашей симуляции игрок Б при таких фазах бьёт первым в 81% разменов — примерно в четырёх из пяти. Игрок с пингом 20 и удачной фазой (20 + 5 = 25) забирает около 70% разменов у игрока с пингом 2 и неудачной фазой (2 + 45 = 47). Не все размены, потому что клик тоже ждёт своего тика и добавляет случайности.

КБ

Отбрасывание приходит к жертве пакетом и применяется только в её тик. С пингом 20 и удачной фазой вы начинаете лететь через 15 мс после того, как сервер засчитал удар: 10 мс на дорогу и 5 на ожидание. С пингом 2 и неудачной фазой — через 46 мс. Пинг в десять раз хуже, а отлетаете раньше.

Пинг 20 с удачной фазой отлетает через 15 мс, пинг 2 с неудачной — через 46 мс.

«Рич 3,2»

Reach Display меряет дистанцию на вашем экране в момент клика — и не врёт. Но у соперника картинка старше. Спринт — около 5,6 блока в секунду, значит 38 мс — это примерно 0,2 блока.

У вас на экране 2,8 блока, у него в тот же момент — около 3,0. А если он ещё и отлетает в комбе, на его записи удар выглядит как с 3,1–3,2.

У вас 2,8 блока, у него 3,0, а в комбе — 3,2.

Правы оба: каждый видит свою картинку. А сервер проверяет удар по своим координатам, а не по чьему-то экрану.

Почему фаза случайная и плывёт

Фазу никто не выбирает. Клиент считает тики с запуска игры, сервер — со своего запуска, и подгонять их друг к другу никто не пытается. Поэтому ожидание выпадает случайно: любое значение от 0 до 50 мс одинаково вероятно, в среднем — 25.

Шесть тысяч запусков игры: ожидание распределено ровно, среднее — 25 мс.

Перезапустили игру — новая лотерея. А вот перезаход на тот же сервер фазу, скорее всего, не меняет: клиент продолжает считать тики от запуска игры.

И фаза не стоит на месте. Часы компьютера и сервера идут чуть-чуть по-разному. Если ваш тик на деле длится, скажем, 50,003 мс, за один тик это ничто, а примерно за 14 минут набегает целый круг в 50 мс. На разных компьютерах полный круг занимает от десятка минут до часа.

Пример: 15 минут игры за 15 секунд. «Поток», граница, вязко и снова «Поток».

Поэтому бывает так: сначала всё летает, потом соперник начинает дёргаться, потом игра становится вязкой, а затем снова приходит «Поток». Подёргивание — это момент, когда пакеты приходят ровно на границе вашего тика: один успевает и лежит 1 мс, следующий опаздывает и лежит 49 — и модель соперника дёргается.

Фраза «вчера сервер летал, а сегодня вязкий» иногда буквально про фазу.

Где проверить на себе: CisPractice

Бои на пинге 2 из этого разбора мы снимали на моём сервере — CisPractice. Из Москвы пинг туда около 2 мс, так что почти вся ваша задержка там и есть фаза. Хотите проверить её на себе — заходите: IP cisprac.xyz.

Остальные раунды нашего теста сыграны на шведском sworder.xyz с пингом 20 — подробности в разделе «Наш тест».

Что даёт удачная фаза и чего не даёт

Фаза — скрытая задержка от 0 до 50 мс, которой нет в пинге. Она случайная, держится минутами и плывёт. Её можно выровнять — и тогда у вас всегда будет удачная.

Что даёт выравнивание фазы и чего не даёт, по пунктам.

ДаётНе даёт
Свежую картинку: до −18 мс на приёме данныхДругой пинг: дорога пакета остаётся той же
Чаще первый удар в разменахУскорение клика: он всё равно ждёт тика
Быстрый отлёт после удараПолной пользы на скачущем Wi‑Fi и 60 FPS
Одинаковое ощущение в каждой сессииЧестности, если мод только у части игроков

Дальше — как это устроено на самом деле, с кодом.

Два ожидания: сервер и клиент

На самом деле ожиданий два. Первое — сервер ждёт свой тик, чтобы обработать ваши пакеты: удары и движение. Второе — клиент ждёт свой тик, чтобы применить пакеты сервера: позиции и КБ.

Два ожидания, сервер с очередью против Paper, код Paper и вывод: остаётся ожидание на клиенте.

Первое ожидание зависит от ядра сервера. Ванильный сервер 1.21.9 и новее (и 1.8) разбирает пакеты игроков только в начале тика — это ещё от 0 до 50 мс на каждый удар. Paper будит сервер, как только пакет пришёл, и обрабатывает его сразу, если сервер в этот момент не занят тиком.

Это видно прямо в коде Paper 1.21.11. В патче PacketProcessor, строки 31–43 есть комментарий «wake up main thread inbetween ticks to process packets» и вызов LockSupport.unpark. В патче MinecraftServer, строка 918 — «process packets while waiting inbetween ticks», а в строках 1012–1015 видно, как Paper заменяет ванильный processQueuedPackets() в начале тика. Оптимизация Moonrise для Fabric делает то же: «Handle packets sent while the integrated/dedicated server is waiting for next tick (lowering perceived latency)».

Значит, на Paper и его форках удары засчитываются по приходу. Остаётся только второе ожидание — на вашей стороне, и убрать его может только мод на клиенте.

Как работает Tick Sync

Tick Sync — открытый мод под Fabric для 1.21.1 и новее, включая версии 26.x (сборка 1.4.0 есть для 1.21.1–1.21.11 и 26.1–26.3, скачать — на странице версий). Он сдвигает ваши тики так, чтобы они наступали сразу после прихода пакетов. Работает в четыре шага:

  1. Замер. Мод меряет, сколько пакеты движения сущностей лежат до вашего тика.
  2. Сдвиг. Считает, на сколько отодвинуть тик. Например, пакеты лежат 43 мс, а нужно 5 — значит, сдвиг 50 − 43 + 5 = 12 мс.
  3. Длинный тик. Один раз растягивает тик: 62 мс вместо 50. После этого тики снова идут ровно по 50 мс, но уже сразу после прихода пакетов.
  4. Слежение. Продолжает мерить и пересинхронизируется, если фаза уплыла или поменялся пинг, — не чаще раза в секунду.

Четыре шага мода: один длинный тик, и ожидание падает с 43 до ~5 мс.

Перезаходить на сервер с модом не нужно: дрейф часов и смену пинга он ловит сам, а при входе на сервер начинает замер заново. Игра при этом не ускоряется: тиков по-прежнему 20 в секунду.

Что видно в исходниках

Функция matchTickSync считает сдвиг, а shiftNextTickDuration растягивает следующий тик (строки 259–295). По умолчанию мод только растягивает тики. Режим fast sync умеет и укорачивать — тогда клиент на мгновение тикает чаще 20 раз в секунду. Для античита это похоже на Timer, поэтому на PvP-серверах fast sync лучше не включать.

Фрагмент исходников Tick Sync: расчёт сдвига и длинный тик.

Цена базового режима — примерно раз в одну-три минуты один тик длиннее обычного на 15–25 мс, когда мод подправляет фазу. Это микрозаминка, которую вы вряд ли заметите. При FPS ниже 40 и сильно скачущей сети мод не синхронизирует вовсе (canSync, строки 131–134).

Сколько это даёт на самом деле

При ровной сети и высоком FPS — около 17–18 мс, а не 25, как обещает реклама. MCPVP Client пишет про «Client-Server tick alignment to reduce your effective latency by 25ms to any server». Но 25 — это ровно среднее того самого ожидания от 0 до 50, то есть теоретический потолок.

Цитата рекламы: «минус 25 мс к любому серверу».

На практике мод оставляет запас на скачки пинга — джиттер: если пакет опоздает хоть на миллисекунду, он пролежит почти 50. Я повторил алгоритм Tick Sync в симуляции прямо по его исходникам. Вот средний выигрыш по модели — это оценка, а не замер:

ДжиттерВыигрыш при 240 FPS, мсВыигрыш при 60 FPS, мс
1 мс (хороший кабель)17,67,1
2 мс14,38,3
3 мс12,57,5
5 мс10,05,3
8 мс7,42,8
10 мс5,52,3
15 мс1,20,4

Столбики «джиттер → выигрыш» при 240 и 60 FPS, затем линии «пинг → выигрыш»: Paper, Wi‑Fi, сервер с очередью.

На Paper выигрыш не зависит от величины пинга: те же ≈ 17 мс и при пинге 2, и при 120, если сеть ровная. Портит его не высокий пинг, а скачущая сеть и низкий FPS.

Клиентский тик случается только на границе кадра, а на 60 FPS кадр длится 17 мс — выигрыш падает примерно до 7 мс. От 144 FPS он почти полный. На ванильном сервере с очередью выигрыш идёт пилой: от 0 до 35 мс в зависимости от пинга.

В минус не уйдёт

Частый вопрос: если пинг и так 2, мод уведёт его в минус? Нет. Мод срезает ожидание тика, а не дорогу пакета: ожидание бывает от 0 до 50, в среднем 25, а мод делает его примерно 7. На пинге 2 было в среднем 1 + 25 = 26 мс, стало 1 + 7 = 8.

Минус 18 мс из ожидания, а не из пинга; кабель, 60 FPS и Wi‑Fi.

Наш тест: 32 раунда

С модом каждый из нас выигрывал на 35 процентных пунктов чаще — но это иллюстрация, а не доказательство. Я (Hanosuko) и PynPun — оба из Москвы, пинг одинаковый. Мы сыграли 32 раунда на двух серверах — на моём CisPractice с пингом 0–2 и на шведском sworder.xyz с пингом 20 — и ставили мод по очереди: сначала мне, потом PynPun, потом снова мне.

СессияСерверПинг, мсМод уСчёт Hanosuko : PynPun
1cisprac.xyz0Hanosuko4 : 5
2cisprac.xyz2PynPun0 : 4
3sworder.xyz (Швеция)20PynPun1 : 5
4sworder.xyz (Швеция)20Hanosuko6 : 7

Раунды по сессиям: в клетках — голова того, у кого мод (зелёная — выиграл раунд, красная — проиграл), затем доли побед.

ИгрокБез модаС модом
PynPun12 из 22 (55%)9 из 10 (90%)
Hanosuko1 из 10 (10%)10 из 22 (45%)

Сессия 4: природный «Поток»

Мод был у меня, а PynPun без мода поймал природный «Поток»: из первых восьми раундов он взял шесть. Минут через пять «Поток» у него уплыл — ровно как в теории про дрейф фазы, — и дальше я взял четыре раунда из пяти.

Сессия 4 на sworder.xyz: 6 из 8 у PynPun в «Потоке», потом 4 из 5 у Hanosuko с модом.

Что совпало и что спорно

Совпало: тот, кто играл без мода, жаловался на «рич 3,2» у соперника — это та самая старая картинка. Ощущение, что искусственный «Поток» хуже природного, тоже объяснимо: мод держит запас 6–16 мс, а удачная природная фаза бывает 1–5 мс. Мод даёт не лучший «Поток», а гарантированный неплохой.

Спорно: ощущения от КБ противоречили друг другу, а жалобу «моделька лагает» с модом стоит сверить со значком синхронизации на отладочном экране.

Что совпало с теорией и что спорно.

Честно об ограничениях

32 раунда — это мало, и мы знали, у кого мод. Точный тест Фишера даёт p ≈ 0,06 — на грани значимости. В сессии 4 разница «до/после» даёт p ≈ 0,09, причём границу мы провели уже после игры.

Чтобы такой тест стал доказательством, синхронизацию должен включать третий человек и не говорить кому. Нужно по 40–50 раундов на каждое положение и включённый у обоих отладочный экран Tick Sync — он даже с выключенной синхронизацией показывает реальную фазу игрока. Все бои нашего теста целиком — в телеграм-канале t.me/hanosuko.

Чего это не делает: Better Hitreg

Better Hitreg — другой популярный мод, и он про другое. В момент удара он сам проигрывает красную вспышку и звук, не дожидаясь подтверждения сервера, а серверный дубль потом глушит. Попадание ощущается быстрее примерно на ваш пинг.

Но это только вид и звук: сервер засчитывает удар в тот же момент, КБ и размены не меняются. Автор сам пишет в README: «All custom hits are in appearance only, your actual hits are not modified in any way». А выравнивание фазы меняет реальное: вы видите позиции, хитбоксы и свой КБ свежее.

Better Hitreg показывает вспышку сразу, но только для вида; выравнивание фазы делает свежее сами данные.

Better HitregTick Sync
Что лечитЗадержку отклика на ваш ударОжидание входящих данных до тика
КакСам рисует вспышку и звук, глушит серверный дубльСдвигает тики сразу после прихода пакетов
Что меняется в игреНичего, только вид и звукПозиции, хитбоксы и ваш КБ свежее
Выигрыш≈ ваш пинг, только в ощущенияхДо ~18 мс настоящей задержки
РискМожет показать попадание, которого не былоПочти нет; fast sync похож на Timer

Когда это честно

Фаза есть у всех, и это не баг — так Майнкрафт работал всегда. Но если мод выравнивания стоит только у вас, у вас до 15–18 мс преимущества над теми, у кого его нет.

Фаза есть у всех; мод только у вас — преимущество 15–18 мс; мод у всех — честно.

Поэтому прежде чем ставить мод, проверьте правила сервера: где-то это могут считать нарушением. Честный вариант — когда мод есть у всех, например сервер кладёт его в свою сборку. Тогда «Поток» становится нормой, и лотерея исчезает.

А разница в пинге между игроками остаётся: её мод не выравнивает. Админам стоит посмотреть на плагин KnockbackSync: он пересчитывает отбрасывание так, будто оно сделано на клиенте, и делает КБ одинаковым при разном пинге.

Как проверить самому

Не верьте на слово — фазу можно проверить четырьмя способами.

  1. Отладочный экран Tick Sync. Включите useDebugScreen в файле config/ticksync-config.json. Экран показывает Tick Delay — сколько пакеты ждут вашего тика. Он работает даже с выключенной синхронизацией, то есть показывает вашу природную фазу.
  2. Команда /hitreg alertDelays в Better Hitreg. После каждого удара мод пишет в чат, через сколько миллисекунд вы увидели отлёт соперника. В удачной фазе это число меньше, правда, оно идёт шагами по 50 мс.
  3. Перезапуск игры. Без мода, когда игра кажется вязкой, перезапустите её и сравните ощущения: это новая лотерея фазы.
  4. Запись с двух сторон. Запишите бой одновременно с обеих сторон и сравните кадры: что и когда видел каждый.

Четыре способа проверки. Сообщения чата на видео — пример, а не запись из игры.

Чек-лист

Чтобы выравнивание фазы дало полный эффект, нужны четыре вещи:

Чек-лист из финала ролика.

Частые вопросы

С модом «Поток» сбрасывается, надо перезаходить?
Нет. Мод сам заново сдвигает тик, когда фаза уплыла или поменялся пинг, — не чаще раза в секунду, а при входе на сервер начинает замер заново. Без мода перезаход на тот же сервер фазу, скорее всего, не меняет: новая лотерея — только при перезапуске игры.
У меня пинг 150 — поможет?
На Paper да: выигрыш не зависит от величины пинга. Мешают скачущая сеть и низкий FPS, а не сам пинг.
Это чит?
Мод ничего не подделывает и не ускоряет игру, но у части игроков даёт преимущество до 15–18 мс — смотрите правила сервера. Fast sync похож на Timer, его не включайте.
Поставил — разницы не чувствую.
Wi‑Fi с джиттером 10+ мс или 60 FPS съедают большую часть выигрыша. И если ваша фаза и так была удачной, мод просто держит её такой всегда.
А на практике разница есть?
В нашем тесте на 32 раунда с модом каждый из нас выигрывал на 35 пунктов чаще. Но раундов мало, и мы знали, у кого мод, — это иллюстрация, а не доказательство.
На пинге 2 мод уведёт в минус?
Нет. Мод срезает только ожидание тика — от 0 до 50, в среднем 25, — примерно до 7 мс. Дорогу пакета не срезает никто: на пинге 2 было около 26 мс, стало около 8.

Как считались цифры

Все числа о выигрыше — оценка по моделям, а не замер в игре. Скрипты и данные теста — в репозитории tick-phase-minecraft на GitHub и в архиве с материалами к статье (ZIP, 13 КБ), для запуска нужны Python 3, numpy и scipy.

Источники

Ссылки на код закреплены за конкретными коммитами, чтобы строки не уехали.

ИсточникЧто подтверждает
Minecraft Wiki — Tick20 тиков в секунду, тик = 50 мс
Tick Sync — ModrinthКлиент ждёт конца тика, прежде чем применить пакет; мод сдвигает тики на клиенте
Tick Sync — версииСборка 1.4.0 для 1.21.1–1.21.11 и 26.1–26.3
Tick Sync — TickSyncMain.javaРасчёт сдвига и растягивание тика; fast sync — отдельный режим
Paper 1.21.11 — патч PacketProcessorPaper будит сервер на каждый пакет между тиками
Paper 1.21.11 — патч MinecraftServerВаниль разбирает очередь пакетов в начале тика, Paper это меняет
Moonrise — Modrinth · кодОбработка пакетов во время ожидания тика снижает задержку
MCPVP ClientРеклама «−25 мс к любому серверу» за счёт выравнивания тиков
Better Hitreg — README · ModrinthКастомные удары только для вида, настоящие не меняются; команда /hitreg alertDelays
KnockbackSyncВыравнивание КБ при разном пинге на стороне сервера
tick-phase-minecraft — GitHubНаши тесты: скрипты моделей и раунды по сессиям
t.me/hanosukoЗаписи всех боёв нашего теста

Discord · Telegram