- Выберите загрузчик игры
- Fabric
Код:
package rich.screens.hud;
import net.minecraft.client.gui.DrawContext;
import rich.client.draggables.AbstractHudElement;
import rich.util.animations.Animation;
import rich.util.animations.Direction;
import rich.util.animations.OutBack;
import rich.util.render.Render2D;
import rich.util.render.font.Fonts;
import java.awt.*;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
public class Notifications extends AbstractHudElement {
private static Notifications instance;
public static Notifications getInstance() {
return instance;
}
private final List<NotificationEntry> notifications = new ArrayList<>();
private static final float NOTIF_HEIGHT = 30f;
private static final float NOTIF_WIDTH = 140f;
private static final float GAP = 6f;
private long lastTimeNs = System.nanoTime();
public Notifications() {
super("Notifications", 0, 0, (int) NOTIF_WIDTH, (int) NOTIF_HEIGHT, false);
instance = this;
}
@Override
public boolean visible() {
return !notifications.isEmpty();
}
@Override
public void tick() {
for (NotificationEntry entry : notifications) {
if (System.currentTimeMillis() > entry.removeTime) {
entry.anim.setDirection(Direction.BACKWARDS);
}
}
notifications.removeIf(entry -> entry.anim.isFinished(Direction.BACKWARDS));
updateTargetPositions();
}
private void updateTargetPositions() {
float offsetY = 10f;
for (NotificationEntry entry : notifications) {
entry.targetY = offsetY;
offsetY += NOTIF_HEIGHT + GAP;
}
}
private void updatePositionsWithPhysics() {
long now = System.nanoTime();
float deltaSec = (now - lastTimeNs) / 1_000_000_000f;
lastTimeNs = now;
deltaSec = Math.min(deltaSec, 0.05f);
float smooth = 3f;
float bounce = 18f;
for (NotificationEntry entry : notifications) {
float diff = entry.targetY - entry.currentY;
float accel = diff * smooth;
entry.velocityY += accel * deltaSec;
entry.velocityY *= (1f - bounce * deltaSec * 0.98f);
entry.currentY += entry.velocityY;
if (Math.abs(diff) < 0.1f && Math.abs(entry.velocityY) < 0.1f) {
entry.currentY = entry.targetY;
entry.velocityY = 0;
}
}
}
public void addNotification(String text, long durationMs) {
Animation anim = new OutBack().setMs(750).setValue(1);
anim.setDirection(Direction.FORWARDS);
long now = System.currentTimeMillis();
NotificationEntry newEntry = new NotificationEntry(
text,
anim,
now,
now + durationMs
);
notifications.add(0, newEntry);
if (notifications.size() > 8) {
notifications.remove(notifications.size() - 1);
}
notifications.sort(Comparator.comparingLong(n -> -n.startTime));
}
private int clampAlpha(int val) {
return Math.max(0, Math.min(255, val));
}
@Override
public void drawDraggable(DrawContext context, int alpha) {
//отрисовка
alpha = clampAlpha(alpha);
if (alpha <= 0) return;
float alphaF = alpha / 255f;
float screenW = mc.getWindow().getScaledWidth();
float screenH = mc.getWindow().getScaledHeight();
updatePositionsWithPhysics();
for (NotificationEntry entry : notifications) {
float animProgress = entry.anim.getOutput().floatValue();
animProgress = Math.max(0f, Math.min(1f, animProgress));
if (animProgress <= 0.01f) continue;
float width = NOTIF_WIDTH;
float height = NOTIF_HEIGHT;
float startX = screenW - (width * animProgress) - 6f;
float startY = screenH - entry.currentY - height;
int bgAlpha = clampAlpha((int) (255 * animProgress * alphaF));
int textAlpha = clampAlpha((int) (255 * animProgress * alphaF));
Render2D.gradientRect(
startX,
startY,
width,
height,
new int[]{
new Color(52, 52, 52, bgAlpha).getRGB(),
new Color(22, 22, 22, bgAlpha).getRGB(),
new Color(52, 52, 52, bgAlpha).getRGB(),
new Color(22, 22, 22, bgAlpha).getRGB()
},
5f
);
Render2D.outline(startX, startY, width, height, 1f, new Color(90, 90, 90, bgAlpha).getRGB(), 5);
Fonts.BOLD.draw(
entry.text,
startX + 40,
startY + 11,
7,
new Color(255, 255, 255, textAlpha).getRGB()
);
Fonts.BOLD.draw(
"!",
startX + 17,
startY + 3,
20,
new Color(255, 255, 255, textAlpha).getRGB()
);
}
setWidth((int) NOTIF_WIDTH);
setHeight((int) screenH);
}
public static class NotificationEntry {
String text;
Animation anim;
long startTime;
long removeTime;
float currentY;
float targetY;
float velocityY;
NotificationEntry(String text, Animation anim, long startTime, long removeTime) {
this.text = text;
this.anim = anim;
this.startTime = startTime;
this.removeTime = removeTime;
this.currentY = 0;
this.targetY = 0;
this.velocityY = 0;
}
}
}
SS:
Сделал на скорую руку нотификейшоны в "старом" стиле, никогда не нравились новые маленькие по центру экрана.
Кому надо тот сам отрисует как ему нравится т.к над дизайном я не парился