- Статус
- Оффлайн
- Регистрация
- 7 Мар 2025
- Сообщения
- 180
- Реакции
- 3
- Выберите загрузчик игры
- Fabric
Всем пр начал делать 1.21.4 решил слить вроде простенькую функцию но полезную
SS -
Code -
new SliderSetting("Радиус зелий", 100, 10, 100, 1, false).hidden(() -> true); MOMENT
SS -
Code -
сарделька:
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;
}
}

