diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/commands/PropertiesCommand.java b/plugin/src/main/java/lol/pyr/znpcsplus/commands/PropertiesCommand.java
index 1faa16c..b8925d5 100644
--- a/plugin/src/main/java/lol/pyr/znpcsplus/commands/PropertiesCommand.java
+++ b/plugin/src/main/java/lol/pyr/znpcsplus/commands/PropertiesCommand.java
@@ -1,5 +1,6 @@
 package lol.pyr.znpcsplus.commands;
 
+import io.github.retrooper.packetevents.util.SpigotConversionUtil;
 import lol.pyr.director.adventure.command.CommandContext;
 import lol.pyr.director.adventure.command.CommandHandler;
 import lol.pyr.director.common.command.CommandExecutionException;
@@ -10,6 +11,7 @@ import lol.pyr.znpcsplus.npc.NpcImpl;
 import lol.pyr.znpcsplus.npc.NpcRegistryImpl;
 import net.kyori.adventure.text.Component;
 import net.kyori.adventure.text.format.NamedTextColor;
+import com.github.retrooper.packetevents.protocol.item.ItemStack;
 
 import java.util.Collections;
 import java.util.List;
@@ -23,15 +25,32 @@ public class PropertiesCommand implements CommandHandler {
 
     @Override
     public void run(CommandContext context) throws CommandExecutionException {
+        context.setUsage(context.getLabel() + " properties <id> <property> <value>");
         NpcEntryImpl entry = context.parse(NpcEntryImpl.class);
         NpcImpl npc = entry.getNpc();
         EntityPropertyImpl<?> property = context.parse(EntityPropertyImpl.class);
 
-        if (!npc.getType().getAllowedProperties().contains(property)) context.halt(Component.text("Property " + property.getName() + " not allowed for npc type " + npc.getType().getName()));
+        if (!npc.getType().getAllowedProperties().contains(property)) context.halt(Component.text("Property " + property.getName() + " not allowed for npc type " + npc.getType().getName(), NamedTextColor.RED));
+        Class<?> type = property.getType();
+        Object value;
+        String valueName;
+        if (type == ItemStack.class) {
+            org.bukkit.inventory.ItemStack bukkitStack = context.ensureSenderIsPlayer().getInventory().getItemInMainHand();
+            if (bukkitStack.getType().isAir()) {
+                value = null;
+                valueName = "EMPTY";
+            } else {
+                value = SpigotConversionUtil.fromBukkitItemStack(bukkitStack);
+                valueName = bukkitStack.toString();
+            }
+        }
+        else {
+            value = context.parse(property.getType());
+            valueName = String.valueOf(value);
+        }
 
-        Object value = context.parse(property.getType());
         npc.UNSAFE_setProperty(property, value);
-        context.send(Component.text("Set property " + property.getName() + " for NPC " + entry.getId() + " to " + value.toString(), NamedTextColor.GREEN));
+        context.send(Component.text("Set property " + property.getName() + " for NPC " + entry.getId() + " to " + valueName, NamedTextColor.GREEN));
     }
 
     @Override
diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java
index 3cf1dae..55bcf21 100644
--- a/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java
+++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java
@@ -1,11 +1,9 @@
 package lol.pyr.znpcsplus.entity;
 
+import com.github.retrooper.packetevents.protocol.item.ItemStack;
 import lol.pyr.znpcsplus.api.entity.EntityPropertyRegistry;
 import lol.pyr.znpcsplus.api.skin.SkinDescriptor;
-import lol.pyr.znpcsplus.entity.serializers.BooleanPropertySerializer;
-import lol.pyr.znpcsplus.entity.serializers.ComponentPropertySerializer;
-import lol.pyr.znpcsplus.entity.serializers.NamedTextColorPropertySerializer;
-import lol.pyr.znpcsplus.entity.serializers.SkinDescriptorSerializer;
+import lol.pyr.znpcsplus.entity.serializers.*;
 import lol.pyr.znpcsplus.skin.cache.SkinCache;
 import net.kyori.adventure.text.Component;
 import net.kyori.adventure.text.format.NamedTextColor;
@@ -23,6 +21,7 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
         registerSerializer(new ComponentPropertySerializer());
         registerSerializer(new NamedTextColorPropertySerializer());
         registerSerializer(new SkinDescriptorSerializer(skinCache));
+        registerSerializer(new ItemStackPropertySerializer());
 
         registerType("glow", NamedTextColor.class);
         registerType("skin_layers", true);
@@ -32,6 +31,13 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
         registerType("skin", SkinDescriptor.class);
         registerType("name", Component.class);
         registerType("look", false);
+
+        registerType("helmet", ItemStack.class);
+        registerType("chestplate", ItemStack.class);
+        registerType("leggings", ItemStack.class);
+        registerType("boots", ItemStack.class);
+        registerType("hand", ItemStack.class);
+        registerType("offhand", ItemStack.class);
     }
 
     private void registerSerializer(PropertySerializer<?> serializer) {
diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/serializers/ItemStackPropertySerializer.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/serializers/ItemStackPropertySerializer.java
new file mode 100644
index 0000000..c6f1cb5
--- /dev/null
+++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/serializers/ItemStackPropertySerializer.java
@@ -0,0 +1,23 @@
+package lol.pyr.znpcsplus.entity.serializers;
+
+import com.github.retrooper.packetevents.protocol.item.ItemStack;
+import io.github.retrooper.packetevents.util.SpigotConversionUtil;
+import lol.pyr.znpcsplus.entity.PropertySerializer;
+import lol.pyr.znpcsplus.util.ItemSerializationUtil;
+
+public class ItemStackPropertySerializer implements PropertySerializer<ItemStack> {
+    @Override
+    public String serialize(ItemStack property) {
+        return ItemSerializationUtil.itemToB64(SpigotConversionUtil.toBukkitItemStack(property));
+    }
+
+    @Override
+    public ItemStack deserialize(String property) {
+        return SpigotConversionUtil.fromBukkitItemStack(ItemSerializationUtil.itemFromB64(property));
+    }
+
+    @Override
+    public Class<ItemStack> getTypeClass() {
+        return ItemStack.class;
+    }
+}
diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java
index f0c3a80..fa5faad 100644
--- a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java
+++ b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java
@@ -114,8 +114,7 @@ public class NpcImpl extends Viewable implements Npc {
     }
 
     public <T> void setProperty(EntityPropertyImpl<T> key, T value) {
-        if (value == null) return;
-        if (value.equals(key.getDefaultValue())) removeProperty(key);
+        if (value == null || value.equals(key.getDefaultValue())) removeProperty(key);
         else propertyMap.put(key, value);
         UNSAFE_refreshMeta();
         if (key.getName().equalsIgnoreCase("glow")) UNSAFE_remakeTeam();
diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeImpl.java
index 7a1d8e9..31669d8 100644
--- a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeImpl.java
+++ b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeImpl.java
@@ -59,6 +59,11 @@ public class NpcTypeImpl implements NpcType {
             return this;
         }
 
+        public Builder addProperties(String... names) {
+            for (String name : names) allowedProperties.add(propertyRegistry.getByName(name));
+            return this;
+        }
+
         public Builder setEnableGlobalProperties(boolean enabled) {
             globalProperties = enabled;
             return this;
diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeRegistryImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeRegistryImpl.java
index 7754f23..e765e86 100644
--- a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeRegistryImpl.java
+++ b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeRegistryImpl.java
@@ -29,7 +29,7 @@ public class NpcTypeRegistryImpl implements NpcTypeRegistry {
         ServerVersion version = packetEvents.getServerManager().getVersion();
 
         register(new NpcTypeImpl.Builder(propertyRegistry, "player", EntityTypes.PLAYER).setHologramOffset(-0.15D)
-                .addProperties(propertyRegistry.getByName("skin"),  propertyRegistry.getByName("skin_layers")));
+                .addProperties("skin", "skin_layers", "helmet", "chestplate", "leggings", "boots", "hand", "offhand"));
 
         register(new NpcTypeImpl.Builder(propertyRegistry, "armor_stand", EntityTypes.ARMOR_STAND));
         register(new NpcTypeImpl.Builder(propertyRegistry, "bat", EntityTypes.BAT).setHologramOffset(-1.365));
diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java b/plugin/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java
index 81244cb..a7ae861 100644
--- a/plugin/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java
+++ b/plugin/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java
@@ -21,4 +21,5 @@ public interface PacketFactory {
     Map<Integer, EntityData> generateMetadata(Player player, PacketEntity entity, PropertyHolder properties);
     void sendAllMetadata(Player player, PacketEntity entity, PropertyHolder properties);
     void sendMetadata(Player player, PacketEntity entity, List<EntityData> data);
+    void sendEquipment(Player player, PacketEntity entity, PropertyHolder properties);
 }
diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_16PacketFactory.java b/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_16PacketFactory.java
new file mode 100644
index 0000000..354d0a9
--- /dev/null
+++ b/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_16PacketFactory.java
@@ -0,0 +1,26 @@
+package lol.pyr.znpcsplus.packets;
+
+import com.github.retrooper.packetevents.PacketEventsAPI;
+import com.github.retrooper.packetevents.protocol.player.Equipment;
+import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityEquipment;
+import lol.pyr.znpcsplus.api.entity.PropertyHolder;
+import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl;
+import lol.pyr.znpcsplus.entity.PacketEntity;
+import lol.pyr.znpcsplus.metadata.MetadataFactory;
+import lol.pyr.znpcsplus.scheduling.TaskScheduler;
+import org.bukkit.entity.Player;
+import org.bukkit.plugin.Plugin;
+
+import java.util.List;
+
+public class V1_16PacketFactory extends V1_14PacketFactory {
+    public V1_16PacketFactory(TaskScheduler scheduler, MetadataFactory metadataFactory, PacketEventsAPI<Plugin> packetEvents, EntityPropertyRegistryImpl propertyRegistry) {
+        super(scheduler, metadataFactory, packetEvents, propertyRegistry);
+    }
+
+    @Override
+    public void sendEquipment(Player player, PacketEntity entity, PropertyHolder properties) {
+        List<Equipment> equipments = generateEquipments(properties);
+        if (equipments.size() > 0) sendPacket(player, new WrapperPlayServerEntityEquipment(entity.getEntityId(), equipments));
+    }
+}
diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_19PacketFactory.java b/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_19PacketFactory.java
index e54875e..cc29fcf 100644
--- a/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_19PacketFactory.java
+++ b/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_19PacketFactory.java
@@ -18,7 +18,7 @@ import org.bukkit.plugin.Plugin;
 import java.util.EnumSet;
 import java.util.concurrent.CompletableFuture;
 
-public class V1_19PacketFactory extends V1_14PacketFactory {
+public class V1_19PacketFactory extends V1_16PacketFactory {
     public V1_19PacketFactory(TaskScheduler scheduler, MetadataFactory metadataFactory, PacketEventsAPI<Plugin> packetEvents, EntityPropertyRegistryImpl propertyRegistry) {
         super(scheduler, metadataFactory, packetEvents, propertyRegistry);
     }
diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_8PacketFactory.java b/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_8PacketFactory.java
index 8b22ac0..513d1da 100644
--- a/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_8PacketFactory.java
+++ b/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_8PacketFactory.java
@@ -4,14 +4,15 @@ import com.github.retrooper.packetevents.PacketEventsAPI;
 import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
 import com.github.retrooper.packetevents.protocol.entity.type.EntityType;
 import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
-import com.github.retrooper.packetevents.protocol.player.ClientVersion;
-import com.github.retrooper.packetevents.protocol.player.GameMode;
-import com.github.retrooper.packetevents.protocol.player.UserProfile;
+import com.github.retrooper.packetevents.protocol.item.ItemStack;
+import com.github.retrooper.packetevents.protocol.item.type.ItemTypes;
+import com.github.retrooper.packetevents.protocol.player.*;
 import com.github.retrooper.packetevents.util.Vector3d;
 import com.github.retrooper.packetevents.wrapper.PacketWrapper;
 import com.github.retrooper.packetevents.wrapper.play.server.*;
 import lol.pyr.znpcsplus.api.entity.PropertyHolder;
 import lol.pyr.znpcsplus.api.skin.SkinDescriptor;
+import lol.pyr.znpcsplus.entity.EntityPropertyImpl;
 import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl;
 import lol.pyr.znpcsplus.entity.PacketEntity;
 import lol.pyr.znpcsplus.metadata.MetadataFactory;
@@ -135,6 +136,7 @@ public class V1_8PacketFactory implements PacketFactory {
     @Override
     public void sendAllMetadata(Player player, PacketEntity entity, PropertyHolder properties) {
         sendMetadata(player, entity, new ArrayList<>(generateMetadata(player, entity, properties).values()));
+        sendEquipment(player, entity, properties);
     }
 
     @Override
@@ -142,6 +144,37 @@ public class V1_8PacketFactory implements PacketFactory {
         packetEvents.getPlayerManager().sendPacket(player, new WrapperPlayServerEntityMetadata(entity.getEntityId(), data));
     }
 
+    @Override
+    public void sendEquipment(Player player, PacketEntity entity, PropertyHolder properties) {
+        for (Equipment equipment : generateEquipments(properties))
+            sendPacket(player, new WrapperPlayServerEntityEquipment(entity.getEntityId(), Collections.singletonList(equipment)));
+    }
+
+    protected List<Equipment> generateEquipments(PropertyHolder properties) {
+        List<Equipment> equipements = new ArrayList<>();
+        ItemStack air = new ItemStack.Builder().type(ItemTypes.AIR).build();
+
+        EntityPropertyImpl<ItemStack> helmet = propertyRegistry.getByName("helmet", ItemStack.class);
+        equipements.add(new Equipment(EquipmentSlot.HELMET, properties.hasProperty(helmet) ? properties.getProperty(helmet) : air));
+
+        EntityPropertyImpl<ItemStack> chestplate = propertyRegistry.getByName("chestplate", ItemStack.class);
+        equipements.add(new Equipment(EquipmentSlot.CHEST_PLATE, properties.hasProperty(chestplate) ? properties.getProperty(chestplate) : air));
+
+        EntityPropertyImpl<ItemStack> leggings = propertyRegistry.getByName("leggings", ItemStack.class);
+        equipements.add(new Equipment(EquipmentSlot.LEGGINGS, properties.hasProperty(leggings) ? properties.getProperty(leggings) : air));
+
+        EntityPropertyImpl<ItemStack> boots = propertyRegistry.getByName("boots", ItemStack.class);
+        equipements.add(new Equipment(EquipmentSlot.BOOTS, properties.hasProperty(boots) ? properties.getProperty(boots) : air));
+
+        EntityPropertyImpl<ItemStack> hand = propertyRegistry.getByName("hand", ItemStack.class);
+        equipements.add(new Equipment(EquipmentSlot.MAIN_HAND, properties.hasProperty(hand) ? properties.getProperty(hand) : air));
+
+        EntityPropertyImpl<ItemStack> offhand = propertyRegistry.getByName("offhand", ItemStack.class);
+        equipements.add(new Equipment(EquipmentSlot.OFF_HAND, properties.hasProperty(offhand) ? properties.getProperty(offhand) : air));
+
+        return equipements;
+    }
+
     protected void sendPacket(Player player, PacketWrapper<?> packet) {
         packetEvents.getPlayerManager().sendPacket(player, packet);
     }
diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/util/ItemSerializationUtil.java b/plugin/src/main/java/lol/pyr/znpcsplus/util/ItemSerializationUtil.java
new file mode 100644
index 0000000..1959845
--- /dev/null
+++ b/plugin/src/main/java/lol/pyr/znpcsplus/util/ItemSerializationUtil.java
@@ -0,0 +1,41 @@
+package lol.pyr.znpcsplus.util;
+
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.util.io.BukkitObjectInputStream;
+import org.bukkit.util.io.BukkitObjectOutputStream;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Base64;
+
+public class ItemSerializationUtil {
+    public static byte[] itemToBytes(ItemStack item) {
+        ByteArrayOutputStream bout = new ByteArrayOutputStream();
+        try {
+            new BukkitObjectOutputStream(bout).writeObject(item);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        return bout.toByteArray();
+    }
+
+    public static ItemStack itemFromBytes(byte[] bytes) {
+        ByteArrayInputStream bin = new ByteArrayInputStream(bytes);
+        try {
+            return (ItemStack) new BukkitObjectInputStream(bin).readObject();
+        } catch (IOException | ClassNotFoundException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static String itemToB64(ItemStack item) {
+        if (item == null) return null;
+        return Base64.getEncoder().encodeToString(itemToBytes(item));
+    }
+
+    public static ItemStack itemFromB64(String str) {
+        if (str == null) return null;
+        return itemFromBytes(Base64.getDecoder().decode(str));
+    }
+}