- Выберите загрузчик игры
- Fabric
WARNING "Вайбкод"
Простенький есп на сундуки у которых сверху есть таймер, сделан с помощью дипсика.
Есть память таймера за большую дистанцию.
SS:
Простенький есп на сундуки у которых сверху есть таймер, сделан с помощью дипсика.
Есть память таймера за большую дистанцию.
SS:
Java:
package ru.zenith.implement.features.modules.render;
import lombok.AccessLevel;
import lombok.experimental.FieldDefaults;
import net.minecraft.block.ChestBlock;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.Entity;
import net.minecraft.entity.decoration.ArmorStandEntity;
import net.minecraft.entity.decoration.DisplayEntity;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.Vec3d;
import org.joml.Vector4d;
import ru.zenith.api.event.EventHandler;
import ru.zenith.api.feature.module.Module;
import ru.zenith.api.feature.module.ModuleCategory;
import ru.zenith.api.feature.module.setting.implement.ValueSetting;
import ru.zenith.api.system.font.FontRenderer;
import ru.zenith.api.system.font.Fonts;
import ru.zenith.api.system.shape.ShapeProperties;
import ru.zenith.common.util.color.ColorUtil;
import ru.zenith.common.util.math.ProjectionUtil;
import ru.zenith.common.util.render.Render3DUtil;
import ru.zenith.implement.events.player.TickEvent;
import ru.zenith.implement.events.render.DrawEvent;
import ru.zenith.implement.events.render.WorldLoadEvent;
import ru.zenith.implement.events.render.WorldRenderEvent;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@FieldDefaults(level = AccessLevel.PRIVATE)
public class ChestTimerESP extends Module {
final Map<BlockPos, ChestData> chests = new ConcurrentHashMap<>();
final Pattern TIME_PATTERN = Pattern.compile("(\\d{1,2})\\s*:\\s*(\\d{2})");
final ValueSetting rangeSetting = new ValueSetting("Range", "Дистанция")
.setValue(30).range(10, 60);
final ValueSetting sizeSetting = new ValueSetting("Tag Size", "Размер текста")
.setValue(13).range(10, 20);
public ChestTimerESP() {
super("ChestTimerESP", "Chest Timer ESP", ModuleCategory.RENDER);
setup(rangeSetting, sizeSetting);
}
@EventHandler
public void onWorldLoad(WorldLoadEvent e) {
chests.clear();
}
@EventHandler
public void onTick(TickEvent e) {
if (mc.world == null || mc.player == null) return;
if (mc.player.age % 5 == 0) {
int range = rangeSetting.getInt();
BlockPos pPos = mc.player.getBlockPos();
for (int x = -range; x <= range; x++) {
for (int z = -range; z <= range; z++) {
for (int y = -5; y <= 5; y++) {
BlockPos pos = pPos.add(x, y, z);
if (mc.world.getBlockState(pos).getBlock() instanceof ChestBlock) {
updateChestTimer(pos);
}
}
}
}
}
Vec3d pVec = mc.player.getPos();
chests.entrySet().removeIf(entry ->
pVec.distanceTo(entry.getKey().toCenterPos()) > rangeSetting.getInt() + 10 ||
(entry.getValue().hasValidTimer() && entry.getValue().getRemainingSeconds() <= 0)
);
}
private void updateChestTimer(BlockPos pos) {
if (mc.world == null) return;
Vec3d center = pos.toCenterPos();
Box searchBox = new Box(center.x - 1, center.y, center.z - 1, center.x + 1, center.y + 4.0, center.z + 1);
for (Entity entity : mc.world.getOtherEntities(null, searchBox)) {
String rawText = null;
if (entity instanceof DisplayEntity.TextDisplayEntity td) rawText = td.getText().getString();
else if (entity instanceof ArmorStandEntity as) rawText = as.getCustomName() != null ? as.getCustomName().getString() : null;
if (rawText != null) {
String clean = rawText.replaceAll("(?i)§[0-9A-FK-OR]", "");
Matcher m = TIME_PATTERN.matcher(clean);
if (m.find()) {
int total = Integer.parseInt(m.group(1)) * 60 + Integer.parseInt(m.group(2));
ChestData existing = chests.get(pos);
if (existing == null || Math.abs(existing.timerSeconds - total) > 1) {
chests.put(pos, new ChestData(total, entity));
}
return;
}
}
}
chests.putIfAbsent(pos, new ChestData(-1, null));
}
@EventHandler
public void onWorldRender(WorldRenderEvent e) {
for (Map.Entry<BlockPos, ChestData> entry : chests.entrySet()) {
BlockPos pos = entry.getKey();
ChestData data = entry.getValue();
if (data.hasValidTimer() && data.getRemainingSeconds() > 0) {
int left = data.getRemainingSeconds();
int color = (left <= 30) ? 0x90FF3333 : 0x9033FF33;
Render3DUtil.drawBox(new Box(pos), color, 2);
}
}
}
@EventHandler
public void onDraw(DrawEvent e) {
DrawContext context = e.getDrawContext();
MatrixStack matrix = context.getMatrices();
FontRenderer font = Fonts.getSize(sizeSetting.getInt(), Fonts.Type.DEFAULT);
for (ChestData data : chests.values()) {
if (!data.hasValidTimer() || data.entity == null) continue;
int left = data.getRemainingSeconds();
if (left <= 0) continue;
Vector4d vec = ProjectionUtil.getVector4D(data.entity);
if (vec == null || ProjectionUtil.cantSee(vec)) continue;
String timeStr = String.format("%02d:%02d", left / 60, left % 60);
Text text = Text.literal(timeStr).formatted(left <= 30 ? Formatting.RED : Formatting.GREEN);
drawText(matrix, text, ProjectionUtil.centerX(vec), vec.y - 5, font);
}
}
private void drawText(MatrixStack matrix, Text text, double x, double y, FontRenderer font) {
float w = font.getStringWidth(text);
float h = font.getFont().getSize() / 1.5F;
float px = (float) x - w / 2;
float py = (float) y - h;
blur.render(ShapeProperties.create(matrix, px - 2, py - 1, w + 4, h + 2)
.round(h / 4).color(ColorUtil.HALF_BLACK).build());
font.drawText(matrix, text, px, py + 3);
}
@FieldDefaults(level = AccessLevel.PRIVATE)
private static class ChestData {
final int timerSeconds;
final long startTime;
final boolean hasTimer;
final Entity entity;
public ChestData(int seconds, Entity entity) {
this.timerSeconds = seconds;
this.hasTimer = seconds > 0;
this.startTime = System.currentTimeMillis();
this.entity = entity;
}
public int getRemainingSeconds() {
if (!hasTimer) return 0;
return Math.max(0, timerSeconds - (int)((System.currentTimeMillis() - startTime) / 1000));
}
public boolean hasValidTimer() { return hasTimer; }
}
}