Introduce custom loader additions to the model data generators. (#7450)

Currently implemented loaders:
* OBJ
* Composite
* Multi-layer
* Item layers (vanilla item/generated but with fullbright texture support)
* Bucket
* Separate Perspective
This commit is contained in:
David Quintana 2020-11-02 02:09:49 +01:00 committed by GitHub
parent cf3e9d1e0c
commit fed7beab89
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 660 additions and 20 deletions

View file

@ -353,8 +353,10 @@ project(':forge') {
'--mod', 'global_loot_test',
'--mod', 'scaffolding_test',
'--mod', 'custom_tag_types_test',
'--mod', 'new_model_loader_test',
'--output', rootProject.file('src/generated_test/resources/'),
'--existing', sourceSets.main.resources.srcDirs[0]
'--existing', sourceSets.main.resources.srcDirs[0],
'--existing', sourceSets.test.resources.srcDirs[0]
}
}
}

View file

@ -63,6 +63,10 @@ bf2e445b48b024354a69138b20a4a4a8aa5d15d1 assets/minecraft/blockstates/oak_trapdo
9c4cc92efb78811e8d70a383a1a89eb75b69db04 assets/minecraft/blockstates/stone.json
570fdd86046df75a073b759ff7aaf4c4caf43115 assets/minecraft/blockstates/torch.json
a012d6d92bab1c91913bd0f2dc0492a0fce916f2 assets/minecraft/blockstates/wall_torch.json
e615d11ed9a452bca5d8b242e733a43ba2df19a3 assets/new_model_loader_test/blockstates/obj_block.json
bab7cd04569c8aa63320772acdc3c91a5ceda14a assets/new_model_loader_test/models/block/obj_block.json
9fa44308a52fbc384d5befee4e117531642299fb assets/new_model_loader_test/models/item/item_layers.json
70c8c81f3a157e4d698f213d5c1a13c13eaa5157 assets/new_model_loader_test/models/item/separate_perspective.json
273e0ed992d227f09f1c83bc22d066fb68d03c84 assets/piston_event_test/blockstates/shiftonmove.json
d2c8e860521c5e738ed0798337f5728d610825ff assets/piston_event_test/models/block/shiftonmove.json
f51f026a75e27a0a53a76771d553c0e3385a2966 assets/piston_event_test/models/item/shiftonmove.json

View file

@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "new_model_loader_test:block/obj_block"
}
}
}

View file

@ -0,0 +1,9 @@
{
"textures": {
"qr": "minecraft:block/oak_planks",
"particle": "#qr"
},
"loader": "forge:obj",
"model": "new_model_loader_test:models/item/sugar_glider.obj",
"flip-v": true
}

View file

@ -0,0 +1,11 @@
{
"parent": "forge:item/default",
"textures": {
"layer0": "minecraft:item/coal",
"layer1": "minecraft:item/stick"
},
"loader": "forge:item-layers",
"fullbright_layers": [
1
]
}

View file

@ -0,0 +1,15 @@
{
"parent": "forge:item/default",
"loader": "forge:separate-perspective",
"base": {
"parent": "minecraft:item/coal"
},
"perspectives": {
"gui": {
"parent": "minecraft:item/snowball"
},
"first_person_left_hand": {
"parent": "minecraft:item/bone"
}
}
}

View file

@ -19,6 +19,7 @@
package net.minecraftforge.client.model;
import com.google.common.collect.ImmutableBiMap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
@ -164,7 +165,7 @@ public class SeparatePerspectiveModel implements IModelGeometry<SeparatePerspect
{
public static final Loader INSTANCE = new Loader();
private static final ImmutableMap<String, ItemCameraTransforms.TransformType> PERSPECTIVES = ImmutableMap.<String, ItemCameraTransforms.TransformType>builder()
public static final ImmutableBiMap<String, ItemCameraTransforms.TransformType> PERSPECTIVES = ImmutableBiMap.<String, ItemCameraTransforms.TransformType>builder()
.put("none", ItemCameraTransforms.TransformType.NONE)
.put("third_person_left_hand", ItemCameraTransforms.TransformType.THIRD_PERSON_LEFT_HAND)
.put("third_person_right_hand", ItemCameraTransforms.TransformType.THIRD_PERSON_RIGHT_HAND)

View file

@ -0,0 +1,55 @@
package net.minecraftforge.client.model.generators;
import com.google.common.base.Preconditions;
import com.google.gson.JsonObject;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.common.data.ExistingFileHelper;
import java.util.LinkedHashMap;
import java.util.Map;
public abstract class CustomLoaderBuilder<T extends ModelBuilder<T>>
{
protected final ResourceLocation loaderId;
protected final T parent;
protected final ExistingFileHelper existingFileHelper;
protected final Map<String, Boolean> visibility = new LinkedHashMap<>();
protected CustomLoaderBuilder(ResourceLocation loaderId, T parent, ExistingFileHelper existingFileHelper)
{
this.loaderId = loaderId;
this.parent = parent;
this.existingFileHelper = existingFileHelper;
}
public CustomLoaderBuilder<T> visibility(String partName, boolean show)
{
Preconditions.checkNotNull(partName, "partName must not be null");
this.visibility.put(partName, show);
return this;
}
public T end()
{
return parent;
}
public JsonObject toJson(JsonObject json)
{
json.addProperty("loader", loaderId.toString());
if (visibility.size() > 0)
{
JsonObject visibilityObj = new JsonObject();
for(Map.Entry<String, Boolean> entry : visibility.entrySet())
{
visibilityObj.addProperty(entry.getKey(), entry.getValue());
}
json.add("visibility", visibilityObj);
}
return json;
}
}

View file

@ -19,13 +19,10 @@
package net.minecraftforge.client.model.generators;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.Map.Entry;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
@ -75,6 +72,8 @@ public class ModelBuilder<T extends ModelBuilder<T>> extends ModelFile {
protected final List<ElementBuilder> elements = new ArrayList<>();
protected CustomLoaderBuilder customLoader = null;
protected ModelBuilder(ResourceLocation outputLocation, ExistingFileHelper existingFileHelper) {
super(outputLocation);
this.existingFileHelper = existingFileHelper;
@ -178,6 +177,7 @@ public class ModelBuilder<T extends ModelBuilder<T>> extends ModelFile {
}
public ElementBuilder element() {
Preconditions.checkState(customLoader == null, "Cannot use elements and custom loaders at the same time");
ElementBuilder ret = new ElementBuilder();
elements.add(ret);
return ret;
@ -191,13 +191,29 @@ public class ModelBuilder<T extends ModelBuilder<T>> extends ModelFile {
* @throws IndexOutOfBoundsException if {@code} index is out of bounds
*/
public ElementBuilder element(int index) {
Preconditions.checkState(customLoader == null, "Cannot use elements and custom loaders at the same time");
Preconditions.checkElementIndex(index, elements.size(), "Element index");
return elements.get(index);
}
/**
* Use a custom loader instead of the vanilla elements.
* @param customLoaderFactory
* @return the custom loader builder
*/
public <L extends CustomLoaderBuilder<T>> L customLoader(BiFunction<T, ExistingFileHelper, L> customLoaderFactory)
{
Preconditions.checkState(elements.size() == 0, "Cannot use elements and custom loaders at the same time");
Preconditions.checkNotNull(customLoaderFactory, "customLoaderFactory must not be null");
L customLoader = customLoaderFactory.apply(self(), existingFileHelper);
this.customLoader = customLoader;
return customLoader;
}
@VisibleForTesting
public JsonObject toJson() {
JsonObject root = new JsonObject();
if (this.parent != null) {
root.addProperty("parent", this.parent.getLocation().toString());
}
@ -290,6 +306,9 @@ public class ModelBuilder<T extends ModelBuilder<T>> extends ModelFile {
root.add("elements", elements);
}
if (customLoader != null)
return customLoader.toJson(root);
return root;
}

View file

@ -35,6 +35,7 @@ import com.google.gson.GsonBuilder;
import net.minecraft.data.DataGenerator;
import net.minecraft.data.DirectoryCache;
import net.minecraft.data.IDataProvider;
import net.minecraft.resources.IResource;
import net.minecraft.resources.ResourcePackType;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.common.data.ExistingFileHelper;
@ -51,12 +52,39 @@ public abstract class ModelProvider<T extends ModelBuilder<T>> implements IDataP
}
@Override
public boolean exists(ResourceLocation loc, ResourcePackType type, String pathSuffix, String pathPrefix) {
if (generatedModels.containsKey(loc)) {
return true;
public boolean exists(ResourceLocation loc, ResourcePackType type, String pathSuffix, String pathPrefix)
{
if (pathPrefix.equals("models") && pathSuffix.equals(".json"))
{
if (generatedModels.containsKey(loc))
{
return true;
}
}
return delegate.exists(loc, type, pathSuffix, pathPrefix);
}
@Override
public boolean exists(ResourceLocation loc, ResourcePackType type) {
if (loc.getPath().startsWith("models/") && loc.getPath().endsWith(".json"))
{
ResourceLocation modelLoc = new ResourceLocation(
loc.getNamespace(),
loc.getPath().substring("models/".length(), loc.getPath().length() - ".json".length())
);
if (generatedModels.containsKey(modelLoc))
{
return true;
}
}
return delegate.exists(loc, type);
}
@Override
public IResource getResource(ResourceLocation loc, ResourcePackType type) throws IOException
{
return delegate.getResource(loc, type);
}
}
public static final String BLOCK_FOLDER = "block";
@ -357,6 +385,14 @@ public abstract class ModelProvider<T extends ModelBuilder<T>> implements IDataP
return singleTexture(name, BLOCK_FOLDER + "/carpet", "wool", wool);
}
/**
* Gets a model builder that's not directly saved to disk. Meant for use in custom model loaders.
*/
public T nested()
{
return factory.apply(new ResourceLocation("dummy:dummy"));
}
public ModelFile.ExistingModelFile getExistingFile(ResourceLocation path) {
ModelFile.ExistingModelFile ret = new ModelFile.ExistingModelFile(extendWithFolder(path), existingFileHelper);
ret.assertExistence();

View file

@ -0,0 +1,50 @@
package net.minecraftforge.client.model.generators.loaders;
import com.google.common.base.Preconditions;
import com.google.gson.JsonObject;
import net.minecraft.fluid.Fluid;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.model.generators.CustomLoaderBuilder;
import net.minecraftforge.client.model.generators.ModelBuilder;
import net.minecraftforge.common.data.ExistingFileHelper;
import java.util.LinkedHashMap;
import java.util.Map;
public class CompositeModelBuilder<T extends ModelBuilder<T>> extends CustomLoaderBuilder<T>
{
public static <T extends ModelBuilder<T>> CompositeModelBuilder<T> begin(T parent, ExistingFileHelper existingFileHelper)
{
return new CompositeModelBuilder<>(parent, existingFileHelper);
}
private final Map<String, T> childModels = new LinkedHashMap<>();
protected CompositeModelBuilder(T parent, ExistingFileHelper existingFileHelper)
{
super(new ResourceLocation("forge:composite"), parent, existingFileHelper);
}
public CompositeModelBuilder<T> submodel(String name, T modelBuilder)
{
Preconditions.checkNotNull(name, "name must not be null");
Preconditions.checkNotNull(modelBuilder, "modelBuilder must not be null");
childModels.put(name, modelBuilder);
return this;
}
@Override
public JsonObject toJson(JsonObject json)
{
json = super.toJson(json);
JsonObject parts = new JsonObject();
for(Map.Entry<String, T> entry : childModels.entrySet())
{
parts.add(entry.getKey(), entry.getValue().toJson());
}
json.add("parts", parts);
return json;
}
}

View file

@ -0,0 +1,83 @@
package net.minecraftforge.client.model.generators.loaders;
import com.google.common.base.Preconditions;
import com.google.gson.JsonObject;
import net.minecraft.fluid.Fluid;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.model.generators.CustomLoaderBuilder;
import net.minecraftforge.client.model.generators.ModelBuilder;
import net.minecraftforge.common.data.ExistingFileHelper;
public class DynamicBucketModelBuilder<T extends ModelBuilder<T>> extends CustomLoaderBuilder<T>
{
public static <T extends ModelBuilder<T>> DynamicBucketModelBuilder<T> begin(T parent, ExistingFileHelper existingFileHelper)
{
return new DynamicBucketModelBuilder<>(parent, existingFileHelper);
}
private ResourceLocation fluid;
private Boolean flipGas;
private Boolean applyTint;
private Boolean coverIsMask;
private Boolean applyFluidLuminosity;
protected DynamicBucketModelBuilder(T parent, ExistingFileHelper existingFileHelper)
{
super(new ResourceLocation("forge:bucket"), parent, existingFileHelper);
}
public DynamicBucketModelBuilder<T> fluid(Fluid fluid)
{
Preconditions.checkNotNull(fluid, "fluid must not be null");
this.fluid = fluid.getRegistryName();
return this;
}
public DynamicBucketModelBuilder<T> flipGas(boolean flip)
{
this.flipGas = flip;
return this;
}
public DynamicBucketModelBuilder<T> applyTint(boolean tint)
{
this.applyTint = tint;
return this;
}
public DynamicBucketModelBuilder<T> coverIsMask(boolean coverIsMask)
{
this.coverIsMask = coverIsMask;
return this;
}
public DynamicBucketModelBuilder<T> applyFluidLuminosity(boolean applyFluidLuminosity)
{
this.applyFluidLuminosity = applyFluidLuminosity;
return this;
}
@Override
public JsonObject toJson(JsonObject json)
{
json = super.toJson(json);
Preconditions.checkNotNull(fluid, "fluid must not be null");
json.addProperty("fluid", fluid.toString());
if (flipGas != null)
json.addProperty("flipGas", flipGas);
if (applyTint != null)
json.addProperty("applyTint", applyTint);
if (coverIsMask != null)
json.addProperty("coverIsMask", coverIsMask);
if (applyFluidLuminosity != null)
json.addProperty("applyFluidLuminosity", applyFluidLuminosity);
return json;
}
}

View file

@ -0,0 +1,49 @@
package net.minecraftforge.client.model.generators.loaders;
import com.google.common.base.Preconditions;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.model.generators.CustomLoaderBuilder;
import net.minecraftforge.client.model.generators.ModelBuilder;
import net.minecraftforge.common.data.ExistingFileHelper;
import java.util.LinkedHashSet;
import java.util.Set;
public class ItemLayersModelBuilder<T extends ModelBuilder<T>> extends CustomLoaderBuilder<T>
{
public static <T extends ModelBuilder<T>> ItemLayersModelBuilder<T> begin(T parent, ExistingFileHelper existingFileHelper)
{
return new ItemLayersModelBuilder<>(parent, existingFileHelper);
}
private final Set<Integer> fullbright = new LinkedHashSet<>();
protected ItemLayersModelBuilder(T parent, ExistingFileHelper existingFileHelper)
{
super(new ResourceLocation("forge:item-layers"), parent, existingFileHelper);
}
public ItemLayersModelBuilder<T> fullbright(int layer)
{
Preconditions.checkArgument(layer >= 0, "layer must be >= 0");
fullbright.add(layer);
return this;
}
@Override
public JsonObject toJson(JsonObject json)
{
json = super.toJson(json);
JsonArray parts = new JsonArray();
for(int entry : fullbright)
{
parts.add(entry);
}
json.add("fullbright_layers", parts);
return json;
}
}

View file

@ -0,0 +1,52 @@
package net.minecraftforge.client.model.generators.loaders;
import com.google.common.base.Preconditions;
import com.google.gson.JsonObject;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.model.MultiLayerModel;
import net.minecraftforge.client.model.generators.CustomLoaderBuilder;
import net.minecraftforge.client.model.generators.ModelBuilder;
import net.minecraftforge.common.data.ExistingFileHelper;
import java.util.LinkedHashMap;
import java.util.Map;
public class MultiLayerModelBuilder<T extends ModelBuilder<T>> extends CustomLoaderBuilder<T>
{
public static <T extends ModelBuilder<T>> MultiLayerModelBuilder<T> begin(T parent, ExistingFileHelper existingFileHelper)
{
return new MultiLayerModelBuilder<>(parent, existingFileHelper);
}
private final Map<String, T> childModels = new LinkedHashMap<>();
protected MultiLayerModelBuilder(T parent, ExistingFileHelper existingFileHelper)
{
super(new ResourceLocation("forge:multi-layer"), parent, existingFileHelper);
}
public MultiLayerModelBuilder<T> submodel(RenderType layer, T modelBuilder)
{
Preconditions.checkNotNull(layer, "layer must not be null");
Preconditions.checkArgument(MultiLayerModel.Loader.BLOCK_LAYERS.containsValue(layer), "layer must be supported by MultiLayerModel");
Preconditions.checkNotNull(modelBuilder, "modelBuilder must not be null");
childModels.put(MultiLayerModel.Loader.BLOCK_LAYERS.inverse().get(layer), modelBuilder);
return this;
}
@Override
public JsonObject toJson(JsonObject json)
{
json = super.toJson(json);
JsonObject parts = new JsonObject();
for(Map.Entry<String, T> entry : childModels.entrySet())
{
parts.add(entry.getKey(), entry.getValue().toJson());
}
json.add("layers", parts);
return json;
}
}

View file

@ -0,0 +1,98 @@
package net.minecraftforge.client.model.generators.loaders;
import com.google.common.base.Preconditions;
import com.google.gson.JsonObject;
import net.minecraft.resources.ResourcePackType;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.model.generators.CustomLoaderBuilder;
import net.minecraftforge.client.model.generators.ModelBuilder;
import net.minecraftforge.common.data.ExistingFileHelper;
public class OBJLoaderBuilder<T extends ModelBuilder<T>> extends CustomLoaderBuilder<T>
{
public static <T extends ModelBuilder<T>> OBJLoaderBuilder<T> begin(T parent, ExistingFileHelper existingFileHelper)
{
return new OBJLoaderBuilder<>(parent, existingFileHelper);
}
private ResourceLocation modelLocation;
private Boolean detectCullableFaces;
private Boolean diffuseLighting;
private Boolean flipV;
private Boolean ambientToFullbright;
private ResourceLocation materialLibraryOverrideLocation;
protected OBJLoaderBuilder(T parent, ExistingFileHelper existingFileHelper)
{
super(new ResourceLocation("forge:obj"), parent, existingFileHelper);
}
public OBJLoaderBuilder<T> modelLocation(ResourceLocation modelLocation)
{
Preconditions.checkNotNull(modelLocation, "modelLocation must not be null");
Preconditions.checkArgument(existingFileHelper.exists(modelLocation, ResourcePackType.CLIENT_RESOURCES),
"OBJ Model %s does not exist in any known resource pack", modelLocation);
this.modelLocation = modelLocation;
return this;
}
public OBJLoaderBuilder<T> detectCullableFaces(boolean detectCullableFaces)
{
this.detectCullableFaces = detectCullableFaces;
return this;
}
public OBJLoaderBuilder<T> diffuseLighting(boolean diffuseLighting)
{
this.diffuseLighting = diffuseLighting;
return this;
}
public OBJLoaderBuilder<T> flipV(boolean flipV)
{
this.flipV = flipV;
return this;
}
public OBJLoaderBuilder<T> ambientToFullbright(boolean ambientToFullbright)
{
this.ambientToFullbright = ambientToFullbright;
return this;
}
public OBJLoaderBuilder<T> overrideMaterialLibrary(ResourceLocation materialLibraryOverrideLocation)
{
Preconditions.checkNotNull(materialLibraryOverrideLocation, "materialLibraryOverrideLocation must not be null");
Preconditions.checkArgument(existingFileHelper.exists(materialLibraryOverrideLocation, ResourcePackType.CLIENT_RESOURCES),
"OBJ Model %s does not exist in any known resource pack", materialLibraryOverrideLocation);
this.materialLibraryOverrideLocation = materialLibraryOverrideLocation;
return this;
}
@Override
public JsonObject toJson(JsonObject json)
{
json = super.toJson(json);
Preconditions.checkNotNull(modelLocation, "modelLocation must not be null");
json.addProperty("model", modelLocation.toString());
if (detectCullableFaces != null)
json.addProperty("detectCullableFaces", detectCullableFaces);
if (diffuseLighting != null)
json.addProperty("diffuseLighting", diffuseLighting);
if (flipV != null)
json.addProperty("flip-v", flipV);
if (ambientToFullbright != null)
json.addProperty("ambientToFullbright", ambientToFullbright);
if (materialLibraryOverrideLocation != null)
json.addProperty("materialLibraryOverrideLocation", materialLibraryOverrideLocation.toString());
return json;
}
}

View file

@ -0,0 +1,66 @@
package net.minecraftforge.client.model.generators.loaders;
import com.google.common.base.Preconditions;
import com.google.gson.JsonObject;
import net.minecraft.client.renderer.model.ItemCameraTransforms;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.model.MultiLayerModel;
import net.minecraftforge.client.model.SeparatePerspectiveModel;
import net.minecraftforge.client.model.generators.CustomLoaderBuilder;
import net.minecraftforge.client.model.generators.ModelBuilder;
import net.minecraftforge.common.data.ExistingFileHelper;
import java.util.LinkedHashMap;
import java.util.Map;
public class SeparatePerspectiveModelBuilder<T extends ModelBuilder<T>> extends CustomLoaderBuilder<T>
{
public static <T extends ModelBuilder<T>> SeparatePerspectiveModelBuilder<T> begin(T parent, ExistingFileHelper existingFileHelper)
{
return new SeparatePerspectiveModelBuilder<>(parent, existingFileHelper);
}
private T base;
private final Map<String, T> childModels = new LinkedHashMap<>();
protected SeparatePerspectiveModelBuilder(T parent, ExistingFileHelper existingFileHelper)
{
super(new ResourceLocation("forge:separate-perspective"), parent, existingFileHelper);
}
public SeparatePerspectiveModelBuilder<T> base(T modelBuilder)
{
Preconditions.checkNotNull(modelBuilder, "modelBuilder must not be null");
base = modelBuilder;
return this;
}
public SeparatePerspectiveModelBuilder<T> perspective(ItemCameraTransforms.TransformType perspective, T modelBuilder)
{
Preconditions.checkNotNull(perspective, "layer must not be null");
Preconditions.checkArgument(SeparatePerspectiveModel.Loader.PERSPECTIVES.containsValue(perspective), "perspective is not included in SeparatePerspectiveModel. New mc version?");
Preconditions.checkNotNull(modelBuilder, "modelBuilder must not be null");
childModels.put(SeparatePerspectiveModel.Loader.PERSPECTIVES.inverse().get(perspective), modelBuilder);
return this;
}
@Override
public JsonObject toJson(JsonObject json)
{
json = super.toJson(json);
if (base != null)
{
json.add("base", base.toJson());
}
JsonObject parts = new JsonObject();
for(Map.Entry<String, T> entry : childModels.entrySet())
{
parts.add(entry.getKey(), entry.getValue().toJson());
}
json.add("perspectives", parts);
return json;
}
}

View file

@ -70,6 +70,22 @@ public class ExistingFileHelper {
return new ResourceLocation(base.getNamespace(), prefix + "/" + base.getPath() + suffix);
}
/**
* Check if a given resource exists in the known resource packs.
*
* @param loc the base location of the resource, e.g.
* {@code "minecraft:block/stone"}
* @param type the type of resources to check
* @return {@code true} if the resource exists in any pack, {@code false}
* otherwise
*/
public boolean exists(ResourceLocation loc, ResourcePackType type) {
if (!enable) {
return true;
}
return getManager(type).hasResource(loc);
}
/**
* Check if a given resource exists in the known resource packs.
*
@ -83,15 +99,17 @@ public class ExistingFileHelper {
* otherwise
*/
public boolean exists(ResourceLocation loc, ResourcePackType type, String pathSuffix, String pathPrefix) {
if (!enable) {
return true;
}
return getManager(type).hasResource(getLocation(loc, pathSuffix, pathPrefix));
return exists(getLocation(loc, pathSuffix, pathPrefix), type);
}
@VisibleForTesting
public IResource getResource(ResourceLocation loc, ResourcePackType type, String pathSuffix, String pathPrefix) throws IOException {
return getManager(type).getResource(getLocation(loc, pathSuffix, pathPrefix));
return getResource(getLocation(loc, pathSuffix, pathPrefix), type);
}
@VisibleForTesting
public IResource getResource(ResourceLocation loc, ResourcePackType type) throws IOException {
return getManager(type).getResource(loc);
}
/**

View file

@ -26,13 +26,11 @@ import com.mojang.datafixers.util.Pair;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.material.Material;
import net.minecraft.client.renderer.model.IModelTransform;
import net.minecraft.client.renderer.model.IUnbakedModel;
import net.minecraft.client.renderer.model.ModelBakery;
import net.minecraft.client.renderer.model.RenderMaterial;
import net.minecraft.client.renderer.model.*;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.renderer.vertex.VertexFormatElement;
import net.minecraft.data.DataGenerator;
import net.minecraft.entity.Entity;
import net.minecraft.inventory.EquipmentSlotType;
import net.minecraft.item.*;
@ -50,12 +48,18 @@ import net.minecraftforge.client.model.IModelBuilder;
import net.minecraftforge.client.model.IModelConfiguration;
import net.minecraftforge.client.model.IModelLoader;
import net.minecraftforge.client.model.ModelLoaderRegistry;
import net.minecraftforge.client.model.generators.BlockStateProvider;
import net.minecraftforge.client.model.generators.ItemModelProvider;
import net.minecraftforge.client.model.generators.loaders.ItemLayersModelBuilder;
import net.minecraftforge.client.model.generators.loaders.OBJLoaderBuilder;
import net.minecraftforge.client.model.generators.loaders.SeparatePerspectiveModelBuilder;
import net.minecraftforge.client.model.geometry.ISimpleModelGeometry;
import net.minecraftforge.client.model.pipeline.BakedQuadBuilder;
import net.minecraftforge.common.data.ExistingFileHelper;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.RegistryObject;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import net.minecraftforge.fml.event.lifecycle.GatherDataEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
@ -136,6 +140,7 @@ public class NewModelLoaderTest
ITEMS.register(modEventBus);
modEventBus.addListener(this::modelRegistry);
modEventBus.addListener(this::datagen);
}
public void modelRegistry(ModelRegistryEvent event)
@ -209,4 +214,64 @@ public class NewModelLoaderTest
return Collections.singleton(owner.resolveTexture("particle"));
}
}
private void datagen(GatherDataEvent event)
{
DataGenerator gen = event.getGenerator();
if (event.includeClient())
{
// Let blockstate provider see generated item models by passing its existing file helper
ItemModelProvider itemModels = new ItemModels(gen, event.getExistingFileHelper());
gen.addProvider(itemModels);
gen.addProvider(new BlockStates(gen, itemModels.existingFileHelper));
}
}
public static class ItemModels extends ItemModelProvider
{
public ItemModels(DataGenerator generator, ExistingFileHelper existingFileHelper)
{
super(generator, MODID, existingFileHelper);
}
@Override
protected void registerModels()
{
withExistingParent(NewModelLoaderTest.item_layers.getId().getPath(), "forge:item/default")
.texture("layer0", "minecraft:item/coal")
.texture("layer1", "minecraft:item/stick")
.customLoader(ItemLayersModelBuilder::begin)
.fullbright(1)
.end();
withExistingParent(NewModelLoaderTest.separate_perspective.getId().getPath(), "forge:item/default")
.customLoader(SeparatePerspectiveModelBuilder::begin)
.base(nested().parent(getExistingFile(mcLoc("minecraft:item/coal"))))
.perspective(ItemCameraTransforms.TransformType.GUI, nested().parent(getExistingFile(mcLoc("minecraft:item/snowball"))))
.perspective(ItemCameraTransforms.TransformType.FIRST_PERSON_LEFT_HAND, nested().parent(getExistingFile(mcLoc("minecraft:item/bone"))))
.end();
}
}
public static class BlockStates extends BlockStateProvider
{
public BlockStates(DataGenerator gen, ExistingFileHelper exFileHelper)
{
super(gen, MODID, exFileHelper);
}
@Override
protected void registerStatesAndModels()
{
simpleBlock(NewModelLoaderTest.obj_block.get(), models()
.getBuilder(NewModelLoaderTest.obj_block.getId().getPath())
.customLoader(OBJLoaderBuilder::begin)
.modelLocation(new ResourceLocation("new_model_loader_test:models/item/sugar_glider.obj"))
.flipV(true)
.end()
.texture("qr", "minecraft:block/oak_planks")
.texture("particle", "#qr")
);
}
}
}