2021-08-11 00:20:51 +02:00
|
|
|
package com.jozufozu.flywheel.backend;
|
|
|
|
|
2021-11-18 23:59:39 +01:00
|
|
|
import java.util.Collection;
|
|
|
|
|
2021-08-11 00:20:51 +02:00
|
|
|
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;
|
2021-09-15 08:45:29 +02:00
|
|
|
import net.minecraft.client.multiplayer.ClientLevel;
|
2021-09-15 09:26:51 +02:00
|
|
|
import net.minecraft.resources.ResourceLocation;
|
2021-09-15 08:45:29 +02:00
|
|
|
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;
|
2021-08-11 00:20:51 +02:00
|
|
|
import net.minecraftforge.fml.ModLoader;
|
2021-09-15 09:26:51 +02:00
|
|
|
|
2021-08-11 00:20: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.
|
2021-08-11 00:20:51 +02:00
|
|
|
* </p>
|
|
|
|
*/
|
2021-09-15 09:26:51 +02:00
|
|
|
public class Loader implements ResourceManagerReloadListener {
|
2021-08-11 00:20:51 +02:00
|
|
|
public static final String PROGRAM_DIR = "flywheel/programs/";
|
|
|
|
private static final Gson GSON = new GsonBuilder().create();
|
|
|
|
|
|
|
|
private final Backend backend;
|
2021-08-11 02:39:11 +02:00
|
|
|
private boolean shouldCrash;
|
2021-08-11 00:20:51 +02:00
|
|
|
|
2021-08-13 20:23:09 +02:00
|
|
|
private boolean firstLoad = true;
|
|
|
|
|
2021-08-11 00:20:51 +02:00
|
|
|
public Loader(Backend backend) {
|
|
|
|
this.backend = backend;
|
|
|
|
|
2021-08-11 02:39:11 +02:00
|
|
|
// Can be null when running datagenerators due to the unfortunate time we call this
|
|
|
|
Minecraft minecraft = Minecraft.getInstance();
|
|
|
|
if (minecraft != null) {
|
2021-09-15 08:45:29 +02:00
|
|
|
ResourceManager manager = minecraft.getResourceManager();
|
|
|
|
if (manager instanceof ReloadableResourceManager) {
|
|
|
|
((ReloadableResourceManager) manager).registerReloadListener(this);
|
2021-08-11 02:39:11 +02:00
|
|
|
}
|
2021-08-11 00:20:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void notifyError() {
|
|
|
|
shouldCrash = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2021-09-15 09:26:51 +02:00
|
|
|
public void onResourceManagerReload(ResourceManager manager) {
|
|
|
|
backend.refresh();
|
2021-08-11 00:20:51 +02:00
|
|
|
|
2021-09-15 09:26:51 +02:00
|
|
|
if (backend.gl20()) {
|
|
|
|
shouldCrash = false;
|
|
|
|
backend._clearContexts();
|
2021-08-11 00:20:51 +02:00
|
|
|
|
2021-09-15 09:26:51 +02:00
|
|
|
Resolver.INSTANCE.invalidate();
|
|
|
|
ModLoader.get()
|
|
|
|
.postEvent(new GatherContextEvent(backend, firstLoad));
|
2021-08-11 00:20:51 +02:00
|
|
|
|
2021-09-15 09:26:51 +02:00
|
|
|
ShaderSources sources = new ShaderSources(manager);
|
2021-08-11 00:20:51 +02:00
|
|
|
|
2021-09-15 09:26:51 +02:00
|
|
|
loadProgramSpecs(manager);
|
2021-08-11 00:20:51 +02:00
|
|
|
|
2021-09-15 09:26:51 +02:00
|
|
|
Resolver.INSTANCE.resolve(sources);
|
2021-08-11 00:20:51 +02:00
|
|
|
|
2021-09-30 22:42:17 +02:00
|
|
|
for (IShaderContext<?> context : backend.allContexts()) {
|
2021-09-15 09:26:51 +02:00
|
|
|
context.load();
|
|
|
|
}
|
2021-08-11 00:20:51 +02:00
|
|
|
|
2021-09-15 09:26:51 +02:00
|
|
|
if (shouldCrash) {
|
|
|
|
throw new ShaderLoadingException("Could not load all shaders, see log for details");
|
|
|
|
}
|
2021-08-11 00:20:51 +02:00
|
|
|
|
2021-09-15 09:26:51 +02:00
|
|
|
Backend.log.info("Loaded all shader programs.");
|
2021-08-11 00:20:51 +02:00
|
|
|
|
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
|
2021-12-08 21:16:01 +01:00
|
|
|
InstancedRenderDispatcher.resetInstanceWorld(world);
|
2021-09-15 09:26:51 +02:00
|
|
|
CrumblingRenderer.reset();
|
2021-08-11 00:20:51 +02:00
|
|
|
}
|
|
|
|
}
|
2021-09-15 09:26:51 +02:00
|
|
|
|
|
|
|
firstLoad = false;
|
2021-08-11 00:20:51 +02:00
|
|
|
}
|
|
|
|
|
2021-09-15 08:45:29 +02:00
|
|
|
private void loadProgramSpecs(ResourceManager manager) {
|
2021-08-11 00:20:51 +02:00
|
|
|
Collection<ResourceLocation> programSpecs = manager.listResources(PROGRAM_DIR, s -> s.endsWith(".json"));
|
|
|
|
|
|
|
|
for (ResourceLocation location : programSpecs) {
|
|
|
|
try {
|
2021-09-15 08:45:29 +02:00
|
|
|
Resource file = manager.getResource(location);
|
2021-08-11 00:20:51 +02:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|