Начинающий
- Статус
- Оффлайн
- Регистрация
- 5 Дек 2025
- Сообщения
- 29
- Реакции
- 0
- Выберите загрузчик игры
- Fabric
Всем ку ну вот партиклы еще надеюсь понравяться
ss :
ss :
Java:
package kronex.fun.features.impl.render;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem;
import kronex.fun.display.screens.panelgui.animation.Easings;
import kronex.fun.features.module.Module;
import kronex.fun.features.module.ModuleCategory;
import kronex.fun.features.module.setting.implement.BooleanSetting;
import kronex.fun.features.module.setting.implement.MultiSelectSetting;
import kronex.fun.features.module.setting.implement.SelectSetting;
import kronex.fun.features.module.setting.implement.SliderSettings;
import kronex.fun.other.events.packet.PacketEvent;
import kronex.fun.other.events.player.AttackEvent;
import kronex.fun.other.events.player.TickEvent;
import kronex.fun.other.events.render.WorldRenderEvent;
import kronex.fun.other.utils.animation.Animation;
import kronex.fun.other.utils.client.managers.event.EventHandler;
import kronex.fun.other.utils.display.color.ColorAssist;
import kronex.fun.other.utils.display.geometry.Render3D;
import kronex.fun.other.utils.display.interfaces.QuickImports;
import kronex.fun.other.utils.math.time.TimerUtil;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.experimental.Accessors;
import lombok.experimental.FieldDefaults;
import lombok.experimental.NonFinal;
import net.minecraft.client.render.Camera;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.projectile.ProjectileEntity;
import net.minecraft.network.packet.s2c.play.EntityStatusS2CPacket;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.RotationAxis;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.Heightmap;
import org.joml.Vector4i;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class Particles extends Module implements QuickImports {
private static final int TOTEM_COLOR_GREEN = ColorAssist.rgba(127, 221, 144, 255);
private static final int TOTEM_COLOR_YELLOW = ColorAssist.rgba(221, 218, 127, 255);
public final MultiSelectSetting events = new MultiSelectSetting("Spawn On", "")
.value("Attack", "Throw", "Totem", "Move", "Idle")
.selected("Attack", "Throw", "Totem", "Idle");
private final SelectSetting particleMode = new SelectSetting("Particle Type", "")
.value("Bloom", "Star", "Heart", "Dollar", "Snow", "Star 2", "Kronex", "Random")
.selected("Bloom");
private final SliderSettings speed = new SliderSettings("Speed", 1.5F, 0.1F, 3.0F, 0.1F);
private final SliderSettings size = new SliderSettings("Size", 0.2F, 0.0F, 1.0F, 0.1F);
private final SliderSettings attackCount = new SliderSettings("Attack Count", 30, 5, 50, 1).visible(() -> events.isSelected("Attack"));
private final SliderSettings totemCount = new SliderSettings("Totem Count", 8, 2, 16, 1).visible(() -> events.isSelected("Totem"));
private final SliderSettings moveCount = new SliderSettings("Move Count", 2, 1, 6, 1).visible(() -> events.isSelected("Move"));
private final SliderSettings throwCount = new SliderSettings("Throw Count", 6, 1, 16, 1).visible(() -> events.isSelected("Throw"));
private final SliderSettings idleCount = new SliderSettings("Idle Count", 5, 1, 25, 1).visible(() -> events.isSelected("Idle"));
private final SliderSettings idleRange = new SliderSettings("Idle Range", 16, 4, 32, 1).visible(() -> events.isSelected("Idle"));
private final BooleanSetting rotation = new BooleanSetting("Rotation", "").setValue(false);
private final BooleanSetting glowEffect = new BooleanSetting("Glow", "").setValue(true);
private final BooleanSetting throughWalls = new BooleanSetting("Through Walls", "").setValue(false);
private final BooleanSetting strongYFactor = new BooleanSetting("Strong Y Factor", "").setValue(false);
private final List<Particle> targetParticles = new ArrayList<>();
private final List<Particle> worldParticles = new ArrayList<>();
private final List<Particle> flameParticles = new ArrayList<>();
private final Random random = new Random();
private double lastPlayerX;
private double lastPlayerY;
private double lastPlayerZ;
private boolean positionInitialized = false;
private long lastUpdateTime = System.nanoTime();
private long totemSpawnTime = 0L;
private boolean spawningTotemParticles = false;
private Entity currentTotemTarget;
public Particles() {
super("Particles", ModuleCategory.RENDER);
setup(events, particleMode, speed, size, attackCount, totemCount, moveCount, throwCount,
idleCount, idleRange, rotation, glowEffect, throughWalls, strongYFactor);
}
@Override
public void deactivate() {
clear();
}
private void clear() {
targetParticles.clear();
worldParticles.clear();
flameParticles.clear();
positionInitialized = false;
spawningTotemParticles = false;
currentTotemTarget = null;
}
@EventHandler
public void onAttack(AttackEvent event) {
if (!events.isSelected("Attack")) return;
Entity target = event.getEntity();
if (target == null) return;
for (int i = 0; i < attackCount.getInt(); i++) {
double yMotion = strongYFactor.isValue() ? randomValue(-1.6, 1.35) : randomValue(-1.25, 1.25);
spawnParticle(targetParticles,
new Vec3d(target.getX() + randomValue(-0.4, 0.4),
target.getY() + randomValue(0.0, target.getHeight()),
target.getZ() + randomValue(-0.4, 0.4)),
new Vec3d(randomValue(-1.35, 1.35), yMotion, randomValue(-1.35, 1.35)));
}
}
@EventHandler
public void onPacket(PacketEvent event) {
if (event.isSend() || !(event.getPacket() instanceof EntityStatusS2CPacket packet) || packet.getStatus() != 35 || !events.isSelected("Totem")) {
return;
}
Entity entity = packet.getEntity(mc.world);
if (!(entity instanceof LivingEntity)) return;
spawningTotemParticles = true;
totemSpawnTime = System.currentTimeMillis();
currentTotemTarget = entity;
}
@EventHandler
public void onTick(TickEvent event) {
if (mc.player == null || mc.world == null) return;
spawnIdleParticles();
spawnMoveParticles();
spawnThrowParticles();
updateTotemParticles();
removeExpiredParticles(targetParticles, 1000L);
removeExpiredParticles(worldParticles, 2000L);
removeExpiredParticles(flameParticles, 2000L);
}
@EventHandler
public void onWorldRender(WorldRenderEvent event) {
long now = System.nanoTime();
double deltaTime = (now - lastUpdateTime) / 1_000_000_000.0;
lastUpdateTime = now;
setupRenderState();
try {
renderParticles(event.getStack(), targetParticles, 400, 600, deltaTime);
renderParticles(event.getStack(), worldParticles, 800, 1500, deltaTime);
renderParticles(event.getStack(), flameParticles, 700, 1200, deltaTime);
} finally {
resetRenderState();
}
}
private void spawnIdleParticles() {
if (!events.isSelected("Idle")) return;
int range = idleRange.getInt();
for (int i = 0; i < idleCount.getInt(); i++) {
Vec3d around = mc.player.getPos().add(randomValue(-range, range), 0.0, randomValue(-range, range));
BlockPos pos = mc.world.getTopPosition(Heightmap.Type.MOTION_BLOCKING, BlockPos.ofFloored(around));
double x = pos.getX() + randomValue(0.0, 1.0);
double z = pos.getZ() + randomValue(0.0, 1.0);
double y = mc.player.getY() + randomValue(mc.player.getHeight(), range);
Vec3d spawnPos = new Vec3d(x, y, z);
while (!mc.world.getBlockState(BlockPos.ofFloored(spawnPos)).isAir() && spawnPos.y < mc.world.getTopYInclusive()) {
spawnPos = spawnPos.add(0.0, 1.0, 0.0);
}
Vec3d playerVel = mc.player.getVelocity();
spawnParticle(worldParticles, spawnPos,
new Vec3d(playerVel.x + randomValue(-0.5, 0.5), randomValue(-0.06, 0.06), playerVel.z + randomValue(-0.5, 0.5)));
}
}
private void spawnMoveParticles() {
if (!events.isSelected("Move") || !hasPlayerMoved() || mc.options.getPerspective().isFirstPerson()) return;
for (int i = 0; i < moveCount.getInt(); i++) {
Vec3d playerVel = mc.player.getVelocity();
spawnParticle(flameParticles,
new Vec3d(mc.player.getX() + randomValue(-0.5, 0.5),
mc.player.getY() + randomValue(0.0, mc.player.getHeight()),
mc.player.getZ() + randomValue(-0.5, 0.5)),
new Vec3d(playerVel.x + randomValue(-0.25, 0.25),
randomValue(-0.15, 0.15),
playerVel.z + randomValue(-0.25, 0.25)));
}
}
private void spawnThrowParticles() {
if (!events.isSelected("Throw")) return;
Vec3d playerPos = mc.player.getPos();
double maxDistSq = 64 * 64;
for (Entity entity : mc.world.getEntities()) {
if (!(entity instanceof ProjectileEntity) || entity.isOnGround()) continue;
if (entity.squaredDistanceTo(playerPos) > maxDistSq) continue;
boolean isMoving = entity.prevX != entity.getX() || entity.prevY != entity.getY() || entity.prevZ != entity.getZ();
if (!isMoving) continue;
Vec3d pos = entity.getPos();
Vec3d vel = entity.getVelocity();
for (int i = 0; i < throwCount.getInt(); i++) {
spawnParticle(flameParticles,
new Vec3d(pos.x + randomValue(-0.5, 0.5), pos.y + randomValue(-0.5, 0.5), pos.z + randomValue(-0.5, 0.5)),
new Vec3d(randomValue(-0.06, 0.06), randomValue(-0.06, 0.06), randomValue(-0.06, 0.06)));
}
}
}
private void updateTotemParticles() {
if (!spawningTotemParticles || currentTotemTarget == null) return;
if (System.currentTimeMillis() - totemSpawnTime > 2500L) {
spawningTotemParticles = false;
currentTotemTarget = null;
return;
}
for (int i = 0; i < totemCount.getInt(); i++) {
int color = random.nextBoolean() ? TOTEM_COLOR_YELLOW : TOTEM_COLOR_GREEN;
spawnParticleTotem(flameParticles,
new Vec3d(currentTotemTarget.getX() + randomValue(-0.4, 0.4),
currentTotemTarget.getY() + randomValue(0.0, 2.0),
currentTotemTarget.getZ() + randomValue(-0.4, 0.4)),
new Vec3d(randomValue(-0.8, 0.8), randomValue(-0.6, 0.1), randomValue(-0.8, 0.8)),
color);
}
}
private void renderParticles(MatrixStack matrix, List<Particle> particles, long fadeInTime, long fadeOutTime, double deltaTime) {
if (particles.isEmpty()) return;
for (Particle particle : particles) {
particle.update(true, deltaTime, "", rotation.isValue());
particle.animation.update();
if (particle.animation.get() != 1.0F && !particle.time.isReached(fadeInTime)) {
particle.animation.run(1.0F, 0.5, Easings.CUBIC_OUT);
}
if (particle.animation.get() != 0.0F && particle.time.isReached(fadeOutTime)) {
particle.animation.run(0.0F, 0.5, Easings.CUBIC_OUT);
}
int color = ColorAssist.replAlpha(particle.color, particle.animation.get());
renderParticle(matrix, particle, particle.position.x, particle.position.y, particle.position.z, particle.size, color);
}
}
private void renderParticle(MatrixStack matrices, Particle particle, double x, double y, double z, float size, int color) {
Camera camera = mc.gameRenderer.getCamera();
Vec3d relativePos = new Vec3d(x, y, z).subtract(camera.getPos());
MatrixStack particleMatrix = new MatrixStack();
particleMatrix.multiply(RotationAxis.POSITIVE_X.rotationDegrees(camera.getPitch()));
particleMatrix.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(camera.getYaw() + 180.0F));
particleMatrix.translate(relativePos.x, relativePos.y, relativePos.z);
particleMatrix.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(-camera.getYaw()));
particleMatrix.multiply(RotationAxis.POSITIVE_X.rotationDegrees(camera.getPitch()));
particleMatrix.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(180.0F));
if (rotation.isValue()) {
particleMatrix.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(particle.rotation));
}
if (throughWalls.isValue()) {
RenderSystem.disableDepthTest();
}
if (glowEffect.isValue()) {
Render3D.drawTexture(particleMatrix.peek().copy(), ParticleType.BLOOM.texture(), -size * 2.0F, -size * 2.0F, size * 4.0F, size * 4.0F,
new Vector4i(ColorAssist.multAlpha(color, 0.1F)), true);
}
Render3D.drawTexture(particleMatrix.peek().copy(), particle.type.texture(), -size, -size, size * 2.0F, size * 2.0F,
new Vector4i(color), true);
if (throughWalls.isValue()) {
RenderSystem.enableDepthTest();
}
}
private void spawnParticle(List<Particle> particles, Vec3d position, Vec3d velocity) {
float particleSize = 0.05F + (size.getValue() * 0.2F);
int color = ColorAssist.fade(particles.size() * 100);
particles.add(new Particle(getParticleType(), position.add(0.0, particleSize, 0.0), velocity, color, particleSize, speed.getValue()));
}
private void spawnParticleTotem(List<Particle> particles, Vec3d position, Vec3d velocity, int color) {
float particleSize = 0.05F + (size.getValue() * 0.2F);
particles.add(new Particle(getParticleType(), position.add(0.0, particleSize, 0.0), velocity, color, particleSize, 2.0F));
}
private ParticleType getParticleType() {
return switch (particleMode.getSelected()) {
case "Dollar" -> ParticleType.DOLLAR;
case "Heart" -> ParticleType.HEART;
case "Star" -> ParticleType.STAR;
case "Snow" -> ParticleType.SNOW;
case "Star 2" -> ParticleType.STARNEW;
case "Kronex" -> ParticleType.KRONEX;
case "Random" -> ParticleType.getRandom();
default -> ParticleType.BLOOM;
};
}
private void removeExpiredParticles(List<Particle> particles, long lifespan) {
particles.removeIf(particle -> particle.time.isReached(lifespan));
}
private boolean hasPlayerMoved() {
if (!positionInitialized) {
lastPlayerX = mc.player.getX();
lastPlayerY = mc.player.getY();
lastPlayerZ = mc.player.getZ();
positionInitialized = true;
return false;
}
boolean moved = Math.abs(mc.player.getX() - lastPlayerX) > 0.001
|| Math.abs(mc.player.getY() - lastPlayerY) > 0.001
|| Math.abs(mc.player.getZ() - lastPlayerZ) > 0.001;
if (moved) {
lastPlayerX = mc.player.getX();
lastPlayerY = mc.player.getY();
lastPlayerZ = mc.player.getZ();
}
return moved;
}
private void setupRenderState() {
RenderSystem.enableBlend();
RenderSystem.disableCull();
RenderSystem.depthMask(false);
RenderSystem.blendFuncSeparate(
GlStateManager.SrcFactor.SRC_ALPHA,
GlStateManager.DstFactor.ONE,
GlStateManager.SrcFactor.ONE,
GlStateManager.DstFactor.ZERO
);
}
private void resetRenderState() {
RenderSystem.blendFuncSeparate(
GlStateManager.SrcFactor.SRC_ALPHA,
GlStateManager.DstFactor.ONE_MINUS_SRC_ALPHA,
GlStateManager.SrcFactor.ONE,
GlStateManager.DstFactor.ZERO
);
RenderSystem.enableCull();
RenderSystem.depthMask(true);
}
private double randomValue(double min, double max) {
return min + (max - min) * random.nextDouble();
}
@Getter
@Accessors(fluent = true)
public enum ParticleType {
DOLLAR("bucks1"),
HEART("heart1"),
STAR("star1"),
BLOOM("glow"),
SNOW("show1"),
STARNEW("firefly"),
KRONEX("kronex");
private final Identifier texture;
ParticleType(String file) {
this.texture = Identifier.of("minecraft", "textures/game.moment/particles/" + file + ".png");
}
public static ParticleType getRandom() {
ParticleType[] values = values();
return values[new Random().nextInt(values.length)];
}
}
@Getter
@Accessors(fluent = true)
@FieldDefaults(level = AccessLevel.PRIVATE)
private class Particle {
static final double BASE_VELOCITY = 0.05;
final ParticleType type;
final int color;
final float size;
final double speedMultiplier;
final TimerUtil time = new TimerUtil();
final Animation animation = new Animation();
@NonFinal Vec3d position;
@NonFinal Vec3d velocity;
@NonFinal Box box;
@NonFinal float rotation;
@NonFinal float rotate;
private Particle(ParticleType type, Vec3d position, Vec3d velocity, int color, float size, double speedMultiplier) {
this.type = type;
this.position = position;
this.velocity = velocity.multiply(BASE_VELOCITY);
this.color = color;
this.size = size;
this.speedMultiplier = speedMultiplier;
this.box = new Box(position, position).expand(size);
this.time.resetCounter();
}
private void update(boolean physic, double deltaTime, String mode, boolean rotateEnabled) {
if (rotateEnabled) {
this.rotation = (this.rotate % 1000.0F) / 150.0F;
this.rotate += 1.0F;
}
if (physic) {
collide(1.0, -1.0, 1.0, -1.0);
this.velocity = this.velocity.multiply(Math.pow(0.999, deltaTime * 60.0));
}
this.position = this.position.add(this.velocity.multiply(deltaTime * 60.0 * speedMultiplier));
this.box = new Box(this.position, this.position).expand(this.size);
}
private void collide(double sideMul, double sideBounce, double yMul, double yBounce) {
if (isBlockSolid(this.position.x, this.position.y, this.position.z + this.velocity.z)) {
this.velocity = new Vec3d(this.velocity.x * sideMul, this.velocity.y * yMul, this.velocity.z * sideBounce);
}
if (isBlockSolid(this.position.x, this.position.y + this.velocity.y, this.position.z)) {
this.velocity = new Vec3d(this.velocity.x * sideMul, this.velocity.y * yBounce, this.velocity.z * sideMul);
}
if (isBlockSolid(this.position.x + this.velocity.x, this.position.y, this.position.z)) {
this.velocity = new Vec3d(this.velocity.x * sideBounce, this.velocity.y * yMul, this.velocity.z * sideMul);
}
}
private boolean isBlockSolid(double x, double y, double z) {
BlockPos pos = BlockPos.ofFloored(x, y, z);
return mc.world != null && !mc.world.getBlockState(pos).getCollisionShape(mc.world, pos).isEmpty();
}
}
}
Последнее редактирование: