diff --git a/buildSrc/src/main/kotlin/dev/engine_room/gradle/platform/PlatformExtension.kt b/buildSrc/src/main/kotlin/dev/engine_room/gradle/platform/PlatformExtension.kt index fc5df1a45..66831cedf 100644 --- a/buildSrc/src/main/kotlin/dev/engine_room/gradle/platform/PlatformExtension.kt +++ b/buildSrc/src/main/kotlin/dev/engine_room/gradle/platform/PlatformExtension.kt @@ -23,16 +23,11 @@ open class PlatformExtension(val project: Project) { var apiArtifactId: String = "flywheel-${project.name}-api-${project.property("artifact_minecraft_version")}" - private val sources = mutableSetOf() private val commonSourceSets: SourceSetContainer by lazy { commonProject.the() } - fun sources(vararg sourceSets: SourceSet) { - this.sources.addAll(sourceSets) - } - - fun setupLoomMod() { + fun setupLoomMod(vararg sourceSets: SourceSet) { project.the().mods.maybeCreate("main").apply { - sources.forEach(::sourceSet) + sourceSets.forEach(::sourceSet) } } @@ -61,13 +56,13 @@ open class PlatformExtension(val project: Project) { } } - fun compileWithCommonSourceSets() { + fun compileWithCommonSourceSets(vararg sourceSets: SourceSet) { project.tasks.apply { withType().configureEach { JarTaskSet.excludeDuplicatePackageInfos(this) } - sources.forEach { + sourceSets.forEach { val commonSourceSet = commonSourceSets.named(it.name).get() named(it.compileJavaTaskName).configure { @@ -80,10 +75,10 @@ open class PlatformExtension(val project: Project) { } } - fun setupFatJar() { + fun setupFatJar(vararg sourceSets: SourceSet) { project.tasks.apply { - val extraSourceSets = sources.filter { it.name != "main" }.toList() - val commonSources = sources.map { commonSourceSets.named(it.name).get() } + val extraSourceSets = sourceSets.filter { it.name != "main" }.toList() + val commonSources = sourceSets.map { commonSourceSets.named(it.name).get() } named("jar").configure { extraSourceSets.forEach { from(it.output) } diff --git a/buildSrc/src/main/kotlin/dev/engine_room/gradle/transitive/TransitiveSourceSetsExtension.kt b/buildSrc/src/main/kotlin/dev/engine_room/gradle/transitive/TransitiveSourceSetsExtension.kt index c259546df..05fa4dc46 100644 --- a/buildSrc/src/main/kotlin/dev/engine_room/gradle/transitive/TransitiveSourceSetsExtension.kt +++ b/buildSrc/src/main/kotlin/dev/engine_room/gradle/transitive/TransitiveSourceSetsExtension.kt @@ -25,7 +25,7 @@ open class TransitiveSourceSetsExtension(private val project: Project) { fun createCompileConfigurations() { val configs = transitives.mapValues { (sourceSet, _) -> - project.configurations.create("for${sourceSet.name.capitalize()}") { + project.configurations.create("for${sourceSet.name.replaceFirstChar { it.uppercase() }}") { isCanBeConsumed = true isCanBeResolved = false } @@ -43,7 +43,7 @@ open class TransitiveSourceSetsExtension(private val project: Project) { fun createRuntimeConfigurations() { val configs = transitives.mapValues { (sourceSet, _) -> - project.configurations.create("run${sourceSet.name.capitalize()}") { + project.configurations.create("run${sourceSet.name.replaceFirstChar { it.uppercase() }}") { isCanBeConsumed = true isCanBeResolved = false } diff --git a/common/build.gradle.kts b/common/build.gradle.kts index de32f0ef5..ffbfa98a2 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -9,6 +9,7 @@ plugins { val api = sourceSets.create("api") val lib = sourceSets.create("lib") val backend = sourceSets.create("backend") +val stubs = sourceSets.create("stubs") val main = sourceSets.getByName("main") transitiveSourceSets { @@ -25,8 +26,11 @@ transitiveSourceSets { rootCompile() compile(api, lib) } + sourceSet(stubs) { + rootCompile() + } sourceSet(main) { - compile(api, lib, backend) + compile(api, lib, backend, stubs) } sourceSet(sourceSets.getByName("test")) { implementation(api, lib, backend) @@ -42,6 +46,7 @@ jarSets { outgoing("commonApiOnly", api) outgoing("commonLib", lib) outgoing("commonBackend", backend) + outgoing("commonStubs", stubs) outgoing("commonImpl", main) // For publishing. diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/Backends.java b/common/src/backend/java/dev/engine_room/flywheel/backend/Backends.java index 81cdf2408..c6de7eb47 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/Backends.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/Backends.java @@ -9,7 +9,7 @@ import dev.engine_room.flywheel.backend.engine.instancing.InstancedDrawManager; import dev.engine_room.flywheel.backend.gl.GlCompat; import dev.engine_room.flywheel.lib.backend.SimpleBackend; -import dev.engine_room.flywheel.lib.util.ShadersModHandler; +import dev.engine_room.flywheel.lib.util.ShadersModHelper; public final class Backends { /** @@ -18,7 +18,7 @@ public final class Backends { public static final Backend INSTANCING = SimpleBackend.builder() .engineFactory(level -> new EngineImpl(level, new InstancedDrawManager(InstancingPrograms.get()), 256)) .priority(500) - .supported(() -> GlCompat.SUPPORTS_INSTANCING && InstancingPrograms.allLoaded() && !ShadersModHandler.isShaderPackInUse()) + .supported(() -> GlCompat.SUPPORTS_INSTANCING && InstancingPrograms.allLoaded() && !ShadersModHelper.isShaderPackInUse()) .register(Flywheel.rl("instancing")); /** @@ -27,7 +27,7 @@ public final class Backends { public static final Backend INDIRECT = SimpleBackend.builder() .engineFactory(level -> new EngineImpl(level, new IndirectDrawManager(IndirectPrograms.get()), 256)) .priority(1000) - .supported(() -> GlCompat.SUPPORTS_INDIRECT && IndirectPrograms.allLoaded() && !ShadersModHandler.isShaderPackInUse()) + .supported(() -> GlCompat.SUPPORTS_INDIRECT && IndirectPrograms.allLoaded() && !ShadersModHelper.isShaderPackInUse()) .register(Flywheel.rl("indirect")); private Backends() { diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/compile/PipelineCompiler.java b/common/src/backend/java/dev/engine_room/flywheel/backend/compile/PipelineCompiler.java index 9804bd48d..e752edfd2 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/compile/PipelineCompiler.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/compile/PipelineCompiler.java @@ -1,7 +1,10 @@ package dev.engine_room.flywheel.backend.compile; import java.util.Collection; +import java.util.Collections; import java.util.List; +import java.util.Set; +import java.util.WeakHashMap; import dev.engine_room.flywheel.api.Flywheel; import dev.engine_room.flywheel.api.instance.InstanceType; @@ -30,7 +33,7 @@ import net.minecraft.resources.ResourceLocation; public final class PipelineCompiler { - private static final List ALL = List.of(); + private static final Set ALL = Collections.newSetFromMap(new WeakHashMap<>()); private static final Compile PIPELINE = new Compile<>(); @@ -44,6 +47,7 @@ public final class PipelineCompiler { public PipelineCompiler(CompilationHarness harness) { this.harness = harness; + ALL.add(this); } public GlProgram get(InstanceType instanceType, ContextShader contextShader, Material material) { @@ -57,15 +61,12 @@ public GlProgram get(InstanceType instanceType, ContextShader contextShader, MaterialShaderIndices.fogSources() .index(fog.source()); - boolean useCutout = cutout != CutoutShaders.OFF; + // Same thing for cutout. + // Add OFF to the index here anyway to ensure MaterialEncoder doesn't deleteAll at an inappropriate time. + MaterialShaderIndices.cutoutSources() + .index(cutout.source()); - if (useCutout) { - // Same thing for cutout. - MaterialShaderIndices.cutoutSources() - .index(cutout.source()); - } - - return harness.get(new PipelineProgramKey(instanceType, contextShader, light, shaders, useCutout, FrameUniforms.debugOn())); + return harness.get(new PipelineProgramKey(instanceType, contextShader, light, shaders, cutout != CutoutShaders.OFF, FrameUniforms.debugOn())); } public void delete() { diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/internal/FlwLibLink.java b/common/src/lib/java/dev/engine_room/flywheel/lib/internal/FlwLibLink.java index 33106ff5b..203cca392 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/internal/FlwLibLink.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/internal/FlwLibLink.java @@ -24,4 +24,12 @@ public interface FlwLibLink { void compileModelPart(ModelPart part, PoseStack.Pose pose, VertexConsumer consumer, int light, int overlay, int color); Deque getPoseStack(PoseStack stack); + + boolean isIrisLoaded(); + + boolean isOptifineInstalled(); + + boolean isShaderPackInUse(); + + boolean isRenderingShadowPass(); } diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/internal/FlwLibXplat.java b/common/src/lib/java/dev/engine_room/flywheel/lib/internal/FlwLibXplat.java index 2809537ee..fa58991ca 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/internal/FlwLibXplat.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/internal/FlwLibXplat.java @@ -1,13 +1,11 @@ package dev.engine_room.flywheel.lib.internal; -import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.UnknownNullability; import dev.engine_room.flywheel.api.internal.DependencyInjection; import dev.engine_room.flywheel.lib.model.baked.BakedModelBuilder; import dev.engine_room.flywheel.lib.model.baked.BlockModelBuilder; import dev.engine_room.flywheel.lib.model.baked.MultiBlockModelBuilder; -import dev.engine_room.flywheel.lib.util.ShadersModHandler; import net.minecraft.client.renderer.block.BlockRenderDispatcher; import net.minecraft.client.resources.model.BakedModel; import net.minecraft.client.resources.model.ModelManager; @@ -29,7 +27,4 @@ public interface FlwLibXplat { BlockModelBuilder createBlockModelBuilder(BlockState state); MultiBlockModelBuilder createMultiBlockModelBuilder(BlockAndTintGetter level, Iterable positions); - - @Nullable - ShadersModHandler.InternalHandler createIrisHandler(); } diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/material/LightShaders.java b/common/src/lib/java/dev/engine_room/flywheel/lib/material/LightShaders.java index 3e15c76ca..ac9e351cc 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/material/LightShaders.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/material/LightShaders.java @@ -3,7 +3,7 @@ import dev.engine_room.flywheel.api.Flywheel; import dev.engine_room.flywheel.api.material.LightShader; -public class LightShaders { +public final class LightShaders { public static final LightShader SMOOTH_WHEN_EMBEDDED = new SimpleLightShader(Flywheel.rl("light/smooth_when_embedded.glsl")); public static final LightShader SMOOTH = new SimpleLightShader(Flywheel.rl("light/smooth.glsl")); public static final LightShader FLAT = new SimpleLightShader(Flywheel.rl("light/flat.glsl")); diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/material/SimpleMaterial.java b/common/src/lib/java/dev/engine_room/flywheel/lib/material/SimpleMaterial.java index cf271ed43..214712af4 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/material/SimpleMaterial.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/material/SimpleMaterial.java @@ -178,6 +178,7 @@ public Builder copyFrom(Material material) { shaders = material.shaders(); fog = material.fog(); cutout = material.cutout(); + light = material.light(); texture = material.texture(); blur = material.blur(); mipmap = material.mipmap(); diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/util/ShadersModHandler.java b/common/src/lib/java/dev/engine_room/flywheel/lib/util/ShadersModHandler.java deleted file mode 100644 index 751767094..000000000 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/util/ShadersModHandler.java +++ /dev/null @@ -1,128 +0,0 @@ -package dev.engine_room.flywheel.lib.util; - -import java.lang.reflect.Field; -import java.util.function.BooleanSupplier; - -import org.jetbrains.annotations.ApiStatus; - -import dev.engine_room.flywheel.lib.internal.FlwLibLink; -import dev.engine_room.flywheel.lib.internal.FlwLibXplat; - -public final class ShadersModHandler { - private static final String OPTIFINE_ROOT_PACKAGE = "net.optifine"; - - private static final boolean IS_IRIS_LOADED; - private static final boolean IS_OPTIFINE_INSTALLED; - private static final InternalHandler INTERNAL_HANDLER; - - static { - InternalHandler irisHandler = FlwLibXplat.INSTANCE - .createIrisHandler(); - IS_IRIS_LOADED = irisHandler != null; - - Package optifinePackage = Package.getPackage(OPTIFINE_ROOT_PACKAGE); - IS_OPTIFINE_INSTALLED = optifinePackage != null; - - // OptiFine and Iris are assumed to be mutually exclusive - - if (IS_IRIS_LOADED) { - FlwLibLink.INSTANCE.getLogger().debug("Iris detected."); - INTERNAL_HANDLER = irisHandler; - } else if (IS_OPTIFINE_INSTALLED) { - FlwLibLink.INSTANCE.getLogger().debug("OptiFine detected."); - INTERNAL_HANDLER = new OptifineHandler(); - } else { - FlwLibLink.INSTANCE.getLogger().debug("No shaders mod detected."); - INTERNAL_HANDLER = new InternalHandler() {}; - } - } - - private ShadersModHandler() { - } - - public static boolean isIrisLoaded() { - return IS_IRIS_LOADED; - } - - public static boolean isOptifineInstalled() { - return IS_OPTIFINE_INSTALLED; - } - - public static boolean isShaderPackInUse() { - return INTERNAL_HANDLER.isShaderPackInUse(); - } - - public static boolean isRenderingShadowPass() { - return INTERNAL_HANDLER.isRenderingShadowPass(); - } - - @ApiStatus.Internal - public static void init() { - } - - @ApiStatus.Internal - public interface InternalHandler { - default boolean isShaderPackInUse() { - return false; - } - - default boolean isRenderingShadowPass() { - return false; - } - } - - // evil reflection - private static class OptifineHandler implements InternalHandler { - private final BooleanSupplier shadersEnabledSupplier; - private final BooleanSupplier shadowPassSupplier; - - private OptifineHandler() { - shadersEnabledSupplier = createShadersEnabledSupplier(); - shadowPassSupplier = createShadowPassSupplier(); - } - - @Override - public boolean isShaderPackInUse() { - return shadersEnabledSupplier.getAsBoolean(); - } - - @Override - public boolean isRenderingShadowPass() { - return shadowPassSupplier.getAsBoolean(); - } - - private static BooleanSupplier createShadersEnabledSupplier() { - try { - Class ofShaders = Class.forName("net.optifine.shaders.Shaders"); - Field field = ofShaders.getDeclaredField("shaderPackLoaded"); - field.setAccessible(true); - return () -> { - try { - return field.getBoolean(null); - } catch (IllegalAccessException e) { - return false; - } - }; - } catch (Exception e) { - return () -> false; - } - } - - private static BooleanSupplier createShadowPassSupplier() { - try { - Class ofShaders = Class.forName("net.optifine.shaders.Shaders"); - Field field = ofShaders.getDeclaredField("isShadowPass"); - field.setAccessible(true); - return () -> { - try { - return field.getBoolean(null); - } catch (IllegalAccessException e) { - return false; - } - }; - } catch (Exception e) { - return () -> false; - } - } - } -} diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/util/ShadersModHelper.java b/common/src/lib/java/dev/engine_room/flywheel/lib/util/ShadersModHelper.java new file mode 100644 index 000000000..abfc3bcbe --- /dev/null +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/util/ShadersModHelper.java @@ -0,0 +1,19 @@ +package dev.engine_room.flywheel.lib.util; + +import dev.engine_room.flywheel.lib.internal.FlwLibLink; + +public final class ShadersModHelper { + public static final boolean IS_IRIS_LOADED = FlwLibLink.INSTANCE.isIrisLoaded(); + public static final boolean IS_OPTIFINE_INSTALLED = FlwLibLink.INSTANCE.isOptifineInstalled(); + + private ShadersModHelper() { + } + + public static boolean isShaderPackInUse() { + return FlwLibLink.INSTANCE.isShaderPackInUse(); + } + + public static boolean isRenderingShadowPass() { + return FlwLibLink.INSTANCE.isRenderingShadowPass(); + } +} diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/FlwImpl.java b/common/src/main/java/dev/engine_room/flywheel/impl/FlwImpl.java index 914959997..909c39647 100644 --- a/common/src/main/java/dev/engine_room/flywheel/impl/FlwImpl.java +++ b/common/src/main/java/dev/engine_room/flywheel/impl/FlwImpl.java @@ -6,7 +6,6 @@ import dev.engine_room.flywheel.api.Flywheel; import dev.engine_room.flywheel.backend.FlwBackend; import dev.engine_room.flywheel.impl.registry.IdRegistryImpl; -import dev.engine_room.flywheel.lib.util.ShadersModHandler; import dev.engine_room.flywheel.vanilla.VanillaVisuals; public final class FlwImpl { @@ -21,7 +20,6 @@ public static void init() { BackendManagerImpl.init(); // lib - ShadersModHandler.init(); // backend FlwBackend.init(FlwConfig.INSTANCE.backendConfig()); diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/FlwImplXplat.java b/common/src/main/java/dev/engine_room/flywheel/impl/FlwImplXplat.java index 0bfe20b5d..c8fb9fec1 100644 --- a/common/src/main/java/dev/engine_room/flywheel/impl/FlwImplXplat.java +++ b/common/src/main/java/dev/engine_room/flywheel/impl/FlwImplXplat.java @@ -6,11 +6,15 @@ public interface FlwImplXplat { FlwImplXplat INSTANCE = DependencyInjection.load(FlwImplXplat.class, "dev.engine_room.flywheel.impl.FlwImplXplatImpl"); - boolean getModLoaded(String modId); + boolean isModLoaded(String modId); void dispatchReloadLevelRendererEvent(ClientLevel level); String getVersionStr(); FlwConfig getConfig(); + + boolean useSodium0_6Compat(); + + boolean useIrisCompat(); } diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/FlwLibLinkImpl.java b/common/src/main/java/dev/engine_room/flywheel/impl/FlwLibLinkImpl.java index cd9c4dd8e..10244b19c 100644 --- a/common/src/main/java/dev/engine_room/flywheel/impl/FlwLibLinkImpl.java +++ b/common/src/main/java/dev/engine_room/flywheel/impl/FlwLibLinkImpl.java @@ -8,6 +8,8 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; +import dev.engine_room.flywheel.impl.compat.IrisCompat; +import dev.engine_room.flywheel.impl.compat.OptifineCompat; import dev.engine_room.flywheel.impl.extension.PoseStackExtension; import dev.engine_room.flywheel.impl.mixin.ModelPartAccessor; import dev.engine_room.flywheel.impl.mixin.PoseStackAccessor; @@ -40,4 +42,36 @@ public void compileModelPart(ModelPart part, PoseStack.Pose pose, VertexConsumer public Deque getPoseStack(PoseStack stack) { return ((PoseStackAccessor) stack).flywheel$getPoseStack(); } + + @Override + public boolean isIrisLoaded() { + return IrisCompat.ACTIVE; + } + + @Override + public boolean isOptifineInstalled() { + return OptifineCompat.IS_INSTALLED; + } + + @Override + public boolean isShaderPackInUse() { + if (IrisCompat.ACTIVE) { + return IrisCompat.isShaderPackInUse(); + } else if (OptifineCompat.IS_INSTALLED) { + return OptifineCompat.isShaderPackInUse(); + } else { + return false; + } + } + + @Override + public boolean isRenderingShadowPass() { + if (IrisCompat.ACTIVE) { + return IrisCompat.isRenderingShadowPass(); + } else if (OptifineCompat.IS_INSTALLED) { + return OptifineCompat.isRenderingShadowPass(); + } else { + return false; + } + } } diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/compat/CompatMod.java b/common/src/main/java/dev/engine_room/flywheel/impl/compat/CompatMod.java new file mode 100644 index 000000000..725208bfa --- /dev/null +++ b/common/src/main/java/dev/engine_room/flywheel/impl/compat/CompatMod.java @@ -0,0 +1,18 @@ +package dev.engine_room.flywheel.impl.compat; + +import dev.engine_room.flywheel.impl.FlwImplXplat; + +public enum CompatMod { + EMBEDDIUM("embeddium"), + IRIS("iris"), + OCULUS("oculus"), + SODIUM("sodium"); + + public final String id; + public final boolean isLoaded; + + CompatMod(String modId) { + id = modId; + isLoaded = FlwImplXplat.INSTANCE.isModLoaded(modId); + } +} diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/compat/IrisCompat.java b/common/src/main/java/dev/engine_room/flywheel/impl/compat/IrisCompat.java new file mode 100644 index 000000000..97fc5f5e5 --- /dev/null +++ b/common/src/main/java/dev/engine_room/flywheel/impl/compat/IrisCompat.java @@ -0,0 +1,46 @@ +package dev.engine_room.flywheel.impl.compat; + +import dev.engine_room.flywheel.impl.FlwImpl; +import dev.engine_room.flywheel.impl.FlwImplXplat; +import net.irisshaders.iris.api.v0.IrisApi; + +public final class IrisCompat { + public static final boolean ACTIVE = FlwImplXplat.INSTANCE.useIrisCompat(); + + static { + if (ACTIVE) { + FlwImpl.LOGGER.debug("Detected Iris"); + } + } + + private IrisCompat() { + } + + public static boolean isShaderPackInUse() { + if (!ACTIVE) { + return false; + } + + return Internals.isShaderPackInUse(); + } + + public static boolean isRenderingShadowPass() { + if (!ACTIVE) { + return false; + } + + return Internals.isRenderingShadowPass(); + } + + private static final class Internals { + static boolean isShaderPackInUse() { + return IrisApi.getInstance() + .isShaderPackInUse(); + } + + static boolean isRenderingShadowPass() { + return IrisApi.getInstance() + .isRenderingShadowPass(); + } + } +} diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/compat/OptifineCompat.java b/common/src/main/java/dev/engine_room/flywheel/impl/compat/OptifineCompat.java new file mode 100644 index 000000000..42dfe4687 --- /dev/null +++ b/common/src/main/java/dev/engine_room/flywheel/impl/compat/OptifineCompat.java @@ -0,0 +1,73 @@ +package dev.engine_room.flywheel.impl.compat; + +import java.lang.reflect.Field; + +import org.jetbrains.annotations.Nullable; + +import dev.engine_room.flywheel.impl.FlwImpl; + +public final class OptifineCompat { + private static final String OPTIFINE_ROOT_PACKAGE = "net.optifine"; + + public static final boolean IS_INSTALLED; + @Nullable + private static final Field SHADER_PACK_LOADED_FIELD; + @Nullable + private static final Field IS_SHADOW_PASS_FIELD; + + static { + Field shaderPackLoadedField = null; + Field isShadowPassField = null; + + Package optifinePackage = Package.getPackage(OPTIFINE_ROOT_PACKAGE); + IS_INSTALLED = optifinePackage != null; + + if (IS_INSTALLED) { + try { + Class shadersClass = Class.forName("net.optifine.shaders.Shaders"); + shaderPackLoadedField = shadersClass.getDeclaredField("shaderPackLoaded"); + shaderPackLoadedField.setAccessible(true); + isShadowPassField = shadersClass.getDeclaredField("isShadowPass"); + isShadowPassField.setAccessible(true); + } catch (Exception e) { + FlwImpl.LOGGER.debug("Failed to access OptiFine internals", e); + } + } + + SHADER_PACK_LOADED_FIELD = shaderPackLoadedField; + IS_SHADOW_PASS_FIELD = isShadowPassField; + } + + static { + if (IS_INSTALLED) { + FlwImpl.LOGGER.debug("Detected OptiFine"); + } + } + + private OptifineCompat() { + } + + public static boolean isShaderPackInUse() { + if (SHADER_PACK_LOADED_FIELD == null) { + return false; + } + + try { + return SHADER_PACK_LOADED_FIELD.getBoolean(null); + } catch (IllegalAccessException e) { + return false; + } + } + + public static boolean isRenderingShadowPass() { + if (IS_SHADOW_PASS_FIELD == null) { + return false; + } + + try { + return IS_SHADOW_PASS_FIELD.getBoolean(null); + } catch (IllegalAccessException e) { + return false; + } + } +} diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/compat/SodiumCompat.java b/common/src/main/java/dev/engine_room/flywheel/impl/compat/SodiumCompat.java index 2caf47486..76fa1d499 100644 --- a/common/src/main/java/dev/engine_room/flywheel/impl/compat/SodiumCompat.java +++ b/common/src/main/java/dev/engine_room/flywheel/impl/compat/SodiumCompat.java @@ -1,20 +1,61 @@ package dev.engine_room.flywheel.impl.compat; +import org.jetbrains.annotations.Nullable; + +import dev.engine_room.flywheel.api.visualization.BlockEntityVisualizer; +import dev.engine_room.flywheel.impl.FlwImpl; +import dev.engine_room.flywheel.impl.FlwImplXplat; import dev.engine_room.flywheel.lib.visualization.VisualizationHelper; import net.caffeinemc.mods.sodium.api.blockentity.BlockEntityRenderHandler; import net.caffeinemc.mods.sodium.api.blockentity.BlockEntityRenderPredicate; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; -@SuppressWarnings({"unchecked", "UnstableApiUsage"}) -public class SodiumCompat { - public static Object forBlockEntityType(BlockEntityType type) { - BlockEntityRenderPredicate predicate = (getter, pos, be) -> VisualizationHelper.tryAddBlockEntity(be); - BlockEntityRenderHandler.instance().addRenderPredicate(type, predicate); +public final class SodiumCompat { + public static final boolean USE_0_6_COMPAT = FlwImplXplat.INSTANCE.useSodium0_6Compat(); + + static { + if (USE_0_6_COMPAT) { + FlwImpl.LOGGER.debug("Detected Sodium 0.6"); + } + } + + private SodiumCompat() { + } + + @Nullable + public static Object onSetBlockEntityVisualizer(BlockEntityType type, @Nullable BlockEntityVisualizer oldVisualizer, @Nullable BlockEntityVisualizer newVisualizer, @Nullable Object predicate) { + if (!USE_0_6_COMPAT) { + return null; + } + + if (oldVisualizer == null && newVisualizer != null) { + if (predicate != null) { + throw new IllegalArgumentException("Sodium predicate must be null when old visualizer is null"); + } + + return Internals.addPredicate(type); + } else if (oldVisualizer != null && newVisualizer == null) { + if (predicate == null) { + throw new IllegalArgumentException("Sodium predicate must not be null when old visualizer is not null"); + } + + Internals.removePredicate(type, predicate); + return null; + } + return predicate; } - public static void removePredicate(BlockEntityType type, Object predicate) { - BlockEntityRenderHandler.instance().removeRenderPredicate(type, (BlockEntityRenderPredicate) predicate); + private static final class Internals { + static Object addPredicate(BlockEntityType type) { + BlockEntityRenderPredicate predicate = (getter, pos, be) -> VisualizationHelper.tryAddBlockEntity(be); + BlockEntityRenderHandler.instance().addRenderPredicate(type, predicate); + return predicate; + } + + static void removePredicate(BlockEntityType type, Object predicate) { + BlockEntityRenderHandler.instance().removeRenderPredicate(type, (BlockEntityRenderPredicate) predicate); + } } } diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/mixin/BlockEntityTypeMixin.java b/common/src/main/java/dev/engine_room/flywheel/impl/mixin/BlockEntityTypeMixin.java index 631d1ead6..901c12957 100644 --- a/common/src/main/java/dev/engine_room/flywheel/impl/mixin/BlockEntityTypeMixin.java +++ b/common/src/main/java/dev/engine_room/flywheel/impl/mixin/BlockEntityTypeMixin.java @@ -29,13 +29,10 @@ abstract class BlockEntityTypeMixin implements BlockEntit @Override public void flywheel$setVisualizer(@Nullable BlockEntityVisualizer visualizer) { - if (CompatMods.SODIUM.isLoaded) { - if (flywheel$visualizer == null && visualizer != null) { - flywheel$sodiumPredicate = SodiumCompat.forBlockEntityType((BlockEntityType) (Object) this); - } else if (flywheel$visualizer != null && visualizer == null && flywheel$sodiumPredicate != null) { - SodiumCompat.removePredicate((BlockEntityType) (Object) this, flywheel$sodiumPredicate); - } + if (SodiumCompat.USE_0_6_COMPAT) { + flywheel$sodiumPredicate = SodiumCompat.onSetBlockEntityVisualizer((BlockEntityType) (Object) this, flywheel$visualizer, visualizer, flywheel$sodiumPredicate); } - this.flywheel$visualizer = visualizer; + + flywheel$visualizer = visualizer; } } diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/mixin/EntityTypeMixin.java b/common/src/main/java/dev/engine_room/flywheel/impl/mixin/EntityTypeMixin.java index e8b605a32..91676872f 100644 --- a/common/src/main/java/dev/engine_room/flywheel/impl/mixin/EntityTypeMixin.java +++ b/common/src/main/java/dev/engine_room/flywheel/impl/mixin/EntityTypeMixin.java @@ -12,6 +12,7 @@ @Mixin(EntityType.class) abstract class EntityTypeMixin implements EntityTypeExtension { @Unique + @Nullable private EntityVisualizer flywheel$visualizer; @Override @@ -22,6 +23,6 @@ abstract class EntityTypeMixin implements EntityTypeExtension< @Override public void flywheel$setVisualizer(@Nullable EntityVisualizer visualizer) { - this.flywheel$visualizer = visualizer; + flywheel$visualizer = visualizer; } } diff --git a/common/src/stubs/java/net/caffeinemc/mods/sodium/api/blockentity/BlockEntityRenderHandler.java b/common/src/stubs/java/net/caffeinemc/mods/sodium/api/blockentity/BlockEntityRenderHandler.java new file mode 100644 index 000000000..5c4a588d7 --- /dev/null +++ b/common/src/stubs/java/net/caffeinemc/mods/sodium/api/blockentity/BlockEntityRenderHandler.java @@ -0,0 +1,38 @@ +// https://github.com/CaffeineMC/sodium-fabric/blob/e7643f4544f61180ed2f0ff4952d7daa2c1feaf4/common/src/api/java/net/caffeinemc/mods/sodium/api/blockentity/BlockEntityRenderHandler.java +// PolyForm Shield License 1.0.0 + +package net.caffeinemc.mods.sodium.api.blockentity; + +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import org.jetbrains.annotations.ApiStatus; + +@ApiStatus.Experimental +@ApiStatus.AvailableSince("0.6.0") +public interface BlockEntityRenderHandler { + BlockEntityRenderHandler INSTANCE = null; + + static BlockEntityRenderHandler instance() { + return INSTANCE; + } + + /** + * Adds a predicate to determine if a block entity should be rendered. + * + *

Upon chunk bake, block entities of the given type will have {@code shouldRender} evaluated. + *
If all predicates returns {@code true} (and the block entity has a renderer), the block entity will be + * added to the chunk for future rendering.

+ * @param type The block entity type to associate the given predicate with. + * @param shouldRender The predicate for the block entity to evaluate. + */ + void addRenderPredicate(BlockEntityType type, BlockEntityRenderPredicate shouldRender); + + /** + * Removes a predicate added by {@code addRenderPredicate}. It must be the same object that was added. + * + * @param type The block entity type to associate the given predicate with. + * @param shouldRender The predicate to remove. + * @return If the predicate existed and was removed. + */ + boolean removeRenderPredicate(BlockEntityType type, BlockEntityRenderPredicate shouldRender); +} diff --git a/common/src/stubs/java/net/caffeinemc/mods/sodium/api/blockentity/BlockEntityRenderPredicate.java b/common/src/stubs/java/net/caffeinemc/mods/sodium/api/blockentity/BlockEntityRenderPredicate.java new file mode 100644 index 000000000..8734005f2 --- /dev/null +++ b/common/src/stubs/java/net/caffeinemc/mods/sodium/api/blockentity/BlockEntityRenderPredicate.java @@ -0,0 +1,16 @@ +// https://github.com/CaffeineMC/sodium-fabric/blob/e7643f4544f61180ed2f0ff4952d7daa2c1feaf4/common/src/api/java/net/caffeinemc/mods/sodium/api/blockentity/BlockEntityRenderPredicate.java +// PolyForm Shield License 1.0.0 + +package net.caffeinemc.mods.sodium.api.blockentity; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.block.entity.BlockEntity; +import org.jetbrains.annotations.ApiStatus; + +@ApiStatus.Experimental +@ApiStatus.AvailableSince("0.6.0") +@FunctionalInterface +public interface BlockEntityRenderPredicate { + boolean shouldRender(BlockGetter blockGetter, BlockPos blockPos, T entity); +} diff --git a/common/src/stubs/java/net/irisshaders/iris/api/v0/IrisApi.java b/common/src/stubs/java/net/irisshaders/iris/api/v0/IrisApi.java new file mode 100644 index 000000000..571667e1c --- /dev/null +++ b/common/src/stubs/java/net/irisshaders/iris/api/v0/IrisApi.java @@ -0,0 +1,114 @@ +// https://github.com/IrisShaders/Iris/blob/20be7fc1ff8a48048cb4eb787e1299782bb1caa4/src/main/java/net/irisshaders/iris/api/v0/IrisApi.java +// GNU Lesser General Public License v3.0 + +package net.irisshaders.iris.api.v0; + +/** + * The entry point to the Iris API, major version 0. This is currently the latest + * version of the API. + * + * To access the API, use {@link #getInstance()}. + */ +public interface IrisApi { + /** + * @since API v0.0 + */ + static IrisApi getInstance() { + return null; + } + + /** + * Gets the minor revision of this API. This is incremented when + * new methods are added without breaking API. Mods can check this + * if they wish to check whether given API calls are available on + * the currently installed Iris version. + * + * @return The current minor revision. Currently, revision 2. + */ + int getMinorApiRevision(); + + /** + * Checks whether a shader pack is currently in use and being used + * for rendering. If there is no shader pack enabled or a shader + * pack failed to compile and is therefore not in use, this will + * return false. + * + *

Mods that need to enable custom workarounds for shaders + * should use this method. + * + * @return Whether shaders are being used for rendering. + * @since {@link #getMinorApiRevision() API v0.0} + */ + boolean isShaderPackInUse(); + + /** + * Checks whether the shadow pass is currently being rendered. + * + *

Generally, mods won't need to call this function for much. + * Mods should be fine with things being rendered multiple times + * each frame from different camera perspectives. Often, there's + * a better approach to fixing bugs than calling this function. + * + *

Pretty much the main legitimate use for this function that + * I've seen is in a mod like Immersive Portals, where it has + * very custom culling that doesn't work when the Iris shadow + * pass is active. + * + *

Naturally, this function can only return true if + * {@link #isShaderPackInUse()} returns true. + * + * @return Whether Iris is currently rendering the shadow pass. + * @since API v0.0 + */ + boolean isRenderingShadowPass(); + + /** + * Opens the main Iris GUI screen. It's up to Iris to decide + * what this screen is, but generally this is the shader selection + * screen. + * + * This method takes and returns Objects instead of any concrete + * Minecraft screen class to avoid referencing Minecraft classes. + * Nevertheless, the passed parent must either be null, or an + * object that is a subclass of the appropriate {@code Screen} + * class for the given Minecraft version. + * + * @param parent The parent screen, an instance of the appropriate + * {@code Screen} class. + * @return A {@code Screen} class for the main Iris GUI screen. + * @since API v0.0 + */ + Object openMainIrisScreenObj(Object parent); + + /** + * Gets the language key of the main screen. Currently, this + * is "options.iris.shaderPackSelection". + * + * @return the language key, for use with {@code TranslatableText} + * / {@code TranslatableComponent} + * @since API v0.0 + */ + String getMainScreenLanguageKey(); + +// /** +// * Gets a config object that can edit the Iris configuration. +// * @since API v0.0 +// */ +// IrisApiConfig getConfig(); + +// /** +// * Gets a text vertex sink to render into. +// * @param maxQuadCount Maximum amount of quads that will be rendered with this sink +// * @param bufferProvider An IntFunction that can provide a {@code ByteBuffer} with at minimum the bytes provided by the input parameter +// * @since API 0.1 +// */ +// IrisTextVertexSink createTextVertexSink(int maxQuadCount, IntFunction bufferProvider); + + /** + * Gets the sun path rotation used by the current shader pack. + * + * @return The sun path rotation as specified by the shader pack, or 0 if no shader pack is in use. + * @since API v0.2 + */ + float getSunPathRotation(); +} diff --git a/fabric/build.gradle.kts b/fabric/build.gradle.kts index 0e6bc0621..50d15209c 100644 --- a/fabric/build.gradle.kts +++ b/fabric/build.gradle.kts @@ -10,6 +10,7 @@ plugins { val api = sourceSets.create("api") val lib = sourceSets.create("lib") val backend = sourceSets.create("backend") +val stubs = sourceSets.create("stubs") val main = sourceSets.getByName("main") transitiveSourceSets { @@ -26,7 +27,12 @@ transitiveSourceSets { rootCompile() compile(api, lib) } + sourceSet(stubs) { + rootCompile() + } sourceSet(main) { + // Don't want stubs at runtime + compile(stubs) implementation(api, lib, backend) } @@ -35,11 +41,10 @@ transitiveSourceSets { platform { commonProject = project(":common") - sources(api, lib, backend, main) - compileWithCommonSourceSets() - setupLoomMod() + compileWithCommonSourceSets(api, lib, backend, stubs, main) + setupLoomMod(api, lib, backend, main) setupLoomRuns() - setupFatJar() + setupFatJar(api, lib, backend, main) } jarSets { @@ -78,5 +83,6 @@ dependencies { "forApi"(project(path = ":common", configuration = "commonApiOnly")) "forLib"(project(path = ":common", configuration = "commonLib")) "forBackend"(project(path = ":common", configuration = "commonBackend")) + "forStubs"(project(path = ":common", configuration = "commonStubs")) "forMain"(project(path = ":common", configuration = "commonImpl")) } diff --git a/fabric/src/main/java/dev/engine_room/flywheel/impl/FlwImplXplatImpl.java b/fabric/src/main/java/dev/engine_room/flywheel/impl/FlwImplXplatImpl.java index 4c1ea44c2..7a2c9df22 100644 --- a/fabric/src/main/java/dev/engine_room/flywheel/impl/FlwImplXplatImpl.java +++ b/fabric/src/main/java/dev/engine_room/flywheel/impl/FlwImplXplatImpl.java @@ -6,7 +6,7 @@ public class FlwImplXplatImpl implements FlwImplXplat { @Override - public boolean getModLoaded(String modId) { + public boolean isModLoaded(String modId) { return FabricLoader.getInstance().isModLoaded(modId); } @@ -24,4 +24,14 @@ public String getVersionStr() { public FlwConfig getConfig() { return FabricFlwConfig.INSTANCE; } + + @Override + public boolean useSodium0_6Compat() { + return FabricSodiumCompat.USE_0_6_COMPAT; + } + + @Override + public boolean useIrisCompat() { + return CompatMod.IRIS.isLoaded; + } } diff --git a/fabric/src/main/java/dev/engine_room/flywheel/impl/FlwLibXplatImpl.java b/fabric/src/main/java/dev/engine_room/flywheel/impl/FlwLibXplatImpl.java index 0a372485f..def03542e 100644 --- a/fabric/src/main/java/dev/engine_room/flywheel/impl/FlwLibXplatImpl.java +++ b/fabric/src/main/java/dev/engine_room/flywheel/impl/FlwLibXplatImpl.java @@ -1,6 +1,5 @@ package dev.engine_room.flywheel.impl; -import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.UnknownNullability; import dev.engine_room.flywheel.impl.compat.CompatMods; diff --git a/fabric/src/main/java/dev/engine_room/flywheel/impl/compat/FabricSodiumCompat.java b/fabric/src/main/java/dev/engine_room/flywheel/impl/compat/FabricSodiumCompat.java new file mode 100644 index 000000000..4a6ee1da4 --- /dev/null +++ b/fabric/src/main/java/dev/engine_room/flywheel/impl/compat/FabricSodiumCompat.java @@ -0,0 +1,48 @@ +package dev.engine_room.flywheel.impl.compat; + +import java.util.Optional; + +import dev.engine_room.flywheel.impl.FlwImpl; +import net.fabricmc.loader.api.FabricLoader; +import net.fabricmc.loader.api.ModContainer; +import net.fabricmc.loader.api.Version; +import net.fabricmc.loader.api.VersionParsingException; +import net.fabricmc.loader.api.metadata.version.VersionPredicate; + +public final class FabricSodiumCompat { + public static final boolean USE_0_5_COMPAT; + public static final boolean USE_0_6_COMPAT; + + static { + boolean use0_5Compat = false; + boolean use0_6Compat = false; + + Optional optionalModContainer = FabricLoader.getInstance().getModContainer(CompatMod.SODIUM.id); + + if (optionalModContainer.isPresent()) { + ModContainer modContainer = optionalModContainer.get(); + Version sodiumVersion = modContainer.getMetadata().getVersion(); + + try { + VersionPredicate predicate0_5 = VersionPredicate.parse("~0.5.0"); + VersionPredicate predicate0_6 = VersionPredicate.parse(">=0.6.0-beta.2"); + use0_5Compat = predicate0_5.test(sodiumVersion); + use0_6Compat = predicate0_6.test(sodiumVersion); + } catch (VersionParsingException e) { + FlwImpl.LOGGER.debug("Failed to parse Sodium version predicates", e); + } + } + + USE_0_5_COMPAT = use0_5Compat; + USE_0_6_COMPAT = use0_6Compat; + } + + static { + if (USE_0_5_COMPAT) { + FlwImpl.LOGGER.debug("Detected Sodium 0.5"); + } + } + + private FabricSodiumCompat() { + } +} diff --git a/fabric/src/main/resources/fabric.mod.json b/fabric/src/main/resources/fabric.mod.json index b94e9847f..3fb114d85 100644 --- a/fabric/src/main/resources/fabric.mod.json +++ b/fabric/src/main/resources/fabric.mod.json @@ -28,6 +28,7 @@ ], "depends": { "minecraft": "${minecraft_semver_version_range}", + "fabricloader": ">=0.15.0", "fabric-api": "${fabric_api_version_range}" }, "breaks": { diff --git a/forge/build.gradle.kts b/forge/build.gradle.kts index 8ecf5d447..d70c1ce80 100644 --- a/forge/build.gradle.kts +++ b/forge/build.gradle.kts @@ -10,6 +10,7 @@ plugins { val api = sourceSets.create("api") val lib = sourceSets.create("lib") val backend = sourceSets.create("backend") +val stubs = sourceSets.create("stubs") val main = sourceSets.getByName("main") transitiveSourceSets { @@ -26,8 +27,11 @@ transitiveSourceSets { rootCompile() compile(api, lib) } + sourceSet(stubs) { + rootCompile() + } sourceSet(main) { - compile(api, lib, backend) + compile(api, lib, backend, stubs) } createCompileConfigurations() @@ -35,11 +39,10 @@ transitiveSourceSets { platform { commonProject = project(":common") - sources(api, lib, backend, main) - compileWithCommonSourceSets() - setupLoomMod() + compileWithCommonSourceSets(api, lib, backend, stubs, main) + setupLoomMod(api, lib, backend, main) setupLoomRuns() - setupFatJar() + setupFatJar(api, lib, backend, main) } jarSets { @@ -88,5 +91,6 @@ dependencies { "forApi"(project(path = ":common", configuration = "commonApiOnly")) "forLib"(project(path = ":common", configuration = "commonLib")) "forBackend"(project(path = ":common", configuration = "commonBackend")) + "forStubs"(project(path = ":common", configuration = "commonStubs")) "forMain"(project(path = ":common", configuration = "commonImpl")) } diff --git a/forge/src/main/java/dev/engine_room/flywheel/impl/FlwImplXplatImpl.java b/forge/src/main/java/dev/engine_room/flywheel/impl/FlwImplXplatImpl.java index 774665549..4e3b1d069 100644 --- a/forge/src/main/java/dev/engine_room/flywheel/impl/FlwImplXplatImpl.java +++ b/forge/src/main/java/dev/engine_room/flywheel/impl/FlwImplXplatImpl.java @@ -1,13 +1,15 @@ package dev.engine_room.flywheel.impl; import dev.engine_room.flywheel.api.event.ReloadLevelRendererEvent; +import dev.engine_room.flywheel.impl.compat.CompatMod; import net.minecraft.client.multiplayer.ClientLevel; import net.neoforged.fml.loading.LoadingModList; import net.neoforged.neoforge.common.NeoForge; +import net.minecraftforge.fml.loading.LoadingModList; public class FlwImplXplatImpl implements FlwImplXplat { @Override - public boolean getModLoaded(String modId) { + public boolean isModLoaded(String modId) { return LoadingModList.get().getModFileById(modId) != null; } @@ -25,4 +27,14 @@ public String getVersionStr() { public FlwConfig getConfig() { return NeoForgeFlwConfig.INSTANCE; } + + @Override + public boolean useSodium0_6Compat() { + return CompatMod.SODIUM.isLoaded && !CompatMod.EMBEDDIUM.isLoaded; + } + + @Override + public boolean useIrisCompat() { + return CompatMod.IRIS.isLoaded || CompatMod.OCULUS.isLoaded; + } } diff --git a/forge/src/main/java/dev/engine_room/flywheel/impl/FlwLibXplatImpl.java b/forge/src/main/java/dev/engine_room/flywheel/impl/FlwLibXplatImpl.java index 0dfbbc4f7..3590aea70 100644 --- a/forge/src/main/java/dev/engine_room/flywheel/impl/FlwLibXplatImpl.java +++ b/forge/src/main/java/dev/engine_room/flywheel/impl/FlwLibXplatImpl.java @@ -2,7 +2,6 @@ import java.lang.reflect.Field; -import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.UnknownNullability; import dev.engine_room.flywheel.impl.compat.CompatMods; diff --git a/forge/src/main/java/dev/engine_room/flywheel/impl/compat/EmbeddiumCompat.java b/forge/src/main/java/dev/engine_room/flywheel/impl/compat/EmbeddiumCompat.java new file mode 100644 index 000000000..cd1e5e138 --- /dev/null +++ b/forge/src/main/java/dev/engine_room/flywheel/impl/compat/EmbeddiumCompat.java @@ -0,0 +1,33 @@ +package dev.engine_room.flywheel.impl.compat; + +import org.embeddedt.embeddium.api.ChunkDataBuiltEvent; + +import dev.engine_room.flywheel.impl.FlwImpl; +import dev.engine_room.flywheel.lib.visualization.VisualizationHelper; + +public final class EmbeddiumCompat { + public static final boolean ACTIVE = CompatMod.EMBEDDIUM.isLoaded; + + static { + if (ACTIVE) { + FlwImpl.LOGGER.debug("Detected Embeddium"); + } + } + + private EmbeddiumCompat() { + } + + public static void init() { + if (ACTIVE) { + Internals.init(); + } + } + + private static final class Internals { + static void init() { + ChunkDataBuiltEvent.BUS.addListener(event -> { + event.getDataBuilder().removeBlockEntitiesIf(VisualizationHelper::tryAddBlockEntity); + }); + } + } +} diff --git a/forge/src/main/resources/META-INF/neoforge.mods.toml b/forge/src/main/resources/META-INF/neoforge.mods.toml index 35a7234fb..1954a3f6d 100644 --- a/forge/src/main/resources/META-INF/neoforge.mods.toml +++ b/forge/src/main/resources/META-INF/neoforge.mods.toml @@ -31,6 +31,13 @@ type = "required" versionRange = "${neoforge_version_range}" side = "CLIENT" +[[dependencies.${mod_id}]] +modId = "sodium" +mandatory = false +versionRange = "[0.6.0-beta.2,)" +side = "CLIENT" + +# Simulates a breaks/incompatible dependency [[dependencies.${mod_id}]] modId = "embeddium" type = "incompatible" diff --git a/gradle.properties b/gradle.properties index 04e0c97fc..f95a97025 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,9 +7,9 @@ mod_name = Flywheel mod_version = 1.0.0-beta mod_description = An overhauled entity and block entity rendering API. mod_license = MIT -mod_sources = https://github.com/Jozufozu/Flywheel -mod_issues = https://github.com/Jozufozu/Flywheel/issues -mod_homepage = https://github.com/Jozufozu/Flywheel +mod_sources = https://github.com/Engine-Room/Flywheel +mod_issues = https://github.com/Engine-Room/Flywheel/issues +mod_homepage = https://github.com/Engine-Room/Flywheel # Mod dependency declarations minecraft_semver_version_range = >=1.21.1 <1.21.2 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 9355b4155..df97d72b8 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME