Breath Weapon
Это библиотечный/API-мод для отрисовки моделей GeckoLib в виде частиц.
- Загрузчики
- Forge
- Скачиваний на Modrinth
- 193
- Подписчиков на Modrinth
- 1
- версий
- 9
- Обновлён
- 13 мая 202613 мая
- Опубликован
- в 2026
Коротко о моде
Нужен и в игре, и на сервере
Использование BreathWeapon
Это руководство объясняет, как интегрировать систему частиц BreathWeapon в ваш мод для Minecraft, чтобы создавать собственные частицы без написания сложного кода рендеринга.
Настройка
1. Добавление зависимости
В вашем build.gradle добавьте BreathWeapon в зависимости:
mavenCentral()
exclusiveContent {
forRepository {
maven {
name = "Modrinth"
url = "https://api.modrinth.com/maven"
}
}
forRepositories(fg.repository)
filter {
includeGroup "maven.modrinth"
}
}
dependencies {
implementation fg.deobf("maven.modrinth:breath-weapon:0.0.1")
}2. Импорт API
В вашем коде импортируйте утилиты для спавна:
import com.dracolich777.breathweapon.util.ParticleSpawner;
import com.dracolich777.breathweapon.api.particle.ParticleRegistry;
import net.minecraft.resources.ResourceLocation;Быстрый старт
Минимальная настройка
1. Создайте JSON-определение частицы:
src/main/resources/data/yourmodid/particles/my_effect.json{
"type": "sprite",
"lifetime": 50
}2. Заспавните её в коде:
ParticleSpawner.spawn(level,
new ResourceLocation("yourmodid", "my_effect"),
x, y, z,
vx, vy, vz);Вот и всё! Частица отрендерится с текстурой и физикой по умолчанию.
Создание определений частиц
Определения частиц — это JSON-файлы, размещаемые в датапаках вашего мода. Создавайте их по пути:
src/main/resources/data/yourmodid/particles/particle_name.jsonСтруктура файлов
src/main/resources/
├── assets/yourmodid/
│ └── textures/
│ └── particle/
│ ├── beam.png
│ ├── spark.png
│ └── smoke.png
└── data/yourmodid/
└── particles/
├── my_beam.json
├── my_spark.json
└── my_smoke.jsonБазовая структура JSON
Каждое определение частицы имеет такую структуру:
{
"type": "sprite | beam | geo",
"texture": "yourmodid:textures/particle/name",
"lifetime": 200,
"scale": 1.0,
"gravity": 0.0,
"drag": 1.0,
"light": { ... },
"animation": { ... }
}Общие свойства
Все типы частиц поддерживают:
| Свойство | Тип | По умолчанию | Описание |
|---|---|---|---|
type | string | "sprite" | Тип частицы: sprite, beam или geo |
lifetime | int | 200 | Длительность в тиках (1 тик = 50мс) |
scale | float | 1.0 | Множитель размера (0.1 - 10.0) |
gravity | float | 0.0 | Ускорение вниз (отрицательное = вверх) |
drag | float | 1.0 | Затухание скорости (0.9 = 10% замедления/тик) |
texture | string | null | Путь к текстуре в формате modid:path |
Настройка освещения
Добавьте свечение/динамическое освещение частицам:
{
"type": "sprite",
"light": {
"mode": "glow",
"color": [1.0, 0.5, 0.0],
"intensity": 1.0
}
}Режимы освещения:
"none"- Без особого освещения"glow"- Постоянный эффект свечения"pulse"- Пульсирующая яркость Для Glow/Pulse:
"light": {
"mode": "glow",
"color": [r, g, b],
"intensity": brightness_0_to_2
}Для Pulse:
"light": {
"mode": "pulse",
"color": [r, g, b],
"intensity": 1.0,
"pulse_min": 0.3,
"pulse_max": 1.0,
"pulse_speed": 0.1
}Спавн частиц
Базовый спавн
Одиночная частица:
ParticleSpawner.spawn(level,
new ResourceLocation("yourmodid", "my_particle"),
x, y, z,
velocityX, velocityY, velocityZ);Спавн по шаблонам
Взрыв (случайные направления):
ParticleSpawner.burst(level,
new ResourceLocation("yourmodid", "spark"),
center, // Позиция Vec3
count, // Количество частиц (например, 10)
speed); // Скорость в блоках/тик (например, 0.5)Поток (направленный):
ParticleSpawner.stream(level,
new ResourceLocation("yourmodid", "smoke"),
entity, // Сущность, от которой спавнить
count, // Количество частиц
speed, // Скорость частиц
spread); // Угловой разброс в радианахСпавн лучей
Равномерный луч:
ParticleSpawner.spawnBeam(level,
new ResourceLocation("yourmodid", "laser"),
from, // Vec3 начальной позиции
to, // Vec3 конечной позиции
width); // Ширина луча (например, 0.3f)Сужающийся луч (ширина меняется по длине):
ParticleSpawner.spawnBeam(level,
new ResourceLocation("yourmodid", "laser"),
from, // Vec3 начало
to, // Vec3 конец
startWidth, // Ширина в начале (например, 0.5f)
endWidth); // Ширина в конце (например, 0.1f)Типы частиц
Тип 1: Sprite (по умолчанию)
Простые 2D-частицы. Быстрые и лёгкие. Определение:
{
"type": "sprite",
"texture": "yourmodid:particle/spark",
"lifetime": 30,
"scale": 0.5,
"gravity": 0.05,
"drag": 0.98,
"light": {
"mode": "glow",
"color": [1.0, 1.0, 0.0],
"intensity": 0.8
}
}Лучше всего для: искр, блёсток, пыли, простых эффектов
Тип 2: Beam
Билборд между двумя точками. Поддерживает динамические конечные точки. Определение:
{
"type": "beam",
"texture": "yourmodid:particle/laser",
"lifetime": 100,
"scale": 1.0,
"light": {
"mode": "glow",
"color": [1.0, 0.0, 0.0],
"intensity": 1.5
}
}Лучше всего для: лазеров, энергетических взрывов, направленных атак, трассеров
Тип 3: Geo (модель GeckoLib)
Полноценные 3D-модели с поддержкой анимации. Определение:
{
"type": "geo",
"model": "yourmodid:geo/explosion.geo.json",
"texture": "yourmodid:textures/particle/explosion.png",
"animation": "yourmodid:animations/explosion.animation.json",
"anim_name": "animation.explosion.burst",
"lifetime": 50,
"scale": 0.8,
"gravity": -0.05,
"drag": 0.95,
"spin": {
"yaw": 5.0,
"pitch": 2.0,
"roll": 3.0
}
}Свойства:
model- Путь к вашему файлу GeckoLib.geo.jsontexture- Текстура для моделиanimation- Путь к файлу анимации (опционально)anim_name- Какую анимацию проигрывать (опционально)spin— скорость вращения в градусах/тик (необязательно) Лучше всего подходит для: сложных эффектов, взрывов, магических эффектов, кастомных моделей
Продвинутые возможности
Динамические конечные точки лучей
Создавайте лучи, которые отслеживают цели или движутся со временем:
import com.dracolich777.breathweapon.client.particle.SimpleBeamParticle;
// При спавне нужен прямой доступ к частице
// Для этого требуется особый способ спавна или обработчик событий
SimpleBeamParticle.EndpointProvider provider = (age, lifetime) -> {
// Вычисляем новую позицию на основе возраста
float progress = age / (float) lifetime;
// Пример: спиральная конечная точка
double angle = progress * Math.PI * 4; // 2 оборота
double newX = centerX + Math.cos(angle) * radius;
double newY = centerY + Math.sin(angle) * radius;
double newZ = centerZ + Math.sin(progress * Math.PI) * 5;
return new SimpleBeamParticle.BeamEndpoint(newX, newY, newZ);
};
// Устанавливаем на частицу (требуется прямой доступ к частице через событие или хук)
particle.setEndpointProvider(provider);Настройка физики
Управляйте движением частиц:
{
"gravity": 0.1, // Скорость падения (положительная = вниз, отрицательная = вверх)
"drag": 0.95, // Замедление на 5% каждый тик
"scale": 1.5 // Увеличить в 1.5 раза
}Примеры:
- Эффект парения:
"gravity": -0.01, "drag": 1.0 - Медленное падение:
"gravity": 0.02, "drag": 0.99 - Затухание: используйте короткое время жизни + высокое drag
- Быстрый зум: используйте высокую начальную скорость + низкую гравитацию
Полные примеры
Пример 1: Атака энергетическим лучом
JSON-описание (data/mymod/particles/energy_blast.json):
{
"type": "beam",
"texture": "mymod:particle/energy_beam",
"lifetime": 80,
"scale": 0.9,
"light": {
"mode": "glow",
"color": [0.2, 0.7, 1.0],
"intensity": 1.3
}
}Код спавна (в обработчике способности):
@SubscribeEvent
public static void onPlayerAttack(LivingAttackEvent event) {
if (event.getEntity() instanceof Player player &&
player.level() instanceof ServerLevel level) {
Vec3 from = player.getEyePosition();
Vec3 to = from.add(player.getLookAngle().scale(50));
ParticleSpawner.spawnBeam(level,
new ResourceLocation("mymod", "energy_blast"),
from, to, 0.2f);
}
}Пример 2: Эффект взрыва
JSON-описание (data/mymod/particles/explosion_burst.json):
{
"type": "sprite",
"texture": "mymod:particle/explosion",
"lifetime": 40,
"scale": 1.2,
"gravity": -0.02,
"drag": 0.96,
"light": {
"mode": "pulse",
"color": [1.0, 0.6, 0.0],
"intensity": 1.5,
"pulse_min": 0.5,
"pulse_max": 1.5,
"pulse_speed": 0.15
}
}Код спавна:
public static void createExplosion(ServerLevel level, Vec3 center, int power) {
ParticleSpawner.burst(level,
new ResourceLocation("mymod", "explosion_burst"),
center,
power * 3, // Больше частиц для большего взрыва
power * 0.1); // Быстрее разлёт для большего взрыва
}Пример 3: Магическая аура
JSON-описание (data/mymod/particles/mana_dust.json):
{
"type": "sprite",
"texture": "mymod:particle/mana",
"lifetime": 100,
"scale": 0.6,
"gravity": -0.005,
"drag": 0.98,
"light": {
"mode": "glow",
"color": [0.7, 0.3, 1.0],
"intensity": 0.9
}
}Код спавна (в тике сущности):
public void createManaAura(Entity entity, ServerLevel level) {
Vec3 pos = entity.position().add(0, entity.getBbHeight() / 2, 0);
// Небольшой выброс частиц вокруг сущности
ParticleSpawner.burst(level,
new ResourceLocation("mymod", "mana_dust"),
pos,
5, // 5 частиц
0.3); // Медленный разлёт
}Пример 4: Индикатор эффекта состояния
JSON-описание (data/mymod/particles/poison_cloud.json):
{
"type": "sprite",
"texture": "mymod:particle/poison",
"lifetime": 60,
"scale": 0.8,
"gravity": 0.01,
"drag": 0.99,
"light": {
"mode": "glow",
"color": [0.3, 0.8, 0.2],
"intensity": 0.7
}
}Код спавна (пока эффект активен):
@SubscribeEvent
public static void onLivingUpdate(LivingTickEvent event) {
LivingEntity entity = event.getEntity();
if (entity.hasEffect(MobEffects.POISON) &&
entity.level() instanceof ServerLevel level &&
entity.tickCount % 5 == 0) { // Каждые 5 тиков
Vec3 pos = entity.position().add(
(Math.random() - 0.5) * 0.5,
Math.random() * entity.getBbHeight(),
(Math.random() - 0.5) * 0.5
);
ParticleSpawner.spawn(level,
new ResourceLocation("mymod", "poison_cloud"),
pos.x, pos.y, pos.z,
0, -0.05, 0); // Лёгкий дрейф вверх
}
}Проверка доступности частиц
Перед спавном убедитесь, что частица зарегистрирована:
import com.dracolich777.breathweapon.api.particle.ParticleRegistry;
ResourceLocation particleId = new ResourceLocation("yourmodid", "my_particle");
if (ParticleRegistry.has(particleId)) {
// Можно безопасно спавнить
ParticleSpawner.spawn(level, particleId, x, y, z, 0, 0, 0);
} else {
LOGGER.warn("Particle not found: {}", particleId);
}Получить информацию о частице:
var definition = ParticleRegistry.get("yourmodid:my_particle");
if (definition != null) {
int lifetime = definition.getLifetime();
float scale = definition.getScale();
String type = definition.getType(); // "beam", "geo", "sprite"
}Лучшие практики
1. Организуйте свои частицы
data/yourmodid/particles/
├── abilities/
│ ├── fireball.json
│ ├── lightning.json
│ └── healing_circle.json
├── effects/
│ ├── hit_effect.json
│ ├── death_burst.json
│ └── buff_indicator.json
└── ambient/
├── magical_dust.json
├── fire_embers.json
└── water_splash.json2. Делайте время жизни коротким
Не заставляйте частицы жить дольше, чем нужно:
- Sparks: 20-60 тиков
- Beams: 50-150 тиков
- Explosions: 30-100 тиков
- Ambient: 60-200 тиков
3. Проверка физики
{
"gravity": 0.0, // Начните без гравитации
"drag": 1.0 // Начните без сопротивления
}Затем корректируйте по визуальному виду.
4. Используйте подходящие типы
- Sprite — большинство эффектов (быстро)
- Beam — нацеленные эффекты, атаки
- Geo — особые случаи (медленнее)
5. Переиспользуйте определения
Создайте одно определение и спавните его несколько раз:
for (int i = 0; i < 10; i++) {
ParticleSpawner.spawn(level,
new ResourceLocation("mymod", "explosion"),
x, y, z,
randomVelX, randomVelY, randomVelZ);
}6. Добавляйте описания в JSON
{
"_comment": "Синий энергетический луч — используется для атак заклинаниями мага",
"type": "beam",
...
}Решение проблем
Частицы не отображаются
Проблема: Я заспавнил частицу, но она не появляется в игре. Решения:
- Проверьте, что определение частицы находится в правильной папке:
data/yourmodid/particles/name.json - Убедитесь, что ID частицы совпадает с именем файла JSON
- Используйте
/reloadдля перезагрузки данных - Проверьте, что путь к текстуре существует:
assets/yourmodid/textures/particle/name.png - Убедитесь, что вы на правильном уровне (ServerLevel, а не ClientLevel) Код для отладки:
var def = ParticleRegistry.get("yourmodid:my_particle");
if (def == null) {
LOGGER.error("Particle not found in registry!");
} else {
LOGGER.info("Particle found: {}", def);
}Текстура не загружается
Проблема: Частица появляется, но текстура неправильная. Решения:
- Убедитесь, что путь к текстуре использует прямые слэши:
"mymod:particle/name" - Проверьте, что файл текстуры в формате PNG
- Путь к текстуре НЕ должен включать расширение
.png - Текстура должна находиться в
assets/yourmodid/textures/
Неправильная позиция луча
Проблема: Луч начинается/заканчивается в неправильной позиции. Решения:
- Используйте мировые координаты (не относительные)
- Для сущностей:
entity.getEyePosition()для уровня глаз - Для блоков:
new Vec3(x + 0.5, y + 0.5, z + 0.5)для центра - Убедитесь, что
fromиtoне находятся в одной позиции
Частица слишком медленная/быстрая
Проблема: Движение частицы не соответствует ожидаемой скорости. Решения:
- Увеличьте параметр
speedвburst()илиstream() - Настройте
drag— меньшие значения = скорость сохраняется дольше - Проверьте, что скорость спавна частицы корректна
- Используйте
gravityдля добавления ускорения со временем
Модель GeckoLib не загружается
Проблема: Тип — "geo", но модель не рендерится. Решения:
- Убедитесь, что путь к файлу модели правильный
- Проверьте, что файл
.geo.jsonсуществует - Путь к модели НЕ должен включать
.geo.jsonв JSON (толькоpathбез расширения) - Путь к текстуре должен совпадать с ссылкой на текстуру в модели
- Название анимации должно совпадать точно (с учётом регистра)
Справочник API
Методы ParticleSpawner
// Одиночная частица
ParticleSpawner.spawn(level, id, x, y, z, vx, vy, vz);
ParticleSpawner.spawn(level, id, x, y, z, vx, vy, vz, extraData);
// Паттерны
ParticleSpawner.burst(level, id, center, count, speed);
ParticleSpawner.stream(level, id, entity, count, speed, spread);
// Лучи
ParticleSpawner.spawnBeam(level, id, from, to, width);
ParticleSpawner.spawnBeam(level, id, from, to, startWidth, endWidth);Методы ParticleRegistry
ParticleRegistry.register(id, definition);
ParticleRegistry.get(id);
ParticleRegistry.has(id);
ParticleRegistry.getAll();
ParticleRegistry.getAllFromMod(namespace);Нужна помощь?
Напишите мне в Discord или зайдите на мой сервер Discord:
- Discord Server
.themrsuitУдачи в создании потрясающих частиц!
Частые вопросы
Как установить Breath Weapon?
Установите Forge под свою версию Minecraft, скачайте Breath Weapon под ту же версию и загрузчик, положите файл в папку mods и запустите игру с профилем загрузчика.
Для каких версий Minecraft есть Breath Weapon?
У Breath Weapon есть сборки для Minecraft 1.20.1.
Нужен ли Breath Weapon на сервере?
Нужен и в игре, и на сервере