diff --git a/src/main/java/com/jozufozu/flywheel/Flywheel.java b/src/main/java/com/jozufozu/flywheel/Flywheel.java index 5b373c878..0cfe41aba 100644 --- a/src/main/java/com/jozufozu/flywheel/Flywheel.java +++ b/src/main/java/com/jozufozu/flywheel/Flywheel.java @@ -76,15 +76,16 @@ public class Flywheel { forgeEventBus.addListener(ProgramCompiler::invalidateAll); forgeEventBus.addListener(Models::onReload); - modEventBus.addListener(LayoutShaders::flwInit); - modEventBus.addListener(InstanceShaders::flwInit); - modEventBus.addListener(MaterialShaders::flwInit); - modEventBus.addListener(Contexts::flwInit); modEventBus.addListener(PartialModel::onModelRegistry); modEventBus.addListener(PartialModel::onModelBake); modEventBus.addListener(StitchedSprite::onTextureStitchPre); modEventBus.addListener(StitchedSprite::onTextureStitchPost); + LayoutShaders.init(); + InstanceShaders.init(); + Contexts.init(); + MaterialShaders.init(); + VanillaInstances.init(); // https://github.com/Jozufozu/Flywheel/issues/69 diff --git a/src/main/java/com/jozufozu/flywheel/backend/Loader.java b/src/main/java/com/jozufozu/flywheel/backend/Loader.java index 2b3c1008e..dfcdf4caa 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/Loader.java +++ b/src/main/java/com/jozufozu/flywheel/backend/Loader.java @@ -1,18 +1,17 @@ package com.jozufozu.flywheel.backend; import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; -import com.jozufozu.flywheel.core.GameStateRegistry; import com.jozufozu.flywheel.core.crumbling.CrumblingRenderer; -import com.jozufozu.flywheel.core.source.Resolver; +import com.jozufozu.flywheel.core.source.FileResolution; +import com.jozufozu.flywheel.core.source.ShaderLoadingException; import com.jozufozu.flywheel.core.source.ShaderSources; -import com.jozufozu.flywheel.event.GatherContextEvent; +import com.jozufozu.flywheel.core.source.error.ErrorReporter; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.server.packs.resources.ReloadableResourceManager; import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.server.packs.resources.ResourceManagerReloadListener; -import net.minecraftforge.fml.ModLoader; /** * The main entity for loading shaders. @@ -22,7 +21,6 @@ import net.minecraftforge.fml.ModLoader; *

*/ public class Loader implements ResourceManagerReloadListener { - private boolean firstLoad = true; Loader() { // Can be null when running datagenerators due to the unfortunate time we call this @@ -39,15 +37,15 @@ public class Loader implements ResourceManagerReloadListener { public void onResourceManagerReload(ResourceManager manager) { Backend.refresh(); - GameStateRegistry._clear(); + var errorReporter = new ErrorReporter(); + ShaderSources sources = new ShaderSources(errorReporter, manager); - Resolver.INSTANCE.invalidate(); - ModLoader.get() - .postEvent(new GatherContextEvent(firstLoad)); + FileResolution.run(errorReporter, sources); - ShaderSources sources = new ShaderSources(manager); - - Resolver.INSTANCE.run(sources); + if (errorReporter.hasErrored()) { + errorReporter.dump(); + throw new ShaderLoadingException("Failed to resolve all source files, see log for details"); + } Backend.LOGGER.info("Loaded all shader sources."); @@ -58,6 +56,5 @@ public class Loader implements ResourceManagerReloadListener { CrumblingRenderer.reset(); } - firstLoad = false; } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/GLSLVersion.java b/src/main/java/com/jozufozu/flywheel/backend/gl/GLSLVersion.java index 978a6ecbd..11a81427a 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/gl/GLSLVersion.java +++ b/src/main/java/com/jozufozu/flywheel/backend/gl/GLSLVersion.java @@ -1,8 +1,16 @@ package com.jozufozu.flywheel.backend.gl; public enum GLSLVersion { + V110(110), + V120(120), + V130(130), + V140(140), V150(150), V330(330), + V400(400), + V410(410), + V420(420), + V430(430), ; public final int version; diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlShader.java b/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlShader.java index b1b4dd71c..12cb002be 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlShader.java +++ b/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlShader.java @@ -1,34 +1,37 @@ package com.jozufozu.flywheel.backend.gl.shader; +import java.io.File; +import java.io.FileWriter; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + import org.lwjgl.opengl.GL20; import com.jozufozu.flywheel.backend.gl.GlObject; import com.jozufozu.flywheel.backend.gl.versioned.GlCompat; +import com.jozufozu.flywheel.core.shader.ShaderConstants; import com.jozufozu.flywheel.core.source.ShaderLoadingException; +import net.minecraft.client.Minecraft; import net.minecraft.resources.ResourceLocation; public class GlShader extends GlObject { - public final ResourceLocation name; public final ShaderType type; + private final List parts; + private final ShaderConstants constants; - public GlShader(ResourceLocation name, ShaderType type, String source) { - this.name = name; + public GlShader(String source, ShaderType type, List parts, ShaderConstants constants) { + this.parts = parts; this.type = type; + this.constants = constants; int handle = GL20.glCreateShader(type.glEnum); GlCompat.safeShaderSource(handle, source); GL20.glCompileShader(handle); -// File dir = new File(Minecraft.getInstance().gameDirectory, "flywheel_sources"); -// dir.mkdirs(); -// File file = new File(dir, name.toString().replaceAll("[:/]", "_")); -// try (FileWriter writer = new FileWriter(file)) { -// writer.write(source); -// } catch (Exception e) { -// e.printStackTrace(); -// } + dumpSource(source, type); // String log = GL20.glGetShaderInfoLog(handle); // @@ -38,7 +41,7 @@ public class GlShader extends GlObject { // } if (GL20.glGetShaderi(handle, GL20.GL_COMPILE_STATUS) != GL20.GL_TRUE) { - throw new ShaderLoadingException("Could not compile " + name + ". See log for details."); + throw new ShaderLoadingException("Could not compile " + getName() + ". See log for details."); } setHandle(handle); @@ -49,4 +52,22 @@ public class GlShader extends GlObject { GL20.glDeleteShader(handle); } + public String getName() { + return parts.stream() + .map(ResourceLocation::toString) + .map(s -> s.replaceAll("/", "_") + .replaceAll(":", "\\$")) + .collect(Collectors.joining(";")) + ';' + Integer.toHexString(constants.hashCode()); + } + + private void dumpSource(String source, ShaderType type) { + File dir = new File(Minecraft.getInstance().gameDirectory, "flywheel_sources"); + dir.mkdirs(); + File file = new File(dir, type.getFileName(getName())); + try (FileWriter writer = new FileWriter(file)) { + writer.write(source); + } catch (Exception e) { + e.printStackTrace(); + } + } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/shader/ShaderType.java b/src/main/java/com/jozufozu/flywheel/backend/gl/shader/ShaderType.java index 2b10e7578..ca42adc46 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/gl/shader/ShaderType.java +++ b/src/main/java/com/jozufozu/flywheel/backend/gl/shader/ShaderType.java @@ -3,21 +3,27 @@ package com.jozufozu.flywheel.backend.gl.shader; import org.lwjgl.opengl.GL20; public enum ShaderType { - VERTEX("vertex", "VERTEX_SHADER", GL20.GL_VERTEX_SHADER), - FRAGMENT("fragment", "FRAGMENT_SHADER", GL20.GL_FRAGMENT_SHADER), + VERTEX("vertex", "VERTEX_SHADER", "vert", GL20.GL_VERTEX_SHADER), + FRAGMENT("fragment", "FRAGMENT_SHADER", "frag", GL20.GL_FRAGMENT_SHADER), ; public final String name; public final String define; + public final String extension; public final int glEnum; - ShaderType(String name, String define, int glEnum) { + ShaderType(String name, String define, String extension, int glEnum) { this.name = name; this.define = define; + this.extension = extension; this.glEnum = glEnum; } public String getDefineStatement() { return "#define " + define + "\n"; } + + public String getFileName(String baseName) { + return baseName + "." + extension; + } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancingEngine.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancingEngine.java index 32d2751c2..3a2ebdbae 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancingEngine.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancingEngine.java @@ -20,7 +20,6 @@ import com.jozufozu.flywheel.core.CoreShaderInfoMap.CoreShaderInfo; import com.jozufozu.flywheel.core.GameStateRegistry; import com.jozufozu.flywheel.core.RenderContext; import com.jozufozu.flywheel.core.compile.ProgramCompiler; -import com.jozufozu.flywheel.core.compile.ProgramContext; import com.jozufozu.flywheel.core.shader.WorldProgram; import com.jozufozu.flywheel.core.vertex.Formats; import com.jozufozu.flywheel.util.Textures; @@ -155,7 +154,7 @@ public class InstancingEngine

implements Engine { alphaDiscard = 0; } - P program = context.getProgram(new ProgramContext(Formats.POS_TEX_NORMAL, instanceType.getInstanceShader(), material.getVertexShader(), material.getFragmentShader(), alphaDiscard, coreShaderInfo.fogType(), GameStateRegistry.takeSnapshot())); + P program = context.getProgram(new ProgramCompiler.Context(Formats.POS_TEX_NORMAL, instanceType.getInstanceShader(), material.getVertexShader(), material.getFragmentShader(), alphaDiscard, coreShaderInfo.fogType(), GameStateRegistry.takeSnapshot())); program.bind(); program.uploadUniforms(camX, camY, camZ, viewProjection, level); diff --git a/src/main/java/com/jozufozu/flywheel/core/Contexts.java b/src/main/java/com/jozufozu/flywheel/core/Contexts.java index ea12a3231..87092d959 100644 --- a/src/main/java/com/jozufozu/flywheel/core/Contexts.java +++ b/src/main/java/com/jozufozu/flywheel/core/Contexts.java @@ -1,13 +1,13 @@ package com.jozufozu.flywheel.core; import com.jozufozu.flywheel.Flywheel; +import com.jozufozu.flywheel.backend.gl.GLSLVersion; import com.jozufozu.flywheel.core.compile.ProgramCompiler; import com.jozufozu.flywheel.core.crumbling.CrumblingProgram; import com.jozufozu.flywheel.core.shader.NormalDebugStateProvider; import com.jozufozu.flywheel.core.shader.WorldProgram; import com.jozufozu.flywheel.core.source.FileResolution; -import com.jozufozu.flywheel.core.source.Resolver; -import com.jozufozu.flywheel.event.GatherContextEvent; +import com.jozufozu.flywheel.core.source.SourceChecks; import com.jozufozu.flywheel.util.ResourceUtil; import net.minecraft.resources.ResourceLocation; @@ -17,16 +17,23 @@ public class Contexts { public static ProgramCompiler WORLD; public static ProgramCompiler CRUMBLING; - public static void flwInit(GatherContextEvent event) { + public static void init() { GameStateRegistry.register(NormalDebugStateProvider.INSTANCE); - FileResolution worldVertex = Resolver.INSTANCE.get(ResourceUtil.subPath(Names.WORLD, ".vert")); - FileResolution worldFragment = Resolver.INSTANCE.get(ResourceUtil.subPath(Names.WORLD, ".frag")); - FileResolution crumblingVertex = Resolver.INSTANCE.get(ResourceUtil.subPath(Names.CRUMBLING, ".vert")); - FileResolution crumblingFragment = Resolver.INSTANCE.get(ResourceUtil.subPath(Names.CRUMBLING, ".frag")); + var checkFrag = SourceChecks.checkFunctionArity("flw_contextFragment", 0); + var checkVert = SourceChecks.checkFunctionArity("flw_contextVertex", 0); - WORLD = ProgramCompiler.create(WorldProgram::new, worldVertex, worldFragment); - CRUMBLING = ProgramCompiler.create(CrumblingProgram::new, crumblingVertex, crumblingFragment); + var worldVertex = FileResolution.get(ResourceUtil.subPath(Names.WORLD, ".vert")) + .validateWith(checkVert); + var worldFragment = FileResolution.get(ResourceUtil.subPath(Names.WORLD, ".frag")) + .validateWith(checkFrag); + var crumblingVertex = FileResolution.get(ResourceUtil.subPath(Names.CRUMBLING, ".vert")) + .validateWith(checkVert); + var crumblingFragment = FileResolution.get(ResourceUtil.subPath(Names.CRUMBLING, ".frag")) + .validateWith(checkFrag); + + WORLD = ProgramCompiler.create(WorldProgram::new, worldVertex, worldFragment, GLSLVersion.V330); + CRUMBLING = ProgramCompiler.create(CrumblingProgram::new, crumblingVertex, crumblingFragment, GLSLVersion.V330); } public static class Names { diff --git a/src/main/java/com/jozufozu/flywheel/core/GameStateRegistry.java b/src/main/java/com/jozufozu/flywheel/core/GameStateRegistry.java index 67a5c2b44..7d797a5bb 100644 --- a/src/main/java/com/jozufozu/flywheel/core/GameStateRegistry.java +++ b/src/main/java/com/jozufozu/flywheel/core/GameStateRegistry.java @@ -51,8 +51,4 @@ public class GameStateRegistry { } return shaderConstants; } - - public static void _clear() { - PROVIDERS.clear(); - } } diff --git a/src/main/java/com/jozufozu/flywheel/core/compile/CompileUtil.java b/src/main/java/com/jozufozu/flywheel/core/compile/CompileUtil.java index b97152197..19784f7fb 100644 --- a/src/main/java/com/jozufozu/flywheel/core/compile/CompileUtil.java +++ b/src/main/java/com/jozufozu/flywheel/core/compile/CompileUtil.java @@ -2,9 +2,14 @@ package com.jozufozu.flywheel.core.compile; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.jetbrains.annotations.NotNull; import com.jozufozu.flywheel.backend.gl.GLSLVersion; import com.jozufozu.flywheel.backend.gl.shader.ShaderType; +import com.jozufozu.flywheel.core.source.SourceFile; public class CompileUtil { @@ -45,4 +50,11 @@ public class CompileUtil { return 1; } + + @NotNull + public static String generateDebugName(SourceFile... stages) { + return Stream.of(stages) + .map(SourceFile::toString) + .collect(Collectors.joining(" -> ")); + } } diff --git a/src/main/java/com/jozufozu/flywheel/core/compile/FragmentCompiler.java b/src/main/java/com/jozufozu/flywheel/core/compile/FragmentCompiler.java index 92ddf67a3..bd88b465c 100644 --- a/src/main/java/com/jozufozu/flywheel/core/compile/FragmentCompiler.java +++ b/src/main/java/com/jozufozu/flywheel/core/compile/FragmentCompiler.java @@ -1,7 +1,6 @@ package com.jozufozu.flywheel.core.compile; import java.util.Objects; -import java.util.Optional; import com.google.common.collect.ImmutableList; import com.jozufozu.flywheel.backend.gl.GLSLVersion; @@ -12,92 +11,57 @@ import com.jozufozu.flywheel.core.shader.ShaderConstants; import com.jozufozu.flywheel.core.shader.StateSnapshot; import com.jozufozu.flywheel.core.source.FileIndexImpl; import com.jozufozu.flywheel.core.source.FileResolution; -import com.jozufozu.flywheel.core.source.ShaderLoadingException; import com.jozufozu.flywheel.core.source.SourceFile; -import com.jozufozu.flywheel.core.source.error.ErrorReporter; -import com.jozufozu.flywheel.core.source.parse.ShaderFunction; -import com.jozufozu.flywheel.core.source.parse.Variable; +/** + * Handles compilation and deletion of fragment shaders. + */ public class FragmentCompiler extends Memoizer { private final FileResolution contextShader; + private final GLSLVersion glslVersion; - public FragmentCompiler(FileResolution contextShader) { + public FragmentCompiler(FileResolution contextShader, GLSLVersion glslVersion) { this.contextShader = contextShader; + this.glslVersion = glslVersion; } @Override protected GlShader _create(Context key) { StringBuilder finalSource = new StringBuilder(); - finalSource.append(CompileUtil.generateHeader(GLSLVersion.V150, ShaderType.FRAGMENT)); + finalSource.append(CompileUtil.generateHeader(glslVersion, ShaderType.FRAGMENT)); - key.getShaderConstants().writeInto(finalSource); + ShaderConstants shaderConstants = key.getShaderConstants(); + shaderConstants.writeInto(finalSource); finalSource.append('\n'); FileIndexImpl index = new FileIndexImpl(); - // + // MATERIAL SourceFile materialShader = key.materialShader; - - Optional maybeMaterialFragment = materialShader.findFunction("flw_materialFragment"); - - if (maybeMaterialFragment.isEmpty()) { - ErrorReporter.generateMissingFunction(materialShader, "flw_materialFragment", "\"flw_materialFragment\" function not defined"); - throw new ShaderLoadingException(); - } - - ShaderFunction materialFragment = maybeMaterialFragment.get(); - ImmutableList params = materialFragment.getParameters(); - - if (params.size() != 0) { - ErrorReporter.generateSpanError(materialFragment.getArgs(), "\"flw_materialFragment\" function must not have any arguments"); - throw new ShaderLoadingException(); - } - materialShader.generateFinalSource(index, finalSource); - // + // CONTEXT SourceFile contextShaderSource = contextShader.getFile(); - - Optional maybeContextFragment = contextShaderSource.findFunction("flw_contextFragment"); - - if (maybeContextFragment.isEmpty()) { - ErrorReporter.generateMissingFunction(contextShaderSource, "flw_contextFragment", "\"flw_contextFragment\" function not defined"); - throw new ShaderLoadingException(); - } - - ShaderFunction contextFragment = maybeContextFragment.get(); - params = contextFragment.getParameters(); - - if (params.size() != 0) { - ErrorReporter.generateSpanError(contextFragment.getArgs(), "\"flw_contextFragment\" function must not have any arguments"); - throw new ShaderLoadingException(); - } - contextShaderSource.generateFinalSource(index, finalSource); - // + // MAIN finalSource.append(generateFooter()); - return new GlShader(contextShader.getFile().name, ShaderType.FRAGMENT, finalSource.toString()); + return new GlShader(finalSource.toString(), ShaderType.FRAGMENT, ImmutableList.of(materialShader.name, contextShaderSource.name), shaderConstants); } protected String generateFooter() { - StringBuilder footer = new StringBuilder(); - - footer.append(""" + return """ void main() { flw_materialFragment(); flw_contextFragment(); } - """ - ); - - return footer.toString(); + """; } @Override @@ -107,34 +71,12 @@ public class FragmentCompiler extends Memoizer params = layoutVertex.getParameters(); - - if (params.size() != 0) { - ErrorReporter.generateSpanError(layoutVertex.getArgs(), "\"flw_layoutVertex\" function must not have any arguments"); - throw new ShaderLoadingException(); - } + // LAYOUT + var layoutShader = key.vertexType.getLayoutShader().getFile(); layoutShader.generateFinalSource(index, finalSource); - // - - SourceFile instanceShader = key.instanceShader; - - Optional maybeInstanceVertex = instanceShader.findFunction("flw_instanceVertex"); - - if (maybeInstanceVertex.isEmpty()) { - ErrorReporter.generateMissingFunction(instanceShader, "flw_instanceVertex", "\"flw_instanceVertex\" function not defined"); - throw new ShaderLoadingException(); - } - - ShaderFunction instanceVertex = maybeInstanceVertex.get(); - params = instanceVertex.getParameters(); - - if (params.size() != 1) { - ErrorReporter.generateSpanError(instanceVertex.getArgs(), "\"flw_instanceVertex\" function must have exactly 1 argument"); - throw new ShaderLoadingException(); - } - - Span instanceName = params.get(0).type; - Optional maybeInstance = instanceShader.findStruct(instanceName); - - if (maybeInstance.isEmpty()) { - ErrorReporter.generateMissingStruct(instanceShader, instanceName, "instance struct not defined"); - throw new ShaderLoadingException(); - } - - ShaderStruct instance = maybeInstance.get(); + // INSTANCE + var instanceShader = key.instanceShader; instanceShader.generateFinalSource(index, finalSource); - // - - SourceFile materialShader = key.materialShader; - - Optional maybeMaterialVertex = materialShader.findFunction("flw_materialVertex"); - - if (maybeMaterialVertex.isEmpty()) { - ErrorReporter.generateMissingFunction(materialShader, "flw_materialVertex", "\"flw_materialVertex\" function not defined"); - throw new ShaderLoadingException(); - } - - ShaderFunction materialVertex = maybeMaterialVertex.get(); - params = materialVertex.getParameters(); - - if (params.size() != 0) { - ErrorReporter.generateSpanError(materialVertex.getArgs(), "\"flw_materialVertex\" function must not have any arguments"); - throw new ShaderLoadingException(); - } + // MATERIAL + var materialShader = key.materialShader; materialShader.generateFinalSource(index, finalSource); - // - - SourceFile contextShaderSource = contextShader.getFile(); - - Optional maybeContextVertex = contextShaderSource.findFunction("flw_contextVertex"); - - if (maybeContextVertex.isEmpty()) { - ErrorReporter.generateMissingFunction(contextShaderSource, "flw_contextVertex", "\"flw_contextVertex\" function not defined"); - throw new ShaderLoadingException(); - } - - ShaderFunction contextVertex = maybeContextVertex.get(); - params = contextVertex.getParameters(); - - if (params.size() != 0) { - ErrorReporter.generateSpanError(contextVertex.getArgs(), "\"flw_contextVertex\" function must not have any arguments"); - throw new ShaderLoadingException(); - } + // CONTEXT + var contextShaderSource = contextShader.getFile(); contextShaderSource.generateFinalSource(index, finalSource); - // + // MAIN - finalSource.append(generateFooter(key.vertexType, instance)); + var instanceStruct = instanceShader.findFunction("flw_instanceVertex") + .flatMap(f -> f.getParameterType(0) + .findStruct()) + .orElseThrow(); + finalSource.append(generateFooter(key.vertexType, instanceStruct)); - return new GlShader(instanceShader.name, ShaderType.VERTEX, finalSource.toString()); + return new GlShader(finalSource.toString(), ShaderType.VERTEX, ImmutableList.of(layoutShader.name, instanceShader.name, materialShader.name, contextShaderSource.name), shaderConstants); } protected String generateFooter(VertexType vertexType, ShaderStruct instance) { @@ -203,45 +131,12 @@ public class VertexCompiler extends Memoizer { value.delete(); } - public static class Context { - /** - * The vertex type to use. - */ - private final VertexType vertexType; - - /** - * The instance shader source. - */ - private final SourceFile instanceShader; - - /** - * The vertex material shader source. - */ - private final SourceFile materialShader; - - /** - * The shader constants to apply. - */ - private final StateSnapshot ctx; - - public Context(VertexType vertexType, SourceFile instanceShader, SourceFile materialShader, StateSnapshot ctx) { - this.vertexType = vertexType; - this.instanceShader = instanceShader; - this.materialShader = materialShader; - this.ctx = ctx; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - var that = (Context) o; - return vertexType == that.vertexType && instanceShader == that.instanceShader && materialShader == that.materialShader && ctx.equals(that.ctx); - } - - @Override - public int hashCode() { - return Objects.hash(vertexType, instanceShader, materialShader, ctx); - } + /** + * @param vertexType The vertex type to use. + * @param instanceShader The instance shader source. + * @param materialShader The vertex material shader source. + * @param ctx The shader constants to apply. + */ + public record Context(VertexType vertexType, SourceFile instanceShader, SourceFile materialShader, StateSnapshot ctx) { } } diff --git a/src/main/java/com/jozufozu/flywheel/core/material/MaterialShaders.java b/src/main/java/com/jozufozu/flywheel/core/material/MaterialShaders.java index d1fc82780..6a0e366ee 100644 --- a/src/main/java/com/jozufozu/flywheel/core/material/MaterialShaders.java +++ b/src/main/java/com/jozufozu/flywheel/core/material/MaterialShaders.java @@ -2,8 +2,7 @@ package com.jozufozu.flywheel.core.material; import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.core.source.FileResolution; -import com.jozufozu.flywheel.core.source.Resolver; -import com.jozufozu.flywheel.event.GatherContextEvent; +import com.jozufozu.flywheel.core.source.SourceChecks; import com.jozufozu.flywheel.util.ResourceUtil; import net.minecraft.resources.ResourceLocation; @@ -13,10 +12,16 @@ public class MaterialShaders { public static FileResolution DEFAULT_FRAGMENT; public static FileResolution SHADED_VERTEX; - public static void flwInit(GatherContextEvent event) { - DEFAULT_VERTEX = Resolver.INSTANCE.get(ResourceUtil.subPath(Names.DEFAULT, ".vert")); - DEFAULT_FRAGMENT = Resolver.INSTANCE.get(ResourceUtil.subPath(Names.DEFAULT, ".frag")); - SHADED_VERTEX = Resolver.INSTANCE.get(ResourceUtil.subPath(Names.SHADED, ".vert")); + public static void init() { + var checkVert = SourceChecks.checkFunctionArity("flw_materialVertex", 0); + var checkFrag = SourceChecks.checkFunctionArity("flw_materialFragment", 0); + + DEFAULT_VERTEX = FileResolution.get(ResourceUtil.subPath(Names.DEFAULT, ".vert")) + .validateWith(checkVert); + DEFAULT_FRAGMENT = FileResolution.get(ResourceUtil.subPath(Names.DEFAULT, ".frag")) + .validateWith(checkFrag); + SHADED_VERTEX = FileResolution.get(ResourceUtil.subPath(Names.SHADED, ".vert")) + .validateWith(checkVert); } public static class Names { diff --git a/src/main/java/com/jozufozu/flywheel/core/shader/ShaderConstants.java b/src/main/java/com/jozufozu/flywheel/core/shader/ShaderConstants.java index ed56ab006..ece98bd05 100644 --- a/src/main/java/com/jozufozu/flywheel/core/shader/ShaderConstants.java +++ b/src/main/java/com/jozufozu/flywheel/core/shader/ShaderConstants.java @@ -3,6 +3,7 @@ package com.jozufozu.flywheel.core.shader; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; /** * A class for manipulating a list of {@code #define} directives. @@ -52,4 +53,17 @@ public class ShaderConstants { acc.append('\n'); } } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ShaderConstants that = (ShaderConstants) o; + return Objects.equals(definitions, that.definitions); + } + + @Override + public int hashCode() { + return Objects.hash(definitions); + } } diff --git a/src/main/java/com/jozufozu/flywheel/core/source/FileIndexImpl.java b/src/main/java/com/jozufozu/flywheel/core/source/FileIndexImpl.java index 90aefb176..fcab6d684 100644 --- a/src/main/java/com/jozufozu/flywheel/core/source/FileIndexImpl.java +++ b/src/main/java/com/jozufozu/flywheel/core/source/FileIndexImpl.java @@ -33,7 +33,7 @@ public class FileIndexImpl implements FileIndex { @Override public boolean exists(SourceFile sourceFile) { - return files.indexOf(sourceFile) != -1; + return files.contains(sourceFile); } @Override @@ -68,10 +68,7 @@ public class FileIndexImpl implements FileIndex { @Nullable private ErrorBuilder parseCompilerError(String line) { try { - ErrorBuilder error = ErrorBuilder.fromLogLine(this, line); - if (error != null) { - return error; - } + return ErrorBuilder.fromLogLine(this, line); } catch (Exception ignored) { } diff --git a/src/main/java/com/jozufozu/flywheel/core/source/FileResolution.java b/src/main/java/com/jozufozu/flywheel/core/source/FileResolution.java index 23bb7f617..8b4503391 100644 --- a/src/main/java/com/jozufozu/flywheel/core/source/FileResolution.java +++ b/src/main/java/com/jozufozu/flywheel/core/source/FileResolution.java @@ -1,11 +1,13 @@ package com.jozufozu.flywheel.core.source; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; -import java.util.function.Consumer; +import java.util.Map; +import java.util.function.BiConsumer; -import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.core.source.error.ErrorBuilder; +import com.jozufozu.flywheel.core.source.error.ErrorReporter; import com.jozufozu.flywheel.core.source.span.Span; import net.minecraft.resources.ResourceLocation; @@ -21,17 +23,73 @@ import net.minecraft.resources.ResourceLocation; */ public class FileResolution { + private static final Map ALL = new HashMap<>(); + private static boolean tooLate = false; + /** - * Extra info about where this resolution is required. Includes ProgramSpecs and shader Spans. + * Extra info about where this resolution is required. Includes shader Spans. */ - private final List> extraCrashInfoProviders = new ArrayList<>(); + private final List neededAt = new ArrayList<>(); + private final List> checks = new ArrayList<>(); + private final ResourceLocation fileLoc; + private SourceFile file; FileResolution(ResourceLocation fileLoc) { this.fileLoc = fileLoc; } + public static FileResolution get(ResourceLocation file) { + if (!tooLate) { + return ALL.computeIfAbsent(file, FileResolution::new); + } else { + // Lock the map after resolution has run. + FileResolution fileResolution = ALL.get(file); + + // ...so crash immediately if the file isn't found. + if (fileResolution == null) { + throw new ShaderLoadingException("could not find source for file: " + file); + } + + return fileResolution; + } + } + + /** + * Try and resolve all referenced source files, printing errors if any aren't found. + */ + public static void run(ErrorReporter errorReporter, SourceFinder sources) { + for (FileResolution resolution : ALL.values()) { + resolution.resolveAndCheck(errorReporter, sources); + } + + tooLate = true; + } + + private void resolveAndCheck(ErrorReporter errorReporter, SourceFinder sources) { + file = sources.findSource(fileLoc); + + if (file == null) { + ErrorBuilder builder = errorReporter.error(String.format("could not find source for file %s", fileLoc)); + for (Span location : neededAt) { + builder.pointAtFile(location.getSourceFile()) + .pointAt(location, 1); + } + } else { + runChecks(errorReporter); + } + + // Let the GC do its thing + neededAt.clear(); + } + + private void runChecks(ErrorReporter errorReporter) { + for (var check : checks) { + check.accept(errorReporter, file); + } + } + public ResourceLocation getFileLoc() { return fileLoc; } @@ -53,45 +111,13 @@ public class FileResolution { * @param span A span where this file is referenced. */ public FileResolution addSpan(Span span) { - extraCrashInfoProviders.add(builder -> builder.pointAtFile(span.getSourceFile()) - .pointAt(span, 1)); + neededAt.add(span); return this; } - public void addSpec(ResourceLocation name) { - extraCrashInfoProviders.add(builder -> builder.extra("needed by spec: " + name + ".json")); - } - - /** - * Check to see if this file actually resolves to something. - * - *

- * Called after all files are loaded. If we can't find the file here, it doesn't exist. - *

- * - * @return True if this file is resolved. - */ - boolean resolve(SourceFinder sources) { - file = sources.findSource(fileLoc); - - if (file == null) { - ErrorBuilder builder = ErrorBuilder.error(String.format("could not find source for file %s", fileLoc)); - for (Consumer consumer : extraCrashInfoProviders) { - consumer.accept(builder); - } - Backend.LOGGER.error(builder.build()); - - return false; - } - - // Let the GC do its thing - extraCrashInfoProviders.clear(); - return true; - } - - void invalidate() { - extraCrashInfoProviders.clear(); - file = null; + public FileResolution validateWith(BiConsumer check) { + checks.add(check); + return this; } @Override diff --git a/src/main/java/com/jozufozu/flywheel/core/source/Resolver.java b/src/main/java/com/jozufozu/flywheel/core/source/Resolver.java deleted file mode 100644 index 9abea7354..000000000 --- a/src/main/java/com/jozufozu/flywheel/core/source/Resolver.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.jozufozu.flywheel.core.source; - -import java.util.HashMap; -import java.util.Map; - -import net.minecraft.resources.ResourceLocation; - -/** - * Manages deferred file resolution. - * - *

- * Interns all file names in shader sources and program specs, deduplicating the final lookups and allowing for more - * dev-friendly error reporting. - *

- * - * @see FileResolution - */ -public class Resolver { - - public static final Resolver INSTANCE = new Resolver(); - - private final Map resolutions = new HashMap<>(); - private boolean hasRun = false; - - public FileResolution get(ResourceLocation file) { - if (!hasRun) { - return resolutions.computeIfAbsent(file, FileResolution::new); - } else { - // Lock the map after resolution has run. - FileResolution fileResolution = resolutions.get(file); - - // ...so crash immediately if the file isn't found. - if (fileResolution == null) { - throw new RuntimeException("could not find source for file: " + file); - } - - return fileResolution; - } - } - - /** - * Try and resolve all referenced source files, printing errors if any aren't found. - */ - public void run(SourceFinder sources) { - boolean needsCrash = false; - for (FileResolution resolution : resolutions.values()) { - if (!resolution.resolve(sources)) { - needsCrash = true; - } - } - - if (needsCrash) { - throw new ShaderLoadingException("Failed to resolve all source files, see log for details"); - } - - hasRun = true; - } - - /** - * Invalidates all FileResolutions. - * - *

- * Called on resource reload. - *

- */ - public void invalidate() { - resolutions.values().forEach(FileResolution::invalidate); - hasRun = false; - } -} diff --git a/src/main/java/com/jozufozu/flywheel/core/source/ShaderLoadingException.java b/src/main/java/com/jozufozu/flywheel/core/source/ShaderLoadingException.java index 36ca1dc73..e09dfa99b 100644 --- a/src/main/java/com/jozufozu/flywheel/core/source/ShaderLoadingException.java +++ b/src/main/java/com/jozufozu/flywheel/core/source/ShaderLoadingException.java @@ -2,9 +2,6 @@ package com.jozufozu.flywheel.core.source; public class ShaderLoadingException extends RuntimeException { - public ShaderLoadingException() { - } - public ShaderLoadingException(String message) { super(message); } diff --git a/src/main/java/com/jozufozu/flywheel/core/source/ShaderSources.java b/src/main/java/com/jozufozu/flywheel/core/source/ShaderSources.java index 8e657fe86..502d19bb2 100644 --- a/src/main/java/com/jozufozu/flywheel/core/source/ShaderSources.java +++ b/src/main/java/com/jozufozu/flywheel/core/source/ShaderSources.java @@ -9,6 +9,7 @@ import java.util.Map; import org.jetbrains.annotations.Nullable; import com.google.common.collect.Lists; +import com.jozufozu.flywheel.core.source.error.ErrorReporter; import com.jozufozu.flywheel.util.ResourceUtil; import com.jozufozu.flywheel.util.StringUtil; @@ -20,14 +21,14 @@ import net.minecraft.server.packs.resources.ResourceManager; * The main object for loading and parsing source files. */ public class ShaderSources implements SourceFinder { - public static final String SHADER_DIR = "flywheel/shaders/"; + public static final String SHADER_DIR = "flywheel/"; public static final ArrayList EXTENSIONS = Lists.newArrayList(".vert", ".vsh", ".frag", ".fsh", ".glsl"); private final Map shaderSources = new HashMap<>(); public final Index index; - public ShaderSources(ResourceManager manager) { + public ShaderSources(ErrorReporter errorReporter, ResourceManager manager) { Collection allShaders = manager.listResources(SHADER_DIR, s -> { for (String ext : EXTENSIONS) { if (s.endsWith(ext)) return true; @@ -41,7 +42,7 @@ public class ShaderSources implements SourceFinder { ResourceLocation name = ResourceUtil.removePrefixUnchecked(location, SHADER_DIR); - shaderSources.put(name, new SourceFile(this, name, source)); + shaderSources.put(name, new SourceFile(errorReporter, this, name, source)); } catch (IOException e) { // } diff --git a/src/main/java/com/jozufozu/flywheel/core/source/SourceChecks.java b/src/main/java/com/jozufozu/flywheel/core/source/SourceChecks.java new file mode 100644 index 000000000..a8247a33e --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/core/source/SourceChecks.java @@ -0,0 +1,57 @@ +package com.jozufozu.flywheel.core.source; + +import java.util.Optional; +import java.util.function.BiConsumer; + +import org.jetbrains.annotations.Nullable; + +import com.google.common.collect.ImmutableList; +import com.jozufozu.flywheel.core.source.error.ErrorReporter; +import com.jozufozu.flywheel.core.source.parse.ShaderFunction; +import com.jozufozu.flywheel.core.source.parse.Variable; + +public class SourceChecks { + + public static BiConsumer checkFunctionArity(String name, int arity) { + return (errorReporter, file) -> checkFunctionArity(errorReporter, file, name, arity); + } + + public static BiConsumer checkFunctionParameterTypeExists(String name, int arity, int param) { + return (errorReporter, file) -> { + var func = checkFunctionArity(errorReporter, file, name, arity); + + if (func == null) { + return; + } + + var maybeStruct = func.getParameterType(param) + .findStruct(); + + if (maybeStruct.isEmpty()) { + errorReporter.generateMissingStruct(file, func.getParameterType(param), "struct not defined"); + } + }; + } + + /** + * @return {@code null} if the function doesn't exist, or if the function has the wrong arity. + */ + @Nullable + private static ShaderFunction checkFunctionArity(ErrorReporter errorReporter, SourceFile file, String name, int arity) { + Optional maybeFunc = file.findFunction(name); + + if (maybeFunc.isEmpty()) { + errorReporter.generateMissingFunction(file, name, "\"" + name + "\" function not defined"); + return null; + } + + ShaderFunction func = maybeFunc.get(); + ImmutableList params = func.getParameters(); + if (params.size() != arity) { + errorReporter.generateFunctionArgumentCountError(name, arity, func.getArgs()); + return null; + } + + return func; + } +} diff --git a/src/main/java/com/jozufozu/flywheel/core/source/SourceFile.java b/src/main/java/com/jozufozu/flywheel/core/source/SourceFile.java index 35004c0d1..c76a08e88 100644 --- a/src/main/java/com/jozufozu/flywheel/core/source/SourceFile.java +++ b/src/main/java/com/jozufozu/flywheel/core/source/SourceFile.java @@ -11,9 +11,11 @@ import java.util.regex.Matcher; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import com.jozufozu.flywheel.core.source.error.ErrorReporter; import com.jozufozu.flywheel.core.source.parse.Import; import com.jozufozu.flywheel.core.source.parse.ShaderFunction; import com.jozufozu.flywheel.core.source.parse.ShaderStruct; +import com.jozufozu.flywheel.core.source.parse.Variable; import com.jozufozu.flywheel.core.source.span.ErrorSpan; import com.jozufozu.flywheel.core.source.span.Span; import com.jozufozu.flywheel.core.source.span.StringSpan; @@ -55,7 +57,7 @@ public class SourceFile { */ public final ImmutableList imports; - public SourceFile(ShaderSources parent, ResourceLocation name, String source) { + public SourceFile(ErrorReporter errorReporter, ShaderSources parent, ResourceLocation name, String source) { this.parent = parent; this.name = name; this.source = source; @@ -64,7 +66,7 @@ public class SourceFile { List elisions = new ArrayList<>(); - this.imports = parseImports(elisions); + this.imports = parseImports(errorReporter, elisions); this.functions = parseFunctions(); this.structs = parseStructs(); @@ -233,7 +235,7 @@ public class SourceFile { * Records the contents of the directive into an {@link Import} object, and marks the directive for elision. * @param elisions */ - private ImmutableList parseImports(List elisions) { + private ImmutableList parseImports(ErrorReporter errorReporter, List elisions) { Matcher uses = Import.PATTERN.matcher(source); Set importedFiles = new HashSet<>(); @@ -245,9 +247,9 @@ public class SourceFile { String fileName = file.get(); if (importedFiles.add(fileName)) { - Import import1 = Import.create(Resolver.INSTANCE, use, file); - if (import1 != null) { - imports.add(import1); + var checked = Import.create(errorReporter, use, file); + if (checked != null) { + imports.add(checked); } } @@ -280,4 +282,15 @@ public class SourceFile { public String toString() { return name.toString(); } + + @Override + public boolean equals(Object o) { + // SourceFiles are only equal by reference. + return this == o; + } + + @Override + public int hashCode() { + return System.identityHashCode(this); + } } diff --git a/src/main/java/com/jozufozu/flywheel/core/source/error/ErrorReporter.java b/src/main/java/com/jozufozu/flywheel/core/source/error/ErrorReporter.java index 9da3055ea..859ec71e2 100644 --- a/src/main/java/com/jozufozu/flywheel/core/source/error/ErrorReporter.java +++ b/src/main/java/com/jozufozu/flywheel/core/source/error/ErrorReporter.java @@ -1,5 +1,6 @@ package com.jozufozu.flywheel.core.source.error; +import java.util.ArrayList; import java.util.List; import java.util.Optional; @@ -13,58 +14,78 @@ import com.jozufozu.flywheel.util.FlwUtil; public class ErrorReporter { - public static void generateSpanError(Span span, String message) { - SourceFile file = span.getSourceFile(); + private final List reportedErrors = new ArrayList<>(); - String error = ErrorBuilder.error(message) - .pointAtFile(file) - .pointAt(span, 2) - .build(); - - Backend.LOGGER.error(error); - } - - public static void generateFileError(SourceFile file, String message) { - String error = ErrorBuilder.error(message) - .pointAtFile(file) - .build(); - - Backend.LOGGER.error(error); - } - - public static void generateMissingStruct(SourceFile file, Span vertexName, CharSequence msg) { + public void generateMissingStruct(SourceFile file, Span vertexName, CharSequence msg) { generateMissingStruct(file, vertexName, msg, ""); } - public static void generateMissingStruct(SourceFile file, Span vertexName, CharSequence msg, CharSequence hint) { + public void generateMissingStruct(SourceFile file, Span vertexName, CharSequence msg, CharSequence hint) { Optional span = file.parent.index.getStructDefinitionsMatching(vertexName) .stream() .findFirst() .map(ShaderStruct::getName); - ErrorBuilder error = ErrorBuilder.error(msg) + this.error(msg) .pointAtFile(file) .pointAt(vertexName, 1) .hintIncludeFor(span.orElse(null), hint); - - Backend.LOGGER.error(error.build()); } - public static void generateMissingFunction(SourceFile file, CharSequence functionName, CharSequence msg) { + public void generateMissingFunction(SourceFile file, CharSequence functionName, CharSequence msg) { generateMissingFunction(file, functionName, msg, ""); } - public static void generateMissingFunction(SourceFile file, CharSequence functionName, CharSequence msg, CharSequence hint) { + public void generateMissingFunction(SourceFile file, CharSequence functionName, CharSequence msg, CharSequence hint) { Optional span = file.parent.index.getFunctionDefinitionsMatching(functionName) .stream() .findFirst() .map(ShaderFunction::getName); - ErrorBuilder error = ErrorBuilder.error(msg) + this.error(msg) .pointAtFile(file) .hintIncludeFor(span.orElse(null), hint); + } - Backend.LOGGER.error(error.build()); + public ErrorBuilder generateFunctionArgumentCountError(String name, int requiredArguments, Span span) { + var msg = '"' + name + "\" function must "; + + if (requiredArguments == 0) { + msg += "not have any arguments"; + } else { + msg += "have exactly " + requiredArguments + " argument" + (requiredArguments == 1 ? "" : "s"); + } + + return generateSpanError(span, msg); + } + + public ErrorBuilder generateSpanError(Span span, String message) { + SourceFile file = span.getSourceFile(); + + return error(message) + .pointAtFile(file) + .pointAt(span, 2); + } + + public ErrorBuilder generateFileError(SourceFile file, String message) { + return error(message) + .pointAtFile(file); + } + + public ErrorBuilder error(CharSequence msg) { + var out = ErrorBuilder.error(msg); + reportedErrors.add(out); + return out; + } + + public boolean hasErrored() { + return !reportedErrors.isEmpty(); + } + + public void dump() { + for (var error : reportedErrors) { + Backend.LOGGER.error(error.build()); + } } public static void printLines(CharSequence source) { diff --git a/src/main/java/com/jozufozu/flywheel/core/source/parse/Import.java b/src/main/java/com/jozufozu/flywheel/core/source/parse/Import.java index 90273e7f8..860617dac 100644 --- a/src/main/java/com/jozufozu/flywheel/core/source/parse/Import.java +++ b/src/main/java/com/jozufozu/flywheel/core/source/parse/Import.java @@ -6,7 +6,6 @@ import java.util.regex.Pattern; import org.jetbrains.annotations.Nullable; import com.jozufozu.flywheel.core.source.FileResolution; -import com.jozufozu.flywheel.core.source.Resolver; import com.jozufozu.flywheel.core.source.SourceFile; import com.jozufozu.flywheel.core.source.error.ErrorReporter; import com.jozufozu.flywheel.core.source.span.Span; @@ -26,16 +25,16 @@ public class Import extends AbstractShaderElement { } @Nullable - public static Import create(Resolver resolver, Span self, Span file) { + public static Import create(ErrorReporter errorReporter, Span self, Span file) { ResourceLocation fileLocation; try { fileLocation = new ResourceLocation(file.get()); } catch (ResourceLocationException e) { - ErrorReporter.generateSpanError(file, "malformed source location"); + errorReporter.generateSpanError(file, "malformed source location"); return null; } - return new Import(self, resolver.get(fileLocation), file); + return new Import(self, FileResolution.get(fileLocation), file); } public FileResolution getResolution() { diff --git a/src/main/java/com/jozufozu/flywheel/core/source/parse/ShaderFunction.java b/src/main/java/com/jozufozu/flywheel/core/source/parse/ShaderFunction.java index b7e735589..134d0214f 100644 --- a/src/main/java/com/jozufozu/flywheel/core/source/parse/ShaderFunction.java +++ b/src/main/java/com/jozufozu/flywheel/core/source/parse/ShaderFunction.java @@ -52,6 +52,10 @@ public class ShaderFunction extends AbstractShaderElement { return name + "(" + String.join(", ", args) + ")"; } + public Span getParameterType(int index) { + return parameters.get(index).type; + } + public ImmutableList getParameters() { return parameters; } diff --git a/src/main/java/com/jozufozu/flywheel/core/source/span/Span.java b/src/main/java/com/jozufozu/flywheel/core/source/span/Span.java index 61961a979..81b8e848a 100644 --- a/src/main/java/com/jozufozu/flywheel/core/source/span/Span.java +++ b/src/main/java/com/jozufozu/flywheel/core/source/span/Span.java @@ -1,8 +1,11 @@ package com.jozufozu.flywheel.core.source.span; +import java.util.Optional; import java.util.regex.Matcher; import com.jozufozu.flywheel.core.source.SourceFile; +import com.jozufozu.flywheel.core.source.parse.ShaderFunction; +import com.jozufozu.flywheel.core.source.parse.ShaderStruct; /** * A segment of code in a {@link SourceFile}. @@ -121,4 +124,18 @@ public abstract class Span implements CharSequence { public static Span fromMatcher(Span superSpan, Matcher m) { return superSpan.subSpan(m.start(), m.end()); } + + public Optional findStruct() { + if (isErr()) { + return Optional.empty(); + } + return in.findStruct(this); + } + + public Optional findFunction() { + if (isErr()) { + return Optional.empty(); + } + return in.findFunction(this); + } } diff --git a/src/main/java/com/jozufozu/flywheel/core/structs/InstanceShaders.java b/src/main/java/com/jozufozu/flywheel/core/structs/InstanceShaders.java index 41507dd0a..fdc5e4768 100644 --- a/src/main/java/com/jozufozu/flywheel/core/structs/InstanceShaders.java +++ b/src/main/java/com/jozufozu/flywheel/core/structs/InstanceShaders.java @@ -2,8 +2,7 @@ package com.jozufozu.flywheel.core.structs; import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.core.source.FileResolution; -import com.jozufozu.flywheel.core.source.Resolver; -import com.jozufozu.flywheel.event.GatherContextEvent; +import com.jozufozu.flywheel.core.source.SourceChecks; import com.jozufozu.flywheel.util.ResourceUtil; import net.minecraft.resources.ResourceLocation; @@ -12,9 +11,13 @@ public class InstanceShaders { public static FileResolution MODEL; public static FileResolution ORIENTED; - public static void flwInit(GatherContextEvent event) { - MODEL = Resolver.INSTANCE.get(ResourceUtil.subPath(Names.MODEL, ".vert")); - ORIENTED = Resolver.INSTANCE.get(ResourceUtil.subPath(Names.ORIENTED, ".vert")); + public static void init() { + var check = SourceChecks.checkFunctionParameterTypeExists("flw_instanceVertex", 1, 0); + + MODEL = FileResolution.get(ResourceUtil.subPath(Names.MODEL, ".vert")) + .validateWith(check); + ORIENTED = FileResolution.get(ResourceUtil.subPath(Names.ORIENTED, ".vert")) + .validateWith(check); } public static class Names { diff --git a/src/main/java/com/jozufozu/flywheel/core/vertex/LayoutShaders.java b/src/main/java/com/jozufozu/flywheel/core/vertex/LayoutShaders.java index 31fd55b64..ff3b8de25 100644 --- a/src/main/java/com/jozufozu/flywheel/core/vertex/LayoutShaders.java +++ b/src/main/java/com/jozufozu/flywheel/core/vertex/LayoutShaders.java @@ -2,8 +2,7 @@ package com.jozufozu.flywheel.core.vertex; import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.core.source.FileResolution; -import com.jozufozu.flywheel.core.source.Resolver; -import com.jozufozu.flywheel.event.GatherContextEvent; +import com.jozufozu.flywheel.core.source.SourceChecks; import com.jozufozu.flywheel.util.ResourceUtil; import net.minecraft.resources.ResourceLocation; @@ -12,9 +11,14 @@ public class LayoutShaders { public static FileResolution BLOCK; public static FileResolution POS_TEX_NORMAL; - public static void flwInit(GatherContextEvent event) { - BLOCK = Resolver.INSTANCE.get(ResourceUtil.subPath(Names.BLOCK, ".vert")); - POS_TEX_NORMAL = Resolver.INSTANCE.get(ResourceUtil.subPath(Names.POS_TEX_NORMAL, ".vert")); + public static void init() { + var check = SourceChecks.checkFunctionArity("flw_layoutVertex", 0); + + BLOCK = FileResolution.get(ResourceUtil.subPath(Names.BLOCK, ".vert")) + .validateWith(check); + + POS_TEX_NORMAL = FileResolution.get(ResourceUtil.subPath(Names.POS_TEX_NORMAL, ".vert")) + .validateWith(check); } public static class Names { diff --git a/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java b/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java index 056966700..c2c5d806d 100644 --- a/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java +++ b/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java @@ -6,6 +6,7 @@ import com.jozufozu.flywheel.light.LightUpdater; import com.jozufozu.flywheel.util.WorldAttached; import net.minecraft.client.Minecraft; +import net.minecraft.client.player.LocalPlayer; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.client.event.RenderGameOverlayEvent; import net.minecraftforge.event.TickEvent; @@ -32,8 +33,10 @@ public class ForgeEvents { @SubscribeEvent public static void tickLight(TickEvent.ClientTickEvent e) { - if (e.phase == TickEvent.Phase.END && Backend.isGameActive()) - LightUpdater.get(Minecraft.getInstance().level).tick(); + if (e.phase == TickEvent.Phase.END && Backend.isGameActive()) { + LightUpdater.get(Minecraft.getInstance().level) + .tick(); + } } } diff --git a/src/main/java/com/jozufozu/flywheel/event/GatherContextEvent.java b/src/main/java/com/jozufozu/flywheel/event/GatherContextEvent.java deleted file mode 100644 index ffbc76341..000000000 --- a/src/main/java/com/jozufozu/flywheel/event/GatherContextEvent.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.jozufozu.flywheel.event; - -import net.minecraftforge.eventbus.api.Event; -import net.minecraftforge.fml.event.IModBusEvent; - -public class GatherContextEvent extends Event implements IModBusEvent { - - private final boolean firstLoad; - - public GatherContextEvent(boolean firstLoad) { - this.firstLoad = firstLoad; - } - - /** - * @return true iff it is the first time the event is fired. - */ - public boolean isFirstLoad() { - return firstLoad; - } -} diff --git a/src/main/resources/assets/flywheel/flywheel/shaders/api/fragment.glsl b/src/main/resources/assets/flywheel/flywheel/api/fragment.glsl similarity index 100% rename from src/main/resources/assets/flywheel/flywheel/shaders/api/fragment.glsl rename to src/main/resources/assets/flywheel/flywheel/api/fragment.glsl diff --git a/src/main/resources/assets/flywheel/flywheel/shaders/api/vertex.glsl b/src/main/resources/assets/flywheel/flywheel/api/vertex.glsl similarity index 100% rename from src/main/resources/assets/flywheel/flywheel/shaders/api/vertex.glsl rename to src/main/resources/assets/flywheel/flywheel/api/vertex.glsl diff --git a/src/main/resources/assets/flywheel/flywheel/shaders/context/common.vert b/src/main/resources/assets/flywheel/flywheel/context/common.vert similarity index 100% rename from src/main/resources/assets/flywheel/flywheel/shaders/context/common.vert rename to src/main/resources/assets/flywheel/flywheel/context/common.vert diff --git a/src/main/resources/assets/flywheel/flywheel/shaders/context/crumbling.frag b/src/main/resources/assets/flywheel/flywheel/context/crumbling.frag similarity index 100% rename from src/main/resources/assets/flywheel/flywheel/shaders/context/crumbling.frag rename to src/main/resources/assets/flywheel/flywheel/context/crumbling.frag diff --git a/src/main/resources/assets/flywheel/flywheel/shaders/context/crumbling.vert b/src/main/resources/assets/flywheel/flywheel/context/crumbling.vert similarity index 100% rename from src/main/resources/assets/flywheel/flywheel/shaders/context/crumbling.vert rename to src/main/resources/assets/flywheel/flywheel/context/crumbling.vert diff --git a/src/main/resources/assets/flywheel/flywheel/shaders/context/world.frag b/src/main/resources/assets/flywheel/flywheel/context/world.frag similarity index 100% rename from src/main/resources/assets/flywheel/flywheel/shaders/context/world.frag rename to src/main/resources/assets/flywheel/flywheel/context/world.frag diff --git a/src/main/resources/assets/flywheel/flywheel/shaders/context/world.vert b/src/main/resources/assets/flywheel/flywheel/context/world.vert similarity index 100% rename from src/main/resources/assets/flywheel/flywheel/shaders/context/world.vert rename to src/main/resources/assets/flywheel/flywheel/context/world.vert diff --git a/src/main/resources/assets/flywheel/flywheel/shaders/instance/model.vert b/src/main/resources/assets/flywheel/flywheel/instance/model.vert similarity index 100% rename from src/main/resources/assets/flywheel/flywheel/shaders/instance/model.vert rename to src/main/resources/assets/flywheel/flywheel/instance/model.vert diff --git a/src/main/resources/assets/flywheel/flywheel/shaders/instance/oriented.vert b/src/main/resources/assets/flywheel/flywheel/instance/oriented.vert similarity index 100% rename from src/main/resources/assets/flywheel/flywheel/shaders/instance/oriented.vert rename to src/main/resources/assets/flywheel/flywheel/instance/oriented.vert diff --git a/src/main/resources/assets/flywheel/flywheel/shaders/layout/block.vert b/src/main/resources/assets/flywheel/flywheel/layout/block.vert similarity index 100% rename from src/main/resources/assets/flywheel/flywheel/shaders/layout/block.vert rename to src/main/resources/assets/flywheel/flywheel/layout/block.vert diff --git a/src/main/resources/assets/flywheel/flywheel/shaders/layout/pos_tex_normal.vert b/src/main/resources/assets/flywheel/flywheel/layout/pos_tex_normal.vert similarity index 100% rename from src/main/resources/assets/flywheel/flywheel/shaders/layout/pos_tex_normal.vert rename to src/main/resources/assets/flywheel/flywheel/layout/pos_tex_normal.vert diff --git a/src/main/resources/assets/flywheel/flywheel/shaders/material/default.frag b/src/main/resources/assets/flywheel/flywheel/material/default.frag similarity index 100% rename from src/main/resources/assets/flywheel/flywheel/shaders/material/default.frag rename to src/main/resources/assets/flywheel/flywheel/material/default.frag diff --git a/src/main/resources/assets/flywheel/flywheel/shaders/material/default.vert b/src/main/resources/assets/flywheel/flywheel/material/default.vert similarity index 100% rename from src/main/resources/assets/flywheel/flywheel/shaders/material/default.vert rename to src/main/resources/assets/flywheel/flywheel/material/default.vert diff --git a/src/main/resources/assets/flywheel/flywheel/shaders/material/shaded.vert b/src/main/resources/assets/flywheel/flywheel/material/shaded.vert similarity index 100% rename from src/main/resources/assets/flywheel/flywheel/shaders/material/shaded.vert rename to src/main/resources/assets/flywheel/flywheel/material/shaded.vert diff --git a/src/main/resources/assets/flywheel/flywheel/shaders/util/color.glsl b/src/main/resources/assets/flywheel/flywheel/util/color.glsl similarity index 100% rename from src/main/resources/assets/flywheel/flywheel/shaders/util/color.glsl rename to src/main/resources/assets/flywheel/flywheel/util/color.glsl diff --git a/src/main/resources/assets/flywheel/flywheel/shaders/util/diffuse.glsl b/src/main/resources/assets/flywheel/flywheel/util/diffuse.glsl similarity index 100% rename from src/main/resources/assets/flywheel/flywheel/shaders/util/diffuse.glsl rename to src/main/resources/assets/flywheel/flywheel/util/diffuse.glsl diff --git a/src/main/resources/assets/flywheel/flywheel/shaders/util/fog.glsl b/src/main/resources/assets/flywheel/flywheel/util/fog.glsl similarity index 100% rename from src/main/resources/assets/flywheel/flywheel/shaders/util/fog.glsl rename to src/main/resources/assets/flywheel/flywheel/util/fog.glsl diff --git a/src/main/resources/assets/flywheel/flywheel/shaders/util/light.glsl b/src/main/resources/assets/flywheel/flywheel/util/light.glsl similarity index 100% rename from src/main/resources/assets/flywheel/flywheel/shaders/util/light.glsl rename to src/main/resources/assets/flywheel/flywheel/util/light.glsl diff --git a/src/main/resources/assets/flywheel/flywheel/shaders/util/matrix.glsl b/src/main/resources/assets/flywheel/flywheel/util/matrix.glsl similarity index 100% rename from src/main/resources/assets/flywheel/flywheel/shaders/util/matrix.glsl rename to src/main/resources/assets/flywheel/flywheel/util/matrix.glsl diff --git a/src/main/resources/assets/flywheel/flywheel/shaders/util/quaternion.glsl b/src/main/resources/assets/flywheel/flywheel/util/quaternion.glsl similarity index 100% rename from src/main/resources/assets/flywheel/flywheel/shaders/util/quaternion.glsl rename to src/main/resources/assets/flywheel/flywheel/util/quaternion.glsl