ModelManager.java
net.minecraft.client.resources.model.ModelManager
信息
- 全限定名:net.minecraft.client.resources.model.ModelManager
- 类型:public class
- 包:net.minecraft.client.resources.model
- 源码路径:src/main/java/net/minecraft/client/resources/model/ModelManager.java
- 起始行号:L66
- 实现:PreparableReloadListener
- 职责:
TODO
字段/常量
-
LOGGER- 类型:
Logger - 修饰符:
private static final - 源码定位:
L67 - 说明:
TODO
- 类型:
-
MODEL_LISTER- 类型:
FileToIdConverter - 修饰符:
private static final - 源码定位:
L68 - 说明:
TODO
- 类型:
-
bakedItemStackModels- 类型:
Map<Identifier,ItemModel> - 修饰符:
private - 源码定位:
L69 - 说明:
TODO
- 类型:
-
itemProperties- 类型:
Map<Identifier,ClientItem.Properties> - 修饰符:
private - 源码定位:
L70 - 说明:
TODO
- 类型:
-
atlasManager- 类型:
AtlasManager - 修饰符:
private final - 源码定位:
L71 - 说明:
TODO
- 类型:
-
playerSkinRenderCache- 类型:
PlayerSkinRenderCache - 修饰符:
private final - 源码定位:
L72 - 说明:
TODO
- 类型:
-
blockColors- 类型:
BlockColors - 修饰符:
private final - 源码定位:
L73 - 说明:
TODO
- 类型:
-
entityModelSet- 类型:
EntityModelSet - 修饰符:
private - 源码定位:
L74 - 说明:
TODO
- 类型:
-
missingModels- 类型:
ModelBakery.MissingModels - 修饰符:
private - 源码定位:
L75 - 说明:
TODO
- 类型:
-
blockStateModelSet- 类型:
BlockStateModelSet - 修饰符:
private - 源码定位:
L76 - 说明:
TODO
- 类型:
-
blockModelSet- 类型:
BlockModelSet - 修饰符:
private - 源码定位:
L77 - 说明:
TODO
- 类型:
-
fluidStateModelSet- 类型:
FluidStateModelSet - 修饰符:
private - 源码定位:
L78 - 说明:
TODO
- 类型:
-
modelGroups- 类型:
Object2IntMap<BlockState> - 修饰符:
private - 源码定位:
L79 - 说明:
TODO
- 类型:
内部类/嵌套类型
-
net.minecraft.client.resources.model.ModelManager.ReloadState- 类型:
record - 修饰符:
private - 源码定位:
L359 - 说明:
TODO
- 类型:
-
net.minecraft.client.resources.model.ModelManager.ResolvedModels- 类型:
record - 修饰符:
private - 源码定位:
L370 - 说明:
TODO
- 类型:
构造器
public ModelManager(BlockColors blockColors, AtlasManager atlasManager, PlayerSkinRenderCache playerSkinRenderCache) @ L81
- 构造器名:ModelManager
- 源码定位:L81
- 修饰符:public
参数:
- blockColors: BlockColors
- atlasManager: AtlasManager
- playerSkinRenderCache: PlayerSkinRenderCache
说明:
TODO
方法
下面的方法块按源码顺序生成。
public ItemModel getItemModel(Identifier id) @ L87
- 方法名:getItemModel
- 源码定位:L87
- 返回类型:ItemModel
- 修饰符:public
参数:
- id: Identifier
说明:
TODO
public ClientItem.Properties getItemProperties(Identifier id) @ L91
- 方法名:getItemProperties
- 源码定位:L91
- 返回类型:ClientItem.Properties
- 修饰符:public
参数:
- id: Identifier
说明:
TODO
public BlockStateModelSet getBlockStateModelSet() @ L95
- 方法名:getBlockStateModelSet
- 源码定位:L95
- 返回类型:BlockStateModelSet
- 修饰符:public
参数:
- 无
说明:
TODO
public BlockModelSet getBlockModelSet() @ L99
- 方法名:getBlockModelSet
- 源码定位:L99
- 返回类型:BlockModelSet
- 修饰符:public
参数:
- 无
说明:
TODO
public FluidStateModelSet getFluidStateModelSet() @ L103
- 方法名:getFluidStateModelSet
- 源码定位:L103
- 返回类型:FluidStateModelSet
- 修饰符:public
参数:
- 无
说明:
TODO
public final CompletableFuture<Void> reload(PreparableReloadListener.SharedState currentReload, Executor taskExecutor, PreparableReloadListener.PreparationBarrier preparationBarrier, Executor reloadExecutor) @ L107
- 方法名:reload
- 源码定位:L107
- 返回类型:CompletableFuture
- 修饰符:public final
参数:
- currentReload: PreparableReloadListener.SharedState
- taskExecutor: Executor
- preparationBarrier: PreparableReloadListener.PreparationBarrier
- reloadExecutor: Executor
说明:
TODO
private static CompletableFuture<Map<Identifier,UnbakedModel>> loadBlockModels(ResourceManager manager, Executor executor) @ L174
- 方法名:loadBlockModels
- 源码定位:L174
- 返回类型:CompletableFuture<Map<Identifier,UnbakedModel>>
- 修饰符:private static
参数:
- manager: ResourceManager
- executor: Executor
说明:
TODO
private static ModelManager.ResolvedModels discoverModelDependencies(Map<Identifier,UnbakedModel> allModels, BlockStateModelLoader.LoadedModels blockStateModels, ClientItemInfoLoader.LoadedClientInfos itemInfos) @ L204
- 方法名:discoverModelDependencies
- 源码定位:L204
- 返回类型:ModelManager.ResolvedModels
- 修饰符:private static
参数:
- allModels: Map<Identifier,UnbakedModel>
- blockStateModels: BlockStateModelLoader.LoadedModels
- itemInfos: ClientItemInfoLoader.LoadedClientInfos
说明:
TODO
private static CompletableFuture<ModelManager.ReloadState> loadModels(SpriteLoader.Preparations blockAtlas, SpriteLoader.Preparations itemAtlas, ModelBakery bakery, LoadedBlockModels blockModels, Object2IntMap<BlockState> modelGroups, EntityModelSet entityModelSet, Executor taskExecutor) @ L219
- 方法名:loadModels
- 源码定位:L219
- 返回类型:CompletableFuture<ModelManager.ReloadState>
- 修饰符:private static
参数:
- blockAtlas: SpriteLoader.Preparations
- itemAtlas: SpriteLoader.Preparations
- bakery: ModelBakery
- blockModels: LoadedBlockModels
- modelGroups: Object2IntMap
- entityModelSet: EntityModelSet
- taskExecutor: Executor
说明:
TODO
private static Map<BlockState,BlockStateModel> createBlockStateToModelDispatch(Map<BlockState,BlockStateModel> bakedModels, BlockStateModel missingModel) @ L296
- 方法名:createBlockStateToModelDispatch
- 源码定位:L296
- 返回类型:Map<BlockState,BlockStateModel>
- 修饰符:private static
参数:
- bakedModels: Map<BlockState,BlockStateModel>
- missingModel: BlockStateModel
说明:
TODO
private static Object2IntMap<BlockState> buildModelGroups(BlockColors blockColors, BlockStateModelLoader.LoadedModels blockStateModels) @ L315
- 方法名:buildModelGroups
- 源码定位:L315
- 返回类型:Object2IntMap
- 修饰符:private static
参数:
- blockColors: BlockColors
- blockStateModels: BlockStateModelLoader.LoadedModels
说明:
TODO
private void apply(ModelManager.ReloadState preparations) @ L324
- 方法名:apply
- 源码定位:L324
- 返回类型:void
- 修饰符:private
参数:
- preparations: ModelManager.ReloadState
说明:
TODO
public boolean requiresRender(BlockState oldState, BlockState newState) @ L336
- 方法名:requiresRender
- 源码定位:L336
- 返回类型:boolean
- 修饰符:public
参数:
- oldState: BlockState
- newState: BlockState
说明:
TODO
public Supplier<EntityModelSet> entityModels() @ L354
- 方法名:entityModels
- 源码定位:L354
- 返回类型:Supplier
- 修饰符:public
参数:
- 无
说明:
TODO
代码
@OnlyIn(Dist.CLIENT)
public class ModelManager implements PreparableReloadListener {
private static final Logger LOGGER = LogUtils.getLogger();
private static final FileToIdConverter MODEL_LISTER = FileToIdConverter.json("models");
private Map<Identifier, ItemModel> bakedItemStackModels = Map.of();
private Map<Identifier, ClientItem.Properties> itemProperties = Map.of();
private final AtlasManager atlasManager;
private final PlayerSkinRenderCache playerSkinRenderCache;
private final BlockColors blockColors;
private EntityModelSet entityModelSet = EntityModelSet.EMPTY;
private ModelBakery.MissingModels missingModels;
private @Nullable BlockStateModelSet blockStateModelSet;
private @Nullable BlockModelSet blockModelSet;
private @Nullable FluidStateModelSet fluidStateModelSet;
private Object2IntMap<BlockState> modelGroups = Object2IntMaps.emptyMap();
public ModelManager(BlockColors blockColors, AtlasManager atlasManager, PlayerSkinRenderCache playerSkinRenderCache) {
this.blockColors = blockColors;
this.atlasManager = atlasManager;
this.playerSkinRenderCache = playerSkinRenderCache;
}
public ItemModel getItemModel(Identifier id) {
return this.bakedItemStackModels.getOrDefault(id, this.missingModels.item());
}
public ClientItem.Properties getItemProperties(Identifier id) {
return this.itemProperties.getOrDefault(id, ClientItem.Properties.DEFAULT);
}
public BlockStateModelSet getBlockStateModelSet() {
return Objects.requireNonNull(this.blockStateModelSet, "Block models not yet initialized");
}
public BlockModelSet getBlockModelSet() {
return Objects.requireNonNull(this.blockModelSet, "Block models not yet initialized");
}
public FluidStateModelSet getFluidStateModelSet() {
return Objects.requireNonNull(this.fluidStateModelSet, "Fluid models not yet initialized");
}
@Override
public final CompletableFuture<Void> reload(
PreparableReloadListener.SharedState currentReload,
Executor taskExecutor,
PreparableReloadListener.PreparationBarrier preparationBarrier,
Executor reloadExecutor
) {
ResourceManager manager = currentReload.resourceManager();
CompletableFuture<EntityModelSet> entityModelSet = CompletableFuture.supplyAsync(EntityModelSet::vanilla, taskExecutor);
CompletableFuture<Map<Identifier, UnbakedModel>> modelCache = loadBlockModels(manager, taskExecutor);
CompletableFuture<BlockStateModelLoader.LoadedModels> blockStateModels = BlockStateModelLoader.loadBlockStates(manager, taskExecutor);
CompletableFuture<Map<BlockState, BlockModel.Unbaked>> blockModelContents = CompletableFuture.supplyAsync(
() -> BuiltInBlockModels.createBlockModels(this.blockColors), taskExecutor
);
CompletableFuture<ClientItemInfoLoader.LoadedClientInfos> itemStackModels = ClientItemInfoLoader.scheduleLoad(manager, taskExecutor);
CompletableFuture<ModelManager.ResolvedModels> modelDiscovery = CompletableFuture.allOf(modelCache, blockStateModels, itemStackModels)
.thenApplyAsync(var3 -> discoverModelDependencies(modelCache.join(), blockStateModels.join(), itemStackModels.join()), taskExecutor);
CompletableFuture<Object2IntMap<BlockState>> modelGroups = blockStateModels.thenApplyAsync(
models -> buildModelGroups(this.blockColors, models), taskExecutor
);
AtlasManager.PendingStitchResults pendingStitches = currentReload.get(AtlasManager.PENDING_STITCH);
CompletableFuture<SpriteLoader.Preparations> pendingBlockAtlasSprites = pendingStitches.get(AtlasIds.BLOCKS);
CompletableFuture<SpriteLoader.Preparations> pendingItemAtlasSprites = pendingStitches.get(AtlasIds.ITEMS);
CompletableFuture<LoadedBlockModels> blockModels = CompletableFuture.allOf(blockModelContents, entityModelSet)
.thenApplyAsync(var3 -> new LoadedBlockModels(blockModelContents.join(), entityModelSet.join(), this.atlasManager, this.playerSkinRenderCache));
return CompletableFuture.allOf(
pendingBlockAtlasSprites,
pendingItemAtlasSprites,
modelDiscovery,
modelGroups,
blockStateModels,
itemStackModels,
entityModelSet,
blockModels,
modelCache
)
.thenComposeAsync(
var11x -> {
SpriteLoader.Preparations blockAtlasSprites = pendingBlockAtlasSprites.join();
SpriteLoader.Preparations itemAtlasSprites = pendingItemAtlasSprites.join();
ModelManager.ResolvedModels resolvedModels = modelDiscovery.join();
Object2IntMap<BlockState> groups = modelGroups.join();
Set<Identifier> unreferencedModels = Sets.difference(modelCache.join().keySet(), resolvedModels.models.keySet());
if (!unreferencedModels.isEmpty()) {
LOGGER.debug(
"Unreferenced models: \n{}",
unreferencedModels.stream().sorted().map(modelId -> "\t" + modelId + "\n").collect(Collectors.joining())
);
}
ModelBakery bakery = new ModelBakery(
entityModelSet.join(),
this.atlasManager,
this.playerSkinRenderCache,
blockStateModels.join().models(),
itemStackModels.join().contents(),
resolvedModels.models(),
resolvedModels.missing()
);
return loadModels(blockAtlasSprites, itemAtlasSprites, bakery, blockModels.join(), groups, entityModelSet.join(), taskExecutor);
},
taskExecutor
)
.thenCompose(preparationBarrier::wait)
.thenAcceptAsync(this::apply, reloadExecutor);
}
private static CompletableFuture<Map<Identifier, UnbakedModel>> loadBlockModels(ResourceManager manager, Executor executor) {
return CompletableFuture.<Map<Identifier, Resource>>supplyAsync(() -> MODEL_LISTER.listMatchingResources(manager), executor)
.thenCompose(
resources -> {
List<CompletableFuture<Pair<Identifier, CuboidModel>>> result = new ArrayList<>(resources.size());
for (Entry<Identifier, Resource> resource : resources.entrySet()) {
result.add(CompletableFuture.supplyAsync(() -> {
Identifier modelId = MODEL_LISTER.fileToId(resource.getKey());
try {
Pair t$;
try (Reader reader = resource.getValue().openAsReader()) {
t$ = Pair.of(modelId, CuboidModel.fromStream(reader));
}
return t$;
} catch (Exception var7) {
LOGGER.error("Failed to load model {}", resource.getKey(), var7);
return null;
}
}, executor));
}
return Util.sequence(result)
.thenApply(pairs -> pairs.stream().filter(Objects::nonNull).collect(Collectors.toUnmodifiableMap(Pair::getFirst, Pair::getSecond)));
}
);
}
private static ModelManager.ResolvedModels discoverModelDependencies(
Map<Identifier, UnbakedModel> allModels, BlockStateModelLoader.LoadedModels blockStateModels, ClientItemInfoLoader.LoadedClientInfos itemInfos
) {
ModelManager.ResolvedModels var5;
try (Zone ignored = Profiler.get().zone("dependencies")) {
ModelDiscovery result = new ModelDiscovery(allModels, MissingCuboidModel.missingModel());
result.addSpecialModel(ItemModelGenerator.GENERATED_ITEM_MODEL_ID, new ItemModelGenerator());
blockStateModels.models().values().forEach(result::addRoot);
itemInfos.contents().values().forEach(info -> result.addRoot(info.model()));
var5 = new ModelManager.ResolvedModels(result.missingModel(), result.resolve());
}
return var5;
}
private static CompletableFuture<ModelManager.ReloadState> loadModels(
SpriteLoader.Preparations blockAtlas,
SpriteLoader.Preparations itemAtlas,
ModelBakery bakery,
LoadedBlockModels blockModels,
Object2IntMap<BlockState> modelGroups,
EntityModelSet entityModelSet,
Executor taskExecutor
) {
final Multimap<String, Identifier> missingSprites = Multimaps.synchronizedMultimap(HashMultimap.create());
final Multimap<String, String> missingReferences = Multimaps.synchronizedMultimap(HashMultimap.create());
MaterialBaker materialBaker = new MaterialBaker() {
private final Material.Baked blockMissing = new Material.Baked(blockAtlas.missing(), false);
private final Map<Material, Material.@Nullable Baked> bakedMaterials = new ConcurrentHashMap<>();
private final Function<Material, Material.@Nullable Baked> bakerFunction = this::bake;
@Override
public Material.Baked get(Material material, ModelDebugName name) {
Material.Baked baked = this.bakedMaterials.computeIfAbsent(material, this.bakerFunction);
if (baked == null) {
missingSprites.put(name.debugName(), material.sprite());
return this.blockMissing;
} else {
return baked;
}
}
private Material.@Nullable Baked bake(Material material) {
Material.Baked itemMaterial = this.bakeForAtlas(material, itemAtlas);
return itemMaterial != null ? itemMaterial : this.bakeForAtlas(material, blockAtlas);
}
private Material.@Nullable Baked bakeForAtlas(Material material, SpriteLoader.Preparations atlas) {
TextureAtlasSprite sprite = atlas.getSprite(material.sprite());
return sprite != null ? new Material.Baked(sprite, material.forceTranslucent()) : null;
}
@Override
public Material.Baked reportMissingReference(String reference, ModelDebugName responsibleModel) {
missingReferences.put(responsibleModel.debugName(), reference);
return this.blockMissing;
}
};
CompletableFuture<ModelBakery.BakingResult> bakedStateResults = bakery.bakeModels(materialBaker, taskExecutor);
CompletableFuture<Map<BlockState, BlockModel>> bakedModelsFuture = bakedStateResults.thenCompose(
bakingResult -> blockModels.bake(bakingResult::getBlockStateModel, bakingResult.missingModels().block(), taskExecutor)
);
return bakedStateResults.thenCombine(
bakedModelsFuture,
(bakingResult, bakedModels) -> {
Map<Fluid, FluidModel> fluidModels = FluidStateModelSet.bake(materialBaker);
missingSprites.asMap()
.forEach(
(location, sprites) -> LOGGER.warn(
"Missing textures in model {}:\n{}",
location,
sprites.stream().sorted().map(sprite -> " " + sprite).collect(Collectors.joining("\n"))
)
);
missingReferences.asMap()
.forEach(
(location, references) -> LOGGER.warn(
"Missing texture references in model {}:\n{}",
location,
references.stream().sorted().map(reference -> " " + reference).collect(Collectors.joining("\n"))
)
);
Map<BlockState, BlockStateModel> modelByStateCache = createBlockStateToModelDispatch(
bakingResult.blockStateModels(), bakingResult.missingModels().block()
);
return new ModelManager.ReloadState(
bakingResult, modelGroups, modelByStateCache, (Map<BlockState, BlockModel>)bakedModels, fluidModels, entityModelSet
);
}
);
}
private static Map<BlockState, BlockStateModel> createBlockStateToModelDispatch(Map<BlockState, BlockStateModel> bakedModels, BlockStateModel missingModel) {
Object var8;
try (Zone ignored = Profiler.get().zone("block state dispatch")) {
Map<BlockState, BlockStateModel> modelByStateCache = new IdentityHashMap<>(bakedModels);
for (Block block : BuiltInRegistries.BLOCK) {
block.getStateDefinition().getPossibleStates().forEach(state -> {
if (bakedModels.putIfAbsent(state, missingModel) == null) {
LOGGER.warn("Missing model for variant: '{}'", state);
}
});
}
var8 = modelByStateCache;
}
return (Map<BlockState, BlockStateModel>)var8;
}
private static Object2IntMap<BlockState> buildModelGroups(BlockColors blockColors, BlockStateModelLoader.LoadedModels blockStateModels) {
Object2IntMap var3;
try (Zone ignored = Profiler.get().zone("block groups")) {
var3 = ModelGroupCollector.build(blockColors, blockStateModels);
}
return var3;
}
private void apply(ModelManager.ReloadState preparations) {
ModelBakery.BakingResult bakedModels = preparations.bakedModels;
this.bakedItemStackModels = bakedModels.itemStackModels();
this.itemProperties = bakedModels.itemProperties();
this.modelGroups = preparations.modelGroups;
this.missingModels = bakedModels.missingModels();
this.blockStateModelSet = new BlockStateModelSet(preparations.blockStateModels, this.missingModels.block());
this.blockModelSet = new BlockModelSet(this.blockStateModelSet, preparations.blockModels, this.blockColors);
this.fluidStateModelSet = new FluidStateModelSet(preparations.fluidModels, this.missingModels.fluid());
this.entityModelSet = preparations.entityModelSet;
}
public boolean requiresRender(BlockState oldState, BlockState newState) {
if (oldState == newState) {
return false;
} else {
int oldModelGroup = this.modelGroups.getInt(oldState);
if (oldModelGroup != -1) {
int newModelGroup = this.modelGroups.getInt(newState);
if (oldModelGroup == newModelGroup) {
FluidState oldFluidState = oldState.getFluidState();
FluidState newFluidState = newState.getFluidState();
return oldFluidState != newFluidState;
}
}
return true;
}
}
public Supplier<EntityModelSet> entityModels() {
return () -> this.entityModelSet;
}
@OnlyIn(Dist.CLIENT)
private record ReloadState(
ModelBakery.BakingResult bakedModels,
Object2IntMap<BlockState> modelGroups,
Map<BlockState, BlockStateModel> blockStateModels,
Map<BlockState, BlockModel> blockModels,
Map<Fluid, FluidModel> fluidModels,
EntityModelSet entityModelSet
) {
}
@OnlyIn(Dist.CLIENT)
private record ResolvedModels(ResolvedModel missing, Map<Identifier, ResolvedModel> models) {
}
}引用的其他类
-
- 引用位置:
参数/字段
- 引用位置:
-
- 引用位置:
参数/字段/返回值
- 引用位置:
-
- 引用位置:
参数/字段
- 引用位置:
-
- 引用位置:
字段/构造调用/返回值 - 关联成员:
BlockModelSet()
- 引用位置:
-
- 引用位置:
字段/构造调用/返回值 - 关联成员:
BlockStateModelSet()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
BuiltInBlockModels.createBlockModels()
- 引用位置:
-
- 引用位置:
字段/方法调用/构造调用/返回值 - 关联成员:
FluidStateModelSet(), FluidStateModelSet.bake()
- 引用位置:
-
- 引用位置:
参数/构造调用 - 关联成员:
LoadedBlockModels()
- 引用位置:
-
- 引用位置:
参数/返回值
- 引用位置:
-
- 引用位置:
字段/返回值
- 引用位置:
-
- 引用位置:
字段/返回值
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
参数/方法调用 - 关联成员:
BlockStateModelLoader.loadBlockStates()
- 引用位置:
-
- 引用位置:
参数/方法调用 - 关联成员:
ClientItemInfoLoader.scheduleLoad()
- 引用位置:
-
- 引用位置:
参数/字段/构造调用 - 关联成员:
ModelBakery()
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
ModelDiscovery()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
ModelGroupCollector.build()
- 引用位置:
-
- 引用位置:
参数/返回值
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
CuboidModel.fromStream()
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
ItemModelGenerator()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
MissingCuboidModel.missingModel()
- 引用位置:
-
- 引用位置:
参数/字段
- 引用位置:
-
- 引用位置:
方法调用/构造调用 - 关联成员:
Baked(), Material.Baked()
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
MaterialBaker()
- 引用位置:
-
- 引用位置:
字段/方法调用 - 关联成员:
FileToIdConverter.json()
- 引用位置:
-
- 引用位置:
参数/字段/返回值
- 引用位置:
-
- 引用位置:
参数/实现
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
Util.sequence()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
Profiler.get()
- 引用位置:
-
- 引用位置:
参数/字段/返回值
- 引用位置: