Add generated resource tracking to ExistingFileHelper

This commit is contained in:
tterrag 2020-12-10 22:22:09 -05:00
parent a57a240c13
commit 2d9a1bc6f9
5 changed files with 154 additions and 80 deletions

View file

@ -1,11 +1,12 @@
--- a/net/minecraft/data/TagsProvider.java --- a/net/minecraft/data/TagsProvider.java
+++ b/net/minecraft/data/TagsProvider.java +++ b/net/minecraft/data/TagsProvider.java
@@ -28,10 +28,18 @@ @@ -28,10 +28,20 @@
protected final DataGenerator field_200433_a; protected final DataGenerator field_200433_a;
protected final Registry<T> field_200435_c; protected final Registry<T> field_200435_c;
protected final Map<ResourceLocation, ITag.Builder> field_200434_b = Maps.newLinkedHashMap(); protected final Map<ResourceLocation, ITag.Builder> field_200434_b = Maps.newLinkedHashMap();
+ protected final String modId; + protected final String modId;
+ protected final net.minecraftforge.common.data.ExistingFileHelper existingFileHelper; + protected final net.minecraftforge.common.data.ExistingFileHelper existingFileHelper;
+ private final net.minecraftforge.common.data.ExistingFileHelper.IResourceType resourceType;
+ @Deprecated//Forge, Use ModID version. + @Deprecated//Forge, Use ModID version.
protected TagsProvider(DataGenerator p_i49827_1_, Registry<T> p_i49827_2_) { protected TagsProvider(DataGenerator p_i49827_1_, Registry<T> p_i49827_2_) {
@ -16,10 +17,11 @@
this.field_200435_c = p_i49827_2_; this.field_200435_c = p_i49827_2_;
+ this.modId = modId; + this.modId = modId;
+ this.existingFileHelper = existingFileHelper; + this.existingFileHelper = existingFileHelper;
+ this.resourceType = new net.minecraftforge.common.data.ExistingFileHelper.ResourceType(net.minecraft.resources.ResourcePackType.SERVER_DATA, ".json", "tags/" + getTagFolder());
} }
protected abstract void func_200432_c(); protected abstract void func_200432_c();
@@ -47,12 +55,14 @@ @@ -47,12 +57,14 @@
return this.field_200435_c.func_241873_b(p_240527_1_).orElse((T)null); return this.field_200435_c.func_241873_b(p_240527_1_).orElse((T)null);
}; };
this.field_200434_b.forEach((p_240524_4_, p_240524_5_) -> { this.field_200434_b.forEach((p_240524_4_, p_240524_5_) -> {
@ -35,7 +37,7 @@
try { try {
String s = field_200437_e.toJson((JsonElement)jsonobject); String s = field_200437_e.toJson((JsonElement)jsonobject);
@@ -74,11 +84,26 @@ @@ -74,20 +86,36 @@
}); });
} }
@ -44,7 +46,7 @@
+ // We only care about non-optional tag entries, this is the only type that can reference a resource and needs validation + // We only care about non-optional tag entries, this is the only type that can reference a resource and needs validation
+ // Optional tags should not be validated + // Optional tags should not be validated
+ if (entry instanceof ITag.TagEntry) { + if (entry instanceof ITag.TagEntry) {
+ return existingFileHelper == null || !existingFileHelper.exists(((ITag.TagEntry)entry).getId(), net.minecraft.resources.ResourcePackType.SERVER_DATA, ".json", "tags/" + getTagFolder()); + return existingFileHelper == null || !existingFileHelper.exists(((ITag.TagEntry)entry).getId(), resourceType);
+ } + }
+ return false; + return false;
+ } + }
@ -63,7 +65,9 @@
} }
protected ITag.Builder func_240525_b_(ITag.INamedTag<T> p_240525_1_) { protected ITag.Builder func_240525_b_(ITag.INamedTag<T> p_240525_1_) {
@@ -87,7 +112,7 @@ return this.field_200434_b.computeIfAbsent(p_240525_1_.func_230234_a_(), (p_240526_0_) -> {
+ existingFileHelper.trackGenerated(p_240526_0_, resourceType);
return new ITag.Builder();
}); });
} }
@ -72,7 +76,7 @@
private final ITag.Builder field_240528_a_; private final ITag.Builder field_240528_a_;
private final Registry<T> field_240529_b_; private final Registry<T> field_240529_b_;
private final String field_240530_c_; private final String field_240530_c_;
@@ -115,5 +140,18 @@ @@ -115,5 +143,18 @@
}); });
return this; return this;
} }

View file

@ -19,7 +19,11 @@
package net.minecraftforge.client.model.generators; package net.minecraftforge.client.model.generators;
import java.util.*; import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import java.util.function.BiFunction; import java.util.function.BiFunction;
@ -33,20 +37,19 @@ import com.google.gson.Gson;
import com.google.gson.JsonArray; import com.google.gson.JsonArray;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import net.minecraft.util.math.vector.Vector3f;
import net.minecraftforge.common.data.ExistingFileHelper;
import net.minecraft.client.renderer.model.BlockFaceUV; import net.minecraft.client.renderer.model.BlockFaceUV;
import net.minecraft.client.renderer.model.BlockModel.GuiLight;
import net.minecraft.client.renderer.model.BlockPart; import net.minecraft.client.renderer.model.BlockPart;
import net.minecraft.client.renderer.model.BlockPartFace; import net.minecraft.client.renderer.model.BlockPartFace;
import net.minecraft.client.renderer.model.BlockPartRotation; import net.minecraft.client.renderer.model.BlockPartRotation;
import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType; import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType;
import net.minecraft.client.renderer.model.ItemTransformVec3f; import net.minecraft.client.renderer.model.ItemTransformVec3f;
import net.minecraft.client.renderer.model.BlockModel.GuiLight;
import net.minecraft.client.renderer.texture.MissingTextureSprite; import net.minecraft.client.renderer.texture.MissingTextureSprite;
import net.minecraft.resources.ResourcePackType;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.vector.Vector3f;
import net.minecraftforge.common.data.ExistingFileHelper;
/** /**
* General purpose model builder, contains all the commonalities between item * General purpose model builder, contains all the commonalities between item
@ -146,7 +149,7 @@ public class ModelBuilder<T extends ModelBuilder<T>> extends ModelFile {
public T texture(String key, ResourceLocation texture) { public T texture(String key, ResourceLocation texture) {
Preconditions.checkNotNull(key, "Key must not be null"); Preconditions.checkNotNull(key, "Key must not be null");
Preconditions.checkNotNull(texture, "Texture must not be null"); Preconditions.checkNotNull(texture, "Texture must not be null");
Preconditions.checkArgument(existingFileHelper.exists(texture, ResourcePackType.CLIENT_RESOURCES, ".png", "textures"), Preconditions.checkArgument(existingFileHelper.exists(texture, ModelProvider.TEXTURE),
"Texture %s does not exist in any known resource pack", texture); "Texture %s does not exist in any known resource pack", texture);
this.textures.put(key, texture.toString()); this.textures.put(key, texture.toString());
return self(); return self();

View file

@ -21,7 +21,6 @@ package net.minecraftforge.client.model.generators;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import net.minecraft.resources.ResourcePackType;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraftforge.common.data.ExistingFileHelper; import net.minecraftforge.common.data.ExistingFileHelper;
@ -78,9 +77,9 @@ public abstract class ModelFile {
@Override @Override
protected boolean exists() { protected boolean exists() {
if (getUncheckedLocation().getPath().contains(".")) if (getUncheckedLocation().getPath().contains("."))
return existingHelper.exists(getUncheckedLocation(), ResourcePackType.CLIENT_RESOURCES, "", "models"); return existingHelper.exists(getUncheckedLocation(), ModelProvider.MODEL_WITH_EXTENSION);
else else
return existingHelper.exists(getUncheckedLocation(), ResourcePackType.CLIENT_RESOURCES, ".json", "models"); return existingHelper.exists(getUncheckedLocation(), ModelProvider.MODEL);
} }
} }
} }

View file

@ -21,7 +21,6 @@ package net.minecraftforge.client.model.generators;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.function.BiFunction; import java.util.function.BiFunction;
@ -35,61 +34,20 @@ import com.google.gson.GsonBuilder;
import net.minecraft.data.DataGenerator; import net.minecraft.data.DataGenerator;
import net.minecraft.data.DirectoryCache; import net.minecraft.data.DirectoryCache;
import net.minecraft.data.IDataProvider; import net.minecraft.data.IDataProvider;
import net.minecraft.resources.IResource;
import net.minecraft.resources.ResourcePackType; import net.minecraft.resources.ResourcePackType;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraftforge.common.data.ExistingFileHelper; import net.minecraftforge.common.data.ExistingFileHelper;
import net.minecraftforge.common.data.ExistingFileHelper.ResourceType;
public abstract class ModelProvider<T extends ModelBuilder<T>> implements IDataProvider { public abstract class ModelProvider<T extends ModelBuilder<T>> implements IDataProvider {
private class ExistingFileHelperIncludingGenerated extends ExistingFileHelper {
private final ExistingFileHelper delegate;
public ExistingFileHelperIncludingGenerated(ExistingFileHelper delegate) {
super(Collections.emptyList(), Collections.emptySet(), true);
this.delegate = delegate;
}
@Override
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"; public static final String BLOCK_FOLDER = "block";
public static final String ITEM_FOLDER = "item"; public static final String ITEM_FOLDER = "item";
protected static final ResourceType TEXTURE = new ResourceType(ResourcePackType.CLIENT_RESOURCES, ".png", "textures");
protected static final ResourceType MODEL = new ResourceType(ResourcePackType.CLIENT_RESOURCES, ".json", "models");
protected static final ResourceType MODEL_WITH_EXTENSION = new ResourceType(ResourcePackType.CLIENT_RESOURCES, "", "models");
private static final Gson GSON = (new GsonBuilder()).setPrettyPrinting().create(); private static final Gson GSON = (new GsonBuilder()).setPrettyPrinting().create();
protected final DataGenerator generator; protected final DataGenerator generator;
protected final String modid; protected final String modid;
@ -112,7 +70,7 @@ public abstract class ModelProvider<T extends ModelBuilder<T>> implements IDataP
Preconditions.checkNotNull(factory); Preconditions.checkNotNull(factory);
this.factory = factory; this.factory = factory;
Preconditions.checkNotNull(existingFileHelper); Preconditions.checkNotNull(existingFileHelper);
this.existingFileHelper = new ExistingFileHelperIncludingGenerated(existingFileHelper); this.existingFileHelper = existingFileHelper;
} }
public ModelProvider(DataGenerator generator, String modid, String folder, BiFunction<ResourceLocation, ExistingFileHelper, T> builderFromModId, ExistingFileHelper existingFileHelper) { public ModelProvider(DataGenerator generator, String modid, String folder, BiFunction<ResourceLocation, ExistingFileHelper, T> builderFromModId, ExistingFileHelper existingFileHelper) {
@ -122,6 +80,7 @@ public abstract class ModelProvider<T extends ModelBuilder<T>> implements IDataP
public T getBuilder(String path) { public T getBuilder(String path) {
Preconditions.checkNotNull(path, "Path must not be null"); Preconditions.checkNotNull(path, "Path must not be null");
ResourceLocation outputLoc = extendWithFolder(path.contains(":") ? new ResourceLocation(path) : new ResourceLocation(modid, path)); ResourceLocation outputLoc = extendWithFolder(path.contains(":") ? new ResourceLocation(path) : new ResourceLocation(modid, path));
this.existingFileHelper.trackGenerated(outputLoc, MODEL);
return generatedModels.computeIfAbsent(outputLoc, factory); return generatedModels.computeIfAbsent(outputLoc, factory);
} }

View file

@ -23,11 +23,14 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.Collection; import java.util.Collection;
import com.google.common.annotations.VisibleForTesting;
import java.util.Collections; import java.util.Collections;
import java.util.Set; import java.util.Set;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import net.minecraft.data.IDataProvider;
import net.minecraft.resources.FilePack; import net.minecraft.resources.FilePack;
import net.minecraft.resources.FolderPack; import net.minecraft.resources.FolderPack;
import net.minecraft.resources.IResource; import net.minecraft.resources.IResource;
@ -37,6 +40,7 @@ import net.minecraft.resources.ResourcePackType;
import net.minecraft.resources.SimpleReloadableResourceManager; import net.minecraft.resources.SimpleReloadableResourceManager;
import net.minecraft.resources.VanillaPack; import net.minecraft.resources.VanillaPack;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.model.generators.ModelBuilder;
import net.minecraftforge.fml.ModList; import net.minecraftforge.fml.ModList;
import net.minecraftforge.fml.event.lifecycle.GatherDataEvent; import net.minecraftforge.fml.event.lifecycle.GatherDataEvent;
import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo; import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo;
@ -51,14 +55,56 @@ import net.minecraftforge.fml.packs.ModFileResourcePack;
*/ */
public class ExistingFileHelper { public class ExistingFileHelper {
public interface IResourceType {
ResourcePackType getPackType();
String getSuffix();
String getPrefix();
}
public static class ResourceType implements IResourceType {
final ResourcePackType packType;
final String suffix, prefix;
public ResourceType(ResourcePackType type, String suffix, String prefix) {
this.packType = type;
this.suffix = suffix;
this.prefix = prefix;
}
@Override
public ResourcePackType getPackType() { return packType; }
@Override
public String getSuffix() { return suffix; }
@Override
public String getPrefix() { return prefix; }
}
private final SimpleReloadableResourceManager clientResources, serverData; private final SimpleReloadableResourceManager clientResources, serverData;
private final boolean enable; private final boolean enable;
private final Multimap<ResourcePackType, ResourceLocation> generated = HashMultimap.create();
@Deprecated//TODO: Remove in 1.17 @Deprecated//TODO: Remove in 1.17
public ExistingFileHelper(Collection<Path> existingPacks, boolean enable) { public ExistingFileHelper(Collection<Path> existingPacks, boolean enable) {
this(existingPacks, Collections.emptySet(), enable); this(existingPacks, Collections.emptySet(), enable);
} }
/**
* Create a new helper. This should probably <em>NOT</em> be used by mods, as
* the instance provided by forge is designed to be a central instance that
* tracks existence of generated data.
* <p>
* Only create a new helper if you intentionally want to ignore the existence of
* other generated files.
*
* @param existingPacks
* @param existingMods
* @param enable
*/
public ExistingFileHelper(Collection<Path> existingPacks, Set<String> existingMods, boolean enable) { public ExistingFileHelper(Collection<Path> existingPacks, Set<String> existingMods, boolean enable) {
this.clientResources = new SimpleReloadableResourceManager(ResourcePackType.CLIENT_RESOURCES); this.clientResources = new SimpleReloadableResourceManager(ResourcePackType.CLIENT_RESOURCES);
this.serverData = new SimpleReloadableResourceManager(ResourcePackType.SERVER_DATA); this.serverData = new SimpleReloadableResourceManager(ResourcePackType.SERVER_DATA);
@ -81,8 +127,8 @@ public class ExistingFileHelper {
this.enable = enable; this.enable = enable;
} }
private IResourceManager getManager(ResourcePackType type) { private IResourceManager getManager(ResourcePackType packType) {
return type == ResourcePackType.CLIENT_RESOURCES ? clientResources : serverData; return packType == ResourcePackType.CLIENT_RESOURCES ? clientResources : serverData;
} }
private ResourceLocation getLocation(ResourceLocation base, String suffix, String prefix) { private ResourceLocation getLocation(ResourceLocation base, String suffix, String prefix) {
@ -92,17 +138,34 @@ public class ExistingFileHelper {
/** /**
* Check if a given resource exists in the known resource packs. * Check if a given resource exists in the known resource packs.
* *
* @param loc the base location of the resource, e.g. * @param loc the complete location of the resource, e.g.
* {@code "minecraft:block/stone"} * {@code "minecraft:textures/block/stone.png"}
* @param type the type of resources to check * @param packType the type of resources to check
* @return {@code true} if the resource exists in any pack, {@code false} * @return {@code true} if the resource exists in any pack, {@code false}
* otherwise * otherwise
*/ */
public boolean exists(ResourceLocation loc, ResourcePackType type) { public boolean exists(ResourceLocation loc, ResourcePackType packType) {
if (!enable) { if (!enable) {
return true; return true;
} }
return getManager(type).hasResource(loc); return generated.get(packType).contains(loc) || getManager(packType).hasResource(loc);
}
/**
* Check if a given resource exists in the known resource packs. This is a
* convenience method to avoid repeating type/prefix/suffix and instead use the
* common definitions in {@link ResourceType}, or a custom {@link IResourceType}
* definition.
*
* @param loc the base location of the resource, e.g.
* {@code "minecraft:block/stone"}
* @param type a {@link IResourceType} describing how to form the path to the
* resource
* @return {@code true} if the resource exists in any pack, {@code false}
* otherwise
*/
public boolean exists(ResourceLocation loc, IResourceType type) {
return exists(getLocation(loc, type.getSuffix(), type.getPrefix()), type.getPackType());
} }
/** /**
@ -110,25 +173,71 @@ public class ExistingFileHelper {
* *
* @param loc the base location of the resource, e.g. * @param loc the base location of the resource, e.g.
* {@code "minecraft:block/stone"} * {@code "minecraft:block/stone"}
* @param type the type of resources to check * @param packType the type of resources to check
* @param pathSuffix a string to append after the path, e.g. {@code ".json"} * @param pathSuffix a string to append after the path, e.g. {@code ".json"}
* @param pathPrefix a string to append before the path, before a slash, e.g. * @param pathPrefix a string to append before the path, before a slash, e.g.
* {@code "models"} * {@code "models"}
* @return {@code true} if the resource exists in any pack, {@code false} * @return {@code true} if the resource exists in any pack, {@code false}
* otherwise * otherwise
*/ */
public boolean exists(ResourceLocation loc, ResourcePackType type, String pathSuffix, String pathPrefix) { public boolean exists(ResourceLocation loc, ResourcePackType packType, String pathSuffix, String pathPrefix) {
return exists(getLocation(loc, pathSuffix, pathPrefix), type); return exists(getLocation(loc, pathSuffix, pathPrefix), packType);
}
/**
* Track the existence of a generated file. This is a convenience method to
* avoid repeating type/prefix/suffix and instead use the common definitions in
* {@link ResourceType}, or a custom {@link IResourceType} definition.
* <p>
* This should be called by data providers immediately when a new data object is
* created, i.e. not during
* {@link IDataProvider#act(net.minecraft.data.DirectoryCache) act} but instead
* when the "builder" (or whatever intermediate object) is created, such as a
* {@link ModelBuilder}.
* <p>
* This represents a <em>promise</em> to generate the file later, since other
* datagen may rely on this file existing.
*
* @param loc the base location of the resource, e.g.
* {@code "minecraft:block/stone"}
* @param type a {@link IResourceType} describing how to form the path to the
* resource
*/
public void trackGenerated(ResourceLocation loc, IResourceType type) {
this.generated.put(type.getPackType(), getLocation(loc, type.getSuffix(), type.getPrefix()));
}
/**
* Track the existence of a generated file.
* <p>
* This should be called by data providers immediately when a new data object is
* created, i.e. not during
* {@link IDataProvider#act(net.minecraft.data.DirectoryCache) act} but instead
* when the "builder" (or whatever intermediate object) is created, such as a
* {@link ModelBuilder}.
* <p>
* This represents a <em>promise</em> to generate the file later, since other
* datagen may rely on this file existing.
*
* @param loc the base location of the resource, e.g.
* {@code "minecraft:block/stone"}
* @param packType the type of resources to check
* @param pathSuffix a string to append after the path, e.g. {@code ".json"}
* @param pathPrefix a string to append before the path, before a slash, e.g.
* {@code "models"}
*/
public void trackGenerated(ResourceLocation loc, ResourcePackType packType, String pathSuffix, String pathPrefix) {
this.generated.put(packType, getLocation(loc, pathSuffix, pathPrefix));
} }
@VisibleForTesting @VisibleForTesting
public IResource getResource(ResourceLocation loc, ResourcePackType type, String pathSuffix, String pathPrefix) throws IOException { public IResource getResource(ResourceLocation loc, ResourcePackType packType, String pathSuffix, String pathPrefix) throws IOException {
return getResource(getLocation(loc, pathSuffix, pathPrefix), type); return getResource(getLocation(loc, pathSuffix, pathPrefix), packType);
} }
@VisibleForTesting @VisibleForTesting
public IResource getResource(ResourceLocation loc, ResourcePackType type) throws IOException { public IResource getResource(ResourceLocation loc, ResourcePackType packType) throws IOException {
return getManager(type).getResource(loc); return getManager(packType).getResource(loc);
} }
/** /**