Начинающий
- Статус
- Оффлайн
- Регистрация
- 7 Мар 2025
- Сообщения
- 97
- Реакции
- 2
- Выберите загрузчик игры
- Vanilla
шрифты говно
SS -
Code -
SS -
Code -
сарделька:
package dev.sk3d.display.hud;
import dev.sk3d.common.animation.implement.Decelerate;
import dev.sk3d.common.animation.implement.EaseOut;
import dev.sk3d.features.impl.render.Hud;
import dev.sk3d.utils.display.render.post.KawaseBlur;
import dev.sk3d.utils.interactions.interact.PlayerInteractionHelper;
import dev.sk3d.utils.theme.ThemeManager;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.effect.StatusEffect;
import net.minecraft.entity.effect.StatusEffectInstance;
import net.minecraft.network.packet.s2c.play.EntityStatusEffectS2CPacket;
import net.minecraft.network.packet.s2c.play.GameJoinS2CPacket;
import net.minecraft.network.packet.s2c.play.PlayerRespawnS2CPacket;
import net.minecraft.network.packet.s2c.play.RemoveEntityStatusEffectS2CPacket;
import net.minecraft.registry.entry.RegistryEntry;
import net.minecraft.util.Formatting;
import dev.sk3d.utils.client.managers.api.draggable.AbstractDraggable;
import dev.sk3d.common.animation.Animation;
import dev.sk3d.common.animation.Direction;
import dev.sk3d.utils.display.render.font.FontRenderer;
import dev.sk3d.utils.display.render.font.Fonts;
import dev.sk3d.utils.display.render.shape.ShapeProperties;
import dev.sk3d.utils.display.color.ColorAssist;
import dev.sk3d.utils.math.calc.Calculate;
import dev.sk3d.utils.display.render.geometry.Render2D;
import dev.sk3d.events.packet.PacketEvent;
import dev.sk3d.utils.client.sound.SoundManager;
import net.minecraft.text.Text;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Random;
import net.minecraft.entity.effect.StatusEffects;
import net.minecraft.registry.Registries;
import net.minecraft.util.Identifier;
import org.joml.Vector4f;
import java.awt.*;
public class Potions extends AbstractDraggable {
private final List<Potion> list = new ArrayList<>();
private static final RegistryEntry<StatusEffect>[] NEGATIVE_EFFECTS = new RegistryEntry[] {
StatusEffects.POISON, StatusEffects.WITHER, StatusEffects.NAUSEA, StatusEffects.BLINDNESS,
StatusEffects.HUNGER, StatusEffects.SLOWNESS, StatusEffects.MINING_FATIGUE, StatusEffects.INSTANT_DAMAGE,
StatusEffects.WEAKNESS, StatusEffects.LEVITATION, StatusEffects.UNLUCK, StatusEffects.BAD_OMEN
};
private long lastEffectChange = 0;
private RegistryEntry<StatusEffect> currentRandomEffect = StatusEffects.SPEED;
private final Map<String, StatusEffectInstance> activeEffects = new HashMap<>();
private final Map<String, Boolean> warnedEffects = new HashMap<>();
public Potions() {
super("Potions", 200, 40, 80, 23, true);
this.scaleAnimation = new EaseOut().setValue(1).setMs(100);
}
@Override
public boolean visible() {
return !list.isEmpty() || PlayerInteractionHelper.isChat(mc.currentScreen);
}
@Override
public boolean mouseClicked(double mouseX, double mouseY, int button) {
if (button == 0) {
FontRenderer HAWENFont = Fonts.getSize(15, Fonts.Type.HAWEN);
float pX = getX() + getWidth() - HAWENFont.getStringWidth("p") - 8;
float pY = getY() + 9.5f;
float pWidth = HAWENFont.getStringWidth("p");
float pHeight = HAWENFont.getStringHeight("p");
if (mouseX >= pX && mouseX <= pX + pWidth && mouseY >= pY && mouseY <= pY + pHeight) {
List<String> selected = new ArrayList<>(Hud.getInstance().interfaceSettings.getSelected());
selected.remove("Potions");
Hud.getInstance().interfaceSettings.setSelected(selected);
return true;
}
}
return super.mouseClicked(mouseX, mouseY, button);
}
@Override
public void tick() {
list.removeIf(p -> p.anim.isFinished(Direction.BACKWARDS));
list.forEach(p -> p.effect.update(mc.player, null));
if (Hud.getInstance().notificationSettings.isSelected("Заканчивающемся зелье") && !PlayerInteractionHelper.nullCheck()) {
List<String> effectsToRemove = new ArrayList<>();
for (Map.Entry<String, StatusEffectInstance> entry : activeEffects.entrySet()) {
String effectKey = entry.getKey();
StatusEffectInstance trackedEffect = entry.getValue();
boolean stillActive = false;
if (mc.player != null) {
for (StatusEffectInstance activeEffect : mc.player.getStatusEffects()) {
if (activeEffect.getEffectType().getIdAsString().equals(trackedEffect.getEffectType().getIdAsString())) {
stillActive = true;
activeEffects.put(effectKey, activeEffect);
int remainingTicks = activeEffect.getDuration();
int warningTicks = 200;
boolean alreadyWarned = warnedEffects.getOrDefault(effectKey, false);
if (remainingTicks <= warningTicks && remainingTicks > 0 && !alreadyWarned) {
sendPotionEndingSoonNotification(activeEffect);
warnedEffects.put(effectKey, true);
}
if (remainingTicks > warningTicks) {
warnedEffects.remove(effectKey);
}
break;
}
}
}
if (!stillActive) {
sendPotionEndedNotification(trackedEffect);
effectsToRemove.add(effectKey);
warnedEffects.remove(effectKey);
}
}
effectsToRemove.forEach(activeEffects::remove);
}
if (list.isEmpty() && PlayerInteractionHelper.isChat(mc.currentScreen)) {
long currentTime = System.currentTimeMillis();
if (currentTime - lastEffectChange >= 1000) {
List<RegistryEntry<StatusEffect>> effects = new ArrayList<>();
for (Identifier id : Registries.STATUS_EFFECT.getIds()) {
Registries.STATUS_EFFECT.getEntry(id).ifPresent(effects::add);
}
if (!effects.isEmpty()) {
currentRandomEffect = effects.get(new Random().nextInt(effects.size()));
lastEffectChange = currentTime;
}
}
}
}
@Override
public void packet(PacketEvent e) {
switch (e.getPacket()) {
case EntityStatusEffectS2CPacket effect -> {
if (!PlayerInteractionHelper.nullCheck() && effect.getEntityId() == Objects.requireNonNull(mc.player).getId()) {
RegistryEntry<StatusEffect> effectId = effect.getEffectId();
String effectKey = effectId.getIdAsString();
boolean isNewEffect = !activeEffects.containsKey(effectKey);
list.stream().filter(p -> p.effect.getEffectType().getIdAsString().equals(effectKey)).forEach(s -> s.anim.setDirection(Direction.BACKWARDS));
StatusEffectInstance newEffect = new StatusEffectInstance(effectId, effect.getDuration(), effect.getAmplifier(), effect.isAmbient(), effect.shouldShowParticles(), effect.shouldShowIcon());
list.add(new Potion(newEffect, new Decelerate().setMs(150).setValue(1.0F)));
activeEffects.put(effectKey, newEffect);
if (isNewEffect && Hud.getInstance().notificationSettings.isSelected("Полученном зелье")) {
sendPotionReceivedNotification(newEffect);
}
}
}
case RemoveEntityStatusEffectS2CPacket effect -> {
String effectKey = effect.effect().getIdAsString();
list.stream().filter(s -> s.effect.getEffectType().getIdAsString().equals(effectKey)).forEach(s -> s.anim.setDirection(Direction.BACKWARDS));
StatusEffectInstance removedEffect = activeEffects.remove(effectKey);
if (removedEffect != null && Hud.getInstance().notificationSettings.isSelected("Заканчивающемся зелье")) {
sendPotionEndedNotification(removedEffect);
}
warnedEffects.remove(effectKey);
}
case PlayerRespawnS2CPacket p -> {
list.clear();
activeEffects.clear();
warnedEffects.clear();
}
case GameJoinS2CPacket p -> {
list.clear();
activeEffects.clear();
warnedEffects.clear();
}
default -> {}
}
}
@Override
public void drawDraggable(DrawContext context) {
MatrixStack matrix = context.getMatrices();
FontRenderer fontName = Fonts.getSize(13, Fonts.Type.SuisseIntlSemiBold);
FontRenderer fontLevel = Fonts.getSize(12, Fonts.Type.BOLD);
FontRenderer fontTime = Fonts.getSize(12, Fonts.Type.MontserratBlack);
float iconSize = 16f;
float iconPadding = 3f;
float spacing = 3f;
float panelHeight = 25f;
float currentY = getY();
float maxWidth = 0;
float timeBoxWidth = 28f;
if (list.isEmpty() && PlayerInteractionHelper.isChat(mc.currentScreen)) {
float namePanelWidth = calculateNamePanelWidth("Example", "lvl 1", fontName, fontLevel);
float totalWidth = iconPadding + iconSize + 3f + namePanelWidth + 3f + timeBoxWidth + 4f;
drawPotionPanel(matrix, getX(), currentY, totalWidth, panelHeight, iconSize, iconPadding,
currentRandomEffect, "Example", "lvl 1", "**:**", 1.0f, fontName, fontLevel, fontTime, false, namePanelWidth, timeBoxWidth);
setWidth((int) totalWidth);
setHeight((int) panelHeight);
} else {
int visibleCount = 0;
for (Potion potion : list) {
StatusEffectInstance effect = potion.effect;
float animation = potion.anim.getOutput().floatValue();
if (animation > 0.01f) {
int amplifier = effect.getAmplifier();
String name = effect.getEffectType().value().getName().getString();
String duration = getDuration(effect);
String level = amplifier > 0 ? "lvl " + (amplifier + 1) : "lvl 1";
boolean isBad = isBadEffect(effect.getEffectType());
float namePanelWidth = calculateNamePanelWidth(name, level, fontName, fontLevel);
float totalWidth = iconPadding + iconSize + 3f + namePanelWidth + 3f + timeBoxWidth + 4f;
maxWidth = Math.max(maxWidth, totalWidth);
drawPotionPanel(matrix, getX(), currentY, totalWidth, panelHeight, iconSize, iconPadding,
effect.getEffectType(), name, level, duration, animation, fontName, fontLevel, fontTime, isBad, namePanelWidth, timeBoxWidth);
currentY += (panelHeight + spacing) * animation;
visibleCount++;
}
}
setWidth((int) maxWidth);
setHeight((int) (visibleCount * (panelHeight + spacing) - spacing));
}
}
private float calculateNamePanelWidth(String name, String level, FontRenderer fontName, FontRenderer fontLevel) {
float nameWidth = fontName.getStringWidth(name);
float levelWidth = fontLevel.getStringWidth(level);
float minWidth = 62f;
float calculatedWidth = 10f + nameWidth + 6f + levelWidth + 10f;
return Math.max(minWidth, calculatedWidth);
}
private void drawPotionPanel(MatrixStack matrix, float x, float y, float width, float height,
float iconSize, float iconPadding, RegistryEntry<StatusEffect> effectType,
String name, String level, String duration, float animation,
FontRenderer fontName, FontRenderer fontLevel, FontRenderer fontTime, boolean isBad,
float namePanelWidth, float timeBoxWidth) {
float centerX = x + width / 2f;
float centerY = y + height / 2f;
Calculate.scale(matrix, centerX, centerY, animation, animation, () -> {
if (Hud.blur.isValue()) {
Render2D.rectangleWithMask(matrix.peek().getPositionMatrix(), x, y, width, height, 5f, 0,
KawaseBlur.INSTANCE.fbos.getFirst().getColorAttachment());
}
rectangle.render(ShapeProperties.create(matrix, x, y, width, height)
.round(5f)
.color(ThemeManager.BackgroundGui.getColor())
.build());
float iconX = x + iconPadding;
float iconY = y + (height - iconSize) / 2f;
rectangle.render(ShapeProperties.create(matrix, iconX, iconY, iconSize, iconSize)
.round(new Vector4f(3f, 3f, 5f, 5f))
.color(ThemeManager.BackgroundSettings.getColor())
.build());
Render2D.drawSprite(matrix, mc.getStatusEffectSpriteManager().getSprite(effectType),
iconX + 3.5f, iconY + 3.5f, 9, 9, -1);
float timeBoxHeight = 16f;
float timeBoxX = x + width - timeBoxWidth - 4f;
float timeBoxY = y + (height - timeBoxHeight) / 2f;
rectangle.render(ShapeProperties.create(matrix, timeBoxX, timeBoxY, timeBoxWidth, timeBoxHeight)
.round(new Vector4f(5f, 5f, 3f, 3f))
.color(ThemeManager.BackgroundSettings.getColor())
.build());
float timeWidth = fontTime.getStringWidth(duration);
int timeColor = ThemeManager.textColor.getColor();
float timeTextHeight = fontTime.getStringHeight(duration);
fontTime.drawString(matrix, duration, timeBoxX + (timeBoxWidth - timeWidth) / 2f, timeBoxY + (timeBoxHeight - timeTextHeight) / 2f + 6f, timeColor);
float namePanelX = iconX + iconSize + 3f;
float namePanelHeight = 16f;
float namePanelY = y + (height - namePanelHeight) / 2f;
rectangle.render(ShapeProperties.create(matrix, namePanelX, namePanelY, namePanelWidth, namePanelHeight)
.round(3f)
.color(ThemeManager.BackgroundSettings.getColor())
.build());
float nameWidth = fontName.getStringWidth(name);
float levelWidth = fontLevel.getStringWidth(level);
float nameTextHeight = fontName.getStringHeight(name);
float textStartX = namePanelX + 5f;
float textY = namePanelY + (namePanelHeight - nameTextHeight) / 2f + 6f;
int nameColor = isBad ? new Color(255, 85, 75, 255).getRGB() : ThemeManager.textColor.getColor();
fontName.drawString(matrix, name, textStartX, textY, nameColor);
float levelX = namePanelX + namePanelWidth - levelWidth - 5f;
fontLevel.drawString(matrix, level, levelX, textY + 1f, ThemeManager.textColor.getColor());
});
}
private String getDuration(StatusEffectInstance pe) {
int var1 = pe.getDuration();
int mins = var1 / 1200;
return pe.isInfinite() || mins > 60 ? "**:**" : mins + ":" + String.format("%02d", (var1 % 1200) / 20);
}
private boolean isBadEffect(RegistryEntry<StatusEffect> effect) {
for (RegistryEntry<StatusEffect> negativeEffect : NEGATIVE_EFFECTS) {
if (effect == negativeEffect) {
return true;
}
}
return false;
}
private void sendPotionReceivedNotification(StatusEffectInstance effect) {
String effectName = effect.getEffectType().value().getName().getString();
String message = effectName + " получен!";
Notifications.getInstance().addList(Text.literal(message), 1000, SoundManager.ENABLE_MODULE, false, null, effect.getEffectType());
SoundManager.playSound(SoundManager.ENABLE_MODULE);
}
private void sendPotionEndedNotification(StatusEffectInstance effect) {
String effectName = effect.getEffectType().value().getName().getString();
String message = effectName + " закончился!";
Notifications.getInstance().addList(Text.literal(message), 1000, SoundManager.DISABLE_MODULE, false, null, effect.getEffectType());
SoundManager.playSound(SoundManager.DISABLE_MODULE);
}
private void sendPotionEndingSoonNotification(StatusEffectInstance effect) {
String effectName = effect.getEffectType().value().getName().getString();
String message = effectName + " закончится через 10 секунд!";
Notifications.getInstance().addList(Text.literal(message), 1000, null, false, null, effect.getEffectType());
}
private record Potion(StatusEffectInstance effect, Animation anim) {}
}