Подписывайтесь на наш Telegram и не пропускайте важные новости! Перейти

Часть функционала WawePlayer | 1.21.8

Начинающий
Начинающий
Статус
Оффлайн
Регистрация
12 Янв 2025
Сообщения
33
Реакции
1
Выберите загрузчик игры
  1. Fabric
Третья тема заполняю форум калом
В кратце прикольная визуальная штучка
Java:
Expand Collapse Copy
import com.mojang.blaze3d.pipeline.BlendFunction;
import com.mojang.blaze3d.pipeline.RenderPipeline;
import com.mojang.blaze3d.platform.DepthTestFunction;
import com.mojang.blaze3d.vertex.VertexFormat;
import net.minecraft.client.network.AbstractClientPlayerEntity;
import net.minecraft.client.gl.RenderPipelines;
import net.minecraft.client.render.*;
import net.minecraft.client.util.BufferAllocator;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.Entity;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.RotationAxis;
import net.minecraft.util.math.Vec3d;
import org.joml.Matrix4f;
import ru.strange.client.event.EventInit;
import ru.strange.client.event.impl.EventEntityStatus;
import ru.strange.client.event.impl.EventRender3D;
import ru.strange.client.event.impl.EventUpdate;
import ru.strange.client.module.api.Category;
import ru.strange.client.module.api.IModule;
import ru.strange.client.module.api.Module;
import ru.strange.client.module.api.setting.impl.BooleanSetting;
import ru.strange.client.module.api.setting.impl.ModeSetting;
import ru.strange.client.module.api.setting.impl.SliderSetting;
import ru.strange.client.module.api.setting.impl.HueSetting;
import ru.strange.client.utils.render.RenderUtil;

import java.awt.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArrayList;

@IModule(
        name = "WawePlayer",
        description = "Запоминает позу при тотеме и рисует летящий призрак",
        category = Category.Utilities,
        bind = -1
)
public class TotemAngle extends Module {
    private final SliderSetting riseHeight = new SliderSetting("Высота подъема", 4f, 0.2f, 5.0f, 0.1f, false);
    private final SliderSetting duration = new SliderSetting("Время жизни", 3f, 0.2f, 6.0f, 0.1f, false);
    private final HueSetting color = new HueSetting("Цвет", new Color(RenderUtil.ColorUtil.getClientColor()));

    private final BooleanSetting onTotem = new BooleanSetting("При тотеме", true);
    private final BooleanSetting onJump = new BooleanSetting("При прыжке", false);
    private final BooleanSetting onWalk = new BooleanSetting("При ходьбе", false);
    private final SliderSetting walkInterval = new SliderSetting("Интервал ходьбы", 0.6f, 0.1f, 3.0f, 0.1f, false)
            .hidden(() -> !onWalk.get());

    private final ModeSetting targets = new ModeSetting("Для кого", "Оба", "У меня", "У игроков", "Оба");
    private final SliderSetting playersRadius = new SliderSetting("Радиус игроков", 8.0f, 1.0f, 64.0f, 1.0f, false)
            .hidden(() -> !targets.is("У игроков") && !targets.is("Оба"));

    private final List<TotemGhost> ghosts = new CopyOnWriteArrayList<>();

    private boolean wasOnGround;
    private long lastWalkSpawnMs;

    private final Map<UUID, PlayerTrack> otherTracks = new HashMap<>();

    public TotemAngle() {
        addSettings(riseHeight, duration, color, onTotem, onJump, onWalk, walkInterval, targets, playersRadius);
    }

    @Override
    public void onDisable() {
        ghosts.clear();
        wasOnGround = false;
        lastWalkSpawnMs = 0L;
        otherTracks.clear();
        super.onDisable();
    }

    @EventInit
    public void onStatus(EventEntityStatus event) {
        if (!enable) return;

        if (mc.world == null) return;
        if (!onTotem.get()) return;
        if (event.getStatus() != 35) return;

        Entity e = event.getEntity();
        if (!(e instanceof AbstractClientPlayerEntity player)) return;
        if (!shouldProcess(player)) return;
        addGhost(player, true);
    }

    @EventInit
    public void onUpdate(EventUpdate event) {
        if (!enable) return;
        if (mc.player == null || mc.world == null) return;

        long now = System.currentTimeMillis();
        long intervalMs = (long) (walkInterval.get() * 1000.0f);
        if (intervalMs < 1L) intervalMs = 1L;

        if (shouldProcessSelf()) {
            boolean onGround = mc.player.isOnGround();

            if (onJump.get()) {
                boolean jumpedThisTick = wasOnGround && !onGround && mc.player.getVelocity().y > 0.0D;
                if (jumpedThisTick) {
                    addGhost(mc.player, true);
                }
            }

            if (onWalk.get()) {
                if (onJump.get() && !onGround) {
                    lastWalkSpawnMs = 0L;
                } else {
                Vec3d v = mc.player.getVelocity();
                double horizontalSpeed = Math.sqrt(v.x * v.x + v.z * v.z);
                boolean moving = horizontalSpeed > 0.02D;

                if (moving) {
                    if (lastWalkSpawnMs == 0L) {
                        lastWalkSpawnMs = now;
                    }
                    if (now - lastWalkSpawnMs >= intervalMs) {
                        lastWalkSpawnMs = now;
                        addGhost(mc.player, false);
                    }
                } else {
                    lastWalkSpawnMs = 0L;
                }
                }
            }

            wasOnGround = onGround;
        }

        if (shouldProcessOthers()) {
            updateOtherPlayers(now, intervalMs);
        } else {
            otherTracks.clear();
        }
    }

    private void updateOtherPlayers(long now, long intervalMs) {
        if (mc.player == null || mc.world == null) return;

        double radius = playersRadius.get();
        double radiusSq = radius * radius;

        otherTracks.entrySet().removeIf(e -> {
            for (AbstractClientPlayerEntity p : mc.world.getPlayers()) {
                if (p == mc.player) continue;
                if (p.getUuid().equals(e.getKey()) && !p.isRemoved() && mc.player.squaredDistanceTo(p) <= radiusSq) {
                    return false;
                }
            }
            return true;
        });

        for (AbstractClientPlayerEntity p : mc.world.getPlayers()) {
            if (p == mc.player) continue;
            if (p.isRemoved()) continue;
            if (mc.player.squaredDistanceTo(p) > radiusSq) continue;

            PlayerTrack track = otherTracks.computeIfAbsent(p.getUuid(), k -> new PlayerTrack());

            boolean onGround = p.isOnGround();

            if (onJump.get()) {
                boolean jumpedThisTick = track.wasOnGround && !onGround && p.getVelocity().y > 0.0D;
                if (jumpedThisTick) {
                    addGhost(p, true);
                }
            }

            if (onWalk.get()) {
                if (onJump.get() && !onGround) {
                    track.lastWalkSpawnMs = 0L;
                } else {
                double dx = p.getX() - track.lastX;
                double dz = p.getZ() - track.lastZ;
                double delta = Math.sqrt(dx * dx + dz * dz);
                boolean moving = delta > 0.003D;

                if (moving) {
                    if (track.lastWalkSpawnMs == 0L) {
                        track.lastWalkSpawnMs = now;
                    }
                    if (now - track.lastWalkSpawnMs >= intervalMs) {
                        track.lastWalkSpawnMs = now;
                        addGhost(p, false);
                    }
                } else {
                    track.lastWalkSpawnMs = 0L;
                }
                }
            }

            track.wasOnGround = onGround;
            track.lastX = p.getX();
            track.lastZ = p.getZ();
        }
    }

    private boolean shouldProcess(AbstractClientPlayerEntity player) {
        if (mc.player == null) return false;
        if (player == mc.player) return shouldProcessSelf();
        return shouldProcessOthers();
    }

    private boolean shouldProcessSelf() {
        return targets.is("У меня") || targets.is("Оба");
    }

    private boolean shouldProcessOthers() {
        return targets.is("У игроков") || targets.is("Оба");
    }

    private static class PlayerTrack {
        private boolean wasOnGround;
        private long lastWalkSpawnMs;
        private double lastX;
        private double lastZ;
    }

    @EventInit
    public void onRender(EventRender3D event) {
        if (!enable) return;
        renderGhosts(event);
    }

    private void addGhost(AbstractClientPlayerEntity player, boolean rising) {
        if (mc.world == null) return;

        Vec3d pos = player.getPos();
        float bodyYaw = player.getBodyYaw();
        boolean sneaking = player.isSneaking();

        float walkPhase = player.age;
        float horizontalSpeed = (float) player.getVelocity().horizontalLength();
        float walkSpeed = net.minecraft.util.math.MathHelper.clamp(horizontalSpeed * 8.0f, 0.0f, 1.0f);

        ghosts.add(new TotemGhost(pos, bodyYaw, sneaking, walkPhase, walkSpeed, rising, System.currentTimeMillis()));
    }

    private void renderGhosts(EventRender3D event) {
        if (ghosts.isEmpty()) return;
        if (mc.world == null) return;

        Vec3d cameraPos = mc.gameRenderer.getCamera().getPos();
        long now = System.currentTimeMillis();

        List<TotemGhost> toRemove = new ArrayList<>();

        BufferAllocator allocator = new BufferAllocator(1 << 18);
        VertexConsumerProvider.Immediate immediate = VertexConsumerProvider.immediate(allocator);

        try {
            VertexConsumer buffer = immediate.getBuffer(COLOR_QUADS_LAYER);

            for (TotemGhost ghost : ghosts) {
                float progress = (now - ghost.startTime) / (duration.get() * 1000.0f);

                if (progress >= 1.0f) {
                    toRemove.add(ghost);
                    continue;
                }

                double motionY = ghost.rising ? (riseHeight.get() * ease(progress)) : 0.0D;
                float alpha = (float) easeOutAlpha(progress);

                int color = resolveColor(progress);
                float r = ((color >> 16) & 0xFF) / 255f;
                float g = ((color >> 8) & 0xFF) / 255f;
                float b = (color & 0xFF) / 255f;

                MatrixStack matrices = event.getMatrixStack();
                matrices.push();

                double renderX = ghost.position.x - cameraPos.x;
                double renderY = ghost.position.y - cameraPos.y + motionY;
                double renderZ = ghost.position.z - cameraPos.z;

                matrices.translate(renderX, renderY, renderZ);
                matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(180.0f - ghost.bodyYaw));

                float effectiveAlpha = net.minecraft.util.math.MathHelper.clamp(alpha, 0.0f, 0.75f);
                renderFlatHumanoid(matrices, buffer, r, g, b, effectiveAlpha, ghost.sneaking, ghost.walkPhase, ghost.walkSpeed);

                matrices.pop();
            }

            immediate.draw();
        } finally {
            allocator.close();
        }

        if (!toRemove.isEmpty()) {
            ghosts.removeAll(toRemove);
        }
    }

    private void renderFlatHumanoid(MatrixStack matrices, VertexConsumer buffer,
                                    float r, float g, float b, float a,
                                    boolean sneaking,
                                    float walkPhase,
                                    float walkSpeed) {
        matrices.push();

        matrices.scale(-1f, -1f, 1f);
        matrices.translate(0.0D, -1.501D, 0.0D);

        if (sneaking) {
            matrices.translate(0.0D, 0.2D, 0.0D);
            matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(28.0f));
        }

        Matrix4f matrix = matrices.peek().getPositionMatrix();

        drawBox(buffer, matrix, -4 * U, 0 * U, -2 * U, 8 * U, 12 * U, 4 * U, r, g, b, a);
        drawBox(buffer, matrix, -4 * U, -8 * U, -4 * U, 8 * U, 8 * U, 8 * U, r, g, b, a);

        float swing = net.minecraft.util.math.MathHelper.sin(walkPhase * 0.6662f) * 1.4f * walkSpeed;

        renderArm(matrices, buffer, r, g, b, a, true, -swing);
        renderArm(matrices, buffer, r, g, b, a, false, swing);

        renderLeg(matrices, buffer, r, g, b, a, true, swing);
        renderLeg(matrices, buffer, r, g, b, a, false, -swing);

        matrices.pop();
    }

    private void renderArm(MatrixStack matrices, VertexConsumer buffer,
                           float r, float g, float b, float a,
                           boolean left, float pitchRad) {
        matrices.push();

        float pivotX = (left ? -6.0f : 6.0f) * U;
        float pivotY = 2.0f * U;

        matrices.translate(pivotX, pivotY, 0.0f);
        matrices.multiply(RotationAxis.POSITIVE_X.rotation(pitchRad));
        matrices.translate(-pivotX, -pivotY, 0.0f);

        Matrix4f matrix = matrices.peek().getPositionMatrix();
        float boxX = (left ? -8.0f : 4.0f) * U;
        drawBox(buffer, matrix, boxX, -2 * U, -2 * U, 4 * U, 12 * U, 4 * U, r, g, b, a);

        matrices.pop();
    }

    private void renderLeg(MatrixStack matrices, VertexConsumer buffer,
                           float r, float g, float b, float a,
                           boolean left, float pitchRad) {
        matrices.push();

        float pivotX = (left ? -2.0f : 2.0f) * U;
        float pivotY = 12.0f * U;

        matrices.translate(pivotX, pivotY, 0.0f);
        matrices.multiply(RotationAxis.POSITIVE_X.rotation(pitchRad));
        matrices.translate(-pivotX, -pivotY, 0.0f);

        Matrix4f matrix = matrices.peek().getPositionMatrix();
        float boxX = (left ? -4.0f : 0.0f) * U;
        drawBox(buffer, matrix, boxX, 12 * U, -2 * U, 4 * U, 12 * U, 4 * U, r, g, b, a);

        matrices.pop();
    }

    private static final float U = 1.0f / 16.0f;

    private static void drawBox(VertexConsumer buffer, Matrix4f matrix,
                                float x, float y, float z,
                                float sx, float sy, float sz,
                                float r, float g, float b, float a) {
        float x1 = x;
        float y1 = y;
        float z1 = z;
        float x2 = x + sx;
        float y2 = y + sy;
        float z2 = z + sz;

        buffer.vertex(matrix, x1, y1, z2).color(r, g, b, a);
        buffer.vertex(matrix, x2, y1, z2).color(r, g, b, a);
        buffer.vertex(matrix, x2, y2, z2).color(r, g, b, a);
        buffer.vertex(matrix, x1, y2, z2).color(r, g, b, a);

        buffer.vertex(matrix, x2, y1, z1).color(r, g, b, a);
        buffer.vertex(matrix, x1, y1, z1).color(r, g, b, a);
        buffer.vertex(matrix, x1, y2, z1).color(r, g, b, a);
        buffer.vertex(matrix, x2, y2, z1).color(r, g, b, a);

        buffer.vertex(matrix, x1, y1, z1).color(r, g, b, a);
        buffer.vertex(matrix, x1, y1, z2).color(r, g, b, a);
        buffer.vertex(matrix, x1, y2, z2).color(r, g, b, a);
        buffer.vertex(matrix, x1, y2, z1).color(r, g, b, a);

        buffer.vertex(matrix, x2, y1, z2).color(r, g, b, a);
        buffer.vertex(matrix, x2, y1, z1).color(r, g, b, a);
        buffer.vertex(matrix, x2, y2, z1).color(r, g, b, a);
        buffer.vertex(matrix, x2, y2, z2).color(r, g, b, a);

        buffer.vertex(matrix, x1, y2, z2).color(r, g, b, a);
        buffer.vertex(matrix, x2, y2, z2).color(r, g, b, a);
        buffer.vertex(matrix, x2, y2, z1).color(r, g, b, a);
        buffer.vertex(matrix, x1, y2, z1).color(r, g, b, a);

        buffer.vertex(matrix, x1, y1, z1).color(r, g, b, a);
        buffer.vertex(matrix, x2, y1, z1).color(r, g, b, a);
        buffer.vertex(matrix, x2, y1, z2).color(r, g, b, a);
        buffer.vertex(matrix, x1, y1, z2).color(r, g, b, a);
    }

    private int resolveColor(float progress) {
        return color.getRGB();
    }

    private double ease(double t) {
        t = net.minecraft.util.math.MathHelper.clamp(t, 0.0D, 0.75D);
        return 1.0D - Math.pow(1.0D - t, 3);
    }

    private double easeOutAlpha(double t) {
        t = net.minecraft.util.math.MathHelper.clamp(t, 0.0D, 1.0D);
        double invT = 1.0D - t;
        return 0.75D * Math.pow(invT, 3);
    }

    private static class TotemGhost {
        private final Vec3d position;
        private final float bodyYaw;
        private final boolean sneaking;
        private final float walkPhase;
        private final float walkSpeed;
        private final boolean rising;
        private final long startTime;

        private TotemGhost(Vec3d position, float bodyYaw, boolean sneaking, float walkPhase, float walkSpeed, boolean rising, long startTime) {
            this.position = position;
            this.bodyYaw = bodyYaw;
            this.sneaking = sneaking;
            this.walkPhase = walkPhase;
            this.walkSpeed = walkSpeed;
            this.rising = rising;
            this.startTime = startTime;
        }
    }

    private static final int QUAD_BUFFER_SIZE_BYTES = 1 << 10;
    private static final String PIPELINE_NAMESPACE = "strange";

    private static final RenderPipeline COLOR_QUADS_PIPELINE = RenderPipelines.register(
            RenderPipeline.builder(RenderPipelines.POSITION_COLOR_SNIPPET)
                    .withLocation(Identifier.of(PIPELINE_NAMESPACE, "pipeline/world/totem_angle_color_quads"))
                    .withVertexFormat(VertexFormats.POSITION_COLOR, VertexFormat.DrawMode.QUADS)
                    .withCull(false)
                    .withDepthTestFunction(DepthTestFunction.NO_DEPTH_TEST)
                    .withDepthWrite(false)
                    .withBlend(BlendFunction.LIGHTNING)
                    .build()
    );

    private static final RenderLayer COLOR_QUADS_LAYER = RenderLayer.of(
            "strange_totem_angle_quads",
            QUAD_BUFFER_SIZE_BYTES,
            false,
            true,
            COLOR_QUADS_PIPELINE,
            RenderLayer.MultiPhaseParameters.builder().build(false)
    );
}

1770729593740.png
 
Назад
Сверху Снизу