Flywheel/src/main/java/com/jozufozu/flywheel/backend/Loader.java

128 lines
3.8 KiB
Java
Raw Normal View History

package com.jozufozu.flywheel.backend;
import java.util.Collection;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
import com.jozufozu.flywheel.backend.source.Resolver;
import com.jozufozu.flywheel.backend.source.ShaderLoadingException;
import com.jozufozu.flywheel.backend.source.ShaderSources;
import com.jozufozu.flywheel.core.crumbling.CrumblingRenderer;
import com.jozufozu.flywheel.core.shader.spec.ProgramSpec;
import com.jozufozu.flywheel.event.GatherContextEvent;
import com.jozufozu.flywheel.util.ResourceUtil;
import com.jozufozu.flywheel.util.StreamUtil;
import com.mojang.datafixers.util.Pair;
import com.mojang.serialization.DataResult;
import com.mojang.serialization.JsonOps;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
2021-09-15 09:26:51 +02:00
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.resources.ReloadableResourceManager;
import net.minecraft.server.packs.resources.Resource;
import net.minecraft.server.packs.resources.ResourceManager;
2021-09-15 09:26:51 +02:00
import net.minecraft.server.packs.resources.ResourceManagerReloadListener;
import net.minecraftforge.fml.ModLoader;
2021-09-15 09:26:51 +02:00
/**
* The main entity for loading shaders.
*
* <p>
2021-09-15 09:26:51 +02:00
* This class is responsible for invoking the loading, parsing, and compilation stages.
* </p>
*/
2021-09-15 09:26:51 +02:00
public class Loader implements ResourceManagerReloadListener {
public static final String PROGRAM_DIR = "flywheel/programs/";
private static final Gson GSON = new GsonBuilder().create();
private final Backend backend;
private boolean shouldCrash;
private boolean firstLoad = true;
public Loader(Backend backend) {
this.backend = backend;
// Can be null when running datagenerators due to the unfortunate time we call this
Minecraft minecraft = Minecraft.getInstance();
if (minecraft != null) {
ResourceManager manager = minecraft.getResourceManager();
if (manager instanceof ReloadableResourceManager) {
((ReloadableResourceManager) manager).registerReloadListener(this);
}
}
}
public void notifyError() {
shouldCrash = true;
}
@Override
2021-09-15 09:26:51 +02:00
public void onResourceManagerReload(ResourceManager manager) {
backend.refresh();
2021-09-15 09:26:51 +02:00
if (backend.gl20()) {
shouldCrash = false;
backend._clearContexts();
2021-09-15 09:26:51 +02:00
Resolver.INSTANCE.invalidate();
ModLoader.get()
.postEvent(new GatherContextEvent(backend, firstLoad));
2021-09-15 09:26:51 +02:00
ShaderSources sources = new ShaderSources(manager);
2021-09-15 09:26:51 +02:00
loadProgramSpecs(manager);
2021-09-15 09:26:51 +02:00
Resolver.INSTANCE.resolve(sources);
for (IShaderContext<?> context : backend.allContexts()) {
2021-09-15 09:26:51 +02:00
context.load();
}
2021-09-15 09:26:51 +02:00
if (shouldCrash) {
throw new ShaderLoadingException("Could not load all shaders, see log for details");
}
2021-09-15 09:26:51 +02:00
Backend.log.info("Loaded all shader programs.");
2021-09-15 09:26:51 +02:00
ClientLevel world = Minecraft.getInstance().level;
if (Backend.isFlywheelWorld(world)) {
// TODO: looks like it might be good to have another event here
InstancedRenderDispatcher.resetInstanceWorld(world);
2021-09-15 09:26:51 +02:00
CrumblingRenderer.reset();
}
}
2021-09-15 09:26:51 +02:00
firstLoad = false;
}
private void loadProgramSpecs(ResourceManager manager) {
Collection<ResourceLocation> programSpecs = manager.listResources(PROGRAM_DIR, s -> s.endsWith(".json"));
for (ResourceLocation location : programSpecs) {
try {
Resource file = manager.getResource(location);
String s = StreamUtil.readToString(file.getInputStream());
ResourceLocation specName = ResourceUtil.trim(location, PROGRAM_DIR, ".json");
DataResult<Pair<ProgramSpec, JsonElement>> result = ProgramSpec.CODEC.decode(JsonOps.INSTANCE, GSON.fromJson(s, JsonElement.class));
ProgramSpec spec = result.get()
.orThrow()
.getFirst();
spec.setName(specName);
backend.register(spec);
} catch (Exception e) {
Backend.log.error(e);
}
}
}
}