From a6377b5fe82ae1a9ac145379b7ba12100a9b1256 Mon Sep 17 00:00:00 2001 From: Jozufozu Date: Thu, 9 Sep 2021 14:06:17 -0700 Subject: [PATCH 1/9] Fix BeginFrameEvent not firing with sodium installed - Rendering is still broken, that fix must come from within sodium --- .../flywheel/mixin/BeginFrameMixin.java | 60 +++++++++++++++++++ .../flywheel/mixin/RenderHooksMixin.java | 9 ++- src/main/resources/flywheel.mixins.json | 17 +----- 3 files changed, 65 insertions(+), 21 deletions(-) create mode 100644 src/main/java/com/jozufozu/flywheel/mixin/BeginFrameMixin.java diff --git a/src/main/java/com/jozufozu/flywheel/mixin/BeginFrameMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/BeginFrameMixin.java new file mode 100644 index 000000000..e7d6f89d6 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/mixin/BeginFrameMixin.java @@ -0,0 +1,60 @@ +package com.jozufozu.flywheel.mixin; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Group; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; + +import com.jozufozu.flywheel.event.BeginFrameEvent; +import com.mojang.blaze3d.matrix.MatrixStack; + +import net.minecraft.client.renderer.ActiveRenderInfo; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.client.renderer.LightTexture; +import net.minecraft.client.renderer.WorldRenderer; +import net.minecraft.client.renderer.culling.ClippingHelper; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.profiler.IProfiler; +import net.minecraft.util.math.vector.Matrix4f; +import net.minecraft.util.math.vector.Vector3d; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.common.MinecraftForge; + +@OnlyIn(Dist.CLIENT) +@Mixin(WorldRenderer.class) +public class BeginFrameMixin { + + @Shadow + private ClientWorld level; + + @Unique + private boolean setup; + + @Group(name = "setupRender", min = 1) + @Inject(method = "renderLevel", + at = @At(value = "INVOKE", target = "net.minecraft.client.renderer.WorldRenderer.compileChunksUntil(J)V"), + locals = LocalCapture.CAPTURE_FAILSOFT) + private void setupRender(MatrixStack stack, float p_228426_2_, long p_228426_3_, boolean p_228426_5_, + ActiveRenderInfo info, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f projection, + CallbackInfo ci, // locals, only care about clippinghelper + IProfiler iprofiler, Vector3d vector3d, double d0, double d1, double d2, Matrix4f matrix4f, boolean flag, + ClippingHelper clippinghelper) { + MinecraftForge.EVENT_BUS.post(new BeginFrameEvent(level, info, clippinghelper)); + + setup = true; + } + + @Group(name = "setupRender") + @Inject(at = @At("HEAD"), method = "setupRender") + private void setupRenderOptifineCompat(ActiveRenderInfo info, ClippingHelper clippingHelper, boolean p_228437_3_, int frameCount, boolean isSpectator, CallbackInfo ci) { + if (!setup) { + MinecraftForge.EVENT_BUS.post(new BeginFrameEvent(level, info, clippingHelper)); + } + setup = false; + } +} diff --git a/src/main/java/com/jozufozu/flywheel/mixin/RenderHooksMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/RenderHooksMixin.java index be51b342c..afdd2d1a8 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/RenderHooksMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/RenderHooksMixin.java @@ -4,9 +4,12 @@ import org.lwjgl.opengl.GL20; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Group; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.OptifineHandler; @@ -26,6 +29,7 @@ import net.minecraft.client.renderer.RenderTypeBuffers; import net.minecraft.client.renderer.WorldRenderer; import net.minecraft.client.renderer.culling.ClippingHelper; import net.minecraft.client.world.ClientWorld; +import net.minecraft.profiler.IProfiler; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.vector.Matrix4f; import net.minecraft.util.math.vector.Vector3d; @@ -44,11 +48,6 @@ public class RenderHooksMixin { @Final private RenderTypeBuffers renderBuffers; - @Inject(at = @At("HEAD"), method = "setupRender") - private void setupRender(ActiveRenderInfo info, ClippingHelper clippingHelper, boolean p_228437_3_, int frameCount, boolean isSpectator, CallbackInfo ci) { - MinecraftForge.EVENT_BUS.post(new BeginFrameEvent(level, info, clippingHelper)); - } - /** * JUSTIFICATION: This method is called once per layer per frame. It allows us to perform * layer-correct custom rendering. RenderWorldLast is not refined enough for rendering world objects. diff --git a/src/main/resources/flywheel.mixins.json b/src/main/resources/flywheel.mixins.json index 2c4db2153..13b737f6f 100644 --- a/src/main/resources/flywheel.mixins.json +++ b/src/main/resources/flywheel.mixins.json @@ -4,22 +4,7 @@ "package": "com.jozufozu.flywheel.mixin", "compatibilityLevel": "JAVA_8", "refmap": "flywheel.refmap.json", - "client": [ - "CancelEntityRenderMixin", - "CancelTileEntityRenderMixin", - "FixFabulousDepthMixin", - "FogColorTrackerMixin", - "RenderHooksMixin", - "ShaderCloseMixin", - "StoreProjectionMatrixMixin", - "TileRemoveMixin", - "TileWorldHookMixin", - "atlas.AtlasDataMixin", - "atlas.SheetDataAccessor", - "light.LightUpdateMixin", - "light.NetworkLightUpdateMixin", - "FastChunkProviderMixin" - ], + "client": ["BeginFrameMixin", "CancelEntityRenderMixin", "CancelTileEntityRenderMixin", "FastChunkProviderMixin", "FixFabulousDepthMixin", "FogColorTrackerMixin", "RenderHooksMixin", "ShaderCloseMixin", "StoreProjectionMatrixMixin", "TileRemoveMixin", "TileWorldHookMixin", "atlas.AtlasDataMixin", "atlas.SheetDataAccessor", "light.LightUpdateMixin", "light.NetworkLightUpdateMixin"], "injectors": { "defaultRequire": 0 } From 3ef6a163f00b370b14505bd1c6f860c1d38d4946 Mon Sep 17 00:00:00 2001 From: Jozufozu Date: Thu, 9 Sep 2021 15:30:50 -0700 Subject: [PATCH 2/9] Fix compat with optifine shaders, again --- .../jozufozu/flywheel/mixin/BeginFrameMixin.java | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/jozufozu/flywheel/mixin/BeginFrameMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/BeginFrameMixin.java index e7d6f89d6..b9a7bb5cb 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/BeginFrameMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/BeginFrameMixin.java @@ -9,6 +9,7 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; +import com.jozufozu.flywheel.backend.OptifineHandler; import com.jozufozu.flywheel.event.BeginFrameEvent; import com.mojang.blaze3d.matrix.MatrixStack; @@ -35,6 +36,9 @@ public class BeginFrameMixin { @Unique private boolean setup; + /** + * This version gets run by default. + */ @Group(name = "setupRender", min = 1) @Inject(method = "renderLevel", at = @At(value = "INVOKE", target = "net.minecraft.client.renderer.WorldRenderer.compileChunksUntil(J)V"), @@ -44,14 +48,20 @@ public class BeginFrameMixin { CallbackInfo ci, // locals, only care about clippinghelper IProfiler iprofiler, Vector3d vector3d, double d0, double d1, double d2, Matrix4f matrix4f, boolean flag, ClippingHelper clippinghelper) { - MinecraftForge.EVENT_BUS.post(new BeginFrameEvent(level, info, clippinghelper)); - setup = true; + if (!OptifineHandler.usingShaders()) { + MinecraftForge.EVENT_BUS.post(new BeginFrameEvent(level, info, clippinghelper)); + + setup = true; + } } + /** + * This version gets run when optifine is installed and shaders are enabled. + */ @Group(name = "setupRender") @Inject(at = @At("HEAD"), method = "setupRender") - private void setupRenderOptifineCompat(ActiveRenderInfo info, ClippingHelper clippingHelper, boolean p_228437_3_, int frameCount, boolean isSpectator, CallbackInfo ci) { + private void setupRender2(ActiveRenderInfo info, ClippingHelper clippingHelper, boolean p_228437_3_, int frameCount, boolean isSpectator, CallbackInfo ci) { if (!setup) { MinecraftForge.EVENT_BUS.post(new BeginFrameEvent(level, info, clippingHelper)); } From a3c92cdf5869e16bf4b04bbf6863403d82bb7781 Mon Sep 17 00:00:00 2001 From: Jozufozu Date: Tue, 14 Sep 2021 13:36:06 -0700 Subject: [PATCH 3/9] Bump version --- changelog.txt | 10 +++++++++- gradle.properties | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/changelog.txt b/changelog.txt index 958eaca7f..0dbf094bd 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,7 +1,15 @@ +0.2.4: + +Fixes + - Partially fix compatibility issues with sodium-forge + note: full compatibility is waiting on https://github.com/spoorn/sodium-forge/pull/175 +Technical/API + - Add separate xyz scaling function to TransformStack interface. + 0.2.3: Fixes - Fix crash moving a deleted LightVolume -Technical/API: +Technical/API - Alter BeginFrameEvent to enable compatibility with optifine shadows 0.2.2: diff --git a/gradle.properties b/gradle.properties index 86775ac82..c7b3522aa 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ org.gradle.jvmargs=-Xmx3G org.gradle.daemon=false # mod version info -mod_version=0.2.3 +mod_version=0.2.4 mc_update_version=1.16 minecraft_version=1.16.5 forge_version=36.1.66 From 46ebdfd43b6746347209543edf2b25a9d8df0c14 Mon Sep 17 00:00:00 2001 From: Jozufozu Date: Sun, 31 Oct 2021 17:24:57 -0700 Subject: [PATCH 4/9] Remove chunk provider mixin and refactor config packets --- .../jozufozu/flywheel/backend/Backend.java | 3 - .../flywheel/config/BooleanConfig.java | 42 +++++---- .../flywheel/config/BooleanDirective.java | 18 +++- .../jozufozu/flywheel/config/FlwCommands.java | 1 - .../jozufozu/flywheel/config/FlwConfig.java | 8 -- .../config/SConfigureBooleanPacket.java | 14 +-- .../mixin/FastChunkProviderMixin.java | 92 ------------------- src/main/resources/flywheel.mixins.json | 2 +- 8 files changed, 48 insertions(+), 132 deletions(-) delete mode 100644 src/main/java/com/jozufozu/flywheel/mixin/FastChunkProviderMixin.java diff --git a/src/main/java/com/jozufozu/flywheel/backend/Backend.java b/src/main/java/com/jozufozu/flywheel/backend/Backend.java index 51853e0ba..770e0734c 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/Backend.java +++ b/src/main/java/com/jozufozu/flywheel/backend/Backend.java @@ -43,7 +43,6 @@ public class Backend { private Matrix4f projectionMatrix = new Matrix4f(); private boolean instancedArrays; private boolean enabled; - public boolean chunkCachingEnabled; private final List> contexts = new ArrayList<>(); private final Map> materialRegistry = new HashMap<>(); @@ -154,8 +153,6 @@ public class Backend { enabled = FlwConfig.get() .enabled() && !OptifineHandler.usingShaders(); - chunkCachingEnabled = FlwConfig.get() - .chunkCaching(); } public boolean canUseInstancing(@Nullable World world) { diff --git a/src/main/java/com/jozufozu/flywheel/config/BooleanConfig.java b/src/main/java/com/jozufozu/flywheel/config/BooleanConfig.java index 98f8701f2..d8ac42a72 100644 --- a/src/main/java/com/jozufozu/flywheel/config/BooleanConfig.java +++ b/src/main/java/com/jozufozu/flywheel/config/BooleanConfig.java @@ -8,6 +8,7 @@ import com.jozufozu.flywheel.backend.OptifineHandler; import net.minecraft.client.Minecraft; import net.minecraft.client.entity.player.ClientPlayerEntity; +import net.minecraft.network.PacketBuffer; import net.minecraft.util.text.IFormattableTextComponent; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.StringTextComponent; @@ -18,7 +19,6 @@ import net.minecraftforge.api.distmarker.OnlyIn; public enum BooleanConfig { ENGINE(() -> BooleanConfig::enabled), NORMAL_OVERLAY(() -> BooleanConfig::normalOverlay), - CHUNK_CACHING(() -> BooleanConfig::chunkCaching), ; final Supplier> receiver; @@ -31,6 +31,27 @@ public enum BooleanConfig { return new SConfigureBooleanPacket(this, directive); } + /** + * Encode a variant of BooleanConfig. Symmetrical function to {@link #decode} + */ + public void encode(PacketBuffer buffer) { + buffer.writeByte(this.ordinal()); + } + + /** + * Safely decode a variant of BooleanConfig. Symmetrical function to {@link #encode} + */ + public static BooleanConfig decode(PacketBuffer buffer) { + byte t = buffer.readByte(); + BooleanConfig[] values = values(); + // Protects against version differences. + // Shouldn't ever happen but do a sanity check for safety. + if (t >= 0 && t < values.length) + return values[t]; + else + return null; + } + @OnlyIn(Dist.CLIENT) private static void enabled(BooleanDirective state) { ClientPlayerEntity player = Minecraft.getInstance().player; @@ -72,25 +93,6 @@ public enum BooleanConfig { player.displayClientMessage(text, false); } - @OnlyIn(Dist.CLIENT) - private static void chunkCaching(BooleanDirective state) { - ClientPlayerEntity player = Minecraft.getInstance().player; - if (player == null || state == null) return; - - if (state == BooleanDirective.DISPLAY) { - ITextComponent text = new StringTextComponent("Chunk caching is currently: ").append(boolToText(FlwConfig.get().client.chunkCaching.get())); - player.displayClientMessage(text, false); - return; - } - - FlwConfig.get().client.chunkCaching.set(state.get()); - - ITextComponent text = boolToText(FlwConfig.get().client.chunkCaching.get()).append(new StringTextComponent(" chunk caching").withStyle(TextFormatting.WHITE)); - - player.displayClientMessage(text, false); - Backend.reloadWorldRenderers(); - } - private static IFormattableTextComponent boolToText(boolean b) { return b ? new StringTextComponent("enabled").withStyle(TextFormatting.DARK_GREEN) : new StringTextComponent("disabled").withStyle(TextFormatting.RED); } diff --git a/src/main/java/com/jozufozu/flywheel/config/BooleanDirective.java b/src/main/java/com/jozufozu/flywheel/config/BooleanDirective.java index d0ff5e62d..ec0d18bee 100644 --- a/src/main/java/com/jozufozu/flywheel/config/BooleanDirective.java +++ b/src/main/java/com/jozufozu/flywheel/config/BooleanDirective.java @@ -1,5 +1,7 @@ package com.jozufozu.flywheel.config; +import net.minecraft.network.PacketBuffer; + public enum BooleanDirective { TRUE(true), FALSE(false), @@ -16,7 +18,21 @@ public enum BooleanDirective { } public boolean get() { - if (this == DISPLAY) throw new IllegalStateException("Cannot get value from DISPLAY directive"); + if (this == DISPLAY) throw new IllegalStateException("DISPLAY directive has no value"); return b; } + + /** + * Encode a variant of BooleanDirective. Symmetrical function to {@link #decode} + */ + public void encode(PacketBuffer buffer) { + buffer.writeByte(this.ordinal()); + } + + /** + * Safely decode a variant of BooleanDirective. Symmetrical function to {@link #encode} + */ + public static BooleanDirective decode(PacketBuffer buffer) { + return values()[buffer.readByte()]; + } } diff --git a/src/main/java/com/jozufozu/flywheel/config/FlwCommands.java b/src/main/java/com/jozufozu/flywheel/config/FlwCommands.java index a601971cb..7775827db 100644 --- a/src/main/java/com/jozufozu/flywheel/config/FlwCommands.java +++ b/src/main/java/com/jozufozu/flywheel/config/FlwCommands.java @@ -17,7 +17,6 @@ public class FlwCommands { dispatcher.register(Commands.literal("flywheel") .then(new BooleanConfigCommand("backend", BooleanConfig.ENGINE).register()) .then(new BooleanConfigCommand("debugNormals", BooleanConfig.NORMAL_OVERLAY).register()) - .then(new BooleanConfigCommand("chunkCaching", BooleanConfig.CHUNK_CACHING).register()) ); } } diff --git a/src/main/java/com/jozufozu/flywheel/config/FlwConfig.java b/src/main/java/com/jozufozu/flywheel/config/FlwConfig.java index 359d7111e..0fd5a2673 100644 --- a/src/main/java/com/jozufozu/flywheel/config/FlwConfig.java +++ b/src/main/java/com/jozufozu/flywheel/config/FlwConfig.java @@ -34,17 +34,12 @@ public class FlwConfig { return client.debugNormals.get(); } - public boolean chunkCaching() { - return client.chunkCaching.get(); - } - public static void init() { } public static class ClientConfig { public final BooleanValue enabled; public final BooleanValue debugNormals; - public final BooleanValue chunkCaching; public ClientConfig(ForgeConfigSpec.Builder builder) { @@ -53,9 +48,6 @@ public class FlwConfig { debugNormals = builder.comment("Enable or disable a debug overlay that colors pixels by their normal") .define("debugNormals", false); - - chunkCaching = builder.comment("Cache chunk lookups to improve performance.") - .define("chunkCaching", true); } } } diff --git a/src/main/java/com/jozufozu/flywheel/config/SConfigureBooleanPacket.java b/src/main/java/com/jozufozu/flywheel/config/SConfigureBooleanPacket.java index 6d2c97394..cc6d6c429 100644 --- a/src/main/java/com/jozufozu/flywheel/config/SConfigureBooleanPacket.java +++ b/src/main/java/com/jozufozu/flywheel/config/SConfigureBooleanPacket.java @@ -19,18 +19,20 @@ public class SConfigureBooleanPacket { } public SConfigureBooleanPacket(PacketBuffer buffer) { - target = BooleanConfig.values()[buffer.readByte()]; - directive = BooleanDirective.values()[buffer.readByte()]; + target = BooleanConfig.decode(buffer); + directive = BooleanDirective.decode(buffer); } public void encode(PacketBuffer buffer) { - buffer.writeByte(target.ordinal()); - buffer.writeByte(directive.ordinal()); + target.encode(buffer); + directive.encode(buffer); } public void execute(Supplier ctx) { - target.receiver.get() - .accept(directive); + if (directive != null) { + target.receiver.get() + .accept(directive); + } ctx.get() .setPacketHandled(true); } diff --git a/src/main/java/com/jozufozu/flywheel/mixin/FastChunkProviderMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/FastChunkProviderMixin.java deleted file mode 100644 index 28301ea18..000000000 --- a/src/main/java/com/jozufozu/flywheel/mixin/FastChunkProviderMixin.java +++ /dev/null @@ -1,92 +0,0 @@ -package com.jozufozu.flywheel.mixin; - -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -import com.jozufozu.flywheel.backend.Backend; - -import net.minecraft.client.multiplayer.ClientChunkProvider; -import net.minecraft.client.world.ClientWorld; -import net.minecraft.nbt.CompoundNBT; -import net.minecraft.network.PacketBuffer; -import net.minecraft.world.biome.BiomeContainer; -import net.minecraft.world.chunk.AbstractChunkProvider; -import net.minecraft.world.chunk.Chunk; -import net.minecraft.world.chunk.ChunkStatus; -import net.minecraft.world.chunk.IChunk; - -@Mixin(ClientChunkProvider.class) -public abstract class FastChunkProviderMixin extends AbstractChunkProvider { - - @Shadow - @Final - private ClientWorld level; - @Unique - private int lastX; - @Unique - private int lastZ; - - @Unique - private IChunk lastChunk; - - @Inject(method = "getChunk", - at = @At("HEAD"), - cancellable = true) - public void returnCachedChunk(int x, int z, ChunkStatus status, boolean create, CallbackInfoReturnable cir) { - if (Backend.getInstance().chunkCachingEnabled && status.isOrAfter(ChunkStatus.FULL)) { - synchronized (level) { - if (lastChunk != null && x == lastX && z == lastZ) { - cir.setReturnValue(lastChunk); - } - } - } - } - - @Inject(method = "getChunk", - at = @At("RETURN")) - public void cacheChunk(int x, int z, ChunkStatus status, boolean create, CallbackInfoReturnable cir) { - if (Backend.getInstance().chunkCachingEnabled && status.isOrAfter(ChunkStatus.FULL)) { - synchronized (level) { - lastChunk = cir.getReturnValue(); - lastX = x; - lastZ = z; - } - } - } - - @Inject(method = "drop", at = @At("HEAD")) - public void invalidateOnDrop(int x, int z, CallbackInfo ci) { - if (Backend.getInstance().chunkCachingEnabled) { - synchronized (level) { - if (x == lastX && z == lastZ) lastChunk = null; - } - } - } - - @Inject(method = "replaceWithPacketData", at = @At("HEAD")) - public void invalidateOnPacket(int x, int z, BiomeContainer p_228313_3_, PacketBuffer p_228313_4_, CompoundNBT p_228313_5_, int p_228313_6_, boolean p_228313_7_, CallbackInfoReturnable cir) { - if (Backend.getInstance().chunkCachingEnabled) { - synchronized (level) { - if (x == lastX && z == lastZ) lastChunk = null; - } - } - } - - @Redirect(method = "isTickingChunk", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/multiplayer/ClientChunkProvider;hasChunk(II)Z")) - public boolean redirectTicking(ClientChunkProvider clientChunkProvider, int x, int z) { - if (Backend.getInstance().chunkCachingEnabled) { - synchronized (level) { - if (lastChunk != null && x == lastX && z == lastZ) return true; - } - } - - return clientChunkProvider.hasChunk(x, z); - } -} diff --git a/src/main/resources/flywheel.mixins.json b/src/main/resources/flywheel.mixins.json index 13b737f6f..ac826f953 100644 --- a/src/main/resources/flywheel.mixins.json +++ b/src/main/resources/flywheel.mixins.json @@ -4,7 +4,7 @@ "package": "com.jozufozu.flywheel.mixin", "compatibilityLevel": "JAVA_8", "refmap": "flywheel.refmap.json", - "client": ["BeginFrameMixin", "CancelEntityRenderMixin", "CancelTileEntityRenderMixin", "FastChunkProviderMixin", "FixFabulousDepthMixin", "FogColorTrackerMixin", "RenderHooksMixin", "ShaderCloseMixin", "StoreProjectionMatrixMixin", "TileRemoveMixin", "TileWorldHookMixin", "atlas.AtlasDataMixin", "atlas.SheetDataAccessor", "light.LightUpdateMixin", "light.NetworkLightUpdateMixin"], + "client": ["BeginFrameMixin", "CancelEntityRenderMixin", "CancelTileEntityRenderMixin", "FixFabulousDepthMixin", "FogColorTrackerMixin", "RenderHooksMixin", "ShaderCloseMixin", "StoreProjectionMatrixMixin", "TileRemoveMixin", "TileWorldHookMixin", "atlas.AtlasDataMixin", "atlas.SheetDataAccessor", "light.LightUpdateMixin", "light.NetworkLightUpdateMixin"], "injectors": { "defaultRequire": 0 } From d2b5b1096b0f7bb545325eacc402f09b3882ea4f Mon Sep 17 00:00:00 2001 From: Jozufozu Date: Sun, 31 Oct 2021 19:50:01 -0700 Subject: [PATCH 5/9] Fix world leak --- .../instancing/InstancedRenderDispatcher.java | 3 ++- .../jozufozu/flywheel/event/ForgeEvents.java | 10 +++++++++ .../jozufozu/flywheel/util/WorldAttached.java | 22 +++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) 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 1db796450..2d1dfefd4 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java @@ -53,7 +53,8 @@ public class InstancedRenderDispatcher { } public static void enqueueUpdate(TileEntity te) { - getTiles(te.getLevel()).queueUpdate(te); + if (te.hasLevel() && te.getLevel() instanceof ClientWorld) + getTiles(te.getLevel()).queueUpdate(te); } public static void enqueueUpdate(Entity entity) { diff --git a/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java b/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java index 0f6e9da62..4a3a73063 100644 --- a/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java +++ b/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java @@ -4,6 +4,7 @@ import java.util.ArrayList; import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; +import com.jozufozu.flywheel.util.WorldAttached; import net.minecraft.client.Minecraft; import net.minecraft.client.world.ClientWorld; @@ -45,4 +46,13 @@ public class ForgeEvents { } } + @SubscribeEvent + public static void onUnloadWorld(WorldEvent.Unload event) { + IWorld world = event.getWorld(); + + if (Backend.isFlywheelWorld(world)) { + WorldAttached.invalidateWorld(world); + } + } + } diff --git a/src/main/java/com/jozufozu/flywheel/util/WorldAttached.java b/src/main/java/com/jozufozu/flywheel/util/WorldAttached.java index a91acb0e8..21a864314 100644 --- a/src/main/java/com/jozufozu/flywheel/util/WorldAttached.java +++ b/src/main/java/com/jozufozu/flywheel/util/WorldAttached.java @@ -1,6 +1,10 @@ package com.jozufozu.flywheel.util; +import java.lang.ref.WeakReference; +import java.util.ArrayList; import java.util.HashMap; +import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.function.BiConsumer; import java.util.function.Consumer; @@ -12,12 +16,30 @@ import net.minecraft.world.IWorld; public class WorldAttached { + // weak references to prevent leaking hashmaps when a WorldAttached is GC'd during runtime + static List>> allMaps = new ArrayList<>(); private final Map attached; private final Function factory; public WorldAttached(Function factory) { this.factory = factory; attached = new HashMap<>(); + allMaps.add(new WeakReference<>(attached)); + } + + public static void invalidateWorld(IWorld world) { + Iterator>> i = allMaps.iterator(); + while (i.hasNext()) { + Map map = i.next() + .get(); + if (map == null) { + // If the map has been GC'd, remove the weak reference + i.remove(); + } else { + // Prevent leaks + map.remove(world); + } + } } @Nonnull From 98a3f759b37d63dff2e654c7883b8f388b555427 Mon Sep 17 00:00:00 2001 From: Jozufozu Date: Sun, 31 Oct 2021 19:54:12 -0700 Subject: [PATCH 6/9] Weak hash map in world attached - More robust solution that listening to WorldEvent.Unload --- .../jozufozu/flywheel/event/ForgeEvents.java | 9 ------- .../jozufozu/flywheel/util/WorldAttached.java | 26 ++----------------- 2 files changed, 2 insertions(+), 33 deletions(-) diff --git a/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java b/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java index 4a3a73063..5d68edb33 100644 --- a/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java +++ b/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java @@ -46,13 +46,4 @@ public class ForgeEvents { } } - @SubscribeEvent - public static void onUnloadWorld(WorldEvent.Unload event) { - IWorld world = event.getWorld(); - - if (Backend.isFlywheelWorld(world)) { - WorldAttached.invalidateWorld(world); - } - } - } diff --git a/src/main/java/com/jozufozu/flywheel/util/WorldAttached.java b/src/main/java/com/jozufozu/flywheel/util/WorldAttached.java index 21a864314..bf9080377 100644 --- a/src/main/java/com/jozufozu/flywheel/util/WorldAttached.java +++ b/src/main/java/com/jozufozu/flywheel/util/WorldAttached.java @@ -1,11 +1,7 @@ package com.jozufozu.flywheel.util; -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; import java.util.Map; +import java.util.WeakHashMap; import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.function.Function; @@ -16,30 +12,12 @@ import net.minecraft.world.IWorld; public class WorldAttached { - // weak references to prevent leaking hashmaps when a WorldAttached is GC'd during runtime - static List>> allMaps = new ArrayList<>(); private final Map attached; private final Function factory; public WorldAttached(Function factory) { this.factory = factory; - attached = new HashMap<>(); - allMaps.add(new WeakReference<>(attached)); - } - - public static void invalidateWorld(IWorld world) { - Iterator>> i = allMaps.iterator(); - while (i.hasNext()) { - Map map = i.next() - .get(); - if (map == null) { - // If the map has been GC'd, remove the weak reference - i.remove(); - } else { - // Prevent leaks - map.remove(world); - } - } + attached = new WeakHashMap<>(); } @Nonnull From e9404d6de347cb2e2c418a3c5ccd07bc636a7068 Mon Sep 17 00:00:00 2001 From: Jozufozu Date: Fri, 5 Nov 2021 16:45:39 -0700 Subject: [PATCH 7/9] Revert "Weak hash map in world attached" This reverts commit 98a3f759b37d63dff2e654c7883b8f388b555427. --- .../jozufozu/flywheel/event/ForgeEvents.java | 9 +++++++ .../jozufozu/flywheel/util/WorldAttached.java | 26 +++++++++++++++++-- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java b/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java index 5d68edb33..4a3a73063 100644 --- a/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java +++ b/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java @@ -46,4 +46,13 @@ public class ForgeEvents { } } + @SubscribeEvent + public static void onUnloadWorld(WorldEvent.Unload event) { + IWorld world = event.getWorld(); + + if (Backend.isFlywheelWorld(world)) { + WorldAttached.invalidateWorld(world); + } + } + } diff --git a/src/main/java/com/jozufozu/flywheel/util/WorldAttached.java b/src/main/java/com/jozufozu/flywheel/util/WorldAttached.java index bf9080377..21a864314 100644 --- a/src/main/java/com/jozufozu/flywheel/util/WorldAttached.java +++ b/src/main/java/com/jozufozu/flywheel/util/WorldAttached.java @@ -1,7 +1,11 @@ package com.jozufozu.flywheel.util; +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; import java.util.Map; -import java.util.WeakHashMap; import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.function.Function; @@ -12,12 +16,30 @@ import net.minecraft.world.IWorld; public class WorldAttached { + // weak references to prevent leaking hashmaps when a WorldAttached is GC'd during runtime + static List>> allMaps = new ArrayList<>(); private final Map attached; private final Function factory; public WorldAttached(Function factory) { this.factory = factory; - attached = new WeakHashMap<>(); + attached = new HashMap<>(); + allMaps.add(new WeakReference<>(attached)); + } + + public static void invalidateWorld(IWorld world) { + Iterator>> i = allMaps.iterator(); + while (i.hasNext()) { + Map map = i.next() + .get(); + if (map == null) { + // If the map has been GC'd, remove the weak reference + i.remove(); + } else { + // Prevent leaks + map.remove(world); + } + } } @Nonnull From 097ecb062ee855e8962436890f90139e116ad8a1 Mon Sep 17 00:00:00 2001 From: Jozufozu Date: Fri, 5 Nov 2021 16:47:27 -0700 Subject: [PATCH 8/9] Invalidate regardless --- src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java b/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java index 4a3a73063..d2f207e28 100644 --- a/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java +++ b/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java @@ -48,11 +48,7 @@ public class ForgeEvents { @SubscribeEvent public static void onUnloadWorld(WorldEvent.Unload event) { - IWorld world = event.getWorld(); - - if (Backend.isFlywheelWorld(world)) { - WorldAttached.invalidateWorld(world); - } + WorldAttached.invalidateWorld(event.getWorld()); } } From b725f2e53e3aa2252fa9635a251712f1380769c0 Mon Sep 17 00:00:00 2001 From: Jozufozu Date: Tue, 23 Nov 2021 16:05:20 -0800 Subject: [PATCH 9/9] Bump version - 0.2.5 --- changelog.txt | 6 +++++- gradle.properties | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/changelog.txt b/changelog.txt index 0dbf094bd..9926322da 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,9 @@ -0.2.4: +0.2.5: +Fixes + - Fix memory leak when many worlds are loaded + - Remove micro optimization causing more trouble than its worth +0.2.4: Fixes - Partially fix compatibility issues with sodium-forge note: full compatibility is waiting on https://github.com/spoorn/sodium-forge/pull/175 diff --git a/gradle.properties b/gradle.properties index c7b3522aa..3b5151324 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ org.gradle.jvmargs=-Xmx3G org.gradle.daemon=false # mod version info -mod_version=0.2.4 +mod_version=0.2.5 mc_update_version=1.16 minecraft_version=1.16.5 forge_version=36.1.66