diff --git a/src/main/java/net/shadow/client/feature/command/impl/Find.java b/src/main/java/net/shadow/client/feature/command/impl/Find.java
index d2dba38..7e7ef46 100644
--- a/src/main/java/net/shadow/client/feature/command/impl/Find.java
+++ b/src/main/java/net/shadow/client/feature/command/impl/Find.java
@@ -42,7 +42,6 @@ public class Find extends Command {
 
     public Find() {
         super("Find", "Nocom 2 (requires creative)", "find", "findPlayer");
-        System.out.println("instanced");
         Events.registerEventHandlerClass(this);
     }
 
diff --git a/src/main/java/net/shadow/client/feature/command/impl/Help.java b/src/main/java/net/shadow/client/feature/command/impl/Help.java
index 3cbd783..e0dd6c5 100644
--- a/src/main/java/net/shadow/client/feature/command/impl/Help.java
+++ b/src/main/java/net/shadow/client/feature/command/impl/Help.java
@@ -44,7 +44,7 @@ public class Help extends Command {
             message("All commands and their description");
             for (Command command : CommandRegistry.getCommands()) {
                 message(command.getName() + ": " + command.getDescription());
-                message0("  " + String.join(", ", command.getAliases()), Color.GRAY);
+                message("  " + String.join(", ", command.getAliases()), Color.GRAY);
             }
         } else {
             String s = args[0];
@@ -52,8 +52,8 @@ public class Help extends Command {
             if (c == null) error("Command \"" + s + "\" was not found");
             else {
                 message("Command " + c.getName());
-                message0(c.getDescription(), Color.GRAY);
-                message0("Aliases: " + String.join(", ", c.getAliases()), Color.GRAY);
+                message(c.getDescription(), Color.GRAY);
+                message("Aliases: " + String.join(", ", c.getAliases()), Color.GRAY);
                 message("");
                 ExamplesEntry e = c.getExampleArguments();
                 if (e == null) {
diff --git a/src/main/java/net/shadow/client/feature/command/impl/OnlineAPI.java b/src/main/java/net/shadow/client/feature/command/impl/OnlineAPI.java
index 240eeac..82f4764 100644
--- a/src/main/java/net/shadow/client/feature/command/impl/OnlineAPI.java
+++ b/src/main/java/net/shadow/client/feature/command/impl/OnlineAPI.java
@@ -16,6 +16,7 @@ import net.shadow.client.helper.ShadowAPIWrapper;
 import net.shadow.client.helper.event.EventType;
 import net.shadow.client.helper.event.Events;
 import org.apache.commons.io.FileUtils;
+import org.apache.logging.log4j.Level;
 
 import java.io.File;
 import java.nio.charset.StandardCharsets;
@@ -45,13 +46,13 @@ public class OnlineAPI extends Command {
                 String session = FileUtils.readFileToString(SESSION_KEY_FILE, StandardCharsets.UTF_8);
                 if (!session.isEmpty()) {
                     if (ShadowAPIWrapper.loginWithKey(session)) {
-                        System.out.println("recovered previous session from backup file");
+                        ShadowMain.log(Level.INFO, "recovered previous session from backup file");
                     } else {
-                        System.out.println("server said no to session recovery, moving on");
+                        ShadowMain.log(Level.INFO, "server said no to session recovery, moving on");
                     }
                 }
             } catch (Exception e) {
-                System.out.println("failed to recover session :(");
+                ShadowMain.log(Level.ERROR, "failed to recover session :(");
                 e.printStackTrace();
             }
         }
diff --git a/src/main/java/net/shadow/client/feature/command/impl/SocketKick.java b/src/main/java/net/shadow/client/feature/command/impl/SocketKick.java
index 19a9e07..9c77baf 100644
--- a/src/main/java/net/shadow/client/feature/command/impl/SocketKick.java
+++ b/src/main/java/net/shadow/client/feature/command/impl/SocketKick.java
@@ -4,7 +4,7 @@
 
 package net.shadow.client.feature.command.impl;
 
-import net.minecraft.client.network.PlayerListEntry;
+import com.mojang.authlib.GameProfile;
 import net.minecraft.entity.player.PlayerEntity;
 import net.minecraft.network.ClientConnection;
 import net.minecraft.network.NetworkState;
@@ -20,7 +20,6 @@ import net.minecraft.text.Text;
 import net.shadow.client.ShadowMain;
 import net.shadow.client.feature.command.Command;
 import net.shadow.client.feature.command.argument.PlayerFromNameArgumentParser;
-import net.shadow.client.feature.command.argument.StreamlineArgumentParser;
 import net.shadow.client.feature.command.coloring.ArgumentType;
 import net.shadow.client.feature.command.coloring.PossibleArgument;
 import net.shadow.client.feature.command.coloring.StaticArgumentServer;
@@ -30,8 +29,6 @@ import net.shadow.client.feature.command.exception.CommandException;
 import java.net.InetSocketAddress;
 import java.util.Objects;
 
-import com.mojang.authlib.GameProfile;
-
 public class SocketKick extends Command {
     public SocketKick() {
         super("SocketKick", "Kicks people out of the server using sockets!!", "socketkick", "skick", "sockkick");
diff --git a/src/main/java/net/shadow/client/feature/gui/notifications/hudNotif/HudNotification.java b/src/main/java/net/shadow/client/feature/gui/notifications/hudNotif/HudNotification.java
new file mode 100644
index 0000000..c51c170
--- /dev/null
+++ b/src/main/java/net/shadow/client/feature/gui/notifications/hudNotif/HudNotification.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) Shadow client, 0x150, Saturn5VFive 2022. All rights reserved.
+ */
+
+package net.shadow.client.feature.gui.notifications.hudNotif;
+
+import com.mojang.blaze3d.systems.RenderSystem;
+import lombok.AccessLevel;
+import lombok.RequiredArgsConstructor;
+import net.minecraft.client.util.math.MatrixStack;
+import net.minecraft.util.math.MathHelper;
+import net.minecraft.util.math.Quaternion;
+import net.shadow.client.helper.GameTexture;
+import net.shadow.client.helper.Texture;
+import net.shadow.client.helper.font.FontRenderers;
+import net.shadow.client.helper.font.adapter.FontAdapter;
+import net.shadow.client.helper.render.ClipStack;
+import net.shadow.client.helper.render.Rectangle;
+import net.shadow.client.helper.render.Renderer;
+
+import java.awt.Color;
+
+@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+public class HudNotification {
+    final String content;
+    final long duration;
+    final Type type;
+    long creation = System.currentTimeMillis();
+    double texDim = 16;
+    double pad = 2;
+    long fadeTime = 1200;
+
+    public static HudNotification create(String content, long duration, Type type) {
+        HudNotification n = new HudNotification(content, duration, type);
+        HudNotificationRenderer.instance.addNotification(n);
+        return n;
+    }
+
+    public long getRemainingLifeTime() {
+        return Math.max(0, (creation + duration) - System.currentTimeMillis());
+    }
+
+    public boolean isDead() {
+        return getRemainingLifeTime() == 0;
+    }
+
+    public double getHeight() {
+        return pad + Math.max(FontRenderers.getRenderer().getFontHeight(), texDim) + pad;
+    }
+
+    public double easeInOutBack(double x) {
+        double c1 = 1.70158;
+        double c2 = c1 * 1.525;
+
+        return x < 0.5
+                ? (Math.pow(2 * x, 2) * ((c2 + 1) * 2 * x - c2)) / 2
+                : (Math.pow(2 * x - 2, 2) * ((c2 + 1) * (x * 2 - 2) + c2) + 2) / 2;
+
+    }
+
+    double getAnimProg() {
+        long remainingLife = getRemainingLifeTime();
+        long timeExpired = duration - remainingLife;
+        double animAccordingToTime = (double) Math.min(timeExpired, fadeTime) / fadeTime;
+        double animAccordingToRemaining = (double) Math.min(remainingLife, fadeTime) / fadeTime;
+        return Math.min(animAccordingToRemaining, animAccordingToTime) * 1.1;
+    }
+
+    public void render(MatrixStack stack, double x, double y) {
+        FontAdapter fa = FontRenderers.getRenderer();
+        double anim = getAnimProg();
+        double moveAnim = easeInOutBack(MathHelper.clamp(anim, 0, 0.5) * 2);
+        double expandAnim = easeInOutBack(MathHelper.clamp(anim, 0.1, 1.1) - .1);
+
+        double notifWidthWithText = Math.max(pad + fa.getStringWidth(content) + pad + texDim + pad, 100);
+        double notifWidthWithoutText = pad + texDim + pad;
+        double notifWidth = MathHelper.lerp(Math.max(expandAnim, 0), notifWidthWithoutText, notifWidthWithText);
+        double notifHeight = getHeight();
+        double rootX = x - notifWidth;
+        double rootY = MathHelper.lerp(moveAnim, -notifHeight, y);
+        Renderer.R2D.renderRoundedQuadWithShadow(stack, new Color(10, 10, 20), rootX, rootY, rootX + notifWidth, rootY + notifHeight, 3, 20);
+        RenderSystem.setShaderTexture(0, type.i);
+        RenderSystem.setShaderColor(1f, 1f, 1f, 1f);
+        stack.push();
+        stack.translate(rootX + notifWidth - pad - texDim + texDim / 2d, rootY + pad + texDim / 2d, 0);
+        stack.multiply(new Quaternion(0f, 0f, (float) (expandAnim * 360f), true));
+        Renderer.R2D.renderTexture(stack, -texDim / 2d, -texDim / 2d, texDim, texDim, 0, 0, texDim, texDim, texDim, texDim);
+        stack.pop();
+        ClipStack.globalInstance.addWindow(stack, new Rectangle(rootX + pad, rootY, rootX + notifWidth - pad - texDim - pad, rootY + notifHeight));
+        fa.drawString(stack, content, rootX + pad, rootY + notifHeight / 2d - fa.getFontHeight() / 2d, 0xFFFFFF);
+        ClipStack.globalInstance.popWindow();
+    }
+
+    public enum Type {
+        SUCCESS(GameTexture.NOTIF_SUCCESS.getWhere(), new Color(58, 223, 118)), INFO(GameTexture.NOTIF_INFO.getWhere(), new Color(39, 186, 253)),
+        WARNING(GameTexture.NOTIF_WARNING.getWhere(), new Color(255, 189, 17)), ERROR(GameTexture.NOTIF_ERROR.getWhere(), new Color(254, 92, 92));
+        final Color c;
+        final Texture i;
+
+        Type(Texture icon, Color color) {
+            this.i = icon;
+            this.c = color;
+        }
+
+        public Texture getI() {
+            return i;
+        }
+
+        public Color getC() {
+            return c;
+        }
+    }
+}
diff --git a/src/main/java/net/shadow/client/feature/gui/notifications/hudNotif/HudNotificationRenderer.java b/src/main/java/net/shadow/client/feature/gui/notifications/hudNotif/HudNotificationRenderer.java
new file mode 100644
index 0000000..4f4ace4
--- /dev/null
+++ b/src/main/java/net/shadow/client/feature/gui/notifications/hudNotif/HudNotificationRenderer.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) Shadow client, 0x150, Saturn5VFive 2022. All rights reserved.
+ */
+
+package net.shadow.client.feature.gui.notifications.hudNotif;
+
+import net.minecraft.client.util.math.MatrixStack;
+import net.minecraft.util.math.MathHelper;
+import net.shadow.client.ShadowMain;
+import net.shadow.client.helper.render.MSAAFramebuffer;
+
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+public class HudNotificationRenderer {
+    public static final HudNotificationRenderer instance = new HudNotificationRenderer();
+    List<HudNotification> notifs = new CopyOnWriteArrayList<>();
+
+    void addNotification(HudNotification notif) {
+        this.notifs.add(notif);
+    }
+
+    public void render(MatrixStack stack) {
+        notifs.removeIf(HudNotification::isDead);
+        double x = ShadowMain.client.getWindow().getScaledWidth() - 5;
+        final double[] y = {5};
+        MSAAFramebuffer.use(MSAAFramebuffer.MAX_SAMPLES, () -> {
+            for (HudNotification notif : notifs) {
+                notif.render(stack, x, y[0]);
+
+                double moveAnim = MathHelper.clamp(notif.easeInOutBack(MathHelper.clamp(notif.getAnimProg(), 0, 0.5) * 2), 0, 1);
+                y[0] += (notif.getHeight() + 5) * moveAnim;
+            }
+        });
+    }
+}
diff --git a/src/main/java/net/shadow/client/feature/gui/screen/AltManagerScreen.java b/src/main/java/net/shadow/client/feature/gui/screen/AltManagerScreen.java
index 8d28189..3b094e9 100644
--- a/src/main/java/net/shadow/client/feature/gui/screen/AltManagerScreen.java
+++ b/src/main/java/net/shadow/client/feature/gui/screen/AltManagerScreen.java
@@ -15,14 +15,13 @@ import me.x150.authlib.login.mojang.profile.MinecraftProfile;
 import net.minecraft.client.gui.Element;
 import net.minecraft.client.gui.screen.Screen;
 import net.minecraft.client.render.GameRenderer;
-import net.minecraft.client.texture.NativeImage;
-import net.minecraft.client.texture.NativeImageBackedTexture;
 import net.minecraft.client.util.DefaultSkinHelper;
 import net.minecraft.client.util.Session;
 import net.minecraft.client.util.math.MatrixStack;
 import net.minecraft.util.math.MathHelper;
 import net.shadow.client.ShadowMain;
 import net.shadow.client.feature.gui.FastTickable;
+import net.shadow.client.feature.gui.notifications.hudNotif.HudNotification;
 import net.shadow.client.feature.gui.widget.RoundButton;
 import net.shadow.client.feature.gui.widget.RoundTextFieldWidget;
 import net.shadow.client.helper.Texture;
@@ -30,6 +29,7 @@ import net.shadow.client.helper.font.FontRenderers;
 import net.shadow.client.helper.font.adapter.FontAdapter;
 import net.shadow.client.helper.render.ClipStack;
 import net.shadow.client.helper.render.MSAAFramebuffer;
+import net.shadow.client.helper.render.PlayerHeadResolver;
 import net.shadow.client.helper.render.Rectangle;
 import net.shadow.client.helper.render.Renderer;
 import net.shadow.client.helper.util.Transitions;
@@ -37,19 +37,11 @@ import net.shadow.client.mixin.IMinecraftClientAccessor;
 import net.shadow.client.mixin.SessionAccessor;
 import org.apache.commons.io.FileUtils;
 import org.apache.logging.log4j.Level;
-import org.lwjgl.BufferUtils;
 import org.lwjgl.opengl.GL40C;
 
-import javax.imageio.ImageIO;
 import java.awt.Color;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
 import java.io.File;
-import java.net.URI;
 import java.net.http.HttpClient;
-import java.net.http.HttpRequest;
-import java.net.http.HttpResponse;
-import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -89,7 +81,7 @@ public class AltManagerScreen extends ClientScreen implements FastTickable {
     double scroll = 0;
     double scrollSmooth = 0;
     Texture currentAccountTexture = new Texture("dynamic/currentaccount");
-    boolean currentAccountTextureLoaded = false;
+    boolean currentAccountTextureLoaded = true;
 
     private AltManagerScreen() {
         super(MSAAFramebuffer.MAX_SAMPLES);
@@ -233,32 +225,7 @@ public class AltManagerScreen extends ClientScreen implements FastTickable {
     void updateCurrentAccount() {
         UUID uid = ShadowMain.client.getSession().getProfile().getId();
 
-        if (texCache.containsKey(uid)) {
-            this.currentAccountTexture = texCache.get(uid);
-            currentAccountTextureLoaded = true;
-            return;
-        }
-
-        HttpRequest hr = HttpRequest.newBuilder().uri(URI.create("https://crafatar.com/avatars/" + uid + "?overlay")).header("User-Agent", "why").build();
-        downloader.sendAsync(hr, HttpResponse.BodyHandlers.ofByteArray()).thenAccept(httpResponse -> {
-            try {
-                ByteArrayOutputStream stream = new ByteArrayOutputStream();
-                ImageIO.write(ImageIO.read(new ByteArrayInputStream(httpResponse.body())), "png", stream);
-                byte[] bytes = stream.toByteArray();
-
-                ByteBuffer data = BufferUtils.createByteBuffer(bytes.length).put(bytes);
-                data.flip();
-                NativeImage img = NativeImage.read(data);
-                NativeImageBackedTexture texture = new NativeImageBackedTexture(img);
-
-                ShadowMain.client.execute(() -> {
-                    ShadowMain.client.getTextureManager().registerTexture(currentAccountTexture, texture);
-                    currentAccountTextureLoaded = true;
-                });
-            } catch (Exception e) {
-                e.printStackTrace();
-            }
-        });
+        this.currentAccountTexture = PlayerHeadResolver.resolve(uid);
     }
 
     void login() {
@@ -270,11 +237,14 @@ public class AltManagerScreen extends ClientScreen implements FastTickable {
             this.selectedAlt.login();
             isLoggingIn.set(false);
             if (!this.selectedAlt.storage.valid) {
+                HudNotification.create("Failed to log in", 5000, HudNotification.Type.ERROR);
                 return;
             }
             Session newSession = new Session(selectedAlt.storage.cachedName, selectedAlt.storage.cachedUuid.toString(), selectedAlt.storage.accessToken, Optional.empty(), Optional.empty(), Session.AccountType.MOJANG);
             ((IMinecraftClientAccessor) ShadowMain.client).setSession(newSession);
+            HudNotification.create("Logged into account " + newSession.getUsername(), 5000, HudNotification.Type.INFO);
             updateCurrentAccount();
+
         }).start();
     }
 
@@ -916,28 +886,7 @@ public class AltManagerScreen extends ClientScreen implements FastTickable {
         }
 
         void downloadTexture() {
-            HttpRequest hr = HttpRequest.newBuilder().uri(URI.create("https://crafatar.com/avatars/" + this.storage.cachedUuid + "?overlay")).header("User-Agent", "why").build();
-            downloader.sendAsync(hr, HttpResponse.BodyHandlers.ofByteArray()).thenAccept(httpResponse -> {
-                try {
-                    ByteArrayOutputStream stream = new ByteArrayOutputStream();
-                    ImageIO.write(ImageIO.read(new ByteArrayInputStream(httpResponse.body())), "png", stream);
-                    byte[] bytes = stream.toByteArray();
-
-                    ByteBuffer data = BufferUtils.createByteBuffer(bytes.length).put(bytes);
-                    data.flip();
-                    NativeImage img = NativeImage.read(data);
-                    NativeImageBackedTexture texture = new NativeImageBackedTexture(img);
-
-                    ShadowMain.client.execute(() -> {
-                        this.tex = new Texture(("dynamic/tex_" + this.storage.cachedUuid.hashCode() + "_" + (Math.random() + "").split("\\.")[1]).toLowerCase());
-                        ShadowMain.client.getTextureManager().registerTexture(this.tex, texture);
-                        texCache.put(this.storage.cachedUuid, this.tex);
-                        texLoaded = true;
-                    });
-                } catch (Exception e) {
-                    e.printStackTrace();
-                }
-            });
+            this.tex = PlayerHeadResolver.resolve(this.storage.cachedUuid);
         }
 
         public double getHeight() {
@@ -1025,11 +974,7 @@ public class AltManagerScreen extends ClientScreen implements FastTickable {
 
             RenderSystem.blendFunc(GL40C.GL_DST_ALPHA, GL40C.GL_ONE_MINUS_DST_ALPHA);
             RenderSystem.setShaderTexture(0, tex);
-            if (texLoaded) {
-                Renderer.R2D.renderTexture(stack, originX + padding, originY + padding, texWidth, texHeight, 0, 0, 64, 64, 64, 64);
-            } else {
-                Renderer.R2D.renderTexture(stack, originX + padding, originY + padding, texWidth, texHeight, 8, 8, 8, 8, 64, 64); // default skin
-            }
+            Renderer.R2D.renderTexture(stack, originX + padding, originY + padding, texWidth, texHeight, 0, 0, 64, 64, 64, 64);
             String mail;
             if (this.storage.type != AddScreenOverlay.AccountType.CRACKED) {
                 mail = this.storage.email;
diff --git a/src/main/java/net/shadow/client/feature/gui/screen/HomeScreen.java b/src/main/java/net/shadow/client/feature/gui/screen/HomeScreen.java
index 68a8c9c..1edd7ec 100644
--- a/src/main/java/net/shadow/client/feature/gui/screen/HomeScreen.java
+++ b/src/main/java/net/shadow/client/feature/gui/screen/HomeScreen.java
@@ -12,8 +12,6 @@ import net.minecraft.client.gui.screen.option.OptionsScreen;
 import net.minecraft.client.gui.screen.world.SelectWorldScreen;
 import net.minecraft.client.realms.gui.screen.RealmsMainScreen;
 import net.minecraft.client.render.GameRenderer;
-import net.minecraft.client.texture.NativeImage;
-import net.minecraft.client.texture.NativeImageBackedTexture;
 import net.minecraft.client.util.DefaultSkinHelper;
 import net.minecraft.client.util.math.MatrixStack;
 import net.shadow.client.ShadowMain;
@@ -24,21 +22,14 @@ import net.shadow.client.helper.Texture;
 import net.shadow.client.helper.font.FontRenderers;
 import net.shadow.client.helper.font.adapter.FontAdapter;
 import net.shadow.client.helper.render.MSAAFramebuffer;
+import net.shadow.client.helper.render.PlayerHeadResolver;
 import net.shadow.client.helper.render.Renderer;
 import org.apache.commons.io.IOUtils;
-import org.lwjgl.BufferUtils;
 import org.lwjgl.opengl.GL40C;
 
-import javax.imageio.ImageIO;
 import java.awt.Color;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
 import java.io.File;
-import java.net.URI;
 import java.net.http.HttpClient;
-import java.net.http.HttpRequest;
-import java.net.http.HttpResponse;
-import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
 import java.time.Duration;
 import java.util.AbstractMap;
@@ -108,7 +99,10 @@ public class HomeScreen extends ClientScreen {
         buttonsMap.add(new AbstractMap.SimpleEntry<>("Singleplayer", () -> ShadowMain.client.setScreen(new SelectWorldScreen(this))));
         buttonsMap.add(new AbstractMap.SimpleEntry<>("Multiplayer", () -> ShadowMain.client.setScreen(new MultiplayerScreen(this))));
         buttonsMap.add(new AbstractMap.SimpleEntry<>("Realms", () -> ShadowMain.client.setScreen(new RealmsMainScreen(this))));
-        buttonsMap.add(new AbstractMap.SimpleEntry<>("Alts", () -> ShadowMain.client.setScreen(AltManagerScreen.instance())));
+        buttonsMap.add(new AbstractMap.SimpleEntry<>("Alts", () -> {
+            ShadowMain.client.setScreen(AltManagerScreen.instance());
+//            Notification.create(RandomStringUtils.randomPrint(20), RandomUtils.nextLong(4000, 7000), Notification.Type.INFO);
+        }));
         buttonsMap.add(new AbstractMap.SimpleEntry<>("Settings", () -> ShadowMain.client.setScreen(new OptionsScreen(this, ShadowMain.client.options))));
         buttonsMap.add(new AbstractMap.SimpleEntry<>("Quit", ShadowMain.client::scheduleStop));
 //        buttonsMap.add(new AbstractMap.SimpleEntry<>("reinit", this::init));
@@ -155,30 +149,9 @@ public class HomeScreen extends ClientScreen {
             return;
         }
         previousChecked = uid;
-
-        HttpRequest hr = HttpRequest.newBuilder().uri(URI.create("https://crafatar.com/avatars/" + uid + "?overlay")).header("User-Agent", "why").timeout(Duration.ofSeconds(5)).build();
-        downloader.sendAsync(hr, HttpResponse.BodyHandlers.ofByteArray()).thenAccept(httpResponse -> {
-            try {
-                ByteArrayOutputStream stream = new ByteArrayOutputStream();
-                ImageIO.write(ImageIO.read(new ByteArrayInputStream(httpResponse.body())), "png", stream);
-                byte[] bytes = stream.toByteArray();
-
-                ByteBuffer data = BufferUtils.createByteBuffer(bytes.length).put(bytes);
-                data.flip();
-                NativeImage img = NativeImage.read(data);
-//                System.out.println(img);
-                NativeImageBackedTexture texture = new NativeImageBackedTexture(img);
-
-                ShadowMain.client.execute(() -> {
-                    ShadowMain.client.getTextureManager().registerTexture(currentAccountTexture, texture);
-                    currentAccountTextureLoaded = true;
-                    callback.run();
-                });
-            } catch (Exception e) {
-                e.printStackTrace();
-                callback.run();
-            }
-        });
+        PlayerHeadResolver.resolve(uid, this.currentAccountTexture);
+        currentAccountTextureLoaded = true;
+        callback.run();
     }
 
     @Override
diff --git a/src/main/java/net/shadow/client/feature/gui/screen/OnlineServicesDashboardScreen.java b/src/main/java/net/shadow/client/feature/gui/screen/OnlineServicesDashboardScreen.java
index dd67042..7243f8d 100644
--- a/src/main/java/net/shadow/client/feature/gui/screen/OnlineServicesDashboardScreen.java
+++ b/src/main/java/net/shadow/client/feature/gui/screen/OnlineServicesDashboardScreen.java
@@ -13,6 +13,7 @@ import net.minecraft.client.gui.Selectable;
 import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder;
 import net.minecraft.client.util.math.MatrixStack;
 import net.shadow.client.feature.gui.FastTickable;
+import net.shadow.client.feature.gui.notifications.hudNotif.HudNotification;
 import net.shadow.client.feature.gui.widget.RoundButton;
 import net.shadow.client.feature.gui.widget.RoundTextFieldWidget;
 import net.shadow.client.helper.IRCWebSocket;
@@ -57,6 +58,7 @@ public class OnlineServicesDashboardScreen extends ClientScreen implements FastT
         if (ShadowAPIWrapper.getAuthKey() != null) {
             logs.clear();
             logsSocket = new SimpleWebsocket(URI.create(ShadowAPIWrapper.BASE_WS + "/admin/logs"), Map.of("Authorization", ShadowAPIWrapper.getAuthKey()), () -> {
+                HudNotification.create("Websocket disconnected, reconnecting in 3 seconds", 3000, HudNotification.Type.INFO);
                 reconnectTime = System.currentTimeMillis() + Duration.ofSeconds(3).toMillis();
                 logs.clear();
             }, this::socketMessageRecieved);
@@ -152,6 +154,7 @@ public class OnlineServicesDashboardScreen extends ClientScreen implements FastT
         BiConsumer<String, String> r;
         RoundTextFieldWidget user, pass;
         RoundButton reg;
+
         public RegisterAccountViewer(double x, double y, double width, double height, BiConsumer<String, String> onReg) {
             super("", "", x, y, width, height, () -> {
             });
@@ -247,12 +250,12 @@ public class OnlineServicesDashboardScreen extends ClientScreen implements FastT
 
         @Override
         public void onFastTick() {
-            deleteBtn.onFastTick();
+            if (deleteBtn != null) deleteBtn.onFastTick();
         }
 
         @Override
         public boolean mouseClicked(double mouseX, double mouseY, int button) {
-            return deleteBtn.mouseClicked(mouseX, mouseY, button);
+            return deleteBtn != null && deleteBtn.mouseClicked(mouseX, mouseY, button);
         }
     }
 
diff --git a/src/main/java/net/shadow/client/feature/module/impl/crash/ErrorCrash.java b/src/main/java/net/shadow/client/feature/module/impl/crash/ErrorCrash.java
index b470a6d..2130b2d 100644
--- a/src/main/java/net/shadow/client/feature/module/impl/crash/ErrorCrash.java
+++ b/src/main/java/net/shadow/client/feature/module/impl/crash/ErrorCrash.java
@@ -4,21 +4,19 @@
 
 package net.shadow.client.feature.module.impl.crash;
 
-import net.minecraft.client.util.math.MatrixStack;
-import net.shadow.client.feature.module.ModuleType;
-import net.shadow.client.feature.config.DoubleSetting;
-import net.shadow.client.feature.config.EnumSetting;
-import net.shadow.client.feature.gui.notifications.Notification;
-import net.shadow.client.feature.module.Module;
 import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
 import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
+import net.minecraft.client.util.math.MatrixStack;
 import net.minecraft.item.ItemStack;
 import net.minecraft.item.Items;
 import net.minecraft.network.packet.c2s.play.ButtonClickC2SPacket;
 import net.minecraft.network.packet.c2s.play.ClickSlotC2SPacket;
 import net.minecraft.network.packet.c2s.play.SelectMerchantTradeC2SPacket;
-import net.minecraft.network.packet.c2s.play.UpdateSelectedSlotC2SPacket;
 import net.minecraft.screen.slot.SlotActionType;
+import net.shadow.client.feature.config.DoubleSetting;
+import net.shadow.client.feature.config.EnumSetting;
+import net.shadow.client.feature.module.Module;
+import net.shadow.client.feature.module.ModuleType;
 
 
 public class ErrorCrash extends Module {
@@ -32,7 +30,7 @@ public class ErrorCrash extends Module {
 
     @Override
     public void tick() {
-        switch(mode.getValue()){
+        switch (mode.getValue()) {
             case Click -> {
                 Int2ObjectMap<ItemStack> ripbozo = new Int2ObjectArrayMap();
                 ripbozo.put(0, new ItemStack(Items.ACACIA_BOAT, 1));
diff --git a/src/main/java/net/shadow/client/feature/module/impl/crash/LoominaCrash.java b/src/main/java/net/shadow/client/feature/module/impl/crash/LoominaCrash.java
index d4d3b17..5082fb6 100644
--- a/src/main/java/net/shadow/client/feature/module/impl/crash/LoominaCrash.java
+++ b/src/main/java/net/shadow/client/feature/module/impl/crash/LoominaCrash.java
@@ -79,7 +79,6 @@ public class LoominaCrash extends Module {
 
 
     void simplePacketMove(int slotId) {
-        //System.out.println(client.player.currentScreenHandler.getSlot(slotId).getStack().getName().getString());
         ScreenHandler screenHandler = client.player.currentScreenHandler;
         Int2ObjectOpenHashMap<ItemStack> int2ObjectMap = new Int2ObjectOpenHashMap<>();
         int2ObjectMap.put(slotId, client.player.currentScreenHandler.getSlot(slotId).getStack().copy());
diff --git a/src/main/java/net/shadow/client/feature/module/impl/crash/SSRFCrash.java b/src/main/java/net/shadow/client/feature/module/impl/crash/SSRFCrash.java
index 51ed7fa..54bf78b 100644
--- a/src/main/java/net/shadow/client/feature/module/impl/crash/SSRFCrash.java
+++ b/src/main/java/net/shadow/client/feature/module/impl/crash/SSRFCrash.java
@@ -17,7 +17,6 @@ import net.minecraft.network.packet.c2s.play.PlayerInteractBlockC2SPacket;
 import net.minecraft.util.Hand;
 import net.minecraft.util.hit.BlockHitResult;
 import net.minecraft.util.math.Direction;
-import net.minecraft.util.math.Vec3d;
 import net.shadow.client.feature.module.Module;
 import net.shadow.client.feature.module.ModuleType;
 
diff --git a/src/main/java/net/shadow/client/feature/module/impl/misc/IRC.java b/src/main/java/net/shadow/client/feature/module/impl/misc/IRC.java
index 65ff34b..e4daafd 100644
--- a/src/main/java/net/shadow/client/feature/module/impl/misc/IRC.java
+++ b/src/main/java/net/shadow/client/feature/module/impl/misc/IRC.java
@@ -19,7 +19,7 @@ import java.net.URI;
 
 public class IRC extends Module {
     static String ircPrefix = "#";
-    IRCWebSocket wsS;
+    public IRCWebSocket wsS;
 
     public IRC() {
         super("IRC", "Chat with others using the client", ModuleType.MISC);
@@ -48,6 +48,9 @@ public class IRC extends Module {
             setEnabled(false);
             return;
         }
+        initSock();
+    }
+    void initSock() {
         this.wsS = new IRCWebSocket(URI.create(ShadowAPIWrapper.BASE_WS + "/irc"), ShadowAPIWrapper.getAuthKey(), () -> {
             this.wsS = null;
             if (this.isEnabled()) this.setEnabled(false);
@@ -60,6 +63,11 @@ public class IRC extends Module {
         if (this.wsS != null) this.wsS.close();
     }
 
+    public void reconnect() {
+        if (this.wsS != null) this.wsS.close();
+        initSock();
+    }
+
     @Override
     public String getContext() {
         return null;
diff --git a/src/main/java/net/shadow/client/feature/module/impl/render/NameTags.java b/src/main/java/net/shadow/client/feature/module/impl/render/NameTags.java
index 2888446..968af6d 100644
--- a/src/main/java/net/shadow/client/feature/module/impl/render/NameTags.java
+++ b/src/main/java/net/shadow/client/feature/module/impl/render/NameTags.java
@@ -4,6 +4,7 @@
 
 package net.shadow.client.feature.module.impl.render;
 
+import com.mojang.blaze3d.systems.RenderSystem;
 import net.minecraft.client.network.AbstractClientPlayerEntity;
 import net.minecraft.client.network.PlayerListEntry;
 import net.minecraft.client.util.math.MatrixStack;
@@ -13,6 +14,8 @@ import net.minecraft.util.math.Vec3d;
 import net.minecraft.world.GameMode;
 import net.shadow.client.feature.module.Module;
 import net.shadow.client.feature.module.ModuleType;
+import net.shadow.client.helper.GameTexture;
+import net.shadow.client.helper.IRCWebSocket;
 import net.shadow.client.helper.font.FontRenderers;
 import net.shadow.client.helper.font.adapter.FontAdapter;
 import net.shadow.client.helper.render.Renderer;
@@ -74,11 +77,28 @@ public class NameTags extends Module {
         }
         MatrixStack stack1 = Renderer.R3D.getEmptyMatrixStack();
         Vec3d actual = new Vec3d(screenPos.x, screenPos.y - labelHeight, screenPos.z);
-        float fontWidth = nameDrawer.getStringWidth(text) + 4;
-        float width = fontWidth;
-        width = Math.max(width, 70);
+        float width = nameDrawer.getStringWidth(text) + 4;
+        width = Math.max(width, 60);
+        boolean in = IRCWebSocket.knownIRCPlayers.stream().anyMatch(playerEntry -> playerEntry.uuid().equals(entity.getUuid()));
+
+        double origWidth = 782;
+        double origHeight = 1000;
+        double newHeight = nameDrawer.getFontHeight();
+        double newWidth = origWidth*(newHeight /origHeight);
+        double req = newWidth+5;
+
+        if (in) {
+
+            if (width-req < nameDrawer.getStringWidth(text)) width += newWidth+5; // make sure we always have some space to draw the icon
+        }
         Renderer.R2D.renderRoundedQuad(stack1, new Color(0, 0, 5, 200), actual.x - width / 2d, actual.y, actual.x + width / 2d, actual.y + labelHeight, 3, 20);
-        nameDrawer.drawString(stack1, text, actual.x - fontWidth / 2d + 2, actual.y + 2, 0xFFFFFF);
+        nameDrawer.drawString(stack1, text, actual.x + width/2d - nameDrawer.getStringWidth(text)-2, actual.y + 2, 0xFFFFFF);
+
+        if (in) {
+            RenderSystem.setShaderTexture(0, GameTexture.TEXTURE_ICON.getWhere());
+            Renderer.R2D.renderTexture(stack1, actual.x -width/2d+2,actual.y+2, newWidth,newHeight,0,0, newWidth,newHeight, newWidth,newHeight);
+        }
+
         infoDrawer.drawString(stack1, gmString, actual.x + width / 2d - infoDrawer.getStringWidth(gmString) - 2, actual.y + 2 + nameDrawer.getFontHeight(), 0xAAAAAA);
         if (ping != -1)
             infoDrawer.drawString(stack1, pingStr, actual.x - width / 2d + 2, actual.y + 2 + nameDrawer.getFontHeight(), 0xAAAAAA);
diff --git a/src/main/java/net/shadow/client/feature/module/impl/render/TargetHud.java b/src/main/java/net/shadow/client/feature/module/impl/render/TargetHud.java
index 41eaa25..d0fcf5c 100644
--- a/src/main/java/net/shadow/client/feature/module/impl/render/TargetHud.java
+++ b/src/main/java/net/shadow/client/feature/module/impl/render/TargetHud.java
@@ -20,6 +20,7 @@ import net.shadow.client.feature.module.ModuleType;
 import net.shadow.client.helper.Texture;
 import net.shadow.client.helper.font.FontRenderers;
 import net.shadow.client.helper.manager.AttackManager;
+import net.shadow.client.helper.render.PlayerHeadResolver;
 import net.shadow.client.helper.render.Renderer;
 import net.shadow.client.helper.util.Transitions;
 import net.shadow.client.helper.util.Utils;
@@ -150,7 +151,7 @@ public class TargetHud extends Module {
             double textLeftAlign = 32 + 10;
             Renderer.R2D.renderRoundedQuad(stack, new Color(20, 20, 20, 200), 0, 0, modalWidth, modalHeight, 5, 10);
 
-            Texture tex = new Texture(Utils.Textures.getSkinPreviewTexture(entity.getUuid()));
+            Texture tex = PlayerHeadResolver.resolve(entity.getUuid());
             RenderSystem.setShaderTexture(0, tex);
 
             RenderSystem.enableBlend();
@@ -193,4 +194,3 @@ public class TargetHud extends Module {
     }
 
 }
-
diff --git a/src/main/java/net/shadow/client/helper/ConfigContainer.java b/src/main/java/net/shadow/client/helper/ConfigContainer.java
index a2af521..5134f5a 100644
--- a/src/main/java/net/shadow/client/helper/ConfigContainer.java
+++ b/src/main/java/net/shadow/client/helper/ConfigContainer.java
@@ -46,7 +46,6 @@ public class ConfigContainer {
     }
 
     void write(String data) {
-        System.out.println("writing " + data);
         try {
             FileUtils.write(path, data, StandardCharsets.UTF_8);
         } catch (Exception e) {
diff --git a/src/main/java/net/shadow/client/helper/IRCWebSocket.java b/src/main/java/net/shadow/client/helper/IRCWebSocket.java
index ddaef08..0562057 100644
--- a/src/main/java/net/shadow/client/helper/IRCWebSocket.java
+++ b/src/main/java/net/shadow/client/helper/IRCWebSocket.java
@@ -5,6 +5,7 @@
 package net.shadow.client.helper;
 
 import com.google.gson.Gson;
+import com.google.gson.internal.LinkedTreeMap;
 import lombok.AllArgsConstructor;
 import net.minecraft.text.Text;
 import net.minecraft.util.Formatting;
@@ -14,18 +15,25 @@ import org.java_websocket.client.WebSocketClient;
 import org.java_websocket.handshake.ServerHandshake;
 
 import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.CopyOnWriteArrayList;
 
 public class IRCWebSocket extends WebSocketClient {
+    public record PlayerEntry(String username, UUID uuid) {
+
+    }
+    public static List<PlayerEntry> knownIRCPlayers = new CopyOnWriteArrayList<>();
     String authToken;
     Runnable onClose;
 
     public IRCWebSocket(URI serverUri, String authToken, Runnable onClose) {
-        super(serverUri, Map.of("Authorization", authToken));
+        super(serverUri, Map.of("Authorization", authToken, "X-MC-UUID", ShadowMain.client.getSession().getUuid(), "X-MC-USERNAME", ShadowMain.client.getSession().getUsername()));
         this.authToken = authToken;
         this.onClose = onClose;
     }
-
     @Override
     public void onOpen(ServerHandshake handshakedata) {
         Utils.Logging.success("Connected to IRC");
@@ -38,20 +46,35 @@ public class IRCWebSocket extends WebSocketClient {
             case "message" -> {
                 String uname = p.data.get("who").toString();
                 String msg = p.data.get("message").toString();
-                ShadowMain.client.player.sendMessage(Text.of(String.format("%s[IRC] %s[%s] %s", Formatting.AQUA, Formatting.BLUE, uname, msg)), false);
+                Utils.Logging.message(Text.of(String.format("%s[IRC] %s[%s] %s", Formatting.AQUA, Formatting.BLUE, uname, msg)));
             }
             case "userJoined" -> {
                 String uname = p.data.get("who").toString();
-                ShadowMain.client.player.sendMessage(Text.of(String.format("%s[IRC] %s%s joined the IRC", Formatting.AQUA, Formatting.GREEN, uname)), false);
+                Utils.Logging.message(Text.of(String.format("%s[IRC] %s%s joined the IRC", Formatting.AQUA, Formatting.GREEN, uname)));
             }
             case "userLeft" -> {
                 String uname = p.data.get("who").toString();
-                ShadowMain.client.player.sendMessage(Text.of(String.format("%s[IRC] %s%s left the IRC", Formatting.AQUA, Formatting.RED, uname)), false);
+                Utils.Logging.message(Text.of(String.format("%s[IRC] %s%s left the IRC", Formatting.AQUA, Formatting.RED, uname)));
             }
             case "connectFailed" -> {
                 String reason = p.data.get("reason").toString();
                 Utils.Logging.error("Failed to establish connection, server said: " + reason);
             }
+            case "usersList" -> {
+                knownIRCPlayers.clear();
+                for (LinkedTreeMap<String, String> who : ((ArrayList<LinkedTreeMap<String, String>>) p.data.get("who"))) {
+                    String u = who.get("username");
+                    UUID uuid;
+                    try {
+                        uuid = UUID.fromString(who.get("uuid"));
+                    } catch (Exception ignored) {
+                        continue;
+                    }
+                    PlayerEntry pe = new PlayerEntry(u,uuid);
+                    if(!knownIRCPlayers.contains(pe)) knownIRCPlayers.add(pe);
+                }
+
+            }
         }
     }
 
@@ -59,6 +82,7 @@ public class IRCWebSocket extends WebSocketClient {
     public void onClose(int code, String reason, boolean remote) {
         Utils.Logging.error("IRC Disconnected");
         this.onClose.run();
+        knownIRCPlayers.clear();
     }
 
     @Override
diff --git a/src/main/java/net/shadow/client/helper/render/Cursor.java b/src/main/java/net/shadow/client/helper/render/Cursor.java
index e20cf14..19d18dc 100644
--- a/src/main/java/net/shadow/client/helper/render/Cursor.java
+++ b/src/main/java/net/shadow/client/helper/render/Cursor.java
@@ -16,12 +16,6 @@ public class Cursor {
 
     public static void setGlfwCursor(long cursor) {
         if (currentCursor == cursor) return;
-        String cname = "(unknown)";
-        if (CLICK == cursor) cname = "CLICK";
-        if (STANDARD == cursor) cname = "STANDARD";
-        if (TEXT_EDIT == cursor) cname = "TEXT_EDIT";
-        if (HSLIDER == cursor) cname = "HSLIDER";
-        System.out.println("set cursor: 0x" + Long.toHexString(cursor).toUpperCase() + ": " + cname);
         currentCursor = cursor;
         GLFW.glfwSetCursor(ShadowMain.client.getWindow().getHandle(), cursor);
     }
diff --git a/src/main/java/net/shadow/client/helper/render/PlayerHeadResolver.java b/src/main/java/net/shadow/client/helper/render/PlayerHeadResolver.java
new file mode 100644
index 0000000..007a529
--- /dev/null
+++ b/src/main/java/net/shadow/client/helper/render/PlayerHeadResolver.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) Shadow client, 0x150, Saturn5VFive 2022. All rights reserved.
+ */
+
+package net.shadow.client.helper.render;
+
+import net.minecraft.client.texture.NativeImage;
+import net.minecraft.client.texture.NativeImageBackedTexture;
+import net.shadow.client.ShadowMain;
+import net.shadow.client.helper.Texture;
+import org.lwjgl.BufferUtils;
+
+import javax.imageio.ImageIO;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.nio.ByteBuffer;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+public class PlayerHeadResolver {
+    static final NativeImageBackedTexture EMPTY = new NativeImageBackedTexture(1, 1, false);
+    static HttpClient client = HttpClient.newBuilder().followRedirects(HttpClient.Redirect.ALWAYS).build();
+    static Map<UUID, NativeImageBackedTexture> imageCache = new HashMap<>();
+
+    public static void resolve(UUID uuid, Texture texture) {
+        if (imageCache.containsKey(uuid)) {
+            ShadowMain.client.execute(() -> ShadowMain.client.getTextureManager().registerTexture(texture, imageCache.get(uuid)));
+            return;
+        }
+        imageCache.put(uuid, EMPTY);
+        ShadowMain.client.execute(() -> ShadowMain.client.getTextureManager().registerTexture(texture, EMPTY));
+        URI u = URI.create("https://mc-heads.net/avatar/" + uuid);
+        HttpRequest hr = HttpRequest.newBuilder().uri(u).header("user-agent", "shadow/1.0").build();
+        System.out.println("getting " + uuid.toString());
+        client.sendAsync(hr, HttpResponse.BodyHandlers.ofByteArray()).thenAccept(httpResponse -> {
+            try {
+                ByteArrayOutputStream stream = new ByteArrayOutputStream();
+                ImageIO.write(ImageIO.read(new ByteArrayInputStream(httpResponse.body())), "png", stream);
+                byte[] bytes = stream.toByteArray();
+
+                ByteBuffer data = BufferUtils.createByteBuffer(bytes.length).put(bytes);
+                data.flip();
+                NativeImage img = NativeImage.read(data);
+                NativeImageBackedTexture nib = new NativeImageBackedTexture(img);
+
+                ShadowMain.client.execute(() -> ShadowMain.client.getTextureManager().registerTexture(texture, nib));
+                imageCache.put(uuid, nib);
+
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }).exceptionally(throwable -> {
+            throwable.printStackTrace();
+            return null;
+        });
+
+    }
+
+    public static Texture resolve(UUID uuid) {
+        Texture tex = new Texture(String.format("skin_preview-%s", uuid.toString()));
+        resolve(uuid, tex);
+        return tex;
+    }
+}
diff --git a/src/main/java/net/shadow/client/helper/util/Utils.java b/src/main/java/net/shadow/client/helper/util/Utils.java
index 67d27ce..df97423 100644
--- a/src/main/java/net/shadow/client/helper/util/Utils.java
+++ b/src/main/java/net/shadow/client/helper/util/Utils.java
@@ -16,6 +16,7 @@ import net.minecraft.nbt.StringNbtReader;
 import net.minecraft.network.packet.c2s.play.PlayerInteractBlockC2SPacket;
 import net.minecraft.screen.slot.SlotActionType;
 import net.minecraft.text.LiteralText;
+import net.minecraft.text.Text;
 import net.minecraft.text.TextColor;
 import net.minecraft.util.Hand;
 import net.minecraft.util.hit.BlockHitResult;
@@ -46,11 +47,13 @@ import java.net.http.HttpResponse;
 import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
 import java.time.Duration;
+import java.util.ArrayDeque;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Queue;
 import java.util.UUID;
 import java.util.concurrent.ConcurrentHashMap;
 
@@ -367,27 +370,37 @@ public class Utils {
     }
 
     public static class Logging {
+        static Queue<Text> messageQueue = new ArrayDeque<>();
+        static void sendMessages() {
+            if (ShadowMain.client.player != null) {
+                Text next;
+                while((next = messageQueue.poll()) != null) {
+                    ShadowMain.client.player.sendMessage(next, false);
+                }
+            }
+        }
         public static void warn(String n) {
-            message0(n, Color.YELLOW);
+            message(n, Color.YELLOW);
         }
 
         public static void success(String n) {
-            message0(n, new Color(65, 217, 101));
+            message(n, new Color(65, 217, 101));
         }
 
         public static void error(String n) {
-            message0(n, new Color(214, 93, 62));
+            message(n, new Color(214, 93, 62));
         }
 
         public static void message(String n) {
-            message0(n, Color.WHITE);
+            message(n, Color.WHITE);
         }
-
-        public static void message0(String n, Color c) {
+        public static void message(Text text) {
+            messageQueue.add(text);
+        }
+        public static void message(String n, Color c) {
             LiteralText t = new LiteralText(n);
             t.setStyle(t.getStyle().withColor(TextColor.fromRgb(c.getRGB())));
-            if (ShadowMain.client.player != null) if (!(ShadowMain.client.currentScreen instanceof ConsoleScreen))
-                ShadowMain.client.player.sendMessage(t, false);
+            if (!(ShadowMain.client.currentScreen instanceof ConsoleScreen)) message(t);
             //            if (c.equals(Color.WHITE)) c = Color.BLACK;
             ConsoleScreen.instance().addLog(new ConsoleScreen.LogEntry(n, c));
         }
@@ -404,6 +417,7 @@ public class Utils {
         }
 
         public static void tick() {
+            Logging.sendMessages();
             for (TickEntry entry : entries.toArray(new TickEntry[0])) {
                 entry.v--;
                 if (entry.v <= 0) {
diff --git a/src/main/java/net/shadow/client/mixin/GameRendererMixin.java b/src/main/java/net/shadow/client/mixin/GameRendererMixin.java
index 350db95..0f3855d 100644
--- a/src/main/java/net/shadow/client/mixin/GameRendererMixin.java
+++ b/src/main/java/net/shadow/client/mixin/GameRendererMixin.java
@@ -15,6 +15,7 @@ import net.minecraft.util.math.Vec3d;
 import net.minecraft.world.RaycastContext;
 import net.shadow.client.ShadowMain;
 import net.shadow.client.feature.gui.DoesMSAA;
+import net.shadow.client.feature.gui.notifications.hudNotif.HudNotificationRenderer;
 import net.shadow.client.feature.gui.screen.ClientScreen;
 import net.shadow.client.feature.module.Module;
 import net.shadow.client.feature.module.ModuleRegistry;
@@ -107,4 +108,9 @@ public class GameRendererMixin {
         double zv = ModuleRegistry.getByClass(Zoom.class).getZoomValue(cir.getReturnValue());
         cir.setReturnValue(zv);
     }
+
+    @Inject(method = "render", at = @At("RETURN"))
+    void a(float tickDelta, long startTime, boolean tick, CallbackInfo ci) {
+        HudNotificationRenderer.instance.render(Renderer.R3D.getEmptyMatrixStack());
+    }
 }
diff --git a/src/main/java/net/shadow/client/mixin/MinecraftClientMixin.java b/src/main/java/net/shadow/client/mixin/MinecraftClientMixin.java
index ca7ad23..228d368 100644
--- a/src/main/java/net/shadow/client/mixin/MinecraftClientMixin.java
+++ b/src/main/java/net/shadow/client/mixin/MinecraftClientMixin.java
@@ -7,15 +7,20 @@ package net.shadow.client.mixin;
 import net.minecraft.client.MinecraftClient;
 import net.minecraft.client.RunArgs;
 import net.minecraft.client.gui.screen.Screen;
+import net.minecraft.client.util.Session;
 import net.shadow.client.ShadowMain;
 import net.shadow.client.feature.module.ModuleRegistry;
+import net.shadow.client.feature.module.impl.misc.IRC;
 import net.shadow.client.feature.module.impl.world.FastUse;
 import net.shadow.client.helper.event.EventType;
 import net.shadow.client.helper.event.Events;
 import net.shadow.client.helper.event.events.base.NonCancellableEvent;
 import net.shadow.client.helper.manager.ConfigManager;
+import net.shadow.client.mixinUtil.MinecraftClientDuck;
 import org.objectweb.asm.Opcodes;
+import org.spongepowered.asm.mixin.Final;
 import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Mutable;
 import org.spongepowered.asm.mixin.Shadow;
 import org.spongepowered.asm.mixin.injection.At;
 import org.spongepowered.asm.mixin.injection.Inject;
@@ -25,16 +30,29 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
 import java.util.Objects;
 
 @Mixin(MinecraftClient.class)
-public class MinecraftClientMixin {
+public class MinecraftClientMixin implements MinecraftClientDuck {
     @Shadow
     private int itemUseCooldown;
 
+    @Mutable
+    @Shadow @Final private Session session;
+
     @Inject(method = "stop", at = @At("HEAD"))
     void real(CallbackInfo ci) {
         ConfigManager.saveState();
         Events.fireEvent(EventType.GAME_EXIT, new NonCancellableEvent());
     }
 
+    @Override
+    public void setSession(Session newSession) {
+        this.session = newSession;
+        IRC i = ModuleRegistry.getByClass(IRC.class);
+        // reconnect to the irc with the new session to stay up to date
+        if (i.isEnabled()) {
+            i.reconnect();
+        }
+    }
+
     @Inject(method = "<init>", at = @At("TAIL"))
     void postInit(RunArgs args, CallbackInfo ci) {
         ShadowMain.INSTANCE.postWindowInit();
diff --git a/src/main/java/net/shadow/client/mixin/PlayerListHudMixin.java b/src/main/java/net/shadow/client/mixin/PlayerListHudMixin.java
new file mode 100644
index 0000000..50e6e8f
--- /dev/null
+++ b/src/main/java/net/shadow/client/mixin/PlayerListHudMixin.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) Shadow client, 0x150, Saturn5VFive 2022. All rights reserved.
+ */
+
+package net.shadow.client.mixin;
+
+import com.mojang.blaze3d.systems.RenderSystem;
+import net.minecraft.client.gui.hud.PlayerListHud;
+import net.minecraft.client.network.PlayerListEntry;
+import net.minecraft.client.util.math.MatrixStack;
+import net.shadow.client.helper.GameTexture;
+import net.shadow.client.helper.IRCWebSocket;
+import net.shadow.client.helper.render.Renderer;
+import net.shadow.client.helper.util.Utils;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+@Mixin(PlayerListHud.class)
+public abstract class PlayerListHudMixin {
+    @Inject(method="renderLatencyIcon",at=@At("HEAD"),cancellable = true)
+    void a(MatrixStack matrices, int width, int x, int y, PlayerListEntry entry, CallbackInfo ci) {
+        if (IRCWebSocket.knownIRCPlayers.stream().anyMatch(playerEntry -> playerEntry.uuid().equals(entry.getProfile().getId()))) {
+            ci.cancel();
+            double supposedWidth = 10;
+            double origWidth = 782;
+            double origHeight = 1000;
+            double newHeight = 8;
+            double newWidth = origWidth*(newHeight /origHeight);
+            Utils.TickManager.runOnNextRender(() -> {
+                RenderSystem.setShaderTexture(0, GameTexture.TEXTURE_ICON.getWhere());
+                Renderer.R2D.renderTexture(matrices,x + width - supposedWidth/2d - newWidth/2d -1,y, newWidth,newHeight,0,0, newWidth,newHeight, newWidth,newHeight);
+            });
+        }
+    }
+}
diff --git a/src/main/java/net/shadow/client/mixin/PlayerSkinMixin.java b/src/main/java/net/shadow/client/mixin/PlayerSkinMixin.java
deleted file mode 100644
index cbb7b48..0000000
--- a/src/main/java/net/shadow/client/mixin/PlayerSkinMixin.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (c) Shadow client, 0x150, Saturn5VFive 2022. All rights reserved.
- */
-
-package net.shadow.client.mixin;
-
-import com.google.gson.JsonObject;
-import com.google.gson.JsonParser;
-import com.mojang.authlib.GameProfile;
-import com.mojang.authlib.minecraft.MinecraftProfileTexture;
-import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type;
-import com.mojang.authlib.minecraft.MinecraftSessionService;
-import net.minecraft.client.texture.PlayerSkinProvider;
-import net.minecraft.util.Identifier;
-import org.jetbrains.annotations.Nullable;
-import org.spongepowered.asm.mixin.Final;
-import org.spongepowered.asm.mixin.Mixin;
-import org.spongepowered.asm.mixin.Shadow;
-import org.spongepowered.asm.mixin.injection.At;
-import org.spongepowered.asm.mixin.injection.Inject;
-import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
-import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
-
-import java.io.InputStreamReader;
-import java.net.URL;
-import java.util.Map;
-
-@Mixin(PlayerSkinProvider.class)
-public class PlayerSkinMixin {
-    private static JsonObject capes;
-    @Shadow
-    @Final
-    private MinecraftSessionService sessionService;
-
-    //I cant even launch mc with this! it doesnt work
-    // skill issue, i would say
-    @Inject(method = "method_4653", at = @At(
-            value = "INVOKE",
-            target = "Lnet/minecraft/client/MinecraftClient;execute(Ljava/lang/Runnable;)V",
-            shift = At.Shift.BEFORE
-    ), locals = LocalCapture.CAPTURE_FAILEXCEPTION)
-    void real(GameProfile gameProfile, boolean bl, PlayerSkinProvider.SkinTextureAvailableCallback skinTextureAvailableCallback, CallbackInfo ci, Map<Type, MinecraftProfileTexture> map) {
-        addCape(gameProfile, map);
-    }
-
-    private void addCape(GameProfile profile,
-                         Map<MinecraftProfileTexture.Type, MinecraftProfileTexture> map) {
-        String name = profile.getName();
-        String uuid = profile.getId().toString();
-
-        try {
-            if (capes == null)
-                setupCapes();
-
-            if (capes.has(name)) {
-                String capeURL = capes.get(name).getAsString();
-                map.put(Type.CAPE, new MinecraftProfileTexture(capeURL, null));
-
-            } else if (capes.has(uuid)) {
-                String capeURL = capes.get(uuid).getAsString();
-                map.put(Type.CAPE, new MinecraftProfileTexture(capeURL, null));
-            }
-
-        } catch (Exception e) {
-            System.err.println("[Shadow] Failed to load cape for '" + name
-                    + "' (" + uuid + ")");
-
-            e.printStackTrace();
-        }
-    }
-
-    private void setupCapes() {
-        try {
-            URL url = new URL("https://moleapi.pythonanywhere.com/retrieve");
-            capes = JsonParser.parseReader(new InputStreamReader(url.openStream())).getAsJsonObject();
-        } catch (Exception e) {
-            System.err.println("[Shadow] Failed to load capes from API");
-            e.printStackTrace();
-        }
-    }
-
-    @Shadow
-    private Identifier loadSkin(MinecraftProfileTexture profileTexture,
-                                Type type,
-                                @Nullable PlayerSkinProvider.SkinTextureAvailableCallback callback) {
-        return null;
-    }
-}
diff --git a/src/main/java/net/shadow/client/mixinUtil/MinecraftClientDuck.java b/src/main/java/net/shadow/client/mixinUtil/MinecraftClientDuck.java
new file mode 100644
index 0000000..c184ef0
--- /dev/null
+++ b/src/main/java/net/shadow/client/mixinUtil/MinecraftClientDuck.java
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) Shadow client, 0x150, Saturn5VFive 2022. All rights reserved.
+ */
+
+package net.shadow.client.mixinUtil;
+
+import net.minecraft.client.util.Session;
+
+public interface MinecraftClientDuck {
+    void setSession(Session newSession);
+}
diff --git a/src/main/resources/shadow.mixins.json b/src/main/resources/shadow.mixins.json
index bfe07cf..0b2596c 100644
--- a/src/main/resources/shadow.mixins.json
+++ b/src/main/resources/shadow.mixins.json
@@ -33,6 +33,7 @@
     "IClientPlayerInteractionManagerAccessor",
     "ICustomPayloadC2SPacketAccessor",
     "IDebugHudAccessor",
+    "IdentifierAccessor",
     "IEntityVelocityUpdateS2CPacketMixin",
     "IInGameHudAccessor",
     "ILivingEntityAccessor",
@@ -57,7 +58,7 @@
     "PlayerEntityMixin",
     "PlayerEntityRendererMixin",
     "PlayerInteractEntityC2SPacketAccessor",
-    "PlayerSkinMixin",
+    "PlayerListHudMixin",
     "RebuildTaskMixin",
     "ScreenMixin",
     "SelectWorldScreenMixin",
@@ -68,8 +69,7 @@
     "SliderWidgetMixin",
     "TitleScreenMixin",
     "WorldRendererAccessor",
-    "WorldRendererMixin",
-    "IdentifierAccessor"
+    "WorldRendererMixin"
   ],
   "client": [],
   "server": [],