ModelDiscovery.java
net.minecraft.client.resources.model.ModelDiscovery
信息
- 全限定名:net.minecraft.client.resources.model.ModelDiscovery
- 类型:public class
- 包:net.minecraft.client.resources.model
- 源码路径:src/main/java/net/minecraft/client/resources/model/ModelDiscovery.java
- 起始行号:L34
- 职责:
TODO
字段/常量
-
LOGGER- 类型:
Logger - 修饰符:
private static final - 源码定位:
L35 - 说明:
TODO
- 类型:
-
modelWrappers- 类型:
Object2ObjectMap<Identifier,ModelDiscovery.ModelWrapper> - 修饰符:
private final - 源码定位:
L36 - 说明:
TODO
- 类型:
-
missingModel- 类型:
ModelDiscovery.ModelWrapper - 修饰符:
private final - 源码定位:
L37 - 说明:
TODO
- 类型:
-
uncachedResolver- 类型:
Object2ObjectFunction<Identifier,ModelDiscovery.ModelWrapper> - 修饰符:
private final - 源码定位:
L38 - 说明:
TODO
- 类型:
-
resolver- 类型:
ResolvableModel.Resolver - 修饰符:
private final - 源码定位:
L39 - 说明:
TODO
- 类型:
-
parentDiscoveryQueue- 类型:
Queue<ModelDiscovery.ModelWrapper> - 修饰符:
private final - 源码定位:
L40 - 说明:
TODO
- 类型:
内部类/嵌套类型
-
net.minecraft.client.resources.model.ModelDiscovery.ModelWrapper- 类型:
class - 修饰符:
private static - 源码定位:
L143 - 说明:
TODO
- 类型:
-
net.minecraft.client.resources.model.ModelDiscovery.Slot- 类型:
record - 修饰符:
private - 源码定位:
L245 - 说明:
TODO
- 类型:
构造器
public ModelDiscovery(Map<Identifier,UnbakedModel> unbakedModels, UnbakedModel missingUnbakedModel) @ L42
- 构造器名:ModelDiscovery
- 源码定位:L42
- 修饰符:public
参数:
- unbakedModels: Map<Identifier,UnbakedModel>
- missingUnbakedModel: UnbakedModel
说明:
TODO
方法
下面的方法块按源码顺序生成。
private static boolean isRoot(UnbakedModel model) @ L58
- 方法名:isRoot
- 源码定位:L58
- 返回类型:boolean
- 修饰符:private static
参数:
- model: UnbakedModel
说明:
TODO
private ModelDiscovery.ModelWrapper getOrCreateModel(Identifier id) @ L62
- 方法名:getOrCreateModel
- 源码定位:L62
- 返回类型:ModelDiscovery.ModelWrapper
- 修饰符:private
参数:
- id: Identifier
说明:
TODO
private ModelDiscovery.ModelWrapper createAndQueueWrapper(Identifier id, UnbakedModel rawModel) @ L66
- 方法名:createAndQueueWrapper
- 源码定位:L66
- 返回类型:ModelDiscovery.ModelWrapper
- 修饰符:private
参数:
- id: Identifier
- rawModel: UnbakedModel
说明:
TODO
public void addRoot(ResolvableModel model) @ L76
- 方法名:addRoot
- 源码定位:L76
- 返回类型:void
- 修饰符:public
参数:
- model: ResolvableModel
说明:
TODO
public void addSpecialModel(Identifier id, UnbakedModel model) @ L80
- 方法名:addSpecialModel
- 源码定位:L80
- 返回类型:void
- 修饰符:public
参数:
- id: Identifier
- model: UnbakedModel
说明:
TODO
public ResolvedModel missingModel() @ L91
- 方法名:missingModel
- 源码定位:L91
- 返回类型:ResolvedModel
- 修饰符:public
参数:
- 无
说明:
TODO
public Map<Identifier,ResolvedModel> resolve() @ L95
- 方法名:resolve
- 源码定位:L95
- 返回类型:Map<Identifier,ResolvedModel>
- 修饰符:public
参数:
- 无
说明:
TODO
private void discoverDependencies(List<ModelDiscovery.ModelWrapper> toValidate) @ L110
- 方法名:discoverDependencies
- 源码定位:L110
- 返回类型:void
- 修饰符:private
参数:
- toValidate: List<ModelDiscovery.ModelWrapper>
说明:
TODO
private static void propagateValidity(List<ModelDiscovery.ModelWrapper> toValidate) @ L124
- 方法名:propagateValidity
- 源码定位:L124
- 返回类型:void
- 修饰符:private static
参数:
- toValidate: List<ModelDiscovery.ModelWrapper>
说明:
TODO
代码
@OnlyIn(Dist.CLIENT)
public class ModelDiscovery {
private static final Logger LOGGER = LogUtils.getLogger();
private final Object2ObjectMap<Identifier, ModelDiscovery.ModelWrapper> modelWrappers = new Object2ObjectOpenHashMap<>();
private final ModelDiscovery.ModelWrapper missingModel;
private final Object2ObjectFunction<Identifier, ModelDiscovery.ModelWrapper> uncachedResolver;
private final ResolvableModel.Resolver resolver;
private final Queue<ModelDiscovery.ModelWrapper> parentDiscoveryQueue = new ArrayDeque<>();
public ModelDiscovery(Map<Identifier, UnbakedModel> unbakedModels, UnbakedModel missingUnbakedModel) {
this.missingModel = new ModelDiscovery.ModelWrapper(MissingCuboidModel.LOCATION, missingUnbakedModel, true);
this.modelWrappers.put(MissingCuboidModel.LOCATION, this.missingModel);
this.uncachedResolver = rawId -> {
Identifier id = (Identifier)rawId;
UnbakedModel rawModel = unbakedModels.get(id);
if (rawModel == null) {
LOGGER.warn("Missing block model: {}", id);
return this.missingModel;
} else {
return this.createAndQueueWrapper(id, rawModel);
}
};
this.resolver = this::getOrCreateModel;
}
private static boolean isRoot(UnbakedModel model) {
return model.parent() == null;
}
private ModelDiscovery.ModelWrapper getOrCreateModel(Identifier id) {
return this.modelWrappers.computeIfAbsent(id, this.uncachedResolver);
}
private ModelDiscovery.ModelWrapper createAndQueueWrapper(Identifier id, UnbakedModel rawModel) {
boolean isRoot = isRoot(rawModel);
ModelDiscovery.ModelWrapper result = new ModelDiscovery.ModelWrapper(id, rawModel, isRoot);
if (!isRoot) {
this.parentDiscoveryQueue.add(result);
}
return result;
}
public void addRoot(ResolvableModel model) {
model.resolveDependencies(this.resolver);
}
public void addSpecialModel(Identifier id, UnbakedModel model) {
if (!isRoot(model)) {
LOGGER.warn("Trying to add non-root special model {}, ignoring", id);
} else {
ModelDiscovery.ModelWrapper previous = this.modelWrappers.put(id, this.createAndQueueWrapper(id, model));
if (previous != null) {
LOGGER.warn("Duplicate special model {}", id);
}
}
}
public ResolvedModel missingModel() {
return this.missingModel;
}
public Map<Identifier, ResolvedModel> resolve() {
List<ModelDiscovery.ModelWrapper> toValidate = new ArrayList<>();
this.discoverDependencies(toValidate);
propagateValidity(toValidate);
Builder<Identifier, ResolvedModel> result = ImmutableMap.builder();
this.modelWrappers.forEach((location, model) -> {
if (model.valid) {
result.put(location, model);
} else {
LOGGER.warn("Model {} ignored due to cyclic dependency", location);
}
});
return result.build();
}
private void discoverDependencies(List<ModelDiscovery.ModelWrapper> toValidate) {
ModelDiscovery.ModelWrapper current;
while ((current = this.parentDiscoveryQueue.poll()) != null) {
Identifier parentLocation = Objects.requireNonNull(current.wrapped.parent());
ModelDiscovery.ModelWrapper parent = this.getOrCreateModel(parentLocation);
current.parent = parent;
if (parent.valid) {
current.valid = true;
} else {
toValidate.add(current);
}
}
}
private static void propagateValidity(List<ModelDiscovery.ModelWrapper> toValidate) {
boolean progressed = true;
while (progressed) {
progressed = false;
Iterator<ModelDiscovery.ModelWrapper> iterator = toValidate.iterator();
while (iterator.hasNext()) {
ModelDiscovery.ModelWrapper model = iterator.next();
if (Objects.requireNonNull(model.parent).valid) {
model.valid = true;
iterator.remove();
progressed = true;
}
}
}
}
@OnlyIn(Dist.CLIENT)
private static class ModelWrapper implements ResolvedModel {
private static final ModelDiscovery.Slot<Boolean> KEY_AMBIENT_OCCLUSION = slot(0);
private static final ModelDiscovery.Slot<UnbakedModel.GuiLight> KEY_GUI_LIGHT = slot(1);
private static final ModelDiscovery.Slot<UnbakedGeometry> KEY_GEOMETRY = slot(2);
private static final ModelDiscovery.Slot<ItemTransforms> KEY_TRANSFORMS = slot(3);
private static final ModelDiscovery.Slot<TextureSlots> KEY_TEXTURE_SLOTS = slot(4);
private static final ModelDiscovery.Slot<Material.Baked> KEY_PARTICLE_SPRITE = slot(5);
private static final ModelDiscovery.Slot<QuadCollection> KEY_DEFAULT_GEOMETRY = slot(6);
private static final int SLOT_COUNT = 7;
private final Identifier id;
private boolean valid;
private ModelDiscovery.@Nullable ModelWrapper parent;
private final UnbakedModel wrapped;
private final AtomicReferenceArray<@Nullable Object> fixedSlots = new AtomicReferenceArray<>(7);
private final Map<ModelState, QuadCollection> modelBakeCache = new ConcurrentHashMap<>();
private static <T> ModelDiscovery.Slot<T> slot(int index) {
Objects.checkIndex(index, 7);
return new ModelDiscovery.Slot<>(index);
}
private ModelWrapper(Identifier id, UnbakedModel wrapped, boolean valid) {
this.id = id;
this.wrapped = wrapped;
this.valid = valid;
}
@Override
public UnbakedModel wrapped() {
return this.wrapped;
}
@Override
public @Nullable ResolvedModel parent() {
return this.parent;
}
@Override
public String debugName() {
return this.id.toString();
}
private <T> @Nullable T getSlot(ModelDiscovery.Slot<T> key) {
return (T)this.fixedSlots.get(key.index);
}
private <T> T updateSlot(ModelDiscovery.Slot<T> key, T value) {
T currentValue = (T)this.fixedSlots.compareAndExchange(key.index, null, value);
return currentValue == null ? value : currentValue;
}
private <T> T getSimpleProperty(ModelDiscovery.Slot<T> key, Function<ResolvedModel, T> getter) {
T result = this.getSlot(key);
return result != null ? result : this.updateSlot(key, getter.apply(this));
}
@Override
public boolean getTopAmbientOcclusion() {
return this.getSimpleProperty(KEY_AMBIENT_OCCLUSION, ResolvedModel::findTopAmbientOcclusion);
}
@Override
public UnbakedModel.GuiLight getTopGuiLight() {
return this.getSimpleProperty(KEY_GUI_LIGHT, ResolvedModel::findTopGuiLight);
}
@Override
public ItemTransforms getTopTransforms() {
return this.getSimpleProperty(KEY_TRANSFORMS, ResolvedModel::findTopTransforms);
}
@Override
public UnbakedGeometry getTopGeometry() {
return this.getSimpleProperty(KEY_GEOMETRY, ResolvedModel::findTopGeometry);
}
@Override
public TextureSlots getTopTextureSlots() {
return this.getSimpleProperty(KEY_TEXTURE_SLOTS, ResolvedModel::findTopTextureSlots);
}
@Override
public Material.Baked resolveParticleMaterial(TextureSlots textureSlots, ModelBaker baker) {
Material.Baked result = this.getSlot(KEY_PARTICLE_SPRITE);
return result != null ? result : this.updateSlot(KEY_PARTICLE_SPRITE, ResolvedModel.resolveParticleMaterial(textureSlots, baker, this));
}
private QuadCollection bakeDefaultState(TextureSlots textureSlots, ModelBaker baker, ModelState state) {
QuadCollection result = this.getSlot(KEY_DEFAULT_GEOMETRY);
return result != null ? result : this.updateSlot(KEY_DEFAULT_GEOMETRY, this.getTopGeometry().bake(textureSlots, baker, state, this));
}
@Override
public QuadCollection bakeTopGeometry(TextureSlots textureSlots, ModelBaker baker, ModelState state) {
return state == BlockModelRotation.IDENTITY ? this.bakeDefaultState(textureSlots, baker, state) : this.modelBakeCache.computeIfAbsent(state, s -> {
UnbakedGeometry topGeometry = this.getTopGeometry();
return topGeometry.bake(textureSlots, baker, s, this);
});
}
}
@OnlyIn(Dist.CLIENT)
private record Slot<T>(int index) {
}
}引用的其他类
-
- 引用位置:
参数/字段
- 引用位置:
-
- 引用位置:
方法调用/返回值 - 关联成员:
ResolvedModel.resolveParticleMaterial()
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
参数/字段/返回值
- 引用位置: