diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 000000000..79643e968 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,13 @@ +# These are supported funding model platforms + +github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +patreon: Jozufozu +open_collective: # Replace with a single Open Collective username +ko_fi: Jozufozu +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry +custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 969100e8c..dba7f7a29 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -59,6 +59,7 @@ body: label: Mod Version description: The version of the mod you were using when the bug occured options: + - "0.6.0" - "0.5.1" - "0.5.0a" - "0.5.0" diff --git a/changelog.txt b/changelog.txt index ccd0e4240..981b3af55 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,15 @@ +0.6.0: +With this release, Flywheel is no longer needed on servers! Forge finally has client commands, +and the /flywheel command now takes advantage of this. +Fixes + - Fix crash when running with sodium/magnesium. +Technical/API + - Backend is now a static class. + - Shaders are now compiled on-the-fly and cached. + - Significantly reduced the amount of boilerplate needed in instancing shaders. + - Struct types no longer need to be registered ahead of time. + - Simplify unnecessarily complicated game state system. + 0.5.1: Fixes - Fix crash on resource reload with backend off diff --git a/gradle.properties b/gradle.properties index eba35d3a2..b44a7ab59 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,12 +6,12 @@ mod_version = 0.6.0 mc_update_version = 1.18 minecraft_version = 1.18.1 loader_version = 0.12.12 -fabric_version = 0.45.0+1.18 +fabric_version = 0.46.1+1.18 # build dependency versions loom_version = 0.10-SNAPSHOT cursegradle_version = 1.4.0 -parchment_version = 2021.12.19 +parchment_version = 2022.01.23 # curseforge info projectId = 486392 diff --git a/src/main/java/com/jozufozu/flywheel/Flywheel.java b/src/main/java/com/jozufozu/flywheel/Flywheel.java index 87e37d91e..ba6a96e96 100644 --- a/src/main/java/com/jozufozu/flywheel/Flywheel.java +++ b/src/main/java/com/jozufozu/flywheel/Flywheel.java @@ -3,12 +3,28 @@ package com.jozufozu.flywheel; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import net.fabricmc.loader.api.FabricLoader; +import net.fabricmc.loader.api.SemanticVersion; +import net.fabricmc.loader.api.Version; import net.minecraft.resources.ResourceLocation; public class Flywheel { public static final String ID = "flywheel"; public static final Logger LOGGER = LogManager.getLogger(Flywheel.class); + public static SemanticVersion VERSION; + + static void initVersion() { + Version version = FabricLoader.getInstance() + .getModContainer(ID) + .orElseThrow(() -> new IllegalStateException("Could not get the mod container for Flywheel!")) + .getMetadata() + .getVersion(); + if (!(version instanceof SemanticVersion semver)) { + throw new IllegalStateException("Got non-semantic version for Flywheel!"); + } + VERSION = semver; + } public static ResourceLocation rl(String path) { return new ResourceLocation(ID, path); diff --git a/src/main/java/com/jozufozu/flywheel/FlywheelClient.java b/src/main/java/com/jozufozu/flywheel/FlywheelClient.java index 2152ec153..98adf752e 100644 --- a/src/main/java/com/jozufozu/flywheel/FlywheelClient.java +++ b/src/main/java/com/jozufozu/flywheel/FlywheelClient.java @@ -28,6 +28,8 @@ public class FlywheelClient implements ClientModInitializer { @Override public void onInitializeClient() { + Flywheel.initVersion(); + Backend.init(); FlywheelEvents.GATHER_CONTEXT.register(Contexts::flwInit); diff --git a/src/main/java/com/jozufozu/flywheel/backend/Backend.java b/src/main/java/com/jozufozu/flywheel/backend/Backend.java index b7de158d4..f0ffd7935 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/Backend.java +++ b/src/main/java/com/jozufozu/flywheel/backend/Backend.java @@ -25,6 +25,10 @@ public class Backend { private static final Loader loader = new Loader(); + public static FlwEngine getEngine() { + return engine; + } + /** * Get a string describing the Flywheel backend. When there are eventually multiple backends * (Meshlet, MDI, GL31 Draw Instanced are planned), this will name which one is in use. @@ -33,10 +37,6 @@ public class Backend { return engine == null ? "" : engine.getProperName(); } - public static FlwEngine getEngine() { - return engine; - } - @Nullable public static ProgramSpec getSpec(ResourceLocation name) { return loader.get(name); diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/AbstractInstancer.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/AbstractInstancer.java index e353a7104..872335853 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/AbstractInstancer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/AbstractInstancer.java @@ -62,12 +62,12 @@ public abstract class AbstractInstancer implements Insta return modelData.vertexCount(); } - public int numInstances() { + public int getInstanceCount() { return data.size(); } - public int getTotalVertexCount() { - return getModelVertexCount() * numInstances(); + public int getVertexCount() { + return getModelVertexCount() * getInstanceCount(); } protected void removeDeletedInstances() { diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/Engine.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/Engine.java index 1e33c16db..51cc0a93e 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/Engine.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/Engine.java @@ -1,6 +1,9 @@ package com.jozufozu.flywheel.backend.instancing; +import java.util.List; + import com.jozufozu.flywheel.api.MaterialManager; public interface Engine extends RenderDispatcher, MaterialManager { + void addDebugInfo(List info); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceManager.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceManager.java index 8c79fe8e9..38936f656 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceManager.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceManager.java @@ -46,6 +46,15 @@ public abstract class InstanceManager implements InstancingEngine.OriginShift this.tickableInstances = new Object2ObjectOpenHashMap<>(); } + /** + * Get the number of game objects that are currently being instanced. + * + * @return The object count. + */ + public int getObjectCount() { + return instances.size(); + } + /** * Is the given object capable of being instanced at all? * diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceWorld.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceWorld.java index 387c1c1c4..9595069eb 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceWorld.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceWorld.java @@ -1,5 +1,8 @@ package com.jozufozu.flywheel.backend.instancing; +import java.util.List; + +import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.api.instance.DynamicInstance; import com.jozufozu.flywheel.api.instance.TickableInstance; import com.jozufozu.flywheel.backend.Backend; @@ -74,7 +77,7 @@ public class InstanceWorld { * Free all acquired resources and invalidate this instance world. */ public void delete() { - this.taskEngine.stopWorkers(); + taskEngine.stopWorkers(); engine.delete(); entityInstanceManager.detachLightListeners(); blockEntityInstanceManager.detachLightListeners(); @@ -133,4 +136,11 @@ public class InstanceWorld { world.entitiesForRendering() .forEach(entityInstanceManager::add); } + + public void getDebugString(List debug) { + debug.add(""); + debug.add("Flywheel: " + Flywheel.VERSION); + debug.add("B: " + blockEntityInstanceManager.getObjectCount() + ", E: " + entityInstanceManager.getObjectCount()); + engine.addDebugInfo(debug); + } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java index 949da1fb8..f32a25d71 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java @@ -1,5 +1,7 @@ package com.jozufozu.flywheel.backend.instancing; +import java.util.List; + import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.event.BeginFrameEvent; import com.jozufozu.flywheel.event.ReloadRenderersEvent; @@ -101,4 +103,8 @@ public class InstancedRenderDispatcher { .loadEntities(world); } + public static void getDebugString(List debug) { + instanceWorlds.get(Minecraft.getInstance().level) + .getDebugString(debug); + } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchedMaterialGroup.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchedMaterialGroup.java index 3d349b600..c44826cc5 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchedMaterialGroup.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchedMaterialGroup.java @@ -20,6 +20,8 @@ public class BatchedMaterialGroup implements MaterialGroup { protected final RenderType state; private final Map, BatchedMaterial> materials = new HashMap<>(); + private int vertexCount; + private int instanceCount; public BatchedMaterialGroup(RenderType state) { this.state = state; @@ -37,11 +39,13 @@ public class BatchedMaterialGroup implements MaterialGroup { public void render(PoseStack stack, BatchDrawingTracker source, TaskEngine pool) { - int vertexCount = 0; + vertexCount = 0; + instanceCount = 0; for (BatchedMaterial material : materials.values()) { for (CPUInstancer instancer : material.models.values()) { instancer.setup(); - vertexCount += instancer.getTotalVertexCount(); + vertexCount += instancer.getVertexCount(); + instanceCount += instancer.getInstanceCount(); } } @@ -65,4 +69,20 @@ public class BatchedMaterialGroup implements MaterialGroup { public void delete() { materials.clear(); } + + /** + * Get the number of instances drawn last frame. + * @return The instance count. + */ + public int getInstanceCount() { + return instanceCount; + } + + /** + * Get the number of vertices drawn last frame. + * @return The vertex count. + */ + public int getVertexCount() { + return vertexCount; + } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchingEngine.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchingEngine.java index 39ea2343b..aa6e7f683 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchingEngine.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchingEngine.java @@ -2,6 +2,7 @@ package com.jozufozu.flywheel.backend.instancing.batching; import java.util.EnumMap; import java.util.HashMap; +import java.util.List; import java.util.Map; import com.jozufozu.flywheel.api.MaterialGroup; @@ -10,6 +11,7 @@ import com.jozufozu.flywheel.backend.instancing.BatchDrawingTracker; import com.jozufozu.flywheel.backend.instancing.Engine; import com.jozufozu.flywheel.backend.instancing.TaskEngine; import com.jozufozu.flywheel.event.RenderLayerEvent; +import com.jozufozu.flywheel.util.FlwUtil; import com.mojang.blaze3d.platform.Lighting; import com.mojang.math.Matrix4f; @@ -28,7 +30,6 @@ public class BatchingEngine implements Engine { for (RenderLayer value : RenderLayer.values()) { layers.put(value, new HashMap<>()); } - } @Override @@ -70,4 +71,18 @@ public class BatchingEngine implements Engine { } + @Override + public void addDebugInfo(List info) { + info.add("Batching"); + info.add("Instances: " + layers.values() + .stream() + .flatMap(FlwUtil::mapValues) + .mapToInt(BatchedMaterialGroup::getInstanceCount) + .sum()); + info.add("Vertices: " + layers.values() + .stream() + .flatMap(FlwUtil::mapValues) + .mapToInt(BatchedMaterialGroup::getVertexCount) + .sum()); + } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/CPUInstancer.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/CPUInstancer.java index d16f4a4d2..828827103 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/CPUInstancer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/CPUInstancer.java @@ -24,7 +24,7 @@ public class CPUInstancer extends AbstractInstancer { } void submitTasks(PoseStack stack, TaskEngine pool, DirectVertexConsumer consumer) { - int instances = numInstances(); + int instances = getInstanceCount(); while (instances > 0) { int end = instances; diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancedMaterial.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancedMaterial.java index becb71114..e22b57ce4 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancedMaterial.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancedMaterial.java @@ -46,6 +46,14 @@ public class InstancedMaterial implements Material { }); } + public int getInstanceCount() { + return models.values().stream().mapToInt(GPUInstancer::getInstanceCount).sum(); + } + + public int getVertexCount() { + return models.values().stream().mapToInt(GPUInstancer::getVertexCount).sum(); + } + public boolean nothingToRender() { return models.size() > 0 && models.values() .stream() diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancedMaterialGroup.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancedMaterialGroup.java index 3e1ba850d..6c640f716 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancedMaterialGroup.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancedMaterialGroup.java @@ -34,6 +34,9 @@ public class InstancedMaterialGroup

implements MaterialG private final Map, InstancedMaterial> materials = new HashMap<>(); private final ModelAllocator allocator; + private int vertexCount; + private int instanceCount; + public InstancedMaterialGroup(InstancingEngine

owner, RenderType type) { this.owner = owner; this.type = type; @@ -54,6 +57,22 @@ public class InstancedMaterialGroup

implements MaterialG } } + /** + * Get the number of instances drawn last frame. + * @return The instance count. + */ + public int getInstanceCount() { + return instanceCount; + } + + /** + * Get the number of vertices drawn last frame. + * @return The vertex count. + */ + public int getVertexCount() { + return vertexCount; + } + public void render(Matrix4f viewProjection, double camX, double camY, double camZ, RenderLayer layer) { type.setupRenderState(); Textures.bindActiveTextures(); @@ -75,6 +94,9 @@ public class InstancedMaterialGroup

implements MaterialG pool.flush(); } + vertexCount = 0; + instanceCount = 0; + for (Map.Entry, InstancedMaterial> entry : materials.entrySet()) { InstancedMaterial material = entry.getValue(); if (material.nothingToRender()) continue; @@ -90,6 +112,8 @@ public class InstancedMaterialGroup

implements MaterialG for (GPUInstancer instancer : material.getAllInstancers()) { instancer.render(); + vertexCount += instancer.getVertexCount(); + instanceCount += instancer.getInstanceCount(); } } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancingEngine.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancingEngine.java index a3259956f..8a3c4c376 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancingEngine.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancingEngine.java @@ -2,6 +2,7 @@ package com.jozufozu.flywheel.backend.instancing.instancing; import java.util.EnumMap; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.stream.Stream; @@ -15,6 +16,7 @@ import com.jozufozu.flywheel.core.compile.ProgramCompiler; import com.jozufozu.flywheel.core.shader.WorldProgram; import com.jozufozu.flywheel.event.RenderLayerEvent; import com.jozufozu.flywheel.fabric.helper.Matrix4fHelper; +import com.jozufozu.flywheel.util.FlwUtil; import com.jozufozu.flywheel.util.WeakHashSet; import com.mojang.math.Matrix4f; @@ -102,8 +104,7 @@ public class InstancingEngine

implements Engine { } else { return layers.values() .stream() - .flatMap(it -> it.values() - .stream()); + .flatMap(FlwUtil::mapValues); } } @@ -151,6 +152,14 @@ public class InstancingEngine

implements Engine { } } + @Override + public void addDebugInfo(List info) { + info.add("GL33 Instanced Arrays"); + info.add("Origin: " + originCoordinate.getX() + ", " + originCoordinate.getY() + ", " + originCoordinate.getZ()); + info.add("Instances: " + getGroupsToRender(null).mapToInt(InstancedMaterialGroup::getInstanceCount).sum()); + info.add("Vertices: " + getGroupsToRender(null).mapToInt(InstancedMaterialGroup::getVertexCount).sum()); + } + @FunctionalInterface public interface OriginShiftListener { void onOriginShift(); diff --git a/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java b/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java index 1a14e63c8..3eebd1d0d 100644 --- a/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java +++ b/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java @@ -3,6 +3,7 @@ package com.jozufozu.flywheel.event; import java.util.List; import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; import com.jozufozu.flywheel.light.LightUpdater; import com.jozufozu.flywheel.util.WorldAttached; @@ -11,16 +12,9 @@ import net.minecraft.client.multiplayer.ClientLevel; public class ForgeEvents { - public static void addToDebugScreen(List right) { + public static void addToDebugScreen(List left) { - String text = "Flywheel: " + Backend.getBackendDescriptor(); - if (right.size() < 10) { - right.add(""); - right.add(text); - } else { - right.add(9, ""); - right.add(10, text); - } + InstancedRenderDispatcher.getDebugString(left); } public static void unloadWorld(ClientLevel world) { diff --git a/src/main/java/com/jozufozu/flywheel/fabric/mixin/DebugScreenOverlayMixin.java b/src/main/java/com/jozufozu/flywheel/fabric/mixin/DebugScreenOverlayMixin.java index ae932936a..7a55f1ce7 100644 --- a/src/main/java/com/jozufozu/flywheel/fabric/mixin/DebugScreenOverlayMixin.java +++ b/src/main/java/com/jozufozu/flywheel/fabric/mixin/DebugScreenOverlayMixin.java @@ -14,8 +14,8 @@ import net.minecraft.client.gui.components.DebugScreenOverlay; @Mixin(DebugScreenOverlay.class) public abstract class DebugScreenOverlayMixin extends GuiComponent { - @Inject(method = "getSystemInformation", at = @At("RETURN")) - private void modifyRightText(CallbackInfoReturnable> cir) { + @Inject(method = "getGameInformation", at = @At("RETURN")) + private void modifyLeftText(CallbackInfoReturnable> cir) { ForgeEvents.addToDebugScreen(cir.getReturnValue()); } } diff --git a/src/main/java/com/jozufozu/flywheel/mixin/BlockEntityRenderDispatcherAccessor.java b/src/main/java/com/jozufozu/flywheel/mixin/BlockEntityRenderDispatcherAccessor.java new file mode 100644 index 000000000..7f7830218 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/mixin/BlockEntityRenderDispatcherAccessor.java @@ -0,0 +1,16 @@ +package com.jozufozu.flywheel.mixin; + +import java.util.Map; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher; +import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; +import net.minecraft.world.level.block.entity.BlockEntityType; + +@Mixin(BlockEntityRenderDispatcher.class) +public interface BlockEntityRenderDispatcherAccessor { + @Accessor("renderers") + Map, BlockEntityRenderer> flywheel$getRenderers(); +} diff --git a/src/main/java/com/jozufozu/flywheel/util/FlwUtil.java b/src/main/java/com/jozufozu/flywheel/util/FlwUtil.java index bcb2177d6..beed0590a 100644 --- a/src/main/java/com/jozufozu/flywheel/util/FlwUtil.java +++ b/src/main/java/com/jozufozu/flywheel/util/FlwUtil.java @@ -1,9 +1,26 @@ package com.jozufozu.flywheel.util; import java.util.Arrays; +import java.util.Map; +import java.util.stream.Stream; + +import com.jozufozu.flywheel.mixin.BlockEntityRenderDispatcherAccessor; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; +import net.minecraft.world.level.block.entity.BlockEntityType; public class FlwUtil { + /** + * Get the (effectively global) map of BlockEntityTypes to Renderers. + * @return An immutable map of BlockEntityTypes to BlockEntityRenderers. + */ + public static Map, BlockEntityRenderer> getBlockEntityRenderers() { + Minecraft mc = Minecraft.getInstance(); + return ((BlockEntityRenderDispatcherAccessor) mc.getBlockEntityRenderDispatcher()).flywheel$getRenderers(); + } + public static String repeatChar(char c, int n) { char[] arr = new char[n]; @@ -52,4 +69,8 @@ public class FlwUtil { } } } + + public static Stream mapValues(Map map) { + return map.values().stream(); + } } diff --git a/src/main/java/com/jozufozu/flywheel/util/transform/Translate.java b/src/main/java/com/jozufozu/flywheel/util/transform/Translate.java index 2e3da5a32..df6b91abd 100644 --- a/src/main/java/com/jozufozu/flywheel/util/transform/Translate.java +++ b/src/main/java/com/jozufozu/flywheel/util/transform/Translate.java @@ -56,8 +56,13 @@ public interface Translate { return translate(-vec.getX(), -vec.getY(), -vec.getZ()); } - default Self nudge(int id) { - long randomBits = (long) id * 31L * 493286711L; + /** + * Translates this object randomly by a very small amount. + * @param seed The seed to use to generate the random offsets. + * @return {@code this} + */ + default Self nudge(int seed) { + long randomBits = (long) seed * 31L * 493286711L; randomBits = randomBits * randomBits * 4392167121L + randomBits * 98761L; float xNudge = (((float) (randomBits >> 16 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F; float yNudge = (((float) (randomBits >> 20 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F; diff --git a/src/main/resources/flywheel.mixins.json b/src/main/resources/flywheel.mixins.json index ebca18251..1ef662c3d 100644 --- a/src/main/resources/flywheel.mixins.json +++ b/src/main/resources/flywheel.mixins.json @@ -4,6 +4,7 @@ "package": "com.jozufozu.flywheel.mixin", "compatibilityLevel": "JAVA_17", "client": [ + "BlockEntityRenderDispatcherAccessor", "BlockEntityTypeMixin", "BufferBuilderMixin", "BufferUploaderMixin",