
com.parzivail.util.client.texture.TextureProvider Maven / Gradle / Ivy
package com.parzivail.util.client.texture;
import com.mojang.authlib.minecraft.InsecurePublicKeyException;
import com.mojang.blaze3d.systems.RenderSystem;
import com.parzivail.util.ParziUtil;
import com.parzivail.util.data.FallbackIdentifier;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Supplier;
import net.minecraft.class_1044;
import net.minecraft.class_1060;
import net.minecraft.class_156;
import net.minecraft.class_2960;
import net.minecraft.class_310;
public abstract class TextureProvider
{
private static final ArrayList TEXTURE_CACHE = new ArrayList<>();
private static final ArrayList FAILURE_CACHE = new ArrayList<>();
private static final HashMap>> LOAD_CALLBACKS = new HashMap<>();
public static final ArrayList> TEXTURE_PROVIDERS = new ArrayList<>();
private final class_2960 root;
private final class_1060 textureManager;
protected TextureProvider(class_2960 cacheIdRoot, class_1060 textureManager)
{
this.root = cacheIdRoot;
this.textureManager = textureManager;
TEXTURE_PROVIDERS.add(this);
}
@NotNull
protected class_2960 createCacheId(String requestName)
{
return new class_2960(root.method_12836(), root.method_12832() + "/" + requestName);
}
public boolean isProviderFor(class_2960 cacheId)
{
return cacheId.method_12836().equals(root.method_12836()) && cacheId.method_12832().startsWith(root.method_12832());
}
public class_2960 getProvidedId(class_2960 cacheId)
{
// If we provided this ID, return it
if (isProviderFor(cacheId))
return cacheId;
// Also return if we provided the fallback ID in a FallbackIdentifier
if (cacheId instanceof FallbackIdentifier fi && isProviderFor(fi.getSource()))
return fi.getSource();
return null;
}
public boolean isReady(class_2960 cacheId)
{
return TEXTURE_CACHE.contains(cacheId) && textureManager.method_34590(cacheId, null) != null;
}
protected void markTextureDirty(class_2960 cacheId)
{
TEXTURE_CACHE.removeIf(cacheId::equals);
}
protected void markTextureFailure(class_2960 cacheId)
{
FAILURE_CACHE.add(cacheId);
}
protected void registerDependencyCallbacks(class_2960 cacheId, class_2960 dependencyCacheId)
{
for (var provider : TEXTURE_PROVIDERS)
{
var providerCacheId = provider.getProvidedId(dependencyCacheId);
if (providerCacheId != null && !provider.isReady(dependencyCacheId))
{
provider.addLoadCallback(providerCacheId, (success) -> {
if (success)
markTextureDirty(cacheId);
});
// There should only be one provider for each cache ID
break;
}
}
}
public class_2960 getId(String requestName, Supplier fallback, Supplier requestFulfiller)
{
var cacheId = createCacheId(requestName);
if (FAILURE_CACHE.contains(cacheId))
return fallback == null ? cacheId : fallback.get();
var texture = textureManager.method_34590(cacheId, null);
// The texture is fully loaded and isn't marked as dirty (i.e. the cache contains it)
if (texture != null && TEXTURE_CACHE.contains(cacheId))
return cacheId;
if (!TEXTURE_CACHE.contains(cacheId))
{
// The texture hasn't been stacked yet
bakeTextureAsync(cacheId, requestFulfiller.get());
TEXTURE_CACHE.add(cacheId);
}
// The texture has been stacked but hasn't been loaded yet
// Don't use a fallback if none is supplied
if (fallback == null)
return cacheId;
// Return the requested fallback
var fallbackId = fallback.get();
return new FallbackIdentifier(fallbackId.method_12836(), fallbackId.method_12832(), cacheId);
}
protected abstract CallbackTexture createTexture(class_2960 destId, TData requestData, Consumer callback);
protected void bakeTextureAsync(class_2960 cacheId, TData request)
{
class_156.method_18349().execute(() -> {
try
{
var minecraft = class_310.method_1551();
minecraft.execute(() -> RenderSystem.recordRenderCall(() -> registerTexture(cacheId, request)));
}
catch (InsecurePublicKeyException insecureTextureException)
{
ParziUtil.LOG.warn("Attempt to load insecure texture blocked: %s ", cacheId, insecureTextureException);
}
});
}
protected void registerTexture(class_2960 cacheId, TData request)
{
ParziUtil.LOG.debug("Registering texture %s", cacheId);
this.textureManager.method_4616(cacheId, createTexture(cacheId, request, success -> pollCallbacks(cacheId, success)));
}
public void addLoadCallback(class_2960 target, Consumer callback)
{
if (isReady(target))
{
callback.accept(true);
return;
}
if (!LOAD_CALLBACKS.containsKey(target))
LOAD_CALLBACKS.put(target, new ArrayList<>());
LOAD_CALLBACKS.get(target).add(callback);
}
private void pollCallbacks(class_2960 identifier, boolean success)
{
var callbacks = LOAD_CALLBACKS.get(identifier);
if (callbacks == null)
return;
callbacks.forEach(callback -> callback.accept(success));
LOAD_CALLBACKS.remove(identifier);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy