This commit is contained in:
IThundxr 2024-11-03 22:21:52 +02:00 committed by GitHub
commit b67f525ecc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
70 changed files with 416 additions and 901 deletions

View File

@ -7,7 +7,7 @@ jobs:
strategy:
matrix:
java: [
17 # Current Java LTS & minimum supported by Minecraft
21 # Current Java LTS & minimum supported by Minecraft
]
os: [ ubuntu-latest ]
runs-on: ${{ matrix.os }}

View File

@ -8,8 +8,8 @@ plugins {
repositories {
gradlePluginPortal()
mavenCentral()
maven("https://maven.minecraftforge.net/") {
name = "MinecraftForge"
maven("https://maven.neoforged.net/releases/") {
name = "NeoForged"
}
maven("https://maven.architectury.dev/") {
name = "Architectury"

View File

@ -166,7 +166,7 @@ class SubprojectPlugin: Plugin<Project> {
}
}
val processResourcesExpandFiles = listOf("pack.mcmeta", "fabric.mod.json", "META-INF/mods.toml")
val processResourcesExpandFiles = listOf("pack.mcmeta", "fabric.mod.json", "META-INF/neoforge.mods.toml")
val processResourcesExpandProperties = listOf(
"mod_id",
@ -180,6 +180,6 @@ val processResourcesExpandProperties = listOf(
"minecraft_semver_version_range",
"minecraft_maven_version_range",
"fabric_api_version_range",
"forge_version_range",
"neoforge_version_range",
)

View File

@ -9,7 +9,6 @@ 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,11 +25,8 @@ transitiveSourceSets {
rootCompile()
compile(api, lib)
}
sourceSet(stubs) {
rootCompile()
}
sourceSet(main) {
compile(api, lib, backend, stubs)
compile(api, lib, backend)
}
sourceSet(sourceSets.getByName("test")) {
implementation(api, lib, backend)
@ -46,7 +42,6 @@ jarSets {
outgoing("commonApiOnly", api)
outgoing("commonLib", lib)
outgoing("commonBackend", backend)
outgoing("commonStubs", stubs)
outgoing("commonImpl", main)
// For publishing.
@ -77,6 +72,9 @@ jarSets {
dependencies {
modCompileOnly("net.fabricmc:fabric-loader:${property("fabric_loader_version")}")
modCompileOnly("maven.modrinth:sodium:${property("sodium_version")}-fabric")
modCompileOnly("maven.modrinth:iris:${property("iris_version")}-fabric")
testImplementation("org.junit.jupiter:junit-jupiter:5.8.1")
}

View File

@ -9,6 +9,6 @@ public final class Flywheel {
}
public static ResourceLocation rl(String path) {
return new ResourceLocation(ID, path);
return ResourceLocation.fromNamespaceAndPath(ID, path);
}
}

View File

@ -16,7 +16,7 @@ public interface RenderContext {
RenderBuffers buffers();
PoseStack stack();
Matrix4fc modelView();
Matrix4fc projection();

View File

@ -73,7 +73,7 @@ public final class FrameUniforms extends UniformWriter {
var camY = (float) (cameraPos.y - renderOrigin.getY());
var camZ = (float) (cameraPos.z - renderOrigin.getZ());
VIEW.set(context.stack().last().pose());
VIEW.set(context.modelView());
VIEW.translate(-camX, -camY, -camZ);
PROJECTION.set(context.projection());
VIEW_PROJECTION.set(context.viewProjection());

View File

@ -41,7 +41,7 @@ public class ShaderSources {
}
private static ResourceLocation locationWithoutFlywheelPrefix(ResourceLocation loc) {
return new ResourceLocation(loc.getNamespace(), loc.getPath()
return ResourceLocation.fromNamespaceAndPath(loc.getNamespace(), loc.getPath()
.substring(SHADER_DIR.length()));
}

View File

@ -2,7 +2,7 @@
"required": true,
"minVersion": "0.8",
"package": "dev.engine_room.flywheel.backend.mixin",
"compatibilityLevel": "JAVA_17",
"compatibilityLevel": "JAVA_21",
"refmap": "backend-flywheel.refmap.json",
"client": [
"AbstractClientPlayerAccessor",

View File

@ -21,7 +21,7 @@ public interface FlwLibLink {
Map<String, ModelPart> getModelPartChildren(ModelPart part);
void compileModelPart(ModelPart part, PoseStack.Pose pose, VertexConsumer consumer, int light, int overlay, float red, float green, float blue, float alpha);
void compileModelPart(ModelPart part, PoseStack.Pose pose, VertexConsumer consumer, int light, int overlay, int color);
Deque<PoseStack.Pose> getPoseStack(PoseStack stack);

View File

@ -60,7 +60,7 @@ public final class ModelUtil {
if (renderType == Sheets.translucentCullBlockSheet() || renderType == Sheets.translucentItemSheet()) {
return Materials.CUTOUT_BLOCK;
}
if (renderType == RenderType.glint() || renderType == RenderType.glintDirect()) {
if (renderType == RenderType.glint() || renderType == RenderType.glintTranslucent()) {
return Materials.GLINT;
}
if (renderType == RenderType.entityGlint() || renderType == RenderType.entityGlintDirect()) {

View File

@ -5,7 +5,7 @@ import java.nio.ByteBuffer;
import org.jetbrains.annotations.Nullable;
import org.lwjgl.system.MemoryUtil;
import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.MeshData;
import dev.engine_room.flywheel.lib.memory.MemoryBlock;
import dev.engine_room.flywheel.lib.model.SimpleQuadMesh;
@ -16,15 +16,15 @@ final class MeshHelper {
private MeshHelper() {
}
public static SimpleQuadMesh blockVerticesToMesh(BufferBuilder.RenderedBuffer buffer, @Nullable String meshDescriptor) {
BufferBuilder.DrawState drawState = buffer.drawState();
public static SimpleQuadMesh blockVerticesToMesh(MeshData data, @Nullable String meshDescriptor) {
MeshData.DrawState drawState = data.drawState();
int vertexCount = drawState.vertexCount();
long srcStride = drawState.format().getVertexSize();
VertexView vertexView = new NoOverlayVertexView();
long dstStride = vertexView.stride();
ByteBuffer src = buffer.vertexBuffer();
ByteBuffer src = data.vertexBuffer();
MemoryBlock dst = MemoryBlock.mallocTracked((long) vertexCount * dstStride);
long srcPtr = MemoryUtil.memAddress(src);
long dstPtr = dst.ptr();

View File

@ -26,67 +26,46 @@ class TransformingVertexConsumer implements VertexConsumer {
}
@Override
public VertexConsumer vertex(double x, double y, double z) {
public VertexConsumer addVertex(float x, float y, float z) {
Matrix4f matrix = poseStack.last().pose();
float fx = (float) x;
float fy = (float) y;
float fz = (float) z;
delegate.vertex(
MatrixMath.transformPositionX(matrix, fx, fy, fz),
MatrixMath.transformPositionY(matrix, fx, fy, fz),
MatrixMath.transformPositionZ(matrix, fx, fy, fz));
delegate.addVertex(
MatrixMath.transformPositionX(matrix, x, y, z),
MatrixMath.transformPositionY(matrix, x, y, z),
MatrixMath.transformPositionZ(matrix, x, y, z));
return this;
}
@Override
public VertexConsumer color(int red, int green, int blue, int alpha) {
delegate.color(red, green, blue, alpha);
public VertexConsumer setColor(int red, int green, int blue, int alpha) {
delegate.setColor(red, green, blue, alpha);
return this;
}
@Override
public VertexConsumer uv(float u, float v) {
delegate.uv(u, v);
public VertexConsumer setUv(float u, float v) {
delegate.setUv(u, v);
return this;
}
@Override
public VertexConsumer overlayCoords(int u, int v) {
delegate.overlayCoords(u, v);
public VertexConsumer setUv1(int u, int v) {
delegate.setUv1(u, v);
return this;
}
@Override
public VertexConsumer uv2(int u, int v) {
delegate.uv2(u, v);
public VertexConsumer setUv2(int u, int v) {
delegate.setUv2(u, v);
return this;
}
@Override
public VertexConsumer normal(float x, float y, float z) {
public VertexConsumer setNormal(float x, float y, float z) {
Matrix3f matrix = poseStack.last().normal();
float fx = (float) x;
float fy = (float) y;
float fz = (float) z;
delegate.normal(
MatrixMath.transformNormalX(matrix, fx, fy, fz),
MatrixMath.transformNormalY(matrix, fx, fy, fz),
MatrixMath.transformNormalZ(matrix, fx, fy, fz));
delegate.setNormal(
MatrixMath.transformNormalX(matrix, x, y, z),
MatrixMath.transformNormalY(matrix, x, y, z),
MatrixMath.transformNormalZ(matrix, x, y, z));
return this;
}
@Override
public void endVertex() {
delegate.endVertex();
}
@Override
public void defaultColor(int red, int green, int blue, int alpha) {
delegate.defaultColor(red, green, blue, alpha);
}
@Override
public void unsetDefaultColor() {
delegate.unsetDefaultColor();
}
}

View File

@ -74,7 +74,7 @@ public final class MeshTree {
}
VertexWriter vertexWriter = objects.vertexWriter;
FlwLibLink.INSTANCE.compileModelPart(modelPart, IDENTITY_POSE, vertexWriter, LightTexture.FULL_BRIGHT, OverlayTexture.NO_OVERLAY, 1.0F, 1.0F, 1.0F, 1.0F);
FlwLibLink.INSTANCE.compileModelPart(modelPart, IDENTITY_POSE, vertexWriter, LightTexture.FULL_BRIGHT, OverlayTexture.NO_OVERLAY, 0xFFFFFFFF);
MemoryBlock data = vertexWriter.copyDataAndReset();
VertexView vertexView = new PosTexNormalVertexView();

View File

@ -23,48 +23,48 @@ class VertexWriter implements VertexConsumer {
}
@Override
public VertexConsumer vertex(double x, double y, double z) {
public VertexConsumer addVertex(float x, float y, float z) {
if (!filledPosition) {
long ptr = vertexPtr();
MemoryUtil.memPutFloat(ptr, (float) x);
MemoryUtil.memPutFloat(ptr + 4, (float) y);
MemoryUtil.memPutFloat(ptr + 8, (float) z);
MemoryUtil.memPutFloat(ptr, x);
MemoryUtil.memPutFloat(ptr + 4, y);
MemoryUtil.memPutFloat(ptr + 8, z);
filledPosition = true;
}
return this;
return endVertexIfNeeded();
}
@Override
public VertexConsumer color(int red, int green, int blue, int alpha) {
public VertexConsumer setColor(int red, int green, int blue, int alpha) {
// ignore color
return this;
return endVertexIfNeeded();
}
@Override
public VertexConsumer uv(float u, float v) {
public VertexConsumer setUv(float u, float v) {
if (!filledTexture) {
long ptr = vertexPtr();
MemoryUtil.memPutFloat(ptr + 12, u);
MemoryUtil.memPutFloat(ptr + 16, v);
filledTexture = true;
}
return this;
return endVertexIfNeeded();
}
@Override
public VertexConsumer overlayCoords(int u, int v) {
public VertexConsumer setUv1(int u, int v) {
// ignore overlay
return this;
return endVertexIfNeeded();
}
@Override
public VertexConsumer uv2(int u, int v) {
public VertexConsumer setUv2(int u, int v) {
// ignore light
return this;
return endVertexIfNeeded();
}
@Override
public VertexConsumer normal(float x, float y, float z) {
public VertexConsumer setNormal(float x, float y, float z) {
if (!filledNormal) {
long ptr = vertexPtr();
MemoryUtil.memPutByte(ptr + 20, DataPacker.packNormI8(x));
@ -72,13 +72,13 @@ class VertexWriter implements VertexConsumer {
MemoryUtil.memPutByte(ptr + 22, DataPacker.packNormI8(z));
filledNormal = true;
}
return this;
return endVertexIfNeeded();
}
@Override
public void endVertex() {
public VertexConsumer endVertexIfNeeded() {
if (!filledPosition || !filledTexture || !filledNormal) {
throw new IllegalStateException("Not filled all elements of the vertex");
// We do not throw here as that matched what vanilla does
return this;
}
filledPosition = false;
@ -91,14 +91,8 @@ class VertexWriter implements VertexConsumer {
if (byteSize > capacity) {
data = data.realloc(capacity * 2);
}
}
@Override
public void defaultColor(int red, int green, int blue, int alpha) {
}
@Override
public void unsetDefaultColor() {
return this;
}
private long vertexPtr() {

View File

@ -16,7 +16,7 @@ public final class ResourceUtil {
}
/**
* Same as {@link ResourceLocation#ResourceLocation(String)}, but defaults to Flywheel namespace.
* Same as {@link ResourceLocation#parse(String)}, but defaults to Flywheel namespace.
*/
public static ResourceLocation parseFlywheelDefault(String location) {
String namespace = Flywheel.ID;
@ -30,7 +30,7 @@ public final class ResourceUtil {
}
}
return new ResourceLocation(namespace, path);
return ResourceLocation.fromNamespaceAndPath(namespace, path);
}
/**

View File

@ -8,8 +8,8 @@ public final class VertexTransformations {
}
public static void retexture(MutableVertexList vertexList, int index, TextureAtlasSprite sprite) {
vertexList.u(index, sprite.getU(vertexList.u(index) * 16));
vertexList.v(index, sprite.getV(vertexList.v(index) * 16));
vertexList.u(index, sprite.getU(vertexList.u(index)));
vertexList.v(index, sprite.getV(vertexList.v(index)));
}
public static void retexture(MutableVertexList vertexList, TextureAtlasSprite sprite) {

View File

@ -42,7 +42,7 @@ import net.minecraft.world.phys.shapes.VoxelShape;
* The shadow will be cast on blocks at most {@code min(radius, 2 * strength)} blocks below the entity.</p>
*/
public final class ShadowComponent implements EntityComponent {
private static final ResourceLocation SHADOW_TEXTURE = new ResourceLocation("textures/misc/shadow.png");
private static final ResourceLocation SHADOW_TEXTURE = ResourceLocation.withDefaultNamespace("textures/misc/shadow.png");
private static final Material SHADOW_MATERIAL = SimpleMaterial.builder()
.texture(SHADOW_TEXTURE)
.mipmap(false)

View File

@ -13,8 +13,4 @@ public interface FlwImplXplat {
String getVersionStr();
FlwConfig getConfig();
boolean useSodium0_6Compat();
boolean useIrisCompat();
}

View File

@ -34,8 +34,8 @@ public class FlwLibLinkImpl implements FlwLibLink {
}
@Override
public void compileModelPart(ModelPart part, PoseStack.Pose pose, VertexConsumer consumer, int light, int overlay, float red, float green, float blue, float alpha) {
((ModelPartAccessor) (Object) part).flywheel$compile(pose, consumer, light, overlay, red, green, blue, alpha);
public void compileModelPart(ModelPart part, PoseStack.Pose pose, VertexConsumer consumer, int light, int overlay, int color) {
((ModelPartAccessor) (Object) part).flywheel$compile(pose, consumer, light, overlay, color);
}
@Override

View File

@ -3,9 +3,7 @@ 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;

View File

@ -1,11 +1,10 @@
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();
public static final boolean ACTIVE = CompatMod.IRIS.isLoaded;
static {
if (ACTIVE) {

View File

@ -4,7 +4,6 @@ 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;
@ -12,11 +11,11 @@ import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
public final class SodiumCompat {
public static final boolean USE_0_6_COMPAT = FlwImplXplat.INSTANCE.useSodium0_6Compat();
public static final boolean ACTIVE = CompatMod.SODIUM.isLoaded;
static {
if (USE_0_6_COMPAT) {
FlwImpl.LOGGER.debug("Detected Sodium 0.6");
if (ACTIVE) {
FlwImpl.LOGGER.debug("Detected Sodium");
}
}
@ -25,7 +24,7 @@ public final class SodiumCompat {
@Nullable
public static <T extends BlockEntity> Object onSetBlockEntityVisualizer(BlockEntityType<T> type, @Nullable BlockEntityVisualizer<? super T> oldVisualizer, @Nullable BlockEntityVisualizer<? super T> newVisualizer, @Nullable Object predicate) {
if (!USE_0_6_COMPAT) {
if (!ACTIVE) {
return null;
}

View File

@ -3,22 +3,19 @@ package dev.engine_room.flywheel.impl.event;
import org.joml.Matrix4f;
import org.joml.Matrix4fc;
import com.mojang.blaze3d.vertex.PoseStack;
import dev.engine_room.flywheel.api.RenderContext;
import net.minecraft.client.Camera;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.client.renderer.RenderBuffers;
public record RenderContextImpl(LevelRenderer renderer, ClientLevel level, RenderBuffers buffers, PoseStack stack,
public record RenderContextImpl(LevelRenderer renderer, ClientLevel level, RenderBuffers buffers, Matrix4fc modelView,
Matrix4fc projection, Matrix4fc viewProjection, Camera camera,
float partialTick) implements RenderContext {
public static RenderContextImpl create(LevelRenderer renderer, ClientLevel level, RenderBuffers buffers, PoseStack stack, Matrix4f projection, Camera camera, float partialTick) {
public static RenderContextImpl create(LevelRenderer renderer, ClientLevel level, RenderBuffers buffers, Matrix4fc modelView, Matrix4f projection, Camera camera, float partialTick) {
Matrix4f viewProjection = new Matrix4f(projection);
viewProjection.mul(stack.last()
.pose());
viewProjection.mul(modelView);
return new RenderContextImpl(renderer, level, buffers, stack, projection, viewProjection, camera, partialTick);
return new RenderContextImpl(renderer, level, buffers, modelView, projection, viewProjection, camera, partialTick);
}
}

View File

@ -28,7 +28,7 @@ abstract class BlockEntityTypeMixin<T extends BlockEntity> implements BlockEntit
@Override
public void flywheel$setVisualizer(@Nullable BlockEntityVisualizer<? super T> visualizer) {
if (SodiumCompat.USE_0_6_COMPAT) {
if (SodiumCompat.ACTIVE) {
flywheel$sodiumPredicate = SodiumCompat.onSetBlockEntityVisualizer((BlockEntityType<T>) (Object) this, flywheel$visualizer, visualizer, flywheel$sodiumPredicate);
}

View File

@ -0,0 +1,12 @@
package dev.engine_room.flywheel.impl.mixin;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import com.mojang.blaze3d.vertex.BufferBuilder;
@Mixin(BufferBuilder.class)
public interface BufferBuilderAccessor {
@Accessor("building")
boolean flywheel$getBuilding();
}

View File

@ -22,6 +22,7 @@ import dev.engine_room.flywheel.impl.event.RenderContextImpl;
import dev.engine_room.flywheel.lib.visualization.VisualizationHelper;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import net.minecraft.client.Camera;
import net.minecraft.client.DeltaTracker;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.LevelRenderer;
@ -51,8 +52,8 @@ abstract class LevelRendererMixin {
// @Inject(method = "renderLevel", at = @At("HEAD"))
@Inject(method = "renderLevel", at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/world/level/lighting/LevelLightEngine;runLightUpdates()I"))
private void flywheel$beginRender(PoseStack poseStack, float partialTick, long finishNanoTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f projectionMatrix, CallbackInfo ci) {
flywheel$renderContext = RenderContextImpl.create((LevelRenderer) (Object) this, level, renderBuffers, poseStack, projectionMatrix, camera, partialTick);
private void flywheel$beginRender(DeltaTracker deltaTracker, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f modelMatrix, Matrix4f projectionMatrix, CallbackInfo ci) {
flywheel$renderContext = RenderContextImpl.create((LevelRenderer) (Object) this, level, renderBuffers, modelMatrix, projectionMatrix, camera, deltaTracker.getGameTimeDeltaPartialTick(false));
VisualizationManager manager = VisualizationManager.get(level);
if (manager != null) {
@ -102,8 +103,8 @@ abstract class LevelRendererMixin {
}
}
@Group(name = "afterParticles", min = 2, max = 2)
@Inject(method = "renderLevel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/particle/ParticleEngine;render(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;Lnet/minecraft/client/renderer/LightTexture;Lnet/minecraft/client/Camera;F)V", shift = Shift.AFTER))
@Group(name = "afterParticles", min = 2, max = 3)
@Inject(method = "renderLevel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/particle/ParticleEngine;render(Lnet/minecraft/client/renderer/LightTexture;Lnet/minecraft/client/Camera;F)V", shift = Shift.AFTER))
private void flywheel$afterParticles$fabric(CallbackInfo ci) {
if (flywheel$renderContext != null) {
VisualizationManager manager = VisualizationManager.get(level);
@ -114,7 +115,7 @@ abstract class LevelRendererMixin {
}
@Group(name = "afterParticles")
@Inject(method = "renderLevel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/particle/ParticleEngine;render(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;Lnet/minecraft/client/renderer/LightTexture;Lnet/minecraft/client/Camera;FLnet/minecraft/client/renderer/culling/Frustum;)V", shift = Shift.AFTER))
@Inject(method = "renderLevel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/particle/ParticleEngine;render(Lnet/minecraft/client/renderer/LightTexture;Lnet/minecraft/client/Camera;FLnet/minecraft/client/renderer/culling/Frustum;Ljava/util/function/Predicate;)V", shift = Shift.AFTER))
private void flywheel$afterParticles$forge(CallbackInfo ci) {
if (flywheel$renderContext != null) {
VisualizationManager manager = VisualizationManager.get(level);

View File

@ -17,5 +17,5 @@ public interface ModelPartAccessor {
Map<String, ModelPart> flywheel$children();
@Invoker("compile")
void flywheel$compile(PoseStack.Pose pose, VertexConsumer vertexConsumer, int packedLight, int packedOverlay, float red, float green, float blue, float alpha);
void flywheel$compile(PoseStack.Pose pose, VertexConsumer buffer, int packedLight, int packedOverlay, int color);
}

View File

@ -1,36 +0,0 @@
package dev.engine_room.flywheel.impl.mixin.fix;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.At.Shift;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyArg;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.mojang.blaze3d.vertex.PoseStack;
@Mixin(PoseStack.class)
abstract class FixNormalScalingMixin {
/**
* Minecraft negates the normal matrix if all scales are equal and negative, but
* does not return afterward. This allows the rest of the method's logic to be
* applied, which negates the matrix again, resulting in the matrix being the
* same as in the beginning.
*/
@Inject(method = "scale(FFF)V", at = @At(value = "INVOKE", target = "Lorg/joml/Matrix3f;scale(F)Lorg/joml/Matrix3f;", shift = Shift.AFTER, remap = false), cancellable = true)
private void flywheel$returnAfterNegate(float x, float y, float z, CallbackInfo ci) {
ci.cancel();
}
/**
* Minecraft takes the inverse cube root of the product of all scales to provide a
* rough estimate for normalization so that it does not need to be done later. It
* does not make sense for this "normalization factor" to be negative though, as
* that would invert all normals. Additionally, Minecraft's fastInvCubeRoot method
* does not work for negative numbers.
*/
@ModifyArg(method = "scale(FFF)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/Mth;fastInvCubeRoot(F)F"))
private float flywheel$absInvCbrtInput(float input) {
return Math.abs(input);
}
}

View File

@ -7,11 +7,12 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import dev.engine_room.flywheel.lib.visualization.VisualizationHelper;
import net.minecraft.client.renderer.chunk.SectionCompiler;
import net.minecraft.world.level.block.entity.BlockEntity;
@Mixin(targets = "net.minecraft.client.renderer.chunk.ChunkRenderDispatcher$RenderChunk$RebuildTask")
abstract class RebuildTaskMixin {
@Inject(method = "handleBlockEntity(Lnet/minecraft/client/renderer/chunk/ChunkRenderDispatcher$RenderChunk$RebuildTask$CompileResults;Lnet/minecraft/world/level/block/entity/BlockEntity;)V", at = @At("HEAD"), cancellable = true)
@Mixin(SectionCompiler.class)
abstract class SectionCompilerMixin {
@Inject(method = "handleBlockEntity", at = @At("HEAD"), cancellable = true)
private void flywheel$tryAddBlockEntity(@Coerce Object compileResults, BlockEntity blockEntity, CallbackInfo ci) {
if (VisualizationHelper.tryAddBlockEntity(blockEntity)) {
ci.cancel();

View File

@ -30,7 +30,7 @@ import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.Vec3;
public class MinecartVisual<T extends AbstractMinecart> extends ComponentEntityVisual<T> implements SimpleTickableVisual, SimpleDynamicVisual {
private static final ResourceLocation TEXTURE = new ResourceLocation("textures/entity/minecart.png");
private static final ResourceLocation TEXTURE = ResourceLocation.withDefaultNamespace("textures/entity/minecart.png");
private static final Material MATERIAL = SimpleMaterial.builder()
.texture(TEXTURE)
.mipmap(false)

View File

@ -2,10 +2,11 @@
"required": true,
"minVersion": "0.8",
"package": "dev.engine_room.flywheel.impl.mixin",
"compatibilityLevel": "JAVA_17",
"compatibilityLevel": "JAVA_21",
"refmap": "flywheel.refmap.json",
"client": [
"BlockEntityTypeMixin",
"BufferBuilderAccessor",
"ClientChunkCacheMixin",
"EntityTypeMixin",
"LevelMixin",
@ -15,11 +16,10 @@
"PoseStackAccessor",
"PoseStackMixin",
"fix.FixFabulousDepthMixin",
"fix.FixNormalScalingMixin",
"visualmanage.BlockEntityMixin",
"visualmanage.LevelChunkMixin",
"visualmanage.LevelRendererMixin",
"visualmanage.RebuildTaskMixin"
"visualmanage.SectionCompilerMixin"
],
"injectors": {
"defaultRequire": 1

View File

@ -1,38 +0,0 @@
// 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.
*
* <p>Upon chunk bake, block entities of the given type will have {@code shouldRender} evaluated.
* <br>If <b>all predicates</b> returns {@code true} (and the block entity has a renderer), the block entity will be
* added to the chunk for future rendering.</p>
* @param type The block entity type to associate the given predicate with.
* @param shouldRender The predicate for the block entity to evaluate.
*/
<T extends BlockEntity> void addRenderPredicate(BlockEntityType<T> type, BlockEntityRenderPredicate<T> shouldRender);
/**
* Removes a predicate added by {@code addRenderPredicate}. <b>It must be the same object that was added.</b>
*
* @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.
*/
<T extends BlockEntity> boolean removeRenderPredicate(BlockEntityType<T> type, BlockEntityRenderPredicate<T> shouldRender);
}

View File

@ -1,16 +0,0 @@
// 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<T extends BlockEntity> {
boolean shouldRender(BlockGetter blockGetter, BlockPos blockPos, T entity);
}

View File

@ -1,114 +0,0 @@
// 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.
*
* <p>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.
*
* <p>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.
*
* <p>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.
*
* <p>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<ByteBuffer> 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();
}

View File

@ -10,7 +10,6 @@ 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 {
@ -27,12 +26,7 @@ transitiveSourceSets {
rootCompile()
compile(api, lib)
}
sourceSet(stubs) {
rootCompile()
}
sourceSet(main) {
// Don't want stubs at runtime
compile(stubs)
implementation(api, lib, backend)
}
@ -41,7 +35,7 @@ transitiveSourceSets {
platform {
commonProject = project(":common")
compileWithCommonSourceSets(api, lib, backend, stubs, main)
compileWithCommonSourceSets(api, lib, backend, main)
setupLoomMod(api, lib, backend, main)
setupLoomRuns()
setupFatJar(api, lib, backend, main)
@ -77,11 +71,11 @@ dependencies {
modImplementation("net.fabricmc:fabric-loader:${property("fabric_loader_version")}")
modApi("net.fabricmc.fabric-api:fabric-api:${property("fabric_api_version")}")
modCompileOnly("maven.modrinth:sodium:${property("sodium_version")}")
modCompileOnly("maven.modrinth:sodium:${property("sodium_version")}-fabric")
modCompileOnly("maven.modrinth:iris:${property("iris_version")}-fabric")
"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"))
}

View File

@ -4,7 +4,7 @@ import java.util.Iterator;
import org.jetbrains.annotations.Nullable;
import com.mojang.blaze3d.vertex.BufferBuilder.RenderedBuffer;
import com.mojang.blaze3d.vertex.MeshData;
import com.mojang.blaze3d.vertex.PoseStack;
import it.unimi.dsi.fastutil.objects.Reference2ReferenceMap;
@ -140,7 +140,7 @@ final class BakedModelBufferer {
}
public interface ResultConsumer {
void accept(RenderType renderType, boolean shaded, RenderedBuffer data);
void accept(RenderType renderType, boolean shaded, MeshData data);
}
private static class ThreadLocalObjects {

View File

@ -3,21 +3,25 @@ package dev.engine_room.flywheel.lib.model.baked;
import org.jetbrains.annotations.UnknownNullability;
import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.ByteBufferBuilder;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.VertexFormat;
import dev.engine_room.flywheel.impl.mixin.BufferBuilderAccessor;
import net.minecraft.client.renderer.RenderType;
class MeshEmitter {
private final RenderType renderType;
private final BufferBuilder bufferBuilder;
private final ByteBufferBuilder byteBufferBuilder;
private BufferBuilder bufferBuilder;
private BakedModelBufferer.@UnknownNullability ResultConsumer resultConsumer;
private boolean currentShade;
MeshEmitter(RenderType renderType) {
this.renderType = renderType;
this.bufferBuilder = new BufferBuilder(renderType.bufferSize());
this.byteBufferBuilder = new ByteBufferBuilder(renderType.bufferSize());
this.bufferBuilder = new BufferBuilder(byteBufferBuilder, VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
}
public void prepare(BakedModelBufferer.ResultConsumer resultConsumer) {
@ -25,7 +29,7 @@ class MeshEmitter {
}
public void end() {
if (bufferBuilder.building()) {
if (((BufferBuilderAccessor) bufferBuilder).flywheel$getBuilding()) {
emit();
}
resultConsumer = null;
@ -37,22 +41,23 @@ class MeshEmitter {
}
void prepareForGeometry(boolean shade) {
if (!bufferBuilder.building()) {
bufferBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
if (!((BufferBuilderAccessor) bufferBuilder).flywheel$getBuilding()) {
bufferBuilder = new BufferBuilder(byteBufferBuilder, VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
} else if (shade != currentShade) {
emit();
bufferBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
}
currentShade = shade;
}
void emit() {
var renderedBuffer = bufferBuilder.endOrDiscardIfEmpty();
var renderedBuffer = bufferBuilder.build();
if (renderedBuffer != null) {
resultConsumer.accept(renderType, currentShade, renderedBuffer);
renderedBuffer.release();
renderedBuffer.close();
}
bufferBuilder = new BufferBuilder(byteBufferBuilder, VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
}
}

View File

@ -56,69 +56,54 @@ class UniversalMeshEmitter implements VertexConsumer {
}
@Override
public VertexConsumer vertex(double x, double y, double z) {
currentDelegate.vertex(x, y, z);
public VertexConsumer addVertex(float x, float y, float z) {
currentDelegate.addVertex(x, y, z);
return this;
}
@Override
public VertexConsumer color(int red, int green, int blue, int alpha) {
currentDelegate.color(red, green, blue, alpha);
public VertexConsumer setColor(int red, int green, int blue, int alpha) {
currentDelegate.setColor(red, green, blue, alpha);
return this;
}
@Override
public VertexConsumer uv(float u, float v) {
currentDelegate.uv(u, v);
public VertexConsumer setUv(float u, float v) {
currentDelegate.setUv(u, v);
return this;
}
@Override
public VertexConsumer overlayCoords(int u, int v) {
currentDelegate.overlayCoords(u, v);
public VertexConsumer setUv1(int u, int v) {
currentDelegate.setUv1(u, v);
return this;
}
@Override
public VertexConsumer uv2(int u, int v) {
currentDelegate.uv2(u, v);
public VertexConsumer setUv2(int u, int v) {
currentDelegate.setUv2(u, v);
return this;
}
@Override
public VertexConsumer normal(float x, float y, float z) {
currentDelegate.normal(x, y, z);
public VertexConsumer setNormal(float x, float y, float z) {
currentDelegate.setNormal(x, y, z);
return this;
}
@Override
public void endVertex() {
currentDelegate.endVertex();
public void addVertex(float x, float y, float z, int color, float u, float v, int packedOverlay, int packedLight, float normalX, float normalY, float normalZ) {
currentDelegate.addVertex(x, y, z, color, u, v, packedOverlay, packedLight, normalX, normalY, normalZ);
}
@Override
public void defaultColor(int red, int green, int blue, int alpha) {
currentDelegate.defaultColor(red, green, blue, alpha);
public void putBulkData(PoseStack.Pose pose, BakedQuad quad, float red, float green, float blue, float alpha, int packedLight, int packedOverlay) {
currentDelegate.putBulkData(pose, quad, red, green, blue, alpha, packedLight, packedOverlay);
}
@Override
public void unsetDefaultColor() {
currentDelegate.unsetDefaultColor();
}
@Override
public void vertex(float x, float y, float z, float red, float green, float blue, float alpha, float u, float v, int overlay, int light, float normalX, float normalY, float normalZ) {
currentDelegate.vertex(x, y, z, red, green, blue, alpha, u, v, overlay, light, normalX, normalY, normalZ);
}
@Override
public void putBulkData(PoseStack.Pose pose, BakedQuad quad, float red, float green, float blue, int light, int overlay) {
currentDelegate.putBulkData(pose, quad, red, green, blue, light, overlay);
}
@Override
public void putBulkData(PoseStack.Pose pose, BakedQuad quad, float[] brightnesses, float red, float green, float blue, int[] lights, int overlay, boolean readExistingColor) {
currentDelegate.putBulkData(pose, quad, brightnesses, red, green, blue, lights, overlay, readExistingColor);
public void putBulkData(PoseStack.Pose pose, BakedQuad quad, float[] brightness, float red, float green, float blue, float alpha, int[] lightmap, int packedOverlay, boolean readAlpha) {
currentDelegate.putBulkData(pose, quad, brightness, red, green, blue, alpha, lightmap, packedOverlay, readAlpha);
}
private class WrapperModel extends ForwardingBakedModel {

View File

@ -120,7 +120,7 @@ public class FabricFlwConfig implements FlwConfig {
if (backendJson instanceof JsonPrimitive primitive && primitive.isString()) {
var value = primitive.getAsString();
try {
this.backend = Backend.REGISTRY.getOrThrow(new ResourceLocation(value));
this.backend = Backend.REGISTRY.getOrThrow(ResourceLocation.parse(value));
return;
} catch (ResourceLocationException e) {
msg = "'backend' value '" + value + "' is not a valid resource location";

View File

@ -1,8 +1,6 @@
package dev.engine_room.flywheel.impl;
import dev.engine_room.flywheel.api.event.ReloadLevelRendererCallback;
import dev.engine_room.flywheel.impl.compat.CompatMod;
import dev.engine_room.flywheel.impl.compat.FabricSodiumCompat;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.client.multiplayer.ClientLevel;
@ -26,14 +24,4 @@ public class FlwImplXplatImpl implements FlwImplXplat {
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;
}
}

View File

@ -1,48 +0,0 @@
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<ModContainer> 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() {
}
}

View File

@ -7,6 +7,7 @@ import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Coerce;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@ -30,14 +31,14 @@ abstract class MinecraftMixin {
FabricFlwConfig.INSTANCE.load();
}
@Inject(method = "method_24040", at = @At("HEAD"))
private void flywheel$onEndInitialResourceReload(Optional<Throwable> error, CallbackInfo ci) {
@Inject(method = "method_53522", at = @At("HEAD"))
private void flywheel$onEndInitialResourceReload(@Coerce Object gameLoadCookie, Optional<Throwable> error, CallbackInfo ci) {
EndClientResourceReloadCallback.EVENT.invoker()
.onEndClientResourceReload((Minecraft) (Object) this, resourceManager, true, error);
}
@Inject(method = "method_24228", at = @At("HEAD"))
private void flywheel$onEndManualResourceReload(boolean recovery, CompletableFuture<Void> future,
private void flywheel$onEndManualResourceReload(boolean recovery, @Coerce Object gameLoadCookie, CompletableFuture<Void> future,
Optional<Throwable> error, CallbackInfo ci) {
EndClientResourceReloadCallback.EVENT.invoker()
.onEndClientResourceReload((Minecraft) (Object) this, resourceManager, false, error);

View File

@ -15,15 +15,15 @@ abstract class MinecraftMixin {
@Shadow
public ClientLevel level;
@Inject(method = "setLevel(Lnet/minecraft/client/multiplayer/ClientLevel;)V", at = @At("HEAD"))
@Inject(method = "setLevel(Lnet/minecraft/client/multiplayer/ClientLevel;Lnet/minecraft/client/gui/screens/ReceivingLevelScreen$Reason;)V", at = @At("HEAD"))
private void flywheel$onSetLevel(CallbackInfo ci) {
if (level != null) {
LevelAttached.invalidateLevel(level);
}
}
@Inject(method = "clearLevel(Lnet/minecraft/client/gui/screens/Screen;)V", at = @At("HEAD"))
private void flywheel$onClearLevel(CallbackInfo ci) {
@Inject(method = "disconnect(Lnet/minecraft/client/gui/screens/Screen;)V", at = @At("HEAD"))
private void flywheel$onDisconnect(CallbackInfo ci) {
if (level != null) {
LevelAttached.invalidateLevel(level);
}

View File

@ -1,33 +0,0 @@
package dev.engine_room.flywheel.impl.mixin.sodium;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import dev.engine_room.flywheel.lib.visualization.VisualizationHelper;
import me.jellysquid.mods.sodium.client.render.chunk.compile.tasks.ChunkBuilderMeshingTask;
import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher;
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
import net.minecraft.world.level.block.entity.BlockEntity;
@Mixin(value = ChunkBuilderMeshingTask.class, remap = false)
abstract class ChunkBuilderMeshingTaskMixin {
@WrapOperation(
method = "execute(Lme/jellysquid/mods/sodium/client/render/chunk/compile/ChunkBuildContext;Lme/jellysquid/mods/sodium/client/util/task/CancellationToken;)Lme/jellysquid/mods/sodium/client/render/chunk/compile/ChunkBuildOutput;",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/client/renderer/blockentity/BlockEntityRenderDispatcher;getRenderer(Lnet/minecraft/world/level/block/entity/BlockEntity;)Lnet/minecraft/client/renderer/blockentity/BlockEntityRenderer;",
remap = true
)
)
@Nullable
private BlockEntityRenderer<?> flywheel$wrapGetRenderer(BlockEntityRenderDispatcher instance, BlockEntity blockEntity, Operation<BlockEntityRenderer<BlockEntity>> original) {
if (VisualizationHelper.tryAddBlockEntity(blockEntity)) {
return null;
}
return original.call(instance, blockEntity);
}
}

View File

@ -1,46 +0,0 @@
package dev.engine_room.flywheel.impl.mixin.sodium;
import java.util.List;
import java.util.Set;
import org.jetbrains.annotations.Nullable;
import org.objectweb.asm.tree.ClassNode;
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
import dev.engine_room.flywheel.impl.compat.FabricSodiumCompat;
public class SodiumMixinPlugin implements IMixinConfigPlugin {
@Override
public void onLoad(String mixinPackage) {
}
@Override
@Nullable
public String getRefMapperConfig() {
return null;
}
@Override
public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
return FabricSodiumCompat.USE_0_5_COMPAT;
}
@Override
public void acceptTargets(Set<String> myTargets, Set<String> otherTargets) {
}
@Override
@Nullable
public List<String> getMixins() {
return null;
}
@Override
public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
}
@Override
public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
}
}

View File

@ -24,8 +24,7 @@
"mixins": [
"flywheel.backend.mixins.json",
"flywheel.impl.mixins.json",
"flywheel.impl.fabric.mixins.json",
"flywheel.impl.sodium.mixins.json"
"flywheel.impl.fabric.mixins.json"
],
"depends": {
"minecraft": "${minecraft_semver_version_range}",
@ -33,7 +32,7 @@
"fabric-api": "${fabric_api_version_range}"
},
"breaks": {
"sodium": ["<0.5.0", "~0.6.0- <0.6.0-beta.2"],
"sodium": "<0.6.0-beta.2",
"embeddium": "*"
}
}

View File

@ -2,7 +2,7 @@
"required": true,
"minVersion": "0.8",
"package": "dev.engine_room.flywheel.impl.mixin.fabric",
"compatibilityLevel": "JAVA_17",
"compatibilityLevel": "JAVA_21",
"refmap": "flywheel.refmap.json",
"client": [
"DebugScreenOverlayMixin",

View File

@ -1,14 +0,0 @@
{
"required": true,
"minVersion": "0.8",
"package": "dev.engine_room.flywheel.impl.mixin.sodium",
"compatibilityLevel": "JAVA_17",
"refmap": "flywheel.refmap.json",
"plugin": "dev.engine_room.flywheel.impl.mixin.sodium.SodiumMixinPlugin",
"client": [
"ChunkBuilderMeshingTaskMixin"
],
"injectors": {
"defaultRequire": 1
}
}

View File

@ -10,7 +10,6 @@ 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 {
@ -27,11 +26,8 @@ transitiveSourceSets {
rootCompile()
compile(api, lib)
}
sourceSet(stubs) {
rootCompile()
}
sourceSet(main) {
compile(api, lib, backend, stubs)
compile(api, lib, backend)
}
createCompileConfigurations()
@ -39,7 +35,7 @@ transitiveSourceSets {
platform {
commonProject = project(":common")
compileWithCommonSourceSets(api, lib, backend, stubs, main)
compileWithCommonSourceSets(api, lib, backend, main)
setupLoomMod(api, lib, backend, main)
setupLoomRuns()
setupFatJar(api, lib, backend, main)
@ -70,11 +66,6 @@ loom {
add(backend, "backend-flywheel.refmap.json")
}
forge {
mixinConfig("flywheel.backend.mixins.json")
mixinConfig("flywheel.impl.mixins.json")
}
runs {
configureEach {
property("forge.logging.markers", "")
@ -83,14 +74,18 @@ loom {
}
}
dependencies {
forge("net.minecraftforge:forge:${property("minecraft_version")}-${property("forge_version")}")
repositories {
maven("https://maven.neoforged.net/releases/")
}
modCompileOnly("maven.modrinth:embeddium:${property("embeddium_version")}")
dependencies {
neoForge("net.neoforged:neoforge:${property("neoforge_version")}")
modCompileOnly("maven.modrinth:sodium:${property("sodium_version")}-neoforge")
modCompileOnly("maven.modrinth:iris:${property("iris_version")}-neoforge")
"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"))
}

View File

@ -1 +1 @@
loom.platform = forge
loom.platform = neoforge

View File

@ -4,8 +4,8 @@ import java.util.Optional;
import net.minecraft.client.Minecraft;
import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraftforge.eventbus.api.Event;
import net.minecraftforge.fml.event.IModBusEvent;
import net.neoforged.bus.api.Event;
import net.neoforged.fml.event.IModBusEvent;
/**
* This event is posted to mod event buses.

View File

@ -1,10 +1,10 @@
package dev.engine_room.flywheel.api.event;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraftforge.eventbus.api.Event;
import net.neoforged.bus.api.Event;
/**
* This event is posted to the Forge event bus.
* This event is posted to the NeoForge event bus.
*/
public final class ReloadLevelRendererEvent extends Event {
private final ClientLevel level;

View File

@ -5,7 +5,7 @@ import java.util.function.Function;
import org.jetbrains.annotations.Nullable;
import com.mojang.blaze3d.vertex.BufferBuilder.RenderedBuffer;
import com.mojang.blaze3d.vertex.MeshData;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.renderer.ItemBlockRenderTypes;
@ -21,8 +21,8 @@ import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.FluidState;
import net.minecraftforge.client.ChunkRenderTypeSet;
import net.minecraftforge.client.model.data.ModelData;
import net.neoforged.neoforge.client.ChunkRenderTypeSet;
import net.neoforged.neoforge.client.model.data.ModelData;
final class BakedModelBufferer {
static final RenderType[] CHUNK_LAYERS = RenderType.chunkBufferLayers().toArray(RenderType[]::new);
@ -141,7 +141,7 @@ final class BakedModelBufferer {
}
public interface ResultConsumer {
void accept(RenderType renderType, boolean shaded, RenderedBuffer data);
void accept(RenderType renderType, boolean shaded, MeshData data);
}
private static class ThreadLocalObjects {

View File

@ -3,24 +3,28 @@ package dev.engine_room.flywheel.lib.model.baked;
import org.jetbrains.annotations.UnknownNullability;
import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.ByteBufferBuilder;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import com.mojang.blaze3d.vertex.VertexFormat;
import dev.engine_room.flywheel.impl.mixin.BufferBuilderAccessor;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.block.model.BakedQuad;
class MeshEmitter implements VertexConsumer {
private final RenderType renderType;
private final BufferBuilder bufferBuilder;
private final ByteBufferBuilder byteBufferBuilder;
private BufferBuilder bufferBuilder;
private BakedModelBufferer.@UnknownNullability ResultConsumer resultConsumer;
private boolean currentShade;
MeshEmitter(RenderType renderType) {
this.renderType = renderType;
this.bufferBuilder = new BufferBuilder(renderType.bufferSize());
this.byteBufferBuilder = new ByteBufferBuilder(renderType.bufferSize());
this.bufferBuilder = new BufferBuilder(byteBufferBuilder, VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
}
public void prepare(BakedModelBufferer.ResultConsumer resultConsumer) {
@ -28,7 +32,7 @@ class MeshEmitter implements VertexConsumer {
}
public void end() {
if (bufferBuilder.building()) {
if (((BufferBuilderAccessor) bufferBuilder).flywheel$getBuilding()) {
emit();
}
resultConsumer = null;
@ -39,12 +43,11 @@ class MeshEmitter implements VertexConsumer {
return bufferBuilder;
}
private void prepareForGeometry(boolean shade) {
if (!bufferBuilder.building()) {
bufferBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
void prepareForGeometry(boolean shade) {
if (!((BufferBuilderAccessor) bufferBuilder).flywheel$getBuilding()) {
bufferBuilder = new BufferBuilder(byteBufferBuilder, VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
} else if (shade != currentShade) {
emit();
bufferBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
}
currentShade = shade;
@ -55,18 +58,14 @@ class MeshEmitter implements VertexConsumer {
}
private void emit() {
var renderedBuffer = bufferBuilder.endOrDiscardIfEmpty();
var renderedBuffer = bufferBuilder.build();
if (renderedBuffer != null) {
resultConsumer.accept(renderType, currentShade, renderedBuffer);
renderedBuffer.release();
}
renderedBuffer.close();
}
@Override
public void putBulkData(PoseStack.Pose pose, BakedQuad quad, float red, float green, float blue, int light, int overlay) {
prepareForGeometry(quad);
bufferBuilder.putBulkData(pose, quad, red, green, blue, light, overlay);
bufferBuilder = new BufferBuilder(byteBufferBuilder, VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
}
@Override
@ -76,9 +75,9 @@ class MeshEmitter implements VertexConsumer {
}
@Override
public void putBulkData(PoseStack.Pose pose, BakedQuad quad, float[] brightnesses, float red, float green, float blue, int[] lights, int overlay, boolean readExistingColor) {
public void putBulkData(PoseStack.Pose pose, BakedQuad quad, float red, float green, float blue, float alpha, int packedLight, int packedOverlay) {
prepareForGeometry(quad);
bufferBuilder.putBulkData(pose, quad, brightnesses, red, green, blue, lights, overlay, readExistingColor);
bufferBuilder.putBulkData(pose, quad, red, green, blue, alpha, packedLight, packedOverlay);
}
@Override
@ -88,47 +87,32 @@ class MeshEmitter implements VertexConsumer {
}
@Override
public VertexConsumer vertex(double x, double y, double z) {
public VertexConsumer addVertex(float x, float y, float z) {
throw new UnsupportedOperationException("MeshEmitter only supports putBulkData!");
}
@Override
public VertexConsumer color(int red, int green, int blue, int alpha) {
public VertexConsumer setColor(int red, int green, int blue, int alpha) {
throw new UnsupportedOperationException("MeshEmitter only supports putBulkData!");
}
@Override
public VertexConsumer uv(float u, float v) {
public VertexConsumer setUv(float u, float v) {
throw new UnsupportedOperationException("MeshEmitter only supports putBulkData!");
}
@Override
public VertexConsumer overlayCoords(int u, int v) {
public VertexConsumer setUv1(int u, int v) {
throw new UnsupportedOperationException("MeshEmitter only supports putBulkData!");
}
@Override
public VertexConsumer uv2(int u, int v) {
public VertexConsumer setUv2(int u, int v) {
throw new UnsupportedOperationException("MeshEmitter only supports putBulkData!");
}
@Override
public VertexConsumer normal(float x, float y, float z) {
throw new UnsupportedOperationException("MeshEmitter only supports putBulkData!");
}
@Override
public void endVertex() {
throw new UnsupportedOperationException("MeshEmitter only supports putBulkData!");
}
@Override
public void defaultColor(int red, int green, int blue, int alpha) {
throw new UnsupportedOperationException("MeshEmitter only supports putBulkData!");
}
@Override
public void unsetDefaultColor() {
public VertexConsumer setNormal(float normalX, float normalY, float normalZ) {
throw new UnsupportedOperationException("MeshEmitter only supports putBulkData!");
}
}

View File

@ -15,41 +15,41 @@ import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.client.model.data.ModelData;
import net.neoforged.neoforge.client.model.data.ModelData;
public final class ForgeBakedModelBuilder extends BakedModelBuilder {
public final class NeoForgeBakedModelBuilder extends BakedModelBuilder {
@Nullable
private ModelData modelData;
public ForgeBakedModelBuilder(BakedModel bakedModel) {
public NeoForgeBakedModelBuilder(BakedModel bakedModel) {
super(bakedModel);
}
@Override
public ForgeBakedModelBuilder level(BlockAndTintGetter level) {
public NeoForgeBakedModelBuilder level(BlockAndTintGetter level) {
super.level(level);
return this;
}
@Override
public ForgeBakedModelBuilder blockState(BlockState blockState) {
public NeoForgeBakedModelBuilder blockState(BlockState blockState) {
super.blockState(blockState);
return this;
}
@Override
public ForgeBakedModelBuilder poseStack(PoseStack poseStack) {
public NeoForgeBakedModelBuilder poseStack(PoseStack poseStack) {
super.poseStack(poseStack);
return this;
}
@Override
public ForgeBakedModelBuilder materialFunc(BiFunction<RenderType, Boolean, Material> materialFunc) {
public NeoForgeBakedModelBuilder materialFunc(BiFunction<RenderType, Boolean, Material> materialFunc) {
super.materialFunc(materialFunc);
return this;
}
public ForgeBakedModelBuilder modelData(ModelData modelData) {
public NeoForgeBakedModelBuilder modelData(ModelData modelData) {
this.modelData = modelData;
return this;
}

View File

@ -14,35 +14,35 @@ import dev.engine_room.flywheel.lib.model.SimpleModel;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.client.model.data.ModelData;
import net.neoforged.neoforge.client.model.data.ModelData;
public final class ForgeBlockModelBuilder extends BlockModelBuilder {
public final class NeoForgeBlockModelBuilder extends BlockModelBuilder {
@Nullable
private ModelData modelData;
public ForgeBlockModelBuilder(BlockState state) {
public NeoForgeBlockModelBuilder(BlockState state) {
super(state);
}
@Override
public ForgeBlockModelBuilder level(BlockAndTintGetter level) {
public NeoForgeBlockModelBuilder level(BlockAndTintGetter level) {
super.level(level);
return this;
}
@Override
public ForgeBlockModelBuilder poseStack(PoseStack poseStack) {
public NeoForgeBlockModelBuilder poseStack(PoseStack poseStack) {
super.poseStack(poseStack);
return this;
}
@Override
public ForgeBlockModelBuilder materialFunc(BiFunction<RenderType, Boolean, Material> materialFunc) {
public NeoForgeBlockModelBuilder materialFunc(BiFunction<RenderType, Boolean, Material> materialFunc) {
super.materialFunc(materialFunc);
return this;
}
public ForgeBlockModelBuilder modelData(ModelData modelData) {
public NeoForgeBlockModelBuilder modelData(ModelData modelData) {
this.modelData = modelData;
return this;
}

View File

@ -15,35 +15,35 @@ import dev.engine_room.flywheel.lib.model.SimpleModel;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraftforge.client.model.data.ModelData;
import net.neoforged.neoforge.client.model.data.ModelData;
public final class ForgeMultiBlockModelBuilder extends MultiBlockModelBuilder {
public final class NeoForgeMultiBlockModelBuilder extends MultiBlockModelBuilder {
@Nullable
private Function<BlockPos, ModelData> modelDataLookup;
public ForgeMultiBlockModelBuilder(BlockAndTintGetter level, Iterable<BlockPos> positions) {
public NeoForgeMultiBlockModelBuilder(BlockAndTintGetter level, Iterable<BlockPos> positions) {
super(level, positions);
}
@Override
public ForgeMultiBlockModelBuilder poseStack(PoseStack poseStack) {
public NeoForgeMultiBlockModelBuilder poseStack(PoseStack poseStack) {
super.poseStack(poseStack);
return this;
}
@Override
public ForgeMultiBlockModelBuilder enableFluidRendering() {
public NeoForgeMultiBlockModelBuilder enableFluidRendering() {
super.enableFluidRendering();
return this;
}
@Override
public ForgeMultiBlockModelBuilder materialFunc(BiFunction<RenderType, Boolean, Material> materialFunc) {
public NeoForgeMultiBlockModelBuilder materialFunc(BiFunction<RenderType, Boolean, Material> materialFunc) {
super.materialFunc(materialFunc);
return this;
}
public ForgeMultiBlockModelBuilder modelDataLookup(Function<BlockPos, ModelData> modelDataLookup) {
public NeoForgeMultiBlockModelBuilder modelDataLookup(Function<BlockPos, ModelData> modelDataLookup) {
this.modelDataLookup = modelDataLookup;
return this;
}

View File

@ -5,8 +5,9 @@ import java.util.Map;
import org.jetbrains.annotations.ApiStatus;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.client.resources.model.ModelResourceLocation;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.client.event.ModelEvent;
import net.neoforged.neoforge.client.event.ModelEvent;
@ApiStatus.Internal
public final class PartialModelEventHandler {
@ -15,16 +16,16 @@ public final class PartialModelEventHandler {
public static void onRegisterAdditional(ModelEvent.RegisterAdditional event) {
for (ResourceLocation modelLocation : PartialModel.ALL.keySet()) {
event.register(modelLocation);
event.register(ModelResourceLocation.standalone(modelLocation));
}
}
public static void onBakingCompleted(ModelEvent.BakingCompleted event) {
PartialModel.populateOnInit = true;
Map<ResourceLocation, BakedModel> models = event.getModels();
Map<ModelResourceLocation, BakedModel> models = event.getModels();
for (PartialModel partial : PartialModel.ALL.values()) {
partial.bakedModel = models.get(partial.modelLocation());
partial.bakedModel = models.get(ModelResourceLocation.standalone(partial.modelLocation()));
}
}
}

View File

@ -17,9 +17,9 @@ import net.minecraft.commands.arguments.coordinates.BlockPosArgument;
import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.Entity;
import net.minecraftforge.client.event.RegisterClientCommandsEvent;
import net.minecraftforge.common.ForgeConfigSpec.BooleanValue;
import net.minecraftforge.common.ForgeConfigSpec.ConfigValue;
import net.neoforged.neoforge.client.event.RegisterClientCommandsEvent;
import net.neoforged.neoforge.common.ModConfigSpec.BooleanValue;
import net.neoforged.neoforge.common.ModConfigSpec.ConfigValue;
public final class FlwCommands {
private FlwCommands() {
@ -28,7 +28,7 @@ public final class FlwCommands {
public static void registerClientCommands(RegisterClientCommandsEvent event) {
LiteralArgumentBuilder<CommandSourceStack> command = Commands.literal("flywheel");
ConfigValue<String> backendValue = ForgeFlwConfig.INSTANCE.client.backend;
ConfigValue<String> backendValue = NeoForgeFlwConfig.INSTANCE.client.backend;
command.then(Commands.literal("backend")
.executes(context -> {
Backend backend = BackendManager.currentBackend();
@ -58,7 +58,7 @@ public final class FlwCommands {
return Command.SINGLE_SUCCESS;
})));
BooleanValue limitUpdatesValue = ForgeFlwConfig.INSTANCE.client.limitUpdates;
BooleanValue limitUpdatesValue = NeoForgeFlwConfig.INSTANCE.client.limitUpdates;
command.then(Commands.literal("limitUpdates")
.executes(context -> {
if (limitUpdatesValue.get()) {
@ -123,7 +123,7 @@ public final class FlwCommands {
return Command.SINGLE_SUCCESS;
})));
var lightSmoothnessValue = ForgeFlwConfig.INSTANCE.client.backendConfig.lightSmoothness;
var lightSmoothnessValue = NeoForgeFlwConfig.INSTANCE.client.backendConfig.lightSmoothness;
command.then(Commands.literal("lightSmoothness")
.then(Commands.argument("mode", LightSmoothnessArgument.INSTANCE)
.executes(context -> {
@ -137,7 +137,7 @@ public final class FlwCommands {
return Command.SINGLE_SUCCESS;
})));
var useLightDirectionsValue = ForgeFlwConfig.INSTANCE.client.backendConfig.useLightDirections;
var useLightDirectionsValue = NeoForgeFlwConfig.INSTANCE.client.backendConfig.useLightDirections;
command.then(Commands.literal("useLightDirections")
.executes(context -> {
if (useLightDirectionsValue.get()) {

View File

@ -3,8 +3,8 @@ 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.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.loading.LoadingModList;
import net.neoforged.fml.loading.LoadingModList;
import net.neoforged.neoforge.common.NeoForge;
public class FlwImplXplatImpl implements FlwImplXplat {
@Override
@ -14,26 +14,16 @@ public class FlwImplXplatImpl implements FlwImplXplat {
@Override
public void dispatchReloadLevelRendererEvent(ClientLevel level) {
MinecraftForge.EVENT_BUS.post(new ReloadLevelRendererEvent(level));
NeoForge.EVENT_BUS.post(new ReloadLevelRendererEvent(level));
}
@Override
public String getVersionStr() {
return FlywheelForge.version().toString();
return FlywheelNeoForge.version().toString();
}
@Override
public FlwConfig getConfig() {
return ForgeFlwConfig.INSTANCE;
}
@Override
public boolean useSodium0_6Compat() {
return CompatMod.SODIUM.isLoaded && !CompatMod.EMBEDDIUM.isLoaded;
}
@Override
public boolean useIrisCompat() {
return CompatMod.IRIS.isLoaded || CompatMod.OCULUS.isLoaded;
return NeoForgeFlwConfig.INSTANCE;
}
}

View File

@ -7,26 +7,27 @@ import org.jetbrains.annotations.UnknownNullability;
import dev.engine_room.flywheel.lib.internal.FlwLibXplat;
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.ForgeBakedModelBuilder;
import dev.engine_room.flywheel.lib.model.baked.ForgeBlockModelBuilder;
import dev.engine_room.flywheel.lib.model.baked.ForgeMultiBlockModelBuilder;
import dev.engine_room.flywheel.lib.model.baked.MultiBlockModelBuilder;
import dev.engine_room.flywheel.lib.model.baked.NeoForgeBakedModelBuilder;
import dev.engine_room.flywheel.lib.model.baked.NeoForgeBlockModelBuilder;
import dev.engine_room.flywheel.lib.model.baked.NeoForgeMultiBlockModelBuilder;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.block.BlockRenderDispatcher;
import net.minecraft.client.renderer.block.ModelBlockRenderer;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.client.resources.model.ModelManager;
import net.minecraft.client.resources.model.ModelResourceLocation;
import net.minecraft.core.BlockPos;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.fml.util.ObfuscationReflectionHelper;
import net.neoforged.fml.util.ObfuscationReflectionHelper;
public class FlwLibXplatImpl implements FlwLibXplat {
@Override
@UnknownNullability
public BakedModel getBakedModel(ModelManager modelManager, ResourceLocation location) {
return modelManager.getModel(location);
return modelManager.getModel(ModelResourceLocation.standalone(location));
}
@Override
@ -38,7 +39,7 @@ public class FlwLibXplatImpl implements FlwLibXplat {
field.setAccessible(true);
field.set(dispatcher, field.get(defaultDispatcher));
}
ObfuscationReflectionHelper.setPrivateValue(BlockRenderDispatcher.class, dispatcher, new ModelBlockRenderer(Minecraft.getInstance().getBlockColors()), "f_110900_");
ObfuscationReflectionHelper.setPrivateValue(BlockRenderDispatcher.class, dispatcher, new ModelBlockRenderer(Minecraft.getInstance().getBlockColors()), "modelRenderer");
} catch (Exception e) {
FlwImpl.LOGGER.error("Failed to initialize vanilla BlockRenderDispatcher!", e);
return defaultDispatcher;
@ -48,16 +49,16 @@ public class FlwLibXplatImpl implements FlwLibXplat {
@Override
public BakedModelBuilder createBakedModelBuilder(BakedModel bakedModel) {
return new ForgeBakedModelBuilder(bakedModel);
return new NeoForgeBakedModelBuilder(bakedModel);
}
@Override
public BlockModelBuilder createBlockModelBuilder(BlockState state) {
return new ForgeBlockModelBuilder(state);
return new NeoForgeBlockModelBuilder(state);
}
@Override
public MultiBlockModelBuilder createMultiBlockModelBuilder(BlockAndTintGetter level, Iterable<BlockPos> positions) {
return new ForgeMultiBlockModelBuilder(level, positions);
return new NeoForgeMultiBlockModelBuilder(level, positions);
}
}

View File

@ -1,132 +0,0 @@
package dev.engine_room.flywheel.impl;
import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.jetbrains.annotations.UnknownNullability;
import dev.engine_room.flywheel.api.Flywheel;
import dev.engine_room.flywheel.api.event.EndClientResourceReloadEvent;
import dev.engine_room.flywheel.api.event.ReloadLevelRendererEvent;
import dev.engine_room.flywheel.backend.compile.FlwProgramsReloader;
import dev.engine_room.flywheel.backend.engine.uniform.Uniforms;
import dev.engine_room.flywheel.impl.compat.EmbeddiumCompat;
import dev.engine_room.flywheel.impl.visualization.VisualizationEventHandler;
import dev.engine_room.flywheel.lib.model.baked.PartialModelEventHandler;
import dev.engine_room.flywheel.lib.util.LevelAttached;
import dev.engine_room.flywheel.lib.util.ResourceReloadCache;
import dev.engine_room.flywheel.lib.util.ResourceReloadHolder;
import net.minecraft.client.Minecraft;
import net.minecraft.commands.synchronization.ArgumentTypeInfos;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.CustomizeGuiOverlayEvent;
import net.minecraftforge.client.event.RegisterClientReloadListenersEvent;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.TickEvent;
import net.minecraftforge.event.entity.EntityJoinLevelEvent;
import net.minecraftforge.event.entity.EntityLeaveLevelEvent;
import net.minecraftforge.event.level.LevelEvent;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.CrashReportCallables;
import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.LogicalSide;
import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegisterEvent;
@Mod(Flywheel.ID)
public final class FlywheelForge {
@UnknownNullability
private static ArtifactVersion version;
public FlywheelForge() {
ModLoadingContext modLoadingContext = ModLoadingContext.get();
version = modLoadingContext
.getActiveContainer()
.getModInfo()
.getVersion();
IEventBus forgeEventBus = MinecraftForge.EVENT_BUS;
IEventBus modEventBus = FMLJavaModLoadingContext.get()
.getModEventBus();
ForgeFlwConfig.INSTANCE.registerSpecs(modLoadingContext);
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> FlywheelForge.clientInit(forgeEventBus, modEventBus));
}
private static void clientInit(IEventBus forgeEventBus, IEventBus modEventBus) {
registerImplEventListeners(forgeEventBus, modEventBus);
registerLibEventListeners(forgeEventBus, modEventBus);
registerBackendEventListeners(forgeEventBus, modEventBus);
CrashReportCallables.registerCrashCallable("Flywheel Backend", BackendManagerImpl::getBackendString);
FlwImpl.init();
EmbeddiumCompat.init();
}
private static void registerImplEventListeners(IEventBus forgeEventBus, IEventBus modEventBus) {
forgeEventBus.addListener((ReloadLevelRendererEvent e) -> BackendManagerImpl.onReloadLevelRenderer(e.level()));
forgeEventBus.addListener((TickEvent.LevelTickEvent e) -> {
// Make sure we don't tick on the server somehow.
if (e.phase == TickEvent.Phase.END && e.side == LogicalSide.CLIENT) {
VisualizationEventHandler.onClientTick(Minecraft.getInstance(), e.level);
}
});
forgeEventBus.addListener((EntityJoinLevelEvent e) -> VisualizationEventHandler.onEntityJoinLevel(e.getLevel(), e.getEntity()));
forgeEventBus.addListener((EntityLeaveLevelEvent e) -> VisualizationEventHandler.onEntityLeaveLevel(e.getLevel(), e.getEntity()));
forgeEventBus.addListener(FlwCommands::registerClientCommands);
forgeEventBus.addListener((CustomizeGuiOverlayEvent.DebugText e) -> {
Minecraft minecraft = Minecraft.getInstance();
if (!minecraft.options.renderDebug) {
return;
}
FlwDebugInfo.addDebugInfo(minecraft, e.getRight());
});
modEventBus.addListener((EndClientResourceReloadEvent e) -> BackendManagerImpl.onEndClientResourceReload(e.error().isPresent()));
modEventBus.addListener((FMLCommonSetupEvent e) -> {
ArgumentTypeInfos.registerByClass(BackendArgument.class, BackendArgument.INFO);
ArgumentTypeInfos.registerByClass(DebugModeArgument.class, DebugModeArgument.INFO);
ArgumentTypeInfos.registerByClass(LightSmoothnessArgument.class, LightSmoothnessArgument.INFO);
});
modEventBus.addListener((RegisterEvent e) -> {
if (e.getRegistryKey().equals(ForgeRegistries.Keys.COMMAND_ARGUMENT_TYPES)) {
e.register(ForgeRegistries.Keys.COMMAND_ARGUMENT_TYPES, Flywheel.rl("backend"), () -> BackendArgument.INFO);
e.register(ForgeRegistries.Keys.COMMAND_ARGUMENT_TYPES, Flywheel.rl("debug_mode"), () -> DebugModeArgument.INFO);
e.register(ForgeRegistries.Keys.COMMAND_ARGUMENT_TYPES, Flywheel.rl("light_smoothness"), () -> LightSmoothnessArgument.INFO);
}
});
}
private static void registerLibEventListeners(IEventBus forgeEventBus, IEventBus modEventBus) {
forgeEventBus.addListener((LevelEvent.Unload e) -> LevelAttached.invalidateLevel(e.getLevel()));
modEventBus.addListener((EndClientResourceReloadEvent e) -> ResourceReloadCache.onEndClientResourceReload());
modEventBus.addListener((EndClientResourceReloadEvent e) -> ResourceReloadHolder.onEndClientResourceReload());
modEventBus.addListener(PartialModelEventHandler::onRegisterAdditional);
modEventBus.addListener(PartialModelEventHandler::onBakingCompleted);
}
private static void registerBackendEventListeners(IEventBus forgeEventBus, IEventBus modEventBus) {
forgeEventBus.addListener((ReloadLevelRendererEvent e) -> Uniforms.onReloadLevelRenderer());
modEventBus.addListener((RegisterClientReloadListenersEvent e) -> {
e.registerReloadListener(FlwProgramsReloader.INSTANCE);
});
}
public static ArtifactVersion version() {
return version;
}
}

View File

@ -0,0 +1,117 @@
package dev.engine_room.flywheel.impl;
import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.jetbrains.annotations.UnknownNullability;
import dev.engine_room.flywheel.api.Flywheel;
import dev.engine_room.flywheel.api.event.EndClientResourceReloadEvent;
import dev.engine_room.flywheel.api.event.ReloadLevelRendererEvent;
import dev.engine_room.flywheel.backend.compile.FlwProgramsReloader;
import dev.engine_room.flywheel.backend.engine.uniform.Uniforms;
import dev.engine_room.flywheel.impl.visualization.VisualizationEventHandler;
import dev.engine_room.flywheel.lib.model.baked.PartialModelEventHandler;
import dev.engine_room.flywheel.lib.util.LevelAttached;
import dev.engine_room.flywheel.lib.util.ResourceReloadCache;
import dev.engine_room.flywheel.lib.util.ResourceReloadHolder;
import net.minecraft.client.Minecraft;
import net.minecraft.commands.synchronization.ArgumentTypeInfos;
import net.minecraft.core.registries.Registries;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.fml.CrashReportCallables;
import net.neoforged.fml.ModContainer;
import net.neoforged.fml.common.Mod;
import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent;
import net.neoforged.neoforge.client.event.CustomizeGuiOverlayEvent;
import net.neoforged.neoforge.client.event.RegisterClientReloadListenersEvent;
import net.neoforged.neoforge.common.NeoForge;
import net.neoforged.neoforge.event.entity.EntityJoinLevelEvent;
import net.neoforged.neoforge.event.entity.EntityLeaveLevelEvent;
import net.neoforged.neoforge.event.level.LevelEvent;
import net.neoforged.neoforge.event.tick.LevelTickEvent;
import net.neoforged.neoforge.registries.RegisterEvent;
@Mod(value = Flywheel.ID, dist = Dist.CLIENT)
public final class FlywheelNeoForge {
@UnknownNullability
private static ArtifactVersion version;
public FlywheelNeoForge(IEventBus modEventBus, ModContainer modContainer) {
version = modContainer
.getModInfo()
.getVersion();
IEventBus gameEventBus = NeoForge.EVENT_BUS;
NeoForgeFlwConfig.INSTANCE.registerSpecs(modContainer);
registerImplEventListeners(gameEventBus, modEventBus);
registerLibEventListeners(gameEventBus, modEventBus);
registerBackendEventListeners(gameEventBus, modEventBus);
CrashReportCallables.registerCrashCallable("Flywheel Backend", BackendManagerImpl::getBackendString);
FlwImpl.init();
}
private static void registerImplEventListeners(IEventBus gameEventBus, IEventBus modEventBus) {
gameEventBus.addListener((ReloadLevelRendererEvent e) -> BackendManagerImpl.onReloadLevelRenderer(e.level()));
gameEventBus.addListener((LevelTickEvent.Post e) -> {
// Make sure we don't tick on the server somehow.
if (e.getLevel().isClientSide()) {
VisualizationEventHandler.onClientTick(Minecraft.getInstance(), e.getLevel());
}
});
gameEventBus.addListener((EntityJoinLevelEvent e) -> VisualizationEventHandler.onEntityJoinLevel(e.getLevel(), e.getEntity()));
gameEventBus.addListener((EntityLeaveLevelEvent e) -> VisualizationEventHandler.onEntityLeaveLevel(e.getLevel(), e.getEntity()));
gameEventBus.addListener(FlwCommands::registerClientCommands);
gameEventBus.addListener((CustomizeGuiOverlayEvent.DebugText e) -> {
Minecraft minecraft = Minecraft.getInstance();
if (!minecraft.getDebugOverlay().showDebugScreen()) {
return;
}
FlwDebugInfo.addDebugInfo(minecraft, e.getRight());
});
modEventBus.addListener((EndClientResourceReloadEvent e) -> BackendManagerImpl.onEndClientResourceReload(e.error().isPresent()));
modEventBus.addListener((FMLCommonSetupEvent e) -> {
ArgumentTypeInfos.registerByClass(BackendArgument.class, BackendArgument.INFO);
ArgumentTypeInfos.registerByClass(DebugModeArgument.class, DebugModeArgument.INFO);
ArgumentTypeInfos.registerByClass(LightSmoothnessArgument.class, LightSmoothnessArgument.INFO);
});
modEventBus.addListener((RegisterEvent e) -> {
if (e.getRegistryKey().equals(Registries.COMMAND_ARGUMENT_TYPE)) {
e.register(Registries.COMMAND_ARGUMENT_TYPE, Flywheel.rl("backend"), () -> BackendArgument.INFO);
e.register(Registries.COMMAND_ARGUMENT_TYPE, Flywheel.rl("debug_mode"), () -> DebugModeArgument.INFO);
e.register(Registries.COMMAND_ARGUMENT_TYPE, Flywheel.rl("light_smoothness"), () -> LightSmoothnessArgument.INFO);
}
});
}
private static void registerLibEventListeners(IEventBus gameEventBus, IEventBus modEventBus) {
gameEventBus.addListener((LevelEvent.Unload e) -> LevelAttached.invalidateLevel(e.getLevel()));
modEventBus.addListener((EndClientResourceReloadEvent e) -> ResourceReloadCache.onEndClientResourceReload());
modEventBus.addListener((EndClientResourceReloadEvent e) -> ResourceReloadHolder.onEndClientResourceReload());
modEventBus.addListener(PartialModelEventHandler::onRegisterAdditional);
modEventBus.addListener(PartialModelEventHandler::onBakingCompleted);
}
private static void registerBackendEventListeners(IEventBus gameEventBus, IEventBus modEventBus) {
gameEventBus.addListener((ReloadLevelRendererEvent e) -> Uniforms.onReloadLevelRenderer());
modEventBus.addListener((RegisterClientReloadListenersEvent e) -> {
e.registerReloadListener(FlwProgramsReloader.INSTANCE);
});
}
public static ArtifactVersion version() {
return version;
}
}

View File

@ -9,18 +9,18 @@ import dev.engine_room.flywheel.backend.BackendConfig;
import dev.engine_room.flywheel.backend.compile.LightSmoothness;
import net.minecraft.ResourceLocationException;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.common.ForgeConfigSpec;
import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.config.ModConfig;
import net.neoforged.fml.ModContainer;
import net.neoforged.fml.config.ModConfig;
import net.neoforged.neoforge.common.ModConfigSpec;
public class ForgeFlwConfig implements FlwConfig {
public static final ForgeFlwConfig INSTANCE = new ForgeFlwConfig();
public class NeoForgeFlwConfig implements FlwConfig {
public static final NeoForgeFlwConfig INSTANCE = new NeoForgeFlwConfig();
public final ClientConfig client;
private final ForgeConfigSpec clientSpec;
private final ModConfigSpec clientSpec;
private ForgeFlwConfig() {
Pair<ClientConfig, ForgeConfigSpec> clientPair = new ForgeConfigSpec.Builder().configure(ClientConfig::new);
private NeoForgeFlwConfig() {
Pair<ClientConfig, ModConfigSpec> clientPair = new ModConfigSpec.Builder().configure(ClientConfig::new);
this.client = clientPair.getLeft();
clientSpec = clientPair.getRight();
}
@ -40,7 +40,7 @@ public class ForgeFlwConfig implements FlwConfig {
private static Backend parseBackend(String idStr) {
ResourceLocation backendId;
try {
backendId = new ResourceLocation(idStr);
backendId = ResourceLocation.parse(idStr);
} catch (ResourceLocationException e) {
FlwImpl.CONFIG_LOGGER.warn("'backend' value '{}' is not a valid resource location", idStr);
return null;
@ -70,18 +70,18 @@ public class ForgeFlwConfig implements FlwConfig {
return client.backendConfig;
}
public void registerSpecs(ModLoadingContext context) {
public void registerSpecs(ModContainer context) {
context.registerConfig(ModConfig.Type.CLIENT, clientSpec);
}
public static class ClientConfig {
public final ForgeConfigSpec.ConfigValue<String> backend;
public final ForgeConfigSpec.BooleanValue limitUpdates;
public final ForgeConfigSpec.IntValue workerThreads;
public final ModConfigSpec.ConfigValue<String> backend;
public final ModConfigSpec.BooleanValue limitUpdates;
public final ModConfigSpec.IntValue workerThreads;
public final ForgeBackendConfig backendConfig;
private ClientConfig(ForgeConfigSpec.Builder builder) {
private ClientConfig(ModConfigSpec.Builder builder) {
backend = builder.comment("Select the backend to use.")
.define("backend", Backend.REGISTRY.getIdOrThrow(BackendManager.defaultBackend()).toString());
@ -100,10 +100,10 @@ public class ForgeFlwConfig implements FlwConfig {
}
public static class ForgeBackendConfig implements BackendConfig {
public final ForgeConfigSpec.EnumValue<LightSmoothness> lightSmoothness;
public final ForgeConfigSpec.BooleanValue useLightDirections;
public final ModConfigSpec.EnumValue<LightSmoothness> lightSmoothness;
public final ModConfigSpec.BooleanValue useLightDirections;
public ForgeBackendConfig(ForgeConfigSpec.Builder builder) {
public ForgeBackendConfig(ModConfigSpec.Builder builder) {
lightSmoothness = builder.comment("How smooth flywheel's shader-based lighting should be. May have a large performance impact.")
.defineEnum("lightSmoothness", LightSmoothness.SMOOTH);

View File

@ -1,33 +0,0 @@
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);
});
}
}
}

View File

@ -2,25 +2,20 @@ package dev.engine_room.flywheel.impl.mixin;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Coerce;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyArg;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.mojang.realmsclient.client.RealmsClient;
import dev.engine_room.flywheel.api.event.EndClientResourceReloadEvent;
import dev.engine_room.flywheel.impl.FlwImpl;
import net.minecraft.client.Minecraft;
import net.minecraft.client.main.GameConfig;
import net.minecraft.server.packs.resources.ReloadInstance;
import net.minecraft.server.packs.resources.ReloadableResourceManager;
import net.minecraftforge.fml.ModLoader;
import net.neoforged.fml.ModLoader;
@Mixin(Minecraft.class)
abstract class MinecraftMixin {
@ -28,20 +23,18 @@ abstract class MinecraftMixin {
@Final
private ReloadableResourceManager resourceManager;
// Inject at invoke cannot be used in constructors in vanilla Mixin, so use ModifyArg instead.
@ModifyArg(method = "<init>", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/packs/resources/ReloadableResourceManager;createReload(Ljava/util/concurrent/Executor;Ljava/util/concurrent/Executor;Ljava/util/concurrent/CompletableFuture;Ljava/util/List;)Lnet/minecraft/server/packs/resources/ReloadInstance;"), index = 0)
private Executor flywheel$onBeginInitialResourceReload(Executor arg0) {
@Inject(method = "<init>", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/packs/resources/ReloadableResourceManager;createReload(Ljava/util/concurrent/Executor;Ljava/util/concurrent/Executor;Ljava/util/concurrent/CompletableFuture;Ljava/util/List;)Lnet/minecraft/server/packs/resources/ReloadInstance;"))
private void flywheel$onBeginInitialResourceReload(CallbackInfo ci) {
FlwImpl.freezeRegistries();
return arg0;
}
@Inject(method = "lambda$new$5", at = @At("HEAD"))
private void flywheel$onEndInitialResourceReload(RealmsClient realmsClient, ReloadInstance reloadInstance, GameConfig gameConfig, Optional<Throwable> error, CallbackInfo ci) {
ModLoader.get().postEvent(new EndClientResourceReloadEvent((Minecraft) (Object) this, resourceManager, true, error));
@Inject(method = "lambda$new$8", at = @At("HEAD"), remap = false)
private void flywheel$onEndInitialResourceReload(@Coerce Object gameLoadCookie, Optional<Throwable> error, CallbackInfo ci) {
ModLoader.postEvent(new EndClientResourceReloadEvent((Minecraft) (Object) this, resourceManager, true, error));
}
@Inject(method = "lambda$reloadResourcePacks$28", at = @At("HEAD"))
private void flywheel$onEndManualResourceReload(boolean recovery, CompletableFuture<Void> future, Optional<Throwable> error, CallbackInfo ci) {
ModLoader.get().postEvent(new EndClientResourceReloadEvent((Minecraft) (Object) this, resourceManager, false, error));
@Inject(method = "lambda$reloadResourcePacks$21", at = @At("HEAD"), remap = false)
private void flywheel$onEndManualResourceReload(boolean recovery, @Coerce Object gameLoadCookie, CompletableFuture<Void> completablefuture, Optional<Throwable> error, CallbackInfo ci) {
ModLoader.postEvent(new EndClientResourceReloadEvent((Minecraft) (Object) this, resourceManager, false, error));
}
}

View File

@ -14,29 +14,21 @@ authors = "Jozufozu, PepperCode1"
displayURL = "${mod_homepage}"
displayTest = "IGNORE_ALL_VERSION"
[[mixins]]
config = "flywheel.backend.mixins.json"
[[mixins]]
config = "flywheel.impl.mixins.json"
[[dependencies.${mod_id}]]
modId = "minecraft"
mandatory = true
type = "required"
versionRange = "${minecraft_maven_version_range}"
side = "CLIENT"
[[dependencies.${mod_id}]]
modId = "forge"
mandatory = true
versionRange = "${forge_version_range}"
side = "CLIENT"
# Simulates a breaks/incompatible dependency
[[dependencies.${mod_id}]]
modId = "rubidium"
mandatory = false
versionRange = "[0.0-INCOMPATIBLE]"
side = "CLIENT"
[[dependencies.${mod_id}]]
modId = "embeddium"
mandatory = false
versionRange = "[0.3.25,)"
modId = "neoforge"
type = "required"
versionRange = "${neoforge_version_range}"
side = "CLIENT"
[[dependencies.${mod_id}]]
@ -44,3 +36,9 @@ modId = "sodium"
mandatory = false
versionRange = "[0.6.0-beta.2,)"
side = "CLIENT"
# Simulates a breaks/incompatible dependency
[[dependencies.${mod_id}]]
modId = "embeddium"
type = "incompatible"
reason = "Remove Embeddium and install Sodium"

View File

@ -12,28 +12,28 @@ 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.20.1 <1.20.2
minecraft_maven_version_range = [1.20.1,1.20.2)
fabric_api_version_range = >=0.86.0
forge_version_range = [47.0.0,)
minecraft_semver_version_range = >=1.21.1 <1.21.2
minecraft_maven_version_range = [1.21.1,1.21.2)
fabric_api_version_range = >=0.105.0
neoforge_version_range = [21.1.66,)
# General build dependency versions
java_version = 17
java_version = 21
arch_loom_version = 1.7.412
cursegradle_version = 1.4.0
parchment_minecraft_version = 1.20.1
parchment_version = 2023.09.03
parchment_minecraft_version = 1.21
parchment_version = 2024.07.07
# Minecraft build dependency versions
minecraft_version = 1.20.1
forge_version = 47.2.19
fabric_loader_version = 0.15.9
fabric_api_version = 0.92.1+1.20.1
minecraft_version = 1.21.1
neoforge_version = 21.1.66
fabric_loader_version = 0.16.5
fabric_api_version = 0.105.0+1.21.1
# Build dependency mod versions
sodium_version = mc1.20.1-0.5.11
embeddium_version = 0.3.25+mc1.20.1
sodium_version = mc1.21-0.6.0-beta.2
iris_version = 1.8.0-beta.1+1.21
# Publication info
group = dev.engine_room.flywheel
artifact_minecraft_version = 1.20.1
artifact_minecraft_version = 1.21

View File

@ -2,8 +2,8 @@ pluginManagement {
repositories {
gradlePluginPortal()
mavenCentral()
maven("https://maven.minecraftforge.net/") {
name = "MinecraftForge"
maven("https://maven.neoforged.net/releases/") {
name = "NeoForged"
}
maven("https://maven.architectury.dev/") {
name = "Architectury"