--- a/net/minecraft/nbt/CompoundTag.java
+++ b/net/minecraft/nbt/CompoundTag.java
@@ -46,7 +46,7 @@
 
         private static CompoundTag loadCompound(DataInput input, NbtAccounter tracker) throws IOException {
             tracker.accountBytes(48L);
-            Map<String, Tag> map = Maps.newHashMap();
+            it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<String, Tag> map = new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>(8, 0.8f); // Paper - reduce memory footprint of NBTTagCompound
 
             byte b;
             while((b = input.readByte()) != 0) {
@@ -160,14 +160,14 @@
             return "TAG_Compound";
         }
     };
-    private final Map<String, Tag> tags;
+    public final Map<String, Tag> tags; // Paper
 
     protected CompoundTag(Map<String, Tag> entries) {
         this.tags = entries;
     }
 
     public CompoundTag() {
-        this(Maps.newHashMap());
+        this(new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>(8, 0.8f)); // Paper - reduce memory footprint of NBTTagCompound
     }
 
     @Override
@@ -233,14 +233,34 @@
     }
 
     public void putUUID(String key, UUID value) {
+        // Paper start - support old format
+        if (this.contains(key + "Most", 99) && this.contains(key + "Least", 99)) {
+            this.tags.remove(key + "Most");
+            this.tags.remove(key + "Least");
+        }
+        // Paper end
         this.tags.put(key, NbtUtils.createUUID(value));
     }
 
+
+    /**
+     * You must use {@link #hasUUID(String)} before or else it <b>will</b> throw an NPE.
+     */
     public UUID getUUID(String key) {
+        // Paper start - support old format
+        if (!contains(key, 11) && this.contains(key + "Most", 99) && this.contains(key + "Least", 99)) {
+            return new UUID(this.getLong(key + "Most"), this.getLong(key + "Least"));
+        }
+        // Paper end
         return NbtUtils.loadUUID(this.get(key));
     }
 
     public boolean hasUUID(String key) {
+        // Paper start - support old format
+        if (this.contains(key + "Most", 99) && this.contains(key + "Least", 99)) {
+            return true;
+        }
+        // Paper end
         Tag tag = this.get(key);
         return tag != null && tag.getType() == IntArrayTag.TYPE && ((IntArrayTag)tag).getAsIntArray().length == 4;
     }
@@ -482,8 +502,16 @@
 
     @Override
     public CompoundTag copy() {
-        Map<String, Tag> map = Maps.newHashMap(Maps.transformValues(this.tags, Tag::copy));
-        return new CompoundTag(map);
+        // Paper start - reduce memory footprint of NBTTagCompound
+        it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<String, Tag> ret = new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>(this.tags.size(), 0.8f);
+        java.util.Iterator<java.util.Map.Entry<String, Tag>> iterator = (this.tags instanceof it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap) ? ((it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap)this.tags).object2ObjectEntrySet().fastIterator() : this.tags.entrySet().iterator();
+        while (iterator.hasNext()) {
+            Map.Entry<String, Tag> entry = iterator.next();
+            ret.put(entry.getKey(), entry.getValue().copy());
+        }
+
+        return new CompoundTag(ret);
+        // Paper end - reduce memory footprint of NBTTagCompound
     }
 
     @Override
