package net.minecraft.client.resources.model; import com.google.gson.JsonElement; import com.google.gson.JsonParseException; import com.google.gson.JsonParser; import com.mojang.logging.LogUtils; import com.mojang.serialization.JsonOps; import java.io.Reader; import java.util.ArrayList; import java.util.IdentityHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; import java.util.function.Function; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.Util; import net.minecraft.client.renderer.block.model.BlockModelDefinition; import net.minecraft.client.renderer.block.model.BlockStateModel; import net.minecraft.resources.FileToIdConverter; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.packs.resources.Resource; import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.StateDefinition; import org.slf4j.Logger; @Environment(EnvType.CLIENT) public class BlockStateModelLoader { private static final Logger LOGGER = LogUtils.getLogger(); private static final FileToIdConverter BLOCKSTATE_LISTER = FileToIdConverter.json("blockstates"); public static CompletableFuture loadBlockStates(ResourceManager resourceManager, Executor executor) { Function> function = BlockStateDefinitions.definitionLocationToBlockStateMapper(); return CompletableFuture.supplyAsync(() -> BLOCKSTATE_LISTER.listMatchingResourceStacks(resourceManager), executor).thenCompose(map -> { List> list = new ArrayList(map.size()); for (Entry> entry : map.entrySet()) { list.add(CompletableFuture.supplyAsync(() -> { ResourceLocation resourceLocation = BLOCKSTATE_LISTER.fileToId((ResourceLocation)entry.getKey()); StateDefinition stateDefinition = (StateDefinition)function.apply(resourceLocation); if (stateDefinition == null) { LOGGER.debug("Discovered unknown block state definition {}, ignoring", resourceLocation); return null; } else { List listx = (List)entry.getValue(); List list2 = new ArrayList(listx.size()); for (Resource resource : listx) { try { Reader reader = resource.openAsReader(); try { JsonElement jsonElement = JsonParser.parseReader(reader); BlockModelDefinition blockModelDefinition = BlockModelDefinition.CODEC.parse(JsonOps.INSTANCE, jsonElement).getOrThrow(JsonParseException::new); list2.add(new BlockStateModelLoader.LoadedBlockModelDefinition(resource.sourcePackId(), blockModelDefinition)); } catch (Throwable var13) { if (reader != null) { try { reader.close(); } catch (Throwable var12) { var13.addSuppressed(var12); } } throw var13; } if (reader != null) { reader.close(); } } catch (Exception var14) { LOGGER.error("Failed to load blockstate definition {} from pack {}", resourceLocation, resource.sourcePackId(), var14); } } try { return loadBlockStateDefinitionStack(resourceLocation, stateDefinition, list2); } catch (Exception var11) { LOGGER.error("Failed to load blockstate definition {}", resourceLocation, var11); return null; } } }, executor)); } return Util.sequence(list).thenApply(listx -> { Map mapx = new IdentityHashMap(); for (BlockStateModelLoader.LoadedModels loadedModels : listx) { if (loadedModels != null) { mapx.putAll(loadedModels.models()); } } return new BlockStateModelLoader.LoadedModels(mapx); }); }); } private static BlockStateModelLoader.LoadedModels loadBlockStateDefinitionStack( ResourceLocation blockStateId, StateDefinition stateDefinition, List modelDefinitions ) { Map map = new IdentityHashMap(); for (BlockStateModelLoader.LoadedBlockModelDefinition loadedBlockModelDefinition : modelDefinitions) { map.putAll(loadedBlockModelDefinition.contents.instantiate(stateDefinition, () -> blockStateId + "/" + loadedBlockModelDefinition.source)); } return new BlockStateModelLoader.LoadedModels(map); } @Environment(EnvType.CLIENT) record LoadedBlockModelDefinition(String source, BlockModelDefinition contents) { } @Environment(EnvType.CLIENT) public record LoadedModels(Map models) { } }