rewrite notifications, add chat-like notification mode (add NotificationRender)
All checks were successful
/ Build BaseBand DSM & Broadway (push) Successful in 2m0s

This commit is contained in:
Daniella / Tove 2024-06-18 07:06:20 +02:00
parent 1d0499753b
commit a8265cf0e6
Signed by: TudbuT
GPG key ID: B3CF345217F202D3
4 changed files with 188 additions and 103 deletions

View file

@ -13,6 +13,7 @@ import de.com.baseband.client.registry.Configuration;
import de.com.baseband.client.registry.Updater;
import de.com.baseband.client.util.interact.Chat;
import de.com.baseband.client.util.net.WebServiceClient;
import de.com.baseband.client.util.render.NotificationRender;
import de.com.baseband.prod.LoadHandler;
import de.tudbut.tools.Lock;
import hint.Mobf;
@ -110,7 +111,7 @@ public class BaseBand {
public static void notify(String text) {
Client c = Features.getFeature(Client.class);
if(Features.isFeatureEnabled(HUD.class) && c.notificationDest != Client.NotificationDest.Chat) {
HUD.notifs.add(new HUD.Notification(text));
HUD.notifs.add(new NotificationRender.Notification(text));
if(c.notificationDest == Client.NotificationDest.Both)
Chat.print(text);
else
@ -121,7 +122,7 @@ public class BaseBand {
public static void notifyAll(String text) {
if(Features.isFeatureEnabled(HUD.class)) {
HUD.notifs.add(new HUD.Notification(text));
HUD.notifs.add(new NotificationRender.Notification(text));
}
Chat.print(text);
}

View file

@ -12,6 +12,8 @@ import de.com.baseband.client.registry.annotation.*;
import de.com.baseband.client.util.adapt.Marker;
import de.com.baseband.client.util.data.GitHash;
import de.com.baseband.client.util.interact.ServerDataManager;
import de.com.baseband.client.util.render.GuiRenderAdapter;
import de.com.baseband.client.util.render.NotificationRender;
import de.com.baseband.client.util.render.Pixels;
import de.com.baseband.client.util.render.TextSplitter;
import de.labystudio.spotifyapi.SpotifyAPI;
@ -32,39 +34,7 @@ import java.util.*;
@Render
public class HUD extends Feature {
public static final ArrayList<Notification> notifs = new ArrayList<>();
public static class Notification {
public final String text;
private final int time;
private final long start = new Date().getTime();
public Notification(String text) {
this(text, 10000);
}
public Notification(String text, int ms) {
this.text = text;
this.time = ms;
}
public float opacity(int sensitivity) {
long elapsed = System.currentTimeMillis() - start;
float animationTime = Math.min(time / 10f, 500f);
if(elapsed < animationTime / 2) {
return elapsed / (animationTime / 2);
}
long timeLeft = (time - elapsed) / sensitivity;
if(timeLeft < animationTime) {
return timeLeft / animationTime;
}
return 1;
}
public int opacity(int n, int sensitivity) {
return Math.max(1, (int) (n * opacity(sensitivity)));
}
}
public static final ArrayList<NotificationRender.Notification> notifs = new ArrayList<>();
public static void notify(String text) {
notify(text, 10000);
@ -72,7 +42,7 @@ public class HUD extends Feature {
public static void notify(String text, int time) {
BaseBand.LOGGER.info(text);
notifs.add(new Notification(text, time));
notifs.add(new NotificationRender.Notification(text, time));
}
public enum ModuleMetaColor {
@ -88,10 +58,6 @@ public class HUD extends Feature {
Trans
}
public enum NotificationLocation {
Left, Center, Right
}
public enum InfoLocation {
TopLeft,
TopRight,
@ -113,7 +79,6 @@ public class HUD extends Feature {
@Gate(1)
public boolean showPing = true;
@Config("Show Spotify")
@Description("Shows the currently playing song of a locally running Spotify Instance.")
@Gate(1)
@ -168,13 +133,12 @@ public class HUD extends Feature {
@Config("Notification location")
@Description("Where to display notifications. Left and Right display the most recent at the top, Center displays the most recent at the bottom.")
public NotificationLocation nLocation = NotificationLocation.Left;
public NotificationRender.NotificationLocation nLocation = NotificationRender.NotificationLocation.Left;
// TODO: finish implementation
@Gate(Integer.MIN_VALUE)
@Config("Notifications like chat")
@Description("Reverses the order in which notifications are shown and shows a fixed number of notifications, in case of Left and Right location.")
public boolean revNotif = false;
@Description("Shows the notifications in the same way the chat is shown, with a given 'chat height'")
@Range("0..30")
public int chatLikeNotif = 0;
@Config("Notification size X")
@Description("How wide a notification should be. The width in pixels is this multiplied by 100.")
@ -203,10 +167,13 @@ public class HUD extends Feature {
return "HUD";
}
private NotificationRender notificationRenderer;
@Override
public void onTick() {
notificationRenderer = new NotificationRender(nLocation, nSize * 100, nVSize * 10, nVSpace, chatLikeNotif, textShadow);
for (int i = 0; i < notifs.size(); i++) {
Notification notif = notifs.get(i);
NotificationRender.Notification notif = notifs.get(i);
if(new Date().getTime() - notif.start >= notif.time) {
notifs.remove(i);
i--;
@ -267,19 +234,22 @@ public class HUD extends Feature {
}
TextSplitter.drawString(initString, 3,3, theme.getGreenColor(), textShadow, false);
int y = 3 + TextSplitter.getStringHeight(initString);
int yl = 3 + TextSplitter.getStringHeight(initString);
for (int i = 0; i < renderFeatures.length; i++) {
Feature f = renderFeatures[i];
mc.fontRenderer.drawString(f.getHUDText(), 3, y, getColor(f, i), textShadow);
y = y + mc.fontRenderer.FONT_HEIGHT;
mc.fontRenderer.drawString(f.getHUDText(), 3, yl, getColor(f, i), textShadow);
yl = yl + mc.fontRenderer.FONT_HEIGHT;
}
yl += 3;
int yr = 0;
if(infoLoc != InfoLocation.TopLeft) {
int x;
y = 3;
yr = 3;
switch (infoLoc) {
case BottomRight:
y = sr.getScaledHeight() - 3 - TextSplitter.getStringHeight(infoString);
yr = sr.getScaledHeight() - 3 - TextSplitter.getStringHeight(infoString);
case TopRight:
x = sr.getScaledWidth() - 3 - TextSplitter.getStringWidth(infoString);
break;
@ -288,59 +258,23 @@ public class HUD extends Feature {
}
if(background) {
drawSizedBox(x - 1, y - 1, TextSplitter.getStringWidth(infoString) + 2, TextSplitter.getStringHeight(infoString) + 2, Pixels.mulTransparency(theme.getBackgroundColor(), 0.5f), false);
GuiRenderAdapter.drawSizedBox(x - 1, yr - 1, TextSplitter.getStringWidth(infoString) + 2, TextSplitter.getStringHeight(infoString) + 2, Pixels.mulTransparency(theme.getBackgroundColor(), 0.5f), false);
}
TextSplitter.drawString(infoString, x, y, theme.getGreenColor(), textShadow, textMatchOrientation);
y += TextSplitter.getStringHeight(infoString);
TextSplitter.drawString(infoString, x, yr, theme.getGreenColor(), textShadow, textMatchOrientation);
yr += TextSplitter.getStringHeight(infoString) + 3;
}
renderNotifications(sr, y);
renderNotifications(yl, yr);
}
// TODO: rewrite asap
private void renderNotifications(ScaledResolution sr, int y) {
int dir = (nLocation == NotificationLocation.Center ? -1 : 1);
int isCenter = (nLocation == NotificationLocation.Center ? 1 : 0);
int xSize = this.nSize * 100;
int ySize = this.nVSize * 10;
int textOffset = (ySize / 2 - (mc.fontRenderer.FONT_HEIGHT / 2));
int x = 2;
if(nLocation == NotificationLocation.Center) {
x = sr.getScaledWidth() / 2 - (xSize / 2);
y = sr.getScaledHeight() / 4;
} else {
if(nLocation == NotificationLocation.Right) {
if(!(showInfo && infoLoc == InfoLocation.TopRight))
y = -5;
x = sr.getScaledWidth() - x - xSize;
}
y += 5;
y += nVSpace;
}
Notification[] notifs = HUD.notifs.toArray(new Notification[0]);
int i;
if(revNotif)
i = 0;
else
i = notifs.length - 1;
while (i >= 0 && i < notifs.length) {
Notification notif = notifs[i];
int localYSize = ySize;
String text = TextSplitter.breakText(notif.text, xSize - textOffset * 2);
localYSize += TextSplitter.getStringHeight(text) - mc.fontRenderer.FONT_HEIGHT;
int textboxYSize = localYSize;
localYSize = notif.opacity(localYSize, 1);
drawSizedBox(x, y, xSize, localYSize, 0x202040 + (notif.opacity(0x80, 1) << 24), isCenter == 1);
GlStateManager.enableBlend();
TextSplitter.drawString(text, x + textOffset, y + textOffset - isCenter * textboxYSize, 0xffffff + (Math.max(8, notif.opacity(0xff, 2)) << 24), notif.opacity(2) == 1.0 && textShadow, false);
GlStateManager.disableBlend();
y += (localYSize + nVSpace) * dir;
i += revNotif ? 1 : -1;
private void renderNotifications(int yl, int yr) {
if(notificationRenderer == null)
return;
int y = nLocation == NotificationRender.NotificationLocation.Left ? yl : yr;
notificationRenderer.begin(infoLoc == InfoLocation.BottomRight ? 2 : y);
for (int i = notifs.size() - 1; i >= 0; i--) {
notificationRenderer.renderNotification(notifs.get(i));
}
}
@ -385,10 +319,6 @@ public class HUD extends Feature {
return 0xFF000000 | (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF);
}
private void drawSizedBox(int x, int y, int sx, int sy, int color, boolean backwards) {
Gui.drawRect(x, y, x + sx, y + sy * (backwards ? -1 : 1), color);
}
private void drawStringCentered(String s, int x, int y, int color, boolean shadow) {
TextSplitter.drawString(s, x - TextSplitter.getStringWidth(s), y, color, shadow, false);
}

View file

@ -0,0 +1,10 @@
package de.com.baseband.client.util.render;
import net.minecraft.client.gui.Gui;
public class GuiRenderAdapter {
public static void drawSizedBox(int x, int y, int sx, int sy, int color, boolean backwards) {
Gui.drawRect(x, y, x + sx, y + sy * (backwards ? -1 : 1), color);
}
}

View file

@ -0,0 +1,144 @@
package de.com.baseband.client.util.render;
import net.minecraft.client.gui.Gui;
import net.minecraft.client.gui.ScaledResolution;
import net.minecraft.client.renderer.GlStateManager;
import java.util.Date;
import static de.com.baseband.client.BaseBand.mc;
public class NotificationRender {
private final NotificationLocation nLocation;
private final int xSize;
private final int ySize;
private final int ySpace;
private final boolean chatLike;
private final int chatLikeSize;
private final int padding;
private final boolean textShadow;
private ScaledResolution sr;
private int startY = 0;
private int endY = 0;
private int x, y;
public NotificationRender(NotificationLocation nLocation, int xSize, int ySize, int ySpace, int chatLikeSize, boolean textShadow) {
this.nLocation = nLocation;
this.xSize = xSize;
this.ySize = ySize;
this.ySpace = ySpace;
this.chatLike = chatLikeSize != 0;
this.chatLikeSize = chatLikeSize;
this.textShadow = textShadow;
padding = (ySize / 2 - (mc.fontRenderer.FONT_HEIGHT / 2));
}
public void begin(int y) {
sr = new ScaledResolution(mc);
switch (nLocation) {
case Left:
this.x = 2;
this.y = y;
break;
case Center:
this.x = sr.getScaledWidth() / 2 - xSize / 2;
this.y = 2;
break;
case Right:
this.x = sr.getScaledWidth() - 2 - xSize;
this.y = y;
break;
default:
throw new IllegalStateException("NotificationLocation " + nLocation.ordinal() + " not implemented");
}
this.startY = this.y;
this.y += (ySize + ySpace) * chatLikeSize;
this.endY = this.y;
}
public void renderNotification(Notification notif) {
if(startY == 0)
return;
String s = notif.text;
s = TextSplitter.breakText(s, xSize - padding * 2);
int ys = TextSplitter.getStringHeight(s) + padding * 2;
ys = notif.opacity(ys, 1);
if(chatLike) {
y -= ys + ySpace;
}
if(y < startY) {
startY = 0;
return;
}
Gui.drawRect(x, y, x + xSize, y + ys, 0x202040 + (notif.opacity(0x80, 1) << 24));
GlStateManager.enableBlend();
int textY = y + 1 + padding;
if(chatLike) {
// prevents notifications from bumping into eachother
textY = Math.min(textY, y + ys - 9);
}
TextSplitter.drawString(s, x + 1 + padding, textY, 0xffffff + (Math.max(8, notif.opacity(0xff, 3)) << 24), notif.opacity(3) == 1.0 && textShadow, false);
GlStateManager.disableBlend();
if(!chatLike) {
y += ys + ySpace;
endY = y;
}
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getEndY() {
return endY;
}
public enum NotificationLocation {
Left, Center, Right
}
public static class Notification {
public final String text;
public final int time;
public final long start = new Date().getTime();
public Notification(String text) {
this(text, 10000);
}
public Notification(String text, int ms) {
this.text = text;
this.time = ms;
}
public float opacity(int sensitivity) {
long elapsed = System.currentTimeMillis() - start;
float animationTime = Math.min(time / 10f, 500f);
if(elapsed < animationTime / 2) {
return elapsed / (animationTime / 2);
}
long timeLeft = (time - elapsed) / sensitivity;
if(timeLeft < animationTime) {
return timeLeft / animationTime;
}
return 1;
}
public int opacity(int n, int sensitivity) {
return Math.max(1, (int) (n * opacity(sensitivity)));
}
}
}