🧲 Вакуумное движение и фазовый сдвиг (MC 26.2)
📌 Отказ от ответственности за исходный код репозитория: Документация в этой Wiki отражает текущее состояние исходного кода в репозитории, которое может включать недавние невыпущенные коммиты или функции в разработке до публичных релизов на CurseForge и Modrinth.
| Инфоблок механики | Технические параметры |
|---|---|
| Системный класс | net.instantgratification.magnet.MagnetMovement |
| Событие срабатывания | Серверный тик игрока (PlayerMixin $\rightarrow$ MagnetManager.tick) |
| Радиус притягивания по умолчанию | 12 блоков (ig:magnet_range) |
| Предельная скорость по умолчанию | 80% ($0.8\text{ блоков/тик} = 16.0\text{ м/с}$) |
| Ускорение по умолчанию | 10% ($0.10\text{ фактор lerp/тик}$) |
| Фазовый сдвиг (NoClip) | Включен (ig:magnet_noclip = true) |
| Вектор цели | Позиция глаз игрока (player.getEyePosition()) |
| Смещение от земли | $+0.05\text{ м}$ по оси Y, когда entity.onGround() |
📖 Обзор системы
Основная механика вакуума в моде Magnet, Let me get that! сканирует выпадающие сущности ItemEntity в пределах заданного радиуса игрока на каждом серверном тике и плавно притягивает их к уровню глаз с использованием нелинейной интерполяции.
Чтобы предметы не цеплялись за края блоков, выступы руд или кроны деревьев, мод активирует Фазовый сдвиг (NoClip), позволяя летящим предметам беспрепятственно проходить сквозь твердые воксели блоков.
+-------------+ Линия обзора OK +----------------------+ Применена скорость Lerp +------------------+
| Item Entity | -------------------------> | Вкл NoClip (2 тика) | --------------------------------> | Глаза игрока |
+-------------+ +----------------------+ +------------------+
|
v
[Отмена выталкивания]
[Игнорирование коллизий]
[Отмена гравитации в блоке]🧮 Физика и векторная математика
При притягивании предмета траектория рассчитывается непосредственно в 3D евклидовом пространстве:
1. Вектор к цели
Пусть $\vec{p}{\text{entity}} = (x_e, y_e, z_e)$ — текущая позиция предмета, а $\vec{p}{\text{eye}} = (x_p, y_p + h_{\text{eye}}, z_p)$ — позиция глаз игрока. $$\vec{v}{\text{target}} = \vec{p}{\text{eye}} - \vec{p}{\text{entity}}$$ $$\hat{d} = \frac{\vec{v}{\text{target}}}{|\vec{v}{\text{target}}|} = \frac{\vec{v}{\text{target}}}{\sqrt{\Delta x^2 + \Delta y^2 + \Delta z^2}}$$
2. Желаемая предельная скорость
Вектор целевой скорости масштабирует единичный вектор направления $\hat{d}$ с учетом настроенного параметра скорости: $$\text{Скаляр скорости } s = \frac{\text{GameRule}(\text{ig:magnet_speed})}{100.0}$$ $$\vec{u}_{\text{target}} = \hat{d} \times s$$ При стандартном значении ($80%$), $s = 0.8\text{ блоков/тик}$. При $20\text{ тиках/с}$ предельная скорость равна $16.0\text{ м/с}$.
3. Нелинейное ускорение (Lerp)
Скорость обновляется линейной интерполяцией (Vec3.lerp) на основе коэффициента ускорения $a$: $$\text{Коэффициент ускорения } a = \frac{\text{GameRule}(\text{ig:magnet_acceleration})}{100.0}$$ $$\vec{v}{\text{new}} = \vec{v}{\text{current}} + (\vec{u}{\text{target}} - \vec{v}{\text{current}}) \times a$$
4. Устранение трения о землю
Если предмет лежит на поверхности блока (entity.onGround() == true), контактное трение мгновенно сбрасывается для предотвращения волочения по полу:
if (entity.onGround()) {
entity.setOnGround(false);
entity.setPos(entity.position().add(0, 0.05, 0));
}🧱 Фазовый сдвиг (Движок NoClip)
Когда параметр ig:magnet_noclip активен, предметам присваивается окно NoClip длительностью в 2 тика:
- Активация состояния: Вызов
((IMagnetEntity) entity).ig_magnet$setMagnetNoClip()устанавливаетnoClipTicks = 2. - Перехват перемещения (
MixinEntity.java):move(MoverType, Vec3): Инъекция@Inject(at = @At("HEAD"))сохраняетoriginalNoPhysicsи принудительно устанавливаетentity.noPhysics = true.move(MoverType, Vec3): Инъекция@Inject(at = @At("RETURN"))восстанавливаетentity.noPhysics = originalNoPhysics.
- Отмена выталкивания из блоков:
@Inject(method = "moveTowardsClosestSpace", at = @At("HEAD"), cancellable = true)блокирует ванильное выталкивание предметов из геометрии блоков. - Условное отключение гравитации:
@Inject(method = "applyGravity", at = @At("HEAD"), cancellable = true)отменяет гравитацию вниз только тогда, когда предмет физически пересекает воксель блока (!level.noCollision(...)), сохраняя естественную дуговую траекторию в воздухе.
⚙️ Связанные настройки и игровые правила (GameRules)
| GameRule | Тип | По умолчанию | Диапазон / Единицы | Описание |
|---|---|---|---|---|
ig:magnet_enabled | Boolean | true | true/false | Главный переключатель всей логики вакуума. |
ig:magnet_range | Integer | 12 | 1..64 блоков | Максимальный сферический радиус вакуума. |
ig:magnet_speed | Integer | 80 | 1..1000% | Процент предельной скорости ($80 = 0.8\text{ б/т}$). |
ig:magnet_acceleration | Integer | 10 | 1..1000% | Процент ускорения притягивания ($10 = 10%\text{ lerp/тик}$). |
ig:magnet_noclip | Boolean | true | true/false | Включает прохождение сквозь блоки при притягивании. |
