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

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

SelfCode
Премиум
Премиум
Статус
Оффлайн
Регистрация
7 Мар 2025
Сообщения
180
Реакции
3
Выберите загрузчик игры
  1. Fabric
Всем пр начал делать 1.21.4 решил слить вроде простенькую функцию но полезную

SS -
1775408910042.png


Code -
сарделька:
Expand Collapse Copy
package ru.explosive.module.impl.misc;

import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.EquipmentSlot;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.projectile.thrown.PotionEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.item.consume.UseAction;
import net.minecraft.network.packet.s2c.play.EntityStatusS2CPacket;
import net.minecraft.text.Text;
import net.minecraft.util.math.Box;
import ru.explosive.event.EventInit;
import ru.explosive.event.impl.EventPacket;
import ru.explosive.event.lifecycle.ClientTickEvent;
import ru.explosive.module.api.Category;
import ru.explosive.module.api.IModule;
import ru.explosive.module.api.Module;
import ru.explosive.module.api.setting.Setting;
import ru.explosive.module.api.setting.impl.BooleanSetting;
import ru.explosive.module.api.setting.impl.SliderSetting;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

@IModule(name = "UseTracker", description = "Трекает тотемы, зелья и еду игроков", category = Category.Misc, bind = -1)
@Environment(EnvType.CLIENT)
public class UseTracker extends Module {

    private final BooleanSetting trackTotem   = new BooleanSetting("Снос тотема", true);
    private final BooleanSetting trackPotions = new BooleanSetting("Полученные зелья", true);
    private final BooleanSetting trackConsume = new BooleanSetting("Съеденный предмет", true);
    private final SliderSetting  radius       = new SliderSetting("Радиус зелий", 100, 10, 100, 1, false).hidden(() -> true);


    private static class PotionData {
        ItemStack stack;
        double lastX, lastY, lastZ;
        PotionData(ItemStack stack, double x, double y, double z) {
            this.stack = stack; this.lastX = x; this.lastY = y; this.lastZ = z;
        }
    }
    private final Map<Integer, PotionData> trackedPotions = new HashMap<>();

    private final Map<UUID, ItemStack> activeUseItem = new HashMap<>();
    private final Map<UUID, Integer>   useStartTick  = new HashMap<>();

    public UseTracker() {
        this.addSettings(new Setting[]{trackTotem, trackPotions, trackConsume, radius});
    }

    @Override
    public void onDisable() {
        trackedPotions.clear();
        activeUseItem.clear();
        useStartTick.clear();
        super.onDisable();
    }

    @EventInit
    public void onTick(ClientTickEvent e) {
        if (!enable || mc.player == null || mc.world == null) return;

        if (trackConsume.get()) {
            for (PlayerEntity player : mc.world.getPlayers()) {
                if (player.getUuid().equals(mc.player.getUuid())) continue;
                UUID id = player.getUuid();
                if (player.isUsingItem()) {
                    if (!activeUseItem.containsKey(id)) {
                        activeUseItem.put(id, player.getActiveItem().copy());
                        useStartTick.put(id, player.age);
                    }
                } else {
                    ItemStack used = activeUseItem.remove(id);
                    Integer startTick = useStartTick.remove(id);
                    if (used == null || used.isEmpty() || startTick == null) continue;
                    if (player.age - startTick < 31) continue;
                    UseAction action = used.getUseAction();
                    String verb = switch (action) {
                        case DRINK -> "выпил";
                        case EAT   -> "съел";
                        default    -> null;
                    };
                    if (verb == null) continue;
                    String name = used.getName().getString().replaceAll("§.", "");
                    chat("§f" + player.getName().getString() + " §7" + verb + " §f" + name);
                }
            }
        }


        if (trackPotions.get()) {
            Set<Integer> current = new HashSet<>();
            float r = radius.get();

            for (var entity : mc.world.getEntities()) {
                if (!(entity instanceof PotionEntity potion)) continue;
                double dist = mc.player.distanceTo(potion);
                if (dist > r) continue;

                int eid = potion.getId();
                current.add(eid);
                if (!trackedPotions.containsKey(eid)) {
                    ItemStack stack = potion.getStack();
                    trackedPotions.put(eid, new PotionData(stack.copy(), potion.getX(), potion.getY(), potion.getZ()));
                } else {
                    PotionData d = trackedPotions.get(eid);
                    d.lastX = potion.getX();
                    d.lastY = potion.getY();
                    d.lastZ = potion.getZ();
                }
            }

            Set<Integer> removed = new HashSet<>(trackedPotions.keySet());
            removed.removeAll(current);

            for (int eid : removed) {
                PotionData data = trackedPotions.remove(eid);
                if (data == null) continue;

                Box hitBox = new Box(
                    data.lastX - 4, data.lastY - 2, data.lastZ - 4,
                    data.lastX + 4, data.lastY + 2, data.lastZ + 4
                );

                for (LivingEntity hit : mc.world.getEntitiesByClass(LivingEntity.class, hitBox, e2 -> true)) {
                    if (!(hit instanceof PlayerEntity player)) continue;
                    double dx = player.getX() - data.lastX;
                    double dz = player.getZ() - data.lastZ;
                    double dist = Math.sqrt(dx * dx + dz * dz);
                    if (dist > 4.0) continue;

                    net.minecraft.text.Text potionNameText = data.stack.getName();
                    String playerName = player.getName().getString();
                    double hitChance = Math.max(0, 1.0 - dist / 4.0) * 100.0;

                    int rgb2 = ru.explosive.util.render.core.Renderer2D.ColorUtil.getClientColor();
                    String hex2 = String.format("%06X", rgb2 & 0xFFFFFF);

                    net.minecraft.util.Formatting hitColor = hitChance >= 65 ? net.minecraft.util.Formatting.GREEN
                            : hitChance >= 35 ? net.minecraft.util.Formatting.YELLOW
                            : net.minecraft.util.Formatting.RED;

                    net.minecraft.text.MutableText potionMsg = net.minecraft.text.Text.empty()
                        .append(net.minecraft.text.Text.literal("Explosive Client").styled(s -> s.withBold(true).withColor(Integer.parseInt(hex2, 16))))
                        .append(net.minecraft.text.Text.literal(" » ").styled(s -> s.withColor(net.minecraft.util.Formatting.GRAY)))
                        .append(net.minecraft.text.Text.literal(playerName).styled(s -> s.withColor(net.minecraft.util.Formatting.WHITE)))
                        .append(net.minecraft.text.Text.literal(" получил ").styled(s -> s.withColor(net.minecraft.util.Formatting.GRAY)))
                        .append(potionNameText)
                        .append(net.minecraft.text.Text.literal(" (").styled(s -> s.withColor(net.minecraft.util.Formatting.GRAY)))
                        .append(net.minecraft.text.Text.literal(String.format("%.0f%%", hitChance)).styled(s -> s.withColor(hitColor)))
                        .append(net.minecraft.text.Text.literal(")").styled(s -> s.withColor(net.minecraft.util.Formatting.GRAY)));

                    mc.player.sendMessage(potionMsg, false);
                }
            }
        }
    }



    @EventInit
    public void onPacket(EventPacket e) {
        if (!enable || mc.world == null || mc.player == null) return;

        if (trackTotem.get() && e.getPacket() instanceof EntityStatusS2CPacket pkt && pkt.getStatus() == 35) {
            var entity = pkt.getEntity(mc.world);
            if (!(entity instanceof PlayerEntity player)) return;
            if (player.getUuid().equals(mc.player.getUuid())) return;

            ItemStack totemStack = player.getOffHandStack().isOf(Items.TOTEM_OF_UNDYING)
                    ? player.getOffHandStack()
                    : player.getMainHandStack().isOf(Items.TOTEM_OF_UNDYING)
                    ? player.getMainHandStack()
                    : player.getOffHandStack();

            String totemName = totemStack.isEmpty()
                    ? "Тотем бессмертия"
                    : null;
            net.minecraft.text.Text totemNameText = totemStack.isEmpty()
                    ? net.minecraft.text.Text.literal("Тотем бессмертия")
                    : totemStack.getName();

            boolean isEnchanted = EnchantmentHelper.hasEnchantments(player.getOffHandStack())
                                || EnchantmentHelper.hasEnchantments(player.getMainHandStack());

            net.minecraft.text.MutableText enchantPart = net.minecraft.text.Text.literal(isEnchanted ? "зачарованный" : "незачарованный")
                    .styled(s -> s.withColor(isEnchanted ? net.minecraft.util.Formatting.GREEN : net.minecraft.util.Formatting.RED));

            int rgb = ru.explosive.util.render.core.Renderer2D.ColorUtil.getClientColor();
            String hex = String.format("%06X", rgb & 0xFFFFFF);

            net.minecraft.text.MutableText text = net.minecraft.text.Text.empty()
                .append(net.minecraft.text.Text.literal("Explosive Client").styled(s -> s.withBold(true).withColor(Integer.parseInt(hex, 16))))
                .append(net.minecraft.text.Text.literal(" » ").styled(s -> s.withColor(net.minecraft.util.Formatting.GRAY)))
                .append(net.minecraft.text.Text.literal(player.getName().getString()).styled(s -> s.withColor(net.minecraft.util.Formatting.WHITE)))
                .append(net.minecraft.text.Text.literal(" потерял ").styled(s -> s.withColor(net.minecraft.util.Formatting.GRAY)))
                .append(totemNameText)
                .append(net.minecraft.text.Text.literal(" (").styled(s -> s.withColor(net.minecraft.util.Formatting.GRAY)))
                .append(enchantPart)
                .append(net.minecraft.text.Text.literal(")").styled(s -> s.withColor(net.minecraft.util.Formatting.GRAY)));

            mc.player.sendMessage(text, false);
        }
    }

    private void chat(String msg) {
        if (mc.player == null) return;
        int rgb = ru.explosive.util.render.core.Renderer2D.ColorUtil.getClientColor();
        String hex = String.format("%06X", rgb & 0xFFFFFF);
        net.minecraft.text.MutableText text = net.minecraft.text.Text.empty()
            .append(net.minecraft.text.Text.literal("Explosive Client").styled(s -> s
                .withBold(true)
                .withColor(Integer.parseInt(hex, 16))))
            .append(net.minecraft.text.Text.literal(" » ").styled(s -> s.withColor(net.minecraft.util.Formatting.GRAY)))
            .append(parseLegacy(msg));
        mc.player.sendMessage(text, false);
    }

    private static net.minecraft.text.MutableText parseLegacy(String msg) {
        net.minecraft.text.MutableText result = net.minecraft.text.Text.empty();
        net.minecraft.util.Formatting currentColor = null;
        boolean bold = false;
        StringBuilder current = new StringBuilder();

        for (int i = 0; i < msg.length(); i++) {
            char c = msg.charAt(i);
            if ((c == '§' || c == '\u00A7') && i + 1 < msg.length()) {
                if (current.length() > 0) {
                    net.minecraft.text.MutableText part = net.minecraft.text.Text.literal(current.toString());
                    if (currentColor != null) part = part.formatted(currentColor);
                    if (bold) part = part.formatted(net.minecraft.util.Formatting.BOLD);
                    result.append(part);
                    current.setLength(0);
                }
                char code = msg.charAt(++i);
                net.minecraft.util.Formatting fmt = net.minecraft.util.Formatting.byCode(code);
                if (fmt != null) {
                    if (fmt == net.minecraft.util.Formatting.BOLD) bold = true;
                    else if (fmt == net.minecraft.util.Formatting.RESET) { currentColor = null; bold = false; }
                    else if (fmt.isColor()) currentColor = fmt;
                }
            } else {
                current.append(c);
            }
        }
        if (current.length() > 0) {
            net.minecraft.text.MutableText part = net.minecraft.text.Text.literal(current.toString());
            if (currentColor != null) part = part.formatted(currentColor);
            if (bold) part = part.formatted(net.minecraft.util.Formatting.BOLD);
            result.append(part);
        }
        return result;
    }
}
new SliderSetting("Радиус зелий", 100, 10, 100, 1, false).hidden(() -> true); MOMENT
 
Всем пр начал делать 1.21.4 решил слить вроде простенькую функцию но полезную

SS - Посмотреть вложение 332446

Code -
сарделька:
Expand Collapse Copy
package ru.explosive.module.impl.misc;

import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.EquipmentSlot;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.projectile.thrown.PotionEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.item.consume.UseAction;
import net.minecraft.network.packet.s2c.play.EntityStatusS2CPacket;
import net.minecraft.text.Text;
import net.minecraft.util.math.Box;
import ru.explosive.event.EventInit;
import ru.explosive.event.impl.EventPacket;
import ru.explosive.event.lifecycle.ClientTickEvent;
import ru.explosive.module.api.Category;
import ru.explosive.module.api.IModule;
import ru.explosive.module.api.Module;
import ru.explosive.module.api.setting.Setting;
import ru.explosive.module.api.setting.impl.BooleanSetting;
import ru.explosive.module.api.setting.impl.SliderSetting;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

@IModule(name = "UseTracker", description = "Трекает тотемы, зелья и еду игроков", category = Category.Misc, bind = -1)
@Environment(EnvType.CLIENT)
public class UseTracker extends Module {

    private final BooleanSetting trackTotem   = new BooleanSetting("Снос тотема", true);
    private final BooleanSetting trackPotions = new BooleanSetting("Полученные зелья", true);
    private final BooleanSetting trackConsume = new BooleanSetting("Съеденный предмет", true);
    private final SliderSetting  radius       = new SliderSetting("Радиус зелий", 100, 10, 100, 1, false).hidden(() -> true);


    private static class PotionData {
        ItemStack stack;
        double lastX, lastY, lastZ;
        PotionData(ItemStack stack, double x, double y, double z) {
            this.stack = stack; this.lastX = x; this.lastY = y; this.lastZ = z;
        }
    }
    private final Map<Integer, PotionData> trackedPotions = new HashMap<>();

    private final Map<UUID, ItemStack> activeUseItem = new HashMap<>();
    private final Map<UUID, Integer>   useStartTick  = new HashMap<>();

    public UseTracker() {
        this.addSettings(new Setting[]{trackTotem, trackPotions, trackConsume, radius});
    }

    @Override
    public void onDisable() {
        trackedPotions.clear();
        activeUseItem.clear();
        useStartTick.clear();
        super.onDisable();
    }

    @EventInit
    public void onTick(ClientTickEvent e) {
        if (!enable || mc.player == null || mc.world == null) return;

        if (trackConsume.get()) {
            for (PlayerEntity player : mc.world.getPlayers()) {
                if (player.getUuid().equals(mc.player.getUuid())) continue;
                UUID id = player.getUuid();
                if (player.isUsingItem()) {
                    if (!activeUseItem.containsKey(id)) {
                        activeUseItem.put(id, player.getActiveItem().copy());
                        useStartTick.put(id, player.age);
                    }
                } else {
                    ItemStack used = activeUseItem.remove(id);
                    Integer startTick = useStartTick.remove(id);
                    if (used == null || used.isEmpty() || startTick == null) continue;
                    if (player.age - startTick < 31) continue;
                    UseAction action = used.getUseAction();
                    String verb = switch (action) {
                        case DRINK -> "выпил";
                        case EAT   -> "съел";
                        default    -> null;
                    };
                    if (verb == null) continue;
                    String name = used.getName().getString().replaceAll("§.", "");
                    chat("§f" + player.getName().getString() + " §7" + verb + " §f" + name);
                }
            }
        }


        if (trackPotions.get()) {
            Set<Integer> current = new HashSet<>();
            float r = radius.get();

            for (var entity : mc.world.getEntities()) {
                if (!(entity instanceof PotionEntity potion)) continue;
                double dist = mc.player.distanceTo(potion);
                if (dist > r) continue;

                int eid = potion.getId();
                current.add(eid);
                if (!trackedPotions.containsKey(eid)) {
                    ItemStack stack = potion.getStack();
                    trackedPotions.put(eid, new PotionData(stack.copy(), potion.getX(), potion.getY(), potion.getZ()));
                } else {
                    PotionData d = trackedPotions.get(eid);
                    d.lastX = potion.getX();
                    d.lastY = potion.getY();
                    d.lastZ = potion.getZ();
                }
            }

            Set<Integer> removed = new HashSet<>(trackedPotions.keySet());
            removed.removeAll(current);

            for (int eid : removed) {
                PotionData data = trackedPotions.remove(eid);
                if (data == null) continue;

                Box hitBox = new Box(
                    data.lastX - 4, data.lastY - 2, data.lastZ - 4,
                    data.lastX + 4, data.lastY + 2, data.lastZ + 4
                );

                for (LivingEntity hit : mc.world.getEntitiesByClass(LivingEntity.class, hitBox, e2 -> true)) {
                    if (!(hit instanceof PlayerEntity player)) continue;
                    double dx = player.getX() - data.lastX;
                    double dz = player.getZ() - data.lastZ;
                    double dist = Math.sqrt(dx * dx + dz * dz);
                    if (dist > 4.0) continue;

                    net.minecraft.text.Text potionNameText = data.stack.getName();
                    String playerName = player.getName().getString();
                    double hitChance = Math.max(0, 1.0 - dist / 4.0) * 100.0;

                    int rgb2 = ru.explosive.util.render.core.Renderer2D.ColorUtil.getClientColor();
                    String hex2 = String.format("%06X", rgb2 & 0xFFFFFF);

                    net.minecraft.util.Formatting hitColor = hitChance >= 65 ? net.minecraft.util.Formatting.GREEN
                            : hitChance >= 35 ? net.minecraft.util.Formatting.YELLOW
                            : net.minecraft.util.Formatting.RED;

                    net.minecraft.text.MutableText potionMsg = net.minecraft.text.Text.empty()
                        .append(net.minecraft.text.Text.literal("Explosive Client").styled(s -> s.withBold(true).withColor(Integer.parseInt(hex2, 16))))
                        .append(net.minecraft.text.Text.literal(" » ").styled(s -> s.withColor(net.minecraft.util.Formatting.GRAY)))
                        .append(net.minecraft.text.Text.literal(playerName).styled(s -> s.withColor(net.minecraft.util.Formatting.WHITE)))
                        .append(net.minecraft.text.Text.literal(" получил ").styled(s -> s.withColor(net.minecraft.util.Formatting.GRAY)))
                        .append(potionNameText)
                        .append(net.minecraft.text.Text.literal(" (").styled(s -> s.withColor(net.minecraft.util.Formatting.GRAY)))
                        .append(net.minecraft.text.Text.literal(String.format("%.0f%%", hitChance)).styled(s -> s.withColor(hitColor)))
                        .append(net.minecraft.text.Text.literal(")").styled(s -> s.withColor(net.minecraft.util.Formatting.GRAY)));

                    mc.player.sendMessage(potionMsg, false);
                }
            }
        }
    }



    @EventInit
    public void onPacket(EventPacket e) {
        if (!enable || mc.world == null || mc.player == null) return;

        if (trackTotem.get() && e.getPacket() instanceof EntityStatusS2CPacket pkt && pkt.getStatus() == 35) {
            var entity = pkt.getEntity(mc.world);
            if (!(entity instanceof PlayerEntity player)) return;
            if (player.getUuid().equals(mc.player.getUuid())) return;

            ItemStack totemStack = player.getOffHandStack().isOf(Items.TOTEM_OF_UNDYING)
                    ? player.getOffHandStack()
                    : player.getMainHandStack().isOf(Items.TOTEM_OF_UNDYING)
                    ? player.getMainHandStack()
                    : player.getOffHandStack();

            String totemName = totemStack.isEmpty()
                    ? "Тотем бессмертия"
                    : null;
            net.minecraft.text.Text totemNameText = totemStack.isEmpty()
                    ? net.minecraft.text.Text.literal("Тотем бессмертия")
                    : totemStack.getName();

            boolean isEnchanted = EnchantmentHelper.hasEnchantments(player.getOffHandStack())
                                || EnchantmentHelper.hasEnchantments(player.getMainHandStack());

            net.minecraft.text.MutableText enchantPart = net.minecraft.text.Text.literal(isEnchanted ? "зачарованный" : "незачарованный")
                    .styled(s -> s.withColor(isEnchanted ? net.minecraft.util.Formatting.GREEN : net.minecraft.util.Formatting.RED));

            int rgb = ru.explosive.util.render.core.Renderer2D.ColorUtil.getClientColor();
            String hex = String.format("%06X", rgb & 0xFFFFFF);

            net.minecraft.text.MutableText text = net.minecraft.text.Text.empty()
                .append(net.minecraft.text.Text.literal("Explosive Client").styled(s -> s.withBold(true).withColor(Integer.parseInt(hex, 16))))
                .append(net.minecraft.text.Text.literal(" » ").styled(s -> s.withColor(net.minecraft.util.Formatting.GRAY)))
                .append(net.minecraft.text.Text.literal(player.getName().getString()).styled(s -> s.withColor(net.minecraft.util.Formatting.WHITE)))
                .append(net.minecraft.text.Text.literal(" потерял ").styled(s -> s.withColor(net.minecraft.util.Formatting.GRAY)))
                .append(totemNameText)
                .append(net.minecraft.text.Text.literal(" (").styled(s -> s.withColor(net.minecraft.util.Formatting.GRAY)))
                .append(enchantPart)
                .append(net.minecraft.text.Text.literal(")").styled(s -> s.withColor(net.minecraft.util.Formatting.GRAY)));

            mc.player.sendMessage(text, false);
        }
    }

    private void chat(String msg) {
        if (mc.player == null) return;
        int rgb = ru.explosive.util.render.core.Renderer2D.ColorUtil.getClientColor();
        String hex = String.format("%06X", rgb & 0xFFFFFF);
        net.minecraft.text.MutableText text = net.minecraft.text.Text.empty()
            .append(net.minecraft.text.Text.literal("Explosive Client").styled(s -> s
                .withBold(true)
                .withColor(Integer.parseInt(hex, 16))))
            .append(net.minecraft.text.Text.literal(" » ").styled(s -> s.withColor(net.minecraft.util.Formatting.GRAY)))
            .append(parseLegacy(msg));
        mc.player.sendMessage(text, false);
    }

    private static net.minecraft.text.MutableText parseLegacy(String msg) {
        net.minecraft.text.MutableText result = net.minecraft.text.Text.empty();
        net.minecraft.util.Formatting currentColor = null;
        boolean bold = false;
        StringBuilder current = new StringBuilder();

        for (int i = 0; i < msg.length(); i++) {
            char c = msg.charAt(i);
            if ((c == '§' || c == '\u00A7') && i + 1 < msg.length()) {
                if (current.length() > 0) {
                    net.minecraft.text.MutableText part = net.minecraft.text.Text.literal(current.toString());
                    if (currentColor != null) part = part.formatted(currentColor);
                    if (bold) part = part.formatted(net.minecraft.util.Formatting.BOLD);
                    result.append(part);
                    current.setLength(0);
                }
                char code = msg.charAt(++i);
                net.minecraft.util.Formatting fmt = net.minecraft.util.Formatting.byCode(code);
                if (fmt != null) {
                    if (fmt == net.minecraft.util.Formatting.BOLD) bold = true;
                    else if (fmt == net.minecraft.util.Formatting.RESET) { currentColor = null; bold = false; }
                    else if (fmt.isColor()) currentColor = fmt;
                }
            } else {
                current.append(c);
            }
        }
        if (current.length() > 0) {
            net.minecraft.text.MutableText part = net.minecraft.text.Text.literal(current.toString());
            if (currentColor != null) part = part.formatted(currentColor);
            if (bold) part = part.formatted(net.minecraft.util.Formatting.BOLD);
            result.append(part);
        }
        return result;
    }
}
new SliderSetting("Радиус зелий", 100, 10, 100, 1, false).hidden(() -> true); MOMENT
/up
Всем пр начал делать 1.21.4 решил слить вроде простенькую функцию но полезную

SS - Посмотреть вложение 332446

Code -
сарделька:
Expand Collapse Copy
package ru.explosive.module.impl.misc;

import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.EquipmentSlot;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.projectile.thrown.PotionEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.item.consume.UseAction;
import net.minecraft.network.packet.s2c.play.EntityStatusS2CPacket;
import net.minecraft.text.Text;
import net.minecraft.util.math.Box;
import ru.explosive.event.EventInit;
import ru.explosive.event.impl.EventPacket;
import ru.explosive.event.lifecycle.ClientTickEvent;
import ru.explosive.module.api.Category;
import ru.explosive.module.api.IModule;
import ru.explosive.module.api.Module;
import ru.explosive.module.api.setting.Setting;
import ru.explosive.module.api.setting.impl.BooleanSetting;
import ru.explosive.module.api.setting.impl.SliderSetting;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

@IModule(name = "UseTracker", description = "Трекает тотемы, зелья и еду игроков", category = Category.Misc, bind = -1)
@Environment(EnvType.CLIENT)
public class UseTracker extends Module {

    private final BooleanSetting trackTotem   = new BooleanSetting("Снос тотема", true);
    private final BooleanSetting trackPotions = new BooleanSetting("Полученные зелья", true);
    private final BooleanSetting trackConsume = new BooleanSetting("Съеденный предмет", true);
    private final SliderSetting  radius       = new SliderSetting("Радиус зелий", 100, 10, 100, 1, false).hidden(() -> true);


    private static class PotionData {
        ItemStack stack;
        double lastX, lastY, lastZ;
        PotionData(ItemStack stack, double x, double y, double z) {
            this.stack = stack; this.lastX = x; this.lastY = y; this.lastZ = z;
        }
    }
    private final Map<Integer, PotionData> trackedPotions = new HashMap<>();

    private final Map<UUID, ItemStack> activeUseItem = new HashMap<>();
    private final Map<UUID, Integer>   useStartTick  = new HashMap<>();

    public UseTracker() {
        this.addSettings(new Setting[]{trackTotem, trackPotions, trackConsume, radius});
    }

    @Override
    public void onDisable() {
        trackedPotions.clear();
        activeUseItem.clear();
        useStartTick.clear();
        super.onDisable();
    }

    @EventInit
    public void onTick(ClientTickEvent e) {
        if (!enable || mc.player == null || mc.world == null) return;

        if (trackConsume.get()) {
            for (PlayerEntity player : mc.world.getPlayers()) {
                if (player.getUuid().equals(mc.player.getUuid())) continue;
                UUID id = player.getUuid();
                if (player.isUsingItem()) {
                    if (!activeUseItem.containsKey(id)) {
                        activeUseItem.put(id, player.getActiveItem().copy());
                        useStartTick.put(id, player.age);
                    }
                } else {
                    ItemStack used = activeUseItem.remove(id);
                    Integer startTick = useStartTick.remove(id);
                    if (used == null || used.isEmpty() || startTick == null) continue;
                    if (player.age - startTick < 31) continue;
                    UseAction action = used.getUseAction();
                    String verb = switch (action) {
                        case DRINK -> "выпил";
                        case EAT   -> "съел";
                        default    -> null;
                    };
                    if (verb == null) continue;
                    String name = used.getName().getString().replaceAll("§.", "");
                    chat("§f" + player.getName().getString() + " §7" + verb + " §f" + name);
                }
            }
        }


        if (trackPotions.get()) {
            Set<Integer> current = new HashSet<>();
            float r = radius.get();

            for (var entity : mc.world.getEntities()) {
                if (!(entity instanceof PotionEntity potion)) continue;
                double dist = mc.player.distanceTo(potion);
                if (dist > r) continue;

                int eid = potion.getId();
                current.add(eid);
                if (!trackedPotions.containsKey(eid)) {
                    ItemStack stack = potion.getStack();
                    trackedPotions.put(eid, new PotionData(stack.copy(), potion.getX(), potion.getY(), potion.getZ()));
                } else {
                    PotionData d = trackedPotions.get(eid);
                    d.lastX = potion.getX();
                    d.lastY = potion.getY();
                    d.lastZ = potion.getZ();
                }
            }

            Set<Integer> removed = new HashSet<>(trackedPotions.keySet());
            removed.removeAll(current);

            for (int eid : removed) {
                PotionData data = trackedPotions.remove(eid);
                if (data == null) continue;

                Box hitBox = new Box(
                    data.lastX - 4, data.lastY - 2, data.lastZ - 4,
                    data.lastX + 4, data.lastY + 2, data.lastZ + 4
                );

                for (LivingEntity hit : mc.world.getEntitiesByClass(LivingEntity.class, hitBox, e2 -> true)) {
                    if (!(hit instanceof PlayerEntity player)) continue;
                    double dx = player.getX() - data.lastX;
                    double dz = player.getZ() - data.lastZ;
                    double dist = Math.sqrt(dx * dx + dz * dz);
                    if (dist > 4.0) continue;

                    net.minecraft.text.Text potionNameText = data.stack.getName();
                    String playerName = player.getName().getString();
                    double hitChance = Math.max(0, 1.0 - dist / 4.0) * 100.0;

                    int rgb2 = ru.explosive.util.render.core.Renderer2D.ColorUtil.getClientColor();
                    String hex2 = String.format("%06X", rgb2 & 0xFFFFFF);

                    net.minecraft.util.Formatting hitColor = hitChance >= 65 ? net.minecraft.util.Formatting.GREEN
                            : hitChance >= 35 ? net.minecraft.util.Formatting.YELLOW
                            : net.minecraft.util.Formatting.RED;

                    net.minecraft.text.MutableText potionMsg = net.minecraft.text.Text.empty()
                        .append(net.minecraft.text.Text.literal("Explosive Client").styled(s -> s.withBold(true).withColor(Integer.parseInt(hex2, 16))))
                        .append(net.minecraft.text.Text.literal(" » ").styled(s -> s.withColor(net.minecraft.util.Formatting.GRAY)))
                        .append(net.minecraft.text.Text.literal(playerName).styled(s -> s.withColor(net.minecraft.util.Formatting.WHITE)))
                        .append(net.minecraft.text.Text.literal(" получил ").styled(s -> s.withColor(net.minecraft.util.Formatting.GRAY)))
                        .append(potionNameText)
                        .append(net.minecraft.text.Text.literal(" (").styled(s -> s.withColor(net.minecraft.util.Formatting.GRAY)))
                        .append(net.minecraft.text.Text.literal(String.format("%.0f%%", hitChance)).styled(s -> s.withColor(hitColor)))
                        .append(net.minecraft.text.Text.literal(")").styled(s -> s.withColor(net.minecraft.util.Formatting.GRAY)));

                    mc.player.sendMessage(potionMsg, false);
                }
            }
        }
    }



    @EventInit
    public void onPacket(EventPacket e) {
        if (!enable || mc.world == null || mc.player == null) return;

        if (trackTotem.get() && e.getPacket() instanceof EntityStatusS2CPacket pkt && pkt.getStatus() == 35) {
            var entity = pkt.getEntity(mc.world);
            if (!(entity instanceof PlayerEntity player)) return;
            if (player.getUuid().equals(mc.player.getUuid())) return;

            ItemStack totemStack = player.getOffHandStack().isOf(Items.TOTEM_OF_UNDYING)
                    ? player.getOffHandStack()
                    : player.getMainHandStack().isOf(Items.TOTEM_OF_UNDYING)
                    ? player.getMainHandStack()
                    : player.getOffHandStack();

            String totemName = totemStack.isEmpty()
                    ? "Тотем бессмертия"
                    : null;
            net.minecraft.text.Text totemNameText = totemStack.isEmpty()
                    ? net.minecraft.text.Text.literal("Тотем бессмертия")
                    : totemStack.getName();

            boolean isEnchanted = EnchantmentHelper.hasEnchantments(player.getOffHandStack())
                                || EnchantmentHelper.hasEnchantments(player.getMainHandStack());

            net.minecraft.text.MutableText enchantPart = net.minecraft.text.Text.literal(isEnchanted ? "зачарованный" : "незачарованный")
                    .styled(s -> s.withColor(isEnchanted ? net.minecraft.util.Formatting.GREEN : net.minecraft.util.Formatting.RED));

            int rgb = ru.explosive.util.render.core.Renderer2D.ColorUtil.getClientColor();
            String hex = String.format("%06X", rgb & 0xFFFFFF);

            net.minecraft.text.MutableText text = net.minecraft.text.Text.empty()
                .append(net.minecraft.text.Text.literal("Explosive Client").styled(s -> s.withBold(true).withColor(Integer.parseInt(hex, 16))))
                .append(net.minecraft.text.Text.literal(" » ").styled(s -> s.withColor(net.minecraft.util.Formatting.GRAY)))
                .append(net.minecraft.text.Text.literal(player.getName().getString()).styled(s -> s.withColor(net.minecraft.util.Formatting.WHITE)))
                .append(net.minecraft.text.Text.literal(" потерял ").styled(s -> s.withColor(net.minecraft.util.Formatting.GRAY)))
                .append(totemNameText)
                .append(net.minecraft.text.Text.literal(" (").styled(s -> s.withColor(net.minecraft.util.Formatting.GRAY)))
                .append(enchantPart)
                .append(net.minecraft.text.Text.literal(")").styled(s -> s.withColor(net.minecraft.util.Formatting.GRAY)));

            mc.player.sendMessage(text, false);
        }
    }

    private void chat(String msg) {
        if (mc.player == null) return;
        int rgb = ru.explosive.util.render.core.Renderer2D.ColorUtil.getClientColor();
        String hex = String.format("%06X", rgb & 0xFFFFFF);
        net.minecraft.text.MutableText text = net.minecraft.text.Text.empty()
            .append(net.minecraft.text.Text.literal("Explosive Client").styled(s -> s
                .withBold(true)
                .withColor(Integer.parseInt(hex, 16))))
            .append(net.minecraft.text.Text.literal(" » ").styled(s -> s.withColor(net.minecraft.util.Formatting.GRAY)))
            .append(parseLegacy(msg));
        mc.player.sendMessage(text, false);
    }

    private static net.minecraft.text.MutableText parseLegacy(String msg) {
        net.minecraft.text.MutableText result = net.minecraft.text.Text.empty();
        net.minecraft.util.Formatting currentColor = null;
        boolean bold = false;
        StringBuilder current = new StringBuilder();

        for (int i = 0; i < msg.length(); i++) {
            char c = msg.charAt(i);
            if ((c == '§' || c == '\u00A7') && i + 1 < msg.length()) {
                if (current.length() > 0) {
                    net.minecraft.text.MutableText part = net.minecraft.text.Text.literal(current.toString());
                    if (currentColor != null) part = part.formatted(currentColor);
                    if (bold) part = part.formatted(net.minecraft.util.Formatting.BOLD);
                    result.append(part);
                    current.setLength(0);
                }
                char code = msg.charAt(++i);
                net.minecraft.util.Formatting fmt = net.minecraft.util.Formatting.byCode(code);
                if (fmt != null) {
                    if (fmt == net.minecraft.util.Formatting.BOLD) bold = true;
                    else if (fmt == net.minecraft.util.Formatting.RESET) { currentColor = null; bold = false; }
                    else if (fmt.isColor()) currentColor = fmt;
                }
            } else {
                current.append(c);
            }
        }
        if (current.length() > 0) {
            net.minecraft.text.MutableText part = net.minecraft.text.Text.literal(current.toString());
            if (currentColor != null) part = part.formatted(currentColor);
            if (bold) part = part.formatted(net.minecraft.util.Formatting.BOLD);
            result.append(part);
        }
        return result;
    }
}
new SliderSetting("Радиус зелий", 100, 10, 100, 1, false).hidden(() -> true); MOMENT
Когда дашь иконки вилда ласт?
 
Всем пр начал делать 1.21.4 решил слить вроде простенькую функцию но полезную

SS - Посмотреть вложение 332446

Code -
сарделька:
Expand Collapse Copy
package ru.explosive.module.impl.misc;

import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.EquipmentSlot;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.projectile.thrown.PotionEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.item.consume.UseAction;
import net.minecraft.network.packet.s2c.play.EntityStatusS2CPacket;
import net.minecraft.text.Text;
import net.minecraft.util.math.Box;
import ru.explosive.event.EventInit;
import ru.explosive.event.impl.EventPacket;
import ru.explosive.event.lifecycle.ClientTickEvent;
import ru.explosive.module.api.Category;
import ru.explosive.module.api.IModule;
import ru.explosive.module.api.Module;
import ru.explosive.module.api.setting.Setting;
import ru.explosive.module.api.setting.impl.BooleanSetting;
import ru.explosive.module.api.setting.impl.SliderSetting;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

@IModule(name = "UseTracker", description = "Трекает тотемы, зелья и еду игроков", category = Category.Misc, bind = -1)
@Environment(EnvType.CLIENT)
public class UseTracker extends Module {

    private final BooleanSetting trackTotem   = new BooleanSetting("Снос тотема", true);
    private final BooleanSetting trackPotions = new BooleanSetting("Полученные зелья", true);
    private final BooleanSetting trackConsume = new BooleanSetting("Съеденный предмет", true);
    private final SliderSetting  radius       = new SliderSetting("Радиус зелий", 100, 10, 100, 1, false).hidden(() -> true);


    private static class PotionData {
        ItemStack stack;
        double lastX, lastY, lastZ;
        PotionData(ItemStack stack, double x, double y, double z) {
            this.stack = stack; this.lastX = x; this.lastY = y; this.lastZ = z;
        }
    }
    private final Map<Integer, PotionData> trackedPotions = new HashMap<>();

    private final Map<UUID, ItemStack> activeUseItem = new HashMap<>();
    private final Map<UUID, Integer>   useStartTick  = new HashMap<>();

    public UseTracker() {
        this.addSettings(new Setting[]{trackTotem, trackPotions, trackConsume, radius});
    }

    @Override
    public void onDisable() {
        trackedPotions.clear();
        activeUseItem.clear();
        useStartTick.clear();
        super.onDisable();
    }

    @EventInit
    public void onTick(ClientTickEvent e) {
        if (!enable || mc.player == null || mc.world == null) return;

        if (trackConsume.get()) {
            for (PlayerEntity player : mc.world.getPlayers()) {
                if (player.getUuid().equals(mc.player.getUuid())) continue;
                UUID id = player.getUuid();
                if (player.isUsingItem()) {
                    if (!activeUseItem.containsKey(id)) {
                        activeUseItem.put(id, player.getActiveItem().copy());
                        useStartTick.put(id, player.age);
                    }
                } else {
                    ItemStack used = activeUseItem.remove(id);
                    Integer startTick = useStartTick.remove(id);
                    if (used == null || used.isEmpty() || startTick == null) continue;
                    if (player.age - startTick < 31) continue;
                    UseAction action = used.getUseAction();
                    String verb = switch (action) {
                        case DRINK -> "выпил";
                        case EAT   -> "съел";
                        default    -> null;
                    };
                    if (verb == null) continue;
                    String name = used.getName().getString().replaceAll("§.", "");
                    chat("§f" + player.getName().getString() + " §7" + verb + " §f" + name);
                }
            }
        }


        if (trackPotions.get()) {
            Set<Integer> current = new HashSet<>();
            float r = radius.get();

            for (var entity : mc.world.getEntities()) {
                if (!(entity instanceof PotionEntity potion)) continue;
                double dist = mc.player.distanceTo(potion);
                if (dist > r) continue;

                int eid = potion.getId();
                current.add(eid);
                if (!trackedPotions.containsKey(eid)) {
                    ItemStack stack = potion.getStack();
                    trackedPotions.put(eid, new PotionData(stack.copy(), potion.getX(), potion.getY(), potion.getZ()));
                } else {
                    PotionData d = trackedPotions.get(eid);
                    d.lastX = potion.getX();
                    d.lastY = potion.getY();
                    d.lastZ = potion.getZ();
                }
            }

            Set<Integer> removed = new HashSet<>(trackedPotions.keySet());
            removed.removeAll(current);

            for (int eid : removed) {
                PotionData data = trackedPotions.remove(eid);
                if (data == null) continue;

                Box hitBox = new Box(
                    data.lastX - 4, data.lastY - 2, data.lastZ - 4,
                    data.lastX + 4, data.lastY + 2, data.lastZ + 4
                );

                for (LivingEntity hit : mc.world.getEntitiesByClass(LivingEntity.class, hitBox, e2 -> true)) {
                    if (!(hit instanceof PlayerEntity player)) continue;
                    double dx = player.getX() - data.lastX;
                    double dz = player.getZ() - data.lastZ;
                    double dist = Math.sqrt(dx * dx + dz * dz);
                    if (dist > 4.0) continue;

                    net.minecraft.text.Text potionNameText = data.stack.getName();
                    String playerName = player.getName().getString();
                    double hitChance = Math.max(0, 1.0 - dist / 4.0) * 100.0;

                    int rgb2 = ru.explosive.util.render.core.Renderer2D.ColorUtil.getClientColor();
                    String hex2 = String.format("%06X", rgb2 & 0xFFFFFF);

                    net.minecraft.util.Formatting hitColor = hitChance >= 65 ? net.minecraft.util.Formatting.GREEN
                            : hitChance >= 35 ? net.minecraft.util.Formatting.YELLOW
                            : net.minecraft.util.Formatting.RED;

                    net.minecraft.text.MutableText potionMsg = net.minecraft.text.Text.empty()
                        .append(net.minecraft.text.Text.literal("Explosive Client").styled(s -> s.withBold(true).withColor(Integer.parseInt(hex2, 16))))
                        .append(net.minecraft.text.Text.literal(" » ").styled(s -> s.withColor(net.minecraft.util.Formatting.GRAY)))
                        .append(net.minecraft.text.Text.literal(playerName).styled(s -> s.withColor(net.minecraft.util.Formatting.WHITE)))
                        .append(net.minecraft.text.Text.literal(" получил ").styled(s -> s.withColor(net.minecraft.util.Formatting.GRAY)))
                        .append(potionNameText)
                        .append(net.minecraft.text.Text.literal(" (").styled(s -> s.withColor(net.minecraft.util.Formatting.GRAY)))
                        .append(net.minecraft.text.Text.literal(String.format("%.0f%%", hitChance)).styled(s -> s.withColor(hitColor)))
                        .append(net.minecraft.text.Text.literal(")").styled(s -> s.withColor(net.minecraft.util.Formatting.GRAY)));

                    mc.player.sendMessage(potionMsg, false);
                }
            }
        }
    }



    @EventInit
    public void onPacket(EventPacket e) {
        if (!enable || mc.world == null || mc.player == null) return;

        if (trackTotem.get() && e.getPacket() instanceof EntityStatusS2CPacket pkt && pkt.getStatus() == 35) {
            var entity = pkt.getEntity(mc.world);
            if (!(entity instanceof PlayerEntity player)) return;
            if (player.getUuid().equals(mc.player.getUuid())) return;

            ItemStack totemStack = player.getOffHandStack().isOf(Items.TOTEM_OF_UNDYING)
                    ? player.getOffHandStack()
                    : player.getMainHandStack().isOf(Items.TOTEM_OF_UNDYING)
                    ? player.getMainHandStack()
                    : player.getOffHandStack();

            String totemName = totemStack.isEmpty()
                    ? "Тотем бессмертия"
                    : null;
            net.minecraft.text.Text totemNameText = totemStack.isEmpty()
                    ? net.minecraft.text.Text.literal("Тотем бессмертия")
                    : totemStack.getName();

            boolean isEnchanted = EnchantmentHelper.hasEnchantments(player.getOffHandStack())
                                || EnchantmentHelper.hasEnchantments(player.getMainHandStack());

            net.minecraft.text.MutableText enchantPart = net.minecraft.text.Text.literal(isEnchanted ? "зачарованный" : "незачарованный")
                    .styled(s -> s.withColor(isEnchanted ? net.minecraft.util.Formatting.GREEN : net.minecraft.util.Formatting.RED));

            int rgb = ru.explosive.util.render.core.Renderer2D.ColorUtil.getClientColor();
            String hex = String.format("%06X", rgb & 0xFFFFFF);

            net.minecraft.text.MutableText text = net.minecraft.text.Text.empty()
                .append(net.minecraft.text.Text.literal("Explosive Client").styled(s -> s.withBold(true).withColor(Integer.parseInt(hex, 16))))
                .append(net.minecraft.text.Text.literal(" » ").styled(s -> s.withColor(net.minecraft.util.Formatting.GRAY)))
                .append(net.minecraft.text.Text.literal(player.getName().getString()).styled(s -> s.withColor(net.minecraft.util.Formatting.WHITE)))
                .append(net.minecraft.text.Text.literal(" потерял ").styled(s -> s.withColor(net.minecraft.util.Formatting.GRAY)))
                .append(totemNameText)
                .append(net.minecraft.text.Text.literal(" (").styled(s -> s.withColor(net.minecraft.util.Formatting.GRAY)))
                .append(enchantPart)
                .append(net.minecraft.text.Text.literal(")").styled(s -> s.withColor(net.minecraft.util.Formatting.GRAY)));

            mc.player.sendMessage(text, false);
        }
    }

    private void chat(String msg) {
        if (mc.player == null) return;
        int rgb = ru.explosive.util.render.core.Renderer2D.ColorUtil.getClientColor();
        String hex = String.format("%06X", rgb & 0xFFFFFF);
        net.minecraft.text.MutableText text = net.minecraft.text.Text.empty()
            .append(net.minecraft.text.Text.literal("Explosive Client").styled(s -> s
                .withBold(true)
                .withColor(Integer.parseInt(hex, 16))))
            .append(net.minecraft.text.Text.literal(" » ").styled(s -> s.withColor(net.minecraft.util.Formatting.GRAY)))
            .append(parseLegacy(msg));
        mc.player.sendMessage(text, false);
    }

    private static net.minecraft.text.MutableText parseLegacy(String msg) {
        net.minecraft.text.MutableText result = net.minecraft.text.Text.empty();
        net.minecraft.util.Formatting currentColor = null;
        boolean bold = false;
        StringBuilder current = new StringBuilder();

        for (int i = 0; i < msg.length(); i++) {
            char c = msg.charAt(i);
            if ((c == '§' || c == '\u00A7') && i + 1 < msg.length()) {
                if (current.length() > 0) {
                    net.minecraft.text.MutableText part = net.minecraft.text.Text.literal(current.toString());
                    if (currentColor != null) part = part.formatted(currentColor);
                    if (bold) part = part.formatted(net.minecraft.util.Formatting.BOLD);
                    result.append(part);
                    current.setLength(0);
                }
                char code = msg.charAt(++i);
                net.minecraft.util.Formatting fmt = net.minecraft.util.Formatting.byCode(code);
                if (fmt != null) {
                    if (fmt == net.minecraft.util.Formatting.BOLD) bold = true;
                    else if (fmt == net.minecraft.util.Formatting.RESET) { currentColor = null; bold = false; }
                    else if (fmt.isColor()) currentColor = fmt;
                }
            } else {
                current.append(c);
            }
        }
        if (current.length() > 0) {
            net.minecraft.text.MutableText part = net.minecraft.text.Text.literal(current.toString());
            if (currentColor != null) part = part.formatted(currentColor);
            if (bold) part = part.formatted(net.minecraft.util.Formatting.BOLD);
            result.append(part);
        }
        return result;
    }
}
new SliderSetting("Радиус зелий", 100, 10, 100, 1, false).hidden(() -> true); MOMENT
Название темы вроде

UseTracker 1.21.8 а не UseTracker 1.21.4​

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