Начинающий
- Статус
- Оффлайн
- Регистрация
- 8 Авг 2025
- Сообщения
- 25
- Реакции
- 0
- Выберите загрузчик игры
- Vanilla
- Forge
- Fabric
- NeoForge
- OptiFine
- ForgeOptiFine
- Прочие моды
Всем привет медвед. Сливаю полезную функцию для всех серверов, пастерам сойдёт.
Увидел данные 2 темы: https://yougame.biz/threads/362214, https://yougame.biz/threads/362451.
И решил их доработать и сделать общий хороший элемент худа, который подойдёт как и для нн паст, так и для популярных читов. Надеюсь не будет /del и так далее, ведь я реально по тратил на это 1час. P.S. Вторая моя тема на югейме
Cделано читом: SpookyClient.fun(noad)
Автор произведения: Rastyshka1337 AKA defByrniy
SS:
код:
Увидел данные 2 темы: https://yougame.biz/threads/362214, https://yougame.biz/threads/362451.
И решил их доработать и сделать общий хороший элемент худа, который подойдёт как и для нн паст, так и для популярных читов. Надеюсь не будет /del и так далее, ведь я реально по тратил на это 1час. P.S. Вторая моя тема на югейме
Cделано читом: SpookyClient.fun(noad)
Автор произведения: Rastyshka1337 AKA defByrniy
SS:
О великий Rastyshka спасибо тебе!!!:
package SpookyRecode.functions.impl.render;
import SpookyRecode.Spooky;
import SpookyRecode.events.EventDisplay;
import SpookyRecode.events.EventKey;
import SpookyRecode.events.EventMouseButtonPress;
import SpookyRecode.events.EventTarget;
import SpookyRecode.events.EventUpdate;
import net.minecraft.network.play.client.CHeldItemChangePacket;
import net.minecraft.network.play.client.CPlayerTryUseItemPacket;
import net.minecraft.util.Hand;
import SpookyRecode.functions.api.Category;
import SpookyRecode.functions.api.Function;
import SpookyRecode.functions.api.FunctionRegister;
import SpookyRecode.functions.settings.impl.BindSetting;
import SpookyRecode.functions.settings.impl.BooleanSetting;
import SpookyRecode.ui.display.ElementRenderer;
import SpookyRecode.utils.client.KeyStorage;
import SpookyRecode.utils.drag.Dragging;
import SpookyRecode.utils.render.DisplayUtils;
import SpookyRecode.utils.render.font.Fonts;
import com.mojang.blaze3d.matrix.MatrixStack;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import java.util.*;
/*
Данный код сделан Rastyshka1337 by SpookyClient.fun
*/
@FunctionRegister(
name = "FTItemRender",
description = "Отображает предметы с привязками клавиш",
type = Category.Render,
key = 0
)
public class FTItemRender extends Function implements ElementRenderer {
private final Dragging dragging;
private float width;
private float height;
private static final float alphaSpeed = 10.0F;
private float currentAlpha = 0.0F;
private static final List<FunItemType> FUN_ITEM_TYPES;
// ТЕСТ: Переменные для тестового кулдауна
private long testCooldownStartTime = 0;
private boolean testCooldownActive = false;
// Настройки для привязок клавиш
public BindSetting disorientationKey = new BindSetting("Дезориентация", -1);
public BindSetting trapKey = new BindSetting("Трапка", -1);
public BindSetting blatantKey = new BindSetting("Явная пыль", -1);
public BindSetting snegKey = new BindSetting("Снежок", -1);
public BindSetting plastKey = new BindSetting("Пласт", -1);
public BindSetting auraKey = new BindSetting("Божья аура", -1);
public BindSetting chorusKey = new BindSetting("Хорус", -1);
public BindSetting enderPearlKey = new BindSetting("Эндержемчуг", -1);
public BooleanSetting showOnlyBound = new BooleanSetting("Показывать только привязанные", false);
public BooleanSetting showBackground = new BooleanSetting("Показывать фон", true);
public BooleanSetting showKeyBinds = new BooleanSetting("Показывать клавиши", true);
public BooleanSetting showCooldowns = new BooleanSetting("Показывать кулдауны", true);
public FTItemRender() {
this.dragging = Dick.getInstance().createDrag(this, "FTItemRender", 10.0F, 10.0F);
this.addSettings(
disorientationKey,
trapKey,
blatantKey,
snegKey,
plastKey,
auraKey,
chorusKey,
enderPearlKey,
showOnlyBound,
showBackground,
showKeyBinds,
showCooldowns
);
}
@EventTarget
private void onDisplay(EventDisplay e) {
if (e.getType() == EventDisplay.Type.POST) {
render(e);
}
}
@EventTarget
private void onUpdate(EventUpdate e) {
// ТЕСТ: Обработка тестового кулдауна
if (mc.isSingleplayer() && testCooldownActive) {
long currentTime = System.currentTimeMillis();
long elapsedTime = currentTime - testCooldownStartTime;
// Если прошло 60 секунд, завершаем кулдаун
if (elapsedTime >= 60000) { // 60 секунд = 60000 миллисекунд
testCooldownActive = false;
}
}
// ТЕСТ: Активация кулдауна по нажатию клавиши Z
// if (mc.isSingleplayer() && mc.gameSettings.keyBindSneak.isKeyDown()) {
// activateTestCooldown();
// }
}
@EventTarget
private void onKey(EventKey e) {
if (mc.player == null || mc.world == null) return;
int key = e.getKey();
Item targetItem = null;
// Проверяем бинды для всех предметов
if (key == (Integer) disorientationKey.get()) targetItem = Items.ENDER_EYE;
if (key == (Integer) trapKey.get()) targetItem = Items.NETHERITE_SCRAP;
if (key == (Integer) blatantKey.get()) targetItem = Items.SUGAR;
if (key == (Integer) snegKey.get()) targetItem = Items.SNOWBALL;
if (key == (Integer) plastKey.get()) targetItem = Items.DRIED_KELP;
if (key == (Integer) auraKey.get()) targetItem = Items.PHANTOM_MEMBRANE;
if (key == (Integer) chorusKey.get()) targetItem = Items.CHORUS_FRUIT;
if (key == (Integer) enderPearlKey.get()) targetItem = Items.ENDER_PEARL;
if (targetItem == null) return;
// Try fast select in hotbar first
int hotbarSlot = -1;
for (int i = 0; i < 9; i++) {
ItemStack stack = mc.player.inventory.getStackInSlot(i);
if (!stack.isEmpty() && stack.getItem() == targetItem) {
hotbarSlot = i;
break;
}
}
if (hotbarSlot != -1) {
int prev = mc.player.inventory.currentItem;
// switch to slot (client + server), then use
mc.player.inventory.currentItem = hotbarSlot;
mc.player.connection.sendPacket(new CHeldItemChangePacket(hotbarSlot));
mc.player.connection.sendPacket(new CPlayerTryUseItemPacket(Hand.MAIN_HAND));
mc.player.swingArm(Hand.MAIN_HAND);
// switch back
mc.player.inventory.currentItem = prev;
mc.player.connection.sendPacket(new CHeldItemChangePacket(prev));
return;
}
// Not in hotbar: pick from inventory (9..35) into hand and use
for (int i = 9; i < 36; i++) {
ItemStack stack = mc.player.inventory.getStackInSlot(i);
if (!stack.isEmpty() && stack.getItem() == targetItem) {
// Pick item from inventory into current hotbar slot, then use
mc.playerController.pickItem(i);
mc.player.connection.sendPacket(new CPlayerTryUseItemPacket(Hand.MAIN_HAND));
mc.player.swingArm(Hand.MAIN_HAND);
break;
}
}
}
@Override
public void render(EventDisplay eventDisplay) {
if (mc.player == null) return;
MatrixStack ms = eventDisplay.getMatrixStack();
float posX = dragging.getX();
float posY = dragging.getY();
float iconSize = 16.0F;
float padding = 4.0F;
float itemSpacing = 2.0F;
float keyFontSize = 10.0F;
List<FunItem> visibleItems = getVisibleItemsFromInventory();
if (visibleItems.isEmpty()) return;
// Размеры как на скриншоте
float itemBoxWidth = 36.0F; // Шире для центрирования букв
float itemBoxHeight = 20.0F; // Компактная высота
this.width = visibleItems.size() * (itemBoxWidth + itemSpacing) - itemSpacing;
this.height = itemBoxHeight;
dragging.setWidth(this.width);
dragging.setHeight(this.height);
float currentX = posX;
int backgroundColor = 0x80000000; // Полупрозрачный черный фон
int textColor = 0xFFFFFFFF; // Белый цвет текста
for (FunItem item : visibleItems) {
// Рисуем белую обводку (сначала, чтобы она была под фоном)
DisplayUtils.drawRoundedRect(currentX - 0.5f, posY - 0.5f, itemBoxWidth + 1.0f, itemBoxHeight + 1.0f, 4.5f, 1.0f, 0xFFFFFFFF);
// Рисуем фон для предмета с закругленными углами (поверх обводки)
DisplayUtils.drawRoundedRect(currentX, posY, itemBoxWidth, itemBoxHeight, 4.0f, 1.0f, backgroundColor);
// Рендерим иконку предмета слева
float iconX = currentX + 2.0F;
float iconY = posY + 2.0F;
mc.getItemRenderer().renderItemAndEffectIntoGUI(item.itemStack, (int) iconX, (int) iconY);
// Определяем, что показывать: кулдаун или бинд
String displayText = "-";
int displayColor = textColor;
boolean showCooldown = false;
if (showCooldowns.get() && hasCooldown(item.itemStack.getItem())) {
// Показываем кулдаун
String cooldownText = getCooldownText(item.itemStack.getItem());
if (cooldownText != null) {
displayText = cooldownText;
displayColor = 0xFFFF0000; // Красный цвет для кулдауна
showCooldown = true;
}
} else if (showKeyBinds.get()) {
// Показываем бинд
BindSetting bindSetting = getBindSettingForItem(item.itemType);
if (bindSetting != null) {
int keyCode = (Integer) bindSetting.get();
displayText = keyCode == -1 ? "-" : KeyStorage.getKey(keyCode);
}
}
// Рендерим текст
if (showCooldown) {
// Кулдаун под иконкой предмета с градиентом от красного к зеленому
float cooldown = getItemCooldown(item.itemStack.getItem());
float progress = cooldown / 60.0f; // Прогресс от 1.0 (начало) до 0.0 (конец)
progress = Math.max(0.0f, Math.min(1.0f, progress)); // Ограничиваем от 0 до 1
// Интерполяция цвета от красного к зеленому
int red = (int)(255 * progress); // От 255 до 0
int green = (int)(255 * (1.0f - progress)); // От 0 до 255
int cooldownColor = 0xFF000000 | (red << 16) | (green << 8); // RGB
float textWidth = Fonts.sfui.getWidth(displayText, keyFontSize);
float textX = currentX + (itemBoxWidth - textWidth) / 2.0F; // По центру
float textY = posY + 24.0F; // Под иконкой, сдвинуто вверх
Fonts.sfui.drawText(ms, displayText, textX, textY, cooldownColor, keyFontSize, 0.05F);
// Показываем бинд справа, если есть
if (showKeyBinds.get()) {
BindSetting bindSetting = getBindSettingForItem(item.itemType);
if (bindSetting != null) {
int keyCode = (Integer) bindSetting.get();
String bindText = keyCode == -1 ? "-" : KeyStorage.getKey(keyCode);
float bindWidth = Fonts.sfui.getWidth(bindText, keyFontSize);
float bindX = currentX + itemBoxWidth - bindWidth - 4.0F;
float bindY = posY + 6.0F;
Fonts.sfui.drawText(ms, bindText, bindX, bindY, textColor, keyFontSize, 0.05F);
}
}
} else {
// Бинд справа
float textWidth = Fonts.sfui.getWidth(displayText, keyFontSize);
float textX = currentX + itemBoxWidth - textWidth - 4.0F; // Отступ от правого края
float textY = posY + 6.0F;
Fonts.sfui.drawText(ms, displayText, textX, textY, displayColor, keyFontSize, 0.05F);
}
currentX += itemBoxWidth + itemSpacing;
}
}
private List<FunItem> getVisibleItemsFromInventory() {
List<FunItem> visibleItems = new ArrayList<>();
if (mc.player == null) return visibleItems;
Set<Item> alreadyAdded = new HashSet<>();
for (int i = 0; i < mc.player.inventory.getSizeInventory(); ++i) {
ItemStack stack = mc.player.inventory.getStackInSlot(i);
if (!stack.isEmpty()) {
for (FunItemType itemType : FUN_ITEM_TYPES) {
if (stack.getItem() == itemType.item && !alreadyAdded.contains(itemType.item) && shouldShowItem(itemType, stack)) {
visibleItems.add(new FunItem(itemType.name, stack, i));
alreadyAdded.add(itemType.item);
break;
}
}
}
}
return visibleItems;
}
private boolean shouldShowItem(FunItemType itemType, ItemStack stack) {
// Показываем все найденные FT предметы, независимо от кулдауна и привязок
return true;
}
private boolean hasCooldown(Item item) {
// ТЕСТ: Для локального мира проверяем тестовый кулдаун
if (mc.isSingleplayer()) {
// Проверяем, является ли предмет одним из наших FT предметов
boolean isFTItem = FUN_ITEM_TYPES.stream()
.anyMatch(itemType -> itemType.item == item);
if (isFTItem && testCooldownActive) {
return true;
}
}
return mc.player.getCooldownTracker().hasCooldown(item);
}
private float getItemCooldown(Item item) {
// ТЕСТ: Для локального мира возвращаем оставшееся время кулдауна
if (mc.isSingleplayer()) {
// Проверяем, является ли предмет одним из наших FT предметов
boolean isFTItem = FUN_ITEM_TYPES.stream()
.anyMatch(itemType -> itemType.item == item);
if (isFTItem && testCooldownActive) {
long currentTime = System.currentTimeMillis();
long elapsedTime = currentTime - testCooldownStartTime;
float remainingTime = (60000 - elapsedTime) / 1000.0f; // Конвертируем в секунды
return Math.max(0, remainingTime);
}
}
return mc.player.getCooldownTracker().getCooldown(item, 0);
}
private String getCooldownText(Item item) {
if (!hasCooldown(item)) return null;
float cooldown = getItemCooldown(item);
if (cooldown >= 1.0f) {
return String.format("%.0fs", cooldown);
} else {
return String.format("%.1fs", cooldown);
}
}
// ТЕСТ: Метод для активации тестового кулдауна (вызывать при использовании предмета)
public void activateTestCooldown() {
if (mc.isSingleplayer()) {
testCooldownStartTime = System.currentTimeMillis();
testCooldownActive = true;
}
}
private boolean isItemBound(FunItemType itemType) {
BindSetting bindSetting = getBindSettingForItem(itemType);
return bindSetting != null && (Integer) bindSetting.get() != -1;
}
private BindSetting getBindSettingForItem(FunItemType itemType) {
return switch (itemType.name) {
case "Дезориентация" -> disorientationKey;
case "Трапка" -> trapKey;
case "Явная пыль" -> blatantKey;
case "Снежок" -> snegKey;
case "Пласт" -> plastKey;
case "Божья аура" -> auraKey;
case "Хорус" -> chorusKey;
case "Эндержемчуг" -> enderPearlKey;
default -> null;
};
}
// Вспомогательные классы
private static class FunItem {
public final String name;
public final ItemStack itemStack;
public final int slot;
public final FunItemType itemType;
public FunItem(String name, ItemStack itemStack, int slot) {
this.name = name;
this.itemStack = itemStack;
this.slot = slot;
this.itemType = FUN_ITEM_TYPES.stream()
.filter(type -> type.name.equals(name))
.findFirst()
.orElse(null);
}
}
private static class FunItemType {
public final String name;
public final Item item;
public FunItemType(String name, Item item) {
this.name = name;
this.item = item;
}
}
static {
FUN_ITEM_TYPES = Arrays.asList(
new FunItemType("Дезориентация", Items.ENDER_EYE), // Око эндера
new FunItemType("Явная пыль", Items.SUGAR), // Сахар
new FunItemType("Снежок", Items.SNOWBALL), // Снежок
new FunItemType("Пласт", Items.DRIED_KELP), // Сушёная ламинария
new FunItemType("Трапка", Items.NETHERITE_SCRAP), // Незеритовый лом
new FunItemType("Божья аура", Items.PHANTOM_MEMBRANE), // Мембрана фантома
new FunItemType("Хорус", Items.CHORUS_FRUIT), // Хорус
new FunItemType("Эндержемчуг", Items.ENDER_PEARL) // Эндержемчуг
);
}
}
Последнее редактирование:
