--- a/net/minecraft/world/level/storage/loot/LootDataManager.java
+++ b/net/minecraft/world/level/storage/loot/LootDataManager.java
@@ -1,6 +1,7 @@
 package net.minecraft.world.level.storage.loot;
 
 import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMap.Builder;
 import com.google.common.collect.ImmutableMultimap;
 import com.google.common.collect.Multimap;
 import com.google.gson.Gson;
@@ -10,6 +11,7 @@
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Objects;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.Executor;
 import javax.annotation.Nullable;
@@ -22,80 +24,97 @@
 import org.slf4j.Logger;
 
 public class LootDataManager implements PreparableReloadListener, LootDataResolver {
+
     private static final Logger LOGGER = LogUtils.getLogger();
     private static final Gson GSON = (new GsonBuilder()).create();
     public static final LootDataId<LootTable> EMPTY_LOOT_TABLE_KEY = new LootDataId<>(LootDataType.TABLE, BuiltInLootTables.EMPTY);
     private Map<LootDataId<?>, ?> elements = Map.of();
     private Multimap<LootDataType<?>, ResourceLocation> typeKeys = ImmutableMultimap.of();
+    public Map<?, ResourceLocation> lootTableToKey = ImmutableMap.of(); // CraftBukkit
+
+    public LootDataManager() {}
 
     @Override
     public final CompletableFuture<Void> reload(PreparableReloadListener.PreparationBarrier synchronizer, ResourceManager manager, ProfilerFiller prepareProfiler, ProfilerFiller applyProfiler, Executor prepareExecutor, Executor applyExecutor) {
-        Map<LootDataType<?>, Map<ResourceLocation, ?>> map = new HashMap<>();
-        CompletableFuture<?>[] completableFutures = LootDataType.values().map((type) -> {
-            return scheduleElementParse(type, manager, prepareExecutor, map);
+        Map<LootDataType<?>, Map<ResourceLocation, ?>> map = new HashMap();
+        CompletableFuture<?>[] acompletablefuture = (CompletableFuture[]) LootDataType.values().map((lootdatatype) -> {
+            return LootDataManager.scheduleElementParse(lootdatatype, manager, prepareExecutor, map);
         }).toArray((i) -> {
             return new CompletableFuture[i];
         });
-        return CompletableFuture.allOf(completableFutures).thenCompose(synchronizer::wait).thenAcceptAsync((v) -> {
+        CompletableFuture completablefuture = CompletableFuture.allOf(acompletablefuture);
+
+        Objects.requireNonNull(synchronizer);
+        return completablefuture.thenCompose(synchronizer::wait).thenAcceptAsync((ovoid) -> {
             this.apply(map);
         }, applyExecutor);
     }
 
     private static <T> CompletableFuture<?> scheduleElementParse(LootDataType<T> type, ResourceManager resourceManager, Executor executor, Map<LootDataType<?>, Map<ResourceLocation, ?>> results) {
-        Map<ResourceLocation, T> map = new HashMap<>();
-        results.put(type, map);
+        Map<ResourceLocation, T> map1 = new HashMap();
+
+        results.put(type, map1);
         return CompletableFuture.runAsync(() -> {
-            Map<ResourceLocation, JsonElement> map2 = new HashMap<>();
-            SimpleJsonResourceReloadListener.scanDirectory(resourceManager, type.directory(), GSON, map2);
-            map2.forEach((id, json) -> {
-                type.deserialize(id, json).ifPresent((value) -> {
-                    map.put(id, value);
+            Map<ResourceLocation, JsonElement> map2 = new HashMap();
+
+            SimpleJsonResourceReloadListener.scanDirectory(resourceManager, type.directory(), LootDataManager.GSON, map2);
+            map2.forEach((minecraftkey, jsonelement) -> {
+                type.deserialize(minecraftkey, jsonelement).ifPresent((object) -> {
+                    map1.put(minecraftkey, object);
                 });
             });
         }, executor);
     }
 
     private void apply(Map<LootDataType<?>, Map<ResourceLocation, ?>> lootData) {
-        Object object = lootData.get(LootDataType.TABLE).remove(BuiltInLootTables.EMPTY);
+        Object object = ((Map) lootData.get(LootDataType.TABLE)).remove(BuiltInLootTables.EMPTY);
+
         if (object != null) {
-            LOGGER.warn("Datapack tried to redefine {} loot table, ignoring", (Object)BuiltInLootTables.EMPTY);
+            LootDataManager.LOGGER.warn("Datapack tried to redefine {} loot table, ignoring", BuiltInLootTables.EMPTY);
         }
 
-        ImmutableMap.Builder<LootDataId<?>, Object> builder = ImmutableMap.builder();
-        ImmutableMultimap.Builder<LootDataType<?>, ResourceLocation> builder2 = ImmutableMultimap.builder();
-        lootData.forEach((type, idToValue) -> {
-            idToValue.forEach((id, value) -> {
-                builder.put(new LootDataId(type, id), value);
-                builder2.put(type, id);
+        Builder<LootDataId<?>, Object> builder = ImmutableMap.builder();
+        com.google.common.collect.ImmutableMultimap.Builder<LootDataType<?>, ResourceLocation> com_google_common_collect_immutablemultimap_builder = ImmutableMultimap.builder();
+
+        lootData.forEach((lootdatatype, map1) -> {
+            map1.forEach((minecraftkey, object1) -> {
+                builder.put(new LootDataId<>(lootdatatype, minecraftkey), object1);
+                com_google_common_collect_immutablemultimap_builder.put(lootdatatype, minecraftkey);
             });
         });
-        builder.put(EMPTY_LOOT_TABLE_KEY, LootTable.EMPTY);
-        final Map<LootDataId<?>, ?> map = builder.build();
-        ValidationContext validationContext = new ValidationContext(LootContextParamSets.ALL_PARAMS, new LootDataResolver() {
+        builder.put(LootDataManager.EMPTY_LOOT_TABLE_KEY, LootTable.EMPTY);
+        final Map<LootDataId<?>, ?> map1 = builder.build();
+        ValidationContext lootcollector = new ValidationContext(LootContextParamSets.ALL_PARAMS, new LootDataResolver() {
             @Nullable
             @Override
             public <T> T getElement(LootDataId<T> key) {
-                return (T)map.get(key);
+                return (T) map1.get(key); // CraftBukkit - decompile error
             }
         });
-        map.forEach((key, value) -> {
-            castAndValidate(validationContext, key, value);
+
+        map1.forEach((lootdataid, object1) -> {
+            LootDataManager.castAndValidate(lootcollector, lootdataid, object1);
         });
-        validationContext.getProblems().forEach((name, message) -> {
-            LOGGER.warn("Found loot table element validation problem in {}: {}", name, message);
+        lootcollector.getProblems().forEach((s, s1) -> {
+            LootDataManager.LOGGER.warn("Found loot table element validation problem in {}: {}", s, s1);
         });
-        this.elements = map;
-        this.typeKeys = builder2.build();
+        this.elements = map1;
+        this.typeKeys = com_google_common_collect_immutablemultimap_builder.build();
+        // CraftBukkit start - build a reversed registry map
+        ImmutableMap.Builder<Object, ResourceLocation> lootTableToKeyBuilder = ImmutableMap.builder();
+        this.elements.forEach((key, lootTable) -> lootTableToKeyBuilder.put((Object) lootTable, key.location()));
+        this.lootTableToKey = lootTableToKeyBuilder.build();
+        // CraftBukkit end
     }
 
     private static <T> void castAndValidate(ValidationContext reporter, LootDataId<T> key, Object value) {
-        key.type().runValidation(reporter, key, (T)value);
+        key.type().runValidation(reporter, key, (T) value); // CraftBukkit - decompile error
     }
 
     @Nullable
     @Override
     public <T> T getElement(LootDataId<T> key) {
-        return (T)this.elements.get(key);
+        return (T) this.elements.get(key); // CraftBukkit - decompile error
     }
 
     public Collection<ResourceLocation> getKeys(LootDataType<?> type) {
