diff --git a/Azurite1.18/libs/1.18.jar b/Azurite1.18/libs/1.18.jar
new file mode 100644
index 0000000..780ee31
Binary files /dev/null and b/Azurite1.18/libs/1.18.jar differ
diff --git a/Azurite1.18/pom.xml b/Azurite1.18/pom.xml
new file mode 100644
index 0000000..bd71b1d
--- /dev/null
+++ b/Azurite1.18/pom.xml
@@ -0,0 +1,44 @@
+
+
+ 4.0.0
+
+ me.keano.azurite
+ Azurite1.18
+ 1.0
+
+
+ 17
+ 17
+ UTF-8
+
+
+
+
+ org.projectlombok
+ lombok
+ 1.18.24
+ provided
+
+
+ org.spigotmc
+ spigot-1.18
+ 1.18
+ system
+ ${project.basedir}/libs/1.18.jar
+
+
+ com.google.guava
+ guava
+ 31.1-jre
+ compile
+
+
+ me.keano.azurite
+ Azurite
+ 1.0-SNAPSHOT
+ provided
+
+
+
\ No newline at end of file
diff --git a/Azurite1.18/src/main/java/me/keano/azurite/modules/nametags/packet/type/NametagPacketV1_18_R2.java b/Azurite1.18/src/main/java/me/keano/azurite/modules/nametags/packet/type/NametagPacketV1_18_R2.java
new file mode 100644
index 0000000..b6590ce
--- /dev/null
+++ b/Azurite1.18/src/main/java/me/keano/azurite/modules/nametags/packet/type/NametagPacketV1_18_R2.java
@@ -0,0 +1,145 @@
+package me.keano.azurite.modules.nametags.packet.type;
+
+import lombok.SneakyThrows;
+import me.keano.azurite.modules.nametags.NametagManager;
+import me.keano.azurite.modules.nametags.extra.NameInfo;
+import me.keano.azurite.modules.nametags.extra.NameVisibility;
+import me.keano.azurite.modules.nametags.packet.NametagPacket;
+import me.keano.azurite.utils.ReflectionUtils;
+import net.minecraft.EnumChatFormat;
+import net.minecraft.network.protocol.Packet;
+import net.minecraft.network.protocol.game.PacketPlayOutScoreboardTeam;
+import net.minecraft.world.scores.Scoreboard;
+import net.minecraft.world.scores.ScoreboardTeam;
+import net.minecraft.world.scores.ScoreboardTeamBase;
+import org.bukkit.craftbukkit.v1_18_R2.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_18_R2.util.CraftChatMessage;
+import org.bukkit.entity.Player;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Collectors;
+
+/**
+ * Copyright (c) 2023. Keano
+ * Use or redistribution of source or file is
+ * only permitted if given explicit permission.
+ */
+@SuppressWarnings("unused")
+public class NametagPacketV1_18_R2 extends NametagPacket {
+
+ private static final Field a = ReflectionUtils.accessField(PacketPlayOutScoreboardTeam.b.class, "a");
+ private static final Field b = ReflectionUtils.accessField(PacketPlayOutScoreboardTeam.b.class, "b");
+ private static final Field c = ReflectionUtils.accessField(PacketPlayOutScoreboardTeam.b.class, "c");
+ private static final Field d = ReflectionUtils.accessField(PacketPlayOutScoreboardTeam.b.class, "d");
+ private static final Field e = ReflectionUtils.accessField(PacketPlayOutScoreboardTeam.b.class, "e");
+ private static final Field f = ReflectionUtils.accessField(PacketPlayOutScoreboardTeam.b.class, "f");
+ private static final Field g = ReflectionUtils.accessField(PacketPlayOutScoreboardTeam.b.class, "g");
+ private static final Constructor> PACKET_SCORE_BOARD_CONSTRUCTOR = ReflectionUtils.accessConstructor(PacketPlayOutScoreboardTeam.class, 1);
+ private static final ScoreboardTeam EMPTY_TEAM = new ScoreboardTeam(new Scoreboard(), "empty");
+
+ private static final Map FORMATS = Arrays
+ .stream(EnumChatFormat.values())
+ .collect(Collectors.toMap(EnumChatFormat::toString, e -> e));
+
+ private final Map teams;
+ private final Map teamsByPlayer;
+
+ public NametagPacketV1_18_R2(NametagManager manager, Player player) {
+ super(manager, player);
+ this.teams = new ConcurrentHashMap<>();
+ this.teamsByPlayer = new ConcurrentHashMap<>();
+ }
+
+ private void sendPacket(Packet> packet) { // Packet type is unknown 1.8+
+ ((CraftPlayer) player).getHandle().b.a(packet);
+ }
+
+ @Override
+ public void addToTeam(Player player, String name) {
+ String currentTeam = teamsByPlayer.get(player.getName());
+ NameInfo info = teams.get(name);
+
+ if (currentTeam != null && currentTeam.equals(name)) return;
+ if (info == null) return;
+
+ teamsByPlayer.put(player.getName(), name);
+ sendPacket(new ScoreboardPacket(info, 3, player).toPacket());
+ }
+
+ @Override
+ public void delete() {
+ for (NameInfo info : teams.values()) {
+ sendPacket(new ScoreboardPacket(info, 1).toPacket());
+ }
+
+ teams.clear();
+ teamsByPlayer.clear();
+ }
+
+ @Override
+ public void create(String name, String color, String prefix, String suffix, boolean friendlyInvis, NameVisibility visibility) {
+ NameInfo current = teams.get(name);
+
+ if (current != null) {
+ if (!current.getColor().equals(color) || !current.getPrefix().equals(prefix) || !current.getSuffix().equals(suffix)) {
+ NameInfo newInfo = new NameInfo(name, color, prefix, suffix, visibility, friendlyInvis);
+ teams.put(name, newInfo);
+ sendPacket(new ScoreboardPacket(newInfo, 2).toPacket());
+ }
+ return;
+ }
+
+ NameInfo info = new NameInfo(name, color, prefix, suffix, visibility, friendlyInvis);
+ teams.put(name, info);
+ sendPacket(new ScoreboardPacket(info, 0).toPacket());
+ }
+
+ private static class ScoreboardPacket {
+
+ private final NameInfo info;
+ private final Player target;
+ private final int action;
+
+ public ScoreboardPacket(NameInfo info, int action) {
+ this.info = info;
+ this.action = action;
+ this.target = null;
+ }
+
+ public ScoreboardPacket(NameInfo info, int action, Player target) {
+ this.info = info;
+ this.action = action;
+ this.target = target;
+ }
+
+ @SneakyThrows
+ public PacketPlayOutScoreboardTeam toPacket() {
+ PacketPlayOutScoreboardTeam.b subPacket = new PacketPlayOutScoreboardTeam.b(EMPTY_TEAM);
+
+ a.set(subPacket, CraftChatMessage.fromString(info.getName())[0]);
+ b.set(subPacket, CraftChatMessage.fromString(info.getPrefix())[0]);
+ c.set(subPacket, CraftChatMessage.fromString(info.getSuffix())[0]);
+ d.set(subPacket, info.getVisibility().getName());
+ e.set(subPacket, ScoreboardTeamBase.EnumTeamPush.b.e);
+ f.set(subPacket, getFormat(info.getColor()));
+ g.set(subPacket, info.isFriendlyInvis() ? 3 : 0);
+
+ return (PacketPlayOutScoreboardTeam) PACKET_SCORE_BOARD_CONSTRUCTOR.newInstance(
+ info.getName(), action,
+ Optional.of(subPacket),
+ (target != null ? Collections.singleton(target.getName()) : Collections.emptySet())
+ );
+ }
+
+ public EnumChatFormat getFormat(String string) {
+ EnumChatFormat format = FORMATS.get(string);
+ return format == null ? EnumChatFormat.v : format;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Azurite1.18/src/main/java/me/keano/azurite/modules/tablist/packet/type/TablistPacketV1_18_R2.java b/Azurite1.18/src/main/java/me/keano/azurite/modules/tablist/packet/type/TablistPacketV1_18_R2.java
new file mode 100644
index 0000000..c7d0e05
--- /dev/null
+++ b/Azurite1.18/src/main/java/me/keano/azurite/modules/tablist/packet/type/TablistPacketV1_18_R2.java
@@ -0,0 +1,145 @@
+package me.keano.azurite.modules.tablist.packet.type;
+
+import com.google.common.collect.HashBasedTable;
+import com.google.common.collect.Table;
+import com.mojang.authlib.GameProfile;
+import com.mojang.authlib.properties.Property;
+import me.keano.azurite.modules.tablist.Tablist;
+import me.keano.azurite.modules.tablist.TablistManager;
+import me.keano.azurite.modules.tablist.extra.TablistEntry;
+import me.keano.azurite.modules.tablist.extra.TablistSkin;
+import me.keano.azurite.modules.tablist.packet.TablistPacket;
+import me.keano.azurite.utils.Utils;
+import net.minecraft.network.protocol.Packet;
+import net.minecraft.network.protocol.game.PacketPlayOutPlayerInfo;
+import net.minecraft.network.protocol.game.PacketPlayOutPlayerListHeaderFooter;
+import net.minecraft.server.MinecraftServer;
+import net.minecraft.server.level.EntityPlayer;
+import net.minecraft.server.level.WorldServer;
+import net.minecraft.server.network.PlayerConnection;
+import org.bukkit.craftbukkit.v1_18_R2.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_18_R2.util.CraftChatMessage;
+import org.bukkit.entity.Player;
+
+import java.util.UUID;
+
+/**
+ * Copyright (c) 2023. Keano
+ * Use or redistribution of source or file is
+ * only permitted if given explicit permission.
+ */
+@SuppressWarnings({"unused", "deprecation"})
+public class TablistPacketV1_18_R2 extends TablistPacket {
+
+ // These can be used for all the players since we can use teams to modify how each player sees them.
+ private final Table fakePlayers;
+ private final int maxColumns;
+
+ // Cache them to see if we don't have to send a packet again.
+ private String header;
+ private String footer;
+
+ public TablistPacketV1_18_R2(TablistManager manager, Player player) {
+ super(manager, player);
+
+ this.fakePlayers = HashBasedTable.create();
+ this.header = "";
+ this.footer = "";
+ this.maxColumns = (Utils.getProtocolVersion(player) <= 5 ? 3 : 4);
+
+ this.loadFakes();
+ this.init();
+ }
+
+ @Override
+ public void update() {
+ this.sendHeaderFooter();
+
+ Tablist tablist = getManager().getAdapter().getInfo(player);
+
+ for (int row = 0; row < 20; row++) {
+ for (int col = 0; col < maxColumns; col++) {
+ TablistEntry entry = tablist.getEntry(col, row);
+ TablistSkin newSkin = entry.getSkin();
+ EntityPlayer fake = fakePlayers.get(col, row);
+
+ if (fake == null) continue;
+
+ if (fake.e != entry.getPing()) {
+ fake.e = entry.getPing();
+ sendPacket(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.c, fake));
+ }
+
+ if (newSkin == null) {
+ newSkin = getManager().getDefaultSkins().get(col, row);
+ }
+
+ updateSkin(fake, newSkin);
+ handleTeams(fake.getBukkitEntity(), entry.getText(), calcSlot(col, row));
+ }
+ }
+ }
+
+ private void updateSkin(EntityPlayer fake, TablistSkin skin) {
+ GameProfile profile = fake.fq();
+ Property old = profile.getProperties().get("textures").stream().findFirst().orElse(null);
+
+ // Verify if we should update
+ if (old != null && old.getValue().equals(skin.getValue()) && old.getSignature().equals(skin.getSignature())) {
+ return;
+ }
+
+ profile.getProperties().clear();
+ profile.getProperties().put("textures", new Property("textures", skin.getValue(), skin.getSignature()));
+
+ sendPacket(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.b, fake));
+ sendPacket(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.a, fake));
+ }
+
+ private void loadFakes() {
+ MinecraftServer server = MinecraftServer.getServer();
+ WorldServer worldServer = server.F().iterator().next();
+
+ for (int row = 0; row < 20; row++) {
+ for (int col = 0; col < 4; col++) {
+ GameProfile profile = new GameProfile(UUID.randomUUID(), getName(col, row));
+ EntityPlayer fake = new EntityPlayer(server, worldServer, profile);
+ TablistSkin skin = getManager().getDefaultSkins().get(col, row);
+ profile.getProperties().put("textures", new Property("textures", skin.getValue(), skin.getSignature()));
+ fakePlayers.put(col, row, fake);
+ }
+ }
+ }
+
+ private void init() {
+ for (int row = 0; row < 20; row++) {
+ for (int col = 0; col < maxColumns; col++) {
+ EntityPlayer fake = fakePlayers.get(col, row);
+ sendPacket(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.a, fake));
+ }
+ }
+ }
+
+ private void sendPacket(Packet> packet) {
+ PlayerConnection connection = ((CraftPlayer) player).getHandle().b;
+ connection.a(packet);
+ }
+
+ private void sendHeaderFooter() {
+ String headerJoined = String.join("\n", getManager().getAdapter().getHeader(player));
+ String footerJoined = String.join("\n", getManager().getAdapter().getFooter(player));
+
+ // Refrain sending a packet again if same.
+ if (footer.equals(headerJoined) && header.equals(headerJoined)) return;
+
+ this.header = headerJoined;
+ this.footer = footerJoined;
+
+ PacketPlayOutPlayerListHeaderFooter packet = new PacketPlayOutPlayerListHeaderFooter(
+ CraftChatMessage.fromJSONOrString(headerJoined, true),
+ CraftChatMessage.fromJSONOrString(footerJoined, true)
+ );
+
+ sendPacket(packet);
+ }
+}
\ No newline at end of file
diff --git a/Azurite1.18/src/main/java/me/keano/azurite/modules/versions/type/Version1_18_R2.java b/Azurite1.18/src/main/java/me/keano/azurite/modules/versions/type/Version1_18_R2.java
new file mode 100644
index 0000000..a7ced77
--- /dev/null
+++ b/Azurite1.18/src/main/java/me/keano/azurite/modules/versions/type/Version1_18_R2.java
@@ -0,0 +1,338 @@
+package me.keano.azurite.modules.versions.type;
+
+import com.google.common.io.ByteArrayDataOutput;
+import com.google.common.io.ByteStreams;
+import com.mojang.authlib.GameProfile;
+import com.mojang.authlib.properties.Property;
+import com.mojang.datafixers.util.Pair;
+import io.netty.channel.ChannelDuplexHandler;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelPipeline;
+import io.netty.channel.ChannelPromise;
+import lombok.SneakyThrows;
+import me.keano.azurite.modules.ability.AbilityManager;
+import me.keano.azurite.modules.ability.type.InvisibilityAbility;
+import me.keano.azurite.modules.framework.Config;
+import me.keano.azurite.modules.framework.Module;
+import me.keano.azurite.modules.loggers.Logger;
+import me.keano.azurite.modules.nametags.Nametag;
+import me.keano.azurite.modules.nametags.extra.NameVisibility;
+import me.keano.azurite.modules.pvpclass.type.ghost.GhostClass;
+import me.keano.azurite.modules.tablist.extra.TablistSkin;
+import me.keano.azurite.modules.versions.Version;
+import me.keano.azurite.modules.versions.VersionManager;
+import me.keano.azurite.utils.ReflectionUtils;
+import net.minecraft.core.BlockPosition;
+import net.minecraft.network.protocol.game.ClientboundSetActionBarTextPacket;
+import net.minecraft.network.protocol.game.PacketPlayOutEntityEquipment;
+import net.minecraft.network.protocol.game.PacketPlayOutPlayerInfo;
+import net.minecraft.server.MinecraftServer;
+import net.minecraft.server.level.EntityPlayer;
+import net.minecraft.server.level.PlayerChunkMap;
+import net.minecraft.server.level.WorldServer;
+import net.minecraft.server.network.ServerPlayerConnection;
+import net.minecraft.world.entity.Entity;
+import net.minecraft.world.entity.EnumItemSlot;
+import net.minecraft.world.level.block.entity.TileEntity;
+import net.minecraft.world.level.block.state.IBlockData;
+import org.bukkit.Bukkit;
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.Particle;
+import org.bukkit.block.Block;
+import org.bukkit.command.CommandMap;
+import org.bukkit.craftbukkit.v1_18_R2.CraftServer;
+import org.bukkit.craftbukkit.v1_18_R2.CraftWorld;
+import org.bukkit.craftbukkit.v1_18_R2.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_18_R2.inventory.CraftItemStack;
+import org.bukkit.craftbukkit.v1_18_R2.util.CraftChatMessage;
+import org.bukkit.enchantments.Enchantment;
+import org.bukkit.entity.Player;
+import org.bukkit.event.entity.EntityPotionEffectEvent;
+import org.bukkit.inventory.ItemFlag;
+import org.bukkit.inventory.ItemStack;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * Copyright (c) 2023. Keano
+ * Use or redistribution of source or file is
+ * only permitted if given explicit permission.
+ */
+@SuppressWarnings("all")
+public class Version1_18_R2 extends Module implements Version {
+
+ private static final Field ENTITY_ID = ReflectionUtils.accessField(PacketPlayOutEntityEquipment.class, "b");
+ private static final Field SLOT = ReflectionUtils.accessField(PacketPlayOutEntityEquipment.class, "c");
+ private static final Field ACTION = ReflectionUtils.accessField(PacketPlayOutPlayerInfo.class, "a");
+ private static final Field DATA = ReflectionUtils.accessField(PacketPlayOutPlayerInfo.class, "b");
+
+ private static final Method SPAWN_PARTICLE = ReflectionUtils.accessMethod(
+ CraftWorld.class, "spawnParticle", Particle.class, Location.class, int.class, Object.class
+ );
+
+ public Version1_18_R2(VersionManager manager) {
+ super(manager);
+ }
+
+ @Override
+ public CommandMap getCommandMap() {
+ try {
+
+ CraftServer server = (CraftServer) Bukkit.getServer();
+ Method method = server.getClass().getMethod("getCommandMap");
+ return (CommandMap) method.invoke(server);
+
+ } catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ @Override
+ @SneakyThrows
+ public Set getTrackedPlayers(Player player) {
+ EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
+ PlayerChunkMap.EntityTracker tracker = entityPlayer.tracker;
+
+ if (tracker != null) {
+ Set players = new HashSet<>();
+
+ for (ServerPlayerConnection connection : tracker.f) {
+ players.add(connection.e().getBukkitEntity());
+ }
+
+ return players;
+ }
+
+ return Collections.emptySet();
+ }
+
+ @Override
+ public boolean isNotGapple(ItemStack item) {
+ return item.getType() != Material.ENCHANTED_GOLDEN_APPLE;
+ }
+
+ @Override
+ public int getPing(Player player) {
+ CraftPlayer craftPlayer = (CraftPlayer) player;
+ return craftPlayer.getHandle().e;
+ }
+
+ @Override
+ public ItemStack getItemInHand(Player player) {
+ try {
+
+ Method method = player.getInventory().getClass().getMethod("getItemInMainHand");
+ return (ItemStack) method.invoke(player.getInventory());
+
+ } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ @Override
+ public ItemStack addGlow(ItemStack itemStack) {
+ itemStack.addUnsafeEnchantment(Enchantment.WATER_WORKER, 1);
+ itemStack.addItemFlags(ItemFlag.HIDE_ENCHANTS);
+ return itemStack;
+ }
+
+ @Override
+ public void setItemInHand(Player player, ItemStack item) {
+ player.getInventory().setItemInMainHand(item);
+ }
+
+ @Override
+ public void handleLoggerDeath(Logger logger) {
+ EntityPlayer player = ((CraftPlayer) logger.getPlayer()).getHandle();
+ player.getBukkitEntity().getInventory().clear();
+ player.getBukkitEntity().getInventory().setArmorContents(null);
+ player.getBukkitEntity().setHealth(0);
+ player.getBukkitEntity().setExp(0.0F);
+ player.removeAllEffects(EntityPotionEffectEvent.Cause.DEATH);
+ player.getBukkitEntity().saveData(); // Save the inventory and everything we just modified
+ }
+
+ @Override
+ public void playEffect(Location location, String name, Object data) {
+ try {
+
+ Particle particle = Particle.valueOf(name);
+ SPAWN_PARTICLE.invoke(location.getWorld(), particle, location, 1, data);
+
+ } catch (IllegalArgumentException e) {
+ throw new IllegalArgumentException("Particle " + name + " does not exist.");
+
+ } catch (InvocationTargetException | IllegalAccessException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public String getTPSColored() {
+ double tps = MinecraftServer.getServer().recentTps[0];
+ String color = (tps > 18 ? "§a" : tps > 16 ? "§e" : "§c");
+ String asterisk = (tps > 20 ? "*" : "");
+ return color + asterisk + Math.min(Math.round(tps * 100.0) / 100.0, 20.0);
+ }
+
+ @Override
+ public void hideArmor(Player player) {
+ EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
+ PlayerChunkMap.EntityTracker tracker = entityPlayer.tracker;
+
+ if (tracker != null) {
+ List> items = new ArrayList<>();
+
+ items.add(new Pair<>(EnumItemSlot.c, CraftItemStack.asNMSCopy(null)));
+ items.add(new Pair<>(EnumItemSlot.d, CraftItemStack.asNMSCopy(null)));
+ items.add(new Pair<>(EnumItemSlot.e, CraftItemStack.asNMSCopy(null)));
+ items.add(new Pair<>(EnumItemSlot.f, CraftItemStack.asNMSCopy(null)));
+
+ tracker.a(new PacketPlayOutEntityEquipment(player.getEntityId(), items));
+ }
+ }
+
+ @Override
+ public void showArmor(Player player) {
+ EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
+ PlayerChunkMap.EntityTracker tracker = entityPlayer.tracker;
+
+ if (tracker != null) {
+ org.bukkit.inventory.PlayerInventory inventory = player.getInventory();
+ List> items = new ArrayList<>();
+
+ items.add(new Pair<>(EnumItemSlot.c, CraftItemStack.asNMSCopy(inventory.getBoots())));
+ items.add(new Pair<>(EnumItemSlot.d, CraftItemStack.asNMSCopy(inventory.getLeggings())));
+ items.add(new Pair<>(EnumItemSlot.e, CraftItemStack.asNMSCopy(inventory.getChestplate())));
+ items.add(new Pair<>(EnumItemSlot.f, CraftItemStack.asNMSCopy(inventory.getHelmet())));
+
+ tracker.a(new PacketPlayOutEntityEquipment(player.getEntityId(), items));
+ }
+ }
+
+ @Override
+ public void handleNettyListener(Player player) {
+ EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
+ ChannelPipeline pipeline = entityPlayer.b.a.m.pipeline();
+ AbilityManager abilityManager = getInstance().getAbilityManager();
+ InvisibilityAbility ability = (InvisibilityAbility) abilityManager.getAbility("Invisibility");
+ GhostClass ghostClass = getInstance().getClassManager().getGhostClass();
+
+ if (pipeline.get("packet_handler") == null) {
+ player.kickPlayer(Config.COULD_NOT_LOAD_DATA);
+ return;
+ }
+
+ pipeline.addBefore("packet_handler", "Azurite", new ChannelDuplexHandler() {
+ @Override
+ public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
+ if (msg instanceof PacketPlayOutEntityEquipment packet) {
+ Entity entity = ((CraftWorld) player.getWorld()).getHandle().O.d().a((int) ENTITY_ID.get(packet));
+
+ if (entity != null) {
+ if (ghostClass != null && ghostClass.getInvisible().contains(entity.getBukkitEntity().getUniqueId())) {
+ List> slot =
+ (List>) SLOT.get(packet);
+
+ Iterator> iterator = slot.iterator();
+
+ while (iterator.hasNext()) {
+ Pair pair = iterator.next();
+
+ if (pair.getFirst().a() == EnumItemSlot.Function.b) {
+ iterator.remove();
+ }
+ }
+ }
+
+ if (ability.getInvisible().contains(entity.getBukkitEntity().getUniqueId())) {
+ List> slot =
+ (List>) SLOT.get(packet);
+
+ Iterator> iterator = slot.iterator();
+
+ while (iterator.hasNext()) {
+ Pair pair = iterator.next();
+
+ if (pair.getFirst().a() == EnumItemSlot.Function.b) {
+ iterator.remove();
+ }
+ }
+ }
+ }
+ } else if (msg instanceof PacketPlayOutPlayerInfo) {
+ PacketPlayOutPlayerInfo packet = (PacketPlayOutPlayerInfo) msg;
+ PacketPlayOutPlayerInfo.EnumPlayerInfoAction action = (PacketPlayOutPlayerInfo.EnumPlayerInfoAction) ACTION.get(packet);
+ Nametag nametag = getInstance().getNametagManager().getNametags().get(player.getUniqueId());
+
+ if (action == PacketPlayOutPlayerInfo.EnumPlayerInfoAction.a && nametag != null) {
+ List data = (List) DATA.get(packet);
+
+ for (PacketPlayOutPlayerInfo.PlayerInfoData info : data) {
+ Player targetPlayer = Bukkit.getPlayer(info.a().getId());
+
+ if (targetPlayer == null) continue;
+
+ // Make tablist sort instantly
+ nametag.getPacket().create("tablist", "", "", "", false, NameVisibility.ALWAYS);
+ nametag.getPacket().addToTeam(targetPlayer, "tablist");
+ }
+ }
+ }
+
+ super.write(ctx, msg, promise);
+ }
+ });
+ }
+
+ @Override
+ public void sendActionBar(Player player, String string) {
+ ClientboundSetActionBarTextPacket packet = new ClientboundSetActionBarTextPacket(CraftChatMessage.fromJSONOrString(string, true));
+ ((CraftPlayer) player).getHandle().b.a(packet);
+ }
+
+ @Override
+ public void sendToServer(Player player, String server) {
+ ByteArrayDataOutput out = ByteStreams.newDataOutput();
+ out.writeUTF("Connect");
+ out.writeUTF(server);
+ player.sendPluginMessage(getInstance(), "BungeeCord", out.toByteArray());
+ }
+
+ @Override
+ public void clearArrows(Player player) {
+ ((CraftPlayer) player).getHandle().setArrowCount(0, false);
+ }
+
+ @Override
+ public List getBlockDrops(Player pl, Block bl, ItemStack hand) {
+ EntityPlayer serverPlayer = ((CraftPlayer) pl).getHandle();
+ WorldServer serverLevel = serverPlayer.s.getMinecraftWorld();
+ BlockPosition blockPos = new BlockPosition(bl.getX(), bl.getY(), bl.getZ());
+ IBlockData blockState = serverLevel.a_(blockPos);
+ TileEntity blockEntity = serverLevel.c_(blockPos);
+
+ return net.minecraft.world.level.block.Block.a(blockState, serverLevel, blockPos, blockEntity, serverPlayer, serverPlayer.es())
+ .stream().map(CraftItemStack::asBukkitCopy).collect(Collectors.toList());
+ }
+
+ @Override
+ public TablistSkin getSkinData(Player player) {
+ EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
+ GameProfile profile = entityPlayer.bc.cs;
+
+ if (profile.getProperties().get("textures").size() == 0) {
+ return null;
+ }
+
+ Property property = profile.getProperties().get("textures").iterator().next();
+ return new TablistSkin(property.getValue(), property.getSignature());
+ }
+}
\ No newline at end of file
diff --git a/Azurite1.19/libs/1.19.jar b/Azurite1.19/libs/1.19.jar
new file mode 100644
index 0000000..51afa18
Binary files /dev/null and b/Azurite1.19/libs/1.19.jar differ